@eeacms/volto-cca-policy 0.3.125 → 0.3.127
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 +144 -0
- package/artifacts/link-integrity-workflow/README.md +76 -0
- package/artifacts/link-integrity-workflow/index.md +33 -0
- package/package.json +1 -1
- package/src/components/manage/Workflow/WorkflowLinkIntegrityModal.jsx +364 -113
- package/src/components/manage/Workflow/WorkflowLinkIntegrityModal.test.jsx +2 -4
- package/src/customizations/volto/components/manage/Workflow/README.md +24 -2
- package/src/customizations/volto/components/manage/Workflow/Workflow.jsx +6 -1
- /package/artifacts/{link-integrity-block-fields-report.md → link-integrity-workflow/link-integrity-block-fields-report.md} +0 -0
- /package/artifacts/{link-integrity-blocks-report.md → link-integrity-workflow/link-integrity-blocks-report.md} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,139 @@ 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
|
+
### [0.3.127](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.3...0.3.127) - 27 May 2026
|
|
8
|
+
|
|
9
|
+
#### :bug: Bug Fixes
|
|
10
|
+
|
|
11
|
+
- fix: resolve remaining lint warnings in WorkflowLinkIntegrityModal [Tiberiu Ichim - [`f1add88`](https://github.com/eea/volto-cca-policy/commit/f1add881c7240ba12dd223bfccb0c4ac86f83056)]
|
|
12
|
+
- fix: resolve lint warnings and a11y errors in WorkflowLinkIntegrityModal [Tiberiu Ichim - [`bc60ca6`](https://github.com/eea/volto-cca-policy/commit/bc60ca604f30f62d6fb225bb319f76bab700ff04)]
|
|
13
|
+
- fix: update warning message in link integrity workflow state change modal [Tiberiu Ichim - [`1244b2e`](https://github.com/eea/volto-cca-policy/commit/1244b2e826590050c6b10506651482cd615b8c92)]
|
|
14
|
+
- fix: resolve workflow state transition failure when confirming via link integrity warning modal [Tiberiu Ichim - [`2fd0d89`](https://github.com/eea/volto-cca-policy/commit/2fd0d899fc421b4944de5488902f4bc35f5102d9)]
|
|
15
|
+
|
|
16
|
+
#### :house: Internal changes
|
|
17
|
+
|
|
18
|
+
- style: Automated code fix [eea-jenkins - [`8ca0234`](https://github.com/eea/volto-cca-policy/commit/8ca0234d1d429ed5964061989dad13cd6b44b027)]
|
|
19
|
+
- style: Automated code fix [eea-jenkins - [`1e4caaf`](https://github.com/eea/volto-cca-policy/commit/1e4caafffd7b026c565887d6ace3c7ec87866bfe)]
|
|
20
|
+
|
|
21
|
+
#### :house: Documentation changes
|
|
22
|
+
|
|
23
|
+
- docs: update link-integrity artifact spec to reflect Portal-based modal [Tiberiu Ichim - [`f697e7e`](https://github.com/eea/volto-cca-policy/commit/f697e7e5b453a31032feeb862526d97a1c995483)]
|
|
24
|
+
- docs: convert index.md absolute links to clean relative links [Tiberiu Ichim - [`bfb2d6a`](https://github.com/eea/volto-cca-policy/commit/bfb2d6a6c592991c4f65875c8db5f9b55205bf4d)]
|
|
25
|
+
- docs: reorganize link integrity workflow artifacts, adding README specification and index overview [Tiberiu Ichim - [`1208c96`](https://github.com/eea/volto-cca-policy/commit/1208c9619ff4097a4d954e355895382978b326dc)]
|
|
26
|
+
- docs: add specification for link integrity check during workflow transitions [Tiberiu Ichim - [`842da3d`](https://github.com/eea/volto-cca-policy/commit/842da3d371f0c5c38a538e3d519bc5eb79705e34)]
|
|
27
|
+
|
|
28
|
+
### [1.0.0-alpha.3](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.2...1.0.0-alpha.3) - 22 May 2026
|
|
29
|
+
|
|
30
|
+
#### :bug: Bug Fixes
|
|
31
|
+
|
|
32
|
+
- fix: imports [kreafox - [`c20878e`](https://github.com/eea/volto-cca-policy/commit/c20878e4c72c91a239a5b5fd1cf2fc11b943dc2a)]
|
|
33
|
+
- fix: undo some changes [kreafox - [`2e7e7fa`](https://github.com/eea/volto-cca-policy/commit/2e7e7fa5596bdcc2b4866c915bc1671fc373ac0a)]
|
|
34
|
+
|
|
35
|
+
#### :hammer_and_wrench: Others
|
|
36
|
+
|
|
37
|
+
- eslint image [iugin - [`c293ec8`](https://github.com/eea/volto-cca-policy/commit/c293ec8a9a525eff431629d7724e65bdd959a07b)]
|
|
38
|
+
- eslint image tag [iugin - [`6f7d575`](https://github.com/eea/volto-cca-policy/commit/6f7d5752466dac4412c6ef119e9f8a624c8f9706)]
|
|
39
|
+
- eslint [iugin - [`a449f36`](https://github.com/eea/volto-cca-policy/commit/a449f36f3b8d5b8e60ff6a3ffcc439b01aa78245)]
|
|
40
|
+
- remove old js files, remains jsx [iugin - [`3ff03ae`](https://github.com/eea/volto-cca-policy/commit/3ff03ae75e5a1a106ebd0547705dcab89d3c4a79)]
|
|
41
|
+
- eslint updates jsx, include and Image tag [iugin - [`ac5abd2`](https://github.com/eea/volto-cca-policy/commit/ac5abd288ec258774a90c2395964521068918d29)]
|
|
42
|
+
### [1.0.0-alpha.2](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.1...1.0.0-alpha.2) - 21 May 2026
|
|
43
|
+
|
|
44
|
+
#### :bug: Bug Fixes
|
|
45
|
+
|
|
46
|
+
- fix: long gap in blocks chooser [kreafox - [`e86ef53`](https://github.com/eea/volto-cca-policy/commit/e86ef531a3a70a024b0c76b47d09e967fd28ba5b)]
|
|
47
|
+
- fix(block): spacing issue with accordion in tabs block [kreafox - [`cf6de7c`](https://github.com/eea/volto-cca-policy/commit/cf6de7c52d941e75bb1c7e4704abfc5ff47775c3)]
|
|
48
|
+
|
|
49
|
+
#### :hammer_and_wrench: Others
|
|
50
|
+
|
|
51
|
+
- rename files for volto-18 [iugin - [`5ca21ab`](https://github.com/eea/volto-cca-policy/commit/5ca21aba63f0133003267531335a207130717234)]
|
|
52
|
+
- Add artifacts [Tiberiu Ichim - [`37cccf1`](https://github.com/eea/volto-cca-policy/commit/37cccf1d3f1d926c64c7d192b071c7cd0061cb0a)]
|
|
53
|
+
- Add blocks overview [Tiberiu Ichim - [`1aa6e8b`](https://github.com/eea/volto-cca-policy/commit/1aa6e8b780f4f7a00641872ef7a99e2223cd1feb)]
|
|
54
|
+
- Refs #296263 - sidebar menu sticky and add "submenus" [iugin - [`1bce280`](https://github.com/eea/volto-cca-policy/commit/1bce2802e815bb1dd4fabb62d3c7ff7478c46b07)]
|
|
55
|
+
- Refs #296263 - remove border landing page [iugin - [`488b7d1`](https://github.com/eea/volto-cca-policy/commit/488b7d1dfbc307d8571802e86e6343fff52b04ce)]
|
|
56
|
+
- Refs #296263 - add submenu [iugin - [`decc8b1`](https://github.com/eea/volto-cca-policy/commit/decc8b16f2d5aea6214f137b3afde5586806021b)]
|
|
57
|
+
- Refs #298498 - force rebuild [iugin - [`f3deed1`](https://github.com/eea/volto-cca-policy/commit/f3deed10893c81768a33ccb44f4659c28cce02a4)]
|
|
58
|
+
- Refs #298498 - exclude UK [iugin - [`43c122d`](https://github.com/eea/volto-cca-policy/commit/43c122d067029a9b08d729a04f9e17ce07b1911f)]
|
|
59
|
+
- Fix Jenkins. [GhitaB - [`8fa1d86`](https://github.com/eea/volto-cca-policy/commit/8fa1d860b3a572d0769d637fdb3fc4f9ecf149f8)]
|
|
60
|
+
- Fix Jenkins. [GhitaB - [`b1baaf2`](https://github.com/eea/volto-cca-policy/commit/b1baaf2274224f0046281d2cfb629138d01ec121)]
|
|
61
|
+
- Refs #296263 - country map eslint [iugin - [`237cf82`](https://github.com/eea/volto-cca-policy/commit/237cf824d6224947b0b1bf053e0a6fbade7673b8)]
|
|
62
|
+
- Refs #296263 - country map eslint [iugin - [`2506368`](https://github.com/eea/volto-cca-policy/commit/250636839550d91b50be1841f491fbf6415e2b13)]
|
|
63
|
+
- Refs #296263 - country map [iugin - [`9c517cb`](https://github.com/eea/volto-cca-policy/commit/9c517cb37dc211732b6e8511c37727f41fdb776f)]
|
|
64
|
+
- Refs #296263 - country profile landing init [iugin - [`ae9ffb4`](https://github.com/eea/volto-cca-policy/commit/ae9ffb4f3c73b2331014808ee114049dfa8fe9ab)]
|
|
65
|
+
- Refs #296263 - country profile ticket updates [iugin - [`edbf93d`](https://github.com/eea/volto-cca-policy/commit/edbf93d071d770f596fce12cf463151bff4efd72)]
|
|
66
|
+
- Refs #296263 - add Monitoring_Evaluation [iugin - [`d18a9de`](https://github.com/eea/volto-cca-policy/commit/d18a9ded8f65fa7bd58ef8e62985da77dead6562)]
|
|
67
|
+
- Refs #296263 - section name update [iugin - [`23e2e25`](https://github.com/eea/volto-cca-policy/commit/23e2e258bec0f51b20e656907cf2a8ee0cc2c427)]
|
|
68
|
+
- Refs #296263 - Key affected sectors tab [iugin - [`6d2c52f`](https://github.com/eea/volto-cca-policy/commit/6d2c52fda49270e704162bb90e48931bbdb7118e)]
|
|
69
|
+
- Refs #296263 - static countries [iugin - [`a58c3aa`](https://github.com/eea/volto-cca-policy/commit/a58c3aa596defc73fbd07ac0a58e05e510627b65)]
|
|
70
|
+
- Refs #296263 - assesments status map and circles [iugin - [`fa9c4a4`](https://github.com/eea/volto-cca-policy/commit/fa9c4a457baf4ad644438ee9649c17cf0798e3a7)]
|
|
71
|
+
- Refs #296263 - className and callout [iugin - [`e0646d7`](https://github.com/eea/volto-cca-policy/commit/e0646d7b28ca6c0724325678b82be2d855533c6c)]
|
|
72
|
+
- Refs #296263 - className [iugin - [`0f568d7`](https://github.com/eea/volto-cca-policy/commit/0f568d7af4ac0b4f6791b08e7209f4ff5f659327)]
|
|
73
|
+
- Refs #296263 - styles and messages [iugin - [`359f2fc`](https://github.com/eea/volto-cca-policy/commit/359f2fcd207a6e58bc9e32d514ca23183ea6ca8e)]
|
|
74
|
+
- Refs #296263 - jenkins update [iugin - [`b424df5`](https://github.com/eea/volto-cca-policy/commit/b424df51271e975a9721e4c0712c3009b68e53fa)]
|
|
75
|
+
- Refs #296263 - init [iugin - [`01bff47`](https://github.com/eea/volto-cca-policy/commit/01bff4757de9d2b01b9476f19b61715a7983999b)]
|
|
76
|
+
### [1.0.0-alpha.1](https://github.com/eea/volto-cca-policy/compare/0.3.126...1.0.0-alpha.1) - 20 May 2026
|
|
77
|
+
|
|
78
|
+
#### :rocket: New Features
|
|
79
|
+
|
|
80
|
+
- feat: update Dockerfile and configuration for Volto 18 compatibility [kreafox - [`2c51416`](https://github.com/eea/volto-cca-policy/commit/2c51416baf7e550936bdce3e5f510631bb7164ab)]
|
|
81
|
+
|
|
82
|
+
#### :bug: Bug Fixes
|
|
83
|
+
|
|
84
|
+
- fix: sonarqube reported issues [kreafox - [`8398f64`](https://github.com/eea/volto-cca-policy/commit/8398f64d10f10444a8a96e1b120fc378aefad727)]
|
|
85
|
+
- fix: resolve React key warnings [kreafox - [`aa5d176`](https://github.com/eea/volto-cca-policy/commit/aa5d176006ddbfd172d78497c13934f6679e2ea0)]
|
|
86
|
+
- fix: resolve React key warnings [kreafox - [`7f90769`](https://github.com/eea/volto-cca-policy/commit/7f90769f56189ce7a9b8592d2faf73864b0d9a76)]
|
|
87
|
+
- fix: remove volto 17 testing from Jenkinsfile [kreafox - [`f239097`](https://github.com/eea/volto-cca-policy/commit/f239097f080abf6cf5eb4bfd69361b4416917e21)]
|
|
88
|
+
|
|
89
|
+
#### :nail_care: Enhancements
|
|
90
|
+
|
|
91
|
+
- refactor: update volto-slate customizations, fix eslint [kreafox - [`42c4c00`](https://github.com/eea/volto-cca-policy/commit/42c4c0096c9cc40037fc856f683c70e3ac202620)]
|
|
92
|
+
- change: update HeaderMenuPopUp.js, fix eslint issue [kreafox - [`2e8fa31`](https://github.com/eea/volto-cca-policy/commit/2e8fa319e7f3e26b17472d18db1acb12292be837)]
|
|
93
|
+
- refactor: constants and imports [kreafox - [`44e6627`](https://github.com/eea/volto-cca-policy/commit/44e662780894dff6a01f150923d41a373560195a)]
|
|
94
|
+
- refactor: change files extension from .js to .jsx [kreafox - [`577d8cf`](https://github.com/eea/volto-cca-policy/commit/577d8cf01f4a3024eb92639ff3898c667c266abb)]
|
|
95
|
+
- refactor: move hocs inside hocs folder, update imports [kreafox - [`2284251`](https://github.com/eea/volto-cca-policy/commit/2284251d4dc3438c754747cc041ce39059a1edcc)]
|
|
96
|
+
- refactor: move AST navigation utilities to local definitions [kreafox - [`e2749d6`](https://github.com/eea/volto-cca-policy/commit/e2749d625a259df4af2a37f2287a1778b753adbb)]
|
|
97
|
+
- refactor: update View component to use withOpenLayers [kreafox - [`63f698d`](https://github.com/eea/volto-cca-policy/commit/63f698de1e44c91d4d8e2b9a3b6e0a48167c069d)]
|
|
98
|
+
- refactor: change files extension from .js to .jsx [kreafox - [`939ecd9`](https://github.com/eea/volto-cca-policy/commit/939ecd910b41ec624a69d883882aaebcf642af46)]
|
|
99
|
+
- refactor: update jest-dom import to remove extend-expect usage [kreafox - [`3a9fc09`](https://github.com/eea/volto-cca-policy/commit/3a9fc096f3e345e6dc7a03a774bf6dd486a3e84f)]
|
|
100
|
+
- refactor: replace native img tags with Volto Image component in ImageWidget [kreafox - [`16494d3`](https://github.com/eea/volto-cca-policy/commit/16494d3fe2d855d739f75930855c5d6caa27491f)]
|
|
101
|
+
- refactor: replace native img tags with Volto Image component in ImageWidget [kreafox - [`bce54f7`](https://github.com/eea/volto-cca-policy/commit/bce54f74c7230027a523a8153d17eb1ced6522ed)]
|
|
102
|
+
- refactor: update lodash imports to use individual method paths [kreafox - [`d949f92`](https://github.com/eea/volto-cca-policy/commit/d949f925a8dedcbe7bbb5bd7589bd395275cb242)]
|
|
103
|
+
- refactor: remove barrel imports [kreafox - [`222bb04`](https://github.com/eea/volto-cca-policy/commit/222bb0488631beff2aa5183b63f3f0e6ce4e7327)]
|
|
104
|
+
- refactor: remove barrel imports [kreafox - [`3028ecd`](https://github.com/eea/volto-cca-policy/commit/3028ecd4e9f9be9252a4ad51bf453eaecbd6f4a8)]
|
|
105
|
+
- refactor: remove barrel imports [kreafox - [`1dde57d`](https://github.com/eea/volto-cca-policy/commit/1dde57d21f2cf536c6653b63687d1a560b70fec8)]
|
|
106
|
+
- refactor: remove barrel imports [kreafox - [`da460b8`](https://github.com/eea/volto-cca-policy/commit/da460b80174d01b557ccc727bfd56ae3eb85dc43)]
|
|
107
|
+
- refactor: update ESLint configuration [kreafox - [`a277217`](https://github.com/eea/volto-cca-policy/commit/a27721764461c0073b320897ef5e9d9dc5204721)]
|
|
108
|
+
- refactor: update Jenkinsfile for Volto 18 integration [kreafox - [`9b6013e`](https://github.com/eea/volto-cca-policy/commit/9b6013e0d2c6ddf068f19d536da455f147552c99)]
|
|
109
|
+
|
|
110
|
+
#### :house: Internal changes
|
|
111
|
+
|
|
112
|
+
- chore: bump version to 1.0.0 [kreafox - [`39de87b`](https://github.com/eea/volto-cca-policy/commit/39de87b1b368cbf41fbc77dbb37b07ceb2253baa)]
|
|
113
|
+
- chore: Volto 18 eslint update [kreafox - [`998accc`](https://github.com/eea/volto-cca-policy/commit/998accce812186a91530403e347054adaed147dc)]
|
|
114
|
+
- chore: disable jsx-filename-extension lint rule [kreafox - [`d5a7a70`](https://github.com/eea/volto-cca-policy/commit/d5a7a70315b5d41db4574e365218a9422dd8e614)]
|
|
115
|
+
- style: Automated code fix [eea-jenkins - [`39a1a0f`](https://github.com/eea/volto-cca-policy/commit/39a1a0f4c4dcf242134cc8c940b7632ca87b135d)]
|
|
116
|
+
- style: Automated code fix [eea-jenkins - [`1308bc6`](https://github.com/eea/volto-cca-policy/commit/1308bc6cc13e7c8deedfd23948af8c0deba45f70)]
|
|
117
|
+
|
|
118
|
+
#### :hammer_and_wrench: Others
|
|
119
|
+
|
|
120
|
+
- test: update snapshots [kreafox - [`420d51d`](https://github.com/eea/volto-cca-policy/commit/420d51d1e88323db7295752dc1a184888d3d504e)]
|
|
121
|
+
- test: mock withScrollToTarget in Spotlight.test.jsx [kreafox - [`5fe54fb`](https://github.com/eea/volto-cca-policy/commit/5fe54fb44960bacc9ff0fe1d91bbbeec2bc58e83)]
|
|
122
|
+
- update language import path [iugin - [`1217dcc`](https://github.com/eea/volto-cca-policy/commit/1217dcc9e6aa3971bf30c07bb93203cb73949c23)]
|
|
123
|
+
### [0.3.126](https://github.com/eea/volto-cca-policy/compare/0.3.125...0.3.126) - 26 May 2026
|
|
124
|
+
|
|
125
|
+
#### :bug: Bug Fixes
|
|
126
|
+
|
|
127
|
+
- fix: update warning message in link integrity workflow state change modal [Tiberiu Ichim - [`1244b2e`](https://github.com/eea/volto-cca-policy/commit/1244b2e826590050c6b10506651482cd615b8c92)]
|
|
128
|
+
- fix: resolve workflow state transition failure when confirming via link integrity warning modal [Tiberiu Ichim - [`2fd0d89`](https://github.com/eea/volto-cca-policy/commit/2fd0d899fc421b4944de5488902f4bc35f5102d9)]
|
|
129
|
+
|
|
130
|
+
#### :house: Internal changes
|
|
131
|
+
|
|
132
|
+
- style: Automated code fix [eea-jenkins - [`1e4caaf`](https://github.com/eea/volto-cca-policy/commit/1e4caafffd7b026c565887d6ace3c7ec87866bfe)]
|
|
133
|
+
|
|
134
|
+
#### :house: Documentation changes
|
|
135
|
+
|
|
136
|
+
- docs: convert index.md absolute links to clean relative links [Tiberiu Ichim - [`bfb2d6a`](https://github.com/eea/volto-cca-policy/commit/bfb2d6a6c592991c4f65875c8db5f9b55205bf4d)]
|
|
137
|
+
- docs: reorganize link integrity workflow artifacts, adding README specification and index overview [Tiberiu Ichim - [`1208c96`](https://github.com/eea/volto-cca-policy/commit/1208c9619ff4097a4d954e355895382978b326dc)]
|
|
138
|
+
- docs: add specification for link integrity check during workflow transitions [Tiberiu Ichim - [`842da3d`](https://github.com/eea/volto-cca-policy/commit/842da3d371f0c5c38a538e3d519bc5eb79705e34)]
|
|
139
|
+
|
|
7
140
|
### [0.3.125](https://github.com/eea/volto-cca-policy/compare/0.3.124...0.3.125) - 18 May 2026
|
|
8
141
|
|
|
9
142
|
#### :rocket: New Features
|
|
@@ -354,6 +487,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
354
487
|
|
|
355
488
|
#### :house: Internal changes
|
|
356
489
|
|
|
490
|
+
- chore: [JENKINSFILE] add package version in sonarqube [valentinab25 - [`e901251`](https://github.com/eea/volto-cca-policy/commit/e901251592eb54609fbc7eb8fcf7bd452c2da9cd)]
|
|
357
491
|
|
|
358
492
|
### [0.3.102](https://github.com/eea/volto-cca-policy/compare/0.3.101...0.3.102) - 24 February 2026
|
|
359
493
|
|
|
@@ -363,6 +497,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
363
497
|
|
|
364
498
|
#### :house: Internal changes
|
|
365
499
|
|
|
500
|
+
- chore: [JENKINSFILE] use sonarqube branches [EEA Jenkins - [`8b3699a`](https://github.com/eea/volto-cca-policy/commit/8b3699a6cbaef662b5e80884ac2c1f7dc9c6591e)]
|
|
366
501
|
|
|
367
502
|
### [0.3.101](https://github.com/eea/volto-cca-policy/compare/0.3.100...0.3.101) - 28 January 2026
|
|
368
503
|
|
|
@@ -650,6 +785,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
650
785
|
- style: fix item spacing [kreafox - [`7d4535d`](https://github.com/eea/volto-cca-policy/commit/7d4535dbc486e6cb80fc55d6ac8c7c01d9cf48af)]
|
|
651
786
|
- chore: code cleanup [kreafox - [`842419b`](https://github.com/eea/volto-cca-policy/commit/842419b1bce3dc624755c81c9dea672198cab9e2)]
|
|
652
787
|
- style: update teaser block styling [kreafox - [`1e0cad8`](https://github.com/eea/volto-cca-policy/commit/1e0cad8e1ed3ae827ee868dce8ad50b292a937ba)]
|
|
788
|
+
- chore: update Makefile, run yarn i18n [kreafox - [`61e6962`](https://github.com/eea/volto-cca-policy/commit/61e6962901068ae6512265417a730bd9befd65fe)]
|
|
653
789
|
- chore: move styling to theme folder [kreafox - [`8cf6a1b`](https://github.com/eea/volto-cca-policy/commit/8cf6a1b8b14abf472a9c61b28db574f6d9e0bd3b)]
|
|
654
790
|
- chore: remove ArrayWidget customization [kreafox - [`249bf93`](https://github.com/eea/volto-cca-policy/commit/249bf93054f7726c3d57a8b8ca01b75cd0d30522)]
|
|
655
791
|
- chore: remove Footer customization [kreafox - [`7038af3`](https://github.com/eea/volto-cca-policy/commit/7038af37d48a328dfc31746f3fa84973e2f840ab)]
|
|
@@ -3412,10 +3548,13 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
3412
3548
|
- Refs #260715 rast-block wip [Tripon Eugen - [`f19d54e`](https://github.com/eea/volto-cca-policy/commit/f19d54e0b9a6a86bf344eb85b6a1cda7f3de91bf)]
|
|
3413
3549
|
- Refs #260715 rast-block wip [Tripon Eugen - [`2828537`](https://github.com/eea/volto-cca-policy/commit/2828537b6c084cd1a82162d552fb4ef025b71f9f)]
|
|
3414
3550
|
- Refs #260715 rast-block updates [Tripon Eugen - [`1e803e5`](https://github.com/eea/volto-cca-policy/commit/1e803e5bd3d3fb7558f261c76c68866be7beb8b5)]
|
|
3551
|
+
- test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`0a15e1b`](https://github.com/eea/volto-cca-policy/commit/0a15e1b2ad081233685e80d5b3c60a8663f6b896)]
|
|
3552
|
+
- test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`9554e44`](https://github.com/eea/volto-cca-policy/commit/9554e44c92a621a52b2adb5a4830fb084ee5734b)]
|
|
3415
3553
|
### [0.1.49](https://github.com/eea/volto-cca-policy/compare/0.1.48...0.1.49) - 15 November 2023
|
|
3416
3554
|
|
|
3417
3555
|
#### :house: Internal changes
|
|
3418
3556
|
|
|
3557
|
+
- chore: [JENKINS] Refactor automated testing [valentinab25 - [`7b820a6`](https://github.com/eea/volto-cca-policy/commit/7b820a6369c2ddd5203b1a4abe352cb4bb43db7a)]
|
|
3419
3558
|
- chore: husky, lint-staged use fixed versions [valentinab25 - [`f0a8061`](https://github.com/eea/volto-cca-policy/commit/f0a8061c275c236deb00087c23fac9860a073106)]
|
|
3420
3559
|
|
|
3421
3560
|
#### :hammer_and_wrench: Others
|
|
@@ -3432,6 +3571,9 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
3432
3571
|
- Refs #259267 - jenkins test [Tripon Eugen - [`cacd31e`](https://github.com/eea/volto-cca-policy/commit/cacd31e7b1afe0983674ed5c7632d2e1d7fa752e)]
|
|
3433
3572
|
- Refs #259267 - jenkins [Tripon Eugen - [`5b3affe`](https://github.com/eea/volto-cca-policy/commit/5b3affee8401239de10097884c1b7f2349d15ec0)]
|
|
3434
3573
|
- Refs #259267 - add When, lead image and title to files [Tripon Eugen - [`2cedb23`](https://github.com/eea/volto-cca-policy/commit/2cedb237f898af9057e13fba94b615ef71077204)]
|
|
3574
|
+
- test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`4d607a5`](https://github.com/eea/volto-cca-policy/commit/4d607a576e9d0a5c34e48c41b409e7df616ee3d6)]
|
|
3575
|
+
- test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`b7f74d5`](https://github.com/eea/volto-cca-policy/commit/b7f74d53513a6edbfbca5cb6d19687929bb1e5db)]
|
|
3576
|
+
- test: [JENKINS] Improve cypress time [valentinab25 - [`db65617`](https://github.com/eea/volto-cca-policy/commit/db656173391f65157098d95d388c25f6429753d8)]
|
|
3435
3577
|
- Refs #259267 - cca event blocks attachments and check not mandatoty fields [Tripon Eugen - [`3138e5a`](https://github.com/eea/volto-cca-policy/commit/3138e5afb5bfbdbed14e27ed457b16867b7fa414)]
|
|
3436
3578
|
- Refs #256681 - Fix error in CCA Event view menu. ([React Intl] An id must be provided to format a message.) [GhitaB - [`517eeb8`](https://github.com/eea/volto-cca-policy/commit/517eeb817264a47bbfd6b9b7d22aaf22d44ed224)]
|
|
3437
3579
|
- Refs #161485 - Fix ECDE name conflict. [GhitaB - [`8bfd99f`](https://github.com/eea/volto-cca-policy/commit/8bfd99ff68bb82a04d1c0ed625fa514fcf46289e)]
|
|
@@ -3648,6 +3790,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
3648
3790
|
|
|
3649
3791
|
#### :house: Internal changes
|
|
3650
3792
|
|
|
3793
|
+
- chore: [JENKINS] Remove alpha testing version [valentinab25 - [`ad1ced0`](https://github.com/eea/volto-cca-policy/commit/ad1ced0971ba116c13a3b5fcc039172cc915c919)]
|
|
3651
3794
|
|
|
3652
3795
|
#### :hammer_and_wrench: Others
|
|
3653
3796
|
|
|
@@ -4128,6 +4271,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
4128
4271
|
#### :hammer_and_wrench: Others
|
|
4129
4272
|
|
|
4130
4273
|
- Refs #158294 - Update supported languages list. [GhitaB - [`0a4f91f`](https://github.com/eea/volto-cca-policy/commit/0a4f91f39b7edc367bd4c127d6a8f273c7788361)]
|
|
4274
|
+
- Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`8f1f9ce`](https://github.com/eea/volto-cca-policy/commit/8f1f9ce6c22805670cc0800d3c779b6d619d0f31)]
|
|
4131
4275
|
### [0.1.1](https://github.com/eea/volto-cca-policy/compare/0.1.0...0.1.1) - 13 December 2022
|
|
4132
4276
|
|
|
4133
4277
|
#### :hammer_and_wrench: Others
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Link Integrity Workflow warning Specification
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
To prevent breaking the browsing experience of public (anonymous) website visitors, Climate-ADAPT intercepts workflow transitions that limit content visibility (such as changing a state to **Private**, **Reject**, or **Retract**).
|
|
6
|
+
|
|
7
|
+
Before finalizing these transitions, the system performs an asynchronous backend check using the Plone link integrity relation catalog (`@linkintegrity`) to discover if any other published pages link to the target item. If referencing items are found, the user is presented with a warning modal detailing the pages that link to the item, allowing them to either cancel or proceed anyway.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Architectural Workflow
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
sequenceDiagram
|
|
15
|
+
autonumber
|
|
16
|
+
actor Editor
|
|
17
|
+
participant WorkflowDropdown as Workflow Dropdown (Workflow.jsx)
|
|
18
|
+
participant API as Plone REST API (/@linkintegrity)
|
|
19
|
+
participant WarningModal as Warning Modal (WorkflowLinkIntegrityModal.jsx)
|
|
20
|
+
|
|
21
|
+
Editor->>WorkflowDropdown: Select "Make Private" / "Reject" / "Retract"
|
|
22
|
+
WorkflowDropdown->>API: Dispatch linkIntegrityCheck([UID])
|
|
23
|
+
WorkflowDropdown->>WarningModal: Open Warning Modal (with Loader active)
|
|
24
|
+
Note over WarningModal: Action buttons are disabled during check
|
|
25
|
+
|
|
26
|
+
alt No breaches exist
|
|
27
|
+
API-->>WorkflowDropdown: Return 0 breaches
|
|
28
|
+
WorkflowDropdown->>WorkflowDropdown: Auto-execute workflow transition
|
|
29
|
+
WorkflowDropdown->>WarningModal: Close Modal automatically
|
|
30
|
+
WorkflowDropdown-->>Editor: Show success toast
|
|
31
|
+
else Breaches exist
|
|
32
|
+
API-->>WorkflowDropdown: Return breach details
|
|
33
|
+
WorkflowDropdown->>WarningModal: Deactivate Loader & enable confirm
|
|
34
|
+
WarningModal-->>Editor: Render list of linking pages & warning copy
|
|
35
|
+
|
|
36
|
+
alt Editor clicks "Cancel"
|
|
37
|
+
Editor->>WarningModal: Click "Cancel"
|
|
38
|
+
WarningModal->>WorkflowDropdown: Reset pending transition & close modal
|
|
39
|
+
else Editor clicks "Change state anyway"
|
|
40
|
+
Editor->>WarningModal: Click "Change state anyway"
|
|
41
|
+
WarningModal->>WorkflowDropdown: Trigger onOk() -> executeTransition()
|
|
42
|
+
WorkflowDropdown->>WorkflowDropdown: Execute workflow transition
|
|
43
|
+
WorkflowDropdown->>WarningModal: Close Modal
|
|
44
|
+
WorkflowDropdown-->>Editor: Show success toast
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Implementation Details
|
|
52
|
+
|
|
53
|
+
### 1. Workflow Interception (Customization)
|
|
54
|
+
* **Path**: [Workflow.jsx](file:///home/tibi/work/eea.docker.plone-climateadapt/cca/frontend/src/addons/volto-cca-policy/src/customizations/volto/components/manage/Workflow/Workflow.jsx)
|
|
55
|
+
* **Role**: Shadows Volto core's workflow select component. Intercepts transitions containing state keys (`private`, `reject`, `retract`) or URL suffixes (`/reject`, `/retract`). Dispatches `linkIntegrityCheck` and manages `pendingOption` state. Executes transition automatically if 0 breaches are found.
|
|
56
|
+
|
|
57
|
+
### 2. Warning Modal Component
|
|
58
|
+
* **Path**: [WorkflowLinkIntegrityModal.jsx](file:///home/tibi/work/eea.docker.plone-climateadapt/cca/frontend/src/addons/volto-cca-policy/src/components/manage/Workflow/WorkflowLinkIntegrityModal.jsx)
|
|
59
|
+
* **Role**: A plain HTML overlay dialog rendered via `ReactDOM.createPortal` into a `<div>` appended to `document.body`. Zero `semantic-ui-react` dependencies — no `Confirm`, `Modal`, or `Portal`.
|
|
60
|
+
* **Why not `semantic-ui-react`?** The `Confirm` and `Modal` components use internal Portals, auto-controlled state, and shorthand factory systems that made click handlers unreliable in the toolbar dropdown context. The Toolbar's global `document mousedown` handler (`handleClickOutside`) would intercept clicks, close the menu, and unmount the modal before `onConfirm` could fire.
|
|
61
|
+
* **Key implementation details**:
|
|
62
|
+
* **Portal rendering** — renders at `document.body` level with `z-index: 10000`, placing it outside the toolbar dropdown's DOM subtree and CSS stacking context so it appears as a proper full-page overlay.
|
|
63
|
+
* **Capture-phase `mousedown` guard** — a `capture=true` listener on the portal root calls `e.stopPropagation()`, preventing the Toolbar's `handleClickOutside` from firing while the modal is open.
|
|
64
|
+
* **Synchronous breach derivation** — `computeBreaches()` computes `brokenReferences` and `breaches` during render (no `useEffect` + `useState`), so the data is always in sync with `loading` in the same render cycle. This prevents a race condition where `loading` becomes `false` but `brokenReferences` is still `0`, causing premature modal closure.
|
|
65
|
+
* **Inline styles** — all CSS is embedded via a `<style>` tag, no external stylesheet dependency.
|
|
66
|
+
* **Key UX Features**:
|
|
67
|
+
* Maintains button state `disabled: loading` during ongoing checks to prevent premature actions.
|
|
68
|
+
* Renders a CSS spinner and loading text during the check.
|
|
69
|
+
* Displays the exact list of referencing (source) items and target sub-items.
|
|
70
|
+
* Displays the warning copy:
|
|
71
|
+
> *"By changing the state, we're not breaking references, but may break user experience for final Anonymous users. There are {brokenReferences} {variation} to this item:"*
|
|
72
|
+
* Closes on backdrop click, button click, or `Escape` key.
|
|
73
|
+
|
|
74
|
+
### 3. Unit Verification Suite
|
|
75
|
+
* **Path**: [WorkflowLinkIntegrityModal.test.jsx](file:///home/tibi/work/eea.docker.plone-climateadapt/cca/frontend/src/addons/volto-cca-policy/src/components/manage/Workflow/WorkflowLinkIntegrityModal.test.jsx)
|
|
76
|
+
* **Role**: Houses Jest/React Testing Library assertions verifying loading indicator visibility, auto-proceed behavior with 0 breaches, warnings list aggregation for multiple breaches, and confirm button presence.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Link Integrity & Workflow Documentation Index
|
|
2
|
+
|
|
3
|
+
This directory houses the research, analysis, and specifications for Plone/Volto Link Integrity tracking and the "Warn Before Private" workflow state transition verification feature.
|
|
4
|
+
|
|
5
|
+
Below is an overview of the role and purpose of each document in this directory:
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📖 Document Catalog
|
|
10
|
+
|
|
11
|
+
### 1. [README.md](./README.md)
|
|
12
|
+
* **Role**: **Feature Specification & Technical Implementation Guide**
|
|
13
|
+
* **Description**: High-level specification outlining the "Warn before private" workflow transition warning system. It explains how workflow transitions to private or retracted states are intercepted to check for breaches, contains a Mermaid sequence diagram of the operational flow, and details pointers to the exact implementation files (`Workflow.jsx`, `WorkflowLinkIntegrityModal.jsx`, and the unit test suite).
|
|
14
|
+
|
|
15
|
+
### 2. [understanding-link-integrity.md](./understanding-link-integrity.md)
|
|
16
|
+
* **Role**: **Initial Research & Mechanics Overview**
|
|
17
|
+
* **Description**: Explains the underlying mechanics of Plone's `plone.app.linkintegrity` package, the `@linkintegrity` and `@relations` REST API endpoints, how internal references are stored in the `zc.relation` catalog using `isReferencing`, and proposes the initial architectural solution for shadowing the Volto toolbar component.
|
|
18
|
+
|
|
19
|
+
### 3. [volto-block-link-discovery.md](./volto-block-link-discovery.md)
|
|
20
|
+
* **Role**: **Block Parser Link Extraction Specs**
|
|
21
|
+
* **Description**: Detailed specifications on how the Plone backend's block-to-HTML parser (via `plone.volto`) parses internal links and retrieves referencing UIDs from complex Volto blocks (e.g. Columns, Teasers, Maps) to keep the relation catalog accurately indexed.
|
|
22
|
+
|
|
23
|
+
### 4. [volto-block-link-analysis.md](./volto-block-link-analysis.md)
|
|
24
|
+
* **Role**: **Technical Analysis of Internal Linking**
|
|
25
|
+
* **Description**: Analyzes how internal links are serialized, stored, and resolved within customized layouts. Explains matching strategies for Dexterity schemas and Choice relation fields.
|
|
26
|
+
|
|
27
|
+
### 5. [link-integrity-blocks-report.md](./link-integrity-blocks-report.md)
|
|
28
|
+
* **Role**: **Volto Blocks Reference Index**
|
|
29
|
+
* **Description**: A quick-reference status report listing the Volto blocks whose internal link fields are covered by link integrity tracking and validation rules.
|
|
30
|
+
|
|
31
|
+
### 6. [link-integrity-block-fields-report.md](./link-integrity-block-fields-report.md)
|
|
32
|
+
* **Role**: **Field Mapping Specification**
|
|
33
|
+
* **Description**: A comprehensive deep-dive report mapping exactly which fields and properties within the custom blocks schemas are indexed and tracked by the link integrity processor.
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
2
3
|
import PropTypes from 'prop-types';
|
|
3
4
|
import { useSelector } from 'react-redux';
|
|
4
5
|
import { Link } from 'react-router-dom';
|
|
5
6
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
|
6
7
|
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
7
|
-
import { Confirm, Dimmer, Loader, Table } from 'semantic-ui-react';
|
|
8
8
|
|
|
9
9
|
const messages = defineMessages({
|
|
10
10
|
confirmHeader: {
|
|
@@ -29,138 +29,237 @@ const messages = defineMessages({
|
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Derive breach data synchronously from linkintegrityInfo.
|
|
34
|
+
* No useEffect + useState — computed during render so it is always
|
|
35
|
+
* in sync with the loading flag in the same render cycle.
|
|
36
|
+
*/
|
|
37
|
+
function computeBreaches(linkintegrityInfo) {
|
|
38
|
+
if (!linkintegrityInfo) {
|
|
39
|
+
return { brokenReferences: 0, breaches: [] };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const all = linkintegrityInfo.flatMap((result) =>
|
|
43
|
+
result.breaches.map((source) => ({ source, target: result })),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const sourceByUid = new Map();
|
|
47
|
+
const bySource = new Map();
|
|
48
|
+
|
|
49
|
+
for (const entry of all) {
|
|
50
|
+
sourceByUid.set(entry.source.uid, entry.source);
|
|
51
|
+
if (!bySource.has(entry.source.uid)) {
|
|
52
|
+
bySource.set(entry.source.uid, new Set());
|
|
53
|
+
}
|
|
54
|
+
bySource.get(entry.source.uid).add(entry.target);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
brokenReferences: bySource.size,
|
|
59
|
+
breaches: Array.from(bySource, ([uid, targets]) => ({
|
|
60
|
+
source: sourceByUid.get(uid),
|
|
61
|
+
targets: Array.from(targets),
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Plain HTML overlay dialog — no semantic-ui-react, no Portal,
|
|
68
|
+
* no Confirm, no Modal. Just a fixed-position div with inline styles.
|
|
69
|
+
*/
|
|
32
70
|
const WorkflowLinkIntegrityModal = (props) => {
|
|
33
71
|
const { open, onCancel, onOk } = props;
|
|
34
72
|
const intl = useIntl();
|
|
35
73
|
const linkintegrityInfo = useSelector((state) => state.linkIntegrity?.result);
|
|
36
74
|
const loading = useSelector((state) => state.linkIntegrity?.loading);
|
|
37
75
|
|
|
38
|
-
const
|
|
39
|
-
|
|
76
|
+
const { brokenReferences, breaches } = computeBreaches(linkintegrityInfo);
|
|
77
|
+
|
|
78
|
+
// Keep visible while loading OR while breaches exist.
|
|
79
|
+
// Because brokenReferences is derived synchronously, it is always
|
|
80
|
+
// consistent with `loading` in the same render.
|
|
81
|
+
const show = open && (loading || brokenReferences > 0);
|
|
82
|
+
|
|
83
|
+
// Create a dedicated mount container attached to document.body so the
|
|
84
|
+
// modal renders outside the toolbar dropdown's stacking context.
|
|
85
|
+
// Initialized synchronously (not in useEffect) so it is available on
|
|
86
|
+
// the first render — important for tests and to avoid a flicker.
|
|
87
|
+
const containerRef = useRef(
|
|
88
|
+
(() => {
|
|
89
|
+
const el = document.createElement('div');
|
|
90
|
+
document.body.appendChild(el);
|
|
91
|
+
return el;
|
|
92
|
+
})(),
|
|
93
|
+
);
|
|
40
94
|
|
|
41
95
|
useEffect(() => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
96
|
+
const container = containerRef.current;
|
|
97
|
+
return () => {
|
|
98
|
+
if (container && container.parentNode) {
|
|
99
|
+
container.parentNode.removeChild(container);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
// Close on Escape key
|
|
105
|
+
const handleKeyDown = useCallback(
|
|
106
|
+
(e) => {
|
|
107
|
+
if (e.key === 'Escape') {
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
e.stopPropagation();
|
|
110
|
+
onCancel();
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
[onCancel],
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// Prevent the Toolbar's global `document mousedown` handler from closing
|
|
117
|
+
// the toolbar menu while our modal is open. The Toolbar listens on
|
|
118
|
+
// `document` for `mousedown` and calls `closeMenu()` if the click is
|
|
119
|
+
// outside the toolbar pusher. By adding a capture-phase listener on our
|
|
120
|
+
// portal root, we intercept the event before it bubbles to `document`.
|
|
121
|
+
const handleMousedown = useCallback((e) => {
|
|
122
|
+
e.stopPropagation();
|
|
123
|
+
}, []);
|
|
124
|
+
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (show) {
|
|
127
|
+
const container = containerRef.current;
|
|
128
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
129
|
+
// capture=true: fires before any bubbling listeners on ancestors
|
|
130
|
+
container.addEventListener('mousedown', handleMousedown, true);
|
|
131
|
+
return () => {
|
|
132
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
133
|
+
container.removeEventListener('mousedown', handleMousedown, true);
|
|
134
|
+
};
|
|
71
135
|
}
|
|
72
|
-
}, [
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
136
|
+
}, [show, handleKeyDown, handleMousedown]);
|
|
137
|
+
|
|
138
|
+
if (!show) return null;
|
|
139
|
+
|
|
140
|
+
return createPortal(
|
|
141
|
+
<>
|
|
142
|
+
<div
|
|
143
|
+
className="li-modal-backdrop"
|
|
144
|
+
role="presentation"
|
|
145
|
+
tabIndex={-1}
|
|
146
|
+
onClick={(e) => {
|
|
147
|
+
// Only cancel when clicking the backdrop itself, not children
|
|
148
|
+
if (e.target === e.currentTarget) {
|
|
149
|
+
onCancel();
|
|
150
|
+
}
|
|
151
|
+
}}
|
|
152
|
+
onKeyDown={(e) => {
|
|
153
|
+
if (e.key === 'Escape') {
|
|
154
|
+
e.preventDefault();
|
|
155
|
+
e.stopPropagation();
|
|
156
|
+
onCancel();
|
|
157
|
+
}
|
|
158
|
+
}}
|
|
159
|
+
data-testid="li-modal-backdrop"
|
|
160
|
+
>
|
|
161
|
+
<div
|
|
162
|
+
className="li-modal-dialog"
|
|
163
|
+
role="dialog"
|
|
164
|
+
aria-modal="true"
|
|
165
|
+
aria-labelledby="li-modal-title"
|
|
166
|
+
data-testid="li-modal-dialog"
|
|
167
|
+
>
|
|
168
|
+
<div className="li-modal-header">
|
|
169
|
+
<span className="li-modal-title" id="li-modal-title">
|
|
170
|
+
{intl.formatMessage(messages.confirmHeader)}
|
|
171
|
+
</span>
|
|
88
172
|
</div>
|
|
89
|
-
}
|
|
90
|
-
onCancel={onCancel}
|
|
91
|
-
onConfirm={() => {}}
|
|
92
|
-
/>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
173
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
174
|
+
<div className="li-modal-content">
|
|
175
|
+
{loading && (
|
|
176
|
+
<div className="li-modal-loading">
|
|
177
|
+
<div className="li-spinner" />
|
|
178
|
+
<span>{intl.formatMessage(messages.loading)}</span>
|
|
179
|
+
</div>
|
|
180
|
+
)}
|
|
181
|
+
|
|
182
|
+
{!loading && brokenReferences > 0 && (
|
|
183
|
+
<>
|
|
184
|
+
<p>
|
|
185
|
+
<FormattedMessage
|
|
186
|
+
id="By changing the state, we're not breaking references, but may break user experience for final Anonymous users. There are {brokenReferences} {variation} to this item:"
|
|
187
|
+
defaultMessage="By changing the state, we're not breaking references, but may break user experience for final Anonymous users. There are {brokenReferences} {variation} to this item:"
|
|
188
|
+
values={{
|
|
189
|
+
brokenReferences: <strong>{brokenReferences}</strong>,
|
|
190
|
+
variation:
|
|
191
|
+
brokenReferences === 1 ? (
|
|
192
|
+
<FormattedMessage
|
|
193
|
+
id="reference"
|
|
194
|
+
defaultMessage="reference"
|
|
195
|
+
/>
|
|
196
|
+
) : (
|
|
197
|
+
<FormattedMessage
|
|
198
|
+
id="references"
|
|
199
|
+
defaultMessage="references"
|
|
200
|
+
/>
|
|
201
|
+
),
|
|
202
|
+
}}
|
|
203
|
+
/>
|
|
204
|
+
</p>
|
|
205
|
+
<BrokenLinksList intl={intl} breaches={breaches} />
|
|
206
|
+
</>
|
|
207
|
+
)}
|
|
129
208
|
</div>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
209
|
+
|
|
210
|
+
<div className="li-modal-actions">
|
|
211
|
+
<button
|
|
212
|
+
className="li-btn li-btn-secondary"
|
|
213
|
+
onClick={onCancel}
|
|
214
|
+
disabled={loading}
|
|
215
|
+
data-testid="li-btn-cancel"
|
|
216
|
+
>
|
|
217
|
+
{intl.formatMessage(messages.cancel)}
|
|
218
|
+
</button>
|
|
219
|
+
<button
|
|
220
|
+
className="li-btn li-btn-primary"
|
|
221
|
+
onClick={onOk}
|
|
222
|
+
disabled={loading}
|
|
223
|
+
data-testid="li-btn-confirm"
|
|
224
|
+
>
|
|
225
|
+
{intl.formatMessage(messages.confirmAction)}
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
<style>{modalStyles}</style>
|
|
231
|
+
</>,
|
|
232
|
+
containerRef.current,
|
|
136
233
|
);
|
|
137
234
|
};
|
|
138
235
|
|
|
139
236
|
const BrokenLinksList = ({ intl, breaches }) => {
|
|
140
237
|
return (
|
|
141
|
-
<div className="broken-links-list"
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
238
|
+
<div className="li-broken-links-list">
|
|
239
|
+
<p>
|
|
240
|
+
<FormattedMessage
|
|
241
|
+
id="These items will have broken links"
|
|
242
|
+
defaultMessage="These items will have broken links"
|
|
243
|
+
/>
|
|
244
|
+
:
|
|
245
|
+
</p>
|
|
246
|
+
<table className="li-breach-table">
|
|
247
|
+
<tbody>
|
|
149
248
|
{breaches.map((breach) => (
|
|
150
|
-
<
|
|
151
|
-
<
|
|
249
|
+
<tr key={breach.source['@id']}>
|
|
250
|
+
<td className="li-breach-source">
|
|
152
251
|
<Link
|
|
153
252
|
to={flattenToAppURL(breach.source['@id'])}
|
|
154
253
|
title={intl.formatMessage(messages.navigate_to_this_item)}
|
|
155
254
|
>
|
|
156
255
|
{breach.source.title}
|
|
157
256
|
</Link>
|
|
158
|
-
</
|
|
159
|
-
<
|
|
257
|
+
</td>
|
|
258
|
+
<td className="li-breach-label">
|
|
160
259
|
<FormattedMessage id="refers to" defaultMessage="refers to" />:
|
|
161
|
-
</
|
|
162
|
-
<
|
|
163
|
-
<ul
|
|
260
|
+
</td>
|
|
261
|
+
<td className="li-breach-targets">
|
|
262
|
+
<ul>
|
|
164
263
|
{breach.targets.map((target) => (
|
|
165
264
|
<li key={target['@id']}>
|
|
166
265
|
<Link
|
|
@@ -174,11 +273,11 @@ const BrokenLinksList = ({ intl, breaches }) => {
|
|
|
174
273
|
</li>
|
|
175
274
|
))}
|
|
176
275
|
</ul>
|
|
177
|
-
</
|
|
178
|
-
</
|
|
276
|
+
</td>
|
|
277
|
+
</tr>
|
|
179
278
|
))}
|
|
180
|
-
</
|
|
181
|
-
</
|
|
279
|
+
</tbody>
|
|
280
|
+
</table>
|
|
182
281
|
</div>
|
|
183
282
|
);
|
|
184
283
|
};
|
|
@@ -190,3 +289,155 @@ WorkflowLinkIntegrityModal.propTypes = {
|
|
|
190
289
|
};
|
|
191
290
|
|
|
192
291
|
export default WorkflowLinkIntegrityModal;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Minimal inline styles — no external CSS dependency.
|
|
295
|
+
* Matches Volto's general look (white dialog, centred, dark backdrop).
|
|
296
|
+
*/
|
|
297
|
+
const modalStyles = `
|
|
298
|
+
.li-modal-backdrop {
|
|
299
|
+
position: fixed;
|
|
300
|
+
inset: 0;
|
|
301
|
+
z-index: 10000;
|
|
302
|
+
display: flex;
|
|
303
|
+
align-items: center;
|
|
304
|
+
justify-content: center;
|
|
305
|
+
background: rgba(0, 0, 0, 0.6);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.li-modal-dialog {
|
|
309
|
+
background: #fff;
|
|
310
|
+
border-radius: 8px;
|
|
311
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
|
312
|
+
max-width: 600px;
|
|
313
|
+
width: 90%;
|
|
314
|
+
max-height: 80vh;
|
|
315
|
+
overflow-y: auto;
|
|
316
|
+
display: flex;
|
|
317
|
+
flex-direction: column;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.li-modal-header {
|
|
321
|
+
padding: 16px 20px;
|
|
322
|
+
border-bottom: 1px solid #e0e0e0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.li-modal-title {
|
|
326
|
+
font-size: 18px;
|
|
327
|
+
font-weight: 600;
|
|
328
|
+
color: #333;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.li-modal-content {
|
|
332
|
+
padding: 20px;
|
|
333
|
+
min-height: 80px;
|
|
334
|
+
color: #4a4a4a;
|
|
335
|
+
font-size: 14px;
|
|
336
|
+
line-height: 1.5;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.li-modal-loading {
|
|
340
|
+
display: flex;
|
|
341
|
+
align-items: center;
|
|
342
|
+
gap: 12px;
|
|
343
|
+
justify-content: center;
|
|
344
|
+
padding: 20px 0;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.li-spinner {
|
|
348
|
+
width: 24px;
|
|
349
|
+
height: 24px;
|
|
350
|
+
border: 3px solid #e0e0e0;
|
|
351
|
+
border-top-color: #007bc1;
|
|
352
|
+
border-radius: 50%;
|
|
353
|
+
animation: li-spin 0.7s linear infinite;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
@keyframes li-spin {
|
|
357
|
+
to { transform: rotate(360deg); }
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.li-modal-actions {
|
|
361
|
+
display: flex;
|
|
362
|
+
justify-content: flex-end;
|
|
363
|
+
gap: 10px;
|
|
364
|
+
padding: 16px 20px;
|
|
365
|
+
border-top: 1px solid #e0e0e0;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.li-btn {
|
|
369
|
+
padding: 8px 18px;
|
|
370
|
+
border-radius: 4px;
|
|
371
|
+
font-size: 14px;
|
|
372
|
+
cursor: pointer;
|
|
373
|
+
border: 1px solid transparent;
|
|
374
|
+
transition: background 0.15s, border-color 0.15s;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.li-btn:disabled {
|
|
378
|
+
opacity: 0.5;
|
|
379
|
+
cursor: not-allowed;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.li-btn-secondary {
|
|
383
|
+
background: #f5f5f5;
|
|
384
|
+
border-color: #d0d0d0;
|
|
385
|
+
color: #333;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.li-btn-secondary:hover:not(:disabled) {
|
|
389
|
+
background: #ebebeb;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.li-btn-primary {
|
|
393
|
+
background: #007bc1;
|
|
394
|
+
color: #fff;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.li-btn-primary:hover:not(:disabled) {
|
|
398
|
+
background: #005a89;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.li-broken-links-list {
|
|
402
|
+
margin-top: 16px;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.li-breach-table {
|
|
406
|
+
width: 100%;
|
|
407
|
+
border-collapse: collapse;
|
|
408
|
+
font-size: 13px;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.li-breach-table td {
|
|
412
|
+
padding: 6px 8px;
|
|
413
|
+
vertical-align: top;
|
|
414
|
+
border-bottom: 1px solid #eee;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.li-breach-label {
|
|
418
|
+
white-space: nowrap;
|
|
419
|
+
padding-left: 12px;
|
|
420
|
+
color: #888;
|
|
421
|
+
width: 1px;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.li-breach-targets ul {
|
|
425
|
+
margin: 0;
|
|
426
|
+
padding-left: 18px;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.li-breach-targets li {
|
|
430
|
+
margin-bottom: 2px;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.li-breach-source a,
|
|
434
|
+
.li-breach-targets a {
|
|
435
|
+
color: #007bc1;
|
|
436
|
+
text-decoration: none;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.li-breach-source a:hover,
|
|
440
|
+
.li-breach-targets a:hover {
|
|
441
|
+
text-decoration: underline;
|
|
442
|
+
}
|
|
443
|
+
`;
|
|
@@ -55,7 +55,7 @@ describe('WorkflowLinkIntegrityModal', () => {
|
|
|
55
55
|
expect(screen.getByText('Checking references...')).toBeInTheDocument();
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
it('
|
|
58
|
+
it('renders nothing when no breaches are found (auto-proceed handled by parent)', () => {
|
|
59
59
|
const store = makeStore({
|
|
60
60
|
result: [{ breaches: [], '@id': 'http://localhost:8080/Plone/target' }],
|
|
61
61
|
loaded: true,
|
|
@@ -68,11 +68,10 @@ describe('WorkflowLinkIntegrityModal', () => {
|
|
|
68
68
|
/>,
|
|
69
69
|
store,
|
|
70
70
|
);
|
|
71
|
-
// brokenReferences === 0 so the Confirm dialog is not rendered
|
|
72
71
|
expect(container.innerHTML).toBe('');
|
|
73
72
|
});
|
|
74
73
|
|
|
75
|
-
it('shows warning
|
|
74
|
+
it('shows warning dialog with breach list when breaches are found', () => {
|
|
76
75
|
const store = makeStore({
|
|
77
76
|
result: [
|
|
78
77
|
{
|
|
@@ -141,7 +140,6 @@ describe('WorkflowLinkIntegrityModal', () => {
|
|
|
141
140
|
/>,
|
|
142
141
|
store,
|
|
143
142
|
);
|
|
144
|
-
// Both breaches come from the same source, so brokenReferences === 1
|
|
145
143
|
expect(screen.getByText('Source Page')).toBeInTheDocument();
|
|
146
144
|
expect(screen.getByText('Target 1')).toBeInTheDocument();
|
|
147
145
|
expect(screen.getByText('Target 2')).toBeInTheDocument();
|
|
@@ -12,11 +12,33 @@ By shadowing this component, we can intercept transitions that might hide conten
|
|
|
12
12
|
|
|
13
13
|
1. **Interception Logic**: The `transition` function was modified to check for "private-like" transitions (`private`, `reject`, `retract`).
|
|
14
14
|
2. **Link Integrity Check**: When a sensitive transition is selected, the `linkIntegrityCheck` action is dispatched to the backend.
|
|
15
|
-
3. **State Management**: Added local state (`showWarningModal`, `pendingOption`) to handle the asynchronous check and the confirmation flow.
|
|
15
|
+
3. **State Management**: Added local state (`showWarningModal`, `pendingOption`, `transitionTriggered`) to handle the asynchronous check and the confirmation flow.
|
|
16
16
|
4. **Confirmation Modal**: Integrated `WorkflowLinkIntegrityModal` which displays the list of pages that would have broken links.
|
|
17
|
-
5. **Auto-proceed**: Added an `useEffect` that automatically executes the transition if the link integrity check returns zero breaches.
|
|
17
|
+
5. **Auto-proceed**: Added an `useEffect` that automatically executes the transition if the link integrity check returns zero breaches. It is guarded by `transitionTriggered` to prevent double-execution if the user clicks "Change state anyway" at the same time.
|
|
18
18
|
6. **Activity Indicators**: Added `Dimmer` and `Loader` components from `semantic-ui-react` to provide visual feedback while the link integrity check is loading and during the workflow transition execution.
|
|
19
19
|
|
|
20
|
+
## Design Decisions
|
|
21
|
+
|
|
22
|
+
### Plain HTML dialog via React Portal — no semantic-ui-react
|
|
23
|
+
|
|
24
|
+
The `WorkflowLinkIntegrityModal` renders via `ReactDOM.createPortal` into a `<div>` appended to `document.body`. This places it outside the toolbar dropdown's DOM subtree and CSS stacking context, so it appears as a proper full-page overlay at `z-index: 10000`.
|
|
25
|
+
|
|
26
|
+
No `semantic-ui-react` `Confirm`, `Modal`, or `Portal` is used. Those components rely on Portals, auto-controlled state, and shorthand factory systems that make click handlers unreliable in our use case. The plain HTML approach gives us full, predictable control: `onClick` on a `<button>` always fires.
|
|
27
|
+
|
|
28
|
+
### Toolbar `handleClickOutside` interference
|
|
29
|
+
|
|
30
|
+
Volto's `Toolbar` component registers a global `document.addEventListener('mousedown', ...)` handler that closes the toolbar menu when clicking outside it. Since our modal renders on top of the toolbar menu, any `mousedown` would bubble up to `document` and trigger the menu close — which unmounts the `Workflow` component and our modal before the button `onClick` can fire.
|
|
31
|
+
|
|
32
|
+
The fix: a **capture-phase** `mousedown` listener on the portal root calls `e.stopPropagation()`, preventing the event from ever reaching `document`. This keeps the toolbar menu open while our modal is visible, without interfering with normal `click` event handling on the buttons.
|
|
33
|
+
|
|
34
|
+
### Synchronous breach derivation (no useEffect + local state)
|
|
35
|
+
|
|
36
|
+
The breach data (`brokenReferences`, `breaches`) is computed synchronously inside a `computeBreaches()` helper function rather than via `useEffect` + `useState`. This is critical: the `linkIntegrity` reducer sets `loading: false` and `result: data` in the same action (`_SUCCESS`). If breach data were derived via `useEffect` + local state, there would be a render cycle where `loading` is already `false` but `brokenReferences` is still `0` (stale local state), causing the modal to close prematurely before the breach data is processed.
|
|
37
|
+
|
|
38
|
+
### `transitionTriggered` guard
|
|
39
|
+
|
|
40
|
+
A `transitionTriggered` state flag prevents the auto-proceed `useEffect` from firing after the user has already clicked "Change state anyway", avoiding duplicate workflow transition API calls.
|
|
41
|
+
|
|
20
42
|
## Reference
|
|
21
43
|
|
|
22
44
|
See implementation details in:
|
|
@@ -220,6 +220,7 @@ const Workflow = (props) => {
|
|
|
220
220
|
|
|
221
221
|
const [showWarningModal, setShowWarningModal] = useState(false);
|
|
222
222
|
const [pendingOption, setPendingOption] = useState(null);
|
|
223
|
+
const [transitionTriggered, setTransitionTriggered] = useState(false);
|
|
223
224
|
|
|
224
225
|
useEffect(() => {
|
|
225
226
|
dispatch(getWorkflow(pathname));
|
|
@@ -229,6 +230,7 @@ const Workflow = (props) => {
|
|
|
229
230
|
const executeTransition = useCallback(
|
|
230
231
|
(selectedOption) => {
|
|
231
232
|
if (selectedOption?.url) {
|
|
233
|
+
setTransitionTriggered(true);
|
|
232
234
|
dispatch(transitionWorkflow(flattenToAppURL(selectedOption.url)));
|
|
233
235
|
toast.success(
|
|
234
236
|
<Toast
|
|
@@ -243,7 +245,7 @@ const Workflow = (props) => {
|
|
|
243
245
|
);
|
|
244
246
|
|
|
245
247
|
useEffect(() => {
|
|
246
|
-
if (showWarningModal) {
|
|
248
|
+
if (showWarningModal && !transitionTriggered) {
|
|
247
249
|
if (linkintegrityError) {
|
|
248
250
|
// If the check fails, we shouldn't block the user forever. Proceed with transition.
|
|
249
251
|
executeTransition(pendingOption);
|
|
@@ -269,6 +271,7 @@ const Workflow = (props) => {
|
|
|
269
271
|
linkintegrityError,
|
|
270
272
|
showWarningModal,
|
|
271
273
|
pendingOption,
|
|
274
|
+
transitionTriggered,
|
|
272
275
|
content,
|
|
273
276
|
executeTransition,
|
|
274
277
|
]);
|
|
@@ -281,6 +284,7 @@ const Workflow = (props) => {
|
|
|
281
284
|
|
|
282
285
|
if (isPrivateTransition) {
|
|
283
286
|
setPendingOption(selectedOption);
|
|
287
|
+
setTransitionTriggered(false);
|
|
284
288
|
dispatch(linkIntegrityCheck([content.UID]));
|
|
285
289
|
setShowWarningModal(true);
|
|
286
290
|
} else {
|
|
@@ -341,6 +345,7 @@ const Workflow = (props) => {
|
|
|
341
345
|
onCancel={() => {
|
|
342
346
|
setShowWarningModal(false);
|
|
343
347
|
setPendingOption(null);
|
|
348
|
+
setTransitionTriggered(false);
|
|
344
349
|
}}
|
|
345
350
|
onOk={() => {
|
|
346
351
|
executeTransition(pendingOption);
|
|
File without changes
|
|
File without changes
|