[REF] website_slides: reorganize javascript

This commit is contained in:
Andrea Ulliana
2018-11-28 09:49:10 +00:00
committed by qsm-odoo
parent 08230abe3c
commit c64c646d62
5 changed files with 655 additions and 475 deletions
+49 -27
View File
@@ -2,34 +2,56 @@
odoo.define('website_slides.slides', function (require) {
"use strict";
var time = require('web.time');
require('root.widget');
var time = require('web.time');
require('root.widget');
var sAnimations = require('website.content.snippets.animation');
(function () {
$("timeago.timeago").each(function (index, el) {
var datetime = $(el).attr('datetime'),
datetime_obj = time.str_to_datetime(datetime),
// if presentation 7 days, 24 hours, 60 min, 60 second, 1000 millis old(one week)
// then return fix formate string else timeago
display_str = "";
if (datetime_obj && new Date().getTime() - datetime_obj.getTime() > 7 * 24 * 60 * 60 * 1000) {
display_str = moment(datetime_obj).format('ll');
} else {
display_str = moment(datetime_obj).fromNow();
}
$(el).text(display_str);
});
var page_widgets = {};
// To prevent showing channel settings alert box once user closed it.
$('.o_slides_hide_channel_settings').on('click', function(ev) {
var channel_id = $(this).data("channelId");
ev.preventDefault();
document.cookie = "slides_channel_" + channel_id + " = closed";
return true;
});
})();
sAnimations.registry.websiteSlides = sAnimations.Class.extend({
selector: 'main',
read_events: {
'each timeago.timeago': '_onTimeAgo',
'click .o_slides_hide_channel_settings': '_onHideChannelSettings',
},
return {
page_widgets: {},
}
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @override
* @param {Object} index
* @param {Object} el
*/
_onTimeAgo: function (index, el) {
var datetime = $(el).attr('datetime'),
datetime_obj = time.str_to_datetime(datetime),
// if presentation 7 days, 24 hours, 60 min, 60 second, 1000 millis old(one week)
// then return fix formate string else timeago
display_str = "";
if (datetime_obj && new Date().getTime() - datetime_obj.getTime() > 7 * 24 * 60 * 60 * 1000) {
display_str = moment(datetime_obj).format('ll');
} else {
display_str = moment(datetime_obj).fromNow();
}
$(el).text(display_str);
},
/**
* To prevent showing channel settings alert box once user closed it.
*
* @override
* @param {Object} ev
*/
_onHideChannelSettings: function (ev) {
var channel_id = $(this).data("channelId");
ev.preventDefault();
document.cookie = "slides_channel_" + channel_id + " = closed";
return true;
},
});
return {
page_widgets: page_widgets,
};
});
@@ -1,50 +1,77 @@
/*global $, _, PDFSlidesViewer*/
odoo.define('website_slides.slides_embed', function (require) {
"use strict";
var time = require('web.time');
var Widget = require('web.Widget');
require('website_slides.slides');
(function () {
/*
* Embedded Code Widget
*/
var SlideSocialEmbed = Widget.extend({
events: {
'change input' : 'change_page',
},
init: function(parent, max_page){
this._super(parent);
this.max_page = max_page || false;
},
change_page: function(ev){
ev.preventDefault();
var input = this.$('input');
var page = parseInt(input.val());
if (this.max_page && !(page > 0 && page <= this.max_page)) {
page = 1;
}
this.update_embedded_code(page);
},
update_embedded_code: function(page){
var embed_input = this.$('.slide_embed_code');
var new_code = embed_input.val().replace(/(page=).*?([^\d]+)/, '$1' + page + '$2');
embed_input.val(new_code);
},
});
"use strict";
$('iframe.o_wslides_iframe_viewer').ready(function() {
// TODO : make it work. For now, once the iframe is loaded, the value of #page_count is
// still now set (the pdf is still loading)
var $iframe = $(this);
var max_page = $iframe.contents().find('#page_count').val();
slides.page_widgets['social_embed'] = new SlideSocialEmbed($iframe, max_page).setElement($('.oe_slide_js_embed_code_widget'));
});
})();
var Widget = require('web.Widget');
require('website_slides.slides');
var sAnimations = require('website.content.snippets.animation');
// Embedded Code Widget
var SlideSocialEmbed = Widget.extend({
events: {
'change input' : '_changePage',
},
/**
* @override
* @param {Object} parent
* @param {Number} max_page
*/
init: function (parent, max_page){
this._super(parent);
this.max_page = max_page || false;
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {Object} ev
*/
_changePage: function (ev){
ev.preventDefault();
var input = this.$('input');
var page = parseInt(input.val());
if (this.max_page && !(page > 0 && page <= this.max_page)) {
page = 1;
}
this._updateEmbeddedCode(page);
},
/**
* @private
* @param {Number} page
*/
_updateEmbeddedCode: function (page){
var embed_input = this.$('.slide_embed_code');
var new_code = embed_input.val().replace(/(page=).*?([^\d]+)/, '$1' + page + '$2');
embed_input.val(new_code);
},
});
sAnimations.registry.websiteSlidesEmbed = sAnimations.Class.extend({
selector: 'main',
read_events: {
'ready iframe.o_wslides_iframe_viewer': '_onIframeViewer',
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @override
*/
_onIframeViewer: function () {
// TODO : make it work. For now, once the iframe is loaded, the value of #page_count is
// still now set (the pdf is still loading)
var $iframe = $(this);
var max_page = $iframe.contents().find('#page_count').val();
new SlideSocialEmbed($iframe, max_page).setElement($('.oe_slide_js_embed_code_widget'));
},
});
});
/**
This file is a minimal version of the PDFViewer widget.
It is NOT use in the website_slides module, but it is
@@ -250,5 +277,3 @@ $(document).ready(function () {
});
}
});
@@ -1,63 +1,85 @@
/*global $, _, PDFJS */
odoo.define('website_slides.slides_like', function (require) {
"use strict";
var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
var local_storage = require('web.local_storage');
var slides = require('website_slides.slides');
var _t = core._t;
(function () {
"use strict";
var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
var local_storage = require('web.local_storage');
var sAnimations = require('website.content.snippets.animation');
var slides = require('website_slides.slides');
var _t = core._t;
// Like/Dislike Buttons Widget
var LikeButton = Widget.extend({
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {Object} $el
*/
setElement: function ($el){
this._super.apply(this, arguments);
this.$el.on('click', this, _.bind(this._applyAction, this));
},
/**
* @private
* @param {Object} ev
*/
_applyAction: function (ev){
var button = $(ev.currentTarget);
var slide_id = button.data('slide-id');
var user_id = button.data('user-id');
var is_public = button.data('public-user');
var href = button.data('href');
if (is_public){
this._popoverAlert(button, _.str.sprintf(_t('Please <a href="/web?redirect=%s">login</a> to vote this slide'), (document.URL)));
} else {
var target = button.find('.fa');
if (local_storage.getItem('slide_vote_' + slide_id) !== user_id.toString()) {
ajax.jsonRpc(href, 'call', {slide_id: slide_id}).then(function (data) {
target.text(data);
local_storage.setItem('slide_vote_' + slide_id, user_id);
});
} else {
this._popoverAlert(button, _t('You have already voted for this slide'));
}
}
},
/**
* @private
* @param {Object} $el
* @param {String} message
*/
_popoverAlert: function ($el, message){
$el.popover({
trigger: 'focus',
placement: 'bottom',
container: 'body',
html: true,
content: function () {
return message;
}
}).popover('show');
},
});
sAnimations.registry.websiteSlidesLike = sAnimations.Class.extend({
selector: 'main',
/**
* @override
* @param {Object} parent
*/
start: function (parent) {
var widget_parent = $('body');
/*
* Like/Dislike Buttons Widget
*/
var LikeButton = Widget.extend({
setElement: function($el){
this._super.apply(this, arguments);
this.$el.on('click', this, _.bind(this.apply_action, this));
},
apply_action: function(ev){
var button = $(ev.currentTarget);
var slide_id = button.data('slide-id');
var user_id = button.data('user-id');
var is_public = button.data('public-user');
var href = button.data('href');
if(is_public){
this.popover_alert(button, _.str.sprintf(_t('Please <a href="/web?redirect=%s">login</a> to vote this slide'), (document.URL)));
}else{
var target = button.find('.fa');
if (local_storage.getItem('slide_vote_' + slide_id) !== user_id.toString()) {
ajax.jsonRpc(href, 'call', {slide_id: slide_id}).then(function (data) {
target.text(data);
local_storage.setItem('slide_vote_' + slide_id, user_id);
});
} else {
this.popover_alert(button, _t('You have already voted for this slide'));
}
}
},
popover_alert: function($el, message){
$el.popover({
trigger: 'focus',
placement: 'bottom',
container: 'body',
html: true,
content: function(){
return message;
}
}).popover('show');
},
});
slides.page_widgets['likeButton'] = new LikeButton(widget_parent).setElement($('.oe_slide_js_like'));
slides.page_widgets['dislikeButton'] = new LikeButton(widget_parent).setElement($('.oe_slide_js_unlike'));
})();
return this._super.apply(this, arguments);
},
});
});
@@ -1,43 +1,56 @@
odoo.define('website_slides.slides_share', function (require) {
"use strict";
var ajax = require('web.ajax');
var Widget = require('web.Widget');
var slides = require('website_slides.slides');
"use strict";
var ajax = require('web.ajax');
var Widget = require('web.Widget');
var sAnimations = require('website.content.snippets.animation');
var slides = require('website_slides.slides');
(function () {
// Send by email Widget
var ShareMail = Widget.extend({
events: {
'click button': '_sendMail',
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
*/
_sendMail: function () {
var self = this;
var input = this.$('input');
var slide_id = this.$('button').data('slide-id');
if (input.val() && input[0].checkValidity()){
this.$el.removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid');
ajax.jsonRpc('/slides/slide/send_share_email', 'call', {
slide_id: slide_id,
email: input.val(),
}).then(function () {
self.$el.html($('<div class="alert alert-info" role="alert"><strong>Thank you!</strong> Mail has been sent.</div>'));
});
} else {
this.$el.addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
input.focus();
}
},
});
sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
selector: 'main',
read_events: {
'click a.o_slides_social_share': '_onSlidesSocialShare'
},
/**
* @override
* @param {Object} parent
*/
start: function (parent) {
var widget_parent = $('body');
/*
* Send by email Widget
*/
var ShareMail = Widget.extend({
events: {
'click button' : 'send_mail',
},
send_mail: function(){
var self = this;
var input = this.$('input');
var slide_id = this.$('button').data('slide-id');
if(input.val() && input[0].checkValidity()){
this.$el.removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid');
ajax.jsonRpc('/slides/slide/send_share_email', 'call', {
slide_id: slide_id,
email: input.val(),
}).then(function () {
self.$el.html($('<div class="alert alert-info" role="alert"><strong>Thank you!</strong> Mail has been sent.</div>'));
});
}else{
this.$el.addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
input.focus();
}
},
});
slides.page_widgets['share_mail'] = new ShareMail(widget_parent).setElement($('.oe_slide_js_share_email'));
/*
* Social Sharing Statistics Widget
*/
if ($('div#statistic').length) {
var slide_url = $("div#statistic").attr('slide-url');
var social_urls = {
@@ -45,66 +58,84 @@ odoo.define('website_slides.slides_share', function (require) {
'twitter': 'https://cdn.api.twitter.com/1/urls/count.json?url=',
'facebook': 'https://graph.facebook.com/?id=',
'gplus': 'https://clients6.google.com/rpc'
}
var update_statistics = function(social_site, slide_url) {
if (social_site == 'gplus') {
$.ajax({
url: social_urls['gplus'],
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify([{
"method": "pos.plusones.get",
"id": "p",
"params": {
"nolog": true,
"id": slide_url,
"source": "widget",
"userId": "@viewer",
"groupId": "@self"
},
// TDE NOTE: should there be a key here ?
"jsonrpc": "2.0",
"apiVersion": "v1"
}]),
success: function(data) {
$('#google-badge').text(data[0].result.metadata.globalCounts.count || 0);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#google-badge').text()));
},
});
} else {
$.ajax({
url: social_urls[social_site] + slide_url,
dataType: 'jsonp',
success: function(data) {
var shareCount = (social_site === 'facebook' ? data.shares : data.count) || 0;
$('#' + social_site + '-badge').text(shareCount);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#' + social_site+ '-badge').text()));
},
});
}
};
}
$.each(social_urls, function(key, value) {
update_statistics(key, slide_url);
$.each(social_urls, function (key, value) {
this._updateStatistics(key, slide_url);
});
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {string} social_site
* @param {string} slide_url
*/
_updateStatistics: function (social_site, slide_url) {
if (social_site === 'gplus') {
$.ajax({
url: this.social_urls['gplus'],
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify([{
"method": "pos.plusones.get",
"id": "p",
"params": {
"nolog": true,
"id": slide_url,
"source": "widget",
"userId": "@viewer",
"groupId": "@self"
},
// TDE NOTE: should there be a key here ?
"jsonrpc": "2.0",
"apiVersion": "v1"
}]),
success: function (data) {
$('#google-badge').text(data[0].result.metadata.globalCounts.count || 0);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#google-badge').text()));
},
});
$("a.o_slides_social_share").on('click', function(ev) {
ev.preventDefault();
var key = $(ev.currentTarget).attr('social-key');
var popUpURL = $(ev.currentTarget).attr('href');
var popUp = window.open(
popUpURL,
'Share Dialog',
'width=626,height=436');
$(window).on('focus', function() {
if (popUp.closed) {
update_statistics(key, slide_url);
$(window).off('focus');
}
});
} else {
$.ajax({
url: this.social_urls[social_site] + slide_url,
dataType: 'jsonp',
success: function (data) {
var shareCount = (social_site === 'facebook' ? data.shares : data.count) || 0;
$('#' + social_site + '-badge').text(shareCount);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#' + social_site+ '-badge').text()));
},
});
}
})();
})
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @override
* @param {Object} ev
*/
_onSlidesSocialShare: function (ev) {
ev.preventDefault();
var key = $(ev.currentTarget).attr('social-key');
var popUpURL = $(ev.currentTarget).attr('href');
var popUp = window.open(
popUpURL,
'Share Dialog',
'width=626,height=436');
$(window).on('focus', function () {
if (popUp.closed) {
this._updateStatistics(key, this.slide_url);
$(window).off('focus');
}
});
},
});
});
@@ -1,81 +1,311 @@
odoo.define('website_slides.upload', function (require) {
"use strict";
var sAnimations = require('website.content.snippets.animation');
var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
require('web.dom_ready');
var weContext = require("web_editor.context");
var slides = require('website_slides.slides');
var qweb = core.qweb;
var _t = core._t;
if (!$('.oe_slide_js_upload').length) {
return $.Deferred().reject("DOM doesn't contain '.oe_slide_js_upload'");
}
ajax.loadXML('/website_slides/static/src/xml/website_slides.xml', qweb);
var SlideDialog = Widget.extend({
template: 'website.slide.upload',
events: {
'hidden.bs.modal': 'destroy',
'click button.save': 'save',
'click button[data-dismiss="modal"]': 'cancel',
'change input#upload': 'slide_upload',
'change input#url': 'slide_url',
'click button.save': '_save',
'click button[data-dismiss="modal"]': '_cancel',
'change input#upload': '_slideUpload',
'change input#url': '_slideUrl',
'click .list-group-item': function (ev) {
this.$('.list-group-item').removeClass('active');
$(ev.target).closest('li').addClass('active');
}
},
/**
* @override
* @param {Object} el
* @param {number} channel_id
*/
init: function (el, channel_id) {
this._super(el, channel_id);
this.channel_id = parseInt(channel_id, 10);
this.file = {};
this.index_content = "";
},
start: function () {
/**
* @override
* @param {Object} parent
*/
start: function (parent) {
this.$el.modal({
backdrop: 'static'
});
this.set_category_id();
this.set_tag_ids();
this._setCategoryId();
this._setTagIds();
},
slide_url: function (ev) {
var self = this,
value = {
'url': $(ev.target).val(),
'channel_id': self.channel_id
};
this.$('.alert-warning').remove();
this.is_valid_url = false;
this.$('.save').button('loading');
ajax.jsonRpc('/slides/dialog_preview/', 'call', value).then(function (data) {
self.$('.save').button('reset');
if (data.error) {
self.display_alert(data.error);
} else {
self.$("#slide-image").attr("src", data.url_src);
self.$('#name').val(data.title);
self.$('#description').val(data.description);
self.is_valid_url = true;
}
});
},
check_unique_slide: function (file_name) {
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {string} file_name
*/
_checkUniqueSlide: function (file_name) {
var self = this;
return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
return this._rpc({
model: 'slide.slide',
method: 'search_count',
args: [[['channel_id', '=', self.channel_id], ['name', '=', file_name]]],
kwargs: {
context: weContext.get(), // TODO use this._rpc
}
});
},
slide_upload: function (ev) {
/**
* @private
*/
_resetFile: function () {
var control = this.$('#upload');
control.replaceWith(control = control.clone(true));
this.file.name = false;
},
/**
* @private
* @param {string} message
*/
_displayAlert: function (message) {
this.$('.alert-warning').remove();
$('<div class="alert alert-warning" role="alert">' + message + '</div>').insertBefore(this.$('form'));
},
/**
* Wrapper for select2 load data from server at once and store it.
*
* @private
* @param {String} Placeholder for element.
* @param {bool} true for multiple selection box, false for single selection
* @param {Function} Function to fetch data from remote location should return $.deferred object
* resolved data should be array of object with id and name. eg. [{'id': id, 'name': 'text'}, ...]
* @returns {Object} select2 wrapper object
*/
_select2Wrapper: function (tag, multi, fetch_fnc) {
return {
width: '100%',
placeholder: tag,
allowClear: true,
formatNoMatches: false,
multiple: multi,
selection_data: false,
fetch_rpc_fnc : fetch_fnc,
formatSelection: function (data) {
if (data.tag) {
data.text = data.tag;
}
return data.text;
},
createSearchChoice: function (term, data) {
var added_tags = $(this.opts.element).select2('data');
if (_.filter(_.union(added_tags, data), function (tag) {
return tag.text.toLowerCase().localeCompare(term.toLowerCase()) === 0;
}).length === 0) {
return {
id: _.uniqueId('tag_'),
create: true,
tag: term,
text: _.str.sprintf(_t("Create new tag '%s'"), term),
};
}
},
fill_data: function (query, data) {
var that = this,
tags = {results: []};
_.each(data, function (obj) {
if (that.matcher(query.term, obj.name)) {
tags.results.push({id: obj.id, text: obj.name });
}
});
query.callback(tags);
},
query: function (query) {
var that = this;
// fetch data only once and store it
if (!this.selection_data) {
this.fetch_rpc_fnc().then(function (data) {
that.fill_data(query, data);
that.selection_data = data;
});
} else {
this.fill_data(query, this.selection_data);
}
}
};
},
/**
* Category management from select2
*
* @private
*/
_setCategoryId: function () {
var self = this;
$('#category_id').select2(this._select2Wrapper(_t('Category'), false,
function () {
return this._rpc({
model: 'slide.category',
method: 'search_read',
args: [],
kwargs: {
fields: ['name'],
domain: [['channel_id', '=', self.channel_id]],
}
});
}));
},
/**
* @private
*/
_getCategoryId: function () {
var value = $('#category_id').select2('data');
if (value && value.create) {
return [0, {'name': value.text}];
}
return [value ? value.id : null];
},
/**
* Tags management from select2
*
* @private
*/
_setTagIds: function () {
$('#tag_ids').select2(this._select2Wrapper(_t('Tags'), true, function () {
return this._rpc({
model: 'slide.tag',
method: 'search_read',
args: [],
kwargs: {
fields: ['name'],
}
});
}));
},
/**
* @private
*/
_getTagIds: function () {
var res = [];
_.each($('#tag_ids').select2('data'),
function (val) {
if (val.create) {
res.push([0, 0, {'name': val.text}]);
} else {
res.push([4, val.id]);
}
});
return res;
},
/**
* @private
*/
// TODO: Remove this part, as now SVG support in image resize tools is included
//Python PIL does not support SVG, so converting SVG to PNG
_svgToPng: function () {
var img = this.$el.find("img#slide-image")[0];
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext("2d").drawImage(img, 0, 0);
return canvas.toDataURL("image/png").split(',')[1];
},
/**
* Values and save
*
* @private
*/
_getValue: function () {
var canvas = this.$('#data_canvas')[0],
values = {
'channel_id': this.channel_id || '',
'name': this.$('#name').val(),
'url': this.$('#url').val(),
'description': this.$('#description').val(),
'tag_ids': this._getTagIds(),
'category_id': this._getCategoryId()
};
if (this.file.type === 'application/pdf') {
_.extend(values, {
'image': canvas.toDataURL().split(',')[1],
'index_content': this.index_content,
'slide_type': canvas.height > canvas.width ? 'document' : 'presentation',
'mime_type': this.file.type,
'datas': this.file.data
});
}
if (/^image\/.*/.test(this.file.type)) {
_.extend(values, {
'slide_type': 'infographic',
'mime_type': this.file.type === 'image/svg+xml' ? 'image/png' : this.file.type,
'datas': this.file.type === 'image/svg+xml' ? this._svgToPng() : this.file.data
});
}
return values;
},
/**
* @private
*/
_validate: function () {
this.$('.form-group').removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid');
if (!this.$('#name').val()) {
this.$('#name').closest('.form-group').addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
return false;
}
var url = this.$('#url').val() ? this.is_valid_url : false;
if (!(this.file.name || url)) {
this.$('#url').closest('.form-group').addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
return false;
}
return true;
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @override
* @param {Object} ev
*/
_save: function (ev) {
var self = this;
if (this._validate()) {
var values = this._getValue();
if ($(ev.target).data('published')) {
values.website_published = true;
}
this.$('.oe_slides_upload_loading').show();
this.$('.modal-footer, .modal-body').hide();
ajax.jsonRpc("/slides/add_slide", 'call', values).then(function (data) {
if (data.error) {
self._displayAlert(data.error);
self.$('.oe_slides_upload_loading').hide();
self.$('.modal-footer, .modal-body').show();
} else {
window.location = data.url;
}
});
}
},
/**
* @override
*/
_cancel: function () {
this.trigger("cancel");
},
/**
* @override
* @param {Object} ev
*/
_slideUpload: function (ev) {
var self = this,
file = ev.target.files[0],
is_image = /^image\/.*/.test(file.type),
@@ -83,13 +313,13 @@ var SlideDialog = Widget.extend({
this.file.name = file.name;
this.file.type = file.type;
if (!(is_image || this.file.type === 'application/pdf')) {
this.display_alert(_t("Invalid file type. Please select pdf or image file"));
this.reset_file();
this._displayAlert(_t("Invalid file type. Please select pdf or image file"));
this._resetFile();
return;
}
if (file.size / 1024 / 1024 > 25) {
this.display_alert(_t("File is too big. File size cannot exceed 25MB"));
this.reset_file();
this._displayAlert(_t("File is too big. File size cannot exceed 25MB"));
this._resetFile();
return;
}
this.$('.alert-warning').remove();
@@ -113,8 +343,8 @@ var SlideDialog = Widget.extend({
ArrayReader.onload = function (evt) {
var buffer = evt.target.result;
var passwordNeeded = function () {
self.display_alert(_t("You can not upload password protected file."));
self.reset_file();
self._displayAlert(_t("You can not upload password protected file."));
self._resetFile();
self.$('.save').button('reset');
};
PDFJS.getDocument(new Uint8Array(buffer), null, passwordNeeded).then(function getPdf(pdf) {
@@ -169,222 +399,72 @@ var SlideDialog = Widget.extend({
var input = file.name;
var input_val = input.substr(0, input.lastIndexOf('.')) || input;
this.check_unique_slide(input_val).then(function (exist) {
this._checkUniqueSlide(input_val).then(function (exist) {
if (exist) {
var message = _t("Channel contains the given title, please change before Save or Publish.");
self.display_alert(message);
self._displayAlert(message);
}
self.$('#name').val(input_val);
});
},
reset_file: function () {
var control = this.$('#upload');
control.replaceWith(control = control.clone(true));
this.file.name = false;
},
display_alert: function (message) {
/**
* @override
* @param {Object} ev
*/
_slideUrl: function (ev) {
var self = this,
value = {
'url': $(ev.target).val(),
'channel_id': self.channel_id
};
this.$('.alert-warning').remove();
$('<div class="alert alert-warning" role="alert">' + message + '</div>').insertBefore(this.$('form'));
this.is_valid_url = false;
this.$('.save').button('loading');
ajax.jsonRpc('/slides/dialog_preview/', 'call', value).then(function (data) {
self.$('.save').button('reset');
if (data.error) {
self._displayAlert(data.error);
} else {
self.$("#slide-image").attr("src", data.url_src);
self.$('#name').val(data.title);
self.$('#description').val(data.description);
self.is_valid_url = true;
}
});
},
});
sAnimations.registry.websiteSlidesUpload = sAnimations.Class.extend({
selector: '.oe_slide_js_upload',
xmlDependencies: ['/website_slides/static/src/xml/website_slides.xml'],
read_events: {
'click .oe_slide_js_upload': '_bindEventButton',
},
/**
Wrapper for select2 load data from server at once and store it.
* @override
* @param {Object} parent
*/
start: function (parent) {
// Automatically open the upload dialog if requested from query string
if ($.deparam.querystring().enable_slide_upload !== undefined) {
$('.oe_slide_js_upload').click();
}
},
@param {String} Placeholder for element.
@param {bool} true for multiple selection box, false for single selection
@param {Function} Function to fetch data from remote location should return $.deferred object
resolved data should be array of object with id and name. eg. [{'id': id, 'name': 'text'}, ...]
@returns {Object} select2 wrapper object
*/
select2_wrapper: function (tag, multi, fetch_fnc) {
return {
width: '100%',
placeholder: tag,
allowClear: true,
formatNoMatches: false,
multiple: multi,
selection_data: false,
fetch_rpc_fnc : fetch_fnc,
formatSelection: function (data) {
if (data.tag) {
data.text = data.tag;
}
return data.text;
},
createSearchChoice: function (term, data) {
var added_tags = $(this.opts.element).select2('data');
if (_.filter(_.union(added_tags, data), function (tag) {
return tag.text.toLowerCase().localeCompare(term.toLowerCase()) === 0;
}).length === 0) {
return {
id: _.uniqueId('tag_'),
create: true,
tag: term,
text: _.str.sprintf(_t("Create new tag '%s'"), term),
};
}
},
fill_data: function (query, data) {
var that = this,
tags = {results: []};
_.each(data, function (obj) {
if (that.matcher(query.term, obj.name)) {
tags.results.push({id: obj.id, text: obj.name });
}
});
query.callback(tags);
},
query: function (query) {
var that = this;
// fetch data only once and store it
if (!this.selection_data) {
this.fetch_rpc_fnc().then(function (data) {
that.fill_data(query, data);
that.selection_data = data;
});
} else {
this.fill_data(query, this.selection_data);
}
}
};
},
// Category management from select2
set_category_id: function () {
var self = this;
$('#category_id').select2(this.select2_wrapper(_t('Category'), false,
function () {
return ajax.jsonRpc("/web/dataset/call_kw", 'call', {
model: 'slide.category',
method: 'search_read',
args: [],
kwargs: {
fields: ['name'],
domain: [['channel_id', '=', self.channel_id]],
context: weContext.get(), // TODO use this._rpc
}
});
}));
},
get_category_id: function () {
var value = $('#category_id').select2('data');
if (value && value.create) {
return [0, {'name': value.text}];
}
return [value ? value.id : null];
},
// Tags management from select2
set_tag_ids: function () {
$('#tag_ids').select2(this.select2_wrapper(_t('Tags'), true, function () {
return ajax.jsonRpc("/web/dataset/call_kw", 'call', {
model: 'slide.tag',
method: 'search_read',
args: [],
kwargs: {
fields: ['name'],
context: weContext.get(), // TODO use this._rpc
}
});
}));
},
get_tag_ids: function () {
var res = [];
_.each($('#tag_ids').select2('data'),
function (val) {
if (val.create) {
res.push([0, 0, {'name': val.text}]);
} else {
res.push([4, val.id]);
}
});
return res;
},
// TODO: Remove this part, as now SVG support in image resize tools is included
//Python PIL does not support SVG, so converting SVG to PNG
svg_to_png: function () {
var img = this.$el.find("img#slide-image")[0];
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext("2d").drawImage(img, 0, 0);
return canvas.toDataURL("image/png").split(',')[1];
},
// Values and save
get_value: function () {
var canvas = this.$('#data_canvas')[0],
values = {
'channel_id': this.channel_id || '',
'name': this.$('#name').val(),
'url': this.$('#url').val(),
'description': this.$('#description').val(),
'tag_ids': this.get_tag_ids(),
'category_id': this.get_category_id()
};
if (this.file.type === 'application/pdf') {
_.extend(values, {
'image': canvas.toDataURL().split(',')[1],
'index_content': this.index_content,
'slide_type': canvas.height > canvas.width ? 'document' : 'presentation',
'mime_type': this.file.type,
'datas': this.file.data
});
}
if (/^image\/.*/.test(this.file.type)) {
_.extend(values, {
'slide_type': 'infographic',
'mime_type': this.file.type === 'image/svg+xml' ? 'image/png' : this.file.type,
'datas': this.file.type === 'image/svg+xml' ? this.svg_to_png() : this.file.data
});
}
return values;
},
validate: function () {
this.$('.form-group').removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid');
if (!this.$('#name').val()) {
this.$('#name').closest('.form-group').addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
return false;
}
var url = this.$('#url').val() ? this.is_valid_url : false;
if (!(this.file.name || url)) {
this.$('#url').closest('.form-group').addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
return false;
}
return true;
},
save: function (ev) {
var self = this;
if (this.validate()) {
var values = this.get_value();
if ($(ev.target).data('published')) {
values.website_published = true;
}
this.$('.oe_slides_upload_loading').show();
this.$('.modal-footer, .modal-body').hide();
ajax.jsonRpc("/slides/add_slide", 'call', values).then(function (data) {
if (data.error) {
self.display_alert(data.error);
self.$('.oe_slides_upload_loading').hide();
self.$('.modal-footer, .modal-body').show();
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
} else {
window.location = data.url;
}
});
}
/**
* @override
*/
_bindEventButton: function () {
var channel_id = $(this).attr('channel_id');
slides.page_widgets['upload_dialog'] = new SlideDialog(this, channel_id).appendTo(document.body);
},
cancel: function () {
this.trigger("cancel");
}
});
// bind the event to the button
$('.oe_slide_js_upload').on('click', function () {
var channel_id = $(this).attr('channel_id');
slides.page_widgets['upload_dialog'] = new SlideDialog(this, channel_id).appendTo(document.body);
});
// automatically open the upload dialog if requested from query string
if ($.deparam.querystring().enable_slide_upload !== undefined) {
$('.oe_slide_js_upload').click();
}
});
});