@eeacms/volto-tableau 3.0.7 → 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 +23 -6
  2. package/Jenkinsfile +2 -0
  3. package/jest-addon.config.js +2 -2
  4. package/package.json +9 -4
  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 -71
  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,27 +1,53 @@
1
- const generalSchema = {
2
- title: 'General',
3
-
1
+ const urlParametersSchema = {
2
+ title: 'Parameter',
4
3
  fieldsets: [
5
- {
6
- id: 'general',
7
- title: 'General',
8
- fields: ['url'],
9
- },
4
+ { id: 'default', title: 'Default', fields: ['field', 'urlParam'] },
10
5
  ],
11
-
12
6
  properties: {
13
- url: {
14
- title: 'Url',
15
- type: 'textarea',
7
+ field: {
8
+ title: 'Tableau fieldname',
9
+ type: 'text',
10
+ },
11
+ urlParam: {
12
+ title: 'URL param',
13
+ type: 'text',
16
14
  },
17
15
  },
18
- required: ['url'],
16
+ required: [],
19
17
  };
20
18
 
21
- const optionsSchema = {
22
- title: 'Options',
19
+ const breakpointUrlSchema = (config) => {
20
+ const breakpoints = config.blocks.blocksConfig.tableau_block.breakpoints;
21
+
22
+ return {
23
+ title: 'URL',
24
+ fieldsets: [{ id: 'default', title: 'Default', fields: ['device', 'url'] }],
25
+ properties: {
26
+ device: {
27
+ title: 'Device',
28
+ type: 'array',
29
+ choices: Object.keys(breakpoints).map((breakpoint) => [
30
+ breakpoint,
31
+ breakpoint,
32
+ ]),
33
+ },
34
+ url: {
35
+ title: 'Url',
36
+ widget: 'textarea',
37
+ },
38
+ },
39
+ required: [],
40
+ };
41
+ };
23
42
 
43
+ export default (config) => ({
44
+ title: 'Tableau',
24
45
  fieldsets: [
46
+ {
47
+ id: 'default',
48
+ title: 'Default',
49
+ fields: ['url'],
50
+ },
25
51
  {
26
52
  id: 'options',
27
53
  title: 'Options',
@@ -33,9 +59,17 @@ const optionsSchema = {
33
59
  'toolbarPosition',
34
60
  ],
35
61
  },
62
+ {
63
+ id: 'extra_options',
64
+ title: 'Extra options',
65
+ fields: ['urlParameters', 'breakpointUrls'],
66
+ },
36
67
  ],
37
-
38
68
  properties: {
69
+ url: {
70
+ title: 'Url',
71
+ widget: 'textarea',
72
+ },
39
73
  sheetname: {
40
74
  title: 'Sheetname',
41
75
  type: 'text',
@@ -58,127 +92,24 @@ const optionsSchema = {
58
92
  },
59
93
  toolbarPosition: {
60
94
  title: 'Toolbar position',
61
- type: 'array',
62
95
  choices: [
63
96
  ['Top', 'Top'],
64
97
  ['Bottom', 'Bottom'],
65
98
  ],
66
99
  default: 'Top',
67
100
  },
68
- },
69
- required: [],
70
- };
71
-
72
- const urlParametersSchema = {
73
- title: 'Parameter',
74
- fieldsets: [
75
- {
76
- id: 'default',
77
- title: 'Default',
78
- fields: ['field', 'urlParam'],
79
- },
80
- ],
81
- properties: {
82
- field: {
83
- title: 'Tableau fieldname',
84
- type: 'text',
101
+ urlParameters: {
102
+ title: 'URL parameters',
103
+ widget: 'object_list',
104
+ schema: urlParametersSchema,
105
+ description: 'Set a list of url parameters to filter the tableau',
85
106
  },
86
- urlParam: {
87
- title: 'URL param',
88
- type: 'text',
107
+ breakpointUrls: {
108
+ title: 'Breakpoint urls',
109
+ widget: 'object_list',
110
+ schema: breakpointUrlSchema(config),
111
+ description: 'Set different vizualization for specific breakpoint',
89
112
  },
90
113
  },
91
- required: [],
92
- };
93
-
94
- const breakpointUrlSchema = (config) => {
95
- const breakpoints = config.blocks.blocksConfig.tableau_block.breakpoints;
96
-
97
- return {
98
- title: 'URL',
99
- fieldsets: [{ id: 'default', title: 'Default', fields: ['device', 'url'] }],
100
- properties: {
101
- device: {
102
- title: 'Device',
103
- type: 'array',
104
- choices: Object.keys(breakpoints).map((breakpoint) => [
105
- breakpoint,
106
- breakpoint,
107
- ]),
108
- },
109
- url: {
110
- title: 'Url',
111
- widget: 'textarea',
112
- },
113
- },
114
- required: [],
115
- };
116
- };
117
-
118
- const extraOptionsSchema = (config) => {
119
- return {
120
- title: 'Extra Options',
121
-
122
- fieldsets: [
123
- {
124
- id: 'default',
125
- title: 'Extra Options Data',
126
- fields: ['urlParameters', 'availableFields', 'breakpointUrls'],
127
- },
128
- ],
129
-
130
- properties: {
131
- urlParameters: {
132
- title: 'URL parameters',
133
- widget: 'object_list',
134
- schema: urlParametersSchema,
135
- description: 'Set a list of url parameters to filter the tableau',
136
- },
137
- availableFields: {
138
- title: 'Available Fields:',
139
- widget: 'url_params_widget',
140
- },
141
- breakpointUrls: {
142
- title: 'Breakpoint urls',
143
- widget: 'object_list',
144
- schema: breakpointUrlSchema(config),
145
- description: 'Set different vizualization for specific breakpoint',
146
- },
147
- },
148
- required: [],
149
- };
150
- };
151
-
152
- export default (config) => {
153
- return {
154
- title: 'Tableau Editor',
155
- fieldsets: [
156
- {
157
- id: 'default',
158
- title: 'Tableau Editor Sections',
159
- fields: ['tableau_data'],
160
- },
161
- ],
162
- properties: {
163
- tableau_data: {
164
- title: 'Panels',
165
- widget: 'object_types_widget',
166
- schemas: [
167
- {
168
- id: 'general',
169
- schema: generalSchema,
170
- },
171
- {
172
- id: 'options',
173
- schema: optionsSchema,
174
- },
175
- {
176
- id: 'extraOptions',
177
- schema: extraOptionsSchema(config),
178
- },
179
- ],
180
- },
181
- },
182
- required: [],
183
- };
184
- };
114
+ required: ['url'],
115
+ });
package/src/helpers.js CHANGED
@@ -1,47 +1,28 @@
1
- const loadTableauScript = (callback, version) => {
2
- const existingScript = __CLIENT__ && document.getElementById(`tableauJS`);
3
- //replace script loaded on each version change
4
- if (existingScript) {
5
- existingScript.setAttribute(
6
- 'src',
7
- `https://public.tableau.com/javascripts/api/tableau-${version}.min.js`,
8
- );
1
+ export const loadTableauScript = (callback, version) => {
2
+ if (!__CLIENT__) return;
3
+ const source = `https://public.tableau.com/javascripts/api/tableau-${version}.min.js`;
4
+ const existingScript = document.getElementById(`tableauJS-${version}`);
5
+ const existingScriptSource =
6
+ existingScript && existingScript.getAttribute('src');
7
+ // Replace script loaded on each version change
8
+ if (existingScript && existingScriptSource !== source) {
9
+ existingScript.setAttribute('src', source);
9
10
  }
10
- if (!existingScript && __CLIENT__) {
11
+ if (!existingScript) {
11
12
  const script = document.createElement('script');
12
- script.src = `https://public.tableau.com/javascripts/api/tableau-${version}.min.js`;
13
- script.id = `tableauJS`;
13
+ script.src = source;
14
+ script.id = `tableauJS-${version}`;
14
15
  document.body.appendChild(script);
15
16
  script.onload = () => {
17
+ window[`tableau_${version}`] = window.tableau;
16
18
  if (callback) callback();
17
19
  };
18
20
  }
19
- //callback, if needed
21
+ // Trigger callback
20
22
  if (existingScript && callback) callback();
21
-
22
- const tableau = isMyScriptLoaded(version) && __CLIENT__ ? window.tableau : '';
23
- return tableau;
24
23
  };
25
24
 
26
- const isMyScriptLoaded = (version) => {
27
- //check for loaded Tableau script in dom scripts
28
- var scripts = __CLIENT__ && document.getElementsByTagName('script');
29
- if (scripts) {
30
- for (var i = scripts.length; i--; ) {
31
- // eslint-disable-next-line eqeqeq
32
- if (
33
- scripts[i].src ===
34
- `https://public.tableau.com/javascripts/api/tableau-${version}.min.js`
35
- )
36
- return true;
37
- }
38
- }
39
- return false;
40
- };
41
-
42
- export { loadTableauScript, isMyScriptLoaded };
43
-
44
- //script url for each version. In case you might need to add them in the load balancer
25
+ // Script url for each version. In case you might need to add them in the load balancer
45
26
  // https://public.tableau.com/javascripts/api/tableau-2.8.0.min.js
46
27
  // https://public.tableau.com/javascripts/api/tableau-2.7.0.min.js
47
28
  // https://public.tableau.com/javascripts/api/tableau-2.6.0.min.js
package/src/hooks.js ADDED
@@ -0,0 +1,18 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { loadTableauScript } from './helpers';
3
+
4
+ export const useTableau = (version) => {
5
+ const [tableau, setTableau] = useState();
6
+
7
+ useEffect(() => {
8
+ loadTableauScript(() => {
9
+ if (window[`tableau_${version}`]) {
10
+ setTableau(window[`tableau_${version}`]);
11
+ } else {
12
+ setTableau(undefined);
13
+ }
14
+ }, version);
15
+ }, [version]);
16
+
17
+ return tableau;
18
+ };
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
2
+ <path
3
+ d="M4 19H20V12H22V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V12H4V19ZM14 9H19L12 16L5 9H10V3H14V9Z">
4
+ </path>
5
+ </svg>
package/src/index.js CHANGED
@@ -1,81 +1,19 @@
1
- import sliderSVG from '@plone/volto/icons/slider.svg';
2
- import TableauEdit from './TableauBlock/Edit';
3
- import TableauView from './TableauBlock/View';
4
- import EmbedTableauView from './Blocks/EmbedEEATableauBlock/View';
5
- import EmbedTableauEdit from './Blocks/EmbedEEATableauBlock/Edit';
1
+ import installBlocks from './Blocks';
6
2
  import { VisualizationView } from './Views';
7
3
  import { VisualizationWidget } from './Widgets';
8
- import UrlParamsWidget from './CustomWidgets/UrlParamsWidget';
9
-
10
- import tableauStore from './store';
11
-
12
- import tableauMiddleware from './middleware';
13
4
 
14
5
  const applyConfig = (config) => {
15
- config.addonReducers = {
16
- ...config.addonReducers,
17
- tableau: tableauStore,
18
- };
19
-
20
6
  config.settings.allowed_cors_destinations = [
21
7
  ...(config.settings.allowed_cors_destinations || []),
22
8
  'public.tableau.com',
23
9
  ];
24
10
 
25
- config.settings.storeExtenders = [
26
- ...(config.settings.storeExtenders || []),
27
- tableauMiddleware,
28
- ];
29
-
30
- config.blocks.blocksConfig.tableau_block = {
31
- id: 'tableau_block',
32
- title: 'Tableau',
33
- icon: sliderSVG,
34
- group: 'common',
35
- edit: TableauEdit,
36
- view: TableauView,
37
- restricted: false,
38
- mostUsed: false,
39
- sidebarTab: 1,
40
- blocks: {},
41
- security: {
42
- addPermission: [],
43
- view: [],
44
- },
45
- breakpoints: {
46
- desktop: [Infinity, 982],
47
- tablet: [981, 768],
48
- mobile: [767, 0],
49
- },
50
- };
51
-
52
- config.blocks.blocksConfig.embed_eea_tableau_block = {
53
- id: 'embed_eea_tableau_block',
54
- title: 'Embed EEA Tableau',
55
- icon: sliderSVG,
56
- group: 'common',
57
- edit: EmbedTableauEdit,
58
- view: EmbedTableauView,
59
- restricted: false,
60
- mostUsed: false,
61
- sidebarTab: 1,
62
- blocks: {},
63
- security: {
64
- addPermission: [],
65
- view: [],
66
- },
67
- breakpoints: {
68
- desktop: [Infinity, 982],
69
- tablet: [981, 768],
70
- mobile: [767, 0],
71
- },
72
- };
11
+ config.settings.storeExtenders = [...(config.settings.storeExtenders || [])];
73
12
 
74
13
  config.views.contentTypesViews.tableau_visualization = VisualizationView;
75
- config.widgets.id.tableau_visualization_data = VisualizationWidget;
76
- config.widgets.widget.url_params_widget = UrlParamsWidget;
14
+ config.widgets.id.tableau_visualization = VisualizationWidget;
77
15
 
78
- return config;
16
+ return [installBlocks].reduce((acc, apply) => apply(acc), config);
79
17
  };
80
18
 
81
19
  export default applyConfig;
@@ -6,43 +6,34 @@
6
6
 
7
7
  .loadAddonVariables();
8
8
 
9
- .tableau-block {
10
- .tableau-info {
11
- h3.tableau-version {
12
- display: flex;
13
- height: 75px;
14
- align-items: center;
15
- justify-content: center;
16
- background-color: #f4f4f1;
17
- color: @tableauTitleColor;
18
- }
19
-
20
- p.tableau-error {
21
- color: @tableauErrorColor;
22
- font-weight: bold;
23
- }
9
+ @keyframes spin {
10
+ 0% {
11
+ background-position: 0 0;
24
12
  }
25
13
 
26
- h3.tableau-title {
27
- margin: @tableauTitleMargin;
28
- color: @tableauTitleColor;
14
+ 100% {
15
+ background-position: 50px 50px;
29
16
  }
17
+ }
30
18
 
31
- p.tableau-description {
32
- margin: @tableauDescriptionMargin;
33
- color: @tableauDescriptionColor;
34
- }
19
+ .tableau-wrapper {
20
+ overflow: auto;
21
+ padding: @tableauWrapperPadding;
22
+ background-color: @tableauWrapperBackground;
35
23
 
36
- .tableau {
37
- width: 100%;
24
+ .tableau-debug {
25
+ margin: 0 auto 1rem auto;
38
26
 
39
- &:not(.tableau-scale) {
40
- iframe {
41
- width: @tableauIframeWidth;
42
- min-width: @tableauMinWidth;
43
- }
27
+ .tableau-version .version {
28
+ color: @secondaryColor;
44
29
  }
30
+ }
31
+
32
+ .tableau-info {
33
+ margin: 0 auto 1rem auto;
34
+ }
45
35
 
36
+ .tableau {
46
37
  iframe {
47
38
  padding: @tableauIframePadding;
48
39
  border: @tableauIframeBorder;
@@ -51,22 +42,6 @@
51
42
  transform-origin: top left;
52
43
  }
53
44
  }
54
- }
55
-
56
- .not_displayed_tableau {
57
- width: 100%;
58
- min-width: 633px;
59
- height: 100%;
60
- min-height: 200px;
61
- background-color: #ebebeb;
62
- }
63
-
64
- .tableau-block {
65
- .tableau-info {
66
- p.tableau-error {
67
- padding: 10px;
68
- }
69
- }
70
45
 
71
46
  .tableau-loader {
72
47
  display: flex;
@@ -75,53 +50,137 @@
75
50
  height: 100%;
76
51
  align-items: center;
77
52
  justify-content: center;
78
- margin: auto;
79
- animation: anim 1s linear infinite;
53
+ margin: 0 auto 1rem auto;
54
+ animation: spin 1s linear infinite;
80
55
  background-image: linear-gradient(
81
56
  -45deg,
82
- #5ac5f1 25%,
83
- #96bbde 25%,
84
- #96bbde 50%,
85
- #5ac5f1 50%,
86
- #5ac5f1 75%,
87
- #96bbde 75%
57
+ @primaryColor 25%,
58
+ @secondaryColor 25%,
59
+ @secondaryColor 50%,
60
+ @primaryColor 50%,
61
+ @primaryColor 75%,
62
+ @secondaryColor 75%
88
63
  );
89
64
  background-size: 100px 100px;
90
65
  border-radius: 5px;
66
+
67
+ span {
68
+ margin: 6px auto;
69
+ color: white;
70
+ font-weight: bold;
71
+ text-align: center;
72
+ }
91
73
  }
92
74
  }
93
75
 
94
- .tableau-loader span {
95
- margin: 6px auto;
96
- color: white;
76
+ // ========= Sources ==========
77
+
78
+ .tableau-wrapper .tableau-info {
79
+ display: flex;
80
+ align-items: center;
81
+
82
+ > * {
83
+ padding: 0 0.5rem;
84
+ border-collapse: collapse;
85
+ }
86
+
87
+ > *:first-child {
88
+ padding-left: 0;
89
+ }
90
+
91
+ > *:last-child {
92
+ padding-right: 0;
93
+ }
94
+
95
+ > *:not(:last-child) {
96
+ border-right: 2px solid @textColor;
97
+ }
98
+ }
99
+
100
+ .embed-sources-header {
101
+ cursor: pointer;
102
+ }
103
+
104
+ .tableau-download-button,
105
+ .tableau-share-button,
106
+ .tableau-sources-button {
107
+ display: inline-flex;
108
+ align-items: center;
109
+ padding-bottom: 3px;
110
+ border: none;
111
+ background-color: transparent;
112
+ color: @textColor;
113
+ cursor: pointer;
97
114
  font-weight: bold;
98
- text-align: center;
115
+
116
+ .icon {
117
+ margin-left: 0.5rem;
118
+ }
119
+
120
+ &:hover {
121
+ color: @secondaryColor;
122
+ }
123
+
124
+ &.expanded {
125
+ padding-bottom: 0;
126
+ border-bottom: 3px solid @secondaryColor;
127
+ color: @secondaryColor;
128
+ }
99
129
  }
100
130
 
101
- @keyframes anim {
102
- 0% {
103
- background-position: 0 0;
131
+ #tableau-sources-popup,
132
+ #tableau-download-popup {
133
+ .ui.popup {
134
+ min-width: 600px;
135
+ background-color: #f9f9f9;
136
+ box-shadow: rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px;
137
+
138
+ &::before {
139
+ background-color: #f9f9f9;
140
+ }
141
+
142
+ .sources-list > li,
143
+ .sources-list > li > * {
144
+ color: @textColor;
145
+ }
146
+
147
+ a:hover {
148
+ color: @secondaryColor;
149
+ }
104
150
  }
105
151
 
106
- 100% {
107
- background-position: 50px 50px;
152
+ .sources-list {
153
+ margin: 0;
154
+ list-style: decimal inside;
155
+ padding-inline-start: 0;
156
+ }
157
+
158
+ @media screen and (max-width: @largestMobileScreen) {
159
+ .ui.popup {
160
+ min-width: 300px;
161
+ }
108
162
  }
109
163
  }
110
164
 
111
- .availableFieldsContainer {
112
- padding: 0 5px 5px 0;
113
- border-bottom: 1px solid #d9d9d9;
165
+ #tableau-download-popup {
166
+ .ui.popup {
167
+ min-width: 460px;
168
+ text-align: center;
169
+ }
114
170
  }
115
171
 
116
- .availableFieldsTitle {
117
- color: darkgray;
118
- font-size: 13px;
119
- font-weight: bold;
172
+ @media print {
173
+ .tableau-download-container,
174
+ .tableau-sources-container,
175
+ .tableau-share-container,
176
+ #tableau-sources-popup {
177
+ display: none;
178
+ }
120
179
  }
121
180
 
122
- .availableFields {
123
- padding: 0 5px;
124
- font-size: 12px;
181
+ #tableau-editor-modal {
182
+ width: 90vw !important;
183
+ height: calc(80vh - 10em) !important;
125
184
  }
126
185
 
127
186
  .loadAddonVariables();
@@ -1,14 +1,7 @@
1
- @tableauTitleColor: #4296b2;
2
- @tableauTitleMargin: 0 0 1rem 0;
1
+ @tableauWrapperBackground : #f5f5f5;
2
+ @tableauWrapperPadding : 1rem 1rem 0 1rem;
3
3
 
4
- @tableauDescriptionColor: #000;
5
- @tableauDescriptionMargin: 0 0 1rem 0;
6
-
7
- @tableauErrorColor: #E9776D;
8
-
9
- @tableauIframeWidth: 100% !important;
10
- @tableauMinWidth: auto;
11
- @tableauIframePadding: 0;
12
- @tableauIframeMargin: 0 0 1rem 0;
13
- @tableauIframeBorder: none;
14
- @tableauIframeBorderRadius: 0;
4
+ @tableauIframePadding : 0;
5
+ @tableauIframeMargin : 0 auto 1rem auto;
6
+ @tableauIframeBorder : none;
7
+ @tableauIframeBorderRadius : 0;