First commit
parent
4aeccb8213
commit
fb0cc822f0
Binary file not shown.
@ -0,0 +1,13 @@
|
||||
.App {
|
||||
padding: 20px;
|
||||
background-color: aliceblue;
|
||||
}
|
||||
|
||||
|
||||
.WhiteWindow{
|
||||
background-color: white;
|
||||
border: 1px rgb(1, 1, 1, 0.1) solid;
|
||||
border-radius: 10px; /* Adjust the value to control the curve */
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,189 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import './App.css';
|
||||
import axios from 'axios';
|
||||
|
||||
import {VersionComponent, InfoComponent} from './Components.tsx';
|
||||
|
||||
import { Grid, Tab, Tabs, Paper, Typography, CircularProgress } from '@mui/material';
|
||||
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
|
||||
|
||||
let theme = createTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#049a9b',
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
const fetchDataSgi = async (streamlineSgiId) => {
|
||||
try {
|
||||
const res = await axios.get("https://cc.streamline.pt/api/applications/findOne",
|
||||
{
|
||||
params: {
|
||||
filter: {
|
||||
where: {
|
||||
id: streamlineSgiId
|
||||
},
|
||||
include: ["modules", {
|
||||
relation: "versions",
|
||||
scope: {
|
||||
include: "module",
|
||||
order: "version DESC"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let data = res.data;
|
||||
let modulesSgi = data.modules;
|
||||
let versionsSgi = data.versions;
|
||||
|
||||
return { modulesSgi, versionsSgi }; // Return both modules and versions
|
||||
|
||||
} catch (error) {
|
||||
// Handle errors if any
|
||||
console.error('Error fetching data:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const fetchDataApp = async (streamlineAppId) => {
|
||||
try {
|
||||
const res = await axios.get("https://cc.streamline.pt/api/applications/findOne",
|
||||
{
|
||||
params: {
|
||||
filter: {
|
||||
where: {
|
||||
id: streamlineAppId
|
||||
},
|
||||
include: ["modules", {
|
||||
relation: "versions",
|
||||
scope: {
|
||||
include: "module",
|
||||
order: "version DESC"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let data = res.data;
|
||||
|
||||
return data
|
||||
|
||||
} catch (error) {
|
||||
// Handle errors if any
|
||||
console.error('Error fetching data:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
function App() {
|
||||
|
||||
const streamlineSgiId = "60a288ed33320700119606f9";
|
||||
const streamlineAppId = "6082b67f1e0f13001133287b";
|
||||
|
||||
const [value, setValue] = useState(0);
|
||||
const [selectedVersion, setSelectedVersion] = useState(null);
|
||||
const [modulesData, setModulesData] = useState({ modules: [], versions: [] });
|
||||
const [appData, setAppData] = useState({ modules: [], versions: [] });
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
setSelectedVersion(null); // Reset selectedVersion when switching tabs
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchModules = async () => {
|
||||
try {
|
||||
const { modulesSgi, versionsSgi } = await fetchDataSgi(streamlineSgiId);
|
||||
setModulesData({ modules: modulesSgi, versions: versionsSgi }); // Set the modules and versions in the state
|
||||
|
||||
const appData = await fetchDataApp(streamlineAppId);
|
||||
setAppData(appData);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching modules:', error); // Handle errors if any
|
||||
|
||||
} finally {
|
||||
setLoading(false); // Set loading state to false when the fetch operation is complete
|
||||
}
|
||||
};
|
||||
|
||||
fetchModules(); // Call the function to fetch modules
|
||||
|
||||
}, [streamlineSgiId]);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
|
||||
|
||||
<div className="App">
|
||||
<Typography variant="h3" sx={{ fontWeight: 'bold', marginBottom: '10px' }}>
|
||||
Histórico de versões
|
||||
</Typography>
|
||||
|
||||
|
||||
{loading ? (
|
||||
// Display a loading circular progress while data is being fetched
|
||||
<div sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '200%' }}>
|
||||
<CircularProgress />
|
||||
</div>
|
||||
|
||||
) : (
|
||||
<div className="WhiteWindow">
|
||||
|
||||
<Grid container>
|
||||
|
||||
{/*----TAB SELECTION AREA----------------------------------------------*/}
|
||||
<Grid item md={12}>
|
||||
<Tabs value={value} onChange={handleChange}>
|
||||
<Tab label="SISTEMA DE GESTÃO INTEGRADO (WEB)" />
|
||||
<Tab label="APLICAÇÃO MÓVEL" />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
|
||||
{/*-------INFO AREA----------------------------------------*/}
|
||||
<Grid container sx={{ margin: '5px', padding: '5px', marginBottom: '20px' }}>
|
||||
|
||||
{/*-------HISTORICO VERSOES----------------------------------------*/}
|
||||
<Grid item md={6} sx={{ padding: "10px" }}>
|
||||
<Paper>
|
||||
{value === 0 && <VersionComponent message={modulesData} setSelectedVersion={setSelectedVersion}/>}
|
||||
{value === 1 && <VersionComponent message={appData} setSelectedVersion={setSelectedVersion} />}
|
||||
</Paper>
|
||||
</Grid>
|
||||
|
||||
{/*-------MORE INFO GRIDS (Info and improvements)----------------------------------------*/}
|
||||
<Grid item md={6} sx={{ padding: "10px" }}>
|
||||
<Paper>
|
||||
{value === 0 && <InfoComponent modules={modulesData} version={selectedVersion} />}
|
||||
{value === 1 && <InfoComponent modules={appData} version={selectedVersion} />}
|
||||
</Paper>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default App;
|
@ -0,0 +1,8 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
@ -0,0 +1,383 @@
|
||||
import React, {useState} from 'react';
|
||||
import './App.css';
|
||||
import MultipleSelectFilter from './MultipleSelectFilter.tsx';
|
||||
import MultipleSelectModule from './MultipleSelectModule.tsx';
|
||||
|
||||
import { Grid, TextField, List, ListItem, Divider, Card, Typography} from '@mui/material';
|
||||
import { Timeline, TimelineItem, TimelineSeparator, TimelineConnector, TimelineContent, TimelineDot} from '@mui/lab';
|
||||
import TimelineOppositeContent, {
|
||||
timelineOppositeContentClasses,
|
||||
} from '@mui/lab/TimelineOppositeContent';
|
||||
|
||||
import DonutLargeIcon from '@mui/icons-material/DonutLarge';
|
||||
import SquareFootIcon from '@mui/icons-material/SquareFoot';
|
||||
import StraightenIcon from '@mui/icons-material/Straighten';
|
||||
import AccountBalanceIcon from '@mui/icons-material/AccountBalance';
|
||||
import WarehouseIcon from '@mui/icons-material/Warehouse';
|
||||
import EuroIcon from '@mui/icons-material/Euro';
|
||||
import PowerIcon from '@mui/icons-material/Power';
|
||||
import LocalFireDepartmentIcon from '@mui/icons-material/LocalFireDepartment';
|
||||
import ConstructionIcon from '@mui/icons-material/Construction';
|
||||
import HeightIcon from '@mui/icons-material/Height';
|
||||
|
||||
import BuildIcon from '@mui/icons-material/Build';
|
||||
import DynamicFeedIcon from '@mui/icons-material/DynamicFeed';
|
||||
import HubIcon from '@mui/icons-material/Hub';
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
|
||||
import FileCopyIcon from '@mui/icons-material/FileCopy';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
|
||||
|
||||
|
||||
let theme = createTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#049a9b',
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const listItemStyle = { margin: '-15px 5px -10px 0px',};
|
||||
const infoTitlesStyle = { fontWeight: 'bold', margin: '15px 0px 10px 8px', fontSize: '25px' };
|
||||
const informacaoTitleStyles = {fontWeight: 'bold', margin: '0px 10px 5px 10px', fontSize: '15px' }
|
||||
const informacaoContentStyle = { margin: '0px 10px 5px 10px', fontSize: '15px' }
|
||||
|
||||
const namesWithIcons = [
|
||||
{ id: 0, name: 'Novas funcionalidade', icon: < HubIcon /> },
|
||||
{ id: 1, name: 'Correção de Falhas', icon: <BuildIcon /> },
|
||||
{ id: 2, name: 'Melhorias', icon: <DynamicFeedIcon /> },
|
||||
];
|
||||
|
||||
|
||||
function formatDate(myString){
|
||||
const date = new Date(myString);
|
||||
const year = date.getUTCFullYear() % 100; // Get the last two digits of the year
|
||||
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0'); // Month is zero-based
|
||||
const day = date.getUTCDate().toString().padStart(2, '0');
|
||||
|
||||
return `${day}/${month}/${year}`;
|
||||
}
|
||||
|
||||
|
||||
function semanticVersions(myString){
|
||||
// Convert from "005001010" to 5.1.10
|
||||
return String(parseInt(myString.slice(0, 3)))+"."+
|
||||
String(+ parseInt(myString.slice(3, 6)))+"."+
|
||||
String(+ parseInt(myString.slice(6, 9)))
|
||||
|
||||
}
|
||||
|
||||
const getIconForModule = (myModuleName) => {
|
||||
switch (myModuleName) {
|
||||
case 'CORE': return <DonutLargeIcon />;
|
||||
case 'FOR': return <SquareFootIcon />;
|
||||
case 'IE': return <PowerIcon/>;
|
||||
case 'LME':
|
||||
case 'LAB': return <StraightenIcon/>;
|
||||
case 'ELV': return <HeightIcon />;
|
||||
case 'FIN': return <AccountBalanceIcon />;
|
||||
case 'ATV': return <AccountBalanceIcon />;
|
||||
case 'PAD': return <EuroIcon />;
|
||||
case 'OBL':
|
||||
case 'OBLER': return <WarehouseIcon/>;
|
||||
case 'GAS': return <LocalFireDepartmentIcon/>;
|
||||
case 'FUN': return <ConstructionIcon />;
|
||||
default: return <AccountBalanceIcon />;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function VersionComponent({message, setSelectedVersion, filters }) {
|
||||
|
||||
//Check for the tab selected --> Could be "SGI" or "Mobile"
|
||||
var tabSelected = "";
|
||||
if (message.name === "SGI Mobile") {tabSelected = "mobile"}
|
||||
else {tabSelected = "SGI"}
|
||||
|
||||
// Versions (TIMELINE)
|
||||
let versions = message.versions //Get all versions
|
||||
const [selectedVersion, setSelectedIcon] = useState(null);
|
||||
|
||||
|
||||
// Module (CHIP)
|
||||
const moduleNames: string[] = [];
|
||||
for (let i = 0; i < message.modules.length; i++){ moduleNames[i] = message.modules[i].value;}
|
||||
|
||||
// Filters
|
||||
const [moduleFilter, setModuleFilter] = useState([]);
|
||||
const [filter, setFilter] = useState([]);
|
||||
|
||||
|
||||
// Handling of the version click
|
||||
const handleIconClick = (index, data) => {
|
||||
setSelectedIcon(index); // Aggiorna lo stato selectedVersion
|
||||
setSelectedVersion(data);
|
||||
};
|
||||
|
||||
// Handle search text
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
// Function for filtering the versions by the search text
|
||||
const cleanedVersions = Object.values(versions).filter((item) => {
|
||||
const versionInfo = `${item.module.value} ${semanticVersions(item.version)} ${item.improvements} ${item.bugfixes} ${item.added}`;
|
||||
return versionInfo.toLowerCase().includes(searchText.toLowerCase());
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Card className="Versoes-Card" variant="outlined">
|
||||
<Typography sx={{ fontWeight: 'bold', margin: '15px 15px 10px 15px', fontSize: '25px' }}>
|
||||
Versões {tabSelected}
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
size="small"
|
||||
id="outlined"
|
||||
label="Pesquisa..."
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
sx={{ width: 'calc(100% - 30px)', marginLeft: '15px', marginRight: '15px', marginBottom: '15px'}}
|
||||
/>
|
||||
|
||||
|
||||
<Grid container sx={{ marginBottom: '10px'}}>
|
||||
|
||||
<Grid item sx={{marginLeft: "8px", marginTop: "-5px"}}>
|
||||
<MultipleSelectModule modules={message.modules} moduleFilter={moduleFilter} setModuleFilter={setModuleFilter}></MultipleSelectModule>
|
||||
</Grid>
|
||||
|
||||
<Grid item sx={{marginLeft: "8px", marginTop: "-5px", paddingRight: '5px'}}>
|
||||
<MultipleSelectFilter names={namesWithIcons} filter={filter} setFilter={setFilter}></MultipleSelectFilter>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<Timeline style={{maxHeight: '800px', overflow: 'auto'}}
|
||||
sx={{[`& .${timelineOppositeContentClasses.root}`]: {flex: 0.1, },}}>
|
||||
{cleanedVersions.map((item, index) => {
|
||||
|
||||
// Filter item by the modulew selected (module chip)
|
||||
if (moduleFilter.length > 0){
|
||||
if (!(moduleFilter.includes(item.module.value))){return null;}
|
||||
}
|
||||
|
||||
//console.log("my item", item.module.value)
|
||||
|
||||
// Filter module by the improvement chip
|
||||
if ((filter.includes(namesWithIcons[2].name)) && ((item.improvements === undefined) || (item.improvements === "")) ) {return null;}
|
||||
// Filter module by the added chip
|
||||
if ((filter.includes(namesWithIcons[0].name)) && ((item.added === undefined) || (item.added === ""))) {return null;}
|
||||
// Filter module by the added chip
|
||||
if ((filter.includes(namesWithIcons[1].name)) && ((item.bugfixes === undefined) || (item.bugfixes === ""))) {return null;}
|
||||
|
||||
|
||||
// Return the item
|
||||
return (
|
||||
<TimelineItem key={index} sx={{ py: '4px' }}>
|
||||
|
||||
<TimelineOppositeContent color="textSecondary" sx={{ py: '22px' }}>
|
||||
<Typography variant="body2" component="div">
|
||||
{formatDate(item.date)}
|
||||
</Typography>
|
||||
|
||||
</TimelineOppositeContent>
|
||||
|
||||
|
||||
<TimelineSeparator>
|
||||
|
||||
<TimelineDot
|
||||
color={selectedVersion === index ? 'warning' : 'primary'}
|
||||
onClick={() => handleIconClick(index, item)}>
|
||||
{getIconForModule(item.module.name)}
|
||||
</TimelineDot>
|
||||
|
||||
<TimelineConnector sx={{ paddingTop: '22px' }} />
|
||||
|
||||
</TimelineSeparator>
|
||||
|
||||
|
||||
<TimelineContent>
|
||||
<Typography variant="h6" sx={{ fontSize: '18px', lineHeight: '18px', padding: '8px 0px 0px 0px' }}>
|
||||
{item.module.value}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
{semanticVersions(item.version)}
|
||||
</Typography>
|
||||
</TimelineContent>
|
||||
|
||||
</TimelineItem>
|
||||
);
|
||||
})}
|
||||
|
||||
</Timeline>
|
||||
|
||||
{console.log("NO VERSIOooN!", cleanedVersions.length)}
|
||||
{console.log("\n\n\n\n\n\n\nYALLE!")}
|
||||
|
||||
|
||||
</Card>
|
||||
</ThemeProvider>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
function InfoComponent({ modules, version: selectedVersion }) {
|
||||
|
||||
// If no version is selected, don't render anything
|
||||
if (!selectedVersion || !selectedVersion.version) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
const copyText = (text) => {
|
||||
// Function that creates an icon to copy the git id
|
||||
const tempInput = document.createElement('input');
|
||||
tempInput.value = text;
|
||||
document.body.appendChild(tempInput);
|
||||
|
||||
tempInput.select();
|
||||
tempInput.setSelectionRange(0, 999);
|
||||
|
||||
document.execCommand('copy');
|
||||
|
||||
document.body.removeChild(tempInput);
|
||||
console.log(`Copied: ${text}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
|
||||
<Card variant="outlined">
|
||||
<List >
|
||||
<ListItem sx={listItemStyle}>
|
||||
<InfoIcon></InfoIcon>
|
||||
<Typography sx={infoTitlesStyle}>
|
||||
Informação para versão {semanticVersions(selectedVersion.version)}
|
||||
</Typography>
|
||||
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={6}>
|
||||
<Typography sx={informacaoTitleStyles}> Módulo </Typography>
|
||||
<Typography sx={informacaoContentStyle}>
|
||||
{selectedVersion.module.value}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid item md={6}>
|
||||
<Typography sx={informacaoTitleStyles}> Data de lançamento </Typography>
|
||||
<Typography sx={informacaoContentStyle}>
|
||||
{formatDate(selectedVersion.date)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid item md={12}>
|
||||
<Typography sx={informacaoTitleStyles}> Revisão GIT (se aplicavel) </Typography>
|
||||
<Typography sx={informacaoContentStyle}>
|
||||
{selectedVersion.gitHash ?
|
||||
(
|
||||
<>
|
||||
{selectedVersion.gitHash}
|
||||
<IconButton sx={{ transform: 'scale(0.6)', margin: '-10px 0px 0px 0px' }}
|
||||
title="Copia"
|
||||
onClick={() => copyText(selectedVersion.gitHash)}
|
||||
>
|
||||
<FileCopyIcon />
|
||||
</IconButton>
|
||||
</>
|
||||
) : (
|
||||
"N/D"
|
||||
)}
|
||||
|
||||
</Typography>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ListItem>
|
||||
|
||||
</List>
|
||||
|
||||
<Divider/>
|
||||
|
||||
{selectedVersion.added && (
|
||||
<List>
|
||||
<ListItem sx={listItemStyle}>
|
||||
{namesWithIcons[0].icon}
|
||||
<Typography sx={infoTitlesStyle}>
|
||||
|
||||
Novas Funcionalidades
|
||||
</Typography>
|
||||
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Typography sx={{ margin: '0px 0px 10px -10px', fontSize: '15px' }}
|
||||
dangerouslySetInnerHTML={{ __html: selectedVersion.added }} />
|
||||
</ListItem>
|
||||
</List>
|
||||
)}
|
||||
|
||||
<Divider/>
|
||||
|
||||
{selectedVersion.bugfixes && (
|
||||
<List>
|
||||
<ListItem sx={listItemStyle}>
|
||||
{namesWithIcons[1].icon}
|
||||
<Typography sx={infoTitlesStyle}>
|
||||
Correção de Falhas
|
||||
</Typography>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Typography sx={{ margin: '0px 0px 10px -10px', fontSize: '15px' }}
|
||||
dangerouslySetInnerHTML={{ __html: selectedVersion.bugfixes }} />
|
||||
|
||||
</ListItem>
|
||||
|
||||
</List>
|
||||
)}
|
||||
|
||||
<Divider/>
|
||||
|
||||
{selectedVersion.improvements && (
|
||||
<List>
|
||||
<ListItem sx={listItemStyle}>
|
||||
{namesWithIcons[2].icon}
|
||||
<Typography sx={infoTitlesStyle}>
|
||||
Melhorias
|
||||
</Typography>
|
||||
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Typography sx={{ margin: '0px 0px 10px -10px', fontSize: '15px' }}
|
||||
dangerouslySetInnerHTML={{ __html: selectedVersion.improvements }} />
|
||||
|
||||
</ListItem>
|
||||
|
||||
</List>
|
||||
|
||||
)}
|
||||
|
||||
<Divider/>
|
||||
|
||||
|
||||
|
||||
</Card>
|
||||
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export {VersionComponent, InfoComponent};
|
@ -0,0 +1,73 @@
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import Select, { SelectChangeEvent } from '@mui/material/Select';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Grid from '@mui/material/Grid';
|
||||
|
||||
|
||||
interface NameWithIcon {
|
||||
name: string;
|
||||
icon: JSX.Element; // Tipo di elemento per l'icona
|
||||
}
|
||||
|
||||
interface Props {
|
||||
names: NameWithIcon[]; // Modifica il tipo delle props per accettare nomi con icone
|
||||
filter: string[]; // Aggiungi il tipo di props per l'array filter
|
||||
|
||||
}
|
||||
|
||||
const MultipleSelectFilter: React.FC<Props> = ({ names, filter, setFilter }) => {
|
||||
const [personName, setPersonName] = React.useState<string[]>([]);
|
||||
|
||||
const handleChange = (event: SelectChangeEvent<typeof personName>) => {
|
||||
const {
|
||||
target: { value },
|
||||
} = event;
|
||||
const selectedValues = typeof value === 'string' ? value.split(',') : value;
|
||||
setPersonName(selectedValues);
|
||||
setFilter(selectedValues); // Aggiorna l'array filter quando cambia la selezione
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<FormControl sx={{ m: 1, minWidth: 240}} >
|
||||
<InputLabel id="demo-multiple-chip-label" sx={{ marginTop: '-8px' }}>Filtra </InputLabel>
|
||||
<Select
|
||||
labelId="demo-multiple-chip-label"
|
||||
//id="demo-multiple-chip"
|
||||
multiple
|
||||
size="small"
|
||||
value={personName}
|
||||
onChange={handleChange}
|
||||
input={<OutlinedInput id="select-multiple-chip" label="Chip" />}
|
||||
renderValue={(selected) => (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: '0.8px' }}>
|
||||
{selected.map((value) => (
|
||||
<Chip
|
||||
key={value}
|
||||
label={names.find((item) => item.name === value)?.icon}
|
||||
sx={{ fontSize: '2rem'}}/>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
>
|
||||
|
||||
{names.map((nameWithIcon) => (
|
||||
<MenuItem key={nameWithIcon.name} value={nameWithIcon.name}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
{nameWithIcon.icon}
|
||||
<span style={{ marginLeft: '10px' }}>{nameWithIcon.name}</span>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
export default MultipleSelectFilter;
|
@ -0,0 +1,101 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import Select, { SelectChangeEvent } from '@mui/material/Select';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Grid from '@mui/material/Grid';
|
||||
|
||||
import DonutLargeIcon from '@mui/icons-material/DonutLarge';
|
||||
import SquareFootIcon from '@mui/icons-material/SquareFoot';
|
||||
import StraightenIcon from '@mui/icons-material/Straighten';
|
||||
import AccountBalanceIcon from '@mui/icons-material/AccountBalance';
|
||||
import WarehouseIcon from '@mui/icons-material/Warehouse';
|
||||
import EuroIcon from '@mui/icons-material/Euro';
|
||||
import PowerIcon from '@mui/icons-material/Power';
|
||||
import LocalFireDepartmentIcon from '@mui/icons-material/LocalFireDepartment';
|
||||
import ConstructionIcon from '@mui/icons-material/Construction';
|
||||
import HeightIcon from '@mui/icons-material/Height';
|
||||
|
||||
const getIconForModule = (moduleName) => {
|
||||
switch (moduleName) {
|
||||
case 'CORE': return <DonutLargeIcon />;
|
||||
case 'FOR': return <SquareFootIcon />;
|
||||
case 'IE': return <PowerIcon/>;
|
||||
case 'LME':
|
||||
case 'LAB': return <StraightenIcon/>;
|
||||
case 'ELV': return <HeightIcon />;
|
||||
case 'FIN': return <AccountBalanceIcon />;
|
||||
case 'ATV': return <AccountBalanceIcon />;
|
||||
case 'PAD': return <EuroIcon />;
|
||||
case 'OBL':
|
||||
case 'OBLER': return <WarehouseIcon/>;
|
||||
case 'GAS': return <LocalFireDepartmentIcon/>;
|
||||
case 'FUN': return <ConstructionIcon />;
|
||||
default: return <AccountBalanceIcon />;
|
||||
}
|
||||
};
|
||||
|
||||
interface Props {
|
||||
modules: { value: string }[];
|
||||
moduleFilter: string[]; // Aggiungi il tipo di props per l'array filter
|
||||
setModuleFilter: (filter: string[]) => void;
|
||||
}
|
||||
|
||||
const MultipleSelectModule: React.FC<Props> = ({ modules, moduleFilter, setModuleFilter }) => {
|
||||
const [selectedModules, setSelectedModules] = React.useState<string[]>([]);
|
||||
|
||||
const handleChange = (event: SelectChangeEvent<typeof selectedModules>) => {
|
||||
console.log("QUi--> ", event.target, event.target.value, event.target.name)
|
||||
setSelectedModules(event.target.value as string[]);
|
||||
|
||||
const selectedValues = (event.target.value as { value: string, name: string }[]).map(module => module.value);
|
||||
setModuleFilter(selectedValues); // Update moduleFilter with only the 'value' properties
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<FormControl sx={{ m: 1, minWidth: 240}}>
|
||||
<InputLabel id="demo-multiple-chip-label" sx={{ marginTop: '-8px' }}>Selecionar modulo</InputLabel>
|
||||
<Select
|
||||
fullWidth
|
||||
labelId="demo-multiple-chip-label"
|
||||
//id="demo-multiple-chip"
|
||||
multiple
|
||||
size="small"
|
||||
value={selectedModules}
|
||||
onChange={handleChange}
|
||||
input={<OutlinedInput id="select-multiple-chip" label="Chip" />}
|
||||
renderValue={(selected) => {
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: '0.1px' }}>
|
||||
{selected.map((value) => (
|
||||
<Chip
|
||||
key={value}
|
||||
icon={getIconForModule(value.name)}
|
||||
sx={{
|
||||
fontSize: '2rem', backgroundColor: 'transparent'}} />
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{modules.map((modulee) => (
|
||||
<MenuItem key={modulee} value={modulee}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'right' }}>
|
||||
{getIconForModule(modulee.name)}
|
||||
<span style={{ marginLeft: '10px' }}>{modulee.value}</span>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default MultipleSelectModule;
|
@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
@ -0,0 +1,13 @@
|
||||
const reportWebVitals = onPerfEntry => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
Loading…
Reference in New Issue