diff --git a/CHANGELOG.md b/CHANGELOG.md index cc8b3302..fb5ab704 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.17.0] - 2024-08-20 + +### Added +- Move components `DashboardById` and `Dashboard` to internal alpha for React, Angular, and Vue +- Support external usage tracking in `AppConfig.trackingConfig.onTrackingEvent` +- Refactor `ChartWidget` to reuse `DrilldownWidget` internally +- Support drill down for scatter chart widgets + +### Changed +- Mark internal property `enableTracking?` as `@deprecated` in `SisenseContextProviderProps` – use `AppConfig.trackingConfig.enabled` instead +- Extend `ThemeSettings` to support animation-related config +- Improve dashboard rendering: locked filters in cross filtering, resetting levels of `CascadingFilterTile`, highlight of all categories in cartesian charts, dashboard theme setting, matching theme for widget header info panel +- Refactor component `Table` to reduce computations and re-renders +- Fix issues of charts: legend position of funnel chart, number formatting for indicator's secondary value +- Improve `SisenseContextProvider` in React: support of pending `token` or `wat` for delayed authentication and custom error handling +- Improve testing: disabling animation for e2e tests + ## [1.16.0] - 2024-08-06 ### Added diff --git a/docs-md/sdk/CHANGELOG.md b/docs-md/sdk/CHANGELOG.md index cc8b3302..fb5ab704 100644 --- a/docs-md/sdk/CHANGELOG.md +++ b/docs-md/sdk/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.17.0] - 2024-08-20 + +### Added +- Move components `DashboardById` and `Dashboard` to internal alpha for React, Angular, and Vue +- Support external usage tracking in `AppConfig.trackingConfig.onTrackingEvent` +- Refactor `ChartWidget` to reuse `DrilldownWidget` internally +- Support drill down for scatter chart widgets + +### Changed +- Mark internal property `enableTracking?` as `@deprecated` in `SisenseContextProviderProps` – use `AppConfig.trackingConfig.enabled` instead +- Extend `ThemeSettings` to support animation-related config +- Improve dashboard rendering: locked filters in cross filtering, resetting levels of `CascadingFilterTile`, highlight of all categories in cartesian charts, dashboard theme setting, matching theme for widget header info panel +- Refactor component `Table` to reduce computations and re-renders +- Fix issues of charts: legend position of funnel chart, number formatting for indicator's secondary value +- Improve `SisenseContextProvider` in React: support of pending `token` or `wat` for delayed authentication and custom error handling +- Improve testing: disabling animation for e2e tests + ## [1.16.0] - 2024-08-06 ### Added diff --git a/docs-md/sdk/modules/sdk-data/interfaces/interface.Cell.md b/docs-md/sdk/modules/sdk-data/interfaces/interface.Cell.md index 98ff739a..68d2bb16 100644 --- a/docs-md/sdk/modules/sdk-data/interfaces/interface.Cell.md +++ b/docs-md/sdk/modules/sdk-data/interfaces/interface.Cell.md @@ -13,7 +13,10 @@ or [query result data set](interface.QueryResultData.md). > **blur**?: `boolean` -Boolean flag whether the data value should be blurred when visualized in a chart +Boolean flag representing three states that can be visualized in a chart: +- `true`: the data value is in blur state +- `false`: the data value is in highlight state +- if not specified, the data value is neither in highlight nor blur state *** diff --git a/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/class.DashboardByIdComponent.md b/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/class.DashboardByIdComponent.md new file mode 100644 index 00000000..bb6da81d --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/class.DashboardByIdComponent.md @@ -0,0 +1,80 @@ +--- +title: DashboardByIdComponent +--- + +# Class DashboardByIdComponent + +An Angular component used for easily rendering a dashboard by its ID created in a Sisense Fusion instance. + +**Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. + +## Example + +```html + +``` +```ts +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.scss'], +}) +export class DashboardComponent { + dashboardOid: string = '60f3e3e3e4b0e3e3e4b0e3e3'; +} +``` + +## Implements + +- `AfterViewInit` +- `OnChanges` +- `OnDestroy` + +## Constructors + +### constructor + +> **new DashboardByIdComponent**(`sisenseContextService`, `themeService`): [`DashboardByIdComponent`](class.DashboardByIdComponent.md) + +Constructor for the `DashboardById` component. + +#### Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `sisenseContextService` | [`SisenseContextService`](../contexts/class.SisenseContextService.md) | Sisense context service | +| `themeService` | [`ThemeService`](../contexts/class.ThemeService.md) | Theme service | + +#### Returns + +[`DashboardByIdComponent`](class.DashboardByIdComponent.md) + +## Properties + +### Constructor + +#### sisenseContextService + +> **sisenseContextService**: [`SisenseContextService`](../contexts/class.SisenseContextService.md) + +Sisense context service + +*** + +#### themeService + +> **themeService**: [`ThemeService`](../contexts/class.ThemeService.md) + +Theme service + +### Other + +#### dashboardOid + +> **dashboardOid**: `string` + +The OID of the dashboard to render. diff --git a/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/class.DashboardComponent.md b/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/class.DashboardComponent.md new file mode 100644 index 00000000..5590136e --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/class.DashboardComponent.md @@ -0,0 +1,141 @@ +--- +title: DashboardComponent +--- + +# Class DashboardComponent + +An Angular component used for easily rendering a dashboard created in Sisense Fusion. + +**Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. + +## Example + +```html + +``` +```ts +import { Component } from '@angular/core'; +import { type DashboardModel, DashboardService } from '@sisense/sdk-ui-angular'; + +@Component({ + selector: 'app-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.scss'], +}) +export class DashboardComponent { + + dashboard: DashboardModel | null = null; + + constructor(private dashboardService: DashboardService) {} + + async ngOnInit(): Promise { + this.dashboard = await this.dashboardService.getDashboardModel('60f3e3e3e4b0e3e3e4b0e3e3', { includeWidgets: true, includeFilters: true }); + } +``` + +## Implements + +- `AfterViewInit` +- `OnChanges` +- `OnDestroy` + +## Constructors + +### constructor + +> **new DashboardComponent**(`sisenseContextService`, `themeService`): [`DashboardComponent`](class.DashboardComponent.md) + +Constructor for the `Dashboard` component. + +#### Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `sisenseContextService` | [`SisenseContextService`](../contexts/class.SisenseContextService.md) | Sisense context service | +| `themeService` | [`ThemeService`](../contexts/class.ThemeService.md) | Theme service | + +#### Returns + +[`DashboardComponent`](class.DashboardComponent.md) + +## Properties + +### Constructor + +#### sisenseContextService + +> **sisenseContextService**: [`SisenseContextService`](../contexts/class.SisenseContextService.md) + +Sisense context service + +*** + +#### themeService + +> **themeService**: [`ThemeService`](../contexts/class.ThemeService.md) + +Theme service + +### Other + +#### defaultDataSource + +> **defaultDataSource**: `undefined` \| [`DataSource`](../../sdk-data/type-aliases/type-alias.DataSource.md) + +The default data source to use for the dashboard + +*** + +#### filters + +> **filters**: [`Filter`](../../sdk-data/interfaces/interface.Filter.md)[] + +The dashboard filters to be applied to each of the widgets based on the widget filter options + +*** + +#### layout + +> **layout**: [`Layout`](../interfaces/interface.Layout.md) + +The layout of the dashboard + +*** + +#### styleOptions + +> **styleOptions**: [`DashboardStyleOptions`](../../sdk-ui/type-aliases/type-alias.DashboardStyleOptions.md) + +The style options for the dashboard + +*** + +#### title + +> **title**: `string` + +The title of the dashboard + +*** + +#### widgetFilterOptions + +> **widgetFilterOptions**: `undefined` \| [`WidgetFilterOptions`](../type-aliases/type-alias.WidgetFilterOptions.md) + +The filter options for each of the widgets + +*** + +#### widgets + +> **widgets**: [`WidgetModel`](class.WidgetModel.md)[] + +The widgets to render in the dashboard diff --git a/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/index.md b/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/index.md index bbb1776c..fc6d6c7e 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/index.md +++ b/docs-md/sdk/modules/sdk-ui-angular/fusion-embed/index.md @@ -6,6 +6,8 @@ title: Fusion Embed Angular modules, services, and components for working with Fusion Embed dashboards, widgets, queries, and formulas +- [DashboardByIdComponent](class.DashboardByIdComponent.md) +- [DashboardComponent](class.DashboardComponent.md) - [DashboardModel](class.DashboardModel.md) - [DashboardService](class.DashboardService.md) - [DashboardWidgetComponent](class.DashboardWidgetComponent.md) diff --git a/docs-md/sdk/modules/sdk-ui-angular/index.md b/docs-md/sdk/modules/sdk-ui-angular/index.md index 52ba3bd1..d6081145 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/index.md +++ b/docs-md/sdk/modules/sdk-ui-angular/index.md @@ -74,6 +74,8 @@ Angular query service Angular modules, services, and components for working with Fusion Embed dashboards, widgets, queries, and formulas +- [DashboardByIdComponent](fusion-embed/class.DashboardByIdComponent.md) +- [DashboardComponent](fusion-embed/class.DashboardComponent.md) - [DashboardModel](fusion-embed/class.DashboardModel.md) - [DashboardService](fusion-embed/class.DashboardService.md) - [DashboardWidgetComponent](fusion-embed/class.DashboardWidgetComponent.md) diff --git a/docs-md/sdk/modules/sdk-ui-angular/interfaces/index.md b/docs-md/sdk/modules/sdk-ui-angular/interfaces/index.md index 187d0955..5756e907 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/interfaces/index.md +++ b/docs-md/sdk/modules/sdk-ui-angular/interfaces/index.md @@ -23,6 +23,7 @@ TypeScript interfaces for components and services listed above - [GetDashboardModelOptions](interface.GetDashboardModelOptions.md) - [GetDashboardModelsOptions](interface.GetDashboardModelsOptions.md) - [IndicatorChartDataOptions](interface.IndicatorChartDataOptions.md) +- [Layout](interface.Layout.md) - [LineStyleOptions](interface.LineStyleOptions.md) - [Member](interface.Member.md) - [NumericBarIndicatorStyleOptions](interface.NumericBarIndicatorStyleOptions.md) diff --git a/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.Layout.md b/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.Layout.md new file mode 100644 index 00000000..c9172584 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.Layout.md @@ -0,0 +1,22 @@ +--- +title: Layout +--- + +# Interface Layout + +Layout of a dashboard. + +## Properties + +### columns + +> **columns**: \{ + `rows`: \{ + `cells`: \{ + `height`: `string` \| `number`; + `widgetId`: `string`; + `widthPercentage`: `number`; + }[]; + }[]; + `widthPercentage`: `number`; + }[] diff --git a/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.SisenseContextConfig.md b/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.SisenseContextConfig.md index 11f7eb56..1914a0b1 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.SisenseContextConfig.md +++ b/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.SisenseContextConfig.md @@ -52,14 +52,18 @@ Set to `true` to use SSO authentication. When `true`, this overrides any other a #### token -> **token**?: `string` +> **token**?: `null` \| `string` Token for [bearer authentication](https://sisense.dev/guides/restApi/using-rest-api.html). +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. + *** #### wat -> **wat**?: `string` +> **wat**?: `null` \| `string` [Web Access Token](https://docs.sisense.com/main/SisenseLinux/using-web-access-token.htm). + +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. diff --git a/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.StyledColumn.md b/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.StyledColumn.md index 31bb2342..68afbcf0 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.StyledColumn.md +++ b/docs-md/sdk/modules/sdk-ui-angular/interfaces/interface.StyledColumn.md @@ -40,6 +40,14 @@ Also, see [StyledMeasureColumn](interface.StyledMeasureColumn.md). ## Properties +### color + +> **color**?: [`DataColorOptions`](../type-aliases/type-alias.DataColorOptions.md) + +All possible color options for data. + +*** + ### column > **column**: [`Column`](../../sdk-data/interfaces/interface.Column.md) diff --git a/docs-md/sdk/modules/sdk-ui-angular/type-aliases/index.md b/docs-md/sdk/modules/sdk-ui-angular/type-aliases/index.md index 27bc23b0..460e515d 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/type-aliases/index.md +++ b/docs-md/sdk/modules/sdk-ui-angular/type-aliases/index.md @@ -77,6 +77,7 @@ TypeScript type aliases for components and services listed above - [UniformDataColorOptions](type-alias.UniformDataColorOptions.md) - [ValueToColorMap](type-alias.ValueToColorMap.md) - [WidgetDataOptions](type-alias.WidgetDataOptions.md) +- [WidgetFilterOptions](type-alias.WidgetFilterOptions.md) - [WidgetStyleOptions](type-alias.WidgetStyleOptions.md) - [WidgetType](type-alias.WidgetType.md) - [X2Title](type-alias.X2Title.md) diff --git a/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.AppConfig.md b/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.AppConfig.md index d06e0226..bd27f2db 100644 --- a/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.AppConfig.md +++ b/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.AppConfig.md @@ -107,3 +107,33 @@ Query limit (max rows count that will be fetched in query) ```ts 20000 ``` + +*** + +### `trackingConfig` + +**trackingConfig**?: `object` + +Tracking configuration + +> #### `trackingConfig.onTrackingEvent` +> +> **onTrackingEvent**?: (`payload`) => `void` +> +> Callback to be invoked when tracking event occurs +> +> ##### Parameters +> +> +> | Parameter | Type | +> | :------ | :------ | +> | `payload` | `TrackingEventDetails` | +> +> +> ##### Returns +> +> `void` +> +> +> +> diff --git a/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.WidgetFilterOptions.md b/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.WidgetFilterOptions.md new file mode 100644 index 00000000..ce1e1a40 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-angular/type-aliases/type-alias.WidgetFilterOptions.md @@ -0,0 +1,9 @@ +--- +title: WidgetFilterOptions +--- + +# Type alias WidgetFilterOptions + +> **WidgetFilterOptions**: `Record`\< `string`, [`CommonFiltersOptions`](../../sdk-ui/type-aliases/type-alias.CommonFiltersOptions.md) \> + +Options for how common filters defined at the dashboard level should be applied to widgets. diff --git a/docs-md/sdk/modules/sdk-ui-vue/contexts/class.SisenseContextProvider.md b/docs-md/sdk/modules/sdk-ui-vue/contexts/class.SisenseContextProvider.md index b0958f85..0596a7c6 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/contexts/class.SisenseContextProvider.md +++ b/docs-md/sdk/modules/sdk-ui-vue/contexts/class.SisenseContextProvider.md @@ -22,8 +22,6 @@ other SDK components inside this component. :token="authToken" :wat="watToken" :appConfig="appConfigurations" - :showRuntimeErrors="true" - :enableTracking="false" > @@ -92,14 +90,18 @@ Set to `true` to use SSO authentication. When `true`, this overrides any other a #### token -> **token**?: `string` +> **token**?: `null` \| `string` Token for [bearer authentication](https://sisense.dev/guides/restApi/using-rest-api.html). +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. + *** #### wat -> **wat**?: `string` +> **wat**?: `null` \| `string` [Web Access Token](https://docs.sisense.com/main/SisenseLinux/using-web-access-token.htm). + +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. diff --git a/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/class.Dashboard.md b/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/class.Dashboard.md new file mode 100644 index 00000000..d54bf181 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/class.Dashboard.md @@ -0,0 +1,91 @@ +--- +title: Dashboard +--- + +# Class Dashboard + +A component used for easily rendering a dashboard. + +## Example + +Here's how you can use the Dashboard component in a Vue application: +```vue + + + +``` + +## Properties + +### defaultDataSource + +> **defaultDataSource**?: [`DataSource`](../../sdk-data/type-aliases/type-alias.DataSource.md) + +The default data source to use for the dashboard + +*** + +### filters + +> **filters**?: [`Filter`](../../sdk-data/interfaces/interface.Filter.md)[] + +The dashboard filters to be applied to each of the widgets based on the widget filter options + +*** + +### layout + +> **layout**?: [`Layout`](../interfaces/interface.Layout.md) + +The layout of the dashboard + +*** + +### styleOptions + +> **styleOptions**?: [`DashboardStyleOptions`](../../sdk-ui/type-aliases/type-alias.DashboardStyleOptions.md) + +The style options for the dashboard + +*** + +### title + +> **title**?: `string` + +The title of the dashboard + +*** + +### widgetFilterOptions + +> **widgetFilterOptions**?: [`WidgetFilterOptions`](../type-aliases/type-alias.WidgetFilterOptions.md) + +The filter options for each of the widgets + +*** + +### widgets + +> **widgets**?: [`WidgetModel`](class.WidgetModel.md)[] + +The widgets to render in the dashboard diff --git a/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/class.DashboardById.md b/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/class.DashboardById.md new file mode 100644 index 00000000..9251e4e0 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/class.DashboardById.md @@ -0,0 +1,34 @@ +--- +title: DashboardById +--- + +# Class DashboardById + +A component used for easily rendering a dashboard by its ID in a Sisense Fusion instance. + +**Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. + +## Example + +Here's how you can use the DashboardById component in a Vue application: +```vue + + + +``` + +## Properties + +### dashboardOid + +> **dashboardOid**?: `string` + +The OID of the dashboard to render. diff --git a/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/index.md b/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/index.md index 3d1a0312..f707774a 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/index.md +++ b/docs-md/sdk/modules/sdk-ui-vue/fusion-embed/index.md @@ -6,6 +6,8 @@ title: Fusion Embed Vue components and functions for working with Fusion Embed dashboards, widgets, queries, and formulas +- [Dashboard](class.Dashboard.md) +- [DashboardById](class.DashboardById.md) - [DashboardModel](class.DashboardModel.md) - [DashboardWidget](class.DashboardWidget.md) - [WidgetModel](class.WidgetModel.md) diff --git a/docs-md/sdk/modules/sdk-ui-vue/index.md b/docs-md/sdk/modules/sdk-ui-vue/index.md index 5bc6dc42..c70dd6c6 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/index.md +++ b/docs-md/sdk/modules/sdk-ui-vue/index.md @@ -72,6 +72,8 @@ Vue query service Vue components and functions for working with Fusion Embed dashboards, widgets, queries, and formulas +- [Dashboard](fusion-embed/class.Dashboard.md) +- [DashboardById](fusion-embed/class.DashboardById.md) - [DashboardModel](fusion-embed/class.DashboardModel.md) - [DashboardWidget](fusion-embed/class.DashboardWidget.md) - [WidgetModel](fusion-embed/class.WidgetModel.md) diff --git a/docs-md/sdk/modules/sdk-ui-vue/interfaces/index.md b/docs-md/sdk/modules/sdk-ui-vue/interfaces/index.md index b4ff35f4..ef69e03c 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/interfaces/index.md +++ b/docs-md/sdk/modules/sdk-ui-vue/interfaces/index.md @@ -22,6 +22,8 @@ TypeScript interfaces for components and composables listed above - [ChartWidgetProps](interface.ChartWidgetProps.md) - [ColumnChartProps](interface.ColumnChartProps.md) - [CriteriaFilterTileProps](interface.CriteriaFilterTileProps.md) +- [DashboardByIdProps](interface.DashboardByIdProps.md) +- [DashboardProps](interface.DashboardProps.md) - [DashboardWidgetProps](interface.DashboardWidgetProps.md) - [DashboardWidgetStyleOptions](interface.DashboardWidgetStyleOptions.md) - [DataLimits](interface.DataLimits.md) @@ -40,6 +42,7 @@ TypeScript interfaces for components and composables listed above - [GetWidgetModelParams](interface.GetWidgetModelParams.md) - [IndicatorChartDataOptions](interface.IndicatorChartDataOptions.md) - [IndicatorChartProps](interface.IndicatorChartProps.md) +- [Layout](interface.Layout.md) - [LineChartProps](interface.LineChartProps.md) - [LineStyleOptions](interface.LineStyleOptions.md) - [Member](interface.Member.md) diff --git a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.DashboardByIdProps.md b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.DashboardByIdProps.md new file mode 100644 index 00000000..b8303775 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.DashboardByIdProps.md @@ -0,0 +1,15 @@ +--- +title: DashboardByIdProps +--- + +# Interface DashboardByIdProps + +Props for the DashboardById component + +## Properties + +### dashboardOid + +> **dashboardOid**: `string` + +The OID of the dashboard to render. diff --git a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.DashboardProps.md b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.DashboardProps.md new file mode 100644 index 00000000..bf58dd05 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.DashboardProps.md @@ -0,0 +1,63 @@ +--- +title: DashboardProps +--- + +# Interface DashboardProps + +Props for the Dashboard component + +## Properties + +### defaultDataSource + +> **defaultDataSource**?: [`DataSource`](../../sdk-data/type-aliases/type-alias.DataSource.md) + +The default data source to use for the dashboard + +*** + +### filters + +> **filters**: [`Filter`](../../sdk-data/interfaces/interface.Filter.md)[] + +The dashboard filters to be applied to each of the widgets based on the widget filter options + +*** + +### layout + +> **layout**: [`Layout`](interface.Layout.md) + +The layout of the dashboard + +*** + +### styleOptions + +> **styleOptions**: [`DashboardStyleOptions`](../../sdk-ui/type-aliases/type-alias.DashboardStyleOptions.md) + +The style options for the dashboard + +*** + +### title + +> **title**: `string` + +The title of the dashboard + +*** + +### widgetFilterOptions + +> **widgetFilterOptions**?: [`WidgetFilterOptions`](../type-aliases/type-alias.WidgetFilterOptions.md) + +The filter options for each of the widgets + +*** + +### widgets + +> **widgets**: [`WidgetModel`](../fusion-embed/class.WidgetModel.md)[] + +The widgets to render in the dashboard diff --git a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.Layout.md b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.Layout.md new file mode 100644 index 00000000..c9172584 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.Layout.md @@ -0,0 +1,22 @@ +--- +title: Layout +--- + +# Interface Layout + +Layout of a dashboard. + +## Properties + +### columns + +> **columns**: \{ + `rows`: \{ + `cells`: \{ + `height`: `string` \| `number`; + `widgetId`: `string`; + `widthPercentage`: `number`; + }[]; + }[]; + `widthPercentage`: `number`; + }[] diff --git a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.SisenseContextProviderProps.md b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.SisenseContextProviderProps.md index e44da085..fe5f55e8 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.SisenseContextProviderProps.md +++ b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.SisenseContextProviderProps.md @@ -52,14 +52,18 @@ Set to `true` to use SSO authentication. When `true`, this overrides any other a #### token -> **token**?: `string` +> **token**?: `null` \| `string` Token for [bearer authentication](https://sisense.dev/guides/restApi/using-rest-api.html). +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. + *** #### wat -> **wat**?: `string` +> **wat**?: `null` \| `string` [Web Access Token](https://docs.sisense.com/main/SisenseLinux/using-web-access-token.htm). + +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. diff --git a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.StyledColumn.md b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.StyledColumn.md index d26f14e2..ac488fec 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.StyledColumn.md +++ b/docs-md/sdk/modules/sdk-ui-vue/interfaces/interface.StyledColumn.md @@ -40,6 +40,14 @@ Also, see [StyledMeasureColumn](interface.StyledMeasureColumn.md). ## Properties +### color + +> **color**?: [`DataColorOptions`](../type-aliases/type-alias.DataColorOptions.md) + +All possible color options for data. + +*** + ### column > **column**: [`Column`](../../sdk-data/interfaces/interface.Column.md) diff --git a/docs-md/sdk/modules/sdk-ui-vue/type-aliases/index.md b/docs-md/sdk/modules/sdk-ui-vue/type-aliases/index.md index f7e2274e..826e75e0 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/type-aliases/index.md +++ b/docs-md/sdk/modules/sdk-ui-vue/type-aliases/index.md @@ -81,6 +81,7 @@ TypeScript type aliases for components and composables listed above - [UseFetchOptions](type-alias.UseFetchOptions.md) - [ValueToColorMap](type-alias.ValueToColorMap.md) - [WidgetDataOptions](type-alias.WidgetDataOptions.md) +- [WidgetFilterOptions](type-alias.WidgetFilterOptions.md) - [WidgetStyleOptions](type-alias.WidgetStyleOptions.md) - [WidgetType](type-alias.WidgetType.md) - [X2Title](type-alias.X2Title.md) diff --git a/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.AppConfig.md b/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.AppConfig.md index d06e0226..bd27f2db 100644 --- a/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.AppConfig.md +++ b/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.AppConfig.md @@ -107,3 +107,33 @@ Query limit (max rows count that will be fetched in query) ```ts 20000 ``` + +*** + +### `trackingConfig` + +**trackingConfig**?: `object` + +Tracking configuration + +> #### `trackingConfig.onTrackingEvent` +> +> **onTrackingEvent**?: (`payload`) => `void` +> +> Callback to be invoked when tracking event occurs +> +> ##### Parameters +> +> +> | Parameter | Type | +> | :------ | :------ | +> | `payload` | `TrackingEventDetails` | +> +> +> ##### Returns +> +> `void` +> +> +> +> diff --git a/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.WidgetFilterOptions.md b/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.WidgetFilterOptions.md new file mode 100644 index 00000000..ce1e1a40 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui-vue/type-aliases/type-alias.WidgetFilterOptions.md @@ -0,0 +1,9 @@ +--- +title: WidgetFilterOptions +--- + +# Type alias WidgetFilterOptions + +> **WidgetFilterOptions**: `Record`\< `string`, [`CommonFiltersOptions`](../../sdk-ui/type-aliases/type-alias.CommonFiltersOptions.md) \> + +Options for how common filters defined at the dashboard level should be applied to widgets. diff --git a/docs-md/sdk/modules/sdk-ui/enumerations/enumeration.CommonFiltersApplyMode.md b/docs-md/sdk/modules/sdk-ui/enumerations/enumeration.CommonFiltersApplyMode.md new file mode 100644 index 00000000..f04db114 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/enumerations/enumeration.CommonFiltersApplyMode.md @@ -0,0 +1,19 @@ +--- +title: CommonFiltersApplyMode +--- + +# Enumeration CommonFiltersApplyMode + +Common filters apply mode. + +## Enumeration Members + +### FILTER + +> **FILTER**: `"filter"` + +*** + +### HIGHLIGHT + +> **HIGHLIGHT**: `"highlight"` diff --git a/docs-md/sdk/modules/sdk-ui/enumerations/index.md b/docs-md/sdk/modules/sdk-ui/enumerations/index.md new file mode 100644 index 00000000..98570ad2 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/enumerations/index.md @@ -0,0 +1,7 @@ +--- +title: Enumerations +--- + +# Enumerations + +- [CommonFiltersApplyMode](enumeration.CommonFiltersApplyMode.md) diff --git a/docs-md/sdk/modules/sdk-ui/fusion-embed/function.Dashboard.md b/docs-md/sdk/modules/sdk-ui/fusion-embed/function.Dashboard.md new file mode 100644 index 00000000..00fb093f --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/fusion-embed/function.Dashboard.md @@ -0,0 +1,21 @@ +--- +title: Dashboard +--- + +# Function Dashboard + +> **Dashboard**(`props`): `null` \| `ReactElement`\< `any`, `any` \> + +React component that renders a dashboard whose elements are customizable. It includes internal logic of applying common filters to widgets. + +**Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. + +## Parameters + +| Parameter | Type | +| :------ | :------ | +| `props` | [`DashboardProps`](../interfaces/interface.DashboardProps.md) | + +## Returns + +`null` \| `ReactElement`\< `any`, `any` \> diff --git a/docs-md/sdk/modules/sdk-ui/fusion-embed/function.DashboardById.md b/docs-md/sdk/modules/sdk-ui/fusion-embed/function.DashboardById.md new file mode 100644 index 00000000..5d24e980 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/fusion-embed/function.DashboardById.md @@ -0,0 +1,21 @@ +--- +title: DashboardById +--- + +# Function DashboardById + +> **DashboardById**(`props`): `null` \| `ReactElement`\< `any`, `any` \> + +React component that renders a dashboard created in Sisense Fusion by its ID. + +**Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. + +## Parameters + +| Parameter | Type | +| :------ | :------ | +| `props` | [`DashboardByIdProps`](../interfaces/interface.DashboardByIdProps.md) | + +## Returns + +`null` \| `ReactElement`\< `any`, `any` \> diff --git a/docs-md/sdk/modules/sdk-ui/fusion-embed/index.md b/docs-md/sdk/modules/sdk-ui/fusion-embed/index.md index 8114edde..d5c0075a 100644 --- a/docs-md/sdk/modules/sdk-ui/fusion-embed/index.md +++ b/docs-md/sdk/modules/sdk-ui/fusion-embed/index.md @@ -6,6 +6,8 @@ title: Fusion Embed React components and hooks for working with Fusion Embed dashboards, widgets, queries, and formulas +- [Dashboard](function.Dashboard.md) +- [DashboardById](function.DashboardById.md) - [DashboardModel](class.DashboardModel.md) - [DashboardWidget](function.DashboardWidget.md) - [ExecuteQueryByWidgetId](function.ExecuteQueryByWidgetId.md) diff --git a/docs-md/sdk/modules/sdk-ui/index.md b/docs-md/sdk/modules/sdk-ui/index.md index d5702964..8f4fc584 100644 --- a/docs-md/sdk/modules/sdk-ui/index.md +++ b/docs-md/sdk/modules/sdk-ui/index.md @@ -77,6 +77,8 @@ React components and hooks for working with queries React components and hooks for working with Fusion Embed dashboards, widgets, queries, and formulas +- [Dashboard](fusion-embed/function.Dashboard.md) +- [DashboardById](fusion-embed/function.DashboardById.md) - [DashboardModel](fusion-embed/class.DashboardModel.md) - [DashboardWidget](fusion-embed/function.DashboardWidget.md) - [ExecuteQueryByWidgetId](fusion-embed/function.ExecuteQueryByWidgetId.md) diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/index.md b/docs-md/sdk/modules/sdk-ui/interfaces/index.md index d6bf5e6f..64dd13ce 100644 --- a/docs-md/sdk/modules/sdk-ui/interfaces/index.md +++ b/docs-md/sdk/modules/sdk-ui/interfaces/index.md @@ -28,6 +28,8 @@ TypeScript interfaces for components and hooks listed above - [ColumnChartProps](interface.ColumnChartProps.md) - [ContextMenuProps](interface.ContextMenuProps.md) - [CriteriaFilterTileProps](interface.CriteriaFilterTileProps.md) +- [DashboardByIdProps](interface.DashboardByIdProps.md) +- [DashboardProps](interface.DashboardProps.md) - [DashboardWidgetProps](interface.DashboardWidgetProps.md) - [DashboardWidgetStyleOptions](interface.DashboardWidgetStyleOptions.md) - [DataLimits](interface.DataLimits.md) @@ -54,6 +56,7 @@ TypeScript interfaces for components and hooks listed above - [GetWidgetModelParams](interface.GetWidgetModelParams.md) - [IndicatorChartDataOptions](interface.IndicatorChartDataOptions.md) - [IndicatorChartProps](interface.IndicatorChartProps.md) +- [Layout](interface.Layout.md) - [LineChartProps](interface.LineChartProps.md) - [LineStyleOptions](interface.LineStyleOptions.md) - [Member](interface.Member.md) diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/interface.ChartThemeSettings.md b/docs-md/sdk/modules/sdk-ui/interfaces/interface.ChartThemeSettings.md index d29cf7f5..9975a1aa 100644 --- a/docs-md/sdk/modules/sdk-ui/interfaces/interface.ChartThemeSettings.md +++ b/docs-md/sdk/modules/sdk-ui/interfaces/interface.ChartThemeSettings.md @@ -8,6 +8,48 @@ Chart theme settings ## Properties +### animation + +> **animation**?: `object` + +Animation options + +#### Type declaration + +> ##### `animation.init` +> +> **init**?: `object` +> +> Chart initialization animation options +> +> > ###### `init.duration` +> > +> > **duration**?: `number` \| `"auto"` +> > +> > Animation duration in milliseconds. +> > If not specified, the default value, `auto`, will be used with a different default value applied per chart type. +> > +> > +> +> ##### `animation.redraw` +> +> **redraw**?: `object` +> +> Chart redraw animation options +> +> > ###### `redraw.duration` +> > +> > **duration**?: `number` \| `"auto"` +> > +> > Animation duration in milliseconds. +> > If not specified, the default value, `auto`, will be used with a different default value applied per chart type. +> > +> > +> +> + +*** + ### backgroundColor > **backgroundColor**?: `string` diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/interface.DashboardByIdProps.md b/docs-md/sdk/modules/sdk-ui/interfaces/interface.DashboardByIdProps.md new file mode 100644 index 00000000..b8303775 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/interfaces/interface.DashboardByIdProps.md @@ -0,0 +1,15 @@ +--- +title: DashboardByIdProps +--- + +# Interface DashboardByIdProps + +Props for the DashboardById component + +## Properties + +### dashboardOid + +> **dashboardOid**: `string` + +The OID of the dashboard to render. diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/interface.DashboardProps.md b/docs-md/sdk/modules/sdk-ui/interfaces/interface.DashboardProps.md new file mode 100644 index 00000000..888ebade --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/interfaces/interface.DashboardProps.md @@ -0,0 +1,63 @@ +--- +title: DashboardProps +--- + +# Interface DashboardProps + +Props for the Dashboard component + +## Properties + +### defaultDataSource + +> **defaultDataSource**?: [`DataSource`](../../sdk-data/type-aliases/type-alias.DataSource.md) + +The default data source to use for the dashboard + +*** + +### filters + +> **filters**: [`Filter`](../../sdk-data/interfaces/interface.Filter.md)[] + +The dashboard filters to be applied to each of the widgets based on the widget filter options + +*** + +### layout + +> **layout**: [`Layout`](interface.Layout.md) + +The layout of the dashboard + +*** + +### styleOptions + +> **styleOptions**: [`DashboardStyleOptions`](../type-aliases/type-alias.DashboardStyleOptions.md) + +The style options for the dashboard + +*** + +### title + +> **title**: `string` + +The title of the dashboard + +*** + +### widgetFilterOptions + +> **widgetFilterOptions**?: [`WidgetFilterOptions`](../type-aliases/type-alias.WidgetFilterOptions.md) + +The filter options for each of the widgets + +*** + +### widgets + +> **widgets**: [`WidgetModel`](../fusion-embed/class.WidgetModel.md)[] + +The widgets to render in the dashboard diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/interface.Layout.md b/docs-md/sdk/modules/sdk-ui/interfaces/interface.Layout.md new file mode 100644 index 00000000..c9172584 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/interfaces/interface.Layout.md @@ -0,0 +1,22 @@ +--- +title: Layout +--- + +# Interface Layout + +Layout of a dashboard. + +## Properties + +### columns + +> **columns**: \{ + `rows`: \{ + `cells`: \{ + `height`: `string` \| `number`; + `widgetId`: `string`; + `widthPercentage`: `number`; + }[]; + }[]; + `widthPercentage`: `number`; + }[] diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/interface.SisenseContextProviderProps.md b/docs-md/sdk/modules/sdk-ui/interfaces/interface.SisenseContextProviderProps.md index e44da085..59263f5b 100644 --- a/docs-md/sdk/modules/sdk-ui/interfaces/interface.SisenseContextProviderProps.md +++ b/docs-md/sdk/modules/sdk-ui/interfaces/interface.SisenseContextProviderProps.md @@ -38,6 +38,40 @@ Default data source explicitly set to be used by child components that are not d URL of the Sisense environment the app connects to +### Sisense App Error Handling + +#### onError + +> **onError**?: (`error`) => `void` + +Callback function that is triggered when an error occurs within the Sisense context. + +This callback is useful for handling errors that happen during the initialization or runtime of the Sisense context, +such as incorrect configuration, invalid authentication, or network-related issues. + +##### Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `error` | `Error` | The error object containing details about the issue. | + +##### Returns + +`void` + +*** + +#### showRuntimeErrors + +> **showRuntimeErrors**?: `boolean` + +Boolean flag to show or hide run-time errors that involve Sisense context in the UI. +Example errors include incorrect Sisense URL or invalid authentication. +Note that this flag does not hide run-time errors in the console. +If disabled - it's recommended to specify an [onError](interface.SisenseContextProviderProps.md#onerror) callback to handle errors. + +If not specified, the default value is `true`. + ### Sisense Authentication #### ssoEnabled @@ -52,14 +86,18 @@ Set to `true` to use SSO authentication. When `true`, this overrides any other a #### token -> **token**?: `string` +> **token**?: `null` \| `string` Token for [bearer authentication](https://sisense.dev/guides/restApi/using-rest-api.html). +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. + *** #### wat -> **wat**?: `string` +> **wat**?: `null` \| `string` [Web Access Token](https://docs.sisense.com/main/SisenseLinux/using-web-access-token.htm). + +To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. diff --git a/docs-md/sdk/modules/sdk-ui/interfaces/interface.StyledColumn.md b/docs-md/sdk/modules/sdk-ui/interfaces/interface.StyledColumn.md index 31bb2342..68afbcf0 100644 --- a/docs-md/sdk/modules/sdk-ui/interfaces/interface.StyledColumn.md +++ b/docs-md/sdk/modules/sdk-ui/interfaces/interface.StyledColumn.md @@ -40,6 +40,14 @@ Also, see [StyledMeasureColumn](interface.StyledMeasureColumn.md). ## Properties +### color + +> **color**?: [`DataColorOptions`](../type-aliases/type-alias.DataColorOptions.md) + +All possible color options for data. + +*** + ### column > **column**: [`Column`](../../sdk-data/interfaces/interface.Column.md) diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/index.md b/docs-md/sdk/modules/sdk-ui/type-aliases/index.md index 68ff8c10..3f54945e 100644 --- a/docs-md/sdk/modules/sdk-ui/type-aliases/index.md +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/index.md @@ -41,6 +41,7 @@ TypeScript type aliases for components and hooks listed above - [ChatbotProps](type-alias.ChatbotProps.md) - [Color](type-alias.Color.md) - [ColorPaletteTheme](type-alias.ColorPaletteTheme.md) +- [CommonFiltersOptions](type-alias.CommonFiltersOptions.md) - [ConditionalDataColorOptions](type-alias.ConditionalDataColorOptions.md) - [Convolution](type-alias.Convolution.md) - [Coordinates](type-alias.Coordinates.md) @@ -58,6 +59,7 @@ TypeScript type aliases for components and hooks listed above - [DashboardModelsLoadingState](type-alias.DashboardModelsLoadingState.md) - [DashboardModelsState](type-alias.DashboardModelsState.md) - [DashboardModelsSuccessState](type-alias.DashboardModelsSuccessState.md) +- [DashboardStyleOptions](type-alias.DashboardStyleOptions.md) - [DataColorCondition](type-alias.DataColorCondition.md) - [DataColorOptions](type-alias.DataColorOptions.md) - [DataPoint](type-alias.DataPoint.md) @@ -73,6 +75,7 @@ TypeScript type aliases for components and hooks listed above - [ExecuteCSVQueryConfig](type-alias.ExecuteCSVQueryConfig.md) - [ExecuteQueryResult](type-alias.ExecuteQueryResult.md) - [FilterVariant](type-alias.FilterVariant.md) +- [FiltersIgnoringRules](type-alias.FiltersIgnoringRules.md) - [GeoDataElement](type-alias.GeoDataElement.md) - [IndicatorChartType](type-alias.IndicatorChartType.md) - [IndicatorComponents](type-alias.IndicatorComponents.md) @@ -147,6 +150,7 @@ TypeScript type aliases for components and hooks listed above - [UseQueryResult](type-alias.UseQueryResult.md) - [ValueToColorMap](type-alias.ValueToColorMap.md) - [WidgetDataOptions](type-alias.WidgetDataOptions.md) +- [WidgetFilterOptions](type-alias.WidgetFilterOptions.md) - [WidgetModelErrorState](type-alias.WidgetModelErrorState.md) - [WidgetModelLoadingState](type-alias.WidgetModelLoadingState.md) - [WidgetModelState](type-alias.WidgetModelState.md) diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.AppConfig.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.AppConfig.md index 43b651f1..e03cca70 100644 --- a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.AppConfig.md +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.AppConfig.md @@ -107,3 +107,33 @@ Query limit (max rows count that will be fetched in query) ```ts 20000 ``` + +*** + +### `trackingConfig` + +**trackingConfig**?: `object` + +Tracking configuration + +> #### `trackingConfig.onTrackingEvent` +> +> **onTrackingEvent**?: (`payload`) => `void` +> +> Callback to be invoked when tracking event occurs +> +> ##### Parameters +> +> +> | Parameter | Type | +> | :------ | :------ | +> | `payload` | `TrackingEventDetails` | +> +> +> ##### Returns +> +> `void` +> +> +> +> diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.CommonFiltersOptions.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.CommonFiltersOptions.md new file mode 100644 index 00000000..28561936 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.CommonFiltersOptions.md @@ -0,0 +1,33 @@ +--- +title: CommonFiltersOptions +--- + +# Type alias CommonFiltersOptions + +> **CommonFiltersOptions**: `object` + +Options for common filters defined at the dashboard level to be applied to certain widgets. + +## Type declaration + +### `applyMode` + +**applyMode**?: \`$\{CommonFiltersApplyMode}\` + +*** + +### `forceApplyBackgroundFilters` + +**forceApplyBackgroundFilters**?: `boolean` + +*** + +### `ignoreFilters` + +**ignoreFilters**?: [`FiltersIgnoringRules`](type-alias.FiltersIgnoringRules.md) + +*** + +### `shouldAffectFilters` + +**shouldAffectFilters**?: `boolean` diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DashboardStyleOptions.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DashboardStyleOptions.md new file mode 100644 index 00000000..47ec6cf0 --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DashboardStyleOptions.md @@ -0,0 +1,41 @@ +--- +title: DashboardStyleOptions +--- + +# Type alias DashboardStyleOptions + +> **DashboardStyleOptions**: `object` + +Style options for the dashboard. + +## Type declaration + +### `backgroundColor` + +**backgroundColor**?: `string` + +Background color + +*** + +### `dividerLineColor` + +**dividerLineColor**?: `string` + +Divider line color + +*** + +### `dividerLineWidth` + +**dividerLineWidth**?: `number` + +Width of the divider line between widgets + +*** + +### `palette` + +**palette**?: [`ColorPaletteTheme`](type-alias.ColorPaletteTheme.md) + +Collection of colors used to color various elements diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DrilldownWidgetConfig.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DrilldownWidgetConfig.md index b7514775..e5bce62e 100644 --- a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DrilldownWidgetConfig.md +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.DrilldownWidgetConfig.md @@ -24,7 +24,9 @@ React component to be rendered as breadcrumbs **contextMenuComponent**?: (`contextMenuProps`) => `JSX.Element` -Boolean to override default breadcrumbs location and instead only return them as a property of the 'children' function +React component to be rendered as context menu + +[ContextMenu](../drilldown/function.ContextMenu.md) will be used if not provided #### Parameters diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.FiltersIgnoringRules.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.FiltersIgnoringRules.md new file mode 100644 index 00000000..0e79feca --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.FiltersIgnoringRules.md @@ -0,0 +1,21 @@ +--- +title: FiltersIgnoringRules +--- + +# Type alias FiltersIgnoringRules + +> **FiltersIgnoringRules**: `object` + +Filters ignoring rules. + +## Type declaration + +### `all` + +**all**?: `boolean` + +*** + +### `ids` + +**ids**?: `string`[] diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.SeriesStyleOptions.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.SeriesStyleOptions.md index 19a4e944..6515d26b 100644 --- a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.SeriesStyleOptions.md +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.SeriesStyleOptions.md @@ -15,7 +15,7 @@ Supported only for cartesian and polar charts. **lineWidth**?: [`LineWidth`](type-alias.LineWidth.md) -Configuration that defines line width +#### Inherit Doc *** @@ -23,4 +23,4 @@ Configuration that defines line width **markers**?: [`Markers`](type-alias.Markers.md) -Configuration for markers - symbols or data points that highlight specific values +#### Inherit Doc diff --git a/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.WidgetFilterOptions.md b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.WidgetFilterOptions.md new file mode 100644 index 00000000..a7fd546b --- /dev/null +++ b/docs-md/sdk/modules/sdk-ui/type-aliases/type-alias.WidgetFilterOptions.md @@ -0,0 +1,9 @@ +--- +title: WidgetFilterOptions +--- + +# Type alias WidgetFilterOptions + +> **WidgetFilterOptions**: `Record`\< `string`, [`CommonFiltersOptions`](type-alias.CommonFiltersOptions.md) \> + +Options for how common filters defined at the dashboard level should be applied to widgets. diff --git a/e2e/scripts/configure-angular-demo-env.cjs b/e2e/scripts/configure-angular-demo-env.cjs index 47d65db1..a5c4f218 100644 --- a/e2e/scripts/configure-angular-demo-env.cjs +++ b/e2e/scripts/configure-angular-demo-env.cjs @@ -11,6 +11,7 @@ if (!process.env.E2E_SISENSE_URL || !process.env.E2E_SISENSE_TOKEN) { const envContent = `export const environment = { APP_SISENSE_URL: '${process.env.E2E_SISENSE_URL}', APP_SISENSE_TOKEN: '${process.env.E2E_SISENSE_TOKEN}', + APP_DISABLE_ANIMATION: true }; `; diff --git a/e2e/scripts/start-servers.sh b/e2e/scripts/start-servers.sh index d24d92a1..bf7b3018 100755 --- a/e2e/scripts/start-servers.sh +++ b/e2e/scripts/start-servers.sh @@ -18,8 +18,9 @@ while IFS='=' read -r key value; do done < "$ENV_FILE" # Set the environment variables for all child process -export VITE_APP_SISENSE_URL="$E2E_SISENSE_URL" -export VITE_APP_SISENSE_TOKEN="$E2E_SISENSE_TOKEN" +export VITE_APP_SISENSE_URL=$E2E_SISENSE_URL +export VITE_APP_SISENSE_TOKEN=$E2E_SISENSE_TOKEN +export VITE_APP_DISABLE_ANIMATION="true" # Preparation scripts configura_angular_env="node ./scripts/configure-angular-demo-env.cjs"; diff --git a/e2e/visual-tests/__test-helpers__/makeScreenshot.ts b/e2e/visual-tests/__test-helpers__/makeScreenshot.ts index 57c5d7d6..276a9fb3 100644 --- a/e2e/visual-tests/__test-helpers__/makeScreenshot.ts +++ b/e2e/visual-tests/__test-helpers__/makeScreenshot.ts @@ -3,8 +3,8 @@ import { expect, type Locator, type Page } from '@playwright/test'; const SCREENSHOT_FILE_EXTENSION = '.png'; const SCREENSHOT_DEFAILT_NAME = 'asset'; const TEST_ID_ATTRIBUTE = 'data-visual-testid'; -const ANIMATION_DELAY = 1000; -const LOADERS_CHECK_DURATION = 2 * 1000; +const READINESS_DELAY = 0.2 * 1000; +const LOADERS_CHECK_DURATION = 1.8 * 1000; const LOADERS_CHECK_INTERVAL = 100; const LOADERS_CHECK_TIMEOUT = 10 * 1000; @@ -51,7 +51,7 @@ export async function makeScreenshotsOverPage(page: Page) { await waitForLoadersToDisappear(page); - await page.waitForTimeout(ANIMATION_DELAY); + await page.waitForTimeout(READINESS_DELAY); const locators = await page.locator(`[${TEST_ID_ATTRIBUTE}]`).all(); await makeScreenshots(page, locators); diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_areamap-chart.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_areamap-chart.png index 67e7f248..f40a8e64 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_areamap-chart.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_areamap-chart.png differ diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_chart-widget.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_chart-widget.png index f2254e92..8e5f31e9 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_chart-widget.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_chart-widget.png differ diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_polar-chart.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_polar-chart.png index 05bfcd2f..67b297e3 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_polar-chart.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_polar-chart.png differ diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_scattermap-chart.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_scattermap-chart.png index e454a3d4..f8ee1c5f 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_scattermap-chart.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_scattermap-chart.png differ diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_sunburst-chart.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_sunburst-chart.png index 02018a4d..a8c2bcbd 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_sunburst-chart.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_sunburst-chart.png differ diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-chart.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-chart.png index b092c17f..8a6931ca 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-chart.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-chart.png differ diff --git a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-widget-chart.png b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-widget-chart.png index eb8d33da..6dbf8612 100644 Binary files a/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-widget-chart.png and b/e2e/visual-tests/angular-demo/__screenshots__/components.spec.ts/verify-components_table-widget-chart.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/dashboard.spec.ts/verify-dashboard-page_scatter.png b/e2e/visual-tests/react-local-demo/__screenshots__/dashboard.spec.ts/verify-dashboard-page_scatter.png index b7b53fe0..f596f814 100644 Binary files a/e2e/visual-tests/react-local-demo/__screenshots__/dashboard.spec.ts/verify-dashboard-page_scatter.png and b/e2e/visual-tests/react-local-demo/__screenshots__/dashboard.spec.ts/verify-dashboard-page_scatter.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_area-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_area-chart-with-drilldown.png new file mode 100644 index 00000000..edab99f9 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_area-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_arearange-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_arearange-chart-with-drilldown.png new file mode 100644 index 00000000..93bb228d Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_arearange-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_bar-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_bar-chart-with-drilldown.png new file mode 100644 index 00000000..d39a5af9 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_bar-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_boxplot-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_boxplot-chart-with-drilldown.png new file mode 100644 index 00000000..002ec215 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_boxplot-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_column-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_column-chart-with-drilldown.png new file mode 100644 index 00000000..a9d9c23d Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_column-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_funnel-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_funnel-chart-with-drilldown.png new file mode 100644 index 00000000..7a67d9a4 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_funnel-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_line-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_line-chart-with-drilldown.png new file mode 100644 index 00000000..e3509c4b Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_line-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_pie-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_pie-chart-with-drilldown.png new file mode 100644 index 00000000..66455bf5 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_pie-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_polar-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_polar-chart-with-drilldown.png new file mode 100644 index 00000000..b2421f76 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_polar-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_scatter-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_scatter-chart-with-drilldown.png new file mode 100644 index 00000000..cab6a956 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_scatter-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_sunburst-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_sunburst-chart-with-drilldown.png new file mode 100644 index 00000000..38a3c800 Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_sunburst-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_treemap-chart-with-drilldown.png b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_treemap-chart-with-drilldown.png new file mode 100644 index 00000000..2e1c4ffb Binary files /dev/null and b/e2e/visual-tests/react-local-demo/__screenshots__/widgets-with-drilldown.spec.ts/verify-widgets-with-drilldown-page_treemap-chart-with-drilldown.png differ diff --git a/e2e/visual-tests/react-local-demo/widgets-with-drilldown.spec.ts b/e2e/visual-tests/react-local-demo/widgets-with-drilldown.spec.ts new file mode 100644 index 00000000..140a2a5e --- /dev/null +++ b/e2e/visual-tests/react-local-demo/widgets-with-drilldown.spec.ts @@ -0,0 +1,11 @@ +import { test } from '@playwright/test'; +import { AppsNames, getAppConfig } from '../appsConfig'; +import { makeScreenshotsOverPage } from '../__test-helpers__/makeScreenshot'; + +const { url } = getAppConfig(AppsNames.REACT_LOCAL_DEMO); + +test('verify widgets with drilldown page', async ({ page }) => { + await page.goto(url); + await page.locator('span', { hasText: 'WidgetsWithDrilldownDemo' }).click(); + await makeScreenshotsOverPage(page); +}); diff --git a/e2e/visual-tests/react-storybook/__screenshots__/boxplot-chart.spec.ts/boxplot-verify-basic-boxplot_charts-boxplot--boxplot.png b/e2e/visual-tests/react-storybook/__screenshots__/boxplot-chart.spec.ts/boxplot-verify-basic-boxplot_charts-boxplot--boxplot.png index d4fd328c..a8dc628e 100644 Binary files a/e2e/visual-tests/react-storybook/__screenshots__/boxplot-chart.spec.ts/boxplot-verify-basic-boxplot_charts-boxplot--boxplot.png and b/e2e/visual-tests/react-storybook/__screenshots__/boxplot-chart.spec.ts/boxplot-verify-basic-boxplot_charts-boxplot--boxplot.png differ diff --git a/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_areamap.png b/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_areamap.png index 3006a80c..2a649ab5 100644 Binary files a/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_areamap.png and b/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_areamap.png differ diff --git a/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_scattermap.png b/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_scattermap.png index a8a7160a..345c878f 100644 Binary files a/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_scattermap.png and b/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_scattermap.png differ diff --git a/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_sunburst.png b/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_sunburst.png index a8bb5bb8..2c5be6a8 100644 Binary files a/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_sunburst.png and b/e2e/visual-tests/vue-demo/__screenshots__/charts.spec.ts/verify-charts-page_sunburst.png differ diff --git a/license-report/license-report-generated.md b/license-report/license-report-generated.md index 2cbec48a..2d4e2b1e 100644 --- a/license-report/license-report-generated.md +++ b/license-report/license-report-generated.md @@ -1,24 +1,26 @@ # License Report License report of third-party dependencies used by Compose SDK and related packages. -Date: 2024-04-01 +Date: 2024-08-15 ## Compose SDK Packages ### @sisense/sdk-cli -| Name | License type | Link | Installed version | Remote version | Author | -| :------------------- | :----------- | :----------------------------------------------------- | :---------------- | :------------- | :------------------------------------------------- | -| cross-fetch | MIT | git+https://github.com/lquixada/cross-fetch.git | 4.0.0 | 4.0.0 | Leonardo Quixada | -| inquirer | MIT | git+https://github.com/SBoudrias/Inquirer.js.git | 8.2.6 | 8.2.6 | Simon Boudrias | -| node-window-polyfill | MIT | git://github.com/tgorka/node-window-polyfill.git | 1.0.2 | 1.0.2 | Tomasz Gorka | -| yargs | MIT | git+https://github.com/yargs/yargs.git | 17.7.1 | 17.7.1 | n/a | -| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.23.2 | 7.24.3 | The Babel Team (https://babel.dev/team) | -| @types/inquirer | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 8.2.6 | 8.2.6 | n/a | -| @types/yargs | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 17.0.28 | 17.0.32 | n/a | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | -| msw | MIT | git+https://github.com/mswjs/msw.git | 2.2.1 | 2.2.1 | Artem Zakharchenko https://github.com/kettanaito | -| prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | -| typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | +| Name | License type | Link | Installed version | Remote version | Author | +| :-------------------- | :----------- | :----------------------------------------------------- | :---------------- | :------------- | :------------------------------------------------- | +| cross-fetch | MIT | git+https://github.com/lquixada/cross-fetch.git | 4.0.0 | 4.0.0 | Leonardo Quixada | +| inquirer | MIT | git+https://github.com/SBoudrias/Inquirer.js.git | 8.2.6 | 8.2.6 | Simon Boudrias | +| js-levenshtein | MIT | git+https://github.com/gustf/js-levenshtein.git | 1.1.6 | 1.1.6 | Gustaf Andersson gustaf@me.com | +| node-window-polyfill | MIT | git://github.com/tgorka/node-window-polyfill.git | 1.0.2 | 1.0.2 | Tomasz Gorka | +| yargs | MIT | git+https://github.com/yargs/yargs.git | 17.7.1 | 17.7.1 | n/a | +| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.24.5 | 7.25.3 | The Babel Team (https://babel.dev/team) | +| @types/inquirer | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 8.2.6 | 8.2.6 | n/a | +| @types/js-levenshtein | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.1.3 | 1.1.3 | n/a | +| @types/yargs | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 17.0.32 | 17.0.33 | n/a | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | +| msw | MIT | git+https://github.com/mswjs/msw.git | 2.2.1 | 2.2.1 | Artem Zakharchenko https://github.com/kettanaito | +| prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | +| typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | ### @sisense/sdk-common @@ -26,7 +28,7 @@ Date: 2024-04-01 | :--------- | :----------- | :---------------------------------------------- | :---------------- | :------------- | :------------------------------------------------------------------- | | i18next | MIT | git+https://github.com/i18next/i18next.git | 23.3.0 | 23.3.0 | Jan Mühlemann (https://github.com/jamuhl) | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | -| vitest | MIT | git+https://github.com/vitest-dev/vitest.git | 1.3.1 | 1.4.0 | Anthony Fu | +| vitest | MIT | git+https://github.com/vitest-dev/vitest.git | 1.6.0 | 1.6.0 | Anthony Fu | ### @sisense/sdk-data @@ -36,11 +38,11 @@ Date: 2024-04-01 | lodash | MIT | git+https://github.com/lodash/lodash.git | 4.17.21 | 4.17.21 | John-David Dalton | | numeral | MIT | git+https://github.com/adamwdraper/Numeral-js.git | 2.0.6 | 2.0.6 | Adam Draper adamwdraper@gmail.com http://github.com/adamwdraper | | object-hash | MIT | git+https://github.com/puleos/object-hash.git | 3.0.0 | 3.0.0 | Scott Puleo | -| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.23.2 | 7.24.3 | The Babel Team (https://babel.dev/team) | -| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.14.201 | 4.17.0 | n/a | +| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.24.5 | 7.25.3 | The Babel Team (https://babel.dev/team) | +| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.17.1 | 4.17.7 | n/a | | @types/numeral | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 2.0.2 | 2.0.2 | n/a | -| @types/object-hash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 3.0.5 | 3.0.6 | n/a | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| @types/object-hash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 3.0.6 | 3.0.6 | n/a | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | @@ -48,41 +50,50 @@ Date: 2024-04-01 | Name | License type | Link | Installed version | Remote version | Author | | :---------------- | :----------- | :---------------------------------------------- | :---------------- | :------------- | :------------------------------------------------- | -| prettier | MIT | git+https://github.com/prettier/prettier.git | 3.2.5 | 3.2.5 | James Long | +| prettier | MIT | git+https://github.com/prettier/prettier.git | 3.2.5 | 3.3.3 | James Long | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | -| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.23.2 | 7.24.3 | The Babel Team (https://babel.dev/team) | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.24.5 | 7.25.3 | The Babel Team (https://babel.dev/team) | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | ### @sisense/sdk-pivot-client | Name | License type | Link | Installed version | Remote version | Author | | :----------------------------- | :----------- | :----------------------------------------------------------------------- | :---------------- | :------------- | :-------------------------------------------------------------- | -| @mui/material | MIT | git+https://github.com/mui/material-ui.git | 5.14.13 | 5.15.14 | MUI Team | -| @types/react-custom-scrollbars | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.0.13 | 4.0.13 | n/a | +| @mui/material | MIT | git+https://github.com/mui/material-ui.git | 5.15.16 | 5.16.7 | MUI Team | | classnames | MIT | git+https://github.com/JedWatson/classnames.git | 2.3.2 | 2.3.2 | Jed Watson | | dom-css | MIT | git://github.com/mattdesl/dom-css.git | 2.1.0 | 2.1.0 | Matt DesLauriers dave.des@gmail.com https://github.com/mattdesl | -| immer | MIT | git+https://github.com/immerjs/immer.git | 10.0.3 | 10.0.4 | Michel Weststrate | +| immer | MIT | git+https://github.com/immerjs/immer.git | 10.1.1 | 10.1.1 | Michel Weststrate | | lodash | MIT | git+https://github.com/lodash/lodash.git | 4.17.21 | 4.17.21 | John-David Dalton | | raf | MIT | git://github.com/chrisdickinson/raf.git | 3.4.0 | 3.4.0 | Chris Dickinson | -| rc-tooltip | MIT | git+ssh://git@github.com/react-component/tooltip.git | 3.7.3 | 3.7.3 | n/a | +| rc-tooltip | MIT | git+ssh://git@github.com/react-component/tooltip.git | 6.2.0 | 6.2.0 | n/a | | react-custom-scrollbars | MIT | git+https://github.com/malte-wessel/react-custom-scrollbars.git | 4.2.1 | 4.2.1 | Malte Wessel | -| react-use | Unlicense | git+https://github.com/streamich/react-use.git | 17.5.0 | 17.5.0 | @streamich | +| react-use | Unlicense | git+https://github.com/streamich/react-use.git | 17.5.0 | 17.5.1 | @streamich | | socket.io-client | MIT | git+https://github.com/Automattic/socket.io-client.git | 2.5.0 | 2.5.0 | n/a | | uuid | MIT | git+https://github.com/uuidjs/uuid.git | 9.0.1 | 9.0.1 | n/a | -| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.23.2 | 7.24.3 | The Babel Team (https://babel.dev/team) | -| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.14.202 | 4.17.0 | n/a | -| @types/rc-tooltip | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 3.7.13 | 3.7.14 | n/a | +| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.24.5 | 7.25.3 | The Babel Team (https://babel.dev/team) | +| @emotion/react | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.4 | 11.13.0 | Emotion Contributors | +| @emotion/styled | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.5 | 11.13.0 | n/a | +| @mui/material | MIT | git+https://github.com/mui/material-ui.git | 5.15.16 | 5.16.7 | MUI Team | +| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.17.1 | 4.17.7 | n/a | +| @types/react | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.3.1 | 18.3.3 | n/a | +| @types/react-custom-scrollbars | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.0.13 | 4.0.13 | n/a | +| @types/react-dom | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.3.0 | 18.3.0 | n/a | | @types/socket.io-client | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.4.36 | 1.4.36 | n/a | -| @vitejs/plugin-react | MIT | git+https://github.com/vitejs/vite-plugin-react.git | 4.2.1 | 4.2.1 | Evan You | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| @vitejs/plugin-react | MIT | git+https://github.com/vitejs/vite-plugin-react.git | 4.2.1 | 4.3.1 | Evan You | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | +| react | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | +| react-dom | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | +| rollup-plugin-re | MIT | git+https://github.com/jetiny/rollup-plugin-re.git | 1.0.7 | 1.0.7 | jetiny 86287344@qq.com | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | | vite | MIT | git+https://github.com/vitejs/vite.git | 4.1.4 | 4.1.4 | Evan You | -| vite-plugin-checker | MIT | git+https://github.com/fi3ework/vite-plugin-checker.git | 0.6.2 | 0.6.4 | fi3ework | +| vite-plugin-checker | MIT | git+https://github.com/fi3ework/vite-plugin-checker.git | 0.6.4 | 0.6.4 | fi3ework | | vite-plugin-css-injected-by-js | MIT | git+https://github.com/marco-prontera/vite-plugin-css-injected-by-js.git | 3.0.1 | 3.0.1 | Marco Prontera | | vite-plugin-dts | MIT | git+https://github.com/qmhc/vite-plugin-dts.git | 2.3.0 | 2.3.0 | qmhc | -| react | MIT | git+https://github.com/facebook/react.git | 18.2.0 | 18.2.0 | n/a | -| react-dom | MIT | git+https://github.com/facebook/react.git | 18.2.0 | 18.2.0 | n/a | +| @emotion/react | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.4 | 11.13.0 | Emotion Contributors | +| @emotion/styled | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.5 | 11.13.0 | n/a | +| react | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | +| react-dom | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | ### @sisense/sdk-query-client @@ -91,14 +102,14 @@ Date: 2024-04-01 | numeral | MIT | git+https://github.com/adamwdraper/Numeral-js.git | 2.0.6 | 2.0.6 | Adam Draper adamwdraper@gmail.com http://github.com/adamwdraper | | ts-deepmerge | ISC | git@github.com:voodoocreation/ts-deepmerge.git | 6.0.2 | 6.0.2 | Raice Hannay | | uuid | MIT | git+https://github.com/uuidjs/uuid.git | 9.0.1 | 9.0.1 | n/a | -| @types/tar | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 6.1.6 | 6.1.11 | n/a | -| @types/uuid | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 9.0.5 | 9.0.8 | n/a | +| @types/tar | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 6.1.13 | 6.1.13 | n/a | +| @types/uuid | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 9.0.8 | 9.0.8 | n/a | | @typescript-eslint/eslint-plugin | MIT | git+https://github.com/typescript-eslint/typescript-eslint.git | 5.62.0 | 5.62.0 | n/a | | @typescript-eslint/parser | BSD-2-Clause | git+https://github.com/typescript-eslint/typescript-eslint.git | 5.62.0 | 5.62.0 | n/a | -| axios | MIT | git+https://github.com/axios/axios.git | 1.5.1 | 1.6.8 | Matt Zabriskie | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| axios | MIT | git+https://github.com/axios/axios.git | 1.6.8 | 1.7.4 | Matt Zabriskie | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.8 | 2.8.8 | James Long | -| tar | ISC | git+https://github.com/isaacs/node-tar.git | 6.2.0 | 6.2.1 | GitHub Inc. | +| tar | ISC | git+https://github.com/isaacs/node-tar.git | 6.2.1 | 6.2.1 | GitHub Inc. | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.9.5 | 4.9.5 | Microsoft Corp. | ### @sisense/sdk-rest-client @@ -106,8 +117,8 @@ Date: 2024-04-01 | Name | License type | Link | Installed version | Remote version | Author | | :---------------- | :----------- | :------------------------------------------------ | :---------------- | :------------- | :------------------------------------------------- | | fetch-intercept | MIT | git+https://github.com/werk85/fetch-intercept.git | 2.4.0 | 2.4.0 | Malte Legenhausen | -| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.23.2 | 7.24.3 | The Babel Team (https://babel.dev/team) | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.24.5 | 7.25.3 | The Babel Team (https://babel.dev/team) | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | @@ -116,123 +127,121 @@ Date: 2024-04-01 | Name | License type | Link | Installed version | Remote version | Author | | :--------- | :----------- | :---------------------------------------------- | :---------------- | :------------- | :------------------------------------ | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | -| vitest | MIT | git+https://github.com/vitest-dev/vitest.git | 1.3.1 | 1.4.0 | Anthony Fu | +| vitest | MIT | git+https://github.com/vitest-dev/vitest.git | 1.6.0 | 1.6.0 | Anthony Fu | ### @sisense/sdk-ui -| Name | License type | Link | Installed version | Remote version | Author | -| :----------------------------- | :--------------------- | :----------------------------------------------------------------------- | :---------------- | :------------- | :-------------------------------------------------------------------- | -| @emotion/react | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.1 | 11.11.4 | Emotion Contributors | -| @emotion/styled | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.0 | 11.11.5 | n/a | -| @mui/material | MIT | git+https://github.com/mui/material-ui.git | 5.14.13 | 5.15.14 | MUI Team | -| @tanstack/react-query | MIT | git+https://github.com/TanStack/query.git | 4.36.1 | 4.36.1 | tannerlinsley | -| classnames | MIT | git+https://github.com/JedWatson/classnames.git | 2.3.2 | 2.5.1 | Jed Watson | -| colorjs.io | MIT | git+https://github.com/LeaVerou/color.js.git | 0.4.5 | 0.4.5 | n/a | -| date-fns | MIT | git+https://github.com/date-fns/date-fns.git | 2.30.0 | 2.30.0 | n/a | -| date-fns-tz | MIT | git+https://github.com/marnusw/date-fns-tz.git | 2.0.0 | 2.0.1 | Marnus Weststrate | -| dayjs | MIT | git+https://github.com/iamkun/dayjs.git | 1.11.10 | 1.11.10 | iamkun | -| fixed-data-table-2 | BSD-3-Clause | git+https://github.com/schrodinger/fixed-data-table-2.git | 1.2.22 | 1.2.22 | n/a | -| geojson | MIT | http://github.com/caseycesari/geojson.js.git | 0.5.0 | 0.5.0 | Casey Cesari | -| guid-typescript | ISC | git+https://github.com/NicolasDeveloper/guid-typescript.git | 1.0.9 | 1.0.9 | nicolas | -| highcharts-react-official | MIT | git+https://github.com/highcharts/highcharts-react.git | 3.2.1 | 3.2.1 | n/a | -| immer | MIT | git+https://github.com/immerjs/immer.git | 10.0.3 | 10.0.4 | Michel Weststrate | -| leaflet | BSD-2-Clause | git://github.com/Leaflet/Leaflet.git | 1.9.4 | 1.9.4 | n/a | -| lodash | MIT | git+https://github.com/lodash/lodash.git | 4.17.21 | 4.17.21 | John-David Dalton | -| merge-deep | MIT | git+https://github.com/jonschlinkert/merge-deep.git | 3.0.3 | 3.0.3 | Jon Schlinkert (https://github.com/jonschlinkert) | -| proj4leaflet | BSD-2-Clause | git://github.com/kartena/Proj4Leaflet.git | 1.0.2 | 1.0.2 | Per Liedman (https://github.com/perliedman/) | -| react-datepicker | MIT | git://github.com/Hacker0x01/react-datepicker.git | 4.20.0 | 4.25.0 | HackerOne | -| react-error-boundary | MIT | git+https://github.com/bvaughn/react-error-boundary.git | 4.0.11 | 4.0.13 | Brian Vaughn | -| react-i18next | MIT | git+https://github.com/i18next/react-i18next.git | 13.3.0 | 13.5.0 | Jan Mühlemann (https://github.com/jamuhl) | -| react-number-format | MIT | git+https://github.com/s-yadav/react-number-format.git | 5.3.1 | 5.3.4 | Sudhanshu Yadav | -| ts-deepmerge | ISC | git@github.com:voodoocreation/ts-deepmerge.git | 6.0.2 | 6.0.2 | Raice Hannay | -| ts-essentials | MIT | git+ssh://git@github.com/krzkaczor/ts-essentials.git | 9.4.1 | 9.4.1 | Krzysztof Kaczor | -| whatwg-fetch | MIT | git+https://github.com/github/fetch.git | 3.6.19 | 3.6.20 | n/a | -| yaml | ISC | git+https://github.com/eemeli/yaml.git | 2.4.0 | 2.4.1 | Eemeli Aro | -| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.23.2 | 7.24.3 | The Babel Team (https://babel.dev/team) | -| @monaco-editor/react | MIT | git+https://github.com/suren-atoyan/monaco-react.git | 4.6.0 | 4.6.0 | Suren Atoyan | -| @mui/icons-material | MIT | git+https://github.com/mui/material-ui.git | 5.14.13 | 5.15.14 | MUI Team | -| @mui/x-data-grid | MIT | git+https://github.com/mui/mui-x.git | 6.16.2 | 6.19.8 | MUI Team | -| @mui/x-data-grid-pro | SEE LICENSE IN LICENSE | git+https://github.com/mui/mui-x.git | 6.16.2 | 6.19.8 | MUI Team | -| @storybook/addon-actions | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/addon-docs | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/addon-essentials | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/addon-interactions | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/addon-links | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/addon-storysource | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/react | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/react-vite | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| @storybook/testing-library | MIT | git+https://github.com/storybookjs/testing-library.git | 0.2.0 | 0.2.0 | yannbf@gmail.com | -| @swc-node/register | MIT | git+https://github.com/swc-project/swc-node.git | 1.6.8 | 1.9.0 | LongYinan | -| @testing-library/jest-dom | MIT | git+https://github.com/testing-library/jest-dom.git | 6.4.2 | 6.4.2 | Ernesto Garcia (http://gnapse.github.io) | -| @testing-library/react | MIT | git+https://github.com/testing-library/react-testing-library.git | 14.0.0 | 14.2.2 | Kent C. Dodds (https://kentcdodds.com) | -| @types/fixed-data-table-2 | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 0.8.9 | 0.8.13 | n/a | -| @types/leaflet | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.9.8 | 1.9.8 | n/a | -| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.14.199 | 4.17.0 | n/a | -| @types/proj4leaflet | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.0.10 | 1.0.10 | n/a | -| @types/react | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.2.0 | 18.2.0 | n/a | -| @types/react-datepicker | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.19.0 | 4.19.6 | n/a | -| @types/react-dom | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.2.0 | 18.2.0 | n/a | -| @types/react-grid-layout | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.3.5 | 1.3.5 | n/a | -| @types/react-plotly.js | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 2.6.1 | 2.6.3 | n/a | -| @vitejs/plugin-react-swc | MIT | git+https://github.com/vitejs/vite-plugin-react-swc.git | 3.4.0 | 3.6.0 | Arnaud Barré (https://github.com/ArnaudBarre) | -| autoprefixer | MIT | git+https://github.com/postcss/autoprefixer.git | 10.4.16 | 10.4.19 | Andrey Sitnik | -| blob-polyfill | MIT | git+https://github.com/bjornstar/blob-polyfill.git | 7.0.20220408 | 7.0.20220408 | Eli Grey (https://eligrey.com) | -| canvas | MIT | git://github.com/Automattic/node-canvas.git | 2.11.2 | 2.11.2 | TJ Holowaychuk | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | -| jsdom | MIT | git+https://github.com/jsdom/jsdom.git | 22.1.0 | 22.1.0 | n/a | -| monaco-editor | MIT | git+https://github.com/microsoft/monaco-editor.git | 0.45.0 | 0.45.0 | Microsoft Corporation | -| msw | MIT | git+https://github.com/mswjs/msw.git | 2.2.1 | 2.2.1 | Artem Zakharchenko https://github.com/kettanaito | -| plotly.js | MIT | git+https://github.com/plotly/plotly.js.git | 2.26.2 | 2.30.1 | Plotly, Inc. | -| postcss | MIT | git+https://github.com/postcss/postcss.git | 8.4.31 | 8.4.38 | Andrey Sitnik | -| prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | -| react | MIT | git+https://github.com/facebook/react.git | 18.2.0 | 18.2.0 | n/a | -| react-dom | MIT | git+https://github.com/facebook/react.git | 18.2.0 | 18.2.0 | n/a | -| react-grid-layout | MIT | git+ssh://git@github.com/STRML/react-grid-layout.git | 1.4.4 | 1.4.4 | Samuel Reed (http://strml.net/) | -| react-json-view | MIT | git+https://github.com/mac-s-g/react-json-view.git | 1.21.3 | 1.21.3 | Mac Gainor | -| react-plotly.js | MIT | git+https://github.com/plotly/react-plotly.js.git | 2.6.0 | 2.6.0 | Plotly, Inc. | -| sass | MIT | git+https://github.com/sass/dart-sass.git | 1.58.3 | 1.58.3 | Natalie Weizenbaum nweiz@google.com https://github.com/nex3 | -| storybook | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | -| tailwindcss | MIT | git+https://github.com/tailwindlabs/tailwindcss.git | 3.3.3 | 3.4.3 | n/a | -| typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | -| vite | MIT | git+https://github.com/vitejs/vite.git | 4.1.4 | 4.1.4 | Evan You | -| vite-plugin-checker | MIT | git+https://github.com/fi3ework/vite-plugin-checker.git | 0.6.2 | 0.6.4 | fi3ework | -| vite-plugin-css-injected-by-js | MIT | git+https://github.com/marco-prontera/vite-plugin-css-injected-by-js.git | 3.0.1 | 3.0.1 | Marco Prontera | -| vite-plugin-dts | MIT | git+https://github.com/qmhc/vite-plugin-dts.git | 2.3.0 | 2.3.0 | qmhc | -| vitest-canvas-mock | MIT | git+https://github.com/wobsoriano/vitest-canvas-mock.git | 0.3.3 | 0.3.3 | Robert Soriano | -| react | MIT | git+https://github.com/facebook/react.git | 18.2.0 | 18.2.0 | n/a | -| react-dom | MIT | git+https://github.com/facebook/react.git | 18.2.0 | 18.2.0 | n/a | +| Name | License type | Link | Installed version | Remote version | Author | +| :----------------------------- | :----------- | :----------------------------------------------------------------------- | :---------------- | :------------- | :-------------------------------------------------------------------- | +| @emotion/react | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.4 | 11.13.0 | Emotion Contributors | +| @emotion/styled | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.5 | 11.13.0 | n/a | +| @mui/material | MIT | git+https://github.com/mui/material-ui.git | 5.15.16 | 5.16.7 | MUI Team | +| @mui/system | MIT | git+https://github.com/mui/material-ui.git | 5.15.15 | 5.16.7 | MUI Team | +| @tanstack/react-query | MIT | git+https://github.com/TanStack/query.git | 4.36.1 | 4.36.1 | tannerlinsley | +| classnames | MIT | git+https://github.com/JedWatson/classnames.git | 2.5.1 | 2.5.1 | Jed Watson | +| colorjs.io | MIT | git+https://github.com/LeaVerou/color.js.git | 0.4.5 | 0.4.5 | n/a | +| date-fns | MIT | git+https://github.com/date-fns/date-fns.git | 2.30.0 | 2.30.0 | n/a | +| date-fns-tz | MIT | git+https://github.com/marnusw/date-fns-tz.git | 2.0.1 | 2.0.1 | Marnus Weststrate | +| dayjs | MIT | git+https://github.com/iamkun/dayjs.git | 1.11.11 | 1.11.12 | iamkun | +| fixed-data-table-2 | BSD-3-Clause | git+https://github.com/schrodinger/fixed-data-table-2.git | 1.2.22 | 1.2.22 | n/a | +| geojson | MIT | http://github.com/caseycesari/geojson.js.git | 0.5.0 | 0.5.0 | Casey Cesari | +| guid-typescript | ISC | git+https://github.com/NicolasDeveloper/guid-typescript.git | 1.0.9 | 1.0.9 | nicolas | +| highcharts-react-official | MIT | git+https://github.com/highcharts/highcharts-react.git | 3.2.1 | 3.2.1 | n/a | +| immer | MIT | git+https://github.com/immerjs/immer.git | 10.1.1 | 10.1.1 | Michel Weststrate | +| leaflet | BSD-2-Clause | git://github.com/Leaflet/Leaflet.git | 1.9.4 | 1.9.4 | n/a | +| lodash | MIT | git+https://github.com/lodash/lodash.git | 4.17.21 | 4.17.21 | John-David Dalton | +| merge-deep | MIT | git+https://github.com/jonschlinkert/merge-deep.git | 3.0.3 | 3.0.3 | Jon Schlinkert (https://github.com/jonschlinkert) | +| proj4leaflet | BSD-2-Clause | git://github.com/kartena/Proj4Leaflet.git | 1.0.2 | 1.0.2 | Per Liedman (https://github.com/perliedman/) | +| react-datepicker | MIT | git://github.com/Hacker0x01/react-datepicker.git | 7.3.0 | 7.3.0 | HackerOne | +| react-error-boundary | MIT | git+https://github.com/bvaughn/react-error-boundary.git | 4.0.13 | 4.0.13 | Brian Vaughn | +| react-i18next | MIT | git+https://github.com/i18next/react-i18next.git | 13.5.0 | 13.5.0 | Jan Mühlemann (https://github.com/jamuhl) | +| react-number-format | MIT | git+https://github.com/s-yadav/react-number-format.git | 5.3.4 | 5.4.0 | Sudhanshu Yadav | +| ts-deepmerge | ISC | git@github.com:voodoocreation/ts-deepmerge.git | 6.0.2 | 6.0.2 | Raice Hannay | +| ts-essentials | MIT | git+ssh://git@github.com/krzkaczor/ts-essentials.git | 9.4.2 | 9.4.2 | Krzysztof Kaczor | +| whatwg-fetch | MIT | git+https://github.com/github/fetch.git | 3.6.20 | 3.6.20 | n/a | +| yaml | ISC | git+https://github.com/eemeli/yaml.git | 2.5.0 | 2.5.0 | Eemeli Aro | +| @babel/preset-env | MIT | https://github.com/babel/babel.git | 7.24.5 | 7.25.3 | The Babel Team (https://babel.dev/team) | +| @mui/icons-material | MIT | git+https://github.com/mui/material-ui.git | 5.15.16 | 5.16.7 | MUI Team | +| @mui/x-data-grid | MIT | git+https://github.com/mui/mui-x.git | 6.19.11 | 6.20.4 | MUI Team | +| @storybook/addon-actions | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/addon-docs | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/addon-essentials | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/addon-interactions | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/addon-links | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/addon-storysource | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/react | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/react-vite | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| @storybook/testing-library | MIT | git+https://github.com/storybookjs/testing-library.git | 0.2.0 | 0.2.0 | yannbf@gmail.com | +| @swc-node/register | MIT | git+https://github.com/swc-project/swc-node.git | 1.9.1 | 1.10.9 | LongYinan | +| @testing-library/jest-dom | MIT | git+https://github.com/testing-library/jest-dom.git | 6.4.5 | 6.4.8 | Ernesto Garcia (http://gnapse.github.io) | +| @testing-library/react | MIT | git+https://github.com/testing-library/react-testing-library.git | 14.3.1 | 14.3.1 | Kent C. Dodds (https://kentcdodds.com) | +| @types/fixed-data-table-2 | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.0.0 | 1.0.0 | n/a | +| @types/leaflet | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.9.12 | 1.9.12 | n/a | +| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.17.1 | 4.17.7 | n/a | +| @types/proj4leaflet | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.0.10 | 1.0.10 | n/a | +| @types/react | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.3.1 | 18.3.1 | n/a | +| @types/react-dom | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.3.0 | 18.3.0 | n/a | +| @types/react-grid-layout | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 1.3.5 | 1.3.5 | n/a | +| @types/react-plotly.js | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 2.6.3 | 2.6.3 | n/a | +| @vitejs/plugin-react-swc | MIT | git+https://github.com/vitejs/vite-plugin-react-swc.git | 3.6.0 | 3.7.0 | Arnaud Barré (https://github.com/ArnaudBarre) | +| autoprefixer | MIT | git+https://github.com/postcss/autoprefixer.git | 10.4.19 | 10.4.20 | Andrey Sitnik | +| blob-polyfill | MIT | git+https://github.com/bjornstar/blob-polyfill.git | 7.0.20220408 | 7.0.20220408 | Eli Grey (https://eligrey.com) | +| canvas | MIT | git://github.com/Automattic/node-canvas.git | 2.11.2 | 2.11.2 | TJ Holowaychuk | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | +| jsdom | MIT | git+https://github.com/jsdom/jsdom.git | 22.1.0 | 22.1.0 | n/a | +| msw | MIT | git+https://github.com/mswjs/msw.git | 2.2.1 | 2.2.1 | Artem Zakharchenko https://github.com/kettanaito | +| plotly.js | MIT | git+https://github.com/plotly/plotly.js.git | 2.32.0 | 2.34.0 | Plotly, Inc. | +| postcss | MIT | git+https://github.com/postcss/postcss.git | 8.4.38 | 8.4.41 | Andrey Sitnik | +| prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | +| react | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | +| react-dom | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | +| react-grid-layout | MIT | git+ssh://git@github.com/STRML/react-grid-layout.git | 1.4.4 | 1.4.4 | Samuel Reed (http://strml.net/) | +| react-json-view | MIT | git+https://github.com/mac-s-g/react-json-view.git | 1.21.3 | 1.21.3 | Mac Gainor | +| react-plotly.js | MIT | git+https://github.com/plotly/react-plotly.js.git | 2.6.0 | 2.6.0 | Plotly, Inc. | +| rollup-plugin-re | MIT | git+https://github.com/jetiny/rollup-plugin-re.git | 1.0.7 | 1.0.7 | jetiny 86287344@qq.com | +| sass | MIT | git+https://github.com/sass/dart-sass.git | 1.58.3 | 1.58.3 | Natalie Weizenbaum nweiz@google.com https://github.com/nex3 | +| storybook | MIT | https://github.com/storybookjs/storybook.git | 7.0.24 | 7.0.24 | n/a | +| tailwindcss | MIT | git+https://github.com/tailwindlabs/tailwindcss.git | 3.4.3 | 3.4.10 | n/a | +| typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | +| vite | MIT | git+https://github.com/vitejs/vite.git | 5.2.10 | 5.2.10 | Evan You | +| vite-plugin-checker | MIT | git+https://github.com/fi3ework/vite-plugin-checker.git | 0.6.4 | 0.6.4 | fi3ework | +| vite-plugin-css-injected-by-js | MIT | git+https://github.com/marco-prontera/vite-plugin-css-injected-by-js.git | 3.0.1 | 3.0.1 | Marco Prontera | +| vite-plugin-dts | MIT | git+https://github.com/qmhc/vite-plugin-dts.git | 2.3.0 | 2.3.0 | qmhc | +| vitest-canvas-mock | MIT | git+https://github.com/wobsoriano/vitest-canvas-mock.git | 0.3.3 | 0.3.3 | Robert Soriano | +| react | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | +| react-dom | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | n/a | ### @sisense/sdk-ui-angular | Name | License type | Link | Installed version | Remote version | Author | | :---------------------------- | :----------- | :----------------------------------------------------------------- | :---------------- | :------------- | :------------------------------------------------- | | rxjs | Apache-2.0 | git+https://github.com/reactivex/rxjs.git | 7.8.1 | 7.8.1 | Ben Lesh | -| ts-deepmerge | ISC | git@github.com:voodoocreation/ts-deepmerge.git | 6.2.0 | 6.2.1 | Raice Hannay | -| tslib | 0BSD | git+https://github.com/Microsoft/tslib.git | 2.6.2 | 2.6.2 | Microsoft Corp. | -| @angular-devkit/build-angular | MIT | git+https://github.com/angular/angular-cli.git | 15.2.10 | 15.2.11 | Angular Authors | -| @angular/cli | MIT | git+https://github.com/angular/angular-cli.git | 15.2.10 | 15.2.11 | Angular Authors | +| ts-deepmerge | ISC | git@github.com:voodoocreation/ts-deepmerge.git | 6.2.1 | 6.2.1 | Raice Hannay | +| tslib | 0BSD | git+https://github.com/Microsoft/tslib.git | 2.6.2 | 2.6.3 | Microsoft Corp. | +| @angular-devkit/build-angular | MIT | git+https://github.com/angular/angular-cli.git | 15.2.11 | 15.2.11 | Angular Authors | +| @angular/cli | MIT | git+https://github.com/angular/angular-cli.git | 15.2.11 | 15.2.11 | Angular Authors | | @angular/common | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 15.2.10 | angular | | @angular/compiler | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 15.2.10 | angular | | @angular/compiler-cli | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 15.2.10 | n/a | | @angular/core | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 15.2.10 | angular | -| @testing-library/angular | MIT | git+https://github.com/testing-library/angular-testing-library.git | 15.0.0 | 15.2.0 | Tim Deschryver | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| @testing-library/angular | MIT | git+https://github.com/testing-library/angular-testing-library.git | 15.2.0 | 15.2.0 | Tim Deschryver | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | | ng-packagr | MIT | git+https://github.com/ng-packagr/ng-packagr.git | 15.2.2 | 15.2.2 | David Herges | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.9.5 | 4.9.5 | Microsoft Corp. | -| vitest | MIT | git+https://github.com/vitest-dev/vitest.git | 1.3.1 | 1.4.0 | Anthony Fu | -| @angular/common | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 17.3.2 | angular | -| @angular/compiler | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 17.3.2 | angular | -| @angular/core | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 17.3.2 | angular | +| vitest | MIT | git+https://github.com/vitest-dev/vitest.git | 1.6.0 | 1.6.0 | Anthony Fu | +| @angular/common | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 18.2.0 | angular | +| @angular/compiler | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 18.2.0 | angular | +| @angular/core | MIT | git+https://github.com/angular/angular.git | 15.2.10 | 18.2.0 | angular | ### @sisense/sdk-ui-preact | Name | License type | Link | Installed version | Remote version | Author | | :------------------ | :----------- | :----------------------------------------------------- | :---------------- | :------------- | :------------------------------------------------- | -| preact | MIT | git+https://github.com/preactjs/preact.git | 10.18.1 | 10.20.1 | n/a | +| preact | MIT | git+https://github.com/preactjs/preact.git | 10.21.0 | 10.23.2 | n/a | | @preact/preset-vite | MIT | git+https://github.com/preactjs/preset-vite.git | 2.5.0 | 2.5.0 | The Preact Team (https://preactjs.com) | -| @types/node | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.18.5 | 18.19.28 | n/a | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | +| @types/node | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.19.32 | 18.19.44 | n/a | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.4 | 2.8.4 | James Long | | rxjs | Apache-2.0 | git+https://github.com/reactivex/rxjs.git | 7.8.1 | 7.8.1 | Ben Lesh | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | @@ -245,22 +254,22 @@ Date: 2024-04-01 | :---------------------------- | :----------- | :-------------------------------------------------------- | :---------------- | :------------- | :------------------------------------------------- | | deepmerge | MIT | git://github.com/TehShrike/deepmerge.git | 4.3.1 | 4.3.1 | n/a | | lodash | MIT | git+https://github.com/lodash/lodash.git | 4.17.21 | 4.17.21 | John-David Dalton | -| vue | MIT | git+https://github.com/vuejs/core.git | 3.3.4 | 3.4.21 | Evan You | -| @rushstack/eslint-patch | MIT | git+https://github.com/microsoft/rushstack.git | 1.5.1 | 1.10.1 | n/a | -| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.14.199 | 4.17.0 | n/a | -| @types/node | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.18.5 | 18.19.28 | n/a | -| @vitejs/plugin-vue | MIT | git+https://github.com/vitejs/vite-plugin-vue.git | 4.4.0 | 4.6.2 | Evan You | +| vue | MIT | git+https://github.com/vuejs/core.git | 3.4.27 | 3.4.38 | Evan You | +| @rushstack/eslint-patch | MIT | git+https://github.com/microsoft/rushstack.git | 1.10.2 | 1.10.4 | n/a | +| @types/lodash | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 4.17.1 | 4.17.7 | n/a | +| @types/node | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.19.32 | 18.19.44 | n/a | +| @vitejs/plugin-vue | MIT | git+https://github.com/vitejs/vite-plugin-vue.git | 4.6.2 | 4.6.2 | Evan You | | @vue/eslint-config-prettier | MIT | git+https://github.com/vuejs/eslint-config-prettier.git | 7.1.0 | 7.1.0 | Evan You | | @vue/eslint-config-typescript | MIT | git+https://github.com/vuejs/eslint-config-typescript.git | 11.0.3 | 11.0.3 | Evan You | | @vue/tsconfig | MIT | git+https://github.com/vuejs/tsconfig.git | 0.1.3 | 0.1.3 | Haoqun Jiang | -| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.51.0 | 8.57.0 | Nicholas C. Zakas | -| eslint-plugin-vue | MIT | git+https://github.com/vuejs/eslint-plugin-vue.git | 9.17.0 | 9.24.0 | Toru Nagashima (https://github.com/mysticatea) | +| eslint | MIT | git+https://github.com/eslint/eslint.git | 8.57.0 | 8.57.0 | Nicholas C. Zakas | +| eslint-plugin-vue | MIT | git+https://github.com/vuejs/eslint-plugin-vue.git | 9.25.0 | 9.27.0 | Toru Nagashima (https://github.com/mysticatea) | | npm-run-all | MIT | git+https://github.com/mysticatea/npm-run-all.git | 4.1.5 | 4.1.5 | Toru Nagashima | | prettier | MIT | git+https://github.com/prettier/prettier.git | 2.8.8 | 2.8.8 | James Long | | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.8.4 | Microsoft Corp. | -| vite | MIT | git+https://github.com/vitejs/vite.git | 4.4.11 | 4.5.3 | Evan You | +| vite | MIT | git+https://github.com/vitejs/vite.git | 4.5.3 | 4.5.3 | Evan You | | vite-plugin-dts | MIT | git+https://github.com/qmhc/vite-plugin-dts.git | 2.3.0 | 2.3.0 | qmhc | -| vue-tsc | MIT | git+https://github.com/vuejs/language-tools.git | 1.8.19 | 1.8.27 | n/a | +| vue-tsc | MIT | git+https://github.com/vuejs/language-tools.git | 1.8.27 | 1.8.27 | n/a | ## Other Sisense Packages Used By Compose SDK Packages @@ -268,7 +277,7 @@ Date: 2024-04-01 | Name | License type | Link | Installed version | Remote version | Author | | :----------------------------- | :--------------------------------- | :------------------------------------------------------------------- | :---------------- | :------------- | :--------------------------------------------------------------------- | -| @emotion/css | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.2 | 11.11.2 | Kye Hohenberger | +| @emotion/css | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.11.2 | 11.13.0 | Kye Hohenberger | | highcharts | https://www.highcharts.com/license | git+https://github.com/highcharts/highcharts-dist.git | 10.3.3 | 10.3.3 | Highsoft AS (http://www.highcharts.com/about) | | lodash-es | MIT | git+https://github.com/lodash/lodash.git | 4.17.21 | 4.17.21 | John-David Dalton | | @types/lodash-es | n/a | https://github.com/DefinitelyTyped/DefinitelyTyped.git | n/a | 4.17.12 | n/a | @@ -280,7 +289,7 @@ Date: 2024-04-01 | typescript | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 4.8.4 | 4.9.5 | Microsoft Corp. | | vite | n/a | git+https://github.com/vitejs/vite.git | n/a | 2.9.15 | n/a | | vite-plugin-require-transform | n/a | git+https://github.com/WarrenJones/vite-plugin-require-transform.git | n/a | 1.0.21 | n/a | -| webpack | MIT | git+https://github.com/webpack/webpack.git | 5.76.1 | 5.91.0 | Tobias Koppers @sokra | +| webpack | MIT | git+https://github.com/webpack/webpack.git | 5.76.1 | 5.93.0 | Tobias Koppers @sokra | | webpack-cli | n/a | git+https://github.com/webpack/webpack-cli.git | n/a | 5.1.4 | n/a | ### @sisense/task-manager diff --git a/package.json b/package.json index 808509da..8318e721 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.16.0", + "version": "1.17.0", "type": "module", "license": "SEE LICENSE IN LICENSE.md", "private": true, diff --git a/packages/sdk-cli/package.json b/packages/sdk-cli/package.json index aa3b72a8..97c57b48 100644 --- a/packages/sdk-cli/package.json +++ b/packages/sdk-cli/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": "./dist/index.js", "main": "./dist/index.js", @@ -20,12 +20,12 @@ "license": "SEE LICENSE IN LICENSE.md", "bin": "./dist/index.js", "dependencies": { - "@sisense/sdk-common": "^1.16.0", - "@sisense/sdk-data": "^1.16.0", - "@sisense/sdk-modeling": "^1.16.0", - "@sisense/sdk-query-client": "^1.16.0", - "@sisense/sdk-rest-client": "^1.16.0", - "@sisense/sdk-tracking": "^1.16.0", + "@sisense/sdk-common": "^1.17.0", + "@sisense/sdk-data": "^1.17.0", + "@sisense/sdk-modeling": "^1.17.0", + "@sisense/sdk-query-client": "^1.17.0", + "@sisense/sdk-rest-client": "^1.17.0", + "@sisense/sdk-tracking": "^1.17.0", "cross-fetch": "^4.0.0", "inquirer": "^8.1.2", "js-levenshtein": "^1.1.6", diff --git a/packages/sdk-cli/src/constants.ts b/packages/sdk-cli/src/constants.ts deleted file mode 100644 index 2c1a56bb..00000000 --- a/packages/sdk-cli/src/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export enum TrackingActions { - Execution = 'sdkCliExec', -} diff --git a/packages/sdk-cli/src/tracking.ts b/packages/sdk-cli/src/tracking.ts index 58ab5566..6c778c09 100644 --- a/packages/sdk-cli/src/tracking.ts +++ b/packages/sdk-cli/src/tracking.ts @@ -1,9 +1,8 @@ -import { TrackingDetails, trackProductEvent } from '@sisense/sdk-tracking'; +import { TrackingEventDetails, trackProductEvent } from '@sisense/sdk-tracking'; import { HttpClient } from '@sisense/sdk-rest-client'; import { PKG_VERSION } from './package-version.js'; -import { TrackingActions } from './constants.js'; -interface ExecutionEventDetails extends TrackingDetails { +interface ExecutionEventDetails extends TrackingEventDetails { packageVersion: string; commandName: string; argumentsPassed: string; @@ -23,7 +22,5 @@ export const trackExecution = ( .join(', '), }; - const action = TrackingActions.Execution; - - trackProductEvent(action, payload, httpClient); + trackProductEvent('sdkCliExec', payload, httpClient); }; diff --git a/packages/sdk-common/package.json b/packages/sdk-common/package.json index a8d57ab6..cac92e02 100644 --- a/packages/sdk-common/package.json +++ b/packages/sdk-common/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": { ".": "./dist/index.js" diff --git a/packages/sdk-data/package.json b/packages/sdk-data/package.json index f0e785bc..22bdae1a 100644 --- a/packages/sdk-data/package.json +++ b/packages/sdk-data/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "main": "./dist/cjs/index.js", "module": "./dist/index.js", @@ -27,8 +27,8 @@ "author": "Sisense", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@sisense/sdk-common": "^1.16.0", - "@sisense/sdk-rest-client": "^1.16.0", + "@sisense/sdk-common": "^1.17.0", + "@sisense/sdk-rest-client": "^1.17.0", "guid-typescript": "^1.0.9", "lodash": "^4.17.21", "numeral": "^2.0.6", diff --git a/packages/sdk-data/src/interfaces.ts b/packages/sdk-data/src/interfaces.ts index 63c24cff..0df51d86 100644 --- a/packages/sdk-data/src/interfaces.ts +++ b/packages/sdk-data/src/interfaces.ts @@ -9,7 +9,12 @@ export interface Cell { data: any; /** Display text */ text?: string; - /** Boolean flag whether the data value should be blurred when visualized in a chart */ + /** + * Boolean flag representing three states that can be visualized in a chart: + * - `true`: the data value is in blur state + * - `false`: the data value is in highlight state + * - if not specified, the data value is neither in highlight nor blur state + */ blur?: boolean; /** Color associated with the data value when visualized in a chart */ color?: string; @@ -36,9 +41,10 @@ export interface DataCell { * * Means different things depending on if it is specified in the returned dataset. * - * The absence of `selected` across all cells means that all data is highlighted. + * The absence of `selected` across all cells means that all data are neutral (neither highlighted nor blurred). * The presence of `selected` in at least one cell means that some cells are highlighted * and some are blurred. + * The presence of `selected` in all cells means that all data are highlighted. */ selected?: boolean; } diff --git a/packages/sdk-modeling/package.json b/packages/sdk-modeling/package.json index c02f93be..aaa5851b 100644 --- a/packages/sdk-modeling/package.json +++ b/packages/sdk-modeling/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "author": "Sisense", "license": "SEE LICENSE IN LICENSE.md", "type": "module", @@ -20,7 +20,7 @@ "module": "./dist/index.js", "types": "./dist/index.d.ts", "dependencies": { - "@sisense/sdk-data": "^1.16.0", + "@sisense/sdk-data": "^1.17.0", "prettier": "^3.2.5", "typescript": "4.8.4" }, diff --git a/packages/sdk-pivot-client/package.json b/packages/sdk-pivot-client/package.json index a86b028b..d1987d86 100644 --- a/packages/sdk-pivot-client/package.json +++ b/packages/sdk-pivot-client/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": "./dist/index.js", "main": "./dist/index.js", @@ -39,8 +39,8 @@ ], "dependencies": { "@mui/material": "^5.11.0", - "@sisense/sdk-data": "^1.16.0", - "@sisense/sdk-rest-client": "^1.16.0", + "@sisense/sdk-data": "^1.17.0", + "@sisense/sdk-rest-client": "^1.17.0", "classnames": "2.3.2", "dom-css": "2.1.0", "immer": "^10.0.2", diff --git a/packages/sdk-query-client/package.json b/packages/sdk-query-client/package.json index 63250167..2d89dbf7 100644 --- a/packages/sdk-query-client/package.json +++ b/packages/sdk-query-client/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": "./dist/index.js", "main": "./dist/index.js", @@ -20,10 +20,10 @@ "author": "Sisense", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@sisense/sdk-common": "^1.16.0", - "@sisense/sdk-data": "^1.16.0", - "@sisense/sdk-pivot-client": "^1.16.0", - "@sisense/sdk-rest-client": "^1.16.0", + "@sisense/sdk-common": "^1.17.0", + "@sisense/sdk-data": "^1.17.0", + "@sisense/sdk-pivot-client": "^1.17.0", + "@sisense/sdk-rest-client": "^1.17.0", "@sisense/task-manager": "^0.1.0", "numeral": "^2.0.6", "ts-deepmerge": "6.0.2", diff --git a/packages/sdk-query-client/src/query-result/get-data-from-query-result.test.ts b/packages/sdk-query-client/src/query-result/get-data-from-query-result.test.ts index bc10efa0..f6fd6654 100644 --- a/packages/sdk-query-client/src/query-result/get-data-from-query-result.test.ts +++ b/packages/sdk-query-client/src/query-result/get-data-from-query-result.test.ts @@ -1,8 +1,8 @@ import { getDataFromQueryResult, setCellsBlur } from './get-data-from-query-result.js'; -import { DimensionalAttribute, DataCell } from '@sisense/sdk-data'; +import { DimensionalAttribute, DataCell, DimensionalBaseMeasure } from '@sisense/sdk-data'; describe('Handle query service response', () => { - it('handle simple response', () => { + it('handle simple response with neutral rows (neither highlighted nor blurred)', () => { const response = { headers: ['Gender'], metadata: [ @@ -59,9 +59,9 @@ describe('Handle query service response', () => { const result = { columns: [{ name: 'Gender', type: 'text' }], rows: [ - [{ data: 'Female', text: 'Female', blur: false }], - [{ data: 'Male', text: 'Male', blur: false }], - [{ data: 'Unspecified', text: 'Unspecified', blur: false }], + [{ data: 'Female', text: 'Female' }], + [{ data: 'Male', text: 'Male' }], + [{ data: 'Unspecified', text: 'Unspecified' }], ], }; @@ -70,7 +70,7 @@ describe('Handle query service response', () => { expect(data).toStrictEqual(result); }); - it('handle response with selection', () => { + it('handle response with a highlighted row', () => { const response = { headers: ['Gender'], metadata: [ @@ -139,8 +139,211 @@ describe('Handle query service response', () => { expect(data).toStrictEqual(result); }); + it('handle response with ALL highlighted rows', () => { + const response = { + headers: ['Category', '$measure0_# of unique Category'], + metadata: [ + { + jaql: { + datatype: 'text', + dim: '[Category.Category]', + title: 'Category', + }, + }, + { + jaql: { + agg: 'count', + datatype: 'text', + dim: '[Category.Category]', + title: '$measure0_# of unique Category', + }, + }, + ], + datasource: { + revisionId: 'TBD', + fullname: 'LocalHost/Sample ECommerce', + }, + processingInfo: { + cacheType: 'result', + cacheTime: '2024-08-10T02:37:54.903Z', + }, + translationInfo: { + translationServiceProvider: 'NewTranslationService', + isTranslationFallback: false, + isQueryFallback: false, + translationDuration: 0.0, + sqlFromCache: true, + }, + values: [ + [ + { + data: 'Apple Mac Desktops', + text: 'Apple Mac Desktops', + selected: true, + }, + { + data: 1, + text: '1', + }, + ], + [ + { + data: 'Apple Mac Laptops', + text: 'Apple Mac Laptops', + selected: true, + }, + { + data: 1, + text: '1', + }, + ], + [ + { + data: 'Camcorders', + text: 'Camcorders', + selected: true, + }, + { + data: 1, + text: '1', + }, + ], + ], + }; + const result = { + columns: [ + { name: 'Gender', type: 'text' }, + { name: '# of unique Category', type: 'number' }, + ], + rows: [ + [ + { data: 'Apple Mac Desktops', text: 'Apple Mac Desktops', blur: false }, + { data: 1, text: '1', blur: false }, + ], + [ + { data: 'Apple Mac Laptops', text: 'Apple Mac Laptops', blur: false }, + { data: 1, text: '1', blur: false }, + ], + [ + { data: 'Camcorders', text: 'Camcorders', blur: false }, + { data: 1, text: '1', blur: false }, + ], + ], + }; + const data = getDataFromQueryResult(response, [ + new DimensionalAttribute('Gender', '[Commerce.Gender]', 'text-attribute'), + new DimensionalBaseMeasure( + '# of unique Category', + new DimensionalAttribute('Category', '[Category.Category]', 'text-attribute'), + 'count', + ), + ]); + + expect(data).toStrictEqual(result); + }); + + it('handle complex response with ALL neutral rows', () => { + const response = { + headers: ['Category', '$measure0_# of unique Category'], + metadata: [ + { + jaql: { + datatype: 'text', + dim: '[Category.Category]', + title: 'Category', + }, + }, + { + jaql: { + agg: 'count', + datatype: 'text', + dim: '[Category.Category]', + title: '$measure0_# of unique Category', + }, + }, + ], + datasource: { + revisionId: 'TBD', + fullname: 'LocalHost/Sample ECommerce', + }, + processingInfo: { + cacheType: 'result', + cacheTime: '2024-08-10T02:37:54.903Z', + }, + translationInfo: { + translationServiceProvider: 'NewTranslationService', + isTranslationFallback: false, + isQueryFallback: false, + translationDuration: 0.0, + sqlFromCache: true, + }, + values: [ + [ + { + data: 'Apple Mac Desktops', + text: 'Apple Mac Desktops', + }, + { + data: 1, + text: '1', + }, + ], + [ + { + data: 'Apple Mac Laptops', + text: 'Apple Mac Laptops', + }, + { + data: 1, + text: '1', + }, + ], + [ + { + data: 'Camcorders', + text: 'Camcorders', + }, + { + data: 1, + text: '1', + }, + ], + ], + }; + const result = { + columns: [ + { name: 'Gender', type: 'text' }, + { name: '# of unique Category', type: 'number' }, + ], + rows: [ + [ + { data: 'Apple Mac Desktops', text: 'Apple Mac Desktops' }, + { data: 1, text: '1' }, + ], + [ + { data: 'Apple Mac Laptops', text: 'Apple Mac Laptops' }, + { data: 1, text: '1' }, + ], + [ + { data: 'Camcorders', text: 'Camcorders' }, + { data: 1, text: '1' }, + ], + ], + }; + const data = getDataFromQueryResult(response, [ + new DimensionalAttribute('Gender', '[Commerce.Gender]', 'text-attribute'), + new DimensionalBaseMeasure( + '# of unique Category', + new DimensionalAttribute('Category', '[Category.Category]', 'text-attribute'), + 'count', + ), + ]); + + expect(data).toStrictEqual(result); + }); + it('should set blur for all fields of cell based on selected field value', () => { - const rows: DataCell[][] = [ + const inputRows: DataCell[][] = [ // selected point [ { data: '25-34', text: '25-34', selected: true }, @@ -163,25 +366,56 @@ describe('Handle query service response', () => { { data: 1884462.598469913, text: '1884462.598469913' }, ], ]; - const cell = setCellsBlur(rows); - expect(cell).toHaveLength(3); - expect(cell[0]).toMatchObject([ + const outputRows = setCellsBlur(inputRows); + expect(outputRows).toHaveLength(3); + expect(outputRows[0]).toMatchObject([ { data: '25-34', text: '25-34', blur: false }, { data: 'Female', text: 'Female', blur: false }, { data: 1048, text: '1048', blur: false }, { data: 135521.08578795195, text: '135521.085787952', blur: false }, ]); - expect(cell[1]).toMatchObject([ + expect(outputRows[1]).toMatchObject([ { data: '25-34', text: '25-34', blur: true }, { data: 'Male', text: 'Male', blur: true }, { data: 3902, text: '3902', blur: true }, { data: 607590.7210561037, text: '607590.7210561037', blur: true }, ]); - expect(cell[2]).toMatchObject([ + expect(outputRows[2]).toMatchObject([ { data: '25-34', text: '25-34', blur: true }, { data: 'Unspecified', text: 'Unspecified', blur: true }, { data: 12639, text: '12639', blur: true }, { data: 1884462.598469913, text: '1884462.598469913', blur: true }, ]); }); + + it('should set blur for all fields of cell based on selected field value 2', () => { + const inputRows: DataCell[][] = [ + [ + { data: 'A', text: 'A', selected: true }, + { data: '1', text: '1' }, + ], + [ + { data: 'B', text: 'B', selected: true }, + { data: '2', text: '2' }, + ], + [ + { data: 'C', text: 'C' }, + { data: '3', text: '3' }, + ], + ]; + const outputRows = setCellsBlur(inputRows); + expect(outputRows).toHaveLength(3); + expect(outputRows[0]).toMatchObject([ + { data: 'A', text: 'A', blur: false }, + { data: '1', text: '1', blur: false }, + ]); + expect(outputRows[1]).toMatchObject([ + { data: 'B', text: 'B', blur: false }, + { data: '2', text: '2', blur: false }, + ]); + expect(outputRows[2]).toMatchObject([ + { data: 'C', text: 'C', blur: true }, + { data: '3', text: '3', blur: true }, + ]); + }); }); diff --git a/packages/sdk-query-client/src/query-result/get-data-from-query-result.ts b/packages/sdk-query-client/src/query-result/get-data-from-query-result.ts index 9d3c3593..e138d0e0 100644 --- a/packages/sdk-query-client/src/query-result/get-data-from-query-result.ts +++ b/packages/sdk-query-client/src/query-result/get-data-from-query-result.ts @@ -32,23 +32,37 @@ export function prepareResultAsColsAndRows( * @returns A new 2D array of cells with the `blur` property set. */ export function setCellsBlur(rows: DataCell[][]): Cell[][] { - // An array indicating whether `blur` is enabled per each column. - const blurEnabledPerColumn = rows[0]?.map((_value, index) => { - return rows.some((r) => 'selected' in r[index]); + // A boolean flag indicating whether highlight is enabled on some column. + let isHighlightEnabledSomeColumn = false; + // An array indicating whether highlight is enabled per each column. + const highlightEnabledPerColumn = rows[0]?.map((_value, index) => { + const isHighlightEnabled = rows.some((r) => 'selected' in r[index]); + if (isHighlightEnabled) { + isHighlightEnabledSomeColumn = true; + } + return isHighlightEnabled; }); return rows.map((r) => { // calculates a single `blur` value for a whole row based on each column (cell) configuration. - const blur = blurEnabledPerColumn.some((isBlurEnabled, columnIndex) => { - return isBlurEnabled && !r[columnIndex].selected; - }); + // true: the data value is blurred + // false: the data value is highlighted + // undefined: the data value is neutral (neither highlighted nor blurred) + const blur = !isHighlightEnabledSomeColumn + ? undefined + : highlightEnabledPerColumn.some( + (isHighlightEnabled, columnIndex) => isHighlightEnabled && !r[columnIndex].selected, + ); return r.map( - (d): Cell => ({ - data: d.data, - text: d.text, - blur, - }), + (d): Cell => + blur !== undefined + ? { + data: d.data, + text: d.text, + blur, + } + : { data: d.data, text: d.text }, ); }); } diff --git a/packages/sdk-rest-client/package.json b/packages/sdk-rest-client/package.json index fabf26f4..219adba0 100644 --- a/packages/sdk-rest-client/package.json +++ b/packages/sdk-rest-client/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": "./dist/index.js", "main": "./dist/index.js", @@ -20,7 +20,7 @@ "author": "Sisense", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@sisense/sdk-common": "^1.16.0", + "@sisense/sdk-common": "^1.17.0", "fetch-intercept": "^2.4.0" }, "scripts": { diff --git a/packages/sdk-rest-client/src/authenticator.ts b/packages/sdk-rest-client/src/authenticator.ts index 6b84e01c..f9de7724 100644 --- a/packages/sdk-rest-client/src/authenticator.ts +++ b/packages/sdk-rest-client/src/authenticator.ts @@ -9,8 +9,8 @@ type AuthenticatorConfig = { url: string; username?: string; password?: string; - token?: string; - wat?: string; + token?: string | null; + wat?: string | null; ssoEnabled?: boolean; enableSilentPreAuth?: boolean; }; diff --git a/packages/sdk-rest-client/src/helpers.test.ts b/packages/sdk-rest-client/src/helpers.test.ts index b59adc3d..0300f515 100644 --- a/packages/sdk-rest-client/src/helpers.test.ts +++ b/packages/sdk-rest-client/src/helpers.test.ts @@ -1,4 +1,4 @@ -import { addQueryParamsToUrl, appendHeaders } from './helpers.js'; +import { addQueryParamsToUrl, appendHeaders, isAuthTokenPending } from './helpers.js'; describe('appendHeaders', () => { it('should append headers to an existing Headers object', () => { @@ -133,4 +133,29 @@ describe('appendHeaders', () => { expect(resultUrl).toBe(url); }); }); + + describe('isAuthTokenPending', () => { + it('should return true when auth token is pending', () => { + let token = null; + let wat = undefined; + + expect(isAuthTokenPending(token, wat)).toBe(true); + + token = undefined; + wat = null; + + expect(isAuthTokenPending(token, wat)).toBe(true); + }); + + it('should return false when auth token is set', () => { + let token: string | undefined = 'TOKEN_VALUE'; + let wat = undefined; + + expect(isAuthTokenPending(token, wat)).toBe(false); + + token = undefined; + wat = 'WAT_VALUE'; + expect(isAuthTokenPending(token, wat)).toBe(false); + }); + }); }); diff --git a/packages/sdk-rest-client/src/helpers.ts b/packages/sdk-rest-client/src/helpers.ts index f797586e..2c3b18ec 100644 --- a/packages/sdk-rest-client/src/helpers.ts +++ b/packages/sdk-rest-client/src/helpers.ts @@ -24,3 +24,13 @@ export const addQueryParamsToUrl = (url: string, params: { [key: string]: string // replace the trailing slash if there is one return urlObject.toString().replace(/\/([?&])/, '$1'); }; + +/** + * Checks if API token or WAT token is pending (e.g., being generated) + * @param token - API token + * @param wat - WAT token + * @returns true if the token is pending + */ +export const isAuthTokenPending = (token?: string | null, wat?: string | null): boolean => { + return token === null || wat === null; +}; diff --git a/packages/sdk-rest-client/src/index.ts b/packages/sdk-rest-client/src/index.ts index db623c53..170da034 100644 --- a/packages/sdk-rest-client/src/index.ts +++ b/packages/sdk-rest-client/src/index.ts @@ -7,4 +7,6 @@ export { BearerAuthenticator, isBearerAuthenticator } from './bearer-authenticat export { WatAuthenticator, isWatAuthenticator } from './wat-authenticator.js'; export { getAuthenticator } from './authenticator.js'; +export { isAuthTokenPending } from './helpers.js'; + export { HttpClient } from './http-client.js'; diff --git a/packages/sdk-tracking/package.json b/packages/sdk-tracking/package.json index d47e21fd..74bb1858 100644 --- a/packages/sdk-tracking/package.json +++ b/packages/sdk-tracking/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": { ".": "./dist/index.js" diff --git a/packages/sdk-tracking/src/index.ts b/packages/sdk-tracking/src/index.ts index 7c59804f..fda9fbec 100644 --- a/packages/sdk-tracking/src/index.ts +++ b/packages/sdk-tracking/src/index.ts @@ -1 +1,2 @@ export * from './tracking.js'; +export * from './registry.js'; diff --git a/packages/sdk-tracking/src/registry.ts b/packages/sdk-tracking/src/registry.ts new file mode 100644 index 00000000..279e8bea --- /dev/null +++ b/packages/sdk-tracking/src/registry.ts @@ -0,0 +1,22 @@ +/** + * Registry of all tracking events + * + * This registry contains tracking events and their configurations. + * Each configuration specifies whether the event should be sent to the server (`internal`) + * and whether a custom tracking callback should be invoked (`external`). + * + * @internal + */ +export const eventRegistry = { + sdkComponentInit: { internal: true, external: true }, + sdkHookInit: { internal: true, external: true }, + sdkError: { internal: true, external: false }, + sdkCliExec: { internal: true, external: false }, + sdkAngularServiceMethodExecuted: { internal: true, external: true }, +}; + +/** + * Type representing each tracking action from the event registry. + * Ensures new events are registered and configured correctly. + */ +export type TrackingEventType = keyof typeof eventRegistry; diff --git a/packages/sdk-tracking/src/tracking.test.ts b/packages/sdk-tracking/src/tracking.test.ts index 4a096a5d..8d8d107a 100644 --- a/packages/sdk-tracking/src/tracking.test.ts +++ b/packages/sdk-tracking/src/tracking.test.ts @@ -1,7 +1,7 @@ import { trackCliError, trackProductEvent, trackUiError } from './tracking.js'; import { HttpClient } from '@sisense/sdk-rest-client'; -const fakeAction = 'fakeAction'; +const fakeAction = 'sdkComponentInit'; const fakeVersion = '0.0.0'; const expectedOptions = { diff --git a/packages/sdk-tracking/src/tracking.ts b/packages/sdk-tracking/src/tracking.ts index 9dd0021a..0788a7b5 100644 --- a/packages/sdk-tracking/src/tracking.ts +++ b/packages/sdk-tracking/src/tracking.ts @@ -1,13 +1,14 @@ /* eslint-disable max-params */ import { HttpClient } from '@sisense/sdk-rest-client'; +import { TrackingEventType } from './registry.js'; const TRACKING_CATEGORY = 'composesdk'; -export type TrackingDetails = Record; +export type TrackingEventDetails = Record; export const trackProductEvent = ( - action: string, - details: TrackingDetails, + action: TrackingEventType, + details: TrackingEventDetails, httpClient: HttpClient, isDebugMode = false, ) => { diff --git a/packages/sdk-ui-angular/package.json b/packages/sdk-ui-angular/package.json index ca888211..39aaae94 100644 --- a/packages/sdk-ui-angular/package.json +++ b/packages/sdk-ui-angular/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "author": "Sisense", "license": "SEE LICENSE IN LICENSE.md", "main": "dist", diff --git a/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.test.ts b/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.test.ts index bcbf273a..343244da 100644 --- a/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.test.ts +++ b/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.test.ts @@ -26,8 +26,12 @@ const createContextProviderRendererMock = createContextProviderRenderer as Mock< describe('createSisenseContextConnector', () => { const sisenseContextConfigMock = { - enableTracking: true, showRuntimeErrors: false, + appConfig: { + trackingConfig: { + enabled: true, + }, + }, }; const appMock = {}; let sisenseContextService: Mocked; @@ -57,7 +61,7 @@ describe('createSisenseContextConnector', () => { isInitialized: true, showRuntimeErrors: sisenseContextConfigMock.showRuntimeErrors, tracking: { - enabled: sisenseContextConfigMock.enableTracking, + enabled: true, packageName: 'sdk-ui-angular', }, }); diff --git a/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.ts b/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.ts index 6d16fc2d..793625be 100644 --- a/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.ts +++ b/packages/sdk-ui-angular/src/lib/component-wrapper-helpers/context-connectors.ts @@ -43,15 +43,19 @@ export const createSisenseContextConnector = ( ): ContextConnector => { return { async prepareContext() { - const { enableTracking, showRuntimeErrors } = sisenseContextService.getConfig(); + const { enableTracking, showRuntimeErrors, appConfig } = sisenseContextService.getConfig(); const app = await sisenseContextService.getApp(); - return { app, isInitialized: true, showRuntimeErrors, tracking: { - enabled: enableTracking, + // if tracking is configured in appConfig, use it, otherwise use enableTracking + // if none is set, default to true + enabled: + appConfig?.trackingConfig?.enabled !== undefined + ? appConfig.trackingConfig.enabled + : enableTracking ?? true, packageName: 'sdk-ui-angular', }, } as CustomSisenseContext; diff --git a/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard-by-id.component.ts b/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard-by-id.component.ts index 3f164427..75f131e3 100644 --- a/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard-by-id.component.ts +++ b/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard-by-id.component.ts @@ -46,7 +46,7 @@ import { template, rootId } from '../../component-wrapper-helpers/template'; * ``` * @group Fusion Embed * @fusionEmbed - * @internal + * @alpha */ @Component({ selector: 'csdk-dashboard-by-id', diff --git a/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard.component.ts b/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard.component.ts index c48778aa..f67dc965 100644 --- a/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard.component.ts +++ b/packages/sdk-ui-angular/src/lib/components/dashboard/dashboard.component.ts @@ -22,7 +22,7 @@ import { import { template, rootId } from '../../component-wrapper-helpers/template'; /** - * An Angular component used for easily rendering a dashboard. + * An Angular component used for easily rendering a dashboard created in Sisense Fusion. * * **Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. * @@ -59,7 +59,7 @@ import { template, rootId } from '../../component-wrapper-helpers/template'; * ``` * @group Fusion Embed * @fusionEmbed - * @internal + * @alpha */ @Component({ selector: 'csdk-dashboard', diff --git a/packages/sdk-ui-angular/src/lib/decorators/trackable.decorator.ts b/packages/sdk-ui-angular/src/lib/decorators/trackable.decorator.ts index 1fcedf44..ba4694f6 100644 --- a/packages/sdk-ui-angular/src/lib/decorators/trackable.decorator.ts +++ b/packages/sdk-ui-angular/src/lib/decorators/trackable.decorator.ts @@ -1,6 +1,7 @@ import { DecoratorsModule } from './decorators.module'; import { trackProductEvent } from '@sisense/sdk-tracking'; import packageVersion from '../../version'; +import { TrackingEventType } from '@sisense/sdk-tracking/src/registry'; export function Trackable(target: unknown, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; @@ -39,11 +40,14 @@ export function TrackableService(trackableMethods: MethodsArray) { }; } -async function track(action: string, methodName: string) { +async function track(action: TrackingEventType, methodName: string) { try { const { enableTracking } = DecoratorsModule.sisenseContextService.getConfig(); const app = await DecoratorsModule.sisenseContextService.getApp(); + const trackingEnabled = + enableTracking && (app.settings?.trackingConfig?.enabled ?? enableTracking); + if (app?.httpClient) { const payload = { packageName: 'sdk-ui-angular', @@ -51,7 +55,7 @@ async function track(action: string, methodName: string) { methodName, }; - void trackProductEvent(action, payload, app.httpClient, !enableTracking); + void trackProductEvent(action, payload, app.httpClient, !trackingEnabled); } } catch (e) { console.warn('tracking error', e); diff --git a/packages/sdk-ui-angular/src/lib/services/sisense-context.service.test.ts b/packages/sdk-ui-angular/src/lib/services/sisense-context.service.test.ts index 4cade513..f0aeccb7 100644 --- a/packages/sdk-ui-angular/src/lib/services/sisense-context.service.test.ts +++ b/packages/sdk-ui-angular/src/lib/services/sisense-context.service.test.ts @@ -51,7 +51,6 @@ describe('SisenseContextService', () => { expect(config).toEqual({ ...sisenseConfigMock, - enableTracking: true, showRuntimeErrors: true, }); }); diff --git a/packages/sdk-ui-angular/src/lib/services/sisense-context.service.ts b/packages/sdk-ui-angular/src/lib/services/sisense-context.service.ts index 90797d76..d470cef7 100644 --- a/packages/sdk-ui-angular/src/lib/services/sisense-context.service.ts +++ b/packages/sdk-ui-angular/src/lib/services/sisense-context.service.ts @@ -51,10 +51,9 @@ export class SisenseContextService { constructor(@Inject(SISENSE_CONTEXT_CONFIG_TOKEN) sisenseContextConfig: SisenseContextConfig) { this.appPromise = createClientApplication(sisenseContextConfig); - const { enableTracking, showRuntimeErrors } = sisenseContextConfig; + const { showRuntimeErrors } = sisenseContextConfig; this.config = { ...sisenseContextConfig, - enableTracking: enableTracking ?? true, showRuntimeErrors: showRuntimeErrors ?? true, }; } diff --git a/packages/sdk-ui-angular/typedoc.config.cjs b/packages/sdk-ui-angular/typedoc.config.cjs index 9e6736d3..f7bc47a8 100644 --- a/packages/sdk-ui-angular/typedoc.config.cjs +++ b/packages/sdk-ui-angular/typedoc.config.cjs @@ -5,4 +5,5 @@ module.exports = { ...baseConfig, entryPoints: ['src/public-api.ts'], intentionallyNotExported: ['ArgumentsAsObject'], + excludeCategories: ['Sisense App Error Handling'], // feature not supported yet in Angular }; diff --git a/packages/sdk-ui-preact/package.json b/packages/sdk-ui-preact/package.json index b274d6aa..4a6ec17a 100644 --- a/packages/sdk-ui-preact/package.json +++ b/packages/sdk-ui-preact/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": { ".": { @@ -25,7 +25,7 @@ "author": "Sisense", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@sisense/sdk-ui": "^1.16.0", + "@sisense/sdk-ui": "^1.17.0", "preact": "^10.13.2" }, "scripts": { diff --git a/packages/sdk-ui-vue/package.json b/packages/sdk-ui-vue/package.json index efca3770..62d0c1ce 100644 --- a/packages/sdk-ui-vue/package.json +++ b/packages/sdk-ui-vue/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.js", diff --git a/packages/sdk-ui-vue/src/components/dashboard/dashboard-by-id.ts b/packages/sdk-ui-vue/src/components/dashboard/dashboard-by-id.ts index 7dee1094..5f582f09 100644 --- a/packages/sdk-ui-vue/src/components/dashboard/dashboard-by-id.ts +++ b/packages/sdk-ui-vue/src/components/dashboard/dashboard-by-id.ts @@ -26,7 +26,7 @@ import { setupHelper } from '../../setup-helper'; * ``` * @group Fusion Embed * @fusionEmbed - * @internal + * @alpha */ export const DashboardById = defineComponent({ props: { diff --git a/packages/sdk-ui-vue/src/components/dashboard/dashboard.ts b/packages/sdk-ui-vue/src/components/dashboard/dashboard.ts index cc1ce379..17ad300a 100644 --- a/packages/sdk-ui-vue/src/components/dashboard/dashboard.ts +++ b/packages/sdk-ui-vue/src/components/dashboard/dashboard.ts @@ -35,7 +35,7 @@ import { setupHelper } from '../../setup-helper'; * ``` * @group Fusion Embed * @fusionEmbed - * @internal + * @alpha */ export const Dashboard = defineComponent({ props: { diff --git a/packages/sdk-ui-vue/src/providers/sisense-context-provider.ts b/packages/sdk-ui-vue/src/providers/sisense-context-provider.ts index 34dddd62..c58872a4 100644 --- a/packages/sdk-ui-vue/src/providers/sisense-context-provider.ts +++ b/packages/sdk-ui-vue/src/providers/sisense-context-provider.ts @@ -59,8 +59,6 @@ export const createSisenseContextConnector = (context: CustomSisenseContext) => * :token="authToken" * :wat="watToken" * :appConfig="appConfigurations" - * :showRuntimeErrors="true" - * :enableTracking="false" * > * * @@ -150,7 +148,9 @@ export const SisenseContextProvider = defineComponent({ showRuntimeErrors: props.showRuntimeErrors!, tracking: { ...defaultSisenseContext.tracking, - enabled: props.enableTracking!, + enabled: + props.enableTracking! && + (props.appConfig?.trackingConfig?.enabled ?? props.enableTracking), }, }); createClientApplication(props as SisenseContextProviderProps).then((newApp) => { diff --git a/packages/sdk-ui-vue/src/providers/theme-provider.ts b/packages/sdk-ui-vue/src/providers/theme-provider.ts index bbb75b3c..05b0a9ad 100644 --- a/packages/sdk-ui-vue/src/providers/theme-provider.ts +++ b/packages/sdk-ui-vue/src/providers/theme-provider.ts @@ -114,10 +114,11 @@ export const ThemeProvider = defineComponent({ const themeSettings = ref(); const context = getSisenseContext(); if (propTheme && typeof propTheme === 'object') { - themeSettings.value = { - ...getDefaultThemeSettings(), - ...(propTheme as ThemeProviderProps), - }; + themeSettings.value = merge.withOptions( + { mergeArrays: false }, + getDefaultThemeSettings(), + propTheme, + ) as CompleteThemeSettings; } watchEffect(async () => { const { app } = context.value; diff --git a/packages/sdk-ui-vue/typedoc.config.cjs b/packages/sdk-ui-vue/typedoc.config.cjs index 8b635b4a..66c44458 100644 --- a/packages/sdk-ui-vue/typedoc.config.cjs +++ b/packages/sdk-ui-vue/typedoc.config.cjs @@ -4,4 +4,5 @@ const baseConfig = require('../../typedoc.package.config.cjs'); module.exports = { ...baseConfig, entryPoints: ['src/index-typedoc.ts'], + excludeCategories: ['Sisense App Error Handling'], // feature not supported yet in Vue }; diff --git a/packages/sdk-ui/package.json b/packages/sdk-ui/package.json index ebb73b34..6290101a 100644 --- a/packages/sdk-ui/package.json +++ b/packages/sdk-ui/package.json @@ -11,7 +11,7 @@ "Sisense", "Compose SDK" ], - "version": "1.16.0", + "version": "1.17.0", "type": "module", "exports": { ".": { @@ -53,12 +53,12 @@ "@emotion/styled": "^11.10.5", "@mui/material": "^5.15.16", "@mui/system": "^5.15.15", - "@sisense/sdk-common": "^1.16.0", - "@sisense/sdk-data": "^1.16.0", - "@sisense/sdk-pivot-client": "^1.16.0", - "@sisense/sdk-query-client": "^1.16.0", - "@sisense/sdk-rest-client": "^1.16.0", - "@sisense/sdk-tracking": "^1.16.0", + "@sisense/sdk-common": "^1.17.0", + "@sisense/sdk-data": "^1.17.0", + "@sisense/sdk-pivot-client": "^1.17.0", + "@sisense/sdk-query-client": "^1.17.0", + "@sisense/sdk-rest-client": "^1.17.0", + "@sisense/sdk-tracking": "^1.17.0", "@sisense/sisense-charts": "5.1.1", "@tanstack/react-query": "4.36.1", "classnames": "^2.3.2", @@ -109,7 +109,6 @@ "@babel/preset-env": "^7.20.2", "@mui/icons-material": "^5.14.9", "@mui/x-data-grid": "^6.16.0", - "@mui/x-data-grid-pro": "^6.16.0", "@storybook/addon-actions": "7.0.24", "@storybook/addon-docs": "7.0.24", "@storybook/addon-essentials": "7.0.24", diff --git a/packages/sdk-ui/src/__snapshots__/sunburst-chart.test.tsx.snap b/packages/sdk-ui/src/__snapshots__/sunburst-chart.test.tsx.snap index 03d20e05..6d416a92 100644 --- a/packages/sdk-ui/src/__snapshots__/sunburst-chart.test.tsx.snap +++ b/packages/sdk-ui/src/__snapshots__/sunburst-chart.test.tsx.snap @@ -100,202 +100,202 @@ exports[`Sunburst Chart > render a sunburst with single category 1`] = ` "name": "Quantity", }, { - "color": "#00cee6", + "color": "rgb(10.196% 90.588% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 8103, + "value": 936, "xCompareValue": [ - 1230768000000, + 1514764800000, ], "xDisplayValue": [ - "2009", + "2018", ], "xValue": [ - "2009-01-01T00:00:00.000Z", + "2018-01-01T00:00:00.000Z", ], }, - "name": "2009", + "name": "2018", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 8103, + "value": 936, }, { - "color": "#00b9cf", + "color": "rgb(8.8898% 86.166% 95.225%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 6814, + "value": 2045, "xCompareValue": [ - 1262304000000, + 1356998400000, ], "xDisplayValue": [ - "2010", + "2013", ], "xValue": [ - "2010-01-01T00:00:00.000Z", + "2013-01-01T00:00:00.000Z", ], }, - "name": "2010", + "name": "2013", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 6814, + "value": 2045, }, { - "color": "#00a5b8", + "color": "rgb(7.5634% 81.786% 90.495%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 3056, + "value": 3010, "xCompareValue": [ - 1293840000000, + 1388534400000, ], "xDisplayValue": [ - "2011", + "2014", ], "xValue": [ - "2011-01-01T00:00:00.000Z", + "2014-01-01T00:00:00.000Z", ], }, - "name": "2011", + "name": "2014", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 3056, + "value": 3010, }, { - "color": "#0090a1", + "color": "rgb(6.2054% 77.449% 85.811%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 8423, + "value": 3056, "xCompareValue": [ - 1325376000000, + 1293840000000, ], "xDisplayValue": [ - "2012", + "2011", ], "xValue": [ - "2012-01-01T00:00:00.000Z", + "2011-01-01T00:00:00.000Z", ], }, - "name": "2012", + "name": "2011", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 8423, + "value": 3056, }, { - "color": "#007c8a", + "color": "rgb(4.797% 73.157% 81.175%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 2045, + "value": 4242, "xCompareValue": [ - 1356998400000, + 1451606400000, ], "xDisplayValue": [ - "2013", + "2016", ], "xValue": [ - "2013-01-01T00:00:00.000Z", + "2016-01-01T00:00:00.000Z", ], }, - "name": "2013", + "name": "2016", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 2045, + "value": 4242, }, { - "color": "#006773", + "color": "rgb(3.3319% 68.912% 76.588%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 3010, + "value": 5447, "xCompareValue": [ - 1388534400000, + 1420070400000, ], "xDisplayValue": [ - "2014", + "2015", ], "xValue": [ - "2014-01-01T00:00:00.000Z", + "2015-01-01T00:00:00.000Z", ], }, - "name": "2014", + "name": "2015", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 3010, + "value": 5447, }, { - "color": "#00525c", + "color": "rgb(2.0254% 64.715% 72.051%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 5447, + "value": 6814, "xCompareValue": [ - 1420070400000, + 1262304000000, ], "xDisplayValue": [ - "2015", + "2010", ], "xValue": [ - "2015-01-01T00:00:00.000Z", + "2010-01-01T00:00:00.000Z", ], }, - "name": "2015", + "name": "2010", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 5447, + "value": 6814, }, { - "color": "#003e45", + "color": "rgb(0.9193% 60.567% 67.567%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 4242, + "value": 8103, "xCompareValue": [ - 1451606400000, + 1230768000000, ], "xDisplayValue": [ - "2016", + "2009", ], "xValue": [ - "2016-01-01T00:00:00.000Z", + "2009-01-01T00:00:00.000Z", ], }, - "name": "2016", + "name": "2009", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 4242, + "value": 8103, }, { - "color": "#00292e", + "color": "rgb(0% 56.471% 63.137%)", "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, - "value": 936, + "value": 8423, "xCompareValue": [ - 1514764800000, + 1325376000000, ], "xDisplayValue": [ - "2018", + "2012", ], "xValue": [ - "2018-01-01T00:00:00.000Z", + "2012-01-01T00:00:00.000Z", ], }, - "name": "2018", + "name": "2012", "parent": "SUNBURST_ROOT_PARENT_ID", - "value": 936, + "value": 8423, }, ], "dataLabels": { @@ -314,8 +314,8 @@ exports[`Sunburst Chart > render a sunburst with single category 1`] = ` }, "level": 1, "levelSize": { - "unit": "pixels", - "value": 60, + "unit": "percentage", + "value": 80, }, }, { @@ -328,6 +328,7 @@ exports[`Sunburst Chart > render a sunburst with single category 1`] = ` ], "name": "Root", "showInLegend": false, + "turboThreshold": 2000, "type": "sunburst", }, { @@ -463,99 +464,108 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "name": "Quantity", }, { - "color": "#00cee6", + "color": "rgb(10.196% 90.588% 100%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 936, }, - "id": "2009-01-01T00:00:00.000Z", - "name": "2009", + "id": "2018-01-01T00:00:00.000Z", + "name": "2018", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00b9cf", + "color": "rgb(8.8898% 86.166% 95.225%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 2045, }, - "id": "2010-01-01T00:00:00.000Z", - "name": "2010", + "id": "2013-01-01T00:00:00.000Z", + "name": "2013", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00a5b8", + "color": "rgb(7.5634% 81.786% 90.495%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 3010, }, - "id": "2011-01-01T00:00:00.000Z", - "name": "2011", + "id": "2014-01-01T00:00:00.000Z", + "name": "2014", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#0090a1", + "color": "rgb(6.2054% 77.449% 85.811%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 3056, }, - "id": "2012-01-01T00:00:00.000Z", - "name": "2012", + "id": "2011-01-01T00:00:00.000Z", + "name": "2011", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#007c8a", + "color": "rgb(4.797% 73.157% 81.175%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 4242, }, - "id": "2013-01-01T00:00:00.000Z", - "name": "2013", + "id": "2016-01-01T00:00:00.000Z", + "name": "2016", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#006773", + "color": "rgb(3.3319% 68.912% 76.588%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 5447, }, - "id": "2014-01-01T00:00:00.000Z", - "name": "2014", + "id": "2015-01-01T00:00:00.000Z", + "name": "2015", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00525c", + "color": "rgb(2.0254% 64.715% 72.051%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 6814, }, - "id": "2015-01-01T00:00:00.000Z", - "name": "2015", + "id": "2010-01-01T00:00:00.000Z", + "name": "2010", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#003e45", + "color": "rgb(0.9193% 60.567% 67.567%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 8103, }, - "id": "2016-01-01T00:00:00.000Z", - "name": "2016", + "id": "2009-01-01T00:00:00.000Z", + "name": "2009", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00292e", + "color": "rgb(0% 56.471% 63.137%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 8423, }, - "id": "2018-01-01T00:00:00.000Z", - "name": "2018", + "id": "2012-01-01T00:00:00.000Z", + "name": "2012", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -578,9 +588,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 8103, }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -603,9 +613,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 6814, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -628,9 +638,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 3056, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -653,9 +663,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 8423, }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -678,9 +688,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 2045, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -703,9 +713,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 3010, }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -728,9 +738,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 5447, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -753,9 +763,9 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` "value": 4242, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -794,8 +804,8 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` }, "level": 1, "levelSize": { - "unit": "pixels", - "value": 60, + "unit": "percentage", + "value": 70, }, }, { @@ -815,6 +825,7 @@ exports[`Sunburst Chart > render a sunburst with two categories 1`] = ` ], "name": "Root", "showInLegend": false, + "turboThreshold": 2000, "type": "sunburst", }, { @@ -961,99 +972,108 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "name": "Quantity", }, { - "color": "#00cee6", + "color": "rgb(10.196% 90.588% 100%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 936, }, - "id": "2009-01-01T00:00:00.000Z", - "name": "2009", + "id": "2018-01-01T00:00:00.000Z", + "name": "2018", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00b9cf", + "color": "rgb(8.8898% 86.166% 95.225%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 2045, }, - "id": "2010-01-01T00:00:00.000Z", - "name": "2010", + "id": "2013-01-01T00:00:00.000Z", + "name": "2013", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00a5b8", + "color": "rgb(7.5634% 81.786% 90.495%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 3010, }, - "id": "2011-01-01T00:00:00.000Z", - "name": "2011", + "id": "2014-01-01T00:00:00.000Z", + "name": "2014", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#0090a1", + "color": "rgb(6.2054% 77.449% 85.811%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 3056, }, - "id": "2012-01-01T00:00:00.000Z", - "name": "2012", + "id": "2011-01-01T00:00:00.000Z", + "name": "2011", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#007c8a", + "color": "rgb(4.797% 73.157% 81.175%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 4242, }, - "id": "2013-01-01T00:00:00.000Z", - "name": "2013", + "id": "2016-01-01T00:00:00.000Z", + "name": "2016", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#006773", + "color": "rgb(3.3319% 68.912% 76.588%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 5447, }, - "id": "2014-01-01T00:00:00.000Z", - "name": "2014", + "id": "2015-01-01T00:00:00.000Z", + "name": "2015", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00525c", + "color": "rgb(2.0254% 64.715% 72.051%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 6814, }, - "id": "2015-01-01T00:00:00.000Z", - "name": "2015", + "id": "2010-01-01T00:00:00.000Z", + "name": "2010", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#003e45", + "color": "rgb(0.9193% 60.567% 67.567%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 8103, }, - "id": "2016-01-01T00:00:00.000Z", - "name": "2016", + "id": "2009-01-01T00:00:00.000Z", + "name": "2009", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#00292e", + "color": "rgb(0% 56.471% 63.137%)", "custom": { "level": 1, "levelsCount": 2, + "subtotalValue": 8423, }, - "id": "2018-01-01T00:00:00.000Z", - "name": "2018", + "id": "2012-01-01T00:00:00.000Z", + "name": "2012", "parent": "SUNBURST_ROOT_PARENT_ID", }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1076,9 +1096,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 8103, }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1101,9 +1121,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 6814, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1126,9 +1146,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 3056, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1151,9 +1171,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 8423, }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1176,9 +1196,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 2045, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1201,9 +1221,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 3010, }, { - "color": "#9b9bd7", + "color": "rgb(42.353% 42.353% 59.216%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1226,9 +1246,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 5447, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1251,9 +1271,9 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = "value": 4242, }, { - "color": "#9b9bd7", + "color": "rgb(77.647% 77.647% 100%)", "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -1292,8 +1312,8 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = }, "level": 1, "levelSize": { - "unit": "pixels", - "value": 60, + "unit": "percentage", + "value": 70, }, }, { @@ -1313,6 +1333,7 @@ exports[`Sunburst Chart > render a sunburst with two categories and legend 1`] = ], "name": "Root", "showInLegend": false, + "turboThreshold": 2000, "type": "sunburst", }, { diff --git a/packages/sdk-ui/src/__snapshots__/treemap-chart.test.tsx.snap b/packages/sdk-ui/src/__snapshots__/treemap-chart.test.tsx.snap index 10a97d06..7929e0c1 100644 --- a/packages/sdk-ui/src/__snapshots__/treemap-chart.test.tsx.snap +++ b/packages/sdk-ui/src/__snapshots__/treemap-chart.test.tsx.snap @@ -247,7 +247,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -274,7 +274,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -301,7 +301,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -328,7 +328,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -355,7 +355,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -382,7 +382,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -409,7 +409,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -436,7 +436,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -463,7 +463,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -490,7 +490,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -517,7 +517,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -544,7 +544,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -571,7 +571,7 @@ exports[`Treemap Chart > render a treemap with coloring 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1034,7 +1034,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1088,7 +1088,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1142,7 +1142,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1196,7 +1196,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1223,7 +1223,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1250,7 +1250,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1277,7 +1277,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1304,7 +1304,7 @@ exports[`Treemap Chart > render a treemap with highlights 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -1489,7 +1489,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` "data": [ { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1510,7 +1510,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1531,7 +1531,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1552,7 +1552,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1573,7 +1573,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1594,7 +1594,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1615,7 +1615,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1636,7 +1636,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1657,7 +1657,7 @@ exports[`Treemap Chart > render a treemap with single category 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 1, "levelsCount": 1, "rawValue": undefined, @@ -1995,7 +1995,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2022,7 +2022,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2049,7 +2049,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2076,7 +2076,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2103,7 +2103,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2130,7 +2130,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2157,7 +2157,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2184,7 +2184,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2211,7 +2211,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2238,7 +2238,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2265,7 +2265,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2292,7 +2292,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2319,7 +2319,7 @@ exports[`Treemap Chart > render a treemap with three categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 3, "levelsCount": 3, "rawValue": undefined, @@ -2585,7 +2585,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2609,7 +2609,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2633,7 +2633,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2657,7 +2657,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2681,7 +2681,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2705,7 +2705,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2729,7 +2729,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2753,7 +2753,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, @@ -2777,7 +2777,7 @@ exports[`Treemap Chart > render a treemap with two categories 1`] = ` }, { "custom": { - "blur": false, + "blur": undefined, "level": 2, "levelsCount": 2, "rawValue": undefined, diff --git a/packages/sdk-ui/src/__stories__/template.tsx b/packages/sdk-ui/src/__stories__/template.tsx index 71dfa11e..b3c8b6c6 100644 --- a/packages/sdk-ui/src/__stories__/template.tsx +++ b/packages/sdk-ui/src/__stories__/template.tsx @@ -1,14 +1,28 @@ import React from 'react'; import type { StoryFn, StoryObj, StoryContext } from '@storybook/react'; import { SisenseContextProvider } from '../sisense-context/sisense-context-provider'; +import { ThemeProvider, type ThemeSettings } from '..'; const url = import.meta.env.VITE_APP_SISENSE_URL ?? ''; const token = import.meta.env.VITE_APP_SISENSE_TOKEN; +const themeSettings = { + chart: { + animation: { + ...(import.meta.env.VITE_APP_DISABLE_ANIMATION === 'true' && { + init: { duration: 0 }, + redraw: { duration: 0 }, + }), + }, + }, +} as ThemeSettings; + const contextDecorator = { decorators: [ (Story: StoryFn) => ( - + + + ), ], diff --git a/packages/sdk-ui/src/app/client-application.ts b/packages/sdk-ui/src/app/client-application.ts index 928021c8..82e62b33 100644 --- a/packages/sdk-ui/src/app/client-application.ts +++ b/packages/sdk-ui/src/app/client-application.ts @@ -11,13 +11,14 @@ import { } from '@sisense/sdk-rest-client'; import { DimensionalQueryClient, QueryClient } from '@sisense/sdk-query-client'; import { DataSource } from '@sisense/sdk-data'; -import { SisenseContextProviderProps } from '../props'; import { DateConfig } from '../query/date-formats'; import { AppSettings, getSettings } from './settings/settings'; import { TranslatableError } from '../translation/translatable-error'; import { PivotClient } from '@sisense/sdk-pivot-client'; import { LoadingIndicatorConfig } from '../types'; import { clearExecuteQueryCache } from '@/query/execute-query'; +import { TrackingEventDetails } from '@sisense/sdk-tracking'; +import { SisenseContextProviderProps } from '@/props'; /** * Application configuration @@ -94,6 +95,24 @@ export type AppConfig = { */ alwaysShowErrorText?: boolean; }; + + /** + * Tracking configuration + */ + trackingConfig?: { + /** + * Whether to enable tracking + * + * If not specified, the default value is `true` + * + * @internal + */ + enabled?: boolean; + /** + * Callback to be invoked when tracking event occurs + */ + onTrackingEvent?: (payload: TrackingEventDetails) => void; + }; }; /** @@ -172,6 +191,11 @@ export class ClientApplication { } } +type ClientApplicationParams = Pick< + SisenseContextProviderProps, + 'appConfig' | 'defaultDataSource' | 'url' | 'token' | 'wat' | 'ssoEnabled' | 'enableSilentPreAuth' +>; + /** @internal */ export const createClientApplication = async ({ defaultDataSource, @@ -181,7 +205,7 @@ export const createClientApplication = async ({ ssoEnabled, appConfig, enableSilentPreAuth, -}: SisenseContextProviderProps): Promise => { +}: ClientApplicationParams): Promise => { if (url !== undefined) { const auth = getAuthenticator({ url, diff --git a/packages/sdk-ui/src/app/settings/settings.ts b/packages/sdk-ui/src/app/settings/settings.ts index 207cfe95..723917eb 100644 --- a/packages/sdk-ui/src/app/settings/settings.ts +++ b/packages/sdk-ui/src/app/settings/settings.ts @@ -52,6 +52,9 @@ const defaultAppConfig: Required = { errorBoundaryConfig: { alwaysShowErrorText: false, }, + trackingConfig: { + enabled: true, + }, }; /** @@ -78,6 +81,7 @@ export async function getSettings( /** * Translate Features to FeatureMap + * * @param features - Features to be mapped * @returns FeatureMap */ diff --git a/packages/sdk-ui/src/chart-data-options/types.ts b/packages/sdk-ui/src/chart-data-options/types.ts index b711ff6e..b5c9bbc9 100644 --- a/packages/sdk-ui/src/chart-data-options/types.ts +++ b/packages/sdk-ui/src/chart-data-options/types.ts @@ -74,6 +74,8 @@ export interface CategoryStyle { * @internal */ width?: number; + /** {@inheritDoc DataColorOptions} */ + color?: DataColorOptions; } /** @@ -192,11 +194,11 @@ export type SeriesStyle = { */ export type SeriesStyleOptions = { /** - * @inheritdoc LineStyleOptions.lineWidth + * @inheritdoc */ lineWidth?: LineWidth; /** - * @inheritdoc LineStyleOptions.markers + * @inheritdoc */ markers?: Markers; }; diff --git a/packages/sdk-ui/src/chart-data-processor/table-creators.ts b/packages/sdk-ui/src/chart-data-processor/table-creators.ts index f2d0fcf3..5382c7f9 100644 --- a/packages/sdk-ui/src/chart-data-processor/table-creators.ts +++ b/packages/sdk-ui/src/chart-data-processor/table-creators.ts @@ -104,7 +104,7 @@ export const createDataTableFromData = (data: Data): DataTable => { rawValue: rowValue.data, displayValue: rowValue.text ?? convertableValue, compareValue: createCompareValue(convertableValue, column.type), - ...(rowValue.blur ? { blur: rowValue.blur } : {}), + ...(rowValue.blur !== undefined ? { blur: rowValue.blur } : {}), ...(rowValue.color ? { color: rowValue.color } : {}), }; } diff --git a/packages/sdk-ui/src/chart-data-processor/table-processor.ts b/packages/sdk-ui/src/chart-data-processor/table-processor.ts index dcfefbde..a3f2e8b5 100644 --- a/packages/sdk-ui/src/chart-data-processor/table-processor.ts +++ b/packages/sdk-ui/src/chart-data-processor/table-processor.ts @@ -265,8 +265,8 @@ export const getValue = (row: Row, column: Column) => { return data.compareValue.value; }; -export const isBlurred = (row: Row, column: Column): boolean => { - return !!row[column.index]?.blur; +export const isBlurred = (row: Row, column: Column): boolean | undefined => { + return row[column.index]?.blur; }; export const getValues = (row: Row, columns: readonly Column[]): ComparableData[] => { diff --git a/packages/sdk-ui/src/chart-data/boxplot-data.ts b/packages/sdk-ui/src/chart-data/boxplot-data.ts index fdaf22d3..16a25c6d 100644 --- a/packages/sdk-ui/src/chart-data/boxplot-data.ts +++ b/packages/sdk-ui/src/chart-data/boxplot-data.ts @@ -59,7 +59,7 @@ export const boxplotData = ( // since we aggregated we know it is single number // expect one row or none const row = rows ? rows[0] : []; - const blur = xColumn && isBlurred(row, xColumn); + const blur = xColumn && !!isBlurred(row, xColumn); seriesValues.push({ q1: boxMinColumn ? (getValue(row, boxMinColumn) as number) : 0, diff --git a/packages/sdk-ui/src/chart-data/scattermap-data.ts b/packages/sdk-ui/src/chart-data/scattermap-data.ts index f00a389c..99b14090 100644 --- a/packages/sdk-ui/src/chart-data/scattermap-data.ts +++ b/packages/sdk-ui/src/chart-data/scattermap-data.ts @@ -48,7 +48,7 @@ export const scattermapData = ( }; } - const blur = locationColumns[0] && isBlurred(row, locationColumns[0]); + const blur = locationColumns[0] && !!isBlurred(row, locationColumns[0]); return { name, rawName, diff --git a/packages/sdk-ui/src/chart-data/types.ts b/packages/sdk-ui/src/chart-data/types.ts index bcc9628b..f4655258 100644 --- a/packages/sdk-ui/src/chart-data/types.ts +++ b/packages/sdk-ui/src/chart-data/types.ts @@ -110,7 +110,7 @@ export type ScattermapChartLocation = { value: number; colorValue?: number; details?: number | string[]; - blur: boolean; + blur?: boolean; coordinates?: Coordinates; }; diff --git a/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.test.ts b/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.test.ts index 7755c9fe..f1274213 100644 --- a/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.test.ts +++ b/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.test.ts @@ -1,3 +1,4 @@ +import { CompleteThemeSettings } from '..'; import { HighchartsOptionsInternal } from './chart-options-service'; import { applyCommonHighchartsOptions, @@ -8,8 +9,16 @@ import { describe('applyCommonHighchartsOptions', () => { it('should apply common options', () => { const chartOptions = {} as HighchartsOptionsInternal; + const themeSettings = { + chart: { + animation: { + init: { duration: 'auto' }, + redraw: { duration: 'auto' }, + }, + }, + } as CompleteThemeSettings; - const result = applyCommonHighchartsOptions(chartOptions, true); + const result = applyCommonHighchartsOptions(chartOptions, themeSettings, true); expect(result).toEqual({ accessibility: { enabled: true }, diff --git a/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.ts b/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.ts index e13b0b3e..724b71bf 100644 --- a/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.ts +++ b/packages/sdk-ui/src/chart-options-processor/common-highcharts-option-service.ts @@ -1,4 +1,5 @@ import merge from 'ts-deepmerge'; +import { CompleteThemeSettings } from '..'; import { HighchartsOptionsInternal } from './chart-options-service'; // Highcharts default is 1000ms @@ -12,13 +13,26 @@ export const DEFAULT_ANIMATION_DURATION_MS_UPDATE = 300; */ export const applyCommonHighchartsOptions = ( chartOptions: HighchartsOptionsInternal, + themeSettings: CompleteThemeSettings, accessibilityEnabled: boolean, ): HighchartsOptionsInternal => { + const initAnimation = { + duration: + themeSettings.chart.animation.init.duration === 'auto' + ? DEFAULT_ANIMATION_DURATION_MS_INIT + : themeSettings.chart.animation.init.duration, + }; + const updateAnimation = { + duration: + themeSettings.chart.animation.redraw.duration === 'auto' + ? DEFAULT_ANIMATION_DURATION_MS_UPDATE + : themeSettings.chart.animation.redraw.duration, + }; return merge(chartOptions, { accessibility: { enabled: accessibilityEnabled }, - chart: { animation: { duration: DEFAULT_ANIMATION_DURATION_MS_UPDATE } }, + chart: { animation: updateAnimation }, plotOptions: { - series: { animation: { duration: DEFAULT_ANIMATION_DURATION_MS_INIT } }, + series: { animation: initAnimation }, }, boost: { useGPUTranslations: true, usePreAllocated: true }, }); diff --git a/packages/sdk-ui/src/chart-options-processor/translations/legend-section.ts b/packages/sdk-ui/src/chart-options-processor/translations/legend-section.ts index 086978fd..b1c13cf5 100644 --- a/packages/sdk-ui/src/chart-options-processor/translations/legend-section.ts +++ b/packages/sdk-ui/src/chart-options-processor/translations/legend-section.ts @@ -43,6 +43,14 @@ export const getLegendSettings = (position: LegendPosition): LegendSettings => { itemStyle: legendItemStyleDefault, }; + if (!position) { + return { + enabled: false, + align: 'center', + verticalAlign: 'bottom', + layout: 'horizontal', + }; + } switch (position) { case 'bottom': return { @@ -76,12 +84,15 @@ export const getLegendSettings = (position: LegendPosition): LegendSettings => { layout: 'horizontal', ...additionalSettings, }; + // edge case when position is something like bottomright or not selected in fusion. + // eslint-disable-next-line sonarjs/no-duplicated-branches default: return { - enabled: false, + enabled: true, align: 'center', verticalAlign: 'bottom', layout: 'horizontal', + ...additionalSettings, }; } }; diff --git a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/__snapshots__/sunburst-series.test.ts.snap b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/__snapshots__/sunburst-series.test.ts.snap new file mode 100644 index 00000000..5b3a6d1c --- /dev/null +++ b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/__snapshots__/sunburst-series.test.ts.snap @@ -0,0 +1,2458 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`prepareSunburstDataItems > should prepare data items with sorting and coloring 1`] = ` +[ + { + "custom": { + "level": 0, + "levelsCount": 3, + }, + "id": "SUNBURST_ROOT_PARENT_ID", + "name": "$measure0_Total Revenue", + }, + { + "color": "rgb(10.196% 90.588% 100%)", + "custom": { + "level": 1, + "levelsCount": 3, + "subtotalValue": 1765420.5938019156, + }, + "id": "Refurbished", + "name": "Refurbished", + "parent": "SUNBURST_ROOT_PARENT_ID", + }, + { + "color": "rgb(6.6625% 78.89% 87.367%)", + "custom": { + "level": 1, + "levelsCount": 3, + "subtotalValue": 2706285.6384671647, + }, + "id": "Unspecified", + "name": "Unspecified", + "parent": "SUNBURST_ROOT_PARENT_ID", + }, + { + "color": "rgb(2.8733% 67.508% 75.07%)", + "custom": { + "level": 1, + "levelsCount": 3, + "subtotalValue": 11850787.423742265, + }, + "id": "New", + "name": "New", + "parent": "SUNBURST_ROOT_PARENT_ID", + }, + { + "color": "rgb(0% 56.471% 63.137%)", + "custom": { + "level": 1, + "levelsCount": 3, + "subtotalValue": 23437131.859015867, + }, + "id": "Used", + "name": "Used", + "parent": "SUNBURST_ROOT_PARENT_ID", + }, + { + "color": "rgb(77.647% 77.647% 100%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 419689.739569366, + }, + "id": "New_Female", + "name": "Female", + "parent": "New", + }, + { + "color": "rgb(59.538% 59.517% 79.118%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 3145290.8236471266, + }, + "id": "New_Male", + "name": "Male", + "parent": "New", + }, + { + "color": "rgb(42.353% 42.353% 59.216%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 8285806.860525772, + }, + "id": "New_Unspecified", + "name": "Unspecified", + "parent": "New", + }, + { + "color": "rgb(77.647% 77.647% 100%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 43991.970816612244, + }, + "id": "Refurbished_Female", + "name": "Female", + "parent": "Refurbished", + }, + { + "color": "rgb(59.538% 59.517% 79.118%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 750247.1492648125, + }, + "id": "Refurbished_Male", + "name": "Male", + "parent": "Refurbished", + }, + { + "color": "rgb(42.353% 42.353% 59.216%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 971181.4737204909, + }, + "id": "Refurbished_Unspecified", + "name": "Unspecified", + "parent": "Refurbished", + }, + { + "color": "rgb(77.647% 77.647% 100%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 107972.20067983866, + }, + "id": "Unspecified_Female", + "name": "Female", + "parent": "Unspecified", + }, + { + "color": "rgb(59.538% 59.517% 79.118%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 521698.6592757795, + }, + "id": "Unspecified_Male", + "name": "Male", + "parent": "Unspecified", + }, + { + "color": "rgb(42.353% 42.353% 59.216%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 2076614.7785115466, + }, + "id": "Unspecified_Unspecified", + "name": "Unspecified", + "parent": "Unspecified", + }, + { + "color": "rgb(77.647% 77.647% 100%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 358606.70924161375, + }, + "id": "Used_Female", + "name": "Female", + "parent": "Used", + }, + { + "color": "rgb(59.538% 59.517% 79.118%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 1741417.177718103, + }, + "id": "Used_Male", + "name": "Male", + "parent": "Used", + }, + { + "color": "rgb(42.353% 42.353% 59.216%)", + "custom": { + "level": 2, + "levelsCount": 3, + "subtotalValue": 21337107.97205615, + }, + "id": "Used_Unspecified", + "name": "Unspecified", + "parent": "Used", + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 27596.497920036316, + "value": 27596.497920036316, + "xCompareValue": [ + "New", + "Female", + "19-24", + ], + "xDisplayValue": [ + "New", + "Female", + "19-24", + ], + "xValue": [ + "New", + "Female", + "19-24", + ], + }, + "name": "19-24", + "parent": "New_Female", + "value": 27596.497920036316, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 39948.90218925476, + "value": 39948.90218925476, + "xCompareValue": [ + "New", + "Female", + "55-64", + ], + "xDisplayValue": [ + "New", + "Female", + "55-64", + ], + "xValue": [ + "New", + "Female", + "55-64", + ], + }, + "name": "55-64", + "parent": "New_Female", + "value": 39948.90218925476, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 45599.37947809696, + "value": 45599.37947809696, + "xCompareValue": [ + "New", + "Female", + "65+", + ], + "xDisplayValue": [ + "New", + "Female", + "65+", + ], + "xValue": [ + "New", + "Female", + "65+", + ], + }, + "name": "65+", + "parent": "New_Female", + "value": 45599.37947809696, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 45748.618012428284, + "value": 45748.618012428284, + "xCompareValue": [ + "New", + "Female", + "0-18", + ], + "xDisplayValue": [ + "New", + "Female", + "0-18", + ], + "xValue": [ + "New", + "Female", + "0-18", + ], + }, + "name": "0-18", + "parent": "New_Female", + "value": 45748.618012428284, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 78766.88491088152, + "value": 78766.88491088152, + "xCompareValue": [ + "New", + "Female", + "25-34", + ], + "xDisplayValue": [ + "New", + "Female", + "25-34", + ], + "xValue": [ + "New", + "Female", + "25-34", + ], + }, + "name": "25-34", + "parent": "New_Female", + "value": 78766.88491088152, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 87107.59865379333, + "value": 87107.59865379333, + "xCompareValue": [ + "New", + "Female", + "45-54", + ], + "xDisplayValue": [ + "New", + "Female", + "45-54", + ], + "xValue": [ + "New", + "Female", + "45-54", + ], + }, + "name": "45-54", + "parent": "New_Female", + "value": 87107.59865379333, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 94921.8584048748, + "value": 94921.8584048748, + "xCompareValue": [ + "New", + "Female", + "35-44", + ], + "xDisplayValue": [ + "New", + "Female", + "35-44", + ], + "xValue": [ + "New", + "Female", + "35-44", + ], + }, + "name": "35-44", + "parent": "New_Female", + "value": 94921.8584048748, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 66774.47116482258, + "value": 66774.47116482258, + "xCompareValue": [ + "New", + "Male", + "0-18", + ], + "xDisplayValue": [ + "New", + "Male", + "0-18", + ], + "xValue": [ + "New", + "Male", + "0-18", + ], + }, + "name": "0-18", + "parent": "New_Male", + "value": 66774.47116482258, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 184136.25476408005, + "value": 184136.25476408005, + "xCompareValue": [ + "New", + "Male", + "19-24", + ], + "xDisplayValue": [ + "New", + "Male", + "19-24", + ], + "xValue": [ + "New", + "Male", + "19-24", + ], + }, + "name": "19-24", + "parent": "New_Male", + "value": 184136.25476408005, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 313586.72774779797, + "value": 313586.72774779797, + "xCompareValue": [ + "New", + "Male", + "55-64", + ], + "xDisplayValue": [ + "New", + "Male", + "55-64", + ], + "xValue": [ + "New", + "Male", + "55-64", + ], + }, + "name": "55-64", + "parent": "New_Male", + "value": 313586.72774779797, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 564301.9120545834, + "value": 564301.9120545834, + "xCompareValue": [ + "New", + "Male", + "65+", + ], + "xDisplayValue": [ + "New", + "Male", + "65+", + ], + "xValue": [ + "New", + "Male", + "65+", + ], + }, + "name": "65+", + "parent": "New_Male", + "value": 564301.9120545834, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 632773.2976089716, + "value": 632773.2976089716, + "xCompareValue": [ + "New", + "Male", + "45-54", + ], + "xDisplayValue": [ + "New", + "Male", + "45-54", + ], + "xValue": [ + "New", + "Male", + "45-54", + ], + }, + "name": "45-54", + "parent": "New_Male", + "value": 632773.2976089716, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 678693.6441895366, + "value": 678693.6441895366, + "xCompareValue": [ + "New", + "Male", + "35-44", + ], + "xDisplayValue": [ + "New", + "Male", + "35-44", + ], + "xValue": [ + "New", + "Male", + "35-44", + ], + }, + "name": "35-44", + "parent": "New_Male", + "value": 678693.6441895366, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 705024.5161173344, + "value": 705024.5161173344, + "xCompareValue": [ + "New", + "Male", + "25-34", + ], + "xDisplayValue": [ + "New", + "Male", + "25-34", + ], + "xValue": [ + "New", + "Male", + "25-34", + ], + }, + "name": "25-34", + "parent": "New_Male", + "value": 705024.5161173344, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 533305.3476567268, + "value": 533305.3476567268, + "xCompareValue": [ + "New", + "Unspecified", + "0-18", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "0-18", + ], + "xValue": [ + "New", + "Unspecified", + "0-18", + ], + }, + "name": "0-18", + "parent": "New_Unspecified", + "value": 533305.3476567268, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 889235.4108940363, + "value": 889235.4108940363, + "xCompareValue": [ + "New", + "Unspecified", + "19-24", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "19-24", + ], + "xValue": [ + "New", + "Unspecified", + "19-24", + ], + }, + "name": "19-24", + "parent": "New_Unspecified", + "value": 889235.4108940363, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1227467.8228343725, + "value": 1227467.8228343725, + "xCompareValue": [ + "New", + "Unspecified", + "55-64", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "55-64", + ], + "xValue": [ + "New", + "Unspecified", + "55-64", + ], + }, + "name": "55-64", + "parent": "New_Unspecified", + "value": 1227467.8228343725, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1261393.4097157717, + "value": 1261393.4097157717, + "xCompareValue": [ + "New", + "Unspecified", + "65+", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "65+", + ], + "xValue": [ + "New", + "Unspecified", + "65+", + ], + }, + "name": "65+", + "parent": "New_Unspecified", + "value": 1261393.4097157717, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1394549.1675406545, + "value": 1394549.1675406545, + "xCompareValue": [ + "New", + "Unspecified", + "25-34", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "25-34", + ], + "xValue": [ + "New", + "Unspecified", + "25-34", + ], + }, + "name": "25-34", + "parent": "New_Unspecified", + "value": 1394549.1675406545, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1404554.6163387299, + "value": 1404554.6163387299, + "xCompareValue": [ + "New", + "Unspecified", + "45-54", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "45-54", + ], + "xValue": [ + "New", + "Unspecified", + "45-54", + ], + }, + "name": "45-54", + "parent": "New_Unspecified", + "value": 1404554.6163387299, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1575301.0855454803, + "value": 1575301.0855454803, + "xCompareValue": [ + "New", + "Unspecified", + "35-44", + ], + "xDisplayValue": [ + "New", + "Unspecified", + "35-44", + ], + "xValue": [ + "New", + "Unspecified", + "35-44", + ], + }, + "name": "35-44", + "parent": "New_Unspecified", + "value": 1575301.0855454803, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 984.3174343109131, + "value": 984.3174343109131, + "xCompareValue": [ + "Refurbished", + "Female", + "0-18", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "0-18", + ], + "xValue": [ + "Refurbished", + "Female", + "0-18", + ], + }, + "name": "0-18", + "parent": "Refurbished_Female", + "value": 984.3174343109131, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 2636.078229904175, + "value": 2636.078229904175, + "xCompareValue": [ + "Refurbished", + "Female", + "55-64", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "55-64", + ], + "xValue": [ + "Refurbished", + "Female", + "55-64", + ], + }, + "name": "55-64", + "parent": "Refurbished_Female", + "value": 2636.078229904175, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 4299.19865322113, + "value": 4299.19865322113, + "xCompareValue": [ + "Refurbished", + "Female", + "19-24", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "19-24", + ], + "xValue": [ + "Refurbished", + "Female", + "19-24", + ], + }, + "name": "19-24", + "parent": "Refurbished_Female", + "value": 4299.19865322113, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 6221.553029060364, + "value": 6221.553029060364, + "xCompareValue": [ + "Refurbished", + "Female", + "65+", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "65+", + ], + "xValue": [ + "Refurbished", + "Female", + "65+", + ], + }, + "name": "65+", + "parent": "Refurbished_Female", + "value": 6221.553029060364, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 7400.3009576797485, + "value": 7400.3009576797485, + "xCompareValue": [ + "Refurbished", + "Female", + "25-34", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "25-34", + ], + "xValue": [ + "Refurbished", + "Female", + "25-34", + ], + }, + "name": "25-34", + "parent": "Refurbished_Female", + "value": 7400.3009576797485, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 11107.082933425903, + "value": 11107.082933425903, + "xCompareValue": [ + "Refurbished", + "Female", + "45-54", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "45-54", + ], + "xValue": [ + "Refurbished", + "Female", + "45-54", + ], + }, + "name": "45-54", + "parent": "Refurbished_Female", + "value": 11107.082933425903, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 11343.43957901001, + "value": 11343.43957901001, + "xCompareValue": [ + "Refurbished", + "Female", + "35-44", + ], + "xDisplayValue": [ + "Refurbished", + "Female", + "35-44", + ], + "xValue": [ + "Refurbished", + "Female", + "35-44", + ], + }, + "name": "35-44", + "parent": "Refurbished_Female", + "value": 11343.43957901001, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 5416.943453788757, + "value": 5416.943453788757, + "xCompareValue": [ + "Refurbished", + "Male", + "0-18", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "0-18", + ], + "xValue": [ + "Refurbished", + "Male", + "0-18", + ], + }, + "name": "0-18", + "parent": "Refurbished_Male", + "value": 5416.943453788757, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 25564.344855308533, + "value": 25564.344855308533, + "xCompareValue": [ + "Refurbished", + "Male", + "55-64", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "55-64", + ], + "xValue": [ + "Refurbished", + "Male", + "55-64", + ], + }, + "name": "55-64", + "parent": "Refurbished_Male", + "value": 25564.344855308533, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 40999.297892570496, + "value": 40999.297892570496, + "xCompareValue": [ + "Refurbished", + "Male", + "45-54", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "45-54", + ], + "xValue": [ + "Refurbished", + "Male", + "45-54", + ], + }, + "name": "45-54", + "parent": "Refurbished_Male", + "value": 40999.297892570496, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 44167.011989593506, + "value": 44167.011989593506, + "xCompareValue": [ + "Refurbished", + "Male", + "19-24", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "19-24", + ], + "xValue": [ + "Refurbished", + "Male", + "19-24", + ], + }, + "name": "19-24", + "parent": "Refurbished_Male", + "value": 44167.011989593506, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 59862.47759819031, + "value": 59862.47759819031, + "xCompareValue": [ + "Refurbished", + "Male", + "35-44", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "35-44", + ], + "xValue": [ + "Refurbished", + "Male", + "35-44", + ], + }, + "name": "35-44", + "parent": "Refurbished_Male", + "value": 59862.47759819031, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 260291.83757686615, + "value": 260291.83757686615, + "xCompareValue": [ + "Refurbished", + "Male", + "25-34", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "25-34", + ], + "xValue": [ + "Refurbished", + "Male", + "25-34", + ], + }, + "name": "25-34", + "parent": "Refurbished_Male", + "value": 260291.83757686615, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 313945.2358984947, + "value": 313945.2358984947, + "xCompareValue": [ + "Refurbished", + "Male", + "65+", + ], + "xDisplayValue": [ + "Refurbished", + "Male", + "65+", + ], + "xValue": [ + "Refurbished", + "Male", + "65+", + ], + }, + "name": "65+", + "parent": "Refurbished_Male", + "value": 313945.2358984947, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 61958.35159444809, + "value": 61958.35159444809, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "0-18", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "0-18", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "0-18", + ], + }, + "name": "0-18", + "parent": "Refurbished_Unspecified", + "value": 61958.35159444809, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 71139.44866776466, + "value": 71139.44866776466, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "19-24", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "19-24", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "19-24", + ], + }, + "name": "19-24", + "parent": "Refurbished_Unspecified", + "value": 71139.44866776466, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 91251.19602972269, + "value": 91251.19602972269, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "55-64", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "55-64", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "55-64", + ], + }, + "name": "55-64", + "parent": "Refurbished_Unspecified", + "value": 91251.19602972269, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 151550.90334415436, + "value": 151550.90334415436, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "65+", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "65+", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "65+", + ], + }, + "name": "65+", + "parent": "Refurbished_Unspecified", + "value": 151550.90334415436, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 170414.25298833847, + "value": 170414.25298833847, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "25-34", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "25-34", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "25-34", + ], + }, + "name": "25-34", + "parent": "Refurbished_Unspecified", + "value": 170414.25298833847, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 203525.73990392685, + "value": 203525.73990392685, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "45-54", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "45-54", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "45-54", + ], + }, + "name": "45-54", + "parent": "Refurbished_Unspecified", + "value": 203525.73990392685, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 221341.5811921358, + "value": 221341.5811921358, + "xCompareValue": [ + "Refurbished", + "Unspecified", + "35-44", + ], + "xDisplayValue": [ + "Refurbished", + "Unspecified", + "35-44", + ], + "xValue": [ + "Refurbished", + "Unspecified", + "35-44", + ], + }, + "name": "35-44", + "parent": "Refurbished_Unspecified", + "value": 221341.5811921358, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1584.9101469516754, + "value": 1584.9101469516754, + "xCompareValue": [ + "Unspecified", + "Female", + "0-18", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "0-18", + ], + "xValue": [ + "Unspecified", + "Female", + "0-18", + ], + }, + "name": "0-18", + "parent": "Unspecified_Female", + "value": 1584.9101469516754, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 7824.6359939575195, + "value": 7824.6359939575195, + "xCompareValue": [ + "Unspecified", + "Female", + "19-24", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "19-24", + ], + "xValue": [ + "Unspecified", + "Female", + "19-24", + ], + }, + "name": "19-24", + "parent": "Unspecified_Female", + "value": 7824.6359939575195, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 9055.553003311157, + "value": 9055.553003311157, + "xCompareValue": [ + "Unspecified", + "Female", + "55-64", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "55-64", + ], + "xValue": [ + "Unspecified", + "Female", + "55-64", + ], + }, + "name": "55-64", + "parent": "Unspecified_Female", + "value": 9055.553003311157, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 12968.002454280853, + "value": 12968.002454280853, + "xCompareValue": [ + "Unspecified", + "Female", + "65+", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "65+", + ], + "xValue": [ + "Unspecified", + "Female", + "65+", + ], + }, + "name": "65+", + "parent": "Unspecified_Female", + "value": 12968.002454280853, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 23053.189082324505, + "value": 23053.189082324505, + "xCompareValue": [ + "Unspecified", + "Female", + "35-44", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "35-44", + ], + "xValue": [ + "Unspecified", + "Female", + "35-44", + ], + }, + "name": "35-44", + "parent": "Unspecified_Female", + "value": 23053.189082324505, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 23686.805324673653, + "value": 23686.805324673653, + "xCompareValue": [ + "Unspecified", + "Female", + "45-54", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "45-54", + ], + "xValue": [ + "Unspecified", + "Female", + "45-54", + ], + }, + "name": "45-54", + "parent": "Unspecified_Female", + "value": 23686.805324673653, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 29799.104674339294, + "value": 29799.104674339294, + "xCompareValue": [ + "Unspecified", + "Female", + "25-34", + ], + "xDisplayValue": [ + "Unspecified", + "Female", + "25-34", + ], + "xValue": [ + "Unspecified", + "Female", + "25-34", + ], + }, + "name": "25-34", + "parent": "Unspecified_Female", + "value": 29799.104674339294, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 24884.059005746618, + "value": 24884.059005746618, + "xCompareValue": [ + "Unspecified", + "Male", + "19-24", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "19-24", + ], + "xValue": [ + "Unspecified", + "Male", + "19-24", + ], + }, + "name": "19-24", + "parent": "Unspecified_Male", + "value": 24884.059005746618, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 37515.3125834465, + "value": 37515.3125834465, + "xCompareValue": [ + "Unspecified", + "Male", + "0-18", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "0-18", + ], + "xValue": [ + "Unspecified", + "Male", + "0-18", + ], + }, + "name": "0-18", + "parent": "Unspecified_Male", + "value": 37515.3125834465, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 53767.647619724274, + "value": 53767.647619724274, + "xCompareValue": [ + "Unspecified", + "Male", + "55-64", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "55-64", + ], + "xValue": [ + "Unspecified", + "Male", + "55-64", + ], + }, + "name": "55-64", + "parent": "Unspecified_Male", + "value": 53767.647619724274, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 92952.79265773296, + "value": 92952.79265773296, + "xCompareValue": [ + "Unspecified", + "Male", + "45-54", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "45-54", + ], + "xValue": [ + "Unspecified", + "Male", + "45-54", + ], + }, + "name": "45-54", + "parent": "Unspecified_Male", + "value": 92952.79265773296, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 95954.37422311306, + "value": 95954.37422311306, + "xCompareValue": [ + "Unspecified", + "Male", + "25-34", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "25-34", + ], + "xValue": [ + "Unspecified", + "Male", + "25-34", + ], + }, + "name": "25-34", + "parent": "Unspecified_Male", + "value": 95954.37422311306, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 103462.71881651878, + "value": 103462.71881651878, + "xCompareValue": [ + "Unspecified", + "Male", + "35-44", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "35-44", + ], + "xValue": [ + "Unspecified", + "Male", + "35-44", + ], + }, + "name": "35-44", + "parent": "Unspecified_Male", + "value": 103462.71881651878, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 113161.7543694973, + "value": 113161.7543694973, + "xCompareValue": [ + "Unspecified", + "Male", + "65+", + ], + "xDisplayValue": [ + "Unspecified", + "Male", + "65+", + ], + "xValue": [ + "Unspecified", + "Male", + "65+", + ], + }, + "name": "65+", + "parent": "Unspecified_Male", + "value": 113161.7543694973, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 126803.61816757917, + "value": 126803.61816757917, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "19-24", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "19-24", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "19-24", + ], + }, + "name": "19-24", + "parent": "Unspecified_Unspecified", + "value": 126803.61816757917, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 216433.62916576862, + "value": 216433.62916576862, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "0-18", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "0-18", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "0-18", + ], + }, + "name": "0-18", + "parent": "Unspecified_Unspecified", + "value": 216433.62916576862, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 251692.10088264942, + "value": 251692.10088264942, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "25-34", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "25-34", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "25-34", + ], + }, + "name": "25-34", + "parent": "Unspecified_Unspecified", + "value": 251692.10088264942, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 304048.96629595757, + "value": 304048.96629595757, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "55-64", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "55-64", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "55-64", + ], + }, + "name": "55-64", + "parent": "Unspecified_Unspecified", + "value": 304048.96629595757, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 372490.0220761895, + "value": 372490.0220761895, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "35-44", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "35-44", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "35-44", + ], + }, + "name": "35-44", + "parent": "Unspecified_Unspecified", + "value": 372490.0220761895, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 392143.8338055238, + "value": 392143.8338055238, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "65+", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "65+", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "65+", + ], + }, + "name": "65+", + "parent": "Unspecified_Unspecified", + "value": 392143.8338055238, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 413002.60811787844, + "value": 413002.60811787844, + "xCompareValue": [ + "Unspecified", + "Unspecified", + "45-54", + ], + "xDisplayValue": [ + "Unspecified", + "Unspecified", + "45-54", + ], + "xValue": [ + "Unspecified", + "Unspecified", + "45-54", + ], + }, + "name": "45-54", + "parent": "Unspecified_Unspecified", + "value": 413002.60811787844, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 11870.398762702942, + "value": 11870.398762702942, + "xCompareValue": [ + "Used", + "Female", + "0-18", + ], + "xDisplayValue": [ + "Used", + "Female", + "0-18", + ], + "xValue": [ + "Used", + "Female", + "0-18", + ], + }, + "name": "0-18", + "parent": "Used_Female", + "value": 11870.398762702942, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 39885.33868396282, + "value": 39885.33868396282, + "xCompareValue": [ + "Used", + "Female", + "55-64", + ], + "xDisplayValue": [ + "Used", + "Female", + "55-64", + ], + "xValue": [ + "Used", + "Female", + "55-64", + ], + }, + "name": "55-64", + "parent": "Used_Female", + "value": 39885.33868396282, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 45237.36557221413, + "value": 45237.36557221413, + "xCompareValue": [ + "Used", + "Female", + "19-24", + ], + "xDisplayValue": [ + "Used", + "Female", + "19-24", + ], + "xValue": [ + "Used", + "Female", + "19-24", + ], + }, + "name": "19-24", + "parent": "Used_Female", + "value": 45237.36557221413, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 53603.03658378124, + "value": 53603.03658378124, + "xCompareValue": [ + "Used", + "Female", + "25-34", + ], + "xDisplayValue": [ + "Used", + "Female", + "25-34", + ], + "xValue": [ + "Used", + "Female", + "25-34", + ], + }, + "name": "25-34", + "parent": "Used_Female", + "value": 53603.03658378124, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 60069.40814638138, + "value": 60069.40814638138, + "xCompareValue": [ + "Used", + "Female", + "65+", + ], + "xDisplayValue": [ + "Used", + "Female", + "65+", + ], + "xValue": [ + "Used", + "Female", + "65+", + ], + }, + "name": "65+", + "parent": "Used_Female", + "value": 60069.40814638138, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 62986.70472574234, + "value": 62986.70472574234, + "xCompareValue": [ + "Used", + "Female", + "35-44", + ], + "xDisplayValue": [ + "Used", + "Female", + "35-44", + ], + "xValue": [ + "Used", + "Female", + "35-44", + ], + }, + "name": "35-44", + "parent": "Used_Female", + "value": 62986.70472574234, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 84954.4567668289, + "value": 84954.4567668289, + "xCompareValue": [ + "Used", + "Female", + "45-54", + ], + "xDisplayValue": [ + "Used", + "Female", + "45-54", + ], + "xValue": [ + "Used", + "Female", + "45-54", + ], + }, + "name": "45-54", + "parent": "Used_Female", + "value": 84954.4567668289, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 75186.67847645283, + "value": 75186.67847645283, + "xCompareValue": [ + "Used", + "Male", + "0-18", + ], + "xDisplayValue": [ + "Used", + "Male", + "0-18", + ], + "xValue": [ + "Used", + "Male", + "0-18", + ], + }, + "name": "0-18", + "parent": "Used_Male", + "value": 75186.67847645283, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 187592.4942316413, + "value": 187592.4942316413, + "xCompareValue": [ + "Used", + "Male", + "19-24", + ], + "xDisplayValue": [ + "Used", + "Male", + "19-24", + ], + "xValue": [ + "Used", + "Male", + "19-24", + ], + }, + "name": "19-24", + "parent": "Used_Male", + "value": 187592.4942316413, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 221294.35766649246, + "value": 221294.35766649246, + "xCompareValue": [ + "Used", + "Male", + "55-64", + ], + "xDisplayValue": [ + "Used", + "Male", + "55-64", + ], + "xValue": [ + "Used", + "Male", + "55-64", + ], + }, + "name": "55-64", + "parent": "Used_Male", + "value": 221294.35766649246, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 282663.31431889534, + "value": 282663.31431889534, + "xCompareValue": [ + "Used", + "Male", + "65+", + ], + "xDisplayValue": [ + "Used", + "Male", + "65+", + ], + "xValue": [ + "Used", + "Male", + "65+", + ], + }, + "name": "65+", + "parent": "Used_Male", + "value": 282663.31431889534, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 311667.9457566738, + "value": 311667.9457566738, + "xCompareValue": [ + "Used", + "Male", + "25-34", + ], + "xDisplayValue": [ + "Used", + "Male", + "25-34", + ], + "xValue": [ + "Used", + "Male", + "25-34", + ], + }, + "name": "25-34", + "parent": "Used_Male", + "value": 311667.9457566738, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 313382.494027555, + "value": 313382.494027555, + "xCompareValue": [ + "Used", + "Male", + "45-54", + ], + "xDisplayValue": [ + "Used", + "Male", + "45-54", + ], + "xValue": [ + "Used", + "Male", + "45-54", + ], + }, + "name": "45-54", + "parent": "Used_Male", + "value": 313382.494027555, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 349629.8932403922, + "value": 349629.8932403922, + "xCompareValue": [ + "Used", + "Male", + "35-44", + ], + "xDisplayValue": [ + "Used", + "Male", + "35-44", + ], + "xValue": [ + "Used", + "Male", + "35-44", + ], + }, + "name": "35-44", + "parent": "Used_Male", + "value": 349629.8932403922, + }, + { + "color": "rgb(55.686% 100% 45.49%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 470974.11550295353, + "value": 470974.11550295353, + "xCompareValue": [ + "Used", + "Unspecified", + "0-18", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "0-18", + ], + "xValue": [ + "Used", + "Unspecified", + "0-18", + ], + }, + "name": "0-18", + "parent": "Used_Unspecified", + "value": 470974.11550295353, + }, + { + "color": "rgb(51.27% 93.079% 41.61%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 875408.5851053596, + "value": 875408.5851053596, + "xCompareValue": [ + "Used", + "Unspecified", + "55-64", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "55-64", + ], + "xValue": [ + "Used", + "Unspecified", + "55-64", + ], + }, + "name": "55-64", + "parent": "Used_Unspecified", + "value": 875408.5851053596, + }, + { + "color": "rgb(42.631% 79.528% 34.028%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1370253.3801133633, + "value": 1370253.3801133633, + "xCompareValue": [ + "Used", + "Unspecified", + "65+", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "65+", + ], + "xValue": [ + "Used", + "Unspecified", + "65+", + ], + }, + "name": "65+", + "parent": "Used_Unspecified", + "value": 1370253.3801133633, + }, + { + "color": "rgb(38.413% 72.907% 30.331%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 1518690.077901557, + "value": 1518690.077901557, + "xCompareValue": [ + "Used", + "Unspecified", + "25-34", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "25-34", + ], + "xValue": [ + "Used", + "Unspecified", + "25-34", + ], + }, + "name": "25-34", + "parent": "Used_Unspecified", + "value": 1518690.077901557, + }, + { + "color": "rgb(46.917% 86.254% 37.789%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 2246986.868683934, + "value": 2246986.868683934, + "xCompareValue": [ + "Used", + "Unspecified", + "19-24", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "19-24", + ], + "xValue": [ + "Used", + "Unspecified", + "19-24", + ], + }, + "name": "19-24", + "parent": "Used_Unspecified", + "value": 2246986.868683934, + }, + { + "color": "rgb(34.267% 66.396% 26.7%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 3643311.798181474, + "value": 3643311.798181474, + "xCompareValue": [ + "Used", + "Unspecified", + "45-54", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "45-54", + ], + "xValue": [ + "Used", + "Unspecified", + "45-54", + ], + }, + "name": "45-54", + "parent": "Used_Unspecified", + "value": 3643311.798181474, + }, + { + "color": "rgb(30.196% 60% 23.137%)", + "custom": { + "level": 3, + "levelsCount": 3, + "rawValue": 11211483.146567509, + "value": 11211483.146567509, + "xCompareValue": [ + "Used", + "Unspecified", + "35-44", + ], + "xDisplayValue": [ + "Used", + "Unspecified", + "35-44", + ], + "xValue": [ + "Used", + "Unspecified", + "35-44", + ], + }, + "name": "35-44", + "parent": "Used_Unspecified", + "value": 11211483.146567509, + }, +] +`; diff --git a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/mock/sunburst-series-props.ts b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/mock/sunburst-series-props.ts new file mode 100644 index 00000000..9040129b --- /dev/null +++ b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/mock/sunburst-series-props.ts @@ -0,0 +1,1301 @@ +/* eslint-disable sonarjs/no-duplicate-string */ + +export const mockedSunburstSeriesProps = { + chartData: { + xValues: [ + { + key: 'New,Female,0-18', + xValues: ['New', 'Female', '0-18'], + rawValues: ['New', 'Female', '0-18'], + compareValues: ['New', 'Female', '0-18'], + }, + { + key: 'New,Female,19-24', + xValues: ['New', 'Female', '19-24'], + rawValues: ['New', 'Female', '19-24'], + compareValues: ['New', 'Female', '19-24'], + }, + { + key: 'New,Female,25-34', + xValues: ['New', 'Female', '25-34'], + rawValues: ['New', 'Female', '25-34'], + compareValues: ['New', 'Female', '25-34'], + }, + { + key: 'New,Female,35-44', + xValues: ['New', 'Female', '35-44'], + rawValues: ['New', 'Female', '35-44'], + compareValues: ['New', 'Female', '35-44'], + }, + { + key: 'New,Female,45-54', + xValues: ['New', 'Female', '45-54'], + rawValues: ['New', 'Female', '45-54'], + compareValues: ['New', 'Female', '45-54'], + }, + { + key: 'New,Female,55-64', + xValues: ['New', 'Female', '55-64'], + rawValues: ['New', 'Female', '55-64'], + compareValues: ['New', 'Female', '55-64'], + }, + { + key: 'New,Female,65+', + xValues: ['New', 'Female', '65+'], + rawValues: ['New', 'Female', '65+'], + compareValues: ['New', 'Female', '65+'], + }, + { + key: 'New,Male,0-18', + xValues: ['New', 'Male', '0-18'], + rawValues: ['New', 'Male', '0-18'], + compareValues: ['New', 'Male', '0-18'], + }, + { + key: 'New,Male,19-24', + xValues: ['New', 'Male', '19-24'], + rawValues: ['New', 'Male', '19-24'], + compareValues: ['New', 'Male', '19-24'], + }, + { + key: 'New,Male,25-34', + xValues: ['New', 'Male', '25-34'], + rawValues: ['New', 'Male', '25-34'], + compareValues: ['New', 'Male', '25-34'], + }, + { + key: 'New,Male,35-44', + xValues: ['New', 'Male', '35-44'], + rawValues: ['New', 'Male', '35-44'], + compareValues: ['New', 'Male', '35-44'], + }, + { + key: 'New,Male,45-54', + xValues: ['New', 'Male', '45-54'], + rawValues: ['New', 'Male', '45-54'], + compareValues: ['New', 'Male', '45-54'], + }, + { + key: 'New,Male,55-64', + xValues: ['New', 'Male', '55-64'], + rawValues: ['New', 'Male', '55-64'], + compareValues: ['New', 'Male', '55-64'], + }, + { + key: 'New,Male,65+', + xValues: ['New', 'Male', '65+'], + rawValues: ['New', 'Male', '65+'], + compareValues: ['New', 'Male', '65+'], + }, + { + key: 'New,Unspecified,0-18', + xValues: ['New', 'Unspecified', '0-18'], + rawValues: ['New', 'Unspecified', '0-18'], + compareValues: ['New', 'Unspecified', '0-18'], + }, + { + key: 'New,Unspecified,19-24', + xValues: ['New', 'Unspecified', '19-24'], + rawValues: ['New', 'Unspecified', '19-24'], + compareValues: ['New', 'Unspecified', '19-24'], + }, + { + key: 'New,Unspecified,25-34', + xValues: ['New', 'Unspecified', '25-34'], + rawValues: ['New', 'Unspecified', '25-34'], + compareValues: ['New', 'Unspecified', '25-34'], + }, + { + key: 'New,Unspecified,35-44', + xValues: ['New', 'Unspecified', '35-44'], + rawValues: ['New', 'Unspecified', '35-44'], + compareValues: ['New', 'Unspecified', '35-44'], + }, + { + key: 'New,Unspecified,45-54', + xValues: ['New', 'Unspecified', '45-54'], + rawValues: ['New', 'Unspecified', '45-54'], + compareValues: ['New', 'Unspecified', '45-54'], + }, + { + key: 'New,Unspecified,55-64', + xValues: ['New', 'Unspecified', '55-64'], + rawValues: ['New', 'Unspecified', '55-64'], + compareValues: ['New', 'Unspecified', '55-64'], + }, + { + key: 'New,Unspecified,65+', + xValues: ['New', 'Unspecified', '65+'], + rawValues: ['New', 'Unspecified', '65+'], + compareValues: ['New', 'Unspecified', '65+'], + }, + { + key: 'Refurbished,Female,0-18', + xValues: ['Refurbished', 'Female', '0-18'], + rawValues: ['Refurbished', 'Female', '0-18'], + compareValues: ['Refurbished', 'Female', '0-18'], + }, + { + key: 'Refurbished,Female,19-24', + xValues: ['Refurbished', 'Female', '19-24'], + rawValues: ['Refurbished', 'Female', '19-24'], + compareValues: ['Refurbished', 'Female', '19-24'], + }, + { + key: 'Refurbished,Female,25-34', + xValues: ['Refurbished', 'Female', '25-34'], + rawValues: ['Refurbished', 'Female', '25-34'], + compareValues: ['Refurbished', 'Female', '25-34'], + }, + { + key: 'Refurbished,Female,35-44', + xValues: ['Refurbished', 'Female', '35-44'], + rawValues: ['Refurbished', 'Female', '35-44'], + compareValues: ['Refurbished', 'Female', '35-44'], + }, + { + key: 'Refurbished,Female,45-54', + xValues: ['Refurbished', 'Female', '45-54'], + rawValues: ['Refurbished', 'Female', '45-54'], + compareValues: ['Refurbished', 'Female', '45-54'], + }, + { + key: 'Refurbished,Female,55-64', + xValues: ['Refurbished', 'Female', '55-64'], + rawValues: ['Refurbished', 'Female', '55-64'], + compareValues: ['Refurbished', 'Female', '55-64'], + }, + { + key: 'Refurbished,Female,65+', + xValues: ['Refurbished', 'Female', '65+'], + rawValues: ['Refurbished', 'Female', '65+'], + compareValues: ['Refurbished', 'Female', '65+'], + }, + { + key: 'Refurbished,Male,0-18', + xValues: ['Refurbished', 'Male', '0-18'], + rawValues: ['Refurbished', 'Male', '0-18'], + compareValues: ['Refurbished', 'Male', '0-18'], + }, + { + key: 'Refurbished,Male,19-24', + xValues: ['Refurbished', 'Male', '19-24'], + rawValues: ['Refurbished', 'Male', '19-24'], + compareValues: ['Refurbished', 'Male', '19-24'], + }, + { + key: 'Refurbished,Male,25-34', + xValues: ['Refurbished', 'Male', '25-34'], + rawValues: ['Refurbished', 'Male', '25-34'], + compareValues: ['Refurbished', 'Male', '25-34'], + }, + { + key: 'Refurbished,Male,35-44', + xValues: ['Refurbished', 'Male', '35-44'], + rawValues: ['Refurbished', 'Male', '35-44'], + compareValues: ['Refurbished', 'Male', '35-44'], + }, + { + key: 'Refurbished,Male,45-54', + xValues: ['Refurbished', 'Male', '45-54'], + rawValues: ['Refurbished', 'Male', '45-54'], + compareValues: ['Refurbished', 'Male', '45-54'], + }, + { + key: 'Refurbished,Male,55-64', + xValues: ['Refurbished', 'Male', '55-64'], + rawValues: ['Refurbished', 'Male', '55-64'], + compareValues: ['Refurbished', 'Male', '55-64'], + }, + { + key: 'Refurbished,Male,65+', + xValues: ['Refurbished', 'Male', '65+'], + rawValues: ['Refurbished', 'Male', '65+'], + compareValues: ['Refurbished', 'Male', '65+'], + }, + { + key: 'Refurbished,Unspecified,0-18', + xValues: ['Refurbished', 'Unspecified', '0-18'], + rawValues: ['Refurbished', 'Unspecified', '0-18'], + compareValues: ['Refurbished', 'Unspecified', '0-18'], + }, + { + key: 'Refurbished,Unspecified,19-24', + xValues: ['Refurbished', 'Unspecified', '19-24'], + rawValues: ['Refurbished', 'Unspecified', '19-24'], + compareValues: ['Refurbished', 'Unspecified', '19-24'], + }, + { + key: 'Refurbished,Unspecified,25-34', + xValues: ['Refurbished', 'Unspecified', '25-34'], + rawValues: ['Refurbished', 'Unspecified', '25-34'], + compareValues: ['Refurbished', 'Unspecified', '25-34'], + }, + { + key: 'Refurbished,Unspecified,35-44', + xValues: ['Refurbished', 'Unspecified', '35-44'], + rawValues: ['Refurbished', 'Unspecified', '35-44'], + compareValues: ['Refurbished', 'Unspecified', '35-44'], + }, + { + key: 'Refurbished,Unspecified,45-54', + xValues: ['Refurbished', 'Unspecified', '45-54'], + rawValues: ['Refurbished', 'Unspecified', '45-54'], + compareValues: ['Refurbished', 'Unspecified', '45-54'], + }, + { + key: 'Refurbished,Unspecified,55-64', + xValues: ['Refurbished', 'Unspecified', '55-64'], + rawValues: ['Refurbished', 'Unspecified', '55-64'], + compareValues: ['Refurbished', 'Unspecified', '55-64'], + }, + { + key: 'Refurbished,Unspecified,65+', + xValues: ['Refurbished', 'Unspecified', '65+'], + rawValues: ['Refurbished', 'Unspecified', '65+'], + compareValues: ['Refurbished', 'Unspecified', '65+'], + }, + { + key: 'Unspecified,Female,0-18', + xValues: ['Unspecified', 'Female', '0-18'], + rawValues: ['Unspecified', 'Female', '0-18'], + compareValues: ['Unspecified', 'Female', '0-18'], + }, + { + key: 'Unspecified,Female,19-24', + xValues: ['Unspecified', 'Female', '19-24'], + rawValues: ['Unspecified', 'Female', '19-24'], + compareValues: ['Unspecified', 'Female', '19-24'], + }, + { + key: 'Unspecified,Female,25-34', + xValues: ['Unspecified', 'Female', '25-34'], + rawValues: ['Unspecified', 'Female', '25-34'], + compareValues: ['Unspecified', 'Female', '25-34'], + }, + { + key: 'Unspecified,Female,35-44', + xValues: ['Unspecified', 'Female', '35-44'], + rawValues: ['Unspecified', 'Female', '35-44'], + compareValues: ['Unspecified', 'Female', '35-44'], + }, + { + key: 'Unspecified,Female,45-54', + xValues: ['Unspecified', 'Female', '45-54'], + rawValues: ['Unspecified', 'Female', '45-54'], + compareValues: ['Unspecified', 'Female', '45-54'], + }, + { + key: 'Unspecified,Female,55-64', + xValues: ['Unspecified', 'Female', '55-64'], + rawValues: ['Unspecified', 'Female', '55-64'], + compareValues: ['Unspecified', 'Female', '55-64'], + }, + { + key: 'Unspecified,Female,65+', + xValues: ['Unspecified', 'Female', '65+'], + rawValues: ['Unspecified', 'Female', '65+'], + compareValues: ['Unspecified', 'Female', '65+'], + }, + { + key: 'Unspecified,Male,0-18', + xValues: ['Unspecified', 'Male', '0-18'], + rawValues: ['Unspecified', 'Male', '0-18'], + compareValues: ['Unspecified', 'Male', '0-18'], + }, + { + key: 'Unspecified,Male,19-24', + xValues: ['Unspecified', 'Male', '19-24'], + rawValues: ['Unspecified', 'Male', '19-24'], + compareValues: ['Unspecified', 'Male', '19-24'], + }, + { + key: 'Unspecified,Male,25-34', + xValues: ['Unspecified', 'Male', '25-34'], + rawValues: ['Unspecified', 'Male', '25-34'], + compareValues: ['Unspecified', 'Male', '25-34'], + }, + { + key: 'Unspecified,Male,35-44', + xValues: ['Unspecified', 'Male', '35-44'], + rawValues: ['Unspecified', 'Male', '35-44'], + compareValues: ['Unspecified', 'Male', '35-44'], + }, + { + key: 'Unspecified,Male,45-54', + xValues: ['Unspecified', 'Male', '45-54'], + rawValues: ['Unspecified', 'Male', '45-54'], + compareValues: ['Unspecified', 'Male', '45-54'], + }, + { + key: 'Unspecified,Male,55-64', + xValues: ['Unspecified', 'Male', '55-64'], + rawValues: ['Unspecified', 'Male', '55-64'], + compareValues: ['Unspecified', 'Male', '55-64'], + }, + { + key: 'Unspecified,Male,65+', + xValues: ['Unspecified', 'Male', '65+'], + rawValues: ['Unspecified', 'Male', '65+'], + compareValues: ['Unspecified', 'Male', '65+'], + }, + { + key: 'Unspecified,Unspecified,0-18', + xValues: ['Unspecified', 'Unspecified', '0-18'], + rawValues: ['Unspecified', 'Unspecified', '0-18'], + compareValues: ['Unspecified', 'Unspecified', '0-18'], + }, + { + key: 'Unspecified,Unspecified,19-24', + xValues: ['Unspecified', 'Unspecified', '19-24'], + rawValues: ['Unspecified', 'Unspecified', '19-24'], + compareValues: ['Unspecified', 'Unspecified', '19-24'], + }, + { + key: 'Unspecified,Unspecified,25-34', + xValues: ['Unspecified', 'Unspecified', '25-34'], + rawValues: ['Unspecified', 'Unspecified', '25-34'], + compareValues: ['Unspecified', 'Unspecified', '25-34'], + }, + { + key: 'Unspecified,Unspecified,35-44', + xValues: ['Unspecified', 'Unspecified', '35-44'], + rawValues: ['Unspecified', 'Unspecified', '35-44'], + compareValues: ['Unspecified', 'Unspecified', '35-44'], + }, + { + key: 'Unspecified,Unspecified,45-54', + xValues: ['Unspecified', 'Unspecified', '45-54'], + rawValues: ['Unspecified', 'Unspecified', '45-54'], + compareValues: ['Unspecified', 'Unspecified', '45-54'], + }, + { + key: 'Unspecified,Unspecified,55-64', + xValues: ['Unspecified', 'Unspecified', '55-64'], + rawValues: ['Unspecified', 'Unspecified', '55-64'], + compareValues: ['Unspecified', 'Unspecified', '55-64'], + }, + { + key: 'Unspecified,Unspecified,65+', + xValues: ['Unspecified', 'Unspecified', '65+'], + rawValues: ['Unspecified', 'Unspecified', '65+'], + compareValues: ['Unspecified', 'Unspecified', '65+'], + }, + { + key: 'Used,Female,0-18', + xValues: ['Used', 'Female', '0-18'], + rawValues: ['Used', 'Female', '0-18'], + compareValues: ['Used', 'Female', '0-18'], + }, + { + key: 'Used,Female,19-24', + xValues: ['Used', 'Female', '19-24'], + rawValues: ['Used', 'Female', '19-24'], + compareValues: ['Used', 'Female', '19-24'], + }, + { + key: 'Used,Female,25-34', + xValues: ['Used', 'Female', '25-34'], + rawValues: ['Used', 'Female', '25-34'], + compareValues: ['Used', 'Female', '25-34'], + }, + { + key: 'Used,Female,35-44', + xValues: ['Used', 'Female', '35-44'], + rawValues: ['Used', 'Female', '35-44'], + compareValues: ['Used', 'Female', '35-44'], + }, + { + key: 'Used,Female,45-54', + xValues: ['Used', 'Female', '45-54'], + rawValues: ['Used', 'Female', '45-54'], + compareValues: ['Used', 'Female', '45-54'], + }, + { + key: 'Used,Female,55-64', + xValues: ['Used', 'Female', '55-64'], + rawValues: ['Used', 'Female', '55-64'], + compareValues: ['Used', 'Female', '55-64'], + }, + { + key: 'Used,Female,65+', + xValues: ['Used', 'Female', '65+'], + rawValues: ['Used', 'Female', '65+'], + compareValues: ['Used', 'Female', '65+'], + }, + { + key: 'Used,Male,0-18', + xValues: ['Used', 'Male', '0-18'], + rawValues: ['Used', 'Male', '0-18'], + compareValues: ['Used', 'Male', '0-18'], + }, + { + key: 'Used,Male,19-24', + xValues: ['Used', 'Male', '19-24'], + rawValues: ['Used', 'Male', '19-24'], + compareValues: ['Used', 'Male', '19-24'], + }, + { + key: 'Used,Male,25-34', + xValues: ['Used', 'Male', '25-34'], + rawValues: ['Used', 'Male', '25-34'], + compareValues: ['Used', 'Male', '25-34'], + }, + { + key: 'Used,Male,35-44', + xValues: ['Used', 'Male', '35-44'], + rawValues: ['Used', 'Male', '35-44'], + compareValues: ['Used', 'Male', '35-44'], + }, + { + key: 'Used,Male,45-54', + xValues: ['Used', 'Male', '45-54'], + rawValues: ['Used', 'Male', '45-54'], + compareValues: ['Used', 'Male', '45-54'], + }, + { + key: 'Used,Male,55-64', + xValues: ['Used', 'Male', '55-64'], + rawValues: ['Used', 'Male', '55-64'], + compareValues: ['Used', 'Male', '55-64'], + }, + { + key: 'Used,Male,65+', + xValues: ['Used', 'Male', '65+'], + rawValues: ['Used', 'Male', '65+'], + compareValues: ['Used', 'Male', '65+'], + }, + { + key: 'Used,Unspecified,0-18', + xValues: ['Used', 'Unspecified', '0-18'], + rawValues: ['Used', 'Unspecified', '0-18'], + compareValues: ['Used', 'Unspecified', '0-18'], + }, + { + key: 'Used,Unspecified,19-24', + xValues: ['Used', 'Unspecified', '19-24'], + rawValues: ['Used', 'Unspecified', '19-24'], + compareValues: ['Used', 'Unspecified', '19-24'], + }, + { + key: 'Used,Unspecified,25-34', + xValues: ['Used', 'Unspecified', '25-34'], + rawValues: ['Used', 'Unspecified', '25-34'], + compareValues: ['Used', 'Unspecified', '25-34'], + }, + { + key: 'Used,Unspecified,35-44', + xValues: ['Used', 'Unspecified', '35-44'], + rawValues: ['Used', 'Unspecified', '35-44'], + compareValues: ['Used', 'Unspecified', '35-44'], + }, + { + key: 'Used,Unspecified,45-54', + xValues: ['Used', 'Unspecified', '45-54'], + rawValues: ['Used', 'Unspecified', '45-54'], + compareValues: ['Used', 'Unspecified', '45-54'], + }, + { + key: 'Used,Unspecified,55-64', + xValues: ['Used', 'Unspecified', '55-64'], + rawValues: ['Used', 'Unspecified', '55-64'], + compareValues: ['Used', 'Unspecified', '55-64'], + }, + { + key: 'Used,Unspecified,65+', + xValues: ['Used', 'Unspecified', '65+'], + rawValues: ['Used', 'Unspecified', '65+'], + compareValues: ['Used', 'Unspecified', '65+'], + }, + ], + series: [ + { + name: '$measure0_Total Revenue', + title: 'Total Revenue', + data: [ + { + rawValue: 45748.618012428284, + xValue: ['New', 'Female', '0-18'], + xDisplayValue: ['New', 'Female', '0-18'], + xCompareValue: ['New', 'Female', '0-18'], + value: 45748.618012428284, + }, + { + rawValue: 27596.497920036316, + xValue: ['New', 'Female', '19-24'], + xDisplayValue: ['New', 'Female', '19-24'], + xCompareValue: ['New', 'Female', '19-24'], + value: 27596.497920036316, + }, + { + rawValue: 78766.88491088152, + xValue: ['New', 'Female', '25-34'], + xDisplayValue: ['New', 'Female', '25-34'], + xCompareValue: ['New', 'Female', '25-34'], + value: 78766.88491088152, + }, + { + rawValue: 94921.8584048748, + xValue: ['New', 'Female', '35-44'], + xDisplayValue: ['New', 'Female', '35-44'], + xCompareValue: ['New', 'Female', '35-44'], + value: 94921.8584048748, + }, + { + rawValue: 87107.59865379333, + xValue: ['New', 'Female', '45-54'], + xDisplayValue: ['New', 'Female', '45-54'], + xCompareValue: ['New', 'Female', '45-54'], + value: 87107.59865379333, + }, + { + rawValue: 39948.90218925476, + xValue: ['New', 'Female', '55-64'], + xDisplayValue: ['New', 'Female', '55-64'], + xCompareValue: ['New', 'Female', '55-64'], + value: 39948.90218925476, + }, + { + rawValue: 45599.37947809696, + xValue: ['New', 'Female', '65+'], + xDisplayValue: ['New', 'Female', '65+'], + xCompareValue: ['New', 'Female', '65+'], + value: 45599.37947809696, + }, + { + rawValue: 66774.47116482258, + xValue: ['New', 'Male', '0-18'], + xDisplayValue: ['New', 'Male', '0-18'], + xCompareValue: ['New', 'Male', '0-18'], + value: 66774.47116482258, + }, + { + rawValue: 184136.25476408005, + xValue: ['New', 'Male', '19-24'], + xDisplayValue: ['New', 'Male', '19-24'], + xCompareValue: ['New', 'Male', '19-24'], + value: 184136.25476408005, + }, + { + rawValue: 705024.5161173344, + xValue: ['New', 'Male', '25-34'], + xDisplayValue: ['New', 'Male', '25-34'], + xCompareValue: ['New', 'Male', '25-34'], + value: 705024.5161173344, + }, + { + rawValue: 678693.6441895366, + xValue: ['New', 'Male', '35-44'], + xDisplayValue: ['New', 'Male', '35-44'], + xCompareValue: ['New', 'Male', '35-44'], + value: 678693.6441895366, + }, + { + rawValue: 632773.2976089716, + xValue: ['New', 'Male', '45-54'], + xDisplayValue: ['New', 'Male', '45-54'], + xCompareValue: ['New', 'Male', '45-54'], + value: 632773.2976089716, + }, + { + rawValue: 313586.72774779797, + xValue: ['New', 'Male', '55-64'], + xDisplayValue: ['New', 'Male', '55-64'], + xCompareValue: ['New', 'Male', '55-64'], + value: 313586.72774779797, + }, + { + rawValue: 564301.9120545834, + xValue: ['New', 'Male', '65+'], + xDisplayValue: ['New', 'Male', '65+'], + xCompareValue: ['New', 'Male', '65+'], + value: 564301.9120545834, + }, + { + rawValue: 533305.3476567268, + xValue: ['New', 'Unspecified', '0-18'], + xDisplayValue: ['New', 'Unspecified', '0-18'], + xCompareValue: ['New', 'Unspecified', '0-18'], + value: 533305.3476567268, + }, + { + rawValue: 889235.4108940363, + xValue: ['New', 'Unspecified', '19-24'], + xDisplayValue: ['New', 'Unspecified', '19-24'], + xCompareValue: ['New', 'Unspecified', '19-24'], + value: 889235.4108940363, + }, + { + rawValue: 1394549.1675406545, + xValue: ['New', 'Unspecified', '25-34'], + xDisplayValue: ['New', 'Unspecified', '25-34'], + xCompareValue: ['New', 'Unspecified', '25-34'], + value: 1394549.1675406545, + }, + { + rawValue: 1575301.0855454803, + xValue: ['New', 'Unspecified', '35-44'], + xDisplayValue: ['New', 'Unspecified', '35-44'], + xCompareValue: ['New', 'Unspecified', '35-44'], + value: 1575301.0855454803, + }, + { + rawValue: 1404554.6163387299, + xValue: ['New', 'Unspecified', '45-54'], + xDisplayValue: ['New', 'Unspecified', '45-54'], + xCompareValue: ['New', 'Unspecified', '45-54'], + value: 1404554.6163387299, + }, + { + rawValue: 1227467.8228343725, + xValue: ['New', 'Unspecified', '55-64'], + xDisplayValue: ['New', 'Unspecified', '55-64'], + xCompareValue: ['New', 'Unspecified', '55-64'], + value: 1227467.8228343725, + }, + { + rawValue: 1261393.4097157717, + xValue: ['New', 'Unspecified', '65+'], + xDisplayValue: ['New', 'Unspecified', '65+'], + xCompareValue: ['New', 'Unspecified', '65+'], + value: 1261393.4097157717, + }, + { + rawValue: 984.3174343109131, + xValue: ['Refurbished', 'Female', '0-18'], + xDisplayValue: ['Refurbished', 'Female', '0-18'], + xCompareValue: ['Refurbished', 'Female', '0-18'], + value: 984.3174343109131, + }, + { + rawValue: 4299.19865322113, + xValue: ['Refurbished', 'Female', '19-24'], + xDisplayValue: ['Refurbished', 'Female', '19-24'], + xCompareValue: ['Refurbished', 'Female', '19-24'], + value: 4299.19865322113, + }, + { + rawValue: 7400.3009576797485, + xValue: ['Refurbished', 'Female', '25-34'], + xDisplayValue: ['Refurbished', 'Female', '25-34'], + xCompareValue: ['Refurbished', 'Female', '25-34'], + value: 7400.3009576797485, + }, + { + rawValue: 11343.43957901001, + xValue: ['Refurbished', 'Female', '35-44'], + xDisplayValue: ['Refurbished', 'Female', '35-44'], + xCompareValue: ['Refurbished', 'Female', '35-44'], + value: 11343.43957901001, + }, + { + rawValue: 11107.082933425903, + xValue: ['Refurbished', 'Female', '45-54'], + xDisplayValue: ['Refurbished', 'Female', '45-54'], + xCompareValue: ['Refurbished', 'Female', '45-54'], + value: 11107.082933425903, + }, + { + rawValue: 2636.078229904175, + xValue: ['Refurbished', 'Female', '55-64'], + xDisplayValue: ['Refurbished', 'Female', '55-64'], + xCompareValue: ['Refurbished', 'Female', '55-64'], + value: 2636.078229904175, + }, + { + rawValue: 6221.553029060364, + xValue: ['Refurbished', 'Female', '65+'], + xDisplayValue: ['Refurbished', 'Female', '65+'], + xCompareValue: ['Refurbished', 'Female', '65+'], + value: 6221.553029060364, + }, + { + rawValue: 5416.943453788757, + xValue: ['Refurbished', 'Male', '0-18'], + xDisplayValue: ['Refurbished', 'Male', '0-18'], + xCompareValue: ['Refurbished', 'Male', '0-18'], + value: 5416.943453788757, + }, + { + rawValue: 44167.011989593506, + xValue: ['Refurbished', 'Male', '19-24'], + xDisplayValue: ['Refurbished', 'Male', '19-24'], + xCompareValue: ['Refurbished', 'Male', '19-24'], + value: 44167.011989593506, + }, + { + rawValue: 260291.83757686615, + xValue: ['Refurbished', 'Male', '25-34'], + xDisplayValue: ['Refurbished', 'Male', '25-34'], + xCompareValue: ['Refurbished', 'Male', '25-34'], + value: 260291.83757686615, + }, + { + rawValue: 59862.47759819031, + xValue: ['Refurbished', 'Male', '35-44'], + xDisplayValue: ['Refurbished', 'Male', '35-44'], + xCompareValue: ['Refurbished', 'Male', '35-44'], + value: 59862.47759819031, + }, + { + rawValue: 40999.297892570496, + xValue: ['Refurbished', 'Male', '45-54'], + xDisplayValue: ['Refurbished', 'Male', '45-54'], + xCompareValue: ['Refurbished', 'Male', '45-54'], + value: 40999.297892570496, + }, + { + rawValue: 25564.344855308533, + xValue: ['Refurbished', 'Male', '55-64'], + xDisplayValue: ['Refurbished', 'Male', '55-64'], + xCompareValue: ['Refurbished', 'Male', '55-64'], + value: 25564.344855308533, + }, + { + rawValue: 313945.2358984947, + xValue: ['Refurbished', 'Male', '65+'], + xDisplayValue: ['Refurbished', 'Male', '65+'], + xCompareValue: ['Refurbished', 'Male', '65+'], + value: 313945.2358984947, + }, + { + rawValue: 61958.35159444809, + xValue: ['Refurbished', 'Unspecified', '0-18'], + xDisplayValue: ['Refurbished', 'Unspecified', '0-18'], + xCompareValue: ['Refurbished', 'Unspecified', '0-18'], + value: 61958.35159444809, + }, + { + rawValue: 71139.44866776466, + xValue: ['Refurbished', 'Unspecified', '19-24'], + xDisplayValue: ['Refurbished', 'Unspecified', '19-24'], + xCompareValue: ['Refurbished', 'Unspecified', '19-24'], + value: 71139.44866776466, + }, + { + rawValue: 170414.25298833847, + xValue: ['Refurbished', 'Unspecified', '25-34'], + xDisplayValue: ['Refurbished', 'Unspecified', '25-34'], + xCompareValue: ['Refurbished', 'Unspecified', '25-34'], + value: 170414.25298833847, + }, + { + rawValue: 221341.5811921358, + xValue: ['Refurbished', 'Unspecified', '35-44'], + xDisplayValue: ['Refurbished', 'Unspecified', '35-44'], + xCompareValue: ['Refurbished', 'Unspecified', '35-44'], + value: 221341.5811921358, + }, + { + rawValue: 203525.73990392685, + xValue: ['Refurbished', 'Unspecified', '45-54'], + xDisplayValue: ['Refurbished', 'Unspecified', '45-54'], + xCompareValue: ['Refurbished', 'Unspecified', '45-54'], + value: 203525.73990392685, + }, + { + rawValue: 91251.19602972269, + xValue: ['Refurbished', 'Unspecified', '55-64'], + xDisplayValue: ['Refurbished', 'Unspecified', '55-64'], + xCompareValue: ['Refurbished', 'Unspecified', '55-64'], + value: 91251.19602972269, + }, + { + rawValue: 151550.90334415436, + xValue: ['Refurbished', 'Unspecified', '65+'], + xDisplayValue: ['Refurbished', 'Unspecified', '65+'], + xCompareValue: ['Refurbished', 'Unspecified', '65+'], + value: 151550.90334415436, + }, + { + rawValue: 1584.9101469516754, + xValue: ['Unspecified', 'Female', '0-18'], + xDisplayValue: ['Unspecified', 'Female', '0-18'], + xCompareValue: ['Unspecified', 'Female', '0-18'], + value: 1584.9101469516754, + }, + { + rawValue: 7824.6359939575195, + xValue: ['Unspecified', 'Female', '19-24'], + xDisplayValue: ['Unspecified', 'Female', '19-24'], + xCompareValue: ['Unspecified', 'Female', '19-24'], + value: 7824.6359939575195, + }, + { + rawValue: 29799.104674339294, + xValue: ['Unspecified', 'Female', '25-34'], + xDisplayValue: ['Unspecified', 'Female', '25-34'], + xCompareValue: ['Unspecified', 'Female', '25-34'], + value: 29799.104674339294, + }, + { + rawValue: 23053.189082324505, + xValue: ['Unspecified', 'Female', '35-44'], + xDisplayValue: ['Unspecified', 'Female', '35-44'], + xCompareValue: ['Unspecified', 'Female', '35-44'], + value: 23053.189082324505, + }, + { + rawValue: 23686.805324673653, + xValue: ['Unspecified', 'Female', '45-54'], + xDisplayValue: ['Unspecified', 'Female', '45-54'], + xCompareValue: ['Unspecified', 'Female', '45-54'], + value: 23686.805324673653, + }, + { + rawValue: 9055.553003311157, + xValue: ['Unspecified', 'Female', '55-64'], + xDisplayValue: ['Unspecified', 'Female', '55-64'], + xCompareValue: ['Unspecified', 'Female', '55-64'], + value: 9055.553003311157, + }, + { + rawValue: 12968.002454280853, + xValue: ['Unspecified', 'Female', '65+'], + xDisplayValue: ['Unspecified', 'Female', '65+'], + xCompareValue: ['Unspecified', 'Female', '65+'], + value: 12968.002454280853, + }, + { + rawValue: 37515.3125834465, + xValue: ['Unspecified', 'Male', '0-18'], + xDisplayValue: ['Unspecified', 'Male', '0-18'], + xCompareValue: ['Unspecified', 'Male', '0-18'], + value: 37515.3125834465, + }, + { + rawValue: 24884.059005746618, + xValue: ['Unspecified', 'Male', '19-24'], + xDisplayValue: ['Unspecified', 'Male', '19-24'], + xCompareValue: ['Unspecified', 'Male', '19-24'], + value: 24884.059005746618, + }, + { + rawValue: 95954.37422311306, + xValue: ['Unspecified', 'Male', '25-34'], + xDisplayValue: ['Unspecified', 'Male', '25-34'], + xCompareValue: ['Unspecified', 'Male', '25-34'], + value: 95954.37422311306, + }, + { + rawValue: 103462.71881651878, + xValue: ['Unspecified', 'Male', '35-44'], + xDisplayValue: ['Unspecified', 'Male', '35-44'], + xCompareValue: ['Unspecified', 'Male', '35-44'], + value: 103462.71881651878, + }, + { + rawValue: 92952.79265773296, + xValue: ['Unspecified', 'Male', '45-54'], + xDisplayValue: ['Unspecified', 'Male', '45-54'], + xCompareValue: ['Unspecified', 'Male', '45-54'], + value: 92952.79265773296, + }, + { + rawValue: 53767.647619724274, + xValue: ['Unspecified', 'Male', '55-64'], + xDisplayValue: ['Unspecified', 'Male', '55-64'], + xCompareValue: ['Unspecified', 'Male', '55-64'], + value: 53767.647619724274, + }, + { + rawValue: 113161.7543694973, + xValue: ['Unspecified', 'Male', '65+'], + xDisplayValue: ['Unspecified', 'Male', '65+'], + xCompareValue: ['Unspecified', 'Male', '65+'], + value: 113161.7543694973, + }, + { + rawValue: 216433.62916576862, + xValue: ['Unspecified', 'Unspecified', '0-18'], + xDisplayValue: ['Unspecified', 'Unspecified', '0-18'], + xCompareValue: ['Unspecified', 'Unspecified', '0-18'], + value: 216433.62916576862, + }, + { + rawValue: 126803.61816757917, + xValue: ['Unspecified', 'Unspecified', '19-24'], + xDisplayValue: ['Unspecified', 'Unspecified', '19-24'], + xCompareValue: ['Unspecified', 'Unspecified', '19-24'], + value: 126803.61816757917, + }, + { + rawValue: 251692.10088264942, + xValue: ['Unspecified', 'Unspecified', '25-34'], + xDisplayValue: ['Unspecified', 'Unspecified', '25-34'], + xCompareValue: ['Unspecified', 'Unspecified', '25-34'], + value: 251692.10088264942, + }, + { + rawValue: 372490.0220761895, + xValue: ['Unspecified', 'Unspecified', '35-44'], + xDisplayValue: ['Unspecified', 'Unspecified', '35-44'], + xCompareValue: ['Unspecified', 'Unspecified', '35-44'], + value: 372490.0220761895, + }, + { + rawValue: 413002.60811787844, + xValue: ['Unspecified', 'Unspecified', '45-54'], + xDisplayValue: ['Unspecified', 'Unspecified', '45-54'], + xCompareValue: ['Unspecified', 'Unspecified', '45-54'], + value: 413002.60811787844, + }, + { + rawValue: 304048.96629595757, + xValue: ['Unspecified', 'Unspecified', '55-64'], + xDisplayValue: ['Unspecified', 'Unspecified', '55-64'], + xCompareValue: ['Unspecified', 'Unspecified', '55-64'], + value: 304048.96629595757, + }, + { + rawValue: 392143.8338055238, + xValue: ['Unspecified', 'Unspecified', '65+'], + xDisplayValue: ['Unspecified', 'Unspecified', '65+'], + xCompareValue: ['Unspecified', 'Unspecified', '65+'], + value: 392143.8338055238, + }, + { + rawValue: 11870.398762702942, + xValue: ['Used', 'Female', '0-18'], + xDisplayValue: ['Used', 'Female', '0-18'], + xCompareValue: ['Used', 'Female', '0-18'], + value: 11870.398762702942, + }, + { + rawValue: 45237.36557221413, + xValue: ['Used', 'Female', '19-24'], + xDisplayValue: ['Used', 'Female', '19-24'], + xCompareValue: ['Used', 'Female', '19-24'], + value: 45237.36557221413, + }, + { + rawValue: 53603.03658378124, + xValue: ['Used', 'Female', '25-34'], + xDisplayValue: ['Used', 'Female', '25-34'], + xCompareValue: ['Used', 'Female', '25-34'], + value: 53603.03658378124, + }, + { + rawValue: 62986.70472574234, + xValue: ['Used', 'Female', '35-44'], + xDisplayValue: ['Used', 'Female', '35-44'], + xCompareValue: ['Used', 'Female', '35-44'], + value: 62986.70472574234, + }, + { + rawValue: 84954.4567668289, + xValue: ['Used', 'Female', '45-54'], + xDisplayValue: ['Used', 'Female', '45-54'], + xCompareValue: ['Used', 'Female', '45-54'], + value: 84954.4567668289, + }, + { + rawValue: 39885.33868396282, + xValue: ['Used', 'Female', '55-64'], + xDisplayValue: ['Used', 'Female', '55-64'], + xCompareValue: ['Used', 'Female', '55-64'], + value: 39885.33868396282, + }, + { + rawValue: 60069.40814638138, + xValue: ['Used', 'Female', '65+'], + xDisplayValue: ['Used', 'Female', '65+'], + xCompareValue: ['Used', 'Female', '65+'], + value: 60069.40814638138, + }, + { + rawValue: 75186.67847645283, + xValue: ['Used', 'Male', '0-18'], + xDisplayValue: ['Used', 'Male', '0-18'], + xCompareValue: ['Used', 'Male', '0-18'], + value: 75186.67847645283, + }, + { + rawValue: 187592.4942316413, + xValue: ['Used', 'Male', '19-24'], + xDisplayValue: ['Used', 'Male', '19-24'], + xCompareValue: ['Used', 'Male', '19-24'], + value: 187592.4942316413, + }, + { + rawValue: 311667.9457566738, + xValue: ['Used', 'Male', '25-34'], + xDisplayValue: ['Used', 'Male', '25-34'], + xCompareValue: ['Used', 'Male', '25-34'], + value: 311667.9457566738, + }, + { + rawValue: 349629.8932403922, + xValue: ['Used', 'Male', '35-44'], + xDisplayValue: ['Used', 'Male', '35-44'], + xCompareValue: ['Used', 'Male', '35-44'], + value: 349629.8932403922, + }, + { + rawValue: 313382.494027555, + xValue: ['Used', 'Male', '45-54'], + xDisplayValue: ['Used', 'Male', '45-54'], + xCompareValue: ['Used', 'Male', '45-54'], + value: 313382.494027555, + }, + { + rawValue: 221294.35766649246, + xValue: ['Used', 'Male', '55-64'], + xDisplayValue: ['Used', 'Male', '55-64'], + xCompareValue: ['Used', 'Male', '55-64'], + value: 221294.35766649246, + }, + { + rawValue: 282663.31431889534, + xValue: ['Used', 'Male', '65+'], + xDisplayValue: ['Used', 'Male', '65+'], + xCompareValue: ['Used', 'Male', '65+'], + value: 282663.31431889534, + }, + { + rawValue: 470974.11550295353, + xValue: ['Used', 'Unspecified', '0-18'], + xDisplayValue: ['Used', 'Unspecified', '0-18'], + xCompareValue: ['Used', 'Unspecified', '0-18'], + value: 470974.11550295353, + }, + { + rawValue: 2246986.868683934, + xValue: ['Used', 'Unspecified', '19-24'], + xDisplayValue: ['Used', 'Unspecified', '19-24'], + xCompareValue: ['Used', 'Unspecified', '19-24'], + value: 2246986.868683934, + }, + { + rawValue: 1518690.077901557, + xValue: ['Used', 'Unspecified', '25-34'], + xDisplayValue: ['Used', 'Unspecified', '25-34'], + xCompareValue: ['Used', 'Unspecified', '25-34'], + value: 1518690.077901557, + }, + { + rawValue: 11211483.146567509, + xValue: ['Used', 'Unspecified', '35-44'], + xDisplayValue: ['Used', 'Unspecified', '35-44'], + xCompareValue: ['Used', 'Unspecified', '35-44'], + value: 11211483.146567509, + }, + { + rawValue: 3643311.798181474, + xValue: ['Used', 'Unspecified', '45-54'], + xDisplayValue: ['Used', 'Unspecified', '45-54'], + xCompareValue: ['Used', 'Unspecified', '45-54'], + value: 3643311.798181474, + }, + { + rawValue: 875408.5851053596, + xValue: ['Used', 'Unspecified', '55-64'], + xDisplayValue: ['Used', 'Unspecified', '55-64'], + xCompareValue: ['Used', 'Unspecified', '55-64'], + value: 875408.5851053596, + }, + { + rawValue: 1370253.3801133633, + xValue: ['Used', 'Unspecified', '65+'], + xDisplayValue: ['Used', 'Unspecified', '65+'], + xCompareValue: ['Used', 'Unspecified', '65+'], + value: 1370253.3801133633, + }, + ], + }, + ], + xAxisCount: 3, + type: 'categorical', + }, + dataOptions: { + y: [ + { + name: '$measure0_Total Revenue', + type: 'basemeasure', + desc: '', + __serializable: 'DimensionalElement', + sort: 0, + aggregation: 'sum', + attribute: { + name: 'TotalRevenue', + type: 'numeric-attribute', + desc: '', + __serializable: 'DimensionalElement', + expression: '[Commerce.Revenue]', + }, + }, + ], + breakBy: [ + { + name: 'Condition', + type: 'text-attribute', + desc: '', + __serializable: 'DimensionalElement', + expression: '[Commerce.Condition]', + }, + { + name: 'Gender', + type: 'text-attribute', + desc: '', + __serializable: 'DimensionalElement', + expression: '[Commerce.Gender]', + }, + { + name: 'AgeRange', + type: 'text-attribute', + desc: '', + __serializable: 'DimensionalElement', + expression: '[Commerce.Age Range]', + }, + ], + seriesToColorMap: { + Condition: {}, + Gender: {}, + AgeRange: {}, + }, + }, + themeSettings: { + chart: { + backgroundColor: '#FFFFFF', + textColor: '#5B6372', + secondaryTextColor: '#9EA2AB', + panelBackgroundColor: '#F6F6F6', + animation: { + init: { + duration: 'auto', + }, + redraw: { + duration: 'auto', + }, + }, + }, + typography: { + fontFamily: 'Open Sans', + primaryTextColor: '#5B6372', + secondaryTextColor: '#9EA2AB', + }, + palette: { + variantColors: ['#00cee6', '#9b9bd7', '#6EDA55', '#fc7570', '#fbb755', '#218A8C'], + }, + general: { + backgroundColor: '#ffffff', + brandColor: '#ffcb05', + primaryButtonTextColor: '#3a4356', + primaryButtonHoverColor: '#f2b900', + }, + widget: { + spaceAround: 'None', + cornerRadius: 'None', + shadow: 'None', + border: false, + borderColor: '#9EA2AB', + header: { + titleTextColor: '#5B6372', + titleAlignment: 'Left', + dividerLine: false, + dividerLineColor: '#5B6372', + backgroundColor: '#FFFFFF', + }, + }, + dashboard: { + backgroundColor: '#FFFFFF', + dividerLineWidth: 4, + dividerLineColor: '#F2F2F2', + }, + aiChat: { + backgroundColor: 'rgba(244, 244, 248, 1)', + primaryTextColor: 'rgba(38, 46, 61, 0.8)', + secondaryTextColor: 'rgba(38, 46, 61, 0.55)', + primaryFontSize: ['13px', '18px'], + body: { + paddingLeft: '16px', + paddingRight: '16px', + paddingTop: '16px', + paddingBottom: '1px', + gapBetweenMessages: '16px', + }, + footer: { + paddingLeft: '16px', + paddingRight: '16px', + paddingTop: '12px', + paddingBottom: '16px', + }, + userMessages: { + backgroundColor: 'rgba(255, 255, 255, 1)', + }, + systemMessages: { + backgroundColor: 'rgba(255, 255, 255, 1)', + }, + input: { + backgroundColor: 'rgba(255, 255, 255, 1)', + focus: { + outlineColor: 'rgba(38, 46, 61, 0.5)', + }, + }, + header: { + textColor: 'rgba(38, 46, 61, 0.8)', + backgroundColor: 'rgba(255, 255, 255, 1)', + }, + dropup: { + backgroundColor: 'rgba(255, 255, 255, 1)', + boxShadow: '0px 1px 2px rgba(9, 9, 10, 0.1), 0px 2px 4px rgba(9, 9, 10, 0.1)', + borderRadius: '4px', + headers: { + textColor: 'rgba(38, 46, 61, 0.8)', + hover: { + backgroundColor: 'rgba(244, 244, 248, 1)', + }, + }, + items: { + textColor: 'rgba(38, 46, 61, 0.8)', + hover: { + backgroundColor: 'rgba(244, 244, 248, 1)', + }, + }, + }, + border: '1px solid #c6c9ce', + borderRadius: '30px', + suggestions: { + textColor: 'rgba(38, 46, 61, 1)', + backgroundColor: 'rgba(244, 244, 248, 1)', + border: '1px solid', + borderRadius: '16px', + borderGradient: ['rgba(75, 153, 233, 1)', 'rgba(102, 57, 191, 1)'], + hover: { + textColor: 'rgba(38, 46, 61, 1)', + backgroundColor: 'rgba(12, 14, 18, 0.07)', + }, + loadingGradient: ['rgba(194, 196, 203, 1)', 'rgba(236, 236, 239, 1)'], + gap: '8px', + }, + clickableMessages: { + textColor: 'rgba(38, 46, 61, 1)', + backgroundColor: 'rgba(244, 244, 248, 1)', + border: '1px solid', + borderGradient: ['rgba(75, 153, 233, 1)', 'rgba(102, 57, 191, 1)'], + hover: { + textColor: 'rgba(38, 46, 61, 1)', + backgroundColor: 'rgba(12, 14, 18, 0.07)', + }, + }, + dataTopics: { + backgroundColor: 'rgba(255, 255, 255, 1)', + items: { + textColor: 'rgba(38, 46, 61, 1)', + backgroundColor: 'rgba(244, 244, 248, 1)', + }, + }, + icons: { + color: 'rgba(38, 46, 61, 0.67)', + feedbackIcons: { + hoverColor: 'rgba(12, 14, 18, 0.07)', + }, + }, + tooltips: { + backgroundColor: 'rgba(255, 255, 255, 1)', + textColor: 'rgba(38, 46, 61, 0.8)', + boxShadow: '0px 4px 12px 0px rgba(9, 9, 10, 0.20), 0px 1px 4px 0px rgba(9, 9, 10, 0.10)', + }, + }, + }, +}; diff --git a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-levels.ts b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-levels.ts index cd7fbfd7..14cb0c04 100644 --- a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-levels.ts +++ b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-levels.ts @@ -7,6 +7,13 @@ import { SunburstChartDesignOptions } from '../design-options'; import { getDarkFactor, toColor } from '../../../utils/color'; import { CompleteThemeSettings } from '../../../types'; +const ROOT_LEVEL_SIZE_PER_CATEGORIES = Object.freeze({ + 1: 80, + 2: 70, + 3: 60, + 4: 50, +}); + export function prepareSunburstLevels( chartData: CategoricalChartData, dataOptions: CategoricalChartDataOptionsInternal, @@ -28,7 +35,9 @@ export function prepareSunburstLevels( return `
-
${ +
${ this.point.name }
${tooltipSeparator()} @@ -43,8 +52,8 @@ export function prepareSunburstLevels( }, }, levelSize: { - unit: 'pixels', - value: 60, + unit: 'percentage', + value: ROOT_LEVEL_SIZE_PER_CATEGORIES[dataOptions.breakBy.length] || 50, }, }; diff --git a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-options.ts b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-options.ts index b8673e4c..8df167f8 100644 --- a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-options.ts +++ b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-options.ts @@ -2,7 +2,7 @@ import { CategoricalChartData } from '../../../chart-data/types'; import { HighchartsOptionsInternal } from '../../chart-options-service'; import { CategoricalChartDataOptionsInternal } from '../../../chart-data-options/types'; -import { CompleteThemeSettings } from '../../../types'; +import { CompleteThemeSettings, UniformDataColorOptions } from '../../../types'; import { SunburstChartDesignOptions } from '../design-options'; import { getTreemapTooltipSettings } from '../treemap/treemap-tooltip'; import { getPaletteColor } from '../../../chart-data-options/coloring/utils'; @@ -62,11 +62,14 @@ export function prepareSunburstOptions( data: prepareSunburstDataItems(chartData, dataOptions, themeSettings), levels: prepareSunburstLevels(chartData, dataOptions, designOptions, themeSettings), showInLegend: false, + turboThreshold: 2000, }, ...dataOptions.breakBy.map((column, index) => ({ name: column.title || column.name, showInLegend: true, - color: getPaletteColor(themeSettings?.palette.variantColors, index), + color: + (column?.color as UniformDataColorOptions)?.color || + getPaletteColor(themeSettings?.palette.variantColors, index), data: [], states: { hover: { diff --git a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.test.ts b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.test.ts new file mode 100644 index 00000000..097c1117 --- /dev/null +++ b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.test.ts @@ -0,0 +1,17 @@ +import { prepareSunburstDataItems } from '@/chart-options-processor/translations/sunburst/sunburst-series'; +import { mockedSunburstSeriesProps } from '@/chart-options-processor/translations/sunburst/mock/sunburst-series-props'; +import { CategoricalChartData } from '@/chart-data/types'; +import { CategoricalChartDataOptionsInternal } from '@/chart-data-options/types'; +import { CompleteThemeSettings } from '@/types'; + +describe('prepareSunburstDataItems', () => { + it('should prepare data items with sorting and coloring', () => { + const result = prepareSunburstDataItems( + mockedSunburstSeriesProps.chartData as CategoricalChartData, + mockedSunburstSeriesProps.dataOptions as unknown as CategoricalChartDataOptionsInternal, + mockedSunburstSeriesProps.themeSettings as CompleteThemeSettings, + ); + + expect(result).toMatchSnapshot(); + }); +}); diff --git a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.ts b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.ts index e002a6da..784de216 100644 --- a/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.ts +++ b/packages/sdk-ui/src/chart-options-processor/translations/sunburst/sunburst-series.ts @@ -1,10 +1,10 @@ import { prepareTreemapDataItems } from '../treemap/treemap-series'; import { CategoricalChartData } from '../../../chart-data/types'; import { CategoricalChartDataOptionsInternal } from '../../../chart-data-options/types'; -import { CompleteThemeSettings } from '../../../types'; +import { CompleteThemeSettings, UniformDataColorOptions } from '../../../types'; import { SeriesPointStructure } from '../translations-to-highcharts'; import { getPaletteColor } from '../../../chart-data-options/coloring/utils'; -import { scaleBrightness } from '../../../utils/color'; +import { getExplicitColorSteps, scaleBrightness } from '../../../utils/color'; export const SUNBURST_ROOT_PARENT_ID = 'SUNBURST_ROOT_PARENT_ID'; @@ -31,9 +31,14 @@ export function prepareSunburstDataItems( return item; }); - const coloredDataItems = handleSunburstSeriesColor(dataItems, dataOptions, themeSettings); + const sortedDataItems = sortSunburstDataItems(dataItems); + const coloredAndSortedDataItems = handleSunburstSeriesColor( + sortedDataItems, + dataOptions, + themeSettings, + ); - return [rootDataItem, ...coloredDataItems]; + return [rootDataItem, ...coloredAndSortedDataItems]; } function handleSunburstSeriesColor( @@ -41,23 +46,50 @@ function handleSunburstSeriesColor( dataOptions: CategoricalChartDataOptionsInternal, themeSettings?: CompleteThemeSettings, ) { + const MAX_BRIGHTNESS_PERCENT = 0.3; const seriesColorMapByLevels = prepareColorMapByLevels(dataOptions); - const colorStepMap = {}; - - return series.map((value) => { - const parent = value?.parent || ''; - const colorBySeriesName = - seriesColorMapByLevels[value.custom?.level || '']?.[value?.name || '']; - const colorStep = (colorStepMap[parent] = - parent in colorStepMap ? (colorStepMap[parent] as number) + 1 : 0); - const paletteColor = getPaletteColor( - themeSettings?.palette.variantColors, - (value.custom?.level || 1) - 1, + + const levelsMembersTotals = dataOptions.breakBy.map(() => new Map()); + series.forEach((item) => { + const relatedMap = levelsMembersTotals[item.custom!.level! - 1]; + if (relatedMap) { + const prevTotal = relatedMap.get(item.name!) ?? 0; + const itemValue = item.value ?? (item.custom?.subtotalValue as number) ?? 0; + relatedMap.set(item.name!, prevTotal + itemValue); + } + }); + + const levelsWithSortedMembers = levelsMembersTotals.map((levelTotals) => { + return Array.from(levelTotals.entries()) + .sort(([, valueA], [, valueB]) => valueA - valueB) + .map(([key]) => key); + }); + + const levelsMembersColorMaps = levelsWithSortedMembers.map((levelSortedMembers, index) => { + const map = new Map(); + const paletteColor = getPaletteColor(themeSettings?.palette.variantColors, index); + const color = + (dataOptions.breakBy[index]?.color as UniformDataColorOptions)?.color || paletteColor; + const colorSteps = getExplicitColorSteps( + scaleBrightness(color, MAX_BRIGHTNESS_PERCENT), + scaleBrightness(color, -MAX_BRIGHTNESS_PERCENT), + levelSortedMembers.length, ); + levelSortedMembers.forEach((member, index) => { + map.set(member, colorSteps[index]); + }); + + return map; + }); + + return series.map((item) => { + const colorBySeriesName = seriesColorMapByLevels[item.custom?.level || '']?.[item?.name || '']; + const colorFromColorMap = levelsMembersColorMaps[item.custom!.level! - 1]?.get(item.name!); + return { - ...value, - color: colorBySeriesName || scaleBrightness(paletteColor, -(colorStep * 0.1)), + ...item, + color: colorBySeriesName || colorFromColorMap, }; }); } @@ -70,3 +102,45 @@ function prepareColorMapByLevels(dataOptions: CategoricalChartDataOptionsInterna return map; }, {}); } + +function sortSunburstDataItems(items: SeriesPointStructure[]): SeriesPointStructure[] { + const byParentMap = new Map(); + const parentsTotalMap = new Map(); + + items.forEach((item) => { + if (item.parent) { + if (!byParentMap.has(item.parent)) { + byParentMap.set(item.parent, []); + } + byParentMap.get(item.parent)!.push(item); + } + }); + + Array.from(byParentMap.values()) + .sort((itemA, itemB) => { + return (itemB[0]?.custom?.level ?? 0) - (itemA[0]?.custom?.level ?? 0); + }) + .forEach((items) => { + items.forEach((item) => { + const value = item.value ?? parentsTotalMap.get(item.id!) ?? 0; + const currentTotal = parentsTotalMap.get(item.parent!) || 0; + parentsTotalMap.set(item.parent!, currentTotal + value); + + if (item.id) { + item.custom!.subtotalValue = parentsTotalMap.get(item.id); + } + }); + }); + + const result: SeriesPointStructure[] = []; + byParentMap.forEach((children) => { + children.sort((itemA, itemB) => { + const valueA = itemA.value ?? parentsTotalMap.get(itemA.id!) ?? 0; + const valueB = itemB.value ?? parentsTotalMap.get(itemB.id!) ?? 0; + return valueA - valueB; + }); + result.push(...children); + }); + + return result; +} diff --git a/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.test.ts b/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.test.ts index 251a834b..b613cc58 100644 --- a/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.test.ts +++ b/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.test.ts @@ -57,14 +57,17 @@ describe('formatSeries', () => { { y: 10, custom: { rawValue: 10, xValue: ['xAxis 1'] }, + selected: false, }, { y: 20, custom: { rawValue: 20, xValue: ['xAxis 2'] }, + selected: false, }, { y: 30, custom: { rawValue: 30, xValue: ['xAxis 3'] }, + selected: false, }, ], }); @@ -89,16 +92,19 @@ describe('formatSeries', () => { y: 10, custom: { rawValue: 10, xValue: ['xAxis 1'] }, color: 'red', + selected: false, }, { y: 20, custom: { rawValue: 20, xValue: ['xAxis 2'] }, color: 'blue', + selected: false, }, { y: 30, custom: { rawValue: 30, xValue: ['xAxis 3'] }, color: 'green', + selected: false, }, ], }); @@ -167,6 +173,7 @@ describe('formatSeries', () => { { y: NaN, custom: { rawValue: 'value1', xValue: ['xAxis 1'] }, + selected: false, }, { y: 20, @@ -175,10 +182,12 @@ describe('formatSeries', () => { enabled: true, isIsolatedPoint: true, }, + selected: false, }, { y: NaN, custom: { rawValue: 'value3', xValue: ['xAxis 3'] }, + selected: false, }, ], }); diff --git a/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.ts b/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.ts index 87e438ae..512e9fe5 100644 --- a/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.ts +++ b/packages/sdk-ui/src/chart-options-processor/translations/translations-to-highcharts.ts @@ -191,7 +191,7 @@ const translateNumbersContinuousXAxis = ( return { x, y: value, - selected: blur, + selected: !!blur, ...(hasMarker && { marker }), ...(color && { color }), custom: { rawValue, xValue, xDisplayValue: xDisplayValue || xValue }, @@ -287,7 +287,7 @@ const translateNumbersToSeriesPointStructure = ( categories?: string[], categoryColors?: string[], ): SeriesPointStructure[] => { - const hasBlurred = input.some((v) => v.blur); + const hasHighlighted = input.some((v) => v.blur !== undefined); return indexMap.map((index: number, indexOfIndex: number): SeriesPointStructure => { if (index < 0) { @@ -300,19 +300,19 @@ const translateNumbersToSeriesPointStructure = ( name: categories[index], y: value, color: color ?? categoryColors?.[index], - ...(hasBlurred && !blur && { selected: true }), + ...(hasHighlighted && !blur && { selected: true }), custom: { rawValue, xValue }, }; } else { const shouldShowIsolatedPoint = isIsolatedPoint(input, indexMap, index, indexOfIndex); - const hasMarker = shouldShowIsolatedPoint || hasBlurred; + const hasMarker = shouldShowIsolatedPoint || hasHighlighted; const marker = { enabled: !blur, isIsolatedPoint: shouldShowIsolatedPoint, }; return { y: isNaN(+value) ? value : +value, - selected: blur, + selected: !!blur, ...(hasMarker && { marker }), ...(color && { color }), custom: { rawValue, xValue }, diff --git a/packages/sdk-ui/src/chart/__snapshots__/advanced-chart.test.tsx.snap b/packages/sdk-ui/src/chart/__snapshots__/advanced-chart.test.tsx.snap index fb2b277b..448376f9 100644 --- a/packages/sdk-ui/src/chart/__snapshots__/advanced-chart.test.tsx.snap +++ b/packages/sdk-ui/src/chart/__snapshots__/advanced-chart.test.tsx.snap @@ -1,6070 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`Advanced Charts > should render forecast trend combo chart 1`] = ` -{ - "accessibility": { - "enabled": false, - }, - "boost": { - "useGPUTranslations": true, - "usePreAllocated": true, - }, - "chart": { - "alignTicks": false, - "animation": { - "duration": 300, - }, - "backgroundColor": "#FFFFFF", - "events": {}, - "polar": false, - "spacing": [ - 20, - 20, - 20, - 20, - ], - "type": "line", - }, - "credits": { - "enabled": false, - }, - "drilldown": { - "activeDataLabelStyle": { - "color": "#5B6372", - }, - "breadcrumbs": { - "buttonTheme": { - "fill": "#ffcb05", - "states": { - "hover": { - "fill": "#f2b900", - "stroke": "#f2b900", - }, - }, - "stroke": "#ffcb05", - "style": { - "color": "#3a4356", - }, - }, - }, - }, - "exporting": { - "enabled": true, - }, - "legend": { - "align": "center", - "backgroundColor": "transparent", - "borderColor": "transparent", - "borderWidth": 0, - "enabled": true, - "itemStyle": { - "color": "#5B6372", - "cursor": "default", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "normal", - "pointerEvents": "auto", - "textOutline": "none", - }, - "layout": "horizontal", - "symbolRadius": 0, - "verticalAlign": "bottom", - }, - "navigator": { - "enabled": true, - "handles": { - "backgroundColor": "#CCCCCC", - "borderColor": "#FFFFFF", - "symbols": [ - "navigator-handle", - "navigator-handle", - ], - }, - "height": 40, - "margin": 30, - "maskFill": "rgba(91,99,114, 0.15)", - "maskInside": true, - "outlineColor": "#CCCCCC", - "outlineWidth": 1, - "series": { - "dataGrouping": { - "enabled": false, - }, - "type": "line", - }, - "tooltipFormatter": [Function], - "xAxis": { - "labels": { - "enabled": false, - }, - }, - }, - "plotOptions": { - "area": { - "className": "area-series--without-pointer-events", - "states": { - "inactive": { - "enabled": true, - "opacity": 0.3, - }, - }, - }, - "series": { - "animation": { - "duration": 600, - }, - "connectNulls": false, - "dataLabels": { - "crop": false, - "enabled": false, - "style": { - "color": "#5B6372", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "normal", - "pointerEvents": "none", - "textOutline": "none", - }, - }, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "point": { - "events": { - "click": [Function], - }, - }, - "stacking": undefined, - "states": { - "select": { - "borderColor": "transparent", - "color": null, - "opacity": 0.3, - }, - }, - "stickyTracking": false, - }, - }, - "series": [ - { - "boostThreshold": 0, - "color": "#00cee6", - "connectNulls": false, - "data": [ - { - "custom": { - "rawValue": 66781.63189208508, - "xValue": [ - "2009-11-01", - ], - }, - "selected": false, - "y": 66781.63189208508, - }, - { - "custom": { - "rawValue": 359971.00955861807, - "xValue": [ - "2009-12-01", - ], - }, - "selected": false, - "y": 359971.00955861807, - }, - { - "custom": { - "rawValue": 290398.9091284871, - "xValue": [ - "2010-01-01", - ], - }, - "selected": false, - "y": 290398.9091284871, - }, - { - "custom": { - "rawValue": 170889.8894996643, - "xValue": [ - "2010-02-01", - ], - }, - "selected": false, - "y": 170889.8894996643, - }, - { - "custom": { - "rawValue": 309543.24207001925, - "xValue": [ - "2010-03-01", - ], - }, - "selected": false, - "y": 309543.24207001925, - }, - { - "custom": { - "rawValue": 371724.55312902667, - "xValue": [ - "2010-04-01", - ], - }, - "selected": false, - "y": 371724.55312902667, - }, - { - "custom": { - "rawValue": 335743.71691042185, - "xValue": [ - "2010-05-01", - ], - }, - "selected": false, - "y": 335743.71691042185, - }, - { - "custom": { - "rawValue": 205558.42935597897, - "xValue": [ - "2010-06-01", - ], - }, - "selected": false, - "y": 205558.42935597897, - }, - { - "custom": { - "rawValue": 157792.30764091015, - "xValue": [ - "2010-07-01", - ], - }, - "selected": false, - "y": 157792.30764091015, - }, - { - "custom": { - "rawValue": 324757.70880162716, - "xValue": [ - "2010-08-01", - ], - }, - "selected": false, - "y": 324757.70880162716, - }, - { - "custom": { - "rawValue": 202324.06454509497, - "xValue": [ - "2010-09-01", - ], - }, - "selected": false, - "y": 202324.06454509497, - }, - { - "custom": { - "rawValue": 235094.33303177357, - "xValue": [ - "2010-10-01", - ], - }, - "selected": false, - "y": 235094.33303177357, - }, - { - "custom": { - "rawValue": 956515.9698420167, - "xValue": [ - "2010-11-01", - ], - }, - "selected": false, - "y": 956515.9698420167, - }, - { - "custom": { - "rawValue": 1125384.2649897337, - "xValue": [ - "2010-12-01", - ], - }, - "selected": false, - "y": 1125384.2649897337, - }, - { - "custom": { - "rawValue": 463382.532077305, - "xValue": [ - "2011-01-01", - ], - }, - "selected": false, - "y": 463382.532077305, - }, - { - "custom": { - "rawValue": 245568.28763371706, - "xValue": [ - "2011-02-01", - ], - }, - "selected": false, - "y": 245568.28763371706, - }, - { - "custom": { - "rawValue": 260606.05075496435, - "xValue": [ - "2011-03-01", - ], - }, - "selected": false, - "y": 260606.05075496435, - }, - { - "custom": { - "rawValue": 268872.20260578394, - "xValue": [ - "2011-04-01", - ], - }, - "selected": false, - "y": 268872.20260578394, - }, - { - "custom": { - "rawValue": 340273.4022771716, - "xValue": [ - "2011-05-01", - ], - }, - "selected": false, - "y": 340273.4022771716, - }, - { - "custom": { - "rawValue": 393066.62418581545, - "xValue": [ - "2011-06-01", - ], - }, - "selected": false, - "y": 393066.62418581545, - }, - { - "custom": { - "rawValue": 456280.5512932539, - "xValue": [ - "2011-07-01", - ], - }, - "selected": false, - "y": 456280.5512932539, - }, - { - "custom": { - "rawValue": 425414.88275170326, - "xValue": [ - "2011-08-01", - ], - }, - "selected": false, - "y": 425414.88275170326, - }, - { - "custom": { - "rawValue": 479749.6705650091, - "xValue": [ - "2011-09-01", - ], - }, - "selected": false, - "y": 479749.6705650091, - }, - { - "custom": { - "rawValue": 579453.2531992197, - "xValue": [ - "2011-10-01", - ], - }, - "selected": false, - "y": 579453.2531992197, - }, - { - "custom": { - "rawValue": 839236.7714686394, - "xValue": [ - "2011-11-01", - ], - }, - "selected": false, - "y": 839236.7714686394, - }, - { - "custom": { - "rawValue": 885736.7923775315, - "xValue": [ - "2011-12-01", - ], - }, - "selected": false, - "y": 885736.7923775315, - }, - { - "custom": { - "rawValue": 473612.27137738466, - "xValue": [ - "2012-01-01", - ], - }, - "selected": false, - "y": 473612.27137738466, - }, - { - "custom": { - "rawValue": 551207.5465496182, - "xValue": [ - "2012-02-01", - ], - }, - "selected": false, - "y": 551207.5465496182, - }, - { - "custom": { - "rawValue": 486378.02141964436, - "xValue": [ - "2012-03-01", - ], - }, - "selected": false, - "y": 486378.02141964436, - }, - { - "custom": { - "rawValue": 844005.6761152148, - "xValue": [ - "2012-04-01", - ], - }, - "selected": false, - "y": 844005.6761152148, - }, - { - "custom": { - "rawValue": 528642.743718408, - "xValue": [ - "2012-05-01", - ], - }, - "selected": false, - "y": 528642.743718408, - }, - { - "custom": { - "rawValue": 500458.08090537786, - "xValue": [ - "2012-06-01", - ], - }, - "selected": false, - "y": 500458.08090537786, - }, - { - "custom": { - "rawValue": 613358.3858718723, - "xValue": [ - "2012-07-01", - ], - }, - "selected": false, - "y": 613358.3858718723, - }, - { - "custom": { - "rawValue": 640640.1058340669, - "xValue": [ - "2012-08-01", - ], - }, - "selected": false, - "y": 640640.1058340669, - }, - { - "custom": { - "rawValue": 6468195.891011775, - "xValue": [ - "2012-09-01", - ], - }, - "selected": false, - "y": 6468195.891011775, - }, - { - "custom": { - "rawValue": 1077545.8103399873, - "xValue": [ - "2012-10-01", - ], - }, - "selected": false, - "y": 1077545.8103399873, - }, - { - "custom": { - "rawValue": 1139118.50432086, - "xValue": [ - "2012-11-01", - ], - }, - "selected": false, - "y": 1139118.50432086, - }, - { - "custom": { - "rawValue": 1207031.0010682344, - "xValue": [ - "2012-12-01", - ], - }, - "selected": false, - "y": 1207031.0010682344, - }, - { - "custom": { - "rawValue": 672788.0245242715, - "xValue": [ - "2013-01-01", - ], - }, - "selected": false, - "y": 672788.0245242715, - }, - { - "custom": { - "rawValue": 664365.3652909398, - "xValue": [ - "2013-02-01", - ], - }, - "selected": false, - "y": 664365.3652909398, - }, - { - "custom": { - "rawValue": 618802.1503348947, - "xValue": [ - "2013-03-01", - ], - }, - "selected": false, - "y": 618802.1503348947, - }, - { - "custom": { - "rawValue": 866949.1155990958, - "xValue": [ - "2013-04-01", - ], - }, - "selected": false, - "y": 866949.1155990958, - }, - { - "custom": { - "rawValue": 618889.3449394181, - "xValue": [ - "2013-05-01", - ], - }, - "selected": false, - "y": 618889.3449394181, - }, - { - "custom": { - "rawValue": 683584.009878993, - "xValue": [ - "2013-06-01", - ], - }, - "selected": false, - "y": 683584.009878993, - }, - { - "custom": { - "rawValue": 798123.2515560985, - "xValue": [ - "2013-07-01", - ], - }, - "selected": false, - "y": 798123.2515560985, - }, - { - "custom": { - "rawValue": 650025.2262863517, - "xValue": [ - "2013-08-01", - ], - }, - "selected": false, - "y": 650025.2262863517, - }, - { - "custom": { - "rawValue": 5916789.096129909, - "xValue": [ - "2013-09-01", - ], - }, - "selected": false, - "y": 5916789.096129909, - }, - { - "custom": { - "rawValue": 1025246.3933910131, - "xValue": [ - "2013-10-01", - ], - }, - "selected": false, - "y": 1025246.3933910131, - }, - { - "custom": { - "rawValue": 1793304.247486055, - "xValue": [ - "2013-11-01", - ], - }, - "selected": false, - "y": 1793304.247486055, - }, - { - "custom": { - "rawValue": 170444.1994921565, - "xValue": [ - "2013-12-01", - ], - }, - "selected": false, - "y": 170444.1994921565, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-01-01", - ], - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-02-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-03-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-04-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-05-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-06-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "lineWidth": 3, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "Total Revenue", - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "yAxis": 0, - "zIndex": 1, - }, - { - "boostThreshold": 0, - "color": "#9b9bd7", - "connectNulls": false, - "data": [ - { - "custom": { - "rawValue": 189976.80757868662, - "xValue": [ - "2009-11-01", - ], - }, - "selected": false, - "y": 189976.80757868662, - }, - { - "custom": { - "rawValue": 1107490.0728950314, - "xValue": [ - "2009-12-01", - ], - }, - "selected": false, - "y": 1107490.0728950314, - }, - { - "custom": { - "rawValue": 845205.6287006252, - "xValue": [ - "2010-01-01", - ], - }, - "selected": false, - "y": 845205.6287006252, - }, - { - "custom": { - "rawValue": 787917.8207888827, - "xValue": [ - "2010-02-01", - ], - }, - "selected": false, - "y": 787917.8207888827, - }, - { - "custom": { - "rawValue": 946810.4692947622, - "xValue": [ - "2010-03-01", - ], - }, - "selected": false, - "y": 946810.4692947622, - }, - { - "custom": { - "rawValue": 900508.5092079439, - "xValue": [ - "2010-04-01", - ], - }, - "selected": false, - "y": 900508.5092079439, - }, - { - "custom": { - "rawValue": 946238.5815005917, - "xValue": [ - "2010-05-01", - ], - }, - "selected": false, - "y": 946238.5815005917, - }, - { - "custom": { - "rawValue": 886700.2053317726, - "xValue": [ - "2010-06-01", - ], - }, - "selected": false, - "y": 886700.2053317726, - }, - { - "custom": { - "rawValue": 900954.317531623, - "xValue": [ - "2010-07-01", - ], - }, - "selected": false, - "y": 900954.317531623, - }, - { - "custom": { - "rawValue": 984546.9012292922, - "xValue": [ - "2010-08-01", - ], - }, - "selected": false, - "y": 984546.9012292922, - }, - { - "custom": { - "rawValue": 947657.5594753642, - "xValue": [ - "2010-09-01", - ], - }, - "selected": false, - "y": 947657.5594753642, - }, - { - "custom": { - "rawValue": 1067067.8516010046, - "xValue": [ - "2010-10-01", - ], - }, - "selected": false, - "y": 1067067.8516010046, - }, - { - "custom": { - "rawValue": 1313277.0609966572, - "xValue": [ - "2010-11-01", - ], - }, - "selected": false, - "y": 1313277.0609966572, - }, - { - "custom": { - "rawValue": 1467710.2702174708, - "xValue": [ - "2010-12-01", - ], - }, - "selected": false, - "y": 1467710.2702174708, - }, - { - "custom": { - "rawValue": 1175238.5499559864, - "xValue": [ - "2011-01-01", - ], - }, - "selected": false, - "y": 1175238.5499559864, - }, - { - "custom": { - "rawValue": 1092969.080261767, - "xValue": [ - "2011-02-01", - ], - }, - "selected": false, - "y": 1092969.080261767, - }, - { - "custom": { - "rawValue": 1188733.9370134315, - "xValue": [ - "2011-03-01", - ], - }, - "selected": false, - "y": 1188733.9370134315, - }, - { - "custom": { - "rawValue": 1468171.674996743, - "xValue": [ - "2011-04-01", - ], - }, - "selected": false, - "y": 1468171.674996743, - }, - { - "custom": { - "rawValue": 1809045.4618380964, - "xValue": [ - "2011-05-01", - ], - }, - "selected": false, - "y": 1809045.4618380964, - }, - { - "custom": { - "rawValue": 1963988.3454919308, - "xValue": [ - "2011-06-01", - ], - }, - "selected": false, - "y": 1963988.3454919308, - }, - { - "custom": { - "rawValue": 2011346.4261528384, - "xValue": [ - "2011-07-01", - ], - }, - "selected": false, - "y": 2011346.4261528384, - }, - { - "custom": { - "rawValue": 2128043.9337140303, - "xValue": [ - "2011-08-01", - ], - }, - "selected": false, - "y": 2128043.9337140303, - }, - { - "custom": { - "rawValue": 2017077.2452351712, - "xValue": [ - "2011-09-01", - ], - }, - "selected": false, - "y": 2017077.2452351712, - }, - { - "custom": { - "rawValue": 2283585.5977138802, - "xValue": [ - "2011-10-01", - ], - }, - "selected": false, - "y": 2283585.5977138802, - }, - { - "custom": { - "rawValue": 2558169.054697007, - "xValue": [ - "2011-11-01", - ], - }, - "selected": false, - "y": 2558169.054697007, - }, - { - "custom": { - "rawValue": 2855504.8063853886, - "xValue": [ - "2011-12-01", - ], - }, - "selected": false, - "y": 2855504.8063853886, - }, - { - "custom": { - "rawValue": 2267886.0520572066, - "xValue": [ - "2012-01-01", - ], - }, - "selected": false, - "y": 2267886.0520572066, - }, - { - "custom": { - "rawValue": 2289422.9980101623, - "xValue": [ - "2012-02-01", - ], - }, - "selected": false, - "y": 2289422.9980101623, - }, - { - "custom": { - "rawValue": 2413584.21836257, - "xValue": [ - "2012-03-01", - ], - }, - "selected": false, - "y": 2413584.21836257, - }, - { - "custom": { - "rawValue": 2450628.8393439148, - "xValue": [ - "2012-04-01", - ], - }, - "selected": false, - "y": 2450628.8393439148, - }, - { - "custom": { - "rawValue": 2616360.1553670047, - "xValue": [ - "2012-05-01", - ], - }, - "selected": false, - "y": 2616360.1553670047, - }, - { - "custom": { - "rawValue": 2482130.5598226488, - "xValue": [ - "2012-06-01", - ], - }, - "selected": false, - "y": 2482130.5598226488, - }, - { - "custom": { - "rawValue": 2594841.3182018436, - "xValue": [ - "2012-07-01", - ], - }, - "selected": false, - "y": 2594841.3182018436, - }, - { - "custom": { - "rawValue": 2673938.1166581884, - "xValue": [ - "2012-08-01", - ], - }, - "selected": false, - "y": 2673938.1166581884, - }, - { - "custom": { - "rawValue": 2867416.29551314, - "xValue": [ - "2012-09-01", - ], - }, - "selected": false, - "y": 2867416.29551314, - }, - { - "custom": { - "rawValue": 3168871.066950053, - "xValue": [ - "2012-10-01", - ], - }, - "selected": false, - "y": 3168871.066950053, - }, - { - "custom": { - "rawValue": 3888213.687782809, - "xValue": [ - "2012-11-01", - ], - }, - "selected": false, - "y": 3888213.687782809, - }, - { - "custom": { - "rawValue": 3992612.938552344, - "xValue": [ - "2012-12-01", - ], - }, - "selected": false, - "y": 3992612.938552344, - }, - { - "custom": { - "rawValue": 2759434.9833942996, - "xValue": [ - "2013-01-01", - ], - }, - "selected": false, - "y": 2759434.9833942996, - }, - { - "custom": { - "rawValue": 2788158.3545121085, - "xValue": [ - "2013-02-01", - ], - }, - "selected": false, - "y": 2788158.3545121085, - }, - { - "custom": { - "rawValue": 3046625.3691154122, - "xValue": [ - "2013-03-01", - ], - }, - "selected": false, - "y": 3046625.3691154122, - }, - { - "custom": { - "rawValue": 2961134.7611477133, - "xValue": [ - "2013-04-01", - ], - }, - "selected": false, - "y": 2961134.7611477133, - }, - { - "custom": { - "rawValue": 3242762.429729399, - "xValue": [ - "2013-05-01", - ], - }, - "selected": false, - "y": 3242762.429729399, - }, - { - "custom": { - "rawValue": 3204714.5343812816, - "xValue": [ - "2013-06-01", - ], - }, - "selected": false, - "y": 3204714.5343812816, - }, - { - "custom": { - "rawValue": 3349081.2784886193, - "xValue": [ - "2013-07-01", - ], - }, - "selected": false, - "y": 3349081.2784886193, - }, - { - "custom": { - "rawValue": 3238694.8539762036, - "xValue": [ - "2013-08-01", - ], - }, - "selected": false, - "y": 3238694.8539762036, - }, - { - "custom": { - "rawValue": 3581952.4929154813, - "xValue": [ - "2013-09-01", - ], - }, - "selected": false, - "y": 3581952.4929154813, - }, - { - "custom": { - "rawValue": 3935084.4678387493, - "xValue": [ - "2013-10-01", - ], - }, - "selected": false, - "y": 3935084.4678387493, - }, - { - "custom": { - "rawValue": 4844611.66696444, - "xValue": [ - "2013-11-01", - ], - }, - "selected": false, - "y": 4844611.66696444, - }, - { - "custom": { - "rawValue": 770441.3868424296, - "xValue": [ - "2013-12-01", - ], - }, - "selected": false, - "y": 770441.3868424296, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-01-01", - ], - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-02-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-03-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-04-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-05-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-06-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "lineWidth": 3, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "Total Cost (+Trend)", - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "yAxis": 0, - "zIndex": 1, - }, - { - "boostThreshold": 0, - "color": "#9b9bd7", - "connectNulls": false, - "dashStyle": "ShortDot", - "data": [ - { - "custom": { - "rawValue": 399877.66021296044, - "xValue": [ - "2009-11-01", - ], - }, - "selected": false, - "y": 399877.66021296044, - }, - { - "custom": { - "rawValue": 760254.7486363016, - "xValue": [ - "2009-12-01", - ], - }, - "selected": false, - "y": 760254.7486363016, - }, - { - "custom": { - "rawValue": 892589.3891729144, - "xValue": [ - "2010-01-01", - ], - }, - "selected": false, - "y": 892589.3891729144, - }, - { - "custom": { - "rawValue": 904228.5180767283, - "xValue": [ - "2010-02-01", - ], - }, - "selected": false, - "y": 904228.5180767283, - }, - { - "custom": { - "rawValue": 912866.4678721044, - "xValue": [ - "2010-03-01", - ], - }, - "selected": false, - "y": 912866.4678721044, - }, - { - "custom": { - "rawValue": 916526.9340331501, - "xValue": [ - "2010-04-01", - ], - }, - "selected": false, - "y": 916526.9340331501, - }, - { - "custom": { - "rawValue": 914095.3329283679, - "xValue": [ - "2010-05-01", - ], - }, - "selected": false, - "y": 914095.3329283679, - }, - { - "custom": { - "rawValue": 904960.4685997746, - "xValue": [ - "2010-06-01", - ], - }, - "selected": false, - "y": 904960.4685997746, - }, - { - "custom": { - "rawValue": 912084.7216383086, - "xValue": [ - "2010-07-01", - ], - }, - "selected": false, - "y": 912084.7216383086, - }, - { - "custom": { - "rawValue": 945423.4204832909, - "xValue": [ - "2010-08-01", - ], - }, - "selected": false, - "y": 945423.4204832909, - }, - { - "custom": { - "rawValue": 1009017.2938368567, - "xValue": [ - "2010-09-01", - ], - }, - "selected": false, - "y": 1009017.2938368567, - }, - { - "custom": { - "rawValue": 1127908.0165300977, - "xValue": [ - "2010-10-01", - ], - }, - "selected": false, - "y": 1127908.0165300977, - }, - { - "custom": { - "rawValue": 1260348.35798684, - "xValue": [ - "2010-11-01", - ], - }, - "selected": false, - "y": 1260348.35798684, - }, - { - "custom": { - "rawValue": 1301643.164863898, - "xValue": [ - "2010-12-01", - ], - }, - "selected": false, - "y": 1301643.164863898, - }, - { - "custom": { - "rawValue": 1226332.721934023, - "xValue": [ - "2011-01-01", - ], - }, - "selected": false, - "y": 1226332.721934023, - }, - { - "custom": { - "rawValue": 1175483.052081485, - "xValue": [ - "2011-02-01", - ], - }, - "selected": false, - "y": 1175483.052081485, - }, - { - "custom": { - "rawValue": 1259954.2895959807, - "xValue": [ - "2011-03-01", - ], - }, - "selected": false, - "y": 1259954.2895959807, - }, - { - "custom": { - "rawValue": 1477513.9658073424, - "xValue": [ - "2011-04-01", - ], - }, - "selected": false, - "y": 1477513.9658073424, - }, - { - "custom": { - "rawValue": 1731745.1938052739, - "xValue": [ - "2011-05-01", - ], - }, - "selected": false, - "y": 1731745.1938052739, - }, - { - "custom": { - "rawValue": 1918408.774731447, - "xValue": [ - "2011-06-01", - ], - }, - "selected": false, - "y": 1918408.774731447, - }, - { - "custom": { - "rawValue": 2019625.0977478286, - "xValue": [ - "2011-07-01", - ], - }, - "selected": false, - "y": 2019625.0977478286, - }, - { - "custom": { - "rawValue": 2080349.5218863264, - "xValue": [ - "2011-08-01", - ], - }, - "selected": false, - "y": 2080349.5218863264, - }, - { - "custom": { - "rawValue": 2160577.230230905, - "xValue": [ - "2011-09-01", - ], - }, - "selected": false, - "y": 2160577.230230905, - }, - { - "custom": { - "rawValue": 2330053.153545553, - "xValue": [ - "2011-10-01", - ], - }, - "selected": false, - "y": 2330053.153545553, - }, - { - "custom": { - "rawValue": 2515328.951597531, - "xValue": [ - "2011-11-01", - ], - }, - "selected": false, - "y": 2515328.951597531, - }, - { - "custom": { - "rawValue": 2571323.757848365, - "xValue": [ - "2011-12-01", - ], - }, - "selected": false, - "y": 2571323.757848365, - }, - { - "custom": { - "rawValue": 2455225.182035394, - "xValue": [ - "2012-01-01", - ], - }, - "selected": false, - "y": 2455225.182035394, - }, - { - "custom": { - "rawValue": 2372277.1257133014, - "xValue": [ - "2012-02-01", - ], - }, - "selected": false, - "y": 2372277.1257133014, - }, - { - "custom": { - "rawValue": 2390716.0906670545, - "xValue": [ - "2012-03-01", - ], - }, - "selected": false, - "y": 2390716.0906670545, - }, - { - "custom": { - "rawValue": 2454806.7004078142, - "xValue": [ - "2012-04-01", - ], - }, - "selected": false, - "y": 2454806.7004078142, - }, - { - "custom": { - "rawValue": 2509923.7089504977, - "xValue": [ - "2012-05-01", - ], - }, - "selected": false, - "y": 2509923.7089504977, - }, - { - "custom": { - "rawValue": 2529590.1527741267, - "xValue": [ - "2012-06-01", - ], - }, - "selected": false, - "y": 2529590.1527741267, - }, - { - "custom": { - "rawValue": 2580856.1512703863, - "xValue": [ - "2012-07-01", - ], - }, - "selected": false, - "y": 2580856.1512703863, - }, - { - "custom": { - "rawValue": 2713417.6342164744, - "xValue": [ - "2012-08-01", - ], - }, - "selected": false, - "y": 2713417.6342164744, - }, - { - "custom": { - "rawValue": 2969220.9206936043, - "xValue": [ - "2012-09-01", - ], - }, - "selected": false, - "y": 2969220.9206936043, - }, - { - "custom": { - "rawValue": 3328777.947662453, - "xValue": [ - "2012-10-01", - ], - }, - "selected": false, - "y": 3328777.947662453, - }, - { - "custom": { - "rawValue": 3620949.4273355627, - "xValue": [ - "2012-11-01", - ], - }, - "selected": false, - "y": 3620949.4273355627, - }, - { - "custom": { - "rawValue": 3556054.100029769, - "xValue": [ - "2012-12-01", - ], - }, - "selected": false, - "y": 3556054.100029769, - }, - { - "custom": { - "rawValue": 3180837.955961699, - "xValue": [ - "2013-01-01", - ], - }, - "selected": false, - "y": 3180837.955961699, - }, - { - "custom": { - "rawValue": 2940071.145840517, - "xValue": [ - "2013-02-01", - ], - }, - "selected": false, - "y": 2940071.145840517, - }, - { - "custom": { - "rawValue": 2928282.3596065277, - "xValue": [ - "2013-03-01", - ], - }, - "selected": false, - "y": 2928282.3596065277, - }, - { - "custom": { - "rawValue": 3012322.5051070023, - "xValue": [ - "2013-04-01", - ], - }, - "selected": false, - "y": 3012322.5051070023, - }, - { - "custom": { - "rawValue": 3126610.365876169, - "xValue": [ - "2013-05-01", - ], - }, - "selected": false, - "y": 3126610.365876169, - }, - { - "custom": { - "rawValue": 3213000.749829498, - "xValue": [ - "2013-06-01", - ], - }, - "selected": false, - "y": 3213000.749829498, - }, - { - "custom": { - "rawValue": 3314632.0388838113, - "xValue": [ - "2013-07-01", - ], - }, - "selected": false, - "y": 3314632.0388838113, - }, - { - "custom": { - "rawValue": 3504006.725372224, - "xValue": [ - "2013-08-01", - ], - }, - "selected": false, - "y": 3504006.725372224, - }, - { - "custom": { - "rawValue": 3819677.0195216006, - "xValue": [ - "2013-09-01", - ], - }, - "selected": false, - "y": 3819677.0195216006, - }, - { - "custom": { - "rawValue": 3984064.438412456, - "xValue": [ - "2013-10-01", - ], - }, - "selected": false, - "y": 3984064.438412456, - }, - { - "custom": { - "rawValue": 3403293.012026755, - "xValue": [ - "2013-11-01", - ], - }, - "selected": false, - "y": 3403293.012026755, - }, - { - "custom": { - "rawValue": 1735405.3318556482, - "xValue": [ - "2013-12-01", - ], - }, - "selected": false, - "y": 1735405.3318556482, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-01-01", - ], - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-02-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-03-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-04-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-05-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2014-06-01", - ], - }, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "lineWidth": 3, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "$trend_Total Cost", - "showInLegend": false, - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "yAxis": 0, - "zIndex": 1, - }, - { - "boostThreshold": 0, - "color": "#00cee6", - "connectNulls": false, - "dashStyle": "ShortDash", - "data": [ - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-12-01", - ], - }, - "high": NaN, - "low": NaN, - "selected": false, - "y": 170444.1994921565, - }, - { - "custom": { - "rawValue": 894228.9346309917, - "xValue": [ - "2014-01-01", - ], - }, - "high": 2502270.7452848963, - "low": -267349.629913955, - "selected": false, - "y": 894228.9346309917, - }, - { - "custom": { - "rawValue": 1089836.547888303, - "xValue": [ - "2014-02-01", - ], - }, - "high": 2774896.364626469, - "low": -216031.2869008225, - "selected": false, - "y": 1089836.547888303, - }, - { - "custom": { - "rawValue": 1021374.1984700696, - "xValue": [ - "2014-03-01", - ], - }, - "high": 2529612.5733055985, - "low": -306281.90247843356, - "selected": false, - "y": 1021374.1984700696, - }, - { - "custom": { - "rawValue": 1128726.544473912, - "xValue": [ - "2014-04-01", - ], - }, - "high": 2586368.303115316, - "low": -598197.3911145851, - "selected": false, - "y": 1128726.544473912, - }, - { - "custom": { - "rawValue": 1128726.544473912, - "xValue": [ - "2014-05-01", - ], - }, - "high": 2506222.5577449454, - "low": 280299.5523669169, - "selected": false, - "y": 1128726.544473912, - }, - { - "custom": { - "rawValue": 1128726.5444739123, - "xValue": [ - "2014-06-01", - ], - }, - "high": 2555594.430841752, - "low": -298656.8438444736, - "selected": false, - "y": 1128726.5444739123, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "lineWidth": 3, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "$forecast_Total Revenue", - "showInLegend": false, - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "yAxis": 0, - "zIndex": 1, - }, - { - "boostThreshold": 0, - "color": "#9b9bd7", - "connectNulls": false, - "dashStyle": "ShortDash", - "data": [ - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-12-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-01-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-02-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-03-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-04-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-05-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-06-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-07-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-08-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-09-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-10-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-11-01", - ], - }, - "high": NaN, - "low": NaN, - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "y": NaN, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-12-01", - ], - }, - "high": NaN, - "low": NaN, - "selected": false, - "y": 770441.3868424296, - }, - { - "custom": { - "rawValue": 3432902.395304515, - "xValue": [ - "2014-01-01", - ], - }, - "high": 4215621.114209566, - "low": 2749857.8158302745, - "selected": false, - "y": 3432902.395304515, - }, - { - "custom": { - "rawValue": 3455861.1150580775, - "xValue": [ - "2014-02-01", - ], - }, - "high": 4257156.218797659, - "low": 2739222.412611501, - "selected": false, - "y": 3455861.1150580775, - }, - { - "custom": { - "rawValue": 3491353.7095914274, - "xValue": [ - "2014-03-01", - ], - }, - "high": 4254548.220516098, - "low": 2768469.4185458464, - "selected": false, - "y": 3491353.7095914274, - }, - { - "custom": { - "rawValue": 3601096.993465676, - "xValue": [ - "2014-04-01", - ], - }, - "high": 4354370.65910466, - "low": 2787704.494487667, - "selected": false, - "y": 3601096.993465676, - }, - { - "custom": { - "rawValue": 3512644.745014943, - "xValue": [ - "2014-05-01", - ], - }, - "high": 4249394.877735277, - "low": 2894009.6375730764, - "selected": false, - "y": 3512644.745014943, - }, - { - "custom": { - "rawValue": 3570184.1638095835, - "xValue": [ - "2014-06-01", - ], - }, - "high": 4319327.450568654, - "low": 2820929.6467809775, - "selected": false, - "y": 3570184.1638095835, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "lineWidth": 3, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "$forecast_Total Cost", - "showInLegend": false, - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "yAxis": 0, - "zIndex": 1, - }, - { - "boostThreshold": 0, - "color": "#00cee6", - "connectNulls": false, - "data": [ - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Revenue_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-12-01", - ], - }, - "high": 170444.1994921565, - "low": 170444.1994921565, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 2502270.7452848963, - "xValue": [ - "2014-01-01", - ], - }, - "high": 2502270.7452848963, - "low": -267349.629913955, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 2774896.364626469, - "xValue": [ - "2014-02-01", - ], - }, - "high": 2774896.364626469, - "low": -216031.2869008225, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 2529612.5733055985, - "xValue": [ - "2014-03-01", - ], - }, - "high": 2529612.5733055985, - "low": -306281.90247843356, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 2586368.303115316, - "xValue": [ - "2014-04-01", - ], - }, - "high": 2586368.303115316, - "low": -598197.3911145851, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 2506222.5577449454, - "xValue": [ - "2014-05-01", - ], - }, - "high": 2506222.5577449454, - "low": 280299.5523669169, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 2555594.430841752, - "xValue": [ - "2014-06-01", - ], - }, - "high": 2555594.430841752, - "low": -298656.8438444736, - "lowerPointName": "$forecast_Total Revenue_lower", - "selected": false, - "upperPointName": "$forecast_Total Revenue_upper", - "y": undefined, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "enableMouseTracking": false, - "fillOpacity": 0.15, - "lineWidth": 0, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "$forecast_Total Revenue $range", - "showInLegend": false, - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "type": "arearange", - "yAxis": 0, - }, - { - "boostThreshold": 0, - "color": "#9b9bd7", - "connectNulls": false, - "data": [ - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2009-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2010-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2011-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2012-12-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-01-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-02-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-03-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-04-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-05-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-06-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-07-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-08-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-09-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-10-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-11-01", - ], - }, - "high": NaN, - "low": NaN, - "lowerPointName": "$forecast_Total Cost_lower", - "marker": { - "enabled": true, - "isIsolatedPoint": true, - }, - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": "N\\A", - "xValue": [ - "2013-12-01", - ], - }, - "high": 770441.3868424296, - "low": 770441.3868424296, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 4215621.114209566, - "xValue": [ - "2014-01-01", - ], - }, - "high": 4215621.114209566, - "low": 2749857.8158302745, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 4257156.218797659, - "xValue": [ - "2014-02-01", - ], - }, - "high": 4257156.218797659, - "low": 2739222.412611501, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 4254548.220516098, - "xValue": [ - "2014-03-01", - ], - }, - "high": 4254548.220516098, - "low": 2768469.4185458464, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 4354370.65910466, - "xValue": [ - "2014-04-01", - ], - }, - "high": 4354370.65910466, - "low": 2787704.494487667, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 4249394.877735277, - "xValue": [ - "2014-05-01", - ], - }, - "high": 4249394.877735277, - "low": 2894009.6375730764, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - { - "custom": { - "rawValue": 4319327.450568654, - "xValue": [ - "2014-06-01", - ], - }, - "high": 4319327.450568654, - "low": 2820929.6467809775, - "lowerPointName": "$forecast_Total Cost_lower", - "selected": false, - "upperPointName": "$forecast_Total Cost_upper", - "y": undefined, - }, - ], - "dataLabels": { - "formatter": [Function], - }, - "enableMouseTracking": false, - "fillOpacity": 0.15, - "lineWidth": 0, - "marker": { - "enabled": false, - "fillColor": null, - "fillOpacity": 0.3, - "lineColor": null, - "lineWidth": 2, - "radius": 4, - "states": { - "hover": { - "fillColor": "#FFFFFF", - "lineWidth": 3, - "radius": 6, - }, - }, - "symbol": "circle", - }, - "name": "$forecast_Total Cost $range", - "showInLegend": false, - "showInNavigator": true, - "stickyTracking": false, - "turboThreshold": 0, - "type": "arearange", - "yAxis": 0, - }, - ], - "title": { - "text": null, - }, - "tooltip": { - "animation": false, - "backgroundColor": "#FFFFFF", - "borderColor": "#CCCCCC", - "borderRadius": 10, - "borderWidth": 1, - "formatter": [Function], - "style": { - "fontFamily": "Open Sans", - }, - "useHTML": true, - }, - "xAxis": [ - { - "categories": [ - "2009-11", - "2009-12", - "2010-01", - "2010-02", - "2010-03", - "2010-04", - "2010-05", - "2010-06", - "2010-07", - "2010-08", - "2010-09", - "2010-10", - "2010-11", - "2010-12", - "2011-01", - "2011-02", - "2011-03", - "2011-04", - "2011-05", - "2011-06", - "2011-07", - "2011-08", - "2011-09", - "2011-10", - "2011-11", - "2011-12", - "2012-01", - "2012-02", - "2012-03", - "2012-04", - "2012-05", - "2012-06", - "2012-07", - "2012-08", - "2012-09", - "2012-10", - "2012-11", - "2012-12", - "2013-01", - "2013-02", - "2013-03", - "2013-04", - "2013-05", - "2013-06", - "2013-07", - "2013-08", - "2013-09", - "2013-10", - "2013-11", - "2013-12", - "2014-01", - "2014-02", - "2014-03", - "2014-04", - "2014-05", - "2014-06", - ], - "endOnTick": false, - "gridLineColor": "#d1d1d7", - "gridLineDashStyle": "Dot", - "gridLineWidth": 0, - "labels": { - "autoRotation": [ - -10, - -20, - -30, - -40, - -50, - -60, - -70, - -80, - -90, - ], - "enabled": true, - "formatter": [Function], - "overflow": "none", - "style": { - "color": "#5B6372", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "normal", - "pointerEvents": "none", - "textOutline": "none", - }, - }, - "lineColor": "#d1d1d7", - "lineWidth": 1, - "max": null, - "min": null, - "minorGridLineColor": "#d1d1d7", - "minorGridLineWidth": 0, - "minorTickColor": "#d1d1d7", - "plotBands": [ - { - "borderWidth": 0, - "color": "#F7F7FA", - "from": 49, - "label": { - "style": { - "color": "#5B6372", - "fontFamily": "Open Sans", - }, - }, - "to": 56, - }, - ], - "plotLines": [], - "startOnTick": false, - "tickColor": "#d1d1d7", - "tickInterval": null, - "tickWidth": 0, - "tickmarkPlacement": "on", - "title": { - "enabled": false, - "margin": 25, - "style": { - "color": "#5B6372", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "normal", - "pointerEvents": "none", - "textOutline": "none", - }, - "text": "X Axis title", - }, - "type": "linear", - }, - ], - "yAxis": [ - { - "endOnTick": true, - "gridLineColor": "#d1d1d7", - "gridLineDashStyle": "Dot", - "gridLineWidth": 1, - "labels": { - "autoRotation": [ - -10, - -20, - -30, - -40, - -50, - -60, - -70, - -80, - -90, - ], - "enabled": true, - "formatter": [Function], - "style": { - "color": "#5B6372", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "normal", - "pointerEvents": "none", - "textOutline": "none", - }, - }, - "lineColor": "#d1d1d7", - "lineWidth": 1, - "max": 6468195.891011775, - "min": -598197.3911145851, - "minorGridLineColor": "#d1d1d7", - "minorGridLineDashStyle": "Dot", - "minorGridLineWidth": 0, - "minorTickColor": "#d1d1d7", - "minorTickWidth": 0, - "plotBands": undefined, - "showLastLabel": true, - "stackLabels": { - "allowOverlap": false, - "crop": true, - "enabled": false, - "labelrank": 99999, - "rotation": 0, - "style": { - "color": "#56535b", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "bold", - "pointerEvents": "none", - "textOutline": "none", - "textOverflow": "ellipsis", - }, - }, - "startOnTick": true, - "tickColor": "#d1d1d7", - "tickInterval": null, - "tickWidth": 0, - "tickmarkPlacement": "on", - "title": { - "enabled": false, - "margin": 25, - "style": { - "color": "#5B6372", - "fontFamily": "Open Sans", - "fontSize": "13px", - "fontWeight": "normal", - "pointerEvents": "none", - "textOutline": "none", - }, - "text": "Y Axis title", - }, - "type": "linear", - }, - ], -} -`; - exports[`Advanced Charts > should render trend chart 1`] = ` { "accessibility": { diff --git a/packages/sdk-ui/src/chart/advanced-chart.test.tsx b/packages/sdk-ui/src/chart/advanced-chart.test.tsx index bb97bb23..20ed30f1 100644 --- a/packages/sdk-ui/src/chart/advanced-chart.test.tsx +++ b/packages/sdk-ui/src/chart/advanced-chart.test.tsx @@ -12,9 +12,11 @@ import { setTimeout } from 'timers/promises'; const contextProviderProps: SisenseContextProviderProps = { url: mockUrl, token: mockToken, - enableTracking: false, defaultDataSource: 'Sample ECommerce', - appConfig: { queryCacheConfig: { enabled: false } }, + appConfig: { + queryCacheConfig: { enabled: false }, + trackingConfig: { enabled: false }, + }, }; describe('Advanced Charts', () => { diff --git a/packages/sdk-ui/src/charts/map-charts/areamap/areamap-map.tsx b/packages/sdk-ui/src/charts/map-charts/areamap/areamap-map.tsx index 32841828..81e5677f 100644 --- a/packages/sdk-ui/src/charts/map-charts/areamap/areamap-map.tsx +++ b/packages/sdk-ui/src/charts/map-charts/areamap/areamap-map.tsx @@ -10,7 +10,9 @@ import { GeoDataElement } from '../../../chart-data/types.js'; import { scaleBrightness } from '../../../utils/color/index.js'; import { AreamapType } from '../../../types.js'; import { createFeatureStylesDictionary, FeaturesDictionary } from './feature-styles-dictionary.js'; +import { useThemeContext } from '@/theme-provider'; import '../map-charts.scss'; +import { prepareFitBoundsAnimationOptions } from '../scattermap/utils/map.js'; export type AreamapProps = { geoJson: GeoJsonFeatureCollection; @@ -26,6 +28,7 @@ export type AreamapProps = { * Component that renders a map with areas (countries or states) for using in Areamap chart */ export const AreamapMap: React.FC = ({ geoJson, geoData, dataOptions, mapType }) => { + const { themeSettings } = useThemeContext(); const mapContainer = useRef(null); const mapInstance = useRef(null); const [mapLayerGroup] = useState(Leaflet.layerGroup()); @@ -79,9 +82,12 @@ export const AreamapMap: React.FC = ({ geoJson, geoData, dataOptio if (mapInstance.current) { mapLayerGroup.clearLayers(); mapLayerGroup.addLayer(geoJsonLayer); - mapInstance.current.fitBounds(geoJsonLayer.getBounds()); + mapInstance.current.fitBounds( + geoJsonLayer.getBounds(), + prepareFitBoundsAnimationOptions(themeSettings), + ); } - }, [dataOptions, featureStylesDictionary, geoJson, mapLayerGroup]); + }, [dataOptions, featureStylesDictionary, geoJson, mapLayerGroup, themeSettings]); return (
{ ...actual, useSisenseContext: vi.fn(() => { return { - app: { settings: { serverVersion: 'mockVersion' } }, + app: { + settings: { + serverVersion: 'mockVersion', + trackingConfig: { + enabled: false, + }, + }, + }, isInitialized: true, - enableTracking: false, }; }), }; diff --git a/packages/sdk-ui/src/charts/map-charts/scattermap/scattermap.tsx b/packages/sdk-ui/src/charts/map-charts/scattermap/scattermap.tsx index 60ca2033..97aeface 100644 --- a/packages/sdk-ui/src/charts/map-charts/scattermap/scattermap.tsx +++ b/packages/sdk-ui/src/charts/map-charts/scattermap/scattermap.tsx @@ -10,7 +10,7 @@ import { useGeoSettings } from './hooks/use-settings.js'; import { getLocationsMarkerColors } from './utils/color.js'; import { createMarker, removeMarkers } from './utils/markers.js'; import { addCopyright } from './utils/copyright.js'; -import { fitMapToBounds } from './utils/map.js'; +import { fitMapToBounds, prepareFitBoundsAnimationOptions } from './utils/map.js'; import { ChartDataOptionsInternal, ScattermapChartDataOptionsInternal, @@ -23,6 +23,7 @@ import '../map-charts.scss'; import './scattermap.scss'; import { DesignOptions } from '@/chart-options-processor/translations/types.js'; import { ChartRendererProps } from '@/chart/types.js'; +import { useThemeContext } from '@/theme-provider'; export type ScattermapProps = { chartData: ScattermapChartData; @@ -43,6 +44,7 @@ export const Scattermap = ({ }: ScattermapProps) => { const { locations } = chartData; const geoSettings = useGeoSettings(); + const { themeSettings } = useThemeContext(); const locationsWithCoordinates = useLocations(locations, dataOptions.locationLevel); @@ -110,7 +112,7 @@ export const Scattermap = ({ color: markerColors[index], size: markerSizes[index], fill: designOptions.markers.fill, - blur: locationWithCoordinates.blur, + blur: !!locationWithCoordinates.blur, }, }); @@ -135,13 +137,18 @@ export const Scattermap = ({ }); }); - fitMapToBounds(mapInstance.current!, markersRef.current); + fitMapToBounds( + mapInstance.current!, + markersRef.current, + prepareFitBoundsAnimationOptions(themeSettings), + ); } }, [ locationsWithCoordinates, markerColors, markerSizes, designOptions, + themeSettings, tooltipHandler, onDataPointClick, ]); diff --git a/packages/sdk-ui/src/charts/map-charts/scattermap/utils/map.ts b/packages/sdk-ui/src/charts/map-charts/scattermap/utils/map.ts index 8bfdea92..99569ad3 100644 --- a/packages/sdk-ui/src/charts/map-charts/scattermap/utils/map.ts +++ b/packages/sdk-ui/src/charts/map-charts/scattermap/utils/map.ts @@ -1,13 +1,36 @@ -import leaflet from 'leaflet'; +import { CompleteThemeSettings } from '@/index'; +import leaflet, { type FitBoundsOptions } from 'leaflet'; -export function fitMapToBounds(map: leaflet.Map, markers: leaflet.CircleMarker[]) { +const DEFAULT_ANIMATION_DURATION = 250; + +type FitBoundsAnimationOptions = Pick; + +export function prepareFitBoundsAnimationOptions( + themeSettings: CompleteThemeSettings, +): FitBoundsAnimationOptions { + const duration = + themeSettings.chart.animation.init.duration === 'auto' + ? DEFAULT_ANIMATION_DURATION + : themeSettings.chart.animation.init.duration; + + return { + animate: duration !== 0, + duration: duration / 1000, + }; +} + +export function fitMapToBounds( + map: leaflet.Map, + markers: leaflet.CircleMarker[], + options: FitBoundsOptions = {}, +) { if (!markers.length) return; map.fitBounds( markers.map((marker) => [marker.getLatLng().lat, marker.getLatLng().lng]), { - animate: true, maxZoom: 4, + ...options, }, ); } diff --git a/packages/sdk-ui/src/charts/map-charts/scattermap/utils/markers.ts b/packages/sdk-ui/src/charts/map-charts/scattermap/utils/markers.ts index e8590bbe..d4008e7c 100644 --- a/packages/sdk-ui/src/charts/map-charts/scattermap/utils/markers.ts +++ b/packages/sdk-ui/src/charts/map-charts/scattermap/utils/markers.ts @@ -5,7 +5,7 @@ type MarkerStyle = { color: string; size: number; fill: Required['fill']; - blur: boolean; + blur?: boolean; }; export type MarkerConfig = { diff --git a/packages/sdk-ui/src/charts/table/data-table-wrapper.tsx b/packages/sdk-ui/src/charts/table/data-table-wrapper.tsx index c2e38c66..e526522f 100644 --- a/packages/sdk-ui/src/charts/table/data-table-wrapper.tsx +++ b/packages/sdk-ui/src/charts/table/data-table-wrapper.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Table, Column, Cell } from 'fixed-data-table-2'; import 'fixed-data-table-2/dist/fixed-data-table.css'; import styles from './styles/data-table-wrapper.module.scss'; @@ -61,14 +61,12 @@ const renderDisplayValue = ({ export const DataTableWrapper = ({ dataTable, dataOptions, - isLoading, height, width, customStyles, themeSettings, onSortUpdate, }: DataTableWrapperProps) => { - const previousIsLoadingRef = useRef(isLoading); const showFieldTypeIcon = customStyles && customStyles.showFieldTypeIcon !== undefined ? customStyles.showFieldTypeIcon @@ -77,152 +75,133 @@ export const DataTableWrapper = ({ const verticalPadding = customStyles?.paddingVertical || DEFAULT_PADDING; const horizontalPadding = customStyles?.paddingHorizontal || DEFAULT_PADDING; + // minus 1px need to avoid crop of right border + const widthVal = + customStyles?.columns?.width === 'auto' + ? (width - horizontalPadding * 2 - 1) / dataOptions.columns.length + : undefined; + const columnsOptions = useMemo( () => dataOptions.columns.map((col) => ({ - isHtml: (col as Category).isHtml ?? false, - ...(customStyles?.columns?.width === 'auto' - ? // minus 1px need to avoid crop of right border - { - width: - (width - horizontalPadding * 2) / dataOptions.columns.length - - 1 / dataOptions.columns.length, - } - : null), + isHtml: !!(col as Category).isHtml, + width: widthVal, })), - [dataOptions, width, customStyles?.columns?.width, horizontalPadding], + [dataOptions.columns, widthVal], ); - const [columnWidths, setColumnWidths] = useState(() => - calcColumnWidths( - dataTable, - isLoading, - showFieldTypeIcon, - columnsOptions, - themeSettings.typography?.fontFamily, - ), - ); + const [fontsLoaded, setFontsLoaded] = useState(document.fonts?.status === 'loaded'); - useEffect(() => { - if (isLoading !== previousIsLoadingRef.current) { - if (!isLoading) { - // transitioning from isLoading to done - setColumnWidths( - calcColumnWidths( - dataTable, - isLoading, - showFieldTypeIcon, - columnsOptions, - themeSettings.typography?.fontFamily, - ), - ); - } - previousIsLoadingRef.current = isLoading; - } - }, [isLoading, dataTable, themeSettings, columnsOptions, showFieldTypeIcon]); + const fontFamily = themeSettings.typography?.fontFamily; + const columnWidths = useMemo(() => { + void fontsLoaded; + return calcColumnWidths(dataTable, showFieldTypeIcon, columnsOptions, fontFamily); + }, [dataTable, showFieldTypeIcon, columnsOptions, fontFamily, fontsLoaded]); - const isFontLoadingObserved = useRef(false); useEffect(() => { - if (!isFontLoadingObserved.current && document.fonts) { - isFontLoadingObserved.current = true; - document.fonts.ready - .then(() => { - setColumnWidths( - calcColumnWidths( - dataTable, - isLoading, - showFieldTypeIcon, - columnsOptions, - themeSettings.typography?.fontFamily, - ), - ); - }) - .catch((e) => { - throw e; - }); - } - }, [ - dataTable, - isLoading, - columnsOptions, - themeSettings.typography?.fontFamily, - showFieldTypeIcon, - ]); + document.fonts?.ready + .then(() => { + setFontsLoaded(true); + }) + .catch((e) => { + console.warn('Failed to observe font loading', e); + }); + }, []); - return ( -
- - {dataTable.columns.map((column, colIndex) => { - return columnWidths[colIndex] ? ( - - - {renderDisplayValue({ - displayValue: - dataOptions.columns[colIndex].title ?? dataOptions.columns[colIndex].name, - width: columnWidths[colIndex], - padding: headerPadding, - ellipsizedLength: HEADER_ELLIPSIZED_LENGTH, - })} - - - } - cell={({ rowIndex, ...props }) => ( - + dataTable.columns.map((column, colIndex) => { + // eslint-disable-next-line security/detect-object-injection + const columnWidth = columnWidths[colIndex]; + // eslint-disable-next-line security/detect-object-injection + const columnOptions = dataOptions.columns[colIndex]; + const headerCellStyle = getCellStyles({ + isHeaderCell: true, + themeSettings, + customStyles, + }); + return columnWidth ? ( + + {renderDisplayValue({ - displayValue: dataTable.rows[rowIndex][colIndex].displayValue, - width: columnWidths[colIndex], - padding: DATA_PADDING, - ellipsizedLength: DATA_ELLIPSIZED_LENGTH, - isHtml: (dataOptions.columns[colIndex] as Category).isHtml ?? false, + displayValue: columnOptions.title ?? columnOptions.name, + width: columnWidth, + padding: headerPadding, + ellipsizedLength: HEADER_ELLIPSIZED_LENGTH, })} - - )} - align={alignmentForColumnType(dataTable.columns[colIndex].type)} - /> - ) : null; - })} -
-
+ + + } + cell={({ rowIndex, ...props }) => ( + + {renderDisplayValue({ + // eslint-disable-next-line security/detect-object-injection + displayValue: dataTable.rows[rowIndex][colIndex].displayValue, + width: columnWidth, + padding: DATA_PADDING, + ellipsizedLength: DATA_ELLIPSIZED_LENGTH, + isHtml: (columnOptions as Category).isHtml ?? false, + })} + + )} + align={alignmentForColumnType(column.type)} + /> + ) : null; + }), + [ + dataTable, + columnWidths, + themeSettings, + customStyles, + onSortUpdate, + showFieldTypeIcon, + dataOptions, + headerPadding, + ], + ); + + return useMemo( + () => ( +
+ + {columns} +
+
+ ), + [columns, customStyles, dataTable, height, horizontalPadding, verticalPadding, width], ); }; diff --git a/packages/sdk-ui/src/charts/table/helpers/calc-column-widths.ts b/packages/sdk-ui/src/charts/table/helpers/calc-column-widths.ts index 155e0a06..24b92be8 100644 --- a/packages/sdk-ui/src/charts/table/helpers/calc-column-widths.ts +++ b/packages/sdk-ui/src/charts/table/helpers/calc-column-widths.ts @@ -10,7 +10,6 @@ import { export const calcColumnWidths = ( dataTable: DataTable, - isLoading: boolean, isShowFieldTypeIcon: boolean, columnsOptions: { isHtml: boolean; @@ -35,7 +34,7 @@ export const calcColumnWidths = ( return { type: simpleColumnType(column.type), index: column.index }; }); // get pixel width of longest data for each column - const rows = isLoading ? dataTable.rows.slice(0, 100) : dataTable.rows; + const { rows } = dataTable; const columnDataWidths = columnsWithSimpleTypes.map((column) => { const pixelForValue = rows.reduce((longestWidth, currentRow) => { const displayValue = currentRow[column.index].displayValue; diff --git a/packages/sdk-ui/src/charts/table/pure-table.tsx b/packages/sdk-ui/src/charts/table/pure-table.tsx index ad4da7c9..da397c49 100644 --- a/packages/sdk-ui/src/charts/table/pure-table.tsx +++ b/packages/sdk-ui/src/charts/table/pure-table.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useLayoutEffect, useMemo } from 'react'; +import { useRef, useLayoutEffect, useMemo } from 'react'; import { DataTableWrapper } from './data-table-wrapper'; import styles from './styles/table-chart.module.scss'; import { TableProps } from './types'; @@ -38,22 +38,24 @@ export const PureTable = ({ loadedTable.current = dataTable; }, [dataTable]); - const isLoading = dataTable !== loadedTable.current; + const customStyles = useMemo( + () => ({ + sortIcon: 'caret' as const, + showFieldTypeIcon: false, + ...designOptions, + }), + [designOptions], + ); return (
diff --git a/packages/sdk-ui/src/charts/table/types.ts b/packages/sdk-ui/src/charts/table/types.ts index 0de26bfa..84f76b32 100644 --- a/packages/sdk-ui/src/charts/table/types.ts +++ b/packages/sdk-ui/src/charts/table/types.ts @@ -49,7 +49,6 @@ export type TableProps = { export type DataTableWrapperProps = { dataTable: DataTable; dataOptions: TableDataOptionsInternal; - isLoading: boolean; height: number; width: number; customStyles?: TableCustomStyles; diff --git a/packages/sdk-ui/src/common-filters/cascading-utils.ts b/packages/sdk-ui/src/common-filters/cascading-utils.ts index 671882b7..6b183bd5 100644 --- a/packages/sdk-ui/src/common-filters/cascading-utils.ts +++ b/packages/sdk-ui/src/common-filters/cascading-utils.ts @@ -1,8 +1,8 @@ import { getFilterCompareId } from '@/dashboard-widget/utils'; -import { isCascadingFilter } from '@/utils/filters'; +import { clearMembersFilter, haveSameAttribute, isCascadingFilter } from '@/utils/filters'; import { CascadingFilter, Filter } from '@sisense/sdk-data'; import { FiltersIgnoringRules, PureFilter } from './types'; -import { clearCommonFilter, haveSameAttribute, isEqualMembersFilters } from './utils'; +import { isEqualMembersFilters } from './utils'; /** * Flattens cascading filters into a single array of filters. @@ -206,7 +206,7 @@ function resetFiltersDeeperThanModified( // Reset filters deeper than the deepest modified filter return newLevelFilters.map((newFilter, index) => { if (index > deepestModifiedNewFilterIndex) { - return clearCommonFilter(newFilter); + return clearMembersFilter(newFilter); } return newFilter; }); diff --git a/packages/sdk-ui/src/common-filters/common-filters-connector.tsx b/packages/sdk-ui/src/common-filters/common-filters-connector.tsx index 59ecbffd..d03a750a 100644 --- a/packages/sdk-ui/src/common-filters/common-filters-connector.tsx +++ b/packages/sdk-ui/src/common-filters/common-filters-connector.tsx @@ -10,12 +10,7 @@ import { PivotTableDataOptions, RenderToolbarHandler, } from '../index.js'; -import { - clearCommonFilter, - getAllowedFilters, - isIncludeAllFilter, - isSameAttribute, -} from './utils.js'; +import { getAllowedFilters } from './utils.js'; import { CommonFiltersApplyMode, CommonFiltersOptions, @@ -29,6 +24,7 @@ import { } from './selection-utils'; import { WidgetTypeInternal } from '@/models/widget/types'; import { withCascadingFiltersConversion } from './cascading-utils'; +import { isSameAttribute, isIncludeAllFilter, clearMembersFilter } from '@/utils/filters'; type CommonFiltersToWidgetConnectProps = Pick< ChartWidgetProps, @@ -121,11 +117,13 @@ export function prepareCommonFiltersToWidgetConnectProps( // registers "renderToolbar" handler const selectedFilters = enabledFilters.filter((f) => - selectableAttributes?.some((a) => isSameAttribute(f.attribute, a) && !isIncludeAllFilter(f)), + selectableAttributes?.some( + (a) => isSameAttribute(f.attribute, a) && !isIncludeAllFilter(f) && !f.locked, + ), ); const hasSelection = !!selectedFilters.length; const clearSelection = () => { - const deselectedFilters = selectedFilters.map(clearCommonFilter); + const deselectedFilters = selectedFilters.map(clearMembersFilter); updateFilters(mergeFilters(pureFilters, deselectedFilters)); }; diff --git a/packages/sdk-ui/src/common-filters/selection-utils.ts b/packages/sdk-ui/src/common-filters/selection-utils.ts index eab1ab1d..a2803821 100644 --- a/packages/sdk-ui/src/common-filters/selection-utils.ts +++ b/packages/sdk-ui/src/common-filters/selection-utils.ts @@ -5,6 +5,7 @@ import { isBoxplot, isCartesian, isCategorical, + isRange, isScatter, isScattermap, } from '@/chart-options-processor/translations/types'; @@ -28,13 +29,9 @@ import { StyledColumn, } from '../index.js'; import { ScatterCustomPointOptions } from '@/chart-options-processor/translations/scatter-tooltip.js'; -import { - clearCommonFilter, - createCommonFilter, - getFilterByAttribute, - isEqualMembersFilters, -} from './utils.js'; +import { createCommonFilter, getFilterByAttribute, isEqualMembersFilters } from './utils.js'; import { WidgetTypeInternal } from '@/models/widget/types.js'; +import { clearMembersFilter, haveSameAttribute } from '@/utils/filters.js'; type WidgetSelection = { attribute: Attribute; @@ -259,7 +256,12 @@ export function getSelectableWidgetAttributes( ...((dataOptions as PivotTableDataOptions).rows || []), ...((dataOptions as PivotTableDataOptions).columns || []), ]; - } else if (isCartesian(widgetType) || isCategorical(widgetType) || isBoxplot(widgetType)) { + } else if ( + isCartesian(widgetType) || + isCategorical(widgetType) || + isBoxplot(widgetType) || + isRange(widgetType) + ) { targetDataOptions = [...(dataOptions as CartesianChartDataOptions).category]; } else if (isScatter(widgetType)) { targetDataOptions = [ @@ -277,21 +279,41 @@ export function getSelectableWidgetAttributes( export function createCommonFiltersOverSelections( selections: WidgetSelection[], - filters: Filter[], + existingCommonFilters: Filter[], ) { - let selectedFilters = selections.map(({ attribute, values }) => - createCommonFilter(attribute, values, filters), + const commonFiltersFromSelections = selections.map(({ attribute, values }) => + createCommonFilter(attribute, values, existingCommonFilters), + ); + + const newSelectedFilters = removeLockedFilters( + existingCommonFilters, + commonFiltersFromSelections, ); - const enabledFilters = filters.filter((f) => !f.disabled); - const isAlreadySelectedFilters = selectedFilters.every((filter) => { + const enabledFilters = existingCommonFilters.filter((f) => !f.disabled); + const isAlreadySelectedFilters = newSelectedFilters.every((filter) => { const existingFilter = getFilterByAttribute(enabledFilters, filter.attribute); return existingFilter && isEqualMembersFilters(filter, existingFilter); }); if (isAlreadySelectedFilters) { - selectedFilters = selectedFilters.map(clearCommonFilter); + return newSelectedFilters.map(clearMembersFilter); } - return selectedFilters; + return newSelectedFilters; +} + +/** + * Removes filters, that are present in `existingFilters` and are locked, from `filtersToRemoveFrom` + */ +function removeLockedFilters(existingFilters: Filter[], filtersToRemoveFrom: Filter[]) { + const lockedExistingFilters = existingFilters.filter((filter) => filter.locked); + + if (!lockedExistingFilters.length) { + return filtersToRemoveFrom; + } + return filtersToRemoveFrom.filter( + (filter) => + !lockedExistingFilters.some((lockedFilter) => haveSameAttribute(lockedFilter, filter)), + ); } diff --git a/packages/sdk-ui/src/common-filters/types.ts b/packages/sdk-ui/src/common-filters/types.ts index f5fb6d41..bea21ea9 100644 --- a/packages/sdk-ui/src/common-filters/types.ts +++ b/packages/sdk-ui/src/common-filters/types.ts @@ -1,13 +1,17 @@ import { CascadingFilter, Filter } from '@sisense/sdk-data'; import { DeepRequired } from 'ts-essentials'; -/** @internal */ +/** + * Common filters apply mode. + */ export enum CommonFiltersApplyMode { HIGHLIGHT = 'highlight', FILTER = 'filter', } -/** @internal */ +/** + * Options for common filters defined at the dashboard level to be applied to certain widgets. + */ export type CommonFiltersOptions = { applyMode?: `${CommonFiltersApplyMode}`; shouldAffectFilters?: boolean; @@ -15,7 +19,9 @@ export type CommonFiltersOptions = { forceApplyBackgroundFilters?: boolean; }; -/** @internal */ +/** + * Filters ignoring rules. + */ export type FiltersIgnoringRules = { all?: boolean; ids?: string[]; diff --git a/packages/sdk-ui/src/common-filters/utils.ts b/packages/sdk-ui/src/common-filters/utils.ts index c8b55779..83264f10 100644 --- a/packages/sdk-ui/src/common-filters/utils.ts +++ b/packages/sdk-ui/src/common-filters/utils.ts @@ -1,10 +1,5 @@ -import { - Filter, - Attribute, - DimensionalLevelAttribute, - filterFactory, - MembersFilter, -} from '@sisense/sdk-data'; +import { isSameAttribute, haveSameAttribute } from '@/utils/filters.js'; +import { Filter, Attribute, filterFactory, MembersFilter } from '@sisense/sdk-data'; import isEqual from 'lodash/isEqual'; import { FiltersIgnoringRules, PureFilter } from './types.js'; @@ -21,14 +16,6 @@ export function getAllowedFilters( }); } -export function isSameAttribute(attributeA: Attribute, attributeB: Attribute) { - return ( - attributeA.expression === attributeB?.expression && - (attributeA as DimensionalLevelAttribute).granularity === - (attributeB as DimensionalLevelAttribute).granularity - ); -} - export function getFilterByAttribute(filters: Filter[], attribute: Attribute) { return filters.find((f) => isSameAttribute(f.attribute, attribute)); } @@ -49,10 +36,6 @@ export function createCommonFilter( ); } -export function haveSameAttribute(filterA: Filter, filterB: Filter) { - return isSameAttribute(filterA.attribute, filterB.attribute); -} - export function isEqualMembersFilters(filterA: Filter, filterB: Filter) { return ( haveSameAttribute(filterA, filterB) && @@ -61,16 +44,3 @@ export function isEqualMembersFilters(filterA: Filter, filterB: Filter) { isEqual((filterA as MembersFilter).members, (filterB as MembersFilter).members) ); } - -export function isIncludeAllFilter(filter: Filter) { - return 'members' in filter && (filter as MembersFilter).members.length === 0; -} - -function createIncludeAllFilter(attribute: Attribute, backgroundFilter?: Filter, guid?: string) { - return filterFactory.members(attribute, [], false, guid, undefined, backgroundFilter); -} - -export function clearCommonFilter(filter: Filter) { - const { attribute, guid, backgroundFilter } = filter as MembersFilter; - return createIncludeAllFilter(attribute, backgroundFilter, guid); -} diff --git a/packages/sdk-ui/src/common/hooks/use-has-changed.ts b/packages/sdk-ui/src/common/hooks/use-has-changed.ts index 67048076..35a6c177 100644 --- a/packages/sdk-ui/src/common/hooks/use-has-changed.ts +++ b/packages/sdk-ui/src/common/hooks/use-has-changed.ts @@ -11,18 +11,26 @@ import { usePrevious } from './use-previous'; */ export function useHasChanged( value: T, - propNames: Array, + propNames?: Array, compare?: (value: T, prev: T) => boolean, ) { const prev = usePrevious(value); - if (!prev) { + // compare primitive values and functions directly + if (!(typeof value === 'object') && value === prev) { + return false; + } + + if (prev === null || prev === undefined) { return true; } - const changed = propNames.some( - // eslint-disable-next-line security/detect-object-injection - (paramName) => !isEqual(prev[paramName], value[paramName]), - ); + const changed = propNames + ? propNames.some( + // eslint-disable-next-line security/detect-object-injection + (paramName) => !isEqual(prev[paramName], value[paramName]), + ) + : !isEqual(prev, value); + if (changed) { return true; } diff --git a/packages/sdk-ui/src/common/hooks/use-tracking.ts b/packages/sdk-ui/src/common/hooks/use-tracking.ts new file mode 100644 index 00000000..deac0e23 --- /dev/null +++ b/packages/sdk-ui/src/common/hooks/use-tracking.ts @@ -0,0 +1,87 @@ +import { useSisenseContext } from '@/sisense-context/sisense-context'; +import { HttpClient } from '@sisense/sdk-rest-client'; +import { + ErrorEventOptions, + eventRegistry, + TrackingEventType, + TrackingEventDetails, + trackProductEvent, +} from '@sisense/sdk-tracking'; +import { useCallback } from 'react'; + +export const executeTracking = ( + eventType: TrackingEventType, + eventPayload: TrackingEventDetails, + httpClient: HttpClient, + onTrackingEvent?: (payload: TrackingEventDetails) => void, + isDebugMode?: boolean, +) => { + const eventConfig = eventRegistry[`${eventType}`]; + + if (eventConfig.internal) { + trackProductEvent(eventType, eventPayload, httpClient, isDebugMode); + } + + if (eventConfig.external && !!onTrackingEvent) { + onTrackingEvent({ action: eventType, ...eventPayload }); + } + + return Promise.resolve(); +}; + +export const useTracking = () => { + const { tracking, app } = useSisenseContext(); + + const trackEvent = useCallback( + ( + eventType: TrackingEventType, + eventPayload: TrackingEventDetails = {}, + isDebugMode = false, + ) => { + if (!app) return Promise.resolve(); + + return executeTracking( + eventType, + eventPayload, + app.httpClient, + tracking.onTrackingEvent, + isDebugMode, + ); + }, + [tracking, app], + ); + + const trackError = useCallback( + (options: ErrorEventOptions, isDebugMode = false) => { + if (!app) return Promise.resolve(); + + const { packageName, packageVersion, component, error } = options; + let errorMessage = ''; + if (typeof error === 'string') { + errorMessage = error; + } else if (error instanceof Error) { + errorMessage = error.message || error.toString(); + } + + const payload = { + packageName, + packageVersion, + component, + error: errorMessage, + }; + return executeTracking( + 'sdkError', + payload, + app.httpClient, + tracking.onTrackingEvent, + isDebugMode, + ); + }, + [tracking, app], + ); + + return { + trackEvent, + trackError, + }; +}; diff --git a/packages/sdk-ui/src/dashboard-widget/dashboard-widget.test.tsx b/packages/sdk-ui/src/dashboard-widget/dashboard-widget.test.tsx index 44a1ed1d..d7dee073 100644 --- a/packages/sdk-ui/src/dashboard-widget/dashboard-widget.test.tsx +++ b/packages/sdk-ui/src/dashboard-widget/dashboard-widget.test.tsx @@ -21,7 +21,11 @@ describe('DashboardWidget', () => { expect.assertions(1); const { getByText } = render( - + , ); diff --git a/packages/sdk-ui/src/dashboard-widget/translate-widget-data-options.ts b/packages/sdk-ui/src/dashboard-widget/translate-widget-data-options.ts index 70614481..ff864b21 100644 --- a/packages/sdk-ui/src/dashboard-widget/translate-widget-data-options.ts +++ b/packages/sdk-ui/src/dashboard-widget/translate-widget-data-options.ts @@ -166,9 +166,21 @@ export function createDataColumn(item: PanelItem, customPaletteColors?: Color[]) const numberFormatConfig = extractNumberFormat(item); const subtotal = item.format?.subtotal; const width = item.format?.width; + let color = createValueColorOptions(item.format?.color, customPaletteColors); + + // Hande specific case in Fusion dashboard model + // Sunburst palette index stores that way + if (!color && !item.format?.color && item.format && 'colorIndex' in item.format) { + color = createValueColorOptions( + { + type: 'color', + colorIndex: item.format.colorIndex, + }, + customPaletteColors, + ); + } if (MetadataTypes.isMeasure(element)) { - const color = createValueColorOptions(item.format?.color, customPaletteColors); const showOnRightAxis = item.y2; const chartType = item.singleSeriesType; const totalsCalculation = 'subtotalAgg' in item.jaql && item.jaql.subtotalAgg; @@ -194,6 +206,7 @@ export function createDataColumn(item: PanelItem, customPaletteColors?: Color[]) ...(numberFormatConfig && { numberFormatConfig }), ...(subtotal && { includeSubTotals: subtotal }), ...(width && { width }), + ...(color && { color }), } as StyledColumn; } diff --git a/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.test.ts b/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.test.ts index 37c0d5d4..c1d8f37b 100644 --- a/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.test.ts +++ b/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.test.ts @@ -53,8 +53,8 @@ describe('translate widget drilldown options', () => { const drilldownOptions = extractDrilldownOptions('chart/column', panels); verifyColumn(dataOptions.category[0], panels[0].items[0].parent!.parent!); - verifyColumn(drilldownOptions?.drilldownDimensions![1]!, panels[0].items[0]); - verifyColumn(drilldownOptions?.drilldownDimensions![0]!, panels[0].items[0].parent!); + verifyColumn(drilldownOptions?.drilldownDimensions![1], panels[0].items[0]); + verifyColumn(drilldownOptions?.drilldownDimensions![0], panels[0].items[0].parent!); verifyColumn(drilldownOptions?.drilldownSelections![1].nextDimension, panels[0].items[0]); verifyColumn( diff --git a/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.ts b/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.ts index bc2bde40..f8c63c13 100644 --- a/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.ts +++ b/packages/sdk-ui/src/dashboard-widget/translate-widget-drilldown-options.ts @@ -5,6 +5,7 @@ import { getEnabledPanelItems } from './utils'; import { DataPoint, DrilldownOptions } from '../types'; import { applyDateFormat } from '../query/date-formats/apply-date-format'; import parseISO from 'date-fns/parseISO'; +import uniqBy from 'lodash/uniqBy'; const getAvailableDrilldowns = (item: PanelItem): Attribute[] => item?.parent @@ -36,33 +37,48 @@ const getDrilldownSelections = ( }; /** - * Gets the panel name allowed for drilling based on the widget type. + * Gets the panel names allowed for drilling based on the widget type. * * @param {WidgetType} widgetType - The type of the widget. * @returns {string[]} An array of panel names allowed for drilling. */ -function getDrilldownAllowedPanelName(widgetType: WidgetType) { +function getDrilldownAllowedPanelNames(widgetType: WidgetType) { switch (widgetType) { case 'chart/line': case 'chart/area': - return 'x-axis'; + return ['x-axis']; case 'chart/boxplot': - return 'category'; + return ['category']; + case 'chart/scatter': + return ['x-axis', 'y-axis', 'point', 'Break By / Color']; default: - return 'categories'; + return ['categories']; } } export const extractDrilldownOptions = ( widgetType: WidgetType, panels: Panel[], + drillHistory: PanelItem[] = [], + enableDrillToAnywhere?: boolean, ): DrilldownOptions => { - const categoriesPanelName = getDrilldownAllowedPanelName(widgetType); - const item = getEnabledPanelItems(panels, categoriesPanelName)[0]; - const drilldownSelections = getDrilldownSelections(item); - const drilldownDimensions = getAvailableDrilldowns(item); + const panelNames = getDrilldownAllowedPanelNames(widgetType); + const drilledItem = panelNames + .map((name) => getEnabledPanelItems(panels, name)) + .flat() + .find((item) => !!item.parent); + + const drilldownSelections = getDrilldownSelections(drilledItem); + const targetDrilldownDimensions = uniqBy( + [ + ...(drilledItem ? getAvailableDrilldowns(drilledItem) : []), + ...(enableDrillToAnywhere ? drillHistory.map(getAvailableDrilldowns).flat() : []), + ], + ({ expression }) => expression, + ); + return { - drilldownDimensions, + drilldownDimensions: targetDrilldownDimensions, drilldownSelections, }; }; diff --git a/packages/sdk-ui/src/dashboard-widget/types.ts b/packages/sdk-ui/src/dashboard-widget/types.ts index c2a0df61..470ea137 100644 --- a/packages/sdk-ui/src/dashboard-widget/types.ts +++ b/packages/sdk-ui/src/dashboard-widget/types.ts @@ -96,6 +96,7 @@ export interface WidgetDto { metadata: { ignore?: FiltersIgnoringRules; panels: Panel[]; + drillHistory?: PanelItem[]; }; style: WidgetStyle; title: string; @@ -103,6 +104,7 @@ export interface WidgetDto { options?: { dashboardFiltersMode: `${WidgetDashboardFilterMode}`; selector: boolean; + drillToAnywhere?: boolean; }; } @@ -177,6 +179,7 @@ export type PanelItem = { subtotal?: boolean; databars?: boolean; width?: number; + colorIndex?: number; }; jaql: Jaql; disabled?: boolean; diff --git a/packages/sdk-ui/src/dashboard/components/content-panel.tsx b/packages/sdk-ui/src/dashboard/components/content-panel.tsx index 543ce463..31cd9a36 100644 --- a/packages/sdk-ui/src/dashboard/components/content-panel.tsx +++ b/packages/sdk-ui/src/dashboard/components/content-panel.tsx @@ -11,24 +11,28 @@ import { TableWidget } from '@/widgets/table-widget'; import styled from '@emotion/styled'; import { PluginService } from './plugin-service'; -const DIVIDER_COLOR = '#f2f2f2'; -const DIVIDER_WIDTH = 4; - const Row = styled.div<{ widths: number[] }>` display: grid; grid-template-columns: ${({ widths }) => widths.map((w) => `${w}%`).join(' ')}; `; -const Column = styled.div` +const Column = styled.div<{ + dividerWidth: number; + dividerColor: string; +}>` &:not(:first-of-type) { - border-left: ${getDividerStyle(DIVIDER_COLOR, DIVIDER_WIDTH)}; + border-left: ${({ dividerWidth, dividerColor }) => getDividerStyle(dividerColor, dividerWidth)}; } `; -const Subcell = styled.div<{ height: string | number }>` - border-bottom: ${getDividerStyle(DIVIDER_COLOR, DIVIDER_WIDTH)}; +const Subcell = styled.div<{ + height: string | number; + dividerWidth: number; + dividerColor: string; +}>` + border-bottom: ${({ dividerWidth, dividerColor }) => getDividerStyle(dividerColor, dividerWidth)}; &:not(:first-of-type) { - border-left: ${getDividerStyle(DIVIDER_COLOR, DIVIDER_WIDTH)}; + border-left: ${({ dividerWidth, dividerColor }) => getDividerStyle(dividerColor, dividerWidth)}; } height: ${({ height }) => `calc(${height} + 32px)`}; `; @@ -78,7 +82,7 @@ const renderWidgetModel = (w: WidgetModel | undefined, theme: CompleteThemeSetti } else if (isPivotWidget(w.widgetType)) { return ; } else { - return ; + return ; } }; @@ -128,7 +132,11 @@ export const ContentPanel = ({ layout, widgets }: ContentPanelProps) => { return ( c.widthPercentage)}> {layout.columns.map((column, columnIndex) => ( - + {column.rows?.map((row, cellIndex) => ( { {renderWidgetModel( widgets.find((w) => w.oid === subcell.widgetId), diff --git a/packages/sdk-ui/src/dashboard/components/dashboard-container.tsx b/packages/sdk-ui/src/dashboard/components/dashboard-container.tsx index 07282406..09eae242 100644 --- a/packages/sdk-ui/src/dashboard/components/dashboard-container.tsx +++ b/packages/sdk-ui/src/dashboard/components/dashboard-container.tsx @@ -37,10 +37,10 @@ export const DashboardContainer = ({ const { themeSettings } = useThemeContext(); return ( - + diff --git a/packages/sdk-ui/src/dashboard/dashboard-by-id.tsx b/packages/sdk-ui/src/dashboard/dashboard-by-id.tsx index be7d88e3..76dc7478 100644 --- a/packages/sdk-ui/src/dashboard/dashboard-by-id.tsx +++ b/packages/sdk-ui/src/dashboard/dashboard-by-id.tsx @@ -3,15 +3,20 @@ import { Dashboard } from './dashboard'; import { DashboardByIdProps } from './types'; import { LoadingOverlay } from '@/common/components/loading-overlay'; import { useThemeContext } from '@/theme-provider'; +import { asSisenseComponent } from '@/decorators/component-decorators/as-sisense-component'; /** - * React component that renders a dashboard created in Sisense Fusion Embed + * React component that renders a dashboard created in Sisense Fusion by its ID. * * **Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. * - * @internal + * @group Fusion Embed + * @fusionEmbed + * @alpha */ -export const DashboardById = ({ dashboardOid }: DashboardByIdProps) => { +export const DashboardById = asSisenseComponent({ + componentName: 'DashboardById', +})(({ dashboardOid }: DashboardByIdProps) => { const { themeSettings } = useThemeContext(); const { dashboard, isLoading, isError } = useGetDashboardModel({ dashboardOid, @@ -26,4 +31,4 @@ export const DashboardById = ({ dashboardOid }: DashboardByIdProps) => { {dashboard && } ); -}; +}); diff --git a/packages/sdk-ui/src/dashboard/dashboard.tsx b/packages/sdk-ui/src/dashboard/dashboard.tsx index 61d40b01..a416df74 100644 --- a/packages/sdk-ui/src/dashboard/dashboard.tsx +++ b/packages/sdk-ui/src/dashboard/dashboard.tsx @@ -4,59 +4,71 @@ import { useEffect, useMemo, useState } from 'react'; import { isSupportedWidgetTypeByDashboard } from '@/dashboard/utils'; import { WidgetModel } from '@/models'; import { useCommonFilters } from '@/common-filters/use-common-filters'; -import { ThemeProvider } from '@/theme-provider'; +import { ThemeProvider, useThemeContext } from '@/theme-provider'; +import { asSisenseComponent } from '@/decorators/component-decorators/as-sisense-component'; /** - * React component that renders a dashboard - * Include inside logic of applying common filters to widgets + * React component that renders a dashboard whose elements are customizable. It includes internal logic of applying common filters to widgets. * * **Note:** Dashboard extensions based on JS scripts and add-ons in Fusion are not supported. * - * @internal + * @group Fusion Embed + * @fusionEmbed + * @alpha */ -export const Dashboard = ({ - title, - layout, - widgets, - filters, - defaultDataSource, - widgetFilterOptions, - styleOptions, -}: DashboardProps) => { - const { - filters: commonFilters, - setFilters, - connectToWidgetModel, - } = useCommonFilters({ initialFilters: filters }); - const [innerWidgets, setInnerWidgets] = useState(widgets); +export const Dashboard = asSisenseComponent({ + componentName: 'Dashboard', +})( + ({ + title, + layout, + widgets, + filters, + defaultDataSource, + widgetFilterOptions, + styleOptions, + }: DashboardProps) => { + const { + filters: commonFilters, + setFilters, + connectToWidgetModel, + } = useCommonFilters({ initialFilters: filters }); + const [innerWidgets, setInnerWidgets] = useState(widgets); + const { themeSettings } = useThemeContext(); + const { palette, ...restDashboardStyles } = styleOptions; - const widgetsWithCommonFilters = useMemo(() => { - return innerWidgets - .filter((widget) => isSupportedWidgetTypeByDashboard(widget.widgetType)) - .map((widget) => connectToWidgetModel(widget, widgetFilterOptions?.[widget.oid])); - }, [innerWidgets, widgetFilterOptions, connectToWidgetModel]); + const widgetsWithCommonFilters = useMemo(() => { + return innerWidgets + .filter((widget) => isSupportedWidgetTypeByDashboard(widget.widgetType)) + .map((widget) => connectToWidgetModel(widget, widgetFilterOptions?.[widget.oid])); + }, [innerWidgets, widgetFilterOptions, connectToWidgetModel]); - useEffect(() => { - setFilters(filters); - }, [filters, setFilters]); + useEffect(() => { + setFilters(filters); + }, [filters, setFilters]); - useEffect(() => { - setInnerWidgets(widgets); - }, [widgets]); - return ( - - - - ); -}; + useEffect(() => { + setInnerWidgets(widgets); + }, [widgets]); + return ( + + + + ); + }, +); diff --git a/packages/sdk-ui/src/dashboard/index.ts b/packages/sdk-ui/src/dashboard/index.ts index 0943d0d5..4b2b3d94 100644 --- a/packages/sdk-ui/src/dashboard/index.ts +++ b/packages/sdk-ui/src/dashboard/index.ts @@ -1,3 +1,3 @@ export { DashboardById } from './dashboard-by-id'; export { Dashboard } from './dashboard'; -export { type DashboardByIdProps, type DashboardProps } from './types'; +export type { DashboardByIdProps, DashboardProps, DashboardStyleOptions } from './types'; diff --git a/packages/sdk-ui/src/dashboard/types.ts b/packages/sdk-ui/src/dashboard/types.ts index f8677c66..dd29e804 100644 --- a/packages/sdk-ui/src/dashboard/types.ts +++ b/packages/sdk-ui/src/dashboard/types.ts @@ -1,19 +1,20 @@ import { DashboardStyleOptions, Layout, WidgetFilterOptions, WidgetModel } from '@/models'; import { DataSource, Filter } from '@sisense/sdk-data'; +export type { DashboardStyleOptions, Layout } from '@/models'; + /** * Props for the DashboardById component - * - * @internal */ export interface DashboardByIdProps { + /** + * The OID of the dashboard to render. + */ dashboardOid: string; } /** * Props for the DashboardLayout component - * - * @internal */ export interface DashboardLayoutProps { title: string; @@ -26,16 +27,21 @@ export interface DashboardLayoutProps { /** * Props for the Dashboard component - * - * @internal */ export interface DashboardProps { + /** The title of the dashboard */ title: string; + /** The layout of the dashboard */ layout: Layout; + /** The widgets to render in the dashboard */ widgets: WidgetModel[]; + /** The dashboard filters to be applied to each of the widgets based on the widget filter options */ filters: Filter[]; + /** The default data source to use for the dashboard */ defaultDataSource?: DataSource; + /** The filter options for each of the widgets */ widgetFilterOptions?: WidgetFilterOptions; + /** The style options for the dashboard */ styleOptions: DashboardStyleOptions; } diff --git a/packages/sdk-ui/src/decorators/component-decorators/with-sisense-context-validation.tsx b/packages/sdk-ui/src/decorators/component-decorators/with-sisense-context-validation.tsx index 5a1bd3b8..0238588f 100644 --- a/packages/sdk-ui/src/decorators/component-decorators/with-sisense-context-validation.tsx +++ b/packages/sdk-ui/src/decorators/component-decorators/with-sisense-context-validation.tsx @@ -3,6 +3,7 @@ import isFunction from 'lodash/isFunction'; import { ComponentDecorator, SisenseComponentConfig } from './as-sisense-component'; import { TranslatableError } from '../../translation/translatable-error'; import { useSisenseContext } from '../../sisense-context/sisense-context'; +import { LoadingIndicator } from '@/common/components/loading-indicator'; type SisenseContextValidationConfig = Pick< SisenseComponentConfig, @@ -44,8 +45,3 @@ function canRenderWithoutSisenseContextWaiting( (isFunction(shouldSkipSisenseContextWaiting) && shouldSkipSisenseContextWaiting(props)) ); } - -function LoadingIndicator() { - // TODO: add a nice loading indicator - return null; -} diff --git a/packages/sdk-ui/src/decorators/component-decorators/with-tracking/error-tracker.tsx b/packages/sdk-ui/src/decorators/component-decorators/with-tracking/error-tracker.tsx index 382967f8..84ce112d 100644 --- a/packages/sdk-ui/src/decorators/component-decorators/with-tracking/error-tracker.tsx +++ b/packages/sdk-ui/src/decorators/component-decorators/with-tracking/error-tracker.tsx @@ -1,10 +1,11 @@ -import { trackUiError } from '@sisense/sdk-tracking'; +import { ErrorEventOptions } from '@sisense/sdk-tracking'; import { HttpClient } from '@sisense/sdk-rest-client'; import { Component, ReactNode } from 'react'; import { SisenseContext, SisenseContextPayload } from '../../../sisense-context/sisense-context'; type ErrorTrackerProps = { children: ReactNode; + handler: (options: ErrorEventOptions) => Promise; componentName: string; }; export class ErrorTracker extends Component { @@ -12,12 +13,15 @@ export class ErrorTracker extends Component Promise; + httpClient?: HttpClient; postponedErrors: Error[] = []; constructor(props: ErrorTrackerProps) { super(props); + this.handler = props.handler; this.componentName = props.componentName; } @@ -34,28 +38,28 @@ export class ErrorTracker extends Component - console.log('Failed to send tracking error event: ', trackingSendingError), - ); + }); + } catch (trackingSendingError) { + console.log('Failed to send tracking error event: ', trackingSendingError); + } } render(): ReactNode { if (this.httpClient && this.postponedErrors.length > 0) { - this.postponedErrors.forEach((error) => this.sendErrorTracking(error, this.httpClient!)); + this.postponedErrors.forEach((error) => this.sendErrorTracking(error)); } this.postponedErrors = []; return this.props.children; diff --git a/packages/sdk-ui/src/decorators/component-decorators/with-tracking/use-track-component-init.tsx b/packages/sdk-ui/src/decorators/component-decorators/with-tracking/use-track-component-init.tsx index c4cbc3c0..ce48f86e 100644 --- a/packages/sdk-ui/src/decorators/component-decorators/with-tracking/use-track-component-init.tsx +++ b/packages/sdk-ui/src/decorators/component-decorators/with-tracking/use-track-component-init.tsx @@ -1,9 +1,10 @@ -import { TrackingDetails, trackProductEvent } from '@sisense/sdk-tracking'; +import { TrackingEventDetails } from '@sisense/sdk-tracking'; import { useSisenseContext } from '../../../sisense-context/sisense-context'; import { createContext, ReactNode, useContext, useEffect, useRef } from 'react'; +import { useTracking } from '@/common/hooks/use-tracking'; const action = 'sdkComponentInit'; -interface ComponentInitEventDetails extends TrackingDetails { +interface ComponentInitEventDetails extends TrackingEventDetails { packageName: string; packageVersion: string; componentName: string; @@ -20,17 +21,15 @@ export const TrackingContextProvider = ({ }) => {children}; export const useTrackComponentInit =

(componentName: string, props: P) => { - const { app, tracking } = useSisenseContext(); + const { tracking } = useSisenseContext(); + const { trackEvent } = useTracking(); const inTrackingContext = useContext(TrackingContext); const hasTrackedRef = useRef(false); useEffect(() => { - if (!app?.httpClient) { - return; - } - + if (!tracking) return; const hasBeenTracked = hasTrackedRef.current; if (!hasBeenTracked && !inTrackingContext) { const payload: ComponentInitEventDetails = { @@ -43,9 +42,9 @@ export const useTrackComponentInit =

(componentName: string, props .join(', '), }; - void trackProductEvent(action, payload, app.httpClient, !tracking.enabled).finally( + void trackEvent(action, payload, !tracking.enabled).finally( () => (hasTrackedRef.current = true), ); } - }, [componentName, props, app, tracking, inTrackingContext]); + }, [componentName, props, tracking, inTrackingContext, trackEvent]); }; diff --git a/packages/sdk-ui/src/decorators/component-decorators/with-tracking/with-tracking.tsx b/packages/sdk-ui/src/decorators/component-decorators/with-tracking/with-tracking.tsx index 0571164c..aa7f2d27 100644 --- a/packages/sdk-ui/src/decorators/component-decorators/with-tracking/with-tracking.tsx +++ b/packages/sdk-ui/src/decorators/component-decorators/with-tracking/with-tracking.tsx @@ -3,6 +3,7 @@ import { ComponentDecorator } from '../as-sisense-component'; import isBoolean from 'lodash/isBoolean'; import isFunction from 'lodash/isFunction'; import { ErrorTracker } from './error-tracker'; +import { useTracking } from '@/common/hooks/use-tracking'; type TrackingDecoratorConfig = { componentName: string; @@ -22,6 +23,8 @@ export const withTracking: ComponentDecorator = ({ const { skip, transparent } = config || {}; return (Component) => { return function Tracking(props) { + const { trackError } = useTracking(); + if ((isBoolean(skip) && skip) || (isFunction(skip) && skip(props))) { return ; } @@ -30,7 +33,7 @@ export const withTracking: ComponentDecorator = ({ return ( // If component is transperent for tracking, nested components will be tracked - + diff --git a/packages/sdk-ui/src/decorators/hook-decorators/with-tracking.ts b/packages/sdk-ui/src/decorators/hook-decorators/with-tracking.ts index f9194f12..6c8d6ad8 100644 --- a/packages/sdk-ui/src/decorators/hook-decorators/with-tracking.ts +++ b/packages/sdk-ui/src/decorators/hook-decorators/with-tracking.ts @@ -1,7 +1,8 @@ -import { TrackingDetails, trackProductEvent } from '@sisense/sdk-tracking'; +import { TrackingEventDetails, trackProductEvent } from '@sisense/sdk-tracking'; import { useEffect, useRef } from 'react'; import { useSisenseContext } from '../../sisense-context/sisense-context'; import { ClientApplication } from '../../app/client-application'; +import { useTracking } from '@/common/hooks/use-tracking'; export type HookDecorator = ( decoratorConfig: DecoratorConfig, @@ -9,7 +10,7 @@ export type HookDecorator = ( hook: (...args: HookArgs) => HookResult, ) => (...args: HookArgs) => HookResult; -interface HookEventDetails extends TrackingDetails { +interface HookEventDetails extends TrackingEventDetails { hookName: string; } @@ -40,22 +41,24 @@ export const trackHook = ( }; function useTrackHook(hookName: string) { - const { app, tracking } = useSisenseContext(); + const { tracking } = useSisenseContext(); + const { trackEvent } = useTracking(); const hasTrackedRef = useRef(false); useEffect(() => { - if (app?.httpClient && !hasTrackedRef.current) { + if (!tracking) return; + if (!hasTrackedRef.current) { const payload: HookEventDetails = { - packageName: tracking.packageName, + packageName: tracking.packageName || 'sdk-ui', packageVersion: __PACKAGE_VERSION__, hookName, }; - void trackProductEvent(action, payload, app.httpClient, !tracking.enabled).finally( + void trackEvent(action, payload, !tracking.enabled).finally( () => (hasTrackedRef.current = true), ); } - }, [app, tracking, hookName]); + }, [tracking, hookName, trackEvent]); } export const withTracking: HookDecorator = diff --git a/packages/sdk-ui/src/error-boundary/error-boundary.tsx b/packages/sdk-ui/src/error-boundary/error-boundary.tsx index d3b622c4..91598efa 100644 --- a/packages/sdk-ui/src/error-boundary/error-boundary.tsx +++ b/packages/sdk-ui/src/error-boundary/error-boundary.tsx @@ -50,8 +50,8 @@ export class ErrorBoundary extends Component :

; + if (error && this.showErrorBox) { + return ; } return this.props.children; diff --git a/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.test.tsx b/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.test.tsx index d8556c06..e2c687d7 100644 --- a/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.test.tsx +++ b/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.test.tsx @@ -12,9 +12,11 @@ import { setTimeout } from 'timers/promises'; const contextProviderProps: SisenseContextProviderProps = { url: mockUrl, token: mockToken, - enableTracking: false, defaultDataSource: 'Sample ECommerce', - appConfig: { queryCacheConfig: { enabled: false } }, + appConfig: { + queryCacheConfig: { enabled: false }, + trackingConfig: { enabled: false }, + }, }; describe('CascadingFilterTile', () => { diff --git a/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.tsx b/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.tsx index c7f33f30..f52741a1 100644 --- a/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.tsx +++ b/packages/sdk-ui/src/filters/components/cascading-filter-tile/cascading-filter-tile.tsx @@ -3,8 +3,8 @@ import { CascadingFilter, DataSource, Filter } from '@sisense/sdk-data'; import { asSisenseComponent } from '../../../decorators/component-decorators/as-sisense-component.js'; import { FilterVariant } from '../common/filter-utils.js'; import { CascadingLevelFilterTile } from './cascading-level-filter.js'; -import { cloneFilterAndToggleDisabled } from '@/filters/utils.js'; import { useSynchronizedFilter } from '@/filters/hooks/use-synchronized-filter.js'; +import { clearMembersFilter, cloneFilterAndToggleDisabled } from '@/utils/filters.js'; /** * Props for {@link CascadingFilterTile} @@ -50,9 +50,24 @@ export const CascadingFilterTile = asSisenseComponent({ componentName: 'Cascadin const levelFilters = filter.filters; - const handleLevelFilterChange = (levelFilter: Filter, index: number) => { - levelFilters[`${index}`] = levelFilter; - updateFilter(filter); + const handleLevelFilterChange = ( + changedLevelFilter: Filter, + changedLevelFilterIndex: number, + ) => { + const newLevelFilters = filter.filters.map((levelFilter, index) => { + if (index === changedLevelFilterIndex) { + return changedLevelFilter; + } + if (index > changedLevelFilterIndex) { + return clearMembersFilter(levelFilter); + } + return levelFilter; + }); + + const newCascadingFilter = new CascadingFilter(newLevelFilters, filter.guid); + newCascadingFilter.disabled = filter.disabled; + + updateFilter(newCascadingFilter); }; return ( diff --git a/packages/sdk-ui/src/filters/components/date-filter/date-range-filter-tile/date-range-filter-tile.test.tsx b/packages/sdk-ui/src/filters/components/date-filter/date-range-filter-tile/date-range-filter-tile.test.tsx index e04a0d61..318eb839 100644 --- a/packages/sdk-ui/src/filters/components/date-filter/date-range-filter-tile/date-range-filter-tile.test.tsx +++ b/packages/sdk-ui/src/filters/components/date-filter/date-range-filter-tile/date-range-filter-tile.test.tsx @@ -21,7 +21,11 @@ describe('DateRangeFilterTile', () => { const dateRangeFilter = filterFactory.dateRange(DM.Commerce.Date.Years); const { container } = render( - + { const dateRangeFilter = filterFactory.dateRange(DM.Commerce.Date.Years); const { findByLabelText, findByText } = render( - + { const dateRangeFilter = filterFactory.dateRange(DM.Commerce.Date.Years, '2009-01-01'); render( - + ` background-color: ${({ theme }) => theme.chart.backgroundColor}; @@ -53,11 +54,9 @@ export type FiltersPanelProps = { * * @internal */ -export const FiltersPanel = ({ - filters, - onFiltersChange, - defaultDataSource, -}: FiltersPanelProps) => { +export const FiltersPanel = asSisenseComponent({ + componentName: 'FiltersPanel', +})(({ filters, onFiltersChange, defaultDataSource }: FiltersPanelProps) => { const { themeSettings } = useThemeContext(); const filterList = [...filters] as (Filter | null)[]; const handleFilterChange = (filter: Filter | null, index: number) => { @@ -85,4 +84,4 @@ export const FiltersPanel = ({ ); -}; +}); diff --git a/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.test.tsx b/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.test.tsx index aab2a892..8fa8e6ba 100644 --- a/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.test.tsx +++ b/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.test.tsx @@ -12,8 +12,10 @@ import { MemberFilterTile } from './member-filter-tile'; const contextProviderProps: SisenseContextProviderProps = { url: mockUrl, token: mockToken, - enableTracking: false, - appConfig: { queryCacheConfig: { enabled: false } }, + appConfig: { + queryCacheConfig: { enabled: false }, + trackingConfig: { enabled: false }, + }, }; describe('MemberFilterTile', () => { diff --git a/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.tsx b/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.tsx index 07af8440..58a9eab5 100644 --- a/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.tsx +++ b/packages/sdk-ui/src/filters/components/member-filter-tile/member-filter-tile.tsx @@ -7,8 +7,8 @@ import { FilterTile, FilterTileDesignOptions } from '../filter-tile'; import { useSynchronizedFilter } from '@/filters/hooks/use-synchronized-filter'; import { PillSection } from './pill-section'; import { MemberList } from './member-list'; -import { cloneFilterAndToggleDisabled } from '@/filters/utils'; import merge from 'lodash/merge'; +import { cloneFilterAndToggleDisabled } from '@/utils/filters'; /** * Props for {@link MemberFilterTile} diff --git a/packages/sdk-ui/src/filters/utils.ts b/packages/sdk-ui/src/filters/utils.ts deleted file mode 100644 index 155dbd56..00000000 --- a/packages/sdk-ui/src/filters/utils.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { type Filter } from '@sisense/sdk-data'; -import cloneDeep from 'lodash/cloneDeep'; - -/** - * Clones a filter with a toggled 'disabled' state. - * - * @param filter - Filter to clone - */ -export const cloneFilterAndToggleDisabled = (filter: TFilter): TFilter => { - const newFilter = cloneFilter(filter); - newFilter.disabled = !filter.disabled; - return newFilter; -}; - -export const cloneFilter = (filter: TFilter): TFilter => { - const newFilter = cloneDeep(filter); - Object.setPrototypeOf(newFilter, filter); - return newFilter; -}; diff --git a/packages/sdk-ui/src/formulas/use-get-shared-formula.test.ts b/packages/sdk-ui/src/formulas/use-get-shared-formula.test.ts index a2fac088..62a4212f 100644 --- a/packages/sdk-ui/src/formulas/use-get-shared-formula.test.ts +++ b/packages/sdk-ui/src/formulas/use-get-shared-formula.test.ts @@ -63,6 +63,7 @@ describe('useGetSharedFormula', () => { }); fetchFormulaMock.mockImplementation(() => Promise.resolve(calculatedMeasureMock)); fetchFormulaByOidMock.mockImplementation(() => Promise.resolve(calculatedMeasureMock)); + trackProductEventMock.mockClear(); }); it('should trow an error if no identifier provided', () => { try { diff --git a/packages/sdk-ui/src/index.ts b/packages/sdk-ui/src/index.ts index c16649ba..595085d8 100644 --- a/packages/sdk-ui/src/index.ts +++ b/packages/sdk-ui/src/index.ts @@ -5,12 +5,7 @@ export { ClientApplication, createClientApplication } from './app/client-applica export * from './chart-data-options/types'; export { Chart } from './chart'; export { ThemeProvider } from './theme-provider'; -export { - DashboardById, - Dashboard, - type DashboardByIdProps, - type DashboardProps, -} from './dashboard'; +export * from './dashboard'; export { DashboardWidget } from './dashboard-widget/dashboard-widget'; export { getSortType } from './dashboard-widget/utils'; export { @@ -23,7 +18,7 @@ export * from './query-execution'; export { executeQuery } from './query/execute-query'; export { SisenseContextProvider } from './sisense-context/sisense-context-provider'; export { DrilldownWidget } from './widgets/drilldown-widget'; -export { processDrilldownSelections } from './widgets/common/custom-drilldown'; +export { processDrilldownSelections } from './widgets/common/use-drilldown'; export { ChartWidget } from './widgets/chart-widget'; export { TableWidget } from './widgets/table-widget'; export { ContextMenu } from './widgets/common/context-menu'; @@ -80,6 +75,9 @@ export { type GetDashboardModelsOptions, type Layout, type WidgetFilterOptions, + type CommonFiltersOptions, + type CommonFiltersApplyMode, + type FiltersIgnoringRules, } from './models'; export { boxWhiskerProcessResult } from './boxplot-utils'; export { queryStateReducer } from './query-execution/query-state-reducer'; diff --git a/packages/sdk-ui/src/models/dashboard/get-dashboard-model.ts b/packages/sdk-ui/src/models/dashboard/get-dashboard-model.ts index 978e46b0..760fea5b 100644 --- a/packages/sdk-ui/src/models/dashboard/get-dashboard-model.ts +++ b/packages/sdk-ui/src/models/dashboard/get-dashboard-model.ts @@ -24,13 +24,13 @@ export interface GetDashboardModelOptions { /** * Retrieves a dashboard model by its OID. + * * @param http - The HTTP client * @param dashboardOid - The OID of the dashboard * @param options - The options to include widgets and filters in the dashboard model * @param themeSettings - Optional theme settings * @param appSettings - Optional application settings * @returns The dashboard model - * * @internal */ export async function getDashboardModel( diff --git a/packages/sdk-ui/src/models/dashboard/types.ts b/packages/sdk-ui/src/models/dashboard/types.ts index 1e8e7a8a..b4c6bfb5 100644 --- a/packages/sdk-ui/src/models/dashboard/types.ts +++ b/packages/sdk-ui/src/models/dashboard/types.ts @@ -1,7 +1,15 @@ import { CommonFiltersOptions } from '@/common-filters/types'; import { ColorPaletteTheme } from '@/types'; -/** @internal */ +export type { + CommonFiltersOptions, + CommonFiltersApplyMode, + FiltersIgnoringRules, +} from '@/common-filters/types'; + +/** + * Layout of a dashboard. + */ export interface Layout { columns: { widthPercentage: number; @@ -15,10 +23,21 @@ export interface Layout { }[]; } -/** @internal */ +/** + * Options for how common filters defined at the dashboard level should be applied to widgets. + */ export type WidgetFilterOptions = Record; -/** @internal */ +/** + * Style options for the dashboard. + */ export type DashboardStyleOptions = { + /** Collection of colors used to color various elements */ palette?: ColorPaletteTheme; + /** Background color */ + backgroundColor?: string; + /** Width of the divider line between widgets */ + dividerLineWidth?: number; + /** Divider line color */ + dividerLineColor?: string; }; diff --git a/packages/sdk-ui/src/models/dashboard/use-get-dashboard-model.test.ts b/packages/sdk-ui/src/models/dashboard/use-get-dashboard-model.test.ts index ec80ed52..d44c2e33 100644 --- a/packages/sdk-ui/src/models/dashboard/use-get-dashboard-model.test.ts +++ b/packages/sdk-ui/src/models/dashboard/use-get-dashboard-model.test.ts @@ -62,6 +62,7 @@ const trackProductEventMock = trackProductEvent as Mock< describe('useGetDashboardModel', () => { beforeEach(() => { getDashboardModelMock.mockClear(); + trackProductEventMock.mockClear(); useSisenseContextMock.mockReturnValue({ app: {} as ClientApplication, isInitialized: true, diff --git a/packages/sdk-ui/src/models/dashboard/use-get-dashboard-models.test.ts b/packages/sdk-ui/src/models/dashboard/use-get-dashboard-models.test.ts index 921ab644..1d131511 100644 --- a/packages/sdk-ui/src/models/dashboard/use-get-dashboard-models.test.ts +++ b/packages/sdk-ui/src/models/dashboard/use-get-dashboard-models.test.ts @@ -59,6 +59,7 @@ const trackProductEventMock = trackProductEvent as Mock< describe('useGetDashboardModels', () => { beforeEach(() => { getDashboarsdModelsMock.mockClear(); + trackProductEventMock.mockClear(); useSisenseContextMock.mockReturnValue({ app: {} as ClientApplication, isInitialized: true, diff --git a/packages/sdk-ui/src/models/widget/get-widget-model.ts b/packages/sdk-ui/src/models/widget/get-widget-model.ts index 7b888428..a6bd750e 100644 --- a/packages/sdk-ui/src/models/widget/get-widget-model.ts +++ b/packages/sdk-ui/src/models/widget/get-widget-model.ts @@ -7,13 +7,13 @@ import { AppSettings } from '@/app/settings/settings'; /** * Retrieves a widget model by its OID. + * * @param httpClient - The HTTP client * @param dashboardOid - The OID of the dashboard * @param widgetOid - The OID of the widget * @param themeSettings - Optional theme settings * @param appSettings - Optional application settings * @returns The widget model - * * @internal */ export async function getWidgetModel( diff --git a/packages/sdk-ui/src/models/widget/translate-widget.ts b/packages/sdk-ui/src/models/widget/translate-widget.ts index 8f8cdb11..199f5a0d 100644 --- a/packages/sdk-ui/src/models/widget/translate-widget.ts +++ b/packages/sdk-ui/src/models/widget/translate-widget.ts @@ -7,6 +7,7 @@ import { AppSettings } from '@/app/settings/settings'; /** * Translates a widget DTO to a widget model. + * * @param widget - The widget DTO to be converted to a widget model * @param themeSettings - Optional theme settings * @param appSettings - Optional application settings diff --git a/packages/sdk-ui/src/models/widget/widget-model.ts b/packages/sdk-ui/src/models/widget/widget-model.ts index b56c2019..ee6d054f 100644 --- a/packages/sdk-ui/src/models/widget/widget-model.ts +++ b/packages/sdk-ui/src/models/widget/widget-model.ts @@ -1,4 +1,4 @@ -import { getPivotQueryOptions } from '@/pivot-table/use-get-pivot-table-query'; +import { getPivotQueryOptions } from '@/pivot-table/hooks/use-get-pivot-table-query'; import { Attribute, Filter, Measure } from '@sisense/sdk-data'; import { over } from 'lodash'; import { getTranslatedDataOptions } from '../../chart-data-options/get-translated-data-options'; diff --git a/packages/sdk-ui/src/pivot-table/__snapshots__/pivot-table.test.tsx.snap b/packages/sdk-ui/src/pivot-table/__snapshots__/pivot-table.test.tsx.snap index 18b87fd5..8b0d05fb 100644 --- a/packages/sdk-ui/src/pivot-table/__snapshots__/pivot-table.test.tsx.snap +++ b/packages/sdk-ui/src/pivot-table/__snapshots__/pivot-table.test.tsx.snap @@ -17,7 +17,936 @@ exports[`PivotTable > should render empty pivot table 1`] = ` >
+ > +
+
+
+
+
+
+
+ + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + +
+
+
+ + + + + +
+
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ + Rows + +

+
+ + + + + +
+

+ + 0-0 / 0 + +

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/sdk-ui/src/pivot-table/helpers/prepare-pivot-styling-props.ts b/packages/sdk-ui/src/pivot-table/helpers/prepare-pivot-styling-props.ts index c9c68bd6..a8a894c0 100644 --- a/packages/sdk-ui/src/pivot-table/helpers/prepare-pivot-styling-props.ts +++ b/packages/sdk-ui/src/pivot-table/helpers/prepare-pivot-styling-props.ts @@ -4,10 +4,31 @@ import { getDarkFactor, getSlightlyDifferentColor, toColor } from '@/utils/color const PIVOT_DEFAULT_BORDER_COLOR = '#cbced7'; const PIVOT_DEFAULT_HIGHLIGHT_COLOR = '#ffff9c'; +export type PivotStylingProps = { + fontFamily?: string; + textColor?: string; + backgroundColor?: string; + borderColor?: string; + fillColor?: string; + additionalFillColor?: string; + fillOptions: { + alternatingRows?: boolean; + alternatingColumns?: boolean; + columnsHeaders?: boolean; + rowMembers?: boolean; + totals?: boolean; + }; + rowHeight?: number; + isAutoHeight: boolean; + navigationPrimaryColor?: string; + navigationSecondaryColor?: string; + selectionColor: string; +}; + export function preparePivotStylingProps( styleOptions?: PivotTableStyleOptions, themeSettings?: CompleteThemeSettings, -) { +): PivotStylingProps { let fillColor; let additionalFillColor; if (themeSettings?.chart?.backgroundColor) { diff --git a/packages/sdk-ui/src/pivot-table/hooks/__snapshots__/use-pivot-table-data-options-internal.test.ts.snap b/packages/sdk-ui/src/pivot-table/hooks/__snapshots__/use-pivot-table-data-options-internal.test.ts.snap new file mode 100644 index 00000000..09c54cb1 --- /dev/null +++ b/packages/sdk-ui/src/pivot-table/hooks/__snapshots__/use-pivot-table-data-options-internal.test.ts.snap @@ -0,0 +1,75 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`usePivotTableDataOptionsInternal > should correctly translate dataOptions into internalDataOptions 1`] = ` +{ + "columns": [ + { + "__serializable": "DimensionalElement", + "desc": "", + "expression": "[Commerce.Gender]", + "name": "Gender", + "type": "text-attribute", + }, + ], + "grandTotals": { + "columns": true, + "rows": true, + "title": "Grand Total", + }, + "rows": [ + { + "__serializable": "DimensionalElement", + "desc": "", + "expression": "[Category.Category]", + "name": "Category", + "type": "text-attribute", + }, + { + "__serializable": "DimensionalElement", + "desc": "", + "expression": "[Commerce.Age Range]", + "name": "AgeRange", + "type": "text-attribute", + }, + { + "__serializable": "DimensionalElement", + "desc": "", + "expression": "[Commerce.Condition]", + "name": "Condition", + "type": "text-attribute", + }, + ], + "values": [ + { + "__serializable": "DimensionalElement", + "aggregation": "sum", + "attribute": { + "__serializable": "DimensionalElement", + "desc": "", + "expression": "[Commerce.Cost]", + "name": "Cost", + "type": "numeric-attribute", + }, + "desc": "", + "name": "Total Cost", + "sort": 0, + "type": "basemeasure", + }, + { + "__serializable": "DimensionalElement", + "aggregation": "sum", + "attribute": { + "__serializable": "DimensionalElement", + "desc": "", + "expression": "[Commerce.Revenue]", + "name": "Revenue", + "type": "numeric-attribute", + }, + "desc": "", + "name": "Total Revenue", + "sort": 0, + "type": "basemeasure", + }, + ], +} +`; diff --git a/packages/sdk-ui/src/pivot-table/use-apply-pivot-table-formatting.test.ts b/packages/sdk-ui/src/pivot-table/hooks/use-apply-pivot-table-formatting.test.ts similarity index 73% rename from packages/sdk-ui/src/pivot-table/use-apply-pivot-table-formatting.test.ts rename to packages/sdk-ui/src/pivot-table/hooks/use-apply-pivot-table-formatting.test.ts index 2658cf07..f572b3f8 100644 --- a/packages/sdk-ui/src/pivot-table/use-apply-pivot-table-formatting.test.ts +++ b/packages/sdk-ui/src/pivot-table/hooks/use-apply-pivot-table-formatting.test.ts @@ -4,20 +4,21 @@ import { EVENT_HEADER_CELL_FORMAT, type DataService, } from '@sisense/sdk-pivot-client'; -import { ClientApplication } from '../app/client-application'; -import { useSisenseContextMock } from '../sisense-context/__mocks__/sisense-context'; + import { useApplyPivotTableFormatting } from './use-apply-pivot-table-formatting'; -import { type PivotTableDataOptions } from '..'; +import { useSisenseContextMock } from '@/sisense-context/__mocks__/sisense-context'; +import type { PivotTableDataOptions } from '@/chart-data-options/types'; +import type { ClientApplication } from '@/app/client-application'; -vi.mock('../sisense-context/sisense-context'); +vi.mock('@/sisense-context/sisense-context'); const dataCellFormatterMock = vi.fn(); -vi.mock('./formatters/data-cell-formatters', () => ({ +vi.mock('../formatters/data-cell-formatters', () => ({ createDataCellValueFormatter: vi.fn(() => dataCellFormatterMock), })); const headerCellFormatterMock = vi.fn(); -vi.mock('./formatters/header-cell-formatters', () => ({ +vi.mock('../formatters/header-cell-formatters', () => ({ createHeaderCellValueFormatter: vi.fn(() => headerCellFormatterMock), })); @@ -32,9 +33,8 @@ describe('useApplyPivotTableFormatting', () => { beforeEach(() => { useSisenseContextMock.mockReturnValue({ - app: {} as ClientApplication, + app: { settings: { trackingConfig: { enabled: false } } } as ClientApplication, isInitialized: true, - enableTracking: false, }); DataServiceMock.on.mockClear(); dataCellFormatterMock.mockClear(); @@ -42,17 +42,24 @@ describe('useApplyPivotTableFormatting', () => { }); it('should run data cell value formatter', () => { + expect(dataCellFormatterMock).toHaveBeenCalledTimes(0); + expect(headerCellFormatterMock).toHaveBeenCalledTimes(0); + renderHook(() => useApplyPivotTableFormatting({ dataService, dataOptions })); + const cell = {}; const [event, handler] = DataServiceMock.on.mock.calls[0]; expect(event).toBe(EVENT_DATA_CELL_FORMAT); - handler(); + handler(cell); expect(dataCellFormatterMock).toHaveBeenCalledTimes(1); }); it('should run header cell value formatter', () => { + expect(dataCellFormatterMock).toHaveBeenCalledTimes(0); + expect(headerCellFormatterMock).toHaveBeenCalledTimes(0); + const cell = {}; renderHook(() => useApplyPivotTableFormatting({ dataService, dataOptions })); diff --git a/packages/sdk-ui/src/pivot-table/use-apply-pivot-table-formatting.ts b/packages/sdk-ui/src/pivot-table/hooks/use-apply-pivot-table-formatting.ts similarity index 91% rename from packages/sdk-ui/src/pivot-table/use-apply-pivot-table-formatting.ts rename to packages/sdk-ui/src/pivot-table/hooks/use-apply-pivot-table-formatting.ts index ca5a31b1..fc854aba 100644 --- a/packages/sdk-ui/src/pivot-table/use-apply-pivot-table-formatting.ts +++ b/packages/sdk-ui/src/pivot-table/hooks/use-apply-pivot-table-formatting.ts @@ -9,8 +9,8 @@ import over from 'lodash/over'; import { type PivotTableDataOptions } from '@/chart-data-options/types'; import { applyDateFormat } from '@/query/date-formats'; import { useSisenseContext } from '@/sisense-context/sisense-context'; -import { createDataCellValueFormatter, createHeaderCellValueFormatter } from './formatters'; -import { createHeaderCellHighlightFormatter } from './formatters/header-cell-formatters/header-cell-highlight-formatter'; +import { createDataCellValueFormatter, createHeaderCellValueFormatter } from '../formatters'; +import { createHeaderCellHighlightFormatter } from '../formatters/header-cell-formatters/header-cell-highlight-formatter'; /** * A hook that applies formatting over pivot table cells. diff --git a/packages/sdk-ui/src/pivot-table/use-get-pivot-table-query.test.ts b/packages/sdk-ui/src/pivot-table/hooks/use-get-pivot-table-query.test.ts similarity index 80% rename from packages/sdk-ui/src/pivot-table/use-get-pivot-table-query.test.ts rename to packages/sdk-ui/src/pivot-table/hooks/use-get-pivot-table-query.test.ts index c8e644f6..5efd6bbb 100644 --- a/packages/sdk-ui/src/pivot-table/use-get-pivot-table-query.test.ts +++ b/packages/sdk-ui/src/pivot-table/hooks/use-get-pivot-table-query.test.ts @@ -1,15 +1,15 @@ import { usePivotTableQuery } from './use-get-pivot-table-query'; import { EMPTY_PIVOT_QUERY_RESULT_DATA } from '@sisense/sdk-data'; import { renderHook, waitFor } from '@testing-library/react'; -import { ClientApplication } from '../app/client-application'; -import { useSisenseContextMock } from '../sisense-context/__mocks__/sisense-context'; -import { executePivotQueryMock } from '../query/__mocks__/execute-query'; -import { mockPivotTableProps } from './__mocks__/mocks'; +import { ClientApplication } from '../../app/client-application'; +import { useSisenseContextMock } from '../../sisense-context/__mocks__/sisense-context'; +import { executePivotQueryMock } from '../../query/__mocks__/execute-query'; +import { mockPivotTableProps } from '../__mocks__/mocks'; import { translatePivotTableDataOptions } from '@/chart-data-options/translate-data-options'; import { type JaqlQueryPayload, type QueryExecutionConfig } from '@sisense/sdk-query-client'; -vi.mock('../query/execute-query'); -vi.mock('../sisense-context/sisense-context'); +vi.mock('@/query/execute-query'); +vi.mock('@/sisense-context/sisense-context'); const usePivotTableQueryPropsMock = { dataSet: mockPivotTableProps.dataSet, @@ -21,9 +21,8 @@ describe('usePivotTableQuery', () => { beforeEach(() => { executePivotQueryMock.mockClear(); useSisenseContextMock.mockReturnValue({ - app: {} as ClientApplication, + app: { settings: { trackingConfig: { enabled: false } } } as ClientApplication, isInitialized: true, - enableTracking: false, }); }); diff --git a/packages/sdk-ui/src/pivot-table/use-get-pivot-table-query.ts b/packages/sdk-ui/src/pivot-table/hooks/use-get-pivot-table-query.ts similarity index 89% rename from packages/sdk-ui/src/pivot-table/use-get-pivot-table-query.ts rename to packages/sdk-ui/src/pivot-table/hooks/use-get-pivot-table-query.ts index abb0fee3..20ac15ac 100644 --- a/packages/sdk-ui/src/pivot-table/use-get-pivot-table-query.ts +++ b/packages/sdk-ui/src/pivot-table/hooks/use-get-pivot-table-query.ts @@ -1,12 +1,13 @@ import { useCallback, useState } from 'react'; import { type JaqlRequest } from '@sisense/sdk-pivot-client'; import type { DataSource, Filter, FilterRelations } from '@sisense/sdk-data'; -import { ExecutePivotQueryParams } from '../query-execution'; -import { useExecutePivotQueryInternal } from '../query-execution/use-execute-pivot-query'; -import { Category, PivotTableDataOptionsInternal, Value } from '../chart-data-options/types'; -import { translateCategoryToAttribute, translateValueToMeasure } from '../chart-data-options/utils'; -import { normalizePivotSort } from './sorting-utils'; + +import { normalizePivotSort } from '../sorting-utils'; import isEqual from 'lodash/isEqual'; +import { ExecutePivotQueryParams } from '@/query-execution'; +import { translateCategoryToAttribute, translateValueToMeasure } from '@/chart-data-options/utils'; +import { Category, PivotTableDataOptionsInternal, Value } from '@/chart-data-options/types'; +import { useExecutePivotQueryInternal } from '@/query-execution/use-execute-pivot-query'; const getPivotAttribute = (category: Category) => { return { diff --git a/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-loading.test.ts b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-loading.test.ts new file mode 100644 index 00000000..ba9df546 --- /dev/null +++ b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-loading.test.ts @@ -0,0 +1,144 @@ +import { renderHook, waitFor } from '@testing-library/react'; +import { usePivotDataLoading } from './use-pivot-data-loading'; +import { + PivotBuilder, + EVENT_QUERY_START, + EVENT_QUERY_END, + JaqlRequest, + JaqlPanel, +} from '@sisense/sdk-pivot-client'; + +type AnyFunction = (...args: any[]) => any; + +// Mock the PivotBuilder +class MockPivotBuilder extends PivotBuilder { + listeners: Record = {}; + + on(event: string, callback: AnyFunction) { + if (!this.listeners[event]) { + this.listeners[event] = []; + } + this.listeners[event].push(callback); + } + + off(event: string, callback: AnyFunction) { + this.listeners[event] = this.listeners[event].filter((cb) => cb !== callback); + } + + trigger(event: string, data?: any) { + if (this.listeners[event]) { + this.listeners[event].forEach((callback) => callback(data)); + } + } + + updateJaql() { + // Mock updateJaql method + } +} + +const pivotJaqlMock: JaqlRequest = { metadata: [] }; + +describe('usePivotDataLoading', () => { + let mockPivotBuilder: MockPivotBuilder; + + beforeEach(() => { + mockPivotBuilder = new MockPivotBuilder(); + }); + + it('should initialize with isLoading = false and isNoResults = false', () => { + const { result } = renderHook(() => + usePivotDataLoading({ + jaql: undefined, + pivotBuilder: mockPivotBuilder, + isForceReload: false, + }), + ); + + expect(result.current.isLoading).toBe(false); + expect(result.current.isNoResults).toBe(false); + }); + + it('should return isLoading === true and isNoResults === false on EVENT_QUERY_START', async () => { + const { result } = renderHook(() => + usePivotDataLoading({ + jaql: pivotJaqlMock, + pivotBuilder: mockPivotBuilder, + isForceReload: false, + }), + ); + + // Trigger the EVENT_QUERY_START event + mockPivotBuilder.trigger(EVENT_QUERY_START); + + await waitFor(() => { + expect(result.current.isLoading).toBe(true); + expect(result.current.isNoResults).toBe(false); + }); + }); + + it('should set isLoading to false and isNoResults based on results availability in EVENT_QUERY_END', async () => { + const { result } = renderHook(() => + usePivotDataLoading({ + jaql: undefined, + pivotBuilder: mockPivotBuilder, + isForceReload: false, + }), + ); + + // Trigger the EVENT_QUERY_START event + mockPivotBuilder.trigger(EVENT_QUERY_START); + + // Trigger the EVENT_QUERY_END event with no results + mockPivotBuilder.trigger(EVENT_QUERY_END, { cellsMetadata: undefined }); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.isNoResults).toBe(true); + }); + + // Trigger the EVENT_QUERY_END event with results + mockPivotBuilder.trigger(EVENT_QUERY_END, { cellsMetadata: {} }); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.isNoResults).toBe(false); + }); + }); + + it('should call jaql update in pivotBuilder when jaql changes or isForceReload is true', () => { + const mockJaql: JaqlRequest = { + metadata: ['some initial jaql metadata' as unknown as JaqlPanel], + }; + + const { rerender } = renderHook( + (props) => + usePivotDataLoading({ + jaql: props.jaql, + pivotBuilder: mockPivotBuilder, + isForceReload: props.isForceReload, + }), + { + initialProps: { jaql: mockJaql, isForceReload: false }, + }, + ); + + const spy = vi.spyOn(mockPivotBuilder, 'updateJaql'); + + const newJaql = { + ...mockJaql, + metadata: [...mockJaql.metadata, 'new jaql metadata' as unknown as JaqlPanel], + }; + // Rerender with a new JAQL object + rerender({ jaql: newJaql, isForceReload: false }); + expect(spy).toHaveBeenCalledWith(newJaql); + expect(spy).toHaveBeenCalledTimes(1); + + // Rerender with the same JAQL object + rerender({ jaql: newJaql, isForceReload: false }); + expect(spy).toHaveBeenCalledTimes(1); + + // Rerender with force reload set to true + rerender({ jaql: newJaql, isForceReload: true }); + expect(spy).toHaveBeenCalledTimes(2); + + spy.mockRestore(); + }); +}); diff --git a/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-loading.ts b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-loading.ts new file mode 100644 index 00000000..67be4691 --- /dev/null +++ b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-loading.ts @@ -0,0 +1,69 @@ +import { useState, useEffect, useCallback } from 'react'; +import { + EVENT_QUERY_END, + EVENT_QUERY_START, + InitPageData, + JaqlRequest, + PivotBuilder, +} from '@sisense/sdk-pivot-client'; +import { useHasChanged } from '@/common/hooks/use-has-changed'; + +interface LoadingState { + isLoading: boolean; + isNoResults: boolean; +} + +/** + * Hook that initiates loading if jaql is changed or force reload is triggered. + * Listens to query lifecycle events to update loading state and no results state. + */ +export function usePivotDataLoading(options: { + jaql: JaqlRequest | undefined; + pivotBuilder: PivotBuilder; + isForceReload: boolean; +}): LoadingState { + const { jaql, pivotBuilder, isForceReload } = options; + + const [loadingState, setLoadingState] = useState({ + isLoading: false, + isNoResults: false, + }); + + const isJaqlChanged = useHasChanged(jaql); + + useEffect(() => { + if (jaql && (isJaqlChanged || isForceReload)) { + pivotBuilder.updateJaql(jaql); + } + }, [isForceReload, isJaqlChanged, jaql, pivotBuilder]); + + const handleQueryStart = useCallback(() => { + setLoadingState({ isLoading: true, isNoResults: false }); + }, []); + + const handleQueryEnd = useCallback((data: InitPageData) => { + setLoadingState({ + isLoading: false, + isNoResults: !data.cellsMetadata, + }); + }, []); + + useEffect(() => { + const eventHandlers = [ + { event: EVENT_QUERY_START, handler: handleQueryStart }, + { event: EVENT_QUERY_END, handler: handleQueryEnd }, + ]; + + eventHandlers.forEach(({ event, handler }) => { + pivotBuilder.on(event, handler); + }); + + return () => { + eventHandlers.forEach(({ event, handler }) => { + pivotBuilder.off(event, handler); + }); + }; + }, [pivotBuilder, handleQueryStart, handleQueryEnd]); + + return loadingState; +} diff --git a/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-service.test.ts b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-service.test.ts new file mode 100644 index 00000000..e9b1c07f --- /dev/null +++ b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-service.test.ts @@ -0,0 +1,99 @@ +/* eslint-disable @typescript-eslint/unbound-method */ +import { renderHook } from '@testing-library/react'; +import { usePivotDataService } from './use-pivot-data-service'; +import { DataService, PivotBuilder, PivotClient } from '@sisense/sdk-pivot-client'; +import { describe, it, expect, vi } from 'vitest'; + +describe('usePivotDataService', () => { + it('should create initial data service', () => { + let dataServiceCounter = 0; + const pivotClient = { + prepareDataService: vi.fn( + () => `dataService_${dataServiceCounter++}` as unknown as DataService, + ), + } as unknown as PivotClient; + + const pivotBuilder = { + updateDataService: vi.fn(), + } as unknown as PivotBuilder; + + const { result } = renderHook(() => + usePivotDataService({ + pivotClient, + pivotBuilder, + shouldBeRecreated: false, + }), + ); + + expect(pivotClient.prepareDataService).toHaveBeenCalledTimes(1); + expect(result.current).toBe('dataService_0'); + }); + + it('should recreate data service when shouldBeRecreated is true', () => { + let dataServiceCounter = 0; + const pivotClient = { + prepareDataService: vi.fn(() => { + return `dataService_${dataServiceCounter++}` as unknown as DataService; + }), + } as unknown as PivotClient; + + const pivotBuilder = { + updateDataService: vi.fn(), + } as unknown as PivotBuilder; + + const { rerender, result } = renderHook( + ({ shouldBeRecreated }) => + usePivotDataService({ + pivotClient, + pivotBuilder, + shouldBeRecreated, + }), + { + initialProps: { + pivotBuilder, + pivotClient, + shouldBeRecreated: false, + }, + }, + ); + + expect(pivotClient.prepareDataService).toHaveBeenCalledTimes(1); + expect(result.current).toBe('dataService_0'); + + rerender({ pivotBuilder, pivotClient, shouldBeRecreated: true }); + + expect(pivotClient.prepareDataService).toHaveBeenCalledTimes(2); + expect(result.current).toBe('dataService_1'); + }); + + it('should not recreate data service when shouldBeRecreated is false', () => { + const pivotClient = { + prepareDataService: vi.fn(() => ({} as DataService)), + } as unknown as PivotClient; + + const pivotBuilder = { + updateDataService: vi.fn(), + } as unknown as PivotBuilder; + + const { rerender } = renderHook( + ({ shouldBeRecreated }) => + usePivotDataService({ + pivotClient, + pivotBuilder, + shouldBeRecreated, + }), + { + initialProps: { + shouldBeRecreated: false, + }, + }, + ); + + expect(pivotClient.prepareDataService).toHaveBeenCalledTimes(1); + + rerender({ shouldBeRecreated: false }); + + expect(pivotClient.prepareDataService).toHaveBeenCalledTimes(1); + expect(pivotBuilder.updateDataService).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-service.ts b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-service.ts new file mode 100644 index 00000000..1168d82f --- /dev/null +++ b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-data-service.ts @@ -0,0 +1,28 @@ +import { useEffect, useState } from 'react'; +import { DataService, PivotBuilder, PivotClient } from '@sisense/sdk-pivot-client'; + +/** + * Hook that recreates a new data service when new jaql request is needed to sent + * and updates the pivot builder with the new data service. + */ +export function usePivotDataService(options: { + pivotClient: PivotClient; + pivotBuilder: PivotBuilder; + shouldBeRecreated: boolean; +}): DataService { + const { pivotClient, pivotBuilder, shouldBeRecreated } = options; + + const [dataService, setDataService] = useState(() => + pivotClient.prepareDataService(), + ); + + useEffect(() => { + if (shouldBeRecreated) { + const newDataService = pivotClient.prepareDataService(); + setDataService(newDataService); + pivotBuilder.updateDataService(newDataService); + } + }, [pivotClient, pivotBuilder, shouldBeRecreated]); + + return dataService; +} diff --git a/packages/sdk-ui/src/pivot-table/use-pivot-table-data-options-internal.test.ts b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-table-data-options-internal.test.ts similarity index 94% rename from packages/sdk-ui/src/pivot-table/use-pivot-table-data-options-internal.test.ts rename to packages/sdk-ui/src/pivot-table/hooks/use-pivot-table-data-options-internal.test.ts index 845a6f1d..0b587bdb 100644 --- a/packages/sdk-ui/src/pivot-table/use-pivot-table-data-options-internal.test.ts +++ b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-table-data-options-internal.test.ts @@ -1,7 +1,7 @@ import { renderHook, waitFor } from '@testing-library/react'; -import { PivotSortCriteria } from './sorting-utils'; +import { PivotSortCriteria } from '../sorting-utils'; import { usePivotTableDataOptionsInternal } from './use-pivot-table-data-options-internal'; -import { mockPivotTableProps } from './__mocks__/mocks'; +import { mockPivotTableProps } from '../__mocks__/mocks'; describe('usePivotTableDataOptionsInternal', () => { it('should correctly translate dataOptions into internalDataOptions', async () => { diff --git a/packages/sdk-ui/src/pivot-table/use-pivot-table-data-options-internal.ts b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-table-data-options-internal.ts similarity index 87% rename from packages/sdk-ui/src/pivot-table/use-pivot-table-data-options-internal.ts rename to packages/sdk-ui/src/pivot-table/hooks/use-pivot-table-data-options-internal.ts index 4744e85c..50bde0a7 100644 --- a/packages/sdk-ui/src/pivot-table/use-pivot-table-data-options-internal.ts +++ b/packages/sdk-ui/src/pivot-table/hooks/use-pivot-table-data-options-internal.ts @@ -2,9 +2,9 @@ import { useState } from 'react'; import { PivotTableDataOptions, PivotTableDataOptionsInternal, -} from '../chart-data-options/types.js'; -import { translatePivotTableDataOptions } from '../chart-data-options/translate-data-options.js'; -import { PivotSortCriteria } from './sorting-utils.js'; +} from '../../chart-data-options/types.js'; +import { translatePivotTableDataOptions } from '../../chart-data-options/translate-data-options.js'; +import { PivotSortCriteria } from '../sorting-utils.js'; import { safeCombine } from '@/chart-data-options/utils.js'; type UsePivotTableDataOptionsInternalResult = { diff --git a/packages/sdk-ui/src/pivot-table/hooks/use-render-pivot.ts b/packages/sdk-ui/src/pivot-table/hooks/use-render-pivot.ts new file mode 100644 index 00000000..d77a2d86 --- /dev/null +++ b/packages/sdk-ui/src/pivot-table/hooks/use-render-pivot.ts @@ -0,0 +1,104 @@ +import { useCallback, useMemo, useEffect } from 'react'; +import type { PivotBuilder, PivotTreeNode } from '@sisense/sdk-pivot-client'; +import type { CompleteThemeSettings, PivotTableStyleOptions } from '@/types'; +import type { PivotTableDataOptions, StyledColumn } from '@/chart-data-options/types'; +import type { ContainerSize } from '@/dynamic-size-container/dynamic-size-container'; +import { preparePivotStylingProps } from '../helpers/prepare-pivot-styling-props'; + +const DEFAULT_TABLE_ROWS_PER_PAGE = 25 as const; + +type PivotRenderOptions = { + /** Reference to the pivot table container. */ + nodeRef: React.RefObject; + /** The pivot builder instance. */ + pivotBuilder: PivotBuilder; + /** The pivot table data options. */ + dataOptions: PivotTableDataOptions; + /** The pivot table style options. */ + styleOptions: PivotTableStyleOptions; + /** The theme settings. */ + themeSettings: CompleteThemeSettings; + /** The size of the pivot table container. */ + size: ContainerSize | null; +}; + +/** + * A hook that renders the pivot table. + */ +export function useRenderPivot({ + nodeRef, + pivotBuilder, + dataOptions, + styleOptions, + themeSettings, + size, +}: PivotRenderOptions): void { + const onUpdatePredefinedColumnWidth = useCallback( + (horizontalLastLevelsNodes: Array, resizedColumnWidth?: Array) => { + const dataOptionsFlatten = [ + ...(dataOptions.rows ? dataOptions.rows : []), + ...(dataOptions.columns ? dataOptions.columns : []), + ...(dataOptions.values ? dataOptions.values : []), + ]; + + const dataOptionsWidths = dataOptionsFlatten.map((i) => (i as StyledColumn)?.width); + + if (resizedColumnWidth) { + const [nodeIndex, newWidth] = resizedColumnWidth; + const node = horizontalLastLevelsNodes[nodeIndex]; + if (node && typeof node.jaqlIndex !== 'undefined') { + dataOptionsWidths[node.jaqlIndex] = newWidth; + } + } + + const predefinedColumnWidth: Array> = []; + horizontalLastLevelsNodes.forEach((columnNode, columnIndex) => { + if ( + typeof columnNode.jaqlIndex !== 'undefined' && + typeof dataOptionsWidths[columnNode.jaqlIndex] !== 'undefined' + ) { + predefinedColumnWidth.push([ + columnIndex, + dataOptionsWidths[columnNode.jaqlIndex] as number, + ]); + } + }); + + return predefinedColumnWidth; + }, + [dataOptions], + ); + + const pivotStylingProps = useMemo( + () => preparePivotStylingProps(styleOptions, themeSettings), + [styleOptions, themeSettings], + ); + + const { rowsPerPage = DEFAULT_TABLE_ROWS_PER_PAGE } = styleOptions; + + const props = useMemo(() => { + if (size) { + return { + width: size.width, + height: size.height, + isPaginated: true, + itemsPerPage: rowsPerPage, + isSelectedMode: true, + onUpdatePredefinedColumnWidth, + ...pivotStylingProps, + }; + } + return null; + }, [size, rowsPerPage, onUpdatePredefinedColumnWidth, pivotStylingProps]); + + useEffect(() => { + if (nodeRef.current && props) { + const isPivotRendered = !!nodeRef.current.children.length; + if (!isPivotRendered) { + pivotBuilder.render(nodeRef.current, props); + } else { + pivotBuilder.updateProps(props); + } + } + }, [nodeRef, pivotBuilder, props]); +} diff --git a/packages/sdk-ui/src/pivot-table/pivot-table.test.tsx b/packages/sdk-ui/src/pivot-table/pivot-table.test.tsx index 14022523..cbce7970 100644 --- a/packages/sdk-ui/src/pivot-table/pivot-table.test.tsx +++ b/packages/sdk-ui/src/pivot-table/pivot-table.test.tsx @@ -21,9 +21,11 @@ describe('PivotTable', () => { useSisenseContextMock.mockReturnValue({ app: { pivotClient: new PivotClient(new HttpClient(url, new SsoAuthenticator(url), 'test'), true), + settings: { + trackingConfig: { enabled: false }, + }, } as ClientApplication, isInitialized: true, - enableTracking: false, }); }); it('should render empty pivot table', async () => { diff --git a/packages/sdk-ui/src/pivot-table/pivot-table.tsx b/packages/sdk-ui/src/pivot-table/pivot-table.tsx index 835ce57b..efdd3306 100644 --- a/packages/sdk-ui/src/pivot-table/pivot-table.tsx +++ b/packages/sdk-ui/src/pivot-table/pivot-table.tsx @@ -1,30 +1,25 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +/* eslint-disable promise/catch-or-return */ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { - EVENT_QUERY_END, - EVENT_QUERY_START, EVENT_SORTING_SETTINGS_CHANGED, - PivotTreeNode, - InitPageData, - PivotBuilder, type SortingSettingsChangePayload, } from '@sisense/sdk-pivot-client'; import { PivotTableProps } from '../props'; import { asSisenseComponent } from '../decorators/component-decorators/as-sisense-component'; import { useSisenseContext } from '../sisense-context/sisense-context'; -import { usePivotTableQuery } from './use-get-pivot-table-query'; import { preparePivotRowsSortCriteriaList } from './sorting-utils'; import { DEFAULT_PIVOT_TABLE_SIZE, DynamicSizeContainer } from '@/dynamic-size-container'; import { type ContainerSize } from '@/dynamic-size-container/dynamic-size-container'; -import { useApplyPivotTableFormatting } from './use-apply-pivot-table-formatting'; -import { preparePivotStylingProps } from '@/pivot-table/helpers/prepare-pivot-styling-props'; import { useThemeContext } from '@/theme-provider'; -import { usePivotTableDataOptionsInternal } from './use-pivot-table-data-options-internal'; import { LoadingOverlay } from '@/common/components/loading-overlay'; -import { StyledColumn } from '@/chart-data-options/types'; import { useHasChanged } from '@/common/hooks/use-has-changed'; import { NoResultsOverlay } from '@/no-results-overlay/no-results-overlay'; - -const DEFAULT_TABLE_ROWS_PER_PAGE = 25 as const; +import { usePivotDataLoading } from './hooks/use-pivot-data-loading'; +import { usePivotDataService } from './hooks/use-pivot-data-service'; +import { usePivotTableDataOptionsInternal } from './hooks/use-pivot-table-data-options-internal'; +import { useApplyPivotTableFormatting } from './hooks/use-apply-pivot-table-formatting'; +import { usePivotTableQuery } from './hooks/use-get-pivot-table-query'; +import { useRenderPivot } from './hooks/use-render-pivot'; /** * Pivot table with pagination. @@ -110,8 +105,7 @@ const DEFAULT_TABLE_ROWS_PER_PAGE = 25 as const; export const PivotTable = asSisenseComponent({ componentName: 'PivotTable', })((pivotTableProps: PivotTableProps) => { - const [isLoading, setIsLoading] = useState(false); - const { dataSet, dataOptions, filters, highlights, refreshCounter } = pivotTableProps; + const { dataSet, dataOptions, filters, highlights, refreshCounter = 0 } = pivotTableProps; const styleOptions = useMemo( () => pivotTableProps.styleOptions ?? {}, [pivotTableProps.styleOptions], @@ -136,105 +130,29 @@ export const PivotTable = asSisenseComponent({ filters, highlights, }); - - const onUpdatePredefinedColumnWidth = useCallback( - (horizontalLastLevelsNodes: Array, resizedColumnWidth?: Array) => { - const dataOptionsFlatten = [ - ...(dataOptions.rows ? dataOptions.rows : []), - ...(dataOptions.columns ? dataOptions.columns : []), - ...(dataOptions.values ? dataOptions.values : []), - ]; - - const dataOptionsWidths = dataOptionsFlatten.map((i) => (i as StyledColumn)?.width); - - if (resizedColumnWidth) { - const [nodeIndex, newWidth] = resizedColumnWidth; - const node = horizontalLastLevelsNodes[nodeIndex]; - if (node && typeof node.jaqlIndex !== 'undefined') { - dataOptionsWidths[node.jaqlIndex] = newWidth; - } - } - - const predefinedColumnWidth: Array> = []; - horizontalLastLevelsNodes.forEach((columnNode, columnIndex) => { - if ( - typeof columnNode.jaqlIndex !== 'undefined' && - typeof dataOptionsWidths[columnNode.jaqlIndex] !== 'undefined' - ) { - predefinedColumnWidth.push([ - columnIndex, - dataOptionsWidths[columnNode.jaqlIndex] as number, - ]); - } - }); - - return predefinedColumnWidth; - }, - [dataOptions], - ); - - const shouldReloadData = useHasChanged({ jaql, refreshCounter }, ['jaql', 'refreshCounter']); - if (error) { throw error; } const pivotBuilder = useMemo(() => pivotClient.preparePivotBuilder(), [pivotClient]); - const dataService = useMemo( - () => pivotClient.prepareDataService(), - // eslint-disable-next-line react-hooks/exhaustive-deps - [pivotClient, shouldReloadData], - ); - useApplyPivotTableFormatting({ dataService, dataOptions }); - useEffect(() => { - if (nodeRef.current && jaql && size) { - const { rowsPerPage = DEFAULT_TABLE_ROWS_PER_PAGE } = styleOptions; - const props = { - width: size.width, - height: size.height, - isPaginated: true, - itemsPerPage: rowsPerPage, - isSelectedMode: true, - onUpdatePredefinedColumnWidth, - ...preparePivotStylingProps(styleOptions, themeSettings), - }; - const isPivotRendered = nodeRef.current.children.length; + const isJaqlChanged = useHasChanged(jaql); + const isForceReload = refreshCounter > 0 && useHasChanged(refreshCounter); - if (!isPivotRendered) { - pivotBuilder.render(nodeRef.current, props); - } else { - pivotBuilder.updateProps(props); - } + const dataService = usePivotDataService({ + pivotClient, + pivotBuilder, + shouldBeRecreated: isJaqlChanged || isForceReload, + }); + useApplyPivotTableFormatting({ dataService, dataOptions }); - // todo: remove "shouldReloadData" workaround after splitting pivot "render" and "data" flows into separate effects/hooks - if (shouldReloadData) { - // sends pivot query by redefining the dataService - pivotBuilder.updateDataService(dataService); - setIsLoading(true); - dataService - .loadData(jaql) - .then(() => { - pivotBuilder.updateJaql(); - setIsLoading(false); - }) - .catch((e) => { - setIsLoading(false); - throw e; - }); - } - } - }, [ + const { isLoading, isNoResults } = usePivotDataLoading({ jaql, - dataService, pivotBuilder, - pivotClient, - styleOptions, - size, - themeSettings, - onUpdatePredefinedColumnWidth, - shouldReloadData, - ]); + isForceReload, + }); + + useRenderPivot({ nodeRef, pivotBuilder, dataOptions, styleOptions, themeSettings, size }); const onSort = useCallback( (payload: SortingSettingsChangePayload) => { @@ -262,8 +180,6 @@ export const PivotTable = asSisenseComponent({ [size, setSize], ); - const { isNoResults } = useCheckForNoResults(pivotBuilder); - return ( ); }); - -/** - * Hook to check if the pivot table has no results. - */ -function useCheckForNoResults(pivotBuilder: PivotBuilder) { - const [isNoResults, setIsNoResults] = useState(false); - const onQueryStart = useCallback(() => { - setIsNoResults(false); - }, []); - - const onQueryEnd = useCallback((data: InitPageData) => { - setIsNoResults(!data.cellsMetadata); - }, []); - - useEffect(() => { - pivotBuilder.on(EVENT_QUERY_START, onQueryStart); - return () => { - pivotBuilder.off(EVENT_QUERY_START, onQueryStart); - }; - }, [pivotBuilder, onQueryStart]); - - useEffect(() => { - pivotBuilder.on(EVENT_QUERY_END, onQueryEnd); - return () => { - pivotBuilder.off(EVENT_QUERY_END, onQueryEnd); - }; - }, [pivotBuilder, onQueryEnd]); - - return { isNoResults }; -} diff --git a/packages/sdk-ui/src/props.tsx b/packages/sdk-ui/src/props.tsx index 6930613f..e79579c7 100644 --- a/packages/sdk-ui/src/props.tsx +++ b/packages/sdk-ui/src/props.tsx @@ -49,6 +49,7 @@ import { TabularChartStyleOptions, TableStyleOptions, AreaRangeStyleOptions, + DrilldownSelection, } from './types'; import { HighchartsOptions } from './chart-options-processor/chart-options-service'; import { ComponentType, PropsWithChildren, ReactNode } from 'react'; @@ -109,16 +110,20 @@ export interface SisenseContextProviderProps { /** * Token for [bearer authentication](https://sisense.dev/guides/restApi/using-rest-api.html). * + * To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. + * * @category Sisense Authentication */ - token?: string; + token?: string | null; /** * [Web Access Token](https://docs.sisense.com/main/SisenseLinux/using-web-access-token.htm). * + * To signify that the token is pending (e.g., being generated), set the value to `null`. This is supported for React and Vue only. + * * @category Sisense Authentication */ - wat?: string; + wat?: string | null; /** * Application specific configurations such as locale and date formats. @@ -131,18 +136,34 @@ export interface SisenseContextProviderProps { * Boolean flag to show or hide run-time errors that involve Sisense context in the UI. * Example errors include incorrect Sisense URL or invalid authentication. * Note that this flag does not hide run-time errors in the console. + * If disabled - it's recommended to specify an {@link onError} callback to handle errors. * * If not specified, the default value is `true`. * - * @internal + * @category Sisense App Error Handling */ showRuntimeErrors?: boolean; + /** + * Callback function that is triggered when an error occurs within the Sisense context. + * + * This callback is useful for handling errors that happen during the initialization or runtime of the Sisense context, + * such as incorrect configuration, invalid authentication, or network-related issues. + * + * @param error - The error object containing details about the issue. + * + * @category Sisense App Error Handling + */ + onError?: (error: Error) => void; + /** * Boolean flag to enable sending tracking events to the Sisense instance. * * If not specified, the default value is `true`. * + * Deprecated: Use {@link AppConfig.trackingConfig | trackingConfig.enabled } + * + * @deprecated Use {@link AppConfig.trackingConfig | trackingConfig.enabled } * @internal */ enableTracking?: boolean; @@ -1511,7 +1532,9 @@ export type DrilldownWidgetConfig = { */ breadcrumbsComponent?: ComponentType; /** - * Boolean to override default breadcrumbs location and instead only return them as a property of the 'children' function + * React component to be rendered as context menu + * + * {@link ContextMenu} will be used if not provided * * @category Widget */ @@ -1534,6 +1557,13 @@ export interface DrilldownWidgetProps { * @category Widget */ initialDimension: Attribute; + + /** + * Initial drilldown selections + * + * @internal + */ + drilldownSelections?: DrilldownSelection[]; /** * An object that allows users to pass advanced configuration options as a prop for the `DrilldownWidget` component * diff --git a/packages/sdk-ui/src/query-execution/execute-query-by-widget-id.test.tsx b/packages/sdk-ui/src/query-execution/execute-query-by-widget-id.test.tsx index a4131e32..a2148933 100644 --- a/packages/sdk-ui/src/query-execution/execute-query-by-widget-id.test.tsx +++ b/packages/sdk-ui/src/query-execution/execute-query-by-widget-id.test.tsx @@ -22,7 +22,11 @@ describe('ExecuteQueryByWidgetId', () => { it('should generate and execute query for the existing widget', async () => { const { getByText } = render( - + {({ data, query }) => { if (!data || !query) { @@ -49,7 +53,11 @@ describe('ExecuteQueryByWidgetId', () => { const onDataChangedMock = vi.fn<[QueryResultData, ExecuteQueryParams]>(); const { getByText } = render( - + { const TEXT_TO_DISPLAY = 'Query result ready'; const { getByText } = render( - + { beforeEach(() => { executeCsvQueryMock.mockClear(); + trackProductEventMock.mockClear(); useSisenseContextMock.mockReturnValue({ app: {} as ClientApplication, isInitialized: true, @@ -114,7 +115,10 @@ describe('useExecuteCsvQuery', () => { }); it('should handle missing Sisense context', () => { - useSisenseContextMock.mockReturnValue({ isInitialized: false, enableTracking: false }); + useSisenseContextMock.mockReturnValue({ + isInitialized: false, + app: { settings: { trackingConfig: { enabled: false } } }, + }); const { result } = renderHook(() => useExecuteCsvQuery(params)); diff --git a/packages/sdk-ui/src/query-execution/use-execute-pivot-query.test.ts b/packages/sdk-ui/src/query-execution/use-execute-pivot-query.test.ts index 903f8108..160f8bf0 100644 --- a/packages/sdk-ui/src/query-execution/use-execute-pivot-query.test.ts +++ b/packages/sdk-ui/src/query-execution/use-execute-pivot-query.test.ts @@ -42,6 +42,7 @@ describe('useExecutePivotQuery', () => { beforeEach(() => { executePivotQueryMock.mockClear(); + trackProductEventMock.mockClear(); useSisenseContextMock.mockReturnValue({ app: {} as ClientApplication, isInitialized: true, @@ -96,7 +97,10 @@ describe('useExecutePivotQuery', () => { }); it('should handle missing Sisense context', () => { - useSisenseContextMock.mockReturnValue({ isInitialized: false, enableTracking: false }); + useSisenseContextMock.mockReturnValue({ + isInitialized: false, + app: { settings: { trackingConfig: { enabled: false } } }, + }); const { result } = renderHook(() => useExecutePivotQuery(params)); diff --git a/packages/sdk-ui/src/query-execution/use-execute-query-by-widget-id.test.ts b/packages/sdk-ui/src/query-execution/use-execute-query-by-widget-id.test.ts index 88ed686a..e9cedc41 100644 --- a/packages/sdk-ui/src/query-execution/use-execute-query-by-widget-id.test.ts +++ b/packages/sdk-ui/src/query-execution/use-execute-query-by-widget-id.test.ts @@ -205,6 +205,7 @@ describe('useExecuteQueryByWidgetId', () => { executePivotQueryMock.mockClear(); getWidgetMock.mockClear(); getDashboardMock.mockClear(); + trackProductEventMock.mockClear(); useSisenseContextMock.mockReturnValue({ app: {} as ClientApplication, isInitialized: true, diff --git a/packages/sdk-ui/src/query-execution/use-execute-query.test.ts b/packages/sdk-ui/src/query-execution/use-execute-query.test.ts index cd704311..d4e32b98 100644 --- a/packages/sdk-ui/src/query-execution/use-execute-query.test.ts +++ b/packages/sdk-ui/src/query-execution/use-execute-query.test.ts @@ -124,7 +124,10 @@ describe('useExecuteQuery', () => { }); it('should handle missing Sisense context', () => { - useSisenseContextMock.mockReturnValue({ isInitialized: false, enableTracking: false }); + useSisenseContextMock.mockReturnValue({ + isInitialized: false, + appConfig: { trackingConfig: { enabled: false } }, + }); const { result } = renderHook(() => useExecuteQuery(params)); @@ -223,6 +226,7 @@ describe('useExecuteQuery', () => { }, }); executeQueryWithCacheMock.mockClear(); + trackProductEventMock.mockClear(); createExecuteQueryCacheKeyMock.mockReturnValue('cache-key'); }); it('should call `executeQueryWithCache` function', async () => { diff --git a/packages/sdk-ui/src/sisense-chart/sisense-chart.tsx b/packages/sdk-ui/src/sisense-chart/sisense-chart.tsx index d00bc076..68b2eedf 100644 --- a/packages/sdk-ui/src/sisense-chart/sisense-chart.tsx +++ b/packages/sdk-ui/src/sisense-chart/sisense-chart.tsx @@ -89,6 +89,7 @@ export const SisenseChart = ({ const accessibilityEnabled = app?.settings.accessibilityConfig?.enabled || false; const highchartsOptionsWithCommonOptions = applyCommonHighchartsOptions( highchartsOptions, + themeSettings, accessibilityEnabled, ); diff --git a/packages/sdk-ui/src/sisense-context/sisense-context-provider.tsx b/packages/sdk-ui/src/sisense-context/sisense-context-provider.tsx index 81a6d388..523a4e76 100644 --- a/packages/sdk-ui/src/sisense-context/sisense-context-provider.tsx +++ b/packages/sdk-ui/src/sisense-context/sisense-context-provider.tsx @@ -6,6 +6,7 @@ import { ErrorBoundary } from '../error-boundary/error-boundary'; import { SisenseContext } from './sisense-context'; import { I18nProvider } from '../translation/i18n-provider'; import { SisenseQueryClientProvider } from './sisense-query-client-provider'; +import { isAuthTokenPending } from '@sisense/sdk-rest-client'; /** * Sisense Context Provider Component allowing you to connect to @@ -54,9 +55,16 @@ export const SisenseContextProvider: FunctionComponent< enableTracking = true, showRuntimeErrors = true, enableSilentPreAuth = false, + onError, }) => { const tracking = { - enabled: enableTracking, + // if tracking is configured in appConfig, use it, otherwise use enableTracking + // if none is set, default to true + enabled: + appConfig?.trackingConfig?.enabled !== undefined + ? appConfig.trackingConfig.enabled + : enableTracking ?? true, + onTrackingEvent: appConfig?.trackingConfig?.onTrackingEvent, packageName: 'sdk-ui', }; const [app, setApp] = useState(); @@ -65,6 +73,14 @@ export const SisenseContextProvider: FunctionComponent< useEffect(() => { let ignore = false; + + // if the token is pending (not ready), wait for it to be set + // instead of trying to create the client application and throw an error + if (isAuthTokenPending(token, wat)) { + console.debug('Waiting for the auth token to be set'); + return; + } + void createClientApplication({ defaultDataSource, url, @@ -80,13 +96,15 @@ export const SisenseContextProvider: FunctionComponent< } }) .catch((asyncError: Error) => { + onError?.(asyncError); + console.error(asyncError); // set error state to trigger rerender and throw synchronous error setClientApplicationError(asyncError); }); return () => { ignore = true; }; - }, [defaultDataSource, url, token, wat, ssoEnabled, appConfig, enableSilentPreAuth]); + }, [defaultDataSource, url, token, wat, ssoEnabled, appConfig, enableSilentPreAuth, onError]); return ( diff --git a/packages/sdk-ui/src/sisense-context/sisense-context.ts b/packages/sdk-ui/src/sisense-context/sisense-context.ts index 67b55ef9..887f888b 100644 --- a/packages/sdk-ui/src/sisense-context/sisense-context.ts +++ b/packages/sdk-ui/src/sisense-context/sisense-context.ts @@ -1,5 +1,6 @@ import { createContext, useContext } from 'react'; import { ClientApplication } from '../app/client-application'; +import { TrackingEventDetails } from '@sisense/sdk-tracking'; export type SisenseContextPayload = { isInitialized: boolean; @@ -7,6 +8,7 @@ export type SisenseContextPayload = { tracking: { enabled: boolean; packageName: string; + onTrackingEvent?: (payload: TrackingEventDetails) => void; }; }; diff --git a/packages/sdk-ui/src/table/hooks/use-table-data.test.ts b/packages/sdk-ui/src/table/hooks/use-table-data.test.ts index 619234a3..8a891a0d 100644 --- a/packages/sdk-ui/src/table/hooks/use-table-data.test.ts +++ b/packages/sdk-ui/src/table/hooks/use-table-data.test.ts @@ -95,7 +95,7 @@ describe('useTableData', () => { const [data, dataOptions] = result.current; expect(data).toBeNull(); - expect(dataOptions).toBeNull(); + expect(dataOptions).toBe(fetchProps.dataOptions); await waitFor(() => { const [data2, dataOptions2] = result.current; @@ -118,7 +118,7 @@ describe('useTableData', () => { const [data, dataOptions] = result.current; expect(data).toBeNull(); - expect(dataOptions).toBeNull(); + expect(dataOptions).toBe(fetchProps.dataOptions); setTimeout(() => { rerender(fetchMoreProps); @@ -153,7 +153,7 @@ describe('useTableData', () => { const [data, dataOptions] = result.current; expect(data).toBeNull(); - expect(dataOptions).toBeNull(); + expect(dataOptions).toBe(fetchAllProps.dataOptions); setTimeout(() => { rerender(fetchMoreProps); @@ -186,7 +186,7 @@ describe('useTableData', () => { const [data, dataOptions] = result.current; expect(data).toBeNull(); - expect(dataOptions).toBeNull(); + expect(dataOptions).toBe(fetchProps.dataOptions); await waitFor(() => { expect(mockSetError).toHaveBeenCalled(); @@ -194,7 +194,7 @@ describe('useTableData', () => { const [data2, dataOptions2] = result.current; expect(data2).toBeNull(); - expect(dataOptions2).toBeNull(); + expect(dataOptions2).toBe(fetchProps.dataOptions); }); }); }); diff --git a/packages/sdk-ui/src/table/hooks/use-table-data.ts b/packages/sdk-ui/src/table/hooks/use-table-data.ts index 9b82f8ed..e57d56bf 100644 --- a/packages/sdk-ui/src/table/hooks/use-table-data.ts +++ b/packages/sdk-ui/src/table/hooks/use-table-data.ts @@ -56,7 +56,7 @@ export const useTableData = ({ const [isLoading, setIsLoading] = useState(false); const isMoreDataAvailable = useRef(true); const { isInitialized, app } = useSisenseContext(); - const [dataOptions, setDataOptions] = useState(null); + const [dataOptions, setDataOptions] = useState(originalDataOptions); useEffect(() => { let ignore = false; diff --git a/packages/sdk-ui/src/table/table-component.tsx b/packages/sdk-ui/src/table/table-component.tsx index 09a221db..6856d1ad 100644 --- a/packages/sdk-ui/src/table/table-component.tsx +++ b/packages/sdk-ui/src/table/table-component.tsx @@ -49,6 +49,11 @@ export const TableComponent = ({ [translatedDataOptions], ); + const designOptions = useMemo( + () => translateTableStyleOptionsToDesignOptions(styleOptions), + [styleOptions], + ); + const [innerDataOptions, setInnerDataOptions] = useState(translatedDataOptions); @@ -100,6 +105,17 @@ export const TableComponent = ({ [innerDataOptions], ); + const paginatedTable = useMemo( + () => + dataTable + ? { + columns: dataTable.columns, + rows: dataTable.rows.slice((currentPage - 1) * rowsPerPage, currentPage * rowsPerPage), + } + : undefined, + [dataTable, currentPage, rowsPerPage], + ); + if (!updatedDataOptions) return null; return ( @@ -111,7 +127,7 @@ export const TableComponent = ({ }} > {(size) => { - if (!dataTable) { + if (!dataTable || !paginatedTable) { return ; } @@ -119,10 +135,6 @@ export const TableComponent = ({ return ; } - const paginatedTable = { - columns: dataTable.columns, - rows: dataTable.rows.slice((currentPage - 1) * rowsPerPage, currentPage * rowsPerPage), - }; const pagesCount = Math.ceil(dataTable.rows.length / rowsPerPage); const paginationHeight = pagesCount > 1 ? 32 : 0; @@ -139,7 +151,7 @@ export const TableComponent = ({ { expect(getSlightlyDifferentColor(color)).toBe('rgba(0, 8, 23, 1)'); }); }); + +describe('getExplicitColorSteps', () => { + it('should calculate the correct color range', () => { + const color1 = '#1ae7ff'; + const color2 = '#0090a1'; + expect(getExplicitColorSteps(color1, color2, 5)).toStrictEqual([ + 'rgb(10.196% 90.588% 100%)', + 'rgb(7.5634% 81.786% 90.495%)', + 'rgb(4.797% 73.157% 81.175%)', + 'rgb(2.0254% 64.715% 72.051%)', + 'rgb(0% 56.471% 63.137%)', + ]); + }); +}); diff --git a/packages/sdk-ui/src/utils/color/color-interpolation.ts b/packages/sdk-ui/src/utils/color/color-interpolation.ts index 9aa2d4a9..ff09a8fe 100644 --- a/packages/sdk-ui/src/utils/color/color-interpolation.ts +++ b/packages/sdk-ui/src/utils/color/color-interpolation.ts @@ -134,3 +134,17 @@ export const applyOpacity = (color: string, opacity: number) => { colorObj.alpha = opacity; return toString(colorObj); }; + +/** + * Give an array of color steps in provided range + * + * @param minColor - start range color + * @param maxColor - end range color + * @param steps - count of color steps + * @returns - array with color steps + */ +export const getExplicitColorSteps = (minColor: string, maxColor: string, steps: number) => { + return Color.steps(new Color(minColor), new Color(maxColor), { steps }).map((color) => + new Color(color).to('srgb').toString(), + ); +}; diff --git a/packages/sdk-ui/src/utils/combine-handlers.ts b/packages/sdk-ui/src/utils/combine-handlers.ts new file mode 100644 index 00000000..55dfbe07 --- /dev/null +++ b/packages/sdk-ui/src/utils/combine-handlers.ts @@ -0,0 +1,18 @@ +import isFunction from 'lodash/isFunction'; +import flow from 'lodash/flow'; +import over from 'lodash/over'; + +type AnyFunction = (...args: any[]) => any; + +export function combineHandlers( + handlers: (Handler | undefined)[], + chainHandlers = false, +): Handler { + const validHandlers = handlers.filter((handler) => isFunction(handler)) as Handler[]; + + if (chainHandlers) { + return flow(validHandlers) as Handler; + } + + return over(validHandlers) as Handler; +} diff --git a/packages/sdk-ui/src/utils/filters.ts b/packages/sdk-ui/src/utils/filters.ts index 88c8d99a..216ece27 100644 --- a/packages/sdk-ui/src/utils/filters.ts +++ b/packages/sdk-ui/src/utils/filters.ts @@ -1,5 +1,62 @@ -import { CascadingFilter, Filter } from '@sisense/sdk-data'; +import { + Attribute, + CascadingFilter, + DimensionalLevelAttribute, + Filter, + filterFactory, + MembersFilter, +} from '@sisense/sdk-data'; +import { cloneDeep } from 'lodash'; export function isCascadingFilter(filter: Filter): filter is CascadingFilter { return filter instanceof CascadingFilter; } + +/** + * Clones a filter with a toggled 'disabled' state. + * + * @param filter - Filter to clone + */ +export const cloneFilterAndToggleDisabled = (filter: TFilter): TFilter => { + const newFilter = cloneFilter(filter); + newFilter.disabled = !filter.disabled; + return newFilter; +}; + +export const cloneFilter = (filter: TFilter): TFilter => { + const newFilter = cloneDeep(filter); + Object.setPrototypeOf(newFilter, filter); + return newFilter; +}; + +function createIncludeAllFilter(attribute: Attribute, backgroundFilter?: Filter, guid?: string) { + return filterFactory.members(attribute, [], false, guid, undefined, backgroundFilter); +} + +export function clearMembersFilter(filter: Filter) { + if (!isMembersFilter(filter)) { + throw new Error('Filter is not a MembersFilter'); + } + const { attribute, guid, backgroundFilter } = filter; + return createIncludeAllFilter(attribute, backgroundFilter, guid); +} + +export function isMembersFilter(filter: Filter): filter is MembersFilter { + return filter instanceof MembersFilter; +} + +export function isIncludeAllFilter(filter: Filter) { + return 'members' in filter && (filter as MembersFilter).members.length === 0; +} + +export function haveSameAttribute(filterA: Filter, filterB: Filter) { + return isSameAttribute(filterA.attribute, filterB.attribute); +} + +export function isSameAttribute(attributeA: Attribute, attributeB: Attribute) { + return ( + attributeA.expression === attributeB?.expression && + (attributeA as DimensionalLevelAttribute).granularity === + (attributeB as DimensionalLevelAttribute).granularity + ); +} diff --git a/packages/sdk-ui/src/vite-env.d.ts b/packages/sdk-ui/src/vite-env.d.ts index dec6db0e..59093bbf 100644 --- a/packages/sdk-ui/src/vite-env.d.ts +++ b/packages/sdk-ui/src/vite-env.d.ts @@ -4,6 +4,7 @@ interface ImportMetaEnv { VITE_APP_SISENSE_URL?: string; VITE_APP_SISENSE_TOKEN?: string; VITE_APP_DEMO_DYNAMIC_IMPORTS?: string; + VITE_APP_ANIMATION_DURATION: string; } interface ImportMeta { diff --git a/packages/sdk-ui/src/widgets/__mocks__/mocks.ts b/packages/sdk-ui/src/widgets/__mocks__/mocks.ts index 57a7f24f..e99f362d 100644 --- a/packages/sdk-ui/src/widgets/__mocks__/mocks.ts +++ b/packages/sdk-ui/src/widgets/__mocks__/mocks.ts @@ -27,7 +27,7 @@ export const mockChartWidgetPropsForTable: ChartWidgetProps = { }, }; -export const mockResolvedTableQuery: QueryResultData = { +export const mockResolvedQuery: QueryResultData = { columns: [ { name: 'AgeRange', diff --git a/packages/sdk-ui/src/widgets/__snapshots__/chart-widget.test.tsx.snap b/packages/sdk-ui/src/widgets/__snapshots__/chart-widget.test.tsx.snap index 2e44a4d2..6d9e6bda 100644 --- a/packages/sdk-ui/src/widgets/__snapshots__/chart-widget.test.tsx.snap +++ b/packages/sdk-ui/src/widgets/__snapshots__/chart-widget.test.tsx.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`ChartWidget > should render ChartWidget for table widget 1`] = ` +exports[`ChartWidget > should render table widget 1`] = `
should render empty pivot table widget 1`] = ` >
+ > +
+
+
+
+
+
+
+ + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + +
+
+
+ + + + + +
+
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ + Rows + +

+
+ + + + + +
+

+ + 0-0 / 0 + +

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/sdk-ui/src/widgets/chart-widget-deprecated.tsx b/packages/sdk-ui/src/widgets/chart-widget-deprecated.tsx deleted file mode 100644 index fcd2fd88..00000000 --- a/packages/sdk-ui/src/widgets/chart-widget-deprecated.tsx +++ /dev/null @@ -1,207 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import React, { useCallback, useMemo, useState, type FunctionComponent } from 'react'; - -import { Chart } from '../chart'; -import { - CompleteThemeSettings, - MenuPosition, - ChartDataPoint, - ChartDataPointEventHandler, - ChartDataPoints, -} from '../types'; -import { ChartDataPointsEventHandler, ChartWidgetProps } from '../props'; -import { ContextMenu } from './common/context-menu'; -import { useWidgetDrilldown } from './common/use-widget-drilldown'; -import { WidgetHeader } from './common/widget-header'; -import { ThemeProvider, useThemeContext } from '../theme-provider'; -import { WidgetCornerRadius, WidgetSpaceAround, getShadowValue } from './common/widget-style-utils'; -import { asSisenseComponent } from '../decorators/component-decorators/as-sisense-component'; -import { DynamicSizeContainer, getWidgetDefaultSize } from '../dynamic-size-container'; -import { getDataSourceName } from '@sisense/sdk-data'; -import get from 'lodash/get'; - -/** - * The Chart Widget component extending the {@link Chart} component to support advanced BI - * capabilities such as drilldown. - * - * @example - * Example of using the `ChartWidget` component to - * plot a bar chart of the `Sample ECommerce` data source hosted in a Sisense instance. - * Drill-down capability is enabled. - * ```tsx - * - * ``` - * - * - * @param props - ChartWidget properties - * @returns ChartWidget component representing a chart type as specified in `ChartWidgetProps.`{@link ChartWidgetProps.chartType} - */ -export const ChartWidgetDeprecated: FunctionComponent = asSisenseComponent({ - componentName: 'ChartWidgetDeprecated', -})((props) => { - const [contextMenuPos, setContextMenuPos] = useState(null); - - const [refreshCounter, setRefreshCounter] = useState(0); - const hasDrilldownOptions = - props.drilldownOptions?.drilldownDimensions?.length || - props.drilldownOptions?.drilldownSelections?.length; - - // drilldown is not supported for scatter charts or filterRelations or when not drilldown configuration was set - if (hasDrilldownOptions && props.chartType !== 'scatter' && Array.isArray(props.filters)) { - props = useWidgetDrilldown(props); - } - - const { - onDataPointContextMenu, - onDataPointsSelected, - onContextMenuClose, - dataSource, - topSlot, - bottomSlot, - contextMenuItems, - title, - description, - - styleOptions, - ...restProps - } = props; - - const { themeSettings } = useThemeContext(); - - const closeContextMenu = useCallback(() => { - setContextMenuPos(null); - onContextMenuClose?.(); - }, [setContextMenuPos, onContextMenuClose]); - - const defaultSize = getWidgetDefaultSize(props.chartType, { - hasHeader: !styleOptions?.header?.hidden, - }); - const { width, height, ...styleOptionsWithoutSizing } = styleOptions || {}; - - const chartProps = { - ...restProps, - dataSet: dataSource, - styleOptions: styleOptionsWithoutSizing, - onDataPointContextMenu: useMemo( - () => - contextMenuItems - ? (point: ChartDataPoint, nativeEvent: PointerEvent) => { - (onDataPointContextMenu as ChartDataPointEventHandler | undefined)?.( - point, - nativeEvent, - ); - const { clientX: left, clientY: top } = nativeEvent; - setContextMenuPos({ left, top }); - } - : onDataPointContextMenu, - [contextMenuItems, onDataPointContextMenu, setContextMenuPos], - ), - onDataPointsSelected: useMemo( - () => - contextMenuItems - ? (points: ChartDataPoints, nativeEvent: MouseEvent) => { - (onDataPointsSelected as ChartDataPointsEventHandler | undefined)?.( - points, - nativeEvent, - ); - const { clientX: left, clientY: top } = nativeEvent; - setContextMenuPos({ left, top }); - } - : onDataPointsSelected, - [contextMenuItems, onDataPointsSelected, setContextMenuPos], - ), - }; - - if (!props.chartType || !props.dataOptions) { - return null; - } - - return ( - -
-
-
- {!styleOptions?.header?.hidden && ( - setRefreshCounter(refreshCounter + 1)} - /> - )} - {topSlot} - - - -
- -
-
- - {bottomSlot} -
-
-
-
- ); -}); diff --git a/packages/sdk-ui/src/widgets/chart-widget.test.tsx b/packages/sdk-ui/src/widgets/chart-widget.test.tsx index 828aa53b..6359f610 100644 --- a/packages/sdk-ui/src/widgets/chart-widget.test.tsx +++ b/packages/sdk-ui/src/widgets/chart-widget.test.tsx @@ -1,11 +1,14 @@ /** @vitest-environment jsdom */ import { render } from '@testing-library/react'; -import { mockChartWidgetPropsForTable, mockResolvedTableQuery } from './__mocks__/mocks'; +import { measureFactory } from '@sisense/sdk-data'; +import cloneDeep from 'lodash/cloneDeep'; +import { mockChartWidgetPropsForTable, mockResolvedQuery } from './__mocks__/mocks'; import { useSisenseContextMock } from '../sisense-context/__mocks__/sisense-context'; import { ClientApplication } from '../app/client-application'; import { HttpClient, SsoAuthenticator } from '@sisense/sdk-rest-client'; import { ChartWidget } from './chart-widget'; import { executeQueryMock } from '@/query/__mocks__/execute-query'; +import * as DM from '../__test-helpers__/sample-ecommerce'; vi.mock('../query/execute-query'); vi.mock('../sisense-context/sisense-context'); @@ -19,16 +22,17 @@ describe('ChartWidget', () => { settings: { locale: 'en', dateConfig: {}, + trackingConfig: { enabled: false }, }, } as unknown as ClientApplication, tracking: { packageName: 'mock-package-name' }, isInitialized: true, - enableTracking: false, }); }); - it('should render ChartWidget for table widget', async () => { - executeQueryMock.mockResolvedValue(mockResolvedTableQuery); + + it('should render table widget', async () => { + executeQueryMock.mockResolvedValue(mockResolvedQuery); const { container, findByLabelText } = render( , ); @@ -36,4 +40,45 @@ describe('ChartWidget', () => { expect(table).toBeTruthy(); expect(container).toMatchSnapshot(); }); + + it('should render column widget with applied drilldown', async () => { + // modifies data mock to match dataOptions with aggregated "Revenue" measure + const dataMock = cloneDeep(mockResolvedQuery); + dataMock.columns[1].name = '$measure0_sum Revenue'; + + executeQueryMock.mockResolvedValue(dataMock); + const { findByLabelText, findByText } = render( + , + ); + + // verifies rendered chart + expect(await findByLabelText('chart-root')).toBeInTheDocument(); + + // verifies existence of drilldown breadcrumbs + expect(await findByText('Male')).toBeInTheDocument(); + expect(await findByText('Age Range (All)')).toBeInTheDocument(); + }); }); diff --git a/packages/sdk-ui/src/widgets/chart-widget.tsx b/packages/sdk-ui/src/widgets/chart-widget.tsx index 9e84c0f7..e05d5524 100644 --- a/packages/sdk-ui/src/widgets/chart-widget.tsx +++ b/packages/sdk-ui/src/widgets/chart-widget.tsx @@ -1,26 +1,22 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { useCallback, useMemo, useState, type FunctionComponent } from 'react'; +import { ReactNode, useMemo, useState, type FunctionComponent } from 'react'; import { Chart } from '../chart'; -import { - DataPoint, - CartesianChartDataOptions, - ScatterDataPoint, - ChartDataPoints, - ChartDataPoint, -} from '../types'; import { ChartProps, ChartWidgetProps } from '../props'; import { asSisenseComponent } from '../decorators/component-decorators/as-sisense-component'; import { DynamicSizeContainer, getWidgetDefaultSize } from '../dynamic-size-container'; -import { - HighchartsOptions, - HighchartsOptionsInternal, -} from '../chart-options-processor/chart-options-service'; -import { isCartesian } from '../chart-options-processor/translations/types'; -import { ChartWidgetDeprecated } from './chart-widget-deprecated'; import { getDataSourceName } from '@sisense/sdk-data'; import { WidgetContainer } from './common/widget-container'; import { useSisenseContext } from '@/sisense-context/sisense-context'; +import { DrilldownWidget } from './drilldown-widget'; +import { useHighlightSelection } from './use-highlight-selection'; +import { combineHandlers } from '../utils/combine-handlers'; +import { + createDrilldownToChartConnector, + getDrilldownInitialDimension, + isSupportedChartForDrilldown, + isValidChartConfigurationForDrilldown, +} from './common/drilldown-connector'; /** * The Chart Widget component extending the {@link Chart} component to support widget style options. @@ -49,178 +45,81 @@ import { useSisenseContext } from '@/sisense-context/sisense-context'; export const ChartWidget: FunctionComponent = asSisenseComponent({ componentName: 'ChartWidget', })((props) => { - const { chartType, drilldownOptions, highlightSelectionDisabled = false } = props; - - // TODO: remove this once drilldownOptions are removed from ChartWidgetProps - if (drilldownOptions) { - return ; - } - - const [refreshCounter, setRefreshCounter] = useState(0); - const [selectedDataPoints, setSelectedDataPoints] = useState([]); - const { app } = useSisenseContext(); - - const isCartesianChart = useMemo(() => isCartesian(chartType), [chartType]); - const isScatterChart = useMemo(() => chartType === 'scatter', [chartType]); - const isDrilldownEnabled = useMemo(() => !!drilldownOptions, [drilldownOptions]); - - const isSelectionAllowed = useMemo( - () => - !highlightSelectionDisabled && - !isDrilldownEnabled && - ((isCartesianChart && - (props.dataOptions as CartesianChartDataOptions).category?.length === 1) || - isScatterChart), - [ - isDrilldownEnabled, - props.dataOptions, - isCartesianChart, - isScatterChart, - highlightSelectionDisabled, - ], - ); - const { + chartType, dataSource = app?.defaultDataSource, - styleOptions, dataOptions, - onDataPointsSelected: originalOnDataPointsSelected, - onDataPointClick: originalOnDataPointClick, - onBeforeRender: originalOnBeforeRender, - ...restProps + styleOptions, + drilldownOptions, + highlightSelectionDisabled = false, + highlights, } = props; + const { width, height, ...styleOptionsWithoutSizing } = styleOptions || {}; + const defaultSize = getWidgetDefaultSize(chartType, { + hasHeader: !styleOptions?.header?.hidden, + }); - const applyPointSelections = useMemo(() => { - if (selectedDataPoints.length === 0) { - return (options: HighchartsOptionsInternal) => - ({ - ...options, - series: options.series.map((s) => ({ - ...s, - data: s.data.map((d) => ({ ...d, selected: false })), - })), - } as HighchartsOptions); - } - if (isScatterChart) { - return (options: HighchartsOptionsInternal) => - ({ - ...options, - series: options.series.map((s) => ({ - ...s, - data: s.data.map((d) => { - return { - ...d, - selected: !(selectedDataPoints as ScatterDataPoint[]).some( - (point) => - point.x === d.x && - point.y === d.y && - point.size === d.z && - point.breakByPoint === d.custom?.maskedBreakByPoint && - point.breakByColor === d.custom?.maskedBreakByColor, - ), - }; - }), - })), - } as HighchartsOptions); - } else { - const categoryValueMap = (selectedDataPoints as DataPoint[]).reduce( - (accu, { categoryValue }) => { - if (categoryValue) { - accu[`${categoryValue}`] = true; - } - return accu; - }, - {}, - ); - - return (options: HighchartsOptionsInternal) => ({ - ...options, - series: options.series.map((s) => ({ - ...s, - data: s.data.map((d) => - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - categoryValueMap[d.custom?.xValue?.[0]] ? d : { ...d, selected: true }, - ), - })), - }); - } - }, [selectedDataPoints, isScatterChart]); - - const setOnClickOutside = useMemo( - () => (options: HighchartsOptions) => - ({ - ...options, - chart: { - ...options.chart, - events: { - ...options.chart?.events, - click: () => { - setSelectedDataPoints([]); - }, - }, - }, - } as HighchartsOptions), - [], - ); - - const onBeforeRender = useCallback( - (options: HighchartsOptions) => { - if (isSelectionAllowed) { - options = applyPointSelections(options as HighchartsOptionsInternal) as HighchartsOptions; - options = setOnClickOutside(options); - } - options = originalOnBeforeRender?.(options) ?? options; - return options; - }, - [originalOnBeforeRender, applyPointSelections, setOnClickOutside, isSelectionAllowed], - ); + const [refreshCounter, setRefreshCounter] = useState(0); - const onDataPointsSelected = useCallback( - (dataPoints: ChartDataPoints, event: MouseEvent): void => { - if (isSelectionAllowed) { - setSelectedDataPoints(dataPoints); - } - originalOnDataPointsSelected?.(dataPoints, event); - }, - [isSelectionAllowed, originalOnDataPointsSelected], - ); + const isDrilldownEnabled = useMemo(() => { + const hasDrilldownConfig = + drilldownOptions?.drilldownSelections?.length || + drilldownOptions?.drilldownDimensions?.length; - type OriginalEvent = Parameters>[1]; - const onDataPointClick = useCallback( - (dataPoint: ChartDataPoint, event: OriginalEvent) => { - if (isSelectionAllowed) { - setSelectedDataPoints([dataPoint] as ChartDataPoints); - } - if (originalOnDataPointClick) { - (originalOnDataPointClick as (dataPoint: ChartDataPoint, event: OriginalEvent) => void)( - dataPoint, - event, - ); - } - }, - [isSelectionAllowed, originalOnDataPointClick], - ); + return ( + hasDrilldownConfig && + isSupportedChartForDrilldown(chartType) && + isValidChartConfigurationForDrilldown(chartType, dataOptions) + ); + }, [drilldownOptions, chartType, dataOptions]); - const defaultSize = getWidgetDefaultSize(chartType, { - hasHeader: !styleOptions?.header?.hidden, + const highlightSelection = useHighlightSelection({ + chartType, + dataOptions, + enabled: !highlightSelectionDisabled && !isDrilldownEnabled && !highlights?.length, }); - const { width, height, ...styleOptionsWithoutSizing } = styleOptions || {}; + + if (!chartType || !dataOptions) { + return null; + } const chartProps = { - ...restProps, - chartType, - dataOptions, + ...props, dataSet: dataSource, styleOptions: styleOptionsWithoutSizing, - onBeforeRender, - onDataPointClick, - onDataPointsSelected, + refreshCounter: refreshCounter, + onDataPointClick: combineHandlers([ + highlightSelection.onDataPointClick, + props.onDataPointClick, + ]), + onDataPointsSelected: combineHandlers([ + highlightSelection.onDataPointsSelected, + props.onDataPointsSelected, + ]), + onBeforeRender: combineHandlers( + [highlightSelection.onBeforeRender, props.onBeforeRender], + true, + ), }; - if (!chartType || !dataOptions) { - return null; - } + const renderChart = (chartProps: ChartProps, topSlot?: ReactNode) => { + return ( + + {props.topSlot} + {topSlot} + + } + dataSetName={dataSource && getDataSourceName(dataSource)} + onRefresh={() => setRefreshCounter(refreshCounter + 1)} + > + + + ); + }; return ( = asSisenseCompone height, }} > - setRefreshCounter(refreshCounter + 1)} - > - - + {isDrilldownEnabled ? ( + + {(drilldownConnectProps) => { + const { breadcrumbsComponent } = drilldownConnectProps; + const withDrilldown = createDrilldownToChartConnector(drilldownConnectProps); + + return renderChart(withDrilldown(chartProps), breadcrumbsComponent); + }} + + ) : ( + renderChart(chartProps) + )} ); }); diff --git a/packages/sdk-ui/src/widgets/common/drilldown-connector.ts b/packages/sdk-ui/src/widgets/common/drilldown-connector.ts new file mode 100644 index 00000000..85d0a725 --- /dev/null +++ b/packages/sdk-ui/src/widgets/common/drilldown-connector.ts @@ -0,0 +1,155 @@ +import { DataPoint, ChartType, ChartDataOptions, ScatterChartDataOptions } from '../../types'; +import { Attribute, type Filter } from '@sisense/sdk-data'; +import { mergeFilters } from '@/dashboard-widget/utils'; +import { combineHandlers } from '../../utils/combine-handlers'; +import { + BOXPLOT_CHART_TYPES, + CARTESIAN_CHART_TYPES, + CATEGORICAL_CHART_TYPES, + RANGE_CHART_TYPES, + SCATTER_CHART_TYPES, + isBoxplot, + isCartesian, + isCategorical, + isRange, + isScatter, +} from '@/chart-options-processor/translations/types'; +import { getSelectableWidgetAttributes } from '@/common-filters/selection-utils'; +import { ChartProps, CustomDrilldownResult, ScatterDataPoint, isMeasureColumn } from '../..'; +import { PointClickEventObject } from '@sisense/sisense-charts'; +import { ScatterCustomPointOptions } from '@/chart-options-processor/translations/scatter-tooltip'; +import camelCase from 'lodash/camelCase'; + +export function getDrilldownInitialDimension(chartType: ChartType, dataOptions: ChartDataOptions) { + return getSelectableWidgetAttributes(chartType, dataOptions)[0]; +} + +export function isSupportedChartForDrilldown(chartType: ChartType) { + return ( + [ + ...CARTESIAN_CHART_TYPES, + ...CATEGORICAL_CHART_TYPES, + ...SCATTER_CHART_TYPES, + ...BOXPLOT_CHART_TYPES, + ...RANGE_CHART_TYPES, + ] as ChartType[] + ).includes(chartType); +} + +export function isValidChartConfigurationForDrilldown( + chartType: ChartType, + dataOptions: ChartDataOptions, +) { + // Drilldown requires the chart to have only one "selectable" attribute (target category) + return getSelectableWidgetAttributes(chartType, dataOptions).length === 1; +} + +function applyDrilldownDimension( + chartType: ChartType, + dataOptions: ChartDataOptions, + drilldownDimension: Attribute, +): ChartDataOptions { + if ( + isCartesian(chartType) || + isCategorical(chartType) || + isBoxplot(chartType) || + isRange(chartType) + ) { + return { + ...dataOptions, + category: [drilldownDimension], + } as ChartDataOptions; + } else if (isScatter(chartType)) { + const scatterDataOptions = dataOptions as ScatterChartDataOptions; + const scatterTargetDataOptionsKeys = ['x', 'y', 'breakByPoint', 'breakByColor']; + + for (const key of scatterTargetDataOptionsKeys) { + if (scatterDataOptions[key] && !isMeasureColumn(scatterDataOptions[key])) { + return { + ...scatterDataOptions, + [key]: drilldownDimension, + } as ScatterChartDataOptions; + } + } + } + + return dataOptions; +} + +function prepareDrilldownSelectionPoints( + points: (DataPoint | ScatterDataPoint)[], + nativeEvent: MouseEvent, + dataOptions: ChartDataOptions, +) { + return points.map((point) => { + const scatterTargetDataOptionsKeys = ['x', 'y', 'breakByPoint', 'breakByColor']; + const isScatterPoint = [...scatterTargetDataOptionsKeys, 'size'].some( + (propName) => propName in point, + ); + const drilldownTargetDataOptionsKey = scatterTargetDataOptionsKeys.find( + (key) => dataOptions[key] && !isMeasureColumn(dataOptions[key]), + )!; + if (isScatterPoint) { + const event = nativeEvent as PointClickEventObject; + const isMultiSelectionEvent = event.type === 'mouseup'; + // todo: add multi-selection support after extending 'points' + if (isMultiSelectionEvent) { + console.warn('No drilldown support for multi-selection in scatter chart'); + } + const value = isMultiSelectionEvent + ? point[drilldownTargetDataOptionsKey] + : (event.point.options.custom as ScatterCustomPointOptions)[ + camelCase(`{masked ${drilldownTargetDataOptionsKey}`) + ]; + return { + categoryValue: value, + categoryDisplayValue: value, + } as DataPoint; + } + + return point as DataPoint; + }); +} + +export function createDrilldownToChartConnector(drilldownConnectProps: CustomDrilldownResult) { + const { drilldownDimension, drilldownFilters, onDataPointsSelected, onContextMenu } = + drilldownConnectProps; + return function withDrilldown(chartProps: ChartProps) { + const { chartType, dataOptions } = chartProps; + + const drilldownOnDataPointsSelected = ( + points: (DataPoint | ScatterDataPoint)[], + nativeEvent: MouseEvent, + ) => { + const drilldownSelectionPoints = prepareDrilldownSelectionPoints( + points, + nativeEvent, + chartProps.dataOptions, + ); + onDataPointsSelected(drilldownSelectionPoints, nativeEvent); + onContextMenu({ + left: nativeEvent.clientX, + top: nativeEvent.clientY, + }); + }; + const drilldownOnDataPointContextMenu = (point: DataPoint, event: MouseEvent) => { + const drilldownSelectionPoints = prepareDrilldownSelectionPoints([point], event, dataOptions); + onDataPointsSelected(drilldownSelectionPoints, event); + onContextMenu({ left: event.clientX, top: event.clientY }); + }; + + return { + ...chartProps, + dataOptions: applyDrilldownDimension(chartType, dataOptions, drilldownDimension), + filters: mergeFilters(chartProps.filters as unknown as Filter[], drilldownFilters), + onDataPointsSelected: combineHandlers([ + drilldownOnDataPointsSelected, + chartProps.onDataPointsSelected, + ]), + onDataPointContextMenu: combineHandlers([ + drilldownOnDataPointContextMenu, + chartProps.onDataPointContextMenu, + ]), + }; + }; +} diff --git a/packages/sdk-ui/src/widgets/common/drilldown.ts b/packages/sdk-ui/src/widgets/common/drilldown.ts deleted file mode 100644 index 605fb6a3..00000000 --- a/packages/sdk-ui/src/widgets/common/drilldown.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* eslint-disable @typescript-eslint/no-use-before-define */ -import { useCallback, useMemo, useState } from 'react'; - -import { - ChartDataOptions, - ChartDataPoint, - DataPoint, - DrilldownOptions, - DrilldownSelection, -} from '../../types'; -import { Attribute, MembersFilter, filterFactory } from '@sisense/sdk-data'; -import { translateColumnToAttribure } from '../../chart-data-options/utils'; - -export const useDrilldown = ( - dataOptions: ChartDataOptions, - drilldownOptions?: DrilldownOptions, -) => { - const { drilldownDimensions = [], drilldownSelections: initialSelections = [] } = - drilldownOptions ?? {}; - - const [drilldownSelections, setDrilldownSelections] = useState(initialSelections); - - const availableDrilldowns = useMemo( - () => - drilldownDimensions.filter(({ expression }) => - drilldownSelections.every(({ nextDimension }) => nextDimension.expression !== expression), - ), - [drilldownDimensions, drilldownSelections], - ); - - const selectDrilldown = useCallback( - (points: DataPoint[], nextDimension: Attribute) => { - setDrilldownSelections((state) => [...state, { points, nextDimension }]); - }, - [setDrilldownSelections], - ); - - const sliceDrilldownSelections = useCallback( - (i: number) => { - setDrilldownSelections((state) => state.slice(0, i)); - }, - [setDrilldownSelections], - ); - - const clearDrilldownSelections = useCallback(() => { - setDrilldownSelections([]); - }, [setDrilldownSelections]); - - const drilldownProps = useMemo( - () => processDrilldownSelections(dataOptions, drilldownSelections), - [dataOptions, drilldownSelections], - ); - - return { - selectDrilldown, - sliceDrilldownSelections, - clearDrilldownSelections, - drilldownSelections, - availableDrilldowns, - ...drilldownProps, - }; -}; - -const processDrilldownSelections = ( - dataOptions: ChartDataOptions, - drilldownSelections: DrilldownSelection[], -) => { - if (!('category' in dataOptions) || !dataOptions.category[0]) { - return { - drilldownFilters: [], - drilldownFiltersDisplayValues: [], - drilldownDimension: undefined, - dataOptionsWithDrilldown: dataOptions, - }; - } - - const [firstCategory, ...otherCategories] = dataOptions.category; - let currentDimension = firstCategory; - const drilldownFilters: MembersFilter[] = []; - const drilldownFiltersDisplayValues: string[][] = []; - - drilldownSelections.forEach(({ points, nextDimension }) => { - drilldownFilters.push( - filterFactory.members( - translateColumnToAttribure(currentDimension), - points.map(getMemberNameFromDataPoint), - ) as MembersFilter, - ); - drilldownFiltersDisplayValues.push(points.map(getDisplayMemberNameFromDataPoint)); - currentDimension = nextDimension; - }); - - return { - drilldownFilters, - drilldownFiltersDisplayValues, - drilldownDimension: translateColumnToAttribure(currentDimension), - dataOptionsWithDrilldown: { - ...dataOptions, - category: [currentDimension, ...otherCategories], - } as ChartDataOptions, - }; -}; - -export function getMemberNameFromDataPoint(point: ChartDataPoint) { - // only DataPoint is currently supported for drilldown - if ('categoryValue' in point) { - return `${point.categoryValue}`; - } else { - return ''; - } -} - -export function getDisplayMemberNameFromDataPoint(point: ChartDataPoint) { - // only DataPoint is currently supported for drilldown - if ('categoryDisplayValue' in point) { - return `${point.categoryDisplayValue}`; - } else if ('categoryValue' in point) { - return `${point.categoryValue}`; - } else { - return ''; - } -} diff --git a/packages/sdk-ui/src/widgets/common/custom-drilldown.test.ts b/packages/sdk-ui/src/widgets/common/use-drilldown.test.ts similarity index 90% rename from packages/sdk-ui/src/widgets/common/custom-drilldown.test.ts rename to packages/sdk-ui/src/widgets/common/use-drilldown.test.ts index 4831c146..4651f037 100644 --- a/packages/sdk-ui/src/widgets/common/custom-drilldown.test.ts +++ b/packages/sdk-ui/src/widgets/common/use-drilldown.test.ts @@ -1,5 +1,5 @@ import { Column, createAttribute } from '@sisense/sdk-data'; -import { processDrilldownSelections, useCustomDrilldown } from './custom-drilldown.js'; +import { processDrilldownSelections, useDrilldown } from './use-drilldown.js'; import { act, renderHook } from '@testing-library/react'; const ageRange = createAttribute({ @@ -20,11 +20,11 @@ const category = createAttribute({ expression: '[Commerce.Category]', }); -describe('Custom Drilldown', () => { - describe('useCustomDrilldown', () => { +describe('Drilldown', () => { + describe('useDrilldown', () => { it('should notify initial dimension is required', () => { expect(() => - useCustomDrilldown({ + useDrilldown({ drilldownDimensions: [], initialDimension: null as unknown as Column, }), @@ -33,7 +33,7 @@ describe('Custom Drilldown', () => { it('should return correct initial drilldown props', () => { const { result } = renderHook(() => - useCustomDrilldown({ drilldownDimensions: [ageRange], initialDimension: gender }), + useDrilldown({ drilldownDimensions: [ageRange], initialDimension: gender }), ); const { @@ -51,7 +51,7 @@ describe('Custom Drilldown', () => { }); it('should update drilldown selections correctly', () => { - const { result } = renderHook(useCustomDrilldown, { + const { result } = renderHook(useDrilldown, { initialProps: { drilldownDimensions: [ageRange], initialDimension: gender }, }); @@ -64,7 +64,7 @@ describe('Custom Drilldown', () => { }); it('should slice drilldown selections correctly', () => { - const { result } = renderHook(useCustomDrilldown, { + const { result } = renderHook(useDrilldown, { initialProps: { drilldownDimensions: [ageRange, category], initialDimension: gender }, }); @@ -91,7 +91,7 @@ describe('Custom Drilldown', () => { }); it('should clear drilldown selections correctly', () => { - const { result } = renderHook(useCustomDrilldown, { + const { result } = renderHook(useDrilldown, { initialProps: { drilldownDimensions: [ageRange], initialDimension: gender }, }); diff --git a/packages/sdk-ui/src/widgets/common/custom-drilldown.ts b/packages/sdk-ui/src/widgets/common/use-drilldown.ts similarity index 61% rename from packages/sdk-ui/src/widgets/common/custom-drilldown.ts rename to packages/sdk-ui/src/widgets/common/use-drilldown.ts index 9eafd3b1..1c0ee2a3 100644 --- a/packages/sdk-ui/src/widgets/common/custom-drilldown.ts +++ b/packages/sdk-ui/src/widgets/common/use-drilldown.ts @@ -1,24 +1,40 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ -import { useCallback, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; -import { StyledColumn, DrilldownSelection, DataPoint } from '../../types.js'; +import { StyledColumn, DrilldownSelection, DataPoint, ChartDataPoint } from '../../types.js'; import { Attribute, Column, MembersFilter, filterFactory } from '@sisense/sdk-data'; -import { getDisplayMemberNameFromDataPoint, getMemberNameFromDataPoint } from './drilldown.js'; +import { useHasChanged } from '@/common/hooks/use-has-changed.js'; -export const useCustomDrilldown = ({ - drilldownDimensions, - initialDimension, -}: { +type UseDrilldownParams = { drilldownDimensions: Attribute[]; initialDimension: Column | StyledColumn; -}) => { + drilldownSelections?: DrilldownSelection[]; +}; + +export const useDrilldown = (params: UseDrilldownParams) => { + const { + drilldownDimensions, + initialDimension, + drilldownSelections: initialDrilldownSelections = [], + } = params; + if (!initialDimension) { throw new Error( 'Initial dimension has to be specified to use drilldown with custom components', ); } - const [drilldownSelections, setDrilldownSelections] = useState([] as DrilldownSelection[]); + const [drilldownSelections, setDrilldownSelections] = useState( + initialDrilldownSelections, + ); + const isInitialSelectionsChanged = useHasChanged(params, ['drilldownSelections']); + + useEffect(() => { + // Apply new selections only if they have changed to prevent losing the selection due to rerendering. + if (isInitialSelectionsChanged) { + setDrilldownSelections(initialDrilldownSelections); + } + }, [initialDrilldownSelections, setDrilldownSelections, isInitialSelectionsChanged]); const availableDrilldowns = useMemo( () => @@ -90,3 +106,23 @@ export const processDrilldownSelections = ( drilldownDimension: currentDimension, }; }; + +function getDisplayMemberNameFromDataPoint(point: ChartDataPoint) { + // only DataPoint is currently supported for drilldown + if ('categoryDisplayValue' in point) { + return `${point.categoryDisplayValue}`; + } else if ('categoryValue' in point) { + return `${point.categoryValue}`; + } else { + return ''; + } +} + +export function getMemberNameFromDataPoint(point: ChartDataPoint) { + // only DataPoint is currently supported for drilldown + if ('categoryValue' in point) { + return `${point.categoryValue}`; + } else { + return ''; + } +} diff --git a/packages/sdk-ui/src/widgets/common/use-widget-drilldown.tsx b/packages/sdk-ui/src/widgets/common/use-widget-drilldown.tsx deleted file mode 100644 index 79b4377d..00000000 --- a/packages/sdk-ui/src/widgets/common/use-widget-drilldown.tsx +++ /dev/null @@ -1,179 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { useCallback, useState, useMemo } from 'react'; - -import { DataPoint } from '../../types'; -import { Attribute, Filter } from '@sisense/sdk-data'; - -import { - HighchartsOptionsInternal, - HighchartsOptions, -} from '../../chart-options-processor/chart-options-service'; -import { ChartWidgetProps, DataPointEventHandler } from '../../props'; -import { useDrilldown } from './drilldown'; -import { DrilldownBreadcrumbs } from './drilldown-breadcrumbs'; -import { MenuItemSection } from '../../types'; - -const defaultDataOptions = { category: [], value: [], breakBy: [] }; -const defaultFilters: Filter[] = []; - -export const useWidgetDrilldown = (props: ChartWidgetProps): ChartWidgetProps => { - const { - dataOptions = defaultDataOptions, - filters = defaultFilters, - drilldownOptions, - onDataPointContextMenu: _onDataPointContextMenu, - onDataPointsSelected: _onDataPointsSelected, - onBeforeRender: _onBeforeRender, - ...restProps - } = props; - - if (['bubble', 'scatter'].includes(restProps.chartType)) { - throw new Error(`Drilldown is not supported for chart type ${restProps.chartType}`); - } - - const [selectedDataPoints, setSelectedDataPoints] = useState([]); - - const { - selectDrilldown, - clearDrilldownSelections, - sliceDrilldownSelections, - availableDrilldowns, - drilldownFilters, - drilldownFiltersDisplayValues, - drilldownDimension, - dataOptionsWithDrilldown, - } = useDrilldown(dataOptions, drilldownOptions); - - const onMenuDrilldownClick = useCallback( - (selectedPoints: DataPoint[], nextDimension: Attribute) => { - selectDrilldown(selectedPoints, nextDimension); - }, - [selectDrilldown], - ); - - const onDataPointContextMenu = useMemo( - () => - drilldownOptions - ? (point: DataPoint, nativeEvent: PointerEvent) => { - if ( - (_onDataPointContextMenu as DataPointEventHandler | undefined)?.(point, nativeEvent) - ) { - return; - } - setSelectedDataPoints([point]); - } - : _onDataPointContextMenu, - [drilldownOptions, _onDataPointContextMenu, setSelectedDataPoints], - ); - - const onDataPointsSelected = useMemo( - () => - drilldownOptions - ? (points: DataPoint[], nativeEvent: MouseEvent) => { - if (_onDataPointsSelected?.(points, nativeEvent)) { - return; - } - setSelectedDataPoints(points); - } - : _onDataPointsSelected, - [drilldownOptions, _onDataPointsSelected, setSelectedDataPoints], - ); - - const chartFilters = useMemo( - () => (filters as Filter[]).concat(drilldownFilters), - [filters, drilldownFilters], - ); - - const applyPointSelections = useMemo(() => { - if (!selectedDataPoints.length) { - return undefined; - } - - const categoryValueMap = selectedDataPoints.reduce((accu, { categoryValue }) => { - if (categoryValue) { - accu[`${categoryValue}`] = true; - } - return accu; - }, {}); - - return (options: HighchartsOptionsInternal) => ({ - ...options, - series: options.series.map((s) => ({ - ...s, - data: s.data.map((d) => - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - categoryValueMap[d.custom?.xValue?.[0]] ? d : { ...d, selected: true }, - ), - })), - }); - }, [selectedDataPoints]); - - const onBeforeRender = useCallback( - (options: HighchartsOptions) => { - options = - (applyPointSelections?.(options as HighchartsOptionsInternal) as HighchartsOptions) ?? - options; - options = _onBeforeRender?.(options) ?? options; - return options; - }, - [_onBeforeRender, applyPointSelections], - ); - - const contextMenuItems = useMemo(() => { - if (drilldownOptions) { - const drillDownMenuItems: MenuItemSection[] = [ - ...(drilldownDimension ? [{ sectionTitle: drilldownDimension?.name }] : []), - ...(selectedDataPoints.length - ? [ - { - sectionTitle: 'Drill', - items: availableDrilldowns.map((dd) => ({ - caption: dd.name, - onClick: () => onMenuDrilldownClick(selectedDataPoints, dd), - })), - }, - ] - : []), - ]; - return drillDownMenuItems.concat(restProps.contextMenuItems ?? []); - } - - return restProps.contextMenuItems; - }, [ - restProps.contextMenuItems, - drilldownOptions, - drilldownDimension, - selectedDataPoints, - availableDrilldowns, - onMenuDrilldownClick, - ]); - - const onContextMenuClose = () => { - restProps.onContextMenuClose?.(); - setSelectedDataPoints([]); - }; - - return { - ...restProps, - dataOptions: dataOptionsWithDrilldown, - onDataPointContextMenu, - onDataPointsSelected, - filters: chartFilters, - onBeforeRender, - topSlot: ( - <> - {restProps.topSlot} - {drilldownDimension && ( - - )} - - ), - contextMenuItems, - onContextMenuClose, - }; -}; diff --git a/packages/sdk-ui/src/widgets/common/widget-header-info-button.tsx b/packages/sdk-ui/src/widgets/common/widget-header-info-button.tsx index f7a40c15..32172d99 100644 --- a/packages/sdk-ui/src/widgets/common/widget-header-info-button.tsx +++ b/packages/sdk-ui/src/widgets/common/widget-header-info-button.tsx @@ -8,6 +8,7 @@ import Typography from '@mui/material/Typography'; import { useState } from 'react'; import { useThemeContext } from '../../theme-provider'; import { WidgetContainerStyleOptions } from '../../types'; +import { getSlightlyDifferentColor } from '@/utils/color'; export default function WidgetHeaderInfoButton({ title, @@ -62,6 +63,16 @@ export default function WidgetHeaderInfoButton({ vertical: 'top', horizontal: 'center', }} + slotProps={{ + root: { + sx: { + '.MuiPaper-root': { + boxShadow: '0 0 8px 0 rgba(0, 0, 0, 0.25)', + borderRadius: 0, + }, + }, + }, + }} >
Widget Details @@ -91,10 +102,12 @@ export default function WidgetHeaderInfoButton({
- + @@ -102,8 +115,8 @@ export default function WidgetHeaderInfoButton({ @@ -114,13 +127,17 @@ export default function WidgetHeaderInfoButton({ {!!description && ( <> diff --git a/packages/sdk-ui/src/widgets/drilldown-widget.tsx b/packages/sdk-ui/src/widgets/drilldown-widget.tsx index 03b86b63..0f678238 100644 --- a/packages/sdk-ui/src/widgets/drilldown-widget.tsx +++ b/packages/sdk-ui/src/widgets/drilldown-widget.tsx @@ -3,7 +3,7 @@ import { Attribute } from '@sisense/sdk-data'; import { DataPoint, MenuPosition, MenuItemSection } from '../types'; import { ContextMenu } from './common/context-menu'; import { DrilldownBreadcrumbs } from './common/drilldown-breadcrumbs'; -import { useCustomDrilldown } from './common/custom-drilldown'; +import { useDrilldown } from './common/use-drilldown'; import { DrilldownWidgetProps } from '../props'; import { asSisenseComponent } from '@/decorators/component-decorators/as-sisense-component'; @@ -45,7 +45,8 @@ import { asSisenseComponent } from '@/decorators/component-decorators/as-sisense export const DrilldownWidget = asSisenseComponent({ componentName: 'DrilldownWidget', trackingConfig: { transparent: true }, -})(({ drilldownDimensions, initialDimension, config, children }: DrilldownWidgetProps) => { +})((props: DrilldownWidgetProps) => { + const { drilldownDimensions, initialDimension, drilldownSelections, config, children } = props; const [selectedDataPoints, setSelectedDataPoints] = useState([]); const [contextMenuPos, setContextMenuPos] = useState(null); @@ -60,9 +61,10 @@ export const DrilldownWidget = asSisenseComponent({ drilldownFilters, drilldownFiltersDisplayValues, drilldownDimension, - } = useCustomDrilldown({ + } = useDrilldown({ drilldownDimensions, initialDimension, + drilldownSelections, }); const breadcrumbs = useMemo(() => { diff --git a/packages/sdk-ui/src/widgets/pivot-table-widget.test.tsx b/packages/sdk-ui/src/widgets/pivot-table-widget.test.tsx index cbdc0c57..57b05ade 100644 --- a/packages/sdk-ui/src/widgets/pivot-table-widget.test.tsx +++ b/packages/sdk-ui/src/widgets/pivot-table-widget.test.tsx @@ -18,9 +18,13 @@ describe('PivotTableWidget', () => { useSisenseContextMock.mockReturnValue({ app: { pivotClient: new PivotClient(new HttpClient(url, new SsoAuthenticator(url), 'test'), true), + settings: { + trackingConfig: { + enabled: false, + }, + }, } as ClientApplication, isInitialized: true, - enableTracking: false, }); }); it('should render empty pivot table widget', async () => { diff --git a/packages/sdk-ui/src/widgets/use-highlight-selection.ts b/packages/sdk-ui/src/widgets/use-highlight-selection.ts new file mode 100644 index 00000000..7dc4568b --- /dev/null +++ b/packages/sdk-ui/src/widgets/use-highlight-selection.ts @@ -0,0 +1,141 @@ +import { useCallback, useMemo, useState } from 'react'; +import { + CartesianChartDataOptions, + ChartDataOptions, + ChartDataPoint, + ChartDataPoints, + ChartType, + DataPoint, + HighchartsOptions, + ScatterDataPoint, +} from '..'; +import { isCartesian, isScatter } from '@/chart-options-processor/translations/types'; +import { HighchartsOptionsInternal } from '@/chart-options-processor/chart-options-service'; + +export function useHighlightSelection({ + chartType, + dataOptions, + enabled, +}: { + chartType: ChartType; + dataOptions: ChartDataOptions; + enabled: boolean; +}) { + const [selectedDataPoints, setSelectedDataPoints] = useState([]); + + const isSelectionAllowed = useMemo(() => { + const isSupportedChart = + (isCartesian(chartType) && + (dataOptions as CartesianChartDataOptions).category?.length === 1) || + isScatter(chartType); + return enabled && isSupportedChart; + }, [enabled, chartType, dataOptions]); + + const applyPointSelections = useMemo(() => { + if (selectedDataPoints.length === 0) { + return (options: HighchartsOptionsInternal) => + ({ + ...options, + series: options.series.map((s) => ({ + ...s, + data: s.data.map((d) => ({ ...d, selected: false })), + })), + } as HighchartsOptions); + } + if (isScatter(chartType)) { + return (options: HighchartsOptionsInternal) => + ({ + ...options, + series: options.series.map((s) => ({ + ...s, + data: s.data.map((d) => { + return { + ...d, + selected: !(selectedDataPoints as ScatterDataPoint[]).some( + (point) => + point.x === d.x && + point.y === d.y && + point.size === d.z && + point.breakByPoint === d.custom?.maskedBreakByPoint && + point.breakByColor === d.custom?.maskedBreakByColor, + ), + }; + }), + })), + } as HighchartsOptions); + } else { + const categoryValueMap = (selectedDataPoints as DataPoint[]).reduce( + (accu, { categoryValue }) => { + if (categoryValue) { + accu[`${categoryValue}`] = true; + } + return accu; + }, + {}, + ); + + return (options: HighchartsOptionsInternal) => ({ + ...options, + series: options.series.map((s) => ({ + ...s, + data: s.data.map((d) => + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + categoryValueMap[d.custom?.xValue?.[0]] ? d : { ...d, selected: true }, + ), + })), + }); + } + }, [selectedDataPoints, chartType]); + + const setOnClickOutside = useMemo( + () => (options: HighchartsOptions) => + ({ + ...options, + chart: { + ...options.chart, + events: { + ...options.chart?.events, + click: () => { + setSelectedDataPoints([]); + }, + }, + }, + } as HighchartsOptions), + [], + ); + + const onBeforeRender = useCallback( + (options: HighchartsOptions) => { + if (isSelectionAllowed) { + options = applyPointSelections(options as HighchartsOptionsInternal) as HighchartsOptions; + options = setOnClickOutside(options); + } + return options; + }, + [applyPointSelections, setOnClickOutside, isSelectionAllowed], + ); + + const onDataPointsSelected = useCallback( + (dataPoints: ChartDataPoints): void => { + if (isSelectionAllowed) { + setSelectedDataPoints(dataPoints); + } + }, + [isSelectionAllowed], + ); + + const onDataPointClick = useCallback( + (dataPoint: ChartDataPoint) => { + if (isSelectionAllowed) { + setSelectedDataPoints([dataPoint] as ChartDataPoints); + } + }, + [isSelectionAllowed], + ); + + return { + onBeforeRender, + onDataPointsSelected, + onDataPointClick, + }; +} diff --git a/yarn.lock b/yarn.lock index 17884856..5b3f2b4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2483,7 +2483,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.24.5 resolution: "@babel/runtime@npm:7.24.5" dependencies: @@ -4710,7 +4710,7 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.13.7, @mui/utils@npm:^5.14.16, @mui/utils@npm:^5.15.14": +"@mui/utils@npm:^5.14.16, @mui/utils@npm:^5.15.14": version: 5.15.14 resolution: "@mui/utils@npm:5.15.14" dependencies: @@ -4728,28 +4728,7 @@ __metadata: languageName: node linkType: hard -"@mui/x-data-grid-pro@npm:^6.16.0": - version: 6.19.11 - resolution: "@mui/x-data-grid-pro@npm:6.19.11" - dependencies: - "@babel/runtime": ^7.23.2 - "@mui/utils": ^5.14.16 - "@mui/x-data-grid": 6.19.11 - "@mui/x-license-pro": 6.10.2 - "@types/format-util": ^1.0.3 - clsx: ^2.0.0 - prop-types: ^15.8.1 - reselect: ^4.1.8 - peerDependencies: - "@mui/material": ^5.4.1 - "@mui/system": ^5.4.1 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - checksum: 0319c7d2a0161e98e017c5adfd6e57412462c63c27d7263f0e8cf09760481a86be384afbba978d636f5ba9f25bf0cbc387677651300fab574a280596da378f3d - languageName: node - linkType: hard - -"@mui/x-data-grid@npm:6.19.11, @mui/x-data-grid@npm:^6.16.0": +"@mui/x-data-grid@npm:^6.16.0": version: 6.19.11 resolution: "@mui/x-data-grid@npm:6.19.11" dependencies: @@ -4767,18 +4746,6 @@ __metadata: languageName: node linkType: hard -"@mui/x-license-pro@npm:6.10.2": - version: 6.10.2 - resolution: "@mui/x-license-pro@npm:6.10.2" - dependencies: - "@babel/runtime": ^7.22.6 - "@mui/utils": ^5.13.7 - peerDependencies: - react: ^17.0.0 || ^18.0.0 - checksum: facacd6aa216fbb7b25eedbd815140fbc620250156670d9424c221fac47402a745f10e6d59bb02685eadff6f41af76c308ab3762cd267482bcd2dc5d79bbdc4f - languageName: node - linkType: hard - "@ndelangen/get-tarball@npm:^3.0.7": version: 3.0.9 resolution: "@ndelangen/get-tarball@npm:3.0.9" @@ -5546,12 +5513,12 @@ __metadata: resolution: "@sisense/sdk-cli@workspace:packages/sdk-cli" dependencies: "@babel/preset-env": ^7.20.2 - "@sisense/sdk-common": ^1.16.0 - "@sisense/sdk-data": ^1.16.0 - "@sisense/sdk-modeling": ^1.16.0 - "@sisense/sdk-query-client": ^1.16.0 - "@sisense/sdk-rest-client": ^1.16.0 - "@sisense/sdk-tracking": ^1.16.0 + "@sisense/sdk-common": ^1.17.0 + "@sisense/sdk-data": ^1.17.0 + "@sisense/sdk-modeling": ^1.17.0 + "@sisense/sdk-query-client": ^1.17.0 + "@sisense/sdk-rest-client": ^1.17.0 + "@sisense/sdk-tracking": ^1.17.0 "@types/inquirer": 8.2.6 "@types/js-levenshtein": ^1.1.3 "@types/yargs": ^17.0.22 @@ -5569,7 +5536,7 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-common@^1.16.0, @sisense/sdk-common@workspace:packages/sdk-common": +"@sisense/sdk-common@^1.17.0, @sisense/sdk-common@workspace:packages/sdk-common": version: 0.0.0-use.local resolution: "@sisense/sdk-common@workspace:packages/sdk-common" dependencies: @@ -5579,13 +5546,13 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-data@^1.16.0, @sisense/sdk-data@workspace:^, @sisense/sdk-data@workspace:packages/sdk-data": +"@sisense/sdk-data@^1.17.0, @sisense/sdk-data@workspace:^, @sisense/sdk-data@workspace:packages/sdk-data": version: 0.0.0-use.local resolution: "@sisense/sdk-data@workspace:packages/sdk-data" dependencies: "@babel/preset-env": ^7.20.2 - "@sisense/sdk-common": ^1.16.0 - "@sisense/sdk-rest-client": ^1.16.0 + "@sisense/sdk-common": ^1.17.0 + "@sisense/sdk-rest-client": ^1.17.0 "@types/lodash": ^4.14.201 "@types/numeral": 2.0.2 "@types/object-hash": ^3.0.5 @@ -5599,19 +5566,19 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-modeling@^1.16.0, @sisense/sdk-modeling@workspace:packages/sdk-modeling": +"@sisense/sdk-modeling@^1.17.0, @sisense/sdk-modeling@workspace:packages/sdk-modeling": version: 0.0.0-use.local resolution: "@sisense/sdk-modeling@workspace:packages/sdk-modeling" dependencies: "@babel/preset-env": ^7.20.2 - "@sisense/sdk-data": ^1.16.0 + "@sisense/sdk-data": ^1.17.0 eslint: ^8.40.0 prettier: ^3.2.5 typescript: 4.8.4 languageName: unknown linkType: soft -"@sisense/sdk-pivot-client@^1.16.0, @sisense/sdk-pivot-client@workspace:packages/sdk-pivot-client": +"@sisense/sdk-pivot-client@^1.17.0, @sisense/sdk-pivot-client@workspace:packages/sdk-pivot-client": version: 0.0.0-use.local resolution: "@sisense/sdk-pivot-client@workspace:packages/sdk-pivot-client" dependencies: @@ -5619,8 +5586,8 @@ __metadata: "@emotion/react": ^11.11.4 "@emotion/styled": ^11.11.5 "@mui/material": ^5.11.6 - "@sisense/sdk-data": ^1.16.0 - "@sisense/sdk-rest-client": ^1.16.0 + "@sisense/sdk-data": ^1.17.0 + "@sisense/sdk-rest-client": ^1.17.0 "@types/lodash": ^4.14.200 "@types/react": ^18.3.1 "@types/react-custom-scrollbars": ^4.0.13 @@ -5655,14 +5622,14 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-query-client@^1.16.0, @sisense/sdk-query-client@workspace:packages/sdk-query-client": +"@sisense/sdk-query-client@^1.17.0, @sisense/sdk-query-client@workspace:packages/sdk-query-client": version: 0.0.0-use.local resolution: "@sisense/sdk-query-client@workspace:packages/sdk-query-client" dependencies: - "@sisense/sdk-common": ^1.16.0 - "@sisense/sdk-data": ^1.16.0 - "@sisense/sdk-pivot-client": ^1.16.0 - "@sisense/sdk-rest-client": ^1.16.0 + "@sisense/sdk-common": ^1.17.0 + "@sisense/sdk-data": ^1.17.0 + "@sisense/sdk-pivot-client": ^1.17.0 + "@sisense/sdk-rest-client": ^1.17.0 "@sisense/task-manager": ^0.1.0 "@types/tar": ^6.1.4 "@types/uuid": ^9.0.0 @@ -5679,12 +5646,12 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-rest-client@^1.16.0, @sisense/sdk-rest-client@workspace:^, @sisense/sdk-rest-client@workspace:packages/sdk-rest-client": +"@sisense/sdk-rest-client@^1.17.0, @sisense/sdk-rest-client@workspace:^, @sisense/sdk-rest-client@workspace:packages/sdk-rest-client": version: 0.0.0-use.local resolution: "@sisense/sdk-rest-client@workspace:packages/sdk-rest-client" dependencies: "@babel/preset-env": ^7.20.2 - "@sisense/sdk-common": ^1.16.0 + "@sisense/sdk-common": ^1.17.0 eslint: ^8.40.0 fetch-intercept: ^2.4.0 prettier: 2.8.4 @@ -5692,7 +5659,7 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-tracking@^1.16.0, @sisense/sdk-tracking@workspace:^, @sisense/sdk-tracking@workspace:packages/sdk-tracking": +"@sisense/sdk-tracking@^1.17.0, @sisense/sdk-tracking@workspace:^, @sisense/sdk-tracking@workspace:packages/sdk-tracking": version: 0.0.0-use.local resolution: "@sisense/sdk-tracking@workspace:packages/sdk-tracking" dependencies: @@ -5737,7 +5704,7 @@ __metadata: dependencies: "@preact/preset-vite": 2.5.0 "@sisense/sdk-data": "workspace:^" - "@sisense/sdk-ui": ^1.16.0 + "@sisense/sdk-ui": ^1.17.0 "@types/node": ^18.16.0 eslint: ^8.40.0 preact: ^10.13.2 @@ -5775,7 +5742,7 @@ __metadata: languageName: unknown linkType: soft -"@sisense/sdk-ui@^1.16.0, @sisense/sdk-ui@workspace:^, @sisense/sdk-ui@workspace:packages/sdk-ui": +"@sisense/sdk-ui@^1.17.0, @sisense/sdk-ui@workspace:^, @sisense/sdk-ui@workspace:packages/sdk-ui": version: 0.0.0-use.local resolution: "@sisense/sdk-ui@workspace:packages/sdk-ui" dependencies: @@ -5786,13 +5753,12 @@ __metadata: "@mui/material": ^5.15.16 "@mui/system": ^5.15.15 "@mui/x-data-grid": ^6.16.0 - "@mui/x-data-grid-pro": ^6.16.0 - "@sisense/sdk-common": ^1.16.0 - "@sisense/sdk-data": ^1.16.0 - "@sisense/sdk-pivot-client": ^1.16.0 - "@sisense/sdk-query-client": ^1.16.0 - "@sisense/sdk-rest-client": ^1.16.0 - "@sisense/sdk-tracking": ^1.16.0 + "@sisense/sdk-common": ^1.17.0 + "@sisense/sdk-data": ^1.17.0 + "@sisense/sdk-pivot-client": ^1.17.0 + "@sisense/sdk-query-client": ^1.17.0 + "@sisense/sdk-rest-client": ^1.17.0 + "@sisense/sdk-tracking": ^1.17.0 "@sisense/sisense-charts": 5.1.1 "@storybook/addon-actions": 7.0.24 "@storybook/addon-docs": 7.0.24 @@ -7460,13 +7426,6 @@ __metadata: languageName: node linkType: hard -"@types/format-util@npm:^1.0.3": - version: 1.0.4 - resolution: "@types/format-util@npm:1.0.4" - checksum: 0be61378a1fbe120573e23a35e04f3c2e4b7a6313971f16b325e2d3b1f775136aa55dafa68af4e964f452653aed2958f390ff7d62fec40e2e87639c83bda3f96 - languageName: node - linkType: hard - "@types/geojson@npm:*": version: 7946.0.14 resolution: "@types/geojson@npm:7946.0.14"