awslabs / iot-app-kit Goto Github PK
View Code? Open in Web Editor NEWA development library for creating web applications to visualize industrial data
License: Apache License 2.0
A development library for creating web applications to visualize industrial data
License: Apache License 2.0
Create the side pane which allows exploring resources (such as SiteWise assets/properties) for utilization in the dashboard (such as adding properties to dashboard widgets)
Followup requirements:
Make sure that the dashboard supports keyboard navigation.
Support:
Is your feature request related to a problem? Please describe.
ReactDOM.render
is no longer supported in react 18, but is utilized in the related table tests.
This causes the following warning
Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
Describe the solution you'd like
Follow guide https://reactjs.org/link/switch-to-createroot
Add support for a text widget in the dashboard.
Requirements:
Organize input fields. Handle resizing of setting panel.
As a user, I can view and configure viewports on the setting panel.
Describe the bug
When using LineChart or BarChart within a ReactJS display component, the axes and chart do not seem to be aligned.
To Reproduce
Steps to reproduce the behavior:
npx create-react-app my-app --template typescript
npm install @iot-app-kit/[email protected] @iot-app-kit/[email protected] @iot-app-kit/[email protected] @awsui/components-react @awsui/global-styles @aws-sdk/types
.env
file in project root with following contentsREACT_APP_AWS_ACCESS_KEY_ID=<replace-with-aws-access-key-id>
REACT_APP_AWS_SECRET_ACCESS_KEY=<replace-with-aws-access-key>
REACT_APP_AWS_SESSION_TOKEN=<replace-with-aws-session-token>
src/fromEnv.ts
as followsimport { CredentialProvider } from "@aws-sdk/types";
// REACT_APP prefix so that react-app picks them up by default
const ENV_KEY = "REACT_APP_AWS_ACCESS_KEY_ID";
const ENV_SECRET = "REACT_APP_AWS_SECRET_ACCESS_KEY";
const ENV_SESSION = "REACT_APP_AWS_SESSION_TOKEN";
const ENV_EXPIRATION = "REACT_APP_AWS_CREDENTIAL_EXPIRATION";
export const fromEnvReactApp = (): CredentialProvider => {
return () => {
const accessKeyId = process.env[ENV_KEY];
const secretAccessKey = process.env[ENV_SECRET];
const expiry = process.env[ENV_EXPIRATION];
if (accessKeyId && secretAccessKey) {
return Promise.resolve({
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey,
sessionToken: process.env[ENV_SESSION],
expiration: expiry ? new Date(expiry) : undefined,
});
};
return Promise.reject(new Error("Unable to find environment variable credentials. Expected REACT_APP_AWS_ACCESS_KEY_ID and REACT_APP_AWS_SECRET_ACCESS_KEY to be defined"));
}
}
App.tsx
file contents shown below to replace the App.tsx created by create-react-app
replacing Asset Ids and Asset Property Ids based on your sitewise assets.import { AppLayout, BreadcrumbGroup, Container, Grid, Header, TopNavigation } from "@awsui/components-react";
/* --- BEGIN: AWS @iot-app-kit and related implementation*/
import { initialize } from "@iot-app-kit/source-iotsitewise";
import { fromEnvReactApp } from "./fromEnv";
import { BarChart, LineChart, StatusTimeline, ResourceExplorer, WebglContext, } from "@iot-app-kit/react-components";
import "./App.css";
const { defineCustomElements } = require("@iot-app-kit/components/loader");
const { query } = initialize({
awsCredentials: fromEnvReactApp(),
awsRegion: "us-east-1",
});
defineCustomElements();
/* --- END: AWS @iot-app-kit and related implementation*/
function Breadcrumbs() {
const breadcrumbItems = [
{
text: 'Bottling Line',
href: '#'
},
{
text: 'Machine Dashboard',
href: '#'
}
];
return <BreadcrumbGroup items={breadcrumbItems} expandAriaLabel="Show path" ariaLabel="Breadcrumbs"/>;
}
function PageHeader() {
return <Header variant="h1">Machine Dashboard</Header>;
}
function SitwiseResourceExplorer() {
const columnDefinitions = [{
sortingField: 'name',
id: 'name',
header: 'Asset Name',
cell: ({ name }: any) => name,
}];
return (
<Container
disableContentPaddings={true}
header={ <Header variant="h2" description="List of sitewise assets"> Sitewise Assets </Header> }
>
{/* --- BEGIN: `ResourceExplorer` implementation*/}
<ResourceExplorer
query={query.assetTree.fromRoot()}
onSelectionChange={(event) => console.log("changes asset", event)}
columnDefinitions={columnDefinitions}
/>
{/* --- END: `ResourceExplorer` implementation*/}
</Container>
);
}
function MachineState(props: any) {
return (
<Container
disableContentPaddings={true}
header={ <Header variant="h2" description="Operational state of the machine as timeline"> Machine State </Header> }
>
{/* --- BEGIN: `StatusTimeline` implementation*/}
<StatusTimeline
viewport={{ duration: '15m' }}
// annotations={{
// y: [
// { color: '#FF0000', comparisonOperator: 'EQ', value: 30.45 },
// { color: '#0000FF', comparisonOperator: 'EQ', value: 2.93 },
// { color: '#00FF00', comparisonOperator: 'EQ', value: 2.93 },
// ]
// }}
queries={[
query.timeSeriesData({
assets: [{
assetId: props.assetId,
properties: [{
propertyId: props.propertyId
}]
}]
})
]}
/>
<WebglContext/>
{/* --- END: `StatusTimeline` implementation*/}
</Container>
);
}
function ProductionCount(props: any) {
return (
<Container disableContentPaddings={true} header={ <Header variant="h2" description="Count of total and bad output from machine"> Production Count </Header> } >
{/* --- BEGIN: `LineChart` implementation*/}
<BarChart
viewport={{ duration: "15m" }}
queries={[
query.timeSeriesData({
assets: [
{
assetId: props.assetId,
properties: [
{
propertyId: props.badPartsCountPropertyId,
refId: 'bad-parts-count'
},
{
propertyId: props.totalPartsCountPropertyId,
refId: 'total-parts-count'
},
],
},
],
}),
]}
styleSettings={{
'bad-parts-count': { color: '#d13212', name: 'Bad Count' },
'total-parts-count': { color: '#1d8102', name: 'Total Count' }
}}
/>
<WebglContext />
{/* --- END: `LineChart` implementation*/}
</Container>
);
}
function Content() {
// Replace the asset ids and asset property ids before you run the application
const WASHING_MACHINE_ASSET_ID = '<replace-with-sitwise-asset-id>';
const BAD_PARTS_COUNT_PROPERTY = '<replace-with-corresponding-sitwise-asset-property-id>';
const TOTAL_PARTS_COUNT_PROPERTY = '<replace-with-corresponding-sitwise-asset-property-id>';
const MACHINE_STATE_PROPERTY = '<replace-with-corresponding-sitwise-asset-property-id>';
return (
<Grid gridDefinition={[
{ colspan: { l: 2, m: 2, default: 12 } },
{ colspan: { l: 5, m: 5, default: 12 } },
{ colspan: { l: 5, m: 5, default: 12 } }
]}>
<SitwiseResourceExplorer/>
<MachineState
assetId={WASHING_MACHINE_ASSET_ID}
propertyId={MACHINE_STATE_PROPERTY}
/>
<ProductionCount
assetId={WASHING_MACHINE_ASSET_ID}
badPartsCountPropertyId={BAD_PARTS_COUNT_PROPERTY}
totalPartsCountPropertyId={TOTAL_PARTS_COUNT_PROPERTY}
/>
</Grid>
);
}
function App() {
return (
<>
<TopNavigation
identity={{
href: "#",
title: "AWS IoT Application Kit Demo",
}}
i18nStrings={{ overflowMenuTitleText: "More", overflowMenuTriggerText: "More" }}
/>
<AppLayout
breadcrumbs={<Breadcrumbs/>}
contentHeader={<PageHeader/>}
content={<Content/>}
navigationHide={true}
toolsHide={true}
/>
</>
);
}
export default App;
npm start
Expected behavior
<Container>
<AppLayout>
should occupy 100% of viewport height and widthScreenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
Describe the bug
When requesting aggregated data and panning an error is thrown to the console and datapoints are missing.
To Reproduce
Steps to reproduce the behavior:
<iot-line-chart
widgetId="line-chart"
viewport={{ duration: '10m' }}
queries={[
this.query.timeSeriesData({
assets: [
{
assetId: DEMO_ASSET,
properties: [
{
propertyId: DEMO_STRING_PROPERTY,
},
],
},
{
assetId: DEMO_ASSET,
properties: [
{
propertyId: DEMO_PROPERTY,
},
],
},
{
assetId: DEMO_ASSET2,
properties: [
{
propertyId: DEMO_PROPERTY,
},
],
},
{
assetId: DEMO_ASSET3,
properties: [
{
propertyId: DEMO_PROPERTY,
},
],
},
{
assetId: DEMO_ASSET4,
properties: [
{
propertyId: DEMO_PROPERTY,
},
],
},
],
}),
]}
/>
Expected behavior
String data is should not be aggregated and always be raw.
Screenshots
Port over the existing status grid cell to IoT App Kit, with the removal of the 'grid' functionality'
Enable dashboard to display iot-appkit components
The dashboard should render an iot-appkit component based on the dashboard configuration.
Port over web-component KPI cell as react component in IoT App Kit with the grid functionality removed.
Support for boolean and string data types in the SiteWise data source.
Is your feature request related to a problem? Please describe.
I want to display my sitewise assets in pages of size 10 as I have multiple production lines each containing 10 numbered assets. Displaying 20 assets by default leads to confusion among operators.
Describe the solution you'd like
I wish that an optional prop be introduced for IotResourceExplorer
or ResourceExplorer
with which I can define the page size when I pass paginationEnabled={true}
. This is currently blocked by a hardcoded pageSize
shown below from
if (this.paginationEnabled) {
collectionOptions.pagination = { pageSize: 20 };
}
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
I do not see any viable alternatives as of now.
Additional context
Add any other context or screenshots about the feature request here.
Describe the bug
The data is being requested but the viewport stops scrolling after a few minutes.
To Reproduce
Steps to reproduce the behavior:
yarn start
Expected behavior
The viewport scrolls to current time
Desktop (please complete the following information):
Create a context menu for quick actions in the dashboard.
Describe the bug
When you load a large size model in the Scene Viewer, the default camera logic can zoom so far out that the model itself is rendered outside the visible range of the viewer, resulting in it seeming not to have been rendered at all.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
Add any other context about the problem here.
Add unit tests to utili functions, UI tests to components, and integ tests.
As a user, I can configure Text widget on the setting panel.
Describe the bug
Can't build ReactJS Typescript project because of the following type checking error
Code
{/* --- BEGIN: `StatusTimeline` implementation*/}
<StatusTimeline
viewport={{ duration: '15m' }}
annotations={{
y: [
{ color: '#FF0000', comparisonOperator: 'EQ', value: 30.45 },
{ color: '#0000FF', comparisonOperator: 'EQ', value: 2.93 },
{ color: '#00FF00', comparisonOperator: 'EQ', value: 2.93 },
]
}}
queries={[
query.timeSeriesData({
assets: [{
assetId: props.assetId,
properties: [{
propertyId: props.propertyId
}]
}]
})
]}
/>
<WebglContext/>
{/* --- END: `StatusTimeline` implementation*/}
To Reproduce
Steps to reproduce the behavior:
StatusTimeline
component in ReactJS Typescript projectExpected behavior
Type check should be successful
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
Describe the bug
When a row is already expanded and expanded prop is set to true the icons turns to '+'
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The row should remain as '-'
Screenshots
Support message overriding on setting panel and provide default message override.
Add a component which presents a view only mode of the dashboard
Requirements
As a user I want to be able to select different data stream aggregations and resolutions and visualize multiple data streams of the same property across multiple aggregations and resolutions
TASK BLOCKED until completion of the Aggregate Data Milestone
Describe the bug
Widget viewport resets to live mode on first load, even after it is already interactive and gestures have been applied.
To Reproduce
Steps to reproduce the behavior:
Create a web page with an app kit component configured.
Expected behavior
Once a component is interactive, any panning should remain intact.
Desktop (please complete the following information):
Need to decide on the zero state UX for items in the dashboard (app kit widgets)
Hey guys, please update the image in README file, it didn't show TwinMaker scene viewer there :p
Describe the bug
Widgets (i.e line chart) are fetching data on a 1s interval by default, rather than 5s.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Default refresh rate should be 5s.
Desktop (please complete the following information):
Additional context
This may be caused by an interaction between synchro-charts live mode and app kit event handling.
<KPI dataStream associatedDataStream {...rest}/> - viz
...... - iot app kit
Create and add the panel to the dashboard which allows for the editing of widgets on the dashboard
Mockup:
Requirements:
Describe the bug
Data is being pushed upon every Live tick to iot-time-series-connector
when in Live mode. The prevDataCache
for hasRequestedInformationChanged()
is sometimes undefined, which causes hasRequestedInformationChanged
to always return true.
To Reproduce
Steps to reproduce the behavior:
hasRequestedInformationChanged
that details prevDataStreamStore
prevDataStreamStore
is occasionally undefined in consoleExpected behavior
Only new incoming data should be pushed to iot-time-series-connector
in Live mode. hasRequestedInformationChanged
should only return true if there's new incoming data that needs to be rendered, and prevDataCache
should only be undefined upon initialization of DataCache
.
Screenshots
example of prevDataStreamStore
being undefined while currDataStreamStore
is defined after letting App Kit run locally for a while.
Desktop (please complete the following information):
Additional context
The frequency of prevDataCache
being undefined depends on the duration of the viewport. The smaller the duration (e.g. 1 minute), the more often prevDataCache
is undefined (about every other tick).
Problem: IoT App Kit's use is limited by how the code is bundled preventing it from being used in some major build systems, such as vite.
Goal: Identify which build systems are critical to support, and make the changes necessary to support those build systems
Describe the bug
Resource explorer component styles aren't being included as expected in the libraries exported styles.css
file
Below is a screen shot of the incorrect styling:
To Reproduce
Utilize iot-resource-explorer
, does not display as expected. An example utilization of iot-app-kit with this occuring is within https://gitlab.aws.dev/proserve-es/awesome-sitewise-applications/amplify-iot-app-kit-demo
Describe the bug
iot-resource-explorer
jest tests failure, but only locally
@iot-app-kit/components: FAIL src/components/iot-resource-explorer/iot-resource-explorer.spec.ts
@iot-app-kit/components: ● Test suite failed to run
@iot-app-kit/components: Call retries were exceeded
@iot-app-kit/components: at ChildProcessWorker.initialize (../../node_modules/jest-worker/build/workers/ChildProcessWorker.js:193:21)
To Reproduce
Steps to reproduce the behavior:
yarn run test
from the workspace rootExpected behavior
All tests pass locally
Desktop (please complete the following information):
Describe the bug
SiteWise assets are sometmes present with an expand/collapse UX presented, with no children to be displayed.
To Reproduce
Steps to reproduce the behavior:
956523055275
in SiteWise Monitorarangol
, which demonstrates this behavior. click expand, and no children will renderExpected behavior
To not present the open/close UX when no children present
Screenshots
https://user-images.githubusercontent.com/77755322/191551255-5bdab249-2b89-4ccc-ba90-01e02a18e55b.mov
✅ reach decision on dataStream change by jan.9 2023
one to one relationship between a line on a widget and a dataStream
so one widget will have multiple dataStreams representing different aggregations and/or raw data
DataStream {
id: DataStreamId;
name: string;
detailedName?: string;
color?: string;
unit?: string;
data: DataPoint<T>[];
meta?: Record<string, string | number | boolean>;
resolution: number | undefined;*
dataType: DataType;
aggregationType: AggregationType | undefined;
streamType?: StreamType;
associatedStreams?: StreamAssociation[];
isLoading?: boolean;
isRefreshing?: boolean;
error?: string;
}
Is your feature request related to a problem? Please describe.
Currently a ReactJS app built with @iot-app-kit doesn't work when using ES6 style imports of @iot-app-kit/components/loader
...
import { defineCustomElements } from "@iot-app-kit/components/loader";
...
Because of the above missing feature we have to rely on ES5 style imports
...
const { defineCustomElements } = require("@iot-app-kit/components/loader");
...
Describe the solution you'd like
We would like ES6 style imports for @iot-app-kit/components/loader
to be supported i.e.,
import { defineCustomElements } from "@iot-app-kit/components/loader";
should be natively supported.
Describe alternatives you've considered
The only other available alternative is ES5 style imports as mentioned above.
Additional context
Add any other context or screenshots about the feature request here.
as a user I can see the asset property information (name, unit and color) for a widget when i select it
Is your feature request related to a problem? Please describe.
Resource explorer should support props for filtering a list of sitewise asset ids without relying on any relation to sitewise hierarchy trees. Consider the situation where a customer is building a dashboard for selected sitewise assets only from a large list of many assets they have in sitewise. Since, the customer would like to focus on limited assets for the custom dashboard, they don't want to display all sitewise assets by default when they use:
...
<ResourceExplorer
query={query.assetTree.fromRoot()}
columnDefinitions={columnDefinitions}
/>
...
Describe the solution you'd like
ResourceExplorer
component to pre-filter matching asset ids and display only matching assets on initial render.Describe alternatives you've considered
There are no documented alternatives as of now. All sitewise assets are displayed by default when using query.assetTree.fromRoot()
.
Additional context
Add any other context or screenshots about the feature request here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.