Skip to content

Commit

Permalink
feat: support auto-assigning colors for certain components (#96)
Browse files Browse the repository at this point in the history
* feat: support auto-assigning colors for certain components

* Update package.json
  • Loading branch information
diehbria committed May 5, 2022
1 parent 1a94387 commit 8df4f15
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 3 deletions.
2 changes: 2 additions & 0 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export namespace Components {
interface IotTestRoutes {
}
interface IotTimeSeriesConnector {
"assignDefaultColors": boolean | undefined;
"initialViewport": Viewport;
"provider": Provider<TimeSeriesData[]>;
"renderFunc": (data: TimeSeriesData) => void;
Expand Down Expand Up @@ -317,6 +318,7 @@ declare namespace LocalJSX {
interface IotTestRoutes {
}
interface IotTimeSeriesConnector {
"assignDefaultColors"?: boolean | undefined;
"initialViewport"?: Viewport;
"provider"?: Provider<TimeSeriesData[]>;
"renderFunc"?: (data: TimeSeriesData) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { bindStylesToDataStreams } from './bindStylesToDataStreams';
import { DATA_STREAM, DATA_STREAM_2 } from '../../testing/mockWidgetProperties';
import { colorPalette } from './colorPalette';

it('returns empty array when provided no data streams', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: false,
dataStreams: [],
styleSettings: { someStyle: { color: 'red' } },
})
Expand All @@ -13,6 +15,7 @@ it('returns empty array when provided no data streams', () => {
it('returns data streams when no matching styles', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: false,
dataStreams: [DATA_STREAM],
styleSettings: { someStyle: { color: 'red' } },
})
Expand All @@ -22,6 +25,7 @@ it('returns data streams when no matching styles', () => {
it('associates styles to corresponding data stream', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: false,
dataStreams: [{ ...DATA_STREAM, refId: 'someStyle' }],
styleSettings: { someStyle: { color: 'red' } },
})
Expand All @@ -31,6 +35,7 @@ it('associates styles to corresponding data stream', () => {
it('associates styles to corresponding data stream for multiple data streams', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: false,
dataStreams: [
{ ...DATA_STREAM, refId: 'someStyle' },
{ ...DATA_STREAM_2, refId: 'someStyle2' },
Expand All @@ -46,8 +51,51 @@ it('associates styles to corresponding data stream for multiple data streams', (
it('returns data stream when no matching refId', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: false,
dataStreams: [{ ...DATA_STREAM, refId: 'someStyle100' }],
styleSettings: { someStyle: { color: 'red' } },
})
).toEqual([{ ...DATA_STREAM, refId: 'someStyle100' }]);
});

describe('assignDefaultColors', () => {
it('does not assign color when set to false', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: false,
dataStreams: [{ ...DATA_STREAM, color: undefined }],
styleSettings: {},
})
).toEqual([expect.objectContaining({ color: undefined })]);
});

it('does not assign color when color on styleSettings is specified', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: true,
dataStreams: [{ ...DATA_STREAM, refId: 'someStyle', color: undefined }],
styleSettings: { someStyle: { color: 'some-color' } },
})
).toEqual([expect.objectContaining({ color: 'some-color' })]);
});

it('does not assign color when color on datastream', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: true,
dataStreams: [{ ...DATA_STREAM, color: 'some-color' }],
styleSettings: {},
})
).toEqual([expect.objectContaining({ color: 'some-color' })]);
});

it('does assign color when no color specified by data stream or style setting', () => {
expect(
bindStylesToDataStreams({
assignDefaultColors: true,
dataStreams: [{ ...DATA_STREAM, color: undefined }],
styleSettings: {},
})
).toEqual([expect.objectContaining({ color: colorPalette[0] })]);
});
});
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
import { StyleSettingsMap, DataStream } from '@iot-app-kit/core';
import { colorPalette } from './colorPalette';

const assignDefaultColor = ({
dataStream,
index,
styleSettings,
}: {
dataStream: DataStream;
index: number;
styleSettings?: StyleSettingsMap;
}): DataStream => {
const associatedStyles = dataStream.refId != null && styleSettings != null ? styleSettings[dataStream.refId] : {};
const hasAssociatedColor = 'color' in associatedStyles;

// Only provide default if one is not already present in the data stream, and none is specified in the associated style settings.
if (dataStream.color == null && !hasAssociatedColor) {
return {
...dataStream,
color: colorPalette[index % colorPalette.length],
};
}
return dataStream;
};

// If the data stream has a reference id with associated styles, append those styles to the data stream.
export const bindStylesToDataStreams = ({
dataStreams,
styleSettings,
assignDefaultColors,
}: {
dataStreams: DataStream[];
assignDefaultColors: boolean;
styleSettings?: StyleSettingsMap;
}): DataStream[] =>
dataStreams.map((dataStream) =>
}): DataStream[] => {
const streams = dataStreams.map((dataStream, i) =>
styleSettings == null || dataStream.refId == null
? dataStream
: {
...dataStream,
...styleSettings[dataStream.refId],
}
);

return assignDefaultColors
? streams.map((dataStream, index) => assignDefaultColor({ dataStream, index, styleSettings }))
: streams;
};
16 changes: 16 additions & 0 deletions packages/components/src/components/common/colorPalette.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// CSS Color strings, in default order they'll be used.
export const colorPalette = [
'#5e87b5',
'#e6ac8c',
'#7fc6b1',
'#d99090',
'#ae779c',
'#f9da95',
'#b088f5',
'#c55305',
'#018574',
'#486de8',
'#962249',
'#096f64',
'#8456ce',
];
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class IotBarChart {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => (
<sc-bar-chart
dataStreams={dataStreams as SynchroChartsDataStream[]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export class IotLineChart {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => {
return (
<sc-line-chart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export class IotScatterChart {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => {
return (
<sc-scatter-chart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class IotStatusTimeline {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => (
<sc-status-timeline
dataStreams={dataStreams as SynchroChartsDataStream[]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Components } from '../../components';
import { DescribeAssetResponse, DescribeAssetModelResponse } from '@aws-sdk/client-iotsitewise';
import { mockSiteWiseSDK } from '../../testing/mocks/siteWiseSDK';
import { DATA_STREAM, DATA_STREAM_2 } from '@iot-app-kit/core';
import { colorPalette } from '../common/colorPalette';

const createAssetResponse = ({
assetId,
Expand Down Expand Up @@ -300,3 +301,30 @@ it('binds styles to data streams', async () => {
viewport,
});
});

it('when assignDefaultColors is true, provides a default color', async () => {
const renderFunc = jest.fn();
const { assetId, propertyId } = toSiteWiseAssetProperty(DATA_STREAM.id);
const REF_ID = 'some-ref-id';

const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
});

await connectorSpecPage({
renderFunc,
provider: query
.timeSeriesData({ assets: [{ assetId, properties: [{ propertyId, refId: REF_ID }] }] })
.build('widget-id', { viewport, settings: { fetchMostRecentBeforeEnd: true } }),
assignDefaultColors: true,
});

expect(renderFunc).lastCalledWith({
dataStreams: [
expect.objectContaining({
color: colorPalette[0],
}),
],
viewport,
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export class IotTimeSeriesConnector {

@Prop() styleSettings: StyleSettingsMap | undefined;

@Prop() assignDefaultColors: boolean | undefined;

@State() data: TimeSeriesData = {
dataStreams: [],
viewport: DEFAULT_VIEWPORT,
Expand Down Expand Up @@ -60,7 +62,11 @@ export class IotTimeSeriesConnector {
} = this;

return this.renderFunc({
dataStreams: bindStylesToDataStreams({ dataStreams, styleSettings: this.styleSettings }),
dataStreams: bindStylesToDataStreams({
dataStreams,
styleSettings: this.styleSettings,
assignDefaultColors: this.assignDefaultColors || false,
}),
viewport,
});
}
Expand Down

0 comments on commit 8df4f15

Please sign in to comment.