@eeacms/volto-slate-footnote 6.1.8 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -22
- package/Dockerfile +1 -1
- package/Jenkinsfile +160 -134
- package/Makefile +33 -2
- package/cypress.config.js +3 -3
- package/package.json +1 -1
- package/src/Blocks/Footnote/FootnotesBlockView.jsx +51 -5
- package/src/editor/FootnoteEditor.jsx +0 -1
- package/src/editor/extensions.js +0 -1
- package/src/editor/render.jsx +15 -7
- package/src/editor/utils.js +71 -34
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,24 @@ 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
|
-
### [6.
|
|
7
|
+
### [6.2.0](https://github.com/eea/volto-slate-footnote/compare/6.1.8...6.2.0) - 17 January 2024
|
|
8
|
+
|
|
9
|
+
#### :rocket: New Features
|
|
10
|
+
|
|
11
|
+
- feat: Allow footnotes work on complex blocks such as statistics, accordion, tabs, where nested data is present - refs #261770 [dobri1408 - [`66363d3`](https://github.com/eea/volto-slate-footnote/commit/66363d3d64cde426c99f0e9f0ecad59816a80552)]
|
|
12
|
+
- feat(popup): is now accessible by keyboard tabbing [David Ichim - [`3649da0`](https://github.com/eea/volto-slate-footnote/commit/3649da0d381ae8a76b77c8a34a6217a72a0c3709)]
|
|
13
|
+
|
|
14
|
+
#### :bug: Bug Fixes
|
|
15
|
+
|
|
16
|
+
- fix: footnote error in statistic block - refs #261770 [dobri1408 - [`3cf696c`](https://github.com/eea/volto-slate-footnote/commit/3cf696c44dbb84fc54935acf3d5951ac2c198d88)]
|
|
17
|
+
|
|
18
|
+
#### :house: Internal changes
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#### :hammer_and_wrench: Others
|
|
22
|
+
|
|
23
|
+
- Release 6.2.0 [Alin Voinea - [`5c14981`](https://github.com/eea/volto-slate-footnote/commit/5c1498162789f753bca3352cacbd4ec3c3bed249)]
|
|
24
|
+
### [6.1.8](https://github.com/eea/volto-slate-footnote/compare/6.1.7...6.1.8) - 22 October 2023
|
|
8
25
|
|
|
9
26
|
#### :house: Internal changes
|
|
10
27
|
|
|
@@ -73,25 +90,17 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
73
90
|
|
|
74
91
|
#### :house: Internal changes
|
|
75
92
|
|
|
76
|
-
- chore: [JENKINS] Deprecate circularity website [valentinab25 - [`ded882a`](https://github.com/eea/volto-slate-footnote/commit/ded882a1ca1183c2ba74ff4246111123ee36e6cb)]
|
|
77
93
|
|
|
78
94
|
#### :hammer_and_wrench: Others
|
|
79
95
|
|
|
80
96
|
- test: jest should look for addons in node_modules Refs #253277 [valentinab25 - [`3e0749c`](https://github.com/eea/volto-slate-footnote/commit/3e0749cc5bd7f5810ac6fd7a3feee4df0435ee0a)]
|
|
81
97
|
- test: Add unit tests for utils - refs #253277 [ana-oprea - [`a709895`](https://github.com/eea/volto-slate-footnote/commit/a709895d9953742ef6d39f8d9673c06b2efe6a64)]
|
|
82
98
|
- test: Fix test config, coverage Refs #253277 [valentinab25 - [`dc4d6dc`](https://github.com/eea/volto-slate-footnote/commit/dc4d6dc9b39bfe2c892156f32c764153d1366486)]
|
|
83
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`4f0ecee`](https://github.com/eea/volto-slate-footnote/commit/4f0ecee224d5d6604dfbb562556e45437edbb8ec)]
|
|
84
99
|
### [6.1.0](https://github.com/eea/volto-slate-footnote/compare/6.0.2...6.1.0) - 27 March 2023
|
|
85
100
|
|
|
86
101
|
#### :hammer_and_wrench: Others
|
|
87
102
|
|
|
88
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`23959ee`](https://github.com/eea/volto-slate-footnote/commit/23959ee43d45ec5eaa483590415a75fc58faae03)]
|
|
89
|
-
- Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`7aa6f34`](https://github.com/eea/volto-slate-footnote/commit/7aa6f3439953cc3d8f28875eff9fbcc24084cbc7)]
|
|
90
|
-
- Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`b117d15`](https://github.com/eea/volto-slate-footnote/commit/b117d15e51b3cf10717b9dd9dfef8304d46ad556)]
|
|
91
103
|
- test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`97ed8fb`](https://github.com/eea/volto-slate-footnote/commit/97ed8fbd92f76c2b3128b62cdc1a77611e79410a)]
|
|
92
|
-
- Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`cb22f5e`](https://github.com/eea/volto-slate-footnote/commit/cb22f5e8e9d3aed0a3b4374b6d4d80c8c2bb66e1)]
|
|
93
|
-
- yarn 3 [Alin Voinea - [`f5bb904`](https://github.com/eea/volto-slate-footnote/commit/f5bb904eecf740ffd57dbccf9a597c99ea2dfc0c)]
|
|
94
|
-
- Add Sonarqube tag using demo-kitkat-frontend addons list [EEA Jenkins - [`59cf6d3`](https://github.com/eea/volto-slate-footnote/commit/59cf6d334a460e373dda3e2e28754fcdd9fb0281)]
|
|
95
104
|
### [6.0.2](https://github.com/eea/volto-slate-footnote/compare/6.0.1...6.0.2) - 16 November 2022
|
|
96
105
|
|
|
97
106
|
#### :hammer_and_wrench: Others
|
|
@@ -107,37 +116,27 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
107
116
|
|
|
108
117
|
#### :hammer_and_wrench: Others
|
|
109
118
|
|
|
110
|
-
- Add Sonarqube tag using marine-frontend addons list [EEA Jenkins - [`dc3c7de`](https://github.com/eea/volto-slate-footnote/commit/dc3c7deaa8c692689ea0cec66cf019f05f9c4e22)]
|
|
111
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`133969a`](https://github.com/eea/volto-slate-footnote/commit/133969a37a6153a19af121d2f6031a70bc67cc9d)]
|
|
112
119
|
### [5.0.1](https://github.com/eea/volto-slate-footnote/compare/5.0.0...5.0.1) - 30 June 2022
|
|
113
120
|
|
|
114
121
|
#### :hammer_and_wrench: Others
|
|
115
122
|
|
|
116
|
-
- Add Sonarqube tag using circularity-frontend addons list [EEA Jenkins - [`4d5af13`](https://github.com/eea/volto-slate-footnote/commit/4d5af1345aad9071c031f7f00efd6bc5da04541f)]
|
|
117
123
|
## [5.0.0](https://github.com/eea/volto-slate-footnote/compare/4.0.5...5.0.0) - 19 May 2022
|
|
118
124
|
|
|
119
125
|
### [4.0.5](https://github.com/eea/volto-slate-footnote/compare/4.0.4...4.0.5) - 17 May 2022
|
|
120
126
|
|
|
121
127
|
#### :hammer_and_wrench: Others
|
|
122
128
|
|
|
123
|
-
- Add Sonarqube tag using clms-frontend addons list [EEA Jenkins - [`85a16ee`](https://github.com/eea/volto-slate-footnote/commit/85a16ee73d21d696282dc24933169d3c31383027)]
|
|
124
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`418349c`](https://github.com/eea/volto-slate-footnote/commit/418349ce22d98bf5dee58130d6f1cb9f45bbaa46)]
|
|
125
129
|
### [4.0.4](https://github.com/eea/volto-slate-footnote/compare/4.0.3...4.0.4) - 3 January 2022
|
|
126
130
|
|
|
127
131
|
### [4.0.3](https://github.com/eea/volto-slate-footnote/compare/4.0.2...4.0.3) - 18 December 2021
|
|
128
132
|
|
|
129
133
|
#### :hammer_and_wrench: Others
|
|
130
134
|
|
|
131
|
-
- Add Sonarqube tag using freshwater-frontend addons list [EEA Jenkins - [`ad06940`](https://github.com/eea/volto-slate-footnote/commit/ad0694074a06eb56ec1891256b262e9854c0303d)]
|
|
132
135
|
- Refs #142010 - Optimize Volto-addons gitflow pipelines [valentinab25 - [`1081079`](https://github.com/eea/volto-slate-footnote/commit/1081079444f5ac806e9d56765c4ccf0b9e415a73)]
|
|
133
|
-
- Add Sonarqube tag using industry-frontend addons list [EEA Jenkins - [`307687b`](https://github.com/eea/volto-slate-footnote/commit/307687b93d966e0df5c4a3f813dbb19442d2e169)]
|
|
134
|
-
- Add Sonarqube tag using clms-frontend addons list [EEA Jenkins - [`0460e2a`](https://github.com/eea/volto-slate-footnote/commit/0460e2a73a4c8ede00b0c1fc3f05624eaa345a33)]
|
|
135
|
-
- Add Sonarqube tag using forests-frontend addons list [EEA Jenkins - [`8aecee9`](https://github.com/eea/volto-slate-footnote/commit/8aecee99f11387e4ce31825209798772d7fee060)]
|
|
136
136
|
### [4.0.2](https://github.com/eea/volto-slate-footnote/compare/4.0.1...4.0.2) - 30 September 2021
|
|
137
137
|
|
|
138
138
|
#### :hammer_and_wrench: Others
|
|
139
139
|
|
|
140
|
-
- Add Sonarqube tag using sustainability-frontend addons list [EEA Jenkins - [`cf33efe`](https://github.com/eea/volto-slate-footnote/commit/cf33efec91b4b8d13562b8c8f660e7a78191d9e0)]
|
|
141
140
|
- Remove :asDefault dependency from volto-slate [Alin Voinea - [`13dad5e`](https://github.com/eea/volto-slate-footnote/commit/13dad5ed23043fa7a24682e1ac6addc86632bfe0)]
|
|
142
141
|
### [4.0.1](https://github.com/eea/volto-slate-footnote/compare/4.0.0...4.0.1) - 29 September 2021
|
|
143
142
|
|
|
@@ -145,7 +144,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
145
144
|
|
|
146
145
|
#### :hammer_and_wrench: Others
|
|
147
146
|
|
|
148
|
-
- Add Sonarqube tag using climate-energy-frontend addons list [EEA Jenkins - [`80a159b`](https://github.com/eea/volto-slate-footnote/commit/80a159bb67698cddedadc494e7ae2da32a96faea)]
|
|
149
147
|
### [3.2.0](https://github.com/eea/volto-slate-footnote/compare/3.1.1...3.2.0) - 13 September 2021
|
|
150
148
|
|
|
151
149
|
#### :hammer_and_wrench: Others
|
|
@@ -158,7 +156,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
158
156
|
- Remove console.log [Alin Voinea - [`b5d83e7`](https://github.com/eea/volto-slate-footnote/commit/b5d83e7c13240151f602d122ecf09ba9b8e335f3)]
|
|
159
157
|
- Fix slate json field default value in DX layout [Alin Voinea - [`f2805bb`](https://github.com/eea/volto-slate-footnote/commit/f2805bbc15c51ebd914ee5f4eb9dd34ef32e095b)]
|
|
160
158
|
- Fix cypress api_url [Alin Voinea - [`6a4966a`](https://github.com/eea/volto-slate-footnote/commit/6a4966a2f92e932e1d0df35351989cda535f15c8)]
|
|
161
|
-
- Add Sonarqube tag using ims-frontend addons list [EEA Jenkins - [`aed3984`](https://github.com/eea/volto-slate-footnote/commit/aed39840ecd467689eaf0adb352bd00ce95bdbbe)]
|
|
162
159
|
### [3.1.0](https://github.com/eea/volto-slate-footnote/compare/3.0.0...3.1.0) - 9 September 2021
|
|
163
160
|
|
|
164
161
|
#### :hammer_and_wrench: Others
|
|
@@ -179,7 +176,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
179
176
|
- Bump version to 2.4.0 [Alin Voinea - [`bef0d34`](https://github.com/eea/volto-slate-footnote/commit/bef0d34c2b9c20915578ffaefb4fd30cbf42f0a1)]
|
|
180
177
|
- Fix Slate point from DOM crash [Alin Voinea - [`c852f79`](https://github.com/eea/volto-slate-footnote/commit/c852f7987ffe8db433235b70792002d40ade690f)]
|
|
181
178
|
- Fix crash on copy&paste beforeInsert condition [Alin Voinea - [`85172cf`](https://github.com/eea/volto-slate-footnote/commit/85172cff3e2ea95a86d4b4fb452f3c0287b80e8f)]
|
|
182
|
-
- Add Sonarqube tag using frontend addons list [EEA Jenkins - [`b471c41`](https://github.com/eea/volto-slate-footnote/commit/b471c418d198b1bde95acfe0b256f642bacc6865)]
|
|
183
179
|
### [2.3.1](https://github.com/eea/volto-slate-footnote/compare/2.3.0...2.3.1) - 25 June 2021
|
|
184
180
|
|
|
185
181
|
### [2.3.0](https://github.com/eea/volto-slate-footnote/compare/2.2.2...2.3.0) - 12 June 2021
|
package/Dockerfile
CHANGED
package/Jenkinsfile
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
pipeline {
|
|
2
|
-
|
|
2
|
+
tools {
|
|
3
|
+
jdk 'Java17'
|
|
4
|
+
}
|
|
5
|
+
agent {
|
|
6
|
+
node { label 'docker-host' }
|
|
7
|
+
}
|
|
3
8
|
|
|
4
9
|
environment {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
GIT_NAME = "volto-slate-footnote"
|
|
11
|
+
NAMESPACE = "@eeacms"
|
|
12
|
+
SONARQUBE_TAGS = "volto.eea.europa.eu,biodiversity.europa.eu,www.eea.europa.eu-ims,climate-energy.eea.europa.eu,sustainability.eionet.europa.eu,forest.eea.europa.eu,clms.land.copernicus.eu,industry.eea.europa.eu,water.europa.eu-freshwater,demo-www.eea.europa.eu,clmsdemo.devel6cph.eea.europa.eu,water.europa.eu-marine,climate-adapt.eea.europa.eu,climate-advisory-board.devel4cph.eea.europa.eu,climate-advisory-board.europa.eu,www.eea.europa.eu-en"
|
|
13
|
+
DEPENDENCIES = ""
|
|
14
|
+
BACKEND_PROFILES = "eea.kitkat:testing"
|
|
15
|
+
BACKEND_ADDONS = ""
|
|
16
|
+
VOLTO = "16"
|
|
17
|
+
IMAGE_NAME = BUILD_TAG.toLowerCase()
|
|
18
|
+
}
|
|
11
19
|
|
|
12
20
|
stages {
|
|
13
|
-
|
|
14
21
|
stage('Release') {
|
|
15
22
|
when {
|
|
16
23
|
allOf {
|
|
@@ -20,52 +27,41 @@ pipeline {
|
|
|
20
27
|
}
|
|
21
28
|
steps {
|
|
22
29
|
node(label: 'docker') {
|
|
23
|
-
withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN'),string(credentialsId: 'eea-jenkins-npm-token', variable: 'NPM_TOKEN')]) {
|
|
24
|
-
sh '''docker pull eeacms/gitflow'''
|
|
25
|
-
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'''
|
|
30
|
+
withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN'), string(credentialsId: 'eea-jenkins-npm-token', variable: 'NPM_TOKEN')]) {
|
|
31
|
+
sh '''docker run -i --rm --pull always --name="$IMAGE_NAME-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'''
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
stage('
|
|
37
|
+
stage('Check if testing needed') {
|
|
32
38
|
when {
|
|
33
39
|
allOf {
|
|
34
|
-
environment name: 'CHANGE_ID', value: ''
|
|
35
|
-
not { changelog '.*^Automated release [0-9\\.]+$' }
|
|
36
40
|
not { branch 'master' }
|
|
41
|
+
not { branch 'develop' }
|
|
42
|
+
environment name: 'CHANGE_ID', value: ''
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
steps {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
node(label: 'docker') {
|
|
44
|
-
sh '''docker run -i --rm --name="$BUILD_TAG-eslint" -e NAMESPACE="$NAMESPACE" -e VOLTO=$VOLTO -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e VOLTO=$VOLTO plone/volto-addon-ci eslint'''
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
"Style lint": {
|
|
49
|
-
node(label: 'docker') {
|
|
50
|
-
sh '''docker run -i --rm --name="$BUILD_TAG-stylelint" -e NAMESPACE="$NAMESPACE" -e VOLTO=$VOLTO -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e VOLTO=$VOLTO plone/volto-addon-ci stylelint'''
|
|
51
|
-
}
|
|
52
|
-
},
|
|
46
|
+
script {
|
|
47
|
+
withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN')]) {
|
|
48
|
+
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
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
if (check_result == 0) {
|
|
51
|
+
env.SKIP_TESTS = 'yes'
|
|
52
|
+
}
|
|
57
53
|
}
|
|
58
|
-
|
|
59
|
-
)
|
|
54
|
+
}
|
|
60
55
|
}
|
|
61
56
|
}
|
|
62
57
|
|
|
63
|
-
stage('
|
|
58
|
+
stage('Testing') {
|
|
64
59
|
when {
|
|
65
60
|
anyOf {
|
|
66
61
|
allOf {
|
|
67
62
|
not { environment name: 'CHANGE_ID', value: '' }
|
|
68
63
|
environment name: 'CHANGE_TARGET', value: 'develop'
|
|
64
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
69
65
|
}
|
|
70
66
|
allOf {
|
|
71
67
|
environment name: 'CHANGE_ID', value: ''
|
|
@@ -73,26 +69,76 @@ pipeline {
|
|
|
73
69
|
not { changelog '.*^Automated release [0-9\\.]+$' }
|
|
74
70
|
branch 'master'
|
|
75
71
|
}
|
|
72
|
+
environment name: 'SKIP_TESTS', value: ''
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
stages {
|
|
77
|
+
stage('Build test image') {
|
|
78
|
+
steps {
|
|
79
|
+
checkout scm
|
|
80
|
+
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'''
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
stage('Fix code') {
|
|
85
|
+
when {
|
|
86
|
+
environment name: 'CHANGE_ID', value: ''
|
|
87
|
+
not { branch 'master' }
|
|
88
|
+
}
|
|
89
|
+
steps {
|
|
90
|
+
script {
|
|
91
|
+
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
|
+
sh '''docker cp $IMAGE_NAME-fix:/app/src/addons/$GIT_NAME/src .'''
|
|
93
|
+
sh '''docker rm -v $IMAGE_NAME-fix'''
|
|
94
|
+
FOUND_FIX = sh(script: '''git diff | wc -l''', returnStdout: true).trim()
|
|
81
95
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
if (FOUND_FIX != '0') {
|
|
97
|
+
withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN')]) {
|
|
98
|
+
sh '''sed -i "s|url = .*|url = https://eea-jenkins:$GITHUB_TOKEN@github.com/eea/$GIT_NAME.git|" .git/config'''
|
|
99
|
+
}
|
|
100
|
+
sh '''git fetch origin $GIT_BRANCH:$GIT_BRANCH'''
|
|
101
|
+
sh '''git checkout $GIT_BRANCH'''
|
|
102
|
+
sh '''git add src/'''
|
|
103
|
+
sh '''git commit -m "style: Automated code fix" '''
|
|
104
|
+
sh '''git push --set-upstream origin $GIT_BRANCH'''
|
|
105
|
+
sh '''exit 1'''
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
stage('ES lint') {
|
|
112
|
+
steps {
|
|
113
|
+
sh '''docker run --rm --name="$IMAGE_NAME-eslint" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend lint'''
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
stage('Style lint') {
|
|
118
|
+
steps {
|
|
119
|
+
sh '''docker run --rm --name="$IMAGE_NAME-stylelint" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend stylelint'''
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
stage('Prettier') {
|
|
124
|
+
steps {
|
|
125
|
+
sh '''docker run --rm --name="$IMAGE_NAME-prettier" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend prettier'''
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
stage('Coverage Tests') {
|
|
130
|
+
parallel {
|
|
131
|
+
|
|
132
|
+
stage('Unit tests') {
|
|
133
|
+
steps {
|
|
134
|
+
script {
|
|
135
|
+
try {
|
|
136
|
+
sh '''docker run --name="$IMAGE_NAME-volto" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend test-ci'''
|
|
137
|
+
sh '''rm -rf xunit-reports'''
|
|
138
|
+
sh '''mkdir -p xunit-reports'''
|
|
139
|
+
sh '''docker cp $IMAGE_NAME-volto:/app/coverage xunit-reports/'''
|
|
140
|
+
sh '''docker cp $IMAGE_NAME-volto:/app/junit.xml xunit-reports/'''
|
|
141
|
+
publishHTML(target : [
|
|
96
142
|
allowMissing: false,
|
|
97
143
|
alwaysLinkToLastBuild: true,
|
|
98
144
|
keepAll: true,
|
|
@@ -105,75 +151,67 @@ pipeline {
|
|
|
105
151
|
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
106
152
|
junit testResults: 'xunit-reports/junit.xml', allowEmptyResults: true
|
|
107
153
|
}
|
|
108
|
-
|
|
154
|
+
sh script: '''docker rm -v $IMAGE_NAME-volto''', returnStatus: true
|
|
155
|
+
}
|
|
109
156
|
}
|
|
110
157
|
}
|
|
111
158
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
159
|
+
|
|
160
|
+
stage('Integration tests') {
|
|
161
|
+
steps {
|
|
162
|
+
script {
|
|
163
|
+
try {
|
|
164
|
+
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=3g --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'''
|
|
166
|
+
sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress make cypress-ci'''
|
|
167
|
+
} finally {
|
|
168
|
+
try {
|
|
169
|
+
sh '''rm -rf cypress-videos cypress-results cypress-coverage cypress-screenshots'''
|
|
170
|
+
sh '''mkdir -p cypress-videos cypress-results cypress-coverage cypress-screenshots'''
|
|
171
|
+
videos = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos/''', returnStatus: true
|
|
172
|
+
sh '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/reports cypress-results/'''
|
|
173
|
+
screenshots = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/screenshots cypress-screenshots''', returnStatus: true
|
|
116
174
|
|
|
117
|
-
|
|
118
|
-
when {
|
|
119
|
-
anyOf {
|
|
120
|
-
allOf {
|
|
121
|
-
not { environment name: 'CHANGE_ID', value: '' }
|
|
122
|
-
environment name: 'CHANGE_TARGET', value: 'develop'
|
|
123
|
-
}
|
|
124
|
-
allOf {
|
|
125
|
-
environment name: 'CHANGE_ID', value: ''
|
|
126
|
-
anyOf {
|
|
127
|
-
not { changelog '.*^Automated release [0-9\\.]+$' }
|
|
128
|
-
branch 'master'
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
steps {
|
|
134
|
-
parallel(
|
|
175
|
+
archiveArtifacts artifacts: 'cypress-screenshots/**', fingerprint: true, allowEmptyArchive: true
|
|
135
176
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
sh '''docker pull eeacms/plone-backend; docker run --rm -d --name="$BUILD_TAG-plone" -e SITE="Plone" -e PROFILES="eea.kitkat:testing" eeacms/plone-backend'''
|
|
141
|
-
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" -e NODE_ENV=development -e VOLTO="$VOLTO" plone/volto-addon-ci cypress'''
|
|
142
|
-
} finally {
|
|
143
|
-
try {
|
|
144
|
-
sh '''rm -rf cypress-reports cypress-results cypress-coverage'''
|
|
145
|
-
sh '''mkdir -p cypress-reports cypress-results cypress-coverage'''
|
|
146
|
-
sh '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/cypress/videos cypress-reports/'''
|
|
147
|
-
sh '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/cypress/reports cypress-results/'''
|
|
148
|
-
coverage = sh script: '''docker cp $BUILD_TAG-cypress:/opt/frontend/my-volto-project/src/addons/$GIT_NAME/coverage cypress-coverage/''', returnStatus: true
|
|
149
|
-
if ( coverage == 0 ) {
|
|
150
|
-
publishHTML (target : [allowMissing: false,
|
|
177
|
+
coverage = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/coverage cypress-coverage''', returnStatus: true
|
|
178
|
+
|
|
179
|
+
if ( coverage == 0 ) {
|
|
180
|
+
publishHTML(target : [allowMissing: false,
|
|
151
181
|
alwaysLinkToLastBuild: true,
|
|
152
182
|
keepAll: true,
|
|
153
183
|
reportDir: 'cypress-coverage/coverage/lcov-report',
|
|
154
184
|
reportFiles: 'index.html',
|
|
155
185
|
reportName: 'CypressCoverage',
|
|
156
186
|
reportTitles: 'Integration Tests Code Coverage'])
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
187
|
+
}
|
|
188
|
+
if ( videos == 0 ) {
|
|
189
|
+
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
|
+
archiveArtifacts artifacts: 'cypress-videos/**/*.mp4', fingerprint: true, allowEmptyArchive: true
|
|
191
|
+
}
|
|
192
|
+
} finally {
|
|
193
|
+
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
164
194
|
junit testResults: 'cypress-results/**/*.xml', allowEmptyResults: true
|
|
195
|
+
}
|
|
196
|
+
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
|
|
197
|
+
sh '''docker logs $IMAGE_NAME-cypress'''
|
|
198
|
+
}
|
|
199
|
+
sh script: "docker stop $IMAGE_NAME-cypress", returnStatus: true
|
|
200
|
+
sh script: "docker stop $IMAGE_NAME-plone", returnStatus: true
|
|
201
|
+
sh script: "docker rm -v $IMAGE_NAME-plone", returnStatus: true
|
|
202
|
+
sh script: "docker rm -v $IMAGE_NAME-cypress", returnStatus: true
|
|
165
203
|
}
|
|
166
|
-
sh script: "docker stop $BUILD_TAG-plone", returnStatus: true
|
|
167
|
-
sh script: "docker rm -v $BUILD_TAG-plone", returnStatus: true
|
|
168
|
-
sh script: "docker rm -v $BUILD_TAG-cypress", returnStatus: true
|
|
169
|
-
|
|
170
204
|
}
|
|
171
205
|
}
|
|
172
206
|
}
|
|
173
207
|
}
|
|
174
208
|
}
|
|
175
|
-
|
|
176
|
-
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
post {
|
|
212
|
+
always {
|
|
213
|
+
sh script: "docker rmi $IMAGE_NAME-frontend", returnStatus: true
|
|
214
|
+
}
|
|
177
215
|
}
|
|
178
216
|
}
|
|
179
217
|
|
|
@@ -197,19 +235,14 @@ pipeline {
|
|
|
197
235
|
}
|
|
198
236
|
}
|
|
199
237
|
steps {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
sh '''sed -i "s#/opt/frontend/my-volto-project/src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
|
|
209
|
-
sh '''sed -i "s#src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
|
|
210
|
-
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-$BRANCH_NAME -Dsonar.projectVersion=$BRANCH_NAME-$BUILD_NUMBER"
|
|
211
|
-
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'''
|
|
212
|
-
}
|
|
238
|
+
script {
|
|
239
|
+
def scannerHome = tool 'SonarQubeScanner'
|
|
240
|
+
def nodeJS = tool 'NodeJS'
|
|
241
|
+
withSonarQubeEnv('Sonarqube') {
|
|
242
|
+
sh '''sed -i "s#/app/src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
|
|
243
|
+
sh '''sed -i "s#src/addons/${GIT_NAME}/##g" xunit-reports/coverage/lcov.info'''
|
|
244
|
+
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-$BRANCH_NAME -Dsonar.projectVersion=$BRANCH_NAME-$BUILD_NUMBER"
|
|
245
|
+
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}-${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 15; try=\$(( \$try - 1 )); fi; done'''
|
|
213
246
|
}
|
|
214
247
|
}
|
|
215
248
|
}
|
|
@@ -230,18 +263,15 @@ pipeline {
|
|
|
230
263
|
}
|
|
231
264
|
}
|
|
232
265
|
steps {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
sh '''
|
|
237
|
-
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
|
238
|
-
sh '''set -o pipefail; docker run -i --rm --name="$BUILD_TAG-gitflow-sn" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" eeacms/gitflow /checkSonarqubemaster.sh | grep -v "Found script" | tee checkresult.txt'''
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
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",
|
|
242
|
-
text: readFile(file: 'checkresult.txt'), conclusion: "${currentBuild.currentResult}",
|
|
243
|
-
detailsURL: "${env.BUILD_URL}display/redirect"
|
|
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'''
|
|
244
270
|
}
|
|
271
|
+
|
|
272
|
+
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',
|
|
273
|
+
text: readFile(file: 'checkresult.txt'), conclusion: "${currentBuild.currentResult}",
|
|
274
|
+
detailsURL: "${env.BUILD_URL}display/redirect"
|
|
245
275
|
}
|
|
246
276
|
}
|
|
247
277
|
}
|
|
@@ -254,20 +284,16 @@ pipeline {
|
|
|
254
284
|
environment name: 'CHANGE_TARGET', value: 'master'
|
|
255
285
|
}
|
|
256
286
|
steps {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
sh '''docker pull eeacms/gitflow'''
|
|
264
|
-
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'''
|
|
265
|
-
}
|
|
287
|
+
script {
|
|
288
|
+
if (env.CHANGE_BRANCH != 'develop') {
|
|
289
|
+
error 'Pipeline aborted due to PR not made from develop branch'
|
|
290
|
+
}
|
|
291
|
+
withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN')]) {
|
|
292
|
+
sh '''docker run --pull always -i --rm --name="$IMAGE_NAME-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'''
|
|
266
293
|
}
|
|
267
294
|
}
|
|
268
295
|
}
|
|
269
296
|
}
|
|
270
|
-
|
|
271
297
|
}
|
|
272
298
|
|
|
273
299
|
post {
|
package/Makefile
CHANGED
|
@@ -50,6 +50,11 @@ VOLTO_VERSION?=16
|
|
|
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
|
|
53
|
+
RAZZLE_INTERNAL_API_PATH?="http://localhost:8080/Plone"
|
|
54
|
+
RAZZLE_DEV_PROXY_API_PATH?="${RAZZLE_INTERNAL_API_PATH}"
|
|
55
|
+
CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}"
|
|
56
|
+
|
|
57
|
+
|
|
53
58
|
|
|
54
59
|
# Top-level targets
|
|
55
60
|
.PHONY: all
|
|
@@ -77,11 +82,11 @@ shell: ## Start a shell in the frontend container
|
|
|
77
82
|
|
|
78
83
|
.PHONY: cypress-open
|
|
79
84
|
cypress-open: ## Open cypress integration tests
|
|
80
|
-
NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress open
|
|
85
|
+
CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress open
|
|
81
86
|
|
|
82
87
|
.PHONY: cypress-run
|
|
83
88
|
cypress-run: ## Run cypress integration tests
|
|
84
|
-
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 --browser chromium
|
|
85
90
|
|
|
86
91
|
.PHONY: test
|
|
87
92
|
test: ## Run jest tests
|
|
@@ -129,3 +134,29 @@ i18n: ## i18n
|
|
|
129
134
|
help: ## Show this help.
|
|
130
135
|
@echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)"
|
|
131
136
|
head -n 14 Makefile
|
|
137
|
+
|
|
138
|
+
.PHONY: ci-fix
|
|
139
|
+
ci-fix:
|
|
140
|
+
echo "Running lint-fix"
|
|
141
|
+
make lint-fix
|
|
142
|
+
echo "Running prettier-fix"
|
|
143
|
+
make prettier-fix
|
|
144
|
+
echo "Running stylelint-fix"
|
|
145
|
+
make stylelint-fix
|
|
146
|
+
|
|
147
|
+
.PHONY: test-ci
|
|
148
|
+
test-ci:
|
|
149
|
+
cd /app
|
|
150
|
+
RAZZLE_JEST_CONFIG=src/addons/${ADDON_PATH}/jest-addon.config.js CI=true yarn test src/addons/${ADDON_PATH}/src --watchAll=false --reporters=default --reporters=jest-junit --collectCoverage --coverageReporters lcov cobertura text
|
|
151
|
+
|
|
152
|
+
.PHONY: start-ci
|
|
153
|
+
start-ci:
|
|
154
|
+
cp .coverage.babel.config.js /app/babel.config.js
|
|
155
|
+
cd ../..
|
|
156
|
+
yarn start
|
|
157
|
+
|
|
158
|
+
.PHONY: cypress-ci
|
|
159
|
+
cypress-ci:
|
|
160
|
+
$(NODE_MODULES)/.bin/wait-on -t 240000 http://localhost:3000
|
|
161
|
+
NODE_ENV=development make cypress-run
|
|
162
|
+
|
package/cypress.config.js
CHANGED
|
@@ -2,12 +2,12 @@ const { defineConfig } = require('cypress');
|
|
|
2
2
|
|
|
3
3
|
module.exports = defineConfig({
|
|
4
4
|
viewportWidth: 1280,
|
|
5
|
-
defaultCommandTimeout:
|
|
5
|
+
defaultCommandTimeout: 8888,
|
|
6
6
|
chromeWebSecurity: false,
|
|
7
7
|
reporter: 'junit',
|
|
8
|
-
video:
|
|
8
|
+
video: false,
|
|
9
9
|
retries: {
|
|
10
|
-
runMode:
|
|
10
|
+
runMode: 2,
|
|
11
11
|
openMode: 0,
|
|
12
12
|
},
|
|
13
13
|
reporterOptions: {
|
package/package.json
CHANGED
|
@@ -20,24 +20,70 @@ const alphabet = 'abcdefghijklmnopqrstuvwxyz';
|
|
|
20
20
|
* received from the Volto form.
|
|
21
21
|
*/
|
|
22
22
|
const FootnotesBlockView = (props) => {
|
|
23
|
-
const { data, properties } = props;
|
|
23
|
+
const { data, properties, tabData, content } = props;
|
|
24
24
|
const { title, global, placeholder = 'Footnotes' } = data;
|
|
25
|
+
|
|
25
26
|
const metadata = props.metadata ? props.metadata : properties;
|
|
26
|
-
|
|
27
|
-
const
|
|
27
|
+
|
|
28
|
+
const localMetadata = content
|
|
29
|
+
? content
|
|
30
|
+
: tabData
|
|
31
|
+
? tabData
|
|
32
|
+
: global
|
|
33
|
+
? metadata
|
|
34
|
+
: properties;
|
|
35
|
+
const blocks = getAllBlocksAndSlateFields(localMetadata);
|
|
28
36
|
const notesObj = makeFootnoteListOfUniqueItems(blocks);
|
|
37
|
+
let startList = 1;
|
|
38
|
+
if (Object.keys(notesObj).length > 0) {
|
|
39
|
+
const noteId = Object.keys(notesObj)[0];
|
|
40
|
+
const note = notesObj[noteId];
|
|
41
|
+
const { zoteroId } = note;
|
|
42
|
+
|
|
43
|
+
const notesGlobalResult = makeFootnoteListOfUniqueItems(
|
|
44
|
+
getAllBlocksAndSlateFields(metadata),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const indiceIfZoteroId = note.extra
|
|
48
|
+
? [
|
|
49
|
+
Object.keys(notesGlobalResult).indexOf(zoteroId) + 1, // parent footnote
|
|
50
|
+
...note.extra.map(
|
|
51
|
+
// citations from extra
|
|
52
|
+
(zoteroObj, _index) =>
|
|
53
|
+
// all zotero citation are indexed by zoteroId in notesGlobalResult
|
|
54
|
+
|
|
55
|
+
Object.keys(notesGlobalResult).indexOf(zoteroObj.zoteroId) + 1,
|
|
56
|
+
),
|
|
57
|
+
]
|
|
58
|
+
: // no extra citations (no multiples)
|
|
59
|
+
Object.keys(notesGlobalResult).indexOf(zoteroId) + 1;
|
|
60
|
+
const citationIndice = zoteroId // ZOTERO
|
|
61
|
+
? indiceIfZoteroId
|
|
62
|
+
: // FOOTNOTES
|
|
63
|
+
// parent footnote
|
|
64
|
+
[note, ...(note.extra || [])].map((footnoteObj, _index) => {
|
|
65
|
+
return (
|
|
66
|
+
Object.keys(notesGlobalResult).indexOf(
|
|
67
|
+
Object.keys(notesGlobalResult).find(
|
|
68
|
+
(key) =>
|
|
69
|
+
notesGlobalResult[key].footnote === footnoteObj.footnote,
|
|
70
|
+
),
|
|
71
|
+
) + 1
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
startList = citationIndice;
|
|
75
|
+
}
|
|
29
76
|
|
|
30
77
|
return (
|
|
31
78
|
<div className="footnotes-listing-block">
|
|
32
79
|
<h3 title={placeholder}>{title}</h3>
|
|
33
80
|
{notesObj && (
|
|
34
|
-
<ol>
|
|
81
|
+
<ol start={startList}>
|
|
35
82
|
{Object.keys(notesObj).map((noteId) => {
|
|
36
83
|
const note = notesObj[noteId];
|
|
37
84
|
const { uid, footnote, zoteroId, parentUid } = note;
|
|
38
85
|
const { refs } = note;
|
|
39
86
|
const refsList = refs ? Object.keys(refs) : null;
|
|
40
|
-
|
|
41
87
|
return (
|
|
42
88
|
<li
|
|
43
89
|
key={`footnote-${zoteroId || uid}`}
|
|
@@ -41,7 +41,6 @@ const FootnoteEditor = (props) => {
|
|
|
41
41
|
const metadataBlocks = getAllBlocksAndSlateFields(metadata);
|
|
42
42
|
const storeBlocks = getAllBlocksAndSlateFields(initialFormData);
|
|
43
43
|
const uniqueFootnoteBlocks = [];
|
|
44
|
-
|
|
45
44
|
const flatAllBlocks = isEmpty(metadata) ? storeBlocks : metadataBlocks;
|
|
46
45
|
/**
|
|
47
46
|
* Will add only the items that are unique by text
|
package/src/editor/extensions.js
CHANGED
package/src/editor/render.jsx
CHANGED
|
@@ -24,6 +24,7 @@ export const FootnoteElement = (props) => {
|
|
|
24
24
|
const { data = {} } = element;
|
|
25
25
|
const { uid, zoteroId } = data;
|
|
26
26
|
const editor = useEditorContext();
|
|
27
|
+
const ref = React.useRef(null);
|
|
27
28
|
|
|
28
29
|
const initialFormData = useSelector((state) => state?.content?.data || {});
|
|
29
30
|
const blockProps = editor?.getBlockProps ? editor.getBlockProps() : null;
|
|
@@ -36,7 +37,6 @@ export const FootnoteElement = (props) => {
|
|
|
36
37
|
const notesObjResult = isEmpty(metadata)
|
|
37
38
|
? makeFootnoteListOfUniqueItems(storeBlocks)
|
|
38
39
|
: makeFootnoteListOfUniqueItems(blocks);
|
|
39
|
-
|
|
40
40
|
// will cosider zotero citations and footnote
|
|
41
41
|
// notesObjResult contains all zotero/footnote as unique, and contain refs for other zotero/footnote
|
|
42
42
|
const indiceIfZoteroId = data.extra
|
|
@@ -58,12 +58,15 @@ export const FootnoteElement = (props) => {
|
|
|
58
58
|
// parent footnote
|
|
59
59
|
[data, ...(data.extra || [])]
|
|
60
60
|
.map((footnoteObj, _index) => {
|
|
61
|
+
const indexInNotesObjResult = Object.keys(notesObjResult).indexOf(
|
|
62
|
+
Object.keys(notesObjResult).find(
|
|
63
|
+
(key) => notesObjResult[key].footnote === footnoteObj.footnote,
|
|
64
|
+
),
|
|
65
|
+
);
|
|
61
66
|
return `[${
|
|
62
|
-
|
|
63
|
-
Object.keys(notesObjResult).
|
|
64
|
-
|
|
65
|
-
),
|
|
66
|
-
) + 1
|
|
67
|
+
indexInNotesObjResult === -1
|
|
68
|
+
? Object.keys(notesObjResult).length + 1
|
|
69
|
+
: indexInNotesObjResult + 1
|
|
67
70
|
}]`;
|
|
68
71
|
})
|
|
69
72
|
.join('');
|
|
@@ -83,15 +86,20 @@ export const FootnoteElement = (props) => {
|
|
|
83
86
|
return (
|
|
84
87
|
<>
|
|
85
88
|
{mode === 'view' ? (
|
|
86
|
-
<span id={`ref-${uid}`} aria-describedby="footnote-label">
|
|
89
|
+
<span id={`ref-${uid}`} aria-describedby="footnote-label" ref={ref}>
|
|
87
90
|
<Popup
|
|
88
91
|
position="bottom left"
|
|
92
|
+
pinned={true}
|
|
93
|
+
mountNode={ref.current}
|
|
94
|
+
on={['click', 'hover', 'focus']}
|
|
89
95
|
trigger={
|
|
90
96
|
<span
|
|
91
97
|
id={`cite_ref-${uid}`}
|
|
92
98
|
{...attributes}
|
|
93
99
|
className="citation-item"
|
|
94
100
|
data-footnote-indice={citationIndice}
|
|
101
|
+
tabIndex={0}
|
|
102
|
+
role={'presentation'}
|
|
95
103
|
>
|
|
96
104
|
{children}
|
|
97
105
|
</span>
|
package/src/editor/utils.js
CHANGED
|
@@ -10,6 +10,37 @@ import { getAllBlocks } from '@plone/volto-slate/utils';
|
|
|
10
10
|
export const makeFootnote = (footnote) => {
|
|
11
11
|
return footnote ? footnote.replace('<?xml version="1.0"?>', '') : '';
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* retrive all slate children of nested objects
|
|
15
|
+
* @param {object} path - the keys that we want to extract the slate children from
|
|
16
|
+
* @param {*} value - the source that we want to extract the slate children from
|
|
17
|
+
* Exemple of parameters
|
|
18
|
+
* path:{items:'value'}
|
|
19
|
+
* @returns string
|
|
20
|
+
*/
|
|
21
|
+
const retriveValuesOfSlateFromNestedPath = (path, value) => {
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
let allSlateValue = [];
|
|
24
|
+
value.forEach((element) => {
|
|
25
|
+
allSlateValue = [
|
|
26
|
+
...allSlateValue,
|
|
27
|
+
...retriveValuesOfSlateFromNestedPath(path, element),
|
|
28
|
+
];
|
|
29
|
+
});
|
|
30
|
+
return allSlateValue;
|
|
31
|
+
}
|
|
32
|
+
if (typeof path === 'string' && value) {
|
|
33
|
+
if (value[path]?.length > 0) return [...value[path]];
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
if (typeof path === 'object' && Object.keys(path).length > 0) {
|
|
37
|
+
return retriveValuesOfSlateFromNestedPath(
|
|
38
|
+
path[Object.keys(path)[0]],
|
|
39
|
+
value[Object.keys(path)[0]],
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return [];
|
|
43
|
+
};
|
|
13
44
|
|
|
14
45
|
/**
|
|
15
46
|
* Will open accordion if contains footnote reference
|
|
@@ -46,6 +77,7 @@ const blockTypesOperations = {
|
|
|
46
77
|
return [...accumulator, ...propertiesBlocks];
|
|
47
78
|
}, []);
|
|
48
79
|
},
|
|
80
|
+
|
|
49
81
|
metadata: (block, properties) => {
|
|
50
82
|
const fId = block?.data?.id;
|
|
51
83
|
return block?.data?.widget === 'slate'
|
|
@@ -80,6 +112,7 @@ const blockTypesOperations = {
|
|
|
80
112
|
*/
|
|
81
113
|
export const getAllBlocksAndSlateFields = (properties) => {
|
|
82
114
|
const blocks = getAllBlocks(properties, []);
|
|
115
|
+
|
|
83
116
|
return blocks.reduce((accumulator, currentblock) => {
|
|
84
117
|
return [
|
|
85
118
|
...accumulator,
|
|
@@ -111,45 +144,48 @@ export const makeFootnoteListOfUniqueItems = (blocks) => {
|
|
|
111
144
|
] || ['value'];
|
|
112
145
|
|
|
113
146
|
mapping.forEach((key) => {
|
|
114
|
-
const value = element
|
|
147
|
+
const value = retriveValuesOfSlateFromNestedPath(key, element);
|
|
148
|
+
|
|
115
149
|
if (!value) return;
|
|
116
150
|
|
|
117
|
-
value
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (node.data
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
node.data
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
151
|
+
value
|
|
152
|
+
.filter((val) => val.children)
|
|
153
|
+
.forEach((item) => {
|
|
154
|
+
// Node.elements(item) returns an iterable generator of nodes
|
|
155
|
+
Array.from(Node.elements(item)).forEach(([node]) => {
|
|
156
|
+
if (footnotes.includes(node.type) && node.data) {
|
|
157
|
+
// for citations (Zotero items) create refs for same zoteroId
|
|
158
|
+
if (node.data.zoteroId) {
|
|
159
|
+
iterateZoteroObj(notesObjResult, node.data);
|
|
160
|
+
// itereate the extra obj for multiple citations
|
|
161
|
+
if (node.data.extra) {
|
|
162
|
+
node.data.extra.forEach((zoteroObjItem) =>
|
|
163
|
+
// send the uid of the parent
|
|
164
|
+
// of the word the will have the reference indice
|
|
165
|
+
iterateZoteroObj(
|
|
166
|
+
notesObjResult,
|
|
167
|
+
zoteroObjItem,
|
|
168
|
+
node.data.uid,
|
|
169
|
+
),
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
// for footnotes - create refs, on identical text
|
|
173
|
+
} else {
|
|
174
|
+
iterateFootnoteObj(notesObjResult, node.data);
|
|
175
|
+
if (node.data.extra) {
|
|
176
|
+
node.data.extra.forEach((footnoteObjItem) =>
|
|
177
|
+
// since is called in case of extra, the parent is needed
|
|
178
|
+
iterateFootnoteObj(
|
|
179
|
+
notesObjResult,
|
|
180
|
+
footnoteObjItem,
|
|
181
|
+
node.data.uid,
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
}
|
|
148
185
|
}
|
|
149
186
|
}
|
|
150
|
-
}
|
|
187
|
+
});
|
|
151
188
|
});
|
|
152
|
-
});
|
|
153
189
|
});
|
|
154
190
|
});
|
|
155
191
|
|
|
@@ -204,6 +240,7 @@ const iterateFootnoteObj = (notesObjResultTemp, node, parentUid) => {
|
|
|
204
240
|
return notesObjResultTemp[noteId].footnote === node.footnote;
|
|
205
241
|
});
|
|
206
242
|
// has not yet been added
|
|
243
|
+
|
|
207
244
|
if (!found) {
|
|
208
245
|
// will use the parentUid instead of own uid for render to be able to reference to the correct element
|
|
209
246
|
//(word containing the footnotes)
|