src/app/devices/module/moduleIdentityList/components/moduleIdentityList.tsx (190 lines of code) (raw):
/***********************************************************
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License
**********************************************************/
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { NavLink, useLocation, useHistory, useRouteMatch } from 'react-router-dom';
import { IColumn, SelectionMode, CommandBar, Label } from '@fluentui/react';
import { ResizableDetailsList } from '../../../../shared/resizeDetailsList/resizableDetailsList';
import { ResourceKeys } from '../../../../../localization/resourceKeys';
import { getDeviceIdFromQueryString } from '../../../../shared/utils/queryStringHelper';
import { REFRESH, ArrayOperation } from '../../../../constants/iconNames';
import { SynchronizationStatus } from '../../../../api/models/synchronizationStatus';
import { parseDateTimeString } from '../../../../api/dataTransforms/transformHelper';
import { ModuleIdentity } from '../../../../api/models/moduleIdentity';
import { MultiLineShimmer } from '../../../../shared/components/multiLineShimmer';
import { ROUTE_PARTS, ROUTE_PARAMS } from '../../../../constants/routes';
import { HeaderView } from '../../../../shared/components/headerView';
import { useAsyncSagaReducer } from '../../../../shared/hooks/useAsyncSagaReducer';
import { moduleIndentityListStateInitial } from '../state';
import { getModuleIdentitiesSaga } from '../saga';
import { moduleIdentityListReducer } from '../reducer';
import { getModuleIdentitiesAction } from '../actions';
import { AppInsightsClient } from '../../../../shared/appTelemetry/appInsightsClient';
import { TELEMETRY_PAGE_NAMES } from '../../../../../app/constants/telemetry';
import '../../../../css/_deviceDetail.scss';
export const ModuleIdentityList: React.FC = () => {
const { t } = useTranslation();
const { search, pathname } = useLocation();
const { url } = useRouteMatch();
const history = useHistory();
const deviceId = getDeviceIdFromQueryString(search);
const [ localState, dispatch ] = useAsyncSagaReducer(moduleIdentityListReducer, getModuleIdentitiesSaga, moduleIndentityListStateInitial(), 'moduleIdentityListState');
const moduleIdentityList = localState.payload;
const synchronizationStatus = localState.synchronizationStatus;
React.useEffect(() => {
dispatch(getModuleIdentitiesAction.started(deviceId));
}, [deviceId]);
React.useEffect(() => {
AppInsightsClient.getInstance()?.trackPageView({name: TELEMETRY_PAGE_NAMES.MODULE_LIST});
}, []); // tslint:disable-line: align
const showCommandBar = () => {
return (
<CommandBar
className="command"
items={[
{
ariaLabel: t(ResourceKeys.moduleIdentity.command.add),
iconProps: {iconName: ArrayOperation.ADD},
key: ArrayOperation.ADD,
name: t(ResourceKeys.moduleIdentity.command.add),
onClick: handleAdd
},
{
ariaLabel: t(ResourceKeys.moduleIdentity.command.refresh),
disabled: synchronizationStatus === SynchronizationStatus.working,
iconProps: {iconName: REFRESH},
key: REFRESH,
name: t(ResourceKeys.moduleIdentity.command.refresh),
onClick: handleRefresh
}
]}
/>
);
};
const handleAdd = () => {
const path = pathname.concat(ROUTE_PARTS.ADD);
history.push(`${path}/?${ROUTE_PARAMS.DEVICE_ID}=${encodeURIComponent(deviceId)}`);
};
const handleRefresh = () => {
dispatch(getModuleIdentitiesAction.started(deviceId));
};
const renderGrid = () => {
return (
<div className="device-detail">
<div className="list-detail">
<ResizableDetailsList
columns={getColumns()}
items={moduleIdentityList}
selectionMode={SelectionMode.none}
onRenderItemColumn={renderItemColumn}
/>
</div>
{synchronizationStatus === SynchronizationStatus.working && <MultiLineShimmer/>}
{synchronizationStatus === SynchronizationStatus.fetched && moduleIdentityList.length === 0 && t(ResourceKeys.moduleIdentity.noModules)}
{synchronizationStatus === SynchronizationStatus.failed && t(ResourceKeys.moduleIdentity.errorFetching)}
</div>
);
};
const getModuleDetailPageUrl = (item: ModuleIdentity) => {
return `${url.endsWith('/') ? url : url + '/'}${ROUTE_PARTS.MODULE_DETAIL}/?${ROUTE_PARAMS.DEVICE_ID}=${encodeURIComponent(deviceId)}&${ROUTE_PARAMS.MODULE_ID}=${item.moduleId}`;
};
// tslint:disable-next-line: cyclomatic-complexity
const renderItemColumn = (item: ModuleIdentity, index: number, column: IColumn) => {
switch (column.key) {
case 'moduleId':
return (
<NavLink
key={column.key}
to={getModuleDetailPageUrl(item)}
>
{item.moduleId}
</NavLink>
);
case 'connectionState':
return (
<Label
key={column.key}
>
{item.connectionState}
</Label>
);
case 'connectionStateLastUpdated':
return (
<Label
key={column.key}
>
{parseDateTimeString(item.connectionStateUpdatedTime) || '--'}
</Label>
);
case 'lastActivityTime':
return (
<Label
key={column.key}
>
{parseDateTimeString(item.lastActivityTime) || '--'}
</Label>
);
case 'modelId':
return (
<Label
key={column.key}
>
{item.modelId || '--'}
</Label>
);
default:
return <></>;
}
};
const getColumns = (): IColumn[] => {
const columns: IColumn[] = [
{
ariaLabel: t(ResourceKeys.moduleIdentity.columns.moduleId),
fieldName: 'moduleId',
key: 'moduleId',
maxWidth: 200,
minWidth: 50,
name: t(ResourceKeys.moduleIdentity.columns.moduleId),
},
{
ariaLabel: t(ResourceKeys.moduleIdentity.columns.connectionState),
fieldName: 'connectionState',
key: 'connectionState',
maxWidth: 200,
minWidth: 50,
name: t(ResourceKeys.moduleIdentity.columns.connectionState)
},
{
ariaLabel: t(ResourceKeys.moduleIdentity.columns.connectionStateLastUpdated),
fieldName: 'connectionStateLastUpdated',
key: 'connectionStateLastUpdated',
maxWidth: 250,
minWidth: 150,
name: t(ResourceKeys.moduleIdentity.columns.connectionStateLastUpdated)
},
{
ariaLabel: t(ResourceKeys.moduleIdentity.columns.lastActivityTime),
fieldName: 'lastActivityTime',
key: 'lastActivityTime',
maxWidth: 250,
minWidth: 150,
name: t(ResourceKeys.moduleIdentity.columns.lastActivityTime)
},
{
ariaLabel: t(ResourceKeys.moduleIdentity.columns.modelId),
fieldName: 'modelId',
key: 'modelId',
maxWidth: 250,
minWidth: 150,
name: t(ResourceKeys.moduleIdentity.columns.modelId)
}];
return columns;
};
return (
<>
{showCommandBar()}
<HeaderView
headerText={ResourceKeys.moduleIdentity.headerText}
link={ResourceKeys.moduleIdentity.link}
tooltip={ResourceKeys.moduleIdentity.tooltip}
/>
{renderGrid()}
</>
);
};