Skip to content

Commit

Permalink
feat: Sitewise Resource Explorer (#21)
Browse files Browse the repository at this point in the history
Co-authored-by: Fernando Pauer <pauerf@amazon.com>
  • Loading branch information
fpauer and Fernando Pauer committed Dec 21, 2021
1 parent b7899f1 commit 8f26b58
Show file tree
Hide file tree
Showing 12 changed files with 439 additions and 170 deletions.
55 changes: 43 additions & 12 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { AnyDataStreamQuery, AssetSummaryQuery, AssetTreeSubscription, DataModule, Request, RequestConfig, SiteWiseAssetTreeQuery } from "@iot-app-kit/core";
import { DataStream, MinimalViewPortConfig } from "@synchro-charts/core";
import { TableProps } from "@awsui/components-react/table";
import { EmptyStateProps, UseTreeCollection } from "@iot-app-kit/related-table";
import { NonCancelableCustomEvent, TextFilterProps } from "@awsui/components-react";
import { EmptyStateProps, ITreeNode, UseTreeCollection } from "@iot-app-kit/related-table";
import { FilterTexts } from "./components/iot-resource-explorer/types";
import { NonCancelableCustomEvent } from "@awsui/components-react";
export namespace Components {
interface IotAssetDetails {
"query": AssetSummaryQuery;
Expand Down Expand Up @@ -86,24 +87,30 @@ export namespace Components {
"collectionOptions": UseTreeCollection<unknown>;
"columnDefinitions": TableProps.ColumnDefinition<unknown>[];
"empty": EmptyStateProps;
"filter": TextFilterProps;
"filterTexts": FilterTexts;
"isItemDisabled": (item: unknown) => boolean;
"items": unknown[];
"loading": boolean;
"loadingText": string;
"onExpandChildren": (node: unknown) => void;
"onExpandChildren": (node: ITreeNode<any>) => void;
"onSelectionChange": (event: NonCancelableCustomEvent<TableProps.SelectionChangeDetail<unknown>>) => void;
"onSortingChange": (event: NonCancelableCustomEvent<TableProps.SortingState<unknown>>) => void;
"resizableColumns": boolean;
"selectedItems": unknown[];
"selectionType": TableProps.SelectionType;
"sortingColumn": TableProps.SortingColumn<unknown>;
"sortingDescending": boolean;
"sortingDisabled": boolean;
"wrapLines": boolean;
}
interface IotTreeTableDemo {
}
interface SitewiseResourceExplorer {
"empty"?: EmptyStateProps;
"filterTexts"?: FilterTexts;
"loadingText"?: string;
"query": SiteWiseAssetTreeQuery;
"selectionType"?: TableProps.SelectionType;
}
interface SitewiseResourceExplorerDemo {
}
interface TestingGround {
}
}
Expand Down Expand Up @@ -186,6 +193,18 @@ declare global {
prototype: HTMLIotTreeTableDemoElement;
new (): HTMLIotTreeTableDemoElement;
};
interface HTMLSitewiseResourceExplorerElement extends Components.SitewiseResourceExplorer, HTMLStencilElement {
}
var HTMLSitewiseResourceExplorerElement: {
prototype: HTMLSitewiseResourceExplorerElement;
new (): HTMLSitewiseResourceExplorerElement;
};
interface HTMLSitewiseResourceExplorerDemoElement extends Components.SitewiseResourceExplorerDemo, HTMLStencilElement {
}
var HTMLSitewiseResourceExplorerDemoElement: {
prototype: HTMLSitewiseResourceExplorerDemoElement;
new (): HTMLSitewiseResourceExplorerDemoElement;
};
interface HTMLTestingGroundElement extends Components.TestingGround, HTMLStencilElement {
}
var HTMLTestingGroundElement: {
Expand All @@ -206,6 +225,8 @@ declare global {
"iot-test-routes": HTMLIotTestRoutesElement;
"iot-tree-table": HTMLIotTreeTableElement;
"iot-tree-table-demo": HTMLIotTreeTableDemoElement;
"sitewise-resource-explorer": HTMLSitewiseResourceExplorerElement;
"sitewise-resource-explorer-demo": HTMLSitewiseResourceExplorerDemoElement;
"testing-ground": HTMLTestingGroundElement;
}
}
Expand Down Expand Up @@ -285,24 +306,30 @@ declare namespace LocalJSX {
"collectionOptions": UseTreeCollection<unknown>;
"columnDefinitions": TableProps.ColumnDefinition<unknown>[];
"empty"?: EmptyStateProps;
"filter"?: TextFilterProps;
"filterTexts"?: FilterTexts;
"isItemDisabled"?: (item: unknown) => boolean;
"items": unknown[];
"loading"?: boolean;
"loadingText"?: string;
"onExpandChildren"?: (node: unknown) => void;
"onExpandChildren"?: (node: ITreeNode<any>) => void;
"onSelectionChange"?: (event: NonCancelableCustomEvent<TableProps.SelectionChangeDetail<unknown>>) => void;
"onSortingChange"?: (event: NonCancelableCustomEvent<TableProps.SortingState<unknown>>) => void;
"resizableColumns"?: boolean;
"selectedItems"?: unknown[];
"selectionType"?: TableProps.SelectionType;
"sortingColumn"?: TableProps.SortingColumn<unknown>;
"sortingDescending"?: boolean;
"sortingDisabled"?: boolean;
"wrapLines"?: boolean;
}
interface IotTreeTableDemo {
}
interface SitewiseResourceExplorer {
"empty"?: EmptyStateProps;
"filterTexts"?: FilterTexts;
"loadingText"?: string;
"query"?: SiteWiseAssetTreeQuery;
"selectionType"?: TableProps.SelectionType;
}
interface SitewiseResourceExplorerDemo {
}
interface TestingGround {
}
interface IntrinsicElements {
Expand All @@ -319,6 +346,8 @@ declare namespace LocalJSX {
"iot-test-routes": IotTestRoutes;
"iot-tree-table": IotTreeTable;
"iot-tree-table-demo": IotTreeTableDemo;
"sitewise-resource-explorer": SitewiseResourceExplorer;
"sitewise-resource-explorer-demo": SitewiseResourceExplorerDemo;
"testing-ground": TestingGround;
}
}
Expand All @@ -339,6 +368,8 @@ declare module "@stencil/core" {
"iot-test-routes": LocalJSX.IotTestRoutes & JSXBase.HTMLAttributes<HTMLIotTestRoutesElement>;
"iot-tree-table": LocalJSX.IotTreeTable & JSXBase.HTMLAttributes<HTMLIotTreeTableElement>;
"iot-tree-table-demo": LocalJSX.IotTreeTableDemo & JSXBase.HTMLAttributes<HTMLIotTreeTableDemoElement>;
"sitewise-resource-explorer": LocalJSX.SitewiseResourceExplorer & JSXBase.HTMLAttributes<HTMLSitewiseResourceExplorerElement>;
"sitewise-resource-explorer-demo": LocalJSX.SitewiseResourceExplorerDemo & JSXBase.HTMLAttributes<HTMLSitewiseResourceExplorerDemoElement>;
"testing-ground": LocalJSX.TestingGround & JSXBase.HTMLAttributes<HTMLTestingGroundElement>;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const collectionOptions = {
},
};

const treeTableSpecPage = async (propOverrides: Partial<Components.IotBarChart> = {}) => {
const treeTableSpecPage = async () => {
const page = await newSpecPage({
components: [IotTreeTable],
html: '<div></div>',
Expand All @@ -73,7 +73,6 @@ const treeTableSpecPage = async (propOverrides: Partial<Components.IotBarChart>
collectionOptions,
columnDefinitions,
selectionType: 'single',
...propOverrides,
};
update(treeTable, props);
page.body.appendChild(treeTable);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Host, h, Element, Prop } from '@stencil/core';
import { Component, Host, h, Element, Prop, State } from '@stencil/core';
import ReactDOM from 'react-dom';
import React from 'react';
import {
Expand All @@ -7,71 +7,77 @@ import {
RelatedTableExtendedProps,
withUseTreeCollection,
UseTreeCollection,
ITreeNode,
} from '@iot-app-kit/related-table';
import { TableProps } from '@awsui/components-react/table';
import { NonCancelableCustomEvent, TextFilterProps } from '@awsui/components-react';
import { NonCancelableCustomEvent } from '@awsui/components-react';
import { FilterTexts } from './types';

const RelatedTableWithCollectionHooks = withUseTreeCollection(RelatedTable);

@Component({
tag: 'iot-tree-table',
})
export class IotTreeTable {
@Element() host: HTMLElement;
@State() selectedItems: unknown[] = [];

@Prop() items!: unknown[];
@Prop() columnDefinitions!: TableProps.ColumnDefinition<unknown>[];
@Prop() collectionOptions!: UseTreeCollection<unknown>;

@Prop() loading: boolean;
@Prop() loadingText: string;
@Prop() filterTexts: FilterTexts;

@Prop() empty: EmptyStateProps;
@Prop() filter: TextFilterProps;

@Prop() selectedItems: unknown[];
@Prop() selectionType: TableProps.SelectionType;
@Prop() empty: EmptyStateProps;

@Prop() isItemDisabled: (item: unknown) => boolean;
@Prop() wrapLines: boolean;
@Prop() resizableColumns: boolean;
@Prop() sortingColumn: TableProps.SortingColumn<unknown>;
@Prop() sortingDescending: boolean;
@Prop() sortingDisabled: boolean;
@Prop() ariaLabels: TableProps.AriaLabels<unknown>;

@Prop() onSelectionChange: (event: NonCancelableCustomEvent<TableProps.SelectionChangeDetail<unknown>>) => void;
@Prop() onExpandChildren: (node: unknown) => void;
@Prop() onExpandChildren: (node: ITreeNode<any>) => void;
@Prop() onSortingChange: (event: NonCancelableCustomEvent<TableProps.SortingState<unknown>>) => void;

componentDidLoad() {
this.componentDidUpdate();
}

componentDidUpdate() {
const properties: RelatedTableExtendedProps<unknown> = {
const attributes = {
items: this.items,
collectionOptions: this.collectionOptions,
columnDefinitions: this.columnDefinitions,

empty: this.empty,
filter: this.filter,
collectionOptions: this.collectionOptions,

loading: this.loading,
loadingText: this.loadingText,
filterPlaceholder: this.filterTexts?.placeholder,

selectionType: this.selectionType,
selectedItems: this.selectedItems,

empty: this.empty,
isItemDisabled: this.isItemDisabled,
wrapLines: this.wrapLines,
resizableColumns: this.resizableColumns,
sortingColumn: this.sortingColumn,
sortingDescending: this.sortingDescending,
sortingDisabled: this.sortingDisabled,
ariaLabels: this.ariaLabels,

expandChildren: this.onExpandChildren,
onSelectionChange: this.onSelectionChange,
onSortingChange: this.onSortingChange,
};
ReactDOM.render(React.createElement(withUseTreeCollection(RelatedTable), properties), this.host);
onSelectionChange: (event: NonCancelableCustomEvent<TableProps.SelectionChangeDetail<unknown>>) => {
this.selectedItems = event.detail.selectedItems;
if (this.onSelectionChange) {
this.onSelectionChange(event);
}
},
} as RelatedTableExtendedProps<unknown>;

ReactDOM.render(React.createElement(RelatedTableWithCollectionHooks, attributes), this.host);
}

render() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { initialize } from '@iot-app-kit/core';
import { MockSiteWiseAssetModule, MockSiteWiseAssetsReplayData } from '@iot-app-kit/core/asset-modules/mocks.spec';
import * as core from '@iot-app-kit/core';
import { newSpecPage } from '@stencil/core/testing';
import { SitewiseResourceExplorer } from './sitewise-resource-explorer';
import { Components } from '../../components.d';
import { CustomHTMLElement } from '../../testing/types';
import { update } from '../../testing/update';

const awsCredentials = {
accessKeyId: 'accessKeyId',
secretAccessKey: 'secretAccessKey',
sessionToken: 'sessionToken',
};

jest.mock('@iot-app-kit/core', () => {
const originalModule = jest.requireActual('@iot-app-kit/core');

return {
...originalModule,
getSiteWiseAssetModule: () => {
return new MockSiteWiseAssetModule(new MockSiteWiseAssetsReplayData());
},
};
});

const sitewiseResourceExplorerSpec = async (injectProps: any) => {
const page = await newSpecPage({
components: [SitewiseResourceExplorer],
html: '<div></div>',
supportsShadowDom: false,
});
const query: core.SiteWiseAssetTreeQuery = { rootAssetId: undefined };
const sitewiseResourceExplorer = page.doc.createElement(
'sitewise-resource-explorer'
) as CustomHTMLElement<Components.SitewiseResourceExplorer>;
const props: Partial<Components.SitewiseResourceExplorer> = {
...injectProps,
query,
};
update(sitewiseResourceExplorer, props);
page.body.appendChild(sitewiseResourceExplorer);

await page.waitForChanges();

return { page, sitewiseResourceExplorer };
};

beforeAll(() => {
initialize({ awsCredentials, awsRegion: 'us-east-1' });
});

it('renders', async () => {
const { sitewiseResourceExplorer } = await sitewiseResourceExplorerSpec();
const elements = sitewiseResourceExplorer.querySelectorAll('iot-tree-table');
expect(elements.length).toBe(1);
});

it('renders with custom copy', async () => {
const { sitewiseResourceExplorer } = await sitewiseResourceExplorerSpec({
selectionType: 'single',
loadingText: 'loading...',
filterText: {
placeholder: 'Filter by name',
empty: 'No assets found.',
noMatch: `We can't find a match.`,
},
empty: {
header: 'No assets',
description: `You don't have any asset.`,
},
});
const elements = sitewiseResourceExplorer.querySelectorAll('iot-tree-table');
expect(elements.length).toBe(1);
});

0 comments on commit 8f26b58

Please sign in to comment.