design-comuni-plone-theme 11.28.0 → 11.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.yarn/cache/{volto-feedback-npm-0.6.0-42c860b5c3-49addbf819.zip → volto-feedback-npm-0.6.1-0de05761ad-127b69de40.zip} +0 -0
  2. package/.yarn/install-state.gz +0 -0
  3. package/CHANGELOG.md +45 -0
  4. package/RELEASE.md +29 -0
  5. package/locales/de/LC_MESSAGES/volto.po +1 -2
  6. package/locales/en/LC_MESSAGES/volto.po +1 -2
  7. package/locales/es/LC_MESSAGES/volto.po +1 -2
  8. package/locales/fr/LC_MESSAGES/volto.po +1 -2
  9. package/locales/it/LC_MESSAGES/volto.po +3 -4
  10. package/locales/volto.pot +2 -3
  11. package/package.json +2 -2
  12. package/publiccode.yml +2 -2
  13. package/src/components/ItaliaTheme/Blocks/Accordion/Block/ViewBlock.jsx +1 -1
  14. package/src/components/ItaliaTheme/Blocks/Listing/CardWithSlideUpTextTemplate.jsx +3 -0
  15. package/src/components/ItaliaTheme/ScrollToTop/ScrollToTop.jsx +0 -1
  16. package/src/components/ItaliaTheme/View/Commons/BandoDates.jsx +27 -47
  17. package/src/components/ItaliaTheme/View/Commons/Dates.jsx +22 -8
  18. package/src/components/ItaliaTheme/View/Commons/Module.jsx +7 -0
  19. package/src/components/ItaliaTheme/View/IncaricoView/IncaricoView.jsx +2 -5
  20. package/src/components/ItaliaTheme/View/PageView/PageView.jsx +3 -0
  21. package/src/components/ItaliaTheme/View/PageView/Placeholder/HeaderEnd.jsx +6 -0
  22. package/src/components/ItaliaTheme/View/PersonaView/PersonaDocumenti.jsx +24 -24
  23. package/src/components/ItaliaTheme/View/PersonaView/PersonaRuolo.jsx +2 -9
  24. package/src/components/ItaliaTheme/View/index.js +1 -0
  25. package/src/components/__tests__/FormValidation.test.js +132 -0
  26. package/src/customizations/volto/components/theme/View/LinkView.jsx +14 -8
  27. package/src/customizations/volto/helpers/FormValidation/FormValidation.js +1 -1
  28. package/src/theme/ItaliaTheme/Blocks/_cardWithSlideUpTextTemplate.scss +9 -1
  29. package/src/theme/ItaliaTheme/Blocks/_gridBlock.scss +25 -23
  30. package/src/theme/ItaliaTheme/_common.scss +6 -1
  31. package/src/theme/ItaliaTheme/_home.scss +4 -2
  32. package/src/theme/bootstrap-override/bootstrap-italia/_buttons.scss +18 -0
  33. package/src/theme/bootstrap-override/bootstrap-italia/_focus.scss +14 -0
  34. package/src/theme/bootstrap-override/bootstrap-italia/_headercenter.scss +5 -0
Binary file
package/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
 
2
2
 
3
+ ## [11.29.1](https://github.com/RedTurtle/design-comuni-plone-theme/compare/v11.29.0...v11.29.1) (2025-03-24)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * document cards layout for ct persona ([#921](https://github.com/RedTurtle/design-comuni-plone-theme/issues/921)) ([63ae761](https://github.com/RedTurtle/design-comuni-plone-theme/commit/63ae7618d7202800538d650ee36a174ffe80a204))
9
+ * focus of buttons + focus of inputs + contrast of buttons ([#915](https://github.com/RedTurtle/design-comuni-plone-theme/issues/915)) ([327b7d1](https://github.com/RedTurtle/design-comuni-plone-theme/commit/327b7d1907bfb0ec0f5c7d5e4c688fb4a5cb1dd6))
10
+ * handle slash in search params in url regex ([#914](https://github.com/RedTurtle/design-comuni-plone-theme/issues/914)) ([6a8744d](https://github.com/RedTurtle/design-comuni-plone-theme/commit/6a8744d32f8250d25604789cae06528178822329))
11
+ * link view redirects when user cannot edit, also redirects server side ([#919](https://github.com/RedTurtle/design-comuni-plone-theme/issues/919)) ([fee3622](https://github.com/RedTurtle/design-comuni-plone-theme/commit/fee362265f34069ad4ec4fbc8d096a12dc6294a3))
12
+ * restored original end of assignment label ([#910](https://github.com/RedTurtle/design-comuni-plone-theme/issues/910)) ([472f264](https://github.com/RedTurtle/design-comuni-plone-theme/commit/472f2647d0043e85c820868dc3886966da43219a))
13
+ * title link margin with no category + title style and bg gradient ([#917](https://github.com/RedTurtle/design-comuni-plone-theme/issues/917)) ([1f831c5](https://github.com/RedTurtle/design-comuni-plone-theme/commit/1f831c5cad258b631f13f681c550dc2101977905))
14
+
15
+
16
+ ### Documentation
17
+
18
+ * updated publiccode and release log ([5be2bd3](https://github.com/RedTurtle/design-comuni-plone-theme/commit/5be2bd3e4931a943369e07c34aea96b4e7c0fcbc))
19
+
20
+ ## [11.29.0](https://github.com/RedTurtle/design-comuni-plone-theme/compare/v11.28.0...v11.29.0) (2025-03-07)
21
+
22
+
23
+ ### Features
24
+
25
+ * added placeholder PagePlaceholderHeaderEnd in PageView ([#903](https://github.com/RedTurtle/design-comuni-plone-theme/issues/903)) ([dd89da5](https://github.com/RedTurtle/design-comuni-plone-theme/commit/dd89da5653dfb22c1fc7d59446b75d0292d6b6c4))
26
+ * allow ct document to contains also File content types and show as a Modulo content type; editors request to handle file cut/paste into ct documento ([#909](https://github.com/RedTurtle/design-comuni-plone-theme/issues/909)) ([71c0f91](https://github.com/RedTurtle/design-comuni-plone-theme/commit/71c0f91e730cabb1e3e9197c93e82e8d1338a73f))
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * a11y bando and events timeline ([#906](https://github.com/RedTurtle/design-comuni-plone-theme/issues/906)) ([c8ea5f0](https://github.com/RedTurtle/design-comuni-plone-theme/commit/c8ea5f004b011f5031faabc3a779e45f3b0808ff))
32
+ * **a11y:** changed display mode of homepage and subsite title([#905](https://github.com/RedTurtle/design-comuni-plone-theme/issues/905)) ([48f6db1](https://github.com/RedTurtle/design-comuni-plone-theme/commit/48f6db19f5c1d7a861d6daa397ce0f2212f472c8))
33
+ * changed homepage h1 from display none to visually hidden ([#904](https://github.com/RedTurtle/design-comuni-plone-theme/issues/904)) ([af0e49b](https://github.com/RedTurtle/design-comuni-plone-theme/commit/af0e49b40e5702d92ed8b5ea96fcbb9dd9bb0eda))
34
+ * no toggle accordion on clicking inside links ([#908](https://github.com/RedTurtle/design-comuni-plone-theme/issues/908)) ([23f6857](https://github.com/RedTurtle/design-comuni-plone-theme/commit/23f68575fa7aa960ab2ef9930dda2d57db036576))
35
+ * styles for listing blocks inside grid block on mobile ([#901](https://github.com/RedTurtle/design-comuni-plone-theme/issues/901)) ([59fc1b5](https://github.com/RedTurtle/design-comuni-plone-theme/commit/59fc1b51ec9c5f158b09c11e748983352471b552))
36
+
37
+
38
+ ### Documentation
39
+
40
+ * updated publiccode and release log ([dfbc39c](https://github.com/RedTurtle/design-comuni-plone-theme/commit/dfbc39cc0d72d73db6b40226e9104467bc6b01fc))
41
+
42
+
43
+ ### Maintenance
44
+
45
+ * fix lockfile ([2c96be2](https://github.com/RedTurtle/design-comuni-plone-theme/commit/2c96be2e9ee691f287d6c66612bb0f32fc9703cf))
46
+ * volto-feedback 0.6.1 ([#902](https://github.com/RedTurtle/design-comuni-plone-theme/issues/902)) ([c69eb91](https://github.com/RedTurtle/design-comuni-plone-theme/commit/c69eb91a05847e6d0676c2bcb0f606768b85815e))
47
+
3
48
  ## [11.28.0](https://github.com/RedTurtle/design-comuni-plone-theme/compare/v11.27.0...v11.28.0) (2025-03-04)
4
49
 
5
50
 
package/RELEASE.md CHANGED
@@ -41,6 +41,35 @@
41
41
  - ...
42
42
  -->
43
43
 
44
+ ## Versione 11.29.1 (24/03/2025)
45
+
46
+ ### Migliorie
47
+
48
+ - Il CT Collegamento identifica meglio i permessi dell'utente e di conseguenza il reindirizzamento automatico è più preciso.
49
+
50
+ ### Fix
51
+
52
+ - I bottoni presentano un contrasto corretto quando selezionati, e il bottone "scroll to top" può essere selezionato tramite navigazione da tastiera.
53
+ - Nel titolo e nel testo del campo "Data di fine dell'incarico" è stato rimosso il riferimento al nome dell'incarico.
54
+ - Risolto un problema con la validazione dei link inseriti nei campi url (ad es. URL del CT Collegamento).
55
+ - Risolto un problema con il template del blocco Elenco, variazione Card con testo animato.
56
+
57
+ ## Versione 11.29.0 (07/03/2025)
58
+
59
+ ### Migliorie
60
+
61
+ - Nel CT Documento ora è possibile gestire anche il CT File tramite taglia/incolla, laddove serva spostare dei File dentro uno specifico documento.
62
+ - Correzione del testo visualizzato sul pulsante "Cancella tutti i commenti" per la Customer Satisfaction, migliorando la leggibilità e conformità.
63
+ - Migliorata l'accessibilità per il widget dei campi di tipo Slate che salvano i dati in formato HTML.
64
+ - Migliorata l'accessibilità per gli elementi di tipo blockquote.
65
+ - Migliorata la lettura delle timeline di date nel dettaglio di Bando e Evento.
66
+
67
+ ### Fix
68
+
69
+ - Sistemata la visualizzazione su mobile dei blocchi elenco inseriti all'interno dei blocchi griglia.
70
+ - Il titolo della homepage del sito è ora accessibile.
71
+ - Risolto un problema con i link all'interno dei blocchi Accordion.
72
+
44
73
  ## Versione 11.28.0 (04/03/2025)
45
74
 
46
75
  ### Migliorie
@@ -1526,8 +1526,7 @@ msgid "data_conclusione"
1526
1526
  msgstr ""
1527
1527
 
1528
1528
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1529
- #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1530
- # defaultMessage: Ha fatto parte dell'organizzazione comunale come {incarico} fino al
1529
+ # defaultMessage: Data di fine dell'incarico
1531
1530
  msgid "data_conclusione_incarico"
1532
1531
  msgstr ""
1533
1532
 
@@ -1511,8 +1511,7 @@ msgid "data_conclusione"
1511
1511
  msgstr "Assignment start date"
1512
1512
 
1513
1513
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1514
- #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1515
- # defaultMessage: Ha fatto parte dell'organizzazione comunale come {incarico} fino al
1514
+ # defaultMessage: Data di fine dell'incarico
1516
1515
  msgid "data_conclusione_incarico"
1517
1516
  msgstr "He was part of the municipal organization until"
1518
1517
 
@@ -1520,8 +1520,7 @@ msgid "data_conclusione"
1520
1520
  msgstr ""
1521
1521
 
1522
1522
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1523
- #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1524
- # defaultMessage: Ha fatto parte dell'organizzazione comunale come {incarico} fino al
1523
+ # defaultMessage: Data di fine dell'incarico
1525
1524
  msgid "data_conclusione_incarico"
1526
1525
  msgstr "Formó parte de la organización municipal hasta"
1527
1526
 
@@ -1528,8 +1528,7 @@ msgid "data_conclusione"
1528
1528
  msgstr ""
1529
1529
 
1530
1530
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1531
- #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1532
- # defaultMessage: Ha fatto parte dell'organizzazione comunale come {incarico} fino al
1531
+ # defaultMessage: Data di fine dell'incarico
1533
1532
  msgid "data_conclusione_incarico"
1534
1533
  msgstr "Date de conclusion de la mission"
1535
1534
 
@@ -1511,15 +1511,14 @@ msgid "data_conclusione"
1511
1511
  msgstr "Data conclusione incarico"
1512
1512
 
1513
1513
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1514
- #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1515
- # defaultMessage: Ha fatto parte dell'organizzazione comunale come {incarico} fino al
1514
+ # defaultMessage: Data di fine dell'incarico
1516
1515
  msgid "data_conclusione_incarico"
1517
- msgstr "Ha fatto parte dell'organizzazione comunale come {incarico} fino al"
1516
+ msgstr "Data di fine dell'incarico"
1518
1517
 
1519
1518
  #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1520
1519
  # defaultMessage: Data di fine dell'incarico
1521
1520
  msgid "data_conclusione_incarico_label"
1522
- msgstr "Data di conclusione dell'incarico"
1521
+ msgstr "Data di fine dell'incarico"
1523
1522
 
1524
1523
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1525
1524
  # defaultMessage: Data inizio incarico
package/locales/volto.pot CHANGED
@@ -1,7 +1,7 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: Plone\n"
4
- "POT-Creation-Date: 2025-03-04T14:31:20.722Z\n"
4
+ "POT-Creation-Date: 2025-03-11T15:48:06.811Z\n"
5
5
  "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
6
  "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
7
  "MIME-Version: 1.0\n"
@@ -1513,8 +1513,7 @@ msgid "data_conclusione"
1513
1513
  msgstr ""
1514
1514
 
1515
1515
  #: components/ItaliaTheme/View/IncaricoView/IncaricoView
1516
- #: components/ItaliaTheme/View/PersonaView/PersonaRuolo
1517
- # defaultMessage: Ha fatto parte dell'organizzazione comunale come {incarico} fino al
1516
+ # defaultMessage: Data di fine dell'incarico
1518
1517
  msgid "data_conclusione_incarico"
1519
1518
  msgstr ""
1520
1519
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "design-comuni-plone-theme",
3
3
  "description": "Volto Theme for Italia design guidelines",
4
4
  "license": "GPL-v3",
5
- "version": "11.28.0",
5
+ "version": "11.29.1",
6
6
  "main": "src/index.js",
7
7
  "repository": {
8
8
  "type": "git",
@@ -151,7 +151,7 @@
151
151
  "volto-data-grid-widget": "2.3.1",
152
152
  "volto-dropdownmenu": "4.1.3",
153
153
  "volto-editablefooter": "5.1.7",
154
- "volto-feedback": "0.6.0",
154
+ "volto-feedback": "0.6.1",
155
155
  "volto-form-block": "3.10.0",
156
156
  "volto-gdpr-privacy": "2.2.12",
157
157
  "volto-google-analytics": "2.0.0",
package/publiccode.yml CHANGED
@@ -227,9 +227,9 @@ maintenance:
227
227
  name: io-Comune - Il sito AgID per Comuni ed Enti Pubblici
228
228
  platforms:
229
229
  - web
230
- releaseDate: '2025-03-04'
230
+ releaseDate: '2025-03-24'
231
231
  softwareType: standalone/web
232
- softwareVersion: 11.28.0
232
+ softwareVersion: 11.29.1
233
233
  url: 'https://github.com/italia/design-comuni-plone-theme'
234
234
  usedBy:
235
235
  - ASP Comuni Modenesi Area Nord
@@ -72,7 +72,7 @@ const ViewBlock = ({ data, isOpen, toggle, id, index }) => {
72
72
  aria-labelledby={`${id}-${index}`}
73
73
  hidden={!isOpen}
74
74
  >
75
- <div className="accordion-inner" onFocus={toggle()}>
75
+ <div className="accordion-inner">
76
76
  {redraft(
77
77
  data.text,
78
78
  config.settings.richtextViewSettings.ToHTMLRenderers,
@@ -90,6 +90,9 @@ const CardWithSlideUpTextTemplate = (props) => {
90
90
  href={isEditMode ? '#' : null}
91
91
  key={index}
92
92
  data-element={id_lighthouse}
93
+ className={cx('title-link', {
94
+ 'auto-margin-link': !category && !date,
95
+ })}
93
96
  >
94
97
  <h3
95
98
  className={cx('title', {
@@ -50,7 +50,6 @@ const ScrollToTop = () => {
50
50
  title={intl.formatMessage(messages.scrollToTop)}
51
51
  onClick={scrollToTop}
52
52
  aria-hidden="true"
53
- tabIndex={-1}
54
53
  >
55
54
  <Icon icon="it-arrow-up" padding={false} size="sm" />
56
55
  </Button>
@@ -57,18 +57,31 @@ const BandoDates = ({ content }) => {
57
57
  ? viewDate(intl.locale, content.chiusura_procedimento_bando)
58
58
  : null;
59
59
 
60
+ const PointListDate = ({ date }) => {
61
+ return (
62
+ <div
63
+ className="point-list-aside point-list-warning"
64
+ aria-label={date.format('DD MMMM Y')}
65
+ >
66
+ <span className="point-date font-monospace" aria-hidden="true">
67
+ {date.format('DD')}
68
+ </span>
69
+ <span className="point-month" aria-hidden="true">
70
+ {date.format('MMMM')}
71
+ </span>
72
+ <span className="point-month" aria-hidden="true">
73
+ {date.format('Y')}
74
+ </span>
75
+ </div>
76
+ );
77
+ };
60
78
  return content ? (
61
79
  <>
62
80
  <div className="point-list-wrapper my-4 mb-5">
63
81
  {effective && (
64
82
  <div className="point-list">
65
- <div className="point-list-aside point-list-warning">
66
- <span className="point-date font-monospace">
67
- {effective.format('DD')}
68
- </span>
69
- <span className="point-month">{effective.format('MMMM')}</span>
70
- <span className="point-month">{effective.format('Y')}</span>
71
- </div>
83
+ <PointListDate date={effective} />
84
+
72
85
  <div className="point-list-content">
73
86
  <Card
74
87
  className="card card-teaser rounded shadow border-left-card"
@@ -87,15 +100,8 @@ const BandoDates = ({ content }) => {
87
100
 
88
101
  {apertura_bando && (
89
102
  <div className="point-list">
90
- <div className="point-list-aside point-list-warning">
91
- <span className="point-date font-monospace">
92
- {apertura_bando.format('DD')}
93
- </span>
94
- <span className="point-month">
95
- {apertura_bando.format('MMMM')}
96
- </span>
97
- <span className="point-month">{apertura_bando.format('Y')}</span>
98
- </div>
103
+ <PointListDate date={apertura_bando} />
104
+
99
105
  <div className="point-list-content">
100
106
  <Card
101
107
  className="card card-teaser rounded shadow border-left-card"
@@ -115,17 +121,8 @@ const BandoDates = ({ content }) => {
115
121
 
116
122
  {scadenza_domande_bando && (
117
123
  <div className="point-list">
118
- <div className="point-list-aside point-list-warning">
119
- <span className="point-date font-monospace">
120
- {scadenza_domande_bando.format('DD')}
121
- </span>
122
- <span className="point-month">
123
- {scadenza_domande_bando.format('MMMM')}
124
- </span>
125
- <span className="point-month">
126
- {scadenza_domande_bando.format('Y')}
127
- </span>
128
- </div>
124
+ <PointListDate date={scadenza_domande_bando} />
125
+
129
126
  <div className="point-list-content">
130
127
  <Card
131
128
  className="card card-teaser rounded shadow border-left-card"
@@ -145,15 +142,7 @@ const BandoDates = ({ content }) => {
145
142
 
146
143
  {scadenza_bando && (
147
144
  <div className="point-list">
148
- <div className="point-list-aside point-list-warning">
149
- <span className="point-date font-monospace">
150
- {scadenza_bando.format('DD')}
151
- </span>
152
- <span className="point-month">
153
- {scadenza_bando.format('MMMM')}
154
- </span>
155
- <span className="point-month">{scadenza_bando.format('Y')}</span>
156
- </div>
145
+ <PointListDate date={scadenza_bando} />
157
146
  <div className="point-list-content">
158
147
  <Card
159
148
  className="card card-teaser rounded shadow border-left-card"
@@ -173,17 +162,8 @@ const BandoDates = ({ content }) => {
173
162
 
174
163
  {chiusura_procedimento_bando && (
175
164
  <div className="point-list">
176
- <div className="point-list-aside point-list-warning">
177
- <span className="point-date font-monospace">
178
- {chiusura_procedimento_bando.format('DD')}
179
- </span>
180
- <span className="point-month">
181
- {chiusura_procedimento_bando.format('MMMM')}
182
- </span>
183
- <span className="point-month">
184
- {chiusura_procedimento_bando.format('Y')}
185
- </span>
186
- </div>
165
+ <PointListDate date={chiusura_procedimento_bando} />
166
+
187
167
  <div className="point-list-content">
188
168
  <Card
189
169
  className="card card-teaser rounded shadow border-left-card"
@@ -100,13 +100,20 @@ const Dates = ({ content, show_image, moment: momentlib, rrule }) => {
100
100
  <>
101
101
  <div className="point-list-wrapper my-4 mb-5">
102
102
  <div className="point-list">
103
- <div className="point-list-aside point-list-warning">
104
- <span className="point-date font-monospace">
103
+ <div
104
+ className="point-list-aside point-list-warning"
105
+ aria-label={start.format('DD MMMM Y')}
106
+ >
107
+ <span className="point-date font-monospace" aria-hidden={true}>
105
108
  {start.format('DD')}
106
109
  </span>
107
- <span className="point-month">{start.format('MMMM')}</span>
110
+ <span className="point-month" aria-hidden={true}>
111
+ {start.format('MMMM')}
112
+ </span>
108
113
  {!start.isSame(end, 'year') && (
109
- <span className="point-month">{start.format('YYYY')}</span>
114
+ <span className="point-month" aria-hidden={true}>
115
+ {start.format('YYYY')}
116
+ </span>
110
117
  )}
111
118
  </div>
112
119
  <div className="point-list-content">
@@ -131,13 +138,20 @@ const Dates = ({ content, show_image, moment: momentlib, rrule }) => {
131
138
  </div>
132
139
  {!openEnd && (
133
140
  <div className="point-list">
134
- <div className="point-list-aside point-list-warning">
135
- <span className="point-date font-monospace">
141
+ <div
142
+ className="point-list-aside point-list-warning"
143
+ aria-label={end.format('DD MMMM Y')}
144
+ >
145
+ <span className="point-date font-monospace" aria-hidden={true}>
136
146
  {end?.format('DD')}
137
147
  </span>
138
- <span className="point-month">{end?.format('MMMM')}</span>
148
+ <span className="point-month" aria-hidden={true}>
149
+ {end?.format('MMMM')}
150
+ </span>
139
151
  {!end?.isSame(start, 'year') && (
140
- <span className="point-month">{end?.format('YYYY')}</span>
152
+ <span className="point-month" aria-hidden={true}>
153
+ {end?.format('YYYY')}
154
+ </span>
141
155
  )}
142
156
  </div>
143
157
  <div className="point-list-content">
@@ -39,6 +39,13 @@ const Module = ({ item }) => {
39
39
 
40
40
  {item.description && <p>{item.description}</p>}
41
41
  <div className="download-formats">
42
+ <DownloadFileFormat
43
+ file={item.file}
44
+ showLabel={true}
45
+ title={item.title ?? item.file.filename}
46
+ hideFileFormatLabel={true}
47
+ className="mb-4"
48
+ />
42
49
  <DownloadFileFormat
43
50
  file={item.file_principale}
44
51
  showLabel={true}
@@ -36,8 +36,7 @@ const messages = defineMessages({
36
36
  },
37
37
  data_conclusione_incarico: {
38
38
  id: 'data_conclusione_incarico',
39
- defaultMessage:
40
- "Ha fatto parte dell'organizzazione comunale come {incarico} fino al",
39
+ defaultMessage: "Data di fine dell'incarico",
41
40
  },
42
41
  data_insediamento: {
43
42
  id: 'data_insediamento',
@@ -116,9 +115,7 @@ const IncaricoView = ({ content, moment: momentlib }) => {
116
115
  {content.data_conclusione_incarico && (
117
116
  <RichTextSection
118
117
  tag_id="data_conclusione_incarico"
119
- title={intl.formatMessage(messages.data_conclusione_incarico, {
120
- incarico: content.title,
121
- })}
118
+ title={intl.formatMessage(messages.data_conclusione_incarico)}
122
119
  >
123
120
  <div className="font-serif">
124
121
  {moment(content.data_conclusione_incarico).format('D-MM-YYYY')}
@@ -11,6 +11,7 @@ import {
11
11
  PagePlaceholderAfterContent,
12
12
  PagePlaceholderAfterRelatedItems,
13
13
  PagePlaceholderTitle,
14
+ PagePlaceholderHeaderEnd,
14
15
  TextOrBlocks,
15
16
  RichText,
16
17
  RelatedItemInEvidence,
@@ -76,6 +77,7 @@ const PageView = ({ content, token, location, history }) => {
76
77
  </PagePlaceholderTitle>
77
78
 
78
79
  <p className="description">{content?.description}</p>
80
+
79
81
  {content?.ricerca_in_testata && (
80
82
  <SearchSectionForm content={content} />
81
83
  )}
@@ -118,6 +120,7 @@ const PageView = ({ content, token, location, history }) => {
118
120
  </div>
119
121
  )}
120
122
  </div>
123
+ <PagePlaceholderHeaderEnd content={content} />
121
124
  </div>
122
125
 
123
126
  <TextOrBlocks content={content} />
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+
3
+ const HeaderEnd = ({ content }) => {
4
+ return <></>;
5
+ };
6
+ export default HeaderEnd;
@@ -240,19 +240,19 @@ const PersonaDocumenti = ({ content }) => {
240
240
  }
241
241
  />
242
242
  )}
243
- {contentFolderHasItems(
244
- content,
245
- 'dichiarazione-insussistenza-cause-di-inconferibilita-e-incompatibilita',
246
- ) && (
247
- <Attachments
248
- content={content}
249
- folder_name={
250
- 'dichiarazione-insussistenza-cause-di-inconferibilita-e-incompatibilita'
251
- }
252
- as_section={false}
253
- />
254
- )}
255
243
  </div>
244
+ {contentFolderHasItems(
245
+ content,
246
+ 'dichiarazione-insussistenza-cause-di-inconferibilita-e-incompatibilita',
247
+ ) && (
248
+ <Attachments
249
+ content={content}
250
+ folder_name={
251
+ 'dichiarazione-insussistenza-cause-di-inconferibilita-e-incompatibilita'
252
+ }
253
+ as_section={false}
254
+ />
255
+ )}
256
256
  </RichTextSection>
257
257
  )}
258
258
  {(content.emolumenti_a_carico_della_finanza_pubblica?.download ||
@@ -277,19 +277,19 @@ const PersonaDocumenti = ({ content }) => {
277
277
  }
278
278
  />
279
279
  )}
280
- {contentFolderHasItems(
281
- content,
282
- 'emolumenti-complessivi-percepiti-a-carico-della-finanza-pubblica',
283
- ) && (
284
- <Attachments
285
- content={content}
286
- folder_name={
287
- 'emolumenti-complessivi-percepiti-a-carico-della-finanza-pubblica'
288
- }
289
- as_section={false}
290
- />
291
- )}
292
280
  </div>
281
+ {contentFolderHasItems(
282
+ content,
283
+ 'emolumenti-complessivi-percepiti-a-carico-della-finanza-pubblica',
284
+ ) && (
285
+ <Attachments
286
+ content={content}
287
+ folder_name={
288
+ 'emolumenti-complessivi-percepiti-a-carico-della-finanza-pubblica'
289
+ }
290
+ as_section={false}
291
+ />
292
+ )}
293
293
  </RichTextSection>
294
294
  )}
295
295
  </>
@@ -74,11 +74,6 @@ const messages = defineMessages({
74
74
  id: 'data_conclusione_incarico_label',
75
75
  defaultMessage: "Data di fine dell'incarico",
76
76
  },
77
- data_conclusione_incarico: {
78
- id: 'data_conclusione_incarico',
79
- defaultMessage:
80
- "Ha fatto parte dell'organizzazione comunale come {incarico} fino al",
81
- },
82
77
  altri_incarichi: {
83
78
  id: 'altri_incarichi',
84
79
  defaultMessage: 'Altri incarichi',
@@ -129,13 +124,11 @@ const PersonaRuolo = ({ content }) => {
129
124
  )}
130
125
  >
131
126
  <div className="font-serif">
132
- {`${intl.formatMessage(messages.data_conclusione_incarico, {
133
- incarico: content.incarichi_persona[0].title,
134
- })} ${viewDate(
127
+ {viewDate(
135
128
  intl.locale,
136
129
  content.incarichi_persona[0].data_conclusione_incarico,
137
130
  'DD MMMM Y',
138
- )}`}
131
+ )}
139
132
  </div>
140
133
  </RichTextSection>
141
134
  )}
@@ -138,6 +138,7 @@ export NewsItemMetadata from 'design-comuni-plone-theme/components/ItaliaTheme/V
138
138
  export PagePlaceholderAfterContent from 'design-comuni-plone-theme/components/ItaliaTheme/View/PageView/Placeholder/AfterContent';
139
139
  export PagePlaceholderAfterRelatedItems from 'design-comuni-plone-theme/components/ItaliaTheme/View/PageView/Placeholder/AfterRelatedItems';
140
140
  export PagePlaceholderTitle from 'design-comuni-plone-theme/components/ItaliaTheme/View/PageView/Placeholder/Title';
141
+ export PagePlaceholderHeaderEnd from 'design-comuni-plone-theme/components/ItaliaTheme/View/PageView/Placeholder/HeaderEnd';
141
142
  export PaginaArgomentoPlaceholderAfterContent from 'design-comuni-plone-theme/components/ItaliaTheme/View/PaginaArgomentoView/Placeholder/AfterContent';
142
143
  export PaginaArgomentoPlaceholderAfterRelatedItems from 'design-comuni-plone-theme/components/ItaliaTheme/View/PaginaArgomentoView/Placeholder/AfterRelatedItems';
143
144
  export PaginaArgomentoViewNoBlocks from 'design-comuni-plone-theme/components/ItaliaTheme/View/PaginaArgomentoView/PaginaArgomentoViewNoBlocks';
@@ -0,0 +1,132 @@
1
+ import FormValidation from '@plone/volto/helpers/FormValidation/FormValidation';
2
+ import { messages } from '@plone/volto/helpers/MessageLabels/MessageLabels';
3
+
4
+ // copied over and tweaked from
5
+ // https://github.com/plone/volto/blob/17.x.x/src/helpers/FormValidation/FormValidation.test.js
6
+ const schema = {
7
+ properties: {
8
+ username: { title: 'Username', type: 'string', description: '' },
9
+ email: { title: 'Email', type: 'string', widget: 'email', description: '' },
10
+ url: { title: 'url', type: 'string', widget: 'url', description: '' },
11
+ },
12
+ fieldsets: [
13
+ { id: 'default', title: 'FIXME: User Data', fields: ['username'] },
14
+ { id: 'second', title: 'Second: User Data', fields: ['email'] },
15
+ ],
16
+ required: ['username'],
17
+ };
18
+ // const errors = { email: ['The specified email is not valid.'] };
19
+ const formData = { username: 'test username', email: 'test@example.com' };
20
+ const formatMessage = (messageObj) => {
21
+ return messageObj?.defaultMessage;
22
+ };
23
+ const errorJSON =
24
+ "[{'message': 'The specified email is not valid.', 'field': 'email', 'error': 'ValidationError'}]";
25
+ // end copied section
26
+
27
+ describe('FormValidation', () => {
28
+ describe('validateFieldsPerFieldset', () => {
29
+ // Tests copied over from Volto
30
+ it('validates incorrect url', () => {
31
+ formData.url = 'foo';
32
+ expect(
33
+ FormValidation.validateFieldsPerFieldset({
34
+ schema,
35
+ formData,
36
+ formatMessage,
37
+ }),
38
+ ).toEqual({ url: [messages.isValidURL.defaultMessage] });
39
+ });
40
+ it('validates url', () => {
41
+ formData.url = 'https://plone.org/';
42
+ expect(
43
+ FormValidation.validateFieldsPerFieldset({
44
+ schema,
45
+ formData,
46
+ formatMessage,
47
+ }),
48
+ ).toEqual({});
49
+ });
50
+ it('validates url with ip', () => {
51
+ formData.url = 'http://127.0.0.1:8080/Plone';
52
+ expect(
53
+ FormValidation.validateFieldsPerFieldset({
54
+ schema,
55
+ formData,
56
+ formatMessage,
57
+ }),
58
+ ).toEqual({});
59
+ });
60
+ it('validates url with localhost', () => {
61
+ formData.url = 'http://localhost:8080/Plone';
62
+ expect(
63
+ FormValidation.validateFieldsPerFieldset({
64
+ schema,
65
+ formData,
66
+ formatMessage,
67
+ }),
68
+ ).toEqual({});
69
+ });
70
+ // Our additional tests
71
+ it('validates url with path', () => {
72
+ formData.url = 'https://plone.org/Plone';
73
+ expect(
74
+ FormValidation.validateFieldsPerFieldset({
75
+ schema,
76
+ formData,
77
+ formatMessage,
78
+ }),
79
+ ).toEqual({});
80
+ });
81
+ it('validates url with port', () => {
82
+ formData.url = 'https://plone.org:8080/Plone';
83
+ expect(
84
+ FormValidation.validateFieldsPerFieldset({
85
+ schema,
86
+ formData,
87
+ formatMessage,
88
+ }),
89
+ ).toEqual({});
90
+ });
91
+ it('validates url with query', () => {
92
+ formData.url = 'https://plone.org/Plone?query=1';
93
+ expect(
94
+ FormValidation.validateFieldsPerFieldset({
95
+ schema,
96
+ formData,
97
+ formatMessage,
98
+ }),
99
+ ).toEqual({});
100
+ });
101
+ it('validates url with query with slashes', () => {
102
+ formData.url = 'https://plone.org/Plone?query=1/2/3';
103
+ expect(
104
+ FormValidation.validateFieldsPerFieldset({
105
+ schema,
106
+ formData,
107
+ formatMessage,
108
+ }),
109
+ ).toEqual({});
110
+ });
111
+ it('validates url with fragment', () => {
112
+ formData.url = 'https://plone.org/Plone#fragment';
113
+ expect(
114
+ FormValidation.validateFieldsPerFieldset({
115
+ schema,
116
+ formData,
117
+ formatMessage,
118
+ }),
119
+ ).toEqual({});
120
+ });
121
+ it('validates url with query and fragment', () => {
122
+ formData.url = 'https://plone.org/Plone?query=1#fragment';
123
+ expect(
124
+ FormValidation.validateFieldsPerFieldset({
125
+ schema,
126
+ formData,
127
+ formatMessage,
128
+ }),
129
+ ).toEqual({});
130
+ });
131
+ });
132
+ });
@@ -1,24 +1,27 @@
1
1
  // CUSTOMIZATION:
2
- // - Added condition to check if user is SPID user (16-18 and 21)
2
+ // - Added condition to check if the user can edit the link (18-21 and 24)
3
+ // - Backported optimizations from volto 18 (lines 33-35 and more specific imports)
3
4
 
4
5
  import { useEffect } from 'react';
5
6
  import { useSelector } from 'react-redux';
6
7
  import PropTypes from 'prop-types';
7
8
  import { useHistory } from 'react-router-dom';
8
- import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers';
9
+ import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers/Url/Url';
9
10
  import { Container as SemanticContainer } from 'semantic-ui-react';
10
- import { UniversalLink } from '@plone/volto/components';
11
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
12
+ import { Redirect } from 'react-router-dom';
11
13
  import { FormattedMessage } from 'react-intl';
12
14
  import config from '@plone/volto/registry';
13
15
 
14
- const LinkView = ({ token, content }) => {
16
+ const LinkView = ({ content }) => {
15
17
  const history = useHistory();
16
- const userWithoutRoles = useSelector((state) =>
17
- state.users?.user ? state.users.user?.roles?.length === 0 : true,
18
+ const userCanEdit = useSelector(
19
+ (state) =>
20
+ !!state.actions.actions.object.find((action) => action.id === 'edit'),
18
21
  );
19
22
 
20
23
  useEffect(() => {
21
- if (!token || userWithoutRoles) {
24
+ if (!userCanEdit) {
22
25
  const { remoteUrl } = content;
23
26
  if (isInternalURL(remoteUrl)) {
24
27
  history.replace(flattenToAppURL(remoteUrl));
@@ -26,7 +29,10 @@ const LinkView = ({ token, content }) => {
26
29
  window.location.href = flattenToAppURL(remoteUrl);
27
30
  }
28
31
  }
29
- }, [content, history, token, userWithoutRoles]);
32
+ }, [content, history, userCanEdit]);
33
+ if (__SERVER__ && !userCanEdit && content.remoteUrl) {
34
+ return <Redirect to={content.remoteUrl} />;
35
+ }
30
36
  const { title, description, remoteUrl } = content;
31
37
  const { openExternalLinkInNewTab } = config.settings;
32
38
  const Container =
@@ -108,7 +108,7 @@ const widgetValidation = {
108
108
  ')' +
109
109
  '(\\:\\d+)?' + // optional port
110
110
  '(\\/[-a-z\\d%_.~+]*)*' + // path
111
- '(\\?[;&a-z\\d%_.~+=-]*)?' + // validate query string
111
+ '(\\?[;&a-z\\d%_.~+\\/=-]*)?' + // validate query string
112
112
  '(\\#[-a-z\\d_]*)?$', // validate fragment locator
113
113
  'i',
114
114
  );
@@ -25,6 +25,10 @@
25
25
  padding: 1.2rem;
26
26
  text-decoration: none;
27
27
 
28
+ .title-link {
29
+ text-decoration: none;
30
+ }
31
+
28
32
  .title {
29
33
  z-index: 2;
30
34
  overflow: hidden;
@@ -43,6 +47,10 @@
43
47
  margin-top: auto !important;
44
48
  }
45
49
 
50
+ .auto-margin-link {
51
+ margin-top: auto;
52
+ }
53
+
46
54
  .category + .title {
47
55
  margin-top: 0 !important;
48
56
  }
@@ -104,7 +112,7 @@
104
112
  height: 100%;
105
113
  --bs-gradient: linear-gradient(
106
114
  to bottom,
107
- rgba(0, 0, 0, 0.3) 0%,
115
+ rgba(0, 0, 0, 0.5) 0%,
108
116
  #000 100%
109
117
  );
110
118
  opacity: 0.4;
@@ -19,36 +19,38 @@
19
19
  width: auto !important;
20
20
  }
21
21
 
22
- &.listing {
23
- &.simpleCard,
24
- &.attachmentCardTemplate {
25
- .card-teaser-block-3 {
26
- > .card-teaser {
27
- flex: 0 0 49%; //invece di 3 elementi per riga, ne mostro due perchè c'è poco spazio
22
+ @media (min-width: #{map-get($grid-breakpoints, md)}) {
23
+ &.listing {
24
+ &.simpleCard,
25
+ &.attachmentCardTemplate {
26
+ .card-teaser-block-3 {
27
+ > .card-teaser {
28
+ flex: 0 0 49%; //invece di 3 elementi per riga, ne mostro due perchè c'è poco spazio
29
+ }
28
30
  }
29
31
  }
30
- }
31
32
 
32
- &.cardWithImageTemplate,
33
- &.ribbonCardTemplate,
34
- &.completeBlockLinksTemplate {
35
- .col-lg-4,
36
- .col-xl-4,
37
- .col-lg-3 {
38
- width: 50%; //invece di 3 elementi per riga, ne mostro due perchè c'è poco spazio
33
+ &.cardWithImageTemplate,
34
+ &.ribbonCardTemplate,
35
+ &.completeBlockLinksTemplate {
36
+ .col-lg-4,
37
+ .col-xl-4,
38
+ .col-lg-3 {
39
+ width: 50%; //invece di 3 elementi per riga, ne mostro due perchè c'è poco spazio
40
+ }
39
41
  }
40
- }
41
42
 
42
- &.cardSlideUpTextTemplate,
43
- &.quaresImageTemplate {
44
- .grid {
45
- grid-template-columns: 1fr 1fr;
43
+ &.cardSlideUpTextTemplate,
44
+ &.quaresImageTemplate {
45
+ .grid {
46
+ grid-template-columns: 1fr 1fr;
47
+ }
46
48
  }
47
- }
48
49
 
49
- &.bandiInEvidenceTemplate {
50
- .bandi-in-evidence-cards-wrapper {
51
- grid-template-columns: 1fr 1fr;
50
+ &.bandiInEvidenceTemplate {
51
+ .bandi-in-evidence-cards-wrapper {
52
+ grid-template-columns: 1fr 1fr;
53
+ }
52
54
  }
53
55
  }
54
56
  }
@@ -10,8 +10,10 @@
10
10
  outline: 2px solid $outer-focus-outline !important;
11
11
  outline-offset: 2px;
12
12
 
13
- border: none !important;
14
13
  box-shadow: 0 0 0 2px $inner-focus-shadow !important;
14
+
15
+ // adds additional internal black border to buttons
16
+ border: 2px solid $outer-focus-outline !important;
15
17
  }
16
18
  }
17
19
 
@@ -40,6 +42,9 @@
40
42
  0 1px 1px $focus-outline-color,
41
43
  0 0 0 0.2rem $focus-outline-color;
42
44
  outline: none;
45
+
46
+ // adds additional black internal border to tertiary buttons
47
+ border: 2px solid $focus-outline-color !important;
43
48
  }
44
49
  }
45
50
 
@@ -2,7 +2,7 @@
2
2
  body.public-ui.contenttype-lrf {
3
3
  .block-editor-title,
4
4
  .documentFirstHeading {
5
- display: none;
5
+ @include visually-hidden;
6
6
  }
7
7
  }
8
8
 
@@ -13,7 +13,9 @@ body.public-ui.contenttype-lrf {
13
13
  body.subsite.subsite-root {
14
14
  &,
15
15
  .public-ui {
16
- .documentFirstHeading,
16
+ .documentFirstHeading {
17
+ @include visually-hidden;
18
+ }
17
19
  #briciole {
18
20
  display: none;
19
21
  }
@@ -6,3 +6,21 @@ button.btn.btn-primary:focus-visible,
6
6
  }
7
7
  }
8
8
  }
9
+
10
+ button.btn.btn-primary:focus-visible {
11
+ // fix for primary buttons to ensure contrast upon focus
12
+ background-color: darken($color: $primary, $amount: 5%);
13
+ color: color-contrast($primary);
14
+ }
15
+
16
+ button.btn.btn-secondary:focus-visible {
17
+ // fix for secondary buttons to ensure contrast upon focus
18
+ background-color: darken($color: $secondary, $amount: 5%);
19
+ color: color-contrast($secondary);
20
+ }
21
+
22
+ button.btn.btn-tertiary:focus-visible {
23
+ // fix for tertiary buttons to ensure contrast upon focus
24
+ background-color: darken($color: $tertiary, $amount: 5%);
25
+ color: color-contrast($tertiary);
26
+ }
@@ -7,6 +7,20 @@
7
7
  box-shadow: 0 0 0 2px $inner-focus-shadow !important;
8
8
  }
9
9
 
10
+ input:focus:not(.focus--mouse) {
11
+ // only add border to input besides default double outline
12
+ border: 2px solid $outer-focus-outline !important;
13
+ }
14
+
10
15
  .skiplinks a:focus:not(.focus--mouse) {
11
16
  border: 2px solid;
12
17
  }
18
+
19
+ .gdpr-privacy-show-banner:focus:not(.focus--mouse) {
20
+ // invert general :focus rule since button is always white
21
+ outline: 2px solid $inner-focus-shadow !important;
22
+ outline-offset: 2px;
23
+
24
+ border: none !important;
25
+ box-shadow: 0 0 0 2px $outer-focus-outline !important;
26
+ }
@@ -23,6 +23,11 @@
23
23
 
24
24
  border: none !important;
25
25
  box-shadow: 0 0 0 2px $inner-focus-shadow !important;
26
+
27
+ //adds border to ensure correct contrast on all bg
28
+ // dark bg + light button --> internal dark border + outer white shadow
29
+ // light bg + dark button --> external dark border + inner white shadow
30
+ border: 2px solid $outer-focus-outline !important;
26
31
  }
27
32
  }
28
33
  }