@thoughtspot/ts-chart-sdk 0.0.1-alpha.7 → 0.0.1-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/main/custom-chart-context.d.ts +10 -3
- package/cjs/main/custom-chart-context.d.ts.map +1 -1
- package/cjs/main/custom-chart-context.js +110 -3
- package/cjs/main/custom-chart-context.js.map +1 -1
- package/cjs/main/custom-chart-context.spec.js +251 -8
- package/cjs/main/custom-chart-context.spec.js.map +1 -1
- package/cjs/react/custom-chart-context-service.d.ts +16 -5
- package/cjs/react/custom-chart-context-service.d.ts.map +1 -1
- package/cjs/react/custom-chart-context-service.js +35 -34
- package/cjs/react/custom-chart-context-service.js.map +1 -1
- package/cjs/react/custom-chart.spec.js +53 -282
- package/cjs/react/custom-chart.spec.js.map +1 -1
- package/cjs/react/mocks/custom-chart-context-mock.d.ts.map +1 -1
- package/cjs/react/mocks/custom-chart-context-mock.js +30 -32
- package/cjs/react/mocks/custom-chart-context-mock.js.map +1 -1
- package/cjs/types/chart-to-ts-event.types.d.ts +28 -1
- package/cjs/types/chart-to-ts-event.types.d.ts.map +1 -1
- package/cjs/types/chart-to-ts-event.types.js +9 -1
- package/cjs/types/chart-to-ts-event.types.js.map +1 -1
- package/cjs/types/common.types.d.ts +1 -0
- package/cjs/types/common.types.d.ts.map +1 -1
- package/cjs/types/ts-to-chart-event.types.d.ts +23 -1
- package/cjs/types/ts-to-chart-event.types.d.ts.map +1 -1
- package/cjs/types/ts-to-chart-event.types.js +2 -0
- package/cjs/types/ts-to-chart-event.types.js.map +1 -1
- package/cjs/types/visual-prop.types.d.ts +23 -9
- package/cjs/types/visual-prop.types.d.ts.map +1 -1
- package/dist/ts-chart-sdk.d.ts +312 -0
- package/lib/dist/ts-chart-sdk.d.ts +312 -0
- package/lib/main/custom-chart-context.d.ts +10 -3
- package/lib/main/custom-chart-context.d.ts.map +1 -1
- package/lib/main/custom-chart-context.js +111 -3
- package/lib/main/custom-chart-context.js.map +1 -1
- package/lib/main/custom-chart-context.spec.js +248 -8
- package/lib/main/custom-chart-context.spec.js.map +1 -1
- package/lib/react/custom-chart-context-service.d.ts +16 -5
- package/lib/react/custom-chart-context-service.d.ts.map +1 -1
- package/lib/react/custom-chart-context-service.js +35 -34
- package/lib/react/custom-chart-context-service.js.map +1 -1
- package/lib/react/custom-chart.spec.js +54 -260
- package/lib/react/custom-chart.spec.js.map +1 -1
- package/lib/react/mocks/custom-chart-context-mock.d.ts.map +1 -1
- package/lib/react/mocks/custom-chart-context-mock.js +30 -32
- package/lib/react/mocks/custom-chart-context-mock.js.map +1 -1
- package/lib/types/chart-to-ts-event.types.d.ts +28 -1
- package/lib/types/chart-to-ts-event.types.d.ts.map +1 -1
- package/lib/types/chart-to-ts-event.types.js +8 -0
- package/lib/types/chart-to-ts-event.types.js.map +1 -1
- package/lib/types/common.types.d.ts +1 -0
- package/lib/types/common.types.d.ts.map +1 -1
- package/lib/types/ts-to-chart-event.types.d.ts +23 -1
- package/lib/types/ts-to-chart-event.types.d.ts.map +1 -1
- package/lib/types/ts-to-chart-event.types.js +2 -0
- package/lib/types/ts-to-chart-event.types.js.map +1 -1
- package/lib/types/visual-prop.types.d.ts +23 -9
- package/lib/types/visual-prop.types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/main/custom-chart-context.spec.ts +310 -0
- package/src/main/custom-chart-context.ts +227 -1
- package/src/types/chart-to-ts-event.types.ts +125 -6
- package/src/types/common.types.ts +14 -0
- package/src/types/ts-to-chart-event.types.ts +70 -0
- package/cjs/react/custom-chart-context-hook.d.ts +0 -22
- package/cjs/react/custom-chart-context-hook.d.ts.map +0 -1
- package/cjs/react/custom-chart-context-hook.js +0 -116
- package/cjs/react/custom-chart-context-hook.js.map +0 -1
- package/cjs/react/custom-chart-context-hook.spec.d.ts +0 -2
- package/cjs/react/custom-chart-context-hook.spec.d.ts.map +0 -1
- package/cjs/react/custom-chart-context-hook.spec.js +0 -343
- package/cjs/react/custom-chart-context-hook.spec.js.map +0 -1
- package/cjs/react/mocks/custom-chart-context-hook.d.ts +0 -3
- package/cjs/react/mocks/custom-chart-context-hook.d.ts.map +0 -1
- package/cjs/react/mocks/custom-chart-context-hook.js +0 -100
- package/cjs/react/mocks/custom-chart-context-hook.js.map +0 -1
- package/lib/react/custom-chart-context-hook.d.ts +0 -22
- package/lib/react/custom-chart-context-hook.d.ts.map +0 -1
- package/lib/react/custom-chart-context-hook.js +0 -86
- package/lib/react/custom-chart-context-hook.js.map +0 -1
- package/lib/react/custom-chart-context-hook.spec.d.ts +0 -2
- package/lib/react/custom-chart-context-hook.spec.d.ts.map +0 -1
- package/lib/react/custom-chart-context-hook.spec.js +0 -315
- package/lib/react/custom-chart-context-hook.spec.js.map +0 -1
- package/lib/react/mocks/custom-chart-context-hook.d.ts +0 -3
- package/lib/react/mocks/custom-chart-context-hook.d.ts.map +0 -1
- package/lib/react/mocks/custom-chart-context-hook.js +0 -94
- package/lib/react/mocks/custom-chart-context-hook.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export interface InputValidation {
|
|
2
|
-
required
|
|
3
|
-
requiredError
|
|
4
|
-
regex
|
|
5
|
-
regexError
|
|
6
|
-
minLength
|
|
7
|
-
minLengthError
|
|
8
|
-
range
|
|
9
|
-
rangeError
|
|
2
|
+
required?: boolean;
|
|
3
|
+
requiredError?: string;
|
|
4
|
+
regex?: string;
|
|
5
|
+
regexError?: string;
|
|
6
|
+
minLength?: number;
|
|
7
|
+
minLengthError?: string;
|
|
8
|
+
range?: string;
|
|
9
|
+
rangeError?: string;
|
|
10
10
|
}
|
|
11
11
|
export interface TextInputFormDetail {
|
|
12
12
|
type: 'text';
|
|
@@ -18,6 +18,20 @@ export interface TextInputFormDetail {
|
|
|
18
18
|
defaultValue?: string;
|
|
19
19
|
inputValidation?: InputValidation;
|
|
20
20
|
}
|
|
21
|
+
export interface NumberInputFormDetail {
|
|
22
|
+
type: 'number';
|
|
23
|
+
key: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
defaultValue?: number;
|
|
26
|
+
inputValidation?: InputValidation;
|
|
27
|
+
}
|
|
28
|
+
export interface ColorPickerFormDetail {
|
|
29
|
+
type: 'colorpicker';
|
|
30
|
+
key: string;
|
|
31
|
+
label?: string;
|
|
32
|
+
selectorType?: 'FONT' | 'COLOR';
|
|
33
|
+
defaultValue?: string;
|
|
34
|
+
}
|
|
21
35
|
export interface ToggleFormDetail {
|
|
22
36
|
type: 'toggle';
|
|
23
37
|
key: string;
|
|
@@ -52,7 +66,7 @@ export interface Section {
|
|
|
52
66
|
alignment?: 'row' | 'column';
|
|
53
67
|
layoutType?: 'accordion' | 'tab' | 'none';
|
|
54
68
|
}
|
|
55
|
-
export type PropElement = Section | TextInputFormDetail | ToggleFormDetail | CheckboxFormDetail | RadioButtonFormDetail | DropDownFormDetail;
|
|
69
|
+
export type PropElement = Section | TextInputFormDetail | NumberInputFormDetail | ColorPickerFormDetail | ToggleFormDetail | CheckboxFormDetail | RadioButtonFormDetail | DropDownFormDetail;
|
|
56
70
|
export interface VisualPropEditorDefinition {
|
|
57
71
|
elements: PropElement[];
|
|
58
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-prop.types.d.ts","sourceRoot":"","sources":["../../src/types/visual-prop.types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,eAAe;IAM5B,QAAQ,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"visual-prop.types.d.ts","sourceRoot":"","sources":["../../src/types/visual-prop.types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,eAAe;IAM5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAMnB,aAAa,CAAC,EAAE,MAAM,CAAC;IAMvB,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,UAAU,CAAC,EAAE,MAAM,CAAC;IAMpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,cAAc,CAAC,EAAE,MAAM,CAAC;IAMxB,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAOD,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC;IAMb,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAOf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAOnB,SAAS,CAAC,EAAE,OAAO,CAAC;IAMpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAMrB,YAAY,CAAC,EAAE,MAAM,CAAC;IAMtB,eAAe,CAAC,EAAE,eAAe,CAAC;CACrC;AAOD,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,QAAQ,CAAC;IAMf,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,YAAY,CAAC,EAAE,MAAM,CAAC;IAMtB,eAAe,CAAC,EAAE,eAAe,CAAC;CACrC;AAOD,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,aAAa,CAAC;IAMpB,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAOf,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAMhC,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,QAAQ,CAAC;IAMf,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAOD,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,UAAU,CAAC;IAMjB,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAOD,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,OAAO,CAAC;IAMd,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,YAAY,CAAC,EAAE,MAAM,CAAC;IAMtB,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AAOD,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,UAAU,CAAC;IAMjB,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,YAAY,CAAC,EAAE,MAAM,CAAC;IAMtB,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AAOD,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,SAAS,CAAC;IAMhB,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IAMzB,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAQ7B,UAAU,CAAC,EAAE,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;CAC7C;AAOD,MAAM,MAAM,WAAW,GACjB,OAAO,GACP,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,gBAAgB,GAChB,kBAAkB,GAClB,qBAAqB,GACrB,kBAAkB,CAAC;AAOzB,MAAM,WAAW,0BAA0B;IAOvC,QAAQ,EAAE,WAAW,EAAE,CAAC;CAC3B"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @author Chetan Agrawal <chetan.agrawal@thoughtspot.com>
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import _ from 'lodash';
|
|
7
8
|
import { mockInitializeContextPayload } from '../test/test-utils';
|
|
8
9
|
import { ChartToTSEvent, ErrorType } from '../types/chart-to-ts-event.types';
|
|
9
10
|
import { TSToChartEvent } from '../types/ts-to-chart-event.types';
|
|
@@ -330,6 +331,71 @@ describe('CustomChartContext', () => {
|
|
|
330
331
|
expect(customChartContext.getChartModel().visualProps).toBe(
|
|
331
332
|
'random data',
|
|
332
333
|
);
|
|
334
|
+
mockPostMessage.mockReset();
|
|
335
|
+
|
|
336
|
+
// mock the event trigger for AxisMenuActionClick
|
|
337
|
+
customChartContext.axisMenuCustomActionPreProcessor([
|
|
338
|
+
{
|
|
339
|
+
customActions: [
|
|
340
|
+
{
|
|
341
|
+
icon: '',
|
|
342
|
+
id: 'custom-action-1',
|
|
343
|
+
label: 'Custom user action 1',
|
|
344
|
+
onClick: () => _.noop(),
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
] as any);
|
|
349
|
+
eventProcessor({
|
|
350
|
+
data: {
|
|
351
|
+
payload: {
|
|
352
|
+
customAction: {
|
|
353
|
+
id: 'custom-action-1',
|
|
354
|
+
columnIds: ['9f96b5b0-f7e4-4a5e-aa11-4c77fdf42125'],
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
eventType: TSToChartEvent.AxisMenuActionClick,
|
|
358
|
+
source: 'ts-host-app',
|
|
359
|
+
},
|
|
360
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
361
|
+
});
|
|
362
|
+
// Check that the response was valid which means action gets
|
|
363
|
+
// executed successfully
|
|
364
|
+
expect(mockPostMessage).toHaveBeenCalledWith({
|
|
365
|
+
isValid: true,
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// mock the event trigger for ContextMenuActionClick
|
|
369
|
+
customChartContext.contextMenuCustomActionPreProcessor([
|
|
370
|
+
{
|
|
371
|
+
customActions: [
|
|
372
|
+
{
|
|
373
|
+
icon: '',
|
|
374
|
+
id: 'custom-action-1',
|
|
375
|
+
label: 'Custom user action 1',
|
|
376
|
+
onClick: () => _.noop(),
|
|
377
|
+
},
|
|
378
|
+
],
|
|
379
|
+
},
|
|
380
|
+
] as any);
|
|
381
|
+
eventProcessor({
|
|
382
|
+
data: {
|
|
383
|
+
payload: {
|
|
384
|
+
customAction: {
|
|
385
|
+
id: 'custom-action-1',
|
|
386
|
+
columnIds: ['9f96b5b0-f7e4-4a5e-aa11-4c77fdf42125'],
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
eventType: TSToChartEvent.ContextMenuActionClick,
|
|
390
|
+
source: 'ts-host-app',
|
|
391
|
+
},
|
|
392
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
393
|
+
});
|
|
394
|
+
// Check that the response was valid which means action gets
|
|
395
|
+
// executed successfully
|
|
396
|
+
expect(mockPostMessage).toHaveBeenCalledWith({
|
|
397
|
+
isValid: true,
|
|
398
|
+
});
|
|
333
399
|
});
|
|
334
400
|
|
|
335
401
|
test('should add an event listener to the specified event type', () => {
|
|
@@ -605,5 +671,249 @@ describe('CustomChartContext', () => {
|
|
|
605
671
|
ChartToTSEvent.RenderStart,
|
|
606
672
|
);
|
|
607
673
|
});
|
|
674
|
+
test('should process the event payload for context menu custom actions', async () => {
|
|
675
|
+
const mockPostMessage = jest.fn();
|
|
676
|
+
const mockCustomAction = jest.fn();
|
|
677
|
+
let resolve: any;
|
|
678
|
+
eventProcessor({
|
|
679
|
+
data: {
|
|
680
|
+
payload: mockInitializeContextPayload,
|
|
681
|
+
eventType: TSToChartEvent.Initialize,
|
|
682
|
+
source: 'ts-host-app',
|
|
683
|
+
},
|
|
684
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
685
|
+
});
|
|
686
|
+
eventProcessor({
|
|
687
|
+
data: {
|
|
688
|
+
payload: {},
|
|
689
|
+
eventType: TSToChartEvent.InitializeComplete,
|
|
690
|
+
source: 'ts-host-app',
|
|
691
|
+
},
|
|
692
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
693
|
+
});
|
|
694
|
+
customChartContext.initialize();
|
|
695
|
+
mockPostMessageToHost.mockImplementation(
|
|
696
|
+
() =>
|
|
697
|
+
new global.Promise<any>((res) => {
|
|
698
|
+
resolve = res;
|
|
699
|
+
}),
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
// Define a test event type and payload
|
|
703
|
+
const TEST_EVENT_TYPE = ChartToTSEvent.OpenContextMenu as any;
|
|
704
|
+
const testPayload = {
|
|
705
|
+
customActions: [
|
|
706
|
+
{
|
|
707
|
+
id: 'custom-action-1',
|
|
708
|
+
label: 'Custom user action 1',
|
|
709
|
+
icon: '',
|
|
710
|
+
onClick: mockCustomAction,
|
|
711
|
+
},
|
|
712
|
+
],
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
// Call the emitEvent function and wait for it to resolve
|
|
716
|
+
customChartContext.emitEvent(TEST_EVENT_TYPE, testPayload);
|
|
717
|
+
|
|
718
|
+
// Check that the result is defined
|
|
719
|
+
expect(mockPostMessageToHost).toHaveBeenCalledWith(
|
|
720
|
+
mockInitializeContextPayload.componentId,
|
|
721
|
+
mockInitializeContextPayload.hostUrl,
|
|
722
|
+
{
|
|
723
|
+
customActions: [
|
|
724
|
+
{
|
|
725
|
+
icon: '',
|
|
726
|
+
id: 'custom-action-1',
|
|
727
|
+
label: 'Custom user action 1',
|
|
728
|
+
},
|
|
729
|
+
],
|
|
730
|
+
},
|
|
731
|
+
TEST_EVENT_TYPE,
|
|
732
|
+
);
|
|
733
|
+
eventProcessor({
|
|
734
|
+
data: {
|
|
735
|
+
payload: {
|
|
736
|
+
customAction: {
|
|
737
|
+
id: 'custom-action-1',
|
|
738
|
+
clickedPoint: {},
|
|
739
|
+
event: {},
|
|
740
|
+
selectedPoints: [{}],
|
|
741
|
+
},
|
|
742
|
+
},
|
|
743
|
+
eventType: TSToChartEvent.ContextMenuActionClick,
|
|
744
|
+
source: 'ts-host-app',
|
|
745
|
+
},
|
|
746
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
747
|
+
});
|
|
748
|
+
expect(mockCustomAction).toHaveBeenCalled();
|
|
749
|
+
expect(mockCustomAction).toHaveBeenCalledWith({
|
|
750
|
+
clickedPoint: {},
|
|
751
|
+
event: {},
|
|
752
|
+
id: 'custom-action-1',
|
|
753
|
+
selectedPoints: [{}],
|
|
754
|
+
});
|
|
755
|
+
});
|
|
756
|
+
test('should process the event payload for axis menu custom actions', async () => {
|
|
757
|
+
const mockPostMessage = jest.fn();
|
|
758
|
+
const mockCustomAction = jest.fn();
|
|
759
|
+
let resolve: any;
|
|
760
|
+
eventProcessor({
|
|
761
|
+
data: {
|
|
762
|
+
payload: mockInitializeContextPayload,
|
|
763
|
+
eventType: TSToChartEvent.Initialize,
|
|
764
|
+
source: 'ts-host-app',
|
|
765
|
+
},
|
|
766
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
767
|
+
});
|
|
768
|
+
eventProcessor({
|
|
769
|
+
data: {
|
|
770
|
+
payload: {},
|
|
771
|
+
eventType: TSToChartEvent.InitializeComplete,
|
|
772
|
+
source: 'ts-host-app',
|
|
773
|
+
},
|
|
774
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
775
|
+
});
|
|
776
|
+
customChartContext.initialize();
|
|
777
|
+
mockPostMessageToHost.mockImplementation(
|
|
778
|
+
() =>
|
|
779
|
+
new global.Promise<any>((res) => {
|
|
780
|
+
resolve = res;
|
|
781
|
+
}),
|
|
782
|
+
);
|
|
783
|
+
|
|
784
|
+
// Define a test event type and payload
|
|
785
|
+
const TEST_EVENT_TYPE = ChartToTSEvent.OpenAxisMenu as any;
|
|
786
|
+
const testPayload = {
|
|
787
|
+
customActions: [
|
|
788
|
+
{
|
|
789
|
+
id: 'custom-action-1',
|
|
790
|
+
label: 'Custom user action 1',
|
|
791
|
+
icon: '',
|
|
792
|
+
onClick: mockCustomAction,
|
|
793
|
+
},
|
|
794
|
+
],
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
// Call the emitEvent function and wait for it to resolve
|
|
798
|
+
customChartContext.emitEvent(TEST_EVENT_TYPE, testPayload);
|
|
799
|
+
// Check that the result is defined
|
|
800
|
+
expect(mockPostMessageToHost).toHaveBeenCalledWith(
|
|
801
|
+
mockInitializeContextPayload.componentId,
|
|
802
|
+
mockInitializeContextPayload.hostUrl,
|
|
803
|
+
{
|
|
804
|
+
customActions: [
|
|
805
|
+
{
|
|
806
|
+
icon: '',
|
|
807
|
+
id: 'custom-action-1',
|
|
808
|
+
label: 'Custom user action 1',
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
},
|
|
812
|
+
TEST_EVENT_TYPE,
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
eventProcessor({
|
|
816
|
+
data: {
|
|
817
|
+
payload: {
|
|
818
|
+
customAction: {
|
|
819
|
+
id: 'custom-action-1',
|
|
820
|
+
columnIds: ['123'],
|
|
821
|
+
event: {},
|
|
822
|
+
},
|
|
823
|
+
},
|
|
824
|
+
eventType: TSToChartEvent.AxisMenuActionClick,
|
|
825
|
+
source: 'ts-host-app',
|
|
826
|
+
},
|
|
827
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
828
|
+
});
|
|
829
|
+
expect(mockCustomAction).toHaveBeenCalled();
|
|
830
|
+
expect(mockCustomAction).toHaveBeenCalledWith({
|
|
831
|
+
id: 'custom-action-1',
|
|
832
|
+
columnIds: ['123'],
|
|
833
|
+
event: {},
|
|
834
|
+
});
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
test('should process the event payload for axis menu when custom actions are not defined', async () => {
|
|
838
|
+
const mockPostMessage = jest.fn();
|
|
839
|
+
let resolve: any;
|
|
840
|
+
eventProcessor({
|
|
841
|
+
data: {
|
|
842
|
+
payload: mockInitializeContextPayload,
|
|
843
|
+
eventType: TSToChartEvent.Initialize,
|
|
844
|
+
source: 'ts-host-app',
|
|
845
|
+
},
|
|
846
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
847
|
+
});
|
|
848
|
+
eventProcessor({
|
|
849
|
+
data: {
|
|
850
|
+
payload: {},
|
|
851
|
+
eventType: TSToChartEvent.InitializeComplete,
|
|
852
|
+
source: 'ts-host-app',
|
|
853
|
+
},
|
|
854
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
855
|
+
});
|
|
856
|
+
customChartContext.initialize();
|
|
857
|
+
mockPostMessageToHost.mockImplementation(
|
|
858
|
+
() =>
|
|
859
|
+
new global.Promise<any>((res) => {
|
|
860
|
+
resolve = res;
|
|
861
|
+
}),
|
|
862
|
+
);
|
|
863
|
+
|
|
864
|
+
// Define a test event type and payload
|
|
865
|
+
const TEST_EVENT_TYPE = ChartToTSEvent.OpenAxisMenu as any;
|
|
866
|
+
const testPayload = {};
|
|
867
|
+
// Call the emitEvent function and wait for it to resolve
|
|
868
|
+
customChartContext.emitEvent(TEST_EVENT_TYPE, testPayload);
|
|
869
|
+
// Check that the result is defined
|
|
870
|
+
expect(mockPostMessageToHost).toHaveBeenCalledWith(
|
|
871
|
+
mockInitializeContextPayload.componentId,
|
|
872
|
+
mockInitializeContextPayload.hostUrl,
|
|
873
|
+
{},
|
|
874
|
+
TEST_EVENT_TYPE,
|
|
875
|
+
);
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
test('should process the event payload for context menu when custom actions are not defined', async () => {
|
|
879
|
+
const mockPostMessage = jest.fn();
|
|
880
|
+
let resolve: any;
|
|
881
|
+
eventProcessor({
|
|
882
|
+
data: {
|
|
883
|
+
payload: mockInitializeContextPayload,
|
|
884
|
+
eventType: TSToChartEvent.Initialize,
|
|
885
|
+
source: 'ts-host-app',
|
|
886
|
+
},
|
|
887
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
888
|
+
});
|
|
889
|
+
eventProcessor({
|
|
890
|
+
data: {
|
|
891
|
+
payload: {},
|
|
892
|
+
eventType: TSToChartEvent.InitializeComplete,
|
|
893
|
+
source: 'ts-host-app',
|
|
894
|
+
},
|
|
895
|
+
ports: [{ postMessage: mockPostMessage }],
|
|
896
|
+
});
|
|
897
|
+
customChartContext.initialize();
|
|
898
|
+
mockPostMessageToHost.mockImplementation(
|
|
899
|
+
() =>
|
|
900
|
+
new global.Promise<any>((res) => {
|
|
901
|
+
resolve = res;
|
|
902
|
+
}),
|
|
903
|
+
);
|
|
904
|
+
|
|
905
|
+
// Define a test event type and payload
|
|
906
|
+
const TEST_EVENT_TYPE = ChartToTSEvent.OpenContextMenu as any;
|
|
907
|
+
const testPayload = {};
|
|
908
|
+
// Call the emitEvent function and wait for it to resolve
|
|
909
|
+
customChartContext.emitEvent(TEST_EVENT_TYPE, testPayload);
|
|
910
|
+
// Check that the result is defined
|
|
911
|
+
expect(mockPostMessageToHost).toHaveBeenCalledWith(
|
|
912
|
+
mockInitializeContextPayload.componentId,
|
|
913
|
+
mockInitializeContextPayload.hostUrl,
|
|
914
|
+
{},
|
|
915
|
+
TEST_EVENT_TYPE,
|
|
916
|
+
);
|
|
917
|
+
});
|
|
608
918
|
});
|
|
609
919
|
});
|
|
@@ -5,13 +5,20 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Copyright: ThoughtSpot Inc. 2023
|
|
7
7
|
*/
|
|
8
|
+
|
|
8
9
|
import _ from 'lodash';
|
|
9
10
|
import {
|
|
11
|
+
AxisMenuActionHandler,
|
|
10
12
|
ChartToTSEvent,
|
|
11
13
|
ChartToTSEventsPayloadMap,
|
|
14
|
+
ContextMenuActionHandler,
|
|
15
|
+
CustomAction,
|
|
12
16
|
ErrorType,
|
|
17
|
+
OpenAxisMenuEventPayload,
|
|
18
|
+
OpenContextMenuEventPayload,
|
|
13
19
|
} from '../types/chart-to-ts-event.types';
|
|
14
20
|
import {
|
|
21
|
+
AppConfig,
|
|
15
22
|
ChartConfig,
|
|
16
23
|
ChartModel,
|
|
17
24
|
ValidationResponse,
|
|
@@ -19,8 +26,10 @@ import {
|
|
|
19
26
|
} from '../types/common.types';
|
|
20
27
|
import { ChartConfigEditorDefinition } from '../types/configurator.types';
|
|
21
28
|
import {
|
|
29
|
+
AxisMenuCustomActionPayload,
|
|
22
30
|
ChartConfigValidateEventPayload,
|
|
23
31
|
ChartModelUpdateEventPayload,
|
|
32
|
+
ContextMenuCustomActionPayload,
|
|
24
33
|
DataUpdateEventPayload,
|
|
25
34
|
GetDataQueryPayload,
|
|
26
35
|
GetDataQueryResponsePayload,
|
|
@@ -149,6 +158,13 @@ export class CustomChartContext {
|
|
|
149
158
|
*/
|
|
150
159
|
private chartModel: ChartModel = {} as any;
|
|
151
160
|
|
|
161
|
+
/**
|
|
162
|
+
* App Config object. This contains the app state like locale and timezones.
|
|
163
|
+
*
|
|
164
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
165
|
+
*/
|
|
166
|
+
private appConfig: AppConfig = {};
|
|
167
|
+
|
|
152
168
|
/**
|
|
153
169
|
* Chart Props Object to define the workflow of the application
|
|
154
170
|
*
|
|
@@ -185,6 +201,22 @@ export class CustomChartContext {
|
|
|
185
201
|
*/
|
|
186
202
|
private triggerInitResolve: () => void = _.noop;
|
|
187
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Stores the callbacks of context menu custom action based on custom action id
|
|
206
|
+
*
|
|
207
|
+
* @returns {@link ContextMenuActionHandler}
|
|
208
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
209
|
+
*/
|
|
210
|
+
private contextMenuActionHandler: ContextMenuActionHandler = {};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Stores the callbacks of axis menu custom action based on custom action id
|
|
214
|
+
*
|
|
215
|
+
* @returns {@link AxisMenuActionHandler}
|
|
216
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
217
|
+
*/
|
|
218
|
+
private axisMenuActionHandler: AxisMenuActionHandler = {};
|
|
219
|
+
|
|
188
220
|
/**
|
|
189
221
|
* Constructor to only accept context props as payload
|
|
190
222
|
*
|
|
@@ -284,6 +316,107 @@ export class CustomChartContext {
|
|
|
284
316
|
*/
|
|
285
317
|
public getChartModel = (): ChartModel => this.chartModel;
|
|
286
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Getter for the chart model object
|
|
321
|
+
*
|
|
322
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
323
|
+
*/
|
|
324
|
+
public getAppConfig = (): AppConfig => this.appConfig;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Function to store the context menu custom action callback mapped with action id
|
|
328
|
+
* @param {[OpenContextMenuEventPayload]} eventPayload Event payload bound
|
|
329
|
+
* to the type of the event
|
|
330
|
+
* @returns payload
|
|
331
|
+
*/
|
|
332
|
+
public contextMenuCustomActionPreProcessor(
|
|
333
|
+
eventPayload: [OpenContextMenuEventPayload],
|
|
334
|
+
): [OpenContextMenuEventPayload] {
|
|
335
|
+
// clear out the stored custom events callback for context menu
|
|
336
|
+
this.contextMenuActionHandler = {};
|
|
337
|
+
if (_.isEmpty(eventPayload?.[0]?.customActions)) {
|
|
338
|
+
return eventPayload;
|
|
339
|
+
}
|
|
340
|
+
eventPayload?.[0]?.customActions?.forEach((action: CustomAction) => {
|
|
341
|
+
this.contextMenuActionHandler[action.id] = action.onClick;
|
|
342
|
+
});
|
|
343
|
+
const processedCustomActions = eventPayload[0]?.customActions?.map(
|
|
344
|
+
(action: CustomAction) => {
|
|
345
|
+
return {
|
|
346
|
+
id: action.id,
|
|
347
|
+
label: action.label,
|
|
348
|
+
icon: action.icon,
|
|
349
|
+
};
|
|
350
|
+
},
|
|
351
|
+
);
|
|
352
|
+
const processedPayload: [OpenContextMenuEventPayload] = [
|
|
353
|
+
{
|
|
354
|
+
...eventPayload[0],
|
|
355
|
+
customActions: processedCustomActions as CustomAction[],
|
|
356
|
+
},
|
|
357
|
+
];
|
|
358
|
+
return processedPayload;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Function to store the axis menu custom action callback mapped with action id
|
|
363
|
+
* @param {[OpenAxisMenuEventPayload]} eventPayload Event payload bound
|
|
364
|
+
* to the type of the event
|
|
365
|
+
* @returns payload
|
|
366
|
+
*/
|
|
367
|
+
public axisMenuCustomActionPreProcessor(
|
|
368
|
+
eventPayload: [OpenAxisMenuEventPayload],
|
|
369
|
+
): [OpenAxisMenuEventPayload] {
|
|
370
|
+
// clear out the stored custom events callback for axis menu
|
|
371
|
+
this.axisMenuActionHandler = {};
|
|
372
|
+
if (_.isEmpty(eventPayload?.[0]?.customActions)) {
|
|
373
|
+
return eventPayload;
|
|
374
|
+
}
|
|
375
|
+
eventPayload[0].customActions?.forEach((action: CustomAction) => {
|
|
376
|
+
this.axisMenuActionHandler[action.id] = action.onClick;
|
|
377
|
+
});
|
|
378
|
+
const processedCustomActions = eventPayload?.[0].customActions?.map(
|
|
379
|
+
(action: CustomAction) => {
|
|
380
|
+
return {
|
|
381
|
+
id: action.id,
|
|
382
|
+
label: action.label,
|
|
383
|
+
icon: action.icon,
|
|
384
|
+
};
|
|
385
|
+
},
|
|
386
|
+
);
|
|
387
|
+
const processedPayload: [OpenAxisMenuEventPayload] = [
|
|
388
|
+
{
|
|
389
|
+
...eventPayload[0],
|
|
390
|
+
customActions: processedCustomActions as CustomAction[],
|
|
391
|
+
},
|
|
392
|
+
];
|
|
393
|
+
return processedPayload;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Function to process the event payload based on event type
|
|
398
|
+
* @param {ChartToTSEventsPayloadMap[T]} eventPayload Event payload bound
|
|
399
|
+
* to the type of the event
|
|
400
|
+
* @returns payload
|
|
401
|
+
*/
|
|
402
|
+
private eventPayloadPreProcessor<T extends keyof ChartToTSEventsPayloadMap>(
|
|
403
|
+
eventType: T,
|
|
404
|
+
eventPayload: ChartToTSEventsPayloadMap[T],
|
|
405
|
+
): ChartToTSEventsPayloadMap[T] {
|
|
406
|
+
switch (eventType) {
|
|
407
|
+
case ChartToTSEvent.OpenContextMenu:
|
|
408
|
+
return this.contextMenuCustomActionPreProcessor(
|
|
409
|
+
eventPayload as [OpenContextMenuEventPayload],
|
|
410
|
+
) as ChartToTSEventsPayloadMap[T];
|
|
411
|
+
case ChartToTSEvent.OpenAxisMenu:
|
|
412
|
+
return this.axisMenuCustomActionPreProcessor(
|
|
413
|
+
eventPayload as [OpenAxisMenuEventPayload],
|
|
414
|
+
) as ChartToTSEventsPayloadMap[T];
|
|
415
|
+
default:
|
|
416
|
+
return eventPayload;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
287
420
|
/**
|
|
288
421
|
* Function to emit Chart to TS Events to the TS application.
|
|
289
422
|
|
|
@@ -302,10 +435,14 @@ export class CustomChartContext {
|
|
|
302
435
|
);
|
|
303
436
|
return Promise.reject(new Error('Context not initialized'));
|
|
304
437
|
}
|
|
438
|
+
const processedPayload = this.eventPayloadPreProcessor(
|
|
439
|
+
eventType,
|
|
440
|
+
eventPayload,
|
|
441
|
+
);
|
|
305
442
|
return PostMessageEventBridge.postMessageToHostApp(
|
|
306
443
|
this.componentId,
|
|
307
444
|
this.hostUrl,
|
|
308
|
-
|
|
445
|
+
processedPayload?.[0] ?? null,
|
|
309
446
|
eventType,
|
|
310
447
|
);
|
|
311
448
|
}
|
|
@@ -447,6 +584,94 @@ export class CustomChartContext {
|
|
|
447
584
|
this.chartContextProps.renderChart(this);
|
|
448
585
|
});
|
|
449
586
|
|
|
587
|
+
/**
|
|
588
|
+
* This event is triggered when the custom context action is triggered from TS app
|
|
589
|
+
*/
|
|
590
|
+
this.onInternal(
|
|
591
|
+
TSToChartEvent.ContextMenuActionClick,
|
|
592
|
+
(
|
|
593
|
+
payload: ContextMenuCustomActionPayload,
|
|
594
|
+
): {
|
|
595
|
+
isValid: boolean;
|
|
596
|
+
error?: unknown;
|
|
597
|
+
} => {
|
|
598
|
+
try {
|
|
599
|
+
const {
|
|
600
|
+
id: customActionCallback,
|
|
601
|
+
clickedPoint,
|
|
602
|
+
selectedPoints,
|
|
603
|
+
event,
|
|
604
|
+
} = payload.customAction;
|
|
605
|
+
const customActionCallbackArgs = {
|
|
606
|
+
id: customActionCallback,
|
|
607
|
+
clickedPoint,
|
|
608
|
+
selectedPoints,
|
|
609
|
+
event,
|
|
610
|
+
};
|
|
611
|
+
this.contextMenuActionHandler[customActionCallback](
|
|
612
|
+
customActionCallbackArgs,
|
|
613
|
+
);
|
|
614
|
+
return {
|
|
615
|
+
isValid: true,
|
|
616
|
+
};
|
|
617
|
+
} catch (error: unknown) {
|
|
618
|
+
console.log(
|
|
619
|
+
'ContextMenuCustomAction: payload recieved:',
|
|
620
|
+
payload,
|
|
621
|
+
'CustomActionCallbackStore:',
|
|
622
|
+
this.axisMenuActionHandler,
|
|
623
|
+
);
|
|
624
|
+
return {
|
|
625
|
+
isValid: false,
|
|
626
|
+
error,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* This event is triggered when the custom axis action is triggered from TS app
|
|
634
|
+
*/
|
|
635
|
+
this.onInternal(
|
|
636
|
+
TSToChartEvent.AxisMenuActionClick,
|
|
637
|
+
(
|
|
638
|
+
payload: AxisMenuCustomActionPayload,
|
|
639
|
+
): {
|
|
640
|
+
isValid: boolean;
|
|
641
|
+
error?: unknown;
|
|
642
|
+
} => {
|
|
643
|
+
try {
|
|
644
|
+
const {
|
|
645
|
+
id: customActionCallback,
|
|
646
|
+
columnIds,
|
|
647
|
+
event,
|
|
648
|
+
} = payload.customAction;
|
|
649
|
+
const customActionCallbackArgs = {
|
|
650
|
+
id: customActionCallback,
|
|
651
|
+
columnIds,
|
|
652
|
+
event,
|
|
653
|
+
};
|
|
654
|
+
this.axisMenuActionHandler[customActionCallback](
|
|
655
|
+
customActionCallbackArgs,
|
|
656
|
+
);
|
|
657
|
+
return {
|
|
658
|
+
isValid: true,
|
|
659
|
+
};
|
|
660
|
+
} catch (error: unknown) {
|
|
661
|
+
console.log(
|
|
662
|
+
'AxisMenuCustomAction: payload recieved:',
|
|
663
|
+
payload,
|
|
664
|
+
'CustomActionCallbackStore:',
|
|
665
|
+
this.axisMenuActionHandler,
|
|
666
|
+
);
|
|
667
|
+
return {
|
|
668
|
+
isValid: false,
|
|
669
|
+
error,
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
);
|
|
674
|
+
|
|
450
675
|
// Register External Events
|
|
451
676
|
// These events are readable by the developer
|
|
452
677
|
|
|
@@ -517,6 +742,7 @@ export class CustomChartContext {
|
|
|
517
742
|
this.componentId = payload.componentId;
|
|
518
743
|
this.hostUrl = payload.hostUrl;
|
|
519
744
|
this.chartModel = payload.chartModel;
|
|
745
|
+
this.appConfig = payload.appConfig ?? {};
|
|
520
746
|
|
|
521
747
|
return this.publishChartContextPropsToHost();
|
|
522
748
|
};
|