@kitconcept/volto-light-theme 4.0.1 → 5.0.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.draft +11 -6
- package/.release-it.json +3 -0
- package/CHANGELOG.md +16 -0
- package/README.md +38 -18
- package/package.json +1 -1
- package/src/components/Blocks/Image/Edit.jsx +53 -380
package/.changelog.draft
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
##
|
|
1
|
+
## 5.0.0 (2024-07-02)
|
|
2
2
|
|
|
3
|
-
###
|
|
3
|
+
### Breaking
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
- Fix install in Volto 17 @sneridagh [#400](https://github.com/kitconcept/volto-light-theme/pull/400)
|
|
5
|
+
- Upgrade to a39, enable new image widget @sneridagh
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
Breaking:
|
|
8
|
+
The new Image widget component is used in the VLT shadowed image component.
|
|
9
|
+
The minimum Volto version requirements have changed for this reason.
|
|
10
|
+
The new image widget is present in core from these versions on:
|
|
11
|
+
- Volto 17.18.0
|
|
12
|
+
- Volto 18.0.0-alpha.36
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
For more information, please take a look at the upgrade guide:
|
|
15
|
+
https://github.com/kitconcept/volto-light-theme/blob/main/UPGRADE-GUIDE.md [#405](https://github.com/kitconcept/volto-light-theme/pull/405)
|
|
11
16
|
|
|
12
17
|
|
package/.release-it.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,22 @@
|
|
|
8
8
|
|
|
9
9
|
<!-- towncrier release notes start -->
|
|
10
10
|
|
|
11
|
+
## 5.0.0 (2024-07-02)
|
|
12
|
+
|
|
13
|
+
### Breaking
|
|
14
|
+
|
|
15
|
+
- Upgrade to a39, enable new image widget @sneridagh
|
|
16
|
+
|
|
17
|
+
Breaking:
|
|
18
|
+
The new Image widget component is used in the VLT shadowed image component.
|
|
19
|
+
The minimum Volto version requirements have changed for this reason.
|
|
20
|
+
The new image widget is present in core from these versions on:
|
|
21
|
+
- Volto 17.18.0
|
|
22
|
+
- Volto 18.0.0-alpha.36
|
|
23
|
+
|
|
24
|
+
For more information, please take a look at the upgrade guide:
|
|
25
|
+
https://github.com/kitconcept/volto-light-theme/blob/main/UPGRADE-GUIDE.md [#405](https://github.com/kitconcept/volto-light-theme/pull/405)
|
|
26
|
+
|
|
11
27
|
## 4.0.1 (2024-06-28)
|
|
12
28
|
|
|
13
29
|
### Bugfix
|
package/README.md
CHANGED
|
@@ -232,17 +232,24 @@ They will be noted properly in the changelog.
|
|
|
232
232
|
|
|
233
233
|
See a detailed upgrade guide in: https://github.com/kitconcept/volto-light-theme/blob/main/UPGRADE-GUIDE.md
|
|
234
234
|
|
|
235
|
-
##
|
|
235
|
+
## Compatibility
|
|
236
|
+
|
|
237
|
+
| VLT version | Volto version |
|
|
238
|
+
|-------------|---------------|
|
|
239
|
+
| 3.x.x | >= Volto 17.0.0-alpha.16 |
|
|
240
|
+
| 4.x.x | < Volto 17.18.0 |
|
|
241
|
+
| 5.x.x | >= Volto 17.18.0 or >=Volto 18.0.0-alpha.36 |
|
|
236
242
|
|
|
237
|
-
|
|
238
|
-
Compatibility with Volto 16 might be achieved, but it has to be at customization level in the
|
|
239
|
-
specific project add-on.
|
|
243
|
+
Compatibility with Volto 16 might be achieved, but it has to be at customization level in the specific project add-on.
|
|
240
244
|
This is mainly due to the `RenderBlocks` customization that is based in the one in 17 because of the Grid block in core and the autogrouping feature.
|
|
241
245
|
See more information about the other dependencies in `peerDependencies` in `package.json`.
|
|
246
|
+
|
|
247
|
+
## Development
|
|
248
|
+
|
|
242
249
|
The development of this add-on is done in isolation using a new approach using pnpm workspaces and latest `mrs-developer` and other Volto core improvements.
|
|
243
250
|
For this reason, it only works with pnpm and Volto 18 (currently in alpha) but it does not mean that the add-on will only work in 18.
|
|
244
251
|
|
|
245
|
-
###
|
|
252
|
+
### Development requisites
|
|
246
253
|
|
|
247
254
|
- Volto 18 (2024-03-21: currently in alpha)
|
|
248
255
|
- pnpm as package manager
|
|
@@ -252,19 +259,32 @@ For this reason, it only works with pnpm and Volto 18 (currently in alpha) but i
|
|
|
252
259
|
Run `make help` to list the available commands.
|
|
253
260
|
|
|
254
261
|
```text
|
|
255
|
-
help
|
|
256
|
-
install
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
test
|
|
267
|
-
test
|
|
262
|
+
help Show this help
|
|
263
|
+
install Installs the add-on in a development environment
|
|
264
|
+
start Starts Volto, allowing reloading of the add-on during development
|
|
265
|
+
build Build a production bundle for distribution of the project with the add-on
|
|
266
|
+
build-deps Build dependencies
|
|
267
|
+
i18n Sync i18n
|
|
268
|
+
ci-i18n Check if i18n is not synced
|
|
269
|
+
format Format codebase
|
|
270
|
+
lint Lint, or catch and remove problems, in code base
|
|
271
|
+
release Release the add-on on npmjs.org
|
|
272
|
+
release-dry-run Dry-run the release of the add-on on npmjs.org
|
|
273
|
+
test Run unit tests
|
|
274
|
+
ci-test Run unit tests in CI
|
|
275
|
+
backend-docker-start Starts a Docker-based backend for development
|
|
276
|
+
storybook-start Start Storybook server on port 6006
|
|
277
|
+
storybook-build Build Storybook
|
|
278
|
+
acceptance-frontend-dev-start Start acceptance frontend in development mode
|
|
279
|
+
acceptance-frontend-prod-start Start acceptance frontend in production mode
|
|
280
|
+
acceptance-backend-start Start backend acceptance server
|
|
281
|
+
ci-acceptance-backend-start Start backend acceptance server in headless mode for CI
|
|
282
|
+
acceptance-test Start Cypress in interactive mode
|
|
283
|
+
ci-acceptance-test Run cypress tests in headless mode for CI
|
|
284
|
+
acceptance-a11y-frontend-prod-start Start a11y acceptance frontend in prod mode
|
|
285
|
+
ci-acceptance-a11y-backend-start Start acceptance a11y server in CI mode (no terminal attached)
|
|
286
|
+
acceptance-a11y-test Start a11y Cypress in interactive mode
|
|
287
|
+
ci-acceptance-a11y-test Run a11y cypress tests in headless mode for CI
|
|
268
288
|
```
|
|
269
289
|
|
|
270
290
|
### Development Environment Setup
|
package/package.json
CHANGED
|
@@ -1,275 +1,52 @@
|
|
|
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';
|
|
1
|
+
import React from 'react';
|
|
14
2
|
import cx from 'classnames';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
import Caption from '../../Caption/Caption';
|
|
3
|
+
import { ImageSidebar, SidebarPortal } from '@plone/volto/components';
|
|
18
4
|
|
|
19
|
-
import { Icon, ImageSidebar, SidebarPortal } from '@plone/volto/components';
|
|
20
|
-
import { createContent } from '@plone/volto/actions';
|
|
21
5
|
import {
|
|
22
6
|
flattenToAppURL,
|
|
23
|
-
getBaseUrl,
|
|
24
7
|
isInternalURL,
|
|
25
8
|
withBlockExtensions,
|
|
26
|
-
validateFileUploadSize,
|
|
27
9
|
} from '@plone/volto/helpers';
|
|
28
10
|
import config from '@plone/volto/registry';
|
|
29
11
|
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
import navTreeSVG from '@plone/volto/icons/nav.svg';
|
|
33
|
-
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
34
|
-
import uploadSVG from '@plone/volto/icons/upload.svg';
|
|
35
|
-
|
|
36
|
-
const Dropzone = loadable(() => import('react-dropzone'));
|
|
37
|
-
|
|
38
|
-
const messages = defineMessages({
|
|
39
|
-
ImageBlockInputPlaceholder: {
|
|
40
|
-
id: 'Browse the site, drop an image, or type an URL',
|
|
41
|
-
defaultMessage: 'Browse the site, drop an image, or type an URL',
|
|
42
|
-
},
|
|
43
|
-
uploadingImage: {
|
|
44
|
-
id: 'Uploading image',
|
|
45
|
-
defaultMessage: 'Uploading image',
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Edit image block class.
|
|
51
|
-
* @class Edit
|
|
52
|
-
* @extends Component
|
|
53
|
-
*/
|
|
54
|
-
class Edit extends Component {
|
|
55
|
-
/**
|
|
56
|
-
* Property types.
|
|
57
|
-
* @property {Object} propTypes Property types.
|
|
58
|
-
* @static
|
|
59
|
-
*/
|
|
60
|
-
static propTypes = {
|
|
61
|
-
selected: PropTypes.bool.isRequired,
|
|
62
|
-
block: PropTypes.string.isRequired,
|
|
63
|
-
index: PropTypes.number.isRequired,
|
|
64
|
-
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
65
|
-
content: PropTypes.objectOf(PropTypes.any),
|
|
66
|
-
request: PropTypes.shape({
|
|
67
|
-
loading: PropTypes.bool,
|
|
68
|
-
loaded: PropTypes.bool,
|
|
69
|
-
}).isRequired,
|
|
70
|
-
pathname: PropTypes.string.isRequired,
|
|
71
|
-
onChangeBlock: PropTypes.func.isRequired,
|
|
72
|
-
onSelectBlock: PropTypes.func.isRequired,
|
|
73
|
-
onDeleteBlock: PropTypes.func.isRequired,
|
|
74
|
-
onFocusPreviousBlock: PropTypes.func.isRequired,
|
|
75
|
-
onFocusNextBlock: PropTypes.func.isRequired,
|
|
76
|
-
handleKeyDown: PropTypes.func.isRequired,
|
|
77
|
-
createContent: PropTypes.func.isRequired,
|
|
78
|
-
openObjectBrowser: PropTypes.func.isRequired,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
state = {
|
|
82
|
-
uploading: false,
|
|
83
|
-
url: '',
|
|
84
|
-
dragging: false,
|
|
85
|
-
};
|
|
12
|
+
import { ImageInput } from '@plone/volto/components/manage/Widgets/ImageWidget';
|
|
13
|
+
import Caption from '../../Caption/Caption';
|
|
86
14
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.setState({
|
|
101
|
-
uploading: false,
|
|
15
|
+
function Edit(props) {
|
|
16
|
+
const { data } = props;
|
|
17
|
+
const Image = config.getComponent({ name: 'Image' }).component;
|
|
18
|
+
const onSelectItem = React.useCallback(
|
|
19
|
+
(url, item) => {
|
|
20
|
+
const dataAdapter = props.blocksConfig[props.data['@type']].dataAdapter;
|
|
21
|
+
dataAdapter({
|
|
22
|
+
block: props.block,
|
|
23
|
+
data: props.data,
|
|
24
|
+
onChangeBlock: props.onChangeBlock,
|
|
25
|
+
id: 'url',
|
|
26
|
+
value: url,
|
|
27
|
+
item,
|
|
102
28
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
29
|
+
},
|
|
30
|
+
[props],
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const handleChange = React.useCallback(
|
|
34
|
+
async (id, image, { title, image_field, image_scales } = {}) => {
|
|
35
|
+
const url = image ? image['@id'] || image : '';
|
|
36
|
+
|
|
37
|
+
props.onChangeBlock(props.block, {
|
|
38
|
+
...props.data,
|
|
39
|
+
url: flattenToAppURL(url),
|
|
40
|
+
image_field,
|
|
41
|
+
image_scales,
|
|
42
|
+
alt: props.data.alt || title || '',
|
|
109
43
|
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @param {*} nextProps
|
|
115
|
-
* @returns {boolean}
|
|
116
|
-
* @memberof Edit
|
|
117
|
-
*/
|
|
118
|
-
shouldComponentUpdate(nextProps) {
|
|
119
|
-
return (
|
|
120
|
-
this.props.selected ||
|
|
121
|
-
nextProps.selected ||
|
|
122
|
-
!isEqual(this.props.data, nextProps.data)
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Upload image handler (not used), but useful in case that we want a button
|
|
128
|
-
* not powered by react-dropzone
|
|
129
|
-
* @method onUploadImage
|
|
130
|
-
* @returns {undefined}
|
|
131
|
-
*/
|
|
132
|
-
onUploadImage = (e) => {
|
|
133
|
-
e.stopPropagation();
|
|
134
|
-
const file = e.target.files[0];
|
|
135
|
-
if (!validateFileUploadSize(file, this.props.intl.formatMessage)) return;
|
|
136
|
-
this.setState({
|
|
137
|
-
uploading: true,
|
|
138
|
-
});
|
|
139
|
-
readAsDataURL(file).then((data) => {
|
|
140
|
-
const fields = data.match(/^data:(.*);(.*),(.*)$/);
|
|
141
|
-
this.props.createContent(
|
|
142
|
-
getBaseUrl(this.props.pathname),
|
|
143
|
-
{
|
|
144
|
-
'@type': 'Image',
|
|
145
|
-
title: file.name,
|
|
146
|
-
image: {
|
|
147
|
-
data: fields[3],
|
|
148
|
-
encoding: fields[2],
|
|
149
|
-
'content-type': fields[1],
|
|
150
|
-
filename: file.name,
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
this.props.block,
|
|
154
|
-
);
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Change url handler
|
|
160
|
-
* @method onChangeUrl
|
|
161
|
-
* @param {Object} target Target object
|
|
162
|
-
* @returns {undefined}
|
|
163
|
-
*/
|
|
164
|
-
onChangeUrl = ({ target }) => {
|
|
165
|
-
this.setState({
|
|
166
|
-
url: target.value,
|
|
167
|
-
});
|
|
168
|
-
};
|
|
44
|
+
},
|
|
45
|
+
[props],
|
|
46
|
+
);
|
|
169
47
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
* @method onSubmitUrl
|
|
173
|
-
* @param {object} e Event
|
|
174
|
-
* @returns {undefined}
|
|
175
|
-
*/
|
|
176
|
-
onSubmitUrl = () => {
|
|
177
|
-
this.props.onChangeBlock(this.props.block, {
|
|
178
|
-
...this.props.data,
|
|
179
|
-
url: flattenToAppURL(this.state.url),
|
|
180
|
-
});
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Drop handler
|
|
185
|
-
* @method onDrop
|
|
186
|
-
* @param {array} files File objects
|
|
187
|
-
* @returns {undefined}
|
|
188
|
-
*/
|
|
189
|
-
onDrop = (files) => {
|
|
190
|
-
if (!validateFileUploadSize(files[0], this.props.intl.formatMessage)) {
|
|
191
|
-
this.setState({ dragging: false });
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
this.setState({ uploading: true });
|
|
195
|
-
|
|
196
|
-
readAsDataURL(files[0]).then((data) => {
|
|
197
|
-
const fields = data.match(/^data:(.*);(.*),(.*)$/);
|
|
198
|
-
this.props.createContent(
|
|
199
|
-
getBaseUrl(this.props.pathname),
|
|
200
|
-
{
|
|
201
|
-
'@type': 'Image',
|
|
202
|
-
title: files[0].name,
|
|
203
|
-
image: {
|
|
204
|
-
data: fields[3],
|
|
205
|
-
encoding: fields[2],
|
|
206
|
-
'content-type': fields[1],
|
|
207
|
-
filename: files[0].name,
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
this.props.block,
|
|
211
|
-
);
|
|
212
|
-
});
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Keydown handler on Variant Menu Form
|
|
217
|
-
* This is required since the ENTER key is already mapped to a onKeyDown
|
|
218
|
-
* event and needs to be overriden with a child onKeyDown.
|
|
219
|
-
* @method onKeyDownVariantMenuForm
|
|
220
|
-
* @param {Object} e Event object
|
|
221
|
-
* @returns {undefined}
|
|
222
|
-
*/
|
|
223
|
-
onKeyDownVariantMenuForm = (e) => {
|
|
224
|
-
if (e.key === 'Enter') {
|
|
225
|
-
e.preventDefault();
|
|
226
|
-
e.stopPropagation();
|
|
227
|
-
this.onSubmitUrl();
|
|
228
|
-
} else if (e.key === 'Escape') {
|
|
229
|
-
e.preventDefault();
|
|
230
|
-
e.stopPropagation();
|
|
231
|
-
// TODO: Do something on ESC key
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
onDragEnter = () => {
|
|
235
|
-
this.setState({ dragging: true });
|
|
236
|
-
};
|
|
237
|
-
onDragLeave = () => {
|
|
238
|
-
this.setState({ dragging: false });
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
node = React.createRef();
|
|
242
|
-
|
|
243
|
-
// START CUSTOMIZATION - Add custom dataAdapter
|
|
244
|
-
// It has to be a class method because if used directly we have closure issues while
|
|
245
|
-
// passing arguments to the dataAdapter function
|
|
246
|
-
onSelectItem = (url, item) => {
|
|
247
|
-
const dataAdapter =
|
|
248
|
-
this.props.blocksConfig[this.props.data['@type']].dataAdapter;
|
|
249
|
-
dataAdapter({
|
|
250
|
-
block: this.props.block,
|
|
251
|
-
data: this.props.data,
|
|
252
|
-
onChangeBlock: this.props.onChangeBlock,
|
|
253
|
-
id: 'url',
|
|
254
|
-
value: url,
|
|
255
|
-
item,
|
|
256
|
-
});
|
|
257
|
-
};
|
|
258
|
-
// END CUSTOMIZATION - Add custom dataAdapter
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Render method.
|
|
262
|
-
* @method render
|
|
263
|
-
* @returns {string} Markup for the component.
|
|
264
|
-
*/
|
|
265
|
-
render() {
|
|
266
|
-
const Image = config.getComponent({ name: 'Image' }).component;
|
|
267
|
-
const { data } = this.props;
|
|
268
|
-
const placeholder =
|
|
269
|
-
this.props.data.placeholder ||
|
|
270
|
-
this.props.intl.formatMessage(messages.ImageBlockInputPlaceholder);
|
|
271
|
-
|
|
272
|
-
return (
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
273
50
|
<div
|
|
274
51
|
className={cx(
|
|
275
52
|
'block image align',
|
|
@@ -280,7 +57,6 @@ class Edit extends Component {
|
|
|
280
57
|
)}
|
|
281
58
|
>
|
|
282
59
|
{data.url ? (
|
|
283
|
-
// START CUSTOMIZATION - Added `figure` tag
|
|
284
60
|
<figure
|
|
285
61
|
className={cx(
|
|
286
62
|
'figure',
|
|
@@ -299,13 +75,14 @@ class Edit extends Component {
|
|
|
299
75
|
)}
|
|
300
76
|
>
|
|
301
77
|
<Image
|
|
302
|
-
//
|
|
78
|
+
// START CUSTOMIZATION - Moved to the figure
|
|
303
79
|
// className={cx({
|
|
304
80
|
// 'full-width': data.align === 'full',
|
|
305
81
|
// large: data.size === 'l',
|
|
306
|
-
// medium: data.size === 'm'
|
|
82
|
+
// medium: data.size === 'm',
|
|
307
83
|
// small: data.size === 's',
|
|
308
84
|
// })}
|
|
85
|
+
// END CUSTOMIZATION
|
|
309
86
|
item={
|
|
310
87
|
data.image_scales
|
|
311
88
|
? {
|
|
@@ -328,9 +105,7 @@ class Edit extends Component {
|
|
|
328
105
|
data.url,
|
|
329
106
|
)}/@@images/image/preview`;
|
|
330
107
|
if (data.size === 's')
|
|
331
|
-
return `${flattenToAppURL(
|
|
332
|
-
data.url,
|
|
333
|
-
)}/@@images/image/mini`;
|
|
108
|
+
return `${flattenToAppURL(data.url)}/@@images/image/mini`;
|
|
334
109
|
return `${flattenToAppURL(data.url)}/@@images/image`;
|
|
335
110
|
})()
|
|
336
111
|
: data.url
|
|
@@ -345,125 +120,23 @@ class Edit extends Component {
|
|
|
345
120
|
description={data.description}
|
|
346
121
|
credit={data?.copyright_and_sources ?? data.credit?.data}
|
|
347
122
|
/>
|
|
348
|
-
{/* // END CUSTOMIZATION - Added `figure` tag */}
|
|
349
123
|
</figure>
|
|
350
124
|
) : (
|
|
351
|
-
<
|
|
352
|
-
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
>
|
|
360
|
-
{({ getRootProps, getInputProps }) => (
|
|
361
|
-
<div {...getRootProps()}>
|
|
362
|
-
<Message>
|
|
363
|
-
{this.state.dragging && <Dimmer active></Dimmer>}
|
|
364
|
-
{this.state.uploading && (
|
|
365
|
-
<Dimmer active>
|
|
366
|
-
<Loader indeterminate>
|
|
367
|
-
{this.props.intl.formatMessage(
|
|
368
|
-
messages.uploadingImage,
|
|
369
|
-
)}
|
|
370
|
-
</Loader>
|
|
371
|
-
</Dimmer>
|
|
372
|
-
)}
|
|
373
|
-
<div className="no-image-wrapper">
|
|
374
|
-
<img src={imageBlockSVG} alt="" />
|
|
375
|
-
<div className="toolbar-inner">
|
|
376
|
-
<Button.Group>
|
|
377
|
-
<Button
|
|
378
|
-
basic
|
|
379
|
-
icon
|
|
380
|
-
onClick={(e) => {
|
|
381
|
-
e.stopPropagation();
|
|
382
|
-
e.preventDefault();
|
|
383
|
-
this.props.openObjectBrowser({
|
|
384
|
-
onSelectItem: this.onSelectItem,
|
|
385
|
-
});
|
|
386
|
-
}}
|
|
387
|
-
>
|
|
388
|
-
<Icon name={navTreeSVG} size="24px" />
|
|
389
|
-
</Button>
|
|
390
|
-
</Button.Group>
|
|
391
|
-
<Button.Group>
|
|
392
|
-
<label className="ui button basic icon">
|
|
393
|
-
<Icon name={uploadSVG} size="24px" />
|
|
394
|
-
<input
|
|
395
|
-
{...getInputProps({
|
|
396
|
-
type: 'file',
|
|
397
|
-
onChange: this.onUploadImage,
|
|
398
|
-
style: { display: 'none' },
|
|
399
|
-
})}
|
|
400
|
-
/>
|
|
401
|
-
</label>
|
|
402
|
-
</Button.Group>
|
|
403
|
-
<Input
|
|
404
|
-
onKeyDown={this.onKeyDownVariantMenuForm}
|
|
405
|
-
onChange={this.onChangeUrl}
|
|
406
|
-
placeholder={placeholder}
|
|
407
|
-
value={this.state.url}
|
|
408
|
-
onClick={(e) => {
|
|
409
|
-
e.target.focus();
|
|
410
|
-
}}
|
|
411
|
-
onFocus={(e) => {
|
|
412
|
-
this.props.onSelectBlock(this.props.id);
|
|
413
|
-
}}
|
|
414
|
-
/>
|
|
415
|
-
{this.state.url && (
|
|
416
|
-
<Button.Group>
|
|
417
|
-
<Button
|
|
418
|
-
basic
|
|
419
|
-
className="cancel"
|
|
420
|
-
onClick={(e) => {
|
|
421
|
-
e.stopPropagation();
|
|
422
|
-
this.setState({ url: '' });
|
|
423
|
-
}}
|
|
424
|
-
>
|
|
425
|
-
<Icon name={clearSVG} size="30px" />
|
|
426
|
-
</Button>
|
|
427
|
-
</Button.Group>
|
|
428
|
-
)}
|
|
429
|
-
<Button.Group>
|
|
430
|
-
<Button
|
|
431
|
-
basic
|
|
432
|
-
primary
|
|
433
|
-
disabled={!this.state.url}
|
|
434
|
-
onClick={(e) => {
|
|
435
|
-
e.stopPropagation();
|
|
436
|
-
this.onSubmitUrl();
|
|
437
|
-
}}
|
|
438
|
-
>
|
|
439
|
-
<Icon name={aheadSVG} size="30px" />
|
|
440
|
-
</Button>
|
|
441
|
-
</Button.Group>
|
|
442
|
-
</div>
|
|
443
|
-
</div>
|
|
444
|
-
</Message>
|
|
445
|
-
</div>
|
|
446
|
-
)}
|
|
447
|
-
</Dropzone>
|
|
448
|
-
)}
|
|
449
|
-
</div>
|
|
125
|
+
<ImageInput
|
|
126
|
+
onChange={handleChange}
|
|
127
|
+
placeholderLinkInput={data.placeholder}
|
|
128
|
+
block={props.block}
|
|
129
|
+
id={props.block}
|
|
130
|
+
objectBrowserPickerType={'image'}
|
|
131
|
+
onSelectItem={onSelectItem}
|
|
132
|
+
/>
|
|
450
133
|
)}
|
|
451
|
-
<SidebarPortal selected={
|
|
452
|
-
<ImageSidebar {...
|
|
134
|
+
<SidebarPortal selected={props.selected}>
|
|
135
|
+
<ImageSidebar {...props} />
|
|
453
136
|
</SidebarPortal>
|
|
454
137
|
</div>
|
|
455
|
-
|
|
456
|
-
|
|
138
|
+
</>
|
|
139
|
+
);
|
|
457
140
|
}
|
|
458
141
|
|
|
459
|
-
export default
|
|
460
|
-
injectIntl,
|
|
461
|
-
withBlockExtensions,
|
|
462
|
-
connect(
|
|
463
|
-
(state, ownProps) => ({
|
|
464
|
-
request: state.content.subrequests[ownProps.block] || {},
|
|
465
|
-
content: state.content.subrequests[ownProps.block]?.data,
|
|
466
|
-
}),
|
|
467
|
-
{ createContent },
|
|
468
|
-
),
|
|
469
|
-
)(Edit);
|
|
142
|
+
export default withBlockExtensions(Edit);
|