@kitconcept/core 2.0.0-alpha.7 → 2.0.0-alpha.9
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.
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
3
|
-
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
|
4
|
-
import {
|
|
5
|
-
Button,
|
|
6
|
-
Modal,
|
|
7
|
-
Table,
|
|
8
|
-
Input,
|
|
9
|
-
Dimmer,
|
|
10
|
-
Progress,
|
|
11
|
-
} from 'semantic-ui-react';
|
|
12
|
-
import cx from 'classnames';
|
|
13
|
-
import filesize from 'filesize';
|
|
14
|
-
import { readAsDataURL } from 'promise-file-reader';
|
|
15
|
-
|
|
16
|
-
import { createContent } from '@plone/volto/actions/content/content';
|
|
17
|
-
import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious';
|
|
18
|
-
import { validateFileUploadSize } from '@plone/volto/helpers/FormValidation/FormValidation';
|
|
19
|
-
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
20
|
-
import uploadSVG from '@plone/volto/icons/upload.svg';
|
|
21
|
-
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
22
|
-
import FormattedRelativeDate from '@plone/volto/components/theme/FormattedDate/FormattedRelativeDate';
|
|
23
|
-
import Image from '@plone/volto/components/theme/Image/Image';
|
|
24
|
-
|
|
25
|
-
const SUBREQUEST = 'batch-upload';
|
|
26
|
-
|
|
27
|
-
const messages = defineMessages({
|
|
28
|
-
cancel: {
|
|
29
|
-
id: 'Cancel',
|
|
30
|
-
defaultMessage: 'Cancel',
|
|
31
|
-
},
|
|
32
|
-
upload: {
|
|
33
|
-
id: '{count, plural, one {Upload {count} file} other {Upload {count} files}}',
|
|
34
|
-
defaultMessage:
|
|
35
|
-
'{count, plural, one {Upload {count} file} other {Upload {count} files}}',
|
|
36
|
-
},
|
|
37
|
-
filesUploaded: {
|
|
38
|
-
id: 'Files uploaded: {uploadedFiles}',
|
|
39
|
-
defaultMessage: 'Files uploaded: {uploadedFiles}',
|
|
40
|
-
},
|
|
41
|
-
totalFilesToUpload: {
|
|
42
|
-
id: 'Total files to upload: {totalFiles}',
|
|
43
|
-
defaultMessage: 'Total files to upload: {totalFiles}',
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const DropZoneContent = (props) => {
|
|
48
|
-
const { onOk, onCancel, pathname, children } = props;
|
|
49
|
-
const [isDragOver, setIsDragOver] = useState(false);
|
|
50
|
-
const [showModal, setShowModal] = useState(false);
|
|
51
|
-
const [droppedFiles, setDroppedFiles] = useState([]);
|
|
52
|
-
const [totalFiles, setTotalFiles] = useState(0);
|
|
53
|
-
|
|
54
|
-
const intl = useIntl();
|
|
55
|
-
const dispatch = useDispatch();
|
|
56
|
-
|
|
57
|
-
const request = useSelector(
|
|
58
|
-
(state) => state.content.subrequests?.[SUBREQUEST] || {},
|
|
59
|
-
shallowEqual,
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const uploadedFiles = useSelector((state) => state.content.uploadedFiles);
|
|
63
|
-
const prevrequestloading = usePrevious(request.loading);
|
|
64
|
-
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (prevrequestloading && request.loaded) {
|
|
67
|
-
onOk();
|
|
68
|
-
setDroppedFiles([]);
|
|
69
|
-
}
|
|
70
|
-
}, [prevrequestloading, request.loaded, onOk]);
|
|
71
|
-
|
|
72
|
-
const handleDragEnter = (e) => {
|
|
73
|
-
e.preventDefault();
|
|
74
|
-
e.stopPropagation();
|
|
75
|
-
setIsDragOver(true);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const handleDragLeave = (e) => {
|
|
79
|
-
e.preventDefault();
|
|
80
|
-
e.stopPropagation();
|
|
81
|
-
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
82
|
-
setIsDragOver(false);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const handleDragOver = (e) => {
|
|
87
|
-
e.preventDefault();
|
|
88
|
-
e.stopPropagation();
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const onDrop = async (e) => {
|
|
92
|
-
setIsDragOver(false);
|
|
93
|
-
const newFiles = Array.from(e.dataTransfer.files);
|
|
94
|
-
const validFiles = [];
|
|
95
|
-
for (let i = 0; i < newFiles.length; i++) {
|
|
96
|
-
if (validateFileUploadSize(newFiles[i], intl.formatMessage)) {
|
|
97
|
-
await readAsDataURL(newFiles[i]).then((data) => {
|
|
98
|
-
const fields = data.match(/^data:(.*);(.*),(.*)$/);
|
|
99
|
-
newFiles[i].preview = fields[0];
|
|
100
|
-
});
|
|
101
|
-
validFiles.push(newFiles[i]);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
setDroppedFiles(droppedFiles.concat(validFiles));
|
|
105
|
-
setTotalFiles(validFiles.length);
|
|
106
|
-
setShowModal(true);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const handleCloseModal = () => {
|
|
110
|
-
setShowModal(false);
|
|
111
|
-
onCancel();
|
|
112
|
-
setDroppedFiles([]);
|
|
113
|
-
setTotalFiles(0);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const onSubmit = () => {
|
|
117
|
-
Promise.all(droppedFiles.map((file) => readAsDataURL(file))).then(
|
|
118
|
-
(dataUrls) => {
|
|
119
|
-
dispatch(
|
|
120
|
-
createContent(
|
|
121
|
-
pathname,
|
|
122
|
-
droppedFiles.map((file, index) => {
|
|
123
|
-
const fields = dataUrls[index].match(/^data:(.*);(.*),(.*)$/);
|
|
124
|
-
const image = fields[1].split('/')[0] === 'image';
|
|
125
|
-
return {
|
|
126
|
-
'@type': image ? 'Image' : 'File',
|
|
127
|
-
title: file.name,
|
|
128
|
-
[image ? 'image' : 'file']: {
|
|
129
|
-
data: fields[3],
|
|
130
|
-
encoding: fields[2],
|
|
131
|
-
'content-type': fields[1],
|
|
132
|
-
filename: file.name,
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
}),
|
|
136
|
-
SUBREQUEST,
|
|
137
|
-
),
|
|
138
|
-
);
|
|
139
|
-
},
|
|
140
|
-
);
|
|
141
|
-
handleCloseModal();
|
|
142
|
-
};
|
|
143
|
-
const onRemoveFile = (index) => {
|
|
144
|
-
const updatedFiles = droppedFiles.filter((file, i) => i !== index);
|
|
145
|
-
setDroppedFiles(updatedFiles);
|
|
146
|
-
setTotalFiles(updatedFiles.length);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const onChangeFileName = (e, index) => {
|
|
150
|
-
let copyOfFiles = [...droppedFiles];
|
|
151
|
-
let originalFile = droppedFiles[index];
|
|
152
|
-
let newFile = new File([originalFile], e.target.value, {
|
|
153
|
-
type: originalFile.type,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
newFile.preview = originalFile.preview;
|
|
157
|
-
newFile.path = e.target.value;
|
|
158
|
-
copyOfFiles[index] = newFile;
|
|
159
|
-
setDroppedFiles(copyOfFiles);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<>
|
|
164
|
-
<div
|
|
165
|
-
className={cx('contents-dropzone', {
|
|
166
|
-
'drag-over': isDragOver,
|
|
167
|
-
'drag-inactive': !isDragOver,
|
|
168
|
-
})}
|
|
169
|
-
onDragEnter={handleDragEnter}
|
|
170
|
-
onDragLeave={handleDragLeave}
|
|
171
|
-
onDragOver={handleDragOver}
|
|
172
|
-
onDrop={onDrop}
|
|
173
|
-
>
|
|
174
|
-
{children}
|
|
175
|
-
{isDragOver && (
|
|
176
|
-
<div className="dropzone-overlay">
|
|
177
|
-
<div className="dropzone-content">
|
|
178
|
-
<Icon name={uploadSVG} size="48px" />
|
|
179
|
-
<h3>Drop files here to upload</h3>
|
|
180
|
-
<p>Release to add file(s) to this folder</p>
|
|
181
|
-
</div>
|
|
182
|
-
</div>
|
|
183
|
-
)}
|
|
184
|
-
</div>
|
|
185
|
-
<Modal
|
|
186
|
-
open={showModal}
|
|
187
|
-
onClose={handleCloseModal}
|
|
188
|
-
className="contents-upload-modal"
|
|
189
|
-
>
|
|
190
|
-
<Modal.Header>Upload Files ({droppedFiles.length})</Modal.Header>
|
|
191
|
-
<Dimmer active={request.loading}>
|
|
192
|
-
<div className="progress-container">
|
|
193
|
-
<Progress
|
|
194
|
-
className="progress-bar"
|
|
195
|
-
value={uploadedFiles}
|
|
196
|
-
total={totalFiles}
|
|
197
|
-
>
|
|
198
|
-
{intl.formatMessage(messages.filesUploaded, {
|
|
199
|
-
uploadedFiles,
|
|
200
|
-
})}
|
|
201
|
-
<br />
|
|
202
|
-
{intl.formatMessage(messages.totalFilesToUpload, {
|
|
203
|
-
totalFiles,
|
|
204
|
-
})}
|
|
205
|
-
</Progress>
|
|
206
|
-
</div>
|
|
207
|
-
</Dimmer>
|
|
208
|
-
<Modal.Content>
|
|
209
|
-
{droppedFiles.length > 0 && (
|
|
210
|
-
<Table compact singleLine>
|
|
211
|
-
<Table.Header>
|
|
212
|
-
<Table.Row>
|
|
213
|
-
<Table.HeaderCell width={8}>
|
|
214
|
-
<FormattedMessage id="Filename" defaultMessage="Filename" />
|
|
215
|
-
</Table.HeaderCell>
|
|
216
|
-
<Table.HeaderCell width={4}>
|
|
217
|
-
<FormattedMessage
|
|
218
|
-
id="Last modified"
|
|
219
|
-
defaultMessage="Last modified"
|
|
220
|
-
/>
|
|
221
|
-
</Table.HeaderCell>
|
|
222
|
-
<Table.HeaderCell width={4}>
|
|
223
|
-
<FormattedMessage
|
|
224
|
-
id="File size"
|
|
225
|
-
defaultMessage="File size"
|
|
226
|
-
/>
|
|
227
|
-
</Table.HeaderCell>
|
|
228
|
-
<Table.HeaderCell width={4}>
|
|
229
|
-
<FormattedMessage id="Preview" defaultMessage="Preview" />
|
|
230
|
-
</Table.HeaderCell>
|
|
231
|
-
<Table.HeaderCell />
|
|
232
|
-
</Table.Row>
|
|
233
|
-
</Table.Header>
|
|
234
|
-
<Table.Body>
|
|
235
|
-
{droppedFiles.map((file, index) => (
|
|
236
|
-
<Table.Row className="upload-row" key={index}>
|
|
237
|
-
<Table.Cell>
|
|
238
|
-
<Input
|
|
239
|
-
className="file-name"
|
|
240
|
-
value={file.name}
|
|
241
|
-
onChange={(e) => onChangeFileName(e, index)}
|
|
242
|
-
/>
|
|
243
|
-
</Table.Cell>
|
|
244
|
-
<Table.Cell>
|
|
245
|
-
{file.lastModifiedDate && (
|
|
246
|
-
<FormattedRelativeDate date={file.lastModifiedDate} />
|
|
247
|
-
)}
|
|
248
|
-
</Table.Cell>
|
|
249
|
-
<Table.Cell>{filesize(file.size, { round: 0 })}</Table.Cell>
|
|
250
|
-
<Table.Cell>
|
|
251
|
-
{file.type.split('/')[0] === 'image' && (
|
|
252
|
-
<Image
|
|
253
|
-
src={file.preview}
|
|
254
|
-
height={60}
|
|
255
|
-
className="ui image"
|
|
256
|
-
/>
|
|
257
|
-
)}
|
|
258
|
-
</Table.Cell>
|
|
259
|
-
<Table.Cell>
|
|
260
|
-
<Icon
|
|
261
|
-
name={clearSVG}
|
|
262
|
-
size="24px"
|
|
263
|
-
onClick={() => onRemoveFile(index)}
|
|
264
|
-
/>
|
|
265
|
-
</Table.Cell>
|
|
266
|
-
</Table.Row>
|
|
267
|
-
))}
|
|
268
|
-
</Table.Body>
|
|
269
|
-
</Table>
|
|
270
|
-
)}
|
|
271
|
-
</Modal.Content>
|
|
272
|
-
<Modal.Actions>
|
|
273
|
-
{droppedFiles.length > 0 && (
|
|
274
|
-
<Button
|
|
275
|
-
basic
|
|
276
|
-
circular
|
|
277
|
-
primary
|
|
278
|
-
floated="right"
|
|
279
|
-
icon="arrow right"
|
|
280
|
-
aria-label={intl.formatMessage(messages.upload, {
|
|
281
|
-
count: droppedFiles.length,
|
|
282
|
-
})}
|
|
283
|
-
onClick={onSubmit}
|
|
284
|
-
title={intl.formatMessage(messages.upload, {
|
|
285
|
-
count: droppedFiles.length,
|
|
286
|
-
})}
|
|
287
|
-
size="big"
|
|
288
|
-
/>
|
|
289
|
-
)}
|
|
290
|
-
<Button
|
|
291
|
-
basic
|
|
292
|
-
circular
|
|
293
|
-
secondary
|
|
294
|
-
icon="remove"
|
|
295
|
-
aria-label={intl.formatMessage(messages.cancel)}
|
|
296
|
-
title={intl.formatMessage(messages.cancel)}
|
|
297
|
-
floated="right"
|
|
298
|
-
size="big"
|
|
299
|
-
onClick={handleCloseModal}
|
|
300
|
-
/>
|
|
301
|
-
</Modal.Actions>
|
|
302
|
-
</Modal>
|
|
303
|
-
</>
|
|
304
|
-
);
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
export default DropZoneContent;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OVERRIDE Contents.jsx
|
|
3
|
-
* REASON: Add component DropzoneContent to enable drag and drop upload.
|
|
4
|
-
* FILE: https://github.com/plone/volto/blob/829f0a61b80adb0d2a637f0160c1e9b00931114f/packages/volto/src/components/manage/Contents/Contents.jsx
|
|
5
|
-
* FILE VERSION: Volto 18.29.1
|
|
6
|
-
* PULL REQUEST: https://github.com/kitconcept/kitconcept-core/pull/71
|
|
7
|
-
* TICKET: https://gitlab.kitconcept.io/kitconcept/distribution-kitconcept-intranet/-/issues/6
|
|
8
|
-
* DEVELOPER: @Tishasoumya-02
|
|
9
|
-
* CHANGELOG:
|
|
10
|
-
* - Add component DropzoneContent to enable drag and drop upload (#6) @Tishasoumya-02
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Contents component.
|
|
15
|
-
* @module components/manage/Contents/Contents
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import Contents from '../../../../../components/Contents/Contents';
|
|
19
|
-
|
|
20
|
-
export default Contents;
|