add filters to fast search and disable data collection installations go bottom
This commit is contained in:
parent
3fbb2eeee0
commit
4a6caa9ed3
|
|
@ -96,8 +96,12 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by status (alarms first)
|
// Sort by status (alarms first); data-collection-disabled sinks below offline.
|
||||||
return filtered.sort((a, b) => {
|
return filtered.sort((a, b) => {
|
||||||
|
const aDisabled = a.dataCollectionEnabled === false;
|
||||||
|
const bDisabled = b.dataCollectionEnabled === false;
|
||||||
|
if (aDisabled !== bDisabled) return aDisabled ? 1 : -1;
|
||||||
|
|
||||||
const a_status = a.status;
|
const a_status = a.status;
|
||||||
const b_status = b.status;
|
const b_status = b.status;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
|
|
@ -31,34 +31,40 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
const [selectedInstallation, setSelectedInstallation] = useState<number>(-1);
|
const [selectedInstallation, setSelectedInstallation] = useState<number>(-1);
|
||||||
const currentLocation = useLocation();
|
const currentLocation = useLocation();
|
||||||
const baseRoute = props.product === 5 ? routes.sodistorepro_installations : routes.sodiohome_installations;
|
const baseRoute = props.product === 5 ? routes.sodistorepro_installations : routes.sodiohome_installations;
|
||||||
//
|
|
||||||
const sortedInstallations = [...props.installations].sort((a, b) => {
|
|
||||||
// Compare the status field of each installation and sort them based on the status.
|
|
||||||
//Installations with alarms go first
|
|
||||||
let a_status = a.status;
|
|
||||||
let b_status = b.status;
|
|
||||||
|
|
||||||
if (a_status > b_status) {
|
const sortedInstallations = useMemo(() => {
|
||||||
return -1;
|
return [...props.installations].sort((a, b) => {
|
||||||
}
|
// Data-collection-disabled installations sink below everything (even offline).
|
||||||
if (a_status < b_status) {
|
const aDisabled = a.dataCollectionEnabled === false;
|
||||||
return 1;
|
const bDisabled = b.dataCollectionEnabled === false;
|
||||||
}
|
if (aDisabled !== bDisabled) return aDisabled ? 1 : -1;
|
||||||
return 0;
|
|
||||||
});
|
// Then sort by status (alarms first)
|
||||||
|
const a_status = a.status;
|
||||||
|
const b_status = b.status;
|
||||||
|
|
||||||
|
if (a_status > b_status) return -1;
|
||||||
|
if (a_status < b_status) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}, [props.installations]);
|
||||||
|
|
||||||
const handleSelectOneInstallation = (installationID: number): void => {
|
const handleSelectOneInstallation = (installationID: number): void => {
|
||||||
if (selectedInstallation != installationID) {
|
if (selectedInstallation != installationID) {
|
||||||
setSelectedInstallation(installationID);
|
setSelectedInstallation(installationID);
|
||||||
setSelectedInstallation(-1);
|
setSelectedInstallation(-1);
|
||||||
|
|
||||||
|
const target = props.installations.find((i) => i.id === installationID);
|
||||||
|
const landingTab =
|
||||||
|
target?.dataCollectionEnabled === false ? routes.information : routes.live;
|
||||||
|
|
||||||
navigate(
|
navigate(
|
||||||
baseRoute +
|
baseRoute +
|
||||||
routes.list +
|
routes.list +
|
||||||
routes.installation +
|
routes.installation +
|
||||||
`${installationID}` +
|
`${installationID}` +
|
||||||
'/' +
|
'/' +
|
||||||
routes.live,
|
landingTab,
|
||||||
{
|
{
|
||||||
replace: true
|
replace: true
|
||||||
}
|
}
|
||||||
|
|
@ -77,18 +83,16 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const isListView =
|
||||||
|
currentLocation.pathname === baseRoute + 'list' ||
|
||||||
|
currentLocation.pathname === baseRoute + routes.list;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={1} sx={{ marginTop: 0.1 }}>
|
<Grid container spacing={1} sx={{ marginTop: 0.1 }}>
|
||||||
<Grid
|
<Grid
|
||||||
item
|
item
|
||||||
sx={{
|
sx={{
|
||||||
display:
|
display: isListView ? 'block' : 'none'
|
||||||
currentLocation.pathname ===
|
|
||||||
baseRoute + 'list' ||
|
|
||||||
currentLocation.pathname ===
|
|
||||||
baseRoute + routes.list
|
|
||||||
? 'block'
|
|
||||||
: 'none'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
|
|
|
||||||
|
|
@ -489,12 +489,14 @@ function SodioHomeInstallation(props: singleInstallationProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{loading &&
|
{loading &&
|
||||||
|
!dataCollectionDisabled &&
|
||||||
currentTab != 'information' &&
|
currentTab != 'information' &&
|
||||||
// currentTab != 'manage' &&
|
// currentTab != 'manage' &&
|
||||||
currentTab != 'history' &&
|
currentTab != 'history' &&
|
||||||
currentTab != 'log' &&
|
currentTab != 'log' &&
|
||||||
currentTab != 'report' &&
|
currentTab != 'report' &&
|
||||||
currentTab != 'installationTickets' && (
|
currentTab != 'installationTickets' &&
|
||||||
|
currentTab != 'documents' && (
|
||||||
<Container
|
<Container
|
||||||
maxWidth="xl"
|
maxWidth="xl"
|
||||||
sx={{
|
sx={{
|
||||||
|
|
@ -670,7 +672,7 @@ function SodioHomeInstallation(props: singleInstallationProps) {
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={'*'}
|
path={'*'}
|
||||||
element={<Navigate to={routes.live}></Navigate>}
|
element={<Navigate to={dataCollectionDisabled ? routes.information : routes.live}></Navigate>}
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { FormControl, Grid, InputAdornment, TextField } from '@mui/material';
|
import {
|
||||||
|
FormControl,
|
||||||
|
Grid,
|
||||||
|
InputAdornment,
|
||||||
|
InputLabel,
|
||||||
|
MenuItem,
|
||||||
|
Select,
|
||||||
|
TextField
|
||||||
|
} from '@mui/material';
|
||||||
import SearchTwoToneIcon from '@mui/icons-material/SearchTwoTone';
|
import SearchTwoToneIcon from '@mui/icons-material/SearchTwoTone';
|
||||||
import { useIntl } from 'react-intl';
|
import { FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { I_Installation } from '../../../interfaces/InstallationTypes';
|
import { I_Installation } from '../../../interfaces/InstallationTypes';
|
||||||
import { Route, Routes, useLocation } from 'react-router-dom';
|
import { Route, Routes, useLocation } from 'react-router-dom';
|
||||||
import routes from '../../../Resources/routes.json';
|
import routes from '../../../Resources/routes.json';
|
||||||
|
|
@ -16,9 +24,10 @@ interface installationSearchProps {
|
||||||
function InstallationSearch(props: installationSearchProps) {
|
function InstallationSearch(props: installationSearchProps) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [sortByStatus, setSortByStatus] = useState('All Installations');
|
||||||
|
const [sortByAction, setSortByAction] = useState('All Installations');
|
||||||
const currentLocation = useLocation();
|
const currentLocation = useLocation();
|
||||||
const baseRoute = props.product === 5 ? routes.sodistorepro_installations : routes.sodiohome_installations;
|
const baseRoute = props.product === 5 ? routes.sodistorepro_installations : routes.sodiohome_installations;
|
||||||
// const [filteredData, setFilteredData] = useState(props.installations);
|
|
||||||
|
|
||||||
const indexedData = useMemo(() => {
|
const indexedData = useMemo(() => {
|
||||||
return props.installations.map((item) => ({
|
return props.installations.map((item) => ({
|
||||||
|
|
@ -30,56 +39,126 @@ function InstallationSearch(props: installationSearchProps) {
|
||||||
}, [props.installations]);
|
}, [props.installations]);
|
||||||
|
|
||||||
const filteredData = useMemo(() => {
|
const filteredData = useMemo(() => {
|
||||||
return indexedData.filter(
|
let list = indexedData.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.nameLower.includes(searchTerm.toLowerCase()) ||
|
item.nameLower.includes(searchTerm.toLowerCase()) ||
|
||||||
item.locationLower.includes(searchTerm.toLowerCase()) ||
|
item.locationLower.includes(searchTerm.toLowerCase()) ||
|
||||||
item.regionLower.includes(searchTerm.toLowerCase())
|
item.regionLower.includes(searchTerm.toLowerCase())
|
||||||
);
|
);
|
||||||
}, [searchTerm, indexedData]);
|
|
||||||
|
switch (sortByStatus) {
|
||||||
|
case 'Installations With Alarm':
|
||||||
|
list = list.filter((i) => i.status === 2);
|
||||||
|
break;
|
||||||
|
case 'Installations with Warning':
|
||||||
|
list = list.filter((i) => i.status === 1);
|
||||||
|
break;
|
||||||
|
case 'Functional Installations':
|
||||||
|
list = list.filter((i) => i.status === 0);
|
||||||
|
break;
|
||||||
|
case 'Offline Installations':
|
||||||
|
list = list.filter((i) => i.status === -1);
|
||||||
|
break;
|
||||||
|
case 'Installations Without Data Collection':
|
||||||
|
list = list.filter((i) => i.dataCollectionEnabled === false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sortByAction) {
|
||||||
|
case 'Installations With Action Flag':
|
||||||
|
list = list.filter((i) => i.testingMode === true);
|
||||||
|
break;
|
||||||
|
case 'Installations Without Action Flag':
|
||||||
|
list = list.filter((i) => i.testingMode === false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}, [searchTerm, indexedData, sortByStatus, sortByAction]);
|
||||||
|
|
||||||
|
const isListView =
|
||||||
|
currentLocation.pathname === baseRoute + 'list' ||
|
||||||
|
currentLocation.pathname === baseRoute + routes.list;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid container>
|
{isListView && (
|
||||||
<Grid
|
<Grid container>
|
||||||
item
|
<Grid item xs={12}>
|
||||||
xs={12}
|
<div
|
||||||
md={6}
|
style={{
|
||||||
sx={{
|
display: 'flex',
|
||||||
display:
|
flexDirection: 'row',
|
||||||
currentLocation.pathname ===
|
alignItems: 'center',
|
||||||
baseRoute + 'list' ||
|
gap: '16px',
|
||||||
currentLocation.pathname ===
|
width: '100%',
|
||||||
baseRoute + routes.list
|
flexWrap: 'wrap'
|
||||||
? 'block'
|
}}
|
||||||
: 'none'
|
>
|
||||||
}}
|
<FormControl variant="outlined" sx={{ width: 280 }}>
|
||||||
>
|
<TextField
|
||||||
<div
|
placeholder={intl.formatMessage({ id: 'search' })}
|
||||||
style={{
|
value={searchTerm}
|
||||||
display: 'flex',
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
flexDirection: 'column',
|
fullWidth
|
||||||
alignItems: 'flex-start'
|
InputProps={{
|
||||||
}}
|
startAdornment: (
|
||||||
>
|
<InputAdornment position="start">
|
||||||
<FormControl variant="outlined">
|
<SearchTwoToneIcon />
|
||||||
<TextField
|
</InputAdornment>
|
||||||
placeholder={intl.formatMessage({ id: 'search' })}
|
)
|
||||||
value={searchTerm}
|
}}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
/>
|
||||||
fullWidth
|
</FormControl>
|
||||||
InputProps={{
|
|
||||||
startAdornment: (
|
<FormControl sx={{ width: 280 }}>
|
||||||
<InputAdornment position="start">
|
<InputLabel>
|
||||||
<SearchTwoToneIcon />
|
<FormattedMessage id="sortByStatus" defaultMessage="Sort By Status" />
|
||||||
</InputAdornment>
|
</InputLabel>
|
||||||
)
|
<Select
|
||||||
}}
|
value={sortByStatus}
|
||||||
/>
|
onChange={(e) => setSortByStatus(e.target.value)}
|
||||||
</FormControl>
|
label={intl.formatMessage({ id: 'sortByStatus' })}
|
||||||
</div>
|
>
|
||||||
|
{[
|
||||||
|
'All Installations',
|
||||||
|
'Installations With Alarm',
|
||||||
|
'Installations with Warning',
|
||||||
|
'Functional Installations',
|
||||||
|
'Offline Installations',
|
||||||
|
'Installations Without Data Collection'
|
||||||
|
].map((type) => (
|
||||||
|
<MenuItem key={type} value={type}>
|
||||||
|
{type}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl sx={{ width: 280 }}>
|
||||||
|
<InputLabel>
|
||||||
|
<FormattedMessage id="sortByActionFlag" defaultMessage="Sort By Action Flag" />
|
||||||
|
</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={sortByAction}
|
||||||
|
onChange={(e) => setSortByAction(e.target.value)}
|
||||||
|
label={intl.formatMessage({ id: 'sortByActionFlag' })}
|
||||||
|
>
|
||||||
|
{[
|
||||||
|
'All Installations',
|
||||||
|
'Installations With Action Flag',
|
||||||
|
'Installations Without Action Flag'
|
||||||
|
].map((type) => (
|
||||||
|
<MenuItem key={type} value={type}>
|
||||||
|
{type}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
)}
|
||||||
|
|
||||||
<FlatInstallationView installations={filteredData} product={props.product} />
|
<FlatInstallationView installations={filteredData} product={props.product} />
|
||||||
<Routes>
|
<Routes>
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,16 @@ function InstallationTree() {
|
||||||
useContext(InstallationsContext);
|
useContext(InstallationsContext);
|
||||||
|
|
||||||
const sortedInstallations = [...foldersAndInstallations].sort((a, b) => {
|
const sortedInstallations = [...foldersAndInstallations].sort((a, b) => {
|
||||||
// Compare the status field of each installation and sort them based on the status.
|
// Folders stay on top (existing behavior).
|
||||||
//Installations with alarms go first
|
|
||||||
|
|
||||||
if (a.type == 'Folder') {
|
if (a.type == 'Folder') {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// Data-collection-disabled installations sink below everything (even offline).
|
||||||
|
const aDisabled = (a as any).dataCollectionEnabled === false;
|
||||||
|
const bDisabled = (b as any).dataCollectionEnabled === false;
|
||||||
|
if (aDisabled !== bDisabled) return aDisabled ? 1 : -1;
|
||||||
|
|
||||||
|
// Then sort by status (alarms first).
|
||||||
let a_status = a.status;
|
let a_status = a.status;
|
||||||
let b_status = b.status;
|
let b_status = b.status;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue