alchemy-media 0.7.0 → 0.7.2
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 +17 -0
- package/README.md +1 -1
- package/assets/stylesheets/media_elements/_icon.scss +15 -1
- package/bootstrap.js +78 -15
- package/controller/media_files_controller.js +27 -9
- package/element/al_file.js +32 -3
- package/element/al_icon.js +18 -1
- package/element/al_svg.js +24 -1
- package/helper/media_helper.js +13 -7
- package/helper/widgets/image_widget.js +27 -3
- package/helper_field/file_field_type.js +42 -0
- package/model/media_file_model.js +16 -3
- package/model/media_raw_model.js +9 -1
- package/package.json +2 -2
- package/view/element/al_file.hwk +7 -1
- package/view/element/al_file_selection.hwk +1 -0
- package/view/form/inputs/edit/file.hwk +2 -1
- package/view/form/inputs/view_inline/file.hwk +1 -1
- package/view/form/inputs/view_inline/file_preview.hwk +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## 0.7.2 (2023-01-23)
|
|
2
|
+
|
|
3
|
+
* Make `al-icon` center its contents
|
|
4
|
+
* Make the file upload action use the extra given filename
|
|
5
|
+
* Rename most route names & make them not-postponable
|
|
6
|
+
|
|
7
|
+
## 0.7.1 (2022-12-23)
|
|
8
|
+
|
|
9
|
+
* Cascade `al-svg` role attribute to child `svg` elements
|
|
10
|
+
* Add `img` role fallback when using `graphics-symbol`
|
|
11
|
+
* Also add default role to `al-icon` element
|
|
12
|
+
* Make `al-file` catch errors and report them to a possible `al-field` parent
|
|
13
|
+
* Add the `accept` attribute to `al-file`
|
|
14
|
+
* Add the `accept` option to `File` fields
|
|
15
|
+
* Add `width_hint` field to `image` widget. This field allows users to specify the approximate maximum width of an image in pixels or as a percentage of the total page width.
|
|
16
|
+
* Add `lazy_load` field to `image` widget
|
|
17
|
+
|
|
1
18
|
## 0.7.0 (2022-11-02)
|
|
2
19
|
|
|
3
20
|
* Use the `al-` prefix for custom elements
|
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ you can do so like this on Debian/Ubuntu
|
|
|
75
75
|
|
|
76
76
|
Install the requirements of the `veronica` module:
|
|
77
77
|
|
|
78
|
-
apt-get install graphicsmagick webp libgif-dev
|
|
78
|
+
apt-get install graphicsmagick webp libgif-dev libcairo2-dev libpango1.0-dev libjpeg-dev librsvg2-dev
|
|
79
79
|
|
|
80
80
|
This plugin requires exiv2
|
|
81
81
|
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
al-icon {
|
|
2
2
|
// inline-flex breaks certain (duotone) icons
|
|
3
|
-
|
|
3
|
+
--fa-display: inline-flex;
|
|
4
|
+
display: inline-flex;
|
|
4
5
|
flex-flow: column;
|
|
5
6
|
justify-content: center;
|
|
6
7
|
align-content: center;
|
|
7
8
|
text-align: center;
|
|
9
|
+
position: relative;
|
|
8
10
|
|
|
9
11
|
&[hidden] {
|
|
10
12
|
display: none !important;
|
|
11
13
|
}
|
|
14
|
+
|
|
15
|
+
// Fix Fontawesome duotone icons
|
|
16
|
+
&[icon-style="duotone"] {
|
|
17
|
+
position: relative;
|
|
18
|
+
|
|
19
|
+
&::before {
|
|
20
|
+
position: absolute;
|
|
21
|
+
top: 50%;
|
|
22
|
+
left: 50%;
|
|
23
|
+
transform: translate(-50%, -50%);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
12
26
|
}
|
package/bootstrap.js
CHANGED
|
@@ -40,32 +40,95 @@ alchemy.createDir(options.scratch);
|
|
|
40
40
|
alchemy.createDir(options.cache);
|
|
41
41
|
|
|
42
42
|
// Create routes
|
|
43
|
-
Router.
|
|
44
|
-
|
|
43
|
+
Router.add({
|
|
44
|
+
name : 'MediaFile#serveStatic',
|
|
45
|
+
methods : ['get'],
|
|
46
|
+
can_be_postponed : false,
|
|
47
|
+
paths : /\/media\/static\/(.*)*/,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
Router.add({
|
|
51
|
+
name : 'MediaFile#image',
|
|
52
|
+
methods : ['get'],
|
|
53
|
+
can_be_postponed : false,
|
|
54
|
+
paths : options.url + '/{id}',
|
|
55
|
+
});
|
|
45
56
|
|
|
46
57
|
// The prefix is added at the end of the route so it does not
|
|
47
58
|
// change the user's active_prefix
|
|
48
|
-
Router.
|
|
49
|
-
|
|
59
|
+
Router.add({
|
|
60
|
+
name : 'MediaFile#data',
|
|
61
|
+
methods : ['get'],
|
|
62
|
+
can_be_postponed : false,
|
|
63
|
+
paths : '/media/data/{prefix}/{id}',
|
|
64
|
+
});
|
|
50
65
|
|
|
51
66
|
Router.add({
|
|
52
|
-
name
|
|
53
|
-
methods
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
name : 'MediaFile#info',
|
|
68
|
+
methods : ['get'],
|
|
69
|
+
can_be_postponed : false,
|
|
70
|
+
paths : '/media/info',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
Router.add({
|
|
74
|
+
name : 'MediaFile#recordsource',
|
|
75
|
+
methods : ['get'],
|
|
76
|
+
can_be_postponed : false,
|
|
77
|
+
paths : '/media/recordsource',
|
|
78
|
+
permission : 'media.recordsource',
|
|
56
79
|
});
|
|
57
80
|
|
|
58
81
|
// Allow dummy extensions
|
|
59
|
-
Router.
|
|
82
|
+
Router.add({
|
|
83
|
+
name : 'Media#fileextension',
|
|
84
|
+
methods : ['get'],
|
|
85
|
+
can_be_postponed : false,
|
|
86
|
+
paths : '/media/file/{id}.{extension}',
|
|
87
|
+
handler : 'MediaFile#file'
|
|
88
|
+
});
|
|
60
89
|
|
|
61
90
|
// Allow direct file downloads
|
|
62
|
-
Router.
|
|
63
|
-
|
|
91
|
+
Router.add({
|
|
92
|
+
name : 'MediaFile#file',
|
|
93
|
+
methods : ['get'],
|
|
94
|
+
can_be_postponed : false,
|
|
95
|
+
paths : '/media/file/{id}',
|
|
96
|
+
});
|
|
64
97
|
|
|
65
|
-
Router.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
98
|
+
Router.add({
|
|
99
|
+
name : 'MediaFile#downloadFile',
|
|
100
|
+
methods : ['get'],
|
|
101
|
+
can_be_postponed : false,
|
|
102
|
+
paths : '/media/download/{id}',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
Router.add({
|
|
106
|
+
name : 'MediaFile#thumbnail',
|
|
107
|
+
methods : ['get'],
|
|
108
|
+
can_be_postponed : false,
|
|
109
|
+
paths : '/media/thumbnail/{id}',
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
Router.add({
|
|
113
|
+
name : 'MediaFile#placeholder',
|
|
114
|
+
methods : ['get'],
|
|
115
|
+
can_be_postponed : false,
|
|
116
|
+
paths : '/media/placeholder',
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
Router.add({
|
|
120
|
+
name : 'MediaFile#upload',
|
|
121
|
+
methods : ['post'],
|
|
122
|
+
can_be_postponed : false,
|
|
123
|
+
paths : '/media/upload',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
Router.add({
|
|
127
|
+
name : 'MediaFile#uploadsingle',
|
|
128
|
+
methods : ['post'],
|
|
129
|
+
can_be_postponed : false,
|
|
130
|
+
paths : '/media/uploadsingle',
|
|
131
|
+
});
|
|
69
132
|
|
|
70
133
|
var profiles = alchemy.shared('Media.profiles');
|
|
71
134
|
|
|
@@ -206,7 +206,7 @@ MediaFiles.setAction(function downloadFile(conduit, id, extension) {
|
|
|
206
206
|
*
|
|
207
207
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
208
208
|
* @since 0.0.1
|
|
209
|
-
* @version 0.
|
|
209
|
+
* @version 0.7.2
|
|
210
210
|
*
|
|
211
211
|
* @param {Conduit} conduit
|
|
212
212
|
*/
|
|
@@ -215,22 +215,29 @@ MediaFiles.setAction(function upload(conduit) {
|
|
|
215
215
|
var MediaFile = this.getModel('MediaFile'),
|
|
216
216
|
files = conduit.files,
|
|
217
217
|
tasks = [],
|
|
218
|
-
|
|
218
|
+
accept = conduit.body?.accept;
|
|
219
219
|
|
|
220
220
|
if (files && files.files && typeof files.files == 'object') {
|
|
221
221
|
files = files.files;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
for (let key in files) {
|
|
225
|
+
let file = files[key];
|
|
226
|
+
|
|
227
|
+
tasks.push(async next => {
|
|
228
|
+
|
|
229
|
+
let filename = file.name;
|
|
230
|
+
|
|
231
|
+
if (key == 'uploaded_file' && conduit.body.filename) {
|
|
232
|
+
filename = conduit.body.filename;
|
|
233
|
+
}
|
|
226
234
|
|
|
227
|
-
tasks[tasks.length] = function storeFile(next) {
|
|
228
235
|
let options = {
|
|
229
236
|
move: true,
|
|
230
|
-
filename:
|
|
237
|
+
filename: filename,
|
|
231
238
|
};
|
|
232
239
|
|
|
233
|
-
let name =
|
|
240
|
+
let name = filename.split('.');
|
|
234
241
|
|
|
235
242
|
// Remove the last piece if there are more than 1
|
|
236
243
|
if (name.length > 1) {
|
|
@@ -242,9 +249,20 @@ MediaFiles.setAction(function upload(conduit) {
|
|
|
242
249
|
|
|
243
250
|
options.name = name;
|
|
244
251
|
|
|
252
|
+
// @TODO: don't trust the browser to dictate the type
|
|
253
|
+
if (accept) {
|
|
254
|
+
let file_type = await file.getMimetype();
|
|
255
|
+
|
|
256
|
+
if (file_type === accept || accept.includes(file_type)) {
|
|
257
|
+
// OK!
|
|
258
|
+
} else {
|
|
259
|
+
return next(new Error('File upload failed: Expected filetype "' + accept + '", but got "' + file_type + '"'));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
245
263
|
MediaFile.addFile(file.path, options, next);
|
|
246
|
-
};
|
|
247
|
-
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
248
266
|
|
|
249
267
|
// Store every file
|
|
250
268
|
Function.parallel(tasks, function storedFiles(err, result) {
|
package/element/al_file.js
CHANGED
|
@@ -79,6 +79,15 @@ AlFile.addElementGetter('icon_uploading', '.uploading-icon');
|
|
|
79
79
|
*/
|
|
80
80
|
AlFile.addElementGetter('icon_empty', '.empty-icon');
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Set the accepted types
|
|
84
|
+
*
|
|
85
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
86
|
+
* @since 0.7.1
|
|
87
|
+
* @version 0.7.1
|
|
88
|
+
*/
|
|
89
|
+
AlFile.setAttribute('accept');
|
|
90
|
+
|
|
82
91
|
/**
|
|
83
92
|
* Set the value
|
|
84
93
|
*
|
|
@@ -135,7 +144,7 @@ AlFile.setMethod(function updatePreview(value) {
|
|
|
135
144
|
*
|
|
136
145
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
137
146
|
* @since 0.6.0
|
|
138
|
-
* @version 0.
|
|
147
|
+
* @version 0.7.1
|
|
139
148
|
*/
|
|
140
149
|
AlFile.setMethod(async function uploadFile(config) {
|
|
141
150
|
|
|
@@ -159,6 +168,10 @@ AlFile.setMethod(async function uploadFile(config) {
|
|
|
159
168
|
form_data.append('format', format);
|
|
160
169
|
}
|
|
161
170
|
|
|
171
|
+
if (this.accept) {
|
|
172
|
+
form_data.append('accept', this.accept);
|
|
173
|
+
}
|
|
174
|
+
|
|
162
175
|
let response;
|
|
163
176
|
|
|
164
177
|
try {
|
|
@@ -167,7 +180,15 @@ AlFile.setMethod(async function uploadFile(config) {
|
|
|
167
180
|
post : form_data,
|
|
168
181
|
});
|
|
169
182
|
} catch (err) {
|
|
170
|
-
|
|
183
|
+
|
|
184
|
+
let alchemy_field = this.queryUp('al-field');
|
|
185
|
+
|
|
186
|
+
if (alchemy_field) {
|
|
187
|
+
alchemy_field.showError(err);
|
|
188
|
+
} else {
|
|
189
|
+
console.error('Failed to upload file:', err);
|
|
190
|
+
alert('Failed to upload file: ' + err);
|
|
191
|
+
}
|
|
171
192
|
}
|
|
172
193
|
|
|
173
194
|
this.classList.remove('uploading');
|
|
@@ -282,12 +303,20 @@ AlFile.setMethod(function _getContent(callback) {
|
|
|
282
303
|
*
|
|
283
304
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
284
305
|
* @since 0.7.0
|
|
285
|
-
* @version 0.7.
|
|
306
|
+
* @version 0.7.1
|
|
286
307
|
*/
|
|
287
308
|
AlFile.setMethod(async function showExistingFileSelection() {
|
|
288
309
|
|
|
289
310
|
let variables = {};
|
|
290
311
|
|
|
312
|
+
if (this.accept) {
|
|
313
|
+
let filters = {
|
|
314
|
+
type : this.accept,
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
variables.filters = filters;
|
|
318
|
+
}
|
|
319
|
+
|
|
291
320
|
await hawkejs.scene.render('element/al_file_selection', variables);
|
|
292
321
|
|
|
293
322
|
let dialog_contents = document.querySelector('he-dialog [data-he-template="element/al_file_selection"]');
|
package/element/al_icon.js
CHANGED
|
@@ -47,6 +47,15 @@ Icon.setAttribute('icon-name');
|
|
|
47
47
|
*/
|
|
48
48
|
Icon.setAttribute('icon-flags');
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Set the default role
|
|
52
|
+
*
|
|
53
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
54
|
+
* @since 0.7.1
|
|
55
|
+
* @version 0.7.1
|
|
56
|
+
*/
|
|
57
|
+
Icon.setRole('graphics-symbol');
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* Refresh the icon when these attributes change
|
|
52
61
|
*
|
|
@@ -85,7 +94,7 @@ Icon.setMethod(function introduced() {
|
|
|
85
94
|
*
|
|
86
95
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
87
96
|
* @since 0.7.0
|
|
88
|
-
* @version 0.7.
|
|
97
|
+
* @version 0.7.1
|
|
89
98
|
*
|
|
90
99
|
* @param {Boolean} force
|
|
91
100
|
*/
|
|
@@ -95,6 +104,14 @@ Icon.setMethod(function refresh(force) {
|
|
|
95
104
|
return;
|
|
96
105
|
}
|
|
97
106
|
|
|
107
|
+
if (this.role == 'graphics-symbol') {
|
|
108
|
+
this.role = 'graphics-symbol img';
|
|
109
|
+
|
|
110
|
+
if (!this.hasAttribute('aria-label')) {
|
|
111
|
+
this.setAttribute('aria-label', '');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
98
115
|
if (!force && Blast.isNode) {
|
|
99
116
|
return;
|
|
100
117
|
}
|
package/element/al_svg.js
CHANGED
|
@@ -21,7 +21,7 @@ Svg.setAttribute('src');
|
|
|
21
21
|
*
|
|
22
22
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
23
23
|
* @since 0.5.1
|
|
24
|
-
* @version 0.
|
|
24
|
+
* @version 0.7.1
|
|
25
25
|
*/
|
|
26
26
|
Svg.setMethod(async function injectSvg() {
|
|
27
27
|
|
|
@@ -50,6 +50,29 @@ Svg.setMethod(async function injectSvg() {
|
|
|
50
50
|
|
|
51
51
|
this.innerHTML = contents;
|
|
52
52
|
|
|
53
|
+
if (this.role) {
|
|
54
|
+
|
|
55
|
+
// Do not allow `graphics-symbol` role, because it is not widely supported
|
|
56
|
+
// and google doesn't know it either
|
|
57
|
+
if (this.role == 'graphics-symbol') {
|
|
58
|
+
this.role = 'img';
|
|
59
|
+
|
|
60
|
+
if (!this.hasAttribute('aria-label')) {
|
|
61
|
+
this.setAttribute('aria-label', '');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let svg = this.querySelector('svg');
|
|
66
|
+
|
|
67
|
+
if (svg) {
|
|
68
|
+
svg.setAttribute('role', this.role);
|
|
69
|
+
|
|
70
|
+
if (this.hasAttribute('aria-label')) {
|
|
71
|
+
svg.setAttribute('aria-label', this.getAttribute('aria-label'));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
if (this._resolve_me_too) {
|
|
54
77
|
this._resolve_me_too.resolve();
|
|
55
78
|
}
|
package/helper/media_helper.js
CHANGED
|
@@ -115,7 +115,7 @@ Media.setMethod(function loadIconFont() {
|
|
|
115
115
|
*
|
|
116
116
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
117
117
|
* @since 0.5.0
|
|
118
|
-
* @version 0.
|
|
118
|
+
* @version 0.7.1
|
|
119
119
|
*
|
|
120
120
|
* @param {Element} element The element to apply to
|
|
121
121
|
* @param {String} image The image identifier
|
|
@@ -160,6 +160,12 @@ Media.setMethod(function applyDirective(element, image, options) {
|
|
|
160
160
|
options.height = height;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
if (options.lazy_load) {
|
|
164
|
+
if (!element.hasAttribute('loading')) {
|
|
165
|
+
element.setAttribute('loading', 'lazy');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
163
169
|
let url = this.imageUrl(image, options),
|
|
164
170
|
clone = url.clone();
|
|
165
171
|
|
|
@@ -224,7 +230,7 @@ Media.setMethod(function applyDirective(element, image, options) {
|
|
|
224
230
|
*
|
|
225
231
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
226
232
|
* @since 0.4.0
|
|
227
|
-
* @version 0.
|
|
233
|
+
* @version 0.7.2
|
|
228
234
|
*
|
|
229
235
|
* @param {String} image_id
|
|
230
236
|
*
|
|
@@ -234,7 +240,7 @@ Media.setMethod(function fileAnchor(file_id, options) {
|
|
|
234
240
|
|
|
235
241
|
var url;
|
|
236
242
|
|
|
237
|
-
return this.view.helpers.Router.printRoute('
|
|
243
|
+
return this.view.helpers.Router.printRoute('MediaFile#file', {id: file_id}, options);
|
|
238
244
|
});
|
|
239
245
|
|
|
240
246
|
/**
|
|
@@ -242,7 +248,7 @@ Media.setMethod(function fileAnchor(file_id, options) {
|
|
|
242
248
|
*
|
|
243
249
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
244
250
|
* @since 0.2.0
|
|
245
|
-
* @version 0.
|
|
251
|
+
* @version 0.7.2
|
|
246
252
|
*
|
|
247
253
|
* @param {String} image_id
|
|
248
254
|
*
|
|
@@ -263,7 +269,7 @@ Media.setMethod(function imageUrl(image_id, options) {
|
|
|
263
269
|
if (options.route) {
|
|
264
270
|
routeName = options.route;
|
|
265
271
|
} else {
|
|
266
|
-
routeName = '
|
|
272
|
+
routeName = 'MediaFile#image';
|
|
267
273
|
}
|
|
268
274
|
|
|
269
275
|
url = this.parseURL(this.view.helpers.Router.routeUrl(routeName, {id: image_id}));
|
|
@@ -305,7 +311,7 @@ Media.setMethod(function imageUrl(image_id, options) {
|
|
|
305
311
|
*
|
|
306
312
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
307
313
|
* @since 0.2.0
|
|
308
|
-
* @version 0.
|
|
314
|
+
* @version 0.7.2
|
|
309
315
|
*
|
|
310
316
|
* @param {Object} options
|
|
311
317
|
*
|
|
@@ -315,7 +321,7 @@ Media.setMethod(function placeholderUrl(options) {
|
|
|
315
321
|
|
|
316
322
|
var url;
|
|
317
323
|
|
|
318
|
-
url = this.parseURL(this.view.helpers.Router.routeUrl('
|
|
324
|
+
url = this.parseURL(this.view.helpers.Router.routeUrl('MediaFile#placeholder'));
|
|
319
325
|
|
|
320
326
|
if (options != null) {
|
|
321
327
|
|
|
@@ -16,12 +16,25 @@ const Image = Function.inherits('Alchemy.Widget', 'Image');
|
|
|
16
16
|
*
|
|
17
17
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
18
18
|
* @since 0.6.0
|
|
19
|
-
* @version 0.
|
|
19
|
+
* @version 0.7.1
|
|
20
20
|
*/
|
|
21
21
|
Image.constitute(function prepareSchema() {
|
|
22
22
|
|
|
23
23
|
this.schema.addField('image', 'File', {
|
|
24
|
+
description : 'Upload/select the image to display',
|
|
25
|
+
widget_config_editable: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.schema.addField('width_hint', 'Number', {
|
|
29
|
+
description : 'Approximate maximum width of the image in pixels or as a percentage of the total page width.',
|
|
30
|
+
widget_config_editable: true,
|
|
31
|
+
default: '25%',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.schema.addField('lazy_load', 'Boolean', {
|
|
35
|
+
description : 'Determines whether the image should be loaded lazily or not',
|
|
24
36
|
widget_config_editable: true,
|
|
37
|
+
default: true,
|
|
25
38
|
});
|
|
26
39
|
});
|
|
27
40
|
|
|
@@ -30,7 +43,7 @@ Image.constitute(function prepareSchema() {
|
|
|
30
43
|
*
|
|
31
44
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
32
45
|
* @since 0.6.0
|
|
33
|
-
* @version 0.
|
|
46
|
+
* @version 0.7.1
|
|
34
47
|
*
|
|
35
48
|
* @param {HTMLElement} widget
|
|
36
49
|
*/
|
|
@@ -38,7 +51,18 @@ Image.setMethod(function populateWidget() {
|
|
|
38
51
|
|
|
39
52
|
let img = this.createElement('img');
|
|
40
53
|
|
|
41
|
-
|
|
54
|
+
let width_hint = this.config.width_hint,
|
|
55
|
+
lazy_load = this.config.lazy_load;
|
|
56
|
+
|
|
57
|
+
if (width_hint === null || width_hint === '' || typeof width_hint == 'undefined') {
|
|
58
|
+
width_hint = '25%';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (lazy_load == null) {
|
|
62
|
+
lazy_load = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.hawkejs_renderer.helpers.Media.applyDirective(img, this.config.image, {width: width_hint, lazy_load});
|
|
42
66
|
|
|
43
67
|
this.widget.append(img);
|
|
44
68
|
|
|
@@ -16,6 +16,48 @@ var FileField = Function.inherits('Alchemy.Field.ObjectId', 'File');
|
|
|
16
16
|
*/
|
|
17
17
|
FileField.setProperty('deferCast', true);
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Get the accepted types
|
|
21
|
+
*
|
|
22
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
23
|
+
* @since 0.7.1
|
|
24
|
+
* @version 0.7.1
|
|
25
|
+
*
|
|
26
|
+
* @return {Array|null}
|
|
27
|
+
*/
|
|
28
|
+
FileField.setMethod(function getAcceptedTypes() {
|
|
29
|
+
|
|
30
|
+
let accept = this.options?.accept;
|
|
31
|
+
|
|
32
|
+
if (!accept) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
accept = Array.cast(accept);
|
|
37
|
+
|
|
38
|
+
return accept;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get the accepted types string, for the input element
|
|
43
|
+
*
|
|
44
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
45
|
+
* @since 0.7.1
|
|
46
|
+
* @version 0.7.1
|
|
47
|
+
*
|
|
48
|
+
* @return {String|null}
|
|
49
|
+
*/
|
|
50
|
+
FileField.setMethod(function getAcceptedTypesString() {
|
|
51
|
+
|
|
52
|
+
let types = this.getAcceptedTypes();
|
|
53
|
+
|
|
54
|
+
if (!types?.length) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return types.join(', ');
|
|
59
|
+
});
|
|
60
|
+
|
|
19
61
|
if (Blast.isBrowser) {
|
|
20
62
|
return;
|
|
21
63
|
}
|
|
@@ -225,20 +225,33 @@ MediaFile.setMethod(function getFile(id, callback) {
|
|
|
225
225
|
*
|
|
226
226
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
227
227
|
* @since 0.0.1
|
|
228
|
-
* @version 0.
|
|
228
|
+
* @version 0.7.1
|
|
229
229
|
*
|
|
230
230
|
* @param {String} file The path to the file, can be a URL
|
|
231
231
|
* @param {Object} options
|
|
232
232
|
* @param {Function} callback
|
|
233
|
+
*
|
|
234
|
+
* @return {Pledge}
|
|
233
235
|
*/
|
|
234
236
|
MediaFile.setMethod(function addFile(file, options, callback) {
|
|
235
237
|
|
|
236
|
-
|
|
238
|
+
const that = this,
|
|
239
|
+
pledge = new Pledge();
|
|
240
|
+
|
|
241
|
+
pledge.done(callback);
|
|
237
242
|
|
|
238
243
|
this.queue.add(function(done) {
|
|
239
244
|
that.getModel('MediaRaw').addFile(file, options, function(err, response) {
|
|
240
|
-
|
|
245
|
+
|
|
241
246
|
done();
|
|
247
|
+
|
|
248
|
+
if (err) {
|
|
249
|
+
pledge.reject(err);
|
|
250
|
+
} else {
|
|
251
|
+
pledge.resolve(response);
|
|
252
|
+
}
|
|
242
253
|
});
|
|
243
254
|
});
|
|
255
|
+
|
|
256
|
+
return pledge;
|
|
244
257
|
});
|
package/model/media_raw_model.js
CHANGED
|
@@ -168,7 +168,7 @@ MediaRaw.Document.setMethod(function extraImportFromStream(input) {
|
|
|
168
168
|
*
|
|
169
169
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
170
170
|
* @since 0.0.1
|
|
171
|
-
* @version 0.
|
|
171
|
+
* @version 0.7.1
|
|
172
172
|
*
|
|
173
173
|
* @param {String} file The path to the file, can be a URL
|
|
174
174
|
* @param {Object} options
|
|
@@ -185,6 +185,14 @@ MediaRaw.setMethod(function addFile(file, options, callback) {
|
|
|
185
185
|
options = {};
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
if (!options) {
|
|
189
|
+
options = {};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (file && typeof file == 'object' && file instanceof Classes.Alchemy.Inode.File) {
|
|
193
|
+
file = file.path;
|
|
194
|
+
}
|
|
195
|
+
|
|
188
196
|
// If the given file is actually a url, we'll need to download it first
|
|
189
197
|
if (file.startsWith('http://') || file.startsWith('https://')) {
|
|
190
198
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy-media",
|
|
3
3
|
"description": "The media plugin for Alchemy",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.2",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type" : "git",
|
|
7
7
|
"url" : "https://github.com/11ways/alchemy-media.git"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"veronica" : "~0.2.2"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"alchemymvc" : ">=1.
|
|
15
|
+
"alchemymvc" : ">=1.3.0"
|
|
16
16
|
},
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"engines": {
|
package/view/element/al_file.hwk
CHANGED
|
@@ -13,7 +13,13 @@
|
|
|
13
13
|
class="empty-icon"
|
|
14
14
|
><% if (self.value) $0.hidden = true %></al-icon>
|
|
15
15
|
|
|
16
|
-
<input
|
|
16
|
+
<input
|
|
17
|
+
class="al-file-input"
|
|
18
|
+
type="file"
|
|
19
|
+
tabindex="-1"
|
|
20
|
+
accept={% self.accept %}
|
|
21
|
+
hidden
|
|
22
|
+
>
|
|
17
23
|
</label>
|
|
18
24
|
|
|
19
25
|
<div class="al-file-right">
|