[IMP] website_slides,_survey: allow certification creation at frontend
Purpose
=======
Before this commit, in the front end, you had to create a certification before
adding it to a course. This commit allows creation of certification in
front-end with pre-filled settings.
Functional Spec
===============
1. On a course, add content, type certification, you can choose an existing one
(normal flow) or create a new one in the dropdown by typing a new survey
name (new flow).
3. When submitting (Publish or save as draft), a certification survey, with
pre-filled settings is created and linked to the slide.
Pre-filled settings:
* One page per question
* Attempts limit : 1
* Time limit : no limit
* Scoring without answers
* Passing score : 70%
* Is Certification : True
* Email Template : Certification: Send by email
* Give Badge : False
4. After submit, the user stays on the Course Content.
5. A toaster is displayed in the top right saying:
Toaster's Title: Certification created
Content: Follow this link to add questions to your certification.
<a>Edit certification</a>
A website editor can select a certification (if available) for the creation of
a slide.
Task id: 1981399
PR #43577
Co-Authored-By: Florent Lejoly <fle@odoo.com>
Co-Authored-By: David Beguin <dbe@odoo.com>
This commit is contained in:
committed by
Thibault Delavallée
co-authored by
David Beguin
parent
dd53c515c8
commit
24033e4aaf
@@ -1,13 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import http
|
||||
from odoo import http, _
|
||||
from odoo.http import request
|
||||
from odoo.exceptions import AccessError
|
||||
|
||||
from odoo.addons.website_slides.controllers.main import WebsiteSlides
|
||||
|
||||
|
||||
class WebsiteSlidesSurvey(http.Controller):
|
||||
class WebsiteSlidesSurvey(WebsiteSlides):
|
||||
|
||||
@http.route(['/slides_survey/certification/search_read'], type='json', auth='user', methods=['POST'], website=True)
|
||||
def slides_certification_search_read(self, fields):
|
||||
can_create = request.env['survey.survey'].check_access_rights('create', raise_exception=False)
|
||||
return {
|
||||
'read_results': request.env['survey.survey'].search_read([('certification', '=', True)], fields),
|
||||
'can_create': can_create,
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Overrides
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route(['/slides/add_slide'], type='json', auth='user', methods=['POST'], website=True)
|
||||
def create_slide(self, *args, **post):
|
||||
create_new_survey = post['slide_type'] == "certification" and post.get('survey') and not post['survey']['id']
|
||||
linked_survey_id = int(post.get('survey', {}).get('id') or 0)
|
||||
|
||||
if create_new_survey:
|
||||
# If user cannot create a new survey, no need to create the slide either.
|
||||
if not request.env['survey.survey'].check_access_rights('create', raise_exception=False):
|
||||
return {'error': _('You are not allowed to create a survey.')}
|
||||
|
||||
# Create survey first as certification slide needs a survey_id (constraint)
|
||||
post['survey_id'] = request.env['survey.survey'].create({
|
||||
'title': post['survey']['title'],
|
||||
'background_image': post['image_1920'],
|
||||
'questions_layout': 'page_per_question',
|
||||
'is_attempts_limited': True,
|
||||
'attempts_limit': 1,
|
||||
'is_time_limited': False,
|
||||
'scoring_type': 'scoring_without_answers',
|
||||
'certification': True,
|
||||
'scoring_success_min': 70.0,
|
||||
'certification_mail_template_id': request.env.ref('survey.mail_template_certification').id,
|
||||
}).id
|
||||
elif linked_survey_id:
|
||||
try:
|
||||
request.env['survey.survey'].browse([linked_survey_id]).read(['title'])
|
||||
except AccessError:
|
||||
return {'error': _('You are not allowed to link a certification.')}
|
||||
|
||||
post['survey_id'] = post['survey']['id']
|
||||
|
||||
# Then create the slide
|
||||
result = super(WebsiteSlidesSurvey, self).create_slide(*args, **post)
|
||||
|
||||
if create_new_survey:
|
||||
# Set the redirect_url used in toaster
|
||||
action_id = request.env.ref('survey.action_survey_form').id
|
||||
result.update({
|
||||
'redirect_url': '/web#id=%s&action=%s&model=survey.survey&view_type=form' % (post['survey_id'], action_id),
|
||||
'redirect_to_certification': True
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
odoo.define('website_slides_survey.certification_upload_toast', function (require) {
|
||||
'use strict';
|
||||
|
||||
var publicWidget = require('web.public.widget');
|
||||
|
||||
var sessionStorage = window.sessionStorage;
|
||||
var core = require('web.core');
|
||||
var _t = core._t;
|
||||
|
||||
|
||||
publicWidget.registry.CertificationUploadToast = publicWidget.Widget.extend({
|
||||
selector: '.o_wslides_survey_certification_upload_toast',
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments).then(function () {
|
||||
var url = sessionStorage.getItem("survey_certification_url");
|
||||
if (url) {
|
||||
self.displayNotification({
|
||||
type: 'info',
|
||||
title: _t('Certification created'),
|
||||
message: _.str.sprintf(
|
||||
_t('Follow this link to add questions to your certification. <a href="%s">Edit certification</a>'),
|
||||
url
|
||||
),
|
||||
sticky: true,
|
||||
});
|
||||
sessionStorage.removeItem("survey_certification_url");
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return publicWidget.registry.CertificationUploadToast;
|
||||
|
||||
});
|
||||
@@ -3,12 +3,34 @@ odoo.define('website_slides_survey.upload_modal', function (require) {
|
||||
|
||||
var core = require('web.core');
|
||||
var _t = core._t;
|
||||
var sessionStorage = window.sessionStorage;
|
||||
var SlidesUpload = require('website_slides.upload_modal');
|
||||
|
||||
/**
|
||||
* Management of the new 'certification' slide_type
|
||||
*/
|
||||
SlidesUpload.SlideUploadDialog.include({
|
||||
events: _.extend({}, SlidesUpload.SlideUploadDialog.prototype.events || {}, {
|
||||
'change input#certification_id': '_onChangeCertification'
|
||||
}),
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Will automatically set the title of the slide to the title of the chosen certification
|
||||
*/
|
||||
_onChangeCertification: function (ev) {
|
||||
if (ev.added && ev.added.text) {
|
||||
this.$("input#name").val(ev.added.text);
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Overridden to add the "certification" slide type
|
||||
*
|
||||
@@ -56,7 +78,7 @@ SlidesUpload.SlideUploadDialog.include({
|
||||
var result = this._super.apply(this, arguments);
|
||||
|
||||
var $certificationInput = this.$('#certification_id');
|
||||
if ($certificationInput.length !== 0){
|
||||
if ($certificationInput.length !== 0) {
|
||||
var $select2Container = $certificationInput
|
||||
.closest('.form-group')
|
||||
.find('.select2-container');
|
||||
@@ -76,15 +98,38 @@ SlidesUpload.SlideUploadDialog.include({
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_getSelect2DropdownValues: function (){
|
||||
_getSelect2DropdownValues: function () {
|
||||
var result = this._super.apply(this, arguments);
|
||||
|
||||
var certificateValue = this.$('#certification_id').select2('data');
|
||||
var survey = {};
|
||||
if (certificateValue) {
|
||||
result['survey_id'] = certificateValue.id;
|
||||
if (certificateValue.create) {
|
||||
survey.id = false;
|
||||
survey.title = certificateValue.text;
|
||||
} else {
|
||||
survey.id = certificateValue.id;
|
||||
}
|
||||
}
|
||||
result['survey'] = survey;
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Overridde to handle certification created on-the-fly: toaster will hold
|
||||
* survey edit url, need to put it in session to use it in CertificationUploadToast
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_onFormSubmitDone: function (data) {
|
||||
if (!data.error && data.redirect_to_certification) {
|
||||
sessionStorage.setItem("survey_certification_url", data.redirect_url);
|
||||
window.location.reload();
|
||||
} else {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
SlidesUpload.websiteSlidesUpload.include({
|
||||
|
||||
@@ -3,33 +3,28 @@
|
||||
<t t-name="website.slide.upload.modal.certification">
|
||||
<div>
|
||||
<form class="clearfix">
|
||||
<div class="form-group row">
|
||||
<label for="certification_id" class="col-form-label col-md-3">Certification</label>
|
||||
<div class="controls col-md-9">
|
||||
<input class="form-control" id="certification_id" required="required"/>
|
||||
<div class="row">
|
||||
<div class="col" id="o_wslides_js_slide_upload_left_column">
|
||||
<div class="form-group">
|
||||
<label for="certification_id" class="col-form-label col-md-3">Certification</label>
|
||||
<input class="form-control" id="certification_id" required="required"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="upload" class="col-form-label">Choose an Image</label>
|
||||
<input id="upload" class="form-control" data-prevent-onchange='true' name="file" accept="image/*" type="file" required="required"/>
|
||||
</div>
|
||||
<t t-call="website.slide.upload.modal.common"/>
|
||||
<canvas id="data_canvas" class="d-none"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<t t-call="website.slide.upload.modal.common"/>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-4">
|
||||
|
||||
<div id="o_wslides_js_slide_upload_preview_column" class="col-md-6 d-none">
|
||||
<div class="img-thumbnail">
|
||||
<div class="o_slide_preview">
|
||||
<img src="/website_slides/static/src/img/document.png" id="slide-image" title="Content Preview" alt="Content Preview" class="img-fluid"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<h5 class="list-group-item-heading">
|
||||
<label for="upload" class="col-form-label">Cover Image File</label>
|
||||
</h5>
|
||||
<input id="upload" name="file" class="form-control" accept="image/*" type="file" required="required" data-prevent-onchange="1"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<canvas id="data_canvas" class="d-none"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<xpath expr="//script[last()]" position="after">
|
||||
<script type="text/javascript" src="/website_slides_survey/static/src/js/slides_upload.js"/>
|
||||
<script type="text/javascript" src="/website_slides_survey/static/src/js/slides_course_fullscreen_player.js"/>
|
||||
<script type="text/javascript" src="/website_slides_survey/static/src/js/slides_certification_upload_toast.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
|
||||
@@ -32,5 +32,11 @@
|
||||
<attribute name="t-if">channel.can_upload and not slide.question_ids and slide.slide_type != 'certification'</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="course_slides_list_inherit_survey" inherit_id="website_slides.course_slides_list">
|
||||
<xpath expr="//div[hasclass('o_wslides_content_actions')]" position="inside">
|
||||
<div class="o_wslides_survey_certification_upload_toast"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user