@thoughtspot/ts-chart-sdk 0.0.1-alpha.8 → 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.
Files changed (36) hide show
  1. package/cjs/main/custom-chart-context.d.ts +9 -2
  2. package/cjs/main/custom-chart-context.d.ts.map +1 -1
  3. package/cjs/main/custom-chart-context.js +109 -1
  4. package/cjs/main/custom-chart-context.js.map +1 -1
  5. package/cjs/main/custom-chart-context.spec.js +251 -0
  6. package/cjs/main/custom-chart-context.spec.js.map +1 -1
  7. package/cjs/types/chart-to-ts-event.types.d.ts +7 -1
  8. package/cjs/types/chart-to-ts-event.types.d.ts.map +1 -1
  9. package/cjs/types/chart-to-ts-event.types.js.map +1 -1
  10. package/cjs/types/common.types.d.ts +1 -0
  11. package/cjs/types/common.types.d.ts.map +1 -1
  12. package/cjs/types/ts-to-chart-event.types.d.ts +23 -1
  13. package/cjs/types/ts-to-chart-event.types.d.ts.map +1 -1
  14. package/cjs/types/ts-to-chart-event.types.js +2 -0
  15. package/cjs/types/ts-to-chart-event.types.js.map +1 -1
  16. package/lib/main/custom-chart-context.d.ts +9 -2
  17. package/lib/main/custom-chart-context.d.ts.map +1 -1
  18. package/lib/main/custom-chart-context.js +110 -2
  19. package/lib/main/custom-chart-context.js.map +1 -1
  20. package/lib/main/custom-chart-context.spec.js +248 -0
  21. package/lib/main/custom-chart-context.spec.js.map +1 -1
  22. package/lib/types/chart-to-ts-event.types.d.ts +7 -1
  23. package/lib/types/chart-to-ts-event.types.d.ts.map +1 -1
  24. package/lib/types/chart-to-ts-event.types.js.map +1 -1
  25. package/lib/types/common.types.d.ts +1 -0
  26. package/lib/types/common.types.d.ts.map +1 -1
  27. package/lib/types/ts-to-chart-event.types.d.ts +23 -1
  28. package/lib/types/ts-to-chart-event.types.d.ts.map +1 -1
  29. package/lib/types/ts-to-chart-event.types.js +2 -0
  30. package/lib/types/ts-to-chart-event.types.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/main/custom-chart-context.spec.ts +310 -0
  33. package/src/main/custom-chart-context.ts +227 -1
  34. package/src/types/chart-to-ts-event.types.ts +21 -1
  35. package/src/types/common.types.ts +14 -0
  36. package/src/types/ts-to-chart-event.types.ts +70 -0
@@ -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
- eventPayload?.[0] ?? null,
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
  };
@@ -1,5 +1,9 @@
1
1
  import { VisualProps } from './common.types';
2
- import { Query } from './ts-to-chart-event.types';
2
+ import {
3
+ CustomAxisMenuAction,
4
+ CustomContextMenuAction,
5
+ Query,
6
+ } from './ts-to-chart-event.types';
3
7
 
4
8
  /**
5
9
  *
@@ -339,3 +343,19 @@ export interface OpenAxisMenuEventPayload {
339
343
  * */
340
344
  customActions?: AxisMenuCustomAction[];
341
345
  }
346
+
347
+ /**
348
+ *
349
+ * @group Custom action callback mapping with action id/ Context Menu
350
+ */
351
+ export interface ContextMenuActionHandler {
352
+ [key: string]: (args: CustomContextMenuAction) => void;
353
+ }
354
+
355
+ /**
356
+ *
357
+ * @group Custom action callback mapping with action id/ Axis Menu
358
+ */
359
+ export interface AxisMenuActionHandler {
360
+ [key: string]: (args: CustomAxisMenuAction) => void;
361
+ }
@@ -160,6 +160,9 @@ export type VisualProps = JSON;
160
160
  type CustomStylingConfig = any;
161
161
 
162
162
  export interface AppConfig {
163
+ /**
164
+ * @hidden
165
+ */
163
166
  styleConfig?: CustomStylingConfig;
164
167
 
165
168
  appOptions?: {
@@ -177,8 +180,19 @@ export interface AppConfig {
177
180
  sessionTimezone: string;
178
181
  };
179
182
 
183
+ /**
184
+ * App url for the custom chart application where the chart app is hosted.
185
+ * This helps the chart developer to access app artifacts relative to this url.
186
+ * There can be different build systems that developers may have used and different ways
187
+ * to host the same. This helps in resolving the same.
188
+ */
189
+ appUrl?: string;
190
+
180
191
  // Idea: we might be able to map this to data and ask user to read data in a
181
192
  // certain way the transformations for point during context menu operations
182
193
  // need to be explored
194
+ /**
195
+ * @hidden
196
+ */
183
197
  customCalendarConfig?: any; // this is to initialize custom calendar service
184
198
  }
@@ -1,4 +1,5 @@
1
1
  import { ChartColumn } from './answer-column.types';
2
+ import { Point } from './chart-to-ts-event.types';
2
3
  import {
3
4
  AppConfig,
4
5
  ChartConfig,
@@ -57,6 +58,16 @@ export enum TSToChartEvent {
57
58
  * @version SDK: 0.1 | ThoughtSpot:
58
59
  */
59
60
  VisualPropsUpdate = 'VisualPropsUpdate',
61
+ /**
62
+ * @version SDK: 0.1 | ThoughtSpot:
63
+ */
64
+
65
+ ContextMenuActionClick = 'ContextMenuActionClick',
66
+
67
+ /**
68
+ * @version SDK: 0.1 | ThoughtSpot:
69
+ */
70
+ AxisMenuActionClick = 'AxisMenuActionClick',
60
71
  }
61
72
 
62
73
  /**
@@ -104,6 +115,14 @@ export interface TSToChartInternalEventsPayloadMap {
104
115
  ) => ValidationResponse;
105
116
 
106
117
  [TSToChartEvent.TriggerRenderChart]: () => void;
118
+
119
+ [TSToChartEvent.ContextMenuActionClick]: (
120
+ payload: ContextMenuCustomActionPayload,
121
+ ) => void;
122
+
123
+ [TSToChartEvent.AxisMenuActionClick]: (
124
+ payload: AxisMenuCustomActionPayload,
125
+ ) => void;
107
126
  }
108
127
 
109
128
  /**
@@ -261,3 +280,54 @@ export interface ChartConfigValidateEventPayload {
261
280
  */
262
281
  chartConfig: ChartConfig[];
263
282
  }
283
+
284
+ /**
285
+ * Custom action dispatched by context menu of the chart
286
+ *
287
+ * @group ThoughtSpot to Chart Events
288
+ * @version SDK: 0.1 | ThoughtSpot:
289
+ */
290
+ export interface CustomContextMenuAction {
291
+ id: string;
292
+ clickedPoint: Point;
293
+ selectedPoints?: Point[];
294
+ event: Pick<PointerEvent, 'clientX' | 'clientY'>;
295
+ }
296
+
297
+ /**
298
+ *
299
+ * @group ThoughtSpot to Chart Events
300
+ */
301
+ export interface ContextMenuCustomActionPayload {
302
+ /**
303
+ * Dispatched custom action from context menu
304
+ *
305
+ * @version SDK: 0.1 | ThoughtSpot:
306
+ */
307
+ customAction: CustomContextMenuAction;
308
+ }
309
+
310
+ /**
311
+ * Custom action dispatched by axis menu of the chart
312
+ *
313
+ * @group ThoughtSpot to Chart Events
314
+ * @version SDK: 0.1 | ThoughtSpot:
315
+ */
316
+ export interface CustomAxisMenuAction {
317
+ id: string;
318
+ columnIds: string[];
319
+ event: Pick<PointerEvent, 'clientX' | 'clientY'>;
320
+ }
321
+
322
+ /**
323
+ *
324
+ * @group ThoughtSpot to Chart Events
325
+ */
326
+ export interface AxisMenuCustomActionPayload {
327
+ /**
328
+ * Dispatched custom action from context menu
329
+ *
330
+ * @version SDK: 0.1 | ThoughtSpot:
331
+ */
332
+ customAction: CustomAxisMenuAction;
333
+ }