Skip to content

Commit

Permalink
feature/cwms-data-integration (#231)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinJJackson authored Aug 9, 2024
1 parent 82b90e2 commit ab980a4
Show file tree
Hide file tree
Showing 18 changed files with 698 additions and 66 deletions.
4 changes: 4 additions & 0 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ VITE_REPORT_DOWNLOAD=false
VITE_API_URL=https://midas.sec.usace.army.mil/api
VITE_URL_BASE_PATH=/midas


# EXTERNAL APIS
VITE_CWMS_API_URL=https://cwms-data.usace.army.mil/cwms-data

# Keycloak
VITE_KC_URL=https://identity.sec.usace.army.mil/auth/
VITE_KC_REALM=cwbi
Expand Down
3 changes: 3 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ VITE_REPORT_DOWNLOAD=false
VITE_API_URL=https://midas-test.cwbi.us/api
VITE_URL_BASE_PATH=/midas

# EXTERNAL APIS
VITE_CWMS_API_URL=https://cwms-data.usace.army.mil/cwms-data

# Keycloak
VITE_KC_URL=https://identity-test.cwbi.us/auth/
VITE_KC_REALM=cwbi
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
VITE_DEVELOPMENT_BANNER: true
VITE_REPORT_DOWNLOAD: true
VITE_API_URL: https://develop-midas-api.rsgis.dev
VITE_CWMS_API_URL: https://cwms-data.usace.army.mil/cwms-data
VITE_URL_BASE_PATH: ''
VITE_KC_URL: https://identity-test.cwbi.us/auth/
VITE_KC_REALM: cwbi
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hhd-ui",
"version": "0.16.1",
"version": "0.17.0",
"private": true,
"dependencies": {
"@ag-grid-community/client-side-row-model": "^30.0.3",
Expand Down
8 changes: 5 additions & 3 deletions src/app-components/domain-select.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ export default connect(
useLabelAsDefault = false,
onChange,
domain,
label = '',
...customProps
}) => {
const options = domainsItemsByGroup[domain]?.map(item => (
{ value: item.id, label: item.value }
)) || [];

return (
<>
<div {...customProps}>
{!options || !options.length ? (
<i className='d-block pl-3'>No Options...</i>
) : (
Expand All @@ -28,12 +30,12 @@ export default connect(
const item = domainsItemsByGroup[domain]?.find(el => el.value === value?.label);
onChange(item);
}}
renderInput={(params) => <TextField {...params} placeholder='Select one...' />}
renderInput={(params) => <TextField {...params} label={label} placeholder='Select one...' />}
options={options}
fullWidth
/>
)}
</>
</div>
);
}
);
156 changes: 156 additions & 0 deletions src/app-pages/instrument/cwms-timeseries/cwmsTimeseries.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import React, { useRef, useState } from 'react';
import ReactDatePicker from 'react-datepicker';
import { AgGridReact } from '@ag-grid-community/react';
import { Button } from '@mui/material';
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
import { connect } from 'redux-bundler-react';
import { DateTime } from 'luxon';
import { endOfDay, startOfDay, subDays } from 'date-fns';
import { Icon } from '@iconify/react';

import CwmsTimeseriesListItem from './cwmsTimeseriesListItem.jsx';
import NewCwmsTimeseriesModal from './newCwmsTimeseries.jsx';
import { useGetMidasCwmsTimeseries, useGetCwmsTimeseriesMeasurements } from '../../../app-services/collections/cwms-timeseries.ts';

const CwmsTimeseries = connect(
'doModalOpen',
'selectProjectsIdByRoute',
'selectInstrumentsByRoute',
({
doModalOpen,
projectsIdByRoute: project,
instrumentsByRoute: instrument,
}) => {
const grid = useRef(null);

const { projectId } = project || {};
const { id } = instrument || {};

const [activeTimeseries, setActiveTimeseries] = useState(null);
const [dateRange, setDateRange] = useState([subDays(startOfDay(new Date()), 1), endOfDay(new Date())]);

const { data: midasTimeseries } = useGetMidasCwmsTimeseries({ projectId, instrumentId: id });
const { data: cwmsMeasurements, isLoading } = useGetCwmsTimeseriesMeasurements(
{
name: activeTimeseries?.cwms_timeseries_id,
office: activeTimeseries?.cwms_office_id,
begin: DateTime.fromJSDate(dateRange[0]).toISO(),
end: DateTime.fromJSDate(dateRange[1]).toISO(),
},
{ enabled: !!activeTimeseries?.cwms_timeseries_id },
);

const { values = [] } = cwmsMeasurements || {};

const data = values.map(el => {
if (el?.length < 2) return null;

return {
timestamp: DateTime.fromMillis(el[0]).toFormat('D HH:mm:ss'),
value: el[1],
};
}).filter(e => e);

return (
<>
<div className='row'>
<div className='col-12'>
CWMS Timeseries are timeseries from the external source, <b>Corps Water Management System (CWMS)</b>, that are manually associated to instruments within the MIDAS
system. Use this panel to manage the connected timeseries and view the data associated with them. While connections can be made, the data it provides is strictly read-only.
</div>
</div>
<div className='row mt-2'>
<div className='col-3'>
<Button
size='small'
color='success'
variant='outlined'
onClick={() => doModalOpen(NewCwmsTimeseriesModal, { projectId, instrumentId: id })}
>
+ New CWMS Timeseries
</Button>
</div>
<div className='col-9'>
{!!activeTimeseries?.id && (
<div className='row no-gutters'>
<div className='col-3'>
<ReactDatePicker
placeholderText='mm/dd/yyyy'
className='form-control'
minDate={activeTimeseries?.extents?.earliest_time}
maxDate={dateRange[1]}
selected={dateRange[0]}
onChange={(date) => setDateRange(prev => [startOfDay(date), prev[1]])}
/>
</div>
<div className='pt-1'>
&emsp;-&emsp;
</div>
<div className='col-3'>
<ReactDatePicker
placeholderText='mm/dd/yyyy'
className='form-control'
maxDate={Date.now()}
minDate={dateRange[0]}
selected={dateRange[1]}
onChange={(date) => setDateRange(prev => [prev[0], endOfDay(date)])}
/>
</div>
</div>
)}
</div>
</div>
<div className='row mt-2'>
<div className='col-3'>
<ul className='list-group limit-item-list'>
{midasTimeseries?.length ? (
<>
{midasTimeseries.map(t => (
<CwmsTimeseriesListItem
key={t.id}
active={activeTimeseries?.id === t.id}
item={t}
onClick={item => setActiveTimeseries(activeTimeseries?.id === t.id ? null : item)}
/>
))}
</>
) : (
<i>No Timeseries Configured</i>
)}
</ul>
</div>
<div className='col-9'>
{isLoading ? (
<div className='w-100 pt-4 d-flex justify-content-center' style={{ minHeight: '225px' }}>
<Icon icon='eos-icons:loading' fontSize={30} />
</div>
) : (
<div
className='ag-theme-balham'
style={{
minHeight: '225px',
height: '85%',
width: '100%',
}}
>
<AgGridReact
ref={grid}
columnDefs={[{
field: 'timestamp'
}, {
field: 'value',
}]}
rowData={data || []}
modules={[ClientSideRowModelModule]}
suppressRowClickSelection
/>
</div>
)}
</div>
</div>
</>
);
},
);

export default CwmsTimeseries;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useRef } from 'react';
import { connect } from 'redux-bundler-react';
import { Edit } from '@mui/icons-material';

import RoleFilter from '../../../app-components/role-filter';
import { classnames } from '../../../common/helpers/utils';
import NewCwmsTimeseriesModal from './newCwmsTimeseries';

export default connect(
'selectProjectsByRoute',
'doModalOpen',
({ projectsByRoute: project, doModalOpen, item, onClick, active }) => {
const li = useRef(null);
const itemClass = classnames({
'pointer': true,
'list-group-item': true,
active: active,
});

return (
item && (
<li
ref={li}
className={itemClass}
onClick={(e) => {
if (e.currentTarget === li.current) onClick(item);
}}
>
<RoleFilter allowRoles={[`${project.slug.toUpperCase()}.*`]}>
<button
className='float-right btn btn-sm btn-outline-info'
onClick={e => {
doModalOpen(NewCwmsTimeseriesModal, { projectId: project.id, instrumentId: item.instrument_id, item, isEdit: true });
e.stopPropagation();
}}
>
<Edit fontSize='inherit' />
</button>
</RoleFilter>
<div>{item.name}</div>
<div>
<small>{`${item.parameter} in ${item.unit}`}</small>
</div>
</li>
)
);
}
);
Loading

0 comments on commit ab980a4

Please sign in to comment.