[REF] web_editor, web_unsplash: review load more feature
* Simplify the code * Make the feature mork without unsplash * Handle corner cases task-1896705
This commit is contained in:
@@ -110,7 +110,7 @@ var AltDialog = Dialog.extend({
|
||||
var MediaWidget = Widget.extend({
|
||||
xmlDependencies: ['/web_editor/static/src/xml/editor.xml'],
|
||||
events: {
|
||||
'input input#icon-search': '_onSearchInput',
|
||||
'input input.o_we_search': '_onSearchInput',
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -120,7 +120,7 @@ var MediaWidget = Widget.extend({
|
||||
this._super.apply(this, arguments);
|
||||
this.media = media;
|
||||
this.$media = $(media);
|
||||
this._onSearchInput = _.debounce(this._onSearchInput, 250);
|
||||
this._onSearchInput = _.debounce(this._onSearchInput, 500);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -136,17 +136,6 @@ var MediaWidget = Widget.extend({
|
||||
}
|
||||
this._clear();
|
||||
},
|
||||
/**
|
||||
* @todo comment
|
||||
*/
|
||||
getControlPanelConfig: function () {
|
||||
return {
|
||||
searchEnabled: true,
|
||||
pagerEnabled: true,
|
||||
pagerLeftEnabled: false,
|
||||
pagerRightEnabled: false,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* @abstract
|
||||
* @param {string} needle
|
||||
@@ -185,6 +174,7 @@ var MediaWidget = Widget.extend({
|
||||
*/
|
||||
_onSearchInput: function (ev) {
|
||||
this.search($(ev.currentTarget).val() || '');
|
||||
this.hasSearched = true;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -198,11 +188,11 @@ var ImageWidget = MediaWidget.extend({
|
||||
'click .o_upload_media_button_no_optimization': '_onUploadButtonNoOptimizationClick',
|
||||
'change input[type=file]': '_onImageSelection',
|
||||
'click .o_upload_media_url_button': '_onUploadURLButtonClick',
|
||||
'input input.url': '_onChangeInputURL',
|
||||
'input input.o_we_url_input': '_onURLInputChange',
|
||||
'click .existing-attachments [data-src]': '_onImageClick',
|
||||
'dblclick .existing-attachments [data-src]': '_onImageDblClick',
|
||||
'click .o_existing_attachment_remove': '_onRemoveClick',
|
||||
'click .o_load_more': '_onLoadMore',
|
||||
'click .o_load_more': '_onLoadMoreClick',
|
||||
}),
|
||||
|
||||
IMAGES_PER_ROW: 6,
|
||||
@@ -214,7 +204,8 @@ var ImageWidget = MediaWidget.extend({
|
||||
init: function (parent, media, options) {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this.IMAGES_DISPLAYED_TOTAL = this.IMAGES_PER_ROW * this.IMAGES_ROWS;
|
||||
this.imagesRows = this.IMAGES_ROWS;
|
||||
this.IMAGES_DISPLAYED_TOTAL = this.IMAGES_PER_ROW * this.imagesRows;
|
||||
|
||||
this.options = options;
|
||||
this.accept = options.accept || (options.document ? '*/*' : 'image/*');
|
||||
@@ -251,7 +242,7 @@ var ImageWidget = MediaWidget.extend({
|
||||
var def = this._super.apply(this, arguments);
|
||||
var self = this;
|
||||
|
||||
this._renderImages();
|
||||
this._renderImages(true);
|
||||
|
||||
var o = {
|
||||
url: null,
|
||||
@@ -354,7 +345,7 @@ var ImageWidget = MediaWidget.extend({
|
||||
search: function (needle, noRender) {
|
||||
var self = this;
|
||||
if (!noRender) {
|
||||
this.$('input.url').val('').trigger('input').trigger('change');
|
||||
this.$('input.o_we_url_input').val('').trigger('input').trigger('change');
|
||||
}
|
||||
// TODO: Expand this for adding SVG
|
||||
var domain = this.domain.concat(['|', ['mimetype', '=', false], ['mimetype', this.options.document ? 'not in' : 'in', ['image/gif', 'image/jpe', 'image/jpeg', 'image/jpg', 'image/gif', 'image/png']]]);
|
||||
@@ -403,6 +394,7 @@ var ImageWidget = MediaWidget.extend({
|
||||
});
|
||||
if (!noRender) {
|
||||
self._renderImages();
|
||||
self._adaptLoadMore();
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -411,6 +403,14 @@ var ImageWidget = MediaWidget.extend({
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_adaptLoadMore: function () {
|
||||
var noMoreImgToLoad = this.IMAGES_DISPLAYED_TOTAL >= this.records.length;
|
||||
this.$('.o_load_more').toggleClass('d-none', noMoreImgToLoad);
|
||||
this.$('.o_load_done_msg').toggleClass('d-none', !noMoreImgToLoad);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -435,30 +435,37 @@ var ImageWidget = MediaWidget.extend({
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_renderImages: function () {
|
||||
_loadMoreImages: function (forceSearch) {
|
||||
this.imagesRows += 2;
|
||||
this.IMAGES_DISPLAYED_TOTAL = this.imagesRows * this.IMAGES_PER_ROW;
|
||||
if (!forceSearch) {
|
||||
this._renderImages();
|
||||
this._adaptLoadMore();
|
||||
} else {
|
||||
this.search(this.$('.o_we_search').val() || '');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_renderImages: function (withEffect) {
|
||||
var self = this;
|
||||
var rows = _(this.records).chain()
|
||||
.slice(0, this.IMAGES_DISPLAYED_TOTAL)
|
||||
.groupBy(function (a, index) { return Math.floor(index / self.IMAGES_PER_ROW); })
|
||||
.values()
|
||||
.value();
|
||||
var noMoreImgToLoad = this.IMAGES_DISPLAYED_TOTAL >= this.records.length;
|
||||
|
||||
this.$('.o_load_more').toggleClass('d-none', noMoreImgToLoad);
|
||||
this.$('.o_load_done_msg').toggleClass('d-none', !noMoreImgToLoad);
|
||||
this.$('.form-text').empty();
|
||||
|
||||
//Rendering menu & content for 'Image' or 'Document' tab
|
||||
var templateMenu = 'web_editor.dialog.files.submenu';
|
||||
var templateContent = 'web_editor.dialog.files.existing.content';
|
||||
this.$('.o_submenu').replaceWith(QWeb.render(templateMenu, {
|
||||
accept: this.accept,
|
||||
isDocument: this.options.document,
|
||||
}));
|
||||
this.$('.existing-attachments').replaceWith(QWeb.render(templateContent, {
|
||||
rows: rows,
|
||||
isDocument: this.options.document,
|
||||
}));
|
||||
// Render menu & content
|
||||
this.$('.existing-attachments').replaceWith(
|
||||
QWeb.render('web_editor.dialog.files.existing.content', {
|
||||
rows: rows,
|
||||
isDocument: this.options.document,
|
||||
withEffect: withEffect,
|
||||
})
|
||||
);
|
||||
|
||||
var $divs = this.$('.o_image');
|
||||
var imageDefs = _.map($divs, function (el) {
|
||||
@@ -474,11 +481,13 @@ var ImageWidget = MediaWidget.extend({
|
||||
return def;
|
||||
}
|
||||
});
|
||||
$.when.apply($, imageDefs).then(function () {
|
||||
_.delay(function () {
|
||||
$divs.removeClass('o_image_loading');
|
||||
}, 400);
|
||||
});
|
||||
if (withEffect) {
|
||||
$.when.apply($, imageDefs).then(function () {
|
||||
_.delay(function () {
|
||||
$divs.removeClass('o_image_loading');
|
||||
}, 400);
|
||||
});
|
||||
}
|
||||
this._highlightSelectedImages();
|
||||
},
|
||||
/**
|
||||
@@ -547,17 +556,10 @@ var ImageWidget = MediaWidget.extend({
|
||||
}
|
||||
});
|
||||
this.$el.submit();
|
||||
// Emptying file inputs
|
||||
|
||||
// Empty file input
|
||||
this.$('.o_file_input').val('');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_loadMoreImages: function () {
|
||||
this.IMAGES_ROWS += 2;
|
||||
this.IMAGES_DISPLAYED_TOTAL = this.IMAGES_ROWS * this.IMAGES_PER_ROW;
|
||||
this._renderImages();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
@@ -596,8 +598,7 @@ var ImageWidget = MediaWidget.extend({
|
||||
*/
|
||||
_onRemoveClick: function (ev) {
|
||||
var self = this;
|
||||
var message = _t("Are you sure you want to delete this file ?");
|
||||
DialogBase.confirm(this, message, {
|
||||
DialogBase.confirm(this, _t("Are you sure you want to delete this file ?"), {
|
||||
confirm_callback: function () {
|
||||
var $helpBlock = this.$('.form-text').empty();
|
||||
var $a = $(ev.currentTarget);
|
||||
@@ -616,7 +617,7 @@ var ImageWidget = MediaWidget.extend({
|
||||
return;
|
||||
}
|
||||
$helpBlock.replaceWith(QWeb.render('web_editor.dialog.image.existing.error', {
|
||||
views: prevented[id]
|
||||
views: prevented[id],
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -625,33 +626,29 @@ var ImageWidget = MediaWidget.extend({
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onChangeInputURL: function (ev) {
|
||||
_onURLInputChange: function (ev) {
|
||||
var $input = $(ev.currentTarget);
|
||||
var $button = $input.next('.input-group-append').children();
|
||||
var $button = this.$('.o_upload_media_url_button');
|
||||
var $success = this.$('.o_we_url_success');
|
||||
var $warning = this.$('.o_we_url_warning');
|
||||
var $error = this.$('.o_we_url_error');
|
||||
|
||||
var inputValue = $input.val();
|
||||
var emptyValue = (inputValue === '');
|
||||
var $warning = this.$('.warning-url');
|
||||
var $success = this.$('.success-url');
|
||||
var $error = this.$('.error-url');
|
||||
var $btn = this.$('.o_upload_media_url_button');
|
||||
var regex = /^(?:https?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/;
|
||||
var isURL = regex.test(inputValue);
|
||||
var showWarningOrError = (inputValue.length !== 0 ? isURL : !isURL);
|
||||
|
||||
var isURL = /^.+\..+$/.test(inputValue); // TODO improve
|
||||
var isImage = _.any(['.gif', '.jpe', '.jpg', '.png'], function (format) {
|
||||
return inputValue.endsWith(format);
|
||||
});
|
||||
|
||||
$button.toggleClass('btn-secondary', emptyValue).toggleClass('btn-primary', !emptyValue)
|
||||
.prop('disabled', emptyValue);
|
||||
|
||||
.prop('disabled', !isURL);
|
||||
if (!this.options.document) {
|
||||
_.each(['.gif', '.jpe', '.jpg', '.png'], function (format) {
|
||||
var endsWith = inputValue.endsWith(format);
|
||||
$button.text(endsWith ? _t("Add image") : _t("Add as document"));
|
||||
});
|
||||
} else {
|
||||
$btn.prop('disabled', !isURL);
|
||||
$button.text((isURL && !isImage) ? _t("Add as document") : _t("Add image"));
|
||||
}
|
||||
$success.toggleClass('d-none', !isURL);
|
||||
$warning.toggleClass('d-none', showWarningOrError);
|
||||
$error.toggleClass('d-none', showWarningOrError);
|
||||
$warning.toggleClass('d-none', !isURL || this.options.document || isImage);
|
||||
$error.toggleClass('d-none', emptyValue || isURL);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -675,9 +672,17 @@ var ImageWidget = MediaWidget.extend({
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onLoadMore: function () {
|
||||
_onLoadMoreClick: function () {
|
||||
this._loadMoreImages();
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_onSearchInput: function () {
|
||||
this.imagesRows = this.IMAGES_ROWS;
|
||||
this.IMAGES_DISPLAYED_TOTAL = this.IMAGES_PER_ROW * this.imagesRows;
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -725,14 +730,6 @@ var IconWidget = MediaWidget.extend({
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getControlPanelConfig: function () {
|
||||
return _.extend(this._super.apply(this, arguments), {
|
||||
pagerEnabled: false,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -849,11 +846,11 @@ var IconWidget = MediaWidget.extend({
|
||||
*/
|
||||
var VideoWidget = MediaWidget.extend({
|
||||
template: 'web_editor.dialog.video',
|
||||
events: {
|
||||
events: _.extend({}, MediaWidget.prototype.events || {}, {
|
||||
'change .o_video_dialog_options input': '_onUpdateVideoOption',
|
||||
'input textarea#o_video_text': '_onVideoCodeInput',
|
||||
'change textarea#o_video_text': '_onVideoCodeChange',
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
@@ -891,15 +888,6 @@ var VideoWidget = MediaWidget.extend({
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getControlPanelConfig: function () {
|
||||
return _.extend(this._super.apply(this, arguments), {
|
||||
searchEnabled: false,
|
||||
pagerEnabled: false,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -1075,7 +1063,6 @@ var VideoWidget = MediaWidget.extend({
|
||||
|
||||
// Hide the entire options box if no options are available
|
||||
$optBox.toggleClass('d-none', $optBox.find('div:not(.d-none)').length === 0);
|
||||
$('.option_title').toggleClass('d-none');
|
||||
|
||||
if (query.type === 'yt') {
|
||||
// Youtube only: If 'hide controls' is checked, hide 'fullscreen'
|
||||
|
||||
@@ -1291,29 +1291,8 @@ body .modal {
|
||||
max-width: 80%;
|
||||
|
||||
.modal-body {
|
||||
.nav-tabs .active > a[href="#editor-media-icon"] {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
li.search {
|
||||
.form-group {
|
||||
position: relative;
|
||||
margin: 0 10px 0 0;
|
||||
> input {
|
||||
padding-right: 30px;
|
||||
}
|
||||
> span {
|
||||
@include o-position-absolute(7px, 7px);
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
border-color: gray('200');
|
||||
border-top-width: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
.tab-pane {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.o_existing_attachment_cell {
|
||||
@@ -1357,8 +1336,6 @@ body .modal {
|
||||
}
|
||||
}
|
||||
.font-icons-icons {
|
||||
padding: 20px 0;
|
||||
|
||||
> span {
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
@@ -1377,34 +1354,14 @@ body .modal {
|
||||
}
|
||||
|
||||
#editor-media-image, #editor-media-document {
|
||||
.card {
|
||||
label {
|
||||
margin: auto 10px;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.o_size_fa_icon {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.o_size_dropdown_item {
|
||||
font-size: 0.9rem;
|
||||
.o_we_url_input {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
// VIDEO TAB
|
||||
#editor-media-video .o_video_dialog_container {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
|
||||
#editor-media-video {
|
||||
.o_video_dialog_form {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
padding: 20px;
|
||||
|
||||
#o_video_form_group {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -1416,17 +1373,17 @@ body .modal {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
> .o_validate_feedback {
|
||||
.o_validate_feedback {
|
||||
@include o-position-absolute(auto, 10px, 10px);
|
||||
|
||||
> .fa {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.o_has_error > .o_validate_feedback > .fa-exclamation-triangle {
|
||||
&.o_has_error .o_validate_feedback > .fa-exclamation-triangle {
|
||||
display: block;
|
||||
}
|
||||
&.o_has_success > .o_validate_feedback > .fa-check {
|
||||
&.o_has_success .o_validate_feedback > .fa-check {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -1434,12 +1391,8 @@ body .modal {
|
||||
|
||||
#video-preview {
|
||||
position: relative;
|
||||
flex: 1 0 50%;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
|
||||
@include o-we-preview-box(0 19px);
|
||||
@include o-we-preview-box();
|
||||
border: none;
|
||||
|
||||
.media_iframe_video {
|
||||
@@ -1504,6 +1457,7 @@ body .modal {
|
||||
|
||||
.o_bg_img_opt_cover_edition {
|
||||
@include o-we-preview-box;
|
||||
padding: 0 25px 25px 25px;
|
||||
|
||||
h6 {
|
||||
color: white;
|
||||
|
||||
@@ -45,8 +45,7 @@ $o-we-switch-inactive-color: $o-we-color-paper !default;
|
||||
// ============ 'Preview' component Mixins ===============
|
||||
// Create a "preview" work-area to edit/customize specific elements
|
||||
|
||||
@mixin o-we-preview-box($padding: 0px 25px 25px 25px, $color-text: white) {
|
||||
padding: $padding;
|
||||
@mixin o-we-preview-box($color-text: white) {
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid white;
|
||||
background-image: linear-gradient(-150deg, $o-we-color-dark, $o-we-color-darker);
|
||||
|
||||
@@ -66,12 +66,21 @@
|
||||
<div role="tabpanel" class="tab-pane fade" id="editor-media-video"/>
|
||||
</div>
|
||||
</div>
|
||||
<t t-name="web_editor.dialog.media.search">
|
||||
<div class="input-group ml-auto">
|
||||
<input type="text" class="form-control o_we_search" t-att-placeholder="searchPlaceholder.trim()"/>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text o_we_search_icon">
|
||||
<i class="fa fa-search" title="Search" role="img" aria-label="Search"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Image choosing part of the Media Dialog -->
|
||||
<t t-name="web_editor.dialog.image">
|
||||
<t t-set="iframeName" t-value="_.uniqueId('fileframe-')"/>
|
||||
<form class="form-inline"
|
||||
method="POST"
|
||||
<form method="POST"
|
||||
action="/web_editor/attachment/add"
|
||||
enctype="multipart/form-data"
|
||||
t-att-target="iframeName">
|
||||
@@ -79,108 +88,71 @@
|
||||
<input type="hidden" name="filters" t-att-value="widget.firstFilters.join('_')"/>
|
||||
<input t-if="widget.options.res_id" type="hidden" name="res_id" t-att-value="widget.options.res_id"/>
|
||||
<input t-if="widget.options.res_model" type="hidden" name="res_model" t-att-value="widget.options.res_model"/>
|
||||
<div class="mt-4 w-100">
|
||||
<div class="mb-4">
|
||||
<div class="o_submenu"></div>
|
||||
</div>
|
||||
<div class="form-text"/>
|
||||
<div class="existing-attachments">
|
||||
<t t-call="web_editor.dialog.image.existing"/>
|
||||
</div>
|
||||
<div class="mt-4 text-center o_load_elements mx-auto">
|
||||
<button class="btn btn-primary o_load_more" type="button">Load more...</button>
|
||||
<div class="mt-4 o_load_done_msg d-none">
|
||||
<span><i>All attachments have been loaded</i></span>
|
||||
</div>
|
||||
<t t-call="web_editor.dialog.files.submenu">
|
||||
<t t-set="isDocument" t-value="widget.options.document"/>
|
||||
<t t-set="accept" t-value="widget.accept"/>
|
||||
</t>
|
||||
<div class="form-text"/>
|
||||
<div class="existing-attachments"/>
|
||||
<div class="mt-4 text-center mx-auto">
|
||||
<button class="btn btn-primary o_load_more" type="button">Load more...</button>
|
||||
<div class="mt-4 o_load_done_msg d-none">
|
||||
<span><i>All attachments have been loaded</i></span>
|
||||
</div>
|
||||
</div>
|
||||
<iframe class="o_file_upload_iframe d-none" t-att-name="iframeName"/>
|
||||
</form>
|
||||
</t>
|
||||
<t t-name="web_editor.dialog.files.submenu">
|
||||
<div class="o_submenu">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="form-inline row no-gutters">
|
||||
<input type="file" class="d-none o_file_input" name="upload" t-att-accept="accept" multiple="multiple"/>
|
||||
<input type="hidden" name="disable_optimization" value=""/>
|
||||
<div class="btn-group o_btn_group_image">
|
||||
<button class="btn btn-primary o_upload_media_button" type="button">
|
||||
<t t-if="isDocument">Upload a document</t>
|
||||
<t t-else="">Upload an image</t>
|
||||
</button>
|
||||
<t t-if="!isDocument">
|
||||
<button class="btn btn-primary dropdown-toggle dropdown-toggle-split o_media_optimization" data-toggle="dropdown" type="button">
|
||||
<span class="sr-only">Alternate Upload</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" class="dropdown-item o_upload_media_button_no_optimization">Upload image without optimization</a>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="input-group col-8 ml-2">
|
||||
<input type="text" class="form-control url col-7" name="url" t-attf-placeholder="https://www.odoo.com/#{isDocument ? 'mydocument' : 'logo.png'}"/>
|
||||
<div class="input-group-append ml-2">
|
||||
<button type="button" class="btn btn-sm btn-secondary o_upload_media_url_button" disabled="disabled">
|
||||
<t t-if="isDocument">Add document</t>
|
||||
<t t-else="">Add image</t>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ml-2 o_size_fa_icon">
|
||||
<span class="success-url text-success d-none fa fa-check" title="The URL seems valid"/>
|
||||
<t t-if="isDocument">
|
||||
<span class="error-url text-danger d-none fa fa-times" title="This URL does not seem to work"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="warning-url text-warning d-none fa fa-warning" title="The URL provided does not contain any image. It will be added in the document section."/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-inline align-items-center py-4">
|
||||
<input type="file" class="d-none o_file_input" name="upload" t-att-accept="accept" multiple="multiple"/>
|
||||
<input type="hidden" name="disable_optimization" value=""/>
|
||||
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary o_upload_media_button">
|
||||
<t t-if="isDocument">Upload a document</t>
|
||||
<t t-else="">Upload an image</t>
|
||||
</button>
|
||||
<t t-if="!isDocument">
|
||||
<button class="btn btn-primary dropdown-toggle dropdown-toggle-split o_media_optimization" data-toggle="dropdown" type="button">
|
||||
<span class="sr-only">Alternate Upload</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<button type="button" role="menuitem" class="dropdown-item o_upload_media_button_no_optimization">Upload image without optimization</button>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<div class="input-group align-items-center ml-2">
|
||||
<input type="text" class="form-control o_we_url_input" name="url" t-attf-placeholder="https://www.odoo.com/#{isDocument ? 'mydocument' : 'logo.png'}"/>
|
||||
<div class="input-group-append align-items-center">
|
||||
<button type="button" class="btn btn-secondary o_upload_media_url_button" disabled="disabled">
|
||||
<t t-if="isDocument">Add document</t>
|
||||
<t t-else="">Add image</t>
|
||||
</button>
|
||||
<div class="ml-2">
|
||||
<span class="o_we_url_success text-success d-none fa fa-lg fa-check" title="The URL seems valid"/>
|
||||
<span class="o_we_url_warning text-warning d-none fa fa-lg fa-warning" title="The URL does not contain any image. The file will be added in the document section."/>
|
||||
<span class="o_we_url_error text-danger d-none fa fa-lg fa-times" title="The URL does not seem to work"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm text-right">
|
||||
<ul class="list-unstyled row">
|
||||
<li class="nav-item ml-auto col-6 search">
|
||||
<div class="form-group o_search_div">
|
||||
<t t-set="searchPlaceholder">
|
||||
<t t-if="isDocument">Search a document</t>
|
||||
<t t-else="">Search an image</t>
|
||||
</t>
|
||||
<input class="form-control w-100" id="icon-search" type="search" t-att-placeholder="searchPlaceholder.trim()"/>
|
||||
<span class="fa fa-search" title="Search" role="img" aria-label="Search"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="web_editor.dialog.image.existing">
|
||||
<div role="dialog" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog select-image">
|
||||
<div class="modal-content">
|
||||
<header class="modal-header">
|
||||
<h3 class="modal-title">Select a Picture</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
||||
</header>
|
||||
<main class="modal-body o_has_error">
|
||||
<div class="existing-attachments"/>
|
||||
<div class="form-text"/>
|
||||
</main>
|
||||
<footer class="modal-footer">
|
||||
<button data-dismiss="modal" type="button" aria-label="Discard">Discard</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<t t-call="web_editor.dialog.media.search">
|
||||
<t t-set="searchPlaceholder">
|
||||
<t t-if="isDocument">Search a document</t>
|
||||
<t t-else="">Search an image</t>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="web_editor.dialog.files.existing.content">
|
||||
<div class="existing-attachments">
|
||||
<div class="row mt16 ml-auto" t-as="row" t-foreach="rows">
|
||||
<div class="col-2 o_existing_attachment_cell" t-as="attachment" t-foreach="row">
|
||||
<div t-foreach="rows" t-as="row" class="row mt-2">
|
||||
<div t-foreach="row" t-as="attachment" class="col-2 o_existing_attachment_cell">
|
||||
<i t-if="attachment.res_model === 'ir.ui.view'" class="fa fa-trash o_existing_attachment_remove" title="This file is a public view attachment" role="img" aria-label="This file is a public view attachment" t-att-data-id="attachment.id"/>
|
||||
<i t-else="" class="fa fa-trash o_existing_attachment_remove" title="This file is attached to the current record" role="img" aria-label="This file is attached to the current record" t-att-data-id="attachment.id"/>
|
||||
<div class="o_attachment_border" t-att-style="attachment.res_model === 'ir.ui.view' ? null : 'border: 1px solid #5cb85c;'"><div t-att-data-src="attachment.src" t-att-data-url="attachment.url" role="img" t-att-aria-label="attachment.name" t-att-title="attachment.name" t-att-data-id="attachment.id" t-att-data-mimetype="attachment.mimetype" class="o_image o_image_loading"/></div>
|
||||
<div class="o_attachment_border" t-att-style="attachment.res_model === 'ir.ui.view' ? null : 'border: 1px solid #5cb85c;'"><div t-att-data-src="attachment.src" t-att-data-url="attachment.url" role="img" t-att-aria-label="attachment.name" t-att-title="attachment.name" t-att-data-id="attachment.id" t-att-data-mimetype="attachment.mimetype" t-attf-class="o_image #{withEffect ? 'o_image_loading' : ''}"/></div>
|
||||
<t t-if="isDocument">
|
||||
<small class="o_file_name"><t t-esc="attachment.name"/></small>
|
||||
</t>
|
||||
@@ -204,14 +176,11 @@
|
||||
|
||||
<!-- Icon choosing part of the Media Dialog -->
|
||||
<t t-name="web_editor.dialog.font-icons">
|
||||
<form action="#" class="mt-2">
|
||||
<div class="d-flex flex-row-reverse">
|
||||
<li class="nav-item search list-unstyled col-3 p-2">
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="icon-search" type="search" placeholder="Search a pictogram"/>
|
||||
<span class="fa fa-search" title="Search" role="img" aria-label="Search"/>
|
||||
</div>
|
||||
</li>
|
||||
<form action="#">
|
||||
<div class="form-inline align-items-center py-4">
|
||||
<t t-call="web_editor.dialog.media.search">
|
||||
<t t-set="searchPlaceholder">Search a pictogram</t>
|
||||
</t>
|
||||
</div>
|
||||
<div class="font-icons-icons">
|
||||
<t t-call="web_editor.dialog.font-icons.icons">
|
||||
@@ -232,57 +201,57 @@
|
||||
</t>
|
||||
|
||||
<!-- Video choosing part of the Media Dialog -->
|
||||
<div t-name="web_editor.dialog.video" class="o_video_dialog_container mt-4">
|
||||
<form action="#" class="form-inline w-100">
|
||||
<div class="o_video_dialog_form">
|
||||
<t t-name="web_editor.dialog.video">
|
||||
<form action="#" class="row">
|
||||
<div class="col mt-4 o_video_dialog_form">
|
||||
<div class="form-group mb-2" id="o_video_form_group">
|
||||
<label>Video code </label>
|
||||
<small class="ml-1 form-text text-muted"> (URL or Embed)</small>
|
||||
<label class="ml-2 col-form-label o_validate_feedback position-static" for="o_video_text">
|
||||
<i class="fa fa-check text-success" role="img" aria-label="Checked" title="Checked"/>
|
||||
<i class="fa fa-exclamation-triangle text-danger" role="img" aria-label="Attention" title="Attention"/>
|
||||
<label class="col-form-label" for="o_video_text">
|
||||
Video code <small>(URL or Embed)</small>
|
||||
<div class="o_validate_feedback">
|
||||
<i class="fa fa-check text-success" role="img" aria-label="Checked" title="Checked"/>
|
||||
<i class="fa fa-exclamation-triangle text-danger" role="img" aria-label="Attention" title="Attention"/>
|
||||
</div>
|
||||
</label>
|
||||
<textarea class="form-control url" id="o_video_text" placeholder="Copy-paste your URL or embed code here"/>
|
||||
<textarea class="form-control" id="o_video_text" placeholder="Copy-paste your URL or embed code here"/>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<small class="text-muted">Accepts <b><i>Youtube</i></b>, <b><i>Instagram</i></b>, <b><i>Vine.co</i></b>, <b><i>Vimeo</i></b>, <b><i>Dailymotion</i></b> and <b><i>Youku</i></b> videos</small>
|
||||
</div>
|
||||
<div class="o_video_dialog_options d-none mt-4">
|
||||
<div class="option_title mb-2 d-flex">
|
||||
<label>Options</label>
|
||||
</div>
|
||||
<div class="o_yt_option o_vim_option o_dm_option d-flex">
|
||||
<div class="o_yt_option o_vim_option o_dm_option">
|
||||
<label class="o_switch mb0"><input id="o_video_autoplay" type="checkbox"/><span/>Autoplay</label>
|
||||
</div>
|
||||
<div class="o_yt_option o_vim_option d-flex">
|
||||
<div class="o_yt_option o_vim_option">
|
||||
<label class="o_switch mb0"><input id="o_video_loop" type="checkbox"/><span/>Loop</label>
|
||||
</div>
|
||||
<div class="o_yt_option o_dm_option d-flex">
|
||||
<div class="o_yt_option o_dm_option">
|
||||
<label class="o_switch mb0"><input id="o_video_hide_controls" type="checkbox"/><span/>Hide player controls</label>
|
||||
</div>
|
||||
<div class="o_yt_option d-flex">
|
||||
<div class="o_yt_option">
|
||||
<label class="o_switch mb0"><input id="o_video_hide_fullscreen" type="checkbox"/><span/>Hide fullscreen button</label>
|
||||
</div>
|
||||
<div class="o_yt_option d-flex">
|
||||
<div class="o_yt_option">
|
||||
<label class="o_switch mb0"><input id="o_video_hide_yt_logo" type="checkbox"/><span/>Hide Youtube logo</label>
|
||||
</div>
|
||||
<div class="o_dm_option d-flex">
|
||||
<div class="o_dm_option">
|
||||
<label class="o_switch mb0"><input id="o_video_hide_dm_logo" type="checkbox"/><span/>Hide Dailymotion logo</label>
|
||||
</div>
|
||||
<div class="o_dm_option d-flex">
|
||||
<div class="o_dm_option">
|
||||
<label class="o_switch mb0"><input id="o_video_hide_dm_share" type="checkbox"/><span/>Hide sharing button</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="video-preview">
|
||||
<div class="o_video_dialog_preview_text small mt16 mb8 d-none">Preview</div>
|
||||
<div class="media_iframe_video">
|
||||
<div class="media_iframe_video_size"/>
|
||||
<iframe class="o_video_dialog_iframe" allowfullscreen="allowfullscreen" frameborder="0" src=""/>
|
||||
<div class="col-md-6">
|
||||
<div id="video-preview" class="p-3">
|
||||
<div class="o_video_dialog_preview_text small mb-2 d-none">Preview</div>
|
||||
<div class="media_iframe_video">
|
||||
<div class="media_iframe_video_size"/>
|
||||
<iframe class="o_video_dialog_iframe" allowfullscreen="allowfullscreen" frameborder="0" src=""/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Link Dialog (allows to choose a style and content for a link on the page) -->
|
||||
<div t-name="web_editor.dialog.link" class="o_link_dialog">
|
||||
@@ -354,7 +323,7 @@
|
||||
<div class="form-group text-center">
|
||||
<label>Preview</label>
|
||||
<div style="overflow: auto; max-width: 100%; max-height: 200px;">
|
||||
<a href="#" type="button" id="link-preview" aria-label="Preview" title="Preview"/>
|
||||
<a href="#" id="link-preview" aria-label="Preview" title="Preview"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,6 @@ odoo.define('web_unsplash.image_widgets', function (require) {
|
||||
var core = require('web.core');
|
||||
var UnsplashAPI = require('unsplash.api');
|
||||
var weWidgets = require('web_editor.widget');
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var unsplashAPI = null;
|
||||
|
||||
@@ -16,32 +15,35 @@ weWidgets.ImageWidget.include({
|
||||
'dblclick .unsplash_img_container [data-imgid]': '_onUnsplashImgDblClick',
|
||||
'click .unsplash_img_container [data-imgid]': '_onUnsplashImgClick',
|
||||
'click button.save_unsplash': '_onSaveUnsplash',
|
||||
'click button.access_key': '_onSetAccessKey',
|
||||
'click .o_load_more': '_onLoadMore',
|
||||
'click .o_search_from_unsplash': '_onSearchFromUnsplash',
|
||||
'click .o_search_an_image': '_onSearchImage',
|
||||
'keyup input#icon-search, .o_dropdown_search': '_onPressKeySearch',
|
||||
'click .o_search_an_image, .o_search_from_unsplash': '_onSourceSwitchClick',
|
||||
'keyup .o_we_search, .o_search_an_image, .o_search_from_unsplash': '_onPressKeySearch',
|
||||
}),
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this._unsplash = {
|
||||
isActive: false,
|
||||
selectedImages: {},
|
||||
isMaxed: false,
|
||||
query: false,
|
||||
error: false,
|
||||
};
|
||||
|
||||
// TODO This is a `hack` to prevent the UnsplashAPI to be destroyed every time
|
||||
// the media dialog is closed.
|
||||
// Indeed, UnsplashAPI has a cache system to recude unsplash call, it is
|
||||
// then better to keep its state to benefic from it from one media dialog
|
||||
// call to another.
|
||||
// Unsplash API will either be (it's still being discussed):
|
||||
// * a service (ideally coming with an improvement to not auto load the service)
|
||||
// * initialized in the website_root (trigger_up)
|
||||
var def = this._super.apply(this, arguments);
|
||||
// TODO improve this
|
||||
//
|
||||
// This is a `hack` to prevent the UnsplashAPI to be destroyed every
|
||||
// time the media dialog is closed. Indeed, UnsplashAPI has a cache
|
||||
// system to recude unsplash call, it is then better to keep its state
|
||||
// to take advantage from it from one media dialog call to another.
|
||||
//
|
||||
// Unsplash API will either be (it's still being discussed):
|
||||
// * a service (ideally coming with an improvement to not auto load
|
||||
// the service)
|
||||
// * initialized in the website_root (trigger_up)
|
||||
if (unsplashAPI === null) {
|
||||
this.unsplashAPI = new UnsplashAPI(this);
|
||||
unsplashAPI = this.unsplashAPI;
|
||||
@@ -49,8 +51,19 @@ weWidgets.ImageWidget.include({
|
||||
this.unsplashAPI = unsplashAPI;
|
||||
this.unsplashAPI.setParent(this);
|
||||
}
|
||||
return def;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
if (!this.options.document) {
|
||||
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
|
||||
@@ -62,19 +75,6 @@ weWidgets.ImageWidget.include({
|
||||
// Public
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getControlPanelConfig: function () {
|
||||
var config = this._super.apply(this, arguments);
|
||||
if (this._unsplash.query) {
|
||||
_.extend(config, {
|
||||
pagerLeftEnabled: this.page > 1,
|
||||
pagerRightEnabled: !this._unsplash.isMaxed,
|
||||
});
|
||||
}
|
||||
return config;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -102,74 +102,102 @@ weWidgets.ImageWidget.include({
|
||||
return _super.apply(self, args);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
search: function (needle, noRender) {
|
||||
var self = this;
|
||||
if (!this._unsplash.isActive) {
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
|
||||
this._unsplash.query = needle;
|
||||
return this.unsplashAPI.getImages(needle, this.IMAGES_DISPLAYED_TOTAL).then(function (res) {
|
||||
self._unsplash.isMaxed = res.isMaxed;
|
||||
self._unsplash.records = res.images;
|
||||
self._unsplash.error = false;
|
||||
}, function (err) {
|
||||
self._unsplash.error = err;
|
||||
}).always(function () {
|
||||
if (!noRender) {
|
||||
self._renderImages();
|
||||
self._adaptLoadMore();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Highlights selected image, when an image is clicked and when pager change
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_adaptLoadMore: function () {
|
||||
if (!this._unsplash.isActive) {
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
|
||||
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);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_highlightSelectedImages: function () {
|
||||
var self = this;
|
||||
if (!this._unsplash.query) {
|
||||
if (!this._unsplash.isActive) {
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
this.$('.o_unsplash_img_cell.o_selected').removeClass("o_selected");
|
||||
|
||||
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");
|
||||
$select.closest('.o_unsplash_img_cell').addClass('o_selected');
|
||||
return $select;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_loadMoreImages: function (forceSearch) {
|
||||
this._super(this._unsplash.isActive || forceSearch);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_renderImages: function () {
|
||||
var self = this;
|
||||
if (!this._unsplash.query) {
|
||||
if (!this._unsplash.isActive) {
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
this.unsplashAPI.getImages(this._unsplash.query, this.IMAGES_PER_PAGE, this.page).then(function (res) {
|
||||
self._unsplash.isMaxed = res.isMaxed;
|
||||
var rows = _(res.images).chain()
|
||||
.groupBy(function (a, index) { return Math.floor(index / self.IMAGES_PER_ROW); })
|
||||
.values()
|
||||
.value();
|
||||
|
||||
self.$('.unsplash_img_container').html(QWeb.render('web_unsplash.dialog.image.content', {rows: rows}));
|
||||
self._highlightSelectedImages();
|
||||
}).fail(function (err) {
|
||||
self.$('.unsplash_img_container').html(QWeb.render('web_unsplash.dialog.error.content', { status: err }));
|
||||
}).always(function () {
|
||||
self._toggleAttachmentContaines(false);
|
||||
});
|
||||
if (this._unsplash.error) {
|
||||
this.$('.unsplash_img_container').html(
|
||||
core.qweb.render('web_unsplash.dialog.error.content', {
|
||||
status: this._unsplash.error,
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var rows = _(this._unsplash.records).chain()
|
||||
.groupBy(function (a, index) { return Math.floor(index / self.IMAGES_PER_ROW); })
|
||||
.values()
|
||||
.value();
|
||||
|
||||
this.$('.unsplash_img_container').html(core.qweb.render('web_unsplash.dialog.image.content', {rows: rows}));
|
||||
this._highlightSelectedImages();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {boolean} show
|
||||
*/
|
||||
_toggleAttachmentContaines: function (hideUnsplash) {
|
||||
this.$('.existing-attachments').toggleClass('d-none', !hideUnsplash);
|
||||
this.$('.unsplash_img_container').toggleClass('d-none', hideUnsplash);
|
||||
this.$('.o_load_more').toggleClass('d-none', hideUnsplash);
|
||||
this.$('.o_load_done_msg').toggleClass('d-none', !hideUnsplash);
|
||||
this.trigger_up('update_control_panel');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_toggleLoadMoreBtnUnsplash: function (display) {
|
||||
this.$('.o_load_done_msg').toggleClass('d-none', display);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_toggleSearchDropdown: function (show) {
|
||||
var inputValue = this.$('#icon-search').val();
|
||||
this.$('.o_search_value_input').text(inputValue);
|
||||
this.$('.o_dropdown_search').toggleClass('show', show);
|
||||
_toggleUnsplashContainer: function (show) {
|
||||
this._unsplash.isActive = show;
|
||||
this.$('.existing-attachments').toggleClass('d-none', show);
|
||||
this.$('.unsplash_img_container').toggleClass('d-none', !show);
|
||||
this.$('.o_we_search_icon > span').text(show ? "Unsplash" : "");
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -204,37 +232,20 @@ weWidgets.ImageWidget.include({
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onChangeUnsplashSearch: _.debounce(function () {
|
||||
// oldPage saves the original image widget pager.
|
||||
// Emptying the unsplash search will set the pager to its previous state
|
||||
this._unsplash.query = this.$('#icon-search').val().trim();
|
||||
if (this._unsplash.query) {
|
||||
this.oldPage = this.page;
|
||||
this.page = 1;
|
||||
this._renderImages();
|
||||
} else {
|
||||
this.page = this.oldPage || 1;
|
||||
this._toggleAttachmentContaines(true);
|
||||
}
|
||||
this._toggleLoadMoreBtnUnsplash(true);
|
||||
}, 1000),
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onUnsplashImgClick: function (ev) {
|
||||
var imgid = $(ev.currentTarget).data('imgid');
|
||||
var url = $(ev.currentTarget).data('url');
|
||||
var downloadUrl = $(ev.currentTarget).data('download-url');
|
||||
var downloadURL = $(ev.currentTarget).data('download-url');
|
||||
if (!this.multiImages) {
|
||||
this._unsplash.selectedImages = {};
|
||||
}
|
||||
if (imgid in this._unsplash.selectedImages) {
|
||||
delete this._unsplash.selectedImages[imgid];
|
||||
} else {
|
||||
this._unsplash.selectedImages[imgid] = {url: url, downloadUrl: downloadUrl};
|
||||
this._unsplash.selectedImages[imgid] = {url: url, download_url: downloadURL};
|
||||
}
|
||||
this._highlightSelectedImages();
|
||||
},
|
||||
@@ -246,46 +257,25 @@ weWidgets.ImageWidget.include({
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onLoadMore: function () {
|
||||
this._unsplash.query = this.$('#icon-search').val().trim();
|
||||
this._loadMoreImages();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onSearchFromUnsplash: function () {
|
||||
this.$('.o_dropdown_search').removeClass('show');
|
||||
this._toggleAttachmentContaines(false);
|
||||
this._onChangeUnsplashSearch();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onSearchImage: function () {
|
||||
var searchText = this.$('#icon-search').val().trim();
|
||||
this._unsplash.query = false;
|
||||
this.search(searchText);
|
||||
this.$('.o_dropdown_search').removeClass('show');
|
||||
this._toggleAttachmentContaines(true);
|
||||
this._renderImages();
|
||||
_onSourceSwitchClick: function (ev) {
|
||||
this._toggleUnsplashContainer(!$(ev.currentTarget).is('.o_search_an_image'));
|
||||
this.search(this.$('.o_we_search').val() || '');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onPressKeySearch: function (ev) {
|
||||
var $searchAnImage = this.$('button.dropdown-item.o_search_an_image');
|
||||
switch (ev.which) {
|
||||
case $.ui.keyCode.ENTER:
|
||||
$searchAnImage.focus();
|
||||
break;
|
||||
case $.ui.keyCode.UP:
|
||||
$searchAnImage.focus();
|
||||
this.$('.o_search_an_image').focus();
|
||||
break;
|
||||
case $.ui.keyCode.DOWN:
|
||||
$searchAnImage.next().focus();
|
||||
this.$('.o_search_from_unsplash').focus();
|
||||
break;
|
||||
default: return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
},
|
||||
@@ -294,11 +284,19 @@ weWidgets.ImageWidget.include({
|
||||
*/
|
||||
_onSearchInput: function (ev) {
|
||||
if (!this.options.document) {
|
||||
this._toggleSearchDropdown(true);
|
||||
} else {
|
||||
this.search($(ev.currentTarget).val() || '');
|
||||
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();
|
||||
}
|
||||
}
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -27,12 +27,11 @@ var UnsplashCore = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
*
|
||||
* @param {String} query search terms
|
||||
* @param {Integer} pageSize number of image to display per page
|
||||
* @param {Integer} pageNumber page number to retrieve
|
||||
*/
|
||||
getImages: function (query, pageSize, pageNumber) {
|
||||
getImages: function (query, pageSize) {
|
||||
var self = this;
|
||||
var to = pageSize * pageNumber;
|
||||
var from = to - pageSize;
|
||||
var from = 0;
|
||||
var to = pageSize;
|
||||
var cachedData = this._cache[query];
|
||||
|
||||
if (cachedData && (cachedData.images.length >= to || (cachedData.totalImages !== 0 && cachedData.totalImages < to))) {
|
||||
|
||||
@@ -7,19 +7,23 @@
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-extend="web_editor.dialog.files.submenu">
|
||||
<t t-jquery=".o_search_div" t-operation="append">
|
||||
<div class="dropdown-menu o_dropdown_search w-100" style="background-color:#efefef;">
|
||||
<button class="dropdown-item o_search_an_image o_size_dropdown_item" type="button">
|
||||
<t t-name="web_unsplash.dialog.media.search_icon" t-extend="">
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle o_we_search_icon" data-toggle="dropdown">
|
||||
<i class="fa fa-search"/>
|
||||
<span/>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<button class="dropdown-item o_search_an_image" type="button">
|
||||
Search among my images for:
|
||||
<div class="font-weight-bold o_search_value_input"></div>
|
||||
</button>
|
||||
<button class="dropdown-item o_search_from_unsplash o_size_dropdown_item" type="button">
|
||||
<button class="dropdown-item o_search_from_unsplash" type="button">
|
||||
Search from Unsplash for:
|
||||
<div class="font-weight-bold o_search_value_input"></div>
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="web_unsplash.dialog.image.content">
|
||||
@@ -39,16 +43,14 @@
|
||||
</t>
|
||||
|
||||
<t t-name="web_unsplash.dialog.error.credentials">
|
||||
<h4 class="text-muted">
|
||||
<t t-esc="title"/>
|
||||
</h4>
|
||||
<h4><t t-esc="title"/></h4>
|
||||
<div class="details">
|
||||
<t t-esc="subtitle"/>
|
||||
<div class="form-group btn-group mt-4 access_key_box">
|
||||
<div class="form-group mt-4 access_key_box">
|
||||
<input type="text" class="form-control w-100" id="accessKeyInput" placeholder="Paste your access key here"/>
|
||||
</div>
|
||||
<a href="https://www.odoo.com/documentation/user/general/unsplash/unsplash_access_key.html" target="_blank"><i class="fa fa-arrow-right"/> Generate an access key</a>
|
||||
<div class="form-group btn-group mt-4 access_key_box">
|
||||
<div class="form-group mt-4 access_key_box">
|
||||
<input type="text" class="form-control w-100" id="appIdInput" placeholder="Paste your application ID here"/>
|
||||
</div>
|
||||
<a href="https://www.odoo.com/documentation/user/general/unsplash/unsplash_application_id.html" target="_blank"><i class="fa fa-arrow-right"/> How to find my Unsplash Application ID?</a>
|
||||
@@ -57,8 +59,8 @@
|
||||
</t>
|
||||
|
||||
<t t-name="web_unsplash.dialog.error.content">
|
||||
<div class="row mt16 text-muted unsplash_error">
|
||||
<div class="m-auto text-center">
|
||||
<div class="d-flex mt-2 unsplash_error">
|
||||
<div class="mx-auto text-center">
|
||||
<t t-if="status == 'key_not_found'">
|
||||
<t t-call="web_unsplash.dialog.error.credentials">
|
||||
<t t-set="title">
|
||||
|
||||
Reference in New Issue
Block a user