[REF] website_slides: refactor the slide archive modal on frontend
Purpose ======= This commits refactors the slide archiving confirmation modal to make it a standard Dialog (remove global selectors, remove most of useless xml, ...). It also adds a new slide archive route to allow channel publishers to archive slides in sudo mode. Indeed ACLs only website_publishers can write on slide model. In some case people without real rights may update slides. Commit linked to task ID 1942852 and PR #31394.
This commit is contained in:
committed by
Thibault Delavallée
parent
362271f35a
commit
5db9ed0391
@@ -559,6 +559,17 @@ class WebsiteSlides(WebsiteProfile):
|
||||
slide.invalidate_cache()
|
||||
return slide.read(['likes', 'dislikes', 'user_vote'])[0]
|
||||
|
||||
@http.route('/slides/slide/archive', type='json', auth='user', website=True)
|
||||
def slide_archive(self, slide_id):
|
||||
""" This route allows channel publishers to archive slides.
|
||||
It has to be done in sudo mode since only website_publishers can write on slides in ACLs """
|
||||
slide = request.env['slide.slide'].browse(int(slide_id))
|
||||
if slide.channel_id.can_publish:
|
||||
slide.sudo().active = False
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@http.route(['/slides/slide/send_share_email'], type='json', auth='user', website=True)
|
||||
def slide_send_share_email(self, slide_id, email):
|
||||
slide = request.env['slide.slide'].browse(int(slide_id))
|
||||
|
||||
@@ -16,9 +16,9 @@ odoo.define('website_slides.slideslist', function (require) {
|
||||
},
|
||||
start: function (){
|
||||
this._super.apply(this,arguments);
|
||||
this.slideCount = $('li.content-slide').length;
|
||||
this.slideCount = $('li.o_wslides_content_slide').length;
|
||||
//Change links HREF to fullscreen mode for SEO
|
||||
var links = $(".link-to-slide");
|
||||
var links = $('.o_wslides_course_slide_link');
|
||||
for (var i = 0; i < links.length; i++){
|
||||
$(links[i]).attr('href', $(links[i]).attr('href') + "?fullscreen=1");
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
odoo.define('website_slides.delete.slide', function (require) {
|
||||
|
||||
var sAnimations = require('website.content.snippets.animation');
|
||||
var core = require('web.core');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
var _t = core._t;
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var DeleteSlideDialog = Widget.extend({
|
||||
template: 'website.slide.delete.slide',
|
||||
events: {
|
||||
'hidden.bs.modal': 'destroy',
|
||||
'click button[data-dismiss="modal"]': '_cancel',
|
||||
'click button.delete': '_delete'
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @param {Object} el
|
||||
* @param {number} channel_id
|
||||
*/
|
||||
init: function (el, slideID) {
|
||||
this._super(el, slideID);
|
||||
this.slide_id = parseInt(slideID, 10);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.modal({
|
||||
backdrop: 'static'
|
||||
});
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
_delete: function (ev) {
|
||||
var self = this;
|
||||
// TO FIX: CallBack is not executed
|
||||
$('[slide_id='+this.slide_id+']').remove();
|
||||
this._rpc({
|
||||
model: 'slide.slide',
|
||||
method: 'unlink',
|
||||
args: [[self.slide_id]],
|
||||
}).then(function () {
|
||||
$('[slide='+this.slide_id+']').remove();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_cancel: function () {
|
||||
this.trigger('cancel');
|
||||
}
|
||||
});
|
||||
|
||||
sAnimations.registry.websiteSlidesDeleteSlide = sAnimations.Class.extend({
|
||||
selector: '.oe_slide_js_delete_slide',
|
||||
xmlDependencies: ['/website_slides/static/src/xml/website_slides_upload.xml'],
|
||||
read_events: {
|
||||
'click': '_onDeleteSlideClick',
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_openDialog: function (slideID) {
|
||||
new DeleteSlideDialog(this, slideID).appendTo(document.body);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onDeleteSlideClick: function (ev) {
|
||||
var target = $(ev.currentTarget);
|
||||
this._openDialog(target.attr('slide_id'));
|
||||
},
|
||||
});
|
||||
return DeleteSlideDialog;
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
odoo.define('website_slides.slide.archive', function (require) {
|
||||
'use strict';
|
||||
|
||||
var sAnimations = require('website.content.snippets.animation');
|
||||
var Dialog = require('web.Dialog');
|
||||
var core = require('web.core');
|
||||
var _t = core._t;
|
||||
|
||||
var SlideArchiveDialog = Dialog.extend({
|
||||
template: 'slides.slide.archive',
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
options = _.defaults(options || {}, {
|
||||
title: _t('Archive Slide'),
|
||||
size: 'medium',
|
||||
buttons: [{
|
||||
text: _t('Archive'),
|
||||
classes: 'btn-primary',
|
||||
click: this._onClickArchive.bind(this)
|
||||
}, {
|
||||
text: _t('Cancel'),
|
||||
close: true
|
||||
}]
|
||||
});
|
||||
|
||||
this.$slideTarget = options.slideTarget;
|
||||
this.slideId = this.$slideTarget.attr('slide_id');
|
||||
this._super(parent, options);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Calls 'archive' on slide controller and then visually removes the slide dom element
|
||||
*/
|
||||
_onClickArchive: function () {
|
||||
var self = this;
|
||||
|
||||
this._rpc({
|
||||
route: '/slides/slide/archive',
|
||||
params: {
|
||||
slide_id: this.slideId
|
||||
},
|
||||
}).then(function () {
|
||||
self.$slideTarget.closest('.o_wslides_content_slide').remove();
|
||||
self.close();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
sAnimations.registry.websiteSlidesSlideArchive = sAnimations.Class.extend({
|
||||
selector: '.o_wslides_js_slide_archive',
|
||||
xmlDependencies: ['/website_slides/static/src/xml/slide_management.xml'],
|
||||
read_events: {
|
||||
'click': '_onArchiveSlideClick',
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_openDialog: function ($slideTarget) {
|
||||
new SlideArchiveDialog(this, {slideTarget: $slideTarget}).open();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onArchiveSlideClick: function (ev) {
|
||||
ev.preventDefault();
|
||||
var $slideTarget = $(ev.currentTarget);
|
||||
this._openDialog($slideTarget);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
slideArchiveDialog: SlideArchiveDialog,
|
||||
websiteSlidesSlideArchive: sAnimations.registry.websiteSlidesSlideArchive
|
||||
};
|
||||
|
||||
});
|
||||
@@ -542,7 +542,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
//Quick and really dirty fix for reordering issues
|
||||
if (data.channel_type === 'training' && self.categoryID){
|
||||
var categoryElement = $('ul[category_id='+self.categoryID+']');
|
||||
$('<li hidden class="content-slide" slide_id="'+data.slide_id+'" category_id="'+self.categoryID+'">temp</li>').appendTo(categoryElement);
|
||||
$('<li hidden class="o_wslides_content_slide" slide_id="'+data.slide_id+'" category_id="'+self.categoryID+'">temp</li>').appendTo(categoryElement);
|
||||
self._reorderSlidesSequence();
|
||||
}
|
||||
window.location = data.url;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="slides.slide.archive">
|
||||
<div>
|
||||
<p>Are you sure you want to archive this slide ?</p>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -208,28 +208,6 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.slide.delete.slide">
|
||||
<div role="dialog" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<header class="modal-header">
|
||||
<h3 class="modal-title">Delete Slide</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
||||
</header>
|
||||
<main class="modal-body">
|
||||
<div>
|
||||
<p>Are you sure you want to remove this slide ? </p>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="modal-footer">
|
||||
<button type="button" class="btn btn-primary delete" data-dismiss="modal">Delete</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.slide.add.section">
|
||||
<div role="dialog" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_share.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_upload.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_category.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_delete_slide.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_slide_archive.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_slides_list.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_progress_bar.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_fullscreen_player.js"/>
|
||||
|
||||
@@ -270,7 +270,8 @@
|
||||
</div>
|
||||
<ul t-attf-category_id="#{category.id}" >
|
||||
<t t-foreach="category.slide_ids" t-as="slide">
|
||||
<li t-att-index="j" t-attf-slide_id="#{slide.id}" t-attf-category_id="#{category.id}" t-attf-class="#{'o_wslides_content_slide slide-draggable d-flex justify-content-between align-items-center p-2' if channel.user_id == user else 'content-slide d-flex justify-content-between align-items-center p-2'}">
|
||||
<li t-att-index="j" t-attf-slide_id="#{slide.id}" t-attf-category_id="#{category.id}"
|
||||
t-att-class="'o_wslides_content_slide %s d-flex justify-content-between align-items-center p-2' % ('slide-draggable' if channel.user_id == user else '')}">
|
||||
<div class="ml-2">
|
||||
<i t-if="channel.user_id == user" class="fa fa-arrows mr-2 text-muted"></i>
|
||||
<i t-if="slide.slide_type == 'document'" class="fa fa-file-pdf-o mr-2 text-muted"></i>
|
||||
@@ -280,14 +281,14 @@
|
||||
<i t-if="slide.slide_type == 'webpage'" class="fa fa-file-text mr-2 text-muted"></i>
|
||||
<i t-if="slide.slide_type == 'quiz'" class="fa fa-question-circle mr-2 text-muted"></i>
|
||||
<i t-if="slide.slide_type == 'certification'" class="fa fa-trophy mr-2 text-muted"></i>
|
||||
<a class="link-to-slide" t-attf-href="/slides/slide/#{slug(slide)}"><span t-field="slide.name"/></a>
|
||||
<a class="o_wslides_course_slide_link" t-attf-href="/slides/slide/#{slug(slide)}"><span t-field="slide.name"/></a>
|
||||
</div>
|
||||
<div class="o_wslides_content_slide_controls mr-2">
|
||||
<i t-if="not slide.id in user_progress or not user_progress[slide.id].completed" class="check-done fa fa-check-circle text-muted mr-1"></i>
|
||||
<i t-if="slide.id in user_progress and user_progress[slide.id].completed" class="check-done text-primary fa fa-check-circle mr-1"></i>
|
||||
<a t-if="channel.user_id == user and not slide.slide_type == 'webpage'" t-attf-href="/web#id=#{slide.id}&action=#{slide_action}&model=slide.slide&view_type=form"><i class="fa fa-pencil text-muted mr-1"></i></a>
|
||||
<a t-if="channel.user_id == user and slide.slide_type == 'webpage'" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><i class="fa fa-pencil text-muted mr-1"></i></a>
|
||||
<i t-if="channel.user_id == user" t-attf-slide_id="#{slide.id}" class="fa fa-trash text-muted oe_slide_js_delete_slide"></i>
|
||||
<a t-if="channel.can_publish and not slide.slide_type == 'webpage'" t-attf-href="/web#id=#{slide.id}&action=#{slide_action}&model=slide.slide&view_type=form"><i class="fa fa-pencil text-muted mr-1"></i></a>
|
||||
<a t-if="channel.can_publish and slide.slide_type == 'webpage'" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><i class="fa fa-pencil text-muted mr-1"></i></a>
|
||||
<i t-if="channel.can_publish" t-attf-slide_id="#{slide.id}" class="fa fa-trash text-muted o_wslides_js_slide_archive"></i>
|
||||
</div>
|
||||
</li>
|
||||
<t t-set="j" t-value="j+1"/>
|
||||
|
||||
Reference in New Issue
Block a user