[MERGE][FIX] website_slides: fix various issues

Purpose of this merge it to merge various fixes and small improvements
related to slides module. As an update of this module is pending fixing
it before is quite helpful.

This merge is linked to task ID 1933820 and PR #30553.
This commit is contained in:
Robot Odoo
2019-01-28 17:23:55 +01:00
committed by GitHub
7 changed files with 142 additions and 90 deletions
+58 -12
View File
@@ -35,6 +35,28 @@ class WebsiteSlides(http.Controller):
request.session[slide_key] = viewed_slides
return True
def _check_session_slide_vote(self, slide, upvote=True):
if not request.session.get('__wslides_upvote'):
request.session['__wslides_upvote'] = []
if not request.session.get('__wslides_downvote'):
request.session['__wslides_downvote'] = []
if upvote and slide.id in request.session['__wslides_upvote']:
return False
if not upvote and slide.id in request.session['__wslides_downvote']:
return False
if upvote and slide.id in request.session['__wslides_downvote']:
request.session['__wslides_downvote'].remove(slide.id)
return 0
if not upvote and slide.id in request.session['__wslides_upvote']:
request.session['__wslides_upvote'].remove(slide.id)
return 0
if upvote:
request.session['__wslides_upvote'].append(slide.id)
return 1
if not upvote:
request.session['__wslides_downvote'].append(slide.id)
return -1
def _get_slide_detail(self, slide):
most_viewed_slides = slide.get_most_viewed_slides(self._slides_per_list)
related_slides = slide.get_related_slides(self._slides_per_list)
@@ -43,7 +65,7 @@ class WebsiteSlides(http.Controller):
'most_viewed_slides': most_viewed_slides,
'related_slides': related_slides,
'user': request.env.user,
'is_public_user': request.env.user == request.website.user_id,
'is_public_user': request.website.is_public_user(),
'comments': slide.channel_id.can_see_full and slide.website_message_ids or [],
'private': not slide.channel_id.can_see_full,
}
@@ -66,7 +88,7 @@ class WebsiteSlides(http.Controller):
return request.render('website_slides.channels', {
'channels': channels,
'user': request.env.user,
'is_public_user': request.env.user == request.website.user_id
'is_public_user': request.website.is_public_user(),
})
def sitemap_slide(env, rule, qs):
@@ -142,7 +164,7 @@ class WebsiteSlides(http.Controller):
'sorting': sorting,
'user': user,
'pager': pager,
'is_public_user': user == request.website.user_id,
'is_public_user': request.website.is_public_user(),
'display_channel_settings': not request.httprequest.cookies.get('slides_channel_%s' % (channel.id), False) and channel.can_see_full,
}
if search:
@@ -209,16 +231,24 @@ class WebsiteSlides(http.Controller):
# JSONRPC
@http.route('/slides/slide/like', type='json', auth="user", website=True)
def slide_like(self, slide_id):
def slide_like(self, slide_id, upvote):
if request.website.is_public_user():
return {'error': 'public_user'}
slide = request.env['slide.slide'].browse(int(slide_id))
slide.likes += 1
return slide.likes
@http.route('/slides/slide/dislike', type='json', auth="user", website=True)
def slide_dislike(self, slide_id):
slide = request.env['slide.slide'].browse(int(slide_id))
slide.dislikes += 1
return slide.dislikes
slide.check_access_rights('read')
slide.check_access_rule('read')
check = self._check_session_slide_vote(slide, upvote=upvote)
if check is False:
return {'error': 'vote_done'}
if check == 1:
slide.sudo().likes += 1
elif check == 0 and upvote:
slide.sudo().dislikes -= 1
elif check == 0 and not upvote:
slide.sudo().likes -= 1
else:
slide.sudo().dislikes += 1
return {'state': check, 'likes': slide.likes, 'dislikes': slide.dislikes}
@http.route(['/slides/slide/send_share_email'], type='json', auth='user', website=True)
def slide_send_share_email(self, slide_id, email):
@@ -296,6 +326,22 @@ class WebsiteSlides(http.Controller):
return {'error': _('Internal server error, please try again later or contact administrator.\nHere is the error message: %s') % e}
return {'url': "/slides/slide/%s" % (slide_id.id)}
@http.route(['/slides/tag/search_read'], type='json', auth='user', methods=['POST'], website=True)
def slide_tag_search_read(self, fields, domain):
can_create = request.env['slide.tag'].check_access_rights('create', raise_exception=False)
return {
'read_results': request.env['slide.tag'].search_read(domain, fields),
'can_create': can_create,
}
@http.route(['/slides/category/search_read'], type='json', auth='user', methods=['POST'], website=True)
def slide_category_search_read(self, fields, domain):
can_create = request.env['slide.category'].check_access_rights('create', raise_exception=False)
return {
'read_results': request.env['slide.category'].search_read(domain, fields),
'can_create': can_create,
}
# --------------------------------------------------
# EMBED IN THIRD PARTY WEBSITES
# --------------------------------------------------
@@ -127,9 +127,9 @@ class Channel(models.Model):
@api.one
@api.depends('visibility', 'group_ids', 'upload_group_ids')
def _compute_access(self):
self.can_see = self.visibility in ['public', 'private'] or bool(self.group_ids & self.env.user.groups_id)
self.can_see = self.visibility in ['public', 'partial'] or bool(self.group_ids & self.env.user.groups_id)
self.can_see_full = self.visibility == 'public' or bool(self.group_ids & self.env.user.groups_id)
self.can_upload = self.can_see and (not self.upload_group_ids or bool(self.upload_group_ids & self.env.user.groups_id))
self.can_upload = not self.env.user.share and (not self.upload_group_ids or bool(self.upload_group_ids & self.env.user.groups_id))
@api.multi
@api.depends('name')
@@ -11,42 +11,14 @@ var _t = core._t;
var LikeButton = Widget.extend({
events: {
'click': '_onClick',
'click .o_wslides_like_up': '_onClickUp',
'click .o_wslides_like_down': '_onClickDown',
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {Object} ev
*/
_applyAction: function (ev) {
var button = $(ev.currentTarget);
var slideID = button.data('slide-id');
var userID = button.data('user-id');
var isPublic = button.data('public-user');
var href = button.data('href');
if (isPublic) {
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 (localStorage.getItem('slide_vote_' + slideID) !== userID.toString()) {
this._rpc({
route: href,
params: {
slide_id: slideID,
},
}).then(function (data) {
target.text(data);
localStorage.setItem('slide_vote_' + slideID, userID);
});
} else {
this._popoverAlert(button, _t('You have already voted for this slide'));
}
}
},
/**
* @private
* @param {Object} $el
@@ -71,8 +43,38 @@ var LikeButton = Widget.extend({
/**
* @private
*/
_onClick: function () {
this._applyAction();
_onClick: function (slideId, voteType) {
var self = this;
this._rpc({
route: '/slides/slide/like',
params: {
slide_id: slideId,
upvote: voteType === 'like',
},
}).then(function (data) {
if (! data.error) {
self.$el.find('span.o_wslides_like_up span').text(data.likes);
self.$el.find('span.o_wslides_like_down span').text(data.dislikes);
} else {
if (data.error === 'public_user') {
self._popoverAlert(self.$el, _.str.sprintf(_t('Please <a href="/web?redirect=%s">login</a> to vote this slide'), (document.URL)));
} else if (data.error === 'vote_done') {
self._popoverAlert(self.$el, _t('You have already voted for this slide'));
} else {
self._popoverAlert(self.$el, _t('Unknown error'));
}
}
});
},
_onClickUp: function (event) {
var slideId = $(event.currentTarget).data('slide-id');
return this._onClick(slideId, 'like');
},
_onClickDown: function (event) {
var slideId = $(event.currentTarget).data('slide-id');
return this._onClick(slideId, 'dislike');
},
});
@@ -83,10 +85,9 @@ sAnimations.registry.websiteSlidesLike = sAnimations.Class.extend({
* @override
* @param {Object} parent
*/
start: function (parent) {
start: function () {
var defs = [this._super.apply(this, arguments)];
defs.push(new LikeButton(this).attachTo($('.oe_slide_js_like')));
defs.push(new LikeButton(this).attachTo($('.oe_slide_js_unlike')));
defs.push(new LikeButton(this).attachTo($('.o_wslides_like')));
return $.when.apply($, defs);
},
});
@@ -50,12 +50,13 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
* @param {Object} parent
*/
start: function (parent) {
var self = this;
var defs = [this._super.apply(this, arguments)];
defs.push(new ShareMail(this).attachTo($('.oe_slide_js_share_email')));
if ($('div#statistic').length) {
var slideURL = $('div#statistic').attr('slide-url');
var socialURLs = {
this.slideURL = $('div#statistic').attr('slide-url');
this.socialURLs = {
linkedin: 'https://www.linkedin.com/countserv/count/share?url=',
twitter: 'https://cdn.api.twitter.com/1/urls/count.json?url=',
facebook: 'https://graph.facebook.com/?id=',
@@ -63,9 +64,9 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
};
}
_.each(socialURLs, function (value, key) {
this._updateStatistics(key, slideURL);
});
_.each(this.socialURLs, function (value, key) {
self._updateStatistics(key, self.slideURL);
});
return $.when.apply($, defs);
},
@@ -80,9 +81,10 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
* @param {string} slide_url
*/
_updateStatistics: function (socialSite, slideURL) {
var self = this;
if (socialSite === 'gplus') {
$.ajax({
url: this.social_urls['gplus'],
url: self.socialURLs['gplus'],
type: 'POST',
dataType: 'json',
contentType: 'application/json',
@@ -107,7 +109,7 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
});
} else {
$.ajax({
url: this.social_urls[socialSite] + slideURL,
url: self.socialURLs[socialSite] + slideURL,
dataType: 'jsonp',
success: function (data) {
var shareCount = (socialSite === 'facebook' ? data.shares : data.count) || 0;
@@ -53,7 +53,6 @@ var SlideDialog = Widget.extend({
* @param {string} file_name
*/
_checkUniqueSlide: function (fileName) {
var self = this;
return this._rpc({
model: 'slide.slide',
method: 'search_count',
@@ -107,12 +106,16 @@ var SlideDialog = Widget.extend({
if (_.filter(_.union(addedTags, 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),
};
if (this.opts.can_create) {
return {
id: _.uniqueId('tag_'),
create: true,
tag: term,
text: _.str.sprintf(_t("Create new tag '%s'"), term),
};
} else {
return undefined;
}
}
},
fill_data: function (query, data) {
@@ -130,8 +133,9 @@ var SlideDialog = Widget.extend({
// 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;
that.can_create = data.can_create;
that.fill_data(query, data.read_results);
that.selection_data = data.read_results;
});
} else {
this.fill_data(query, this.selection_data);
@@ -148,11 +152,9 @@ var SlideDialog = Widget.extend({
var self = this;
$('#category_id').select2(this._select2Wrapper(_t('Category'), false,
function () {
return this._rpc({
model: 'slide.category',
method: 'search_read',
args: [],
kwargs: {
return self._rpc({
route: '/slides/category/search_read',
params: {
fields: ['name'],
domain: [['channel_id', '=', self.channel_id]],
}
@@ -175,13 +177,13 @@ var SlideDialog = Widget.extend({
* @private
*/
_setTagIds: function () {
var self = this;
$('#tag_ids').select2(this._select2Wrapper(_t('Tags'), true, function () {
return this._rpc({
model: 'slide.tag',
method: 'search_read',
args: [],
kwargs: {
return self._rpc({
route: '/slides/tag/search_read',
params: {
fields: ['name'],
domain: [],
}
});
}));
@@ -84,7 +84,7 @@ img.oe_slides_promote_image {
border-bottom: 1px solid $nav-tabs-border-color;
}
.oe_slide_js_like, .oe_slide_js_unlike{
.o_wslides_like_up, .o_wslides_like_down {
cursor: pointer;
color: $link-color;
}
@@ -153,6 +153,13 @@ textarea.o_slides_comment {
padding: 10px;
}
// Slide display
div.embed-responsive {
iframe.o_wslides_iframe_viewer {
position: relative;
}
}
// PDF Viewer Share bar
.oe_slides_share_bar{
padding: 10px 0;
@@ -88,7 +88,7 @@
/ <a t-attf-href="/slides/#{slug(channel)}/category/#{slug(category)}" t-esc="category.name"/>
</t>
<!-- Public user has not right to create/write on slide -->
<t t-if="channel.can_upload and not is_public_user">
<t t-if="channel.can_see and channel.can_upload and not is_public_user">
<a role="button" class="btn btn-primary oe_slide_js_upload" title="Upload Presentation" t-attf-channel_id="#{channel.id}" aria-label="Upload Presentation" href="#">
<i class="fa fa-cloud-upload"></i> Upload
</a>
@@ -233,13 +233,13 @@
<h1>No presentation published yet.</h1>
<p>
The <i><t t-esc="channel.name"/></i> is empty.
<span t-if="can_upload">
<span t-if="channel.can_see and channel.can_upload">
Upload PDF presentations, documents, videos or infographic using the button below.
</span>
</p>
<p>
<!-- Public user has not right to create/write on slide-->
<a role="button" t-if="can_upload and not is_public_user" class="btn btn-primary oe_slide_js_upload" t-attf-channel_id="#{channel.id}" aria-label="Upload Presentation" title="Upload Presentation" href="#">
<a role="button" t-if="channel.can_see and channel.can_upload and not is_public_user" class="btn btn-primary oe_slide_js_upload" t-attf-channel_id="#{channel.id}" aria-label="Upload Presentation" title="Upload Presentation" href="#">
<i class="fa fa-cloud-upload"></i> Upload
</a>
</p>
@@ -436,28 +436,22 @@
</div>
<!-- LikeButton widget -->
<div class="text-muted mt4">
<div class="float-right mb16 text-right">
<div class="float-right mb16 text-right o_wslides_like">
<span
class="oe_slide_js_like"
data-href="/slides/slide/like"
t-att-data-user-id="user.id"
t-att-data-public-user="is_public_user"
class="o_wslides_like_up"
t-att-data-slide-id="slide.id"
tabindex="0"
data-toggle="popover">
<i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"/>
<span class="o_wslides_like_dislike_count" t-esc="slide.likes"/>
<span t-esc="slide.likes"/>
</span>
<span
class="oe_slide_js_unlike"
data-href="/slides/slide/dislike"
t-att-data-user-id="user.id"
t-att-data-public-user="is_public_user"
class="o_wslides_like_down"
t-att-data-slide-id="slide.id"
tabindex="0"
data-toggle="popover">
<i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"/>
<span class="o_wslides_like_dislike_count" t-esc="slide.dislikes"/>
<span t-esc="slide.dislikes"/>
</span>
</div>
</div>