Skip to content

Commit a7eb16d

Browse files
committed
version 0.1, apiFetch middleware, post processing, completed bulk action, commenting
1 parent c73b556 commit a7eb16d

File tree

6 files changed

+623
-324
lines changed

6 files changed

+623
-324
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Vrannemstein is a WordPress plugin to make image thumbnails via the client-side.
44

55
It uses [wasm-vips](https://github.com/kleisauke/wasm-vips), a WebAssembly (Emscripten) flavor of [libvips](https://www.libvips.org/) (vips image processing library).
66

7-
🚧 *Under development* 🚧
7+
*Under testing*
88

99
## Usage
1010

@@ -70,9 +70,9 @@ To syncronously read and write metadata (Xmp, Exif, Iptc), use the javascript fu
7070
Don't forget to allow configuration to read from and to keep metadata according, through config filtering `array( 'readxmp' => true, 'readexif' => true, 'readiptc' => true, 'jpegsave' => array( 'keep' => 7 ), ... )`.
7171

7272
```js
73-
vrannemstein.readxmp = (xmpData, source_url) => console.log('readxmp', xmpData);
74-
vrannemstein.readexif = (exifData, source_url) => console.log('readexif', exifData);
75-
vrannemstein.readiptc = (iptcData, source_url) => console.log('readiptc', iptcData);
73+
vrannemstein.readxmp = (xmpData, source_url) => console.log('readxmp', xmpData, source_url);
74+
vrannemstein.readexif = (exifData, source_url) => console.log('readexif', exifData, source_url);
75+
vrannemstein.readiptc = (iptcData, source_url) => console.log('readiptc', iptcData, source_url);
7676

7777
vrannemstein.writexmp = (source_url) => '<x:xmpmeta xmlns:x="adobe:ns:meta/"></x:xmpmeta>';
7878
vrannemstein.writeexif = (source_url) => ({ IFD2: { UserComment: 'test' } });

inc/bulk-actions-script.php

Lines changed: 185 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -5,150 +5,213 @@
55
* @package vrannemstein
66
* @author Leonardo Laureti
77
* @license GPL-2.0-or-later
8-
*
9-
* @todo
108
*/
119

1210
defined( 'ABSPATH' ) || die();
1311

1412
?><script id="vrannemstein-bulk-actions-script">
15-
function vrannemsteinBulkThumbnails() {
16-
const mode = wp.media ? 1 : 0; // (0 list, 1 grid)
17-
18-
//
19-
let iter = 0;
20-
21-
function generate(data) {
22-
const images = [];
23-
let i = 0;
24-
for (const obj of data) {
25-
let source_url = mode ? obj.attributes.url : obj.src;
26-
source_url = source_url.replace(/-\d+x\d+(\.[^\.]+)$/, '$1');
27-
28-
if (iter && i++ == iter)
29-
break;
30-
31-
images.push(source_url);
13+
(function(wp, jQuery) {
14+
const debug = true;
15+
16+
/**
17+
* @private
18+
* @constructor
19+
* @external 'wp.media'
20+
* @external 'wp.apiFetch'
21+
*/
22+
function vrannemsteinBulkThumbnails() {
23+
const mode = wp.media ? 1 : 0; // (0 list, 1 grid)
24+
25+
/**
26+
* @private
27+
* @external vrannemstein
28+
* @external 'wp.apiFetch'
29+
* @param {array} items
30+
* @return {Promise}
31+
*/
32+
function createImageSubsizes(items) {
33+
debug && console.log('createImageSubsizes', {items});
34+
35+
const refs = {};
36+
const images = [];
37+
for (const item of items) {
38+
const {attachmentId, attachment} = item;
39+
const source_url = attachment.source_url;
40+
refs[source_url] = items.indexOf(item);
41+
images.push(source_url);
42+
}
43+
const data = [];
44+
return vrannemstein(images, true)
45+
.then((imgs) => {
46+
for (const img of imgs) {
47+
try {
48+
const body = new FormData();
49+
const i = refs[img.source_url];
50+
const {attachmentId, attachment} = items[i];
51+
const sizes = {};
52+
for (const size in img.thumbs) {
53+
const {blob, type, filename} = img.thumbs[size];
54+
body.append(size, new Blob([blob], {type}), filename);
55+
sizes[size] = img.thumbs[size].data;
56+
}
57+
body.append('data', JSON.stringify(sizes));
58+
data.push({body, attachmentId, attachment});
59+
} catch (err) {
60+
console.error(err);
61+
}
62+
}
63+
})
64+
.then(() => {
65+
const p = [];
66+
for (const {body, attachmentId} of data) {
67+
p.push(
68+
wp.apiFetch({
69+
path: `/vrannemstein/v2/attachment/${attachmentId}/post-process?action=image-subsizes`,
70+
method: 'POST',
71+
body,
72+
parse: false
73+
})
74+
);
75+
}
76+
return Promise.all(p);
77+
});
3278
}
3379

34-
//todo testing
35-
vrannemstein(images).then(thumbnails => console.log(thumbnails));
36-
}
37-
38-
function bulk_select() {
39-
const form = document.querySelector('form#posts-filter');
40-
41-
function submit(event) {
42-
const bulk = this.querySelector('select[name="action"]');
43-
44-
if (bulk.value === 'bulk-thumbnails') {
45-
event.preventDefault();
46-
47-
if (this.querySelector('input[name="media[]"]:checked')) {
48-
const elements = [];
80+
/**
81+
* @private
82+
* @param {string} src
83+
* @return {string}
84+
*/
85+
function imageSourceUrl(src) {
86+
return src.replace(/-\d+x\d+(\.[^\.]+)$/, '$1');
87+
}
4988

50-
this.querySelectorAll('input[name="media[]"]:checked').forEach((element) => {
51-
elements.push(element.closest('tr').querySelector('img'));
52-
});
53-
generate(elements);
89+
/**
90+
* @private
91+
*/
92+
function bulkMediaList() {
93+
debug && console.log('bulkMediaList');
94+
95+
const form = document.querySelector('form#posts-filter');
96+
function submit(event) {
97+
const bulk = this.querySelector('select[name="action"]');
98+
99+
if (bulk.value === 'bulk-thumbnails') {
100+
event.preventDefault();
101+
102+
if (this.querySelector('input[name="media[]"]:checked')) {
103+
const data = [];
104+
const elements = this.querySelectorAll('input[name="media[]"]:checked');
105+
elements.forEach((element) => {
106+
const row = element.closest('tr');
107+
const img = row.querySelector('img');
108+
if (img) {
109+
const attachmentId = element.value;
110+
const source_url = imageSourceUrl(img.src);
111+
data.push({attachmentId, attachment: {id: attachmentId, source_url}, batch: true});
112+
}
113+
});
114+
createImageSubsizes(data)
115+
.then(() => {
116+
elements.forEach((element) => {
117+
element.checked = false;
118+
});
119+
})
120+
.catch(err => console.error(err));
121+
}
54122
}
55123
}
124+
form && form.addEventListener('submit', submit);
56125
}
57126

58-
form && form.addEventListener('submit', submit);
59-
}
60-
61-
function bulk_button() {
62-
const frame = wp.media.frames.browse;
63-
const view = wp.media.view;
64-
const controller = frame.browserView.controller;
65-
const toolbar = frame.browserView.toolbar;
66-
const l10n = view.l10n;
67-
const Button = view.Button;
68-
69-
const BulkThumbnailsButton = Button.extend({
70-
initialize: function() {
71-
Button.prototype.initialize.apply(this, arguments);
72-
this.controller.on('selection:toggle', this.toggleDisabled, this);
73-
this.controller.on('select:activate', this.toggleDisabled, this);
74-
},
75-
toggleDisabled: function() {
76-
this.model.set('disabled', ! this.controller.state().get('selection').length);
77-
},
78-
render: function() {
79-
Button.prototype.render.apply(this, arguments);
80-
this.$el.addClass('bulk-thumbnails-button hidden');
81-
if (! this.controller.isModeActive('select')) {
82-
this.$el.addClass('hidden');
83-
} else {
84-
this.$el.removeClass('hidden');
127+
/**
128+
* @private
129+
* @external 'wp.media'
130+
*/
131+
function bulkMediaGrid() {
132+
debug && console.log('bulkMediaGrid');
133+
134+
const frame = wp.media.frames.browse;
135+
const view = wp.media.view;
136+
const controller = frame.browserView.controller;
137+
const toolbar = frame.browserView.toolbar;
138+
const l10n = view.l10n;
139+
const Button = view.Button;
140+
const BulkThumbnailsButton = Button.extend({
141+
initialize: function() {
142+
Button.prototype.initialize.apply(this, arguments);
143+
this.controller.on('selection:toggle', this.toggleDisabled, this);
144+
this.controller.on('select:activate', this.toggleDisabled, this);
145+
},
146+
toggleDisabled: function() {
147+
this.model.set('disabled', ! this.controller.state().get('selection').length);
148+
},
149+
render: function() {
150+
Button.prototype.render.apply(this, arguments);
151+
this.$el.addClass('bulk-thumbnails-button hidden');
152+
if (! this.controller.isModeActive('select')) {
153+
this.$el.addClass('hidden');
154+
} else {
155+
this.$el.removeClass('hidden');
156+
}
157+
this.toggleDisabled();
158+
return this;
85159
}
86-
this.toggleDisabled();
87-
return this;
160+
});
161+
const toggler = () => {
162+
if (controller.isModeActive('select'))
163+
toolbar.$('.bulk-thumbnails-button').removeClass('hidden');
164+
else
165+
toolbar.$('.bulk-thumbnails-button').addClass('hidden');
88166
}
89-
});
90-
const toggler = () => {
91-
if (controller.isModeActive('select'))
92-
toolbar.$('.bulk-thumbnails-button').removeClass('hidden');
93-
else
94-
toolbar.$('.bulk-thumbnails-button').addClass('hidden');
95-
}
96-
const button = new BulkThumbnailsButton({
97-
filters: controller.state().get('filterable'),
98-
style: 'primary',
99-
disabled: true,
100-
text: l10n.update,
101-
controller: controller,
102-
priority: -75,
103-
click: function() {
104-
var data = [];
105-
var selection = controller.state().get('selection');
106-
107-
if (! selection.length)
108-
return;
109-
110-
selection.each(function(model) {
111-
data.push(model);
112-
});
113-
114-
if (data.length) {
115-
generate(data);
116-
controller.trigger('selection:action:done');
117-
} else {
118-
controller.trigger('selection:action:done');
167+
const button = new BulkThumbnailsButton({
168+
filters: controller.state().get('filterable'),
169+
style: 'primary',
170+
disabled: true,
171+
text: l10n.update,
172+
controller,
173+
priority: -75,
174+
click: function() {
175+
const items = [];
176+
const selection = controller.state().get('selection');
177+
if (! selection.length)
178+
return;
179+
selection.each(function(model) {
180+
items.push(model);
181+
});
182+
if (items.length) {
183+
const data = [];
184+
for (const item of items) {
185+
const attachmentId = item.id;
186+
const source_url = imageSourceUrl(item.attributes.url);
187+
data.push({attachmentId, attachment: {id: attachmentId, source_url}, batch: true});
188+
}
189+
createImageSubsizes(data)
190+
.then(() => controller.trigger('selection:action:done'))
191+
.catch(err => console.error(err));
192+
} else {
193+
controller.trigger('selection:action:done');
194+
}
119195
}
120-
}
121-
});
122-
view.BulkThumbnailsButton = BulkThumbnailsButton;
196+
});
197+
view.BulkThumbnailsButton = BulkThumbnailsButton;
123198

124-
if (controller.isModeActive('grid'))
125-
toolbar.secondary.views.add(button, {at: -2});
199+
if (controller.isModeActive('grid'))
200+
toolbar.secondary.views.add(button, {at: -2});
126201

127-
controller.on('select:activate select:deactivate', toggler, frame);
128-
controller.off('select:activate select:deactivate', toggler, frame);
129-
130-
//
131-
frame.on('select:activate', () => console.log('activate'), frame);
132-
frame.on('select:deactivate', () => console.log('deactivate'), frame);
133-
}
202+
controller.on('select:activate select:deactivate', toggler, frame);
203+
}
134204

135-
function test() {
136-
iter = 2;
137-
const images = [];
138-
const elements = document.querySelectorAll('.media img, .thumbnail img');
139-
generate(elements);
205+
if (wp.apiFetch)
206+
mode ? bulkMediaGrid() : bulkMediaList();
140207
}
141-
// test();
208+
const $fn = vrannemsteinBulkThumbnails;
142209

143-
mode && bulk_button() || bulk_select();
144-
}
145-
146-
(function(wp, jQuery) {
210+
wp = wp || {};
147211
jQuery(function() {
148-
wp.media && wp.media.frame && wp.media.frames.browse && wp.media.frames.browse.browserView.collection.once( 'attachments:received', vrannemstein_bulk_thumbnails );
212+
wp.media && wp.media.frame && wp.media.frames.browse && wp.media.frames.browse.browserView.collection.once('attachments:received', $fn);
149213
});
150-
151-
wp.media || vrannemsteinBulkThumbnails();
214+
wp.media || $fn();
152215
})(wp, jQuery);
153216
</script>
154217

inc/class-vrannemstein-rest-controller.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
* @package vrannemstein
66
* @author Leonardo Laureti
77
* @license GPL-2.0-or-later
8-
*
98
* @api
10-
* @todo
119
*/
1210

1311
defined( 'ABSPATH' ) || die();

0 commit comments

Comments
 (0)