@eeacms/volto-tabs-block 1.2.3 → 1.2.8

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.
@@ -0,0 +1,9 @@
1
+ const defaultBabel = require('@plone/volto/babel');
2
+
3
+ function applyDefault(api) {
4
+ const voltoBabel = defaultBabel(api);
5
+ voltoBabel.plugins.push('@babel/plugin-transform-modules-commonjs', 'transform-class-properties', 'istanbul');
6
+ return voltoBabel;
7
+ }
8
+
9
+ module.exports = applyDefault;
package/CHANGELOG.md CHANGED
@@ -4,8 +4,51 @@ 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
+ #### [1.2.8](https://github.com/eea/volto-tabs-block/compare/1.2.7...1.2.8)
8
+
9
+ - Correct Cypress tests [`#12`](https://github.com/eea/volto-tabs-block/pull/12)
10
+ - Refs #142010 - Optimize Volto-addons gitflow pipelines [`d10c0b3`](https://github.com/eea/volto-tabs-block/commit/d10c0b3d35d25c530d19eebde38dfe5da8fda01b)
11
+
12
+ #### [1.2.7](https://github.com/eea/volto-tabs-block/compare/1.2.6...1.2.7)
13
+
14
+ > 27 August 2021
15
+
16
+ - Remove hard dependencies to Volto add-ons to avoid dependencies hell [`#11`](https://github.com/eea/volto-tabs-block/pull/11)
17
+ - Develop [`#10`](https://github.com/eea/volto-tabs-block/pull/10)
18
+ - Develop [`#9`](https://github.com/eea/volto-tabs-block/pull/9)
19
+ - Cypress coverage [`#8`](https://github.com/eea/volto-tabs-block/pull/8)
20
+ - Remove hard dependencies to Volto add-ons [`58c579e`](https://github.com/eea/volto-tabs-block/commit/58c579ebcacb6f924642ee6094e0668b430462b9)
21
+
22
+ #### [1.2.6](https://github.com/eea/volto-tabs-block/compare/1.2.5...1.2.6)
23
+
24
+ > 29 July 2021
25
+
26
+ - Release 1.2.6 [`b316664`](https://github.com/eea/volto-tabs-block/commit/b316664577eb1dceec94d82622c9dc2056dffbba)
27
+
28
+ #### [1.2.5](https://github.com/eea/volto-tabs-block/compare/1.2.4...1.2.5)
29
+
30
+ > 29 July 2021
31
+
32
+ - Develop [`#10`](https://github.com/eea/volto-tabs-block/pull/10)
33
+ - Develop [`#9`](https://github.com/eea/volto-tabs-block/pull/9)
34
+ - Move less import in View instead of Edit [`84aeff0`](https://github.com/eea/volto-tabs-block/commit/84aeff04a980076f54687c546691d37b6e790478)
35
+ - gitignore tweaks [`f4c993d`](https://github.com/eea/volto-tabs-block/commit/f4c993d004b126f08f16651ab9460546fa9e9cad)
36
+ - Style update [`323aaaf`](https://github.com/eea/volto-tabs-block/commit/323aaafcad01d8fdf0e713a1fc254ae9fe319f43)
37
+ - Fix 'scroll to' feature on carousel [`16c6a08`](https://github.com/eea/volto-tabs-block/commit/16c6a08f6db687542ea38e07a92b265e592f6173)
38
+ - Better accesibility [`3511611`](https://github.com/eea/volto-tabs-block/commit/351161197270a4807f01d85a7055cbaadae72f8e)
39
+ - Add jest configuration [`c01b021`](https://github.com/eea/volto-tabs-block/commit/c01b0213bcb4b51408b6e3c196b2dcfa086377a9)
40
+
41
+ #### [1.2.4](https://github.com/eea/volto-tabs-block/compare/1.2.3...1.2.4)
42
+
43
+ > 27 May 2021
44
+
45
+ - Cypress coverage [`#8`](https://github.com/eea/volto-tabs-block/pull/8)
46
+ - Added z-index [`5aa8221`](https://github.com/eea/volto-tabs-block/commit/5aa8221d20c02e34788571d9231e73431c1043fe)
47
+
7
48
  #### [1.2.3](https://github.com/eea/volto-tabs-block/compare/1.2.2...1.2.3)
8
49
 
50
+ > 24 May 2021
51
+
9
52
  - Value of tabs is not visible in real time bug fixed [`#7`](https://github.com/eea/volto-tabs-block/pull/7)
10
53
  - Value of tabs is not visible in real time [`#6`](https://github.com/eea/volto-tabs-block/pull/6)
11
54
  - Fix block remaining selected when not needed [`a4d7ef7`](https://github.com/eea/volto-tabs-block/commit/a4d7ef736879cbe6d6e99cc3060256505ca4094b)
@@ -14,7 +57,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
14
57
 
15
58
  > 12 May 2021
16
59
 
17
- - JENKINS: auto-release pipeline [`#5`](https://github.com/eea/volto-tabs-block/pull/5)
18
60
  - Update style for menu title & description [`0683074`](https://github.com/eea/volto-tabs-block/commit/06830749ca9655ba74e07984536020b826da0696)
19
61
  - Updated styles [`104f8ab`](https://github.com/eea/volto-tabs-block/commit/104f8ab3cf60f7e4e54e84d1b523010e97be1f66)
20
62
  - Prettier [`f1dd4bc`](https://github.com/eea/volto-tabs-block/commit/f1dd4bcd3d82c37db00810bdc7a11c7dee4c3276)
package/Jenkinsfile CHANGED
@@ -2,33 +2,102 @@ pipeline {
2
2
  agent any
3
3
 
4
4
  environment {
5
- GIT_NAME = "volto-tabs-block"
6
- NAMESPACE = "@eeacms"
7
- SONARQUBE_TAGS = "volto.eea.europa.eu"
8
- DEPENDENCIES = "@eeacms/volto-block-style"
9
- }
5
+ GIT_NAME = "volto-tabs-block"
6
+ NAMESPACE = "@eeacms"
7
+ SONARQUBE_TAGS = "volto.eea.europa.eu,climate-energy.eea.europa.eu,biodiversity.europa.eu,www.eea.europa.eu-ims,sustainability.eionet.europa.eu,forest.eea.europa.eu,clms.land.copernicus.eu,industry.eea.europa.eu"
8
+ DEPENDENCIES = "@eeacms/volto-block-style"
9
+ }
10
10
 
11
11
  stages {
12
12
 
13
+ stage('Release') {
14
+ when {
15
+ allOf {
16
+ environment name: 'CHANGE_ID', value: ''
17
+ branch 'master'
18
+ }
19
+ }
20
+ steps {
21
+ node(label: 'docker') {
22
+ withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN'),string(credentialsId: 'eea-jenkins-npm-token', variable: 'NPM_TOKEN')]) {
23
+ sh '''docker pull eeacms/gitflow'''
24
+ sh '''docker run -i --rm --name="$BUILD_TAG-gitflow-master" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" -e GIT_TOKEN="$GITHUB_TOKEN" -e NPM_TOKEN="$NPM_TOKEN" -e LANGUAGE=javascript eeacms/gitflow'''
25
+ }
26
+ }
27
+ }
28
+ }
29
+
13
30
  stage('Code') {
31
+ when {
32
+ allOf {
33
+ environment name: 'CHANGE_ID', value: ''
34
+ not { branch 'master' }
35
+ not { changelog '.*^Automated release [0-9\\.]+$' }
36
+ }
37
+ }
14
38
  steps {
15
39
  parallel(
16
40
 
17
41
  "ES lint": {
18
42
  node(label: 'docker') {
19
- sh '''docker pull plone/volto-addon-ci; docker run -i --rm --name="$BUILD_TAG-eslint" -e NAMESPACE="$NAMESPACE" -e DEPENDENCIES="$DEPENDENCIES" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci eslint'''
43
+ sh '''docker run -i --rm --name="$BUILD_TAG-eslint" -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci eslint'''
20
44
  }
21
45
  },
22
46
 
23
47
  "Style lint": {
24
48
  node(label: 'docker') {
25
- sh '''docker pull plone/volto-addon-ci; docker run -i --rm --name="$BUILD_TAG-stylelint" -e NAMESPACE="$NAMESPACE" -e DEPENDENCIES="$DEPENDENCIES" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci stylelint'''
49
+ sh '''docker run -i --rm --name="$BUILD_TAG-stylelint" -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci stylelint'''
26
50
  }
27
51
  },
28
52
 
29
53
  "Prettier": {
30
54
  node(label: 'docker') {
31
- sh '''docker pull plone/volto-addon-ci; docker run -i --rm --name="$BUILD_TAG-prettier" -e NAMESPACE="$NAMESPACE" -e DEPENDENCIES="$DEPENDENCIES" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci prettier'''
55
+ sh '''docker run -i --rm --name="$BUILD_TAG-prettier" -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci prettier'''
56
+ }
57
+ }
58
+ )
59
+ }
60
+ }
61
+
62
+ stage('Tests') {
63
+ when {
64
+ allOf {
65
+ environment name: 'CHANGE_ID', value: ''
66
+ not { changelog '.*^Automated release [0-9\\.]+$' }
67
+ }
68
+ }
69
+ steps {
70
+ parallel(
71
+
72
+ "Volto": {
73
+ node(label: 'docker') {
74
+ script {
75
+ try {
76
+ sh '''docker pull plone/volto-addon-ci'''
77
+ sh '''docker run -i --name="$BUILD_TAG-volto" -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci'''
78
+ sh '''rm -rf xunit-reports'''
79
+ sh '''mkdir -p xunit-reports'''
80
+ sh '''docker cp $BUILD_TAG-volto:/opt/frontend/my-volto-project/coverage xunit-reports/'''
81
+ sh '''docker cp $BUILD_TAG-volto:/opt/frontend/my-volto-project/junit.xml xunit-reports/'''
82
+ sh '''docker cp $BUILD_TAG-volto:/opt/frontend/my-volto-project/unit_tests_log.txt xunit-reports/'''
83
+ stash name: "xunit-reports", includes: "xunit-reports/**"
84
+ archiveArtifacts artifacts: "xunit-reports/unit_tests_log.txt", fingerprint: true
85
+ publishHTML (target : [
86
+ allowMissing: false,
87
+ alwaysLinkToLastBuild: true,
88
+ keepAll: true,
89
+ reportDir: 'xunit-reports/coverage/lcov-report',
90
+ reportFiles: 'index.html',
91
+ reportName: 'UTCoverage',
92
+ reportTitles: 'Unit Tests Code Coverage'
93
+ ])
94
+ } finally {
95
+ catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
96
+ junit testResults: 'xunit-reports/junit.xml', allowEmptyResults: true
97
+ }
98
+ sh script: '''docker rm -v $BUILD_TAG-volto''', returnStatus: true
99
+ }
100
+ }
32
101
  }
33
102
  }
34
103
  )
@@ -36,6 +105,12 @@ pipeline {
36
105
  }
37
106
 
38
107
  stage('Integration tests') {
108
+ when {
109
+ allOf {
110
+ environment name: 'CHANGE_ID', value: ''
111
+ not { changelog '.*^Automated release [0-9\\.]+$' }
112
+ }
113
+ }
39
114
  steps {
40
115
  parallel(
41
116
 
@@ -44,13 +119,35 @@ pipeline {
44
119
  script {
45
120
  try {
46
121
  sh '''docker pull plone; docker run -d --name="$BUILD_TAG-plone" -e SITE="Plone" -e PROFILES="profile-plone.restapi:blocks" plone fg'''
47
- sh '''docker pull plone/volto-addon-ci; docker run -i --name="$BUILD_TAG-cypress" --link $BUILD_TAG-plone:plone -e NAMESPACE="$NAMESPACE" -e DEPENDENCIES="$DEPENDENCIES" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci cypress'''
122
+ sh '''docker pull plone/volto-addon-ci; docker run -i --name="$BUILD_TAG-cypress" --link $BUILD_TAG-plone:plone -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e DEPENDENCIES="$DEPENDENCIES" plone/volto-addon-ci cypress'''
48
123
  } finally {
49
- sh '''mkdir -p cypress-reports'''
50
- sh '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/cypress/videos cypress-reports/'''
51
- stash name: "cypress-reports", includes: "cypress-reports/**/*"
52
- archiveArtifacts artifacts: 'cypress-reports/videos/*.mp4', fingerprint: true
53
- sh '''echo "$(docker stop $BUILD_TAG-plone; docker rm -v $BUILD_TAG-plone; docker rm -v $BUILD_TAG-cypress)" '''
124
+ try {
125
+ sh '''rm -rf cypress-reports cypress-results cypress-coverage'''
126
+ sh '''mkdir -p cypress-reports cypress-results cypress-coverage'''
127
+ sh '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/cypress/videos cypress-reports/'''
128
+ sh '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/cypress/reports cypress-results/'''
129
+ coverage = sh script: '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/coverage cypress-coverage/''', returnStatus: true
130
+ if ( coverage == 0 ) {
131
+ publishHTML (target : [allowMissing: false,
132
+ alwaysLinkToLastBuild: true,
133
+ keepAll: true,
134
+ reportDir: 'cypress-coverage/coverage/lcov-report',
135
+ reportFiles: 'index.html',
136
+ reportName: 'CypressCoverage',
137
+ reportTitles: 'Integration Tests Code Coverage'])
138
+ }
139
+ archiveArtifacts artifacts: 'cypress-reports/videos/*.mp4', fingerprint: true
140
+ stash name: "cypress-coverage", includes: "cypress-coverage/**", allowEmpty: true
141
+ }
142
+ finally {
143
+ catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
144
+ junit testResults: 'cypress-results/**/*.xml', allowEmptyResults: true
145
+ }
146
+ sh script: "docker stop $BUILD_TAG-plone", returnStatus: true
147
+ sh script: "docker rm -v $BUILD_TAG-plone", returnStatus: true
148
+ sh script: "docker rm -v $BUILD_TAG-cypress", returnStatus: true
149
+
150
+ }
54
151
  }
55
152
  }
56
153
  }
@@ -59,67 +156,74 @@ pipeline {
59
156
  )
60
157
  }
61
158
  }
62
-
63
- stage('Pull Request') {
159
+
160
+ stage('Report to SonarQube') {
64
161
  when {
65
- not {
66
162
  environment name: 'CHANGE_ID', value: ''
67
- }
68
- environment name: 'CHANGE_TARGET', value: 'master'
163
+ anyOf {
164
+ branch 'master'
165
+ branch 'develop'
166
+ }
167
+ not { changelog '.*^Automated release [0-9\\.]+$' }
69
168
  }
70
169
  steps {
71
- node(label: 'docker') {
72
- script {
73
- if ( env.CHANGE_BRANCH != "develop" && !( env.CHANGE_BRANCH.startsWith("hotfix")) ) {
74
- error "Pipeline aborted due to PR not made from develop or hotfix branch"
170
+ node(label: 'swarm') {
171
+ script{
172
+ checkout scm
173
+ unstash "xunit-reports"
174
+ unstash "cypress-coverage"
175
+ def scannerHome = tool 'SonarQubeScanner';
176
+ def nodeJS = tool 'NodeJS11';
177
+ withSonarQubeEnv('Sonarqube') {
178
+ sh '''sed -i "s#/opt/frontend/my-volto-project/src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
179
+ sh "export PATH=$PATH:${scannerHome}/bin:${nodeJS}/bin; sonar-scanner -Dsonar.javascript.lcov.reportPaths=./xunit-reports/coverage/lcov.info,./cypress-coverage/coverage/lcov.info -Dsonar.sources=./src -Dsonar.projectKey=$GIT_NAME-$BRANCH_NAME -Dsonar.projectVersion=$BRANCH_NAME-$BUILD_NUMBER"
180
+ sh '''try=2; while [ \$try -gt 0 ]; do curl -s -XPOST -u "${SONAR_AUTH_TOKEN}:" "${SONAR_HOST_URL}api/project_tags/set?project=${GIT_NAME}-${BRANCH_NAME}&tags=${SONARQUBE_TAGS},${BRANCH_NAME}" > set_tags_result; if [ \$(grep -ic error set_tags_result ) -eq 0 ]; then try=0; else cat set_tags_result; echo "... Will retry"; sleep 60; try=\$(( \$try - 1 )); fi; done'''
75
181
  }
76
- withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN')]) {
77
- sh '''docker pull eeacms/gitflow'''
78
- sh '''docker run -i --rm --name="$BUILD_TAG-gitflow-pr" -e GIT_CHANGE_TARGET="$CHANGE_TARGET" -e GIT_CHANGE_BRANCH="$CHANGE_BRANCH" -e GIT_CHANGE_AUTHOR="$CHANGE_AUTHOR" -e GIT_CHANGE_TITLE="$CHANGE_TITLE" -e GIT_TOKEN="$GITHUB_TOKEN" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e GIT_ORG="$GIT_ORG" -e GIT_NAME="$GIT_NAME" eeacms/gitflow'''
79
- }
80
182
  }
81
183
  }
82
184
  }
83
185
  }
84
- stage('Release') {
186
+
187
+ stage('Pull Request') {
85
188
  when {
86
- allOf {
189
+ not {
87
190
  environment name: 'CHANGE_ID', value: ''
88
- branch 'master'
89
191
  }
192
+ environment name: 'CHANGE_TARGET', value: 'master'
90
193
  }
91
194
  steps {
92
195
  node(label: 'docker') {
93
- withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN'),string(credentialsId: 'eea-jenkins-npm-token', variable: 'NPM_TOKEN')]) {
196
+ script {
197
+ if ( env.CHANGE_BRANCH != "develop" ) {
198
+ error "Pipeline aborted due to PR not made from develop branch"
199
+ }
200
+ withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN')]) {
94
201
  sh '''docker pull eeacms/gitflow'''
95
- sh '''docker run -i --rm --name="$BUILD_TAG-gitflow-master" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" -e GIT_TOKEN="$GITHUB_TOKEN" -e NPM_TOKEN="$NPM_TOKEN" eeacms/gitflow'''
202
+ sh '''docker run -i --rm --name="$BUILD_TAG-gitflow-pr" -e GIT_CHANGE_TARGET="$CHANGE_TARGET" -e GIT_CHANGE_BRANCH="$CHANGE_BRANCH" -e GIT_CHANGE_AUTHOR="$CHANGE_AUTHOR" -e GIT_CHANGE_TITLE="$CHANGE_TITLE" -e GIT_TOKEN="$GITHUB_TOKEN" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e GIT_ORG="$GIT_ORG" -e GIT_NAME="$GIT_NAME" -e LANGUAGE=javascript eeacms/gitflow'''
203
+ }
96
204
  }
97
205
  }
98
206
  }
99
207
  }
100
208
 
101
-
102
209
  }
103
210
 
104
211
  post {
212
+ always {
213
+ cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
214
+ }
105
215
  changed {
106
216
  script {
107
- def url = "${env.BUILD_URL}/display/redirect"
108
- def status = currentBuild.currentResult
109
- def subject = "${status}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'"
110
- def summary = "${subject} (${url})"
111
- def details = """<h1>${env.JOB_NAME} - Build #${env.BUILD_NUMBER} - ${status}</h1>
112
- <p>Check console output at <a href="${url}">${env.JOB_BASE_NAME} - #${env.BUILD_NUMBER}</a></p>
217
+ def details = """<h1>${env.JOB_NAME} - Build #${env.BUILD_NUMBER} - ${currentBuild.currentResult}</h1>
218
+ <p>Check console output at <a href="${env.BUILD_URL}/display/redirect">${env.JOB_BASE_NAME} - #${env.BUILD_NUMBER}</a></p>
113
219
  """
114
-
115
- def color = '#FFFF00'
116
- if (status == 'SUCCESS') {
117
- color = '#00FF00'
118
- } else if (status == 'FAILURE') {
119
- color = '#FF0000'
120
- }
121
-
122
- emailext (subject: '$DEFAULT_SUBJECT', to: '$DEFAULT_RECIPIENTS', body: details)
220
+ emailext(
221
+ subject: '$DEFAULT_SUBJECT',
222
+ body: details,
223
+ attachLog: true,
224
+ compressLog: true,
225
+ recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'CulpritsRecipientProvider']]
226
+ )
123
227
  }
124
228
  }
125
229
  }
package/Makefile ADDED
@@ -0,0 +1,50 @@
1
+ SHELL=/bin/bash
2
+
3
+ DIR=$(shell basename $$(pwd))
4
+ ADDON ?= "@eeacms/volto-tabs-block"
5
+
6
+ # We like colors
7
+ # From: https://coderwall.com/p/izxssa/colored-makefile-for-golang-projects
8
+ RED=`tput setaf 1`
9
+ GREEN=`tput setaf 2`
10
+ RESET=`tput sgr0`
11
+ YELLOW=`tput setaf 3`
12
+
13
+ project:
14
+ npm install -g yo
15
+ npm install -g @plone/generator-volto
16
+ npm install -g mrs-developer
17
+ yo @plone/volto project --addon ${ADDON} --workspace "src/addons/${DIR}" --no-interactive
18
+ ln -sf $$(pwd) project/src/addons/
19
+ cp .project.eslintrc.js .eslintrc.js
20
+ cd project && yarn
21
+ @echo "-------------------"
22
+ @echo "$(GREEN)Volto project is ready!$(RESET)"
23
+ @echo "$(RED)Now run: cd project && yarn start$(RESET)"
24
+
25
+ all: project
26
+
27
+ .PHONY: start-test-backend
28
+ start-test-backend: ## Start Test Plone Backend
29
+ @echo "$(GREEN)==> Start Test Plone Backend$(RESET)"
30
+ docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e SITE=plone -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,kitconcept.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,kitconcept.volto,kitconcept.volto.cors -e ADDONS='plone.app.robotframework plone.app.contenttypes plone.restapi kitconcept.volto' plone ./bin/robot-server plone.app.robotframework.testing.PLONE_ROBOT_TESTING
31
+
32
+ .PHONY: start-backend-docker
33
+ start-backend-docker: ## Starts a Docker-based backend
34
+ @echo "$(GREEN)==> Start Docker-based Plone Backend$(RESET)"
35
+ docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e ADDONS="kitconcept.volto" -e ZCML="kitconcept.volto.cors" plone
36
+
37
+ .PHONY: test
38
+ test:
39
+ docker pull plone/volto-addon-ci
40
+ docker run -it --rm -e NAMESPACE="@eeacms" -e GIT_NAME="${DIR}" -e RAZZLE_JEST_CONFIG=jest-addon.config.js -v "$$(pwd):/opt/frontend/my-volto-project/src/addons/${DIR}" plone/volto-addon-ci yarn test --watchAll=false
41
+
42
+ .PHONY: test-update
43
+ test-update:
44
+ docker pull plone/volto-addon-ci
45
+ docker run -it --rm -e NAMESPACE="@eeacms" -e GIT_NAME="${DIR}" -e RAZZLE_JEST_CONFIG=jest-addon.config.js -v "$$(pwd):/opt/frontend/my-volto-project/src/addons/${DIR}" plone/volto-addon-ci yarn test --watchAll=false -u
46
+
47
+ .PHONY: help
48
+ help: ## Show this help.
49
+ @echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)"
50
+ -s :)"
package/bootstrap CHANGED
@@ -1,5 +1,6 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
+ const ejs = require('ejs');
3
4
 
4
5
  const currentDir = path.basename(process.cwd());
5
6
 
@@ -8,13 +9,23 @@ const bootstrap = function (ofile) {
8
9
  if (err) {
9
10
  return console.log(err);
10
11
  }
11
- var result = data.replace(/volto-addon-template/g, currentDir);
12
-
13
- fs.writeFile(ofile, result, 'utf8', function (err) {
12
+ const result = ejs.render(data, {
13
+ addonName: `@eeacms/${currentDir}`,
14
+ name: currentDir
15
+ });
16
+ const output = ofile.replace('.tpl', '');
17
+ fs.writeFile(output, result, 'utf8', function (err) {
14
18
  if (err) {
15
19
  return console.log(err);
16
20
  }
17
21
  });
22
+ if (ofile.includes('.tpl')) {
23
+ fs.unlink(ofile, (err) => {
24
+ if (err) {
25
+ return console.error(err);
26
+ }
27
+ });
28
+ }
18
29
  });
19
30
  }
20
31
 
@@ -5,16 +5,17 @@ describe('Blocks Tests', () => {
5
5
  afterEach(tearDownAfterEach);
6
6
 
7
7
  it('Add Block: Empty', () => {
8
+ // without this the clear command below does nothing sometimes
9
+ cy.wait(500);
10
+
8
11
  // Change page title
9
- cy.get('.documentFirstHeading > .public-DraftStyleDefault-block')
10
- .clear()
11
- .type('My Add-on Page')
12
- .get('.documentFirstHeading span[data-text]')
13
- .contains('My Add-on Page');
14
-
15
- cy.get('.documentFirstHeading > .public-DraftStyleDefault-block').type(
16
- '{enter}',
17
- );
12
+ cy.get('[contenteditable=true]').first().clear();
13
+
14
+ cy.get('[contenteditable=true]').first().type('My Add-on Page');
15
+
16
+ cy.get('.documentFirstHeading').contains('My Add-on Page');
17
+
18
+ cy.get('[contenteditable=true]').first().type('{enter}');
18
19
 
19
20
  // Add block
20
21
  cy.get('.ui.basic.icon.button.block-add-button').first().click();
@@ -18,4 +18,9 @@
18
18
  module.exports = (on, config) => {
19
19
  // `on` is used to hook into various events Cypress emits
20
20
  // `config` is the resolved Cypress config
21
+ /* coverage-start
22
+ require('@cypress/code-coverage/task')(on, config)
23
+ on('file:preprocessor', require('@cypress/code-coverage/use-babelrc'))
24
+ return config
25
+ coverage-end */
21
26
  };
@@ -19,6 +19,11 @@ import './commands';
19
19
  // Alternatively you can use CommonJS syntax:
20
20
  // require('./commands')
21
21
 
22
+ /* coverage-start
23
+ //Generate code-coverage
24
+ import '@cypress/code-coverage/support';
25
+ coverage-end */
26
+
22
27
  export const setupBeforeEach = () => {
23
28
  cy.autologin();
24
29
  cy.createContent({
@@ -39,7 +44,7 @@ export const setupBeforeEach = () => {
39
44
  cy.waitForResourceToLoad('@types');
40
45
  cy.waitForResourceToLoad('my-page');
41
46
  cy.navigate('/cypress/my-page/edit');
42
- cy.get(`.block.title [data-contents]`);
47
+ cy.get(`.block.title h1`);
43
48
  };
44
49
 
45
50
  export const tearDownAfterEach = () => {
package/cypress.json CHANGED
@@ -1,4 +1,12 @@
1
1
  {
2
2
  "baseUrl": "http://localhost:3000",
3
- "viewportWidth": 1280
3
+ "viewportWidth": 1280,
4
+ "defaultCommandTimeout": 15000,
5
+ "reporter": "junit",
6
+ "video": true,
7
+ "reporterOptions": {
8
+ "mochaFile": "cypress/reports/cypress-[hash].xml",
9
+ "jenkinsMode": true,
10
+ "toConsole": true
11
+ }
4
12
  }
@@ -0,0 +1,36 @@
1
+ module.exports = {
2
+ testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'],
3
+ collectCoverageFrom: [
4
+ 'src/addons/**/src/**/*.{js,jsx,ts,tsx}',
5
+ '!src/**/*.d.ts',
6
+ ],
7
+ moduleNameMapper: {
8
+ '@plone/volto/cypress': '<rootDir>/node_modules/@plone/volto/cypress',
9
+ '@plone/volto/babel': '<rootDir>/node_modules/@plone/volto/babel',
10
+ '@plone/volto/(.*)$': '<rootDir>/node_modules/@plone/volto/src/$1',
11
+ '@package/(.*)$': '<rootDir>/src/$1',
12
+ '@plone/volto-quanta/(.*)$': '<rootDir>/src/addons/volto-quanta/src/$1',
13
+ '@eeacms/(.*?)/(.*)$': '<rootDir>/src/addons/$1/src/$2',
14
+ 'volto-slate/(.*)$': '<rootDir>/src/addons/volto-slate/src/$1',
15
+ '~/(.*)$': '<rootDir>/src/$1',
16
+ 'load-volto-addons':
17
+ '<rootDir>/node_modules/@plone/volto/jest-addons-loader.js',
18
+ },
19
+ transform: {
20
+ '^.+\\.js(x)?$': 'babel-jest',
21
+ '^.+\\.css$': 'jest-css-modules',
22
+ '^.+\\.less$': 'jest-css-modules',
23
+ '^.+\\.scss$': 'jest-css-modules',
24
+ '^.+\\.(png)$': 'jest-file',
25
+ '^.+\\.(jpg)$': 'jest-file',
26
+ '^.+\\.(svg)$': './node_modules/@plone/volto/jest-svgsystem-transform.js',
27
+ },
28
+ coverageThreshold: {
29
+ global: {
30
+ branches: 5,
31
+ functions: 5,
32
+ lines: 5,
33
+ statements: 5,
34
+ },
35
+ },
36
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-tabs-block",
3
- "version": "1.2.3",
3
+ "version": "1.2.8",
4
4
  "description": "volto-tabs-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -22,20 +22,27 @@
22
22
  "dependencies": {
23
23
  "react-slick": "^0.24.0",
24
24
  "slick-carousel": "^1.8.1",
25
- "@eeacms/volto-block-style": "^2.5.1"
25
+ "@eeacms/volto-block-style": "*"
26
+ },
27
+ "devDependencies": {
28
+ "@cypress/code-coverage": "^3.9.5",
29
+ "babel-plugin-transform-class-properties": "^6.24.1"
26
30
  },
27
31
  "scripts": {
28
32
  "release": "release-it",
33
+ "bootstrap": "npm install -g ejs; npm link ejs; node bootstrap",
34
+ "test": "make test",
35
+ "test:fix": "make test-update",
36
+ "i18n": "rm -rf build/messages && NODE_ENV=production node src/i18n.js",
29
37
  "pre-commit": "yarn stylelint:fix && yarn prettier:fix && yarn lint:fix",
30
- "bootstrap": "node bootstrap",
31
- "stylelint": "../../../node_modules/stylelint/bin/stylelint.js --allow-empty-input 'src/**/*.{css,less}'",
32
- "stylelint:overrides": "../../../node_modules/.bin/stylelint --syntax less --allow-empty-input 'theme/**/*.overrides' 'src/**/*.overrides'",
38
+ "stylelint": "if [ -d ./project ]; then ./project/node_modules/stylelint/bin/stylelint.js --allow-empty-input 'src/**/*.{css,less}'; else ../../../node_modules/stylelint/bin/stylelint.js --allow-empty-input 'src/**/*.{css,less}'; fi",
39
+ "stylelint:overrides": "if [ -d ./project ]; then ./project/node_modules/.bin/stylelint --syntax less --allow-empty-input 'theme/**/*.overrides' 'src/**/*.overrides'; else ../../../node_modules/.bin/stylelint --syntax less --allow-empty-input 'theme/**/*.overrides' 'src/**/*.overrides'; fi",
33
40
  "stylelint:fix": "yarn stylelint --fix && yarn stylelint:overrides --fix",
34
- "prettier": "../../../node_modules/.bin/prettier --single-quote --check 'src/**/*.{js,jsx,json,css,less,md}'",
35
- "prettier:fix": "../../../node_modules/.bin/prettier --single-quote --write 'src/**/*.{js,jsx,json,css,less,md}'",
36
- "lint": "../../../node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}'",
37
- "lint:fix": "../../../node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx}'",
38
- "cypress:run": "../../../node_modules/cypress/bin/cypress run",
39
- "cypress:open": "../../../node_modules/cypress/bin/cypress open"
41
+ "prettier": "if [ -d ./project ]; then ./project/node_modules/.bin/prettier --single-quote --check 'src/**/*.{js,jsx,json,css,less,md}'; else ../../../node_modules/.bin/prettier --single-quote --check 'src/**/*.{js,jsx,json,css,less,md}'; fi",
42
+ "prettier:fix": "if [ -d ./project ]; then ./project/node_modules/.bin/prettier --single-quote --write 'src/**/*.{js,jsx,json,css,less,md}'; else ../../../node_modules/.bin/prettier --single-quote --write 'src/**/*.{js,jsx,json,css,less,md}'; fi",
43
+ "lint": "if [ -d ./project ]; then ./project/node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}'; else ../../../node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}'; fi",
44
+ "lint:fix": "if [ -d ./project ]; then ./project/node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx}'; else ../../../node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx}'; fi",
45
+ "cypress:run": "if [ -d ./project ]; then ./project/node_modules/cypress/bin/cypress run; else ../../../node_modules/cypress/bin/cypress run; fi",
46
+ "cypress:open": "if [ -d ./project ]; then ./project/node_modules/cypress/bin/cypress open; else ../../../node_modules/cypress/bin/cypress open; fi"
40
47
  }
41
48
  }
@@ -13,8 +13,6 @@ import cx from 'classnames';
13
13
 
14
14
  import config from '@plone/volto/registry';
15
15
 
16
- import '@eeacms/volto-tabs-block/less/tabs-block.less';
17
-
18
16
  const Edit = (props) => {
19
17
  const { onChangeBlock } = props;
20
18
  const { data = {}, block = null } = props;
@@ -6,6 +6,8 @@ import cx from 'classnames';
6
6
 
7
7
  import config from '@plone/volto/registry';
8
8
 
9
+ import '@eeacms/volto-tabs-block/less/tabs-block.less';
10
+
9
11
  const View = (props) => {
10
12
  const view = React.useRef(null);
11
13
  const { data = {}, uiContainer = '' } = props;
@@ -33,6 +35,7 @@ const View = (props) => {
33
35
  >
34
36
  <div
35
37
  className={cx('tabs-block', template, theme, verticalAlign)}
38
+ id={props.id}
36
39
  ref={view}
37
40
  >
38
41
  <StyleWrapperView
@@ -26,6 +26,7 @@ const Dots = (props) => {
26
26
  className={cx({ 'slick-active': activeTab === tab })}
27
27
  >
28
28
  <button
29
+ aria-label={`Select slide ${index + 1}`}
29
30
  onClick={() => {
30
31
  if (slider.current) {
31
32
  slider.current.slickGoTo(index);
@@ -55,7 +56,7 @@ const ArrowsGroup = (props) => {
55
56
  >
56
57
  {currentSlide > 0 ? (
57
58
  <button
58
- data-role="none"
59
+ aria-label="Previous slide"
59
60
  className="slick-arrow slick-prev"
60
61
  onClick={() => {
61
62
  if (slider.current) {
@@ -70,7 +71,7 @@ const ArrowsGroup = (props) => {
70
71
  )}
71
72
  {currentSlide < slideCount - 1 ? (
72
73
  <button
73
- data-role="none"
74
+ aria-label="Next slide"
74
75
  className="slick-arrow slick-next"
75
76
  onClick={() => {
76
77
  if (slider.current) {
@@ -118,6 +119,18 @@ const View = (props) => {
118
119
  },
119
120
  };
120
121
 
122
+ React.useEffect(() => {
123
+ if (!slider.current?.innerSlider?.list) return;
124
+ const unfocuseElements = ['a', 'button', 'input'];
125
+ unfocuseElements.forEach((tag) => {
126
+ for (let element of slider.current.innerSlider.list.querySelectorAll(
127
+ ".slick-slide[aria-hidden='true'] a",
128
+ )) {
129
+ element.setAttribute('aria-hiden', 'true');
130
+ }
131
+ });
132
+ }, [activeTab]);
133
+
121
134
  React.useEffect(() => {
122
135
  const urlHash = props.location.hash.substring(1) || '';
123
136
  if (
@@ -130,10 +143,14 @@ const View = (props) => {
130
143
  const parent = document.getElementById(parentId);
131
144
  // TODO: Find the best way to add offset relative to header
132
145
  // The header can be static on mobile and relative on > mobile
133
- // const headerWrapper = document.querySelector('.header-wrapper');
134
- // const offsetHeight = headerWrapper?.offsetHeight || 0;
135
- const offsetHeight = 0;
136
- if (id !== parentId && index > -1 && parent) {
146
+ const headerWrapper = document.querySelector('.header-wrapper');
147
+ const offsetHeight = headerWrapper?.offsetHeight || 0;
148
+ if (
149
+ id !== parentId &&
150
+ parentId === hashlink.data.parentId &&
151
+ index > -1 &&
152
+ parent
153
+ ) {
137
154
  if (activeTabIndex !== index) {
138
155
  slider.current.slickGoTo(index);
139
156
  }
@@ -103,7 +103,7 @@ const View = (props) => {
103
103
  },
104
104
  render: () => {
105
105
  return (
106
- <Tab.Pane>
106
+ <Tab.Pane className={uiContainer}>
107
107
  {' '}
108
108
  <RenderBlocks {...props} metadata={metadata} content={tabs[tab]} />
109
109
  </Tab.Pane>
@@ -116,7 +116,7 @@ const View = (props) => {
116
116
  <>
117
117
  <Tab
118
118
  activeIndex={activeTabIndex}
119
- className={cx('default tabs', menuPosition, uiContainer)}
119
+ className={cx('default tabs', menuPosition)}
120
120
  menu={{
121
121
  className: cx(menuAlign),
122
122
  }}
package/src/index.js CHANGED
@@ -58,6 +58,7 @@ export default (config) => {
58
58
  blocks: blocks_layout.items.map((block, index) => ({
59
59
  title: blocks[block]['title'] || `Tab ${index + 1}`,
60
60
  id: block,
61
+ parentId: data.parentId,
61
62
  type: TABS_BLOCK,
62
63
  })),
63
64
  };