@eeacms/volto-tableau 8.1.5 → 9.0.1
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/.eslintrc.js +6 -6
- package/CHANGELOG.md +19 -0
- package/DEVELOP.md +19 -17
- package/Dockerfile +10 -1
- package/Jenkinsfile +88 -82
- package/Makefile +3 -3
- package/README.md +33 -19
- package/cypress/e2e/block-basics.cy.js +9 -7
- package/cypress/e2e/block-tableau.cy.js +12 -5
- package/cypress/support/commands.js +7 -3
- package/docker-compose.yml +1 -1
- package/jest-addon.config.js +16 -4
- package/package.json +1 -1
- package/src/Blocks/EmbedTableauVisualization/Edit.jsx +1 -1
- package/src/Blocks/EmbedTableauVisualization/Edit.test.jsx +10 -59
- package/src/Blocks/EmbedTableauVisualization/View.jsx +3 -3
- package/src/Blocks/EmbedTableauVisualization/View.test.jsx +1 -1
- package/src/Blocks/TableauBlock/Edit.jsx +1 -1
- package/src/Blocks/TableauBlock/View.test.jsx +1 -1
- package/src/Blocks/index.js +1 -1
- package/src/Tableau/Tableau.jsx +16 -17
- package/src/Tableau/Tableau.test.jsx +1 -1
- package/src/Tableau/helpers.js +3 -1
- package/src/Views/VisualizationView.jsx +1 -1
- package/src/Views/VisualizationView.test.jsx +1 -1
- package/src/Widgets/CreatableSelectWidget.jsx +7 -4
- package/src/Widgets/VisualizationViewWidget.test.jsx +1 -1
- package/src/Widgets/VisualizationWidget.jsx +4 -3
- package/src/Widgets/VisualizationWidget.test.jsx +9 -4
- package/src/Widgets/{schema.js → schema.jsx} +3 -1
- /package/src/Blocks/EmbedTableauVisualization/{schema.js → schema.jsx} +0 -0
- /package/src/Blocks/TableauBlock/{schema.js → schema.jsx} +0 -0
package/.eslintrc.js
CHANGED
|
@@ -16,16 +16,16 @@ if (configFile) {
|
|
|
16
16
|
voltoPath = `./${jsConfig.baseUrl}/${pathsConfig['@plone/volto'][0]}`;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
const
|
|
19
|
+
const { AddonRegistry } = require('@plone/registry/addon-registry');
|
|
20
|
+
const { registry } = AddonRegistry.init(projectRootPath);
|
|
21
21
|
|
|
22
22
|
// Extends ESlint configuration for adding the aliases to `src` directories in Volto addons
|
|
23
|
-
const addonAliases = Object.keys(
|
|
23
|
+
const addonAliases = Object.keys(registry.packages).map((o) => [
|
|
24
24
|
o,
|
|
25
|
-
|
|
25
|
+
registry.packages[o].modulePath,
|
|
26
26
|
]);
|
|
27
27
|
|
|
28
|
-
const addonExtenders =
|
|
28
|
+
const addonExtenders = registry.getEslintExtenders().map((m) => require(m));
|
|
29
29
|
|
|
30
30
|
const defaultConfig = {
|
|
31
31
|
extends: `${voltoPath}/.eslintrc`,
|
|
@@ -34,7 +34,7 @@ const defaultConfig = {
|
|
|
34
34
|
alias: {
|
|
35
35
|
map: [
|
|
36
36
|
['@plone/volto', '@plone/volto/src'],
|
|
37
|
-
['@plone/volto-slate', '@plone/volto
|
|
37
|
+
['@plone/volto-slate', '@plone/volto-slate/src'],
|
|
38
38
|
...addonAliases,
|
|
39
39
|
['@package', `${__dirname}/src`],
|
|
40
40
|
['@root', `${__dirname}/src`],
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ 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
|
+
### [9.0.1](https://github.com/eea/volto-tableau/compare/9.0.0...9.0.1) - 8 April 2026
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- test: Fix make test [Alin V. (Claudiu) - [`34446a7`](https://github.com/eea/volto-tableau/commit/34446a71fa6f5715cf797c4c0ca80bed33181d71)]
|
|
12
|
+
## [9.0.0](https://github.com/eea/volto-tableau/compare/8.1.5...9.0.0) - 25 March 2026
|
|
13
|
+
|
|
14
|
+
#### :rocket: New Features
|
|
15
|
+
|
|
16
|
+
- feat: Volto 18 support - refs #287700 [Alin Voinea - [`9b3e664`](https://github.com/eea/volto-tableau/commit/9b3e664c40418e950816242f95f306399dc527c4)]
|
|
17
|
+
|
|
18
|
+
#### :house: Internal changes
|
|
19
|
+
|
|
20
|
+
- chore: [JENKINSFILE] add package version in sonarqube [valentinab25 - [`929dd7c`](https://github.com/eea/volto-tableau/commit/929dd7cb27faaecf96f133377acf4efcc8e0ca78)]
|
|
21
|
+
- chore: [JENKINSFILE] use sonarqube branches [EEA Jenkins - [`ce94213`](https://github.com/eea/volto-tableau/commit/ce9421395395abfc6ddab7950f9a2c9ffadbfbbe)]
|
|
22
|
+
|
|
23
|
+
#### :hammer_and_wrench: Others
|
|
24
|
+
|
|
25
|
+
- tests: Fix Sonar Qube tags - refs #297339 [Alin Voinea - [`cfbd646`](https://github.com/eea/volto-tableau/commit/cfbd646a9c09cb90f6ffa6a886822e7a4759ba4d)]
|
|
7
26
|
### [8.1.5](https://github.com/eea/volto-tableau/compare/8.1.4...8.1.5) - 4 August 2025
|
|
8
27
|
|
|
9
28
|
#### :hammer_and_wrench: Others
|
package/DEVELOP.md
CHANGED
|
@@ -26,21 +26,20 @@
|
|
|
26
26
|
|
|
27
27
|
### Or add @eeacms/volto-tableau to your Volto project
|
|
28
28
|
|
|
29
|
-
Before starting make sure your development environment is properly set. See [Volto
|
|
29
|
+
Before starting make sure your development environment is properly set. See the official Plone documentation for [creating a project with Cookieplone](https://6.docs.plone.org/install/create-project-cookieplone.html) and [installing an add-on in development mode in Volto 18 and 19](https://6.docs.plone.org/volto/development/add-ons/install-an-add-on-dev-18.html).
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
For new Volto 18+ projects, use Cookieplone. It includes `mrs-developer` by default.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
1. Create a new Volto project with Cookieplone
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
yo @plone/volto my-volto-project --addon @eeacms/volto-tableau --skip-install
|
|
38
|
-
cd my-volto-project
|
|
35
|
+
uvx cookieplone project
|
|
36
|
+
cd project-title
|
|
39
37
|
|
|
40
38
|
1. Add the following to `mrs.developer.json`:
|
|
41
39
|
|
|
42
40
|
{
|
|
43
41
|
"volto-tableau": {
|
|
42
|
+
"output": "packages",
|
|
44
43
|
"url": "https://github.com/eea/volto-tableau.git",
|
|
45
44
|
"package": "@eeacms/volto-tableau",
|
|
46
45
|
"branch": "develop",
|
|
@@ -48,28 +47,31 @@ Before starting make sure your development environment is properly set. See [Vol
|
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
1.
|
|
50
|
+
1. Add `@eeacms/volto-tableau` to the `addons` key in your project `volto.config.js`
|
|
51
|
+
|
|
52
|
+
1. Install or refresh the project setup
|
|
52
53
|
|
|
53
|
-
make
|
|
54
|
-
yarn
|
|
54
|
+
make install
|
|
55
55
|
|
|
56
|
-
1. Start backend
|
|
56
|
+
1. Start backend in one terminal
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
make backend-start
|
|
59
59
|
|
|
60
|
-
...wait for backend to setup and start
|
|
60
|
+
...wait for backend to setup and start, ending with `Ready to handle requests`
|
|
61
61
|
|
|
62
62
|
...you can also check http://localhost:8080/Plone
|
|
63
63
|
|
|
64
|
-
1. Start frontend
|
|
64
|
+
1. Start frontend in a second terminal
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
make frontend-start
|
|
67
67
|
|
|
68
68
|
1. Go to http://localhost:3000
|
|
69
69
|
|
|
70
70
|
1. Happy hacking!
|
|
71
71
|
|
|
72
|
-
cd
|
|
72
|
+
cd packages/volto-tableau
|
|
73
|
+
|
|
74
|
+
For legacy Volto 17 projects, keep using the yarn-based workflow from the Volto 17 documentation.
|
|
73
75
|
|
|
74
76
|
## Cypress
|
|
75
77
|
|
|
@@ -81,7 +83,7 @@ project where you added `volto-tableau` to `mrs.developer.json`
|
|
|
81
83
|
Go to:
|
|
82
84
|
|
|
83
85
|
```BASH
|
|
84
|
-
cd
|
|
86
|
+
cd packages/volto-tableau/
|
|
85
87
|
```
|
|
86
88
|
|
|
87
89
|
Start:
|
package/Dockerfile
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
# syntax=docker/dockerfile:1
|
|
2
2
|
ARG VOLTO_VERSION
|
|
3
|
-
FROM
|
|
3
|
+
FROM plone/frontend-builder:${VOLTO_VERSION}
|
|
4
4
|
|
|
5
5
|
ARG ADDON_NAME
|
|
6
6
|
ARG ADDON_PATH
|
|
7
|
+
ENV HOST="0.0.0.0"
|
|
8
|
+
|
|
9
|
+
USER root
|
|
10
|
+
RUN apt-get update -q \
|
|
11
|
+
&& apt-get install -qy --no-install-recommends \
|
|
12
|
+
chromium libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb \
|
|
13
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
14
|
+
USER node
|
|
7
15
|
|
|
8
16
|
COPY --chown=node:node ./ /app/src/addons/${ADDON_PATH}/
|
|
9
17
|
|
|
10
18
|
RUN /setupAddon
|
|
19
|
+
RUN yarn add jest-junit
|
|
11
20
|
RUN yarn install
|
|
12
21
|
|
|
13
22
|
ENTRYPOINT ["yarn"]
|
package/Jenkinsfile
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
pipeline {
|
|
2
|
-
tools {
|
|
3
|
-
jdk 'Java17'
|
|
4
|
-
}
|
|
5
2
|
agent {
|
|
6
3
|
node { label 'docker-host' }
|
|
7
4
|
}
|
|
@@ -9,12 +6,12 @@ pipeline {
|
|
|
9
6
|
environment {
|
|
10
7
|
GIT_NAME = "volto-tableau"
|
|
11
8
|
NAMESPACE = "@eeacms"
|
|
12
|
-
SONARQUBE_TAGS = "volto.eea.europa.eu,climate-energy.eea.europa.eu,forest.eea.europa.eu,biodiversity.europa.eu,water.europa.eu-freshwater,water.europa.eu-marine,industry.eea.europa.eu,demo-www.eea.europa.eu,www.eea.europa.eu-en,insitu.copernicus.eu"
|
|
9
|
+
SONARQUBE_TAGS = "volto.eea.europa.eu,climate-energy.eea.europa.eu,forest.eea.europa.eu,biodiversity.europa.eu,water.europa.eu-freshwater,water.europa.eu-marine,industry.eea.europa.eu,demo-www.eea.europa.eu,www.eea.europa.eu-en,www.eea.europa.eu,insitu.copernicus.eu"
|
|
13
10
|
DEPENDENCIES = ""
|
|
14
11
|
BACKEND_PROFILES = "eea.kitkat:testing"
|
|
15
12
|
BACKEND_ADDONS = ""
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
CURRENT_VOLTO = "18-yarn"
|
|
14
|
+
PREVIOUS_VOLTO = "17"
|
|
18
15
|
IMAGE_NAME = BUILD_TAG.toLowerCase()
|
|
19
16
|
}
|
|
20
17
|
|
|
@@ -75,12 +72,13 @@ pipeline {
|
|
|
75
72
|
}
|
|
76
73
|
parallel {
|
|
77
74
|
|
|
78
|
-
stage
|
|
75
|
+
// Declarative stage names must stay string literals.
|
|
76
|
+
stage('Volto 18-yarn') {
|
|
79
77
|
agent { node { label 'docker-1.13'} }
|
|
80
78
|
stages {
|
|
81
79
|
stage('Build test image') {
|
|
82
80
|
steps {
|
|
83
|
-
sh '''docker build --pull --build-arg="VOLTO_VERSION=$
|
|
81
|
+
sh '''docker build --pull --build-arg="VOLTO_VERSION=$CURRENT_VOLTO" --build-arg="ADDON_NAME=$NAMESPACE/$GIT_NAME" --build-arg="ADDON_PATH=$GIT_NAME" . -t $IMAGE_NAME-frontend-current'''
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
|
|
@@ -91,9 +89,9 @@ pipeline {
|
|
|
91
89
|
}
|
|
92
90
|
steps {
|
|
93
91
|
script {
|
|
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)
|
|
95
|
-
sh '''docker cp $IMAGE_NAME-fix:/app/src/addons/$GIT_NAME/src .'''
|
|
96
|
-
sh '''docker rm -v $IMAGE_NAME-fix'''
|
|
92
|
+
fix_result = sh(script: '''docker run --name="$IMAGE_NAME-fix-current" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-current ci-fix''', returnStatus: true)
|
|
93
|
+
sh '''docker cp $IMAGE_NAME-fix-current:/app/src/addons/$GIT_NAME/src .'''
|
|
94
|
+
sh '''docker rm -v $IMAGE_NAME-fix-current'''
|
|
97
95
|
FOUND_FIX = sh(script: '''git diff | wc -l''', returnStdout: true).trim()
|
|
98
96
|
|
|
99
97
|
if (FOUND_FIX != '0') {
|
|
@@ -114,21 +112,21 @@ pipeline {
|
|
|
114
112
|
stage('ES lint') {
|
|
115
113
|
when { environment name: 'SKIP_TESTS', value: '' }
|
|
116
114
|
steps {
|
|
117
|
-
sh '''docker run --rm --name="$IMAGE_NAME-eslint" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend lint'''
|
|
115
|
+
sh '''docker run --rm --name="$IMAGE_NAME-eslint-current" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-current lint'''
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
|
|
121
119
|
stage('Style lint') {
|
|
122
120
|
when { environment name: 'SKIP_TESTS', value: '' }
|
|
123
121
|
steps {
|
|
124
|
-
sh '''docker run --rm --name="$IMAGE_NAME-stylelint" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend stylelint'''
|
|
122
|
+
sh '''docker run --rm --name="$IMAGE_NAME-stylelint-current" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-current stylelint'''
|
|
125
123
|
}
|
|
126
124
|
}
|
|
127
125
|
|
|
128
126
|
stage('Prettier') {
|
|
129
127
|
when { environment name: 'SKIP_TESTS', value: '' }
|
|
130
128
|
steps {
|
|
131
|
-
sh '''docker run --rm --name="$IMAGE_NAME-prettier" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend prettier'''
|
|
129
|
+
sh '''docker run --rm --name="$IMAGE_NAME-prettier-current" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-current prettier'''
|
|
132
130
|
}
|
|
133
131
|
}
|
|
134
132
|
stage('Unit tests') {
|
|
@@ -136,25 +134,25 @@ pipeline {
|
|
|
136
134
|
steps {
|
|
137
135
|
script {
|
|
138
136
|
try {
|
|
139
|
-
sh '''docker run --name="$IMAGE_NAME-volto" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend test-ci'''
|
|
140
|
-
sh '''rm -rf xunit-reports'''
|
|
141
|
-
sh '''mkdir -p xunit-reports'''
|
|
142
|
-
sh '''docker cp $IMAGE_NAME-volto:/app/coverage xunit-reports/'''
|
|
143
|
-
sh '''docker cp $IMAGE_NAME-volto:/app/junit.xml xunit-reports/'''
|
|
137
|
+
sh '''docker run --name="$IMAGE_NAME-volto-current" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-current test-ci'''
|
|
138
|
+
sh '''rm -rf xunit-reports-current'''
|
|
139
|
+
sh '''mkdir -p xunit-reports-current'''
|
|
140
|
+
sh '''docker cp $IMAGE_NAME-volto-current:/app/coverage xunit-reports-current/'''
|
|
141
|
+
sh '''docker cp $IMAGE_NAME-volto-current:/app/junit.xml xunit-reports-current/'''
|
|
144
142
|
publishHTML(target : [
|
|
145
143
|
allowMissing: false,
|
|
146
144
|
alwaysLinkToLastBuild: true,
|
|
147
145
|
keepAll: true,
|
|
148
|
-
reportDir: 'xunit-reports/coverage/lcov-report',
|
|
146
|
+
reportDir: 'xunit-reports-current/coverage/lcov-report',
|
|
149
147
|
reportFiles: 'index.html',
|
|
150
148
|
reportName: 'UTCoverage',
|
|
151
149
|
reportTitles: 'Unit Tests Code Coverage'
|
|
152
150
|
])
|
|
153
151
|
} finally {
|
|
154
152
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
155
|
-
junit testResults: 'xunit-reports/junit.xml', allowEmptyResults: true
|
|
153
|
+
junit testResults: 'xunit-reports-current/junit.xml', allowEmptyResults: true
|
|
156
154
|
}
|
|
157
|
-
sh script: '''docker rm -v $IMAGE_NAME-volto''', returnStatus: true
|
|
155
|
+
sh script: '''docker rm -v $IMAGE_NAME-volto-current''', returnStatus: true
|
|
158
156
|
}
|
|
159
157
|
}
|
|
160
158
|
}
|
|
@@ -165,52 +163,52 @@ pipeline {
|
|
|
165
163
|
steps {
|
|
166
164
|
script {
|
|
167
165
|
try {
|
|
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'''
|
|
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
|
|
166
|
+
sh '''docker run --pull always --rm -d --name="$IMAGE_NAME-plone-current" -e SITE="Plone" -e PROFILES="$BACKEND_PROFILES" -e ADDONS="$BACKEND_ADDONS" eeacms/plone-backend'''
|
|
167
|
+
sh '''docker run -d --shm-size=4g --link $IMAGE_NAME-plone-current:plone --name="$IMAGE_NAME-cypress-current" -e "RAZZLE_INTERNAL_API_PATH=http://plone:8080/Plone" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-current start-ci'''
|
|
168
|
+
frontend = sh script:'''docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress-current make check-ci''', returnStatus: true
|
|
171
169
|
if ( frontend != 0 ) {
|
|
172
|
-
sh '''docker logs $IMAGE_NAME-cypress; exit 1'''
|
|
170
|
+
sh '''docker logs $IMAGE_NAME-cypress-current; exit 1'''
|
|
173
171
|
}
|
|
174
172
|
|
|
175
|
-
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress make cypress-ci'''
|
|
173
|
+
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress-current make cypress-ci'''
|
|
176
174
|
} finally {
|
|
177
175
|
try {
|
|
178
176
|
if ( frontend == 0 ) {
|
|
179
|
-
sh '''rm -rf cypress-videos cypress-results cypress-coverage cypress-screenshots'''
|
|
180
|
-
sh '''mkdir -p cypress-videos cypress-results cypress-coverage cypress-screenshots'''
|
|
181
|
-
videos = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos/''', returnStatus: true
|
|
182
|
-
sh '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/reports cypress-results/'''
|
|
183
|
-
screenshots = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/screenshots cypress-screenshots''', returnStatus: true
|
|
177
|
+
sh '''rm -rf cypress-videos-current cypress-results-current cypress-coverage-current cypress-screenshots-current'''
|
|
178
|
+
sh '''mkdir -p cypress-videos-current cypress-results-current cypress-coverage-current cypress-screenshots-current'''
|
|
179
|
+
videos = sh script: '''docker cp $IMAGE_NAME-cypress-current:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos-current/''', returnStatus: true
|
|
180
|
+
sh '''docker cp $IMAGE_NAME-cypress-current:/app/src/addons/$GIT_NAME/cypress/reports cypress-results-current/'''
|
|
181
|
+
screenshots = sh script: '''docker cp $IMAGE_NAME-cypress-current:/app/src/addons/$GIT_NAME/cypress/screenshots cypress-screenshots-current''', returnStatus: true
|
|
184
182
|
|
|
185
|
-
archiveArtifacts artifacts: 'cypress-screenshots/**', fingerprint: true, allowEmptyArchive: true
|
|
183
|
+
archiveArtifacts artifacts: 'cypress-screenshots-current/**', fingerprint: true, allowEmptyArchive: true
|
|
186
184
|
|
|
187
|
-
coverage = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/coverage cypress-coverage''', returnStatus: true
|
|
185
|
+
coverage = sh script: '''docker cp $IMAGE_NAME-cypress-current:/app/src/addons/$GIT_NAME/coverage cypress-coverage-current''', returnStatus: true
|
|
188
186
|
|
|
189
187
|
if ( coverage == 0 ) {
|
|
190
188
|
publishHTML(target : [allowMissing: false,
|
|
191
189
|
alwaysLinkToLastBuild: true,
|
|
192
190
|
keepAll: true,
|
|
193
|
-
reportDir: 'cypress-coverage/coverage/lcov-report',
|
|
191
|
+
reportDir: 'cypress-coverage-current/coverage/lcov-report',
|
|
194
192
|
reportFiles: 'index.html',
|
|
195
193
|
reportName: 'CypressCoverage',
|
|
196
194
|
reportTitles: 'Integration Tests Code Coverage'])
|
|
197
195
|
}
|
|
198
196
|
if ( videos == 0 ) {
|
|
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'''
|
|
200
|
-
archiveArtifacts artifacts: 'cypress-videos/**/*.mp4', fingerprint: true, allowEmptyArchive: true
|
|
197
|
+
sh '''for file in $(find cypress-results-current -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-current/videos/$testname.mp4; fi; done'''
|
|
198
|
+
archiveArtifacts artifacts: 'cypress-videos-current/**/*.mp4', fingerprint: true, allowEmptyArchive: true
|
|
201
199
|
}
|
|
202
200
|
}
|
|
203
201
|
} finally {
|
|
204
202
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
205
|
-
junit testResults: 'cypress-results/**/*.xml', allowEmptyResults: true
|
|
203
|
+
junit testResults: 'cypress-results-current/**/*.xml', allowEmptyResults: true
|
|
206
204
|
}
|
|
207
205
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
208
|
-
sh '''docker logs $IMAGE_NAME-cypress'''
|
|
206
|
+
sh '''docker logs $IMAGE_NAME-cypress-current'''
|
|
209
207
|
}
|
|
210
|
-
sh script: "docker stop $IMAGE_NAME-cypress", returnStatus: true
|
|
211
|
-
sh script: "docker stop $IMAGE_NAME-plone", returnStatus: true
|
|
212
|
-
sh script: "docker rm -v $IMAGE_NAME-plone", returnStatus: true
|
|
213
|
-
sh script: "docker rm -v $IMAGE_NAME-cypress", returnStatus: true
|
|
208
|
+
sh script: "docker stop $IMAGE_NAME-cypress-current", returnStatus: true
|
|
209
|
+
sh script: "docker stop $IMAGE_NAME-plone-current", returnStatus: true
|
|
210
|
+
sh script: "docker rm -v $IMAGE_NAME-plone-current", returnStatus: true
|
|
211
|
+
sh script: "docker rm -v $IMAGE_NAME-cypress-current", returnStatus: true
|
|
214
212
|
}
|
|
215
213
|
}
|
|
216
214
|
}
|
|
@@ -242,11 +240,17 @@ pipeline {
|
|
|
242
240
|
script {
|
|
243
241
|
def scannerHome = tool 'SonarQubeScanner'
|
|
244
242
|
def nodeJS = tool 'NodeJS'
|
|
243
|
+
if (env.CHANGE_ID) {
|
|
244
|
+
env.sonarParams = " -Dsonar.pullrequest.base=${env.CHANGE_TARGET} -Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} -Dsonar.pullrequest.key=${env.CHANGE_ID} "
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
env.sonarParams = " -Dsonar.branch.name=${env.BRANCH_NAME}"
|
|
248
|
+
}
|
|
245
249
|
withSonarQubeEnv('Sonarqube') {
|
|
246
|
-
sh '''sed -i "s#/app/src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
|
|
247
|
-
sh '''sed -i "s#src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
|
|
248
|
-
sh "export PATH=${scannerHome}/bin:${nodeJS}/bin:$PATH; sonar-scanner -Dsonar.javascript.lcov.reportPaths=./xunit-reports/coverage/lcov.info,./cypress-coverage/coverage/lcov.info -Dsonar.sources=./src -Dsonar.projectKey=$GIT_NAME
|
|
249
|
-
sh '''try=5; while [ \$try -gt 0 ]; do curl -s -XPOST -u "${SONAR_AUTH_TOKEN}:" "${SONAR_HOST_URL}api/project_tags/set?project=${GIT_NAME}
|
|
250
|
+
sh '''sed -i "s#/app/src/addons/${GIT_NAME}/##g" xunit-reports-current/coverage/lcov.info'''
|
|
251
|
+
sh '''sed -i "s#src/addons/${GIT_NAME}/##g" xunit-reports-current/coverage/lcov.info'''
|
|
252
|
+
sh "export PATH=${scannerHome}/bin:${nodeJS}/bin:$PATH; sonar-scanner -Dsonar.javascript.lcov.reportPaths=./xunit-reports-current/coverage/lcov.info,./cypress-coverage-current/coverage/lcov.info -Dsonar.sources=./src -Dsonar.projectKey=$GIT_NAME -Dsonar.projectName=$GIT_NAME -Dsonar.projectVersion=\$(jq -r '.version' package.json) ${env.sonarParams}"
|
|
253
|
+
sh '''try=5; while [ \$try -gt 0 ]; do curl -s -XPOST -u "${SONAR_AUTH_TOKEN}:" "${SONAR_HOST_URL}api/project_tags/set?project=${GIT_NAME}&tags=${SONARQUBE_TAGS}" > set_tags_result; if [ \$(grep -ic error set_tags_result ) -eq 0 ]; then try=0; else cat set_tags_result; echo "... Will retry"; sleep 15; try=\$(( \$try - 1 )); fi; done'''
|
|
250
254
|
}
|
|
251
255
|
}
|
|
252
256
|
}
|
|
@@ -256,75 +260,77 @@ pipeline {
|
|
|
256
260
|
}
|
|
257
261
|
}
|
|
258
262
|
|
|
259
|
-
stage('Volto
|
|
263
|
+
stage('Volto 17') {
|
|
260
264
|
agent { node { label 'integration'} }
|
|
261
|
-
when {
|
|
262
|
-
|
|
263
|
-
|
|
265
|
+
when {
|
|
266
|
+
allOf {
|
|
267
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
268
|
+
expression { return !!env.PREVIOUS_VOLTO?.trim() }
|
|
269
|
+
}
|
|
264
270
|
}
|
|
265
271
|
stages {
|
|
266
272
|
stage('Build test image') {
|
|
267
273
|
steps {
|
|
268
|
-
sh '''docker build --pull --build-arg="VOLTO_VERSION
|
|
274
|
+
sh '''docker build --pull --build-arg="VOLTO_VERSION=$PREVIOUS_VOLTO" --build-arg="ADDON_NAME=$NAMESPACE/$GIT_NAME" --build-arg="ADDON_PATH=$GIT_NAME" . -t $IMAGE_NAME-frontend-previous'''
|
|
269
275
|
}
|
|
270
276
|
}
|
|
271
277
|
|
|
272
|
-
stage('Unit tests
|
|
278
|
+
stage('Unit tests') {
|
|
273
279
|
steps {
|
|
274
280
|
script {
|
|
275
281
|
try {
|
|
276
|
-
sh '''docker run --name="$IMAGE_NAME-
|
|
277
|
-
sh '''rm -rf xunit-
|
|
278
|
-
sh '''mkdir -p xunit-
|
|
279
|
-
sh '''docker cp $IMAGE_NAME-
|
|
282
|
+
sh '''docker run --name="$IMAGE_NAME-volto-previous" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-previous test-ci'''
|
|
283
|
+
sh '''rm -rf xunit-reports-previous'''
|
|
284
|
+
sh '''mkdir -p xunit-reports-previous'''
|
|
285
|
+
sh '''docker cp $IMAGE_NAME-volto-previous:/app/junit.xml xunit-reports-previous/'''
|
|
280
286
|
} finally {
|
|
281
287
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
282
|
-
junit testResults: 'xunit-
|
|
288
|
+
junit testResults: 'xunit-reports-previous/junit.xml', allowEmptyResults: true
|
|
283
289
|
}
|
|
284
|
-
sh script: '''docker rm -v $IMAGE_NAME-
|
|
290
|
+
sh script: '''docker rm -v $IMAGE_NAME-volto-previous''', returnStatus: true
|
|
285
291
|
}
|
|
286
292
|
}
|
|
287
293
|
}
|
|
288
294
|
}
|
|
289
295
|
|
|
290
|
-
stage('Integration tests
|
|
296
|
+
stage('Integration tests') {
|
|
291
297
|
steps {
|
|
292
298
|
script {
|
|
293
299
|
try {
|
|
294
|
-
sh '''docker run --pull always --rm -d --name="$IMAGE_NAME-
|
|
295
|
-
sh '''docker run -d --shm-size=4g --link $IMAGE_NAME-
|
|
296
|
-
frontend = sh script:'''docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-
|
|
300
|
+
sh '''docker run --pull always --rm -d --name="$IMAGE_NAME-plone-previous" -e SITE="Plone" -e PROFILES="$BACKEND_PROFILES" -e ADDONS="$BACKEND_ADDONS" eeacms/plone-backend'''
|
|
301
|
+
sh '''docker run -d --shm-size=4g --link $IMAGE_NAME-plone-previous:plone --name="$IMAGE_NAME-cypress-previous" -e "RAZZLE_INTERNAL_API_PATH=http://plone:8080/Plone" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend-previous start-ci'''
|
|
302
|
+
frontend = sh script:'''docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress-previous make check-ci''', returnStatus: true
|
|
297
303
|
if ( frontend != 0 ) {
|
|
298
|
-
sh '''docker logs $IMAGE_NAME-
|
|
304
|
+
sh '''docker logs $IMAGE_NAME-cypress-previous; exit 1'''
|
|
299
305
|
}
|
|
300
|
-
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-
|
|
306
|
+
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress-previous make cypress-ci'''
|
|
301
307
|
} finally {
|
|
302
308
|
try {
|
|
303
309
|
if ( frontend == 0 ) {
|
|
304
|
-
sh '''rm -rf cypress-
|
|
305
|
-
sh '''mkdir -p cypress-
|
|
306
|
-
videos = sh script: '''docker cp $IMAGE_NAME-
|
|
307
|
-
sh '''docker cp $IMAGE_NAME-
|
|
308
|
-
screenshots = sh script: '''docker cp $IMAGE_NAME-
|
|
310
|
+
sh '''rm -rf cypress-videos-previous cypress-results-previous cypress-coverage-previous cypress-screenshots-previous'''
|
|
311
|
+
sh '''mkdir -p cypress-videos-previous cypress-results-previous cypress-coverage-previous cypress-screenshots-previous'''
|
|
312
|
+
videos = sh script: '''docker cp $IMAGE_NAME-cypress-previous:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos-previous/''', returnStatus: true
|
|
313
|
+
sh '''docker cp $IMAGE_NAME-cypress-previous:/app/src/addons/$GIT_NAME/cypress/reports cypress-results-previous/'''
|
|
314
|
+
screenshots = sh script: '''docker cp $IMAGE_NAME-cypress-previous:/app/src/addons/$GIT_NAME/cypress/screenshots cypress-screenshots-previous''', returnStatus: true
|
|
309
315
|
|
|
310
|
-
archiveArtifacts artifacts: 'cypress-
|
|
316
|
+
archiveArtifacts artifacts: 'cypress-screenshots-previous/**', fingerprint: true, allowEmptyArchive: true
|
|
311
317
|
|
|
312
318
|
if ( videos == 0 ) {
|
|
313
|
-
sh '''for file in $(find cypress-
|
|
314
|
-
archiveArtifacts artifacts: 'cypress-
|
|
319
|
+
sh '''for file in $(find cypress-results-previous -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-previous/videos/$testname.mp4; fi; done'''
|
|
320
|
+
archiveArtifacts artifacts: 'cypress-videos-previous/**/*.mp4', fingerprint: true, allowEmptyArchive: true
|
|
315
321
|
}
|
|
316
322
|
}
|
|
317
323
|
} finally {
|
|
318
324
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
319
|
-
junit testResults: 'cypress-
|
|
325
|
+
junit testResults: 'cypress-results-previous/**/*.xml', allowEmptyResults: true
|
|
320
326
|
}
|
|
321
327
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
322
|
-
sh '''docker logs $IMAGE_NAME-
|
|
328
|
+
sh '''docker logs $IMAGE_NAME-cypress-previous'''
|
|
323
329
|
}
|
|
324
|
-
sh script: "docker stop $IMAGE_NAME-
|
|
325
|
-
sh script: "docker stop $IMAGE_NAME-
|
|
326
|
-
sh script: "docker rm -v $IMAGE_NAME-
|
|
327
|
-
sh script: "docker rm -v $IMAGE_NAME-
|
|
330
|
+
sh script: "docker stop $IMAGE_NAME-cypress-previous", returnStatus: true
|
|
331
|
+
sh script: "docker stop $IMAGE_NAME-plone-previous", returnStatus: true
|
|
332
|
+
sh script: "docker rm -v $IMAGE_NAME-plone-previous", returnStatus: true
|
|
333
|
+
sh script: "docker rm -v $IMAGE_NAME-cypress-previous", returnStatus: true
|
|
328
334
|
}
|
|
329
335
|
}
|
|
330
336
|
}
|
|
@@ -336,8 +342,8 @@ pipeline {
|
|
|
336
342
|
}
|
|
337
343
|
post {
|
|
338
344
|
always {
|
|
339
|
-
sh script: "docker rmi $IMAGE_NAME-frontend", returnStatus: true
|
|
340
|
-
sh script: "docker rmi $IMAGE_NAME-
|
|
345
|
+
sh script: "docker rmi $IMAGE_NAME-frontend-current", returnStatus: true
|
|
346
|
+
sh script: "docker rmi $IMAGE_NAME-frontend-previous", returnStatus: true
|
|
341
347
|
}
|
|
342
348
|
}
|
|
343
349
|
}
|
|
@@ -363,7 +369,7 @@ pipeline {
|
|
|
363
369
|
script {
|
|
364
370
|
sh '''echo "Error" > checkresult.txt'''
|
|
365
371
|
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 /
|
|
372
|
+
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 /checkSonarqubemasterV2.sh | grep -v "Found script" | tee checkresult.txt'''
|
|
367
373
|
}
|
|
368
374
|
|
|
369
375
|
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',
|
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?=18-yarn
|
|
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
|
|
@@ -90,11 +90,11 @@ cypress-run: ## Run cypress integration tests
|
|
|
90
90
|
|
|
91
91
|
.PHONY: test
|
|
92
92
|
test: ## Run jest tests
|
|
93
|
-
${DOCKER_COMPOSE} run -e CI=1 frontend test
|
|
93
|
+
${DOCKER_COMPOSE} run --no-deps -e CI=1 frontend test
|
|
94
94
|
|
|
95
95
|
.PHONY: test-update
|
|
96
96
|
test-update: ## Update jest tests snapshots
|
|
97
|
-
${DOCKER_COMPOSE} run -e CI=1 frontend test -u
|
|
97
|
+
${DOCKER_COMPOSE} run --no-deps -e CI=1 frontend test -u
|
|
98
98
|
|
|
99
99
|
.PHONY: stylelint
|
|
100
100
|
stylelint: ## Stylelint
|
package/README.md
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
[](https://github.com/eea/volto-tableau/releases)
|
|
4
4
|
|
|
5
5
|
[](https://ci.eionet.europa.eu/view/Github/job/volto-addons/job/volto-tableau/job/master/display/redirect)
|
|
6
|
-
[](https://sonarqube.eea.europa.eu/api/project_badges/measure?project=volto-tableau
|
|
6
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau)
|
|
7
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau)
|
|
8
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau)
|
|
9
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau)
|
|
10
10
|
|
|
11
11
|
[](https://ci.eionet.europa.eu/view/Github/job/volto-addons/job/volto-tableau/job/develop/display/redirect)
|
|
12
|
-
[](https://sonarqube.eea.europa.eu/api/project_badges/measure?project=volto-tableau
|
|
12
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau&branch=develop)
|
|
13
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau&branch=develop)
|
|
14
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau&branch=develop)
|
|
15
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-tableau&branch=develop)
|
|
16
16
|
|
|
17
17
|
[Volto](https://github.com/plone/volto) add-on
|
|
18
18
|
|
|
@@ -37,6 +37,11 @@ Registers a VisualizationView component for a content type named 'tableau_visual
|
|
|
37
37
|
|
|
38
38
|
Go to http://localhost:3000
|
|
39
39
|
|
|
40
|
+
`make start` now defaults to Volto 18. To run the same setup against Volto 17, use:
|
|
41
|
+
|
|
42
|
+
VOLTO_VERSION=17 make
|
|
43
|
+
VOLTO_VERSION=17 make start
|
|
44
|
+
|
|
40
45
|
### Add volto-tableau to your Volto project
|
|
41
46
|
|
|
42
47
|
1. Make sure you have a [Plone backend](https://plone.org/download) up-and-running at http://localhost:8080/Plone
|
|
@@ -50,30 +55,39 @@ Go to http://localhost:3000
|
|
|
50
55
|
- If you already have a volto project, just update `package.json`:
|
|
51
56
|
|
|
52
57
|
```JSON
|
|
53
|
-
"addons": [
|
|
54
|
-
"@eeacms/volto-tableau"
|
|
55
|
-
],
|
|
56
|
-
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@eeacms/volto-tableau": "*"
|
|
59
60
|
}
|
|
60
61
|
```
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
and `volto.config.js`:
|
|
64
|
+
|
|
65
|
+
```JavaScript
|
|
66
|
+
const addons = ['@eeacms/volto-tableau'];
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- If not, create one with Cookieplone, as recommended by the official Plone documentation for Volto 18+:
|
|
63
70
|
|
|
64
71
|
```
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
cd my-volto-project
|
|
72
|
+
uvx cookieplone project
|
|
73
|
+
cd project-title
|
|
68
74
|
```
|
|
69
75
|
|
|
70
|
-
1. Install
|
|
76
|
+
1. Install or update dependencies, then start the project:
|
|
71
77
|
|
|
72
78
|
```
|
|
73
|
-
|
|
74
|
-
yarn start
|
|
79
|
+
make install
|
|
75
80
|
```
|
|
76
81
|
|
|
82
|
+
For a Cookieplone project, start the backend and frontend in separate terminals:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
make backend-start
|
|
86
|
+
make frontend-start
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
For a legacy Volto 17 project, install the package with `yarn` and restart the frontend as usual.
|
|
90
|
+
|
|
77
91
|
1. Go to http://localhost:3000
|
|
78
92
|
|
|
79
93
|
1. Happy editing!
|
|
@@ -5,22 +5,24 @@ describe('Blocks Tests', () => {
|
|
|
5
5
|
afterEach(slateAfterEach);
|
|
6
6
|
|
|
7
7
|
it('Add Block: Empty', () => {
|
|
8
|
+
const titleSelector = '.block.inner.title [contenteditable="true"]';
|
|
9
|
+
|
|
8
10
|
// Change page title
|
|
9
|
-
cy.
|
|
10
|
-
cy.
|
|
11
|
+
cy.get(titleSelector).clear();
|
|
12
|
+
cy.get(titleSelector).type('My Add-on Page');
|
|
11
13
|
|
|
12
14
|
cy.get('.documentFirstHeading').contains('My Add-on Page');
|
|
13
15
|
|
|
14
|
-
cy.
|
|
16
|
+
cy.get(titleSelector).type('{enter}');
|
|
15
17
|
|
|
16
18
|
// Add block
|
|
17
19
|
cy.get('.ui.basic.icon.button.block-add-button')
|
|
18
20
|
.first()
|
|
19
21
|
.click({ force: true });
|
|
20
|
-
cy.get(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
cy.get(".blocks-chooser .ui.form .field.searchbox input[type='text']").type(
|
|
23
|
+
'image',
|
|
24
|
+
);
|
|
25
|
+
cy.get('.button.image').contains('Image').click({ force: true });
|
|
24
26
|
|
|
25
27
|
// Save
|
|
26
28
|
cy.get('#toolbar-save').click({ force: true });
|
|
@@ -27,15 +27,22 @@ describe('Blocks Tests', () => {
|
|
|
27
27
|
afterEach(slateAfterEach);
|
|
28
28
|
|
|
29
29
|
it('Add Tableau block', () => {
|
|
30
|
-
cy.
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
cy.on('uncaught:exception', (err) => {
|
|
31
|
+
if (err.message?.includes('Not Found')) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
cy.intercept('GET', `/**/*?expand*`).as('content');
|
|
33
37
|
// when I add a maps block
|
|
34
|
-
cy.addNewBlock('tableau');
|
|
38
|
+
cy.addNewBlock('tableau', true);
|
|
35
39
|
|
|
36
40
|
cy.get(
|
|
37
41
|
`.sidebar-container .field-wrapper-tableau_vis_url #field-tableau_vis_url`,
|
|
38
|
-
).
|
|
42
|
+
).clear({ force: true });
|
|
43
|
+
cy.get(
|
|
44
|
+
`.sidebar-container .field-wrapper-tableau_vis_url #field-tableau_vis_url`,
|
|
45
|
+
).type('/cypress/my-page', { force: true });
|
|
39
46
|
cy.wait('@content');
|
|
40
47
|
cy.get('#toolbar-save').click({ force: true });
|
|
41
48
|
cy.intercept('GET', `/**/*?expand*`).as('content');
|
|
@@ -387,8 +387,9 @@ Cypress.Commands.add('getSlate', ({ createNewSlate = true } = {}) => {
|
|
|
387
387
|
},
|
|
388
388
|
() => {
|
|
389
389
|
if (createNewSlate) {
|
|
390
|
-
cy.get(
|
|
391
|
-
.
|
|
390
|
+
cy.get(SLATE_TITLE_SELECTOR)
|
|
391
|
+
.focus()
|
|
392
|
+
.click({ force: true })
|
|
392
393
|
.type('{moveToEnd}{enter}', { force: true });
|
|
393
394
|
}
|
|
394
395
|
slate = cy.get(SLATE_SELECTOR, { timeout: 10000 }).last();
|
|
@@ -548,7 +549,10 @@ Cypress.Commands.add('addNewBlock', (blockName, createNewSlate = false) => {
|
|
|
548
549
|
Cypress.Commands.add('getSlate', (createNewSlate = false) => {
|
|
549
550
|
let slate;
|
|
550
551
|
if (createNewSlate) {
|
|
551
|
-
cy.get(
|
|
552
|
+
cy.get(SLATE_TITLE_SELECTOR)
|
|
553
|
+
.focus()
|
|
554
|
+
.click({ force: true })
|
|
555
|
+
.type('{moveToEnd}{enter}', { force: true });
|
|
552
556
|
}
|
|
553
557
|
cy.getIfExists(
|
|
554
558
|
SLATE_SELECTOR,
|
package/docker-compose.yml
CHANGED
package/jest-addon.config.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
require('dotenv').config({ path: __dirname + '/.env' })
|
|
2
2
|
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
|
|
6
|
+
const voltoSlatePath = fs.existsSync(
|
|
7
|
+
path.join(__dirname, '../../../node_modules/@plone/volto-slate/src'),
|
|
8
|
+
)
|
|
9
|
+
? '<rootDir>/node_modules/@plone/volto-slate/src'
|
|
10
|
+
: '<rootDir>/node_modules/@plone/volto/packages/volto-slate/src'
|
|
11
|
+
|
|
12
|
+
const countupPath = fs.existsSync(path.join(__dirname, '../countup/src'))
|
|
13
|
+
? '<rootDir>/src/addons/countup/src'
|
|
14
|
+
: '<rootDir>/node_modules/@eeacms/countup'
|
|
15
|
+
|
|
3
16
|
module.exports = {
|
|
4
17
|
testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'],
|
|
5
18
|
collectCoverageFrom: [
|
|
@@ -16,11 +29,10 @@ module.exports = {
|
|
|
16
29
|
'@plone/volto-quanta/(.*)$': '<rootDir>/src/addons/volto-quanta/src/$1',
|
|
17
30
|
'@eeacms/search/(.*)$': '<rootDir>/src/addons/volto-searchlib/searchlib/$1',
|
|
18
31
|
'@eeacms/search': '<rootDir>/src/addons/volto-searchlib/searchlib',
|
|
32
|
+
'@eeacms/countup$': countupPath,
|
|
19
33
|
'@eeacms/(.*?)/(.*)$': '<rootDir>/node_modules/@eeacms/$1/src/$2',
|
|
20
|
-
'@plone/volto-slate$':
|
|
21
|
-
|
|
22
|
-
'@plone/volto-slate/(.*)$':
|
|
23
|
-
'<rootDir>/node_modules/@plone/volto/packages/volto-slate/src/$1',
|
|
34
|
+
'@plone/volto-slate$': voltoSlatePath,
|
|
35
|
+
'@plone/volto-slate/(.*)$': `${voltoSlatePath}/$1`,
|
|
24
36
|
'~/(.*)$': '<rootDir>/src/$1',
|
|
25
37
|
'load-volto-addons':
|
|
26
38
|
'<rootDir>/node_modules/@plone/volto/jest-addons-loader.js',
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { compose } from 'redux';
|
|
3
3
|
import { injectIntl } from 'react-intl';
|
|
4
4
|
import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
|
|
5
|
-
import
|
|
5
|
+
import SidebarPortal from '@plone/volto/components/manage/Sidebar/SidebarPortal';
|
|
6
6
|
import getSchema from './schema';
|
|
7
7
|
|
|
8
8
|
import View from './View';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render
|
|
2
|
+
import { render } 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
|
|
5
|
+
import '@testing-library/jest-dom';
|
|
6
6
|
|
|
7
7
|
import Edit from './Edit';
|
|
8
8
|
import installEmbedTableau from '.';
|
|
@@ -22,14 +22,18 @@ describe('Edit', () => {
|
|
|
22
22
|
with_share: true,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
it('should render the component', () => {
|
|
25
|
+
it('should render the component', async () => {
|
|
26
|
+
const sidebar = document.createElement('div');
|
|
27
|
+
sidebar.id = 'sidebar';
|
|
28
|
+
document.body.appendChild(sidebar);
|
|
29
|
+
|
|
26
30
|
const { container } = render(
|
|
27
31
|
<Provider store={global.store}>
|
|
28
32
|
<Edit
|
|
29
33
|
id="my-tableau"
|
|
30
34
|
data={data}
|
|
31
35
|
pathname="/news"
|
|
32
|
-
selected={
|
|
36
|
+
selected={true}
|
|
33
37
|
block="1234"
|
|
34
38
|
index={1}
|
|
35
39
|
onChangeBlock={() => {}}
|
|
@@ -55,60 +59,7 @@ describe('Edit', () => {
|
|
|
55
59
|
position: 'relative',
|
|
56
60
|
});
|
|
57
61
|
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
58
|
-
expect(
|
|
59
|
-
|
|
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();
|
|
62
|
+
expect(document.querySelector('#sidebar')).toBeInTheDocument();
|
|
63
|
+
sidebar.remove();
|
|
113
64
|
});
|
|
114
65
|
});
|
|
@@ -2,10 +2,10 @@ import React, { useEffect, useState } from 'react';
|
|
|
2
2
|
import { withRouter } from 'react-router';
|
|
3
3
|
import { connect } from 'react-redux';
|
|
4
4
|
import { compose } from 'redux';
|
|
5
|
-
import
|
|
5
|
+
import isFunction from 'lodash/isFunction';
|
|
6
6
|
import { Message } from 'semantic-ui-react';
|
|
7
|
-
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
8
|
-
import { getContent } from '@plone/volto/actions';
|
|
7
|
+
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
8
|
+
import { getContent } from '@plone/volto/actions/content/content';
|
|
9
9
|
import PrivacyProtection from '@eeacms/volto-embed/PrivacyProtection/PrivacyProtection';
|
|
10
10
|
import Tableau from '@eeacms/volto-tableau/Tableau/Tableau';
|
|
11
11
|
import {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import SidebarPortal from '@plone/volto/components/manage/Sidebar/SidebarPortal';
|
|
3
3
|
import BlockDataForm from '@plone/volto/components/manage/Form/InlineForm';
|
|
4
4
|
import config from '@plone/volto/registry';
|
|
5
5
|
import getSchema from './schema';
|
|
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react';
|
|
|
3
3
|
import { Provider } from 'react-redux';
|
|
4
4
|
import configureStore from 'redux-mock-store';
|
|
5
5
|
import View from './View';
|
|
6
|
-
import '@testing-library/jest-dom
|
|
6
|
+
import '@testing-library/jest-dom';
|
|
7
7
|
import Tableau from '@eeacms/volto-tableau/Tableau/Tableau';
|
|
8
8
|
|
|
9
9
|
jest.mock('@eeacms/volto-tableau/Tableau/Tableau', () =>
|
package/src/Blocks/index.js
CHANGED
package/src/Tableau/Tableau.jsx
CHANGED
|
@@ -9,26 +9,25 @@ import React, {
|
|
|
9
9
|
} from 'react';
|
|
10
10
|
import { connect } from 'react-redux';
|
|
11
11
|
import { toast } from 'react-toastify';
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
toNumber,
|
|
27
|
-
} from 'lodash';
|
|
12
|
+
import isEqual from 'lodash/isEqual';
|
|
13
|
+
import isUndefined from 'lodash/isUndefined';
|
|
14
|
+
import isNaN from 'lodash/isNaN';
|
|
15
|
+
import isNumber from 'lodash/isNumber';
|
|
16
|
+
import forOwn from 'lodash/forOwn';
|
|
17
|
+
import find from 'lodash/find';
|
|
18
|
+
import includes from 'lodash/includes';
|
|
19
|
+
import isArray from 'lodash/isArray';
|
|
20
|
+
import isString from 'lodash/isString';
|
|
21
|
+
import isInteger from 'lodash/isInteger';
|
|
22
|
+
import isBoolean from 'lodash/isBoolean';
|
|
23
|
+
import toString from 'lodash/toString';
|
|
24
|
+
import toInteger from 'lodash/toInteger';
|
|
25
|
+
import toNumber from 'lodash/toNumber';
|
|
28
26
|
import qs from 'qs';
|
|
29
27
|
import cx from 'classnames';
|
|
30
28
|
import { Button } from 'semantic-ui-react';
|
|
31
|
-
import
|
|
29
|
+
import Toast from '@plone/volto/components/manage/Toast/Toast';
|
|
30
|
+
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
32
31
|
import {
|
|
33
32
|
FigureNote,
|
|
34
33
|
Sources,
|
package/src/Tableau/helpers.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import reduce from 'lodash/reduce';
|
|
2
|
+
import isUndefined from 'lodash/isUndefined';
|
|
3
|
+
import isString from 'lodash/isString';
|
|
2
4
|
import qs from 'query-string';
|
|
3
5
|
import { pickMetadata } from '@eeacms/volto-embed/helpers';
|
|
4
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { withRouter } from 'react-router';
|
|
3
3
|
import { Container } from 'semantic-ui-react';
|
|
4
|
-
import { hasBlocksData } from '@plone/volto/helpers';
|
|
4
|
+
import { hasBlocksData } from '@plone/volto/helpers/Blocks/Blocks';
|
|
5
5
|
import config from '@plone/volto/registry';
|
|
6
6
|
import RenderBlocks from '@plone/volto/components/theme/View/RenderBlocks';
|
|
7
7
|
import Tableau from '@eeacms/volto-tableau/Tableau/Tableau';
|
|
@@ -7,15 +7,18 @@ import React, { Component } from 'react';
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { connect } from 'react-redux';
|
|
9
9
|
import { compose } from 'redux';
|
|
10
|
-
import
|
|
10
|
+
import map from 'lodash/map';
|
|
11
11
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
12
12
|
import {
|
|
13
13
|
getVocabFromHint,
|
|
14
14
|
getVocabFromField,
|
|
15
15
|
getVocabFromItems,
|
|
16
|
-
} from '@plone/volto/helpers';
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
16
|
+
} from '@plone/volto/helpers/Vocabularies/Vocabularies';
|
|
17
|
+
import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';
|
|
18
|
+
import {
|
|
19
|
+
getVocabulary,
|
|
20
|
+
getVocabularyTokenTitle,
|
|
21
|
+
} from '@plone/volto/actions/vocabularies/vocabularies';
|
|
19
22
|
import { normalizeValue } from '@plone/volto/components/manage/Widgets/SelectUtils';
|
|
20
23
|
|
|
21
24
|
import {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
|
-
import '@testing-library/jest-dom
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
4
|
import { Provider } from 'react-redux';
|
|
5
5
|
|
|
6
6
|
import VisualizationViewWidget from './VisualizationViewWidget';
|
|
@@ -3,10 +3,11 @@ import { withRouter } from 'react-router';
|
|
|
3
3
|
import { connect } from 'react-redux';
|
|
4
4
|
import { injectIntl } from 'react-intl';
|
|
5
5
|
import { compose } from 'redux';
|
|
6
|
-
import
|
|
6
|
+
import isEqual from 'lodash/isEqual';
|
|
7
7
|
import { Modal, Button, Grid } from 'semantic-ui-react';
|
|
8
8
|
import config from '@plone/volto/registry';
|
|
9
|
-
import
|
|
9
|
+
import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';
|
|
10
|
+
import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
|
|
10
11
|
import Tableau from '@eeacms/volto-tableau/Tableau/Tableau';
|
|
11
12
|
import getSchema from './schema';
|
|
12
13
|
import {
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
} from '@eeacms/volto-tableau/Tableau/helpers';
|
|
18
19
|
|
|
19
20
|
import '@eeacms/volto-tableau/less/tableau.less';
|
|
20
|
-
import { getBaseUrl } from '@plone/volto/helpers';
|
|
21
|
+
import { getBaseUrl } from '@plone/volto/helpers/Url/Url';
|
|
21
22
|
|
|
22
23
|
function blobToBase64(blob) {
|
|
23
24
|
return new Promise((resolve, reject) => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import '@testing-library/jest-dom
|
|
2
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
4
|
import { Provider } from 'react-intl-redux';
|
|
5
5
|
import VisualizationWidget from './VisualizationWidget';
|
|
6
6
|
|
|
7
7
|
describe('VisualizationWidget', () => {
|
|
8
|
-
it('should render the component', () => {
|
|
8
|
+
it('should render the component', async () => {
|
|
9
9
|
const data = {
|
|
10
10
|
value: {
|
|
11
11
|
url: 'http://localhost:3000/tableau-ct',
|
|
@@ -29,6 +29,11 @@ describe('VisualizationWidget', () => {
|
|
|
29
29
|
<VisualizationWidget {...data} id={'1234'} title="Title" />
|
|
30
30
|
</Provider>,
|
|
31
31
|
);
|
|
32
|
-
expect(
|
|
32
|
+
expect(
|
|
33
|
+
await screen.findByRole('button', { name: /open tableau editor/i }),
|
|
34
|
+
).toBeInTheDocument();
|
|
35
|
+
await waitFor(() => {
|
|
36
|
+
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
37
|
+
});
|
|
33
38
|
});
|
|
34
39
|
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { defineMessages } from 'react-intl';
|
|
2
|
-
import
|
|
2
|
+
import find from 'lodash/find';
|
|
3
|
+
import includes from 'lodash/includes';
|
|
4
|
+
import uniq from 'lodash/uniq';
|
|
3
5
|
import { canChangeVizData } from '@eeacms/volto-tableau/Tableau/helpers';
|
|
4
6
|
|
|
5
7
|
const messages = defineMessages({
|
|
File without changes
|
|
File without changes
|