@astrato-io/visualizations 0.0.0-stage → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/LICENSE +93 -0
- package/README.md +843 -2
- package/THIRD_PARTY_NOTICES.md +8387 -0
- package/VISUALIZATION_DEFINITIONS.md +2378 -0
- package/chunks/LinearProgress-CUZ0D8_t.js +253 -0
- package/chunks/Radio-Ciu-F4CU.js +957 -0
- package/chunks/ToggleButton-BCJc3Jlc.js +153 -0
- package/chunks/_baseFlatten-DPXPOrea.js +7076 -0
- package/chunks/accessors-DemrDevR.js +128 -0
- package/chunks/app-filter-bar.compiler-j_CVoWTa.js +55 -0
- package/chunks/bar.compiler-oqaPzIut.js +370 -0
- package/chunks/color-settings-ZIvgNTq1.js +10 -0
- package/chunks/coloring-C16AUZEi.js +663 -0
- package/chunks/data-item-resolution-1lvYB5ln.js +53 -0
- package/chunks/debounce-fn-CUixuz45.js +7 -0
- package/chunks/escobar-BGqT1EsE.js +34580 -0
- package/chunks/event-bus-KiSiCJrC.js +2683 -0
- package/chunks/events-WZut5Ow6.js +4 -0
- package/chunks/extend-BKUkc4_i.js +37 -0
- package/chunks/filter.compiler-CuLtc_02.js +60 -0
- package/chunks/filtering-Yq4DEa0t.js +953 -0
- package/chunks/gauge-target-type-BkKXAqkX.js +4 -0
- package/chunks/grouping-type-BX_9Ix5q.js +3 -0
- package/chunks/interfaces-VUY4_yVO.js +8742 -0
- package/chunks/line-settings-DfYTUyPz.js +4 -0
- package/chunks/line.compiler-BpA_6Tc7.js +188 -0
- package/chunks/metadata-CPXdYoln.js +28 -0
- package/chunks/number.compiler-DbkWcG4S.js +44 -0
- package/chunks/pie-uv42Eqal.js +10 -0
- package/chunks/range-DrzdfBX4.js +22 -0
- package/chunks/registry-CExpGJ1N.js +920 -0
- package/chunks/requirements-DNhuShLS.js +6 -0
- package/chunks/rolldown-runtime-DleVn1XH.js +28 -0
- package/chunks/set-coloring-datafield-B3uIS1Pe.js +8 -0
- package/chunks/shared-CKDL4hx9.js +1171 -0
- package/chunks/src-BC7cGcJ-.js +2024 -0
- package/chunks/src-BOS6SqkZ.js +67 -0
- package/chunks/src-C0LgoUWY.js +26105 -0
- package/chunks/src-Cum_2NLV.js +12145 -0
- package/chunks/src-D9XogOrc.js +422 -0
- package/chunks/src-Dun_jXtz.js +10295 -0
- package/chunks/src-DvX5LU9T.js +14742 -0
- package/chunks/standalone-87YV_m9n.js +687 -0
- package/chunks/standalone-BDCwI6Hn.js +4619 -0
- package/chunks/standalone-BH5NqDwp.js +1763 -0
- package/chunks/standalone-BLVAWLNJ.js +385 -0
- package/chunks/standalone-BPomtAVs.js +2 -0
- package/chunks/standalone-BXyBcUOQ.js +2 -0
- package/chunks/standalone-BYm1UjLr.js +140 -0
- package/chunks/standalone-BllF4rDp.js +383 -0
- package/chunks/standalone-BmfMt74U.js +726 -0
- package/chunks/standalone-BqWyrnZI.js +281 -0
- package/chunks/standalone-C85u7U6I.js +340 -0
- package/chunks/standalone-CCNtaJ7s.js +741 -0
- package/chunks/standalone-CDQnr6qT.js +345 -0
- package/chunks/standalone-CNyNHKVx.js +674 -0
- package/chunks/standalone-CY57qwZ-.js +1129 -0
- package/chunks/standalone-CZynjFG7.js +12979 -0
- package/chunks/standalone-D5vnf-9y.js +3943 -0
- package/chunks/standalone-DFPva_ku.js +299 -0
- package/chunks/standalone-DQxxNwF8.js +675 -0
- package/chunks/standalone-DS9T0FZ-.js +830 -0
- package/chunks/standalone-Dx3MLlrO.js +512 -0
- package/chunks/standalone-DzixzZAL.js +411 -0
- package/chunks/standalone-QJ1kKMnO.js +6 -0
- package/chunks/standalone-jiz0L2Dg.js +3855 -0
- package/chunks/standalone-lBm9hQ-q.js +179 -0
- package/chunks/standalone-rJ45Zfl1.js +68 -0
- package/chunks/stroke-dash-UgMEcCS4.js +6 -0
- package/chunks/table.compiler-BrXkm4Fz.js +213 -0
- package/chunks/toInteger-DVZr-D1j.js +11 -0
- package/chunks/treemap-x_zmJoG7.js +23 -0
- package/chunks/typeof-CJDtcySz.js +13 -0
- package/chunks/types-dVVCsDWD.js +4 -0
- package/chunks/ui-D1HQNIBy.js +54039 -0
- package/chunks/url-utils-B17gj_mr.js +5501 -0
- package/chunks/useFieldName-oqQ3bvnO.js +7 -0
- package/chunks/utils-Ba9T0TqC.js +31097 -0
- package/chunks/view-CLqWMV7Z.js +156 -0
- package/definitions.js +3 -0
- package/docs/operations/astrato-app-filter-bar.md +161 -0
- package/docs/operations/bar.md +7050 -0
- package/docs/operations/combo.md +5825 -0
- package/docs/operations/date-picker.md +644 -0
- package/docs/operations/distribution-gauge.md +3218 -0
- package/docs/operations/dot.md +5662 -0
- package/docs/operations/filter.md +1507 -0
- package/docs/operations/gauge.md +3452 -0
- package/docs/operations/heatMap.md +6026 -0
- package/docs/operations/histogram.md +1870 -0
- package/docs/operations/iframe.md +56 -0
- package/docs/operations/image.md +177 -0
- package/docs/operations/index.md +46 -0
- package/docs/operations/line.md +6468 -0
- package/docs/operations/number.md +3969 -0
- package/docs/operations/pie.md +6089 -0
- package/docs/operations/radar.md +4646 -0
- package/docs/operations/sankey.md +3210 -0
- package/docs/operations/scatter.md +6075 -0
- package/docs/operations/shape.md +315 -0
- package/docs/operations/simpleTextObject.md +706 -0
- package/docs/operations/slider.md +230 -0
- package/docs/operations/table.md +8790 -0
- package/docs/operations/tree.md +2874 -0
- package/docs/operations/treemap.md +3619 -0
- package/docs/operations/waterfall.md +2938 -0
- package/docs/operations/word-cloud.md +3071 -0
- package/getters.js +18 -0
- package/index.js +1183 -0
- package/metadata.js +20 -0
- package/operations.js +64 -0
- package/package.json +191 -4
- package/src/definitions/index.d.ts +2 -0
- package/src/definitions/shared/index.d.ts +5 -0
- package/src/definitions/shared/lib/available-fields.d.ts +36 -0
- package/src/definitions/shared/lib/compilers/index.d.ts +7 -0
- package/src/definitions/shared/lib/registry/compile.d.ts +2 -0
- package/src/definitions/shared/lib/registry/descriptor-registry.d.ts +587 -0
- package/src/definitions/shared/lib/registry/index.d.ts +3 -0
- package/src/definitions/shared/lib/registry/validation.d.ts +3 -0
- package/src/definitions/shared/lib/schemas/app-filter-bar.schema.d.ts +22 -0
- package/src/definitions/shared/lib/schemas/bar.schema.d.ts +73 -0
- package/src/definitions/shared/lib/schemas/broad-chart.schema.d.ts +68 -0
- package/src/definitions/shared/lib/schemas/common.schema.d.ts +304 -0
- package/src/definitions/shared/lib/schemas/filter.schema.d.ts +22 -0
- package/src/definitions/shared/lib/schemas/index.d.ts +9 -0
- package/src/definitions/shared/lib/schemas/line.schema.d.ts +72 -0
- package/src/definitions/shared/lib/schemas/number.schema.d.ts +21 -0
- package/src/definitions/shared/lib/schemas/object.schema.d.ts +215 -0
- package/src/definitions/shared/lib/schemas/table.schema.d.ts +458 -0
- package/src/definitions/shared/lib/types/compilation.types.d.ts +36 -0
- package/src/definitions/shared/lib/types/definition.types.d.ts +2 -0
- package/src/definitions/shared/lib/types/descriptor.types.d.ts +39 -0
- package/src/definitions/shared/lib/types/index.d.ts +3 -0
- package/src/getters/index.d.ts +30 -0
- package/src/index.d.ts +4 -0
- package/src/metadata/index.d.ts +4 -0
- package/src/operations/index.d.ts +30 -0
- package/src/registry/index.d.ts +6 -0
- package/src/runtime/index.d.ts +2 -0
- package/src/types.d.ts +307 -0
- package/src/visualization-catalog.d.ts +82 -0
- package/src/web-components/index.d.ts +12 -0
- package/styles.css +2 -0
|
@@ -0,0 +1,2378 @@
|
|
|
1
|
+
# Visualization Definition Reference
|
|
2
|
+
|
|
3
|
+
This reference documents version 1 of the public `VisualizationDefinition` creation contract exposed from `@astrato-io/visualizations/definitions`.
|
|
4
|
+
|
|
5
|
+
The reference and the public per-type descriptors share the same metadata catalog.
|
|
6
|
+
|
|
7
|
+
## How To Use This Reference
|
|
8
|
+
|
|
9
|
+
- Use a definition only to create a visualization from a fresh default or preset vSpec.
|
|
10
|
+
- Use exact, opaque engine `fieldKey` values. Never parse, reconstruct, or replace them with view/name pairs.
|
|
11
|
+
- Definition-local `ref` values let sorting, Top N, and similar settings refer to data items before internal identities exist.
|
|
12
|
+
- Raw fields used as measures require `aggregation`. Semantic dimensions, predefined measures, and calculations retain their engine semantics.
|
|
13
|
+
- Unsupported sections and properties are rejected instead of ignored.
|
|
14
|
+
- The compiler returns one complete vSpec or structured issues; it never returns partial state.
|
|
15
|
+
- Settings a definition cannot express are applied with `applyOperations` on the compiled vSpec before mounting. See "Finishing A Chart Before Mounting".
|
|
16
|
+
|
|
17
|
+
## Integrating With AI
|
|
18
|
+
|
|
19
|
+
When building an AI integration, first choose the visualization type, such as `bar` or `table`. The compact `supportedFeatures` list can help with this discovery step without loading every full schema.
|
|
20
|
+
|
|
21
|
+
After selecting the type, give the model only:
|
|
22
|
+
|
|
23
|
+
1. `descriptor.jsonSchema`, which defines the allowed JSON structure.
|
|
24
|
+
2. `descriptor.documentation`, which explains what the properties mean and lists chart-specific rules.
|
|
25
|
+
3. `descriptor.examples`, which shows valid definitions.
|
|
26
|
+
4. The compatible available fields, including their exact engine keys.
|
|
27
|
+
|
|
28
|
+
Do not send schemas for every visualization or ask the model to generate a raw vSpec. That would give the model unrelated information and require it to understand internal vSpec properties and generated data-item IDs.
|
|
29
|
+
|
|
30
|
+
After the model returns a definition, pass it to `compileVisualizationDefinition()`. On success, use the returned vSpec. On failure, give the structured issues back to the model so it can correct the definition and try again.
|
|
31
|
+
|
|
32
|
+
Use `getVisualizationDefinitionDescriptor(type, 1)` to get the descriptor for one selected type. Use `listVisualizationDefinitionDescriptors()` to discover the available visualization types and compare their `supportedFeatures`.
|
|
33
|
+
|
|
34
|
+
A definition does not cover every setting yet. If the chart needs a setting the definition cannot express, finish it with operations before mounting, as described in the next section.
|
|
35
|
+
|
|
36
|
+
## Finishing A Chart Before Mounting
|
|
37
|
+
|
|
38
|
+
A definition covers a subset of the operation catalogue. For settings outside it, apply operations to the compiled vSpec with `applyOperations` from `@astrato-io/visualizations/operations`, in one batch and before creating the instance. This runs in memory: it needs no runtime and makes no engine requests.
|
|
39
|
+
|
|
40
|
+
Use `compilation.resolvedRefs` to get the data-item identity that operation payloads expect for a definition `ref`:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { applyOperations } from '@astrato-io/visualizations/operations';
|
|
44
|
+
|
|
45
|
+
const compilation = await compileVisualizationDefinition({ definition, availableFields, baseVSpec });
|
|
46
|
+
if (!compilation.success) throw new Error(JSON.stringify(compilation.issues));
|
|
47
|
+
|
|
48
|
+
const { dataItemInternalKey, dataItemUniqueSignature } = compilation.resolvedRefs.sales;
|
|
49
|
+
const finished = await applyOperations({
|
|
50
|
+
instance: { id: 'sales-by-manufacturer', type: 'bar', vSpec: compilation.vSpec },
|
|
51
|
+
operationRequests: [
|
|
52
|
+
{ id: 'radius', name: 'setBarChartBarRadius', payload: 4 },
|
|
53
|
+
{
|
|
54
|
+
id: 'color',
|
|
55
|
+
name: 'setMeasureGraphColor',
|
|
56
|
+
payload: { dataItemInternalKey, dataItemUniqueSignature, graphColor: '#0f766e' },
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// a batch is not transactional: a request that fails while running is reported here;
|
|
62
|
+
// an unsupported operation name or a missing vSpec throws before any result is returned
|
|
63
|
+
const failures = Object.values(finished.results as Record<string, { success: boolean }>).filter(
|
|
64
|
+
(result) => !result.success,
|
|
65
|
+
);
|
|
66
|
+
if (failures.length) throw new Error(JSON.stringify(failures));
|
|
67
|
+
|
|
68
|
+
runtime.createInstance({ id: 'sales-by-manufacturer', type: 'bar', vSpec: finished.vSpec, dataBinding });
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Get operation names and payload schemas from `getVisualizationMetadata(type).operations`.
|
|
72
|
+
|
|
73
|
+
Avoid finishing a chart by applying operations one at a time after it is mounted. Each change to a mounted instance's vSpec can trigger a new data request, so a dashboard built that way makes one engine request per operation per chart.
|
|
74
|
+
|
|
75
|
+
## Common Feature Names
|
|
76
|
+
|
|
77
|
+
| Feature | Meaning |
|
|
78
|
+
| -------------------- | ------------------------------------------------------------------------------ |
|
|
79
|
+
| `axes` | Semantic dimension/primary-measure/secondary-measure axis presentation. |
|
|
80
|
+
| `axis-bands` | Shaded ranges between two primary measure axis values. |
|
|
81
|
+
| `axis-range` | Measure-axis range (min, max, starts at zero) and inversion. |
|
|
82
|
+
| `axis-scale` | Linear or logarithmic measure axis. |
|
|
83
|
+
| `content` | User-visible content such as text, image, or URL. |
|
|
84
|
+
| `data-labels` | Chart or measure label visibility and supported label settings. |
|
|
85
|
+
| `dimensions` | Dimension or field-backed data items. |
|
|
86
|
+
| `filter-settings` | Settings of an interactive filter-like object. |
|
|
87
|
+
| `filters` | Static visualization filters applied at creation. |
|
|
88
|
+
| `input-settings` | Variable-backed input behavior and presentation. |
|
|
89
|
+
| `legend` | Legend visibility, position, and title. |
|
|
90
|
+
| `measures` | Aggregated raw fields, predefined measures, or calculations. |
|
|
91
|
+
| `object-settings` | Object-specific non-data presentation settings. |
|
|
92
|
+
| `orientation` | Horizontal or vertical chart orientation. |
|
|
93
|
+
| `query-limit` | Maximum number of rows requested by the visualization. |
|
|
94
|
+
| `selection-settings` | Selection behavior and available filter controls for a shared selection group. |
|
|
95
|
+
| `sorting` | Ordered sorting rules referencing definition-local refs. |
|
|
96
|
+
| `table-structure` | Normal, expandable, or pivot table data arrangement. |
|
|
97
|
+
| `top-n` | Top N limiting referencing a definition-local measure ref. |
|
|
98
|
+
| `totals` | Table totals behavior and presentation. |
|
|
99
|
+
| `value-formatting` | Dimension, measure, or table-column value formatting. |
|
|
100
|
+
|
|
101
|
+
## Capability Index
|
|
102
|
+
|
|
103
|
+
| Type | Name | Data requirements | Supported features |
|
|
104
|
+
| ------------------------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
105
|
+
| `bar` | Bar chart | At least one dimension. At least one measure. | `axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `top-n`, `value-formatting` |
|
|
106
|
+
| `combo` | Combo chart | Exactly one dimension. Between one and ten measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `axes`, `axis-bands`, `axis-range`, `axis-scale`, `data-labels`, `legend`, `measure-axis`, `orientation`, `query-limit`, `series-type`, `sorting` |
|
|
107
|
+
| `distribution-gauge` | Distribution gauge | Zero or one dimension. Between one and twenty measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend` |
|
|
108
|
+
| `dot` | Dot chart | Exactly two dimensions. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `orientation` |
|
|
109
|
+
| `gauge` | Gauge chart | Zero or one dimension. Between one and twenty measures; with one dimension, at most two measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend` |
|
|
110
|
+
| `heatMap` | Heat map | Exactly two dimensions. One or two measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `legend`, `query-limit`, `sorting` |
|
|
111
|
+
| `histogram` | Histogram | Exactly one numeric dimension. No caller-supplied measures. | `axes`, `axis-bands`, `axis-range`, `dimensions`, `filters`, `legend`, `orientation`, `value-formatting` |
|
|
112
|
+
| `line` | Line chart | At least one dimension. At least one measure. | `axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `data-points`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `value-formatting` |
|
|
113
|
+
| `radar` | Radar chart | Zero to two dimensions. Two to five measures without dimensions, or one with dimensions. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend` |
|
|
114
|
+
| `pie` | Pie chart | Exactly one dimension. One or two measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`, `query-limit`, `sorting` |
|
|
115
|
+
| `tree` | Tree chart | Zero to ten dimensions. Zero to one hundred measures, or at most one with dimensions. | `dimensions`, `filters`, `measures`, `value-formatting`, `layout`, `query-limit`, `sorting` |
|
|
116
|
+
| `treemap` | Treemap | Between one and ten dimensions. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend` |
|
|
117
|
+
| `sankey` | Sankey chart | Between two and fifteen dimensions. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring` |
|
|
118
|
+
| `scatter` | Scatter chart | One or two dimensions. Two or three measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `query-limit`, `sorting` |
|
|
119
|
+
| `table` | Table | Normal tables require at least one ordered dimension or measure column. Expandable tables require at least one dimension and one measure. Pivot tables require at least one row dimension, one column dimension, and one measure. | `dimensions`, `filters`, `layout`, `measures`, `query-limit`, `sorting`, `table-structure`, `totals`, `value-formatting` |
|
|
120
|
+
| `waterfall` | Waterfall chart | Between one and one hundred measures. | `axes`, `axis-bands`, `axis-range`, `data-labels`, `filters`, `measures`, `orientation`, `value-formatting` |
|
|
121
|
+
| `word-cloud` | Word cloud | Exactly one dimension. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring` |
|
|
122
|
+
| `date-picker` | Date picker | Exactly one field. | `dimensions`, `filter-settings` |
|
|
123
|
+
| `filter` | Filter | Exactly one field. | `dimensions`, `filter-settings` |
|
|
124
|
+
| `iframe` | Iframe | No query data. | `content` |
|
|
125
|
+
| `image` | Image | No query data. | `content`, `object-settings` |
|
|
126
|
+
| `number` | Number | Exactly one measure. | `filters`, `measures`, `value-formatting` |
|
|
127
|
+
| `shape` | Shape | No query data. | `object-settings` |
|
|
128
|
+
| `simpleTextObject` | Text object | No query data. | `content`, `object-settings` |
|
|
129
|
+
| `atomic-input` | Atomic input | No query data; variable-backed input. | `input-settings` |
|
|
130
|
+
| `astrato-app-filter-bar` | Astrato App Filter Bar | No query data; uses field metadata and selections supplied by the host. | `selection-settings` |
|
|
131
|
+
| `slider` | Slider | Exactly one field. | `dimensions`, `filter-settings` |
|
|
132
|
+
|
|
133
|
+
## `bar`: Bar chart
|
|
134
|
+
|
|
135
|
+
Categorical comparison chart with sorting, limiting, per-measure axes, labels, and orientation controls.
|
|
136
|
+
|
|
137
|
+
**Data requirements**
|
|
138
|
+
|
|
139
|
+
- At least one dimension.
|
|
140
|
+
- At least one measure.
|
|
141
|
+
|
|
142
|
+
**Supported features**
|
|
143
|
+
|
|
144
|
+
`axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `top-n`, `value-formatting`
|
|
145
|
+
|
|
146
|
+
**Constraints and semantics**
|
|
147
|
+
|
|
148
|
+
- Sorting and Top N refer to definition-local refs, not generated data-item IDs.
|
|
149
|
+
- Every dimension and measure must resolve to an available field with a compatible role.
|
|
150
|
+
- Set axis per measure to plot it against the primary or the secondary measure axis.
|
|
151
|
+
- presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
|
|
152
|
+
- Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
|
|
153
|
+
- Set scale to log on a measure axis to draw it logarithmically, with gridlines at powers of ten. Zero and negative values are drawn at the floor of a log axis.
|
|
154
|
+
|
|
155
|
+
**Canonical example**
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"data": {
|
|
160
|
+
"dimensions": [
|
|
161
|
+
{
|
|
162
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
163
|
+
"format": {
|
|
164
|
+
"formatType": "none"
|
|
165
|
+
},
|
|
166
|
+
"ref": "manufacturer",
|
|
167
|
+
"showNullValues": false
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"measures": [
|
|
171
|
+
{
|
|
172
|
+
"aggregation": "SUM",
|
|
173
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
174
|
+
"format": {
|
|
175
|
+
"formatType": "number2Decimal",
|
|
176
|
+
"negativeType": "parenthesis"
|
|
177
|
+
},
|
|
178
|
+
"ref": "sales",
|
|
179
|
+
"dataLabels": {
|
|
180
|
+
"placements": ["outside", "inside"],
|
|
181
|
+
"visible": true
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
"filterGroup": {
|
|
187
|
+
"filters": [
|
|
188
|
+
{
|
|
189
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
190
|
+
"operator": "inList",
|
|
191
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
"operator": "and"
|
|
195
|
+
},
|
|
196
|
+
"limiting": {
|
|
197
|
+
"queryLimit": 100,
|
|
198
|
+
"topN": {
|
|
199
|
+
"by": "sales",
|
|
200
|
+
"count": 10,
|
|
201
|
+
"direction": "desc",
|
|
202
|
+
"showOthers": false
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"presentation": {
|
|
206
|
+
"axes": {
|
|
207
|
+
"dimension": {
|
|
208
|
+
"labelsVisible": true,
|
|
209
|
+
"title": "Manufacturer",
|
|
210
|
+
"titleVisible": true
|
|
211
|
+
},
|
|
212
|
+
"primaryMeasure": {
|
|
213
|
+
"labelsVisible": true,
|
|
214
|
+
"title": "Sales",
|
|
215
|
+
"titleVisible": true,
|
|
216
|
+
"bands": [
|
|
217
|
+
{
|
|
218
|
+
"color": "#E6E6E6",
|
|
219
|
+
"end": 150000,
|
|
220
|
+
"label": "Target range",
|
|
221
|
+
"start": 100000
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
"secondaryMeasure": {
|
|
226
|
+
"labelsVisible": true,
|
|
227
|
+
"title": "Horsepower",
|
|
228
|
+
"titleVisible": true
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"legend": {
|
|
232
|
+
"position": "right",
|
|
233
|
+
"title": "Cars comparison",
|
|
234
|
+
"visible": true
|
|
235
|
+
},
|
|
236
|
+
"orientation": "vertical"
|
|
237
|
+
},
|
|
238
|
+
"sorting": [
|
|
239
|
+
{
|
|
240
|
+
"by": "sales",
|
|
241
|
+
"direction": "desc"
|
|
242
|
+
}
|
|
243
|
+
],
|
|
244
|
+
"type": "bar",
|
|
245
|
+
"version": 1
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Additional scenarios**
|
|
250
|
+
|
|
251
|
+
### Colors bound to dimension values and a measure threshold
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"data": {
|
|
256
|
+
"dimensions": [
|
|
257
|
+
{
|
|
258
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
259
|
+
"format": {
|
|
260
|
+
"formatType": "none"
|
|
261
|
+
},
|
|
262
|
+
"ref": "manufacturer"
|
|
263
|
+
}
|
|
264
|
+
],
|
|
265
|
+
"measures": [
|
|
266
|
+
{
|
|
267
|
+
"aggregation": "SUM",
|
|
268
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
269
|
+
"format": {
|
|
270
|
+
"formatType": "number2Decimal",
|
|
271
|
+
"negativeType": "parenthesis"
|
|
272
|
+
},
|
|
273
|
+
"ref": "sales"
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
},
|
|
277
|
+
"presentation": {
|
|
278
|
+
"coloring": {
|
|
279
|
+
"overwrites": [
|
|
280
|
+
{
|
|
281
|
+
"color": "#0F766E",
|
|
282
|
+
"value": "Audi"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"color": "#D97706",
|
|
286
|
+
"operator": "inList",
|
|
287
|
+
"values": ["BMW", "Buick"]
|
|
288
|
+
}
|
|
289
|
+
],
|
|
290
|
+
"rules": [
|
|
291
|
+
{
|
|
292
|
+
"color": "#DC2626",
|
|
293
|
+
"measure": "sales",
|
|
294
|
+
"operator": "less",
|
|
295
|
+
"value": 20
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"type": "bar",
|
|
301
|
+
"version": 1
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## `combo`: Combo chart
|
|
306
|
+
|
|
307
|
+
Combined categorical chart supporting multiple measures, per-measure axes, sorting, limiting, labels, legend, and orientation.
|
|
308
|
+
|
|
309
|
+
**Data requirements**
|
|
310
|
+
|
|
311
|
+
- Exactly one dimension.
|
|
312
|
+
- Between one and ten measures.
|
|
313
|
+
|
|
314
|
+
**Supported features**
|
|
315
|
+
|
|
316
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `axes`, `axis-bands`, `axis-range`, `axis-scale`, `data-labels`, `legend`, `measure-axis`, `orientation`, `query-limit`, `series-type`, `sorting`
|
|
317
|
+
|
|
318
|
+
**Constraints and semantics**
|
|
319
|
+
|
|
320
|
+
- The single dimension is assigned the combo category role.
|
|
321
|
+
- Set seriesType per measure to create bar, line, or point series; omission keeps the existing line default.
|
|
322
|
+
- Data labels apply only to bar series.
|
|
323
|
+
- Sorting refers to definition-local refs, not generated data-item IDs.
|
|
324
|
+
- Set axis per measure to plot it against the primary or the secondary measure axis. Bar series share one axis: state it on any bar measure, and every bar measure that states one must state the same axis.
|
|
325
|
+
- presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
|
|
326
|
+
- Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
|
|
327
|
+
- Set scale to log on a measure axis to draw it logarithmically, with gridlines at powers of ten. Zero and negative values are drawn at the floor of a log axis.
|
|
328
|
+
|
|
329
|
+
**Canonical example**
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"data": {
|
|
334
|
+
"dimensions": [
|
|
335
|
+
{
|
|
336
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
337
|
+
"format": {
|
|
338
|
+
"formatType": "none"
|
|
339
|
+
},
|
|
340
|
+
"ref": "manufacturer"
|
|
341
|
+
}
|
|
342
|
+
],
|
|
343
|
+
"measures": [
|
|
344
|
+
{
|
|
345
|
+
"aggregation": "SUM",
|
|
346
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
347
|
+
"format": {
|
|
348
|
+
"formatType": "number2Decimal",
|
|
349
|
+
"negativeType": "parenthesis"
|
|
350
|
+
},
|
|
351
|
+
"ref": "sales",
|
|
352
|
+
"dataLabels": {
|
|
353
|
+
"visible": true
|
|
354
|
+
},
|
|
355
|
+
"seriesType": "bar"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"aggregation": "AVG",
|
|
359
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
360
|
+
"format": {
|
|
361
|
+
"formatType": "number2Decimal",
|
|
362
|
+
"negativeType": "parenthesis"
|
|
363
|
+
},
|
|
364
|
+
"ref": "horsepower",
|
|
365
|
+
"axis": "secondary",
|
|
366
|
+
"seriesType": "line"
|
|
367
|
+
}
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
"filterGroup": {
|
|
371
|
+
"filters": [
|
|
372
|
+
{
|
|
373
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
374
|
+
"operator": "inList",
|
|
375
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
376
|
+
}
|
|
377
|
+
],
|
|
378
|
+
"operator": "and"
|
|
379
|
+
},
|
|
380
|
+
"limiting": {
|
|
381
|
+
"queryLimit": 100
|
|
382
|
+
},
|
|
383
|
+
"presentation": {
|
|
384
|
+
"axes": {
|
|
385
|
+
"dimension": {
|
|
386
|
+
"labelsVisible": true,
|
|
387
|
+
"title": "Manufacturer",
|
|
388
|
+
"titleVisible": true
|
|
389
|
+
},
|
|
390
|
+
"primaryMeasure": {
|
|
391
|
+
"labelsVisible": true,
|
|
392
|
+
"title": "Sales",
|
|
393
|
+
"titleVisible": true
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
"dataLabels": {
|
|
397
|
+
"visible": true
|
|
398
|
+
},
|
|
399
|
+
"legend": {
|
|
400
|
+
"position": "right",
|
|
401
|
+
"title": "Cars comparison",
|
|
402
|
+
"visible": true
|
|
403
|
+
},
|
|
404
|
+
"orientation": "vertical"
|
|
405
|
+
},
|
|
406
|
+
"sorting": [
|
|
407
|
+
{
|
|
408
|
+
"by": "sales",
|
|
409
|
+
"direction": "desc"
|
|
410
|
+
}
|
|
411
|
+
],
|
|
412
|
+
"type": "combo",
|
|
413
|
+
"version": 1
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## `distribution-gauge`: Distribution gauge
|
|
418
|
+
|
|
419
|
+
Gauge distribution across one or more values, optionally grouped by a dimension.
|
|
420
|
+
|
|
421
|
+
**Data requirements**
|
|
422
|
+
|
|
423
|
+
- Zero or one dimension.
|
|
424
|
+
- Between one and twenty measures.
|
|
425
|
+
|
|
426
|
+
**Supported features**
|
|
427
|
+
|
|
428
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend`
|
|
429
|
+
|
|
430
|
+
**Constraints and semantics**
|
|
431
|
+
|
|
432
|
+
- All measures are assigned the gauge-value role.
|
|
433
|
+
- Distribution definitions enable the established gauge comparison mode.
|
|
434
|
+
|
|
435
|
+
**Canonical example**
|
|
436
|
+
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"data": {
|
|
440
|
+
"dimensions": [
|
|
441
|
+
{
|
|
442
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
443
|
+
"format": {
|
|
444
|
+
"formatType": "none"
|
|
445
|
+
},
|
|
446
|
+
"ref": "manufacturer"
|
|
447
|
+
}
|
|
448
|
+
],
|
|
449
|
+
"measures": [
|
|
450
|
+
{
|
|
451
|
+
"aggregation": "SUM",
|
|
452
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
453
|
+
"format": {
|
|
454
|
+
"formatType": "number2Decimal",
|
|
455
|
+
"negativeType": "parenthesis"
|
|
456
|
+
},
|
|
457
|
+
"ref": "sales"
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"aggregation": "AVG",
|
|
461
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
462
|
+
"format": {
|
|
463
|
+
"formatType": "number2Decimal",
|
|
464
|
+
"negativeType": "parenthesis"
|
|
465
|
+
},
|
|
466
|
+
"ref": "averageSales"
|
|
467
|
+
}
|
|
468
|
+
]
|
|
469
|
+
},
|
|
470
|
+
"filterGroup": {
|
|
471
|
+
"filters": [
|
|
472
|
+
{
|
|
473
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
474
|
+
"operator": "inList",
|
|
475
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
476
|
+
}
|
|
477
|
+
],
|
|
478
|
+
"operator": "and"
|
|
479
|
+
},
|
|
480
|
+
"presentation": {
|
|
481
|
+
"displayMode": "bar",
|
|
482
|
+
"legend": {
|
|
483
|
+
"position": "right",
|
|
484
|
+
"title": "Cars comparison",
|
|
485
|
+
"visible": true
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
"type": "distribution-gauge",
|
|
489
|
+
"version": 1
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
## `dot`: Dot chart
|
|
494
|
+
|
|
495
|
+
Dot comparison using two categorical dimensions and one measure.
|
|
496
|
+
|
|
497
|
+
**Data requirements**
|
|
498
|
+
|
|
499
|
+
- Exactly two dimensions.
|
|
500
|
+
- Exactly one measure.
|
|
501
|
+
|
|
502
|
+
**Supported features**
|
|
503
|
+
|
|
504
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `orientation`
|
|
505
|
+
|
|
506
|
+
**Constraints and semantics**
|
|
507
|
+
|
|
508
|
+
- Dimension order is significant and maps to the two dot-chart dimension roles.
|
|
509
|
+
- Set range on the primary measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on the primary measure axis to reverse its values.
|
|
510
|
+
|
|
511
|
+
**Canonical example**
|
|
512
|
+
|
|
513
|
+
```json
|
|
514
|
+
{
|
|
515
|
+
"data": {
|
|
516
|
+
"dimensions": [
|
|
517
|
+
{
|
|
518
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
519
|
+
"format": {
|
|
520
|
+
"formatType": "none"
|
|
521
|
+
},
|
|
522
|
+
"ref": "manufacturer"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
"fieldKey": "[Cars].[Model]",
|
|
526
|
+
"format": {
|
|
527
|
+
"formatType": "none"
|
|
528
|
+
},
|
|
529
|
+
"ref": "model"
|
|
530
|
+
}
|
|
531
|
+
],
|
|
532
|
+
"measures": [
|
|
533
|
+
{
|
|
534
|
+
"aggregation": "SUM",
|
|
535
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
536
|
+
"format": {
|
|
537
|
+
"formatType": "number2Decimal",
|
|
538
|
+
"negativeType": "parenthesis"
|
|
539
|
+
},
|
|
540
|
+
"ref": "sales"
|
|
541
|
+
}
|
|
542
|
+
]
|
|
543
|
+
},
|
|
544
|
+
"filterGroup": {
|
|
545
|
+
"filters": [
|
|
546
|
+
{
|
|
547
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
548
|
+
"operator": "inList",
|
|
549
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
550
|
+
}
|
|
551
|
+
],
|
|
552
|
+
"operator": "and"
|
|
553
|
+
},
|
|
554
|
+
"presentation": {
|
|
555
|
+
"axes": {
|
|
556
|
+
"dimension": {
|
|
557
|
+
"labelsVisible": true,
|
|
558
|
+
"title": "Manufacturer",
|
|
559
|
+
"titleVisible": true
|
|
560
|
+
},
|
|
561
|
+
"primaryMeasure": {
|
|
562
|
+
"labelsVisible": true,
|
|
563
|
+
"title": "Sales",
|
|
564
|
+
"titleVisible": true
|
|
565
|
+
}
|
|
566
|
+
},
|
|
567
|
+
"legend": {
|
|
568
|
+
"position": "right",
|
|
569
|
+
"title": "Cars comparison",
|
|
570
|
+
"visible": true
|
|
571
|
+
},
|
|
572
|
+
"orientation": "horizontal"
|
|
573
|
+
},
|
|
574
|
+
"type": "dot",
|
|
575
|
+
"version": 1
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## `gauge`: Gauge chart
|
|
580
|
+
|
|
581
|
+
Gauge values with an optional grouping dimension and optional data target.
|
|
582
|
+
|
|
583
|
+
**Data requirements**
|
|
584
|
+
|
|
585
|
+
- Zero or one dimension.
|
|
586
|
+
- Between one and twenty measures; with one dimension, at most two measures.
|
|
587
|
+
|
|
588
|
+
**Supported features**
|
|
589
|
+
|
|
590
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend`
|
|
591
|
+
|
|
592
|
+
**Constraints and semantics**
|
|
593
|
+
|
|
594
|
+
- With a dimension, the first measure is the gauge value and the optional second measure is the target.
|
|
595
|
+
- Without a dimension, supplied measures are gauge values.
|
|
596
|
+
- When a target measure is supplied, the compiler enables the established data-target mode.
|
|
597
|
+
|
|
598
|
+
**Canonical example**
|
|
599
|
+
|
|
600
|
+
```json
|
|
601
|
+
{
|
|
602
|
+
"data": {
|
|
603
|
+
"dimensions": [
|
|
604
|
+
{
|
|
605
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
606
|
+
"format": {
|
|
607
|
+
"formatType": "none"
|
|
608
|
+
},
|
|
609
|
+
"ref": "manufacturer"
|
|
610
|
+
}
|
|
611
|
+
],
|
|
612
|
+
"measures": [
|
|
613
|
+
{
|
|
614
|
+
"aggregation": "SUM",
|
|
615
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
616
|
+
"format": {
|
|
617
|
+
"formatType": "number2Decimal",
|
|
618
|
+
"negativeType": "parenthesis"
|
|
619
|
+
},
|
|
620
|
+
"ref": "sales"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"aggregation": "AVG",
|
|
624
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
625
|
+
"format": {
|
|
626
|
+
"formatType": "number2Decimal",
|
|
627
|
+
"negativeType": "parenthesis"
|
|
628
|
+
},
|
|
629
|
+
"ref": "targetSales"
|
|
630
|
+
}
|
|
631
|
+
]
|
|
632
|
+
},
|
|
633
|
+
"filterGroup": {
|
|
634
|
+
"filters": [
|
|
635
|
+
{
|
|
636
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
637
|
+
"operator": "inList",
|
|
638
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
639
|
+
}
|
|
640
|
+
],
|
|
641
|
+
"operator": "and"
|
|
642
|
+
},
|
|
643
|
+
"presentation": {
|
|
644
|
+
"displayMode": "radial",
|
|
645
|
+
"legend": {
|
|
646
|
+
"position": "right",
|
|
647
|
+
"title": "Cars comparison",
|
|
648
|
+
"visible": true
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
"type": "gauge",
|
|
652
|
+
"version": 1
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## `heatMap`: Heat map
|
|
657
|
+
|
|
658
|
+
Two-dimensional matrix colored and optionally sized by measures.
|
|
659
|
+
|
|
660
|
+
**Data requirements**
|
|
661
|
+
|
|
662
|
+
- Exactly two dimensions.
|
|
663
|
+
- One or two measures.
|
|
664
|
+
|
|
665
|
+
**Supported features**
|
|
666
|
+
|
|
667
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `legend`, `query-limit`, `sorting`
|
|
668
|
+
|
|
669
|
+
**Constraints and semantics**
|
|
670
|
+
|
|
671
|
+
- Dimension order maps to horizontal then vertical roles.
|
|
672
|
+
- Measure order maps to color then optional size roles.
|
|
673
|
+
|
|
674
|
+
**Canonical example**
|
|
675
|
+
|
|
676
|
+
```json
|
|
677
|
+
{
|
|
678
|
+
"data": {
|
|
679
|
+
"dimensions": [
|
|
680
|
+
{
|
|
681
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
682
|
+
"format": {
|
|
683
|
+
"formatType": "none"
|
|
684
|
+
},
|
|
685
|
+
"ref": "manufacturer"
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
"fieldKey": "[Cars].[Model]",
|
|
689
|
+
"format": {
|
|
690
|
+
"formatType": "none"
|
|
691
|
+
},
|
|
692
|
+
"ref": "model"
|
|
693
|
+
}
|
|
694
|
+
],
|
|
695
|
+
"measures": [
|
|
696
|
+
{
|
|
697
|
+
"aggregation": "SUM",
|
|
698
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
699
|
+
"format": {
|
|
700
|
+
"formatType": "number2Decimal",
|
|
701
|
+
"negativeType": "parenthesis"
|
|
702
|
+
},
|
|
703
|
+
"ref": "sales"
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
"aggregation": "AVG",
|
|
707
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
708
|
+
"format": {
|
|
709
|
+
"formatType": "number2Decimal",
|
|
710
|
+
"negativeType": "parenthesis"
|
|
711
|
+
},
|
|
712
|
+
"ref": "horsepower"
|
|
713
|
+
}
|
|
714
|
+
]
|
|
715
|
+
},
|
|
716
|
+
"filterGroup": {
|
|
717
|
+
"filters": [
|
|
718
|
+
{
|
|
719
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
720
|
+
"operator": "inList",
|
|
721
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
722
|
+
}
|
|
723
|
+
],
|
|
724
|
+
"operator": "and"
|
|
725
|
+
},
|
|
726
|
+
"limiting": {
|
|
727
|
+
"queryLimit": 100
|
|
728
|
+
},
|
|
729
|
+
"presentation": {
|
|
730
|
+
"axes": {
|
|
731
|
+
"dimension": {
|
|
732
|
+
"labelsVisible": true,
|
|
733
|
+
"title": "Manufacturer",
|
|
734
|
+
"titleVisible": true
|
|
735
|
+
},
|
|
736
|
+
"primaryMeasure": {
|
|
737
|
+
"labelsVisible": true,
|
|
738
|
+
"title": "Sales",
|
|
739
|
+
"titleVisible": true
|
|
740
|
+
},
|
|
741
|
+
"secondaryDimension": {
|
|
742
|
+
"labelsVisible": true,
|
|
743
|
+
"title": "Model",
|
|
744
|
+
"titleVisible": true
|
|
745
|
+
}
|
|
746
|
+
},
|
|
747
|
+
"legend": {
|
|
748
|
+
"position": "right",
|
|
749
|
+
"title": "Cars comparison",
|
|
750
|
+
"visible": true
|
|
751
|
+
}
|
|
752
|
+
},
|
|
753
|
+
"sorting": [
|
|
754
|
+
{
|
|
755
|
+
"by": "sales",
|
|
756
|
+
"direction": "desc"
|
|
757
|
+
}
|
|
758
|
+
],
|
|
759
|
+
"type": "heatMap",
|
|
760
|
+
"version": 1
|
|
761
|
+
}
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
## `histogram`: Histogram
|
|
765
|
+
|
|
766
|
+
Distribution of a numeric field into generated bins and counts.
|
|
767
|
+
|
|
768
|
+
**Data requirements**
|
|
769
|
+
|
|
770
|
+
- Exactly one numeric dimension.
|
|
771
|
+
- No caller-supplied measures.
|
|
772
|
+
|
|
773
|
+
**Supported features**
|
|
774
|
+
|
|
775
|
+
`axes`, `axis-bands`, `axis-range`, `dimensions`, `filters`, `legend`, `orientation`, `value-formatting`
|
|
776
|
+
|
|
777
|
+
**Constraints and semantics**
|
|
778
|
+
|
|
779
|
+
- The compiler creates the canonical generated count measure; callers do not provide measures.
|
|
780
|
+
- presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
|
|
781
|
+
- Set range on the primary measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on the primary measure axis to reverse its values.
|
|
782
|
+
|
|
783
|
+
**Canonical example**
|
|
784
|
+
|
|
785
|
+
```json
|
|
786
|
+
{
|
|
787
|
+
"data": {
|
|
788
|
+
"dimensions": [
|
|
789
|
+
{
|
|
790
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
791
|
+
"format": {
|
|
792
|
+
"formatType": "none"
|
|
793
|
+
},
|
|
794
|
+
"ref": "horsepower"
|
|
795
|
+
}
|
|
796
|
+
]
|
|
797
|
+
},
|
|
798
|
+
"filterGroup": {
|
|
799
|
+
"filters": [
|
|
800
|
+
{
|
|
801
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
802
|
+
"operator": "inList",
|
|
803
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
804
|
+
}
|
|
805
|
+
],
|
|
806
|
+
"operator": "and"
|
|
807
|
+
},
|
|
808
|
+
"presentation": {
|
|
809
|
+
"axes": {
|
|
810
|
+
"dimension": {
|
|
811
|
+
"labelsVisible": true,
|
|
812
|
+
"title": "Horsepower",
|
|
813
|
+
"titleVisible": true
|
|
814
|
+
},
|
|
815
|
+
"primaryMeasure": {
|
|
816
|
+
"labelsVisible": true,
|
|
817
|
+
"title": "Count",
|
|
818
|
+
"titleVisible": true
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
"legend": {
|
|
822
|
+
"position": "right",
|
|
823
|
+
"title": "Cars comparison",
|
|
824
|
+
"visible": true
|
|
825
|
+
},
|
|
826
|
+
"orientation": "vertical"
|
|
827
|
+
},
|
|
828
|
+
"type": "histogram",
|
|
829
|
+
"version": 1
|
|
830
|
+
}
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
## `line`: Line chart
|
|
834
|
+
|
|
835
|
+
Trend chart with sorting, query limiting, dual measure axes, labels, legend, and orientation.
|
|
836
|
+
|
|
837
|
+
**Data requirements**
|
|
838
|
+
|
|
839
|
+
- At least one dimension.
|
|
840
|
+
- At least one measure.
|
|
841
|
+
|
|
842
|
+
**Supported features**
|
|
843
|
+
|
|
844
|
+
`axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `data-points`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `value-formatting`
|
|
845
|
+
|
|
846
|
+
**Constraints and semantics**
|
|
847
|
+
|
|
848
|
+
- Each measure may select the primary or secondary axis using its axis property.
|
|
849
|
+
- Visible data labels require dataPointShape on every measure.
|
|
850
|
+
- presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
|
|
851
|
+
- Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
|
|
852
|
+
- Set scale to log on a measure axis to draw it logarithmically, with gridlines at powers of ten. Zero and negative values are drawn at the floor of a log axis.
|
|
853
|
+
- Value colors in presentation.coloring require at least two dimensions; measure color rules are not supported.
|
|
854
|
+
|
|
855
|
+
**Canonical example**
|
|
856
|
+
|
|
857
|
+
```json
|
|
858
|
+
{
|
|
859
|
+
"data": {
|
|
860
|
+
"dimensions": [
|
|
861
|
+
{
|
|
862
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
863
|
+
"format": {
|
|
864
|
+
"formatType": "none"
|
|
865
|
+
},
|
|
866
|
+
"ref": "manufacturer"
|
|
867
|
+
}
|
|
868
|
+
],
|
|
869
|
+
"measures": [
|
|
870
|
+
{
|
|
871
|
+
"aggregation": "SUM",
|
|
872
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
873
|
+
"format": {
|
|
874
|
+
"formatType": "number2Decimal",
|
|
875
|
+
"negativeType": "parenthesis"
|
|
876
|
+
},
|
|
877
|
+
"ref": "sales",
|
|
878
|
+
"axis": "primary",
|
|
879
|
+
"dataPointShape": "circle"
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
"aggregation": "AVG",
|
|
883
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
884
|
+
"format": {
|
|
885
|
+
"formatType": "number2Decimal",
|
|
886
|
+
"negativeType": "parenthesis"
|
|
887
|
+
},
|
|
888
|
+
"ref": "horsepower",
|
|
889
|
+
"axis": "secondary",
|
|
890
|
+
"dataPointShape": "square"
|
|
891
|
+
}
|
|
892
|
+
]
|
|
893
|
+
},
|
|
894
|
+
"filterGroup": {
|
|
895
|
+
"filters": [
|
|
896
|
+
{
|
|
897
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
898
|
+
"operator": "inList",
|
|
899
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
900
|
+
}
|
|
901
|
+
],
|
|
902
|
+
"operator": "and"
|
|
903
|
+
},
|
|
904
|
+
"limiting": {
|
|
905
|
+
"queryLimit": 100
|
|
906
|
+
},
|
|
907
|
+
"presentation": {
|
|
908
|
+
"axes": {
|
|
909
|
+
"dimension": {
|
|
910
|
+
"labelsVisible": true,
|
|
911
|
+
"title": "Manufacturer",
|
|
912
|
+
"titleVisible": true
|
|
913
|
+
},
|
|
914
|
+
"primaryMeasure": {
|
|
915
|
+
"labelsVisible": true,
|
|
916
|
+
"title": "Sales",
|
|
917
|
+
"titleVisible": true
|
|
918
|
+
},
|
|
919
|
+
"secondaryMeasure": {
|
|
920
|
+
"labelsVisible": true,
|
|
921
|
+
"title": "Horsepower",
|
|
922
|
+
"titleVisible": true
|
|
923
|
+
}
|
|
924
|
+
},
|
|
925
|
+
"dataLabels": {
|
|
926
|
+
"density": "medium",
|
|
927
|
+
"visible": true
|
|
928
|
+
},
|
|
929
|
+
"legend": {
|
|
930
|
+
"position": "right",
|
|
931
|
+
"title": "Cars comparison",
|
|
932
|
+
"visible": true
|
|
933
|
+
},
|
|
934
|
+
"orientation": "vertical"
|
|
935
|
+
},
|
|
936
|
+
"sorting": [
|
|
937
|
+
{
|
|
938
|
+
"by": "sales",
|
|
939
|
+
"direction": "desc"
|
|
940
|
+
}
|
|
941
|
+
],
|
|
942
|
+
"type": "line",
|
|
943
|
+
"version": 1
|
|
944
|
+
}
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
**Additional scenarios**
|
|
948
|
+
|
|
949
|
+
### Fixed, inverted measure axis
|
|
950
|
+
|
|
951
|
+
```json
|
|
952
|
+
{
|
|
953
|
+
"data": {
|
|
954
|
+
"dimensions": [
|
|
955
|
+
{
|
|
956
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
957
|
+
"format": {
|
|
958
|
+
"formatType": "none"
|
|
959
|
+
},
|
|
960
|
+
"ref": "manufacturer"
|
|
961
|
+
}
|
|
962
|
+
],
|
|
963
|
+
"measures": [
|
|
964
|
+
{
|
|
965
|
+
"aggregation": "SUM",
|
|
966
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
967
|
+
"format": {
|
|
968
|
+
"formatType": "number2Decimal",
|
|
969
|
+
"negativeType": "parenthesis"
|
|
970
|
+
},
|
|
971
|
+
"ref": "sales",
|
|
972
|
+
"dataPointShape": "circle"
|
|
973
|
+
}
|
|
974
|
+
]
|
|
975
|
+
},
|
|
976
|
+
"presentation": {
|
|
977
|
+
"axes": {
|
|
978
|
+
"primaryMeasure": {
|
|
979
|
+
"inverted": true,
|
|
980
|
+
"range": {
|
|
981
|
+
"max": 100,
|
|
982
|
+
"min": 1
|
|
983
|
+
},
|
|
984
|
+
"title": "Rank"
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
},
|
|
988
|
+
"type": "line",
|
|
989
|
+
"version": 1
|
|
990
|
+
}
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
### Series colored by dimension value
|
|
994
|
+
|
|
995
|
+
```json
|
|
996
|
+
{
|
|
997
|
+
"data": {
|
|
998
|
+
"dimensions": [
|
|
999
|
+
{
|
|
1000
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1001
|
+
"format": {
|
|
1002
|
+
"formatType": "none"
|
|
1003
|
+
},
|
|
1004
|
+
"ref": "manufacturer"
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
"fieldKey": "[Cars].[Model]",
|
|
1008
|
+
"format": {
|
|
1009
|
+
"formatType": "none"
|
|
1010
|
+
},
|
|
1011
|
+
"ref": "model"
|
|
1012
|
+
}
|
|
1013
|
+
],
|
|
1014
|
+
"measures": [
|
|
1015
|
+
{
|
|
1016
|
+
"aggregation": "SUM",
|
|
1017
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1018
|
+
"format": {
|
|
1019
|
+
"formatType": "number2Decimal",
|
|
1020
|
+
"negativeType": "parenthesis"
|
|
1021
|
+
},
|
|
1022
|
+
"ref": "sales",
|
|
1023
|
+
"dataPointShape": "circle"
|
|
1024
|
+
}
|
|
1025
|
+
]
|
|
1026
|
+
},
|
|
1027
|
+
"presentation": {
|
|
1028
|
+
"coloring": {
|
|
1029
|
+
"overwrites": [
|
|
1030
|
+
{
|
|
1031
|
+
"color": "#7C3AED",
|
|
1032
|
+
"operator": "startsWith",
|
|
1033
|
+
"value": "A"
|
|
1034
|
+
}
|
|
1035
|
+
]
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
"type": "line",
|
|
1039
|
+
"version": 1
|
|
1040
|
+
}
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
## `radar`: Radar chart
|
|
1044
|
+
|
|
1045
|
+
Radial comparison chart for one or more measures with optional categorical dimensions.
|
|
1046
|
+
|
|
1047
|
+
**Data requirements**
|
|
1048
|
+
|
|
1049
|
+
- Zero to two dimensions.
|
|
1050
|
+
- Two to five measures without dimensions, or one with dimensions.
|
|
1051
|
+
|
|
1052
|
+
**Supported features**
|
|
1053
|
+
|
|
1054
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`
|
|
1055
|
+
|
|
1056
|
+
**Constraints and semantics**
|
|
1057
|
+
|
|
1058
|
+
- Without dimensions, at least two measures are required.
|
|
1059
|
+
- With dimensions, exactly one measure is supported.
|
|
1060
|
+
- Value colors in presentation.coloring require two dimensions; measure color rules are not supported.
|
|
1061
|
+
|
|
1062
|
+
**Canonical example**
|
|
1063
|
+
|
|
1064
|
+
```json
|
|
1065
|
+
{
|
|
1066
|
+
"data": {
|
|
1067
|
+
"dimensions": [
|
|
1068
|
+
{
|
|
1069
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1070
|
+
"format": {
|
|
1071
|
+
"formatType": "none"
|
|
1072
|
+
},
|
|
1073
|
+
"ref": "manufacturer"
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
"measures": [
|
|
1077
|
+
{
|
|
1078
|
+
"aggregation": "SUM",
|
|
1079
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1080
|
+
"format": {
|
|
1081
|
+
"formatType": "number2Decimal",
|
|
1082
|
+
"negativeType": "parenthesis"
|
|
1083
|
+
},
|
|
1084
|
+
"ref": "sales"
|
|
1085
|
+
}
|
|
1086
|
+
]
|
|
1087
|
+
},
|
|
1088
|
+
"filterGroup": {
|
|
1089
|
+
"filters": [
|
|
1090
|
+
{
|
|
1091
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1092
|
+
"operator": "inList",
|
|
1093
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1094
|
+
}
|
|
1095
|
+
],
|
|
1096
|
+
"operator": "and"
|
|
1097
|
+
},
|
|
1098
|
+
"presentation": {
|
|
1099
|
+
"legend": {
|
|
1100
|
+
"position": "right",
|
|
1101
|
+
"title": "Cars comparison",
|
|
1102
|
+
"visible": true
|
|
1103
|
+
}
|
|
1104
|
+
},
|
|
1105
|
+
"type": "radar",
|
|
1106
|
+
"version": 1
|
|
1107
|
+
}
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
## `pie`: Pie chart
|
|
1111
|
+
|
|
1112
|
+
Part-to-whole chart with optional secondary radial measure.
|
|
1113
|
+
|
|
1114
|
+
**Data requirements**
|
|
1115
|
+
|
|
1116
|
+
- Exactly one dimension.
|
|
1117
|
+
- One or two measures.
|
|
1118
|
+
|
|
1119
|
+
**Supported features**
|
|
1120
|
+
|
|
1121
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`, `query-limit`, `sorting`
|
|
1122
|
+
|
|
1123
|
+
**Constraints and semantics**
|
|
1124
|
+
|
|
1125
|
+
- The first measure is the slice value; the optional second measure receives the length role.
|
|
1126
|
+
|
|
1127
|
+
**Canonical example**
|
|
1128
|
+
|
|
1129
|
+
```json
|
|
1130
|
+
{
|
|
1131
|
+
"data": {
|
|
1132
|
+
"dimensions": [
|
|
1133
|
+
{
|
|
1134
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1135
|
+
"format": {
|
|
1136
|
+
"formatType": "none"
|
|
1137
|
+
},
|
|
1138
|
+
"ref": "manufacturer"
|
|
1139
|
+
}
|
|
1140
|
+
],
|
|
1141
|
+
"measures": [
|
|
1142
|
+
{
|
|
1143
|
+
"aggregation": "SUM",
|
|
1144
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1145
|
+
"format": {
|
|
1146
|
+
"formatType": "number2Decimal",
|
|
1147
|
+
"negativeType": "parenthesis"
|
|
1148
|
+
},
|
|
1149
|
+
"ref": "sales"
|
|
1150
|
+
}
|
|
1151
|
+
]
|
|
1152
|
+
},
|
|
1153
|
+
"filterGroup": {
|
|
1154
|
+
"filters": [
|
|
1155
|
+
{
|
|
1156
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1157
|
+
"operator": "inList",
|
|
1158
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1159
|
+
}
|
|
1160
|
+
],
|
|
1161
|
+
"operator": "and"
|
|
1162
|
+
},
|
|
1163
|
+
"limiting": {
|
|
1164
|
+
"queryLimit": 100
|
|
1165
|
+
},
|
|
1166
|
+
"presentation": {
|
|
1167
|
+
"legend": {
|
|
1168
|
+
"position": "right",
|
|
1169
|
+
"title": "Cars comparison",
|
|
1170
|
+
"visible": true
|
|
1171
|
+
}
|
|
1172
|
+
},
|
|
1173
|
+
"sorting": [
|
|
1174
|
+
{
|
|
1175
|
+
"by": "sales",
|
|
1176
|
+
"direction": "desc"
|
|
1177
|
+
}
|
|
1178
|
+
],
|
|
1179
|
+
"type": "pie",
|
|
1180
|
+
"version": 1
|
|
1181
|
+
}
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
**Additional scenarios**
|
|
1185
|
+
|
|
1186
|
+
### Ordered bands colored along a ramp
|
|
1187
|
+
|
|
1188
|
+
```json
|
|
1189
|
+
{
|
|
1190
|
+
"data": {
|
|
1191
|
+
"dimensions": [
|
|
1192
|
+
{
|
|
1193
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1194
|
+
"format": {
|
|
1195
|
+
"formatType": "none"
|
|
1196
|
+
},
|
|
1197
|
+
"ref": "manufacturer"
|
|
1198
|
+
}
|
|
1199
|
+
],
|
|
1200
|
+
"measures": [
|
|
1201
|
+
{
|
|
1202
|
+
"aggregation": "SUM",
|
|
1203
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1204
|
+
"format": {
|
|
1205
|
+
"formatType": "number2Decimal",
|
|
1206
|
+
"negativeType": "parenthesis"
|
|
1207
|
+
},
|
|
1208
|
+
"ref": "sales"
|
|
1209
|
+
}
|
|
1210
|
+
]
|
|
1211
|
+
},
|
|
1212
|
+
"presentation": {
|
|
1213
|
+
"coloring": {
|
|
1214
|
+
"overwrites": [
|
|
1215
|
+
{
|
|
1216
|
+
"color": "#134E4A",
|
|
1217
|
+
"value": "Audi"
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
"color": "#2DD4BF",
|
|
1221
|
+
"value": "BMW"
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
"color": "#CCFBF1",
|
|
1225
|
+
"value": "Buick"
|
|
1226
|
+
}
|
|
1227
|
+
]
|
|
1228
|
+
}
|
|
1229
|
+
},
|
|
1230
|
+
"type": "pie",
|
|
1231
|
+
"version": 1
|
|
1232
|
+
}
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
## `tree`: Tree chart
|
|
1236
|
+
|
|
1237
|
+
Hierarchical tree built from dimensions, measures, or both.
|
|
1238
|
+
|
|
1239
|
+
**Data requirements**
|
|
1240
|
+
|
|
1241
|
+
- Zero to ten dimensions.
|
|
1242
|
+
- Zero to one hundred measures, or at most one with dimensions.
|
|
1243
|
+
|
|
1244
|
+
**Supported features**
|
|
1245
|
+
|
|
1246
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `layout`, `query-limit`, `sorting`
|
|
1247
|
+
|
|
1248
|
+
**Constraints and semantics**
|
|
1249
|
+
|
|
1250
|
+
- At least one dimension or measure must be supplied.
|
|
1251
|
+
- Trees with dimensions support at most one measure; measure-only trees may contain multiple measures.
|
|
1252
|
+
|
|
1253
|
+
**Canonical example**
|
|
1254
|
+
|
|
1255
|
+
```json
|
|
1256
|
+
{
|
|
1257
|
+
"data": {
|
|
1258
|
+
"dimensions": [
|
|
1259
|
+
{
|
|
1260
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1261
|
+
"format": {
|
|
1262
|
+
"formatType": "none"
|
|
1263
|
+
},
|
|
1264
|
+
"ref": "manufacturer"
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
"fieldKey": "[Cars].[Model]",
|
|
1268
|
+
"format": {
|
|
1269
|
+
"formatType": "none"
|
|
1270
|
+
},
|
|
1271
|
+
"ref": "model"
|
|
1272
|
+
}
|
|
1273
|
+
],
|
|
1274
|
+
"measures": [
|
|
1275
|
+
{
|
|
1276
|
+
"aggregation": "SUM",
|
|
1277
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1278
|
+
"format": {
|
|
1279
|
+
"formatType": "number2Decimal",
|
|
1280
|
+
"negativeType": "parenthesis"
|
|
1281
|
+
},
|
|
1282
|
+
"ref": "sales"
|
|
1283
|
+
}
|
|
1284
|
+
]
|
|
1285
|
+
},
|
|
1286
|
+
"filterGroup": {
|
|
1287
|
+
"filters": [
|
|
1288
|
+
{
|
|
1289
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1290
|
+
"operator": "inList",
|
|
1291
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1292
|
+
}
|
|
1293
|
+
],
|
|
1294
|
+
"operator": "and"
|
|
1295
|
+
},
|
|
1296
|
+
"limiting": {
|
|
1297
|
+
"queryLimit": 100
|
|
1298
|
+
},
|
|
1299
|
+
"presentation": {
|
|
1300
|
+
"layout": {
|
|
1301
|
+
"compact": true,
|
|
1302
|
+
"direction": "top",
|
|
1303
|
+
"forceAutoFit": false,
|
|
1304
|
+
"initialExpandedLevels": 1
|
|
1305
|
+
}
|
|
1306
|
+
},
|
|
1307
|
+
"sorting": [
|
|
1308
|
+
{
|
|
1309
|
+
"by": "sales",
|
|
1310
|
+
"direction": "desc"
|
|
1311
|
+
}
|
|
1312
|
+
],
|
|
1313
|
+
"type": "tree",
|
|
1314
|
+
"version": 1
|
|
1315
|
+
}
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
## `treemap`: Treemap
|
|
1319
|
+
|
|
1320
|
+
Hierarchical area chart using ordered dimensions and one size measure.
|
|
1321
|
+
|
|
1322
|
+
**Data requirements**
|
|
1323
|
+
|
|
1324
|
+
- Between one and ten dimensions.
|
|
1325
|
+
- Exactly one measure.
|
|
1326
|
+
|
|
1327
|
+
**Supported features**
|
|
1328
|
+
|
|
1329
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`
|
|
1330
|
+
|
|
1331
|
+
**Constraints and semantics**
|
|
1332
|
+
|
|
1333
|
+
- Dimension order defines hierarchy depth.
|
|
1334
|
+
|
|
1335
|
+
**Canonical example**
|
|
1336
|
+
|
|
1337
|
+
```json
|
|
1338
|
+
{
|
|
1339
|
+
"data": {
|
|
1340
|
+
"dimensions": [
|
|
1341
|
+
{
|
|
1342
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1343
|
+
"format": {
|
|
1344
|
+
"formatType": "none"
|
|
1345
|
+
},
|
|
1346
|
+
"ref": "manufacturer"
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
"fieldKey": "[Cars].[Model]",
|
|
1350
|
+
"format": {
|
|
1351
|
+
"formatType": "none"
|
|
1352
|
+
},
|
|
1353
|
+
"ref": "model"
|
|
1354
|
+
}
|
|
1355
|
+
],
|
|
1356
|
+
"measures": [
|
|
1357
|
+
{
|
|
1358
|
+
"aggregation": "SUM",
|
|
1359
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1360
|
+
"format": {
|
|
1361
|
+
"formatType": "number2Decimal",
|
|
1362
|
+
"negativeType": "parenthesis"
|
|
1363
|
+
},
|
|
1364
|
+
"ref": "sales"
|
|
1365
|
+
}
|
|
1366
|
+
]
|
|
1367
|
+
},
|
|
1368
|
+
"filterGroup": {
|
|
1369
|
+
"filters": [
|
|
1370
|
+
{
|
|
1371
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1372
|
+
"operator": "inList",
|
|
1373
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1374
|
+
}
|
|
1375
|
+
],
|
|
1376
|
+
"operator": "and"
|
|
1377
|
+
},
|
|
1378
|
+
"presentation": {
|
|
1379
|
+
"legend": {
|
|
1380
|
+
"position": "right",
|
|
1381
|
+
"title": "Cars comparison",
|
|
1382
|
+
"visible": true
|
|
1383
|
+
}
|
|
1384
|
+
},
|
|
1385
|
+
"type": "treemap",
|
|
1386
|
+
"version": 1
|
|
1387
|
+
}
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
## `sankey`: Sankey chart
|
|
1391
|
+
|
|
1392
|
+
Flow chart across an ordered sequence of categorical dimensions.
|
|
1393
|
+
|
|
1394
|
+
**Data requirements**
|
|
1395
|
+
|
|
1396
|
+
- Between two and fifteen dimensions.
|
|
1397
|
+
- Exactly one measure.
|
|
1398
|
+
|
|
1399
|
+
**Supported features**
|
|
1400
|
+
|
|
1401
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`
|
|
1402
|
+
|
|
1403
|
+
**Constraints and semantics**
|
|
1404
|
+
|
|
1405
|
+
- Dimension order defines the source-to-target flow stages.
|
|
1406
|
+
- Every value color in presentation.coloring must name the dimension it applies to.
|
|
1407
|
+
|
|
1408
|
+
**Canonical example**
|
|
1409
|
+
|
|
1410
|
+
```json
|
|
1411
|
+
{
|
|
1412
|
+
"data": {
|
|
1413
|
+
"dimensions": [
|
|
1414
|
+
{
|
|
1415
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1416
|
+
"format": {
|
|
1417
|
+
"formatType": "none"
|
|
1418
|
+
},
|
|
1419
|
+
"ref": "manufacturer"
|
|
1420
|
+
},
|
|
1421
|
+
{
|
|
1422
|
+
"fieldKey": "[Cars].[Model]",
|
|
1423
|
+
"format": {
|
|
1424
|
+
"formatType": "none"
|
|
1425
|
+
},
|
|
1426
|
+
"ref": "model"
|
|
1427
|
+
}
|
|
1428
|
+
],
|
|
1429
|
+
"measures": [
|
|
1430
|
+
{
|
|
1431
|
+
"aggregation": "SUM",
|
|
1432
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1433
|
+
"format": {
|
|
1434
|
+
"formatType": "number2Decimal",
|
|
1435
|
+
"negativeType": "parenthesis"
|
|
1436
|
+
},
|
|
1437
|
+
"ref": "sales"
|
|
1438
|
+
}
|
|
1439
|
+
]
|
|
1440
|
+
},
|
|
1441
|
+
"filterGroup": {
|
|
1442
|
+
"filters": [
|
|
1443
|
+
{
|
|
1444
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1445
|
+
"operator": "inList",
|
|
1446
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1447
|
+
}
|
|
1448
|
+
],
|
|
1449
|
+
"operator": "and"
|
|
1450
|
+
},
|
|
1451
|
+
"type": "sankey",
|
|
1452
|
+
"version": 1
|
|
1453
|
+
}
|
|
1454
|
+
```
|
|
1455
|
+
|
|
1456
|
+
**Additional scenarios**
|
|
1457
|
+
|
|
1458
|
+
### A color bound to a value of one flow stage
|
|
1459
|
+
|
|
1460
|
+
```json
|
|
1461
|
+
{
|
|
1462
|
+
"data": {
|
|
1463
|
+
"dimensions": [
|
|
1464
|
+
{
|
|
1465
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1466
|
+
"format": {
|
|
1467
|
+
"formatType": "none"
|
|
1468
|
+
},
|
|
1469
|
+
"ref": "manufacturer"
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
"fieldKey": "[Cars].[Model]",
|
|
1473
|
+
"format": {
|
|
1474
|
+
"formatType": "none"
|
|
1475
|
+
},
|
|
1476
|
+
"ref": "model"
|
|
1477
|
+
}
|
|
1478
|
+
],
|
|
1479
|
+
"measures": [
|
|
1480
|
+
{
|
|
1481
|
+
"aggregation": "SUM",
|
|
1482
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1483
|
+
"format": {
|
|
1484
|
+
"formatType": "number2Decimal",
|
|
1485
|
+
"negativeType": "parenthesis"
|
|
1486
|
+
},
|
|
1487
|
+
"ref": "sales"
|
|
1488
|
+
}
|
|
1489
|
+
]
|
|
1490
|
+
},
|
|
1491
|
+
"presentation": {
|
|
1492
|
+
"coloring": {
|
|
1493
|
+
"overwrites": [
|
|
1494
|
+
{
|
|
1495
|
+
"color": "#CA8A04",
|
|
1496
|
+
"dimension": "manufacturer",
|
|
1497
|
+
"value": "Audi"
|
|
1498
|
+
}
|
|
1499
|
+
]
|
|
1500
|
+
}
|
|
1501
|
+
},
|
|
1502
|
+
"type": "sankey",
|
|
1503
|
+
"version": 1
|
|
1504
|
+
}
|
|
1505
|
+
```
|
|
1506
|
+
|
|
1507
|
+
## `scatter`: Scatter chart
|
|
1508
|
+
|
|
1509
|
+
Relationship chart using horizontal and vertical measures with optional size and image roles.
|
|
1510
|
+
|
|
1511
|
+
**Data requirements**
|
|
1512
|
+
|
|
1513
|
+
- One or two dimensions.
|
|
1514
|
+
- Two or three measures.
|
|
1515
|
+
|
|
1516
|
+
**Supported features**
|
|
1517
|
+
|
|
1518
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `query-limit`, `sorting`
|
|
1519
|
+
|
|
1520
|
+
**Constraints and semantics**
|
|
1521
|
+
|
|
1522
|
+
- Measure order maps to horizontal, vertical, and optional size roles.
|
|
1523
|
+
- The optional second dimension receives the image role.
|
|
1524
|
+
- Roles come from item order only; a ref is a label and does not select a role.
|
|
1525
|
+
- With a size measure, points scale between the setPointSize and setMaxPointSize operation values.
|
|
1526
|
+
- Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
|
|
1527
|
+
|
|
1528
|
+
**Canonical example**
|
|
1529
|
+
|
|
1530
|
+
```json
|
|
1531
|
+
{
|
|
1532
|
+
"data": {
|
|
1533
|
+
"dimensions": [
|
|
1534
|
+
{
|
|
1535
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1536
|
+
"format": {
|
|
1537
|
+
"formatType": "none"
|
|
1538
|
+
},
|
|
1539
|
+
"ref": "manufacturer"
|
|
1540
|
+
}
|
|
1541
|
+
],
|
|
1542
|
+
"measures": [
|
|
1543
|
+
{
|
|
1544
|
+
"aggregation": "SUM",
|
|
1545
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1546
|
+
"format": {
|
|
1547
|
+
"formatType": "number2Decimal",
|
|
1548
|
+
"negativeType": "parenthesis"
|
|
1549
|
+
},
|
|
1550
|
+
"ref": "sales"
|
|
1551
|
+
},
|
|
1552
|
+
{
|
|
1553
|
+
"aggregation": "AVG",
|
|
1554
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
1555
|
+
"format": {
|
|
1556
|
+
"formatType": "number2Decimal",
|
|
1557
|
+
"negativeType": "parenthesis"
|
|
1558
|
+
},
|
|
1559
|
+
"ref": "horsepower"
|
|
1560
|
+
},
|
|
1561
|
+
{
|
|
1562
|
+
"aggregation": "AVG",
|
|
1563
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1564
|
+
"format": {
|
|
1565
|
+
"formatType": "number2Decimal",
|
|
1566
|
+
"negativeType": "parenthesis"
|
|
1567
|
+
},
|
|
1568
|
+
"ref": "size"
|
|
1569
|
+
}
|
|
1570
|
+
]
|
|
1571
|
+
},
|
|
1572
|
+
"filterGroup": {
|
|
1573
|
+
"filters": [
|
|
1574
|
+
{
|
|
1575
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1576
|
+
"operator": "inList",
|
|
1577
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1578
|
+
}
|
|
1579
|
+
],
|
|
1580
|
+
"operator": "and"
|
|
1581
|
+
},
|
|
1582
|
+
"presentation": {
|
|
1583
|
+
"axes": {
|
|
1584
|
+
"primaryMeasure": {
|
|
1585
|
+
"labelsVisible": true,
|
|
1586
|
+
"title": "Sales",
|
|
1587
|
+
"titleVisible": true
|
|
1588
|
+
},
|
|
1589
|
+
"secondaryMeasure": {
|
|
1590
|
+
"labelsVisible": true,
|
|
1591
|
+
"title": "Horsepower",
|
|
1592
|
+
"titleVisible": true
|
|
1593
|
+
}
|
|
1594
|
+
},
|
|
1595
|
+
"legend": {
|
|
1596
|
+
"position": "right",
|
|
1597
|
+
"title": "Cars comparison",
|
|
1598
|
+
"visible": true
|
|
1599
|
+
}
|
|
1600
|
+
},
|
|
1601
|
+
"type": "scatter",
|
|
1602
|
+
"version": 1
|
|
1603
|
+
}
|
|
1604
|
+
```
|
|
1605
|
+
|
|
1606
|
+
## `table`: Table
|
|
1607
|
+
|
|
1608
|
+
Normal, expandable, or pivot tabular output with formatting, filtering, sorting, query limiting, and totals.
|
|
1609
|
+
|
|
1610
|
+
**Data requirements**
|
|
1611
|
+
|
|
1612
|
+
- Normal tables require at least one ordered dimension or measure column.
|
|
1613
|
+
- Expandable tables require at least one dimension and one measure.
|
|
1614
|
+
- Pivot tables require at least one row dimension, one column dimension, and one measure.
|
|
1615
|
+
|
|
1616
|
+
**Supported features**
|
|
1617
|
+
|
|
1618
|
+
`dimensions`, `filters`, `layout`, `measures`, `query-limit`, `sorting`, `table-structure`, `totals`, `value-formatting`
|
|
1619
|
+
|
|
1620
|
+
**Constraints and semantics**
|
|
1621
|
+
|
|
1622
|
+
- Normal table column order is preserved, and each column declares whether it is a dimension or measure.
|
|
1623
|
+
- Expandable table dimension order defines the expansion hierarchy.
|
|
1624
|
+
- Pivot tables explicitly separate row dimensions, column dimensions, and measures.
|
|
1625
|
+
- Measure definitions require valid aggregation for raw fields.
|
|
1626
|
+
- Presentation settings initialize table appearance and layout; later runtime operations preserve them.
|
|
1627
|
+
- Totals settings are optional; omitted totals properties preserve their values from the fresh default or preset vSpec.
|
|
1628
|
+
|
|
1629
|
+
**Canonical example**
|
|
1630
|
+
|
|
1631
|
+
```json
|
|
1632
|
+
{
|
|
1633
|
+
"data": {
|
|
1634
|
+
"columns": [
|
|
1635
|
+
{
|
|
1636
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1637
|
+
"format": {
|
|
1638
|
+
"formatType": "none"
|
|
1639
|
+
},
|
|
1640
|
+
"ref": "manufacturer",
|
|
1641
|
+
"role": "dimension"
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
"fieldKey": "[Cars].[Model]",
|
|
1645
|
+
"format": {
|
|
1646
|
+
"formatType": "none"
|
|
1647
|
+
},
|
|
1648
|
+
"ref": "model",
|
|
1649
|
+
"role": "dimension"
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
"aggregation": "SUM",
|
|
1653
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1654
|
+
"format": {
|
|
1655
|
+
"formatType": "number2Decimal",
|
|
1656
|
+
"negativeType": "parenthesis"
|
|
1657
|
+
},
|
|
1658
|
+
"ref": "sales",
|
|
1659
|
+
"role": "measure"
|
|
1660
|
+
}
|
|
1661
|
+
],
|
|
1662
|
+
"structure": "normal"
|
|
1663
|
+
},
|
|
1664
|
+
"filterGroup": {
|
|
1665
|
+
"filters": [
|
|
1666
|
+
{
|
|
1667
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1668
|
+
"operator": "inList",
|
|
1669
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1670
|
+
}
|
|
1671
|
+
],
|
|
1672
|
+
"operator": "and"
|
|
1673
|
+
},
|
|
1674
|
+
"limiting": {
|
|
1675
|
+
"queryLimit": 100
|
|
1676
|
+
},
|
|
1677
|
+
"presentation": {
|
|
1678
|
+
"background": {
|
|
1679
|
+
"color": "#ffffff",
|
|
1680
|
+
"type": "single"
|
|
1681
|
+
},
|
|
1682
|
+
"body": {
|
|
1683
|
+
"fontColor": "#1f1c3b",
|
|
1684
|
+
"fontFamily": "Roboto",
|
|
1685
|
+
"fontSize": 13,
|
|
1686
|
+
"horizontalAlign": "center",
|
|
1687
|
+
"verticalAlign": "middle"
|
|
1688
|
+
},
|
|
1689
|
+
"borders": {
|
|
1690
|
+
"color": "#e0e0e0",
|
|
1691
|
+
"dividerColor": "#e0e0e0",
|
|
1692
|
+
"dividers": "all",
|
|
1693
|
+
"enabled": true,
|
|
1694
|
+
"lineStyle": "line",
|
|
1695
|
+
"radius": 4,
|
|
1696
|
+
"strokeWidth": 1
|
|
1697
|
+
},
|
|
1698
|
+
"header": {
|
|
1699
|
+
"backgroundColor": "#ffffff",
|
|
1700
|
+
"borderColor": "#e0e0e0",
|
|
1701
|
+
"fontColor": "#1f1c3b",
|
|
1702
|
+
"fontFamily": "Roboto",
|
|
1703
|
+
"fontSize": 13
|
|
1704
|
+
},
|
|
1705
|
+
"highlight": {
|
|
1706
|
+
"backgroundColor": "#f2f2f2",
|
|
1707
|
+
"mode": "row"
|
|
1708
|
+
},
|
|
1709
|
+
"layout": {
|
|
1710
|
+
"columnWidthBehavior": "responsive",
|
|
1711
|
+
"rowHeight": 41
|
|
1712
|
+
}
|
|
1713
|
+
},
|
|
1714
|
+
"sorting": [
|
|
1715
|
+
{
|
|
1716
|
+
"by": "sales",
|
|
1717
|
+
"direction": "desc"
|
|
1718
|
+
}
|
|
1719
|
+
],
|
|
1720
|
+
"totals": {
|
|
1721
|
+
"applyTo": "both",
|
|
1722
|
+
"enabled": true,
|
|
1723
|
+
"showRecordsCount": true,
|
|
1724
|
+
"style": {
|
|
1725
|
+
"backgroundColor": "#f3f4f6",
|
|
1726
|
+
"fontColor": "#111827",
|
|
1727
|
+
"fontStyle": {
|
|
1728
|
+
"bold": true
|
|
1729
|
+
},
|
|
1730
|
+
"position": "bottom",
|
|
1731
|
+
"responsiveHeight": true
|
|
1732
|
+
}
|
|
1733
|
+
},
|
|
1734
|
+
"type": "table",
|
|
1735
|
+
"version": 1
|
|
1736
|
+
}
|
|
1737
|
+
```
|
|
1738
|
+
|
|
1739
|
+
**Additional scenarios**
|
|
1740
|
+
|
|
1741
|
+
### Expandable table
|
|
1742
|
+
|
|
1743
|
+
```json
|
|
1744
|
+
{
|
|
1745
|
+
"data": {
|
|
1746
|
+
"dimensions": [
|
|
1747
|
+
{
|
|
1748
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1749
|
+
"format": {
|
|
1750
|
+
"formatType": "none"
|
|
1751
|
+
},
|
|
1752
|
+
"ref": "manufacturer"
|
|
1753
|
+
},
|
|
1754
|
+
{
|
|
1755
|
+
"fieldKey": "[Cars].[Model]",
|
|
1756
|
+
"format": {
|
|
1757
|
+
"formatType": "none"
|
|
1758
|
+
},
|
|
1759
|
+
"ref": "model"
|
|
1760
|
+
}
|
|
1761
|
+
],
|
|
1762
|
+
"measures": [
|
|
1763
|
+
{
|
|
1764
|
+
"aggregation": "SUM",
|
|
1765
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1766
|
+
"format": {
|
|
1767
|
+
"formatType": "number2Decimal",
|
|
1768
|
+
"negativeType": "parenthesis"
|
|
1769
|
+
},
|
|
1770
|
+
"ref": "sales"
|
|
1771
|
+
}
|
|
1772
|
+
],
|
|
1773
|
+
"structure": "expandable"
|
|
1774
|
+
},
|
|
1775
|
+
"filterGroup": {
|
|
1776
|
+
"filters": [
|
|
1777
|
+
{
|
|
1778
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1779
|
+
"operator": "inList",
|
|
1780
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1781
|
+
}
|
|
1782
|
+
],
|
|
1783
|
+
"operator": "and"
|
|
1784
|
+
},
|
|
1785
|
+
"limiting": {
|
|
1786
|
+
"queryLimit": 100
|
|
1787
|
+
},
|
|
1788
|
+
"sorting": [
|
|
1789
|
+
{
|
|
1790
|
+
"by": "sales",
|
|
1791
|
+
"direction": "desc"
|
|
1792
|
+
}
|
|
1793
|
+
],
|
|
1794
|
+
"type": "table",
|
|
1795
|
+
"version": 1
|
|
1796
|
+
}
|
|
1797
|
+
```
|
|
1798
|
+
|
|
1799
|
+
### Pivot table
|
|
1800
|
+
|
|
1801
|
+
```json
|
|
1802
|
+
{
|
|
1803
|
+
"data": {
|
|
1804
|
+
"columnDimensions": [
|
|
1805
|
+
{
|
|
1806
|
+
"fieldKey": "[Cars].[Model]",
|
|
1807
|
+
"format": {
|
|
1808
|
+
"formatType": "none"
|
|
1809
|
+
},
|
|
1810
|
+
"ref": "model"
|
|
1811
|
+
}
|
|
1812
|
+
],
|
|
1813
|
+
"measures": [
|
|
1814
|
+
{
|
|
1815
|
+
"aggregation": "SUM",
|
|
1816
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1817
|
+
"format": {
|
|
1818
|
+
"formatType": "number2Decimal",
|
|
1819
|
+
"negativeType": "parenthesis"
|
|
1820
|
+
},
|
|
1821
|
+
"ref": "sales"
|
|
1822
|
+
}
|
|
1823
|
+
],
|
|
1824
|
+
"rowDimensions": [
|
|
1825
|
+
{
|
|
1826
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1827
|
+
"format": {
|
|
1828
|
+
"formatType": "none"
|
|
1829
|
+
},
|
|
1830
|
+
"ref": "manufacturer"
|
|
1831
|
+
}
|
|
1832
|
+
],
|
|
1833
|
+
"structure": "pivot"
|
|
1834
|
+
},
|
|
1835
|
+
"filterGroup": {
|
|
1836
|
+
"filters": [
|
|
1837
|
+
{
|
|
1838
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1839
|
+
"operator": "inList",
|
|
1840
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1841
|
+
}
|
|
1842
|
+
],
|
|
1843
|
+
"operator": "and"
|
|
1844
|
+
},
|
|
1845
|
+
"limiting": {
|
|
1846
|
+
"queryLimit": 100
|
|
1847
|
+
},
|
|
1848
|
+
"sorting": [
|
|
1849
|
+
{
|
|
1850
|
+
"by": "sales",
|
|
1851
|
+
"direction": "desc"
|
|
1852
|
+
}
|
|
1853
|
+
],
|
|
1854
|
+
"type": "table",
|
|
1855
|
+
"version": 1
|
|
1856
|
+
}
|
|
1857
|
+
```
|
|
1858
|
+
|
|
1859
|
+
## `waterfall`: Waterfall chart
|
|
1860
|
+
|
|
1861
|
+
Sequential contribution chart composed from one or more measures.
|
|
1862
|
+
|
|
1863
|
+
**Data requirements**
|
|
1864
|
+
|
|
1865
|
+
- Between one and one hundred measures.
|
|
1866
|
+
|
|
1867
|
+
**Supported features**
|
|
1868
|
+
|
|
1869
|
+
`axes`, `axis-bands`, `axis-range`, `data-labels`, `filters`, `measures`, `orientation`, `value-formatting`
|
|
1870
|
+
|
|
1871
|
+
**Constraints and semantics**
|
|
1872
|
+
|
|
1873
|
+
- Dimensions are not supported. Measure order defines the waterfall sequence.
|
|
1874
|
+
- Set range on the primary measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on the primary measure axis to reverse its values.
|
|
1875
|
+
- presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
|
|
1876
|
+
|
|
1877
|
+
**Canonical example**
|
|
1878
|
+
|
|
1879
|
+
```json
|
|
1880
|
+
{
|
|
1881
|
+
"data": {
|
|
1882
|
+
"measures": [
|
|
1883
|
+
{
|
|
1884
|
+
"aggregation": "SUM",
|
|
1885
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1886
|
+
"format": {
|
|
1887
|
+
"formatType": "number2Decimal",
|
|
1888
|
+
"negativeType": "parenthesis"
|
|
1889
|
+
},
|
|
1890
|
+
"ref": "sales",
|
|
1891
|
+
"dataLabels": {
|
|
1892
|
+
"visible": true
|
|
1893
|
+
}
|
|
1894
|
+
},
|
|
1895
|
+
{
|
|
1896
|
+
"aggregation": "AVG",
|
|
1897
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
1898
|
+
"format": {
|
|
1899
|
+
"formatType": "number2Decimal",
|
|
1900
|
+
"negativeType": "parenthesis"
|
|
1901
|
+
},
|
|
1902
|
+
"ref": "horsepower",
|
|
1903
|
+
"dataLabels": {
|
|
1904
|
+
"visible": true
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
]
|
|
1908
|
+
},
|
|
1909
|
+
"filterGroup": {
|
|
1910
|
+
"filters": [
|
|
1911
|
+
{
|
|
1912
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1913
|
+
"operator": "inList",
|
|
1914
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1915
|
+
}
|
|
1916
|
+
],
|
|
1917
|
+
"operator": "and"
|
|
1918
|
+
},
|
|
1919
|
+
"presentation": {
|
|
1920
|
+
"axes": {
|
|
1921
|
+
"dimension": {
|
|
1922
|
+
"labelsVisible": true,
|
|
1923
|
+
"title": "Measure",
|
|
1924
|
+
"titleVisible": true
|
|
1925
|
+
},
|
|
1926
|
+
"primaryMeasure": {
|
|
1927
|
+
"labelsVisible": true,
|
|
1928
|
+
"title": "Value",
|
|
1929
|
+
"titleVisible": true
|
|
1930
|
+
}
|
|
1931
|
+
},
|
|
1932
|
+
"dataLabels": {
|
|
1933
|
+
"visible": true
|
|
1934
|
+
},
|
|
1935
|
+
"orientation": "vertical"
|
|
1936
|
+
},
|
|
1937
|
+
"type": "waterfall",
|
|
1938
|
+
"version": 1
|
|
1939
|
+
}
|
|
1940
|
+
```
|
|
1941
|
+
|
|
1942
|
+
## `word-cloud`: Word cloud
|
|
1943
|
+
|
|
1944
|
+
Weighted word display using one label dimension and one measure.
|
|
1945
|
+
|
|
1946
|
+
**Data requirements**
|
|
1947
|
+
|
|
1948
|
+
- Exactly one dimension.
|
|
1949
|
+
- Exactly one measure.
|
|
1950
|
+
|
|
1951
|
+
**Supported features**
|
|
1952
|
+
|
|
1953
|
+
`dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`
|
|
1954
|
+
|
|
1955
|
+
**Constraints and semantics**
|
|
1956
|
+
|
|
1957
|
+
- The dimension supplies words and the measure supplies their weight.
|
|
1958
|
+
|
|
1959
|
+
**Canonical example**
|
|
1960
|
+
|
|
1961
|
+
```json
|
|
1962
|
+
{
|
|
1963
|
+
"data": {
|
|
1964
|
+
"dimensions": [
|
|
1965
|
+
{
|
|
1966
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1967
|
+
"format": {
|
|
1968
|
+
"formatType": "none"
|
|
1969
|
+
},
|
|
1970
|
+
"ref": "manufacturer"
|
|
1971
|
+
}
|
|
1972
|
+
],
|
|
1973
|
+
"measures": [
|
|
1974
|
+
{
|
|
1975
|
+
"aggregation": "SUM",
|
|
1976
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
1977
|
+
"format": {
|
|
1978
|
+
"formatType": "number2Decimal",
|
|
1979
|
+
"negativeType": "parenthesis"
|
|
1980
|
+
},
|
|
1981
|
+
"ref": "sales"
|
|
1982
|
+
}
|
|
1983
|
+
]
|
|
1984
|
+
},
|
|
1985
|
+
"filterGroup": {
|
|
1986
|
+
"filters": [
|
|
1987
|
+
{
|
|
1988
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
1989
|
+
"operator": "inList",
|
|
1990
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
1991
|
+
}
|
|
1992
|
+
],
|
|
1993
|
+
"operator": "and"
|
|
1994
|
+
},
|
|
1995
|
+
"type": "word-cloud",
|
|
1996
|
+
"version": 1
|
|
1997
|
+
}
|
|
1998
|
+
```
|
|
1999
|
+
|
|
2000
|
+
## `date-picker`: Date picker
|
|
2001
|
+
|
|
2002
|
+
Date selection control with single/range modes, labels, quick select, and responsive settings.
|
|
2003
|
+
|
|
2004
|
+
**Data requirements**
|
|
2005
|
+
|
|
2006
|
+
- Exactly one field.
|
|
2007
|
+
|
|
2008
|
+
**Supported features**
|
|
2009
|
+
|
|
2010
|
+
`dimensions`, `filter-settings`
|
|
2011
|
+
|
|
2012
|
+
**Constraints and semantics**
|
|
2013
|
+
|
|
2014
|
+
- The selected field must be date- or timestamp-compatible.
|
|
2015
|
+
|
|
2016
|
+
**Canonical example**
|
|
2017
|
+
|
|
2018
|
+
```json
|
|
2019
|
+
{
|
|
2020
|
+
"data": {
|
|
2021
|
+
"field": {
|
|
2022
|
+
"fieldKey": "[Cars].[Latest Launch]",
|
|
2023
|
+
"ref": "latestLaunch"
|
|
2024
|
+
}
|
|
2025
|
+
},
|
|
2026
|
+
"settings": {
|
|
2027
|
+
"endDateLabel": "To",
|
|
2028
|
+
"pickerState": "expanded",
|
|
2029
|
+
"pickerType": "range",
|
|
2030
|
+
"quickSelect": true,
|
|
2031
|
+
"responsive": true,
|
|
2032
|
+
"startDateLabel": "From",
|
|
2033
|
+
"timePickerVisibility": "never",
|
|
2034
|
+
"weekStart": "1"
|
|
2035
|
+
},
|
|
2036
|
+
"type": "date-picker",
|
|
2037
|
+
"version": 1
|
|
2038
|
+
}
|
|
2039
|
+
```
|
|
2040
|
+
|
|
2041
|
+
## `filter`: Filter
|
|
2042
|
+
|
|
2043
|
+
Interactive field filter with list/dropdown presentation and search/quick-select controls.
|
|
2044
|
+
|
|
2045
|
+
**Data requirements**
|
|
2046
|
+
|
|
2047
|
+
- Exactly one field.
|
|
2048
|
+
|
|
2049
|
+
**Supported features**
|
|
2050
|
+
|
|
2051
|
+
`dimensions`, `filter-settings`
|
|
2052
|
+
|
|
2053
|
+
**Constraints and semantics**
|
|
2054
|
+
|
|
2055
|
+
- The selected field is used as a filter dimension.
|
|
2056
|
+
|
|
2057
|
+
**Canonical example**
|
|
2058
|
+
|
|
2059
|
+
```json
|
|
2060
|
+
{
|
|
2061
|
+
"data": {
|
|
2062
|
+
"field": {
|
|
2063
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
2064
|
+
"ref": "manufacturer"
|
|
2065
|
+
}
|
|
2066
|
+
},
|
|
2067
|
+
"presentation": {
|
|
2068
|
+
"mode": "listbox",
|
|
2069
|
+
"quickSelect": true,
|
|
2070
|
+
"responsive": true,
|
|
2071
|
+
"searchable": true,
|
|
2072
|
+
"showProgressBar": false
|
|
2073
|
+
},
|
|
2074
|
+
"type": "filter",
|
|
2075
|
+
"version": 1
|
|
2076
|
+
}
|
|
2077
|
+
```
|
|
2078
|
+
|
|
2079
|
+
## `iframe`: Iframe
|
|
2080
|
+
|
|
2081
|
+
Embedded external web content.
|
|
2082
|
+
|
|
2083
|
+
**Data requirements**
|
|
2084
|
+
|
|
2085
|
+
- No query data.
|
|
2086
|
+
|
|
2087
|
+
**Supported features**
|
|
2088
|
+
|
|
2089
|
+
`content`
|
|
2090
|
+
|
|
2091
|
+
**Constraints and semantics**
|
|
2092
|
+
|
|
2093
|
+
- The URL must be absolute and valid; null clears the source.
|
|
2094
|
+
|
|
2095
|
+
**Canonical example**
|
|
2096
|
+
|
|
2097
|
+
```json
|
|
2098
|
+
{
|
|
2099
|
+
"settings": {
|
|
2100
|
+
"url": "https://example.com"
|
|
2101
|
+
},
|
|
2102
|
+
"type": "iframe",
|
|
2103
|
+
"version": 1
|
|
2104
|
+
}
|
|
2105
|
+
```
|
|
2106
|
+
|
|
2107
|
+
## `image`: Image
|
|
2108
|
+
|
|
2109
|
+
Image content with fit, opacity, blur, saturation, and shadow controls.
|
|
2110
|
+
|
|
2111
|
+
**Data requirements**
|
|
2112
|
+
|
|
2113
|
+
- No query data.
|
|
2114
|
+
|
|
2115
|
+
**Supported features**
|
|
2116
|
+
|
|
2117
|
+
`content`, `object-settings`
|
|
2118
|
+
|
|
2119
|
+
**Constraints and semantics**
|
|
2120
|
+
|
|
2121
|
+
- The source must use one of the supported image source variants.
|
|
2122
|
+
|
|
2123
|
+
**Canonical example**
|
|
2124
|
+
|
|
2125
|
+
```json
|
|
2126
|
+
{
|
|
2127
|
+
"settings": {
|
|
2128
|
+
"blur": 0,
|
|
2129
|
+
"fit": "contain",
|
|
2130
|
+
"opacity": 0.95,
|
|
2131
|
+
"saturation": 0.9,
|
|
2132
|
+
"shadow": true,
|
|
2133
|
+
"source": {
|
|
2134
|
+
"imageUrl": "https://example.com/image.png",
|
|
2135
|
+
"sourceKind": "url"
|
|
2136
|
+
}
|
|
2137
|
+
},
|
|
2138
|
+
"type": "image",
|
|
2139
|
+
"version": 1
|
|
2140
|
+
}
|
|
2141
|
+
```
|
|
2142
|
+
|
|
2143
|
+
## `number`: Number
|
|
2144
|
+
|
|
2145
|
+
Single aggregated or semantic value with value formatting and static filters.
|
|
2146
|
+
|
|
2147
|
+
**Data requirements**
|
|
2148
|
+
|
|
2149
|
+
- Exactly one measure.
|
|
2150
|
+
|
|
2151
|
+
**Supported features**
|
|
2152
|
+
|
|
2153
|
+
`filters`, `measures`, `value-formatting`
|
|
2154
|
+
|
|
2155
|
+
**Constraints and semantics**
|
|
2156
|
+
|
|
2157
|
+
- A raw field measure requires aggregation; semantic measures and calculations omit it.
|
|
2158
|
+
|
|
2159
|
+
**Canonical example**
|
|
2160
|
+
|
|
2161
|
+
```json
|
|
2162
|
+
{
|
|
2163
|
+
"data": {
|
|
2164
|
+
"measure": {
|
|
2165
|
+
"aggregation": "SUM",
|
|
2166
|
+
"fieldKey": "[Cars].[Sales In Thousands]",
|
|
2167
|
+
"format": {
|
|
2168
|
+
"formatType": "number2Decimal",
|
|
2169
|
+
"negativeType": "parenthesis"
|
|
2170
|
+
},
|
|
2171
|
+
"ref": "sales"
|
|
2172
|
+
}
|
|
2173
|
+
},
|
|
2174
|
+
"filterGroup": {
|
|
2175
|
+
"filters": [
|
|
2176
|
+
{
|
|
2177
|
+
"fieldKey": "[Cars].[Manufacturer]",
|
|
2178
|
+
"operator": "inList",
|
|
2179
|
+
"values": ["Acura", "Audi", "BMW"]
|
|
2180
|
+
}
|
|
2181
|
+
],
|
|
2182
|
+
"operator": "and"
|
|
2183
|
+
},
|
|
2184
|
+
"type": "number",
|
|
2185
|
+
"version": 1
|
|
2186
|
+
}
|
|
2187
|
+
```
|
|
2188
|
+
|
|
2189
|
+
## `shape`: Shape
|
|
2190
|
+
|
|
2191
|
+
Decorative shape with fill, stroke, sizing, rotation, and border controls.
|
|
2192
|
+
|
|
2193
|
+
**Data requirements**
|
|
2194
|
+
|
|
2195
|
+
- No query data.
|
|
2196
|
+
|
|
2197
|
+
**Supported features**
|
|
2198
|
+
|
|
2199
|
+
`object-settings`
|
|
2200
|
+
|
|
2201
|
+
**Constraints and semantics**
|
|
2202
|
+
|
|
2203
|
+
- Image-specific settings apply only when the selected shape/background mode supports them.
|
|
2204
|
+
|
|
2205
|
+
**Canonical example**
|
|
2206
|
+
|
|
2207
|
+
```json
|
|
2208
|
+
{
|
|
2209
|
+
"settings": {
|
|
2210
|
+
"backgroundColor": {
|
|
2211
|
+
"code": "#2e6e9e"
|
|
2212
|
+
},
|
|
2213
|
+
"backgroundType": "color",
|
|
2214
|
+
"borderEnabled": true,
|
|
2215
|
+
"borderRadius": 8,
|
|
2216
|
+
"heightBasedSize": false,
|
|
2217
|
+
"lineThickness": 4,
|
|
2218
|
+
"preserveAspectRatio": true,
|
|
2219
|
+
"rotate": 12,
|
|
2220
|
+
"scale": 0.7,
|
|
2221
|
+
"shape": "hexagon",
|
|
2222
|
+
"strokeColor": {
|
|
2223
|
+
"code": "#18212b"
|
|
2224
|
+
}
|
|
2225
|
+
},
|
|
2226
|
+
"type": "shape",
|
|
2227
|
+
"version": 1
|
|
2228
|
+
}
|
|
2229
|
+
```
|
|
2230
|
+
|
|
2231
|
+
## `simpleTextObject`: Text object
|
|
2232
|
+
|
|
2233
|
+
Text or Markdown content with typography, alignment, wrapping, and responsive controls.
|
|
2234
|
+
|
|
2235
|
+
**Data requirements**
|
|
2236
|
+
|
|
2237
|
+
- No query data.
|
|
2238
|
+
|
|
2239
|
+
**Supported features**
|
|
2240
|
+
|
|
2241
|
+
`content`, `object-settings`
|
|
2242
|
+
|
|
2243
|
+
**Constraints and semantics**
|
|
2244
|
+
|
|
2245
|
+
- Content interpretation follows the selected representation.
|
|
2246
|
+
|
|
2247
|
+
**Canonical example**
|
|
2248
|
+
|
|
2249
|
+
```json
|
|
2250
|
+
{
|
|
2251
|
+
"settings": {
|
|
2252
|
+
"align": "center",
|
|
2253
|
+
"content": "## Revenue overview",
|
|
2254
|
+
"fontFamily": "Arial",
|
|
2255
|
+
"fontSize": 30,
|
|
2256
|
+
"position": "middle",
|
|
2257
|
+
"representation": "markdown",
|
|
2258
|
+
"responsive": true,
|
|
2259
|
+
"textColor": "#18212b",
|
|
2260
|
+
"wordWrap": true
|
|
2261
|
+
},
|
|
2262
|
+
"type": "simpleTextObject",
|
|
2263
|
+
"version": 1
|
|
2264
|
+
}
|
|
2265
|
+
```
|
|
2266
|
+
|
|
2267
|
+
## `atomic-input`: Atomic input
|
|
2268
|
+
|
|
2269
|
+
Variable input control with input type, label, placeholder, and responsive settings.
|
|
2270
|
+
|
|
2271
|
+
**Data requirements**
|
|
2272
|
+
|
|
2273
|
+
- No query data; variable-backed input.
|
|
2274
|
+
|
|
2275
|
+
**Supported features**
|
|
2276
|
+
|
|
2277
|
+
`input-settings`
|
|
2278
|
+
|
|
2279
|
+
**Constraints and semantics**
|
|
2280
|
+
|
|
2281
|
+
- The referenced variable must exist in the host variable service when variable behavior is used.
|
|
2282
|
+
|
|
2283
|
+
**Canonical example**
|
|
2284
|
+
|
|
2285
|
+
```json
|
|
2286
|
+
{
|
|
2287
|
+
"settings": {
|
|
2288
|
+
"customLabel": {
|
|
2289
|
+
"enabled": true,
|
|
2290
|
+
"text": "Target"
|
|
2291
|
+
},
|
|
2292
|
+
"inputType": "text",
|
|
2293
|
+
"placeholder": "Enter target",
|
|
2294
|
+
"responsive": true,
|
|
2295
|
+
"variableId": "target-variable"
|
|
2296
|
+
},
|
|
2297
|
+
"type": "atomic-input",
|
|
2298
|
+
"version": 1
|
|
2299
|
+
}
|
|
2300
|
+
```
|
|
2301
|
+
|
|
2302
|
+
## `astrato-app-filter-bar`: Astrato App Filter Bar
|
|
2303
|
+
|
|
2304
|
+
App filter bar settings for selection behavior, filter creation, associative filtering, and selectable fields.
|
|
2305
|
+
|
|
2306
|
+
**Data requirements**
|
|
2307
|
+
|
|
2308
|
+
- No query data; uses field metadata and selections supplied by the host.
|
|
2309
|
+
|
|
2310
|
+
**Supported features**
|
|
2311
|
+
|
|
2312
|
+
`selection-settings`
|
|
2313
|
+
|
|
2314
|
+
**Constraints and semantics**
|
|
2315
|
+
|
|
2316
|
+
- Orientation defaults to horizontal. Use vertical for stacked sidebar filters; editors open beside the sidebar when space permits.
|
|
2317
|
+
- The bar displays active selections from its selection group, regardless of the fields allowed for creating new filters.
|
|
2318
|
+
- An empty selectableFieldKeys list allows users to create filters on any selectable field.
|
|
2319
|
+
- Selection mode overrides apply only to selections created by this bar; apply, cancel, and clear affect the shared selection group.
|
|
2320
|
+
- Chart breakdown switching is hidden by default. Enable showChartBreakdown only when the app uses dimension groups; a group must have multiple available fields for the control to appear.
|
|
2321
|
+
|
|
2322
|
+
**Canonical example**
|
|
2323
|
+
|
|
2324
|
+
```json
|
|
2325
|
+
{
|
|
2326
|
+
"settings": {
|
|
2327
|
+
"enableAddingNewFilters": true,
|
|
2328
|
+
"enableAssociativeFilter": true,
|
|
2329
|
+
"selectableFieldKeys": ["[Cars].[Manufacturer]", "[Cars].[Model]"],
|
|
2330
|
+
"selectionMode": "inherit",
|
|
2331
|
+
"showChartBreakdown": false,
|
|
2332
|
+
"showClearAll": true
|
|
2333
|
+
},
|
|
2334
|
+
"type": "astrato-app-filter-bar",
|
|
2335
|
+
"version": 1
|
|
2336
|
+
}
|
|
2337
|
+
```
|
|
2338
|
+
|
|
2339
|
+
## `slider`: Slider
|
|
2340
|
+
|
|
2341
|
+
Numeric or date range control with single/multi layout, step, and quick select.
|
|
2342
|
+
|
|
2343
|
+
**Data requirements**
|
|
2344
|
+
|
|
2345
|
+
- Exactly one field.
|
|
2346
|
+
|
|
2347
|
+
**Supported features**
|
|
2348
|
+
|
|
2349
|
+
`dimensions`, `filter-settings`
|
|
2350
|
+
|
|
2351
|
+
**Constraints and semantics**
|
|
2352
|
+
|
|
2353
|
+
- The field must be numeric or date-compatible with the configured range and step.
|
|
2354
|
+
- Providing range enables manual bounds; omitting it keeps data-derived bounds.
|
|
2355
|
+
|
|
2356
|
+
**Canonical example**
|
|
2357
|
+
|
|
2358
|
+
```json
|
|
2359
|
+
{
|
|
2360
|
+
"data": {
|
|
2361
|
+
"field": {
|
|
2362
|
+
"fieldKey": "[Cars].[Horsepower]",
|
|
2363
|
+
"ref": "horsepower"
|
|
2364
|
+
}
|
|
2365
|
+
},
|
|
2366
|
+
"settings": {
|
|
2367
|
+
"layout": "multi",
|
|
2368
|
+
"quickSelect": true,
|
|
2369
|
+
"range": {
|
|
2370
|
+
"max": 500,
|
|
2371
|
+
"min": 0
|
|
2372
|
+
},
|
|
2373
|
+
"step": 10
|
|
2374
|
+
},
|
|
2375
|
+
"type": "slider",
|
|
2376
|
+
"version": 1
|
|
2377
|
+
}
|
|
2378
|
+
```
|