@eeacms/volto-tableau 7.2.0 → 8.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.
- package/.env +1 -0
- package/.eslintrc.js +65 -0
- package/CHANGELOG.md +19 -2
- package/Jenkinsfile +169 -71
- package/Makefile +11 -8
- package/cypress/support/e2e.js +0 -4
- package/jest-addon.config.js +13 -4
- package/package.json +2 -1
- package/src/Blocks/EmbedTableauVisualization/Edit.test.jsx +70 -4
- package/src/Blocks/EmbedTableauVisualization/View.test.jsx +16 -4
- package/src/Blocks/EmbedTableauVisualization/index.js +3 -1
- package/src/Blocks/EmbedTableauVisualization/schema.js +4 -2
- package/src/Blocks/TableauBlock/Edit.jsx +4 -3
- package/src/Blocks/TableauBlock/index.js +3 -1
- package/src/Blocks/TableauBlock/schema.js +3 -1
- package/src/Blocks/index.js +3 -1
- package/src/Tableau/helpers.js +4 -4
- package/src/Widgets/VisualizationWidget.jsx +5 -4
- package/src/Widgets/schema.js +3 -1
- package/src/less/tableau.less +2 -2
- package/.project.eslintrc.js +0 -47
- package/src/Blocks/EmbedTableauVisualization/__snapshots__/Edit.test.jsx.snap +0 -336
- package/src/Blocks/EmbedTableauVisualization/__snapshots__/View.test.jsx.snap +0 -32
package/.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
JEST_USE_SETUP=ON
|
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const projectRootPath = fs.realpathSync(__dirname + '/../../../');
|
|
4
|
+
|
|
5
|
+
let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto');
|
|
6
|
+
let configFile;
|
|
7
|
+
if (fs.existsSync(`${projectRootPath}/tsconfig.json`))
|
|
8
|
+
configFile = `${projectRootPath}/tsconfig.json`;
|
|
9
|
+
else if (fs.existsSync(`${projectRootPath}/jsconfig.json`))
|
|
10
|
+
configFile = `${projectRootPath}/jsconfig.json`;
|
|
11
|
+
|
|
12
|
+
if (configFile) {
|
|
13
|
+
const jsConfig = require(configFile).compilerOptions;
|
|
14
|
+
const pathsConfig = jsConfig.paths;
|
|
15
|
+
if (pathsConfig['@plone/volto'])
|
|
16
|
+
voltoPath = `./${jsConfig.baseUrl}/${pathsConfig['@plone/volto'][0]}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`);
|
|
20
|
+
const reg = new AddonConfigurationRegistry(projectRootPath);
|
|
21
|
+
|
|
22
|
+
// Extends ESlint configuration for adding the aliases to `src` directories in Volto addons
|
|
23
|
+
const addonAliases = Object.keys(reg.packages).map((o) => [
|
|
24
|
+
o,
|
|
25
|
+
reg.packages[o].modulePath,
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const addonExtenders = reg.getEslintExtenders().map((m) => require(m));
|
|
29
|
+
|
|
30
|
+
const defaultConfig = {
|
|
31
|
+
extends: `${voltoPath}/.eslintrc`,
|
|
32
|
+
settings: {
|
|
33
|
+
'import/resolver': {
|
|
34
|
+
alias: {
|
|
35
|
+
map: [
|
|
36
|
+
['@plone/volto', '@plone/volto/src'],
|
|
37
|
+
['@plone/volto-slate', '@plone/volto/packages/volto-slate/src'],
|
|
38
|
+
...addonAliases,
|
|
39
|
+
['@package', `${__dirname}/src`],
|
|
40
|
+
['@root', `${__dirname}/src`],
|
|
41
|
+
['~', `${__dirname}/src`],
|
|
42
|
+
],
|
|
43
|
+
extensions: ['.js', '.jsx', '.json'],
|
|
44
|
+
},
|
|
45
|
+
'babel-plugin-root-import': {
|
|
46
|
+
rootPathSuffix: 'src',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
rules: {
|
|
51
|
+
'react/jsx-no-target-blank': [
|
|
52
|
+
'error',
|
|
53
|
+
{
|
|
54
|
+
allowReferrer: true,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const config = addonExtenders.reduce(
|
|
61
|
+
(acc, extender) => extender.modify(acc),
|
|
62
|
+
defaultConfig,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
module.exports = config;
|
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,28 @@ 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
|
-
### [
|
|
7
|
+
### [8.0.0](https://github.com/eea/volto-tableau/compare/7.2.1...8.0.0) - 22 April 2024
|
|
8
8
|
|
|
9
9
|
#### :rocket: New Features
|
|
10
10
|
|
|
11
|
-
- feat:
|
|
11
|
+
- feat: Release 8.0.0 - Volto 17 support [alin - [`c471a7a`](https://github.com/eea/volto-tableau/commit/c471a7abcfcc8f39c3d16823c097c041598acc76)]
|
|
12
|
+
- feat: Volto 17 support - refs #264527 [EEA Jenkins - [`f0ffca3`](https://github.com/eea/volto-tableau/commit/f0ffca315f668a57214d742429d116abe9b3ea23)]
|
|
13
|
+
|
|
14
|
+
#### :house: Internal changes
|
|
15
|
+
|
|
16
|
+
- chore: package.json [Alin Voinea - [`2feda54`](https://github.com/eea/volto-tableau/commit/2feda54b9f653b90d0995412f6e8d8db9041fcc9)]
|
|
17
|
+
|
|
18
|
+
#### :hammer_and_wrench: Others
|
|
19
|
+
|
|
20
|
+
- test: use latest volto 16 in Jenkinsfile [valentinab25 - [`eba82ac`](https://github.com/eea/volto-tableau/commit/eba82acca9cacb0e17670d989ae2ec13b103899a)]
|
|
21
|
+
### [7.2.1](https://github.com/eea/volto-tableau/compare/7.2.0...7.2.1) - 31 January 2024
|
|
22
|
+
|
|
23
|
+
#### :hammer_and_wrench: Others
|
|
24
|
+
|
|
25
|
+
- fix tests [Razvan - [`e370ea4`](https://github.com/eea/volto-tableau/commit/e370ea49343f52b1a07dbe402ce48c9ef53b6a7b)]
|
|
26
|
+
- fix eslint [Razvan - [`82f9311`](https://github.com/eea/volto-tableau/commit/82f9311fadd7c269321c23d4a3e029c2d5a133c6)]
|
|
27
|
+
- test: Update jest,Jenkinsfile,lint to volto-addons-template PR30 [valentinab25 - [`6a19c5c`](https://github.com/eea/volto-tableau/commit/6a19c5ceaf229d944f3f15ee32a833ae37619d74)]
|
|
28
|
+
### [7.2.0](https://github.com/eea/volto-tableau/compare/7.1.0...7.2.0) - 17 January 2024
|
|
12
29
|
|
|
13
30
|
#### :bug: Bug Fixes
|
|
14
31
|
|
package/Jenkinsfile
CHANGED
|
@@ -13,7 +13,8 @@ pipeline {
|
|
|
13
13
|
DEPENDENCIES = ""
|
|
14
14
|
BACKEND_PROFILES = "eea.kitkat:testing"
|
|
15
15
|
BACKEND_ADDONS = ""
|
|
16
|
-
VOLTO = "
|
|
16
|
+
VOLTO = "17"
|
|
17
|
+
VOLTO16_BREAKING_CHANGES = "no"
|
|
17
18
|
IMAGE_NAME = BUILD_TAG.toLowerCase()
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -44,6 +45,7 @@ pipeline {
|
|
|
44
45
|
}
|
|
45
46
|
steps {
|
|
46
47
|
script {
|
|
48
|
+
checkout scm
|
|
47
49
|
withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN')]) {
|
|
48
50
|
check_result = sh script: '''docker run --pull always -i --rm --name="$IMAGE_NAME-gitflow-check" -e GIT_TOKEN="$GITHUB_TOKEN" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_ORG="$GIT_ORG" -e GIT_NAME="$GIT_NAME" eeacms/gitflow /check_if_testing_needed.sh''', returnStatus: true
|
|
49
51
|
|
|
@@ -61,7 +63,6 @@ pipeline {
|
|
|
61
63
|
allOf {
|
|
62
64
|
not { environment name: 'CHANGE_ID', value: '' }
|
|
63
65
|
environment name: 'CHANGE_TARGET', value: 'develop'
|
|
64
|
-
environment name: 'SKIP_TESTS', value: ''
|
|
65
66
|
}
|
|
66
67
|
allOf {
|
|
67
68
|
environment name: 'CHANGE_ID', value: ''
|
|
@@ -69,25 +70,27 @@ pipeline {
|
|
|
69
70
|
not { changelog '.*^Automated release [0-9\\.]+$' }
|
|
70
71
|
branch 'master'
|
|
71
72
|
}
|
|
72
|
-
environment name: 'SKIP_TESTS', value: ''
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
parallel {
|
|
77
|
+
|
|
78
|
+
stage('Volto 17') {
|
|
79
|
+
agent { node { label 'docker-1.13'} }
|
|
80
|
+
stages {
|
|
81
|
+
stage('Build test image') {
|
|
82
|
+
steps {
|
|
83
|
+
sh '''docker build --pull --build-arg="VOLTO_VERSION=$VOLTO" --build-arg="ADDON_NAME=$NAMESPACE/$GIT_NAME" --build-arg="ADDON_PATH=$GIT_NAME" . -t $IMAGE_NAME-frontend'''
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
when {
|
|
86
|
+
|
|
87
|
+
stage('Fix code') {
|
|
88
|
+
when {
|
|
86
89
|
environment name: 'CHANGE_ID', value: ''
|
|
87
90
|
not { branch 'master' }
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
}
|
|
92
|
+
steps {
|
|
93
|
+
script {
|
|
91
94
|
fix_result = sh(script: '''docker run --name="$IMAGE_NAME-fix" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend ci-fix''', returnStatus: true)
|
|
92
95
|
sh '''docker cp $IMAGE_NAME-fix:/app/src/addons/$GIT_NAME/src .'''
|
|
93
96
|
sh '''docker rm -v $IMAGE_NAME-fix'''
|
|
@@ -105,31 +108,31 @@ pipeline {
|
|
|
105
108
|
sh '''exit 1'''
|
|
106
109
|
}
|
|
107
110
|
}
|
|
111
|
+
}
|
|
108
112
|
}
|
|
109
|
-
}
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
stage('ES lint') {
|
|
115
|
+
when { environment name: 'SKIP_TESTS', value: '' }
|
|
116
|
+
steps {
|
|
117
|
+
sh '''docker run --rm --name="$IMAGE_NAME-eslint" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend lint'''
|
|
118
|
+
}
|
|
114
119
|
}
|
|
115
|
-
}
|
|
116
120
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
stage('Style lint') {
|
|
122
|
+
when { environment name: 'SKIP_TESTS', value: '' }
|
|
123
|
+
steps {
|
|
124
|
+
sh '''docker run --rm --name="$IMAGE_NAME-stylelint" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend stylelint'''
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
|
-
}
|
|
122
127
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
128
|
+
stage('Prettier') {
|
|
129
|
+
when { environment name: 'SKIP_TESTS', value: '' }
|
|
130
|
+
steps {
|
|
131
|
+
sh '''docker run --rm --name="$IMAGE_NAME-prettier" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend prettier'''
|
|
132
|
+
}
|
|
126
133
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
stage('Coverage Tests') {
|
|
130
|
-
parallel {
|
|
131
|
-
|
|
132
|
-
stage('Unit tests') {
|
|
134
|
+
stage('Unit tests') {
|
|
135
|
+
when { environment name: 'SKIP_TESTS', value: '' }
|
|
133
136
|
steps {
|
|
134
137
|
script {
|
|
135
138
|
try {
|
|
@@ -155,17 +158,24 @@ pipeline {
|
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
|
-
|
|
161
|
+
}
|
|
159
162
|
|
|
160
|
-
|
|
163
|
+
stage('Integration tests') {
|
|
164
|
+
when { environment name: 'SKIP_TESTS', value: '' }
|
|
161
165
|
steps {
|
|
162
166
|
script {
|
|
163
167
|
try {
|
|
164
168
|
sh '''docker run --pull always --rm -d --name="$IMAGE_NAME-plone" -e SITE="Plone" -e PROFILES="$BACKEND_PROFILES" -e ADDONS="$BACKEND_ADDONS" eeacms/plone-backend'''
|
|
165
|
-
sh '''docker run -d --shm-size=
|
|
169
|
+
sh '''docker run -d --shm-size=4g --link $IMAGE_NAME-plone:plone --name="$IMAGE_NAME-cypress" -e "RAZZLE_INTERNAL_API_PATH=http://plone:8080/Plone" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend start-ci'''
|
|
170
|
+
frontend = sh script:'''docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress make check-ci''', returnStatus: true
|
|
171
|
+
if ( frontend != 0 ) {
|
|
172
|
+
sh '''docker logs $IMAGE_NAME-cypress; exit 1'''
|
|
173
|
+
}
|
|
174
|
+
|
|
166
175
|
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress make cypress-ci'''
|
|
167
176
|
} finally {
|
|
168
177
|
try {
|
|
178
|
+
if ( frontend == 0 ) {
|
|
169
179
|
sh '''rm -rf cypress-videos cypress-results cypress-coverage cypress-screenshots'''
|
|
170
180
|
sh '''mkdir -p cypress-videos cypress-results cypress-coverage cypress-screenshots'''
|
|
171
181
|
videos = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos/''', returnStatus: true
|
|
@@ -189,6 +199,7 @@ pipeline {
|
|
|
189
199
|
sh '''for file in $(find cypress-results -name *.xml); do if [ $(grep -E 'failures="[1-9].*"' $file | wc -l) -eq 0 ]; then testname=$(grep -E 'file=.*failures="0"' $file | sed 's#.* file=".*\\/\\(.*\\.[jsxt]\\+\\)" time.*#\\1#' ); rm -f cypress-videos/videos/$testname.mp4; fi; done'''
|
|
190
200
|
archiveArtifacts artifacts: 'cypress-videos/**/*.mp4', fingerprint: true, allowEmptyArchive: true
|
|
191
201
|
}
|
|
202
|
+
}
|
|
192
203
|
} finally {
|
|
193
204
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
194
205
|
junit testResults: 'cypress-results/**/*.xml', allowEmptyResults: true
|
|
@@ -204,16 +215,7 @@ pipeline {
|
|
|
204
215
|
}
|
|
205
216
|
}
|
|
206
217
|
}
|
|
207
|
-
}
|
|
208
218
|
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
post {
|
|
212
|
-
always {
|
|
213
|
-
sh script: "docker rmi $IMAGE_NAME-frontend", returnStatus: true
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
219
|
|
|
218
220
|
stage('Report to SonarQube') {
|
|
219
221
|
when {
|
|
@@ -221,9 +223,11 @@ pipeline {
|
|
|
221
223
|
allOf {
|
|
222
224
|
not { environment name: 'CHANGE_ID', value: '' }
|
|
223
225
|
environment name: 'CHANGE_TARGET', value: 'develop'
|
|
226
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
224
227
|
}
|
|
225
228
|
allOf {
|
|
226
229
|
environment name: 'CHANGE_ID', value: ''
|
|
230
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
227
231
|
anyOf {
|
|
228
232
|
allOf {
|
|
229
233
|
branch 'develop'
|
|
@@ -248,33 +252,126 @@ pipeline {
|
|
|
248
252
|
}
|
|
249
253
|
}
|
|
250
254
|
|
|
251
|
-
// stage('SonarQube compare to master') {
|
|
252
|
-
// when {
|
|
253
|
-
// anyOf {
|
|
254
|
-
// allOf {
|
|
255
|
-
// not { environment name: 'CHANGE_ID', value: '' }
|
|
256
|
-
// environment name: 'CHANGE_TARGET', value: 'develop'
|
|
257
|
-
// }
|
|
258
|
-
// allOf {
|
|
259
|
-
// environment name: 'CHANGE_ID', value: ''
|
|
260
|
-
// branch 'develop'
|
|
261
|
-
// not { changelog '.*^Automated release [0-9\\.]+$' }
|
|
262
|
-
// }
|
|
263
|
-
// }
|
|
264
|
-
// }
|
|
265
|
-
// steps {
|
|
266
|
-
// script {
|
|
267
|
-
// sh '''echo "Error" > checkresult.txt'''
|
|
268
|
-
// catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
|
269
|
-
// sh '''set -o pipefail; docker run -i --rm --pull always --name="$IMAGE_NAME-gitflow-sn" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" eeacms/gitflow /checkSonarqubemaster.sh | grep -v "Found script" | tee checkresult.txt'''
|
|
270
|
-
// }
|
|
271
255
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
stage('Volto 16') {
|
|
260
|
+
agent { node { label 'integration'} }
|
|
261
|
+
when {
|
|
262
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
263
|
+
not { environment name: 'VOLTO16_BREAKING_CHANGES', value: 'yes' }
|
|
264
|
+
}
|
|
265
|
+
stages {
|
|
266
|
+
stage('Build test image') {
|
|
267
|
+
steps {
|
|
268
|
+
sh '''docker build --pull --build-arg="VOLTO_VERSION=16" --build-arg="ADDON_NAME=$NAMESPACE/$GIT_NAME" --build-arg="ADDON_PATH=$GIT_NAME" . -t $IMAGE_NAME-frontend16'''
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
stage('Unit tests Volto 16') {
|
|
273
|
+
steps {
|
|
274
|
+
script {
|
|
275
|
+
try {
|
|
276
|
+
sh '''docker run --name="$IMAGE_NAME-volto16" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend16 test-ci'''
|
|
277
|
+
sh '''rm -rf xunit-reports16'''
|
|
278
|
+
sh '''mkdir -p xunit-reports16'''
|
|
279
|
+
sh '''docker cp $IMAGE_NAME-volto16:/app/junit.xml xunit-reports16/'''
|
|
280
|
+
} finally {
|
|
281
|
+
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
282
|
+
junit testResults: 'xunit-reports16/junit.xml', allowEmptyResults: true
|
|
283
|
+
}
|
|
284
|
+
sh script: '''docker rm -v $IMAGE_NAME-volto16''', returnStatus: true
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
stage('Integration tests Volto 16') {
|
|
291
|
+
steps {
|
|
292
|
+
script {
|
|
293
|
+
try {
|
|
294
|
+
sh '''docker run --pull always --rm -d --name="$IMAGE_NAME-plone16" -e SITE="Plone" -e PROFILES="$BACKEND_PROFILES" -e ADDONS="$BACKEND_ADDONS" eeacms/plone-backend'''
|
|
295
|
+
sh '''docker run -d --shm-size=4g --link $IMAGE_NAME-plone16:plone --name="$IMAGE_NAME-cypress16" -e "RAZZLE_INTERNAL_API_PATH=http://plone:8080/Plone" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend16 start-ci'''
|
|
296
|
+
frontend = sh script:'''docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress16 make check-ci''', returnStatus: true
|
|
297
|
+
if ( frontend != 0 ) {
|
|
298
|
+
sh '''docker logs $IMAGE_NAME-cypress16; exit 1'''
|
|
299
|
+
}
|
|
300
|
+
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress16 make cypress-ci'''
|
|
301
|
+
} finally {
|
|
302
|
+
try {
|
|
303
|
+
if ( frontend == 0 ) {
|
|
304
|
+
sh '''rm -rf cypress-videos16 cypress-results16 cypress-coverage16 cypress-screenshots16'''
|
|
305
|
+
sh '''mkdir -p cypress-videos16 cypress-results16 cypress-coverage16 cypress-screenshots16'''
|
|
306
|
+
videos = sh script: '''docker cp $IMAGE_NAME-cypress16:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos16/''', returnStatus: true
|
|
307
|
+
sh '''docker cp $IMAGE_NAME-cypress16:/app/src/addons/$GIT_NAME/cypress/reports cypress-results16/'''
|
|
308
|
+
screenshots = sh script: '''docker cp $IMAGE_NAME-cypress16:/app/src/addons/$GIT_NAME/cypress/screenshots cypress-screenshots16''', returnStatus: true
|
|
309
|
+
|
|
310
|
+
archiveArtifacts artifacts: 'cypress-screenshots16/**', fingerprint: true, allowEmptyArchive: true
|
|
311
|
+
|
|
312
|
+
if ( videos == 0 ) {
|
|
313
|
+
sh '''for file in $(find cypress-results16 -name *.xml); do if [ $(grep -E 'failures="[1-9].*"' $file | wc -l) -eq 0 ]; then testname=$(grep -E 'file=.*failures="0"' $file | sed 's#.* file=".*\\/\\(.*\\.[jsxt]\\+\\)" time.*#\\1#' ); rm -f cypress-videos16/videos/$testname.mp4; fi; done'''
|
|
314
|
+
archiveArtifacts artifacts: 'cypress-videos16/**/*.mp4', fingerprint: true, allowEmptyArchive: true
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
} finally {
|
|
318
|
+
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
319
|
+
junit testResults: 'cypress-results16/**/*.xml', allowEmptyResults: true
|
|
320
|
+
}
|
|
321
|
+
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
322
|
+
sh '''docker logs $IMAGE_NAME-cypress16'''
|
|
323
|
+
}
|
|
324
|
+
sh script: "docker stop $IMAGE_NAME-cypress16", returnStatus: true
|
|
325
|
+
sh script: "docker stop $IMAGE_NAME-plone16", returnStatus: true
|
|
326
|
+
sh script: "docker rm -v $IMAGE_NAME-plone16", returnStatus: true
|
|
327
|
+
sh script: "docker rm -v $IMAGE_NAME-cypress16", returnStatus: true
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
post {
|
|
338
|
+
always {
|
|
339
|
+
sh script: "docker rmi $IMAGE_NAME-frontend", returnStatus: true
|
|
340
|
+
sh script: "docker rmi $IMAGE_NAME-frontend16", returnStatus: true
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
stage('SonarQube compare to master') {
|
|
347
|
+
when {
|
|
348
|
+
anyOf {
|
|
349
|
+
allOf {
|
|
350
|
+
not { environment name: 'CHANGE_ID', value: '' }
|
|
351
|
+
environment name: 'CHANGE_TARGET', value: 'develop'
|
|
352
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
353
|
+
}
|
|
354
|
+
allOf {
|
|
355
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
356
|
+
environment name: 'CHANGE_ID', value: ''
|
|
357
|
+
branch 'develop'
|
|
358
|
+
not { changelog '.*^Automated release [0-9\\.]+$' }
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
steps {
|
|
363
|
+
script {
|
|
364
|
+
sh '''echo "Error" > checkresult.txt'''
|
|
365
|
+
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
|
366
|
+
sh '''set -o pipefail; docker run -i --rm --pull always --name="$IMAGE_NAME-gitflow-sn" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" eeacms/gitflow /checkSonarqubemaster.sh | grep -v "Found script" | tee checkresult.txt'''
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
publishChecks name: 'SonarQube', title: 'Sonarqube Code Quality Check', summary: 'Quality check on the SonarQube metrics from branch develop, comparing it with the ones from master branch. No bugs are allowed',
|
|
370
|
+
text: readFile(file: 'checkresult.txt'), conclusion: "${currentBuild.currentResult}",
|
|
371
|
+
detailsURL: "${env.BUILD_URL}display/redirect"
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
278
375
|
|
|
279
376
|
stage('Pull Request') {
|
|
280
377
|
when {
|
|
@@ -316,3 +413,4 @@ pipeline {
|
|
|
316
413
|
}
|
|
317
414
|
}
|
|
318
415
|
}
|
|
416
|
+
|
package/Makefile
CHANGED
|
@@ -46,7 +46,7 @@ endif
|
|
|
46
46
|
DIR=$(shell basename $$(pwd))
|
|
47
47
|
NODE_MODULES?="../../../node_modules"
|
|
48
48
|
PLONE_VERSION?=6
|
|
49
|
-
VOLTO_VERSION?=
|
|
49
|
+
VOLTO_VERSION?=17
|
|
50
50
|
ADDON_PATH="${DIR}"
|
|
51
51
|
ADDON_NAME="@eeacms/${ADDON_PATH}"
|
|
52
52
|
DOCKER_COMPOSE=PLONE_VERSION=${PLONE_VERSION} VOLTO_VERSION=${VOLTO_VERSION} ADDON_NAME=${ADDON_NAME} ADDON_PATH=${ADDON_PATH} docker compose
|
|
@@ -86,7 +86,7 @@ cypress-open: ## Open cypress integration tests
|
|
|
86
86
|
|
|
87
87
|
.PHONY: cypress-run
|
|
88
88
|
cypress-run: ## Run cypress integration tests
|
|
89
|
-
CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run
|
|
89
|
+
CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run
|
|
90
90
|
|
|
91
91
|
.PHONY: test
|
|
92
92
|
test: ## Run jest tests
|
|
@@ -98,7 +98,7 @@ test-update: ## Update jest tests snapshots
|
|
|
98
98
|
|
|
99
99
|
.PHONY: stylelint
|
|
100
100
|
stylelint: ## Stylelint
|
|
101
|
-
$(NODE_MODULES)
|
|
101
|
+
$(NODE_MODULES)/.bin/stylelint --allow-empty-input 'src/**/*.{css,less}'
|
|
102
102
|
|
|
103
103
|
.PHONY: stylelint-overrides
|
|
104
104
|
stylelint-overrides:
|
|
@@ -106,7 +106,7 @@ stylelint-overrides:
|
|
|
106
106
|
|
|
107
107
|
.PHONY: stylelint-fix
|
|
108
108
|
stylelint-fix: ## Fix stylelint
|
|
109
|
-
$(NODE_MODULES)
|
|
109
|
+
$(NODE_MODULES)/.bin/stylelint --allow-empty-input 'src/**/*.{css,less}' --fix
|
|
110
110
|
$(NODE_MODULES)/.bin/stylelint --custom-syntax less --allow-empty-input 'theme/**/*.overrides' 'src/**/*.overrides' --fix
|
|
111
111
|
|
|
112
112
|
.PHONY: prettier
|
|
@@ -119,11 +119,11 @@ prettier-fix: ## Fix prettier
|
|
|
119
119
|
|
|
120
120
|
.PHONY: lint
|
|
121
121
|
lint: ## ES Lint
|
|
122
|
-
$(NODE_MODULES)
|
|
122
|
+
$(NODE_MODULES)/.bin/eslint --max-warnings=0 'src/**/*.{js,jsx}'
|
|
123
123
|
|
|
124
124
|
.PHONY: lint-fix
|
|
125
125
|
lint-fix: ## Fix ES Lint
|
|
126
|
-
$(NODE_MODULES)
|
|
126
|
+
$(NODE_MODULES)/.bin/eslint --fix 'src/**/*.{js,jsx}'
|
|
127
127
|
|
|
128
128
|
.PHONY: i18n
|
|
129
129
|
i18n: ## i18n
|
|
@@ -155,8 +155,11 @@ start-ci:
|
|
|
155
155
|
cd ../..
|
|
156
156
|
yarn start
|
|
157
157
|
|
|
158
|
+
.PHONY: check-ci
|
|
159
|
+
check-ci:
|
|
160
|
+
$(NODE_MODULES)/.bin/wait-on -t 240000 http://localhost:3000
|
|
161
|
+
|
|
158
162
|
.PHONY: cypress-ci
|
|
159
163
|
cypress-ci:
|
|
160
164
|
$(NODE_MODULES)/.bin/wait-on -t 240000 http://localhost:3000
|
|
161
|
-
NODE_ENV=development
|
|
162
|
-
|
|
165
|
+
CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run --browser chromium
|
package/cypress/support/e2e.js
CHANGED
|
@@ -35,10 +35,6 @@ export const slateBeforeEach = (contentType = 'Document') => {
|
|
|
35
35
|
path: 'cypress',
|
|
36
36
|
});
|
|
37
37
|
cy.visit('/cypress/my-page');
|
|
38
|
-
// cy.waitForResourceToLoad('@navigation');
|
|
39
|
-
// cy.waitForResourceToLoad('@breadcrumbs');
|
|
40
|
-
// cy.waitForResourceToLoad('@actions');
|
|
41
|
-
// cy.waitForResourceToLoad('@types');
|
|
42
38
|
cy.waitForResourceToLoad('my-page');
|
|
43
39
|
cy.navigate('/cypress/my-page/edit');
|
|
44
40
|
};
|
package/jest-addon.config.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require('dotenv').config({ path: __dirname + '/.env' })
|
|
2
|
+
|
|
1
3
|
module.exports = {
|
|
2
4
|
testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'],
|
|
3
5
|
collectCoverageFrom: [
|
|
@@ -12,7 +14,11 @@ module.exports = {
|
|
|
12
14
|
'@package/(.*)$': '<rootDir>/node_modules/@plone/volto/src/$1',
|
|
13
15
|
'@root/(.*)$': '<rootDir>/node_modules/@plone/volto/src/$1',
|
|
14
16
|
'@plone/volto-quanta/(.*)$': '<rootDir>/src/addons/volto-quanta/src/$1',
|
|
17
|
+
'@eeacms/search/(.*)$': '<rootDir>/src/addons/volto-searchlib/searchlib/$1',
|
|
18
|
+
'@eeacms/search': '<rootDir>/src/addons/volto-searchlib/searchlib',
|
|
15
19
|
'@eeacms/(.*?)/(.*)$': '<rootDir>/node_modules/@eeacms/$1/src/$2',
|
|
20
|
+
'@plone/volto-slate$':
|
|
21
|
+
'<rootDir>/node_modules/@plone/volto/packages/volto-slate/src',
|
|
16
22
|
'@plone/volto-slate/(.*)$':
|
|
17
23
|
'<rootDir>/node_modules/@plone/volto/packages/volto-slate/src/$1',
|
|
18
24
|
'~/(.*)$': '<rootDir>/src/$1',
|
|
@@ -24,6 +30,7 @@ module.exports = {
|
|
|
24
30
|
],
|
|
25
31
|
transform: {
|
|
26
32
|
'^.+\\.js(x)?$': 'babel-jest',
|
|
33
|
+
'^.+\\.ts(x)?$': 'babel-jest',
|
|
27
34
|
'^.+\\.(png)$': 'jest-file',
|
|
28
35
|
'^.+\\.(jpg)$': 'jest-file',
|
|
29
36
|
'^.+\\.(svg)$': './node_modules/@plone/volto/jest-svgsystem-transform.js',
|
|
@@ -36,7 +43,9 @@ module.exports = {
|
|
|
36
43
|
statements: 5,
|
|
37
44
|
},
|
|
38
45
|
},
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
...(process.env.JEST_USE_SETUP === 'ON' && {
|
|
47
|
+
setupFilesAfterEnv: [
|
|
48
|
+
'<rootDir>/node_modules/@eeacms/volto-tableau/jest.setup.js',
|
|
49
|
+
],
|
|
50
|
+
}),
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-tableau",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.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",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@cypress/code-coverage": "^3.9.5",
|
|
31
31
|
"@plone/scripts": "*",
|
|
32
32
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
33
|
+
"dotenv": "^16.3.2",
|
|
33
34
|
"husky": "^8.0.3",
|
|
34
35
|
"lint-staged": "^14.0.1",
|
|
35
36
|
"md5": "^2.3.0"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
3
|
import { Provider } from 'react-intl-redux';
|
|
4
4
|
import config from '@plone/volto/registry';
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
5
6
|
|
|
6
7
|
import Edit from './Edit';
|
|
7
8
|
import installEmbedTableau from '.';
|
|
@@ -22,7 +23,7 @@ describe('Edit', () => {
|
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
it('should render the component', () => {
|
|
25
|
-
const
|
|
26
|
+
const { container } = render(
|
|
26
27
|
<Provider store={global.store}>
|
|
27
28
|
<Edit
|
|
28
29
|
id="my-tableau"
|
|
@@ -42,7 +43,72 @@ describe('Edit', () => {
|
|
|
42
43
|
/>
|
|
43
44
|
</Provider>,
|
|
44
45
|
);
|
|
45
|
-
|
|
46
|
-
expect(
|
|
46
|
+
|
|
47
|
+
expect(container.querySelector('.embed-tableau')).toBeInTheDocument();
|
|
48
|
+
expect(
|
|
49
|
+
container.querySelector('.privacy-protection-wrapper'),
|
|
50
|
+
).toBeInTheDocument();
|
|
51
|
+
expect(container.querySelector('.privacy-protection-wrapper')).toHaveStyle({
|
|
52
|
+
height: 'auto',
|
|
53
|
+
minHeight: '200px',
|
|
54
|
+
overflow: 'hidden',
|
|
55
|
+
position: 'relative',
|
|
56
|
+
});
|
|
57
|
+
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
58
|
+
expect(container.querySelector('#sidebar')).toBeInTheDocument();
|
|
59
|
+
expect(container.querySelector('#sidebar .ui.form')).toBeInTheDocument();
|
|
60
|
+
expect(
|
|
61
|
+
container.querySelector('#sidebar .ui.form .header.pulled'),
|
|
62
|
+
).toBeInTheDocument();
|
|
63
|
+
expect(screen.getByText('Embed Dashboard (Tableau)')).toBeInTheDocument();
|
|
64
|
+
expect(
|
|
65
|
+
container.querySelector('#blockform-fieldset-default'),
|
|
66
|
+
).toBeInTheDocument();
|
|
67
|
+
expect(
|
|
68
|
+
container.querySelector(
|
|
69
|
+
'#blockform-fieldset-default .ui.segment.form.attached',
|
|
70
|
+
),
|
|
71
|
+
).toBeInTheDocument();
|
|
72
|
+
expect(
|
|
73
|
+
container.querySelector(
|
|
74
|
+
'#mocked-field-tableau_vis_url.mocked-default-widget',
|
|
75
|
+
),
|
|
76
|
+
).toBeInTheDocument();
|
|
77
|
+
expect(screen.getByText(/Tableau visualization/)).toBeInTheDocument();
|
|
78
|
+
expect(
|
|
79
|
+
screen.getByText(
|
|
80
|
+
'When using context query parameters please use the corresponding field name from the Tableau service.',
|
|
81
|
+
),
|
|
82
|
+
).toBeInTheDocument();
|
|
83
|
+
expect(
|
|
84
|
+
screen.getByText(
|
|
85
|
+
'When using context query parameters please use the corresponding field name from the Tableau service.',
|
|
86
|
+
),
|
|
87
|
+
).toBeInTheDocument();
|
|
88
|
+
expect(
|
|
89
|
+
container.querySelector(
|
|
90
|
+
'#mocked-field-tableau_height.mocked-default-widget',
|
|
91
|
+
),
|
|
92
|
+
).toBeInTheDocument();
|
|
93
|
+
expect(
|
|
94
|
+
container.querySelector(
|
|
95
|
+
'a[href="https://developer.mozilla.org/en-US/docs/Web/CSS/height"]',
|
|
96
|
+
),
|
|
97
|
+
).toBeInTheDocument();
|
|
98
|
+
expect(
|
|
99
|
+
container.querySelector('.accordion.ui.fluid.styled.form'),
|
|
100
|
+
).toBeInTheDocument();
|
|
101
|
+
expect(
|
|
102
|
+
container.querySelector('#blockform-fieldset-toolbar'),
|
|
103
|
+
).toBeInTheDocument();
|
|
104
|
+
expect(
|
|
105
|
+
container.querySelector('#blockform-fieldset-toolbar .active.title'),
|
|
106
|
+
).toBeInTheDocument();
|
|
107
|
+
expect(screen.getByText('Toolbar')).toBeInTheDocument();
|
|
108
|
+
expect(screen.getByText(/Show note/)).toBeInTheDocument();
|
|
109
|
+
expect(screen.getByText(/Show more info/)).toBeInTheDocument();
|
|
110
|
+
expect(screen.getByText(/Show download button/)).toBeInTheDocument();
|
|
111
|
+
expect(screen.getByText(/Show share button/)).toBeInTheDocument();
|
|
112
|
+
expect(screen.getByText(/Show enlarge button/)).toBeInTheDocument();
|
|
47
113
|
});
|
|
48
114
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
3
|
import { Provider } from 'react-intl-redux';
|
|
4
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
5
|
+
|
|
4
6
|
import View from './View';
|
|
5
7
|
|
|
6
8
|
describe('View', () => {
|
|
@@ -17,12 +19,22 @@ describe('View', () => {
|
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
it('should render the component', () => {
|
|
20
|
-
const
|
|
22
|
+
const { container } = render(
|
|
21
23
|
<Provider store={global.store}>
|
|
22
24
|
<View data={data} useVisibilitySensor={false} />
|
|
23
25
|
</Provider>,
|
|
24
26
|
);
|
|
25
|
-
|
|
26
|
-
expect(
|
|
27
|
+
|
|
28
|
+
expect(container.querySelector('.embed-tableau')).toBeInTheDocument();
|
|
29
|
+
expect(
|
|
30
|
+
container.querySelector('.privacy-protection-wrapper'),
|
|
31
|
+
).toBeInTheDocument();
|
|
32
|
+
expect(container.querySelector('.privacy-protection-wrapper')).toHaveStyle({
|
|
33
|
+
height: 'auto',
|
|
34
|
+
minHeight: '200px',
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
position: 'relative',
|
|
37
|
+
});
|
|
38
|
+
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
27
39
|
});
|
|
28
40
|
});
|
|
@@ -3,7 +3,7 @@ import EmbedTableauVisualizatonView from './View';
|
|
|
3
3
|
|
|
4
4
|
import sliderSVG from '@plone/volto/icons/slider.svg';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const config = (config) => {
|
|
7
7
|
config.blocks.blocksConfig.embed_tableau_visualization = {
|
|
8
8
|
id: 'embed_tableau_visualization',
|
|
9
9
|
title: 'Embed Dashboard (Tableau)',
|
|
@@ -28,3 +28,5 @@ export default (config) => {
|
|
|
28
28
|
|
|
29
29
|
return config;
|
|
30
30
|
};
|
|
31
|
+
|
|
32
|
+
export default config;
|
|
@@ -69,7 +69,7 @@ const staticParameters = {
|
|
|
69
69
|
required: [],
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
const schema = (props) => {
|
|
73
73
|
return {
|
|
74
74
|
title: 'Embed Dashboard (Tableau)',
|
|
75
75
|
fieldsets: [
|
|
@@ -155,7 +155,7 @@ export default (props) => {
|
|
|
155
155
|
tableau_height: {
|
|
156
156
|
title: (
|
|
157
157
|
<a
|
|
158
|
-
rel="noreferrer"
|
|
158
|
+
rel="noopener noreferrer"
|
|
159
159
|
target="_blank"
|
|
160
160
|
href="https://developer.mozilla.org/en-US/docs/Web/CSS/height"
|
|
161
161
|
>
|
|
@@ -181,3 +181,5 @@ export default (props) => {
|
|
|
181
181
|
required: ['tableau_vis_url'],
|
|
182
182
|
};
|
|
183
183
|
};
|
|
184
|
+
|
|
185
|
+
export default schema;
|
|
@@ -13,9 +13,10 @@ const Edit = (props) => {
|
|
|
13
13
|
error: null,
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
const schema = React.useMemo(
|
|
17
|
-
vizState,
|
|
18
|
-
|
|
16
|
+
const schema = React.useMemo(
|
|
17
|
+
() => getSchema(config, viz.current, vizState),
|
|
18
|
+
[vizState],
|
|
19
|
+
);
|
|
19
20
|
|
|
20
21
|
return (
|
|
21
22
|
<>
|
|
@@ -3,7 +3,7 @@ import TableauView from './View';
|
|
|
3
3
|
|
|
4
4
|
import sliderSVG from '@plone/volto/icons/slider.svg';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const config = (config) => {
|
|
7
7
|
config.blocks.blocksConfig.tableau_block = {
|
|
8
8
|
id: 'tableau_block',
|
|
9
9
|
title: 'Tableau',
|
|
@@ -28,3 +28,5 @@ export default (config) => {
|
|
|
28
28
|
|
|
29
29
|
return config;
|
|
30
30
|
};
|
|
31
|
+
|
|
32
|
+
export default config;
|
|
@@ -84,7 +84,7 @@ const sourceSchema = {
|
|
|
84
84
|
required: [],
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
const schema = (config, viz, vizState) => {
|
|
88
88
|
const isDisabled = !canChangeVizData(viz, vizState);
|
|
89
89
|
|
|
90
90
|
return {
|
|
@@ -227,3 +227,5 @@ export default (config, viz, vizState) => {
|
|
|
227
227
|
required: ['url'],
|
|
228
228
|
};
|
|
229
229
|
};
|
|
230
|
+
|
|
231
|
+
export default schema;
|
package/src/Blocks/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { uniqBy } from 'lodash';
|
|
|
2
2
|
import installEmbedTableauVisualization from './EmbedTableauVisualization';
|
|
3
3
|
import installTableauBlock from './TableauBlock';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const config = (config) => {
|
|
6
6
|
config.blocks.groupBlocksOrder = uniqBy(
|
|
7
7
|
[
|
|
8
8
|
...config.blocks.groupBlocksOrder,
|
|
@@ -16,3 +16,5 @@ export default (config) => {
|
|
|
16
16
|
config,
|
|
17
17
|
);
|
|
18
18
|
};
|
|
19
|
+
|
|
20
|
+
export default config;
|
package/src/Tableau/helpers.js
CHANGED
|
@@ -28,8 +28,8 @@ export function getQuery({
|
|
|
28
28
|
export function getTableauVisualization({
|
|
29
29
|
isBlock,
|
|
30
30
|
data,
|
|
31
|
-
tableauContent,
|
|
32
|
-
content,
|
|
31
|
+
tableauContent = {},
|
|
32
|
+
content = {},
|
|
33
33
|
}) {
|
|
34
34
|
const mergedContent =
|
|
35
35
|
(isBlock
|
|
@@ -37,12 +37,12 @@ export function getTableauVisualization({
|
|
|
37
37
|
: {
|
|
38
38
|
...content,
|
|
39
39
|
tableau_visualization: {
|
|
40
|
-
...(content
|
|
40
|
+
...(content.tableau_visualization || {}),
|
|
41
41
|
...pickMetadata(content),
|
|
42
42
|
},
|
|
43
43
|
}) || {};
|
|
44
44
|
const tableau_visualization =
|
|
45
|
-
mergedContent
|
|
45
|
+
mergedContent.tableau_visualization || data?.tableau_visualization || {};
|
|
46
46
|
return {
|
|
47
47
|
...tableau_visualization,
|
|
48
48
|
...(isBlock ? pickMetadata(mergedContent) : {}),
|
|
@@ -19,6 +19,7 @@ import '@eeacms/volto-tableau/less/tableau.less';
|
|
|
19
19
|
|
|
20
20
|
const VisualizationWidget = (props) => {
|
|
21
21
|
const { location, content } = props;
|
|
22
|
+
const ogValue = props.value || {};
|
|
22
23
|
const viz = React.useRef();
|
|
23
24
|
const [schema, setSchema] = React.useState(null);
|
|
24
25
|
const [vizState, setVizState] = React.useState({
|
|
@@ -27,7 +28,7 @@ const VisualizationWidget = (props) => {
|
|
|
27
28
|
error: null,
|
|
28
29
|
});
|
|
29
30
|
const [open, setOpen] = React.useState(false);
|
|
30
|
-
const [value, setValue] = React.useState(
|
|
31
|
+
const [value, setValue] = React.useState(ogValue);
|
|
31
32
|
|
|
32
33
|
const [tableauVisualization, setTableauVisualization] = useState(() =>
|
|
33
34
|
getTableauVisualization({
|
|
@@ -57,13 +58,13 @@ const VisualizationWidget = (props) => {
|
|
|
57
58
|
};
|
|
58
59
|
|
|
59
60
|
const handleClose = () => {
|
|
60
|
-
setValue(
|
|
61
|
+
setValue(ogValue);
|
|
61
62
|
setOpen(false);
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
React.useEffect(() => {
|
|
65
|
-
if (!open && !isEqual(props.value, value)) {
|
|
66
|
-
setValue(props.value);
|
|
66
|
+
if (!open && !isEqual(props.value || {}, value)) {
|
|
67
|
+
setValue(props.value || {});
|
|
67
68
|
}
|
|
68
69
|
}, [props.value, value, open]);
|
|
69
70
|
|
package/src/Widgets/schema.js
CHANGED
|
@@ -168,7 +168,7 @@ const breakpointUrlSchema = (config) => {
|
|
|
168
168
|
};
|
|
169
169
|
};
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
const schema = async ({ config, viz, vizState, data }) => {
|
|
172
172
|
const isDisabled = !canChangeVizData(viz, vizState);
|
|
173
173
|
|
|
174
174
|
return {
|
|
@@ -428,3 +428,5 @@ export default async ({ config, viz, vizState, data }) => {
|
|
|
428
428
|
required: ['url'],
|
|
429
429
|
};
|
|
430
430
|
};
|
|
431
|
+
|
|
432
|
+
export default schema;
|
package/src/less/tableau.less
CHANGED
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
iframe {
|
|
44
44
|
padding: @tableauIframePadding;
|
|
45
45
|
border: @tableauIframeBorder;
|
|
46
|
-
margin: @tableauIframeMargin;
|
|
47
46
|
border-radius: @tableauIframeBorderRadius;
|
|
47
|
+
margin: @tableauIframeMargin;
|
|
48
48
|
transform-origin: top left;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
height: auto;
|
|
57
57
|
align-items: center;
|
|
58
58
|
justify-content: center;
|
|
59
|
+
border-radius: 5px;
|
|
59
60
|
margin: 0 auto 1rem auto;
|
|
60
61
|
animation: spin 1s linear infinite;
|
|
61
62
|
background-image: linear-gradient(
|
|
@@ -68,7 +69,6 @@
|
|
|
68
69
|
@grey-2 75%
|
|
69
70
|
);
|
|
70
71
|
background-size: 100px 100px;
|
|
71
|
-
border-radius: 5px;
|
|
72
72
|
|
|
73
73
|
span {
|
|
74
74
|
margin: 6px auto;
|
package/.project.eslintrc.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
const projectRootPath = fs.existsSync('./project')
|
|
5
|
-
? fs.realpathSync('./project')
|
|
6
|
-
: fs.realpathSync('./../../../');
|
|
7
|
-
const packageJson = require(path.join(projectRootPath, 'package.json'));
|
|
8
|
-
const jsConfig = require(path.join(projectRootPath, 'jsconfig.json'))
|
|
9
|
-
.compilerOptions;
|
|
10
|
-
|
|
11
|
-
const pathsConfig = jsConfig.paths;
|
|
12
|
-
|
|
13
|
-
let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto');
|
|
14
|
-
|
|
15
|
-
Object.keys(pathsConfig).forEach((pkg) => {
|
|
16
|
-
if (pkg === '@plone/volto') {
|
|
17
|
-
voltoPath = `./${jsConfig.baseUrl}/${pathsConfig[pkg][0]}`;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`);
|
|
21
|
-
const reg = new AddonConfigurationRegistry(projectRootPath);
|
|
22
|
-
|
|
23
|
-
// Extends ESlint configuration for adding the aliases to `src` directories in Volto addons
|
|
24
|
-
const addonAliases = Object.keys(reg.packages).map((o) => [
|
|
25
|
-
o,
|
|
26
|
-
reg.packages[o].modulePath,
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
module.exports = {
|
|
30
|
-
extends: `${projectRootPath}/node_modules/@plone/volto/.eslintrc`,
|
|
31
|
-
settings: {
|
|
32
|
-
'import/resolver': {
|
|
33
|
-
alias: {
|
|
34
|
-
map: [
|
|
35
|
-
['@plone/volto', '@plone/volto/src'],
|
|
36
|
-
...addonAliases,
|
|
37
|
-
['@package', `${__dirname}/src`],
|
|
38
|
-
['~', `${__dirname}/src`],
|
|
39
|
-
],
|
|
40
|
-
extensions: ['.js', '.jsx', '.json'],
|
|
41
|
-
},
|
|
42
|
-
'babel-plugin-root-import': {
|
|
43
|
-
rootPathSuffix: 'src',
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
};
|
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`Edit should render the component 1`] = `
|
|
4
|
-
Array [
|
|
5
|
-
<div
|
|
6
|
-
className="embed-tableau"
|
|
7
|
-
>
|
|
8
|
-
<div
|
|
9
|
-
className="privacy-protection-wrapper"
|
|
10
|
-
style={
|
|
11
|
-
Object {
|
|
12
|
-
"height": "auto",
|
|
13
|
-
"minHeight": "200px",
|
|
14
|
-
"overflow": "hidden",
|
|
15
|
-
"position": "relative",
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
>
|
|
19
|
-
<div
|
|
20
|
-
className="tableau-wrapper"
|
|
21
|
-
>
|
|
22
|
-
<div
|
|
23
|
-
className="tableau tableau-2.8.0"
|
|
24
|
-
style={
|
|
25
|
-
Object {
|
|
26
|
-
"height": "700px",
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
/>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
</div>,
|
|
33
|
-
<div
|
|
34
|
-
id="sidebar"
|
|
35
|
-
>
|
|
36
|
-
<div
|
|
37
|
-
className="ui form"
|
|
38
|
-
>
|
|
39
|
-
<header
|
|
40
|
-
className="header pulled"
|
|
41
|
-
>
|
|
42
|
-
<h2>
|
|
43
|
-
Embed Dashboard (Tableau)
|
|
44
|
-
</h2>
|
|
45
|
-
</header>
|
|
46
|
-
<div
|
|
47
|
-
id="blockform-fieldset-default"
|
|
48
|
-
>
|
|
49
|
-
<div
|
|
50
|
-
className="ui segment form attached"
|
|
51
|
-
>
|
|
52
|
-
<div
|
|
53
|
-
className="mocked-default-widget"
|
|
54
|
-
id="mocked-field-tableau_vis_url"
|
|
55
|
-
>
|
|
56
|
-
Tableau visualization
|
|
57
|
-
-
|
|
58
|
-
<div>
|
|
59
|
-
<p>
|
|
60
|
-
When using context query parameters please use the corresponding field name from the Tableau service.
|
|
61
|
-
</p>
|
|
62
|
-
<p>
|
|
63
|
-
NOTE: The embeded tableau dashboard must have the parameters defined in the
|
|
64
|
-
|
|
65
|
-
<span
|
|
66
|
-
style={
|
|
67
|
-
Object {
|
|
68
|
-
"color": "rgb(15, 130, 204)",
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
>
|
|
72
|
-
'Dynamic parameters'
|
|
73
|
-
</span>
|
|
74
|
-
|
|
75
|
-
list so that the context query parameters can take effect.
|
|
76
|
-
</p>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
<div
|
|
80
|
-
className="mocked-default-widget"
|
|
81
|
-
id="mocked-field-tableau_height"
|
|
82
|
-
>
|
|
83
|
-
<a
|
|
84
|
-
href="https://developer.mozilla.org/en-US/docs/Web/CSS/height"
|
|
85
|
-
rel="noreferrer"
|
|
86
|
-
target="_blank"
|
|
87
|
-
>
|
|
88
|
-
CSS height
|
|
89
|
-
</a>
|
|
90
|
-
-
|
|
91
|
-
Tableau height
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
<div
|
|
96
|
-
className="accordion ui fluid styled form"
|
|
97
|
-
>
|
|
98
|
-
<div
|
|
99
|
-
id="blockform-fieldset-toolbar"
|
|
100
|
-
>
|
|
101
|
-
<div
|
|
102
|
-
className="active title"
|
|
103
|
-
onClick={[Function]}
|
|
104
|
-
>
|
|
105
|
-
Toolbar
|
|
106
|
-
<svg
|
|
107
|
-
className="icon"
|
|
108
|
-
dangerouslySetInnerHTML={
|
|
109
|
-
Object {
|
|
110
|
-
"__html": undefined,
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
onClick={null}
|
|
114
|
-
style={
|
|
115
|
-
Object {
|
|
116
|
-
"fill": "currentColor",
|
|
117
|
-
"height": "20px",
|
|
118
|
-
"width": "auto",
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
viewBox=""
|
|
122
|
-
xmlns=""
|
|
123
|
-
/>
|
|
124
|
-
</div>
|
|
125
|
-
<div
|
|
126
|
-
className="content active"
|
|
127
|
-
>
|
|
128
|
-
<div
|
|
129
|
-
aria-hidden={false}
|
|
130
|
-
className="rah-static rah-static--height-auto"
|
|
131
|
-
style={
|
|
132
|
-
Object {
|
|
133
|
-
"height": "auto",
|
|
134
|
-
"overflow": "visible",
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
>
|
|
138
|
-
<div
|
|
139
|
-
style={
|
|
140
|
-
Object {
|
|
141
|
-
"WebkitTransition": "opacity 500ms ease 0ms",
|
|
142
|
-
"transition": "opacity 500ms ease 0ms",
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
>
|
|
146
|
-
<div
|
|
147
|
-
className="ui segment attached"
|
|
148
|
-
>
|
|
149
|
-
<div
|
|
150
|
-
className="mocked-boolean-widget"
|
|
151
|
-
id="mocked-field-with_notes"
|
|
152
|
-
>
|
|
153
|
-
Show note
|
|
154
|
-
-
|
|
155
|
-
No description
|
|
156
|
-
</div>
|
|
157
|
-
<div
|
|
158
|
-
className="mocked-boolean-widget"
|
|
159
|
-
id="mocked-field-with_more_info"
|
|
160
|
-
>
|
|
161
|
-
Show more info
|
|
162
|
-
-
|
|
163
|
-
No description
|
|
164
|
-
</div>
|
|
165
|
-
<div
|
|
166
|
-
className="mocked-boolean-widget"
|
|
167
|
-
id="mocked-field-with_download"
|
|
168
|
-
>
|
|
169
|
-
Show download button
|
|
170
|
-
-
|
|
171
|
-
No description
|
|
172
|
-
</div>
|
|
173
|
-
<div
|
|
174
|
-
className="mocked-boolean-widget"
|
|
175
|
-
id="mocked-field-with_share"
|
|
176
|
-
>
|
|
177
|
-
Show share button
|
|
178
|
-
-
|
|
179
|
-
No description
|
|
180
|
-
</div>
|
|
181
|
-
<div
|
|
182
|
-
className="mocked-boolean-widget"
|
|
183
|
-
id="mocked-field-with_enlarge"
|
|
184
|
-
>
|
|
185
|
-
Show enlarge button
|
|
186
|
-
-
|
|
187
|
-
No description
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
<div
|
|
196
|
-
className="accordion ui fluid styled form"
|
|
197
|
-
>
|
|
198
|
-
<div
|
|
199
|
-
id="blockform-fieldset-options"
|
|
200
|
-
>
|
|
201
|
-
<div
|
|
202
|
-
className="title"
|
|
203
|
-
onClick={[Function]}
|
|
204
|
-
>
|
|
205
|
-
Parameters
|
|
206
|
-
<svg
|
|
207
|
-
className="icon"
|
|
208
|
-
dangerouslySetInnerHTML={
|
|
209
|
-
Object {
|
|
210
|
-
"__html": undefined,
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
onClick={null}
|
|
214
|
-
style={
|
|
215
|
-
Object {
|
|
216
|
-
"fill": "currentColor",
|
|
217
|
-
"height": "20px",
|
|
218
|
-
"width": "auto",
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
viewBox=""
|
|
222
|
-
xmlns=""
|
|
223
|
-
/>
|
|
224
|
-
</div>
|
|
225
|
-
<div
|
|
226
|
-
className="content"
|
|
227
|
-
>
|
|
228
|
-
<div
|
|
229
|
-
aria-hidden={true}
|
|
230
|
-
className="rah-static rah-static--height-zero"
|
|
231
|
-
style={
|
|
232
|
-
Object {
|
|
233
|
-
"height": 0,
|
|
234
|
-
"overflow": "hidden",
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
>
|
|
238
|
-
<div
|
|
239
|
-
style={
|
|
240
|
-
Object {
|
|
241
|
-
"WebkitTransition": "opacity 500ms ease 0ms",
|
|
242
|
-
"opacity": 0,
|
|
243
|
-
"transition": "opacity 500ms ease 0ms",
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
>
|
|
247
|
-
<div
|
|
248
|
-
className="ui segment attached"
|
|
249
|
-
>
|
|
250
|
-
<div
|
|
251
|
-
className="mocked-default-widget"
|
|
252
|
-
id="mocked-field-staticParameters"
|
|
253
|
-
>
|
|
254
|
-
Static parameters
|
|
255
|
-
-
|
|
256
|
-
Set a list of static parameters.
|
|
257
|
-
</div>
|
|
258
|
-
</div>
|
|
259
|
-
</div>
|
|
260
|
-
</div>
|
|
261
|
-
</div>
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
<div
|
|
265
|
-
className="accordion ui fluid styled form"
|
|
266
|
-
>
|
|
267
|
-
<div
|
|
268
|
-
id="blockform-fieldset-privacy"
|
|
269
|
-
>
|
|
270
|
-
<div
|
|
271
|
-
className="title"
|
|
272
|
-
onClick={[Function]}
|
|
273
|
-
>
|
|
274
|
-
Privacy
|
|
275
|
-
<svg
|
|
276
|
-
className="icon"
|
|
277
|
-
dangerouslySetInnerHTML={
|
|
278
|
-
Object {
|
|
279
|
-
"__html": undefined,
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
onClick={null}
|
|
283
|
-
style={
|
|
284
|
-
Object {
|
|
285
|
-
"fill": "currentColor",
|
|
286
|
-
"height": "20px",
|
|
287
|
-
"width": "auto",
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
viewBox=""
|
|
291
|
-
xmlns=""
|
|
292
|
-
/>
|
|
293
|
-
</div>
|
|
294
|
-
<div
|
|
295
|
-
className="content"
|
|
296
|
-
>
|
|
297
|
-
<div
|
|
298
|
-
aria-hidden={true}
|
|
299
|
-
className="rah-static rah-static--height-zero"
|
|
300
|
-
style={
|
|
301
|
-
Object {
|
|
302
|
-
"height": 0,
|
|
303
|
-
"overflow": "hidden",
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
>
|
|
307
|
-
<div
|
|
308
|
-
style={
|
|
309
|
-
Object {
|
|
310
|
-
"WebkitTransition": "opacity 500ms ease 0ms",
|
|
311
|
-
"opacity": 0,
|
|
312
|
-
"transition": "opacity 500ms ease 0ms",
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
>
|
|
316
|
-
<div
|
|
317
|
-
className="ui segment attached"
|
|
318
|
-
>
|
|
319
|
-
<div
|
|
320
|
-
className="mocked-default-widget"
|
|
321
|
-
id="mocked-field-dataprotection"
|
|
322
|
-
>
|
|
323
|
-
No title
|
|
324
|
-
-
|
|
325
|
-
No description
|
|
326
|
-
</div>
|
|
327
|
-
</div>
|
|
328
|
-
</div>
|
|
329
|
-
</div>
|
|
330
|
-
</div>
|
|
331
|
-
</div>
|
|
332
|
-
</div>
|
|
333
|
-
</div>
|
|
334
|
-
</div>,
|
|
335
|
-
]
|
|
336
|
-
`;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`View should render the component 1`] = `
|
|
4
|
-
<div
|
|
5
|
-
className="embed-tableau"
|
|
6
|
-
>
|
|
7
|
-
<div
|
|
8
|
-
className="privacy-protection-wrapper"
|
|
9
|
-
style={
|
|
10
|
-
Object {
|
|
11
|
-
"height": "auto",
|
|
12
|
-
"minHeight": "200px",
|
|
13
|
-
"overflow": "hidden",
|
|
14
|
-
"position": "relative",
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
>
|
|
18
|
-
<div
|
|
19
|
-
className="tableau-wrapper"
|
|
20
|
-
>
|
|
21
|
-
<div
|
|
22
|
-
className="tableau tableau-2.8.0"
|
|
23
|
-
style={
|
|
24
|
-
Object {
|
|
25
|
-
"height": "700px",
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
`;
|