@eeacms/volto-tableau 8.0.6 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,12 +4,47 @@ 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
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - Update version [dobri1408 - [`dc7280a`](https://github.com/eea/volto-tableau/commit/dc7280ae0a99dd91af2c589715ee16a789eae9f9)]
12
+ - Make an extra cleaning step for the action [dobri1408 - [`cec9ff9`](https://github.com/eea/volto-tableau/commit/cec9ff98dde77a729c04339bac889463949f3d1c)]
13
+ ### [8.0.7](https://github.com/eea/volto-tableau/compare/8.0.6...8.0.7) - 9 September 2024
14
+
15
+ #### :house: Internal changes
16
+
17
+ - style: Automated code fix [eea-jenkins - [`ef00271`](https://github.com/eea/volto-tableau/commit/ef00271928ae63ba0d22485f9343fc304e090b03)]
18
+
19
+ #### :hammer_and_wrench: Others
20
+
21
+ - Update View.test.jsx [dobri1408 - [`984f762`](https://github.com/eea/volto-tableau/commit/984f76249550287ef297526d3962a61fd498a0be)]
22
+ - increase code coverage [dobri1408 - [`4a0b444`](https://github.com/eea/volto-tableau/commit/4a0b4449f244c4deacc4015b0d2373d0baa49e2f)]
23
+ - increase code coverage [dobri1408 - [`0a036f4`](https://github.com/eea/volto-tableau/commit/0a036f4d45401da63e71104cae57f7378a4d3624)]
24
+ - increase code coverage [dobri1408 - [`0438558`](https://github.com/eea/volto-tableau/commit/0438558970650d3a01d74802e622cd9d27ebda81)]
25
+ - double check preview [dobri1408 - [`85e0689`](https://github.com/eea/volto-tableau/commit/85e0689f800064e98937be6f74bfdd9959ccd1da)]
26
+ - double check preview [dobri1408 - [`1671a45`](https://github.com/eea/volto-tableau/commit/1671a45608c765f832b48789721dbe7b06b65ed4)]
27
+ - Update preview_image.js [dobri1408 - [`87925c5`](https://github.com/eea/volto-tableau/commit/87925c5c45d8395c9c5b956ead2a7d988823233a)]
28
+ - double check preview [dobri1408 - [`1579659`](https://github.com/eea/volto-tableau/commit/1579659822d56993dd147a6256013b0e7c12bbb5)]
29
+ - Create preview_image.test.js [dobri1408 - [`c562940`](https://github.com/eea/volto-tableau/commit/c562940a2f0bb7ae34ef98a62d2c95f4fe2506c0)]
30
+ - Update preview_image.js [dobri1408 - [`aa3b15e`](https://github.com/eea/volto-tableau/commit/aa3b15edd95d64c8ca969a8252f7d9371e142a6d)]
31
+ - merge [dobri1408 - [`ba63a8f`](https://github.com/eea/volto-tableau/commit/ba63a8f95349d00e5782ebff31870e96891362ca)]
32
+ - manage redux and action right [dobri1408 - [`85be516`](https://github.com/eea/volto-tableau/commit/85be51613a3789adbebd3a517f6b87f600ed3e92)]
33
+ - Update preview_image.js [dobri1408 - [`bb20a02`](https://github.com/eea/volto-tableau/commit/bb20a0204292ef9f94734b343eea9f2fd3e5a96a)]
34
+ - Update VisualizationWidget.jsx [dobri1408 - [`e5ee11c`](https://github.com/eea/volto-tableau/commit/e5ee11ca4f5ee10a42f28e7087582744628aa144)]
35
+ - Update VisualizationWidget.jsx [dobri1408 - [`f0d3bdf`](https://github.com/eea/volto-tableau/commit/f0d3bdf6edff339a037a64453eea714496c39d92)]
36
+ - fix multiple rerenders [dobri1408 - [`6cc0ef0`](https://github.com/eea/volto-tableau/commit/6cc0ef0b8d1bb7f3a0770666c6e60bb3c28df0d4)]
37
+ - Update VisualizationWidget.jsx [dobri1408 - [`56d94fd`](https://github.com/eea/volto-tableau/commit/56d94fdf9bd26db1512d2ae5ee5f65e743b795b5)]
38
+ - fix eslint [dobri1408 - [`d7d754e`](https://github.com/eea/volto-tableau/commit/d7d754e9d89b60951ac7da27b14db93389832216)]
39
+ - fix eslint [dobri1408 - [`58b50d9`](https://github.com/eea/volto-tableau/commit/58b50d995059eea0cc31a0bb6e8e80b48ace99ea)]
40
+ - middleware to save preview image [dobri1408 - [`4b9d1b3`](https://github.com/eea/volto-tableau/commit/4b9d1b3efc5c1cc04d273ce91ccc0621cb60b324)]
41
+ - Update package.json [dobri1408 - [`12a1c94`](https://github.com/eea/volto-tableau/commit/12a1c9478591ba4729f00a55932858b5ef616ff2)]
42
+ - middleware to save preview image [dobri1408 - [`9fe3dd7`](https://github.com/eea/volto-tableau/commit/9fe3dd795842f40e2f0d91475df04b7b97de922e)]
7
43
  ### [8.0.6](https://github.com/eea/volto-tableau/compare/8.0.5...8.0.6) - 25 July 2024
8
44
 
9
45
  #### :hammer_and_wrench: Others
10
46
 
11
47
  - Update Jenkinsfile [Alexandru Ghica - [`d5e7d48`](https://github.com/eea/volto-tableau/commit/d5e7d48a52e494ebf139b14ea06d0cac8cce82f3)]
12
- - more checks [Miu Razvan - [`575a1d5`](https://github.com/eea/volto-tableau/commit/575a1d5db3310f9b2dec343adca7c9b912316414)]
13
48
  ### [8.0.5](https://github.com/eea/volto-tableau/compare/8.0.4...8.0.5) - 23 July 2024
14
49
 
15
50
  ### [8.0.4](https://github.com/eea/volto-tableau/compare/8.0.3...8.0.4) - 22 July 2024
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-tableau",
3
- "version": "8.0.6",
3
+ "version": "8.1.0",
4
4
  "description": "@eeacms/volto-tableau: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,144 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Provider } from 'react-redux';
4
+ import configureStore from 'redux-mock-store';
5
+ import View from './View';
6
+ import '@testing-library/jest-dom/extend-expect';
7
+ import Tableau from '@eeacms/volto-tableau/Tableau/Tableau';
8
+
9
+ jest.mock('@eeacms/volto-tableau/Tableau/Tableau', () =>
10
+ jest.fn(() => <div>Mocked Tableau</div>),
11
+ );
12
+
13
+ jest.mock('@plone/volto/registry', () => ({
14
+ blocks: {
15
+ blocksConfig: {
16
+ tableau_block: {
17
+ breakpoints: {},
18
+ },
19
+ },
20
+ },
21
+ }));
22
+
23
+ const mockStore = configureStore([]);
24
+
25
+ describe('View component', () => {
26
+ let store;
27
+
28
+ beforeEach(() => {
29
+ store = mockStore({
30
+ router: {
31
+ location: {
32
+ search: '?param1=value1',
33
+ },
34
+ },
35
+ discodata_query: {
36
+ search: {},
37
+ },
38
+ screen: {},
39
+ });
40
+ });
41
+
42
+ it('renders correctly with title and description when loaded', () => {
43
+ const mockProps = {
44
+ block: '1234',
45
+ data: {
46
+ title: 'Test Title',
47
+ description: 'Test Description',
48
+ staticParameters: [],
49
+ urlParameters: [],
50
+ },
51
+ mode: 'view',
52
+ query: {},
53
+ };
54
+
55
+ render(
56
+ <Provider store={store}>
57
+ <View {...mockProps} />
58
+ </Provider>,
59
+ );
60
+
61
+ // Simulăm vizualizarea încărcată
62
+ const tableauBlock = screen.getByText('Mocked Tableau');
63
+ expect(tableauBlock).toBeInTheDocument();
64
+
65
+ // Verificăm titlul și descrierea
66
+ expect(screen.queryByText('Test Title')).not.toBeInTheDocument();
67
+ expect(screen.queryByText('Test Description')).not.toBeInTheDocument();
68
+
69
+ // Aici simulăm setVizState pentru a actualiza starea vizualizării ca fiind "loaded"
70
+ mockProps.setVizState = jest.fn((state) => {
71
+ state.loaded = true;
72
+ });
73
+
74
+ // Re-render după schimbarea stării
75
+ render(
76
+ <Provider store={store}>
77
+ <View {...mockProps} />
78
+ </Provider>,
79
+ );
80
+
81
+ expect(screen.getByText('Test Title')).toBeInTheDocument();
82
+ expect(screen.getByText('Test Description')).toBeInTheDocument();
83
+ });
84
+
85
+ it('sets extraFilters correctly based on query parameters', () => {
86
+ const mockProps = {
87
+ block: '1234',
88
+ data: {
89
+ staticParameters: [],
90
+ urlParameters: [{ field: 'filter1', urlParam: 'param1' }],
91
+ },
92
+ mode: 'view',
93
+ query: { param1: 'value1' },
94
+ };
95
+
96
+ render(
97
+ <Provider store={store}>
98
+ <View {...mockProps} />
99
+ </Provider>,
100
+ );
101
+
102
+ expect(Tableau).toHaveBeenCalledWith(
103
+ expect.objectContaining({
104
+ extraFilters: { filter1: 'value1' },
105
+ }),
106
+ {},
107
+ );
108
+ });
109
+
110
+ it('renders Tableau with correct props', () => {
111
+ const mockProps = {
112
+ block: '1234',
113
+ data: {
114
+ title: 'Test Title',
115
+ description: 'Test Description',
116
+ staticParameters: [{ field: 'static1', value: 'staticValue' }],
117
+ urlParameters: [],
118
+ },
119
+ mode: 'view',
120
+ query: {},
121
+ };
122
+
123
+ render(
124
+ <Provider store={store}>
125
+ <View {...mockProps} />
126
+ </Provider>,
127
+ );
128
+
129
+ expect(Tableau).toHaveBeenCalledWith(
130
+ expect.objectContaining({
131
+ data: expect.objectContaining({
132
+ title: 'Test Title',
133
+ description: 'Test Description',
134
+ with_sources: true,
135
+ with_download: true,
136
+ with_share: true,
137
+ with_enlarge: true,
138
+ }),
139
+ extraOptions: { static1: 'staticValue' },
140
+ }),
141
+ {},
142
+ );
143
+ });
144
+ });
@@ -16,9 +16,21 @@ import {
16
16
  } from '@eeacms/volto-tableau/Tableau/helpers';
17
17
 
18
18
  import '@eeacms/volto-tableau/less/tableau.less';
19
+ import { getBaseUrl } from '@plone/volto/helpers';
20
+
21
+ function blobToBase64(blob) {
22
+ return new Promise((resolve, reject) => {
23
+ const reader = new FileReader();
24
+ reader.onloadend = () => {
25
+ resolve(reader.result);
26
+ };
27
+ reader.onerror = reject;
28
+ reader.readAsDataURL(blob);
29
+ });
30
+ }
19
31
 
20
32
  const VisualizationWidget = (props) => {
21
- const { location, content } = props;
33
+ const { location, content, onChange, id } = props;
22
34
  const ogValue = props.value || {};
23
35
  const inAddForm = props.location.pathname.split('/').pop() === 'add';
24
36
  const viz = React.useRef();
@@ -120,6 +132,29 @@ const VisualizationWidget = (props) => {
120
132
  );
121
133
  }, [vizState, value]);
122
134
 
135
+ React.useEffect(() => {
136
+ if (value && value.url && value.preview_url_loaded !== value.url) {
137
+ fetch(
138
+ `${getBaseUrl(
139
+ '',
140
+ )}/cors-proxy/https://screenshot.eea.europa.eu/api/v1/retrieve_image_for_url?url=${encodeURIComponent(
141
+ value.url,
142
+ )}&w=1920&h=1000&waitfor=4000`,
143
+ )
144
+ .then((e) => e.blob())
145
+ .then((myBlob) => {
146
+ blobToBase64(myBlob).then((base64String) => {
147
+ onChange(id, {
148
+ ...value,
149
+ preview: base64String,
150
+ preview_url_loaded: value.url,
151
+ });
152
+ });
153
+ })
154
+ .catch(() => {});
155
+ }
156
+ }, [value, onChange, id]);
157
+
123
158
  return (
124
159
  <FormFieldWrapper {...props}>
125
160
  <Modal id="tableau-editor-modal" open={open}>
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  VisualizationViewWidget,
6
6
  CreatableSelectWidget,
7
7
  } from './Widgets';
8
+ import { preview_image } from './middlewares/preview_image';
8
9
 
9
10
  const applyConfig = (config) => {
10
11
  config.settings.allowed_cors_destinations = [
@@ -12,7 +13,10 @@ const applyConfig = (config) => {
12
13
  'public.tableau.com',
13
14
  ];
14
15
 
15
- config.settings.storeExtenders = [...(config.settings.storeExtenders || [])];
16
+ config.settings.storeExtenders = [
17
+ ...(config.settings.storeExtenders || []),
18
+ preview_image,
19
+ ];
16
20
 
17
21
  config.views.contentTypesViews.tableau_visualization = VisualizationView;
18
22
  config.widgets.id.tableau_visualization = VisualizationWidget;
@@ -0,0 +1,112 @@
1
+ import {
2
+ CREATE_CONTENT,
3
+ UPDATE_CONTENT,
4
+ } from '@plone/volto/constants/ActionTypes';
5
+
6
+ const cleanAction = (action) => {
7
+ if (action?.request?.data?.tableau_visualization) {
8
+ const tableauVisualizationData = {
9
+ ...action.request.data.tableau_visualization,
10
+ };
11
+
12
+ if (
13
+ tableauVisualizationData.preview &&
14
+ tableauVisualizationData.preview_url_loaded
15
+ )
16
+ delete tableauVisualizationData.preview;
17
+ delete tableauVisualizationData.preview_url_loaded;
18
+
19
+ return {
20
+ ...action,
21
+ request: {
22
+ ...action.request,
23
+ data: {
24
+ ...action.request.data,
25
+
26
+ tableau_visualization: tableauVisualizationData,
27
+ },
28
+ },
29
+ };
30
+ } else return action;
31
+ };
32
+
33
+ export const preview_image = (middlewares) => [
34
+ (store) => (next) => (action) => {
35
+ if (![CREATE_CONTENT, UPDATE_CONTENT].includes(action.type)) {
36
+ return next(action);
37
+ }
38
+ const state = store.getState();
39
+ const contentData = state.content.data;
40
+ const lastPreviewImage = Object.keys(action?.request?.data).includes(
41
+ 'preview_image',
42
+ )
43
+ ? action?.request?.data.preview_image
44
+ : contentData?.preview_image;
45
+ const type = action?.request?.data?.['@type'] || contentData['@type'];
46
+ if (
47
+ !contentData ||
48
+ type !== 'tableau_visualization' ||
49
+ contentData.preview_image_saved ||
50
+ !action?.request?.data?.tableau_visualization?.preview
51
+ ) {
52
+ return next(cleanAction(action));
53
+ }
54
+
55
+ if (
56
+ lastPreviewImage &&
57
+ lastPreviewImage !== 'preview_image_generated_tableau_visualization.png'
58
+ ) {
59
+ return next(cleanAction(action));
60
+ }
61
+
62
+ try {
63
+ const previewImage = {
64
+ preview_image: {
65
+ data: action.request.data.tableau_visualization.preview.split(',')[1],
66
+ encoding: 'base64',
67
+ 'content-type': 'image/png',
68
+ filename: 'preview_image_generated_tableau_visualization.png',
69
+ },
70
+ preview_image_saved: true,
71
+ };
72
+
73
+ const tableauVisualizationData = {
74
+ ...action.request.data.tableau_visualization,
75
+ };
76
+ delete tableauVisualizationData.preview;
77
+ delete tableauVisualizationData.preview_url_loaded;
78
+
79
+ return next({
80
+ ...action,
81
+ request: {
82
+ ...action.request,
83
+ data: {
84
+ ...action.request.data,
85
+ ...previewImage,
86
+ tableau_visualization: tableauVisualizationData,
87
+ },
88
+ },
89
+ });
90
+ } catch (error) {
91
+ if (action.request.data.tableau_visualization.preview) {
92
+ const tableauVisualizationData = {
93
+ ...action.request.data.tableau_visualization,
94
+ };
95
+ delete tableauVisualizationData.preview;
96
+ delete tableauVisualizationData.preview_url_loaded;
97
+
98
+ return next({
99
+ ...action,
100
+ request: {
101
+ ...action.request,
102
+ data: {
103
+ ...action.request.data,
104
+ tableau_visualization: tableauVisualizationData,
105
+ },
106
+ },
107
+ });
108
+ } else return next(action);
109
+ }
110
+ },
111
+ ...middlewares,
112
+ ];
@@ -0,0 +1,30 @@
1
+ import { preview_image } from './preview_image';
2
+ describe('preview_image middleware', () => {
3
+ let store;
4
+ let next;
5
+ let action;
6
+ let middlewares;
7
+
8
+ beforeEach(() => {
9
+ store = {
10
+ getState: jest.fn(() => ({
11
+ content: {
12
+ data: {
13
+ '@type': 'tableau_visualization',
14
+ preview_image: 'existing_image.png',
15
+ preview_image_saved: false,
16
+ },
17
+ },
18
+ })),
19
+ };
20
+ next = jest.fn();
21
+ middlewares = [];
22
+ });
23
+
24
+ it('should pass through if action type is not CREATE_CONTENT or UPDATE_CONTENT', () => {
25
+ action = { type: 'UPDATE_CONTENT', request: { data: {} } };
26
+ const middleware = preview_image(middlewares)[0]; // Accesăm prima funcție din array
27
+ middleware(store)(next)(action); // Executăm funcția de middleware
28
+ expect(next).toHaveBeenCalledWith(action); // Verificăm că funcția next a fost apelată cu acțiunea originală
29
+ });
30
+ });