@plone/volto 18.0.0-alpha.42 → 18.0.0-alpha.43

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/finalreleasechangelog.py +48 -0
  3. package/locales/ca/LC_MESSAGES/volto.po +8 -12
  4. package/locales/ca.json +1 -1
  5. package/locales/de/LC_MESSAGES/volto.po +9 -13
  6. package/locales/de.json +1 -1
  7. package/locales/en/LC_MESSAGES/volto.po +8 -12
  8. package/locales/en.json +1 -1
  9. package/locales/es/LC_MESSAGES/volto.po +9 -13
  10. package/locales/es.json +1 -1
  11. package/locales/eu/LC_MESSAGES/volto.po +9 -13
  12. package/locales/eu.json +1 -1
  13. package/locales/fi/LC_MESSAGES/volto.po +9 -13
  14. package/locales/fi.json +1 -1
  15. package/locales/fr/LC_MESSAGES/volto.po +9 -13
  16. package/locales/fr.json +1 -1
  17. package/locales/hi/LC_MESSAGES/volto.po +9 -13
  18. package/locales/hi.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +9 -13
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +8 -12
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +8 -12
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +8 -12
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +9 -13
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +8 -12
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +9 -13
  32. package/locales/zh_CN/LC_MESSAGES/volto.po +9 -13
  33. package/locales/zh_CN.json +1 -1
  34. package/package.json +3 -3
  35. package/razzle.config.js +1 -1
  36. package/src/components/manage/Actions/Actions.stories.jsx +138 -0
  37. package/src/components/manage/Add/Add.jsx +7 -4
  38. package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
  39. package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
  40. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
  41. package/src/components/manage/Blocks/Block/Order/Item.jsx +3 -1
  42. package/src/components/manage/Blocks/Grid/View.jsx +3 -0
  43. package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
  44. package/src/components/manage/Blocks/Search/components/SortOn.jsx +82 -55
  45. package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
  46. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
  47. package/src/components/manage/Blocks/ToC/Edit.jsx +36 -29
  48. package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
  49. package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
  50. package/src/components/manage/Contents/Contents.jsx +3 -0
  51. package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
  52. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
  53. package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
  54. package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
  55. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
  56. package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
  57. package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
  58. package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
  59. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
  60. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
  61. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
  62. package/src/components/manage/Display/Display.jsx +92 -148
  63. package/src/components/manage/Display/Display.stories.jsx +46 -0
  64. package/src/components/manage/Edit/Edit.jsx +2 -4
  65. package/src/components/manage/Preferences/ChangePassword.jsx +94 -172
  66. package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
  67. package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
  68. package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
  69. package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
  70. package/src/components/manage/Toolbar/More.jsx +308 -399
  71. package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
  72. package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
  73. package/src/components/theme/Register/Register.jsx +70 -142
  74. package/src/components/theme/Register/Register.stories.jsx +49 -0
  75. package/src/components/theme/Tags/Tags.jsx +19 -10
  76. package/src/components/theme/Tags/Tags.test.jsx +9 -11
  77. package/src/components/theme/View/AlbumView.jsx +122 -167
  78. package/src/components/theme/View/LinkView.jsx +4 -0
  79. package/src/components/theme/View/LinkView.test.jsx +2 -0
  80. package/src/components/theme/View/View.jsx +0 -6
  81. package/src/config/ControlPanels.js +49 -43
  82. package/src/config/config.test.js +1 -0
  83. package/src/config/index.js +16 -0
  84. package/src/config/slots.js +12 -0
  85. package/src/helpers/Blocks/Blocks.js +12 -7
  86. package/src/helpers/Blocks/Blocks.test.js +15 -0
  87. package/src/helpers/Blocks/cloneBlocks.ts +1 -1
  88. package/src/helpers/FormValidation/FormValidation.jsx +19 -2
  89. package/src/helpers/FormValidation/validators.ts +1 -1
  90. package/src/helpers/Url/Url.test.js +15 -2
  91. package/src/helpers/Url/urlRegex.js +1 -1
  92. package/src/helpers/index.js +2 -0
  93. package/src/middleware/api.js +4 -2
  94. package/src/middleware/index.js +1 -0
  95. package/src/middleware/userSessionReset.js +46 -0
  96. package/src/store.js +2 -0
  97. package/test-setup-config.jsx +3 -0
  98. package/theme/themes/pastanaga/extras/blocks.less +6 -0
  99. package/types/components/manage/Actions/Actions.stories.d.ts +8 -0
  100. package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
  101. package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
  102. package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
  103. package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
  104. package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
  105. package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
  106. package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
  107. package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
  108. package/types/components/manage/Contents/index.d.ts +1 -1
  109. package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
  110. package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
  111. package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
  112. package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
  113. package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
  114. package/types/components/manage/Controlpanels/index.d.ts +4 -4
  115. package/types/components/manage/Display/Display.stories.d.ts +8 -0
  116. package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
  117. package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
  118. package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
  119. package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
  120. package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
  121. package/types/components/manage/Toolbar/More.d.ts +8 -5
  122. package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
  123. package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
  124. package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
  125. package/types/components/manage/Widgets/index.d.ts +1 -1
  126. package/types/components/theme/Register/Register.d.ts +2 -2
  127. package/types/components/theme/Register/Register.stories.d.ts +9 -0
  128. package/types/components/theme/Tags/Tags.d.ts +15 -7
  129. package/types/components/theme/View/AlbumView.d.ts +3 -17
  130. package/types/config/ControlPanels.d.ts +8 -0
  131. package/types/config/Widgets.d.ts +1 -1
  132. package/types/config/slots.d.ts +21 -0
  133. package/types/helpers/Blocks/Blocks.d.ts +6 -0
  134. package/types/helpers/FormValidation/FormValidation.d.ts +1 -0
  135. package/types/helpers/index.d.ts +2 -2
  136. package/types/middleware/index.d.ts +1 -0
  137. package/types/middleware/userSessionReset.d.ts +5 -0
@@ -1,12 +1,6 @@
1
- /**
2
- * Contents upload modal.
3
- * @module components/manage/Contents/ContentsUploadModal
4
- */
5
-
6
- import React, { Component } from 'react';
1
+ import { useState, useEffect } from 'react';
7
2
  import PropTypes from 'prop-types';
8
- import { connect } from 'react-redux';
9
- import { compose } from 'redux';
3
+ import { shallowEqual, useDispatch, useSelector } from 'react-redux';
10
4
  import {
11
5
  Button,
12
6
  Dimmer,
@@ -23,10 +17,10 @@ import loadable from '@loadable/component';
23
17
  import { concat, filter, map } from 'lodash';
24
18
  import filesize from 'filesize';
25
19
  import { readAsDataURL } from 'promise-file-reader';
26
- import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
20
+ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
27
21
  import { FormattedRelativeDate } from '@plone/volto/components';
28
22
  import { createContent } from '@plone/volto/actions';
29
- import { validateFileUploadSize } from '@plone/volto/helpers';
23
+ import { validateFileUploadSize, usePrevious } from '@plone/volto/helpers';
30
24
 
31
25
  const Dropzone = loadable(() => import('react-dropzone'));
32
26
 
@@ -52,154 +46,77 @@ const messages = defineMessages({
52
46
 
53
47
  const SUBREQUEST = 'batch-upload';
54
48
 
55
- /**
56
- * ContentsUploadModal class.
57
- * @class ContentsUploadModal
58
- * @extends Component
59
- */
60
- class ContentsUploadModal extends Component {
61
- /**
62
- * Property types.
63
- * @property {Object} propTypes Property types.
64
- * @static
65
- */
66
- static propTypes = {
67
- createContent: PropTypes.func.isRequired,
68
- pathname: PropTypes.string.isRequired,
69
- request: PropTypes.shape({
70
- loading: PropTypes.bool,
71
- loaded: PropTypes.bool,
72
- }).isRequired,
73
- open: PropTypes.bool.isRequired,
74
- onOk: PropTypes.func.isRequired,
75
- onCancel: PropTypes.func.isRequired,
76
- uploadedFiles: PropTypes.number,
77
- multiple: PropTypes.bool,
78
- minSize: PropTypes.number,
79
- maxSize: PropTypes.number,
80
- accept: PropTypes.oneOfType([
81
- PropTypes.string,
82
- PropTypes.arrayOf(PropTypes.string),
83
- ]),
84
- };
49
+ const ContentsUploadModal = (props) => {
50
+ const intl = useIntl();
51
+ const dispatch = useDispatch();
52
+ const request = useSelector(
53
+ (state) => state.content.subrequests?.[SUBREQUEST] || {},
54
+ shallowEqual,
55
+ );
56
+ const uploadedFiles = useSelector((state) => state.content.uploadedFiles);
85
57
 
86
- /**
87
- * Constructor
88
- * @method constructor
89
- * @param {Object} props Component properties
90
- * @constructs ContentsUploadModal
91
- */
92
- constructor(props) {
93
- super(props);
94
- this.onRemoveFile = this.onRemoveFile.bind(this);
95
- this.onDrop = this.onDrop.bind(this);
96
- this.onCancel = this.onCancel.bind(this);
97
- this.onSubmit = this.onSubmit.bind(this);
98
- this.state = {
99
- files: [],
100
- totalFiles: 0,
101
- };
102
- }
103
- /**
104
- * Component will receive props
105
- * @method componentWillReceiveProps
106
- * @param {Object} nextProps Next properties
107
- * @returns {undefined}
108
- */
109
- UNSAFE_componentWillReceiveProps(nextProps) {
110
- if (this.props.request.loading && nextProps.request.loaded) {
111
- this.props.onOk();
112
- this.setState({
113
- files: [],
114
- });
58
+ const prevrequestloading = usePrevious(request.loading);
59
+ const [files, setFiles] = useState([]);
60
+ const [totalFiles, setTotalFiles] = useState(0);
61
+ const { onOk } = props;
62
+ useEffect(() => {
63
+ if (prevrequestloading && request.loaded) {
64
+ onOk();
65
+ setFiles([]);
115
66
  }
116
- }
67
+ }, [prevrequestloading, request.loaded, onOk]);
117
68
 
118
- /**
119
- * Remove file handler
120
- * @method onRemoveFile
121
- * @param {Object} event Event object
122
- * @returns {undefined}
123
- */
124
- onRemoveFile(event) {
125
- this.setState({
126
- files: filter(
127
- this.state.files,
69
+ const onRemoveFile = (event) => {
70
+ setFiles(
71
+ filter(
72
+ files,
128
73
  (file, index) =>
129
74
  index !== parseInt(event.target.getAttribute('value'), 10),
130
75
  ),
131
- });
132
- this.setState((prevState) => ({ totalFiles: prevState.totalFiles - 1 }));
133
- }
76
+ );
77
+ setTotalFiles(totalFiles - 1);
78
+ };
134
79
 
135
- /**
136
- * Drop handler
137
- * @method onDrop
138
- * @param {array} files File objects
139
- * @returns {undefined}
140
- */
141
- onDrop = async (files) => {
80
+ const onDrop = async (newFiles) => {
142
81
  const validFiles = [];
143
- for (let i = 0; i < files.length; i++) {
144
- if (validateFileUploadSize(files[i], this.props.intl.formatMessage)) {
145
- await readAsDataURL(files[i]).then((data) => {
82
+ for (let i = 0; i < newFiles.length; i++) {
83
+ if (validateFileUploadSize(newFiles[i], intl.formatMessage)) {
84
+ await readAsDataURL(newFiles[i]).then((data) => {
146
85
  const fields = data.match(/^data:(.*);(.*),(.*)$/);
147
- files[i].preview = fields[0];
86
+ newFiles[i].preview = fields[0];
148
87
  });
149
- validFiles.push(files[i]);
88
+ validFiles.push(newFiles[i]);
150
89
  }
151
90
  }
152
- this.setState({
153
- files: concat(this.state.files, validFiles),
154
- });
155
-
156
- this.setState({ totalFiles: validFiles.length });
91
+ setFiles(concat(files, validFiles));
92
+ setTotalFiles(validFiles.length);
157
93
  };
158
94
 
159
- /**
160
- * Cancel handler
161
- * @method onCancel
162
- * @returns {undefined}
163
- */
164
- onCancel() {
165
- this.props.onCancel();
166
- this.setState({
167
- files: [],
168
- });
169
- this.setState({ totalFiles: 0 });
170
- }
171
- /**
172
- * Name change handler
173
- * @method onChangeFileName
174
- * @returns {undefined}
175
- */
95
+ const onCancel = () => {
96
+ props.onCancel();
97
+ setFiles([]);
98
+ setTotalFiles(0);
99
+ };
176
100
 
177
- onChangeFileName(e, index) {
178
- let copyOfFiles = [...this.state.files];
179
- let originalFile = this.state.files[index];
101
+ const onChangeFileName = (e, index) => {
102
+ let copyOfFiles = [...files];
103
+ let originalFile = files[index];
180
104
  let newFile = new File([originalFile], e.target.value, {
181
105
  type: originalFile.type,
182
106
  });
183
107
  newFile.preview = originalFile.preview;
184
108
  newFile.path = e.target.value;
185
109
  copyOfFiles[index] = newFile;
186
- this.setState({
187
- files: copyOfFiles,
188
- });
189
- }
110
+ setFiles(copyOfFiles);
111
+ };
190
112
 
191
- /**
192
- * Submit handlers
193
- * @method onSubmit
194
- * @returns {undefined}
195
- */
196
- onSubmit() {
197
- Promise.all(map(this.state.files, (file) => readAsDataURL(file))).then(
198
- (files) => {
199
- this.props.createContent(
200
- this.props.pathname,
201
- map(this.state.files, (file, index) => {
202
- const fields = files[index].match(/^data:(.*);(.*),(.*)$/);
113
+ const onSubmit = () => {
114
+ Promise.all(map(files, (file) => readAsDataURL(file))).then((dataUrls) => {
115
+ dispatch(
116
+ createContent(
117
+ props.pathname,
118
+ map(files, (file, index) => {
119
+ const fields = dataUrls[index].match(/^data:(.*);(.*),(.*)$/);
203
120
  const image = fields[1].split('/')[0] === 'image';
204
121
  return {
205
122
  '@type': image ? 'Image' : 'File',
@@ -213,205 +130,195 @@ class ContentsUploadModal extends Component {
213
130
  };
214
131
  }),
215
132
  SUBREQUEST,
216
- );
217
- },
218
- );
219
- }
220
-
221
- /**
222
- * Render method.
223
- * @method render
224
- * @returns {string} Markup for the component.
225
- */
226
- render() {
227
- const {
228
- multiple = true,
229
- minSize = null,
230
- maxSize = null,
231
- accept = null,
232
- disabled = false,
233
- } = this.props;
234
-
235
- const dropzoneOptions = {
236
- multiple,
237
- minSize,
238
- maxSize,
239
- accept,
240
- disabled,
241
- };
133
+ ),
134
+ );
135
+ });
136
+ };
242
137
 
243
- return (
244
- this.props.open && (
245
- <Modal className="contents-upload-modal" open={this.props.open}>
246
- <Header>
247
- <FormattedMessage id="Upload files" defaultMessage="Upload files" />
248
- </Header>
138
+ const {
139
+ multiple = true,
140
+ minSize = null,
141
+ maxSize = null,
142
+ accept = null,
143
+ disabled = false,
144
+ } = props;
145
+ const dropzoneOptions = {
146
+ multiple,
147
+ minSize,
148
+ maxSize,
149
+ accept,
150
+ disabled,
151
+ };
249
152
 
250
- <Dimmer active={this.props.request.loading}>
251
- <div className="progress-container">
252
- <Progress
253
- className="progress-bar"
254
- value={this.props.uploadedFiles}
255
- total={this.state.totalFiles}
256
- >
257
- {this.props.intl.formatMessage(messages.filesUploaded, {
258
- uploadedFiles: this.props.uploadedFiles,
259
- })}
260
- <br />
261
- {this.props.intl.formatMessage(messages.totalFilesToUpload, {
262
- totalFiles: this.state.totalFiles,
263
- })}
264
- </Progress>
265
- </div>
266
- </Dimmer>
267
- <Modal.Content>
268
- <Dropzone
269
- onDrop={this.onDrop}
270
- className="dropzone"
271
- noDragEventsBubbling={true}
272
- {...dropzoneOptions}
153
+ return (
154
+ props.open && (
155
+ <Modal className="contents-upload-modal" open={props.open}>
156
+ <Header>
157
+ <FormattedMessage id="Upload files" defaultMessage="Upload files" />
158
+ </Header>
159
+ <Dimmer active={request.loading}>
160
+ <div className="progress-container">
161
+ <Progress
162
+ className="progress-bar"
163
+ value={uploadedFiles}
164
+ total={totalFiles}
273
165
  >
274
- {({ getRootProps, getInputProps }) => (
275
- <div {...getRootProps({ className: 'dashed' })}>
276
- <Segment>
277
- <Table basic="very">
278
- <Table.Body>
279
- <Table.Row>
280
- <Table.Cell>
166
+ {intl.formatMessage(messages.filesUploaded, {
167
+ uploadedFiles,
168
+ })}
169
+ <br />
170
+ {intl.formatMessage(messages.totalFilesToUpload, {
171
+ totalFiles,
172
+ })}
173
+ </Progress>
174
+ </div>
175
+ </Dimmer>
176
+ <Modal.Content>
177
+ <Dropzone
178
+ onDrop={onDrop}
179
+ className="dropzone"
180
+ noDragEventsBubbling={true}
181
+ {...dropzoneOptions}
182
+ >
183
+ {({ getRootProps, getInputProps }) => (
184
+ <div {...getRootProps({ className: 'dashed' })}>
185
+ <Segment>
186
+ <Table basic="very">
187
+ <Table.Body>
188
+ <Table.Row>
189
+ <Table.Cell>
190
+ <FormattedMessage
191
+ id="Drag and drop files from your computer onto this area or click the “Browse” button."
192
+ defaultMessage="Drag and drop files from your computer onto this area or click the “Browse” button."
193
+ />
194
+ </Table.Cell>
195
+ <Table.Cell>
196
+ <Button className="ui button primary">
281
197
  <FormattedMessage
282
- id="Drag and drop files from your computer onto this area or click the “Browse” button."
283
- defaultMessage="Drag and drop files from your computer onto this area or click the “Browse” button."
284
- />
285
- </Table.Cell>
286
- <Table.Cell>
287
- <Button className="ui button primary">
288
- <FormattedMessage
289
- id="Browse"
290
- defaultMessage="Browse"
291
- />
292
- </Button>
293
- <input
294
- {...getInputProps({
295
- type: 'file',
296
- style: { display: 'none' },
297
- })}
198
+ id="Browse"
199
+ defaultMessage="Browse"
298
200
  />
299
- </Table.Cell>
300
- </Table.Row>
301
- </Table.Body>
302
- </Table>
303
- </Segment>
304
- </div>
305
- )}
306
- </Dropzone>
307
- {this.state.files.length > 0 && (
308
- <Table compact singleLine>
309
- <Table.Header>
310
- <Table.Row>
311
- <Table.HeaderCell width={8}>
312
- <FormattedMessage
313
- id="Filename"
314
- defaultMessage="Filename"
315
- />
316
- </Table.HeaderCell>
317
- <Table.HeaderCell width={4}>
318
- <FormattedMessage
319
- id="Last modified"
320
- defaultMessage="Last modified"
201
+ </Button>
202
+ <input
203
+ {...getInputProps({
204
+ type: 'file',
205
+ style: { display: 'none' },
206
+ })}
207
+ />
208
+ </Table.Cell>
209
+ </Table.Row>
210
+ </Table.Body>
211
+ </Table>
212
+ </Segment>
213
+ </div>
214
+ )}
215
+ </Dropzone>
216
+ {files.length > 0 && (
217
+ <Table compact singleLine>
218
+ <Table.Header>
219
+ <Table.Row>
220
+ <Table.HeaderCell width={8}>
221
+ <FormattedMessage id="Filename" defaultMessage="Filename" />
222
+ </Table.HeaderCell>
223
+ <Table.HeaderCell width={4}>
224
+ <FormattedMessage
225
+ id="Last modified"
226
+ defaultMessage="Last modified"
227
+ />
228
+ </Table.HeaderCell>
229
+ <Table.HeaderCell width={4}>
230
+ <FormattedMessage
231
+ id="File size"
232
+ defaultMessage="File size"
233
+ />
234
+ </Table.HeaderCell>
235
+ <Table.HeaderCell width={4}>
236
+ <FormattedMessage id="Preview" defaultMessage="Preview" />
237
+ </Table.HeaderCell>
238
+ <Table.HeaderCell />
239
+ </Table.Row>
240
+ </Table.Header>
241
+ <Table.Body>
242
+ {map(files, (file, index) => (
243
+ <Table.Row className="upload-row" key={index}>
244
+ <Table.Cell>
245
+ <Input
246
+ className="file-name"
247
+ value={file.name}
248
+ onChange={(e) => onChangeFileName(e, index)}
321
249
  />
322
- </Table.HeaderCell>
323
- <Table.HeaderCell width={4}>
324
- <FormattedMessage
325
- id="File size"
326
- defaultMessage="File size"
250
+ </Table.Cell>
251
+ <Table.Cell>
252
+ {file.lastModifiedDate && (
253
+ <FormattedRelativeDate date={file.lastModifiedDate} />
254
+ )}
255
+ </Table.Cell>
256
+ <Table.Cell>{filesize(file.size, { round: 0 })}</Table.Cell>
257
+ <Table.Cell>
258
+ {file.type.split('/')[0] === 'image' && (
259
+ <Image src={file.preview} height={60} />
260
+ )}
261
+ </Table.Cell>
262
+ <Table.Cell>
263
+ <Icon
264
+ name="close"
265
+ value={index}
266
+ link
267
+ onClick={onRemoveFile}
327
268
  />
328
- </Table.HeaderCell>
329
- <Table.HeaderCell width={4}>
330
- <FormattedMessage id="Preview" defaultMessage="Preview" />
331
- </Table.HeaderCell>
332
- <Table.HeaderCell />
269
+ </Table.Cell>
333
270
  </Table.Row>
334
- </Table.Header>
335
- <Table.Body>
336
- {map(this.state.files, (file, index) => (
337
- <Table.Row className="upload-row" key={index}>
338
- <Table.Cell>
339
- <Input
340
- className="file-name"
341
- value={file.name}
342
- onChange={(e) => this.onChangeFileName(e, index)}
343
- />
344
- </Table.Cell>
345
- <Table.Cell>
346
- {file.lastModifiedDate && (
347
- <FormattedRelativeDate date={file.lastModifiedDate} />
348
- )}
349
- </Table.Cell>
350
- <Table.Cell>
351
- {filesize(file.size, { round: 0 })}
352
- </Table.Cell>
353
- <Table.Cell>
354
- {file.type.split('/')[0] === 'image' && (
355
- <Image src={file.preview} height={60} />
356
- )}
357
- </Table.Cell>
358
- <Table.Cell>
359
- <Icon
360
- name="close"
361
- value={index}
362
- link
363
- onClick={this.onRemoveFile}
364
- />
365
- </Table.Cell>
366
- </Table.Row>
367
- ))}
368
- </Table.Body>
369
- </Table>
370
- )}
371
- </Modal.Content>
372
- <Modal.Actions>
373
- {this.state.files.length > 0 && (
374
- <Button
375
- basic
376
- circular
377
- primary
378
- floated="right"
379
- icon="arrow right"
380
- aria-label={this.props.intl.formatMessage(messages.upload, {
381
- count: this.state.files.length,
382
- })}
383
- onClick={this.onSubmit}
384
- title={this.props.intl.formatMessage(messages.upload, {
385
- count: this.state.files.length,
386
- })}
387
- size="big"
388
- />
389
- )}
271
+ ))}
272
+ </Table.Body>
273
+ </Table>
274
+ )}
275
+ </Modal.Content>
276
+ <Modal.Actions>
277
+ {files.length > 0 && (
390
278
  <Button
391
279
  basic
392
280
  circular
393
- secondary
394
- icon="remove"
395
- aria-label={this.props.intl.formatMessage(messages.cancel)}
396
- title={this.props.intl.formatMessage(messages.cancel)}
281
+ primary
397
282
  floated="right"
283
+ icon="arrow right"
284
+ aria-label={intl.formatMessage(messages.upload, {
285
+ count: files.length,
286
+ })}
287
+ onClick={onSubmit}
288
+ title={intl.formatMessage(messages.upload, {
289
+ count: files.length,
290
+ })}
398
291
  size="big"
399
- onClick={this.onCancel}
400
292
  />
401
- </Modal.Actions>
402
- </Modal>
403
- )
404
- );
405
- }
406
- }
293
+ )}
294
+ <Button
295
+ basic
296
+ circular
297
+ secondary
298
+ icon="remove"
299
+ aria-label={intl.formatMessage(messages.cancel)}
300
+ title={intl.formatMessage(messages.cancel)}
301
+ floated="right"
302
+ size="big"
303
+ onClick={onCancel}
304
+ />
305
+ </Modal.Actions>
306
+ </Modal>
307
+ )
308
+ );
309
+ };
407
310
 
408
- export default compose(
409
- injectIntl,
410
- connect(
411
- (state) => ({
412
- request: state.content.subrequests?.[SUBREQUEST] || {},
413
- uploadedFiles: state.content.uploadedFiles,
414
- }),
415
- { createContent },
416
- ),
417
- )(ContentsUploadModal);
311
+ ContentsUploadModal.propTypes = {
312
+ pathname: PropTypes.string.isRequired,
313
+ open: PropTypes.bool.isRequired,
314
+ onOk: PropTypes.func.isRequired,
315
+ onCancel: PropTypes.func.isRequired,
316
+ multiple: PropTypes.bool,
317
+ minSize: PropTypes.number,
318
+ maxSize: PropTypes.number,
319
+ accept: PropTypes.oneOfType([
320
+ PropTypes.string,
321
+ PropTypes.arrayOf(PropTypes.string),
322
+ ]),
323
+ };
324
+ export default ContentsUploadModal;
@@ -0,0 +1,56 @@
1
+ import { injectIntl } from 'react-intl';
2
+ import React from 'react';
3
+ import ContentsUploadModalComponent from './ContentsUploadModal';
4
+ import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
5
+
6
+ const IntlContentUploadModalComponent = injectIntl(
7
+ ContentsUploadModalComponent,
8
+ );
9
+
10
+ function StoryComponent(args) {
11
+ return (
12
+ <Wrapper
13
+ customStore={{
14
+ content: {
15
+ create: {
16
+ loading: false,
17
+ loaded: true,
18
+ },
19
+ },
20
+ intl: {
21
+ locale: 'en',
22
+ messages: {},
23
+ },
24
+ }}
25
+ >
26
+ <div id="toolbar" style={{ display: 'none' }} />
27
+ <IntlContentUploadModalComponent
28
+ {...args}
29
+ pathname="/blog"
30
+ loading={false}
31
+ loaded={true}
32
+ onOk={() => {}}
33
+ onCancel={() => {}}
34
+ />
35
+ </Wrapper>
36
+ );
37
+ }
38
+
39
+ export const ContentUploadModal = StoryComponent.bind({});
40
+
41
+ ContentUploadModal.args = {
42
+ open: false,
43
+ };
44
+
45
+ export default {
46
+ title: 'Public components/Contents/Content Upload Modal',
47
+ component: ContentUploadModal,
48
+ decorators: [
49
+ (Story) => (
50
+ <div className="ui segment form attached" style={{ width: '400px' }}>
51
+ <Story />
52
+ </div>
53
+ ),
54
+ ],
55
+ argTypes: {},
56
+ };