@thoughtspot/ts-chart-sdk 0.0.2-alpha.9 → 1.1.0
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/README.md +126 -50
- package/dist/ts-chart-sdk.d.ts +330 -32
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/main/custom-chart-context.d.ts +17 -4
- package/lib/main/custom-chart-context.d.ts.map +1 -1
- package/lib/main/custom-chart-context.js +46 -16
- package/lib/main/custom-chart-context.js.map +1 -1
- package/lib/main/custom-chart-context.spec.js +302 -4
- package/lib/main/custom-chart-context.spec.js.map +1 -1
- package/lib/main/logger.d.ts +13 -0
- package/lib/main/logger.d.ts.map +1 -0
- package/lib/main/logger.js +64 -0
- package/lib/main/logger.js.map +1 -0
- package/lib/main/logger.spec.d.ts +2 -0
- package/lib/main/logger.spec.d.ts.map +1 -0
- package/lib/main/logger.spec.js +88 -0
- package/lib/main/logger.spec.js.map +1 -0
- package/lib/main/util.d.ts +2 -0
- package/lib/main/util.d.ts.map +1 -1
- package/lib/main/util.js +11 -0
- package/lib/main/util.js.map +1 -1
- package/lib/main/util.spec.d.ts +2 -0
- package/lib/main/util.spec.d.ts.map +1 -0
- package/lib/main/util.spec.js +73 -0
- package/lib/main/util.spec.js.map +1 -0
- package/lib/react/use-custom-chart-context.d.ts.map +1 -1
- package/lib/react/use-custom-chart-context.js +3 -1
- package/lib/react/use-custom-chart-context.js.map +1 -1
- package/lib/react/use-custom-chart-context.spec.js +0 -1
- package/lib/react/use-custom-chart-context.spec.js.map +1 -1
- package/lib/react/use-custom-chart-context.util.d.ts.map +1 -1
- package/lib/react/use-custom-chart-context.util.js +5 -3
- package/lib/react/use-custom-chart-context.util.js.map +1 -1
- package/lib/types/answer-column.types.d.ts +7 -4
- package/lib/types/answer-column.types.d.ts.map +1 -1
- package/lib/types/answer-column.types.js +3 -3
- package/lib/types/answer-column.types.js.map +1 -1
- package/lib/types/chart-to-ts-event.types.d.ts +2 -0
- package/lib/types/chart-to-ts-event.types.d.ts.map +1 -1
- package/lib/types/chart-to-ts-event.types.js +1 -0
- package/lib/types/chart-to-ts-event.types.js.map +1 -1
- package/lib/types/common.types.d.ts +65 -6
- package/lib/types/common.types.d.ts.map +1 -1
- package/lib/types/common.types.js.map +1 -1
- package/lib/types/conditional-formatting.types.d.ts +1 -16
- package/lib/types/conditional-formatting.types.d.ts.map +1 -1
- package/lib/types/conditional-formatting.types.js.map +1 -1
- package/lib/types/configurator.types.d.ts +1 -1
- package/lib/types/configurator.types.d.ts.map +1 -1
- package/lib/types/number-formatting.types.d.ts +55 -0
- package/lib/types/number-formatting.types.d.ts.map +1 -0
- package/lib/types/number-formatting.types.js +23 -0
- package/lib/types/number-formatting.types.js.map +1 -0
- package/lib/types/ts-to-chart-event.types.d.ts +20 -6
- package/lib/types/ts-to-chart-event.types.d.ts.map +1 -1
- package/lib/types/ts-to-chart-event.types.js +1 -0
- package/lib/types/ts-to-chart-event.types.js.map +1 -1
- package/lib/types/visual-prop.types.d.ts +71 -3
- package/lib/types/visual-prop.types.d.ts.map +1 -1
- package/lib/types/visual-prop.types.js +32 -1
- package/lib/types/visual-prop.types.js.map +1 -1
- package/lib/utils/date-formatting.d.ts +85 -1
- package/lib/utils/date-formatting.d.ts.map +1 -1
- package/lib/utils/date-formatting.js +344 -9
- package/lib/utils/date-formatting.js.map +1 -1
- package/lib/utils/date-formatting.spec.js +301 -31
- package/lib/utils/date-formatting.spec.js.map +1 -1
- package/lib/utils/date-utils.d.ts +6 -0
- package/lib/utils/date-utils.d.ts.map +1 -0
- package/lib/utils/date-utils.js +20 -0
- package/lib/utils/date-utils.js.map +1 -0
- package/lib/utils/date-utils.spec.d.ts +2 -0
- package/lib/utils/date-utils.spec.d.ts.map +1 -0
- package/lib/utils/date-utils.spec.js +63 -0
- package/lib/utils/date-utils.spec.js.map +1 -0
- package/lib/utils/formatting-util.d.ts +10 -0
- package/lib/utils/formatting-util.d.ts.map +1 -0
- package/lib/utils/formatting-util.js +78 -0
- package/lib/utils/formatting-util.js.map +1 -0
- package/lib/utils/formatting-util.spec.d.ts +2 -0
- package/lib/utils/formatting-util.spec.d.ts.map +1 -0
- package/lib/utils/formatting-util.spec.js +247 -0
- package/lib/utils/formatting-util.spec.js.map +1 -0
- package/lib/utils/globalize-Initializer/globalize-utils.d.ts +16 -0
- package/lib/utils/globalize-Initializer/globalize-utils.d.ts.map +1 -0
- package/lib/utils/globalize-Initializer/globalize-utils.js +101 -0
- package/lib/utils/globalize-Initializer/globalize-utils.js.map +1 -0
- package/lib/utils/globalize-Initializer/globalize-utils.spec.d.ts +2 -0
- package/lib/utils/globalize-Initializer/globalize-utils.spec.d.ts.map +1 -0
- package/lib/utils/globalize-Initializer/globalize-utils.spec.js +149 -0
- package/lib/utils/globalize-Initializer/globalize-utils.spec.js.map +1 -0
- package/lib/utils/number-formatting/number-formatting-utils.d.ts +20 -0
- package/lib/utils/number-formatting/number-formatting-utils.d.ts.map +1 -0
- package/lib/utils/number-formatting/number-formatting-utils.js +159 -0
- package/lib/utils/number-formatting/number-formatting-utils.js.map +1 -0
- package/lib/utils/number-formatting/number-formatting-utils.spec.d.ts +2 -0
- package/lib/utils/number-formatting/number-formatting-utils.spec.d.ts.map +1 -0
- package/lib/utils/number-formatting/number-formatting-utils.spec.js +221 -0
- package/lib/utils/number-formatting/number-formatting-utils.spec.js.map +1 -0
- package/lib/utils/number-formatting/number-formatting.d.ts +5 -0
- package/lib/utils/number-formatting/number-formatting.d.ts.map +1 -0
- package/lib/utils/number-formatting/number-formatting.js +128 -0
- package/lib/utils/number-formatting/number-formatting.js.map +1 -0
- package/lib/utils/number-formatting/number-formatting.spec.d.ts +2 -0
- package/lib/utils/number-formatting/number-formatting.spec.d.ts.map +1 -0
- package/lib/utils/number-formatting/number-formatting.spec.js +159 -0
- package/lib/utils/number-formatting/number-formatting.spec.js.map +1 -0
- package/package.json +4 -1
- package/src/index.ts +3 -0
- package/src/main/custom-chart-context.spec.ts +356 -6
- package/src/main/custom-chart-context.ts +205 -16
- package/src/main/logger.spec.ts +114 -0
- package/src/main/logger.ts +97 -0
- package/src/main/util.spec.ts +94 -0
- package/src/main/util.ts +20 -0
- package/src/react/use-custom-chart-context.spec.tsx +0 -1
- package/src/react/use-custom-chart-context.tsx +4 -1
- package/src/react/use-custom-chart-context.util.ts +6 -3
- package/src/types/answer-column.types.ts +9 -6
- package/src/types/chart-to-ts-event.types.ts +7 -0
- package/src/types/common.types.ts +100 -10
- package/src/types/conditional-formatting.types.ts +2 -17
- package/src/types/configurator.types.ts +1 -1
- package/src/types/number-formatting.types.ts +80 -0
- package/src/types/ts-to-chart-event.types.ts +63 -5
- package/src/types/visual-prop.types.ts +197 -3
- package/src/utils/date-formatting.spec.ts +375 -32
- package/src/utils/date-formatting.ts +587 -14
- package/src/utils/date-utils.spec.ts +93 -0
- package/src/utils/date-utils.ts +69 -0
- package/src/utils/formatting-util.spec.ts +312 -0
- package/src/utils/formatting-util.ts +234 -0
- package/src/utils/globalize-Initializer/globalize-utils.spec.ts +192 -0
- package/src/utils/globalize-Initializer/globalize-utils.ts +216 -0
- package/src/utils/number-formatting/number-formatting-utils.spec.ts +296 -0
- package/src/utils/number-formatting/number-formatting-utils.ts +260 -0
- package/src/utils/number-formatting/number-formatting.spec.ts +243 -0
- package/src/utils/number-formatting/number-formatting.ts +264 -0
|
@@ -35,6 +35,8 @@ import {
|
|
|
35
35
|
ChartModelUpdateEventPayload,
|
|
36
36
|
ContextMenuCustomActionPayload,
|
|
37
37
|
DataUpdateEventPayload,
|
|
38
|
+
GetColumnDataPayload,
|
|
39
|
+
GetColumnDataResponsePayload,
|
|
38
40
|
GetDataQueryPayload,
|
|
39
41
|
GetDataQueryResponsePayload,
|
|
40
42
|
InitializeEventPayload,
|
|
@@ -50,16 +52,127 @@ import {
|
|
|
50
52
|
VisualEditorDefinitionSetter,
|
|
51
53
|
VisualPropEditorDefinition,
|
|
52
54
|
} from '../types/visual-prop.types';
|
|
55
|
+
import { setLocaleBasedStringFormats } from '../utils/number-formatting/number-formatting-utils';
|
|
56
|
+
import { create } from './logger';
|
|
53
57
|
import {
|
|
54
58
|
globalThis,
|
|
55
59
|
initMessageListener,
|
|
56
60
|
postMessageToHostApp,
|
|
57
61
|
} from './post-message-event-bridge';
|
|
58
62
|
|
|
63
|
+
const logger = create('TsChartSDKContext');
|
|
64
|
+
/**
|
|
65
|
+
* Configuration for allowing or disallowing specific TS UI features.
|
|
66
|
+
*
|
|
67
|
+
* @fileoverview
|
|
68
|
+
* This configuration defines the ability to toggle specific features such as
|
|
69
|
+
* column number formatting, conditional formatting, and measure names/values.
|
|
70
|
+
*
|
|
71
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
72
|
+
*/
|
|
59
73
|
export type AllowedConfigurations = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Allows column-level number formatting.
|
|
76
|
+
*
|
|
77
|
+
* @default false
|
|
78
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
79
|
+
*/
|
|
80
|
+
allowColumnNumberFormatting?: boolean;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Allows conditional formatting at the column level.
|
|
84
|
+
* This allows users to apply rules that visually highlight or differentiate data.
|
|
85
|
+
*
|
|
86
|
+
* @default false
|
|
87
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
88
|
+
*/
|
|
89
|
+
allowColumnConditionalFormatting?: boolean;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Allows Gradient coloring at the column level.
|
|
93
|
+
*
|
|
94
|
+
* @default false
|
|
95
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
96
|
+
*/
|
|
97
|
+
allowGradientColoring?: boolean;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Enables measure_name and measure_values in the chart configuration.
|
|
101
|
+
*
|
|
102
|
+
* @default false
|
|
103
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
104
|
+
*/
|
|
105
|
+
allowMeasureNamesAndValues?: boolean;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Key stored in persistedVisualPropKeys array will be preserved on changing the
|
|
109
|
+
* visualPropeditorDefinition, any other key (expect clientState) would not be preserved for visual props.
|
|
110
|
+
* ### NOTE: like clientState this variable should be a string, preferrably a result of JSON.stringify(<yourlocalClientState>)
|
|
111
|
+
* ### USE CASE: This is to maintain different clientSate for different custom charts developed by same TS custom chart developer.
|
|
112
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
113
|
+
*/
|
|
114
|
+
export type PersistedVisualPropKeys = string[];
|
|
115
|
+
/**
|
|
116
|
+
* Configuration parameters for setting chart-specific options.
|
|
117
|
+
*
|
|
118
|
+
* @fileoverview
|
|
119
|
+
* This configuration includes settings for controlling measure name/value columns
|
|
120
|
+
* and batch size limits for data processing.
|
|
121
|
+
*
|
|
122
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
123
|
+
*/
|
|
124
|
+
export type ChartConfigParameters = {
|
|
125
|
+
/**
|
|
126
|
+
* Configurations related to measure name and value columns.
|
|
127
|
+
* These parameters allow for enabling/disabling and aliasing the columns
|
|
128
|
+
* used to represent measure names and values.
|
|
129
|
+
*
|
|
130
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
131
|
+
*/
|
|
132
|
+
measureNameValueColumns?: {
|
|
133
|
+
/**
|
|
134
|
+
* Enables or disables the measure_name column.
|
|
135
|
+
*
|
|
136
|
+
* @default false
|
|
137
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
138
|
+
*/
|
|
139
|
+
enableMeasureNameColumn?: boolean;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Enables or disables the measure_value column.
|
|
143
|
+
*
|
|
144
|
+
* @default false
|
|
145
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
146
|
+
*/
|
|
147
|
+
enableMeasureValueColumn?: boolean;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Alias for the measure_name column.
|
|
151
|
+
* This allows users to define a custom name for the measure_name column.
|
|
152
|
+
*
|
|
153
|
+
* @default 'Measure Name'
|
|
154
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
155
|
+
*/
|
|
156
|
+
measureNameColumnAlias?: string;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Alias for the measure_value column.
|
|
160
|
+
* This allows users to define a custom name for the measure_value column.
|
|
161
|
+
*
|
|
162
|
+
* @default 'Measure Value'
|
|
163
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
164
|
+
*/
|
|
165
|
+
measureValueColumnAlias?: string;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Limit on the batch size for data processing.
|
|
170
|
+
* This sets an upper limit on how much data can be processed in a single batch.
|
|
171
|
+
*
|
|
172
|
+
* @default 20000
|
|
173
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
174
|
+
*/
|
|
175
|
+
batchSizeLimit?: number;
|
|
63
176
|
};
|
|
64
177
|
|
|
65
178
|
export type CustomChartContextProps = {
|
|
@@ -116,6 +229,7 @@ export type CustomChartContextProps = {
|
|
|
116
229
|
validateVisualProps?: (
|
|
117
230
|
updatedVisualProps: VisualProps,
|
|
118
231
|
chartModel: ChartModel,
|
|
232
|
+
activeColumnId?: string,
|
|
119
233
|
) => ValidationResponse;
|
|
120
234
|
|
|
121
235
|
/**
|
|
@@ -141,8 +255,36 @@ export type CustomChartContextProps = {
|
|
|
141
255
|
| VisualEditorDefinitionSetter
|
|
142
256
|
| VisualPropEditorDefinition;
|
|
143
257
|
|
|
144
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Optional configuration to toggle native TS UI configurations, such as column number
|
|
260
|
+
* formatting and conditional formatting.
|
|
261
|
+
*
|
|
262
|
+
* @type {AllowedConfigurations}
|
|
263
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
264
|
+
*/
|
|
145
265
|
allowedConfigurations?: AllowedConfigurations;
|
|
266
|
+
/**
|
|
267
|
+
/**
|
|
268
|
+
* Key stored in persistedVisualPropKeys array will be preserved on changing the
|
|
269
|
+
* visualPropeditorDefinition, any other key (expect clientState)
|
|
270
|
+
* would not be preserved for visual props.
|
|
271
|
+
* ### NOTE: like clientState this variable should be a string,
|
|
272
|
+
* preferrably a result of JSON.stringify(<yourlocalClientState>)
|
|
273
|
+
* ### USE CASE: This is to maintain different clientSate for different custom charts
|
|
274
|
+
* developed by same TS custom chart developer.
|
|
275
|
+
*
|
|
276
|
+
* @type {PersistedVisualPropKeys}
|
|
277
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
278
|
+
*/
|
|
279
|
+
persistedVisualPropKeys?: PersistedVisualPropKeys;
|
|
280
|
+
/**
|
|
281
|
+
* Optional parameters for configuring specific chart-related features, such as measure name
|
|
282
|
+
* and value columns.
|
|
283
|
+
*
|
|
284
|
+
* @type {ChartConfigParameters}
|
|
285
|
+
* @version SDK: 0.1 | ThoughtSpot:
|
|
286
|
+
*/
|
|
287
|
+
chartConfigParameters?: ChartConfigParameters;
|
|
146
288
|
};
|
|
147
289
|
|
|
148
290
|
export type ValidationFunctions =
|
|
@@ -159,8 +301,19 @@ const DEFAULT_CHART_CONTEXT_PROPS: Partial<CustomChartContextProps> = {
|
|
|
159
301
|
allowedConfigurations: {
|
|
160
302
|
allowColumnNumberFormatting: false,
|
|
161
303
|
allowColumnConditionalFormatting: false,
|
|
304
|
+
allowGradientColoring: false,
|
|
162
305
|
allowMeasureNamesAndValues: false,
|
|
163
306
|
},
|
|
307
|
+
persistedVisualPropKeys: undefined,
|
|
308
|
+
chartConfigParameters: {
|
|
309
|
+
measureNameValueColumns: {
|
|
310
|
+
enableMeasureNameColumn: false,
|
|
311
|
+
enableMeasureValueColumn: false,
|
|
312
|
+
measureNameColumnAlias: 'Measure Name',
|
|
313
|
+
measureValueColumnAlias: 'Measure Values',
|
|
314
|
+
},
|
|
315
|
+
batchSizeLimit: 20000,
|
|
316
|
+
},
|
|
164
317
|
};
|
|
165
318
|
|
|
166
319
|
export class CustomChartContext {
|
|
@@ -269,6 +422,9 @@ export class CustomChartContext {
|
|
|
269
422
|
this.hasInitializedPromise = new Promise((resolve, reject) => {
|
|
270
423
|
this.triggerInitResolve = resolve;
|
|
271
424
|
});
|
|
425
|
+
// Not using this.emitEvent as the context is not yet completely
|
|
426
|
+
// initialized, thus short circuiting.
|
|
427
|
+
postMessageToHostApp('', '*', null, ChartToTSEvent.InitStart);
|
|
272
428
|
}
|
|
273
429
|
|
|
274
430
|
/**
|
|
@@ -279,7 +435,7 @@ export class CustomChartContext {
|
|
|
279
435
|
* @version SDK: 0.1 | ThoughtSpot:
|
|
280
436
|
*/
|
|
281
437
|
public initialize = (): Promise<void> => {
|
|
282
|
-
|
|
438
|
+
logger.log('Chart Context: initialization start');
|
|
283
439
|
return this.hasInitializedPromise;
|
|
284
440
|
};
|
|
285
441
|
|
|
@@ -311,7 +467,7 @@ export class CustomChartContext {
|
|
|
311
467
|
*/
|
|
312
468
|
public off<T extends keyof TSToChartEventsPayloadMap>(eventType: T): void {
|
|
313
469
|
if (_.isNil(this.eventListeners[eventType])) {
|
|
314
|
-
|
|
470
|
+
logger.log('No event listener found to remove');
|
|
315
471
|
this.eventListeners[eventType] = [];
|
|
316
472
|
return;
|
|
317
473
|
}
|
|
@@ -424,6 +580,7 @@ export class CustomChartContext {
|
|
|
424
580
|
* @returns {VisualPropEditorDefinition}
|
|
425
581
|
*/
|
|
426
582
|
private getVisualPropEditorDefinition = (
|
|
583
|
+
activeColumnId?: string,
|
|
427
584
|
currentState: Partial<ChartModel> = {},
|
|
428
585
|
) => {
|
|
429
586
|
if (_.isFunction(this.chartContextProps.visualPropEditorDefinition)) {
|
|
@@ -433,6 +590,7 @@ export class CustomChartContext {
|
|
|
433
590
|
...currentState,
|
|
434
591
|
},
|
|
435
592
|
this,
|
|
593
|
+
activeColumnId,
|
|
436
594
|
);
|
|
437
595
|
}
|
|
438
596
|
return this.chartContextProps.visualPropEditorDefinition;
|
|
@@ -500,8 +658,10 @@ export class CustomChartContext {
|
|
|
500
658
|
private validationsResponseProcessor(
|
|
501
659
|
currentValidationState: Partial<ChartModel>,
|
|
502
660
|
validationResponse: ValidationResponse,
|
|
661
|
+
activeColumnId?: string,
|
|
503
662
|
) {
|
|
504
663
|
const visualPropEditorDefinition = this.getVisualPropEditorDefinition(
|
|
664
|
+
activeColumnId,
|
|
505
665
|
currentValidationState,
|
|
506
666
|
);
|
|
507
667
|
const chartConfigEditorDefinition = this.getChartConfigEditorDefinition(
|
|
@@ -528,7 +688,7 @@ export class CustomChartContext {
|
|
|
528
688
|
...eventPayload: ChartToTSEventsPayloadMap[T]
|
|
529
689
|
): Promise<any> {
|
|
530
690
|
if (!globalThis.isInitialized) {
|
|
531
|
-
|
|
691
|
+
logger.log(
|
|
532
692
|
'Chart Context: not initialized the context, something went wrong',
|
|
533
693
|
);
|
|
534
694
|
return Promise.reject(new Error('Context not initialized'));
|
|
@@ -551,7 +711,7 @@ export class CustomChartContext {
|
|
|
551
711
|
*/
|
|
552
712
|
private registerEventProcessor = () => {
|
|
553
713
|
if (globalThis.isInitialized) {
|
|
554
|
-
|
|
714
|
+
logger.error(
|
|
555
715
|
'The context is already initialized. you cannot have multiple contexts',
|
|
556
716
|
);
|
|
557
717
|
throw new Error(ErrorType.MultipleContextsNotSupported);
|
|
@@ -567,12 +727,12 @@ export class CustomChartContext {
|
|
|
567
727
|
* @param event : Message Event Object
|
|
568
728
|
*/
|
|
569
729
|
private eventProcessor = (data: any) => {
|
|
570
|
-
|
|
730
|
+
logger.log('Chart Context: message received:', data.eventType, data);
|
|
571
731
|
|
|
572
732
|
const messageResponse = this.executeEventListenerCBs(data);
|
|
573
733
|
|
|
574
734
|
// respond back to parent to confirm/ack the receipt
|
|
575
|
-
return messageResponse;
|
|
735
|
+
return messageResponse || {};
|
|
576
736
|
};
|
|
577
737
|
|
|
578
738
|
/**
|
|
@@ -617,15 +777,17 @@ export class CustomChartContext {
|
|
|
617
777
|
this.chartContextProps.validateVisualProps(
|
|
618
778
|
payload.visualProps,
|
|
619
779
|
this.chartModel,
|
|
780
|
+
payload?.activeColumnId,
|
|
620
781
|
);
|
|
621
782
|
if (validationResponse.isValid) {
|
|
622
783
|
const currentVisualState = {
|
|
623
784
|
visualProps: payload.visualProps,
|
|
624
785
|
};
|
|
625
|
-
|
|
786
|
+
const activeColumnId = payload?.activeColumnId;
|
|
626
787
|
return this.validationsResponseProcessor(
|
|
627
788
|
currentVisualState,
|
|
628
789
|
validationResponse,
|
|
790
|
+
activeColumnId,
|
|
629
791
|
);
|
|
630
792
|
}
|
|
631
793
|
return validationResponse;
|
|
@@ -690,6 +852,28 @@ export class CustomChartContext {
|
|
|
690
852
|
},
|
|
691
853
|
);
|
|
692
854
|
|
|
855
|
+
/**
|
|
856
|
+
* This event is triggered when the TS app asks for data in a specific columns
|
|
857
|
+
* for certain validations for settings and drop down options related to Conditional
|
|
858
|
+
* formatting and other advanced settings
|
|
859
|
+
*/
|
|
860
|
+
this.onInternal(
|
|
861
|
+
TSToChartEvent.GetColumnData,
|
|
862
|
+
(payload: GetColumnDataPayload): GetColumnDataResponsePayload => {
|
|
863
|
+
const parsedData = this.chartModel.data?.[0].data;
|
|
864
|
+
const dataIdx = parsedData?.columns.findIndex(
|
|
865
|
+
(columnId) => columnId === payload.columnId,
|
|
866
|
+
);
|
|
867
|
+
const dataArray =
|
|
868
|
+
!_.isNil(dataIdx) && dataIdx > -1
|
|
869
|
+
? parsedData?.dataValue.map((it) => it[dataIdx])
|
|
870
|
+
: [];
|
|
871
|
+
return {
|
|
872
|
+
data: dataArray,
|
|
873
|
+
};
|
|
874
|
+
},
|
|
875
|
+
);
|
|
876
|
+
|
|
693
877
|
/**
|
|
694
878
|
* This event is triggered when the TS app re-renders the chart
|
|
695
879
|
*/
|
|
@@ -728,7 +912,7 @@ export class CustomChartContext {
|
|
|
728
912
|
isValid: true,
|
|
729
913
|
};
|
|
730
914
|
} catch (error: unknown) {
|
|
731
|
-
|
|
915
|
+
logger.log(
|
|
732
916
|
'ContextMenuCustomAction: payload recieved:',
|
|
733
917
|
payload,
|
|
734
918
|
'CustomActionCallbackStore:',
|
|
@@ -771,7 +955,7 @@ export class CustomChartContext {
|
|
|
771
955
|
isValid: true,
|
|
772
956
|
};
|
|
773
957
|
} catch (error: unknown) {
|
|
774
|
-
|
|
958
|
+
logger.log(
|
|
775
959
|
'AxisMenuCustomAction: payload recieved:',
|
|
776
960
|
payload,
|
|
777
961
|
'CustomActionCallbackStore:',
|
|
@@ -859,7 +1043,9 @@ export class CustomChartContext {
|
|
|
859
1043
|
this.containerEl = payload.containerElSelector
|
|
860
1044
|
? document.querySelector(payload.containerElSelector)
|
|
861
1045
|
: null;
|
|
862
|
-
|
|
1046
|
+
setLocaleBasedStringFormats(
|
|
1047
|
+
this.appConfig.dateFormatsConfig?.tsLocaleBasedStringsFormats,
|
|
1048
|
+
);
|
|
863
1049
|
return this.publishChartContextPropsToHost();
|
|
864
1050
|
};
|
|
865
1051
|
|
|
@@ -901,6 +1087,10 @@ export class CustomChartContext {
|
|
|
901
1087
|
this.getVisualPropEditorDefinition(),
|
|
902
1088
|
allowedConfigurations:
|
|
903
1089
|
this.chartContextProps.allowedConfigurations,
|
|
1090
|
+
chartConfigParameters:
|
|
1091
|
+
this.chartContextProps.chartConfigParameters,
|
|
1092
|
+
persistedVisualPropKeys:
|
|
1093
|
+
this.chartContextProps.persistedVisualPropKeys,
|
|
904
1094
|
};
|
|
905
1095
|
};
|
|
906
1096
|
|
|
@@ -928,7 +1118,7 @@ export class CustomChartContext {
|
|
|
928
1118
|
};
|
|
929
1119
|
}
|
|
930
1120
|
|
|
931
|
-
|
|
1121
|
+
logger.log(
|
|
932
1122
|
'ChartContext: Response:',
|
|
933
1123
|
data.eventType,
|
|
934
1124
|
response,
|
|
@@ -951,6 +1141,5 @@ export const getChartContext = async (
|
|
|
951
1141
|
// wait for initialization here as the host app
|
|
952
1142
|
// needs to first handshake with the client app.
|
|
953
1143
|
await ctx.initialize();
|
|
954
|
-
|
|
955
1144
|
return ctx;
|
|
956
1145
|
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { create, LogLevel, logMethods } from './logger';
|
|
2
|
+
|
|
3
|
+
jest.mock('./util', () => ({
|
|
4
|
+
getQueryParam: jest.fn().mockReturnValue('true'),
|
|
5
|
+
}));
|
|
6
|
+
|
|
7
|
+
describe('Logger', () => {
|
|
8
|
+
let originalConsole: Record<string, any>;
|
|
9
|
+
let logger: any;
|
|
10
|
+
|
|
11
|
+
beforeAll(() => {
|
|
12
|
+
// Save original console methods
|
|
13
|
+
originalConsole = {
|
|
14
|
+
error: console.error,
|
|
15
|
+
warn: console.warn,
|
|
16
|
+
info: console.info,
|
|
17
|
+
log: console.log,
|
|
18
|
+
trace: console.trace,
|
|
19
|
+
};
|
|
20
|
+
// Mock console methods
|
|
21
|
+
const error = jest.fn();
|
|
22
|
+
const warn = jest.fn();
|
|
23
|
+
const info = jest.fn();
|
|
24
|
+
const log = jest.fn();
|
|
25
|
+
const trace = jest.fn();
|
|
26
|
+
logMethods[LogLevel.ERROR] = error;
|
|
27
|
+
logMethods[LogLevel.WARN] = warn;
|
|
28
|
+
logMethods[LogLevel.INFO] = info;
|
|
29
|
+
logMethods[LogLevel.DEBUG] = log;
|
|
30
|
+
logMethods[LogLevel.TRACE] = trace;
|
|
31
|
+
console.error = error;
|
|
32
|
+
console.warn = warn;
|
|
33
|
+
console.info = info;
|
|
34
|
+
console.log = log;
|
|
35
|
+
console.trace = trace;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterAll(() => {
|
|
39
|
+
// Restore original console methods
|
|
40
|
+
logMethods[LogLevel.ERROR] = originalConsole.error;
|
|
41
|
+
logMethods[LogLevel.WARN] = originalConsole.warn;
|
|
42
|
+
logMethods[LogLevel.INFO] = originalConsole.info;
|
|
43
|
+
logMethods[LogLevel.DEBUG] = originalConsole.log;
|
|
44
|
+
logMethods[LogLevel.TRACE] = originalConsole.trace;
|
|
45
|
+
console.error = originalConsole.error;
|
|
46
|
+
console.warn = originalConsole.warn;
|
|
47
|
+
console.info = originalConsole.info;
|
|
48
|
+
console.log = originalConsole.log;
|
|
49
|
+
console.trace = originalConsole.trace;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
// Set debug to 'true' to enable logging
|
|
54
|
+
(global as any).window = {
|
|
55
|
+
location: { href: 'https://example.com/?debug=true' },
|
|
56
|
+
};
|
|
57
|
+
logger = create('TestLogger');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
jest.clearAllMocks();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('logMessages', () => {
|
|
65
|
+
it('should log messages with appropriate prefixes for DEBUG level', async () => {
|
|
66
|
+
await logger.debug('Debug message');
|
|
67
|
+
expect(console.log).toHaveBeenCalledWith(
|
|
68
|
+
'DEBUG (TestLogger)(] Debug message)',
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should log messages with appropriate prefixes for INFO level', async () => {
|
|
73
|
+
await logger.info('Info message');
|
|
74
|
+
expect(console.info).toHaveBeenCalledWith(
|
|
75
|
+
'INFO (TestLogger)(] Info message)',
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should log messages with appropriate prefixes for WARN level', async () => {
|
|
80
|
+
await logger.warn('Warn message');
|
|
81
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
82
|
+
'WARN (TestLogger)(] Warn message)',
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should log messages with appropriate prefixes for ERROR level', async () => {
|
|
87
|
+
await logger.error('Error message');
|
|
88
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
89
|
+
'ERROR (TestLogger)(] Error message)',
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should log messages with appropriate prefixes for TRACE level', async () => {
|
|
94
|
+
await logger.trace('Trace message');
|
|
95
|
+
expect(console.trace).toHaveBeenCalledWith(
|
|
96
|
+
'TRACE (TestLogger)(] Trace message)',
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('create function', () => {
|
|
102
|
+
it('should create a new logger instance if one does not exist', () => {
|
|
103
|
+
const newLogger = create('NewLogger');
|
|
104
|
+
expect(newLogger).not.toBe(undefined);
|
|
105
|
+
expect(newLogger).toBeInstanceOf(Object);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should return the same logger instance if it already exists', () => {
|
|
109
|
+
const logger1 = create('SharedLogger');
|
|
110
|
+
const logger2 = create('SharedLogger');
|
|
111
|
+
expect(logger1).toBe(logger2);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { getQueryParam } from './util';
|
|
2
|
+
|
|
3
|
+
const loggers: Record<string, any> = {};
|
|
4
|
+
const url = window.location.href;
|
|
5
|
+
|
|
6
|
+
export enum LogLevel {
|
|
7
|
+
SILENT = -1 as number,
|
|
8
|
+
ERROR = 0 as number,
|
|
9
|
+
WARN = 1 as number,
|
|
10
|
+
INFO = 2 as number,
|
|
11
|
+
DEBUG = 3 as number,
|
|
12
|
+
TRACE = 4 as number,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const logMethods: { [key: number]: any } = {
|
|
16
|
+
[LogLevel.ERROR]: console.error,
|
|
17
|
+
[LogLevel.WARN]: console.warn,
|
|
18
|
+
[LogLevel.INFO]: console.info,
|
|
19
|
+
[LogLevel.DEBUG]: console.log,
|
|
20
|
+
[LogLevel.TRACE]: console.trace,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
class Logger {
|
|
24
|
+
private msgPrefix: string;
|
|
25
|
+
|
|
26
|
+
constructor(name: string) {
|
|
27
|
+
this.msgPrefix = name ? `(${name})` : '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private getFormattedMessage(msg: string, logLevel: LogLevel) {
|
|
31
|
+
return (
|
|
32
|
+
`${LogLevel[logLevel]} ${this.msgPrefix}` +
|
|
33
|
+
`(${msg ? `] ${msg}` : ''})`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public async logMessages(args: any, logLevel: LogLevel) {
|
|
38
|
+
const newArgs = args;
|
|
39
|
+
if (getQueryParam(url, 'debug') !== 'true') {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const logFn = logMethods[logLevel];
|
|
43
|
+
newArgs[0] = this.getFormattedMessage(newArgs[0], logLevel);
|
|
44
|
+
if (logFn) {
|
|
45
|
+
logFn(...newArgs);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public async trace(...args: any) {
|
|
50
|
+
this.logMessages(args, LogLevel.TRACE);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Wrapper for log.log() with debug level
|
|
55
|
+
* @param msg
|
|
56
|
+
*/
|
|
57
|
+
public async debug(...args: any) {
|
|
58
|
+
this.logMessages(args, LogLevel.DEBUG);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async log(...args: any) {
|
|
62
|
+
this.debug(...args);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Wrapper for log.info() with info level
|
|
67
|
+
* @param msg
|
|
68
|
+
*/
|
|
69
|
+
public async info(...args: any) {
|
|
70
|
+
this.logMessages(args, LogLevel.INFO);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Wrapper for log.warn() with warn level
|
|
75
|
+
*
|
|
76
|
+
* @param {string} msg The log message
|
|
77
|
+
*/
|
|
78
|
+
public async warn(...args: any) {
|
|
79
|
+
this.logMessages(args, LogLevel.WARN);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Wrapper for log.error() with error level
|
|
84
|
+
* Error is propagated via callback
|
|
85
|
+
* @param {string} msg The log message
|
|
86
|
+
*/
|
|
87
|
+
public async error(...args: any) {
|
|
88
|
+
const stackTrace = this.logMessages(args, LogLevel.ERROR);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function create(name: string): any {
|
|
93
|
+
if (!loggers[name]) {
|
|
94
|
+
loggers[name] = new Logger(name);
|
|
95
|
+
}
|
|
96
|
+
return loggers[name];
|
|
97
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { getQueryParam, handleMissingValue, timeout } from './util';
|
|
2
|
+
|
|
3
|
+
describe('timeout function', () => {
|
|
4
|
+
jest.useFakeTimers();
|
|
5
|
+
|
|
6
|
+
it('should resolve with the original promise result if it completes before timeout', async () => {
|
|
7
|
+
const promise = Promise.resolve('success');
|
|
8
|
+
const result = timeout(promise, 1000);
|
|
9
|
+
|
|
10
|
+
await expect(result).resolves.toBe('success');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should reject with a timeout error if the promise takes too long', async () => {
|
|
14
|
+
const promise = new Promise((resolve) => {
|
|
15
|
+
setTimeout(resolve, 2000);
|
|
16
|
+
});
|
|
17
|
+
const result = timeout(promise, 1000);
|
|
18
|
+
|
|
19
|
+
jest.advanceTimersByTime(1000);
|
|
20
|
+
|
|
21
|
+
await expect(result).rejects.toThrow('Operation timed out.');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should use the custom error message when provided', async () => {
|
|
25
|
+
const promise = new Promise((resolve) => {
|
|
26
|
+
setTimeout(resolve, 2000);
|
|
27
|
+
});
|
|
28
|
+
const result = timeout(promise, 1000, 'Custom timeout message');
|
|
29
|
+
|
|
30
|
+
jest.advanceTimersByTime(1000);
|
|
31
|
+
|
|
32
|
+
await expect(result).rejects.toThrow('Custom timeout message');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should reject with the original promise error if it rejects before timeout', async () => {
|
|
36
|
+
const promise = Promise.reject(new Error('Original error'));
|
|
37
|
+
const result = timeout(promise, 1000);
|
|
38
|
+
|
|
39
|
+
await expect(result).rejects.toThrow('Original error');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('getQueryParam', () => {
|
|
44
|
+
it('should return the value of a query parameter if it exists', () => {
|
|
45
|
+
const url = 'https://example.com/?key=value';
|
|
46
|
+
expect(getQueryParam(url, 'key')).toBe('value');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should return an empty string if the query parameter does not exist', () => {
|
|
50
|
+
const url = 'https://example.com/';
|
|
51
|
+
expect(getQueryParam(url, 'missingKey')).toBe('');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should return "false" if the query parameter is "debug" and it is not present', () => {
|
|
55
|
+
const url = 'https://example.com/';
|
|
56
|
+
expect(getQueryParam(url, 'debug')).toBe('false');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should return the default value "false" if the query parameter is "debug" and is set to an empty value', () => {
|
|
60
|
+
const url = 'https://example.com/?debug=';
|
|
61
|
+
expect(getQueryParam(url, 'debug')).toBe('');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should handle complex URLs with multiple parameters correctly', () => {
|
|
65
|
+
const url = 'https://example.com/?key1=value1&key2=value2';
|
|
66
|
+
expect(getQueryParam(url, 'key2')).toBe('value2');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('handleMissingValue', () => {
|
|
71
|
+
it('should return "false" if paramKey is "debug" and paramValue is undefined', () => {
|
|
72
|
+
expect(handleMissingValue('debug', undefined)).toBe('false');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should return "false" if paramKey is "debug" and paramValue is null', () => {
|
|
76
|
+
expect(handleMissingValue('debug', null)).toBe('false');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return an empty string if paramValue is undefined and paramKey is not "debug"', () => {
|
|
80
|
+
expect(handleMissingValue('param', undefined)).toBe('');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should return an empty string if paramValue is null and paramKey is not "debug"', () => {
|
|
84
|
+
expect(handleMissingValue('param', null)).toBe('');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should return the paramValue if paramValue is defined and not null', () => {
|
|
88
|
+
expect(handleMissingValue('param', 'value')).toBe('value');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return the paramValue even if paramKey is "debug" and paramValue is defined', () => {
|
|
92
|
+
expect(handleMissingValue('debug', 'true')).toBe('true');
|
|
93
|
+
});
|
|
94
|
+
});
|