@eeacms/volto-tableau 8.1.0 → 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 CHANGED
@@ -4,7 +4,21 @@ 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.0](https://github.com/eea/volto-tableau/compare/8.0.7...8.1.0) - 11 September 2024
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)]
15
+ ### [8.1.1](https://github.com/eea/volto-tableau/compare/8.1.0...8.1.1) - 11 October 2024
16
+
17
+ #### :bug: Bug Fixes
18
+
19
+ - fix: Increase wait time EEA Screenshooter when saving preview image - refs #277935 [dobri1408 - [`f9e5d01`](https://github.com/eea/volto-tableau/commit/f9e5d01033fd011c1b411b2cb3e271dfc140f19b)]
20
+
21
+ ### [8.1.0](https://github.com/eea/volto-tableau/compare/8.0.7...8.1.0) - 13 September 2024
8
22
 
9
23
  #### :hammer_and_wrench: Others
10
24
 
@@ -51,6 +65,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
51
65
 
52
66
  #### :hammer_and_wrench: Others
53
67
 
68
+ - Add Sonarqube tag using insitu-frontend addons list [EEA Jenkins - [`22eeee9`](https://github.com/eea/volto-tableau/commit/22eeee93cfa8516261bb037a4bffef654af7a179)]
54
69
  - Revert "Add fullwidth property" [Miu Razvan - [`ea36e3c`](https://github.com/eea/volto-tableau/commit/ea36e3c4be0ff20999a5ea7ced69cc77f287ced5)]
55
70
  - Add fullwidth property [Miu Razvan - [`8d21ed0`](https://github.com/eea/volto-tableau/commit/8d21ed0b219f94d18998155a77acf2a0c50c9338)]
56
71
  ### [8.0.3](https://github.com/eea/volto-tableau/compare/8.0.2...8.0.3) - 14 June 2024
@@ -182,12 +197,14 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
182
197
  - test [Dobricean Ioan Dorian - [`48505ca`](https://github.com/eea/volto-tableau/commit/48505caef84d12091035fdd79cf64067e7f819e2)]
183
198
  - split the view and edit [Dobricean Ioan Dorian - [`7227bb1`](https://github.com/eea/volto-tableau/commit/7227bb1fb70e5d895f15872ed6533e089be99836)]
184
199
  - update embed tableau so it can work with serialized data [Dobricean Ioan Dorian - [`59d958c`](https://github.com/eea/volto-tableau/commit/59d958c7a1a5055ea62e04abcbf34ee93f52e23a)]
200
+ - test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`c452d70`](https://github.com/eea/volto-tableau/commit/c452d704819fb485e3cd3b39c2501361d20e8559)]
185
201
  ### [6.0.6](https://github.com/eea/volto-tableau/compare/6.0.5...6.0.6) - 17 November 2023
186
202
 
187
203
  #### :hammer_and_wrench: Others
188
204
 
189
205
  - tests: add cypress for tableau [nileshgulia1 - [`6eca683`](https://github.com/eea/volto-tableau/commit/6eca6834b85cdab4ed82367fee32fdbbb35b0f5e)]
190
206
  - tests: update unit tests [nileshgulia1 - [`96cae09`](https://github.com/eea/volto-tableau/commit/96cae09eab2e737f032c97eb401a3efa88e68ec6)]
207
+ - test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`c7e81cb`](https://github.com/eea/volto-tableau/commit/c7e81cb0768f755dd4107a4998253d9bccc33809)]
191
208
  - comment test [Miu Razvan - [`a459525`](https://github.com/eea/volto-tableau/commit/a459525fdccf8ee61651d4cb2e04eb253e841c61)]
192
209
  ### [6.0.5](https://github.com/eea/volto-tableau/compare/6.0.4...6.0.5) - 15 November 2023
193
210
 
@@ -214,6 +231,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
214
231
 
215
232
  #### :house: Internal changes
216
233
 
234
+ - chore: [JENKINS] Refactor automated testing [valentinab25 - [`903b90a`](https://github.com/eea/volto-tableau/commit/903b90a2df0abc183aa68d99a89bb688de3a0c73)]
217
235
 
218
236
  #### :hammer_and_wrench: Others
219
237
 
@@ -223,6 +241,9 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
223
241
  - tests: increase coverage [kreafox - [`ecb9262`](https://github.com/eea/volto-tableau/commit/ecb92625a44365faf4c39f0ff3f02ccc4ca21656)]
224
242
  - Fix tableau height [kreafox - [`6194c24`](https://github.com/eea/volto-tableau/commit/6194c2405e2bd93aba9865caed76292cd55193d3)]
225
243
  - Show share & download button on widget view [kreafox - [`a66e253`](https://github.com/eea/volto-tableau/commit/a66e2537d08dc7129e249c28e1daa27246c88815)]
244
+ - test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`9d2189d`](https://github.com/eea/volto-tableau/commit/9d2189d4edb13dd449d75cd6dd9052bbed67304d)]
245
+ - test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`f2fa3f9`](https://github.com/eea/volto-tableau/commit/f2fa3f9ccabab918586179ac16ead44e2eba8498)]
246
+ - test: [JENKINS] Improve cypress time [valentinab25 - [`5748183`](https://github.com/eea/volto-tableau/commit/5748183c27dae18a4ebbc067d659cbc24cad8f71)]
226
247
  - use toolbar from volto-embed [Miu Razvan - [`1a232a1`](https://github.com/eea/volto-tableau/commit/1a232a15f2bbe05da75307800590d0a0a1c4996b)]
227
248
  ## [6.0.0](https://github.com/eea/volto-tableau/compare/5.0.2...6.0.0) - 30 October 2023
228
249
 
@@ -280,6 +301,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
280
301
  - test: change volto version in Jenkinsfile [ana-oprea - [`347aceb`](https://github.com/eea/volto-tableau/commit/347aceb07d152fddeebbf3a7e7a6ac9c55dc21ba)]
281
302
  - test: increase cypress timeout [ana-oprea - [`bdf4408`](https://github.com/eea/volto-tableau/commit/bdf44083cd84c96b4914d3f8a3bb17c5187f191c)]
282
303
  - test: EN locales, pre-commit fix, feature PRs checks Refs #257193 [valentinab25 - [`caff974`](https://github.com/eea/volto-tableau/commit/caff9742a703b224133a8dd2a969629e70c9fd33)]
304
+ - test: Fix eslint and yarn i18n [Alin Voinea - [`b8be7fb`](https://github.com/eea/volto-tableau/commit/b8be7fb9ab10faed0a1be8ce7e3d4e7c78ebe020)]
283
305
  - i18n: Add en [Alin Voinea - [`c5e20dd`](https://github.com/eea/volto-tableau/commit/c5e20ddea25c830ac80665ee9a71e557e8cd117d)]
284
306
  - test: Update Makefile and docker-compose to align it with Jenkinsfile [valentinab25 - [`2116ff9`](https://github.com/eea/volto-tableau/commit/2116ff95c6454e813bdca44e6c3aa81fa0a916b8)]
285
307
  ## [5.0.0](https://github.com/eea/volto-tableau/compare/4.1.1...5.0.0) - 25 July 2023
@@ -291,17 +313,21 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
291
313
  #### :hammer_and_wrench: Others
292
314
 
293
315
  - Release 5.0.0 [Alin Voinea - [`97c98e9`](https://github.com/eea/volto-tableau/commit/97c98e98b1295a4ad45756326dc20cd59517515f)]
316
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`2acb3a5`](https://github.com/eea/volto-tableau/commit/2acb3a5490f62ce0a95ebbd03c32874ac3a42603)]
294
317
  ### [4.1.1](https://github.com/eea/volto-tableau/compare/4.1.0...4.1.1) - 21 July 2023
295
318
 
296
319
  #### :hammer_and_wrench: Others
297
320
 
298
321
  - Add VisualizationViewWidget [Tiberiu Ichim - [`fa881cb`](https://github.com/eea/volto-tableau/commit/fa881cbc3643a46697fb16d1c86ada1d4121a46a)]
322
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`cbcbad2`](https://github.com/eea/volto-tableau/commit/cbcbad26f7aa3683122199c8d5cbd142903df93b)]
323
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`51abe6d`](https://github.com/eea/volto-tableau/commit/51abe6d4db80825fe2e396e04c7003c6ad79b480)]
299
324
  ### [4.1.0](https://github.com/eea/volto-tableau/compare/4.0.0...4.1.0) - 15 June 2023
300
325
 
301
326
  ## [4.0.0](https://github.com/eea/volto-tableau/compare/3.0.8...4.0.0) - 13 June 2023
302
327
 
303
328
  #### :house: Internal changes
304
329
 
330
+ - chore: [JENKINS] Remove alpha testing version [valentinab25 - [`e33bb21`](https://github.com/eea/volto-tableau/commit/e33bb21eb429c33e3a15d771487a1c9af8ccb0d5)]
305
331
 
306
332
  #### :hammer_and_wrench: Others
307
333
 
@@ -333,6 +359,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
333
359
 
334
360
  #### :hammer_and_wrench: Others
335
361
 
362
+ - Add Sonarqube tag using industry-frontend addons list [EEA Jenkins - [`f5deccd`](https://github.com/eea/volto-tableau/commit/f5deccd84372752908b300c5cfd78134818e5ce4)]
336
363
  ### [3.0.6](https://github.com/eea/volto-tableau/compare/3.0.5...3.0.6) - 30 January 2023
337
364
 
338
365
  ### [3.0.5](https://github.com/eea/volto-tableau/compare/3.0.4...3.0.5) - 26 January 2023
@@ -404,6 +431,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
404
431
  - Update commands.js [Nilesh - [`7c48437`](https://github.com/eea/volto-tableau/commit/7c4843780efb9b85a4728de73c00d831c1d8fdcf)]
405
432
  - Update e2e.js [Nilesh - [`f67b45c`](https://github.com/eea/volto-tableau/commit/f67b45c170f58f8d0301192994226f173e4cb00a)]
406
433
  - latest volto compatibility refs #154757 [nileshgulia1 - [`881ba48`](https://github.com/eea/volto-tableau/commit/881ba482dc9b82e7fdac16549d41e80a6d26b3de)]
434
+ - Add Sonarqube tag using marine-frontend addons list [EEA Jenkins - [`58e25df`](https://github.com/eea/volto-tableau/commit/58e25df2291add09670143bee54cde103ee835b9)]
407
435
  ### [1.3.0](https://github.com/eea/volto-tableau/compare/1.2.5...1.3.0) - 28 September 2022
408
436
 
409
437
  #### :hammer_and_wrench: Others
@@ -417,11 +445,15 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
417
445
  - Use volto 16 alpha 14 [Miu Razvan - [`93641be`](https://github.com/eea/volto-tableau/commit/93641be4c2393f49008aff789400cf7c947949fd)]
418
446
  - Revert volto-tableau group to common [Andrei Grigore - [`9d24c6d`](https://github.com/eea/volto-tableau/commit/9d24c6d2767fed6a840cddaee55dbd5cecb544b5)]
419
447
  - Tableaugroup typo fix [Andrei Grigore - [`b0b5378`](https://github.com/eea/volto-tableau/commit/b0b5378a437043120a96c9e5e8802584145daa22)]
448
+ - Add Sonarqube tag using freshwater-frontend addons list [EEA Jenkins - [`3234347`](https://github.com/eea/volto-tableau/commit/3234347e524cc0ed4918242f503fe9e7dba266b2)]
420
449
  - Refs #142010 - Optimize Volto-addons gitflow pipelines [valentinab25 - [`d237e1c`](https://github.com/eea/volto-tableau/commit/d237e1c72817d7e68a3eb698563674d1514db24f)]
421
450
  ### [1.2.4](https://github.com/eea/volto-tableau/compare/1.2.3...1.2.4) - 25 October 2021
422
451
 
423
452
  #### :hammer_and_wrench: Others
424
453
 
454
+ - Add Sonarqube tag using frontend addons list [EEA Jenkins - [`2b19679`](https://github.com/eea/volto-tableau/commit/2b19679e2c7bcdc83082d1c73a595eea8b86d14f)]
455
+ - Add Sonarqube tag using frontend addons list [EEA Jenkins - [`384ccae`](https://github.com/eea/volto-tableau/commit/384ccaebed8c414a5c90eb96c6ce0a2b091f249c)]
456
+ - Add Sonarqube tag using frontend addons list [EEA Jenkins - [`589258e`](https://github.com/eea/volto-tableau/commit/589258e9b3cbba9cee37c57bb85ca5b707bc65d7)]
425
457
  ### [1.2.3](https://github.com/eea/volto-tableau/compare/1.2.2...1.2.3) - 14 June 2021
426
458
 
427
459
  #### :hammer_and_wrench: Others
@@ -27,13 +27,18 @@ describe('Blocks Tests', () => {
27
27
  afterEach(slateAfterEach);
28
28
 
29
29
  it('Add Tableau block', () => {
30
+ cy.intercept('GET', `/**/*?expand*`, {
31
+ statusCode: 200,
32
+ }).as('content');
30
33
  // when I add a maps block
31
34
  cy.addNewBlock('tableau');
32
35
 
33
36
  cy.get(
34
37
  `.sidebar-container .field-wrapper-tableau_vis_url #field-tableau_vis_url`,
35
38
  ).type('/path/to/dashboard', { force: true });
39
+ cy.wait('@content');
36
40
  cy.get('#toolbar-save').click({ force: true });
41
+ cy.intercept('GET', `/**/*?expand*`).as('content');
37
42
  cy.wait('@content');
38
43
  cy.url().should('eq', Cypress.config().baseUrl + '/cypress/my-page');
39
44
  });
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-tableau",
3
- "version": "8.1.0",
3
+ "version": "8.1.2",
4
4
  "description": "@eeacms/volto-tableau: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -69,7 +69,7 @@ const staticParameters = {
69
69
  required: [],
70
70
  };
71
71
 
72
- const schema = (props) => {
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 schema;
185
+ export default getSchema;
@@ -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((loaded, loading, error) => {
218
- vizState.current = { ...vizState.current, loaded, loading, error };
219
- setLoaded(loaded);
220
- setLoading(loading);
221
- setError(error);
222
- if (setVizState) {
223
- setVizState({ loaded, loading, error });
224
- }
225
- /* eslint-disable-next-line */
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).then(() => {
235
- onVizStateUpdate(true, false, null);
236
- });
237
- } else {
238
- onVizStateUpdate(true, false, null);
260
+ return workbook.activateSheetAsync(sheetname);
239
261
  }
240
- }, [onVizStateUpdate, sheetname]);
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
- setInitiateViz(false);
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
- /* eslint-disable-next-line */
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,21 +463,9 @@ const Tableau = forwardRef((props, ref) => {
419
463
  value = value
420
464
  .filter((v) => includes(values, v))
421
465
  .map((v) => {
422
- if (dataType === 'string' && !isString(v)) {
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
- if (value.length) {
468
+ if (value?.length) {
437
469
  workbook.changeParameterValueAsync(fieldName, value);
438
470
  }
439
471
  }
@@ -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
  () => {
@@ -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) return false;
155
- return !!viz || isUndefined(viz);
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
+ });
@@ -1,6 +1,7 @@
1
1
  import React, { useState } from 'react';
2
2
  import { withRouter } from 'react-router';
3
3
  import { connect } from 'react-redux';
4
+ import { injectIntl } from 'react-intl';
4
5
  import { compose } from 'redux';
5
6
  import { isEqual } from 'lodash';
6
7
  import { Modal, Button, Grid } from 'semantic-ui-react';
@@ -34,6 +35,7 @@ const VisualizationWidget = (props) => {
34
35
  const ogValue = props.value || {};
35
36
  const inAddForm = props.location.pathname.split('/').pop() === 'add';
36
37
  const viz = React.useRef();
38
+ const [tableauData, setTableauData] = React.useState({});
37
39
  const [schema, setSchema] = React.useState(null);
38
40
  const [vizState, setVizState] = React.useState({
39
41
  loaded: false,
@@ -75,6 +77,33 @@ const VisualizationWidget = (props) => {
75
77
  setOpen(false);
76
78
  };
77
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
+ */
78
107
  React.useEffect(() => {
79
108
  if (!open && !isEqual(props.value || {}, value)) {
80
109
  setValue(props.value || {});
@@ -125,12 +154,17 @@ const VisualizationWidget = (props) => {
125
154
  * Get schema
126
155
  */
127
156
  React.useEffect(() => {
128
- getSchema({ config, viz: viz.current, vizState, data: value }).then(
129
- (schema) => {
130
- setSchema(schema);
131
- },
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
+ }),
132
166
  );
133
- }, [vizState, value]);
167
+ }, [vizState, value, tableauData, props.intl]);
134
168
 
135
169
  React.useEffect(() => {
136
170
  if (value && value.url && value.preview_url_loaded !== value.url) {
@@ -139,7 +173,7 @@ const VisualizationWidget = (props) => {
139
173
  '',
140
174
  )}/cors-proxy/https://screenshot.eea.europa.eu/api/v1/retrieve_image_for_url?url=${encodeURIComponent(
141
175
  value.url,
142
- )}&w=1920&h=1000&waitfor=4000`,
176
+ )}&w=1920&h=1000&waitfor=8000`,
143
177
  )
144
178
  .then((e) => e.blob())
145
179
  .then((myBlob) => {
@@ -216,8 +250,14 @@ const VisualizationWidget = (props) => {
216
250
  <Grid>
217
251
  <Grid.Row>
218
252
  <div className="map-edit-actions-container">
219
- <Button onClick={handleClose}>Close</Button>
220
- <Button color="green" onClick={handleApplyChanges}>
253
+ <Button disabled={vizState.loading} onClick={handleClose}>
254
+ Close
255
+ </Button>
256
+ <Button
257
+ disabled={vizState.loading}
258
+ color="green"
259
+ onClick={handleApplyChanges}
260
+ >
221
261
  Apply changes
222
262
  </Button>
223
263
  </div>
@@ -260,5 +300,6 @@ const VisualizationWidget = (props) => {
260
300
 
261
301
  export default compose(
262
302
  withRouter,
303
+ injectIntl,
263
304
  connect((state) => ({ content: state?.content?.data })),
264
305
  )(VisualizationWidget);
@@ -1,12 +1,20 @@
1
- import { find, includes } from 'lodash';
2
- import {
3
- getSheetnamesChoices,
4
- canChangeVizData,
5
- } from '@eeacms/volto-tableau/Tableau/helpers';
1
+ import { defineMessages } from 'react-intl';
2
+ import { find, includes, uniq } from 'lodash';
3
+ import { canChangeVizData } from '@eeacms/volto-tableau/Tableau/helpers';
6
4
 
7
- async function getUrlParametersSchema({ viz, vizState, data }) {
8
- const tableauParameters =
9
- vizState.loaded && viz ? await viz.getWorkbook().getParametersAsync() : [];
5
+ const messages = defineMessages({
6
+ CSSHeight: {
7
+ id: 'CSS height',
8
+ defaultMessage: 'CSS height',
9
+ },
10
+ CSSTableauHeightDescription: {
11
+ id: 'Tableau height',
12
+ defaultMessage: 'Tableau height',
13
+ },
14
+ });
15
+
16
+ function getUrlParametersSchema({ data, tableauData }) {
17
+ const tableauParameters = tableauData?.parameters || [];
10
18
 
11
19
  const currentFields = (data.urlParameters || [])
12
20
  .map((p) => p.field)
@@ -39,11 +47,8 @@ async function getUrlParametersSchema({ viz, vizState, data }) {
39
47
  };
40
48
  }
41
49
 
42
- async function getStaticParametersSchema({ viz, vizState, data }) {
43
- const tableauParameters =
44
- vizState.loaded && viz
45
- ? (await viz.getWorkbook?.().getParametersAsync?.()) || []
46
- : [];
50
+ function getStaticParametersSchema({ data, tableauData }) {
51
+ const tableauParameters = tableauData?.parameters || [];
47
52
 
48
53
  const currentFields = (data.staticParameters || [])
49
54
  .map((p) => p.field)
@@ -74,11 +79,8 @@ async function getStaticParametersSchema({ viz, vizState, data }) {
74
79
  };
75
80
  }
76
81
 
77
- async function getDynamicFiltersSchema({ viz, vizState, data }) {
78
- const tableauFilters =
79
- vizState.loaded && viz
80
- ? (await viz.getWorkbook?.().getActiveSheet?.().getFiltersAsync?.()) || []
81
- : [];
82
+ function getDynamicFiltersSchema({ data, tableauData }) {
83
+ const tableauFilters = tableauData?.filters || [];
82
84
 
83
85
  const currentFields = (data.staticFilters || [])
84
86
  .map((p) => p.field)
@@ -111,11 +113,8 @@ async function getDynamicFiltersSchema({ viz, vizState, data }) {
111
113
  };
112
114
  }
113
115
 
114
- async function getStaticFiltersSchema({ viz, vizState, data }) {
115
- const tableauFilters =
116
- vizState.loaded && viz
117
- ? (await viz.getWorkbook?.().getActiveSheet?.().getFiltersAsync?.()) || []
118
- : [];
116
+ function getStaticFiltersSchema({ data, tableauData }) {
117
+ const tableauFilters = tableauData?.filters || [];
119
118
 
120
119
  const currentFields = (data.staticFilters || [])
121
120
  .map((p) => p.field)
@@ -130,11 +129,13 @@ async function getStaticFiltersSchema({ viz, vizState, data }) {
130
129
  widget: 'creatable_select',
131
130
  isMulti: false,
132
131
  creatable: true,
133
- choices: tableauFilters
134
- .filter((p) => {
135
- return !includes(currentFields, p.getFieldName());
136
- })
137
- .map((p) => [p.getFieldName(), p.getFieldName()]),
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]),
138
139
  },
139
140
  value: {
140
141
  title: 'Value',
@@ -170,7 +171,7 @@ const breakpointUrlSchema = (config) => {
170
171
  };
171
172
  };
172
173
 
173
- const schema = async ({ config, viz, vizState, data }) => {
174
+ const schema = ({ config, viz, vizState, data, tableauData, intl }) => {
174
175
  const isDisabled = !canChangeVizData(viz, vizState);
175
176
 
176
177
  return {
@@ -189,6 +190,7 @@ const schema = async ({ config, viz, vizState, data }) => {
189
190
  'hideTabs',
190
191
  'hideToolbar',
191
192
  'autoScale',
193
+ 'tableau_height',
192
194
  'toolbarPosition',
193
195
  'breakpointUrls',
194
196
  ],
@@ -211,7 +213,7 @@ const schema = async ({ config, viz, vizState, data }) => {
211
213
  },
212
214
  sheetname: {
213
215
  title: 'Sheetname',
214
- choices: getSheetnamesChoices(viz),
216
+ choices: tableauData?.sheetNames?.map((sheet) => [sheet, sheet]) || [],
215
217
  isDisabled,
216
218
  },
217
219
  hideTabs: {
@@ -230,6 +232,18 @@ const schema = async ({ config, viz, vizState, data }) => {
230
232
  description: 'Scale down tableau according to width',
231
233
  isDisabled,
232
234
  },
235
+ tableau_height: {
236
+ title: (
237
+ <a
238
+ rel="noopener noreferrer"
239
+ target="_blank"
240
+ href="https://developer.mozilla.org/en-US/docs/Web/CSS/height"
241
+ >
242
+ {intl.formatMessage(messages.CSSHeight)}
243
+ </a>
244
+ ),
245
+ description: intl.formatMessage(messages.CSSTableauHeightDescription),
246
+ },
233
247
  toolbarPosition: {
234
248
  title: 'Toolbar position',
235
249
  choices: [
@@ -242,7 +256,7 @@ const schema = async ({ config, viz, vizState, data }) => {
242
256
  urlParameters: {
243
257
  title: 'Dynamic parameters',
244
258
  widget: 'object_list',
245
- schema: await getUrlParametersSchema({ viz, vizState, data }),
259
+ schema: getUrlParametersSchema({ data, tableauData }),
246
260
  description: (
247
261
  <div style={{ color: 'rgb(15, 130, 204)', fontWeight: '400' }}>
248
262
  <p>Set a list of dynamic parameters that can be used as:</p>
@@ -288,7 +302,7 @@ const schema = async ({ config, viz, vizState, data }) => {
288
302
  staticParameters: {
289
303
  title: 'Static parameters',
290
304
  widget: 'object_list',
291
- schema: await getStaticParametersSchema({ viz, vizState, data }),
305
+ schema: getStaticParametersSchema({ data, tableauData }),
292
306
  schemaExtender: (schema, data) => {
293
307
  const tableauParameter = find(
294
308
  schema.tableauParameters,
@@ -335,7 +349,7 @@ const schema = async ({ config, viz, vizState, data }) => {
335
349
  dynamicFilters: {
336
350
  title: 'Dynamic filters',
337
351
  widget: 'object_list',
338
- schema: await getDynamicFiltersSchema({ viz, vizState, data }),
352
+ schema: getDynamicFiltersSchema({ data, tableauData }),
339
353
  description: (
340
354
  <div style={{ color: 'rgb(15, 130, 204)', fontWeight: '400' }}>
341
355
  <p>Set a list of dynamic filters that can be used as:</p>
@@ -381,7 +395,7 @@ const schema = async ({ config, viz, vizState, data }) => {
381
395
  staticFilters: {
382
396
  title: 'Static filters',
383
397
  widget: 'object_list',
384
- schema: await getStaticFiltersSchema({ viz, vizState, data }),
398
+ schema: getStaticFiltersSchema({ data, tableauData }),
385
399
  schemaExtender: (schema, data) => {
386
400
  const tableauFilters = find(
387
401
  schema.tableauFilters,