From 6b1cfd73e3c0397ddd600f590a3c4da65570b92c Mon Sep 17 00:00:00 2001 From: Kevin Jackson <30411845+KevinJJackson@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:46:18 -0500 Subject: [PATCH] enhancement/formula-list-filtering (#240) --- package.json | 2 +- .../navigation/secondaryNavBar.jsx | 2 +- src/app-pages/instrument/formula/formula.jsx | 90 ++++++++++++--- src/app-pages/instrument/settings.jsx | 104 ++++++++++++++---- 4 files changed, 160 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index cc3ea43a..f382f2a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hhd-ui", - "version": "0.17.5", + "version": "0.17.6", "private": true, "dependencies": { "@ag-grid-community/client-side-row-model": "^30.0.3", diff --git a/src/app-components/navigation/secondaryNavBar.jsx b/src/app-components/navigation/secondaryNavBar.jsx index 7cfc9e36..5979fda7 100644 --- a/src/app-components/navigation/secondaryNavBar.jsx +++ b/src/app-components/navigation/secondaryNavBar.jsx @@ -19,7 +19,7 @@ const CustomTabPanel = props => { )} ); -} +}; const SecondaryNavBar = connect( 'selectHashStripQuery', diff --git a/src/app-pages/instrument/formula/formula.jsx b/src/app-pages/instrument/formula/formula.jsx index 7773c099..b36f50d0 100644 --- a/src/app-pages/instrument/formula/formula.jsx +++ b/src/app-pages/instrument/formula/formula.jsx @@ -1,9 +1,35 @@ -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { connect } from 'redux-bundler-react'; +import { Accordion, AccordionDetails, AccordionSummary, Autocomplete, TextField } from '@mui/material'; +import { ArrowDropDown } from '@mui/icons-material'; import Button from '../../../app-components/button'; import FormulaCard from './formulaCard'; +const generateTimeseriesOptions = timeseries => { + return timeseries.map(ts => ({ + label: `${ts.instrument} - ${ts.name}`, + value: ts.id, + variable: ts.variable, + instrumentName: ts.instrument, + })); +}; + +const groupTimeseries = (timeseries = []) => { + return timeseries.reduce((accum, current) => { + const { instrument_id, instrument } = current; + + + return { + ...accum, + [instrument_id]: { + name: instrument, + timeseries: [...(accum[instrument_id]?.timeseries || []), current], + }, + }; + }, {}); +}; + export default connect( 'doModalOpen', 'doInstrumentFormulasSave', @@ -19,7 +45,11 @@ export default connect( nonComputedTimeseriesItemsByRoute: timeseries, }) => { const [activeFormula, setActiveFormula] = useState(null); - const sortedTimeseries = timeseries.sort((a, b) => String(a.variable).localeCompare(b.variable)); + const [searchString, setSeachString] = useState(undefined); + + const groupedTs = groupTimeseries(timeseries); + const groupKeys = Object.keys(groupedTs).sort((a, b) => groupedTs[a].name.localeCompare(groupedTs[b].name)); + const options = useMemo(() => generateTimeseriesOptions(timeseries).sort((a, b) => -b.label.localeCompare(a.label)), [timeseries]); const createNewFormula = () => { doInstrumentFormulasSave({ @@ -30,6 +60,7 @@ export default connect( }; const insertParam = (param) => { + if (!activeFormula) return; const { input, formula, setFormula } = activeFormula; const start = input.current.selectionStart; @@ -51,17 +82,50 @@ export default connect( Available parameters
- + opt.instrumentName} + getOptionLabel={opt => opt.label} + options={options} + value={undefined} + onChange={(e, val) => { + if (val) { + insertParam(`[${val.variable}]`); + } + setSeachString(undefined); + }} + renderInput={(params) => ( + setSeachString(e.target.value)} + variant='outlined' + label='Select a timeseries...' + /> + )} + /> + { + groupKeys.map(group => ( + + }>{groupedTs[group].name} + +
    + {groupedTs[group].timeseries.sort((a, b) => String(a.variable).localeCompare(b.variable)).map((ts, i) => ( +
  • insertParam(`[${ts.variable}]`)} + > + {ts.variable} +
  • + ))} +
+
+
+ )) + } +
{instrumentFormulasItems.length ? ( diff --git a/src/app-pages/instrument/settings.jsx b/src/app-pages/instrument/settings.jsx index 9e22d711..1cdcd5ca 100644 --- a/src/app-pages/instrument/settings.jsx +++ b/src/app-pages/instrument/settings.jsx @@ -1,5 +1,6 @@ -import React from 'react'; +import React, { useState } from 'react'; import { connect } from 'redux-bundler-react'; +import { Box, Tab, Tabs, tabsClasses } from '@mui/material'; import AlertEditor from './alert/alert-editor'; import Card from '../../app-components/card'; @@ -7,10 +8,27 @@ import Chart from './chart/chart'; import Constants from './constants/constants'; import CwmsTimeseries from './cwms-timeseries/cwmsTimeseries'; import FormulaEditor from './formula/formula'; -import TabContainer from '../../app-components/tab'; import Timeseries from './timeseries/timeseries'; import Sensors from './sensors/sensors'; +const CustomTabPanel = props => { + const { children, value, active } = props; + + return ( + + ); +}; + export default connect( 'selectTimeseriesMeasurementsItemsObject', 'selectInstrumentsByRoute', @@ -18,47 +36,87 @@ export default connect( timeseriesMeasurementsItemsObject: measurements, instrumentsByRoute: instrument, }) => { - const { type, show_cwms_tab } = instrument || {}; - - // const alertsReady = import.meta.env.VITE_ALERT_EDITOR === 'true'; const alertsReady = false; + // const alertsReady = import.meta.env.VITE_ALERT_EDITOR === 'true'; const forumlaReady = import.meta.env.VITE_FORMULA_EDITOR === 'true'; const chartReady = import.meta.env.VITE_INSTRUMENT_CHART === 'true'; + + const { type, show_cwms_tab } = instrument || {}; + const [activeTab, setActiveTab] = useState(alertsReady ? 'Alerts' : 'Constants'); + const isShapeArray = type === 'SAA'; const isIPI = type === 'IPI'; const tabs = [ - alertsReady && { + { title: 'Alerts', - content: + isVisible: alertsReady, }, { title: 'Constants', - content: + isVisible: true, }, { title: 'Timeseries', - content: , - }, show_cwms_tab && { + isVisible: true, + }, { title: 'CWMS Timeseries', - content: , - }, (isShapeArray || isIPI) && { + isVisible: show_cwms_tab, + }, { title: 'Sensors', - content: , - }, forumlaReady && { + isVisible: (isShapeArray || isIPI), + }, { title: 'Formula Editor', - content: , - }, chartReady && { + isVisible: forumlaReady, + }, { title: 'Chart', - content: , + isVisible: chartReady, } - ].filter(e => e); + ]; return ( - + + + setActiveTab(val)} + variant='scrollable' + scrollButtons='auto' + sx={{ + [`& .${tabsClasses.scrollButtons}`]: { + '&.Mui-disabled': { opacity: 0.25 }, + }, + }} + > + {tabs.map(tab => { + const { title, isVisible } = tab; + + return isVisible ? : null; + }).filter(e => e)} + + + {/* Mapping over these doesnt work... interesting */} + + + + + + + + + + + + + + + + + + + + + + ); }