@eeacms/volto-eea-website-theme 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -9
- package/package.json +1 -1
- package/src/customizations/volto/components/manage/Blocks/Image/Edit.jsx +408 -0
- package/src/customizations/volto/components/manage/Blocks/Image/View.jsx +111 -0
- package/src/customizations/volto/components/manage/Blocks/Image/schema.js +121 -0
- package/src/customizations/volto/components/manage/Blocks/Image/style.less +12 -0
- package/src/customizations/volto/components/manage/Blocks/LeadImage/AlignChooser.jsx +76 -0
- package/src/customizations/volto/components/manage/Blocks/LeadImage/Edit.jsx +141 -0
- package/src/customizations/volto/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +296 -0
- package/src/customizations/volto/components/manage/Blocks/LeadImage/View.jsx +86 -0
- package/src/customizations/volto/components/manage/Blocks/LeadImage/style.less +12 -0
- package/src/customizations/volto/components/manage/Form/Form.jsx +15 -2
- package/src/customizations/volto/components/manage/Sidebar/ObjectBrowserNav.jsx +5 -2
- package/src/customizations/volto/components/theme/Header/Header.jsx +2 -1
- package/theme/site/imageicons/imageicons.less +0 -5
package/CHANGELOG.md
CHANGED
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
4
4
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
6
6
|
|
7
|
+
### [1.5.0](https://github.com/eea/volto-eea-website-theme/compare/1.4.2...1.5.0) - 9 January 2023
|
8
|
+
|
9
|
+
#### :hammer_and_wrench: Others
|
10
|
+
|
11
|
+
- Release 1.5.0 [Alin Voinea - [`1b87380`](https://github.com/eea/volto-eea-website-theme/commit/1b87380b5eb5cd7324b1816c08e932c52c7e107b)]
|
12
|
+
### [1.4.2](https://github.com/eea/volto-eea-website-theme/compare/1.4.1...1.4.2) - 29 December 2022
|
13
|
+
|
14
|
+
#### :bug: Bug Fixes
|
15
|
+
|
16
|
+
- fix(Sidebar): Remove faulty imageicons.less import [Alin Voinea - [`49ed0cc`](https://github.com/eea/volto-eea-website-theme/commit/49ed0cc7e3f030f6e70c01d0fd4dba2318ab00bb)]
|
17
|
+
|
7
18
|
### [1.4.1](https://github.com/eea/volto-eea-website-theme/compare/1.4.0...1.4.1) - 29 December 2022
|
8
19
|
|
9
20
|
#### :bug: Bug Fixes
|
@@ -26,7 +37,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
26
37
|
|
27
38
|
- Release 1.4.0 [Alin Voinea - [`bd42a0d`](https://github.com/eea/volto-eea-website-theme/commit/bd42a0d26e928cac5d99933194755da3db06b341)]
|
28
39
|
- bump version to use as volto-eea-design-system [David Ichim - [`f4be047`](https://github.com/eea/volto-eea-website-theme/commit/f4be047328b46399b03b612d378b18aaf82e7dc1)]
|
29
|
-
- Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`9b7cfef`](https://github.com/eea/volto-eea-website-theme/commit/9b7cfefb4d34fc1c948015e491feb370f9795bd8)]
|
30
40
|
- test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`df252a9`](https://github.com/eea/volto-eea-website-theme/commit/df252a9bfed0bb86cadf53c59dd1603b1e2cd822)]
|
31
41
|
### [1.3.2](https://github.com/eea/volto-eea-website-theme/compare/1.3.1...1.3.2) - 16 December 2022
|
32
42
|
|
@@ -36,7 +46,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
36
46
|
|
37
47
|
#### :hammer_and_wrench: Others
|
38
48
|
|
39
|
-
- Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`a43c658`](https://github.com/eea/volto-eea-website-theme/commit/a43c658a7920c8df95e763b9a637f38ce77eba2c)]
|
40
49
|
- Better razzle.config [Tiberiu Ichim - [`81dbf48`](https://github.com/eea/volto-eea-website-theme/commit/81dbf48815fb27facb4f82c9b764540fdf188b2e)]
|
41
50
|
- Better razzle.config [Tiberiu Ichim - [`7bc9da2`](https://github.com/eea/volto-eea-website-theme/commit/7bc9da2cd837ab62a95cd29979cdd9b0055b7d67)]
|
42
51
|
### [1.3.1](https://github.com/eea/volto-eea-website-theme/compare/1.3.0...1.3.1) - 28 November 2022
|
@@ -45,9 +54,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
45
54
|
|
46
55
|
- feat(Footer): Bring back footer contacts extra actions - refs #151856 [Alin Voinea - [`6c19413`](https://github.com/eea/volto-eea-website-theme/commit/6c194139420c9fd847692d180db1c1593e2483de)]
|
47
56
|
|
48
|
-
#### :hammer_and_wrench: Others
|
49
|
-
|
50
|
-
- yarn 3 [Alin Voinea - [`ea7a709`](https://github.com/eea/volto-eea-website-theme/commit/ea7a7094945312776e9b6f44e371178603e92139)]
|
51
57
|
### [1.3.0](https://github.com/eea/volto-eea-website-theme/compare/1.2.0...1.3.0) - 22 November 2022
|
52
58
|
|
53
59
|
#### :rocket: New Features
|
@@ -88,7 +94,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
88
94
|
- Add subsite class to body [Tiberiu Ichim - [`74d700f`](https://github.com/eea/volto-eea-website-theme/commit/74d700fbfd6249a8604762a7e4e49cce857db0f3)]
|
89
95
|
- Add subsite info to header [Tiberiu Ichim - [`47daf8b`](https://github.com/eea/volto-eea-website-theme/commit/47daf8bb6374a1222040626b19d4154df7ba1b83)]
|
90
96
|
- fix eslint [Miu Razvan - [`eb8d0a7`](https://github.com/eea/volto-eea-website-theme/commit/eb8d0a790bc70c0aae256c6ff35f63c4885f338e)]
|
91
|
-
- Add Sonarqube tag using circularity-frontend addons list [EEA Jenkins - [`cc578a4`](https://github.com/eea/volto-eea-website-theme/commit/cc578a413b205a8e61e091fab3a88f94cedefc89)]
|
92
97
|
### [1.1.0](https://github.com/eea/volto-eea-website-theme/compare/1.0.0...1.1.0) - 28 October 2022
|
93
98
|
|
94
99
|
#### :nail_care: Enhancements
|
@@ -136,7 +141,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
136
141
|
|
137
142
|
#### :hammer_and_wrench: Others
|
138
143
|
|
139
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`33b56ac`](https://github.com/eea/volto-eea-website-theme/commit/33b56acb13fbaf0c5b79e8fc6e13c4b699c79c90)]
|
140
144
|
### [0.7.3](https://github.com/eea/volto-eea-website-theme/compare/0.7.2...0.7.3) - 22 September 2022
|
141
145
|
|
142
146
|
#### :hammer_and_wrench: Others
|
@@ -404,7 +408,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
404
408
|
- Header refactor, add custom logo #5 [ichim-david - [`4950235`](https://github.com/eea/volto-eea-website-theme/commit/49502358105437cfeac3b144e6d301cb59aa2346)]
|
405
409
|
- Update footer.config with new publication card component [ichim-david - [`2e38e9a`](https://github.com/eea/volto-eea-website-theme/commit/2e38e9a417f835009d60c80d4eb4b30229f55e45)]
|
406
410
|
- feature(breadcrumbs): implement eea-design-system breadcrumb as Volto component #32 #7 [ichim-david - [`181af41`](https://github.com/eea/volto-eea-website-theme/commit/181af4125ce2b9ddac56dab4723cb11c26633221)]
|
407
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`da8ceb6`](https://github.com/eea/volto-eea-website-theme/commit/da8ceb68ea68bfbc9504e48ccd4d68277f11ab9a)]
|
408
411
|
- use breadcrumbs from eea-design-system [nileshgulia1 - [`db2f9e9`](https://github.com/eea/volto-eea-website-theme/commit/db2f9e9a4327420a3cce9a9903cd88549b129eab)]
|
409
412
|
- Update theme.config [ichim-david - [`8eca4f4`](https://github.com/eea/volto-eea-website-theme/commit/8eca4f40397a4aeca6d39029c92db78968d37064)]
|
410
413
|
- Added keyContent component to theme.config [ichim-david - [`d86f202`](https://github.com/eea/volto-eea-website-theme/commit/d86f202d0274d839487a88b51cae9a0e899beb23)]
|
@@ -446,5 +449,4 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
446
449
|
|
447
450
|
#### :hammer_and_wrench: Others
|
448
451
|
|
449
|
-
- yarn bootstrap [Alin Voinea - [`6995e9e`](https://github.com/eea/volto-eea-website-theme/commit/6995e9e091f21fdbbdffa8a44fc0e2c626f6d46a)]
|
450
452
|
- Initial commit [Alin Voinea - [`6a9c03a`](https://github.com/eea/volto-eea-website-theme/commit/6a9c03a7cebe71ca87e82cf58c42904063e9d8d3)]
|
package/package.json
CHANGED
@@ -0,0 +1,408 @@
|
|
1
|
+
/**
|
2
|
+
* Edit image block.
|
3
|
+
* @module components/manage/Blocks/Image/Edit
|
4
|
+
*/
|
5
|
+
|
6
|
+
import React, { Component } from 'react';
|
7
|
+
import PropTypes from 'prop-types';
|
8
|
+
import { connect } from 'react-redux';
|
9
|
+
import { compose } from 'redux';
|
10
|
+
import { readAsDataURL } from 'promise-file-reader';
|
11
|
+
import { Button, Dimmer, Input, Loader, Message } from 'semantic-ui-react';
|
12
|
+
import { defineMessages, injectIntl } from 'react-intl';
|
13
|
+
import loadable from '@loadable/component';
|
14
|
+
import cx from 'classnames';
|
15
|
+
import { isEqual } from 'lodash';
|
16
|
+
|
17
|
+
import { Icon, ImageSidebar, SidebarPortal } from '@plone/volto/components';
|
18
|
+
import { Icon as IconSemantic } from 'semantic-ui-react';
|
19
|
+
import { withBlockExtensions } from '@plone/volto/helpers';
|
20
|
+
import { createContent } from '@plone/volto/actions';
|
21
|
+
import { Copyright } from '@eeacms/volto-eea-design-system/ui';
|
22
|
+
|
23
|
+
import {
|
24
|
+
flattenToAppURL,
|
25
|
+
getBaseUrl,
|
26
|
+
isInternalURL,
|
27
|
+
} from '@plone/volto/helpers';
|
28
|
+
|
29
|
+
import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
|
30
|
+
import clearSVG from '@plone/volto/icons/clear.svg';
|
31
|
+
import navTreeSVG from '@plone/volto/icons/nav.svg';
|
32
|
+
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
33
|
+
import uploadSVG from '@plone/volto/icons/upload.svg';
|
34
|
+
import './style.less';
|
35
|
+
const Dropzone = loadable(() => import('react-dropzone'));
|
36
|
+
|
37
|
+
const messages = defineMessages({
|
38
|
+
ImageBlockInputPlaceholder: {
|
39
|
+
id: 'Browse the site, drop an image, or type an URL',
|
40
|
+
defaultMessage: 'Browse the site, drop an image, or type an URL',
|
41
|
+
},
|
42
|
+
});
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Edit image block class.
|
46
|
+
* @class Edit
|
47
|
+
* @extends Component
|
48
|
+
*/
|
49
|
+
class Edit extends Component {
|
50
|
+
/**
|
51
|
+
* Property types.
|
52
|
+
* @property {Object} propTypes Property types.
|
53
|
+
* @static
|
54
|
+
*/
|
55
|
+
static propTypes = {
|
56
|
+
selected: PropTypes.bool.isRequired,
|
57
|
+
block: PropTypes.string.isRequired,
|
58
|
+
index: PropTypes.number.isRequired,
|
59
|
+
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
60
|
+
content: PropTypes.objectOf(PropTypes.any).isRequired,
|
61
|
+
request: PropTypes.shape({
|
62
|
+
loading: PropTypes.bool,
|
63
|
+
loaded: PropTypes.bool,
|
64
|
+
}).isRequired,
|
65
|
+
pathname: PropTypes.string.isRequired,
|
66
|
+
onChangeBlock: PropTypes.func.isRequired,
|
67
|
+
onSelectBlock: PropTypes.func.isRequired,
|
68
|
+
onDeleteBlock: PropTypes.func.isRequired,
|
69
|
+
onFocusPreviousBlock: PropTypes.func.isRequired,
|
70
|
+
onFocusNextBlock: PropTypes.func.isRequired,
|
71
|
+
handleKeyDown: PropTypes.func.isRequired,
|
72
|
+
createContent: PropTypes.func.isRequired,
|
73
|
+
openObjectBrowser: PropTypes.func.isRequired,
|
74
|
+
};
|
75
|
+
|
76
|
+
state = {
|
77
|
+
uploading: false,
|
78
|
+
url: '',
|
79
|
+
dragging: false,
|
80
|
+
};
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Component will receive props
|
84
|
+
* @method componentWillReceiveProps
|
85
|
+
* @param {Object} nextProps Next properties
|
86
|
+
* @returns {undefined}
|
87
|
+
*/
|
88
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
89
|
+
if (
|
90
|
+
this.props.request.loading &&
|
91
|
+
nextProps.request.loaded &&
|
92
|
+
this.state.uploading
|
93
|
+
) {
|
94
|
+
this.setState({
|
95
|
+
uploading: false,
|
96
|
+
});
|
97
|
+
this.props.onChangeBlock(this.props.block, {
|
98
|
+
...this.props.data,
|
99
|
+
url: nextProps.content['@id'],
|
100
|
+
alt: '',
|
101
|
+
});
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* @param {*} nextProps
|
107
|
+
* @returns {boolean}
|
108
|
+
* @memberof Edit
|
109
|
+
*/
|
110
|
+
shouldComponentUpdate(nextProps) {
|
111
|
+
return (
|
112
|
+
this.props.selected ||
|
113
|
+
nextProps.selected ||
|
114
|
+
!isEqual(this.props.data, nextProps.data)
|
115
|
+
);
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* Upload image handler (not used), but useful in case that we want a button
|
120
|
+
* not powered by react-dropzone
|
121
|
+
* @method onUploadImage
|
122
|
+
* @returns {undefined}
|
123
|
+
*/
|
124
|
+
onUploadImage = (e) => {
|
125
|
+
e.stopPropagation();
|
126
|
+
const file = e.target.files[0];
|
127
|
+
this.setState({
|
128
|
+
uploading: true,
|
129
|
+
});
|
130
|
+
readAsDataURL(file).then((data) => {
|
131
|
+
const fields = data.match(/^data:(.*);(.*),(.*)$/);
|
132
|
+
this.props.createContent(
|
133
|
+
getBaseUrl(this.props.pathname),
|
134
|
+
{
|
135
|
+
'@type': 'Image',
|
136
|
+
title: file.name,
|
137
|
+
image: {
|
138
|
+
data: fields[3],
|
139
|
+
encoding: fields[2],
|
140
|
+
'content-type': fields[1],
|
141
|
+
filename: file.name,
|
142
|
+
},
|
143
|
+
},
|
144
|
+
this.props.block,
|
145
|
+
);
|
146
|
+
});
|
147
|
+
};
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Change url handler
|
151
|
+
* @method onChangeUrl
|
152
|
+
* @param {Object} target Target object
|
153
|
+
* @returns {undefined}
|
154
|
+
*/
|
155
|
+
onChangeUrl = ({ target }) => {
|
156
|
+
this.setState({
|
157
|
+
url: target.value,
|
158
|
+
});
|
159
|
+
};
|
160
|
+
|
161
|
+
/**
|
162
|
+
* Submit url handler
|
163
|
+
* @method onSubmitUrl
|
164
|
+
* @param {object} e Event
|
165
|
+
* @returns {undefined}
|
166
|
+
*/
|
167
|
+
onSubmitUrl = () => {
|
168
|
+
this.props.onChangeBlock(this.props.block, {
|
169
|
+
...this.props.data,
|
170
|
+
url: flattenToAppURL(this.state.url),
|
171
|
+
});
|
172
|
+
};
|
173
|
+
|
174
|
+
/**
|
175
|
+
* Drop handler
|
176
|
+
* @method onDrop
|
177
|
+
* @param {array} files File objects
|
178
|
+
* @returns {undefined}
|
179
|
+
*/
|
180
|
+
onDrop = (file) => {
|
181
|
+
this.setState({
|
182
|
+
uploading: true,
|
183
|
+
});
|
184
|
+
|
185
|
+
readAsDataURL(file[0]).then((data) => {
|
186
|
+
const fields = data.match(/^data:(.*);(.*),(.*)$/);
|
187
|
+
this.props.createContent(
|
188
|
+
getBaseUrl(this.props.pathname),
|
189
|
+
{
|
190
|
+
'@type': 'Image',
|
191
|
+
title: file[0].name,
|
192
|
+
image: {
|
193
|
+
data: fields[3],
|
194
|
+
encoding: fields[2],
|
195
|
+
'content-type': fields[1],
|
196
|
+
filename: file[0].name,
|
197
|
+
},
|
198
|
+
},
|
199
|
+
this.props.block,
|
200
|
+
);
|
201
|
+
});
|
202
|
+
};
|
203
|
+
|
204
|
+
/**
|
205
|
+
* Keydown handler on Variant Menu Form
|
206
|
+
* This is required since the ENTER key is already mapped to a onKeyDown
|
207
|
+
* event and needs to be overriden with a child onKeyDown.
|
208
|
+
* @method onKeyDownVariantMenuForm
|
209
|
+
* @param {Object} e Event object
|
210
|
+
* @returns {undefined}
|
211
|
+
*/
|
212
|
+
onKeyDownVariantMenuForm = (e) => {
|
213
|
+
if (e.key === 'Enter') {
|
214
|
+
e.preventDefault();
|
215
|
+
e.stopPropagation();
|
216
|
+
this.onSubmitUrl();
|
217
|
+
} else if (e.key === 'Escape') {
|
218
|
+
e.preventDefault();
|
219
|
+
e.stopPropagation();
|
220
|
+
// TODO: Do something on ESC key
|
221
|
+
}
|
222
|
+
};
|
223
|
+
onDragEnter = () => {
|
224
|
+
this.setState({ dragging: true });
|
225
|
+
};
|
226
|
+
onDragLeave = () => {
|
227
|
+
this.setState({ dragging: false });
|
228
|
+
};
|
229
|
+
|
230
|
+
node = React.createRef();
|
231
|
+
|
232
|
+
/**
|
233
|
+
* Render method.
|
234
|
+
* @method render
|
235
|
+
* @returns {string} Markup for the component.
|
236
|
+
*/
|
237
|
+
render() {
|
238
|
+
const { data } = this.props;
|
239
|
+
const placeholder =
|
240
|
+
this.props.data.placeholder ||
|
241
|
+
this.props.intl.formatMessage(messages.ImageBlockInputPlaceholder);
|
242
|
+
const { copyright, copyrightIcon, copyrightPosition } = data;
|
243
|
+
return (
|
244
|
+
<div
|
245
|
+
className={cx(
|
246
|
+
'block image align',
|
247
|
+
{
|
248
|
+
center: !Boolean(data.align),
|
249
|
+
},
|
250
|
+
data.align,
|
251
|
+
)}
|
252
|
+
>
|
253
|
+
{data.url ? (
|
254
|
+
<div className="image-block">
|
255
|
+
<img
|
256
|
+
className={cx({
|
257
|
+
'full-width': data.align === 'full',
|
258
|
+
large: data.size === 'l',
|
259
|
+
medium: data.size === 'm',
|
260
|
+
small: data.size === 's',
|
261
|
+
})}
|
262
|
+
src={
|
263
|
+
isInternalURL(data.url)
|
264
|
+
? // Backwards compat in the case that the block is storing the full server URL
|
265
|
+
(() => {
|
266
|
+
if (data.size === 'l')
|
267
|
+
return `${flattenToAppURL(data.url)}/@@images/image`;
|
268
|
+
if (data.size === 'm')
|
269
|
+
return `${flattenToAppURL(
|
270
|
+
data.url,
|
271
|
+
)}/@@images/image/preview`;
|
272
|
+
if (data.size === 's')
|
273
|
+
return `${flattenToAppURL(
|
274
|
+
data.url,
|
275
|
+
)}/@@images/image/mini`;
|
276
|
+
return `${flattenToAppURL(data.url)}/@@images/image`;
|
277
|
+
})()
|
278
|
+
: data.url
|
279
|
+
}
|
280
|
+
alt={data.alt || ''}
|
281
|
+
/>
|
282
|
+
<div className="copyright-image">
|
283
|
+
{copyright ? (
|
284
|
+
<Copyright copyrightPosition={copyrightPosition}>
|
285
|
+
<Copyright.Icon>
|
286
|
+
<IconSemantic name={copyrightIcon} />
|
287
|
+
</Copyright.Icon>
|
288
|
+
<Copyright.Text>{copyright}</Copyright.Text>
|
289
|
+
</Copyright>
|
290
|
+
) : (
|
291
|
+
''
|
292
|
+
)}
|
293
|
+
</div>
|
294
|
+
</div>
|
295
|
+
) : (
|
296
|
+
<div>
|
297
|
+
{this.props.editable && (
|
298
|
+
<Dropzone
|
299
|
+
noClick
|
300
|
+
onDrop={this.onDrop}
|
301
|
+
onDragEnter={this.onDragEnter}
|
302
|
+
onDragLeave={this.onDragLeave}
|
303
|
+
className="dropzone"
|
304
|
+
>
|
305
|
+
{({ getRootProps, getInputProps }) => (
|
306
|
+
<div {...getRootProps()}>
|
307
|
+
<Message>
|
308
|
+
{this.state.dragging && <Dimmer active></Dimmer>}
|
309
|
+
{this.state.uploading && (
|
310
|
+
<Dimmer active>
|
311
|
+
<Loader indeterminate>Uploading image</Loader>
|
312
|
+
</Dimmer>
|
313
|
+
)}
|
314
|
+
<div className="no-image-wrapper">
|
315
|
+
<img src={imageBlockSVG} alt="" />
|
316
|
+
<div className="toolbar-inner">
|
317
|
+
<Button.Group>
|
318
|
+
<Button
|
319
|
+
basic
|
320
|
+
icon
|
321
|
+
onClick={(e) => {
|
322
|
+
e.stopPropagation();
|
323
|
+
e.preventDefault();
|
324
|
+
this.props.openObjectBrowser();
|
325
|
+
}}
|
326
|
+
>
|
327
|
+
<Icon name={navTreeSVG} size="24px" />
|
328
|
+
</Button>
|
329
|
+
</Button.Group>
|
330
|
+
<Button.Group>
|
331
|
+
<label className="ui button basic icon">
|
332
|
+
<Icon name={uploadSVG} size="24px" />
|
333
|
+
<input
|
334
|
+
{...getInputProps({
|
335
|
+
type: 'file',
|
336
|
+
onChange: this.onUploadImage,
|
337
|
+
style: { display: 'none' },
|
338
|
+
})}
|
339
|
+
/>
|
340
|
+
</label>
|
341
|
+
</Button.Group>
|
342
|
+
<Input
|
343
|
+
onKeyDown={this.onKeyDownVariantMenuForm}
|
344
|
+
onChange={this.onChangeUrl}
|
345
|
+
placeholder={placeholder}
|
346
|
+
value={this.state.url}
|
347
|
+
onClick={(e) => {
|
348
|
+
e.target.focus();
|
349
|
+
}}
|
350
|
+
onFocus={(e) => {
|
351
|
+
this.props.onSelectBlock(this.props.id);
|
352
|
+
}}
|
353
|
+
/>
|
354
|
+
{this.state.url && (
|
355
|
+
<Button.Group>
|
356
|
+
<Button
|
357
|
+
basic
|
358
|
+
className="cancel"
|
359
|
+
onClick={(e) => {
|
360
|
+
e.stopPropagation();
|
361
|
+
this.setState({ url: '' });
|
362
|
+
}}
|
363
|
+
>
|
364
|
+
<Icon name={clearSVG} size="30px" />
|
365
|
+
</Button>
|
366
|
+
</Button.Group>
|
367
|
+
)}
|
368
|
+
<Button.Group>
|
369
|
+
<Button
|
370
|
+
basic
|
371
|
+
primary
|
372
|
+
disabled={!this.state.url}
|
373
|
+
onClick={(e) => {
|
374
|
+
e.stopPropagation();
|
375
|
+
this.onSubmitUrl();
|
376
|
+
}}
|
377
|
+
>
|
378
|
+
<Icon name={aheadSVG} size="30px" />
|
379
|
+
</Button>
|
380
|
+
</Button.Group>
|
381
|
+
</div>
|
382
|
+
</div>
|
383
|
+
</Message>
|
384
|
+
</div>
|
385
|
+
)}
|
386
|
+
</Dropzone>
|
387
|
+
)}
|
388
|
+
</div>
|
389
|
+
)}
|
390
|
+
<SidebarPortal selected={this.props.selected}>
|
391
|
+
<ImageSidebar {...this.props} />
|
392
|
+
</SidebarPortal>
|
393
|
+
</div>
|
394
|
+
);
|
395
|
+
}
|
396
|
+
}
|
397
|
+
|
398
|
+
export default compose(
|
399
|
+
injectIntl,
|
400
|
+
withBlockExtensions,
|
401
|
+
connect(
|
402
|
+
(state, ownProps) => ({
|
403
|
+
request: state.content.subrequests[ownProps.block] || {},
|
404
|
+
content: state.content.subrequests[ownProps.block]?.data,
|
405
|
+
}),
|
406
|
+
{ createContent },
|
407
|
+
),
|
408
|
+
)(Edit);
|
@@ -0,0 +1,111 @@
|
|
1
|
+
/**
|
2
|
+
* View image block.
|
3
|
+
* @module components/manage/Blocks/Image/View
|
4
|
+
*/
|
5
|
+
|
6
|
+
import React from 'react';
|
7
|
+
import PropTypes from 'prop-types';
|
8
|
+
import { UniversalLink } from '@plone/volto/components';
|
9
|
+
import { Icon } from 'semantic-ui-react';
|
10
|
+
import cx from 'classnames';
|
11
|
+
import { withBlockExtensions } from '@plone/volto/helpers';
|
12
|
+
import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers';
|
13
|
+
import { Copyright } from '@eeacms/volto-eea-design-system/ui';
|
14
|
+
import './style.less';
|
15
|
+
/**
|
16
|
+
* View image block class.
|
17
|
+
* @class View
|
18
|
+
* @extends Component
|
19
|
+
*/
|
20
|
+
export const View = ({ data, detached }) => {
|
21
|
+
const href = data?.href?.[0]?.['@id'] || '';
|
22
|
+
const { copyright, copyrightIcon, copyrightPosition } = data;
|
23
|
+
return (
|
24
|
+
<p
|
25
|
+
className={cx(
|
26
|
+
'block image align',
|
27
|
+
{
|
28
|
+
center: !Boolean(data.align),
|
29
|
+
detached,
|
30
|
+
},
|
31
|
+
data.align,
|
32
|
+
)}
|
33
|
+
>
|
34
|
+
{data.url && (
|
35
|
+
<>
|
36
|
+
{(() => {
|
37
|
+
const image = (
|
38
|
+
<div className="image-block">
|
39
|
+
<img
|
40
|
+
className={cx({
|
41
|
+
'full-width': data.align === 'full',
|
42
|
+
large: data.size === 'l',
|
43
|
+
medium: data.size === 'm',
|
44
|
+
small: data.size === 's',
|
45
|
+
})}
|
46
|
+
src={
|
47
|
+
isInternalURL(data.url)
|
48
|
+
? // Backwards compat in the case that the block is storing the full server URL
|
49
|
+
(() => {
|
50
|
+
if (data.size === 'l')
|
51
|
+
return `${flattenToAppURL(
|
52
|
+
data.url,
|
53
|
+
)}/@@images/image`;
|
54
|
+
if (data.size === 'm')
|
55
|
+
return `${flattenToAppURL(
|
56
|
+
data.url,
|
57
|
+
)}/@@images/image/preview`;
|
58
|
+
if (data.size === 's')
|
59
|
+
return `${flattenToAppURL(
|
60
|
+
data.url,
|
61
|
+
)}/@@images/image/mini`;
|
62
|
+
return `${flattenToAppURL(data.url)}/@@images/image`;
|
63
|
+
})()
|
64
|
+
: data.url
|
65
|
+
}
|
66
|
+
alt={data.alt || ''}
|
67
|
+
loading="lazy"
|
68
|
+
/>
|
69
|
+
<div className="copyright-image">
|
70
|
+
{copyright ? (
|
71
|
+
<Copyright copyrightPosition={copyrightPosition}>
|
72
|
+
<Copyright.Icon>
|
73
|
+
<Icon className={copyrightIcon} />
|
74
|
+
</Copyright.Icon>
|
75
|
+
<Copyright.Text>{copyright}</Copyright.Text>
|
76
|
+
</Copyright>
|
77
|
+
) : (
|
78
|
+
''
|
79
|
+
)}
|
80
|
+
</div>
|
81
|
+
</div>
|
82
|
+
);
|
83
|
+
if (href) {
|
84
|
+
return (
|
85
|
+
<UniversalLink
|
86
|
+
href={href}
|
87
|
+
openLinkInNewTab={data.openLinkInNewTab}
|
88
|
+
>
|
89
|
+
{image}
|
90
|
+
</UniversalLink>
|
91
|
+
);
|
92
|
+
} else {
|
93
|
+
return image;
|
94
|
+
}
|
95
|
+
})()}
|
96
|
+
</>
|
97
|
+
)}
|
98
|
+
</p>
|
99
|
+
);
|
100
|
+
};
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Property types.
|
104
|
+
* @property {Object} propTypes Property types.
|
105
|
+
* @static
|
106
|
+
*/
|
107
|
+
View.propTypes = {
|
108
|
+
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
109
|
+
};
|
110
|
+
|
111
|
+
export default withBlockExtensions(View);
|