@eeacms/volto-tableau 3.0.8 → 4.0.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +14 -7
  2. package/Jenkinsfile +2 -0
  3. package/jest-addon.config.js +2 -2
  4. package/package.json +1 -1
  5. package/src/Blocks/EmbedTableauVisualization/Edit.jsx +31 -0
  6. package/src/Blocks/EmbedTableauVisualization/View.jsx +63 -0
  7. package/src/Blocks/EmbedTableauVisualization/index.js +30 -0
  8. package/src/Blocks/{EmbedEEATableauBlock → EmbedTableauVisualization}/schema.js +29 -13
  9. package/src/{TableauBlock → Blocks/TableauBlock}/Edit.jsx +3 -2
  10. package/src/{TableauBlock → Blocks/TableauBlock}/View.jsx +29 -40
  11. package/src/Blocks/TableauBlock/index.js +30 -0
  12. package/src/{TableauBlock → Blocks/TableauBlock}/schema.js +50 -2
  13. package/src/Blocks/index.js +9 -0
  14. package/src/Tableau/Tableau.jsx +263 -0
  15. package/src/Utils/Download/Download.jsx +72 -0
  16. package/src/Utils/Share/Share.jsx +21 -0
  17. package/src/Utils/Sources/Sources.jsx +66 -0
  18. package/src/Views/VisualizationView.jsx +12 -32
  19. package/src/Widgets/VisualizationWidget.jsx +60 -124
  20. package/src/Widgets/schema.js +62 -131
  21. package/src/helpers.js +15 -34
  22. package/src/hooks.js +18 -0
  23. package/src/icons/download.svg +5 -0
  24. package/src/index.js +4 -66
  25. package/src/less/tableau.less +131 -72
  26. package/src/less/tableau.variables +6 -13
  27. package/src/Blocks/EmbedEEATableauBlock/Edit.jsx +0 -56
  28. package/src/Blocks/EmbedEEATableauBlock/View.jsx +0 -74
  29. package/src/ConnectedTableau/ConnectedTableau.jsx +0 -29
  30. package/src/CustomWidgets/UrlParamsWidget.jsx +0 -29
  31. package/src/DownloadExtras/TableauDownload.jsx +0 -124
  32. package/src/DownloadExtras/TableauFullscreen.jsx +0 -78
  33. package/src/DownloadExtras/TableauShare.jsx +0 -81
  34. package/src/DownloadExtras/style.less +0 -152
  35. package/src/Sources/Sources.jsx +0 -50
  36. package/src/Sources/index.js +0 -3
  37. package/src/Sources/style.css +0 -7
  38. package/src/Tableau/View.jsx +0 -254
  39. package/src/Widgets/style.less +0 -8
  40. package/src/actions.js +0 -9
  41. package/src/constants.js +0 -1
  42. package/src/downloadHelpers/downloadHelpers.js +0 -25
  43. package/src/middleware.js +0 -39
  44. package/src/store.js +0 -72
@@ -1,254 +0,0 @@
1
- import React from 'react';
2
- import { connect } from 'react-redux';
3
- import { compose } from 'redux';
4
- import { toast } from 'react-toastify';
5
- import { Toast } from '@plone/volto/components';
6
- import { setTableauApi } from '@eeacms/volto-tableau/actions';
7
- import cx from 'classnames';
8
- import { loadTableauScript } from '../helpers';
9
- import TableauDownload from '../DownloadExtras/TableauDownload';
10
- import TableauShare from '../DownloadExtras/TableauShare';
11
- import '../DownloadExtras/style.less';
12
-
13
- const Tableau = (props) => {
14
- const ref = React.useRef(null);
15
- const filters = React.useRef(props.data.filters || {});
16
- const mounted = React.useRef(false);
17
- const [viz, setViz] = React.useState(null);
18
- const {
19
- canUpdateUrl = true,
20
- data = {},
21
- error = null,
22
- extraFilters = {},
23
- extraOptions = {},
24
- loaded = false,
25
- mode = 'view',
26
- screen = {},
27
- setError = () => {},
28
- setLoaded = () => {},
29
- version = '2.8.0',
30
- } = props;
31
- const {
32
- autoScale = false,
33
- hideTabs = false,
34
- hideToolbar = false,
35
- sheetname = '',
36
- toolbarPosition = 'Top',
37
- } = data;
38
- const defaultUrl = data.url;
39
- const url = props.url || defaultUrl;
40
-
41
- //load tableau from script tag
42
- const tableau = loadTableauScript(() => {}, version);
43
-
44
- const onFilterChange = (filter) => {
45
- const newFilters = { ...filters.current };
46
- const fieldName = filter.getFieldName();
47
- const values = filter
48
- .getAppliedValues()
49
- .map((appliedValue) => appliedValue.value);
50
- newFilters[fieldName] = values;
51
- if (JSON.stringify(newFilters) !== JSON.stringify(filters)) {
52
- props.onChangeBlock(props.block, {
53
- ...data,
54
- filters: {
55
- ...newFilters,
56
- },
57
- });
58
- filters.current = { ...newFilters };
59
- }
60
- };
61
-
62
- const disposeViz = () => {
63
- if (viz) {
64
- viz.dispose();
65
- }
66
- if (loaded) {
67
- setLoaded(false);
68
- }
69
- if (error) {
70
- setError(null);
71
- }
72
- };
73
-
74
- const initViz = () => {
75
- disposeViz();
76
- try {
77
- const newViz = new tableau.Viz(ref.current, url || defaultUrl, {
78
- hideTabs,
79
- hideToolbar,
80
- sheetname,
81
- toolbarPosition,
82
- ...data.filters,
83
- ...extraFilters,
84
- ...extraOptions,
85
- onFirstInteractive: () => {
86
- setLoaded(true);
87
- if (newViz && mode === 'edit') {
88
- const workbook = newViz.getWorkbook();
89
- const newData = {
90
- url: canUpdateUrl ? newViz.getUrl() : defaultUrl,
91
- sheetname: workbook.getActiveSheet().getName(),
92
- };
93
- if (newData.url !== url || newData.sheetname !== sheetname) {
94
- props.onChangeBlock(props.block, {
95
- ...data,
96
- ...newData,
97
- });
98
- toast.success(<Toast success title={'Tableau data updated'} />);
99
- }
100
- // Filter change event
101
- newViz.addEventListener(
102
- tableau.TableauEventName.FILTER_CHANGE,
103
- (event) => {
104
- event.getFilterAsync().then((filter) => {
105
- onFilterChange(filter);
106
- });
107
- },
108
- );
109
- }
110
- },
111
- });
112
-
113
- return setViz(newViz);
114
- } catch (e) {
115
- setError(e._message);
116
- }
117
- };
118
-
119
- const addExtraFilters = (extraFilters) => {
120
- const worksheets = viz.getWorkbook().getActiveSheet().getWorksheets() || [];
121
-
122
- worksheets.forEach((worksheet) => {
123
- if (worksheet.getSheetType() === tableau.DashboardObjectType.WORKSHEET) {
124
- Object.keys(extraFilters).forEach((filter) => {
125
- if (!extraFilters[filter]) {
126
- worksheet.clearFilterAsync(filter);
127
- } else {
128
- worksheet.applyFilterAsync(
129
- filter,
130
- extraFilters[filter],
131
- tableau.FilterUpdateType.REPLACE,
132
- );
133
- }
134
- });
135
- }
136
- });
137
- };
138
-
139
- const updateScale = () => {
140
- const tableauWrapper = ref.current;
141
- const tableau = tableauWrapper?.querySelector('iframe');
142
- if (mounted.current && viz && tableauWrapper && tableau) {
143
- const { sheetSize = {} } = viz.getVizSize() || {};
144
- const vizWidth = sheetSize?.minSize?.width || 1;
145
- const vizHeight = sheetSize?.minSize?.height || 0;
146
- const scale = Math.min(tableauWrapper.clientWidth / vizWidth, 1);
147
- tableau.style.transform = `scale(${scale})`;
148
- tableau.style.width = `${100 / scale}%`;
149
- tableauWrapper.style.height = `${scale * vizHeight}px`;
150
- }
151
- };
152
-
153
- React.useEffect(() => {
154
- if (!mounted.current) {
155
- mounted.current = true;
156
- }
157
- return () => {
158
- mounted.current = false;
159
- };
160
- }, []);
161
-
162
- React.useEffect(() => {
163
- // Load new tableau api
164
- if (__CLIENT__ && !props.tableau[version]) {
165
- props.setTableauApi(version, props.mode);
166
- }
167
- if (__CLIENT__) {
168
- loadTableauScript(() => {}, version);
169
- }
170
- /* eslint-disable-next-line */
171
- }, [version]);
172
-
173
- React.useEffect(() => {
174
- if (__CLIENT__ && tableau && url) {
175
- initViz();
176
- } else {
177
- disposeViz();
178
- }
179
-
180
- return () => {
181
- disposeViz();
182
- };
183
- /* eslint-disable-next-line */
184
- }, [
185
- hideTabs,
186
- hideToolbar,
187
- autoScale,
188
- sheetname,
189
- tableau,
190
- toolbarPosition,
191
- url,
192
- version,
193
- ]);
194
-
195
- React.useEffect(() => {
196
- if (mounted.current && loaded && viz) {
197
- addExtraFilters(extraFilters);
198
- }
199
- /* eslint-disable-next-line */
200
- }, [JSON.stringify(extraFilters)]);
201
-
202
- React.useEffect(() => {
203
- if (autoScale) {
204
- updateScale();
205
- }
206
- /* eslint-disable-next-line */
207
- }, [loaded, screen?.page?.width]);
208
-
209
- return (
210
- <div id="tableau-wrap">
211
- <div id="tableau-outer">
212
- {data && Object.keys(data).length > 0 ? (
213
- <>
214
- {loaded ? (
215
- ''
216
- ) : (
217
- <div className="tableau-loader">
218
- <span>Loading...</span>
219
- </div>
220
- )}
221
- </>
222
- ) : (
223
- <div>No data present in that visualization.</div>
224
- )}
225
- <div className="dashboard-wrapper">
226
- <div className="tableau-block">
227
- {viz ? (
228
- <div className="tableau-icons">
229
- <TableauDownload {...props} viz={viz} />
230
- <TableauShare {...props} viz={viz} data={{ url: url }} />
231
- </div>
232
- ) : null}
233
- <div
234
- className={cx('tableau', version, {
235
- 'tableau-scale': autoScale,
236
- })}
237
- ref={ref}
238
- />
239
- </div>
240
- </div>
241
- </div>
242
- </div>
243
- );
244
- };
245
-
246
- export default compose(
247
- connect(
248
- (state, props) => ({
249
- tableau: state.tableau,
250
- screen: state.screen,
251
- }),
252
- { setTableauApi },
253
- ),
254
- )(Tableau);
@@ -1,8 +0,0 @@
1
- .sidebar-container-enter-done {
2
- z-index: 1001 !important;
3
- }
4
-
5
- .field-provider-data-action-button {
6
- border: 1px solid #c7d5d8;
7
- cursor: pointer;
8
- }
package/src/actions.js DELETED
@@ -1,9 +0,0 @@
1
- import { SET_TABLEAU_API } from '@eeacms/volto-tableau/constants';
2
-
3
- export const setTableauApi = (version, mode = 'view') => {
4
- return {
5
- type: `${SET_TABLEAU_API}_PENDING`,
6
- version,
7
- mode,
8
- };
9
- };
package/src/constants.js DELETED
@@ -1 +0,0 @@
1
- export const SET_TABLEAU_API = 'SET_TABLEAU_API';
@@ -1,25 +0,0 @@
1
- import React from 'react';
2
-
3
- const useCopyToClipboard = (text) => {
4
- const [copyStatus, setCopyStatus] = React.useState('inactive');
5
- const copy = React.useCallback(() => {
6
- navigator.clipboard.writeText(text).then(
7
- () => setCopyStatus('copied'),
8
- () => setCopyStatus('failed'),
9
- );
10
- }, [text]);
11
-
12
- React.useEffect(() => {
13
- if (copyStatus === 'inactive') {
14
- return;
15
- }
16
-
17
- const timeout = setTimeout(() => setCopyStatus('inactive'), 3000);
18
-
19
- return () => clearTimeout(timeout);
20
- }, [copyStatus]);
21
-
22
- return [copyStatus, copy];
23
- };
24
-
25
- export default useCopyToClipboard;
package/src/middleware.js DELETED
@@ -1,39 +0,0 @@
1
- import { SET_TABLEAU_API } from '@eeacms/volto-tableau/constants';
2
-
3
- //need to see if we need redux anymore for this
4
- export default (middlewares) => [
5
- (store) => (next) => (action) => {
6
- const state = store.getState();
7
- const { version = '' } = action || {};
8
-
9
- if (
10
- action.type === `${SET_TABLEAU_API}_PENDING` &&
11
- !state.tableau.loading[version]
12
- ) {
13
- // loadTableauScript(() => {}, version);
14
- // fetchTableau(version)
15
- // .then((response) => {
16
- // if (mode === 'edit') {
17
- // toast.success(<Toast success title={response.message} />);
18
- // }
19
- // store.dispatch({
20
- // type: `${SET_TABLEAU_API}_SUCCESS`,
21
- // version,
22
- // api: response,
23
- // });
24
- // })
25
- // .catch((error) => {
26
- // if (mode === 'edit') {
27
- // toast.error(<Toast error title={error.message} />);
28
- // }
29
- // store.dispatch({
30
- // type: `${SET_TABLEAU_API}_FAILED`,
31
- // version,
32
- // });
33
- // });
34
- }
35
-
36
- return next(action);
37
- },
38
- ...middlewares,
39
- ];
package/src/store.js DELETED
@@ -1,72 +0,0 @@
1
- import { SET_TABLEAU_API } from '@eeacms/volto-tableau/constants';
2
-
3
- const initialState = {
4
- loading: {},
5
- loaded: {},
6
- errors: {},
7
- };
8
-
9
- export default function tableau(state = initialState, action = {}) {
10
- const loading = { ...state.loading };
11
- const loaded = { ...state.loaded };
12
- const errors = { ...state.errors };
13
-
14
- switch (action.type) {
15
- case `${SET_TABLEAU_API}_PENDING`:
16
- loading[action.version] = true;
17
- loaded[action.version] = false;
18
- errors[action.version] = false;
19
-
20
- return {
21
- ...state,
22
- loading: {
23
- ...loading,
24
- },
25
- loaded: {
26
- ...loaded,
27
- },
28
- errors: {
29
- ...errors,
30
- },
31
- };
32
-
33
- case `${SET_TABLEAU_API}_SUCCESS`:
34
- loading[action.version] = false;
35
- loaded[action.version] = true;
36
- errors[action.version] = false;
37
- return {
38
- ...state,
39
- [action.version]: action.api,
40
- loading: {
41
- ...loading,
42
- },
43
- loaded: {
44
- ...loaded,
45
- },
46
- errors: {
47
- ...errors,
48
- },
49
- };
50
-
51
- case `${SET_TABLEAU_API}_FAILED`:
52
- loading[action.version] = false;
53
- loaded[action.version] = false;
54
- errors[action.version] = true;
55
-
56
- return {
57
- ...state,
58
- loading: {
59
- ...loading,
60
- },
61
- loaded: {
62
- ...loaded,
63
- },
64
- errors: {
65
- ...errors,
66
- },
67
- };
68
-
69
- default:
70
- return state;
71
- }
72
- }