Skip to content

Commit

Permalink
feat(dashboard): csv data hook
Browse files Browse the repository at this point in the history
  • Loading branch information
corteggiano authored and diehbria committed Nov 21, 2023
1 parent 7d7918d commit 33379af
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
16 changes: 16 additions & 0 deletions packages/dashboard/src/components/csvDownloadButton/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Primitive } from '@iot-app-kit/core';

export type CSVDownloadObject = {
id: string;
timestamp: string;
value?: Primitive;
unit?: string;
aggregationType?: string;
resolution?: number;
propertyName?: string;
assetName?: string;
propertyAlias?: string;
assetId?: string;
dataType?: string;
propertyId?: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Viewport, parseDuration, DataStream, DataPoint } from '@iot-app-kit/core';
import { useTimeSeriesData, useViewport } from '@iot-app-kit/react-components';
import { StyledSiteWiseQueryConfig } from '~/customization/widgets/types';
import { useAssetDescriptionMapQuery } from '~/hooks/useAssetDescriptionQueries';
import { useQueries } from '~/components/dashboard/queryContext';
import { CSVDownloadObject } from './types';

const DEFAULT_VIEWPORT = { duration: '10m' };

// Format Date to be a string in format: "YYYY/MM/DD HH:MM:SS"
export const formatDate = (date: Date) => {
const dateString = date.getFullYear().toString() + '/' + (date.getMonth() + 1) + '/' + date.getDate();
const timeString = date.toTimeString().split(' ')[0];
const dateTime = dateString + ' ' + timeString;
return dateTime;
};

// Check if time is within passed in viewport OR within last x amount of time from request
const isTimeWithinViewport = (dataPointTimestamp: number, viewport: Viewport, timeOfRequestMS: number) => {
const currentPoint = new Date(dataPointTimestamp);
if ('duration' in viewport) {
// absolute time range
const duration = parseDuration(viewport.duration);
return currentPoint >= new Date(timeOfRequestMS - duration) && currentPoint <= new Date(timeOfRequestMS);
} else {
// relative time range
return currentPoint >= viewport.start && currentPoint <= viewport.end;
}
};

export const useViewportData = ({
queryConfig,
viewport: passedInViewport,
}: {
queryConfig: StyledSiteWiseQueryConfig;
viewport?: Viewport;
}) => {
const queries = useQueries(queryConfig.query);

const { dataStreams } = useTimeSeriesData({ queries });

const describedAssetsMapQuery = useAssetDescriptionMapQuery(queryConfig.query);
const describedAssetsMap = describedAssetsMapQuery.data ?? {};

const { viewport: injectedViewport } = useViewport();
const viewport = passedInViewport || injectedViewport || DEFAULT_VIEWPORT;

// flatten all the data in a single dataStream into one array of CSVDownloadObject
const flattenDataPoints = (dataStream: DataStream, timeOfRequestMS: number) => {
const { id, unit, resolution, aggregationType, data } = dataStream;

return data.reduce((flattenedData: CSVDownloadObject[], currentDataPoint: DataPoint) => {
const { x: xValue, y: yValue } = currentDataPoint;
const pointWithinViewport = isTimeWithinViewport(xValue, viewport, timeOfRequestMS);

// do not include data point if it falls outside viewport range
if (pointWithinViewport) {
const isUnmodeledData = queryConfig.query?.properties?.some((pr) => pr.propertyAlias === dataStream.id);
const assetPropId = !isUnmodeledData ? dataStream.id.split('---') : []; // modeled datastream IDs follow the pattern {assetID}---{propertyID}
const describedModelProperty = describedAssetsMap[assetPropId[0]]?.properties.find(
(p) => p.propertyId === assetPropId[1]
);

const flatDataPoint: CSVDownloadObject = {
id,
value: yValue,
unit,
timestamp: formatDate(new Date(xValue)),
aggregationType,
resolution,
assetId: !isUnmodeledData ? assetPropId[0] : undefined,
propertyId: !isUnmodeledData ? assetPropId[1] : undefined,
dataType: describedModelProperty?.dataType,
propertyName: describedModelProperty?.name,
assetName: describedAssetsMap[assetPropId[0]]?.assetName,
propertyAlias: describedModelProperty?.alias,
};

flattenedData.push(flatDataPoint);
}
return flattenedData;
}, [] as CSVDownloadObject[]);
};

const fetchViewportData = (timeOfRequestMS: number) => {
return dataStreams.reduce((flattenedStreams: CSVDownloadObject[], currentDataStream: DataStream) => {
flattenedStreams.push(...flattenDataPoints(currentDataStream, timeOfRequestMS));
return flattenedStreams;
}, [] as CSVDownloadObject[]);
};

return {
fetchViewportData,
};
};

0 comments on commit 33379af

Please sign in to comment.