Skip to content

Commit

Permalink
feat(react-component): adding drag and delete to TC
Browse files Browse the repository at this point in the history
  • Loading branch information
mnischay committed Jul 13, 2023
1 parent c62e68b commit 7c6a017
Show file tree
Hide file tree
Showing 14 changed files with 325 additions and 64 deletions.
10 changes: 5 additions & 5 deletions configuration/jest-config/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export default {
moduleNameMapper: {
'\\.(css|scss)$': 'identity-obj-proxy',
},
"coverageThreshold": {
"global": {
"lines": 50
}
}
coverageThreshold: {
global: {
lines: 50,
},
},
};
4 changes: 4 additions & 0 deletions packages/react-components/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const config = {
lines: 80,
},
},
transform: {
...reactConfig.transform,
'^.+\\.svg$': '<rootDir>/svgTransform.js',
},
};

export default config;
35 changes: 35 additions & 0 deletions packages/react-components/src/components/chart/Chart.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';

import { mockTimeSeriesDataQuery } from '@iot-app-kit/testing-util';
import { DataStream } from '@iot-app-kit/core';
import Chart from './index';
import { render } from '@testing-library/react';

const VIEWPORT = { duration: '5m' };

const DATA_STREAM: DataStream = { id: 'abc-1', data: [], resolution: 0, name: 'my-name' };
jest.mock('echarts', () => ({
use: jest.fn(),
init: jest.fn(),
getInstanceByDom: jest.fn(),
registerTheme: jest.fn(),
}));

afterEach(() => {
jest.clearAllMocks();
});

describe('Chart Component Testing', () => {
it('Chart renders', async () => {
const query = mockTimeSeriesDataQuery([
{
dataStreams: [DATA_STREAM],
viewport: VIEWPORT,
thresholds: [],
},
]);

const element = render(<Chart queries={[query]} viewport={VIEWPORT} size={{ width: 500, height: 500 }} />);
expect(element).not.toBeNull();
});
});
6 changes: 4 additions & 2 deletions packages/react-components/src/components/chart/baseChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const Chart = ({ viewport, queries, size, ...options }: ChartOptions) => {
);
const [trendCursors, setTrendCursors] = useState(options.graphic ?? []);
const [isInCursorAddMode, setIsInCursorAddMode] = useState(false);

const option = {
...convertOptions({
...options,
Expand All @@ -49,9 +50,10 @@ const Chart = ({ viewport, queries, size, ...options }: ChartOptions) => {
option,
loading: isLoading,
size,
theme: options?.theme,
});

useTrendCursors(ref, trendCursors, size, isInCursorAddMode, setTrendCursors, viewport);
useTrendCursors(ref, trendCursors, size, isInCursorAddMode, setTrendCursors, viewport, options.theme);

const handlers = {
commandDown: () => setIsInCursorAddMode(true),
Expand All @@ -60,7 +62,7 @@ const Chart = ({ viewport, queries, size, ...options }: ChartOptions) => {

return (
<HotKeys keyMap={keyMap} handlers={handlers}>
<div ref={ref} style={{ width: size?.width, height: size?.height }} />
<div ref={ref} style={{ height: size.height, width: size.width }} />
</HotKeys>
);
};
Expand Down
3 changes: 3 additions & 0 deletions packages/react-components/src/components/chart/close.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 11 additions & 5 deletions packages/react-components/src/components/chart/eChartsConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const DEFAULT_DATA_ZOOM: DataZoomComponentOption = {
moveOnMouseWheel: false,
};

export const DEFAULT_ECHART_OPTIONS: EChartsOption = {
export const DEFAULT_ECHARTS_OPTIONS: EChartsOption = {
xAxis: [DEFAULT_X_AXIS],
yAxis: [DEFAULT_Y_AXIS],
legend: DEFAULT_LEGEND,
Expand All @@ -62,9 +62,15 @@ export const DEFAULT_ECHART_OPTIONS: EChartsOption = {
};

// Trend Cursor constants
export const trendCursorHeaderColors = ['#DA7596', '#2EA597', '#688AE8'];
export const trendCursorHeaderColors = ['#DA7596', '#2EA597', '#688AE8', '#A783E1', '#E07941'];
export const trendCursorLineColor = '#5F6B7A';
export const trendCursorNameWidth = 60;
export const trendCursorNameHeight = 20;
export const trendCursorHeaderWidth = 110;
export const trendCursorHeaderHeight = 110;
export const trendCursorLineWidth = 2;
export const trendCursorZIndex = 4;
export const trendCursorZIndex = 100;
export const MAX_TREND_CURSORS = 5;

export const trendCursorHeaderTextColor = 'white';
export const trendCursorHeaderBackgroundColor = 'black';
export const trendCursorCloseButtonYOffset = DEFAULT_MARGIN + 2.5;
export const trendCursorCloseButtonXOffset = 40;
19 changes: 17 additions & 2 deletions packages/react-components/src/components/chart/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Threshold, ThresholdSettings, TimeSeriesDataQuery, Viewport } from '@iot-app-kit/core';
import { GraphicComponentOption } from 'echarts';
import {
GraphicComponentImageOption,
GraphicComponentTextOption,
GraphicComponentZRPathOption,
} from 'echarts/types/src/component/graphic/GraphicModel';
import { OptionId } from 'echarts/types/src/util/types';

export type YAxisOptions = {
yAxisLabel?: string;
Expand Down Expand Up @@ -63,6 +68,15 @@ export type ChartStyleSettings = {
[refId: string]: ChartStyleSettingsOptions;
};

export type InternalGraphicComponentGroupOption = { timestampInMs: number } & {
children: Array<GraphicComponentTextOption | GraphicComponentImageOption | GraphicComponentZRPathOption>;
id: string;
$action: string;
type: string;
};

export type ChartEventType = { target: { id?: OptionId }; offsetX?: number };

export type ChartOptions = {
queries: TimeSeriesDataQuery[];
defaultVisualizationType?: Visualization;
Expand All @@ -78,5 +92,6 @@ export type ChartOptions = {
fontSettings?: SimpleFontSettings;
legend?: ChartLegend;
significantDigits?: number;
graphic?: GraphicComponentOption[];
graphic?: InternalGraphicComponentGroupOption[];
theme?: string;
};
40 changes: 23 additions & 17 deletions packages/react-components/src/components/chart/useTrendCursors.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,51 @@
import React, { Dispatch, SetStateAction, useEffect } from 'react';
import { EChartsType, getInstanceByDom, GraphicComponentOption } from 'echarts';
import { EChartsType, getInstanceByDom } from 'echarts';
import { addNewTrendCursor } from './utils/getInfo';
import { Viewport } from '@iot-app-kit/core';
import { SizeConfig } from './types';
import { InternalGraphicComponentGroupOption, SizeConfig } from './types';
import { MAX_TREND_CURSORS } from './eChartsConstants';

const useTrendCursors = (
ref: React.RefObject<HTMLDivElement>,
graphic: GraphicComponentOption[],
graphic: InternalGraphicComponentGroupOption[],
size: SizeConfig,
isInCursorAddMode: boolean,
setGraphic: Dispatch<SetStateAction<GraphicComponentOption[]>>,
viewport?: Viewport
setGraphic: Dispatch<SetStateAction<InternalGraphicComponentGroupOption[]>>,
viewport?: Viewport,
theme?: string
) => {
const mouseoverHandler = (isInCursorAddMode: boolean, chart?: EChartsType) => {
if (isInCursorAddMode) {
chart?.getZr().setCursorStyle('crosshair');
} else {
chart?.getZr().setCursorStyle('auto');
}
};
useEffect(() => {
let chart: EChartsType | undefined;
if (ref.current !== null) {
chart = getInstanceByDom(ref.current);

chart?.getZr().on('click', (e) => {
if (isInCursorAddMode) {
setGraphic([...graphic, addNewTrendCursor(e, size, viewport)]);
if (isInCursorAddMode && graphic.length < MAX_TREND_CURSORS) {
setGraphic(addNewTrendCursor(e, size, graphic.length, graphic, setGraphic, viewport, chart));
}
});

chart?.getZr().on('mousemove', () => {
if (isInCursorAddMode) {
chart?.getZr().setCursorStyle('crosshair');
} else {
chart?.getZr().setCursorStyle('auto');
}
});
chart?.getZr().on('mousemove', () => mouseoverHandler(isInCursorAddMode, chart));
}

return () => {
if (ref.current !== null) {
chart?.getZr().off('click');
// intentionally not removing the "moverover" event as shown below, this will remove the default show tooltip behaviour
// chart?.getZr().off('mouseover');
chart?.getZr().off('mouseover', () => mouseoverHandler(isInCursorAddMode, chart));
}
};
}, [ref, graphic, size, isInCursorAddMode]);
}, [ref, graphic, size, isInCursorAddMode, setGraphic, viewport, theme]);

useEffect(() => {
console.log(graphic);
}, [graphic]);
};

export default useTrendCursors;
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { describe, expect } from '@jest/globals';
import { addNewTrendCursor, setXWithBounds } from './getInfo';
import { ElementEvent } from 'echarts';

describe('Testing Charts getInfo', () => {
const mockSize = { width: 500, height: 500 };

describe('addNewTrendCursor', () => {
it('should add a new TC', () => {
const mockEvent = {} as ElementEvent;
const mockSetGraphic = () => jest.fn();
const mockViewport = { duration: '5m' };
const newTrendCursor = addNewTrendCursor(mockEvent, mockSize, 0, [], mockSetGraphic, mockViewport);

expect(newTrendCursor).not.toBeNull();
expect(newTrendCursor[0].children.length).toBe(3);
});

it('on drag should should the TC x co-ordinate', () => {
const mockEvent = {} as ElementEvent;
const mockSetGraphic = () => jest.fn();
const mockViewport = { duration: '5m' };
const newTrendCursor = addNewTrendCursor(mockEvent, mockSize, 0, [], mockSetGraphic, mockViewport);

if (newTrendCursor[0]!.children[0]!.ondrag) {
newTrendCursor[0]!.children[0]!.ondrag({
target: { id: newTrendCursor[0].children[0].id },
offsetX: 100,
} as never);
expect(newTrendCursor[0].children[1].x).toBe(100);
}
});

it('on delete should should the TC x co-ordinate', () => {
const mockEvent = {} as ElementEvent;
const mockSetGraphic = () => jest.fn();
const mockViewport = { duration: '5m' };
const newTrendCursor = addNewTrendCursor(mockEvent, mockSize, 0, [], mockSetGraphic, mockViewport);

if (newTrendCursor[0]!.children[2]!.onmousedown) {
newTrendCursor[0]!.children[2]!.onmousedown({
target: { id: newTrendCursor[0].children[2].id },
} as never);
expect(newTrendCursor.length).toBe(0);
}
});
});

describe('setXWithBounds', () => {
it('should return max of width minus margin', () => {
const maxX = setXWithBounds(mockSize, 475);

expect(maxX).toBe(450);
});

it('should return min of margin', () => {
const maxX = setXWithBounds(mockSize, 20);

expect(maxX).toBe(50);
});
});
});

0 comments on commit 7c6a017

Please sign in to comment.