Skip to content

Commit

Permalink
feature/saa-dataloggers (#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinJJackson authored Nov 8, 2023
1 parent 8aa0202 commit 633dd5b
Show file tree
Hide file tree
Showing 34 changed files with 1,205 additions and 70 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/app-bundles/chart-editor-bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,14 @@ const chartEditorBundle = {
}

const domainName = getDomainName(domains, parameter_id);
const unitName = domains['unit'].find(el => el.id === unit_id)?.value;

if (!chartData.find(x => x.name === parameter_id)) {
chartData.push({
id: series.id,
name: parameter_id,
domainName,
unitName,
unit: unit_id,
data: plotData,
});
Expand All @@ -364,6 +366,7 @@ const chartEditorBundle = {
id: series.id,
name: parameter_id,
domainName,
unitName,
unit: unit_id,
data: plotData,
});
Expand All @@ -377,6 +380,7 @@ const chartEditorBundle = {
id: series.id,
name: parameter_id,
domainName,
unitName,
unit: unit_id,
data: [...item.data, ...plotData],
});
Expand Down
27 changes: 23 additions & 4 deletions src/app-bundles/data-logger-equivalency-bundle.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { tUpdateError, tUpdateSuccess } from "../common/helpers/toast-helpers";

export default {
name: 'dataLoggerEquivalency',
getReducer: () => {
Expand Down Expand Up @@ -65,7 +67,7 @@ export default {
});
},

doUpdateDataLoggerEquivalency: (data) => ({ store, apiPut }) => {
doUpdateSingleDataLoggerEquivalency: (data) => ({ store, apiPut }) => {
const { dataLoggerId, id, fieldName, displayName, instrumentId, timeseriesId } = data;
const uri = `/datalogger/${dataLoggerId}/equivalency_table`;
// const toastId = toast.loading('Updating Field Mapping...');
Expand Down Expand Up @@ -95,9 +97,26 @@ export default {
});
},

// doDeleteDataLoggerEquivalency: ({ dataLoggerId }) => ({ dispatch, store, apiDelete }) => {
// const uri = `/datalogger/${dataLoggerId}/equivalency_table`;
// },
// For use in auto-assigning only.
doUpdateMultipleDataLoggerEquivalency: (dataLoggerId, rows, toastId) => ({ store, apiPut }) => {
const uri = `/datalogger/${dataLoggerId}/equivalency_table`;

const payload = {
datalogger_id: dataLoggerId,
rows,
};

apiPut(uri, payload, (err, _body) => {
if (err) {
// eslint-disable-next-line no-console
console.log('test err: ', JSON.stringify(err));
tUpdateError(toastId, 'Failed to assign timeseries to field names. Please try again later.');
} else {
tUpdateSuccess(toastId, 'Successfully assigned timeseries to field names!');
store.doFetchDataLoggerEquivalency({ dataLoggerId });
}
});
},

doDeleteDataLoggerEquivalencyRow: ({ dataLoggerId, id, refreshData = true }) => ({ store, apiDelete }) => {
const uri = `/datalogger/${dataLoggerId}/equivalency_table/row?id=${id}`;
Expand Down
2 changes: 2 additions & 0 deletions src/app-bundles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import instrumentGroupInstrumentsBundle from './instrument-group-instruments-bun
import instrumentGroupMapBundle from './instrument-group-map-bundle';
import instrumentMapBundle from './instrument-map-bundle';
import instrumentNotesBundle from './instrument-notes-bundle';
import instrumentSensorsBundle from './instrument-sensors-bundle';
import instrumentStatusBundle from './instrument-status-bundle';
import mapsBundle from './maps-bundle';
import modalBundle from './modal-bundle';
Expand Down Expand Up @@ -138,6 +139,7 @@ export default composeBundles(
instrumentGroupInstrumentsBundle,
instrumentMapBundle,
instrumentNotesBundle,
instrumentSensorsBundle,
instrumentStatusBundle,
mapsBundle,
modalBundle,
Expand Down
91 changes: 91 additions & 0 deletions src/app-bundles/instrument-sensors-bundle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
export default {
name: 'instrumentSensors',
getReducer: () => {
const initialState = {
sensors: [],
measurements: [],
_lastFetched: null,
};

return (state = initialState, { type, payload }) => {
switch (type) {
case 'INSTRUMENT_SENSORS_UPDATED':
return {
...state,
sensors: payload,
_lastFetched: new Date(),
};
case 'SENSOR_MEASUREMENTS_UPDATED':
return {
...state,
measurements: payload,
};
default:
return state;
}
};
},

selectInstrumentSensorsRaw: (state) => state.instrumentSensors,
selectInstrumentSensors: (state) => state.instrumentSensors.sensors,
selectInstrumentSensorsMeasurements: (state) => state.instrumentSensors.measurements,
selectInstrumentSensorsLastFetched: (state) => state.instrumentSensors._lastFetched,

doFetchInstrumentSensorsById: () => ({ dispatch, store, apiGet }) => {
dispatch({ type: 'INSTRUMENT_SENSORS_BY_ID_FETCH_START' });
const { instrumentId } = store.selectInstrumentsIdByRoute();

const url = `/instruments/saa/${instrumentId}/segments`;

apiGet(url, (err, body) => {
if (err) {
// eslint-disable-next-line no-console
console.log('error: ', err);
} else {
dispatch({
type: 'INSTRUMENT_SENSORS_UPDATED',
payload: body,
});
}

dispatch({ type: 'INSTRUMENT_SENSORS_BY_ID_FETCH_FINISHED' });
});
},

doUpdateInstrumentSensor: (formData) => ({ dispatch, store, apiPut }) => {
dispatch({ type: 'INSTRUMENT_SENSOR_UPDATE_START' });

const { instrumentId } = store.selectInstrumentsIdByRoute();
const url = `/instruments/saa/${instrumentId}/segments`;

apiPut(url, formData, (err, _body) => {
if (err) {
// eslint-disable-next-line no-console
console.log('todo', err);
} else {
store.doFetchInstrumentSensorsById();
}
});
},

doFetchInstrumentSensorMeasurements: (before, after) => ({ dispatch, store, apiGet }) => {
dispatch({ type: 'SENSOR_MEASUREMENTS_FETCH_START' });
const { instrumentId } = store.selectInstrumentsIdByRoute();
const url = `/instruments/saa/${instrumentId}/measurements?before=${before}&after=${after}`;

apiGet(url, (err, body) => {
if (err) {
// eslint-disable-next-line no-console
console.log('todo', err);
} else {
dispatch({
type: 'SENSOR_MEASUREMENTS_UPDATED',
payload: body,
});
}
});

dispatch({ type: 'SENSOR_MEASUREMENTS_FETCH_FINISHED' });

},
};
53 changes: 52 additions & 1 deletion src/app-bundles/time-series-bundle.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import createRestBundle from './create-rest-bundle';
import { createSelector } from 'redux-bundler';

import createRestBundle from './create-rest-bundle';
import { tLoading, tUpdateError, tUpdateManual } from '../common/helpers/toast-helpers';

export default createRestBundle({
name: 'instrumentTimeseries',
uid: 'id',
Expand All @@ -17,6 +19,7 @@ export default createRestBundle({
'INSTRUMENTGROUPS_FETCH_FINISHED',
'INSTRUMENTCONSTANTS_SAVE_FINISHED',
'INSTRUMENTTIMESERIES_SAVE_FINISHED',
'CREATED_NEW_TIMESERIES_FOR_FIELD_NAMES',
],
urlParamSelectors: ['selectProjectsIdByRoute'],
reduceFurther: (state, { type, payload }) => {
Expand All @@ -27,6 +30,54 @@ export default createRestBundle({
}
},
addons: {
doSaveFieldNamesToTimeseries: (newObject, instrumentId, dataLoggerId) => ({ dispatch, store, apiPost }) => {
dispatch({ type: 'ASSIGN_FIELD_NAMES_TO_TIMESERIES_START' });
const toastId = tLoading('Creating new timeseries...');
const { projectId } = store.selectProjectsIdByRoute();
const { newTs, existingTs } = newObject;

const uri = '/timeseries';
const formData = [];

newTs.forEach(item => formData.push({
project_id: projectId,
instrument_id: instrumentId,
name: item?.field_name,
}));

apiPost(uri, formData, (err, body) => {
if (err) {
tUpdateError(toastId, 'Failed to create new timeseries. Please try again later.');
// eslint-disable-next-line no-console
console.error(err);
} else {
dispatch({ type: 'CREATED_NEW_TIMESERIES_FOR_FIELD_NAMES' });
tUpdateManual(toastId, 'Assigning timeseries to field names...', { isLoading: true });
const rows = [];

rows.push(...newTs.map(el => ({
...el,
instrument_id: instrumentId,
timeseries_id: body.find(item => item.name === el.field_name)?.id,
})));

rows.push(...existingTs.map(el => {
const { field, timeseries } = el;

return {
...field,
instrument_id: instrumentId,
timeseries_id: timeseries?.id,
};
}));

store.doUpdateMultipleDataLoggerEquivalency(dataLoggerId, rows, toastId);
}
});

dispatch({ type: 'ASSIGN_FIELD_NAMES_TO_TIMESERIES_FINISHED' });
},

doInstrumentTimeseriesSetActiveId: (id) => ({ dispatch }) => {
dispatch({
type: 'INSTRUMENTTIMESERIES_SET_ACTIVE_ID',
Expand Down
6 changes: 2 additions & 4 deletions src/app-bundles/time-series-measurements-bundle.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { toast } from 'react-toastify';

import createRestBundle from './create-rest-bundle';
import { tUpdateError, tUpdateSuccess } from '../common/helpers/toast-helpers';
import { tLoading, tUpdateError, tUpdateSuccess } from '../common/helpers/toast-helpers';

const afterDate = '1900-01-01T00:00:00.00Z';
const beforeDate = '2025-12-31T00:00:00.00Z';
Expand Down Expand Up @@ -83,7 +81,7 @@ export default createRestBundle({

const url = `/projects/${projectId}/timeseries_measurements`;

const toastId = toast.loading('Uploading measurements...');
const toastId = tLoading('Uploading measurements. This may take a while for large data files...');

apiPost(url, measurements, (err, _body) => {
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion src/app-components/chart/viz-timeseries.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default connect(
data.length ? (
<Accordion.List className='m-2'>
{data.map(x => (
<Accordion.Item headingText={x.domainName} key={x.id}>
<Accordion.Item headingText={`${x.domainName} (in ${x.unitName})`} key={x.id}>
<div style={{ height: x.data[0].isInclinometer ? '800px' : '600px' }}>
{x.data[0].isInclinometer
? <Chart data={x.data} config={config} />
Expand Down
37 changes: 21 additions & 16 deletions src/app-components/domain-select.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { connect } from 'redux-bundler-react';
import Select from 'react-select';
import { Autocomplete, TextField } from '@mui/material';

export default connect(
'selectDomainsItemsByGroup',
({ value, onChange, domain, domainsItemsByGroup }) => {
({
domainsItemsByGroup,
defaultValue,
onChange,
domain,
}) => {
const [selectValue, setSelectValue] = useState();
const options = domainsItemsByGroup[domain]?.map(item => (
{ value: item.id, label: item.value }
));
)) || [];

const initValue = domainsItemsByGroup[domain]?.find(el => el.id === value);
useEffect(() => {
const item = domainsItemsByGroup[domain]?.find(el => el.value === selectValue);
onChange(item);
}, [selectValue]);

return (
<>
{!options || !options.length ? (
<i className='d-block pl-3'>No Options...</i>
) : (
<Select
isSearchable
defaultValue={initValue ? { value: initValue.id, label: initValue.value } : undefined}
onChange={val => onChange(val.value)}
placeholder='Select one...'
<Autocomplete
size='small'
defaultValue={options.find(el => el.value === defaultValue)}
isOptionEqualToValue={(opt, val) => opt.value === val.value}
onChange={e => setSelectValue(e.target.innerText)}
renderInput={(params) => <TextField {...params} placeholder='Select one...' />}
options={options}
styles={{
menuList: base => ({
...base,
maxHeight: '200px',
})
}}
fullWidth
/>
)}
</>
Expand Down
8 changes: 4 additions & 4 deletions src/app-pages/instrument/constants/constant-form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@ export default connect(
<div className='form-group'>
<label>Parameter</label>
<DomainSelect
value={parameter_id}
onChange={val => setParameterId(val)}
defaultValue={parameter_id}
onChange={val => setParameterId(val?.id)}
domain='parameter'
/>
</div>
<div className='form-group'>
<label>Unit</label>
<DomainSelect
value={unit_id}
onChange={val => setUnitId(val)}
defaultValue={unit_id}
onChange={val => setUnitId(val?.id)}
domain='unit'
/>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/app-pages/instrument/constants/constants.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import RoleFilter from '../../../app-components/role-filter';
import usePrevious from '../../../customHooks/usePrevious';

import '../../../css/grids.scss';
import '../instrument.css';

const Constants = connect(
'doModalOpen',
Expand Down Expand Up @@ -149,7 +150,7 @@ const Constants = connect(
icon={<Add fontSize='inherit' sx={{ marginBottom: '2px' }} />}
/>
</RoleFilter>
<ul className='list-group'>
<ul className='list-group limit-item-list'>
{constants.map((id, i) => (
<ConstantListItem
key={i}
Expand Down
Loading

0 comments on commit 633dd5b

Please sign in to comment.