[IMP] website_slides: create channel in frontend
This commit provides the abilty to create channel from the website instead of creating a slide. To do so, the user still have the "upload" button on the channel home page. The new modal allow user to set title, description, type and channel tags. We prevent channel tag and group tag creation on the fly, as it can impact the UI (coming in a future commits). Task-1938643
This commit is contained in:
@@ -147,15 +147,15 @@
|
||||
</a>
|
||||
</div>
|
||||
<div groups="base.group_system" name="module_website_slides" t-att-data-module-id="env.ref('base.module_website_slides').id" t-att-data-module-shortdesc="env.ref('base.module_website_slides').shortdesc" class="col-md-4 mb8 o_new_content_element">
|
||||
<a href="#" data-action="new_slide">
|
||||
<a href="#" data-action="new_slide_channel">
|
||||
<i class="fa fa-youtube-play"/>
|
||||
<p>New Slide</p>
|
||||
<p>New Slide Channel</p>
|
||||
</a>
|
||||
</div>
|
||||
<div groups="base.group_system" name="module_website_livechat" t-att-data-module-id="env.ref('base.module_website_livechat').id" t-att-data-module-shortdesc="env.ref('base.module_website_livechat').shortdesc" class="col-md-4 mb8 o_new_content_element">
|
||||
<a href="#" data-action="new_channel">
|
||||
<i class="fa fa-hashtag"/>
|
||||
<p>New Channel</p>
|
||||
<p>New Livechat Channel</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -183,6 +183,23 @@ class WebsiteSlides(http.Controller):
|
||||
|
||||
return request.render('website_slides.home', values)
|
||||
|
||||
@http.route(['/slides/channel/add'], type='http', auth='user', methods=['POST'], website=True)
|
||||
def slide_channel_create(self, *args, **kw):
|
||||
# `tag_ids` is a string representing a list of int with coma. i.e.: '2,5,7'
|
||||
# We don't want to allow user to create tags and tag groups on the fly.
|
||||
tag_ids = []
|
||||
if kw.get('tag_ids'):
|
||||
tag_ids = [int(item) for item in kw['tag_ids'].split(',')]
|
||||
|
||||
channel = request.env['slide.channel'].create({
|
||||
'name': kw['name'],
|
||||
'description': kw.get('description'),
|
||||
'channel_type': kw.get('channel_type', 'documentation'),
|
||||
'user_id': request.env.user.id,
|
||||
'tag_ids': [(6, 0, tag_ids)],
|
||||
})
|
||||
return werkzeug.utils.redirect("/slides/%s" % (slug(channel)))
|
||||
|
||||
# --------------------------------------------------
|
||||
# SLIDE.SLIDE CONTOLLERS
|
||||
# --------------------------------------------------
|
||||
@@ -319,6 +336,14 @@ 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)}
|
||||
|
||||
@http.route(['/slides/channel/tag/search_read'], type='json', auth='user', methods=['POST'], website=True)
|
||||
def slide_channel_tag_search_read(self, fields, domain):
|
||||
can_create = request.env['slide.channel.tag'].check_access_rights('create', raise_exception=False)
|
||||
return {
|
||||
'read_results': request.env['slide.channel.tag'].search_read(domain, fields),
|
||||
'can_create': can_create,
|
||||
}
|
||||
|
||||
@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)
|
||||
|
||||
@@ -67,6 +67,7 @@ class Channel(models.Model):
|
||||
('documentation', 'Documentation'), ('training', 'Training')],
|
||||
string="Course type", default="documentation", required=True)
|
||||
sequence = fields.Integer(default=10, help='Display order')
|
||||
user_id = fields.Many2one('res.users', string='Responsible', default=lambda self: self.env.uid)
|
||||
tag_ids = fields.Many2many(
|
||||
'slide.channel.tag', 'slide_channel_tag_rel', 'channel_id', 'tag_id',
|
||||
string='Tags', help='Used to categorize and filter displayed channels/courses')
|
||||
|
||||
@@ -8,12 +8,83 @@ var WebsiteNewMenu = require('website.newMenu');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
|
||||
var ChannelCreateDialog = Dialog.extend({
|
||||
template: 'website.slide.channel.create',
|
||||
/**
|
||||
* @override
|
||||
* @param {Object} parent
|
||||
* @param {Object} options
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
options = _.defaults(options || {}, {
|
||||
title: _t("New Channel Slide"),
|
||||
size: 'medium',
|
||||
buttons: [{
|
||||
text: _t("Create"),
|
||||
classes: 'btn-primary',
|
||||
click: this._onClickFormSubmit.bind(this)
|
||||
}, {
|
||||
text: _t("Discard"),
|
||||
close: true
|
||||
},]
|
||||
});
|
||||
this._super(parent, options);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function () {
|
||||
var $input = self.$('#tag_ids');
|
||||
$input.select2({
|
||||
width: '100%',
|
||||
allowClear: true,
|
||||
formatNoMatches: false,
|
||||
multiple: true,
|
||||
selection_data: false,
|
||||
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) {
|
||||
self._rpc({
|
||||
route: '/slides/channel/tag/search_read',
|
||||
params: {
|
||||
fields: ['name'],
|
||||
domain: [],
|
||||
}
|
||||
}).then(function (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);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
_onClickFormSubmit: function (ev) {
|
||||
var $form = this.$("#slide_channel_add_form");
|
||||
$form.submit()
|
||||
},
|
||||
});
|
||||
|
||||
WebsiteNewMenu.include({
|
||||
actions: _.extend({}, WebsiteNewMenu.prototype.actions || {}, {
|
||||
new_slide: '_createNewSlide',
|
||||
new_slide_channel: '_createNewSlideChannel',
|
||||
}),
|
||||
xmlDependencies: WebsiteNewMenu.prototype.xmlDependencies.concat(
|
||||
['/website_slides/static/src/xml/website_slides.xml']
|
||||
['/website_slides/static/src/xml/website_slides_channel.xml']
|
||||
),
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -21,44 +92,20 @@ WebsiteNewMenu.include({
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Asks the user information about in which channel to create a new slide,
|
||||
* and redirects the user to this channel with the "new slide" popup open.
|
||||
* Displays the popup to create a new slide channel,
|
||||
* and redirects the user to this channel.
|
||||
*
|
||||
* @private
|
||||
* @returns {Deferred} Unresolved if there is a redirection
|
||||
*/
|
||||
_createNewSlide: function () {
|
||||
var self = this;
|
||||
return this._rpc({
|
||||
model: 'slide.channel',
|
||||
method: 'list_all',
|
||||
args: [[]],
|
||||
}).then(function (data) {
|
||||
var def = $.Deferred();
|
||||
new Dialog(self, {
|
||||
title: _t("New slide"),
|
||||
subtitle: _t("On which channel do you want to add a slide?"),
|
||||
size: 'medium',
|
||||
$content: QWeb.render('website.slide.create', data),
|
||||
buttons: [{
|
||||
text: _t("Select"),
|
||||
classes: 'btn-primary',
|
||||
click: function () {
|
||||
var channel_url = this.$("option:selected").val();
|
||||
if (channel_url) {
|
||||
window.location.href = channel_url + '?enable_slide_upload';
|
||||
} else {
|
||||
def.reject();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
text: _t("Cancel"), close: true
|
||||
},]
|
||||
}).open()
|
||||
.on('closed', def.resolve.bind(def));
|
||||
|
||||
return def;
|
||||
_createNewSlideChannel: function () {
|
||||
var def = $.Deferred();
|
||||
var dialog = new ChannelCreateDialog(this, {});
|
||||
dialog.open();
|
||||
dialog.on('closed', this, function() {
|
||||
def.resolve();
|
||||
});
|
||||
},
|
||||
return def;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="website.slide.channel.create">
|
||||
<div>
|
||||
<form action="/slides/channel/add" method="POST" id="slide_channel_add_form">
|
||||
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
|
||||
<div class="form-group row">
|
||||
<label for="title" class="col-sm-2 col-form-label">Title</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name" id="title" placeholder="Title"/>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="form-group">
|
||||
<div class="row">
|
||||
<legend class="col-form-label col-sm-2">Type</legend>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="channel_type" id="channel_type1" value="training" checked="checked"/>
|
||||
<label class="form-check-label" for="channel_type1">
|
||||
Training (with progress)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="channel_type" id="channel_type2" value="documentation"/>
|
||||
<label class="form-check-label" for="channel_type2">
|
||||
Documentation
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="form-group row">
|
||||
<label for="title" class="col-sm-2 col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea name="description" id="description" style="height:8em" class="form-control" placeholder="Write here a short description of your first course"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="title" class="col-sm-2 col-form-label">Tags</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="tag_ids" id="tag_ids" placeholder="Tags"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -79,6 +79,7 @@
|
||||
context="{'default_channel_id': active_id}"
|
||||
domain="[('channel_id','=', active_id)]"/>
|
||||
<field name="tag_ids" widget="many2many_tags" placeholder="Tags"/>
|
||||
<field name="user_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
@@ -88,7 +89,7 @@
|
||||
<page string="Options">
|
||||
<group>
|
||||
<group>
|
||||
<field name="channel_type"/>
|
||||
<field name="channel_type" widget="radio"/>
|
||||
<field name="website_id" options="{'no_create': True}" groups="website.group_multi_website"/>
|
||||
<field name="promote_strategy" widget="radio"/>
|
||||
</group>
|
||||
|
||||
Reference in New Issue
Block a user