diff options
| author | Samuel Degueldre <sad@odoo.com> | 2020-02-11 07:43:23 +0000 |
|---|---|---|
| committer | Samuel Degueldre <sad@odoo.com> | 2020-03-30 11:06:45 +0000 |
| commit | 5576a5f84d7d7b539498f15b7e26165b61c52ba5 (patch) | |
| tree | 6af69fe4f0e0d7b53fa82ec5e7a7ec496bc45693 /addons/web_unsplash/static/src/js/unsplash_image_widget.js | |
| parent | 634c00a32fe18365039f83d890965fe35de7d23b (diff) | |
[IMP] web_editor, web_unsplash: improve media-dialog UX
Previously, searching for images in the database and on unsplash was
mutually exclusive, and controlled by a dropdown menu next to the search
bar. Additionally, the display of db images and unsplash images was very
different, making using the search function inconsistent and awkward.
This commit merges the unsplash search into the db search. When
searching, the first few matches from the database are displayed, then
results from unsplash.
Additionally, the layout of images has been greatly improved,
eliminating almost all padding, using some flex-box magic to allow the
images to take up all the available space without being cropped or
deformed.
The input to add an attachment by URL is now collapsed by
default, and clicking on it will expand it to reduce visual clutter.
Finally, when not in multi-images mode, the clicked image is immediately
used, rather than the user having to click it and then click the add
button, or having to double click, which was not obvious.
task-2091417
closes odoo/odoo#45174
Diffstat (limited to 'addons/web_unsplash/static/src/js/unsplash_image_widget.js')
| -rw-r--r-- | addons/web_unsplash/static/src/js/unsplash_image_widget.js | 223 |
1 files changed, 92 insertions, 131 deletions
diff --git a/addons/web_unsplash/static/src/js/unsplash_image_widget.js b/addons/web_unsplash/static/src/js/unsplash_image_widget.js index 86d299c46a6..35a9771c838 100644 --- a/addons/web_unsplash/static/src/js/unsplash_image_widget.js +++ b/addons/web_unsplash/static/src/js/unsplash_image_widget.js @@ -7,17 +7,28 @@ var widgetsMedia = require('wysiwyg.widgets.media'); var unsplashAPI = null; +// Prevent base class from treating unsplash images like regular attachments +const originalEvents = widgetsMedia.ImageWidget.prototype.events; +const clickHandler = originalEvents['click .o_existing_attachment_cell']; +if (!clickHandler) { + throw new Error(`Couldn't find a handler for o_existing_attachment_cell clicks. +The unsplash image widget needs to prevent this handler from executing on unsplash attachments.`); +} +_.extend(originalEvents, { + 'click .o_existing_attachment_cell:not(.o_unsplash_attachment_cell)': clickHandler, +}); +delete originalEvents['click .o_existing_attachment_cell']; + widgetsMedia.ImageWidget.include({ xmlDependencies: widgetsMedia.ImageWidget.prototype.xmlDependencies.concat( ['/web_unsplash/static/src/xml/unsplash_image_widget.xml'] ), events: _.extend({}, widgetsMedia.ImageWidget.prototype.events, { - 'dblclick .unsplash_img_container [data-imgid]': '_onUnsplashImgDblClick', - 'click .unsplash_img_container [data-imgid]': '_onUnsplashImgClick', - 'click button.save_unsplash': '_onSaveUnsplash', - 'click .o_search_an_image, .o_search_from_unsplash': '_onSourceSwitchClick', - 'keyup .o_we_search, .o_search_an_image, .o_search_from_unsplash': '_onPressKeySearch', + 'click .o_unsplash_attachment_cell[data-imgid]': '_onUnsplashImgClick', + 'click button.save_unsplash': '_onSaveUnsplashCredentials', }), + // Max number of database attachments to show when searching. + maxDbAttachments: 5, /** * @override @@ -26,11 +37,11 @@ widgetsMedia.ImageWidget.include({ this._super.apply(this, arguments); this._unsplash = { - isActive: false, selectedImages: {}, isMaxed: false, query: false, error: false, + records: [], }; // TODO improve this @@ -55,13 +66,6 @@ widgetsMedia.ImageWidget.include({ /** * @override */ - start: function () { - this.$('.o_we_search_icon').replaceWith(core.qweb.render('web_unsplash.dialog.media.search_icon')); - return this._super.apply(this, arguments); - }, - /** - * @override - */ destroy: function () { // TODO See `hack` explained in `init`. This prevent the media dialog destroy // to destroy unsplashAPI when destroying the children @@ -76,50 +80,43 @@ widgetsMedia.ImageWidget.include({ /** * @override */ - _save: function () { - if (!this._unsplash.query) { - return this._super.apply(this, arguments); + _save: async function () { + const _super = this._super; + if (Object.keys(this._unsplash.selectedImages).length) { + this.saved = true; + const images = await this._rpc({ + route: '/web_unsplash/attachment/add', + params: { + unsplashurls: this._unsplash.selectedImages, + res_model: this.options.res_model, + res_id: this.options.res_id, + query: this._unsplash.query, + }, + }); + this.attachments.push(...images); + this.selectedAttachments.push(...images); } - var self = this; - var args = arguments; - var _super = this._super; - return this._rpc({ - route: '/web_unsplash/attachment/add', - params: { - unsplashurls: self._unsplash.selectedImages, - res_model: self.options.res_model, - res_id: self.options.res_id, - query: self._unsplash.query, - } - }).then(function (images) { - self.attachments = images; - self.selectedAttachments = images; - return _super.apply(self, args); - }); + return _super.apply(this, arguments); }, /** * @override */ - search: function (needle, noRender) { + search: async function (needle) { var self = this; - if (!this._unsplash.isActive) { - return this._super.apply(this, arguments); - } + await this._super(needle, true); this._unsplash.query = needle; + if (!needle) { + return; + } - var always = function () { - if (!noRender) { - self._renderImages(); - } - }; - return this.unsplashAPI.getImages(needle, this.numberOfAttachmentsToDisplay).then(function (res) { + await this.unsplashAPI.getImages(needle, this.numberOfAttachmentsToDisplay).then(function (res) { self._unsplash.isMaxed = res.isMaxed; self._unsplash.records = res.images; self._unsplash.error = false; }, function (err) { self._unsplash.error = err; - }).then(always).guardedCatch(always); + }); }, //-------------------------------------------------------------------------- @@ -130,60 +127,68 @@ widgetsMedia.ImageWidget.include({ * @override */ _highlightSelected: function () { - var self = this; - if (!this._unsplash.isActive) { - return this._super.apply(this, arguments); - } + this._super.apply(this, arguments); - this.$('.o_unsplash_img_cell.o_selected').removeClass('o_selected'); - var $select = this.$('.o_unsplash_img_cell [data-imgid]').filter(function () { - return $(this).data('imgid') in self._unsplash.selectedImages; - }); - $select.closest('.o_unsplash_img_cell').addClass('o_selected'); + const $select = this.$('.o_unsplash_attachment_cell[data-imgid]').filter((i, el) => { + return $(el).data('imgid') in this._unsplash.selectedImages; + }).addClass('o_we_attachment_selected'); return $select; }, /** * @private */ _loadMoreImages: function (forceSearch) { - if (!this._unsplash.isActive) { + if (!this.$('.o_we_search').val()) { return this._super(forceSearch); } this.numberOfAttachmentsToDisplay += 10; - this.search(this.$('.o_we_search').val() || ''); + this.search(this.$('.o_we_search').val()).then(() => this._renderThumbnails()); }, /** * @override */ - _renderImages: function () { - if (!this._unsplash.isActive) { - return this._super.apply(this, arguments); - } - - if (this._unsplash.error) { - this.$('.unsplash_img_container').html( + _renderThumbnails: function () { + this._super(...arguments); + if (this._unsplash.query && this._unsplash.error) { + this.$('.unsplash_error').html( core.qweb.render('web_unsplash.dialog.error.content', { status: this._unsplash.error, }) ); return; } + this.$('.unsplash_error').empty(); - this.$('.unsplash_img_container').html(core.qweb.render('web_unsplash.dialog.image.content', {records: this._unsplash.records})); - this._highlightSelected(); - - this.$('.o_load_more').toggleClass('d-none', !!this._unsplash.error || this._unsplash.isMaxed); - this.$('.o_load_done_msg').toggleClass('d-none', !!this._unsplash.error || !this._unsplash.isMaxed); + if (this._unsplash.query && !this._unsplash.isMaxed) { + this.$('.o_load_more').removeClass('d-none'); + this.$('.o_load_done_msg').addClass('d-none'); + } }, /** - * @private - * @param {boolean} show + * @override */ - _toggleUnsplashContainer: function (show) { - this._unsplash.isActive = show; - this.$('.o_we_existing_attachments').toggleClass('d-none', show); - this.$('.unsplash_img_container').toggleClass('d-none', !show); - this.$('.o_we_search_icon > span').text(show ? "Unsplash" : ""); + _renderExisting: function (attachments) { + if (this._unsplash.records.length) { + attachments.splice(this.maxDbAttachments); + } + return this._super(attachments.concat(this._unsplash.records.map(record => { + const url = new URL(record.urls.regular); + // In small windows, row height could get quite a bit larger than the min, so we keep some leeway. + url.searchParams.set('h', 2 * this.MIN_ROW_HEIGHT); + url.searchParams.delete('w'); + return Object.assign({}, record, { + url: url.toString(), + }); + }))); + }, + /** + * @override + */ + _selectAttachement: function (attachment, save) { + if (!this.options.multiImages) { + this._unsplash.selectedImages = {}; + } + this._super(...arguments); }, //-------------------------------------------------------------------------- @@ -193,7 +198,7 @@ widgetsMedia.ImageWidget.include({ /** * @private */ - _onSaveUnsplash: function () { + _onSaveUnsplashCredentials: function () { var self = this; var key = this.$('#accessKeyInput').val().trim(); var appId = this.$('#appIdInput').val().trim(); @@ -202,19 +207,14 @@ widgetsMedia.ImageWidget.include({ this.$('#appIdInput').toggleClass('is-invalid', !appId); if (key && appId) { - var params = { - 'key': key, - 'appId': appId, - }; - if (!this.$el.find('.is-invalid').length) { this._rpc({ route: '/web_unsplash/save_unsplash', - params: params, + params: {key: key, appId: appId}, }).then(function () { self.unsplashAPI.clientId = key; self._unsplash.error = false; - self.search(self._unsplash.query); + self.search(self._unsplash.query).then(() => self._renderThumbnails()); }); } } @@ -223,65 +223,26 @@ widgetsMedia.ImageWidget.include({ * @private */ _onUnsplashImgClick: function (ev) { - var imgid = $(ev.currentTarget).data('imgid'); - var url = $(ev.currentTarget).data('url'); - var downloadURL = $(ev.currentTarget).data('download-url'); + if (this.saved) { + // already saved, probably a double click. Ignore. + return; + } + const {imgid, url, downloadUrl} = ev.currentTarget.dataset; if (!this.options.multiImages) { this._unsplash.selectedImages = {}; + this.selectedAttachments = []; } if (imgid in this._unsplash.selectedImages) { delete this._unsplash.selectedImages[imgid]; } else { - this._unsplash.selectedImages[imgid] = {url: url, download_url: downloadURL}; + const _1920Url = new URL(url); + _1920Url.searchParams.set('w', '1920'); + this._unsplash.selectedImages[imgid] = {url: _1920Url.href, download_url: downloadUrl}; } this._highlightSelected(); - }, - /** - * @private - */ - _onUnsplashImgDblClick: function (ev) { - this.trigger_up('save_request'); - }, - /** - * @private - * @param {Event} ev - */ - _onSourceSwitchClick: function (ev) { - this._toggleUnsplashContainer(!$(ev.currentTarget).is('.o_search_an_image')); - this.search(this.$('.o_we_search').val() || ''); - }, - /** - * @private - */ - _onPressKeySearch: function (ev) { - switch (ev.which) { - case $.ui.keyCode.UP: - this.$('.o_search_an_image').focus(); - break; - case $.ui.keyCode.DOWN: - this.$('.o_search_from_unsplash').focus(); - break; - default: - return; - } - ev.preventDefault(); - }, - /** - * @override - */ - _onSearchInput: function (ev) { - var $input = $(ev.currentTarget); - var inputValue = $input.val(); - this.$('.o_search_value_input').text(inputValue); - - var $icon = this.$('.o_we_search_icon'); - if ($icon.parent().is('.show')) { - $icon.dropdown('update'); - } else if (!this.hasSearched) { - $icon.dropdown('toggle'); - $input.focus(); + if (!this.options.multiImages) { + this.trigger_up('save_request'); } - this._super.apply(this, arguments); }, }); }); |
