@eeacms/volto-tableau 8.1.1 → 8.1.2
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 +8 -0
- package/jest.setup.js +11 -0
- package/package.json +1 -1
- package/src/Blocks/EmbedTableauVisualization/schema.js +2 -2
- package/src/Tableau/Tableau.jsx +79 -41
- package/src/Tableau/helpers.js +4 -2
- package/src/Views/VisualizationView.test.jsx +37 -0
- package/src/Widgets/VisualizationWidget.jsx +47 -12
- package/src/Widgets/schema.js +23 -34
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
### [8.1.2](https://github.com/eea/volto-tableau/compare/8.1.1...8.1.2) - 14 November 2024
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- add test [Miu Razvan - [`862b32c`](https://github.com/eea/volto-tableau/commit/862b32c6d2760cc2169eef9f900491e6afb9a00a)]
|
|
12
|
+
- add VisualizationView test [Miu Razvan - [`b4bea0a`](https://github.com/eea/volto-tableau/commit/b4bea0a6fc9814927b0b471ceebf4a9d4bfc50f2)]
|
|
13
|
+
- Disable tableau editor actions while loading the tableau [Miu Razvan - [`9f33c3c`](https://github.com/eea/volto-tableau/commit/9f33c3c2c3bcb0a3e36ba21e40cbb86f2dfc6150)]
|
|
14
|
+
- Extract parameters from tableau url, ref #279989 [Miu Razvan - [`f3c00d1`](https://github.com/eea/volto-tableau/commit/f3c00d124bd9417f44d9e9a6b054687de0859bbd)]
|
|
7
15
|
### [8.1.1](https://github.com/eea/volto-tableau/compare/8.1.0...8.1.1) - 11 October 2024
|
|
8
16
|
|
|
9
17
|
#### :bug: Bug Fixes
|
package/jest.setup.js
CHANGED
|
@@ -23,6 +23,17 @@ global.store = mockStore({
|
|
|
23
23
|
const mockReactRouter = jest.requireActual('react-router');
|
|
24
24
|
const mockSemanticComponents = jest.requireActual('semantic-ui-react');
|
|
25
25
|
const mockComponents = jest.requireActual('@plone/volto/components');
|
|
26
|
+
const config = jest.requireActual('@plone/volto/registry').default;
|
|
27
|
+
|
|
28
|
+
config.blocks.blocksConfig = {
|
|
29
|
+
embed_tableau_visualization: {
|
|
30
|
+
breakpoints: {
|
|
31
|
+
desktop: [Infinity, 992],
|
|
32
|
+
tablet: [991, 768],
|
|
33
|
+
phone: [767, 0],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
26
37
|
|
|
27
38
|
jest.mock('react-router', () => {
|
|
28
39
|
return {
|
package/package.json
CHANGED
|
@@ -69,7 +69,7 @@ const staticParameters = {
|
|
|
69
69
|
required: [],
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
const
|
|
72
|
+
const getSchema = (props) => {
|
|
73
73
|
return {
|
|
74
74
|
title: 'Embed Dashboard (Tableau)',
|
|
75
75
|
fieldsets: [
|
|
@@ -182,4 +182,4 @@ const schema = (props) => {
|
|
|
182
182
|
};
|
|
183
183
|
};
|
|
184
184
|
|
|
185
|
-
export default
|
|
185
|
+
export default getSchema;
|
package/src/Tableau/Tableau.jsx
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
toInteger,
|
|
26
26
|
toNumber,
|
|
27
27
|
} from 'lodash';
|
|
28
|
+
import qs from 'qs';
|
|
28
29
|
import cx from 'classnames';
|
|
29
30
|
import { Button } from 'semantic-ui-react';
|
|
30
31
|
import { Toast, Icon } from '@plone/volto/components';
|
|
@@ -44,6 +45,12 @@ import resetSVG from '@plone/volto/icons/reset.svg';
|
|
|
44
45
|
|
|
45
46
|
import '@eeacms/volto-embed/Toolbar/styles.less';
|
|
46
47
|
|
|
48
|
+
function decodeString(str) {
|
|
49
|
+
const tempDiv = document.createElement('div');
|
|
50
|
+
tempDiv.innerHTML = str;
|
|
51
|
+
return tempDiv.textContent || tempDiv.innerText || '';
|
|
52
|
+
}
|
|
53
|
+
|
|
47
54
|
function getHeight(height) {
|
|
48
55
|
const asNumber = isNumber(Number(height)) && !isNaN(Number(height));
|
|
49
56
|
if (asNumber) {
|
|
@@ -52,6 +59,22 @@ function getHeight(height) {
|
|
|
52
59
|
return height;
|
|
53
60
|
}
|
|
54
61
|
|
|
62
|
+
function getTableauValue(value, dataType) {
|
|
63
|
+
if (dataType === 'string' && !isString(value)) {
|
|
64
|
+
return toString(value);
|
|
65
|
+
}
|
|
66
|
+
if (dataType === 'integer' && !isInteger(value)) {
|
|
67
|
+
return toInteger(value);
|
|
68
|
+
}
|
|
69
|
+
if (dataType === 'float' && !isNumber(value)) {
|
|
70
|
+
return toNumber(value);
|
|
71
|
+
}
|
|
72
|
+
if (dataType === 'boolean' && !isBoolean(value)) {
|
|
73
|
+
return !!value;
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
|
|
55
78
|
const TableauDebug = ({ mode, data, vizState, url, version, clearData }) => {
|
|
56
79
|
const { loaded, error } = vizState;
|
|
57
80
|
const { filters = {}, parameters = {} } = data;
|
|
@@ -136,6 +159,7 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
136
159
|
with_enlarge = true,
|
|
137
160
|
tableau_height,
|
|
138
161
|
} = data;
|
|
162
|
+
|
|
139
163
|
const device = useMemo(
|
|
140
164
|
() => getDevice(breakpoints, screen.page?.width || Infinity),
|
|
141
165
|
[breakpoints, screen],
|
|
@@ -214,46 +238,45 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
214
238
|
}
|
|
215
239
|
};
|
|
216
240
|
|
|
217
|
-
const onVizStateUpdate = useCallback(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
setVizState
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
241
|
+
const onVizStateUpdate = useCallback(
|
|
242
|
+
(loaded, loading, error) => {
|
|
243
|
+
vizState.current = { ...vizState.current, loaded, loading, error };
|
|
244
|
+
setLoaded(loaded);
|
|
245
|
+
setLoading(loading);
|
|
246
|
+
setError(error);
|
|
247
|
+
if (setVizState) {
|
|
248
|
+
setVizState({ loaded, loading, error });
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
[setVizState],
|
|
252
|
+
);
|
|
227
253
|
|
|
228
|
-
const activateDefaultSheet = useCallback(() => {
|
|
229
|
-
if (!vizState.current.loaded || !viz.current) return;
|
|
254
|
+
const activateDefaultSheet = useCallback(async () => {
|
|
255
|
+
if (!vizState.current.loaded || !viz.current) return Promise.resolve();
|
|
230
256
|
const workbook = viz.current.getWorkbook();
|
|
231
257
|
const sheetnames = getSheetnames(viz.current);
|
|
232
258
|
const activeSheetName = getActiveSheetname(viz.current);
|
|
233
259
|
if (sheetnames.includes(sheetname) && sheetname !== activeSheetName) {
|
|
234
|
-
workbook.activateSheetAsync(sheetname)
|
|
235
|
-
onVizStateUpdate(true, false, null);
|
|
236
|
-
});
|
|
237
|
-
} else {
|
|
238
|
-
onVizStateUpdate(true, false, null);
|
|
260
|
+
return workbook.activateSheetAsync(sheetname);
|
|
239
261
|
}
|
|
240
|
-
|
|
262
|
+
return Promise.resolve();
|
|
263
|
+
}, [sheetname]);
|
|
241
264
|
|
|
242
|
-
const clearData = () => {
|
|
265
|
+
const clearData = useCallback(() => {
|
|
243
266
|
onChangeBlock(block, {
|
|
244
267
|
...data,
|
|
245
268
|
filters: {},
|
|
246
269
|
parameters: {},
|
|
247
270
|
});
|
|
248
|
-
};
|
|
271
|
+
}, [onChangeBlock, block, data]);
|
|
249
272
|
|
|
250
|
-
const disposeViz = () => {
|
|
273
|
+
const disposeViz = useCallback(() => {
|
|
251
274
|
if (viz.current) {
|
|
252
275
|
viz.current.dispose();
|
|
253
276
|
viz.current = null;
|
|
254
277
|
}
|
|
255
278
|
onVizStateUpdate(false, false, null);
|
|
256
|
-
};
|
|
279
|
+
}, [onVizStateUpdate]);
|
|
257
280
|
|
|
258
281
|
const initViz = () => {
|
|
259
282
|
try {
|
|
@@ -265,12 +288,12 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
265
288
|
device: !!breakpointUrl ? device : 'desktop',
|
|
266
289
|
...extraOptions,
|
|
267
290
|
...data.filters,
|
|
291
|
+
...data.parameters,
|
|
268
292
|
...extraFilters,
|
|
269
293
|
...extraParameters,
|
|
270
|
-
onFirstInteractive: () => {
|
|
294
|
+
onFirstInteractive: async () => {
|
|
271
295
|
onVizStateUpdate(true, true, null);
|
|
272
|
-
|
|
273
|
-
activateDefaultSheet();
|
|
296
|
+
await activateDefaultSheet();
|
|
274
297
|
if (viz.current && mode === 'edit' && !breakpointUrl) {
|
|
275
298
|
const sheetnames = getSheetnames(viz.current);
|
|
276
299
|
const activeSheetname = getActiveSheetname(viz.current);
|
|
@@ -282,6 +305,24 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
282
305
|
if (!sheetname || !sheetnames.includes(sheetname)) {
|
|
283
306
|
newData.sheetname = activeSheetname;
|
|
284
307
|
}
|
|
308
|
+
if (newData.url !== url) {
|
|
309
|
+
// Get parameters from url
|
|
310
|
+
const workbook = viz.current.getWorkbook();
|
|
311
|
+
const tableauParameters = await workbook.getParametersAsync();
|
|
312
|
+
const searchParams = qs.parse(decodeString(new URL(url).search));
|
|
313
|
+
tableauParameters.forEach((param) => {
|
|
314
|
+
const name = param.getName();
|
|
315
|
+
const dataType = param.getDataType();
|
|
316
|
+
if (!searchParams[name]) return;
|
|
317
|
+
if (!newData.parameters) {
|
|
318
|
+
newData.parameters = {};
|
|
319
|
+
}
|
|
320
|
+
newData.parameters[name] = getTableauValue(
|
|
321
|
+
searchParams[name],
|
|
322
|
+
dataType,
|
|
323
|
+
);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
285
326
|
if (newData.url !== url || newData.sheetname !== sheetname) {
|
|
286
327
|
onChangeBlock(block, {
|
|
287
328
|
...data,
|
|
@@ -312,6 +353,8 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
312
353
|
},
|
|
313
354
|
);
|
|
314
355
|
}
|
|
356
|
+
onVizStateUpdate(true, false, null);
|
|
357
|
+
setInitiateViz(false);
|
|
315
358
|
},
|
|
316
359
|
});
|
|
317
360
|
} catch (e) {
|
|
@@ -346,9 +389,9 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
346
389
|
} else {
|
|
347
390
|
disposeViz();
|
|
348
391
|
}
|
|
349
|
-
|
|
350
|
-
}, [tableau, url, hideTabs, hideToolbar, toolbarPosition]);
|
|
392
|
+
}, [tableau, url, disposeViz, hideTabs, hideToolbar, toolbarPosition]);
|
|
351
393
|
|
|
394
|
+
// Initialize viz
|
|
352
395
|
useEffect(() => {
|
|
353
396
|
if (initiateViz && !loaded && !loading) {
|
|
354
397
|
initViz();
|
|
@@ -396,6 +439,7 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
396
439
|
// /* eslint-disable-next-line */
|
|
397
440
|
// }, [loaded, JSON.stringify(extraFilters)]);
|
|
398
441
|
|
|
442
|
+
// Add extra parameters
|
|
399
443
|
useEffect(() => {
|
|
400
444
|
async function addExtraParameters() {
|
|
401
445
|
if (vizState.current.loaded && viz.current) {
|
|
@@ -419,19 +463,7 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
419
463
|
value = value
|
|
420
464
|
.filter((v) => includes(values, v))
|
|
421
465
|
.map((v) => {
|
|
422
|
-
|
|
423
|
-
return toString(v);
|
|
424
|
-
}
|
|
425
|
-
if (dataType === 'integer' && !isInteger(v)) {
|
|
426
|
-
return toInteger(v);
|
|
427
|
-
}
|
|
428
|
-
if (dataType === 'float' && !isNumber(v)) {
|
|
429
|
-
return toNumber(v);
|
|
430
|
-
}
|
|
431
|
-
if (dataType === 'boolean' && !isBoolean(v)) {
|
|
432
|
-
return !!v;
|
|
433
|
-
}
|
|
434
|
-
return v;
|
|
466
|
+
return getTableauValue(v, dataType);
|
|
435
467
|
});
|
|
436
468
|
if (value?.length) {
|
|
437
469
|
workbook.changeParameterValueAsync(fieldName, value);
|
|
@@ -450,6 +482,7 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
450
482
|
/* eslint-disable-next-line */
|
|
451
483
|
}, [loaded, JSON.stringify(extraParameters)]);
|
|
452
484
|
|
|
485
|
+
// Update viz scale on window resize
|
|
453
486
|
useEffect(() => {
|
|
454
487
|
if (vizState.current.loaded && viz.current && autoScale) {
|
|
455
488
|
updateScale();
|
|
@@ -457,14 +490,18 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
457
490
|
/* eslint-disable-next-line */
|
|
458
491
|
}, [loaded, screen?.page?.width]);
|
|
459
492
|
|
|
493
|
+
// Activate default sheet
|
|
460
494
|
useEffect(() => {
|
|
461
495
|
if (vizState.current.loaded && viz.current) {
|
|
462
496
|
onVizStateUpdate(true, true, null);
|
|
463
|
-
activateDefaultSheet()
|
|
497
|
+
activateDefaultSheet().then(() => {
|
|
498
|
+
onVizStateUpdate(true, false, null);
|
|
499
|
+
});
|
|
464
500
|
}
|
|
465
501
|
/* eslint-disable-next-line */
|
|
466
502
|
}, [sheetname]);
|
|
467
503
|
|
|
504
|
+
// Set mobile mode
|
|
468
505
|
useEffect(() => {
|
|
469
506
|
if (!loading && tableauEl.current) {
|
|
470
507
|
const visWidth = tableauEl.current.offsetWidth;
|
|
@@ -477,6 +514,7 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
477
514
|
}
|
|
478
515
|
}, [screen, mobile, loading]);
|
|
479
516
|
|
|
517
|
+
// Keep viz reference
|
|
480
518
|
useImperativeHandle(
|
|
481
519
|
ref,
|
|
482
520
|
() => {
|
package/src/Tableau/helpers.js
CHANGED
|
@@ -151,8 +151,10 @@ export const getActiveSheetname = (viz) => {
|
|
|
151
151
|
export const canChangeVizData = (viz, vizState) => {
|
|
152
152
|
// If viz is null it means that the viz is loading
|
|
153
153
|
// If viz is undefined it means that there is no viz nor it is loading
|
|
154
|
-
if (vizState?.loading)
|
|
155
|
-
|
|
154
|
+
if (vizState?.loading || !viz || isUndefined(viz)) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
156
158
|
};
|
|
157
159
|
|
|
158
160
|
export const getDevice = (breakpoints, width) => {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
4
|
+
import { Provider } from 'react-redux';
|
|
5
|
+
|
|
6
|
+
import VisualizationView from './VisualizationView';
|
|
7
|
+
|
|
8
|
+
jest.doMock('@plone/volto/registry', {
|
|
9
|
+
blocks: {
|
|
10
|
+
blocksConfig: {
|
|
11
|
+
embed_tableau_visualization: {
|
|
12
|
+
breakpoints: {
|
|
13
|
+
desktop: [Infinity, 992],
|
|
14
|
+
tablet: [991, 768],
|
|
15
|
+
phone: [767, 0],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('VisualizationViewWidget', () => {
|
|
23
|
+
it('should render the component', () => {
|
|
24
|
+
const { container } = render(
|
|
25
|
+
<Provider store={{ ...global.store }}>
|
|
26
|
+
<VisualizationView
|
|
27
|
+
content={{
|
|
28
|
+
tableau_visualization: {
|
|
29
|
+
url: 'http://localhost:3000/tableau-ct',
|
|
30
|
+
},
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
</Provider>,
|
|
34
|
+
);
|
|
35
|
+
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -35,6 +35,7 @@ const VisualizationWidget = (props) => {
|
|
|
35
35
|
const ogValue = props.value || {};
|
|
36
36
|
const inAddForm = props.location.pathname.split('/').pop() === 'add';
|
|
37
37
|
const viz = React.useRef();
|
|
38
|
+
const [tableauData, setTableauData] = React.useState({});
|
|
38
39
|
const [schema, setSchema] = React.useState(null);
|
|
39
40
|
const [vizState, setVizState] = React.useState({
|
|
40
41
|
loaded: false,
|
|
@@ -76,6 +77,33 @@ const VisualizationWidget = (props) => {
|
|
|
76
77
|
setOpen(false);
|
|
77
78
|
};
|
|
78
79
|
|
|
80
|
+
React.useEffect(() => {
|
|
81
|
+
if (!vizState.loaded || !viz.current || !!tableauData[value.url]) return;
|
|
82
|
+
|
|
83
|
+
async function _setTableauData() {
|
|
84
|
+
const workbook = await viz.current.getWorkbook();
|
|
85
|
+
const sheetNames = workbook.getPublishedSheetsInfo().map((sheet) => {
|
|
86
|
+
return sheet.getName();
|
|
87
|
+
});
|
|
88
|
+
const parameters = await workbook.getParametersAsync();
|
|
89
|
+
const filters = await workbook.getActiveSheet().getFiltersAsync();
|
|
90
|
+
setTableauData((tableauData) => ({
|
|
91
|
+
...tableauData,
|
|
92
|
+
[value.url]: {
|
|
93
|
+
sheetNames,
|
|
94
|
+
parameters,
|
|
95
|
+
filters,
|
|
96
|
+
},
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_setTableauData();
|
|
101
|
+
}, [vizState, tableauData, value.url]);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Synchronizes the local `value` state with the `props.value` prop when the component is not open and the values differ.
|
|
105
|
+
* This ensures that the component's internal state reflects the latest value from the parent component.
|
|
106
|
+
*/
|
|
79
107
|
React.useEffect(() => {
|
|
80
108
|
if (!open && !isEqual(props.value || {}, value)) {
|
|
81
109
|
setValue(props.value || {});
|
|
@@ -126,16 +154,17 @@ const VisualizationWidget = (props) => {
|
|
|
126
154
|
* Get schema
|
|
127
155
|
*/
|
|
128
156
|
React.useEffect(() => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
157
|
+
setSchema(
|
|
158
|
+
getSchema({
|
|
159
|
+
config,
|
|
160
|
+
viz: viz.current,
|
|
161
|
+
vizState,
|
|
162
|
+
data: value,
|
|
163
|
+
tableauData: tableauData[value.url],
|
|
164
|
+
intl: props.intl,
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
167
|
+
}, [vizState, value, tableauData, props.intl]);
|
|
139
168
|
|
|
140
169
|
React.useEffect(() => {
|
|
141
170
|
if (value && value.url && value.preview_url_loaded !== value.url) {
|
|
@@ -221,8 +250,14 @@ const VisualizationWidget = (props) => {
|
|
|
221
250
|
<Grid>
|
|
222
251
|
<Grid.Row>
|
|
223
252
|
<div className="map-edit-actions-container">
|
|
224
|
-
<Button onClick={handleClose}>
|
|
225
|
-
|
|
253
|
+
<Button disabled={vizState.loading} onClick={handleClose}>
|
|
254
|
+
Close
|
|
255
|
+
</Button>
|
|
256
|
+
<Button
|
|
257
|
+
disabled={vizState.loading}
|
|
258
|
+
color="green"
|
|
259
|
+
onClick={handleApplyChanges}
|
|
260
|
+
>
|
|
226
261
|
Apply changes
|
|
227
262
|
</Button>
|
|
228
263
|
</div>
|
package/src/Widgets/schema.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { defineMessages } from 'react-intl';
|
|
2
|
-
import { find, includes } from 'lodash';
|
|
3
|
-
import {
|
|
4
|
-
getSheetnamesChoices,
|
|
5
|
-
canChangeVizData,
|
|
6
|
-
} from '@eeacms/volto-tableau/Tableau/helpers';
|
|
2
|
+
import { find, includes, uniq } from 'lodash';
|
|
3
|
+
import { canChangeVizData } from '@eeacms/volto-tableau/Tableau/helpers';
|
|
7
4
|
|
|
8
5
|
const messages = defineMessages({
|
|
9
6
|
CSSHeight: {
|
|
@@ -16,9 +13,8 @@ const messages = defineMessages({
|
|
|
16
13
|
},
|
|
17
14
|
});
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
const tableauParameters =
|
|
21
|
-
vizState.loaded && viz ? await viz.getWorkbook().getParametersAsync() : [];
|
|
16
|
+
function getUrlParametersSchema({ data, tableauData }) {
|
|
17
|
+
const tableauParameters = tableauData?.parameters || [];
|
|
22
18
|
|
|
23
19
|
const currentFields = (data.urlParameters || [])
|
|
24
20
|
.map((p) => p.field)
|
|
@@ -51,11 +47,8 @@ async function getUrlParametersSchema({ viz, vizState, data }) {
|
|
|
51
47
|
};
|
|
52
48
|
}
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
const tableauParameters =
|
|
56
|
-
vizState.loaded && viz
|
|
57
|
-
? (await viz.getWorkbook?.().getParametersAsync?.()) || []
|
|
58
|
-
: [];
|
|
50
|
+
function getStaticParametersSchema({ data, tableauData }) {
|
|
51
|
+
const tableauParameters = tableauData?.parameters || [];
|
|
59
52
|
|
|
60
53
|
const currentFields = (data.staticParameters || [])
|
|
61
54
|
.map((p) => p.field)
|
|
@@ -86,11 +79,8 @@ async function getStaticParametersSchema({ viz, vizState, data }) {
|
|
|
86
79
|
};
|
|
87
80
|
}
|
|
88
81
|
|
|
89
|
-
|
|
90
|
-
const tableauFilters =
|
|
91
|
-
vizState.loaded && viz
|
|
92
|
-
? (await viz.getWorkbook?.().getActiveSheet?.().getFiltersAsync?.()) || []
|
|
93
|
-
: [];
|
|
82
|
+
function getDynamicFiltersSchema({ data, tableauData }) {
|
|
83
|
+
const tableauFilters = tableauData?.filters || [];
|
|
94
84
|
|
|
95
85
|
const currentFields = (data.staticFilters || [])
|
|
96
86
|
.map((p) => p.field)
|
|
@@ -123,11 +113,8 @@ async function getDynamicFiltersSchema({ viz, vizState, data }) {
|
|
|
123
113
|
};
|
|
124
114
|
}
|
|
125
115
|
|
|
126
|
-
|
|
127
|
-
const tableauFilters =
|
|
128
|
-
vizState.loaded && viz
|
|
129
|
-
? (await viz.getWorkbook?.().getActiveSheet?.().getFiltersAsync?.()) || []
|
|
130
|
-
: [];
|
|
116
|
+
function getStaticFiltersSchema({ data, tableauData }) {
|
|
117
|
+
const tableauFilters = tableauData?.filters || [];
|
|
131
118
|
|
|
132
119
|
const currentFields = (data.staticFilters || [])
|
|
133
120
|
.map((p) => p.field)
|
|
@@ -142,11 +129,13 @@ async function getStaticFiltersSchema({ viz, vizState, data }) {
|
|
|
142
129
|
widget: 'creatable_select',
|
|
143
130
|
isMulti: false,
|
|
144
131
|
creatable: true,
|
|
145
|
-
choices:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
132
|
+
choices: uniq(
|
|
133
|
+
tableauFilters
|
|
134
|
+
.filter((f) => {
|
|
135
|
+
return !includes(currentFields, f.getFieldName());
|
|
136
|
+
})
|
|
137
|
+
.map((f) => f.getFieldName()),
|
|
138
|
+
).map((f) => [f, f]),
|
|
150
139
|
},
|
|
151
140
|
value: {
|
|
152
141
|
title: 'Value',
|
|
@@ -182,7 +171,7 @@ const breakpointUrlSchema = (config) => {
|
|
|
182
171
|
};
|
|
183
172
|
};
|
|
184
173
|
|
|
185
|
-
const schema =
|
|
174
|
+
const schema = ({ config, viz, vizState, data, tableauData, intl }) => {
|
|
186
175
|
const isDisabled = !canChangeVizData(viz, vizState);
|
|
187
176
|
|
|
188
177
|
return {
|
|
@@ -224,7 +213,7 @@ const schema = async ({ config, viz, vizState, data, intl }) => {
|
|
|
224
213
|
},
|
|
225
214
|
sheetname: {
|
|
226
215
|
title: 'Sheetname',
|
|
227
|
-
choices:
|
|
216
|
+
choices: tableauData?.sheetNames?.map((sheet) => [sheet, sheet]) || [],
|
|
228
217
|
isDisabled,
|
|
229
218
|
},
|
|
230
219
|
hideTabs: {
|
|
@@ -267,7 +256,7 @@ const schema = async ({ config, viz, vizState, data, intl }) => {
|
|
|
267
256
|
urlParameters: {
|
|
268
257
|
title: 'Dynamic parameters',
|
|
269
258
|
widget: 'object_list',
|
|
270
|
-
schema:
|
|
259
|
+
schema: getUrlParametersSchema({ data, tableauData }),
|
|
271
260
|
description: (
|
|
272
261
|
<div style={{ color: 'rgb(15, 130, 204)', fontWeight: '400' }}>
|
|
273
262
|
<p>Set a list of dynamic parameters that can be used as:</p>
|
|
@@ -313,7 +302,7 @@ const schema = async ({ config, viz, vizState, data, intl }) => {
|
|
|
313
302
|
staticParameters: {
|
|
314
303
|
title: 'Static parameters',
|
|
315
304
|
widget: 'object_list',
|
|
316
|
-
schema:
|
|
305
|
+
schema: getStaticParametersSchema({ data, tableauData }),
|
|
317
306
|
schemaExtender: (schema, data) => {
|
|
318
307
|
const tableauParameter = find(
|
|
319
308
|
schema.tableauParameters,
|
|
@@ -360,7 +349,7 @@ const schema = async ({ config, viz, vizState, data, intl }) => {
|
|
|
360
349
|
dynamicFilters: {
|
|
361
350
|
title: 'Dynamic filters',
|
|
362
351
|
widget: 'object_list',
|
|
363
|
-
schema:
|
|
352
|
+
schema: getDynamicFiltersSchema({ data, tableauData }),
|
|
364
353
|
description: (
|
|
365
354
|
<div style={{ color: 'rgb(15, 130, 204)', fontWeight: '400' }}>
|
|
366
355
|
<p>Set a list of dynamic filters that can be used as:</p>
|
|
@@ -406,7 +395,7 @@ const schema = async ({ config, viz, vizState, data, intl }) => {
|
|
|
406
395
|
staticFilters: {
|
|
407
396
|
title: 'Static filters',
|
|
408
397
|
widget: 'object_list',
|
|
409
|
-
schema:
|
|
398
|
+
schema: getStaticFiltersSchema({ data, tableauData }),
|
|
410
399
|
schemaExtender: (schema, data) => {
|
|
411
400
|
const tableauFilters = find(
|
|
412
401
|
schema.tableauFilters,
|