@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 +7 -1
- package/package.json +1 -1
- package/src/Blocks/EmbedTableauVisualization/View.jsx +8 -5
- package/src/Blocks/EmbedTableauVisualization/index.js +3 -3
- package/src/Blocks/EmbedTableauVisualization/schema.js +3 -0
- package/src/Blocks/TableauBlock/Edit.jsx +11 -2
- package/src/Blocks/TableauBlock/View.jsx +47 -44
- package/src/Blocks/TableauBlock/index.js +3 -3
- package/src/Blocks/TableauBlock/schema.js +158 -106
- package/src/Tableau/Tableau.jsx +257 -90
- package/src/Tableau/helpers.js +41 -0
- package/src/Utils/Download/Download.jsx +4 -4
- package/src/Utils/JsonCodeSnippet/JsonCodeSnippet.jsx +48 -0
- package/src/Views/VisualizationView.jsx +10 -4
- package/src/Widgets/VisualizationWidget.jsx +38 -4
- package/src/Widgets/schema.js +115 -73
- package/src/less/tableau.less +46 -3
- package/src/less/tableau.variables +2 -1
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.
|
|
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
|
@@ -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={
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
)}
|
|
@@ -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
|
|
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
|
|
11
|
-
const
|
|
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 = {},
|
|
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
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
39
|
+
const newFilters = { ...extraFilters };
|
|
51
40
|
urlParameters.forEach((element) => {
|
|
52
41
|
if (element.field && typeof query[element.urlParam] !== 'undefined') {
|
|
53
|
-
|
|
54
|
-
} else if (
|
|
55
|
-
delete
|
|
42
|
+
newFilters[element.field] = query[element.urlParam];
|
|
43
|
+
} else if (newFilters[element.field]) {
|
|
44
|
+
delete newFilters[element.field];
|
|
56
45
|
}
|
|
57
46
|
});
|
|
58
|
-
setExtraFilters(
|
|
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
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
91
|
-
|
|
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
|
-
|
|
97
|
+
}),
|
|
98
|
+
null,
|
|
99
|
+
null,
|
|
100
|
+
{ forwardRef: true },
|
|
101
|
+
)(View);
|
|
@@ -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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
'
|
|
87
|
-
'
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
172
|
-
}
|
|
222
|
+
required: ['url'],
|
|
223
|
+
};
|
|
224
|
+
};
|