@eeacms/volto-eea-website-theme 1.4.2 → 1.5.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/CHANGELOG.md +16 -9
- package/package.json +1 -1
- package/src/components/theme/Banner/View.jsx +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/theme/Header/Header.jsx +2 -1
package/CHANGELOG.md
CHANGED
@@ -4,6 +4,22 @@ 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.1](https://github.com/eea/volto-eea-website-theme/compare/1.5.0...1.5.1) - 13 January 2023
|
8
|
+
|
9
|
+
#### :bug: Bug Fixes
|
10
|
+
|
11
|
+
- fix(++api++): o.filter - refs #157627 [Alin Voinea - [`bd5a3ac`](https://github.com/eea/volto-eea-website-theme/commit/bd5a3ac3fcfef3cdbc36cedc896bd33696521df4)]
|
12
|
+
- fix(++api++): TypeError: o.filter is not a function - refs #157627 [Alin Voinea - [`f955115`](https://github.com/eea/volto-eea-website-theme/commit/f955115e9ffcc09a0f68d20ec854309e8770cf0a)]
|
13
|
+
|
14
|
+
#### :hammer_and_wrench: Others
|
15
|
+
|
16
|
+
- For some reasons types is a string [Alin Voinea - [`3769a09`](https://github.com/eea/volto-eea-website-theme/commit/3769a0981181d5b633f3498daebbe96be8b4b833)]
|
17
|
+
- Fix(redirect): o.filter - refs #157627 [Alin Voinea - [`deb23da`](https://github.com/eea/volto-eea-website-theme/commit/deb23da846444cc96539697fd798429ae0abe89e)]
|
18
|
+
### [1.5.0](https://github.com/eea/volto-eea-website-theme/compare/1.4.2...1.5.0) - 9 January 2023
|
19
|
+
|
20
|
+
#### :hammer_and_wrench: Others
|
21
|
+
|
22
|
+
- Release 1.5.0 [Alin Voinea - [`1b87380`](https://github.com/eea/volto-eea-website-theme/commit/1b87380b5eb5cd7324b1816c08e932c52c7e107b)]
|
7
23
|
### [1.4.2](https://github.com/eea/volto-eea-website-theme/compare/1.4.1...1.4.2) - 29 December 2022
|
8
24
|
|
9
25
|
#### :bug: Bug Fixes
|
@@ -32,7 +48,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
32
48
|
|
33
49
|
- Release 1.4.0 [Alin Voinea - [`bd42a0d`](https://github.com/eea/volto-eea-website-theme/commit/bd42a0d26e928cac5d99933194755da3db06b341)]
|
34
50
|
- bump version to use as volto-eea-design-system [David Ichim - [`f4be047`](https://github.com/eea/volto-eea-website-theme/commit/f4be047328b46399b03b612d378b18aaf82e7dc1)]
|
35
|
-
- Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`9b7cfef`](https://github.com/eea/volto-eea-website-theme/commit/9b7cfefb4d34fc1c948015e491feb370f9795bd8)]
|
36
51
|
- test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`df252a9`](https://github.com/eea/volto-eea-website-theme/commit/df252a9bfed0bb86cadf53c59dd1603b1e2cd822)]
|
37
52
|
### [1.3.2](https://github.com/eea/volto-eea-website-theme/compare/1.3.1...1.3.2) - 16 December 2022
|
38
53
|
|
@@ -42,7 +57,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
42
57
|
|
43
58
|
#### :hammer_and_wrench: Others
|
44
59
|
|
45
|
-
- Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`a43c658`](https://github.com/eea/volto-eea-website-theme/commit/a43c658a7920c8df95e763b9a637f38ce77eba2c)]
|
46
60
|
- Better razzle.config [Tiberiu Ichim - [`81dbf48`](https://github.com/eea/volto-eea-website-theme/commit/81dbf48815fb27facb4f82c9b764540fdf188b2e)]
|
47
61
|
- Better razzle.config [Tiberiu Ichim - [`7bc9da2`](https://github.com/eea/volto-eea-website-theme/commit/7bc9da2cd837ab62a95cd29979cdd9b0055b7d67)]
|
48
62
|
### [1.3.1](https://github.com/eea/volto-eea-website-theme/compare/1.3.0...1.3.1) - 28 November 2022
|
@@ -51,9 +65,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
51
65
|
|
52
66
|
- feat(Footer): Bring back footer contacts extra actions - refs #151856 [Alin Voinea - [`6c19413`](https://github.com/eea/volto-eea-website-theme/commit/6c194139420c9fd847692d180db1c1593e2483de)]
|
53
67
|
|
54
|
-
#### :hammer_and_wrench: Others
|
55
|
-
|
56
|
-
- yarn 3 [Alin Voinea - [`ea7a709`](https://github.com/eea/volto-eea-website-theme/commit/ea7a7094945312776e9b6f44e371178603e92139)]
|
57
68
|
### [1.3.0](https://github.com/eea/volto-eea-website-theme/compare/1.2.0...1.3.0) - 22 November 2022
|
58
69
|
|
59
70
|
#### :rocket: New Features
|
@@ -94,7 +105,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
94
105
|
- Add subsite class to body [Tiberiu Ichim - [`74d700f`](https://github.com/eea/volto-eea-website-theme/commit/74d700fbfd6249a8604762a7e4e49cce857db0f3)]
|
95
106
|
- Add subsite info to header [Tiberiu Ichim - [`47daf8b`](https://github.com/eea/volto-eea-website-theme/commit/47daf8bb6374a1222040626b19d4154df7ba1b83)]
|
96
107
|
- fix eslint [Miu Razvan - [`eb8d0a7`](https://github.com/eea/volto-eea-website-theme/commit/eb8d0a790bc70c0aae256c6ff35f63c4885f338e)]
|
97
|
-
- Add Sonarqube tag using circularity-frontend addons list [EEA Jenkins - [`cc578a4`](https://github.com/eea/volto-eea-website-theme/commit/cc578a413b205a8e61e091fab3a88f94cedefc89)]
|
98
108
|
### [1.1.0](https://github.com/eea/volto-eea-website-theme/compare/1.0.0...1.1.0) - 28 October 2022
|
99
109
|
|
100
110
|
#### :nail_care: Enhancements
|
@@ -142,7 +152,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
142
152
|
|
143
153
|
#### :hammer_and_wrench: Others
|
144
154
|
|
145
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`33b56ac`](https://github.com/eea/volto-eea-website-theme/commit/33b56acb13fbaf0c5b79e8fc6e13c4b699c79c90)]
|
146
155
|
### [0.7.3](https://github.com/eea/volto-eea-website-theme/compare/0.7.2...0.7.3) - 22 September 2022
|
147
156
|
|
148
157
|
#### :hammer_and_wrench: Others
|
@@ -410,7 +419,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
410
419
|
- Header refactor, add custom logo #5 [ichim-david - [`4950235`](https://github.com/eea/volto-eea-website-theme/commit/49502358105437cfeac3b144e6d301cb59aa2346)]
|
411
420
|
- Update footer.config with new publication card component [ichim-david - [`2e38e9a`](https://github.com/eea/volto-eea-website-theme/commit/2e38e9a417f835009d60c80d4eb4b30229f55e45)]
|
412
421
|
- 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)]
|
413
|
-
- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`da8ceb6`](https://github.com/eea/volto-eea-website-theme/commit/da8ceb68ea68bfbc9504e48ccd4d68277f11ab9a)]
|
414
422
|
- use breadcrumbs from eea-design-system [nileshgulia1 - [`db2f9e9`](https://github.com/eea/volto-eea-website-theme/commit/db2f9e9a4327420a3cce9a9903cd88549b129eab)]
|
415
423
|
- Update theme.config [ichim-david - [`8eca4f4`](https://github.com/eea/volto-eea-website-theme/commit/8eca4f40397a4aeca6d39029c92db78968d37064)]
|
416
424
|
- Added keyContent component to theme.config [ichim-david - [`d86f202`](https://github.com/eea/volto-eea-website-theme/commit/d86f202d0274d839487a88b51cae9a0e899beb23)]
|
@@ -452,5 +460,4 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
452
460
|
|
453
461
|
#### :hammer_and_wrench: Others
|
454
462
|
|
455
|
-
- yarn bootstrap [Alin Voinea - [`6995e9e`](https://github.com/eea/volto-eea-website-theme/commit/6995e9e091f21fdbbdffa8a44fc0e2c626f6d46a)]
|
456
463
|
- 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);
|