diff options
Diffstat (limited to 'addons/website_slides/static')
15 files changed, 2693 insertions, 8 deletions
diff --git a/addons/website_slides/static/src/js/slides_category.js b/addons/website_slides/static/src/js/slides_category.js new file mode 100644 index 00000000000..d1d7efb7747 --- /dev/null +++ b/addons/website_slides/static/src/js/slides_category.js @@ -0,0 +1,148 @@ +odoo.define('website_slides.add.section', function (require) { + 'use strict'; + + var sAnimations = require('website.content.snippets.animation'); + var core = require('web.core'); + var Widget = require('web.Widget'); + + var _t = core._t; + + var SectionDialog = Widget.extend({ + template: 'website.slide.add.section', + events: { + 'hidden.bs.modal': 'destroy', + '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, channelID) { + this._super(el, channelID); + this.channel_id = parseInt(channelID, 10); + this.index_content = ''; + }, + /** + * @override + */ + start: function () { + this.$el.modal({ + backdrop: 'static' + }); + + return this._super.apply(this, arguments); + }, + _getValue: function () { + var canvas = this.$('#data_canvas')[0], + values = { + 'channel_id': this.channel_id || '', + 'url': this.$('#url').val(), + 'name': this.$('#section_name').val() + }; + 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; + + 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(); + this._rpc({ + route: '/slides/add_category', + params: 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'); + }, + + }); + + sAnimations.registry.websiteSlidesSection = sAnimations.Class.extend({ + selector: '.oe_slide_js_add_section', + xmlDependencies: ['/website_slides/static/src/xml/website_slides_upload.xml'], + read_events: { + 'click': '_onAddSectionClick', + }, + + /** + * @override + */ + start: function () { + // Automatically open the upload dialog if requested from query string + if ($.deparam.querystring().enable_slide_upload !== undefined) { + this._openDialog(this.$el.attr('channel_id')); + } + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + _openDialog: function (channelID) { + new SectionDialog(this, channelID).appendTo(document.body); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {Event} ev + */ + _onAddSectionClick: function (ev) { + console.log('test'); + this._openDialog($(ev.currentTarget).attr('channel_id')); + }, + }); + });
\ No newline at end of file diff --git a/addons/website_slides/static/src/js/slides_course_fullscreen_player.js b/addons/website_slides/static/src/js/slides_course_fullscreen_player.js new file mode 100644 index 00000000000..1da173a2f46 --- /dev/null +++ b/addons/website_slides/static/src/js/slides_course_fullscreen_player.js @@ -0,0 +1,427 @@ +var onYouTubeIframeAPIReady; + +odoo.define('website_slides.fullscreen', function (require) { + 'use strict'; + var sAnimations = require('website.content.snippets.animation'); + var Widget = require('web.Widget'); + var core = require('web.core'); + var QWeb = core.qweb; + + var tag = document.createElement('script'); + + var QuizWidget = require('website_slides.quiz'); + + tag.src = "https://www.youtube.com/iframe_api"; + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + + + var Fullscreen = Widget.extend({ + /** + * @override + * @param {Object} el + * @param {Object} data holding channelId and optionally upload and publish control parameters + */ + init: function(el, course_id,slide_id, user_id){ + this._super.apply(this,arguments); + this.courseID = parseInt(course_id, 10); + this.slideID = parseInt(slide_id, 10); + this.userID = parseInt(user_id, 10); + this.course = undefined; + this.slide = undefined; + this.slides = []; + this.nextSlide = undefined; + this.previousSlide = undefined; + this.url = undefined; + this.urlToSmallScreen = undefined; + this.activetab = undefined; + this.player = undefined; + this.goToQuiz = false; + this.answeredQuestions = []; + this.slideTitle = undefined; + }, + start: function(){ + var self = this; + this.url = window.location.pathname; + this.urlToSmallScreen = this.url.replace('/fullscreen',''); + this._getSlides(); + this._renderPlayer(); + this._bindListEvents(); + + $(document).keydown(this._onKeyDown.bind(this)); + return this._super.apply(this, arguments); + }, + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + /** + * @private + * Renders the player accordingly to the current slide + */ + _renderPlayer: function(){ + var self = this; + var embed_url; + if(self.slide.slide_type !== 'webpage' || self.slide.htmlContent){ + if((self.slide.slide_type == "quiz" || self.slide.hasQuiz) && !self.slide.quiz){ + self._fetchQuiz(); + } else { + embed_url = $(this.slide.embed_code).attr('src'); + if (self.slide.slide_type === "video"){ + embed_url = "https://" + embed_url + "&rel=0&autoplay=1&enablejsapi=1&origin=" + window.location.origin; + } + $('.o_wslides_fullscreen_player').html(QWeb.render('website.slides.fullscreen', { + slide: self.slide, + nextSlide: self.nextSlide, + questions: self.slide.quiz ? self.slide.quiz.questions: '', + reward: self.slide.quiz ? self.slide.quiz.nb_attempts < 3 ? self.slide.quiz.possible_rewards[self.slide.quiz.nb_attempts] : self.slide.quiz.possible_rewards[3]: self.slide.maxPoints, + embed_url: embed_url, + question_count: self.slide.quiz ? self.slide.quiz.questions.length : '', + letters: self.slide.quiz ? self.letters : '', + showMiniQuiz: self.goToQuiz + })); + if(self.slide.slide_type === "video"){ + self._renderYoutubeIframe(); + } + if(self.slide.slide_type == 'webpage'){ + self._renderWebpage(); + } + if((self.slide.slide_type == "presentation" || self.slide.slide_type == "document" || self.slide.slide_type == "infographic" || self.slide.slide_type == "webpage") && !self.slide.quiz){ + self._setSlideStateAsDone(); + } + if ((self.slide.quiz && self.slide.slide_type === "quiz") || self.goToQuiz){ + self._renderQuiz(); + } + } + } else { + self._fetchHtmlContent(); + } + self._renderTitle(); + }, + _renderYoutubeIframe: function(){ + var self = this; + /** + * Due to issues of synchronization between the youtube api script and the widget's instanciation. + */ + try{ + self._setupYoutubePlayer(); + } + catch { + onYouTubeIframeAPIReady = function(){ + var self = this; + self._setupYoutubePlayer(); + }.bind(this) + } + }, + _renderWebpage: function(){ + var self = this; + $(self.slide.htmlContent).appendTo('.o_wslides_fullscreen_webpage_content'); + }, + _renderQuiz: function(){ + var self = this; + var Quiz = new QuizWidget(this, self.slide); + Quiz.appendTo('.o_wslides_fullscreen_player'); + $('.next-slide').click(function(){ + self._goToNextSlide(); + }) + $('.back-to-video').click(function(){ + self.goToQuiz = false; + self._renderPlayer(); + }); + }, + _renderTitle: function(){ + var self = this; + $('.o_wslides_fullscreen_slide_title').empty().html(QWeb.render('website.course.fullscreen.title', { + slide: self.slide, + miniQuiz: self.goToQuiz + })); + }, + /** + * @private + * Links the youtube api to the iframe present in the template + */ + _setupYoutubePlayer: function(){ + var self = this; + self.player = new YT.Player('youtube-player', { + host: 'https://www.youtube.com', + playerVars: {'autoplay': 1, 'origin': window.location.origin}, + autoplay: 1, + events: { + 'onReady': self._onPlayerReady, + 'onStateChange': this._onPlayerStateChange.bind(self) + } + }); + }, + /** + * @param {*} event + * Specific method of the youtube api. + * Whenever the player starts playing, a setinterval is created. + * This setinterval is used to check te user's progress in the video. + * Once the user reaches a particular time in the video, the slide will be considered as completed if the video doesn't have a mini-quiz. + * This method also allows to automatically go to the next slide (or the quiz associated to the current video) once the video is over + */ + _onPlayerStateChange: function(event){ + var self = this; + var tid; + clearInterval(self.tid); + if (event.data == YT.PlayerState.PLAYING && !self.slide.done) { + self.tid = setInterval(function(){ + if(event.target.getCurrentTime){ + var currentTime = event.target.getCurrentTime(); + var totalTime = event.target.getDuration(); + if(totalTime && currentTime > totalTime - 30){ + clearInterval(self.tid); + if(!self.slide.hasQuiz && !self.slide.done){ + self.slide.done = true; + self._setSlideStateAsDone(); + } + } + } + }, 1000); + } + if(event.data == YT.PlayerState.ENDED){ + self.player = undefined; + self._goToNextSlide(); + } + }, + /** + * @private + * Creates slides objects from every slide-list-cells attributes + */ + _getSlides: function(){ + var self = this; + var slides = $('.o_wslides_fullscreen_sidebar_slide_tab'); + for(var i = 0; i < slides.length;i++){ + var slide = $(slides[i]); + self.slides.push({ + id: parseInt(slide.attr('slide_id'), 10), + name: slide.attr('slide_name'), + embed_code: slide.attr('slide_embed_code'), + slide_type: slide.attr('slide_type'), + done: slide.attr('done'), + hasQuiz: slide.attr('quiz'), + slug: slide.attr('slide_slug'), + htmlContent: undefined + }); + this._getActiveSlide(); + } + }, + /** + * @private + * @param {object} slide + * Fetch the quiz for a particular slide + */ + _fetchQuiz: function(){ + var self = this; + self._rpc({ + route:"/slide/quiz/get", + params: { + 'slide_id': self.slide.id + } + }).then(function(data){ + if(data){ + self.slide.quiz = data; + self._renderPlayer(); + } + }) + }, + _fetchHtmlContent: function(){ + var self = this; + self._rpc({ + route:"/slide/html_content/get", + params: { + 'slide_id': self.slide.id + } + }).then(function(data){ + self.slide.htmlContent = data.html_content; + self._renderPlayer(); + }) + }, + /** + * @private + * Once the completion conditions are filled, + * sends a json request to the backend to set the relation between the slide and the user as being completed + */ + _setSlideStateAsDone: function(){ + var self = this; + self._rpc({ + route: '/slides/set_completed', + params: { + slide_id: self.slide.id, + } + }).then(function(data){ + $('#check-'+self.slide.id).replaceWith($('<i class="check-done o_wslides_slide_completed fa fa-check-circle"></i>')) + self.slide.done = true; + clearInterval(self.tid); + self.channelCompletion = data.channel_completion; + self._updateProgressbar(); + }); + }, + _updateProgressbar: function(){ + var self = this; + var completion = self.channelCompletion <= 100 ? self.channelCompletion : 100; + $('.o_wslides_fullscreen_sidebar_progress_gauge').css('width', completion + "%" ); + $('.o_wslides_progress_percentage').text(completion); + }, + /** + * @private + * Creates an array of letters to be used in the quiz with a foreach + */ + _generateQuizLetters: function(){ + var letters = []; + for(var i = 65; i < 91; i++){ + letters.push(String.fromCharCode(i)); + } + return letters; + }, + _goToNextSlide: function(){ + var self = this; + clearInterval(self.tid); + self.player = undefined; + self.goToQuiz = self.slide.hasQuiz && !self.goToQuiz; + if(self.nextSlide && !self.goToQuiz){ + self.slide = self.nextSlide; + self.index++; + self._setActiveTab(); + self._renderPlayer(); + self._setPreviousAndNextSlides(); + self._updateUrl(); + history.pushState(null,'',self.url); + } + else if(self.nextSlide){ + self._renderPlayer(); + } + }, + _goToPreviousSlide: function(){ + var self = this; + clearInterval(self.tid); + self.goToQuiz = false; + self.player = undefined; + if(self.previousSlide){ + self.slide = self.previousSlide; + self.index--; + self._setActiveTab(); + self._renderPlayer(); + self._setPreviousAndNextSlides(); + self._updateUrl(); + history.pushState(null,'',self.url); + } + }, + _setPreviousAndNextSlides: function(){ + var self = this; + self.previousSlide = self.index > 0 ? self.slides[self.index-1] : undefined; + self.nextSlide = self.index < (self.slides.length - 1) ? self.slides[self.index+1] : undefined; + }, + /** + * Changes the url whenever the user changes slides. + * This allows the user to refresh the page and stay at the right video + */ + _updateUrl: function(){ + var self = this; + var url = window.location.pathname.split('/'); + url[url.length-1] = self.slide.slug; + url = url.join('/'); + self.url = url; + self.urlToSmallScreen = self.url; + self.url += "?fullscreen=1"; + $('.o_wslides_small_screen').attr('href', self.urlToSmallScreen); + }, + /** + * Whenever the user changes slide, change the active tab + */ + _setActiveTab: function(){ + var self = this; + self.activeTab.removeClass('active'); + $('li.active').removeClass('active'); + $('li[slide_id='+self.slide.id+']').addClass('active'); + self.activeTab = $('.o_wslides_fullscreen_sidebar_slide_tab[index="'+self.index+'"]') + self.activeTab.addClass('active'); + }, + /** + * The first time the user gets on the player, + * get the slide that is represented by the active tab in the sidebar + */ + _getActiveSlide: function(){ + var self = this; + self.activeTab = $('.o_wslides_fullscreen_sidebar_slide_tab.active'); + self.index = parseInt(self.activeTab.attr('index'), 10); + self.slide = self.slides[self.index]; + self._setPreviousAndNextSlides(); + }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + _onListCellClick: function(ev){ + var self = this; + clearInterval(self.tid); + self.player = undefined; + var target = $(ev.currentTarget); + self.goToQuiz = false; + if(target[0] !== self.activeTab[0]){ + self.activeTab.removeClass('active'); + target.addClass('active'); + self.index = parseInt(target.attr('index')); + self._getActiveSlide(); + self._renderPlayer(); + $('li.active').removeClass('active'); + $('li[slide_id='+self.slide.id+']').addClass('active'); + self._setPreviousAndNextSlides(); + self._updateUrl(); + history.pushState(null,'',self.url); + } + }, + _onMiniQuizClick: function(ev){ + var self = this; + self.index = parseInt($(ev.currentTarget).attr('index')); + self.slide = self.slides[self.index]; + self.goToQuiz = true; + self._setPreviousAndNextSlides(); + self._renderPlayer(); + self._setActiveTab(); + self._updateUrl(); + history.pushState(null,'' ,self.url); + }, + /** + * @private + * Binds events related to the list + */ + _bindListEvents: function(){ + var self = this; + $('.o_wslides_fullscreen_sidebar_slide_tab').each(function () { + $(this).click(self._onListCellClick.bind(self)); + }); + + $('.o_wslides_slide_quiz ').each(function(){ + $(this).click(self._onMiniQuizClick.bind(self)); + }) + }, + _onKeyDown: function(ev){ + var self = this; + switch(ev.key){ + case "ArrowRight": + self._goToNextSlide(); + break; + case "ArrowLeft": + self._goToPreviousSlide(); + break; + } + }, + }) + + sAnimations.registry.websiteSlidesFullscreenPlayer = Widget.extend({ + selector: '.oe_js_course_slide', + xmlDependencies: ['/website_slides/static/src/xml/website_slides_fullscreen.xml'], + init: function(el){ + this._super.apply(this, arguments); + }, + start: function(){ + this._super.apply(this, arguments); + var user_id = this.$el.attr('user_id'); + var course_id = this.$el.attr('course_id'); + var slide_id = this.$el.attr('slide_id'); + var fullscreen = new Fullscreen(this, course_id, slide_id, user_id); + fullscreen.appendTo(".oe_js_course_slide"); + } + }); + + return Fullscreen; +});
\ No newline at end of file diff --git a/addons/website_slides/static/src/js/slides_course_progress_bar.js b/addons/website_slides/static/src/js/slides_course_progress_bar.js new file mode 100644 index 00000000000..2412368018f --- /dev/null +++ b/addons/website_slides/static/src/js/slides_course_progress_bar.js @@ -0,0 +1,47 @@ +odoo.define('website_slides.progress.bar', function (require) { + + var sAnimations = require('website.content.snippets.animation'); + var Widget = require('web.Widget'); + + var ProgressBar = Widget.extend({ + + /** + * @override + * @param {Object} el + * @param {number} channel_id + */ + init: function (el, completion) { + this._super(el); + this.completion = completion; + }, + /** + * @override + */ + start: function () { + this._renderProgressBar(); + return this._super.apply(this, arguments); + }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + _renderProgressBar: function (ev) { + var self = this; + $('.oe_slide_js_progress_bar').css('width', (self.completion <= 100 ? self.completion : 100) + '%'); + }, + }); + + sAnimations.registry.websiteSlidesProgressBar = sAnimations.Class.extend({ + selector: '.oe_slide_js_progress_bar', + /** + * @override + */ + start: function () { + var completion = parseInt($('.oe_slide_js_progress_bar').attr('channel_completion')); + var progressBar = new ProgressBar(this, completion); + progressBar.appendTo(".oe_slide_js_progress_bar"); + return this._super.apply(this, arguments); + }, + }); + + return ProgressBar; + }); diff --git a/addons/website_slides/static/src/js/slides_course_quiz.js b/addons/website_slides/static/src/js/slides_course_quiz.js new file mode 100644 index 00000000000..f98d5b3ed8a --- /dev/null +++ b/addons/website_slides/static/src/js/slides_course_quiz.js @@ -0,0 +1,206 @@ +odoo.define('website_slides.quiz', function (require) { + 'use strict'; + var sAnimations = require('website.content.snippets.animation'); + var core = require('web.core'); + var Widget = require('web.Widget'); + + var QWeb = core.qweb; + + var Quiz= Widget.extend({ + /** + * @override + * @param {Object} el + * @param {Object} data holding all the slide elements needed for the quiz + * It will either come from the fullscreen widget or the sAnimation at the end of this file + */ + init: function(el, data){ + this.slide = data; + this.answeredQuestions = []; + this.fullscreen = el; + return this._super.apply(this,arguments); + }, + start: function(){ + var self = this; + self._bindQuizEvents(); + /** + * If the quiz is rendered by the server instead of the fullscreen widget, + * questions and their answers will have to be created manually from attributes + */ + if(self.slide.quiz.questions.length === 0){ + this._setQuestions(); + } + return this._super.apply(this, arguments); + }, + _renderSuccessModal: function(){ + var self =this; + $('.o_wslides_fullscreen_quiz').append(QWeb.render('website.course.quiz.success', { + data: data + })); + $('.submit-quiz').remove(); + $('.next-slide').css('display', 'inline-block'); + $('.next-slide').click(function(){ + self.fullscreen._goToNextSlide(); + }); + $('.o_wslides_quiz_success_modal_close').click(function(){ + $('.o_wslides_quiz_success_modal').remove(); + $('.o_wslides_quiz_modal_background').remove(); + }); + $(".o_wslides_quiz_modal_background").click(function(ev){ + $(ev.currentTarget).remove(); + $('.o_wslides_quiz_success_modal').remove(); + }); + }, + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + /** + * @private + * In case the quiz is rendered by the server and the data don't come from the fullscreen widget, + * questions and their answers will have to be set here by using attributes + */ + _setQuestions: function(){ + var self = this; + $('.o_wslides_quiz_question').each(function(){ + self.slide.quiz.questions.push({ + id: parseInt($(this).attr('id')), + title: $(this).attr('title'), + answers: [] + }); + }) + for(var i = 0; i < self.slide.quiz.questions.length; i++){ + self._setAnswersForQuestion(self.slide.quiz.questions[i]); + } + }, + _setAnswersForQuestion: function (question){ + var self = this; + $('.o_wslides_quiz_answer[question_id='+question.id+']').each(function (){ + question.answers.push({ + id: parseInt($(this).attr('id')), + text: $(this).attr('text_value'), + is_correct: $(this).attr('is_correct') + }); + }); + }, + _updateProgressbar: function (){ + var self = this; + var completion = self.channelCompletion <= 100 ? self.channelCompletion : 100; + $('.o_wslides_fullscreen_sidebar_progress_gauge').css('width', completion + "%" ); + $('.o_wslides_progress_percentage').text(completion); + }, + _bindQuizEvents: function (){ + var self = this; + if (!self.slide.done){ + $('.o_wslides_quiz_answer').each(function(){ + $(this).click(self._onAnswerClick.bind(self)); + }); + } + $('.submit-quiz').click(self._onSubmitQuiz.bind(self)); + }, + _highlightAnswers: function (answers){ + var self = this; + self.answeredQuestions = []; + for (var i = 0; i < answers.goodAnswers.length; i++){ + $('#answer'+ answers.goodAnswers[i] +'').addClass('o_wslides_quiz_good_answer'); + $('#answer'+ answers.goodAnswers[i] +' .o_wslides_quiz_radio_box span').replaceWith($('<i class="fa fa-check-circle"></i>')); + var questionID =$('#answer'+ answers.goodAnswers[i] +' .o_wslides_quiz_radio_box input').attr('question_id'); + self.answeredQuestions.push(questionID); + $('.o_wslides_quiz_answer[question_id='+questionID+']:not(.o_wslides_quiz_good_answer)').addClass('o_wslides_quiz_ignored_answer'); + $('.o_wslides_quiz_answer[question_id='+questionID+']').each(function(){ + $(this).unbind('click') + }); + $('input[question_id='+questionID+']').each(function(){ + $(this).prop('disabled',true); + }); + } + for (i = 0; i < answers.badAnswers.length; i++){ + $('#answer'+ answers.badAnswers[i]).removeClass('o_wslides_quiz_good_answer') + .addClass('o_wslides_quiz_bad_answer') + .unbind('click'); + $('#answer'+ answers.badAnswers[i] +' .o_wslides_quiz_radio_box span').replaceWith($('<i class="fa fa-times "></i>')); + $('#answer'+ answers.badAnswers[i] +' .o_wslides_quiz_radio_box input').prop('checked', false); + } + }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + _onAnswerClick: function (ev){ + var self = this; + var target = $(ev.currentTarget); + if ((self.answeredQuestions.indexOf(target.attr('question_id'))) === -1){ + var id = target.attr('id'); + var question_id = target.attr('question_id'); + $('.o_wslides_quiz_answer[question_id='+question_id+']').removeClass('o_wslides_quiz_good_answer'); + $('#'+id+' input[type=radio]').prop('checked', true); + } + }, + _onSubmitQuiz: function (){ + var self = this; + var inputs = $('input[type=radio]:checked'); + var values = []; + for (var i = 0; i < inputs.length; i++){ + values.push(parseInt($(inputs[i]).val())); + } + if (values.length === self.slide.quiz.questions.length){ + $('.quiz-danger').remove(); + self._rpc({ + route: "/slide/quiz/submit", + params: { + slide_id: self.slide.id, + answer_ids: values, + quiz_id: self.slide.quiz_id + } + }).then(function(data){ + self._highlightAnswers(data); + self.slide.quiz.nb_attempts = data.attempts_count; + if (data.passed){ + self.channelCompletion = data.channel_completion; + self._updateProgressbar(); + $('#check-'+self.slide.id).replaceWith($('<i class="check-done o_wslides_slide_completed fa fa-check-circle"></i>')); + self.slide.done = true; + self._renderSuccessModal(); + } + else { + $('#quiz-points').text(self.slide.quiz.nb_attempts < 3 ? self.slide.quiz.possible_rewards[self.slide.quiz.nb_attempts] : self.slide.quiz.possible_rewards[self.slide.quiz.possible_rewards.length-1]); + } + }); + } else { + $('.o_wslides_fullscreen_player').append($('<p class="quiz-danger text-danger mt-1">All questions must be answered !</p>')); + } + }, +}); + + sAnimations.registry.websiteSlidesQuizNoFullscreen = Widget.extend({ + selector: '.o_w_slides_quiz_no_fullscreen', + xmlDependencies: ['/website_slides/static/src/xml/website_slides_fullscreen.xml'], + init: function (el){ + this._super.apply(this, arguments); + }, + start: function (){ + this._super.apply(this, arguments); + var slideID = parseInt(this.$el.attr('slide_id'),10); + var slideDone = this.$el.attr('slide_done'); + var nbAttempts = parseInt(this.$el.attr('nb_attempts'), 10); + var firstAttemptReward = this.$el.attr('first_reward'); + var secondAttemptReward = this.$el.attr('second_reward'); + var thirdAttemptReward = this.$el.attr('third_reward'); + var fourthAttemptReward = this.$el.attr('fourth_reward'); + var possibleRewards = [firstAttemptReward,secondAttemptReward,thirdAttemptReward,fourthAttemptReward] + var data = { + id: slideID, + done: slideDone, + quiz: { + questions: [], + nb_attempts: nbAttempts, + possible_rewards: possibleRewards, + reward: nbAttempts < possibleRewards.length ? possibleRewards[nbAttempts] : possibleRewards[possibleRewards.length-1] + } + } + if(!slideDone){ + var NewQuiz = new Quiz(this, data); + NewQuiz.appendTo(".o_w_slides_quiz_no_fullscreen"); + } + } + }); + + return Quiz; +});
\ No newline at end of file diff --git a/addons/website_slides/static/src/js/slides_course_sidebar_list.js b/addons/website_slides/static/src/js/slides_course_sidebar_list.js new file mode 100644 index 00000000000..11b61d4e5ec --- /dev/null +++ b/addons/website_slides/static/src/js/slides_course_sidebar_list.js @@ -0,0 +1,34 @@ +odoo.define('website_slides.sidebar', function (require) { + 'use strict'; + var sAnimations = require('website.content.snippets.animation'); + var core = require('web.core'); + var Widget = require('web.Widget'); + + var SideBar = Widget.extend({ + init: function (el){ + this._super.apply(this,arguments); + }, + start: function (){ + $('.o_wslides_fullscreen_toggle_sidebar').click(function (ev){ + ev.preventDefault(); + $(ev.currentTarget).toggleClass('active'); + $('.o_wslides_fullscreen_sidebar').toggleClass('o_wslides_fullscreen_sidebar_hidden'); + $('.o_wslides_fullscreen_player').toggleClass('o_wslides_fullscreen_player_no_sidebar') + }) + return this._super.apply(this, arguments); + }, + }); + + sAnimations.registry.websiteSlidesSidebarList = Widget.extend({ + selector: '.o_wslides_fullscreen_toggle_sidebar', + // xmlDependencies: ['/website_slides/static/src/xml/website_slides.xml'], + init: function (el){ + this._super.apply(this, arguments); + }, + start: function (){ + this._super.apply(this, arguments); + var sideBar = new SideBar(this); + sideBar.appendTo(".oe_js_side_bar_list"); + } + }); +});
\ No newline at end of file diff --git a/addons/website_slides/static/src/js/slides_course_slides_list.js b/addons/website_slides/static/src/js/slides_course_slides_list.js new file mode 100644 index 00000000000..bf634f542e3 --- /dev/null +++ b/addons/website_slides/static/src/js/slides_course_slides_list.js @@ -0,0 +1,251 @@ +odoo.define('website_slides.slideslist', function (require) { + 'use strict'; + var sAnimations = require('website.content.snippets.animation'); + var Widget = require('web.Widget'); + + var SlideUpload = require('website_slides.upload_modal'); + + var List = Widget.extend({ + init: function (el){ + this._super.apply(this,arguments); + this.draggedElement = undefined; + this.dropTarget = undefined; + this.slideCount = undefined; + this.slides = []; + this.categories = []; + }, + start: function (){ + this._super.apply(this,arguments); + this.slideCount = $('li.content-slide').length; + //Change links HREF to fullscreen mode for SEO + var links = $(".link-to-slide"); + for (var i = 0; i < links.length; i++){ + $(links[i]).attr('href', $(links[i]).attr('href') + "?fullscreen=1"); + } + this._bindEvents(); + }, + _bindEvents: function (){ + var self = this; + $('.slide-draggable').each(function (){ + self._addSlideDragAndDropHandlers($(this)); + }); + $('.section-draggable').each(function (){ + self._addSectionDragAndDropHandlers($(this)); + }); + $('.course-section').each(function (){ + self._addDropSlideOnSectionHandler($(this)); + }); + }, + _unbind: function (className){ + $("."+className).each(function (){ + $(this).unbind(); + }); + }, + _unbindAll: function (){ + this._unbind('slide-draggable'); + this._unbind('section-draggable'); + this._unbind('course-section'); + }, + _getSlides: function (){ + var self = this; + var slides = $('li.content-slide'); + for(var i = 0; i < slides.length;i++){ + var slide = $(slides[i]); + self.slides.push({ + id: parseInt(slide.attr('slide_id')), + category_id: parseInt(slide.attr('category_id')), + sequence: i + }); + } + }, + _getCategories: function (){ + var self = this; + self.categories = []; + var categories = $('.course-section'); + for (var i = 0; i < categories.length;i++){ + var category = $(categories[i]); + self.categories.push(parseInt(category.attr('category_id'))); + } + }, + _addDropSlideOnSectionHandler: function (target){ + var self = this; + target.on('drop', function (ev){ + if (ev.preventDefault){ + ev.preventDefault(); + } + self.dropTarget = $(ev.currentTarget); + self.draggedElement[0].parentNode.removeChild(self.draggedElement[0]); + $('ul[category_id='+target.attr('category_id')+']').append(self.draggedElement) + self._addSlideDragAndDropHandlers(self.draggedElement); + self._reorderSlides(); + }); + target.on('dragover', function (ev){ + if(ev.preventDefault){ + ev.preventDefault(); + } + }); + }, + _addSlideDragAndDropHandlers: function (target){ + var self = this; + target.on('dragstart', function (ev){ + $('.section-draggable').removeClass('hold') + self._unbind('section-draggable'); + ev.originalEvent.dataTransfer.effectAllowed = 'move'; + ev.originalEvent.dataTransfer.setData('text/html', this.outerHTML); + self.draggedElement = target; + self.draggedElement.addClass('hold'); + }); + target.on('dragover', function (ev){ + if ($(ev.currentTarget) !== self.draggedElement){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.addClass('slide-hovered'); + } + }); + target.on('dragleave', function (ev){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.removeClass('slide-hovered'); + }); + target.on('drop', function (ev){ + if (self.draggedElement.hasClass('slide-draggable') && target.hasClass('slide-draggable')){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.removeClass('slide-hovered'); + target.removeClass('hold'); + if (target !== self.draggedElement){ + self.dropTarget = $(ev.currentTarget); + self.draggedElement[0].parentNode.removeChild(self.draggedElement[0]); + var dropHTML = ev.originalEvent.dataTransfer.getData('text/html'); + target[0].insertAdjacentHTML('beforebegin',dropHTML); + self.draggedElement = $(target[0].previousSibling); + self._reorderSlides(); + } + self._unbindAll(); + self._bindEvents(); + } + }); + target.on('dragend', function (ev){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.removeClass('slide-hovered'); + target.removeClass('hold'); + }); + }, + _addSectionDragAndDropHandlers: function(target){ + var self = this; + target.on('dragstart', function (ev){ + self._unbind('slide-draggable'); + self._unbind('course-section'); + ev.originalEvent.dataTransfer.effectAllowed = 'move'; + ev.originalEvent.dataTransfer.setData('text/html', this.outerHTML); + self.draggedElement = target; + self.draggedElement.addClass('hold'); + }); + target.on('dragover', function (ev){ + if (target.hasClass('section-draggable') && self.draggedElement.hasClass('section-draggable')){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.addClass('slide-hovered'); + } + }); + target.on('dragleave', function (ev){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.removeClass('slide-hovered'); + }); + target.on('drop', function (ev){ + if(ev.preventDefault){ + ev.preventDefault(); + } + if(self.draggedElement.hasClass('section-draggable') && target.hasClass('section-draggable')){ + target.removeClass('slide-hovered'); + target.removeClass('hold'); + self.dropTarget = $(ev.currentTarget); + if(target !== self.draggedElement && $(ev.currentTarget).hasClass('section-draggable')){ + self.draggedElement[0].parentNode.removeChild(self.draggedElement[0]); + var dropHTML = ev.originalEvent.dataTransfer.getData('text/html'); + target[0].insertAdjacentHTML('beforebegin',dropHTML); + self.draggedElement = $(target[0].previousSibling); + self._reorderCategories(); + self._reorderSlides(); + self._rebindUploadButton(self.draggedElement.attr('category_id')); + } + self._unbindAll(); + self._bindEvents(); + } + }); + target.on('dragend', function (ev){ + if (ev.preventDefault){ + ev.preventDefault(); + } + target.removeClass('slide-hovered'); + target.removeClass('hold'); + }); + }, + _reorderCategories: function (){ + var self = this; + self._getCategories(); + self._rpc({ + route: '/web/dataset/resequence', + params: { + model: "slide.category", + ids: self.categories + } + }).then(function (){ + self._resetCategoriesIndex(); + }); + }, + _resetCategoriesIndex: function (){ + var categoriesIndexes = $('.section-index') + for (var i = 0; i < categoriesIndexes.length; i++){ + $(categoriesIndexes[i]).text(i+1) + } + }, + _reorderSlides: function(){ + var self = this; + // In case the slide was transfered to another section + if (self.draggedElement.hasClass('slide-draggable')){ + self.draggedElement.attr('category_id', parseInt(self.dropTarget.attr('category_id'))) + } + self.slides = []; + self._getSlides(); + self._rpc({ + route: "/slides/resequence_slides", + params: { + slides_data: self.slides + } + }).then(function(){ + }); + }, + _rebindUploadButton: function(categoryID){ + var self = this; + this.$('.oe_slide_js_upload[data-category-id='+categoryID+']').click(function(ev){ + ev.preventDefault(); + var data = $(ev.currentTarget).data(); + var dialog = new SlideUpload.SlideUploadDialog(self, data); + dialog.appendTo(document.body); + dialog.open(); + }) + } + }) + + sAnimations.registry.websiteSlidesCourseSlidesList = Widget.extend({ + selector: '.oe_js_course_slides_list', + xmlDependencies: ['/website_slides/static/src/xml/website_slides_upload.xml'], + init: function (el){ + this._super.apply(this, arguments); + }, + start: function (){ + this._super.apply(this, arguments); + var list = new List(this); + list.appendTo(".oe_js_course_slides_list"); + } + }); +});
\ No newline at end of file diff --git a/addons/website_slides/static/src/js/slides_delete_slide.js b/addons/website_slides/static/src/js/slides_delete_slide.js new file mode 100644 index 00000000000..e3eef38502d --- /dev/null +++ b/addons/website_slides/static/src/js/slides_delete_slide.js @@ -0,0 +1,88 @@ +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; + }); diff --git a/addons/website_slides/static/src/js/slides_upload.js b/addons/website_slides/static/src/js/slides_upload.js index 855b7e52932..7b0a2964bf8 100644 --- a/addons/website_slides/static/src/js/slides_upload.js +++ b/addons/website_slides/static/src/js/slides_upload.js @@ -30,6 +30,7 @@ var SlideUploadDialog = Dialog.extend({ this._setup(); this.channelID = parseInt(options.channelId, 10); + this.defaultCategoryID = parseInt(options.categoryId,10) this.canUpload = options.canUpload === 'True'; this.canPublish = options.canPublish === 'True'; @@ -198,6 +199,7 @@ var SlideUploadDialog = Dialog.extend({ */ _getSelect2DropdownValues: function (){ var result = {}; + var self = this; // tags var tagValues = []; _.each(this.$('#tag_ids').select2('data'), function (val) { @@ -211,11 +213,17 @@ var SlideUploadDialog = Dialog.extend({ result['tag_ids'] = tagValues; } // category - var categoryValue = this.$('#category_id').select2('data'); - if (categoryValue && categoryValue.create) { - result['category_id'] = [0, {'name': categoryValue.text}]; - } else if (categoryValue) { - result['category_id'] = [categoryValue.id]; + if(!self.defaultCategoryID){ + var categoryValue = this.$('#category_id').select2('data'); + if (categoryValue && categoryValue.create) { + result['category_id'] = [0, {'name': categoryValue.text}]; + } else if (categoryValue) { + result['category_id'] = [categoryValue.id]; + this.categoryID = categoryValue.id; + } + } else { + result['category_id'] = [self.defaultCategoryID]; + this.categoryID = self.defaultCategoryID; } return result; }, @@ -303,6 +311,25 @@ var SlideUploadDialog = Dialog.extend({ return values; }, + _reorderSlidesSequence: function(){ + var self = this; + var slidesElement = $('li.content-slide'); + var slides = []; + for(var i = 0; i < slidesElement.length;i++){ + slides.push({ + id: parseInt($(slidesElement[i]).attr('slide_id')), + category_id: parseInt($(slidesElement[i]).attr('category_id')), + sequence: i + }) + } + self._rpc({ + route: '/slides/resequence_slides', + params: { + slides_data: slides + } + }).then(function(){ + }) + }, /** * Init the data relative to the support slide type to upload * @@ -325,6 +352,11 @@ var SlideUploadDialog = Dialog.extend({ label: _t('Video'), template: 'website.slide.upload.modal.video', }, + quiz: { + icon: 'fa-question-circle', + label: _t('Quiz'), + template: 'website.slide.upload.quiz' + } }; }, /** @@ -472,12 +504,11 @@ var SlideUploadDialog = Dialog.extend({ _onChangeSlideUrl: function (ev) { var self = this; var url = $(ev.target).val(); - this._alertRemove(); this.isValidUrl = false; this.set('can_submit_form', false); this._fetchUrlPreview(url).then(function (data) { - this.set('can_submit_form', true); + self.set('can_submit_form', true); if (data.error) { self._alertDisplay(data.error); } else { @@ -508,6 +539,12 @@ var SlideUploadDialog = Dialog.extend({ self.set('state', oldType); self._alertDisplay(data.error); } else { + //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) + self._reorderSlidesSequence(); + } window.location = data.url; } }); diff --git a/addons/website_slides/static/src/js/website_slides.editor.js b/addons/website_slides/static/src/js/website_slides.editor.js index 40513e785e2..72a18bb93ee 100644 --- a/addons/website_slides/static/src/js/website_slides.editor.js +++ b/addons/website_slides/static/src/js/website_slides.editor.js @@ -5,6 +5,7 @@ var core = require('web.core'); var Dialog = require('web.Dialog'); var QWeb = core.qweb; var WebsiteNewMenu = require('website.newMenu'); +var wUtils = require('website.utils'); var _t = core._t; diff --git a/addons/website_slides/static/src/scss/slide_course.scss b/addons/website_slides/static/src/scss/slide_course.scss new file mode 100644 index 00000000000..38179498415 --- /dev/null +++ b/addons/website_slides/static/src/scss/slide_course.scss @@ -0,0 +1,536 @@ + +.banner{ + position: absolute; + top: 0; + left: 0; + height: 20%; + background-color: $primary; + width: 256px; + opacity: 0; + color: #fff; + transition: all .3s ease-out; + z-index: 2; + visibility: hidden; + display: flex; + justify-content: space-around; + align-items: center; + margin-left: 15px; +} + +.banner a { + font-size: 1.5rem; + text-align: center; + padding: 20px; +} + +.banner a:hover{ + cursor: pointer; +} + +.fill { + display: flex; + justify-content: center; + align-items: center; + overflow: hidden +} +.fill img { + flex-shrink: 0; + min-width: 100%; + min-height: 100% +} + +.main_image{ + position: relative +} +.main_image:hover{ + .banner{ + opacity: 1; + visibility: visible; + } + +} + +.course-content { + padding: 0; + + ul { + list-style: none; + padding: 0 + } +} + +.course-section { + margin: 0; + background-color: #ddd; + display: flex; + list-style: none; + font-size: 1.05rem; + border-bottom: 1px solid #ccc +} + +.content-type { + width: 30%; +} + +.content-type:hover{ + cursor: pointer; +} + +.course-progress-bar{ + height: 10px; + width: 80%; + box-sizing: border-box; + border-radius: 5px; + background-color: rgba(0,0,0,.2); + overflow: hidden; + + .progress-gauge{ + height: 100%; + width: 0; + background-color: $primary; + + transition: all .8s ease-out; + } +} + +.course-rating{ + color:$primary; +} +.course-banner{ + border-bottom: 1px solid $primary; +} + +.content-tab{ + .active { + + border: none; + border-bottom: 1px solid $secondary; + } +} + +.content-tab a:hover{ + border:none; + border-bottom: 1px solid $secondary; +} + +.content-container{ + border:none; +} + +.content-slide:nth-child(odd){ + background-color: #f6f6f6; +} + +.content-slide:nth-child(even){ + background-color: #f9f9f9; +} + +.content-slide-controls { + i:hover{ + color: $primary !important; + cursor: pointer; + } +} + +.viewer-container { + display: flex; + align-items: stretch; + height: 500px; + width: 100%; + background-color: #ccc; + justify-content: flex-start; +} + + + +.slide-infos { + margin-top: 1rem; + display: flex; + justify-content: space-between; + align-items: start; +} + +.oe_js_player { + +} + +.slide-deactivated { + pointer-events: none; +} + +.slide-draggable { + user-select: none; + -khtml-user-drag: element; + -webkit-user-drag: element; +} + +.slide-hovered{ + margin-top: 10px; +} + +.section-draggable { + user-select: none; + -khtml-user-drag: element; + -webkit-user-drag: element; +} + +.hold{ + border: solid #ccc 4px; +} + + +.fullscreen { + position: absolute; + top: 0; + right: 0; + width: 100%; + z-index: 1000; + height: 100%; + margin: 0; + padding: 0; +} + + +.sidebar-list{ + position: fixed; + top: 46px; + bottom: 0; + left: 0; + width: 300px; + z-index: 2000; +} + + + +.sidebar-list-visible { + left: 50px; +} + +.show-list { + position: absolute; + top: 15%; + left: 50px; + font-size: 2rem; + z-index: 10000; + color: #a0a0a0; + border: 2px solid #ccc; + border-radius: 10px; + padding: 5px 10px; +} + +.hover-background { + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 3000; +} + +.hover-background:hover { + opacity: 1; +} + + +.show-list:hover { + cursor: pointer; +} + +.change-small-screen { + font-size: 1.5rem; + z-index: 10000; + color: #a0a0a0; +} + +.change-small-screen:hover { + cursor: pointer; + border-color: $primary; + color: $primary; +} + +.sidebar-header { + padding: 10px 15px; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 1.5rem; + border-bottom: 1px solid #ccc; + height: 80px; + + a { + color: black; + } + + a:hover { + color: $primary; + } + + i:hover{ + color: $primary; + } +} + +.close-list:hover { + cursor: pointer; +} + +.fullscreen-btn{ + font-size: 2rem; + display: inline-block; + a { + text-decoration: none; + color: $text-muted; + } +} + +.fullscreen-btn:hover{ + cursor: pointer; + + a { + color: $primary; + } +} + +.sidebar-fullscreen { + position: relative; + top: 0; + left: 0; + bottom: 0; + height: auto; + transform: translateX(-100%); + width: 0; +} + +.fullscreen-question-container{ + background-color: #fff; + width: 100%; + padding-top: 20px; + overflow: auto; +} + +.fullscreen-question{ + border-radius: 10px; + padding: 10px 20px; + box-shadow: 0px 1px 4px rgba(0,0,0,.5); + margin-top: 50px; +} + +.question-title { + font-size: 1.5rem; +} + +.buttons-container{ + width: 80%; + display: flex; + justify-content: space-between; + flex-direction: row-reverse; + margin-top: 40px; +} + +// .slide-resources { +// border-bottom: 1px solid #ccc; +// } + +.slide-resource { + padding: 5px 50px; + width: 100%; + i{ + margin-right: 10px; + } +} + +.list-cell { +} + + +.quiz-header{ + border-bottom: 2px solid #CBCBCB; + margin-bottom: 50px; +} + +.quiz-header-container{ + display: flex; + justify-content: space-between; + align-items: center; + + h1 { + width: 80%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} + +.quiz-good-answer{ + background-color: #C7EAE9; +} + +.quiz-bad-answer{ + background-color: #FEBEBE; +} + +.quiz-bad-answer label.radio-box, +.quiz-good-answer label.radio-box{ + border: none; +} + +.quiz-bad-answer label.radio-box i{ + background-color: #FD0606; + color: white; + height: 100%; + width: 100%; + font-size: 1.5rem; + display: flex; + justify-content: center; + align-items: center; + padding: 50px; +} + +.quiz-ignored-answer { + color: $text-muted; +} + + +.quiz-good-answer label.radio-box input:checked + i{ + height: 100%; + width: 100%; + background-color: #fff; + display: flex; + justify-content: center; + align-items: center; + font-size: 2.4rem; + border: 10px solid $primary; + border-radius: 50px; +} + +.quiz-answer { + border-radius: 10px; + padding: 5px 10px; + transition: all .2s ease-in-out; + display: flex; + align-items: center; + margin-bottom: 5px; +} + +.quiz-answer:not(.quiz-good-answer,.quiz-bad-answer,.quiz-ignored-answer):hover{ + background-color: #E5E5E5; + cursor: pointer; +} + +label.radio-box{ + border: 2px solid #CBCBCB; + background-color: #fff; + width: 50px; + height: 50px; + display: inline-flex; + border-radius: 50%; + overflow: hidden; + justify-content: center; + align-items: center; + margin: 0; + margin-right: 20px; + font-size: 1.2rem; + outline: none; +} + +.quiz-answer:not(.quiz-good-answer,.quiz-bad-answer,.quiz-ignored-answer) label.radio-box:hover{ + cursor: pointer; +} + +label.radio-box input{ + display:none; + outline: none; + border: none; +} + + +label.radio-box span{ + color: inherit; + padding: 20px; +} + +label.radio-box input:checked + span{ + background-color: $primary; + color: #fff; +} + +label.radio-box input:checked{ + background-color: #C7EAE9; +} + +.quiz-question { + border-bottom: 2px solid #CBCBCB; + padding-bottom: 20px; + margin-bottom: 20px; +} + +.quiz-question-answers { + list-style: none; + margin: 0; + margin-top: 20px; + padding: 0; + font-size: 1rem; +} + +.submit-quiz { + margin-top: 20px; +} + + +.quiz-modal-background{ + position: absolute; + top: 0; + left: 0; + background-color: rgba(0,0,0,.5); + width: 100%; + height: 100%; +} + +.quiz-modal-container{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.quiz-modal{ + position: absolute; + width: 30%; + height: 500px; + background-color: #fff; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); + border-radius: 10px; + z-index: 2000; +} +.quiz-points-container{ + font-size: 1.2rem; +} + +.quiz-points { + background-color: #C4C4C4; + padding: 0 4px ; + border-radius: 10px; + color: #fff; +} + + +.quiz-points-won{ + background-color: $primary; +} + +.webpage-container{ + background-color: #fff; + width: 100%; +} + +.webpage-content { + background-color: #fff; + height: 100%; +} + + + + diff --git a/addons/website_slides/static/src/scss/slide_slide.scss b/addons/website_slides/static/src/scss/slide_slide.scss new file mode 100644 index 00000000000..d99aaea101a --- /dev/null +++ b/addons/website_slides/static/src/scss/slide_slide.scss @@ -0,0 +1,156 @@ +.slide-header { + background-color: #62495B; + height: 200px; +} + +.slide-header-container { + width: 1000px; + margin: 0 auto; + height: 100%; +} + +.slide-header-box{ + display: flex; + height: 100%; + width: 50%; + flex-direction: column; + justify-content: flex-end; + padding-bottom: 50px; + + a { + color: #fff; + font-size: 2.5rem; + text-decoration: none !important; + } +} + + +.slide-content-list { + position: absolute; + top: 140px; + left: 80px; + background-color: #fff; + height: 500px; + z-index: 200; +} + +.slide-list{ + background-color: #fff; + list-style: none; + height: 100%; + padding: 0; + overflow: auto; + border: 1px solid #ccc; + border-left: none; + box-sizing: border-box; + flex: 1; + + a { + text-decoration: none; + color: $text-muted; + } + + a .active{ + background-color: #eee !important; + } +} + +.slide-content-list-section{ + border-bottom: 1px solid #fff; + color: #9B9B9B; + text-transform: uppercase; + padding: 10px 15px; +} + +.slide-content-list-slide{ + color: #666666; + padding: 10px 15px; +} + +.slide-list-cell{ + word-wrap: none; + padding: 0.5rem 1rem;; + height: 40px; + box-sizing: border-box; + display: flex; + align-items: center; + text-decoration: none !important; +} + +.slide-list-cell:hover{ + background-color: #eee; + cursor: pointer; +} + +.slide-list-cell:active{ + background-color: #eee; + cursor: pointer; +} + + +.slide-content-list-header { + padding: 10px 15px; + font-size: 1.2rem; + background-color: #F7F7F7; + color: #6F6F6F; +} + +.slide-button { + color: #666; + text-decoration: none; + border:1px solid #B9B9B9; + padding: 5px 10px; + width: 50px; + text-align: center; + text-transform: uppercase; + margin: 0; + border-radius: 3px; +} + +.slide-button-fullscreen { + color: #666; + text-decoration: none; + border:1px solid #B9B9B9; + padding: 5px 10px; + text-align: center; + text-transform: uppercase; + margin: 0; + border-radius: 3px; +} + +.slide-button-done { + color: #fff; + text-transform: uppercase; + background-color: $primary; + text-decoration: none; + padding: 10px 15px; + width: 50px; + text-align: center; + border-radius: 3px; + margin: 0; +} + +.slide-title { + width: 60%; + display: flex; + align-items: center; + + h1 { + font-size: 1.5rem; + } + + .slide-points { + margin-left: 20px; + padding: 5px 10px; + background-color: #DC9D45; + border-radius: 10px; + color: #fff; + font-weight: bold; + } +} + +.slide-documentation-sidebar { + position: absolute; + top: 300px; + left: 30px; +}
\ No newline at end of file diff --git a/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss b/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss new file mode 100644 index 00000000000..de5493d2f7e --- /dev/null +++ b/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss @@ -0,0 +1,303 @@ +.o_wslides { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 2000; + + .o_wslides_slide_fullscreen_header { + align-items: center; + background-color: #313A44; + color: #AEB0B2; + display: flex; + height: 50px; + justify-content: space-between; + width: 100%; + + .o_wslides_fullscreen_slide_title { + height: 100%; + display: flex; + align-items: center; + padding: 0 20px; + color: #D5D7D9; + font-weight: bold; + + i.fa-flag-checkered{ + color: #D39B4B; + margin-right: 10px; + } + } + + div { + display: flex; + height: 100%; + + a { + align-items: center; + background-color: #1F242C; + color: inherit; + display: flex; + font-size: 0.8rem; + font-weight: bold; + height: 100%; + justify-content: center; + padding: 0 20px; + text-decoration: none !important; + text-transform: uppercase; + + i { + align-items: center; + display: flex; + height: 100%; + margin: 0; + margin-right: 5px; + } + } + + a:hover, + a.active{ + background-color: #313A44; + color: #fff; + } + } + } + + .o_wslides_fullscreen_container { + display: flex; + align-items: stretch; + height: 100%; + position: relative; + background-color: #313A44; + } + + .o_wslides_fullscreen_sidebar_hidden{ + transform: translateX(-100%); + } + + .o_wslides_fullscreen_sidebar{ + width: 400px; + min-width: 400px; + background-color: #313A44; + color: #fff; + transition: all .2s ease-in; + overflow: auto; + + a { + text-decoration: none !important; + color: inherit; + } + + ul { + margin: 0; + padding: 0; + list-style: none; + } + + li { + padding-left: 20px; + } + + .o_wslides_fullscreen_sidebar_header{ + height: 100px; + padding: 20px 0; + display: flex; + flex-direction: column; + + .o_wslides_slide_fullscreen_progress_box{ + display: flex; + align-items: center; + font-size: .9rem; + .o_wslides_fullscreen_sidebar_progressbar{ + height: 5px; + border-radius: 10px; + width: 70%; + background-color: rgba(0,0,0,.3); + margin-right: 40px; + overflow: hidden; + + } + + .o_wslides_fullscreen_sidebar_progress_gauge { + background-color: $primary; + height: 100%; + width: 0; + transition: all 1.5s ease-in; + } + + span { + color: #BABDC0; + } + + } + + a { + font-size: 1.5rem; + font-weight: bold; + } + + } + + .o_wslides_fullscreen_sidebar_section { + margin-bottom: 20px; + background-color: #283038; + padding: 10px 0; + + } + + .o_wslides_fullscreen_sidebar_section_tab { + color: #656B72; + font-size: .8rem; + text-transform: uppercase; + font-weight: bold; + padding: 5px 0 5px 15px; + } + + .o_wslides_fullscreen_sidebar_section_slides{ + padding: 0; + margin-bottom: 15px; + + + + li { + margin: 0; + padding: 0; + border-left: 2px solid transparent; + display: flex; + + a { + flex: 1; + } + } + + .o_wslides_top_line, + .o_wslides_bottom_line{ + width: 1px; + display: flex; + flex-grow: 1; + background-color: #787D82; + } + + li:first-child .o_wslides_top_line{ + background-color: transparent; + } + + li:last-child .o_wslides_bottom_line{ + background-color: transparent; + } + + li:hover, + li.active { + border-left: 2px solid $primary; + cursor: pointer; + background-color: #1D2228; + } + + .o_wslides_fullscreen_sidebar_slide_tab { + padding:5px 0 5px 15px; + font-size: .8rem; + color: #8A8F93; + font-weight: bold; + flex: 1; + + } + + .o_wslides_fullscreen_sidebar_slide_tab.active{ + color: #fff; + } + + .o_wslides_fullscreen_slide_tab_line{ + width: 15px; + padding: 0; + margin: 0; + margin-left: 10px; + display: flex; + flex-direction: column; + align-items: center; + + i { + z-index: 100; + padding: 0; + margin: 0; + } + + i.o_wslides_slide_completed{ + color: #00A04A; + border-radius: 50%; + overflow: hidden; + background-color: #fff; + height: 12px; + width: 12px; + display: flex; + justify-content: center; + align-items: center; + border: 1px solid #00A04A; + } + + .o_wslides_full_line{ + width: 1px; + height: 100%; + background-color: #787D82; + } + } + + .o_wslides_slide_link { + color: #098586; + font-size: .8rem; + margin-left: 15px; + flex: 1; + + i { + margin-right: 10px; + } + } + + .o_wslides_slide_quiz { + font-size: .8rem; + margin-left: 15px; + color: #8A8F93; + flex: 1; + i { + color: #D39B4B; + margin-right: 10px; + } + } + } + + + } + + .o_wslides_fullscreen_player { + display: flex; + align-items: stretch; + max-width: calc(100% - 400px); + height: 100%; + background-color: #283038; + transition: all .2s ease-in; + position: absolute; + top: 0; + right: 0; + height: 100%; + width: 80%; + + iframe { + height: 100%; + width: 100%; + } + } + + .o_wslides_fullscreen_webpage { + background-color: #fff; + width: 100%; + height: 100%; + overflow-y: scroll; + padding: 20px 0; + } + + .o_wslides_fullscreen_player_no_sidebar { + max-width: 100%; + width: 100%; + } + + +}
\ No newline at end of file diff --git a/addons/website_slides/static/src/scss/website_slides_quiz.scss b/addons/website_slides/static/src/scss/website_slides_quiz.scss new file mode 100644 index 00000000000..9fe4438ee57 --- /dev/null +++ b/addons/website_slides/static/src/scss/website_slides_quiz.scss @@ -0,0 +1,237 @@ + + .o_wslides_fullscreen_quiz { + background-color: #F6F6F6; + width: 100%; + height: 100%; + overflow: scroll; + overflow-x: hidden; + padding-bottom: 50px; + + } + + .o_wslides_quiz_question { + margin-top: 50px; + width: 100%; + .o_wslides_quiz_question_title { + font-size: 1.5rem; + margin-bottom: 20px; + .o_wslides_quiz_question_title_number { + color: #8C8C8C; + font-size: 1.3rem; + font-weight: bold; + } + + .o_wslides_quiz_question_title_text { + margin-left: 2px; + color: #2F2F2F; + } + } + + .o_wslides_quiz_question_answers{ + background-color: #fff; + list-style: none; + padding: 0; + + .o_wslides_quiz_answer { + padding: 10px 20px; + border-bottom: 1px solid #B6B6B6; + font-size: 1.2rem; + display: flex; + align-items: center; + + label.o_wslides_quiz_radio_box{ + background-color: #f6f6f6; + width: 35px; + height: 35px; + display: inline-flex; + border-radius: 50%; + overflow: hidden; + justify-content: center; + align-items: center; + margin: 0; + margin-right: 20px; + font-size: 1.2rem; + outline: none; + border: none; + padding: 0; + } + + label.o_wslides_quiz_radio_box input{ + display:none; + outline: none; + border: none; + } + + + label.o_wslides_quiz_radio_box span{ + width: 18px; + height: 18px; + margin: 0; + } + + label.o_wslides_quiz_radio_box input:checked + span{ + background-color: $primary; + border-radius: 50%; + overflow: hidden; + } + + label.o_wslides_quiz_radio_box input:checked{ + background-color: #C7EAE9; + } + } + + .o_wslides_quiz_answer:not(.o_wslides_quiz_good_answer,.o_wslides_quiz_bad_answer,.o_wslides_quiz_ignored_answer):hover { + cursor: pointer; + } + + .o_wslides_quiz_good_answer{ + border: 2px solid #28A745; + label.o_wslides_quiz_radio_box input:checked + i{ + height: 100%; + width: 100%; + background-color: #fff; + color: #28A745; + display: flex; + justify-content: center; + align-items: center; + font-size: 1.4rem; + border: 10px solid #28A745; + border-radius: 50px; + } + } + + .o_wslides_quiz_bad_answer{ + border: 2px solid #A94442; + + label.o_wslides_quiz_radio_box i{ + background-color: #A94442; + color: white; + height: 100%; + width: 100%; + font-size: 1rem; + display: flex; + justify-content: center; + align-items: center; + } + } + + + .quiz-ignored-answer { + color: $text-muted; + } + } + } + + .o_wslides_quiz_modal_background{ + position: absolute; + top: 0; + left: 0; + background-color: rgba(0,0,0,.2); + width: 100%; + height: 100%; + + } + + .o_wslides_quiz_success_modal { + display: flex; + position: absolute; + width: 40%; + max-width: 600px; + height: 450px; + background-color: #fff; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); + z-index: 2000; + } + + .o_wslides_quiz_success_modal_left_panel { + width: 50%; + background-color: #855B79; + + } + + .o_wslides_quiz_success_modal_right_panel{ + width: 50%; + display: flex; + flex-direction: column; + padding: 10px 20px 10px 50px; + position: relative; + + .o_wslides_quiz_success_modal_close { + position: absolute; + top: 10px; + right: 15px; + text-transform: uppercase; + color: #787878; + font-size: 1.2rem; + } + + .o_wslides_quiz_success_modal_close:hover{ + cursor: pointer; + } + + h1 { + color: #21272B; + font-weight: bold; + font-size: 2.3rem; + padding: 20px 0; + letter-spacing: 1px; + } + + .o_wslides_quiz_success_progress_bar{ + height: 10px; + width: 100%; + background-color: rgba(0,0,0,.1); + + .o_wslides_quiz_success_progress_gauge{ + width: 75%; + height: 100%; + background-color: #01ADAB; + } + } + + .o_wslides_quiz_success_progress_bounds{ + display: flex; + justify-content: space-between; + } + + .o_wslides_quiz_success_progress_bounds{ + font-weight: bold; + span:first-child { + color: #019F9D; + } + span:last-child{ + color: #787878; + } + } + + .o_wslides_quiz_success_reward { + height: 80px; + width: 100%; + border: 1px dashed #ccc; + margin-top: 70px; + } + + .o_wslides_quiz_success_button{ + flex: 1; + display: flex; + justify-content: flex-end; + align-items: flex-end; + + a { + color: #787878; + text-transform: uppercase; + background-color: #fff; + border-radius: 3px; + border: 1px solid #C4C4C4; + font-weight: bold; + padding: 5px 15px; + text-align: center; + } + + a:hover { + cursor: pointer; + } + } + }
\ No newline at end of file diff --git a/addons/website_slides/static/src/xml/website_slides_fullscreen.xml b/addons/website_slides/static/src/xml/website_slides_fullscreen.xml new file mode 100644 index 00000000000..a9aff0d2ec7 --- /dev/null +++ b/addons/website_slides/static/src/xml/website_slides_fullscreen.xml @@ -0,0 +1,111 @@ +<templates id="template" xml:space="preserve"> + <t t-name="website.slides.fullscreen"> + <div t-if="slide.slide_type == 'video' && !showMiniQuiz" class="player embed-responsive embed-responsive-16by9 embed-responsive-item"> + <iframe id="youtube-player" t-att-src="embed_url" allowFullScreen="true" frameborder="0" enablejsapi="1" autoplay="1" allow="autoplay"></iframe> + </div> + <div t-if="slide.slide_type in ['presentation', 'document'] && !showMiniQuiz" class="embed-responsive embed-responsive-4by3 embed-responsive-item "> + <iframe t-att-src="embed_url" class="o_wslides_iframe_viewer" allowFullScreen="true" height="315" width="420" frameborder="0"></iframe> + </div> + <div style="width:100%;height:100%;" t-if="slide.slide_type == 'infographic' && !showMiniQuiz"> + <img t-attf-src="/web/image/slide.slide/#{slide.id}/datas" class="img-fluid" style="width: 100%" alt="Slide image"/> + </div> + <div t-if="(slide.slide_type == 'quiz' || showMiniQuiz) && questions " class="o_wslides_fullscreen_quiz"> + <div> + <t t-call="website.slide.quiz"/> + <div class="container"> + <button t-if="!slide.done" class="btn btn-primary submit-quiz" >Check your answers</button> + <button t-if="embed_url" class="btn btn-primary back-to-video" >Watch again</button> + <button t-if="slide.done && nextSlide" class="btn btn-primary next-slide" >Continue</button> + </div> + </div> + </div> + <div t-if="slide.slide_type == 'webpage'" class="o_wslides_fullscreen_webpage"> + <div class="o_wslides_fullscreen_webpage_content container"/> + </div> + <div class="o_wslides_fullscreen_content"/> + </t> + + <t t-name="website.slide.quiz"> + <div class="container quiz-questions"> + <t t-set="i" t-value="1"/> + <t t-foreach="questions" t-as="question"> + <t t-set="j" t-value="0"/> + <div class="o_wslides_quiz_question"> + <div> + <div class="o_wslides_quiz_question_title"> + <span class="o_wslides_quiz_question_title_number"><span t-esc="i"/>. </span> + <span class="o_wslides_quiz_question_title_text" t-esc="question.title"/> + </div> + <ul class="o_wslides_quiz_question_answers"> + <t t-foreach="question.answers" t-as="answer"> + <li t-attf-id="answer#{answer.id}" t-att-question_id="question.id" t-att-class="(slide.done && answer.correct) ? 'o_wslides_quiz_answer o_wslides_quiz_good_answer': slide.done ? 'o_wslides_quiz_answer o_wslides_quiz_ignored_answer' : 'o_wslides_quiz_answer'"> + <label class="o_wslides_quiz_radio_box"> + <input t-att-answer_id="answer.id" type="radio" t-att-name="question.id" t-att-question_id="question.id" t-att-value="answer.id" t-att-checked="(slide.done && answer.correct) ? 'checked' : undefined" t-att-disabled="slide.done"/> + <span t-if="!(slide.done && answer.correct)"/> + <i t-if="(slide.done && answer.correct)" class="fa fa-check-circle"></i> + </label> + <span t-esc="answer.text"/> + </li> + <t t-set="j" t-value="j+1"/> + </t> + </ul> + </div> + </div> + <t t-set="i" t-value="i+1"/> + </t> + </div> + </t> + + <t t-name="website.course.player.infos"> + <div class="text-box"> + <h1><t t-esc="slide.name"/></h1> + <a t-att-href="url" class="oe_js_show_comments">Show comments</a> + </div> + <div> + <button class="oe_js_slide_full_screen btn btn-secondary">Full Screen</button> + <button t-att-current_slide_id="slide.id" class="btn btn-primary oe_js_slide_completed">Mark as completed<i class="fa fa-check-circle ml-1"></i></button> + </div> + </t> + + <t t-name="website.course.quiz.success"> + <div class="o_wslides_quiz_modal_background"> + </div> + <div class="o_wslides_quiz_success_modal"> + <div class="o_wslides_quiz_success_modal_left_panel"></div> + <div class="o_wslides_quiz_success_modal_right_panel"> + <div class="o_wslides_quiz_success_modal_close"><i class="fa fa-times"></i></div> + <h1>Amazing!</h1> + <div class="o_wslides_quiz_success_xp"> + <p>You gained <span t-esc="data.points"/> !</p> + <div class="o_wslides_quiz_success_progress_bar"> + <div class="o_wslides_quiz_success_progress_gauge"/> + </div> + <div class="o_wslides_quiz_success_progress_bounds"> + <span>600</span> + <span>1000</span> + </div> + </div> + <div class="o_wslides_quiz_success_reward"></div> + <div class="o_wslides_quiz_success_button"> + <a class="next-slide">Next ></a> + </div> + </div> + </div> + </t> + + <t t-name="website.course.fullscreen.title"> + <t t-if="!miniQuiz"> + <i t-if="slide.slide_type == 'document'" class="fa fa-file-pdf-o mr-2"></i> + <i t-if="slide.slide_type == 'infographic'" class="fa fa-file-picture-o mr-2"></i> + <i t-if="slide.slide_type == 'video'" class="fa fa-play-circle mr-2"></i> + <i t-if="slide.slide_type == 'link'" class="fa fa-file-code-o mr-2"></i> + <i t-if="slide.slide_type == 'webpage'" class="fa fa-file-text mr-2"></i> + <i t-if="slide.slide_type == 'quiz'" class="fa fa-question-circle mr-2 text"></i> + <span class="o_wslides_fullscreen_slide_title_span" t-esc="slide.name"/> + </t> + <t t-else=""> + <span><i class="fa fa-flag-checkered"></i>Quiz: <span t-esc="slide.name"/></span> + </t> + </t> + +</templates> diff --git a/addons/website_slides/static/src/xml/website_slides_upload.xml b/addons/website_slides/static/src/xml/website_slides_upload.xml index 966ff3362cd..d57923c561b 100644 --- a/addons/website_slides/static/src/xml/website_slides_upload.xml +++ b/addons/website_slides/static/src/xml/website_slides_upload.xml @@ -47,7 +47,7 @@ <input id="name" name="name" placeholder="Title" class="form-control" required="required"/> </div> </div> - <div class="form-group row"> + <div t-if="!widget.defaultCategoryID" class="form-group row"> <label for="category_id" class="col-form-label col-md-3">Category</label> <div class="controls col-md-9"> <input class="form-control" id="category_id"/> @@ -155,4 +155,107 @@ </div> </t> + <t t-name="website.slide.upload.quiz"> + <div> + <form class="clearfix"> + <canvas id="data_canvas" class="d-none"></canvas> + <t t-call="website.slide.upload.modal.common"/> + </form> + </div> + </t> + + <t t-name="website.slide.image.upload"> + <div role="dialog" class="modal" tabindex="-1"> + <div class="modal-dialog"> + <div class="modal-content"> + <header class="modal-header"> + <h3 class="modal-title">Upload Image</h3> + <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button> + </header> + <div class="oe_slides_upload_loading text-center" style="display:none" aria-hidden="true" role="status"> + <h4><i class='fa fa-spinner fa-spin'></i> Uploading Image... </h4> + </div> + <main class="modal-body"> + <form class="clearfix"> + <div class="form-group row"> + <div class="col-md-4"> + <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">Image File</label> + </h5> + <input id="upload" name="file" class="form-control" accept="image/*,application/pdf" type="file"/> + </li> + </ul> + </div> + </div> + <canvas id="data_canvas" style="display: none;"></canvas> + </form> + </main> + <footer class="modal-footer"> + <button type="button" data-loading-text="Loading..." data-published="true" class="btn btn-primary save">Upload</button> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Discard</button> + </footer> + </div> + </div> + </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"> + <div class="modal-content"> + <header class="modal-header"> + <h3 class="modal-title">Add a section</h3> + <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button> + </header> + <main class="modal-body modal-content"> + <form class="clearfix"> + <div class="form-group row"> + <label for="section_name" class="col-form-label col-md-3">Section name</label> + <div class="col-md-9"> + <input type="text" class="form-control" id="section_name"/> + </div> + </div> + <canvas id="data_canvas" style="display: none;"></canvas> + </form> + </main> + <footer class="modal-footer"> + <button type="button" data-loading-text="Loading..." data-published="true" class="btn btn-primary save">Add</button> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Discard</button> + </footer> + </div> + </div> + </div> + </t> + </templates> |
