@cocreate/file 1.14.1 → 1.15.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 +23 -0
- package/demo/index.html +16 -0
- package/docs/index.html +0 -5
- package/package.json +1 -2
- package/src/client.js +75 -28
- package/src/server.js +18 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
# [1.15.0](https://github.com/CoCreate-app/CoCreate-file/compare/v1.14.2...v1.15.0) (2024-02-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Removed https://cdn.cocreate.app/latest/CoCreate.min.css ([e0ae28d](https://github.com/CoCreate-app/CoCreate-file/commit/e0ae28de52a02ee58947093f6dad3dd9dfee93e8))
|
|
7
|
+
* renderValue ([4e3308a](https://github.com/CoCreate-app/CoCreate-file/commit/4e3308a157ee2257bc1eb603ddc1484b5579cac8))
|
|
8
|
+
* typo renderValue condition ([65ba50f](https://github.com/CoCreate-app/CoCreate-file/commit/65ba50fe6a84e02bad033f423d39a0ab22fdb766))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* setValue() ([44d4012](https://github.com/CoCreate-app/CoCreate-file/commit/44d40127823d7ccdf8286943b435eeff939e6e2f))
|
|
14
|
+
|
|
15
|
+
## [1.14.2](https://github.com/CoCreate-app/CoCreate-file/compare/v1.14.1...v1.14.2) (2024-01-17)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* await getFilter() ([339a343](https://github.com/CoCreate-app/CoCreate-file/commit/339a34379f51982b1447e5fffb81f4001c40b223))
|
|
21
|
+
* support defining storage and database in config ([bc992c1](https://github.com/CoCreate-app/CoCreate-file/commit/bc992c15dd586bdc3de580557617fc3eddb4a176))
|
|
22
|
+
* update to support new query system ([d3d43dc](https://github.com/CoCreate-app/CoCreate-file/commit/d3d43dc0585e6656167a8072fa3d2d848aca3b14))
|
|
23
|
+
|
|
1
24
|
## [1.14.1](https://github.com/CoCreate-app/CoCreate-file/compare/v1.14.0...v1.14.1) (2023-12-28)
|
|
2
25
|
|
|
3
26
|
|
package/demo/index.html
CHANGED
|
@@ -32,10 +32,26 @@
|
|
|
32
32
|
<button actions="upload">upload</button>
|
|
33
33
|
</form>
|
|
34
34
|
|
|
35
|
+
<div
|
|
36
|
+
type="file"
|
|
37
|
+
array="test"
|
|
38
|
+
object=""
|
|
39
|
+
key="image"
|
|
40
|
+
accept="image/*"
|
|
41
|
+
placeholder="Upload Image or Video Thumbnail"
|
|
42
|
+
class="floating-label min-height:40px active"
|
|
43
|
+
render-selector="[template]"
|
|
44
|
+
active>
|
|
45
|
+
<div template>
|
|
46
|
+
<img src="{{image.src}}" alt="image" width="100%" />
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
35
50
|
<form>
|
|
36
51
|
<input
|
|
37
52
|
type="file"
|
|
38
53
|
directory
|
|
54
|
+
realtime="false"
|
|
39
55
|
render-selector="document; [template]" />
|
|
40
56
|
|
|
41
57
|
<button actions="saveLocally">saveLocally</button>
|
package/docs/index.html
CHANGED
|
@@ -21,11 +21,6 @@
|
|
|
21
21
|
property="og:image"
|
|
22
22
|
content="https://cdn.cocreate.app/docs/file.png" />
|
|
23
23
|
|
|
24
|
-
<!-- CoCreate CSS -->
|
|
25
|
-
<link
|
|
26
|
-
rel="stylesheet"
|
|
27
|
-
href="https://cdn.cocreate.app/latest/CoCreate.min.css"
|
|
28
|
-
type="text/css" />
|
|
29
24
|
<link
|
|
30
25
|
rel="stylesheet"
|
|
31
26
|
href="../index.css"
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/file",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "A headless file uploader that uses HTML5 attributes for customization. Allows easy upload of files to server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file",
|
|
7
|
-
"chain-functions",
|
|
8
7
|
"cocreate",
|
|
9
8
|
"low-code-framework",
|
|
10
9
|
"no-code-framework",
|
package/src/client.js
CHANGED
|
@@ -26,7 +26,7 @@ import Observer from '@cocreate/observer';
|
|
|
26
26
|
import Crud from '@cocreate/crud-client';
|
|
27
27
|
import Elements from '@cocreate/elements';
|
|
28
28
|
import Actions from '@cocreate/actions';
|
|
29
|
-
import render from '@cocreate/render';
|
|
29
|
+
import { render } from '@cocreate/render';
|
|
30
30
|
import { queryElements } from '@cocreate/utils';
|
|
31
31
|
import '@cocreate/element-prototype';
|
|
32
32
|
|
|
@@ -42,38 +42,67 @@ const Files = new Map();
|
|
|
42
42
|
* - If a single element is provided, it initializes that element (assuming it is of type "file").
|
|
43
43
|
* - If an array of elements is provided, each element in the array is initialized.
|
|
44
44
|
*/
|
|
45
|
-
function init(elements) {
|
|
45
|
+
async function init(elements) {
|
|
46
46
|
if (!elements)
|
|
47
47
|
elements = document.querySelectorAll('[type="file"]')
|
|
48
48
|
else if (!Array.isArray(elements))
|
|
49
49
|
elements = [elements]
|
|
50
50
|
for (let i = 0; i < elements.length; i++) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
let input = document.createElement("input");
|
|
55
|
-
input.type = "file";
|
|
56
|
-
input.setAttribute('hidden', '')
|
|
57
|
-
elements[i].appendChild(input);
|
|
51
|
+
let nestedInput, isInput = elements[i].tagName === 'INPUT'
|
|
52
|
+
if (!isInput) {
|
|
53
|
+
nestedInput = elements[i].querySelector('input[type="file"]')
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
elements[i].getValue = async () => await getFiles([elements[i]])
|
|
61
57
|
elements[i].getFiles = async () => await getFiles([elements[i]])
|
|
58
|
+
elements[i].setValue = (files) => setFiles(elements[i], files);
|
|
59
|
+
elements[i].renderValue = (files) => setFiles(elements[i], files);
|
|
62
60
|
|
|
63
|
-
// elements[i].
|
|
61
|
+
// if (elements[i].renderValue) {
|
|
62
|
+
// let data = await elements[i].getValue()
|
|
63
|
+
// if (data)
|
|
64
|
+
// elements[i].setValue(data)
|
|
65
|
+
// }
|
|
64
66
|
|
|
65
67
|
if (elements[i].hasAttribute('directory')) {
|
|
66
|
-
if (window.showDirectoryPicker)
|
|
68
|
+
if (!isInput && window.showDirectoryPicker)
|
|
67
69
|
elements[i].addEventListener("click", fileEvent);
|
|
68
70
|
else if ('webkitdirectory' in elements[i]) {
|
|
69
71
|
elements[i].webkitdirectory = true
|
|
70
|
-
|
|
72
|
+
if (!isInput && !nestedInput) {
|
|
73
|
+
nestedInput = document.createElement("input");
|
|
74
|
+
nestedInput.type = "file";
|
|
75
|
+
nestedInput.setAttribute('hidden', '')
|
|
76
|
+
elements[i].appendChild(nestedInput);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (nestedInput) {
|
|
80
|
+
elements[i].addEventListener("click", function () {
|
|
81
|
+
nestedInput.click()
|
|
82
|
+
});
|
|
83
|
+
nestedInput.addEventListener("change", fileEvent);
|
|
84
|
+
} else
|
|
85
|
+
elements[i].addEventListener("change", fileEvent);
|
|
71
86
|
} else
|
|
72
87
|
console.error("Directory selection not supported in this browser.");
|
|
73
|
-
} else if (window.showOpenFilePicker)
|
|
88
|
+
} else if (!isInput && window.showOpenFilePicker)
|
|
74
89
|
elements[i].addEventListener("click", fileEvent);
|
|
75
|
-
else
|
|
76
|
-
|
|
90
|
+
else {
|
|
91
|
+
if (!isInput && !nestedInput) {
|
|
92
|
+
nestedInput = document.createElement("input");
|
|
93
|
+
nestedInput.type = "file";
|
|
94
|
+
nestedInput.setAttribute('hidden', '')
|
|
95
|
+
elements[i].appendChild(nestedInput);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (nestedInput) {
|
|
99
|
+
elements[i].addEventListener("click", function () {
|
|
100
|
+
nestedInput.click()
|
|
101
|
+
});
|
|
102
|
+
nestedInput.addEventListener("change", fileEvent);
|
|
103
|
+
} else
|
|
104
|
+
elements[i].addEventListener("change", fileEvent);
|
|
105
|
+
}
|
|
77
106
|
}
|
|
78
107
|
}
|
|
79
108
|
|
|
@@ -82,7 +111,7 @@ async function fileEvent(event) {
|
|
|
82
111
|
const input = event.target;
|
|
83
112
|
let selected = inputs.get(input) || new Map()
|
|
84
113
|
let files = input.files;
|
|
85
|
-
if (!files.length) {
|
|
114
|
+
if (!files || !files.length) {
|
|
86
115
|
event.preventDefault()
|
|
87
116
|
const multiple = input.multiple
|
|
88
117
|
if (input.hasAttribute('directory')) {
|
|
@@ -120,7 +149,7 @@ async function fileEvent(event) {
|
|
|
120
149
|
}
|
|
121
150
|
|
|
122
151
|
if (!files[i].src)
|
|
123
|
-
|
|
152
|
+
await readFile(files[i])
|
|
124
153
|
|
|
125
154
|
files[i].directory = handle.directory || '/'
|
|
126
155
|
files[i].path = handle.path || '/'
|
|
@@ -140,15 +169,14 @@ async function fileEvent(event) {
|
|
|
140
169
|
inputs.set(input, selected);
|
|
141
170
|
console.log("Files selected:", selected);
|
|
142
171
|
|
|
143
|
-
if (
|
|
144
|
-
input.renderValue(selected.values())
|
|
172
|
+
if (input.renderValue)
|
|
173
|
+
input.renderValue(Array.from(selected.values()))
|
|
145
174
|
|
|
146
175
|
const isImport = input.getAttribute('import')
|
|
147
176
|
const isRealtime = input.getAttribute('realtime')
|
|
148
177
|
if (isRealtime !== 'false' && (isImport || isImport == "")) {
|
|
149
178
|
Import(input)
|
|
150
179
|
}
|
|
151
|
-
|
|
152
180
|
}
|
|
153
181
|
} catch (error) {
|
|
154
182
|
if (error.name !== 'AbortError') {
|
|
@@ -201,9 +229,9 @@ async function getFiles(fileInputs) {
|
|
|
201
229
|
for (let input of fileInputs) {
|
|
202
230
|
const selected = inputs.get(input)
|
|
203
231
|
if (selected) {
|
|
204
|
-
for (let file of selected.values()) {
|
|
232
|
+
for (let file of Array.from(selected.values())) {
|
|
205
233
|
if (!file.src)
|
|
206
|
-
|
|
234
|
+
await readFile(file)
|
|
207
235
|
|
|
208
236
|
file = await getCustomData({ ...file })
|
|
209
237
|
files.push(file)
|
|
@@ -214,7 +242,6 @@ async function getFiles(fileInputs) {
|
|
|
214
242
|
return files
|
|
215
243
|
}
|
|
216
244
|
|
|
217
|
-
// gets file custom data
|
|
218
245
|
async function getCustomData(file) {
|
|
219
246
|
let form = document.querySelector(`[file_id="${file.id}"]`);
|
|
220
247
|
if (form) {
|
|
@@ -226,10 +253,12 @@ async function getCustomData(file) {
|
|
|
226
253
|
}
|
|
227
254
|
}
|
|
228
255
|
}
|
|
256
|
+
|
|
257
|
+
delete file.input;
|
|
258
|
+
|
|
229
259
|
return file;
|
|
230
260
|
}
|
|
231
261
|
|
|
232
|
-
|
|
233
262
|
// This function reads the file and returns its src
|
|
234
263
|
function readFile(file) {
|
|
235
264
|
return new Promise((resolve) => {
|
|
@@ -244,7 +273,7 @@ function readFile(file) {
|
|
|
244
273
|
} else if (['mp4', 'avi', 'mov', 'mpeg', 'flv'].includes(fileType[1])
|
|
245
274
|
|| fileType[0] === 'video') {
|
|
246
275
|
readAs = 'readAsDataURL';
|
|
247
|
-
} if (['mp3', 'wav', 'wma', 'aac', 'ogg'].includes(fileType[1])
|
|
276
|
+
} else if (['mp3', 'wav', 'wma', 'aac', 'ogg'].includes(fileType[1])
|
|
248
277
|
|| fileType[0] === 'audio') { // updated condition
|
|
249
278
|
readAs = 'readAsDataURL';
|
|
250
279
|
} else if (fileType[1] === 'pdf') {
|
|
@@ -269,6 +298,24 @@ function readFile(file) {
|
|
|
269
298
|
});
|
|
270
299
|
}
|
|
271
300
|
|
|
301
|
+
function setFiles(element, files) {
|
|
302
|
+
if (!files) return
|
|
303
|
+
if (!Array.isArray(files))
|
|
304
|
+
files = [files]
|
|
305
|
+
else if (!files.length)
|
|
306
|
+
return
|
|
307
|
+
|
|
308
|
+
let selected = inputs.get(element) || new Map()
|
|
309
|
+
for (let i = 0; i < files.length; i++) {
|
|
310
|
+
files[i].input = element
|
|
311
|
+
selected.set(files[i].id, files[i])
|
|
312
|
+
Files.set(files[i].id, files[i])
|
|
313
|
+
}
|
|
314
|
+
inputs.set(element, selected);
|
|
315
|
+
if (element.renderValue)
|
|
316
|
+
render({ source: element, data: Array.from(selected.values()) })
|
|
317
|
+
}
|
|
318
|
+
|
|
272
319
|
async function save(element, action, data) {
|
|
273
320
|
try {
|
|
274
321
|
if (!data)
|
|
@@ -374,7 +421,7 @@ async function upload(element, data) {
|
|
|
374
421
|
let Data = Elements.getObject(input);
|
|
375
422
|
if (Data.type) {
|
|
376
423
|
if (input.getFilter)
|
|
377
|
-
Data.$filter = input.getFilter()
|
|
424
|
+
Data.$filter = await input.getFilter()
|
|
378
425
|
|
|
379
426
|
let files = await getFiles(input)
|
|
380
427
|
|
|
@@ -454,7 +501,7 @@ async function Import(element, data) {
|
|
|
454
501
|
let Data = Elements.getObject(element[i]);
|
|
455
502
|
if (Data.type) {
|
|
456
503
|
if (element[i].getFilter)
|
|
457
|
-
Data.$filter = element[i].getFilter()
|
|
504
|
+
Data.$filter = await element[i].getFilter()
|
|
458
505
|
|
|
459
506
|
if (Data.type === 'key')
|
|
460
507
|
Data.type = 'object'
|
|
@@ -504,7 +551,7 @@ async function Export(element, data) {
|
|
|
504
551
|
let Data = Elements.getObject(element[i]);
|
|
505
552
|
if (Data.type) {
|
|
506
553
|
if (element[i].getFilter)
|
|
507
|
-
Data.$filter = element[i].getFilter()
|
|
554
|
+
Data.$filter = await element[i].getFilter()
|
|
508
555
|
|
|
509
556
|
if (Data.type === 'key')
|
|
510
557
|
Data.type = 'object'
|
package/src/server.js
CHANGED
|
@@ -127,10 +127,10 @@ module.exports = async function file(CoCreateConfig, configPath, match) {
|
|
|
127
127
|
method: 'signIn',
|
|
128
128
|
array: 'users',
|
|
129
129
|
$filter: {
|
|
130
|
-
query:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
query: {
|
|
131
|
+
email: config.email,
|
|
132
|
+
password: config.password
|
|
133
|
+
}
|
|
134
134
|
},
|
|
135
135
|
...config
|
|
136
136
|
}
|
|
@@ -267,6 +267,14 @@ module.exports = async function file(CoCreateConfig, configPath, match) {
|
|
|
267
267
|
array: directory.array || 'files',
|
|
268
268
|
object
|
|
269
269
|
}
|
|
270
|
+
|
|
271
|
+
if (directory.storage)
|
|
272
|
+
newObject.storage = directory.storage
|
|
273
|
+
if (directory.database)
|
|
274
|
+
newObject.database = directory.database
|
|
275
|
+
if (directory.array)
|
|
276
|
+
newObject.array = directory.array || 'files'
|
|
277
|
+
|
|
270
278
|
for (const key of Object.keys(directory.object)) {
|
|
271
279
|
if (typeof directory.object[key] == 'string') {
|
|
272
280
|
|
|
@@ -284,7 +292,9 @@ module.exports = async function file(CoCreateConfig, configPath, match) {
|
|
|
284
292
|
if (skip !== 'directory') {
|
|
285
293
|
if (!newObject.object._id)
|
|
286
294
|
newObject.$filter = {
|
|
287
|
-
query:
|
|
295
|
+
query: {
|
|
296
|
+
pathname
|
|
297
|
+
}
|
|
288
298
|
}
|
|
289
299
|
|
|
290
300
|
response = await runStore(newObject);
|
|
@@ -396,7 +406,9 @@ module.exports = async function file(CoCreateConfig, configPath, match) {
|
|
|
396
406
|
let data = { array, object }
|
|
397
407
|
if (!object._id && object.pathname)
|
|
398
408
|
data.$filter = {
|
|
399
|
-
query:
|
|
409
|
+
query: {
|
|
410
|
+
$or: [{ pathname: object.pathname }]
|
|
411
|
+
}
|
|
400
412
|
}
|
|
401
413
|
|
|
402
414
|
if (match.length && isMatch)
|