design-comuni-plone-theme 10.6.1 → 10.6.3
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 +27 -0
- package/RELEASE.md +13 -1
- package/package.json +2 -2
- package/publiccode.yml +13 -2
- package/src/config/RichTextEditor/config.js +30 -13
- package/src/customizations/volto/components/manage/Blocks/Search/SearchBlockView.jsx +4 -1
- package/src/customizations/volto/components/manage/Widgets/WysiwygWidget.jsx +362 -0
- package/src/theme/ItaliaTheme/Blocks/_bandiInEvidenceTemplate.scss +2 -2
- package/src/theme/ItaliaTheme/Blocks/_search.scss +11 -5
- package/src/customizations/volto-gdpr-privacy/components/ConditionalEmbed/ConditionalEmbed.jsx +0 -135
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## [10.6.3](https://github.com/redturtle/design-comuni-plone-theme/compare/v10.6.2...v10.6.3) (2023-12-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* different styles and ui for all Search block listing templates when compared to default Listing template ([#437](https://github.com/redturtle/design-comuni-plone-theme/issues/437)) ([d6cf41d](https://github.com/redturtle/design-comuni-plone-theme/commit/d6cf41dd63e6d1b891ff045238d5d7d9d9df5ff0))
|
|
9
|
+
* gdpr privacy conditional embed to work in diff view ([#438](https://github.com/redturtle/design-comuni-plone-theme/issues/438)) ([6a8c361](https://github.com/redturtle/design-comuni-plone-theme/commit/6a8c361feda654f0301b5026533234438469ff37))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Documentation
|
|
13
|
+
|
|
14
|
+
* aggiornamento della lista dei comuni in publiccode.yml ([#159](https://github.com/redturtle/design-comuni-plone-theme/issues/159)) ([7e87e9f](https://github.com/redturtle/design-comuni-plone-theme/commit/7e87e9f2071adeced38eae57eb8d09cee6433fa1))
|
|
15
|
+
* updated publiccode and release log ([f27a61a](https://github.com/redturtle/design-comuni-plone-theme/commit/f27a61aef3f41ac34bcbdf9e58e2a6ae0166d0f9))
|
|
16
|
+
|
|
17
|
+
## [10.6.2](https://github.com/redturtle/design-comuni-plone-theme/compare/v10.6.1...v10.6.2) (2023-12-14)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* custom inline styles rendering in wysiwygwidget ([17e1d10](https://github.com/redturtle/design-comuni-plone-theme/commit/17e1d10a2de1c8ba4d12a7364bc8858761b4b92e))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Documentation
|
|
26
|
+
|
|
27
|
+
* aggiornamento lista dei comuni in publiccode.yml ([#158](https://github.com/redturtle/design-comuni-plone-theme/issues/158)) ([2abad9a](https://github.com/redturtle/design-comuni-plone-theme/commit/2abad9aecaa288ca87670183df13212bdb47fa66))
|
|
28
|
+
* updated publiccode and release log ([38d8d00](https://github.com/redturtle/design-comuni-plone-theme/commit/38d8d00daf1b3c822d11a701ecc3a83657c865cb))
|
|
29
|
+
|
|
3
30
|
## [10.6.1](https://github.com/RedTurtle/design-comuni-plone-theme/compare/v10.6.0...v10.6.1) (2023-12-13)
|
|
4
31
|
|
|
5
32
|
|
package/RELEASE.md
CHANGED
|
@@ -41,11 +41,23 @@
|
|
|
41
41
|
- ...
|
|
42
42
|
-->
|
|
43
43
|
|
|
44
|
+
## Versione 10.6.3 (15/12/2023)
|
|
45
|
+
|
|
46
|
+
### Fix
|
|
47
|
+
|
|
48
|
+
- Sistemati alcuni problemi di visualizzazione nei template disponibili per il blocco Cerca. Ora tutti i template disponibili per questo blocco rispecchiano graficamente quelli per il blocco Elenco sia in visualizzazione che in modifica.
|
|
49
|
+
|
|
50
|
+
## Versione 10.6.2 (14/12/2023)
|
|
51
|
+
|
|
52
|
+
### Fix
|
|
53
|
+
|
|
54
|
+
- Ora si vedono correttamente gli stili di allineamento del testo in alcuni editor di testo, ad esempio header e footer dei sottositi.
|
|
55
|
+
|
|
44
56
|
## Versione 10.6.1 (13/12/2023)
|
|
45
57
|
|
|
46
58
|
### Novità
|
|
47
59
|
|
|
48
|
-
- I seguenti campi sono ora riordinabili liberamente: "Timeline tempi e scadenze" per il tipo di contenuto
|
|
60
|
+
- I seguenti campi sono ora riordinabili liberamente: "Timeline tempi e scadenze" per il tipo di contenuto _Servizio_ e "Valore punto di contatto" del tipo di contenuto _Punto di contatto_.
|
|
49
61
|
|
|
50
62
|
### Fix
|
|
51
63
|
|
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": "10.6.
|
|
5
|
+
"version": "10.6.3",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"volto-addon",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"volto-editablefooter": "5.0.1",
|
|
147
147
|
"volto-feedback": "0.1.5",
|
|
148
148
|
"volto-form-block": "3.1.0",
|
|
149
|
-
"volto-gdpr-privacy": "2.1.
|
|
149
|
+
"volto-gdpr-privacy": "2.1.1",
|
|
150
150
|
"volto-google-analytics": "2.0.0",
|
|
151
151
|
"volto-multilingual-widget": "3.0.0",
|
|
152
152
|
"volto-querywidget-with-browser": "0.4.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: '2023-12-
|
|
230
|
+
releaseDate: '2023-12-15'
|
|
231
231
|
softwareType: standalone/web
|
|
232
|
-
softwareVersion: 10.6.
|
|
232
|
+
softwareVersion: 10.6.3
|
|
233
233
|
url: 'https://github.com/italia/design-comuni-plone-theme'
|
|
234
234
|
usedBy:
|
|
235
235
|
- ASP Comuni Modenesi Area Nord
|
|
@@ -243,6 +243,7 @@ usedBy:
|
|
|
243
243
|
- Biblioteche Pianura Est
|
|
244
244
|
- Camera di Commercio dell'Umbria
|
|
245
245
|
- Camera di Commercio di Reggio Emilia
|
|
246
|
+
- Comune della Spezia
|
|
246
247
|
- Comune di Bibbiano
|
|
247
248
|
- Comune di Camposanto
|
|
248
249
|
- Comune di Cantagallo
|
|
@@ -251,14 +252,21 @@ usedBy:
|
|
|
251
252
|
- Comune di Concordia sul Secchia
|
|
252
253
|
- Comune di Gattatico
|
|
253
254
|
- Comune di Finale Emilia
|
|
255
|
+
- Comune di Fiorano Modenese
|
|
256
|
+
- Comune di Formigine
|
|
257
|
+
- Comune di Frassinoro
|
|
254
258
|
- Comune di Imola
|
|
259
|
+
- Comune di Maranello
|
|
255
260
|
- Comune di Medolla
|
|
256
261
|
- Comune di Mirandola
|
|
257
262
|
- Comune di Modena
|
|
258
263
|
- Comune di Montecchio Emilia
|
|
264
|
+
- Comune di Montefiorino
|
|
259
265
|
- Comune di Novellara
|
|
266
|
+
- Comune di Palagano
|
|
260
267
|
- Comune di Parma
|
|
261
268
|
- Comune di Piacenza
|
|
269
|
+
- Comune di Prignano
|
|
262
270
|
- Comune di Reggio Emilia
|
|
263
271
|
- Comune di San Felice sul Panaro
|
|
264
272
|
- Comune di San Lazzaro di Savena
|
|
@@ -266,6 +274,8 @@ usedBy:
|
|
|
266
274
|
- Comune di San Possidonio
|
|
267
275
|
- Comune di San Prospero
|
|
268
276
|
- Comune di Santilario d'Enza
|
|
277
|
+
- Comune di Sassuolo
|
|
278
|
+
- Comune di Toscolano Maderno
|
|
269
279
|
- Comune di Vaiano
|
|
270
280
|
- Comune di Vernio
|
|
271
281
|
- Comando Generale della Guardia di Finanza
|
|
@@ -273,6 +283,7 @@ usedBy:
|
|
|
273
283
|
- Nuovo Circondario Imolese
|
|
274
284
|
- Ospedali Galliera - Bilancio Sociale
|
|
275
285
|
- Provincia di Pisa
|
|
286
|
+
- Unione Comuni Distretto Ceramico
|
|
276
287
|
- UCMAN (Unione dei Comuni Modenesi Area Nord)
|
|
277
288
|
- Unione Val d'Enza
|
|
278
289
|
- Unione Val di Bisenzio
|
|
@@ -136,33 +136,50 @@ const ItaliaFromHTMLCustomBlockFn = (element) => {
|
|
|
136
136
|
ret = {
|
|
137
137
|
type: 'buttons',
|
|
138
138
|
};
|
|
139
|
-
} else if (element.className === '
|
|
139
|
+
} else if (element.className === 'text-center') {
|
|
140
140
|
ret = {
|
|
141
|
-
type: '
|
|
141
|
+
type: 'align-center',
|
|
142
|
+
};
|
|
143
|
+
} else if (element.className === 'text-end') {
|
|
144
|
+
ret = {
|
|
145
|
+
type: 'align-right',
|
|
146
|
+
};
|
|
147
|
+
} else if (element.className === 'text-justify') {
|
|
148
|
+
ret = {
|
|
149
|
+
type: 'align-justify',
|
|
142
150
|
};
|
|
143
151
|
}
|
|
144
152
|
}
|
|
145
153
|
return ret;
|
|
146
154
|
};
|
|
147
155
|
|
|
156
|
+
const ItaliaFromHTMLCustomInlineFn = (element, { Style }) => {
|
|
157
|
+
if (element.tagName === 'SPAN') {
|
|
158
|
+
if (element.className === 'draftjs-text-larger') {
|
|
159
|
+
return Style('TEXT_LARGER');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
148
164
|
export default function applyConfig(config) {
|
|
149
165
|
config.settings.richtextEditorSettings = (props) => {
|
|
150
166
|
const { plugins /*, inlineToolbarButtons*/ } = Plugins(props); // volto plugins
|
|
151
|
-
const { extendedBlockRenderMap, blockStyleFn, listBlockTypes } =
|
|
152
|
-
|
|
167
|
+
const { extendedBlockRenderMap, blockStyleFn, listBlockTypes } = Blocks(
|
|
168
|
+
props,
|
|
169
|
+
);
|
|
153
170
|
|
|
154
171
|
const { immutableLib } = props;
|
|
155
172
|
const { Map } = immutableLib;
|
|
156
173
|
|
|
157
174
|
const blockRenderMap = Map({
|
|
158
175
|
'align-center': {
|
|
159
|
-
element:
|
|
176
|
+
element: (props) => <p {...props} style={{ textAlign: 'center' }} />,
|
|
160
177
|
},
|
|
161
178
|
'align-right': {
|
|
162
|
-
element:
|
|
179
|
+
element: (props) => <p {...props} style={{ textAlign: 'right' }} />,
|
|
163
180
|
},
|
|
164
181
|
'align-justify': {
|
|
165
|
-
element:
|
|
182
|
+
element: (props) => <p {...props} style={{ textAlign: 'justify' }} />,
|
|
166
183
|
},
|
|
167
184
|
'callout-bg': {
|
|
168
185
|
element: 'p',
|
|
@@ -179,9 +196,6 @@ export default function applyConfig(config) {
|
|
|
179
196
|
r = r.length > 0 ? ' ' : r;
|
|
180
197
|
|
|
181
198
|
const styles = {
|
|
182
|
-
'align-center': 'text-center',
|
|
183
|
-
'align-right': 'text-end',
|
|
184
|
-
'align-justify': 'text-justify',
|
|
185
199
|
callout: 'callout',
|
|
186
200
|
'callout-bg': 'callout-bg',
|
|
187
201
|
buttons: 'draftjs-buttons',
|
|
@@ -203,9 +217,12 @@ export default function applyConfig(config) {
|
|
|
203
217
|
...plugins,
|
|
204
218
|
...ItaliaRichTextEditorPlugins(props),
|
|
205
219
|
],
|
|
206
|
-
richTextEditorInlineToolbarButtons:
|
|
207
|
-
|
|
208
|
-
|
|
220
|
+
richTextEditorInlineToolbarButtons: ItaliaRichTextEditorInlineToolbarButtons(
|
|
221
|
+
props,
|
|
222
|
+
plugins,
|
|
223
|
+
), //[inlineToolbarButtons,...ItaliaRichTextEditorInlineToolbarButtons(props)]
|
|
224
|
+
FromHTMLCustomBlockFn: ItaliaFromHTMLCustomBlockFn,
|
|
225
|
+
FromHTMLCustomInlineFn: ItaliaFromHTMLCustomInlineFn,
|
|
209
226
|
customStyleMap: {
|
|
210
227
|
TEXT_LARGER: { fontSize: '1.75rem' },
|
|
211
228
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* CUSTOMIZATIONS:
|
|
2
2
|
- Agid styling
|
|
3
|
+
- Add class .block.listing in listing body container div to use
|
|
4
|
+
existing listing template styles
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import React from 'react';
|
|
@@ -99,7 +101,8 @@ const SearchBlockView = (props) => {
|
|
|
99
101
|
selectedView={selectedView}
|
|
100
102
|
setSelectedView={setSelectedView}
|
|
101
103
|
>
|
|
102
|
-
|
|
104
|
+
{/* Add class .block.listing to benefit from existing listing template styles */}
|
|
105
|
+
<div className="block listing search-results">
|
|
103
106
|
<ListingBody
|
|
104
107
|
variation={{ ...data, ...listingBodyVariation }}
|
|
105
108
|
data={listingBodyData}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Customizations
|
|
3
|
+
* - add customInlineFn to stateFromHTML call (line 179)
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* WysiwygWidget container.
|
|
7
|
+
* @module components/manage/WysiwygWidget/WysiwygWidget
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React, { Component } from 'react';
|
|
11
|
+
import ReactDOMServer from 'react-dom/server';
|
|
12
|
+
import PropTypes from 'prop-types';
|
|
13
|
+
import { connect, Provider } from 'react-redux';
|
|
14
|
+
import { compose } from 'redux';
|
|
15
|
+
import redraft from 'redraft';
|
|
16
|
+
import { Form, Label, TextArea } from 'semantic-ui-react';
|
|
17
|
+
import { map } from 'lodash';
|
|
18
|
+
import { defineMessages, injectIntl } from 'react-intl';
|
|
19
|
+
import configureStore from 'redux-mock-store';
|
|
20
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
21
|
+
import config from '@plone/volto/registry';
|
|
22
|
+
|
|
23
|
+
import { FormFieldWrapper } from '@plone/volto/components';
|
|
24
|
+
|
|
25
|
+
import loadable from '@loadable/component';
|
|
26
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
27
|
+
|
|
28
|
+
const Editor = loadable(() => import('draft-js-plugins-editor'));
|
|
29
|
+
|
|
30
|
+
const messages = defineMessages({
|
|
31
|
+
default: {
|
|
32
|
+
id: 'Default',
|
|
33
|
+
defaultMessage: 'Default',
|
|
34
|
+
},
|
|
35
|
+
idTitle: {
|
|
36
|
+
id: 'Short Name',
|
|
37
|
+
defaultMessage: 'Short Name',
|
|
38
|
+
},
|
|
39
|
+
idDescription: {
|
|
40
|
+
id: 'Used for programmatic access to the fieldset.',
|
|
41
|
+
defaultMessage: 'Used for programmatic access to the fieldset.',
|
|
42
|
+
},
|
|
43
|
+
title: {
|
|
44
|
+
id: 'Title',
|
|
45
|
+
defaultMessage: 'Title',
|
|
46
|
+
},
|
|
47
|
+
description: {
|
|
48
|
+
id: 'Description',
|
|
49
|
+
defaultMessage: 'Description',
|
|
50
|
+
},
|
|
51
|
+
required: {
|
|
52
|
+
id: 'Required',
|
|
53
|
+
defaultMessage: 'Required',
|
|
54
|
+
},
|
|
55
|
+
delete: {
|
|
56
|
+
id: 'Delete',
|
|
57
|
+
defaultMessage: 'Delete',
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* WysiwygWidget HTML richtext editing widget
|
|
63
|
+
*
|
|
64
|
+
* To use it, in schema properties, declare a field like:
|
|
65
|
+
*
|
|
66
|
+
* ```jsx
|
|
67
|
+
* {
|
|
68
|
+
* title: "Rich text",
|
|
69
|
+
* widget: 'richtext',
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
class WysiwygWidgetComponent extends Component {
|
|
75
|
+
/**
|
|
76
|
+
* Property types.
|
|
77
|
+
* @property {Object} propTypes Property types.
|
|
78
|
+
* @static
|
|
79
|
+
*/
|
|
80
|
+
static propTypes = {
|
|
81
|
+
/**
|
|
82
|
+
* Id of the field
|
|
83
|
+
*/
|
|
84
|
+
id: PropTypes.string.isRequired,
|
|
85
|
+
/**
|
|
86
|
+
* Title of the field
|
|
87
|
+
*/
|
|
88
|
+
title: PropTypes.string.isRequired,
|
|
89
|
+
/**
|
|
90
|
+
* Description of the field
|
|
91
|
+
*/
|
|
92
|
+
description: PropTypes.string,
|
|
93
|
+
/**
|
|
94
|
+
* True if field is required
|
|
95
|
+
*/
|
|
96
|
+
required: PropTypes.bool,
|
|
97
|
+
/**
|
|
98
|
+
* Value of the field
|
|
99
|
+
*/
|
|
100
|
+
value: PropTypes.shape({
|
|
101
|
+
/**
|
|
102
|
+
* Content type of the value
|
|
103
|
+
*/
|
|
104
|
+
'content-type': PropTypes.string,
|
|
105
|
+
/**
|
|
106
|
+
* Data of the value
|
|
107
|
+
*/
|
|
108
|
+
data: PropTypes.string,
|
|
109
|
+
/**
|
|
110
|
+
* Encoding of the value
|
|
111
|
+
*/
|
|
112
|
+
encoding: PropTypes.string,
|
|
113
|
+
}),
|
|
114
|
+
/**
|
|
115
|
+
* Placeholder for the editor
|
|
116
|
+
*/
|
|
117
|
+
placeholder: PropTypes.string,
|
|
118
|
+
/**
|
|
119
|
+
* List of error messages
|
|
120
|
+
*/
|
|
121
|
+
error: PropTypes.arrayOf(PropTypes.string),
|
|
122
|
+
/**
|
|
123
|
+
* On change handler
|
|
124
|
+
*/
|
|
125
|
+
onChange: PropTypes.func,
|
|
126
|
+
/**
|
|
127
|
+
* On delete handler
|
|
128
|
+
*/
|
|
129
|
+
onDelete: PropTypes.func,
|
|
130
|
+
/**
|
|
131
|
+
* On edit handler
|
|
132
|
+
*/
|
|
133
|
+
onEdit: PropTypes.func,
|
|
134
|
+
/**
|
|
135
|
+
* Wrapped form component
|
|
136
|
+
*/
|
|
137
|
+
wrapped: PropTypes.bool,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Default properties
|
|
142
|
+
* @property {Object} defaultProps Default properties.
|
|
143
|
+
* @static
|
|
144
|
+
*/
|
|
145
|
+
static defaultProps = {
|
|
146
|
+
description: null,
|
|
147
|
+
required: false,
|
|
148
|
+
value: {
|
|
149
|
+
'content-type': 'text/html',
|
|
150
|
+
data: '',
|
|
151
|
+
encoding: 'utf8',
|
|
152
|
+
},
|
|
153
|
+
error: [],
|
|
154
|
+
onEdit: null,
|
|
155
|
+
onDelete: null,
|
|
156
|
+
onChange: null,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Constructor
|
|
161
|
+
* @method constructor
|
|
162
|
+
* @param {Object} props Component properties
|
|
163
|
+
* @constructs WysiwygWidget
|
|
164
|
+
*/
|
|
165
|
+
constructor(props) {
|
|
166
|
+
super(props);
|
|
167
|
+
|
|
168
|
+
const { stateFromHTML } = props.draftJsImportHtml;
|
|
169
|
+
const { EditorState } = props.draftJs;
|
|
170
|
+
const createInlineToolbarPlugin = props.draftJsInlineToolbarPlugin.default;
|
|
171
|
+
|
|
172
|
+
this.draftConfig = config.settings.richtextEditorSettings(props);
|
|
173
|
+
|
|
174
|
+
if (!__SERVER__) {
|
|
175
|
+
let editorState;
|
|
176
|
+
if (props.value && props.value.data) {
|
|
177
|
+
const contentState = stateFromHTML(props.value.data, {
|
|
178
|
+
customBlockFn: this.draftConfig.FromHTMLCustomBlockFn,
|
|
179
|
+
customInlineFn: this.draftConfig.FromHTMLCustomInlineFn,
|
|
180
|
+
});
|
|
181
|
+
editorState = EditorState.createWithContent(contentState);
|
|
182
|
+
} else {
|
|
183
|
+
editorState = EditorState.createEmpty();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const inlineToolbarPlugin = createInlineToolbarPlugin({
|
|
187
|
+
structure: this.draftConfig.richTextEditorInlineToolbarButtons,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
this.state = { editorState, inlineToolbarPlugin };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.schema = {
|
|
194
|
+
fieldsets: [
|
|
195
|
+
{
|
|
196
|
+
id: 'default',
|
|
197
|
+
title: props.intl.formatMessage(messages.default),
|
|
198
|
+
fields: ['title', 'id', 'description', 'required'],
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
properties: {
|
|
202
|
+
id: {
|
|
203
|
+
type: 'string',
|
|
204
|
+
title: props.intl.formatMessage(messages.idTitle),
|
|
205
|
+
description: props.intl.formatMessage(messages.idDescription),
|
|
206
|
+
},
|
|
207
|
+
title: {
|
|
208
|
+
type: 'string',
|
|
209
|
+
title: props.intl.formatMessage(messages.title),
|
|
210
|
+
},
|
|
211
|
+
description: {
|
|
212
|
+
type: 'string',
|
|
213
|
+
widget: 'textarea',
|
|
214
|
+
title: props.intl.formatMessage(messages.description),
|
|
215
|
+
},
|
|
216
|
+
required: {
|
|
217
|
+
type: 'boolean',
|
|
218
|
+
title: props.intl.formatMessage(messages.required),
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
required: ['id', 'title'],
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
this.onChange = this.onChange.bind(this);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Change handler
|
|
229
|
+
* @method onChange
|
|
230
|
+
* @param {object} editorState Editor state.
|
|
231
|
+
* @returns {undefined}
|
|
232
|
+
*/
|
|
233
|
+
onChange(editorState) {
|
|
234
|
+
const { convertToRaw } = this.props.draftJs;
|
|
235
|
+
this.setState({ editorState });
|
|
236
|
+
const mockStore = configureStore();
|
|
237
|
+
|
|
238
|
+
this.props.onChange(this.props.id, {
|
|
239
|
+
'content-type': this.props.value
|
|
240
|
+
? this.props.value['content-type']
|
|
241
|
+
: 'text/html',
|
|
242
|
+
encoding: this.props.value ? this.props.value.encoding : 'utf8',
|
|
243
|
+
data: ReactDOMServer.renderToStaticMarkup(
|
|
244
|
+
<Provider
|
|
245
|
+
store={mockStore({
|
|
246
|
+
userSession: {
|
|
247
|
+
token: this.props.token,
|
|
248
|
+
},
|
|
249
|
+
})}
|
|
250
|
+
>
|
|
251
|
+
<MemoryRouter>
|
|
252
|
+
{redraft(
|
|
253
|
+
convertToRaw(editorState.getCurrentContent()),
|
|
254
|
+
config.settings.richtextViewSettings.ToHTMLRenderers,
|
|
255
|
+
config.settings.richtextViewSettings.ToHTMLOptions,
|
|
256
|
+
)}
|
|
257
|
+
</MemoryRouter>
|
|
258
|
+
</Provider>,
|
|
259
|
+
),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Render method.
|
|
265
|
+
* @method render
|
|
266
|
+
* @returns {string} Markup for the component.
|
|
267
|
+
*/
|
|
268
|
+
render() {
|
|
269
|
+
const {
|
|
270
|
+
id,
|
|
271
|
+
title,
|
|
272
|
+
description,
|
|
273
|
+
required,
|
|
274
|
+
value,
|
|
275
|
+
error,
|
|
276
|
+
fieldSet,
|
|
277
|
+
} = this.props;
|
|
278
|
+
|
|
279
|
+
if (__SERVER__) {
|
|
280
|
+
return (
|
|
281
|
+
<Form.Field
|
|
282
|
+
inline
|
|
283
|
+
required={required}
|
|
284
|
+
error={error.length > 0}
|
|
285
|
+
className={description ? 'help' : ''}
|
|
286
|
+
id={`${fieldSet || 'field'}-${id}`}
|
|
287
|
+
>
|
|
288
|
+
<div className="wrapper">
|
|
289
|
+
<label htmlFor={`field-${id}`}>{title}</label>
|
|
290
|
+
<TextArea id={id} name={id} value={value ? value.data : ''} />
|
|
291
|
+
{description && <p className="help">{description}</p>}
|
|
292
|
+
{map(error, (message) => (
|
|
293
|
+
<Label key={message} basic color="red" pointing>
|
|
294
|
+
{message}
|
|
295
|
+
</Label>
|
|
296
|
+
))}
|
|
297
|
+
</div>
|
|
298
|
+
</Form.Field>
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
const { InlineToolbar } = this.state.inlineToolbarPlugin;
|
|
302
|
+
|
|
303
|
+
return (
|
|
304
|
+
<FormFieldWrapper {...this.props} className="wysiwyg">
|
|
305
|
+
<div style={{ boxSizing: 'initial' }}>
|
|
306
|
+
{this.props.onChange ? (
|
|
307
|
+
<>
|
|
308
|
+
<Editor
|
|
309
|
+
id={`field-${id}`}
|
|
310
|
+
readOnly={this.props.isDisabled}
|
|
311
|
+
onChange={this.onChange}
|
|
312
|
+
editorState={this.state.editorState}
|
|
313
|
+
plugins={[
|
|
314
|
+
this.state.inlineToolbarPlugin,
|
|
315
|
+
...this.draftConfig.richTextEditorPlugins,
|
|
316
|
+
]}
|
|
317
|
+
placeholder={this.props.placeholder}
|
|
318
|
+
blockRenderMap={this.draftConfig.extendedBlockRenderMap}
|
|
319
|
+
blockStyleFn={this.draftConfig.blockStyleFn}
|
|
320
|
+
customStyleMap={this.draftConfig.customStyleMap}
|
|
321
|
+
/>
|
|
322
|
+
{this.props.onChange && <InlineToolbar />}
|
|
323
|
+
</>
|
|
324
|
+
) : (
|
|
325
|
+
<div className="DraftEditor-root" />
|
|
326
|
+
)}
|
|
327
|
+
</div>
|
|
328
|
+
</FormFieldWrapper>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export const WysiwygWidget = compose(
|
|
334
|
+
injectIntl,
|
|
335
|
+
injectLazyLibs([
|
|
336
|
+
'draftJs',
|
|
337
|
+
'draftJsBlockBreakoutPlugin',
|
|
338
|
+
'draftJsCreateBlockStyleButton',
|
|
339
|
+
'draftJsCreateInlineStyleButton',
|
|
340
|
+
'draftJsFilters',
|
|
341
|
+
'draftJsImportHtml',
|
|
342
|
+
'draftJsInlineToolbarPlugin',
|
|
343
|
+
'draftJsLibIsSoftNewlineEvent',
|
|
344
|
+
'immutableLib',
|
|
345
|
+
]),
|
|
346
|
+
connect(
|
|
347
|
+
(state, props) => ({
|
|
348
|
+
token: state.userSession.token,
|
|
349
|
+
}),
|
|
350
|
+
{},
|
|
351
|
+
),
|
|
352
|
+
)(WysiwygWidgetComponent);
|
|
353
|
+
|
|
354
|
+
const Preloader = (props) => {
|
|
355
|
+
const [loaded, setLoaded] = React.useState(false);
|
|
356
|
+
React.useEffect(() => {
|
|
357
|
+
Editor.load().then(() => setLoaded(true));
|
|
358
|
+
}, []);
|
|
359
|
+
return loaded ? <WysiwygWidget {...props} /> : null;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
export default Preloader;
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
|
|
57
57
|
// tablet
|
|
58
58
|
.bandi-in-evidence-cards-wrapper {
|
|
59
|
-
@media (min-width: #{map-get($grid-breakpoints, md)}) and (max-width: #{map-get($grid-breakpoints,
|
|
60
|
-
grid-template-columns: auto
|
|
59
|
+
@media (min-width: #{map-get($grid-breakpoints, md)}) and (max-width: #{map-get($grid-breakpoints, xl)}) {
|
|
60
|
+
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
@media (min-width: #{map-get($grid-breakpoints, md)}) and (max-width: #{map-get($grid-breakpoints, lg)}) {
|
|
@@ -151,15 +151,13 @@
|
|
|
151
151
|
border-color: hsl(210deg, 17.6470588235%, 43.35%) !important;
|
|
152
152
|
border-bottom: 1px solid;
|
|
153
153
|
font-size: 1rem;
|
|
154
|
-
transition:
|
|
155
|
-
border-color 0.3s ease-in,
|
|
154
|
+
transition: border-color 0.3s ease-in,
|
|
156
155
|
background-color 0.2s cubic-bezier(0, 1, 0, 1) 0.2s;
|
|
157
156
|
|
|
158
157
|
&[aria-expanded='true'] {
|
|
159
158
|
border-color: transparent !important;
|
|
160
159
|
box-shadow: 0 1rem 2rem -0.25rem rgba(0, 0, 0, 0.15) !important;
|
|
161
|
-
transition:
|
|
162
|
-
background-color 0.2s cubic-bezier(0, 1, 0, 1),
|
|
160
|
+
transition: background-color 0.2s cubic-bezier(0, 1, 0, 1),
|
|
163
161
|
border-color 0.05s cubic-bezier(1, 0, 1, 0);
|
|
164
162
|
}
|
|
165
163
|
|
|
@@ -246,8 +244,16 @@
|
|
|
246
244
|
}
|
|
247
245
|
}
|
|
248
246
|
}
|
|
247
|
+
.block.listing {
|
|
248
|
+
.bandi-in-evidence .bandi-in-evidence-cards-wrapper {
|
|
249
|
+
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
250
|
+
@media (min-width: #{map-get($grid-breakpoints, md)}) and (max-width: #{map-get($grid-breakpoints, lg)}) {
|
|
251
|
+
display: block !important;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
249
255
|
}
|
|
250
256
|
|
|
251
|
-
|
|
257
|
+
.cms-ui .block.search .sideColumn .columnText .draftjs-buttons a {
|
|
252
258
|
color: $primary-text;
|
|
253
259
|
}
|
package/src/customizations/volto-gdpr-privacy/components/ConditionalEmbed/ConditionalEmbed.jsx
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
CUSTOMIZATIONS
|
|
3
|
-
- permit render if server, cannot use in history diff otherwise
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { useEffect, useState } from 'react';
|
|
7
|
-
import { useSelector, useDispatch } from 'react-redux';
|
|
8
|
-
import { useIntl, defineMessages } from 'react-intl';
|
|
9
|
-
import { useLocation } from 'react-router-dom';
|
|
10
|
-
import {
|
|
11
|
-
displayBanner,
|
|
12
|
-
updateGdprPrivacyConsent,
|
|
13
|
-
} from 'volto-gdpr-privacy/actions';
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
usePanelConfigAndPreferences,
|
|
17
|
-
GDPRCookies,
|
|
18
|
-
getLocaleConf,
|
|
19
|
-
} from 'volto-gdpr-privacy/helpers';
|
|
20
|
-
|
|
21
|
-
import 'volto-gdpr-privacy/components/ConditionalEmbed/conditional-embed.css';
|
|
22
|
-
|
|
23
|
-
const messages = defineMessages({
|
|
24
|
-
conditionalEmbedAcceptCookiesDefaultDescription: {
|
|
25
|
-
id: 'volto-gdpr-privacy-conditional-embed-default-description',
|
|
26
|
-
defaultMessage:
|
|
27
|
-
'Please, accept {cookie_type} cookies to view this content.',
|
|
28
|
-
},
|
|
29
|
-
conditionalEmbedAcceptCookiesAcceptMessage: {
|
|
30
|
-
id: 'volto-gdpr-privacy-conditional-embed-accept-message',
|
|
31
|
-
defaultMessage: '{enable_cookie_button}, or {manage_preferences_button}',
|
|
32
|
-
},
|
|
33
|
-
specificCookieLink: {
|
|
34
|
-
id: 'volto-gdpr-privacy-conditional-embed-specific-cookie-link',
|
|
35
|
-
defaultMessage: 'Enable {cookie_type} cookies',
|
|
36
|
-
},
|
|
37
|
-
genericCookieLink: {
|
|
38
|
-
id: 'volto-gdpr-privacy-conditional-embed-generic-cookie-link',
|
|
39
|
-
defaultMessage: 'manage your cookie preferences',
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
const ConditionalEmbed = ({ code, url, children }) => {
|
|
43
|
-
const intl = useIntl();
|
|
44
|
-
const cookies = new GDPRCookies();
|
|
45
|
-
const embed = code ?? url ?? '';
|
|
46
|
-
const dispatch = useDispatch();
|
|
47
|
-
const location = useLocation();
|
|
48
|
-
|
|
49
|
-
const { defaultPreferences } = usePanelConfigAndPreferences(cookies);
|
|
50
|
-
const profilingConfig = useSelector((state) =>
|
|
51
|
-
state.gdprPrivacyConfig?.config?.profiling?.choices?.filter(
|
|
52
|
-
(c) => c?.referenceUrls?.length > 0,
|
|
53
|
-
),
|
|
54
|
-
);
|
|
55
|
-
const gdprPreferences = useSelector(
|
|
56
|
-
(state) => state.gdprPrivacyConsent.preferences ?? defaultPreferences,
|
|
57
|
-
);
|
|
58
|
-
const [urlReferenceConfig, setUrlReferenceConfig] = useState(null);
|
|
59
|
-
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
if (profilingConfig && !urlReferenceConfig) {
|
|
62
|
-
let conditionalConfig = profilingConfig.filter(
|
|
63
|
-
(c) =>
|
|
64
|
-
c.referenceUrls.filter((r) => embed?.indexOf(r) >= 0)?.length > 0,
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
setUrlReferenceConfig(conditionalConfig?.[0] ?? null);
|
|
68
|
-
}
|
|
69
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
70
|
-
}, [profilingConfig, setUrlReferenceConfig, urlReferenceConfig, embed]);
|
|
71
|
-
|
|
72
|
-
//return value
|
|
73
|
-
let ret = <></>;
|
|
74
|
-
let embedDisabled = true;
|
|
75
|
-
|
|
76
|
-
embedDisabled =
|
|
77
|
-
urlReferenceConfig != null &&
|
|
78
|
-
!gdprPreferences[urlReferenceConfig.config_key];
|
|
79
|
-
const isDiffView = location.pathname?.includes('/diff');
|
|
80
|
-
if (__CLIENT__ && !gdprPreferences && !isDiffView) {
|
|
81
|
-
return <></>;
|
|
82
|
-
} else if (embedDisabled && !isDiffView) {
|
|
83
|
-
//embed disabled
|
|
84
|
-
const text = getLocaleConf(urlReferenceConfig.text, intl.locale);
|
|
85
|
-
const key = urlReferenceConfig.config_key;
|
|
86
|
-
ret = (
|
|
87
|
-
<div className="volto-gdpr-embed-disabled">
|
|
88
|
-
{text.conditional_embed_text ??
|
|
89
|
-
intl.formatMessage(
|
|
90
|
-
messages.conditionalEmbedAcceptCookiesDefaultDescription,
|
|
91
|
-
{ cookie_type: key },
|
|
92
|
-
)}{' '}
|
|
93
|
-
{intl.formatMessage(
|
|
94
|
-
messages.conditionalEmbedAcceptCookiesAcceptMessage,
|
|
95
|
-
{
|
|
96
|
-
enable_cookie_button: (
|
|
97
|
-
<button
|
|
98
|
-
onClick={(e) => {
|
|
99
|
-
e.preventDefault();
|
|
100
|
-
cookies.set(key, true);
|
|
101
|
-
dispatch(
|
|
102
|
-
updateGdprPrivacyConsent({
|
|
103
|
-
...gdprPreferences,
|
|
104
|
-
[key]: true,
|
|
105
|
-
}),
|
|
106
|
-
);
|
|
107
|
-
}}
|
|
108
|
-
>
|
|
109
|
-
{intl.formatMessage(messages.specificCookieLink, {
|
|
110
|
-
cookie_type: key,
|
|
111
|
-
})}
|
|
112
|
-
</button>
|
|
113
|
-
),
|
|
114
|
-
manage_preferences_button: (
|
|
115
|
-
<button
|
|
116
|
-
onClick={(e) => {
|
|
117
|
-
e.preventDefault();
|
|
118
|
-
dispatch(displayBanner(true, true));
|
|
119
|
-
}}
|
|
120
|
-
>
|
|
121
|
-
{intl.formatMessage(messages.genericCookieLink)}
|
|
122
|
-
</button>
|
|
123
|
-
),
|
|
124
|
-
},
|
|
125
|
-
)}
|
|
126
|
-
</div>
|
|
127
|
-
);
|
|
128
|
-
} else {
|
|
129
|
-
ret = <>{children}</>;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return ret;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
export default ConditionalEmbed;
|