@eeacms/volto-tableau 4.0.0 → 4.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,7 +4,13 @@ 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
- ### [4.0.0](https://github.com/eea/volto-tableau/compare/3.0.8...4.0.0) - 13 June 2023
7
+ ### [4.1.0](https://github.com/eea/volto-tableau/compare/4.0.0...4.1.0) - 15 June 2023
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat: improved tableau [Miu Razvan - [`4189653`](https://github.com/eea/volto-tableau/commit/41896533c23857cc4ffc9517b042b1066dfe590b)]
12
+
13
+ ## [4.0.0](https://github.com/eea/volto-tableau/compare/3.0.8...4.0.0) - 13 June 2023
8
14
 
9
15
  #### :house: Internal changes
10
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-tableau",
3
- "version": "4.0.0",
3
+ "version": "4.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",
@@ -10,6 +10,7 @@ import { compose } from 'redux';
10
10
 
11
11
  const View = (props) => {
12
12
  const data = props.data;
13
+ const { with_sources = true, with_download = true, with_share = true } = data;
13
14
  const { data_provenance, tableau_visualization } =
14
15
  props.tableau_visualization_data || {};
15
16
  const tableau_vis_url = flattenToAppURL(data.tableau_vis_url || '');
@@ -28,7 +29,7 @@ const View = (props) => {
28
29
  data={{ ...data, url: tableau_visualization?.url }}
29
30
  >
30
31
  {!tableau_vis_url && (
31
- <div>Please select a visualization from block editor.</div>
32
+ <div>Please select a tableau visualization from block editor.</div>
32
33
  )}
33
34
  {!!tableau_vis_url && (
34
35
  <>
@@ -37,10 +38,12 @@ const View = (props) => {
37
38
  )}
38
39
  {!!tableau_visualization?.url && (
39
40
  <Tableau
40
- data={tableau_visualization}
41
- with_sources={true}
42
- with_download={true}
43
- with_share={true}
41
+ data={{
42
+ ...tableau_visualization,
43
+ with_sources,
44
+ with_download,
45
+ with_share,
46
+ }}
44
47
  sources={data_provenance.data || []}
45
48
  />
46
49
  )}
@@ -20,9 +20,9 @@ export default (config) => {
20
20
  view: [],
21
21
  },
22
22
  breakpoints: {
23
- desktop: [Infinity, 982],
24
- tablet: [981, 768],
25
- mobile: [767, 0],
23
+ desktop: [Infinity, 992],
24
+ tablet: [991, 768],
25
+ phone: [767, 0],
26
26
  },
27
27
  };
28
28
 
@@ -68,14 +68,17 @@ export default () => {
68
68
  with_download: {
69
69
  title: 'Show download button',
70
70
  type: 'boolean',
71
+ defaultValue: true,
71
72
  },
72
73
  with_share: {
73
74
  title: 'Show share button',
74
75
  type: 'boolean',
76
+ defaultValue: true,
75
77
  },
76
78
  with_sources: {
77
79
  title: 'Show sources',
78
80
  type: 'boolean',
81
+ defaultValue: true,
79
82
  },
80
83
  dataprotection: {
81
84
  widget: 'object',
@@ -6,11 +6,20 @@ import getSchema from './schema';
6
6
  import View from './View';
7
7
 
8
8
  const Edit = (props) => {
9
- const [schema] = React.useState(getSchema(config));
9
+ const viz = React.useRef();
10
+ const [vizState, setVizState] = React.useState({
11
+ loaded: false,
12
+ loading: false,
13
+ error: null,
14
+ });
15
+
16
+ const schema = React.useMemo(() => getSchema(config, viz.current, vizState), [
17
+ vizState,
18
+ ]);
10
19
 
11
20
  return (
12
21
  <>
13
- <View {...props} mode="edit" />
22
+ <View {...props} mode="edit" setVizState={setVizState} ref={viz} />
14
23
  <SidebarPortal selected={props.selected}>
15
24
  <BlockDataForm
16
25
  block={props.block}
@@ -1,64 +1,64 @@
1
1
  import React from 'react';
2
2
  import { connect } from 'react-redux';
3
- import { compose } from 'redux';
4
- import { withRouter } from 'react-router';
5
3
  import Tableau from '@eeacms/volto-tableau/Tableau/Tableau';
6
- import config from '@plone/volto/registry';
7
4
  import qs from 'querystring';
5
+ import config from '@plone/volto/registry';
8
6
  import '@eeacms/volto-tableau/less/tableau.less';
9
7
 
10
- const getDevice = (config, width) => {
11
- const breakpoints = config.blocks.blocksConfig.tableau_block.breakpoints;
12
- let device = 'default';
13
- Object.keys(breakpoints).forEach((breakpoint) => {
14
- if (
15
- width <= breakpoints[breakpoint][0] &&
16
- width >= breakpoints[breakpoint][1]
17
- ) {
18
- device = breakpoint;
19
- }
20
- });
21
- return device;
22
- };
23
-
24
- const View = (props) => {
8
+ const View = React.forwardRef((props, ref) => {
9
+ const viz = React.useRef();
25
10
  const [vizState, setVizState] = React.useState({
26
11
  loaded: false,
27
12
  loading: false,
28
13
  error: null,
29
14
  });
30
15
  const [extraFilters, setExtraFilters] = React.useState({});
31
- const { data = {}, query = {}, screen = {} } = props;
16
+ const { block, data = {}, query = {}, onChangeBlock, mode } = props;
32
17
  const {
33
- breakpointUrls = [],
34
18
  urlParameters = [],
19
+ staticParameters = [],
35
20
  title = null,
36
21
  description = null,
37
- autoScale = false,
38
22
  with_sources = true,
39
23
  with_download = true,
40
24
  with_share = true,
41
25
  sources,
42
26
  } = data;
43
- const device = getDevice(config, screen.page?.width || Infinity);
44
- const breakpointUrl = breakpointUrls.filter(
45
- (breakpoint) => breakpoint.device === device,
46
- )[0]?.url;
47
- const url = breakpointUrl || data.url;
27
+
28
+ const extraOptions = React.useMemo(() => {
29
+ const options = {};
30
+ staticParameters.forEach((parameter) => {
31
+ if (parameter.field) {
32
+ options[parameter.field] = parameter.value;
33
+ }
34
+ });
35
+ return options;
36
+ }, [staticParameters]);
48
37
 
49
38
  React.useEffect(() => {
50
- const newExtraFilters = { ...extraFilters };
39
+ const newFilters = { ...extraFilters };
51
40
  urlParameters.forEach((element) => {
52
41
  if (element.field && typeof query[element.urlParam] !== 'undefined') {
53
- newExtraFilters[element.field] = query[element.urlParam];
54
- } else if (newExtraFilters[element.field]) {
55
- delete newExtraFilters[element.field];
42
+ newFilters[element.field] = query[element.urlParam];
43
+ } else if (newFilters[element.field]) {
44
+ delete newFilters[element.field];
56
45
  }
57
46
  });
58
- setExtraFilters(newExtraFilters);
47
+ setExtraFilters(newFilters);
59
48
  /* eslint-disable-next-line */
60
49
  }, [JSON.stringify(query), JSON.stringify(urlParameters)]);
61
50
 
51
+ React.useImperativeHandle(ref, () => {
52
+ return viz.current;
53
+ });
54
+
55
+ React.useEffect(() => {
56
+ if (props.setVizState) {
57
+ props.setVizState(vizState);
58
+ }
59
+ /* eslint-disable-next-line */
60
+ }, [vizState]);
61
+
62
62
  return (
63
63
  <div className="tableau-block">
64
64
  {vizState.loaded && title ? (
@@ -72,27 +72,30 @@ const View = (props) => {
72
72
  ''
73
73
  )}
74
74
  <Tableau
75
- {...props}
76
- canUpdateUrl={!breakpointUrl}
77
- extraFilters={extraFilters}
78
- extraOptions={{ device: autoScale ? 'desktop' : device }}
79
- url={url}
80
- with_sources={with_sources}
81
- with_download={with_download}
82
- with_share={with_share}
75
+ ref={viz}
76
+ mode={mode}
77
+ block={block}
78
+ data={{ ...data, with_sources, with_download, with_share }}
83
79
  sources={sources}
80
+ extraFilters={extraFilters}
81
+ extraOptions={extraOptions}
82
+ breakpoints={config.blocks.blocksConfig.tableau_block.breakpoints}
84
83
  setVizState={setVizState}
84
+ onChangeBlock={onChangeBlock}
85
85
  />
86
86
  </div>
87
87
  );
88
- };
88
+ });
89
89
 
90
- export default compose(
91
- connect((state, props) => ({
90
+ export default connect(
91
+ (state) => ({
92
92
  query: {
93
93
  ...(qs.parse(state.router.location?.search?.replace('?', '')) || {}),
94
94
  ...(state.discodata_query?.search || {}),
95
95
  },
96
96
  screen: state.screen,
97
- })),
98
- )(withRouter(View));
97
+ }),
98
+ null,
99
+ null,
100
+ { forwardRef: true },
101
+ )(View);
@@ -20,9 +20,9 @@ export default (config) => {
20
20
  view: [],
21
21
  },
22
22
  breakpoints: {
23
- desktop: [Infinity, 982],
24
- tablet: [981, 768],
25
- mobile: [767, 0],
23
+ desktop: [Infinity, 992],
24
+ tablet: [991, 768],
25
+ phone: [767, 0],
26
26
  },
27
27
  };
28
28
 
@@ -1,3 +1,8 @@
1
+ import {
2
+ getSheetnamesChoices,
3
+ canChangeVizData,
4
+ } from '@eeacms/volto-tableau/Tableau/helpers';
5
+
1
6
  const urlParametersSchema = {
2
7
  title: 'Parameter',
3
8
  fieldsets: [
@@ -16,6 +21,22 @@ const urlParametersSchema = {
16
21
  required: [],
17
22
  };
18
23
 
24
+ const staticParameters = {
25
+ title: 'Parameter',
26
+ fieldsets: [{ id: 'default', title: 'Default', fields: ['field', 'value'] }],
27
+ properties: {
28
+ field: {
29
+ title: 'Tableau fieldname',
30
+ type: 'text',
31
+ },
32
+ value: {
33
+ title: 'Value',
34
+ type: 'text',
35
+ },
36
+ },
37
+ required: [],
38
+ };
39
+
19
40
  const breakpointUrlSchema = (config) => {
20
41
  const breakpoints = config.blocks.blocksConfig.tableau_block.breakpoints;
21
42
 
@@ -25,7 +46,6 @@ const breakpointUrlSchema = (config) => {
25
46
  properties: {
26
47
  device: {
27
48
  title: 'Device',
28
- type: 'array',
29
49
  choices: Object.keys(breakpoints).map((breakpoint) => [
30
50
  breakpoint,
31
51
  breakpoint,
@@ -64,109 +84,141 @@ const sourceSchema = {
64
84
  required: [],
65
85
  };
66
86
 
67
- export default (config) => ({
68
- title: 'Tableau',
69
- fieldsets: [
70
- {
71
- id: 'default',
72
- title: 'Default',
73
- fields: ['url', 'title', 'description', 'with_download', 'with_share'],
74
- },
75
- {
76
- id: 'sources',
77
- title: 'Sources',
78
- fields: ['with_sources', 'sources'],
79
- },
80
- {
81
- id: 'options',
82
- title: 'Options',
83
- fields: [
84
- 'sheetname',
85
- 'hideTabs',
86
- 'hideToolbar',
87
- 'autoScale',
88
- 'toolbarPosition',
89
- ],
90
- },
91
- {
92
- id: 'extra_options',
93
- title: 'Extra options',
94
- fields: ['urlParameters', 'breakpointUrls'],
95
- },
96
- ],
97
- properties: {
98
- url: {
99
- title: 'Url',
100
- widget: 'textarea',
101
- },
102
- title: {
103
- title: 'Title',
104
- widget: 'textarea',
105
- },
106
- description: {
107
- title: 'Description',
108
- widget: 'textarea',
109
- },
110
- with_download: {
111
- title: 'Show download button',
112
- type: 'boolean',
113
- defaultValue: true,
114
- },
115
- with_share: {
116
- title: 'Show share button',
117
- type: 'boolean',
118
- defaultValue: true,
119
- },
120
- with_sources: {
121
- title: 'Show sources',
122
- type: 'boolean',
123
- defaultValue: true,
124
- },
125
- sources: {
126
- title: 'Sources',
127
- widget: 'object_list',
128
- schema: sourceSchema,
129
- },
130
- sheetname: {
131
- title: 'Sheetname',
132
- type: 'text',
133
- },
134
- hideTabs: {
135
- title: 'Hide tabs',
136
- type: 'boolean',
137
- default: false,
138
- },
139
- hideToolbar: {
140
- title: 'Hide toolbar',
141
- type: 'boolean',
142
- default: false,
143
- },
144
- autoScale: {
145
- title: 'Auto scale',
146
- type: 'boolean',
147
- default: false,
148
- description: 'Scale down tableau according to width',
149
- },
150
- toolbarPosition: {
151
- title: 'Toolbar position',
152
- choices: [
153
- ['Top', 'Top'],
154
- ['Bottom', 'Bottom'],
155
- ],
156
- default: 'Top',
157
- },
158
- urlParameters: {
159
- title: 'URL parameters',
160
- widget: 'object_list',
161
- schema: urlParametersSchema,
162
- description: 'Set a list of url parameters to filter the tableau',
163
- },
164
- breakpointUrls: {
165
- title: 'Breakpoint urls',
166
- widget: 'object_list',
167
- schema: breakpointUrlSchema(config),
168
- description: 'Set different vizualization for specific breakpoint',
87
+ export default (config, viz, vizState) => {
88
+ const isDisabled = !canChangeVizData(viz, vizState);
89
+
90
+ return {
91
+ title: 'Tableau',
92
+ fieldsets: [
93
+ {
94
+ id: 'default',
95
+ title: 'Default',
96
+ fields: [
97
+ 'url',
98
+ 'title',
99
+ 'description',
100
+ 'with_sources',
101
+ 'with_download',
102
+ 'with_share',
103
+ ],
104
+ },
105
+ {
106
+ id: 'options',
107
+ title: 'Options',
108
+ fields: [
109
+ 'sheetname',
110
+ 'hideTabs',
111
+ 'hideToolbar',
112
+ 'autoScale',
113
+ 'toolbarPosition',
114
+ ],
115
+ },
116
+ {
117
+ id: 'extra_options',
118
+ title: 'Extra options',
119
+ fields: ['urlParameters', 'staticParameters', 'breakpointUrls'],
120
+ },
121
+ {
122
+ id: 'sources',
123
+ title: 'Sources',
124
+ fields: ['sources'],
125
+ },
126
+ ],
127
+ properties: {
128
+ url: {
129
+ title: 'Url',
130
+ widget: 'textarea',
131
+ isDisabled,
132
+ },
133
+ title: {
134
+ title: 'Title',
135
+ widget: 'textarea',
136
+ },
137
+ description: {
138
+ title: 'Description',
139
+ widget: 'textarea',
140
+ },
141
+ with_download: {
142
+ title: 'Show download button',
143
+ type: 'boolean',
144
+ defaultValue: true,
145
+ },
146
+ with_share: {
147
+ title: 'Show share button',
148
+ type: 'boolean',
149
+ defaultValue: true,
150
+ },
151
+ with_sources: {
152
+ title: 'Show sources',
153
+ type: 'boolean',
154
+ defaultValue: true,
155
+ },
156
+ sources: {
157
+ title: 'Sources',
158
+ widget: 'object_list',
159
+ schema: sourceSchema,
160
+ },
161
+ sheetname: {
162
+ title: 'Sheetname',
163
+ choices: getSheetnamesChoices(viz),
164
+ isDisabled,
165
+ },
166
+ hideTabs: {
167
+ title: 'Hide tabs',
168
+ type: 'boolean',
169
+ default: false,
170
+ isDisabled,
171
+ },
172
+ hideToolbar: {
173
+ title: 'Hide toolbar',
174
+ type: 'boolean',
175
+ default: false,
176
+ isDisabled,
177
+ },
178
+ autoScale: {
179
+ title: 'Auto scale',
180
+ type: 'boolean',
181
+ default: false,
182
+ description: 'Scale down tableau according to width',
183
+ isDisabled,
184
+ },
185
+ toolbarPosition: {
186
+ title: 'Toolbar position',
187
+ choices: [
188
+ ['Top', 'Top'],
189
+ ['Bottom', 'Bottom'],
190
+ ],
191
+ default: 'Top',
192
+ isDisabled,
193
+ },
194
+ urlParameters: {
195
+ title: 'URL parameters',
196
+ widget: 'object_list',
197
+ schema: urlParametersSchema,
198
+ description: 'Set a list of url parameters to filter the tableau',
199
+ isDisabled,
200
+ },
201
+ staticParameters: {
202
+ title: 'Static parameters',
203
+ widget: 'object_list',
204
+ schema: staticParameters,
205
+ description: (
206
+ <>
207
+ Set a list of static parameters.
208
+ <br />
209
+ <b>NOTE: You need to trigger a refresh for this to take effect</b>
210
+ </>
211
+ ),
212
+ isDisabled,
213
+ },
214
+ breakpointUrls: {
215
+ title: 'Breakpoint urls',
216
+ widget: 'object_list',
217
+ schema: breakpointUrlSchema(config),
218
+ description: 'Set different vizualization for specific breakpoint',
219
+ isDisabled,
220
+ },
169
221
  },
170
- },
171
- required: ['url'],
172
- });
222
+ required: ['url'],
223
+ };
224
+ };