design-comuni-plone-theme 11.29.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.
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +17 -0
- package/RELEASE.md +13 -0
- package/locales/de/LC_MESSAGES/volto.po +1 -2
- package/locales/en/LC_MESSAGES/volto.po +1 -2
- package/locales/es/LC_MESSAGES/volto.po +1 -2
- package/locales/fr/LC_MESSAGES/volto.po +1 -2
- package/locales/it/LC_MESSAGES/volto.po +3 -4
- package/locales/volto.pot +2 -3
- package/package.json +1 -1
- package/publiccode.yml +2 -2
- package/src/components/ItaliaTheme/Blocks/Listing/CardWithSlideUpTextTemplate.jsx +3 -0
- package/src/components/ItaliaTheme/ScrollToTop/ScrollToTop.jsx +0 -1
- package/src/components/ItaliaTheme/View/IncaricoView/IncaricoView.jsx +2 -5
- package/src/components/ItaliaTheme/View/PersonaView/PersonaDocumenti.jsx +24 -24
- package/src/components/ItaliaTheme/View/PersonaView/PersonaRuolo.jsx +2 -9
- package/src/components/__tests__/FormValidation.test.js +132 -0
- package/src/customizations/volto/components/theme/View/LinkView.jsx +14 -8
- package/src/customizations/volto/helpers/FormValidation/FormValidation.js +1 -1
- package/src/theme/ItaliaTheme/Blocks/_cardWithSlideUpTextTemplate.scss +9 -1
- package/src/theme/ItaliaTheme/_common.scss +6 -1
- package/src/theme/bootstrap-override/bootstrap-italia/_buttons.scss +18 -0
- package/src/theme/bootstrap-override/bootstrap-italia/_focus.scss +14 -0
- package/src/theme/bootstrap-override/bootstrap-italia/_headercenter.scss +5 -0
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
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
|
+
|
|
3
20
|
## [11.29.0](https://github.com/RedTurtle/design-comuni-plone-theme/compare/v11.28.0...v11.29.0) (2025-03-07)
|
|
4
21
|
|
|
5
22
|
|
package/RELEASE.md
CHANGED
|
@@ -41,6 +41,19 @@
|
|
|
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
|
+
|
|
44
57
|
## Versione 11.29.0 (07/03/2025)
|
|
45
58
|
|
|
46
59
|
### Migliorie
|
|
@@ -1526,8 +1526,7 @@ msgid "data_conclusione"
|
|
|
1526
1526
|
msgstr ""
|
|
1527
1527
|
|
|
1528
1528
|
#: components/ItaliaTheme/View/IncaricoView/IncaricoView
|
|
1529
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 "
|
|
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
|
|
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-
|
|
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
|
-
|
|
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
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-
|
|
230
|
+
releaseDate: '2025-03-24'
|
|
231
231
|
softwareType: standalone/web
|
|
232
|
-
softwareVersion: 11.29.
|
|
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
|
|
@@ -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')}
|
|
@@ -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
|
-
{
|
|
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
|
)}
|
|
@@ -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
|
|
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
|
|
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 = ({
|
|
16
|
+
const LinkView = ({ content }) => {
|
|
15
17
|
const history = useHistory();
|
|
16
|
-
const
|
|
17
|
-
state
|
|
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 (!
|
|
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,
|
|
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%_
|
|
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.
|
|
115
|
+
rgba(0, 0, 0, 0.5) 0%,
|
|
108
116
|
#000 100%
|
|
109
117
|
);
|
|
110
118
|
opacity: 0.4;
|
|
@@ -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
|
|
|
@@ -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
|
}
|