alchemy-media 0.6.3 → 0.6.4

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 CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.6.4 (2022-10-13)
2
+
3
+ * Add the `Media#loadIconFont()` helper method
4
+ * Make the `image` route serve up filetype thumbnails for non-images
5
+ * Add file preview image to the chimera edit view of MediaFile
6
+ * Add thumbnail column to MediaFile chimera index view
7
+ * Add `prefix` parameter to the `MediaFile#data` route
8
+
1
9
  ## 0.6.3 (2022-07-23)
2
10
 
3
11
  * Fix `al-file` element showing wrong buttons on load
@@ -92,4 +92,30 @@ al-file {
92
92
  button {
93
93
  min-height: 2rem;
94
94
  }
95
+ }
96
+
97
+ alchemy-field[field-view="file_preview"] {
98
+ [data-he-name="field"] .field {
99
+ padding: 0;
100
+
101
+ img {
102
+ max-height: 25rem;
103
+ object-fit: contain;
104
+ }
105
+ }
106
+ }
107
+
108
+ alchemy-field[field-view="file_preview"],
109
+ alchemy-field[field-view="file"],
110
+ alchemy-field[field-type="file"] {
111
+
112
+ &[mode="inline"] {
113
+ .field img {
114
+ object-fit: contain;
115
+ width: 100px;
116
+ height: 100px;
117
+ display: block;
118
+ margin: auto;
119
+ }
120
+ }
95
121
  }
package/bootstrap.js CHANGED
@@ -43,7 +43,9 @@ alchemy.createDir(options.cache);
43
43
  Router.get('Media::static', /\/media\/static\/(.*)*/, 'MediaFile#serveStatic');
44
44
  Router.get('Media::image', options.url + '/{id}', 'MediaFile#image');
45
45
 
46
- Router.get('MediaFile#data', '/media/data/{[MediaFile._id]id}', 'MediaFile#data');
46
+ // The prefix is added at the end of the route so it does not
47
+ // change the user's active_prefix
48
+ Router.get('MediaFile#data', '/media/data/{prefix}/{id}', 'MediaFile#data');
47
49
  Router.get('MediaFile#info', '/media/info', 'MediaFile#info');
48
50
 
49
51
  // Allow dummy extensions
@@ -13,16 +13,14 @@ var fs = require('fs'),
13
13
  * @since 0.0.1
14
14
  * @version 0.3.0
15
15
  */
16
- var MediaFiles = Function.inherits('Alchemy.Controller', function MediaFile(conduit, options) {
17
- MediaFile.super.call(this, conduit, options);
18
- });
16
+ const MediaFiles = Function.inherits('Alchemy.Controller', 'MediaFile');
19
17
 
20
18
  /**
21
19
  * Serve a thumbnail
22
20
  *
23
21
  * @author Jelle De Loecker <jelle@develry.be>
24
22
  * @since 0.0.1
25
- * @version 0.4.1
23
+ * @version 0.6.4
26
24
  *
27
25
  * @param {Conduit} conduit
28
26
  */
@@ -35,21 +33,15 @@ MediaFiles.setAction(function thumbnail(conduit, id) {
35
33
  // Get the requested file
36
34
  this.getModel('MediaFile').getFile(id, function gotFile(err, record) {
37
35
 
38
- var Type;
39
-
40
36
  if (err) {
41
37
  return conduit.notFound(err);
42
38
  }
43
39
 
44
- Type = MediaTypes[record.type];
45
-
46
- if (!Type) {
47
- Type = Classes.Alchemy.MediaType;
48
- }
40
+ const Type = MediaTypes[record.type] || Classes.Alchemy.MediaType;
49
41
 
50
42
  if (Type) {
51
- Type = new Type();
52
- Type.thumbnail(conduit, record);
43
+ let instance = new Type();
44
+ instance.thumbnail(conduit, record);
53
45
  } else {
54
46
  conduit.error('Error generating thumbnail of ' + record.type);
55
47
  }
@@ -100,7 +92,7 @@ MediaFiles.setAction(function serveStatic(conduit, path) {
100
92
  *
101
93
  * @author Jelle De Loecker <jelle@develry.be>
102
94
  * @since 0.0.1
103
- * @version 0.4.1
95
+ * @version 0.6.4
104
96
  *
105
97
  * @param {Conduit} conduit
106
98
  */
@@ -112,12 +104,22 @@ MediaFiles.setAction(function image(conduit, id) {
112
104
 
113
105
  this.getModel('MediaFile').getFile(id, function gotFile(err, record) {
114
106
 
115
- var Image = new MediaTypes.image;
107
+ if (err) {
108
+ return conduit.error(err);
109
+ }
110
+
111
+ const Image = new MediaTypes.image;
116
112
 
117
113
  if (!record) {
118
114
  return Image.placeholder(conduit, {text: 404, status: 404});
119
115
  }
120
116
 
117
+ if (record.type != 'image') {
118
+ const Type = MediaTypes[record.type] || Classes.Alchemy.MediaType;
119
+ let instance = new Type();
120
+ return instance.thumbnail(conduit, record);
121
+ }
122
+
121
123
  Image.serve(conduit, record);
122
124
  });
123
125
  });
@@ -315,14 +317,23 @@ MediaFiles.setAction(function uploadsingle(conduit) {
315
317
  /**
316
318
  * Get the file data
317
319
  *
318
- * @author Jelle De Loecker <jelle@develry.be>
320
+ * @author Jelle De Loecker <jelle@elevenways.be>
319
321
  * @since 0.5.1
320
- * @version 0.5.1
322
+ * @version 0.6.4
321
323
  *
322
- * @param {Conduit} conduit
323
- * @param {Document.MediaFile} media_file
324
+ * @param {Conduit} conduit
325
+ * @param {ObjectId} media_file_id
324
326
  */
325
- MediaFiles.setAction(function data(conduit, media_file) {
327
+ MediaFiles.setAction(async function data(conduit, prefix, media_file_id) {
328
+
329
+ conduit.prefix = prefix;
330
+
331
+ let media_file = await this.model.findById(media_file_id);
332
+
333
+ if (!media_file) {
334
+ return conduit.notFound();
335
+ }
336
+
326
337
  conduit.setHeader('cache-control', 'public, max-age=3600, must-revalidate');
327
338
 
328
339
  conduit.end({
@@ -112,7 +112,7 @@ Icon.setMethod(function setIcon(info) {
112
112
  *
113
113
  * @author Jelle De Loecker <jelle@elevenways.be>
114
114
  * @since 0.6.3
115
- * @version 0.6.3
115
+ * @version 0.6.4
116
116
  */
117
117
  Icon.setMethod(function setCssClasses() {
118
118
 
@@ -120,14 +120,13 @@ Icon.setMethod(function setCssClasses() {
120
120
  return;
121
121
  }
122
122
 
123
+ // Load the appropriate font style
124
+ this.hawkejs_renderer.helpers.Media.loadIconFont();
125
+
123
126
  let fa_pro = this.hawkejs_renderer.expose('fontawesome_pro'),
124
127
  style = this.icon_style || 'regular';
125
128
 
126
- if (fa_pro) {
127
- this.hawkejs_renderer.style(fa_pro);
128
- } else {
129
- this.hawkejs_renderer.style('alchemy_icons_fafree');
130
-
129
+ if (!fa_pro) {
131
130
  if (style == 'duotone' || style == 'light' || style == 'thin' || style == 'regular') {
132
131
  style = 'solid';
133
132
  }
@@ -88,6 +88,28 @@ Media.setStatic(function loadImagesBasedOnSize() {
88
88
  }
89
89
  });
90
90
 
91
+ /**
92
+ * Load the icon font
93
+ *
94
+ * @author Jelle De Loecker <jelle@elevenways.be>
95
+ * @since 0.6.4
96
+ * @version 0.6.4
97
+ *
98
+ * @return {string}
99
+ */
100
+ Media.setMethod(function loadIconFont() {
101
+
102
+ let font_style = this.hawkejs_renderer.expose('fontawesome_pro');
103
+
104
+ if (!font_style) {
105
+ font_style = 'alchemy_icons_fafree';
106
+ }
107
+
108
+ this.hawkejs_renderer.style(font_style);
109
+
110
+ return font_style;
111
+ });
112
+
91
113
  /**
92
114
  * Apply directive to an element
93
115
  *
@@ -173,7 +195,8 @@ Media.setMethod(function applyDirective(element, image, options) {
173
195
  this.view.helpers.Alchemy.getResource({
174
196
  name: 'MediaFile#data',
175
197
  params: {
176
- id: image
198
+ id : image,
199
+ prefix : this.view.expose('active_prefix') || '__',
177
200
  }
178
201
  }, function gotResult(err, data) {
179
202
 
@@ -4,8 +4,8 @@
4
4
  * @constructor
5
5
  *
6
6
  * @author Jelle De Loecker <jelle@elevenways.be>
7
- * @since 0.1.0
8
- * @version 0.1.0
7
+ * @since 0.6.0
8
+ * @version 0.6.0
9
9
  *
10
10
  * @param {Object} data
11
11
  */
@@ -15,8 +15,8 @@ const Image = Function.inherits('Alchemy.Widget', 'Image');
15
15
  * Prepare the schema
16
16
  *
17
17
  * @author Jelle De Loecker <jelle@elevenways.be>
18
- * @since 0.1.0
19
- * @version 0.1.0
18
+ * @since 0.6.0
19
+ * @version 0.6.0
20
20
  */
21
21
  Image.constitute(function prepareSchema() {
22
22
 
@@ -29,8 +29,8 @@ Image.constitute(function prepareSchema() {
29
29
  * Populate the widget
30
30
  *
31
31
  * @author Jelle De Loecker <jelle@elevenways.be>
32
- * @since 0.1.0
33
- * @version 0.1.0
32
+ * @since 0.6.0
33
+ * @version 0.6.4
34
34
  *
35
35
  * @param {HTMLElement} widget
36
36
  */
@@ -40,7 +40,7 @@ Image.setMethod(function populateWidget() {
40
40
 
41
41
  this.hawkejs_renderer.helpers.Media.applyDirective(img, this.config.image);
42
42
 
43
- populateWidget.super.call(this);
44
-
45
43
  this.widget.append(img);
44
+
45
+ return populateWidget.super.call(this);
46
46
  });
@@ -14,10 +14,10 @@ var exiv2 = alchemy.use('@11ways/exiv2'),
14
14
  * @author Jelle De Loecker <jelle@develry.be>
15
15
  * @since 0.0.1
16
16
  * @version 0.2.0
17
+ *
18
+ * @param {Object} options
17
19
  */
18
- var ImageMedia = Function.inherits('Alchemy.MediaType', function ImageMediaType(options) {
19
- ImageMediaType.super.call(this, options);
20
- });
20
+ const ImageMedia = Function.inherits('Alchemy.MediaType', 'ImageMediaType');
21
21
 
22
22
  ImageMedia.setProperty('exivPath', alchemy.plugins.media.exiv2);
23
23
  ImageMedia.setProperty('hashType', alchemy.plugins.media.hash);
@@ -19,32 +19,48 @@ var MediaFile = Function.inherits('Alchemy.Model', function MediaFile(options) {
19
19
 
20
20
  MediaFile.setProperty('types', alchemy.shared('Media.types'));
21
21
 
22
+ /**
23
+ * The default sort options
24
+ *
25
+ * @type {Object}
26
+ */
27
+ MediaFile.prepareProperty('sort', function sort() {
28
+ return {created: -1};
29
+ });
30
+
22
31
  /**
23
32
  * Constitute the class wide schema
24
33
  *
25
- * @author Jelle De Loecker <jelle@develry.be>
34
+ * @author Jelle De Loecker <jelle@elevenways.be>
26
35
  * @since 0.2.0
27
- * @version 0.5.1
36
+ * @version 0.6.4
28
37
  */
29
38
  MediaFile.constitute(function addFields() {
30
39
 
31
- this.addField('name', 'String');
32
- this.addField('filename', 'String');
40
+ this.addField('name', 'String', {
41
+ description: 'The name of the file',
42
+ });
43
+
44
+ this.addField('filename', 'String', {
45
+ description : 'The actual filename',
46
+ });
33
47
 
34
48
  this.addField('type', 'Enum', {
35
- values: alchemy.getClassGroup('media_type')
49
+ values: alchemy.getClassGroup('media_type'),
50
+ description: 'The type of file',
36
51
  });
37
52
 
38
53
  this.addField('extra', 'Object');
39
54
 
40
- let options = {};
41
-
42
- if (alchemy.plugins.media.translatable) {
43
- options.translatable = true;
44
- }
55
+ this.addField('title', 'String', {
56
+ translatable : alchemy.plugins.media.translatable,
57
+ description : 'The title of the file (will be used in the title attribute)',
58
+ });
45
59
 
46
- this.addField('title', 'String', options);
47
- this.addField('alt', 'String', options);
60
+ this.addField('alt', 'String', {
61
+ translatable : alchemy.plugins.media.translatable,
62
+ description : 'The alternative information of the file (will be used in the alt attribute)',
63
+ });
48
64
 
49
65
  this.belongsTo('MediaRaw');
50
66
  });
@@ -54,7 +70,7 @@ MediaFile.constitute(function addFields() {
54
70
  *
55
71
  * @author Jelle De Loecker <jelle@develry.be>
56
72
  * @since 0.2.0
57
- * @version 0.5.1
73
+ * @version 0.6.4
58
74
  */
59
75
  MediaFile.constitute(function chimeraConfig() {
60
76
 
@@ -69,6 +85,15 @@ MediaFile.constitute(function chimeraConfig() {
69
85
  // Get the list group
70
86
  list = this.chimera.getActionFields('list');
71
87
 
88
+ list.addField('_id', {
89
+ view : 'file_preview',
90
+ wrapper : 'file_preview',
91
+ title : 'Thumbnail',
92
+ filter : false,
93
+ sortable : false,
94
+ });
95
+
96
+ list.addField('created');
72
97
  list.addField('name');
73
98
  list.addField('filename');
74
99
  list.addField('type');
@@ -78,6 +103,12 @@ MediaFile.constitute(function chimeraConfig() {
78
103
  // Get the edit group
79
104
  edit = this.chimera.getActionFields('edit');
80
105
 
106
+ edit.addField('_id', {
107
+ view : 'file_preview',
108
+ wrapper : 'file_preview',
109
+ title : 'Preview',
110
+ });
111
+
81
112
  edit.addField('name');
82
113
  edit.addField('filename');
83
114
  edit.addField('type');
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.6.3",
4
+ "version": "0.6.4",
5
5
  "repository": {
6
6
  "type" : "git",
7
7
  "url" : "https://github.com/skerit/alchemy-media.git"
@@ -0,0 +1,5 @@
1
+ <% style('element/alchemy_file') %>
2
+
3
+ <img
4
+ !Media={% value %}
5
+ >
@@ -0,0 +1,8 @@
1
+ <% style('element/alchemy_file') %>
2
+
3
+ {% if value %}
4
+ <img
5
+ !Media={% value %}
6
+ +media-route="Media::thumb"
7
+ >
8
+ {% /if %}
@@ -0,0 +1,8 @@
1
+ <% style('element/alchemy_file') %>
2
+
3
+ {% if value %}
4
+ <img
5
+ !Media={% value %}
6
+ +media-route="Media::thumb"
7
+ >
8
+ {% /if %}
@@ -0,0 +1,13 @@
1
+ <div class="form-field-info">
2
+ <alchemy-label>
3
+ <span
4
+ data-he-name="field-title"
5
+ data-he-slot="field-title"
6
+ ><%= alchemy_field.field_title %></span>
7
+ <small
8
+ data-he-name="field-description"
9
+ data-he-slot="field-description"
10
+ ><%= alchemy_field.field_description %></small>
11
+ </alchemy-label>
12
+ </div>
13
+ <div data-he-name="field"></div>