@plone/volto 18.6.0 → 18.8.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 +53 -0
- package/cypress/support/commands.js +22 -0
- package/locales/nl/LC_MESSAGES/volto.po +9 -9
- package/locales/nl.json +1 -1
- package/package.json +4 -4
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +6 -4
- package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +1 -0
- package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +18 -14
- package/src/components/manage/Controlpanels/Relations/Relations.jsx +48 -46
- package/src/components/manage/Toolbar/More.jsx +113 -117
- package/src/components/manage/Toolbar/More.test.jsx +0 -24
- package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +15 -2
- package/src/components/manage/Widgets/RegistryImageWidget.jsx +15 -16
- package/src/components/manage/WorkingCopyToastsFactory/WorkingCopyToastsFactory.jsx +53 -56
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +23 -0
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +135 -0
- package/src/components/theme/Image/Image.jsx +8 -1
- package/src/components/theme/View/View.jsx +2 -0
- package/src/config/ControlPanels.js +0 -1
- package/src/config/index.js +0 -1
- package/src/express-middleware/robotstxt.js +4 -5
- package/src/helpers/Api/Api.js +1 -1
- package/src/helpers/Blocks/Blocks.js +26 -4
- package/src/helpers/Blocks/Blocks.test.js +46 -0
- package/src/helpers/FormValidation/validators.ts +3 -1
- package/src/helpers/Robots/Robots.js +12 -31
- package/src/hooks/clipboard/useClipboard.js +7 -3
- package/types/components/manage/Widgets/ObjectBrowserWidget.d.ts +1 -0
- package/types/components/theme/AlternateHrefLangs/AlternateHrefLangs.d.ts +1 -0
- package/types/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.d.ts +1 -0
- package/types/helpers/Api/Api.d.ts +7 -0
- package/types/helpers/Blocks/Blocks.d.ts +15 -5
- package/public/robots.txt +0 -2
|
@@ -60,22 +60,26 @@ const BrokenRelations = () => {
|
|
|
60
60
|
}).map((el, index) => (
|
|
61
61
|
<Table.Row key={index}>
|
|
62
62
|
<Table.Cell>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
{el[0] && (
|
|
64
|
+
<ConditionalLink
|
|
65
|
+
to={`${el[0]}/edit`}
|
|
66
|
+
openLinkInNewTab={true}
|
|
67
|
+
condition={el[0].includes('http')}
|
|
68
|
+
>
|
|
69
|
+
{flattenToAppURL(el[0])}
|
|
70
|
+
</ConditionalLink>
|
|
71
|
+
)}
|
|
70
72
|
</Table.Cell>
|
|
71
73
|
<Table.Cell>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
{el[1] && (
|
|
75
|
+
<ConditionalLink
|
|
76
|
+
to={`${el[1]}/edit`}
|
|
77
|
+
openLinkInNewTab={true}
|
|
78
|
+
condition={el[1].includes('http')}
|
|
79
|
+
>
|
|
80
|
+
{flattenToAppURL(el[1])}
|
|
81
|
+
</ConditionalLink>
|
|
82
|
+
)}
|
|
79
83
|
</Table.Cell>
|
|
80
84
|
</Table.Row>
|
|
81
85
|
))}
|
|
@@ -47,53 +47,55 @@ const RelationsControlPanel = () => {
|
|
|
47
47
|
|
|
48
48
|
return (
|
|
49
49
|
<>
|
|
50
|
-
<div className="
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<Segment
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<
|
|
58
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
50
|
+
<div className="ui container">
|
|
51
|
+
<div className="relations-control-panel">
|
|
52
|
+
<Helmet title={intl.formatMessage(messages.relations)} />
|
|
53
|
+
{can_edit ? (
|
|
54
|
+
<Segment.Group raised>
|
|
55
|
+
<Segment className="primary">
|
|
56
|
+
{brokenRelations && Object.keys(brokenRelations).length > 0 ? (
|
|
57
|
+
<React.Fragment>
|
|
58
|
+
<Message warning>
|
|
59
|
+
<FormattedMessage
|
|
60
|
+
id="Some relations are broken. Please fix."
|
|
61
|
+
defaultMessage="Some relations are broken. Please fix."
|
|
62
|
+
/>
|
|
63
|
+
</Message>
|
|
64
|
+
<Divider hidden />
|
|
65
|
+
</React.Fragment>
|
|
66
|
+
) : null}
|
|
67
|
+
<h1>
|
|
68
|
+
<FormattedMessage id="Relations" defaultMessage="Relations" />
|
|
69
|
+
</h1>
|
|
70
|
+
{relations_stats?.error ? (
|
|
71
|
+
<React.Fragment>
|
|
72
|
+
<Divider hidden />
|
|
73
|
+
<Message warning>
|
|
74
|
+
<FormattedMessage
|
|
75
|
+
id="Please upgrade to plone.restapi >= 8.39.0."
|
|
76
|
+
defaultMessage="Please upgrade to plone.restapi >= 8.39.0."
|
|
77
|
+
/>
|
|
78
|
+
</Message>
|
|
79
|
+
</React.Fragment>
|
|
80
|
+
) : null}
|
|
81
|
+
</Segment>
|
|
82
|
+
<Segment>
|
|
83
|
+
<RelationsMatrix />
|
|
84
|
+
</Segment>
|
|
85
|
+
</Segment.Group>
|
|
86
|
+
) : (
|
|
87
|
+
<Segment.Group>
|
|
88
|
+
<Segment>
|
|
67
89
|
<FormattedMessage id="Relations" defaultMessage="Relations" />
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
</Message>
|
|
78
|
-
</React.Fragment>
|
|
79
|
-
) : null}
|
|
80
|
-
</Segment>
|
|
81
|
-
<Segment>
|
|
82
|
-
<RelationsMatrix />
|
|
83
|
-
</Segment>
|
|
84
|
-
</Segment.Group>
|
|
85
|
-
) : (
|
|
86
|
-
<Segment.Group>
|
|
87
|
-
<Segment>
|
|
88
|
-
<FormattedMessage id="Relations" defaultMessage="Relations" />
|
|
89
|
-
<Divider hidden />
|
|
90
|
-
<FormattedMessage
|
|
91
|
-
id="You have not the required permission for this control panel."
|
|
92
|
-
defaultMessage="You have not the required permission for this control panel."
|
|
93
|
-
/>
|
|
94
|
-
</Segment>
|
|
95
|
-
</Segment.Group>
|
|
96
|
-
)}
|
|
90
|
+
<Divider hidden />
|
|
91
|
+
<FormattedMessage
|
|
92
|
+
id="You have not the required permission for this control panel."
|
|
93
|
+
defaultMessage="You have not the required permission for this control panel."
|
|
94
|
+
/>
|
|
95
|
+
</Segment>
|
|
96
|
+
</Segment.Group>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
97
99
|
</div>
|
|
98
100
|
|
|
99
101
|
{isClient &&
|
|
@@ -191,6 +191,13 @@ const More = (props) => {
|
|
|
191
191
|
id: 'redirection',
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
+
const workingCopyCheckoutAction = find(actions.object_buttons, {
|
|
195
|
+
id: 'iterate_checkout',
|
|
196
|
+
});
|
|
197
|
+
const workingCopyCheckinAction = find(actions.object_buttons, {
|
|
198
|
+
id: 'iterate_checkin',
|
|
199
|
+
});
|
|
200
|
+
|
|
194
201
|
const dateOptions = {
|
|
195
202
|
year: 'numeric',
|
|
196
203
|
month: 'long',
|
|
@@ -320,125 +327,114 @@ const More = (props) => {
|
|
|
320
327
|
</>
|
|
321
328
|
)}
|
|
322
329
|
</Pluggable>
|
|
323
|
-
{
|
|
324
|
-
content
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}}
|
|
337
|
-
>
|
|
338
|
-
{intl.formatMessage(messages.CreateWorkingCopy)}
|
|
330
|
+
{workingCopyCheckoutAction && (
|
|
331
|
+
<Plug pluggable="toolbar-more-manage-content" id="workingcopy">
|
|
332
|
+
<li>
|
|
333
|
+
<button
|
|
334
|
+
aria-label={intl.formatMessage(messages.CreateWorkingCopy)}
|
|
335
|
+
onClick={() => {
|
|
336
|
+
dispatch(createWorkingCopy(path)).then((response) => {
|
|
337
|
+
history.push(flattenToAppURL(response['@id']));
|
|
338
|
+
props.closeMenu();
|
|
339
|
+
});
|
|
340
|
+
}}
|
|
341
|
+
>
|
|
342
|
+
{intl.formatMessage(messages.CreateWorkingCopy)}
|
|
339
343
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
{
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
});
|
|
381
|
-
}}
|
|
382
|
-
>
|
|
383
|
-
{intl.formatMessage(messages.applyWorkingCopy)}
|
|
344
|
+
<Icon name={rightArrowSVG} size="24px" />
|
|
345
|
+
</button>
|
|
346
|
+
</li>
|
|
347
|
+
</Plug>
|
|
348
|
+
)}
|
|
349
|
+
{workingCopyCheckinAction && (
|
|
350
|
+
<Plug pluggable="toolbar-more-manage-content" id="workingcopy">
|
|
351
|
+
<li>
|
|
352
|
+
<button
|
|
353
|
+
aria-label={intl.formatMessage(messages.applyWorkingCopy)}
|
|
354
|
+
onClick={() => {
|
|
355
|
+
dispatch(applyWorkingCopy(path)).then((response) => {
|
|
356
|
+
history.push(flattenToAppURL(content.working_copy_of['@id']));
|
|
357
|
+
props.closeMenu();
|
|
358
|
+
toast.info(
|
|
359
|
+
<Toast
|
|
360
|
+
info
|
|
361
|
+
title={intl.formatMessage(messages.workingAppliedTitle)}
|
|
362
|
+
content={intl.formatMessage(
|
|
363
|
+
messages.workingCopyAppliedBy,
|
|
364
|
+
{
|
|
365
|
+
creator: content.working_copy?.creator_name,
|
|
366
|
+
date: (
|
|
367
|
+
<FormattedDate
|
|
368
|
+
date={content.working_copy?.created}
|
|
369
|
+
format={dateOptions}
|
|
370
|
+
/>
|
|
371
|
+
),
|
|
372
|
+
},
|
|
373
|
+
)}
|
|
374
|
+
/>,
|
|
375
|
+
{
|
|
376
|
+
toastId: 'workingcopyapplyinfo',
|
|
377
|
+
autoClose: 10000,
|
|
378
|
+
},
|
|
379
|
+
);
|
|
380
|
+
});
|
|
381
|
+
}}
|
|
382
|
+
>
|
|
383
|
+
{intl.formatMessage(messages.applyWorkingCopy)}
|
|
384
384
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
</Plug>
|
|
439
|
-
)}
|
|
440
|
-
</>
|
|
441
|
-
)}
|
|
385
|
+
<Icon
|
|
386
|
+
name={applySVG}
|
|
387
|
+
size="24px"
|
|
388
|
+
title={intl.formatMessage(messages.applyWorkingCopy)}
|
|
389
|
+
/>
|
|
390
|
+
</button>
|
|
391
|
+
</li>
|
|
392
|
+
<li>
|
|
393
|
+
<button
|
|
394
|
+
aria-label={intl.formatMessage(messages.removeWorkingCopy)}
|
|
395
|
+
onClick={() => {
|
|
396
|
+
dispatch(removeWorkingCopy(path)).then((response) => {
|
|
397
|
+
history.push(flattenToAppURL(content.working_copy_of['@id']));
|
|
398
|
+
props.closeMenu();
|
|
399
|
+
toast.info(
|
|
400
|
+
<Toast
|
|
401
|
+
info
|
|
402
|
+
title={intl.formatMessage(
|
|
403
|
+
messages.workingCopyRemovedTitle,
|
|
404
|
+
)}
|
|
405
|
+
/>,
|
|
406
|
+
{
|
|
407
|
+
toastId: 'workingcopyremovednotice',
|
|
408
|
+
autoClose: 10000,
|
|
409
|
+
},
|
|
410
|
+
);
|
|
411
|
+
});
|
|
412
|
+
}}
|
|
413
|
+
>
|
|
414
|
+
{intl.formatMessage(messages.removeWorkingCopy)}
|
|
415
|
+
<Icon
|
|
416
|
+
name={removeSVG}
|
|
417
|
+
size="24px"
|
|
418
|
+
color="#e40166"
|
|
419
|
+
title={intl.formatMessage(messages.removeWorkingCopy)}
|
|
420
|
+
/>
|
|
421
|
+
</button>
|
|
422
|
+
</li>
|
|
423
|
+
</Plug>
|
|
424
|
+
)}
|
|
425
|
+
{content.working_copy && !content.working_copy_of && (
|
|
426
|
+
<Plug pluggable="toolbar-more-manage-content" id="workingcopy">
|
|
427
|
+
<li>
|
|
428
|
+
<Link
|
|
429
|
+
to={flattenToAppURL(content.working_copy['@id'])}
|
|
430
|
+
onClick={() => props.closeMenu()}
|
|
431
|
+
>
|
|
432
|
+
{intl.formatMessage(messages.viewWorkingCopy)}
|
|
433
|
+
<Icon name={rightArrowSVG} size="24px" />
|
|
434
|
+
</Link>
|
|
435
|
+
</li>
|
|
436
|
+
</Plug>
|
|
437
|
+
)}
|
|
442
438
|
{editAction && config.settings.isMultilingual && (
|
|
443
439
|
<Plug pluggable="toolbar-more-manage-content" id="multilingual">
|
|
444
440
|
<li>
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import configureStore from 'redux-mock-store';
|
|
3
2
|
import { Provider } from 'react-intl-redux';
|
|
4
3
|
import { MemoryRouter } from 'react-router-dom';
|
|
5
4
|
import { PluggablesProvider } from '@plone/volto/components/manage/Pluggable';
|
|
6
5
|
import { waitFor, render } from '@testing-library/react';
|
|
7
|
-
import config from '@plone/volto/registry';
|
|
8
6
|
|
|
9
7
|
import More from './More';
|
|
10
8
|
|
|
@@ -162,26 +160,4 @@ describe('Toolbar More component', () => {
|
|
|
162
160
|
await waitFor(() => {});
|
|
163
161
|
expect(container).toMatchSnapshot();
|
|
164
162
|
});
|
|
165
|
-
it('renders a Toolbar More component with manage content (working copy)', async () => {
|
|
166
|
-
config.settings.hasWorkingCopySupport = true;
|
|
167
|
-
|
|
168
|
-
const { container } = render(
|
|
169
|
-
<PluggablesProvider>
|
|
170
|
-
<Provider store={store}>
|
|
171
|
-
<MemoryRouter>
|
|
172
|
-
<More
|
|
173
|
-
pathname="/blah"
|
|
174
|
-
loadComponent={() => {}}
|
|
175
|
-
theToolbar={{
|
|
176
|
-
current: { getBoundingClientRect: () => ({ width: '320' }) },
|
|
177
|
-
}}
|
|
178
|
-
closeMenu={() => {}}
|
|
179
|
-
/>
|
|
180
|
-
</MemoryRouter>
|
|
181
|
-
</Provider>
|
|
182
|
-
</PluggablesProvider>,
|
|
183
|
-
);
|
|
184
|
-
await waitFor(() => {});
|
|
185
|
-
expect(container).toMatchSnapshot();
|
|
186
|
-
});
|
|
187
163
|
});
|
|
@@ -16,10 +16,10 @@ import { Image, Label, Popup, Button } from 'semantic-ui-react';
|
|
|
16
16
|
import {
|
|
17
17
|
flattenToAppURL,
|
|
18
18
|
isInternalURL,
|
|
19
|
-
isUrl,
|
|
20
19
|
normalizeUrl,
|
|
21
20
|
removeProtocol,
|
|
22
21
|
} from '@plone/volto/helpers/Url/Url';
|
|
22
|
+
import { urlValidator } from '@plone/volto/helpers/FormValidation/validators';
|
|
23
23
|
import { searchContent } from '@plone/volto/actions/search/search';
|
|
24
24
|
import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
|
|
25
25
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
@@ -102,6 +102,7 @@ export class ObjectBrowserWidgetComponent extends Component {
|
|
|
102
102
|
state = {
|
|
103
103
|
manualLinkInput: '',
|
|
104
104
|
validURL: false,
|
|
105
|
+
errors: [],
|
|
105
106
|
};
|
|
106
107
|
|
|
107
108
|
constructor(props) {
|
|
@@ -230,7 +231,16 @@ export class ObjectBrowserWidgetComponent extends Component {
|
|
|
230
231
|
|
|
231
232
|
validateManualLink = (url) => {
|
|
232
233
|
if (this.props.allowExternals) {
|
|
233
|
-
|
|
234
|
+
const error = urlValidator({
|
|
235
|
+
value: url,
|
|
236
|
+
formatMessage: this.props.intl.formatMessage,
|
|
237
|
+
});
|
|
238
|
+
if (error && url !== '') {
|
|
239
|
+
this.setState({ errors: [error] });
|
|
240
|
+
} else {
|
|
241
|
+
this.setState({ errors: [] });
|
|
242
|
+
}
|
|
243
|
+
return !Boolean(error);
|
|
234
244
|
} else {
|
|
235
245
|
return isInternalURL(url);
|
|
236
246
|
}
|
|
@@ -344,6 +354,8 @@ export class ObjectBrowserWidgetComponent extends Component {
|
|
|
344
354
|
return (
|
|
345
355
|
<FormFieldWrapper
|
|
346
356
|
{...this.props}
|
|
357
|
+
// At the moment, OBW handles its own errors and validation
|
|
358
|
+
error={this.state.errors}
|
|
347
359
|
className={description ? 'help text' : 'text'}
|
|
348
360
|
>
|
|
349
361
|
<div
|
|
@@ -372,6 +384,7 @@ export class ObjectBrowserWidgetComponent extends Component {
|
|
|
372
384
|
items.length === 0 &&
|
|
373
385
|
this.props.mode !== 'multiple' && (
|
|
374
386
|
<input
|
|
387
|
+
onBlur={this.onSubmitManualLink}
|
|
375
388
|
onKeyDown={this.onKeyDownManualLink}
|
|
376
389
|
onChange={this.onManualLinkInput}
|
|
377
390
|
value={this.state.manualLinkInput}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module components/manage/Widgets/RegistryImageWidget
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { Button, Image, Dimmer } from 'semantic-ui-react';
|
|
9
9
|
import { readAsDataURL } from 'promise-file-reader';
|
|
@@ -76,12 +76,15 @@ const RegistryImageWidget = (props) => {
|
|
|
76
76
|
const { id, value, onChange, isDisabled } = props;
|
|
77
77
|
const intl = useIntl();
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)}
|
|
84
|
-
|
|
79
|
+
// State to manage the preview image source
|
|
80
|
+
const [previewSrc, setPreviewSrc] = useState(() => {
|
|
81
|
+
const fileName = value?.split(';')[0];
|
|
82
|
+
return fileName
|
|
83
|
+
? `${toPublicURL('/')}@@site-logo/${atob(
|
|
84
|
+
fileName.replace('filenameb64:', ''),
|
|
85
|
+
)}`
|
|
86
|
+
: '';
|
|
87
|
+
});
|
|
85
88
|
|
|
86
89
|
/**
|
|
87
90
|
* Drop handler
|
|
@@ -102,8 +105,7 @@ const RegistryImageWidget = (props) => {
|
|
|
102
105
|
reader.onload = function () {
|
|
103
106
|
const fields = reader.result.match(/^data:(.*);(.*),(.*)$/);
|
|
104
107
|
if (imageMimetypes.includes(fields[1])) {
|
|
105
|
-
|
|
106
|
-
imagePreview.src = reader.result;
|
|
108
|
+
setPreviewSrc(reader.result);
|
|
107
109
|
}
|
|
108
110
|
};
|
|
109
111
|
reader.readAsDataURL(files[0]);
|
|
@@ -115,12 +117,12 @@ const RegistryImageWidget = (props) => {
|
|
|
115
117
|
{({ getRootProps, getInputProps, isDragActive }) => (
|
|
116
118
|
<div className="file-widget-dropzone" {...getRootProps()}>
|
|
117
119
|
{isDragActive && <Dimmer active></Dimmer>}
|
|
118
|
-
{
|
|
120
|
+
{previewSrc ? (
|
|
119
121
|
<Image
|
|
120
122
|
className="image-preview"
|
|
121
123
|
id={`field-${id}-image`}
|
|
122
124
|
size="small"
|
|
123
|
-
src={
|
|
125
|
+
src={previewSrc}
|
|
124
126
|
/>
|
|
125
127
|
) : (
|
|
126
128
|
<div className="dropzone-placeholder">
|
|
@@ -139,7 +141,6 @@ const RegistryImageWidget = (props) => {
|
|
|
139
141
|
)}
|
|
140
142
|
</div>
|
|
141
143
|
)}
|
|
142
|
-
|
|
143
144
|
<label className="label-file-widget-input">
|
|
144
145
|
{value
|
|
145
146
|
? intl.formatMessage(messages.replaceFile)
|
|
@@ -168,6 +169,7 @@ const RegistryImageWidget = (props) => {
|
|
|
168
169
|
disabled={isDisabled}
|
|
169
170
|
onClick={() => {
|
|
170
171
|
onChange(id, '');
|
|
172
|
+
setPreviewSrc(''); // Clear the preview image
|
|
171
173
|
}}
|
|
172
174
|
>
|
|
173
175
|
<Icon name={deleteSVG} size="20px" />
|
|
@@ -189,10 +191,7 @@ RegistryImageWidget.propTypes = {
|
|
|
189
191
|
description: PropTypes.string,
|
|
190
192
|
required: PropTypes.bool,
|
|
191
193
|
error: PropTypes.arrayOf(PropTypes.string),
|
|
192
|
-
value: PropTypes.
|
|
193
|
-
'@type': PropTypes.string,
|
|
194
|
-
title: PropTypes.string,
|
|
195
|
-
}),
|
|
194
|
+
value: PropTypes.string,
|
|
196
195
|
onChange: PropTypes.func.isRequired,
|
|
197
196
|
wrapped: PropTypes.bool,
|
|
198
197
|
};
|