diff options
Diffstat (limited to 'addons/website_event/static/src')
26 files changed, 1156 insertions, 0 deletions
diff --git a/addons/website_event/static/src/img/event_cover_0.jpg b/addons/website_event/static/src/img/event_cover_0.jpg Binary files differnew file mode 100644 index 00000000..c77c47f2 --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_0.jpg diff --git a/addons/website_event/static/src/img/event_cover_1.jpg b/addons/website_event/static/src/img/event_cover_1.jpg Binary files differnew file mode 100644 index 00000000..0dc8960e --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_1.jpg diff --git a/addons/website_event/static/src/img/event_cover_2.jpg b/addons/website_event/static/src/img/event_cover_2.jpg Binary files differnew file mode 100644 index 00000000..6fda12d4 --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_2.jpg diff --git a/addons/website_event/static/src/img/event_cover_3.jpg b/addons/website_event/static/src/img/event_cover_3.jpg Binary files differnew file mode 100644 index 00000000..4ccf99f2 --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_3.jpg diff --git a/addons/website_event/static/src/img/event_cover_4.jpg b/addons/website_event/static/src/img/event_cover_4.jpg Binary files differnew file mode 100644 index 00000000..157a101a --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_4.jpg diff --git a/addons/website_event/static/src/img/event_cover_5.jpg b/addons/website_event/static/src/img/event_cover_5.jpg Binary files differnew file mode 100644 index 00000000..89070a4f --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_5.jpg diff --git a/addons/website_event/static/src/img/event_cover_7.jpg b/addons/website_event/static/src/img/event_cover_7.jpg Binary files differnew file mode 100644 index 00000000..9914bdf2 --- /dev/null +++ b/addons/website_event/static/src/img/event_cover_7.jpg diff --git a/addons/website_event/static/src/img/event_past_0.jpg b/addons/website_event/static/src/img/event_past_0.jpg Binary files differnew file mode 100644 index 00000000..0c070fbe --- /dev/null +++ b/addons/website_event/static/src/img/event_past_0.jpg diff --git a/addons/website_event/static/src/img/event_training_0.jpg b/addons/website_event/static/src/img/event_training_0.jpg Binary files differnew file mode 100644 index 00000000..2a2897f8 --- /dev/null +++ b/addons/website_event/static/src/img/event_training_0.jpg diff --git a/addons/website_event/static/src/img/openerp_enterprise_of_the_year.png b/addons/website_event/static/src/img/openerp_enterprise_of_the_year.png Binary files differnew file mode 100644 index 00000000..71d8f5b5 --- /dev/null +++ b/addons/website_event/static/src/img/openerp_enterprise_of_the_year.png diff --git a/addons/website_event/static/src/img/snippets_thumbs/s_country_events.svg b/addons/website_event/static/src/img/snippets_thumbs/s_country_events.svg new file mode 100644 index 00000000..d8eb58a0 --- /dev/null +++ b/addons/website_event/static/src/img/snippets_thumbs/s_country_events.svg @@ -0,0 +1,52 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="82" height="60" viewBox="0 0 82 60"> + <defs> + <rect id="path-1" width="28" height="4" x="0" y="0"/> + <filter id="filter-2" width="103.6%" height="150%" x="-1.8%" y="-12.5%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0"/> + </filter> + <rect id="path-3" width="28" height="4" x="0" y="5"/> + <filter id="filter-4" width="103.6%" height="150%" x="-1.8%" y="-12.5%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0"/> + </filter> + <rect id="path-5" width="28" height="4" x="0" y="10"/> + <filter id="filter-6" width="103.6%" height="150%" x="-1.8%" y="-12.5%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0"/> + </filter> + <linearGradient id="linearGradient-7" x1="50%" x2="50%" y1="0%" y2="100%"> + <stop offset="0%" stop-color="#00A09D"/> + <stop offset="100%" stop-color="#00E2FF"/> + </linearGradient> + <path id="path-8" d="M7.429 3.279L9.72 5.571l-4.15 4.15-2.29-2.292 4.15-4.15zm-1.531 7.102l4.483-4.483a.446.446 0 0 0 .138-.327.446.446 0 0 0-.138-.326L7.755 2.619a.443.443 0 0 0-.326-.13.443.443 0 0 0-.327.13L2.62 7.102a.446.446 0 0 0-.138.327c0 .125.046.234.138.326l2.626 2.626c.087.087.196.13.326.13.131 0 .24-.043.327-.13zm6.45-4.621l-6.58 6.587a.893.893 0 0 1-.657.269.893.893 0 0 1-.657-.269l-.914-.914c.271-.27.406-.6.406-.987 0-.386-.135-.715-.406-.986-.27-.271-.6-.406-.986-.406-.387 0-.716.135-.987.406L.66 8.546a.893.893 0 0 1-.268-.657c0-.259.09-.477.268-.656L7.24.66a.893.893 0 0 1 .656-.268c.26 0 .478.09.657.268l.907.907c-.271.27-.406.6-.406.987 0 .386.135.715.406.986.27.271.6.406.986.406.387 0 .716-.135.987-.406l.914.907a.893.893 0 0 1 .269.657c0 .258-.09.477-.269.656z"/> + </defs> + <g fill="none" fill-rule="evenodd" class="snippets_thumbs"> + <g class="s_country_events"> + <rect width="82" height="60" class="bg"/> + <g class="group" transform="translate(18 23)"> + <g class="group_2" transform="translate(18)"> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-2)" xlink:href="#path-1"/> + <use fill="#FFF" fill-opacity=".95" xlink:href="#path-1"/> + </g> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-4)" xlink:href="#path-3"/> + <use fill="#FFF" fill-opacity=".95" xlink:href="#path-3"/> + </g> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-6)" xlink:href="#path-5"/> + <use fill="#FFF" fill-opacity=".95" xlink:href="#path-5"/> + </g> + </g> + <mask id="mask-9" fill="#fff"> + <use xlink:href="#path-8"/> + </mask> + <use fill="url(#linearGradient-7)" class="ticket" xlink:href="#path-8"/> + </g> + </g> + </g> +</svg> diff --git a/addons/website_event/static/src/img/snippets_thumbs/s_speaker_bio.svg b/addons/website_event/static/src/img/snippets_thumbs/s_speaker_bio.svg new file mode 100644 index 00000000..7bc92057 --- /dev/null +++ b/addons/website_event/static/src/img/snippets_thumbs/s_speaker_bio.svg @@ -0,0 +1,62 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="82" height="60" viewBox="0 0 82 60"> + <defs> + <rect id="path-1" width="28" height="2" x="0" y="0"/> + <filter id="filter-2" width="103.6%" height="200%" x="-1.8%" y="-25%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0"/> + </filter> + <rect id="path-3" width="21" height="1" x="0" y="5"/> + <filter id="filter-4" width="104.8%" height="300%" x="-2.4%" y="-50%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.0995137675 0"/> + </filter> + <rect id="path-5" width="24" height="1" x="0" y="8"/> + <filter id="filter-6" width="104.2%" height="300%" x="-2.1%" y="-50%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.0995137675 0"/> + </filter> + <rect id="path-7" width="17" height="1" x="0" y="11"/> + <filter id="filter-8" width="105.9%" height="300%" x="-2.9%" y="-50%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feComposite in="shadowOffsetOuter1" in2="SourceAlpha" operator="out" result="shadowOffsetOuter1"/> + <feColorMatrix in="shadowOffsetOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.0995137675 0"/> + </filter> + <linearGradient id="linearGradient-9" x1="50%" x2="50%" y1="0%" y2="100%"> + <stop offset="0%" stop-color="#00A09D"/> + <stop offset="100%" stop-color="#00E2FF"/> + </linearGradient> + <path id="path-10" d="M9.758 10.149c0 .527-.15.98-.453 1.357-.302.377-.666.565-1.092.565H2.018c-.426 0-.79-.188-1.092-.565-.302-.378-.453-.83-.453-1.357 0-.411.02-.8.061-1.164.041-.365.118-.733.229-1.103.111-.37.253-.687.424-.95a2.03 2.03 0 0 1 .682-.646c.283-.167.608-.25.976-.25.633.619 1.39.928 2.27.928.88 0 1.638-.31 2.271-.928.368 0 .693.083.976.25.283.167.51.382.682.646.171.263.313.58.424.95.111.37.188.738.229 1.103.04.365.061.753.061 1.164zM7.901 3.714c0 .77-.272 1.426-.816 1.97-.544.544-1.2.816-1.97.816a2.684 2.684 0 0 1-1.97-.816 2.684 2.684 0 0 1-.815-1.97c0-.769.272-1.425.816-1.97A2.684 2.684 0 0 1 5.116.93c.768 0 1.425.272 1.97.816.543.544.815 1.2.815 1.97z"/> + </defs> + <g fill="none" fill-rule="evenodd" class="snippets_thumbs"> + <g class="s_speaker_bio"> + <rect width="82" height="60" class="bg"/> + <g class="group" transform="translate(21 24)"> + <g class="group_2" transform="translate(13 1)"> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-2)" xlink:href="#path-1"/> + <use fill="#FFF" fill-opacity=".95" xlink:href="#path-1"/> + </g> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-4)" xlink:href="#path-3"/> + <use fill="#FFF" fill-opacity=".348" xlink:href="#path-3"/> + </g> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-6)" xlink:href="#path-5"/> + <use fill="#FFF" fill-opacity=".348" xlink:href="#path-5"/> + </g> + <g class="rectangle"> + <use fill="#000" filter="url(#filter-8)" xlink:href="#path-7"/> + <use fill="#FFF" fill-opacity=".348" xlink:href="#path-7"/> + </g> + </g> + <mask id="mask-11" fill="#fff"> + <use xlink:href="#path-10"/> + </mask> + <use fill="url(#linearGradient-9)" class="user" xlink:href="#path-10"/> + </g> + </g> + </g> +</svg> diff --git a/addons/website_event/static/src/img/speaker.png b/addons/website_event/static/src/img/speaker.png Binary files differnew file mode 100644 index 00000000..b1921736 --- /dev/null +++ b/addons/website_event/static/src/img/speaker.png diff --git a/addons/website_event/static/src/img/training.jpg b/addons/website_event/static/src/img/training.jpg Binary files differnew file mode 100644 index 00000000..05ab1082 --- /dev/null +++ b/addons/website_event/static/src/img/training.jpg diff --git a/addons/website_event/static/src/js/display_timer_widget.js b/addons/website_event/static/src/js/display_timer_widget.js new file mode 100644 index 00000000..5f612736 --- /dev/null +++ b/addons/website_event/static/src/js/display_timer_widget.js @@ -0,0 +1,111 @@ +odoo.define('website_event.display_timer_widget', function (require) { +'use strict'; + +var core = require('web.core'); +var _t = core._t; +var publicWidget = require('web.public.widget'); + +publicWidget.registry.displayTimerWidget = publicWidget.Widget.extend({ + selector: '.o_display_timer', + + /** + * This widget allows to display a dom element at the end of a certain time laps. + * There are 2 timers available: + * - The main-timer: display the DOM element (using the displayClass) at the end of this timer. + * - The pre-timer: additional timer to display the main-timer. This pre-timer can be invisible or visible, + * depending of the startCountdownDisplay option. Once the pre-timer is over, + the main-timer is displayed. + * @override + */ + start: function () { + var self = this; + return this._super.apply(this, arguments).then(function () { + self.options = self.$target.data(); + self.preCountdownDisplay = self.options["preCountdownDisplay"]; + self.preCountdownTime = self.options["preCountdownTime"]; + self.preCountdownText = self.options["preCountdownText"]; + + self.mainCountdownTime = self.options["mainCountdownTime"]; + self.mainCountdownText = self.options["mainCountdownText"]; + self.mainCountdownDisplay = self.options["mainCountdownDisplay"]; + + self.displayClass = self.options["displayClass"]; + + if (self.preCountdownDisplay) { + $(self.$el).parent().removeClass('d-none'); + } + + self._checkTimer(); + self.interval = setInterval(function () { self._checkTimer(); }, 1000); + }); + }, + + /** + * This method removes 1 second to the current timer (pre-timer or main-timer) + * and call the method to update the DOM, unless main-timer is over. In that last case, + * the DOM element to show is displayed. + * + * @private + */ + _checkTimer: function () { + var now = new Date(); + + var remainingPreSeconds = this.preCountdownTime - (now.getTime()/1000); + if (remainingPreSeconds <= 1) { + this.$('.o_countdown_text').text(this.mainCountdownText); + if (this.mainCountdownDisplay) { + $(this.$el).parent().removeClass('d-none'); + } + var remainingMainSeconds = this.mainCountdownTime - (now.getTime()/1000); + if (remainingMainSeconds <= 1) { + clearInterval(this.interval); + $(this.displayClass).removeClass('d-none'); + $(this.$el).parent().addClass('d-none'); + } else { + this._updateCountdown(remainingMainSeconds); + } + } else { + this._updateCountdown(remainingPreSeconds); + } + }, + + /** + * This method update the DOM to display the remaining time. + * from seconds, the method extract the number of days, hours, minutes and seconds and + * override the different DOM elements values. + * + * @private + */ + _updateCountdown: function (remainingTime) { + var remainingSeconds = remainingTime; + var days = Math.floor(remainingSeconds / 86400); + + remainingSeconds = remainingSeconds % 86400; + var hours = Math.floor(remainingSeconds / 3600); + + remainingSeconds = remainingSeconds % 3600; + var minutes = Math.floor(remainingSeconds / 60); + + remainingSeconds = Math.floor(remainingSeconds % 60); + + this.$("span.o_timer_days").text(days); + this.$("span.o_timer_hours").text(this._zeroPad(hours, 2)); + this.$("span.o_timer_minutes").text(this._zeroPad(minutes, 2)); + this.$("span.o_timer_seconds").text(this._zeroPad(remainingSeconds, 2)); + }, + + /** + * Small tool to add leading zéros to the given number, in function of the needed number of leading zéros. + * + * @private + */ + _zeroPad: function (num, places) { + var zero = places - num.toString().length + 1; + return new Array(+(zero > 0 && zero)).join("0") + num; + }, + +}); + +return publicWidget.registry.countdownWidget; + +}); diff --git a/addons/website_event/static/src/js/register_toaster_widget.js b/addons/website_event/static/src/js/register_toaster_widget.js new file mode 100644 index 00000000..891f6155 --- /dev/null +++ b/addons/website_event/static/src/js/register_toaster_widget.js @@ -0,0 +1,31 @@ +odoo.define('website_event.register_toaster_widget', function (require) { +'use strict'; + +let core = require('web.core'); +let _t = core._t; +let publicWidget = require('web.public.widget'); + +publicWidget.registry.RegisterToasterWidget = publicWidget.Widget.extend({ + selector: '.o_wevent_register_toaster', + + /** + * This widget allows to display a toast message on the page. + * + * @override + */ + start: function () { + const message = this.$el.data('message'); + if (message && message.length) { + this.displayNotification({ + title: _t("Register"), + message: message, + type: 'info' + }); + } + return this._super.apply(this, arguments); + }, +}); + +return publicWidget.registry.RegisterToasterWidget; + +}); diff --git a/addons/website_event/static/src/js/tours/event_tour.js b/addons/website_event/static/src/js/tours/event_tour.js new file mode 100644 index 00000000..421146c1 --- /dev/null +++ b/addons/website_event/static/src/js/tours/event_tour.js @@ -0,0 +1,61 @@ +odoo.define('website_event.event_steps', function (require) { +"use strict"; + +var core = require('web.core'); +var _t = core._t; + +var EventAdditionalTourSteps = require('event.event_steps'); + +EventAdditionalTourSteps.include({ + + init: function() { + this._super.apply(this, arguments); + }, + + _get_website_event_steps: function () { + this._super.apply(this, arguments); + return [{ + trigger: '.o_event_form_view button[name="is_published"]', + content: _t("Use this <b>shortcut</b> to easily access your event web page."), + position: 'bottom', + }, { + trigger: 'li#edit-page-menu a', + extra_trigger: '.o_wevent_event', + content: _t("With the Edit button, you can <b>customize</b> the web page visitors will see when registering."), + position: 'bottom', + }, { + trigger: 'div[name="Image - Text"] .oe_snippet_thumbnail', + extra_trigger: '.o_wevent_event', + content: _t("<b>Drag and Drop</b> this snippet below the event title."), + position: 'bottom', + run: 'drag_and_drop #o_wevent_event_main_col', + }, { + trigger: 'button[data-action="save"]', + extra_trigger: '.o_wevent_event', + content: _t("Don't forget to click <b>save</b> when you're done."), + position: 'bottom', + }, { + trigger: 'label.js_publish_btn', + extra_trigger: '.o_wevent_event', + content: _t("Looking great! Let's now <b>publish</b> this page so that it becomes <b>visible</b> on your website!"), + position: 'bottom', + }, { + trigger: 'a.css_edit_dynamic', + extra_trigger: '.js_publish_management[data-object="event.event"] .js_publish_btn .css_unpublish:visible', + content: _t("Want to change your event configuration? Let's go back to the event form."), + position: 'bottom', + run: function (actions) { + actions.click('div.dropdown-menu a#edit-in-backend'); + }, + }, { + trigger: 'a#edit-in-backend', + extra_trigger: '.o_wevent_event', + content: _t("This shortcut will bring you right back to the event form."), + position: 'bottom' + }]; + } +}); + +return EventAdditionalTourSteps; + +}); diff --git a/addons/website_event/static/src/js/tours/website_event.js b/addons/website_event/static/src/js/tours/website_event.js new file mode 100644 index 00000000..b07c83a3 --- /dev/null +++ b/addons/website_event/static/src/js/tours/website_event.js @@ -0,0 +1,49 @@ +odoo.define("website_event.tour", function (require) { + "use strict"; + + var core = require("web.core"); + var tour = require("web_tour.tour"); + + var _t = core._t; + + tour.register("event", { + url: "/", + }, [{ + content: _t("Click here to add new content to your website."), + trigger: '#new-content-menu > a', + position: 'bottom', + }, { + trigger: "a[data-action=new_event]", + content: _t("Click here to create a new event."), + position: "bottom", + }, { + trigger: '.modal-dialog #editor_new_event input[type=text]', + content: _t("Create a name for your new event and click <em>\"Continue\"</em>. e.g: Technical Training"), + position: "left", + }, { + trigger: '.modal-footer button.btn-primary.btn-continue', + extra_trigger: '#editor_new_event input[type=text][value!=""]', + content: _t("Click <em>Continue</em> to create the event."), + position: "right", + }, { + trigger: "#snippet_structure .oe_snippet:eq(2) .oe_snippet_thumbnail", + content: _t("Drag this block and drop it in your page."), + position: "bottom", + run: "drag_and_drop", + }, { + trigger: "button[data-action=save]", + content: _t("Once you click on save, your event is updated."), + position: "bottom", + extra_trigger: ".o_dirty", + }, { + trigger: ".js_publish_management .js_publish_btn", + extra_trigger: "body:not(.editor_enable)", + content: _t("Click to publish your event."), + position: "top", + }, { + trigger: ".css_edit_dynamic", + extra_trigger: ".js_publish_management .js_publish_btn .css_unpublish:visible", + content: _t("Click here to customize your event further."), + position: "bottom", + }]); +}); diff --git a/addons/website_event/static/src/js/website_event.editor.js b/addons/website_event/static/src/js/website_event.editor.js new file mode 100644 index 00000000..48f3a995 --- /dev/null +++ b/addons/website_event/static/src/js/website_event.editor.js @@ -0,0 +1,49 @@ +odoo.define('website_event.editor', function (require) { +"use strict"; + +var core = require('web.core'); +var wUtils = require('website.utils'); +var WebsiteNewMenu = require('website.newMenu'); + +var _t = core._t; + +WebsiteNewMenu.include({ + actions: _.extend({}, WebsiteNewMenu.prototype.actions || {}, { + new_event: '_createNewEvent', + }), + + //-------------------------------------------------------------------------- + // Actions + //-------------------------------------------------------------------------- + + /** + * Asks the user information about a new event to create, then creates it + * and redirects the user to this new event. + * + * @private + * @returns {Promise} Unresolved if there is a redirection + */ + _createNewEvent: function () { + var self = this; + return wUtils.prompt({ + id: "editor_new_event", + window_title: _t("New Event"), + input: _t("Event Name"), + }).then(function (result) { + var eventName = result.val; + if (!eventName) { + return; + } + return self._rpc({ + route: '/event/add_event', + params: { + event_name: eventName, + }, + }).then(function (url) { + window.location.href = url; + return new Promise(function () {}); + }); + }); + }, +}); +}); diff --git a/addons/website_event/static/src/js/website_event.js b/addons/website_event/static/src/js/website_event.js new file mode 100644 index 00000000..11990e97 --- /dev/null +++ b/addons/website_event/static/src/js/website_event.js @@ -0,0 +1,93 @@ +odoo.define('website_event.website_event', function (require) { + +var ajax = require('web.ajax'); +var core = require('web.core'); +var Widget = require('web.Widget'); +var publicWidget = require('web.public.widget'); + +var _t = core._t; + +// Catch registration form event, because of JS for attendee details +var EventRegistrationForm = Widget.extend({ + + /** + * @override + */ + start: function () { + var self = this; + var res = this._super.apply(this.arguments).then(function () { + $('#registration_form .a-submit') + .off('click') + .click(function (ev) { + self.on_click(ev); + }); + }); + return res; + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {Event} ev + */ + on_click: function (ev) { + ev.preventDefault(); + ev.stopPropagation(); + var $form = $(ev.currentTarget).closest('form'); + var $button = $(ev.currentTarget).closest('[type="submit"]'); + var post = {}; + $('#registration_form table').siblings('.alert').remove(); + $('#registration_form select').each(function () { + post[$(this).attr('name')] = $(this).val(); + }); + var tickets_ordered = _.some(_.map(post, function (value, key) { return parseInt(value); })); + if (!tickets_ordered) { + $('<div class="alert alert-info"/>') + .text(_t('Please select at least one ticket.')) + .insertAfter('#registration_form table'); + return new Promise(function () {}); + } else { + $button.attr('disabled', true); + return ajax.jsonRpc($form.attr('action'), 'call', post).then(function (modal) { + var $modal = $(modal); + $modal.modal({backdrop: 'static', keyboard: false}); + $modal.find('.modal-body > div').removeClass('container'); // retrocompatibility - REMOVE ME in master / saas-19 + $modal.appendTo('body').modal(); + $modal.on('click', '.js_goto_event', function () { + $modal.modal('hide'); + $button.prop('disabled', false); + }); + $modal.on('click', '.close', function () { + $button.prop('disabled', false); + }); + }); + } + }, +}); + +publicWidget.registry.EventRegistrationFormInstance = publicWidget.Widget.extend({ + selector: '#registration_form', + + /** + * @override + */ + start: function () { + var def = this._super.apply(this, arguments); + this.instance = new EventRegistrationForm(this); + return Promise.all([def, this.instance.attachTo(this.$el)]); + }, + /** + * @override + */ + destroy: function () { + this.instance.setElement(null); + this._super.apply(this, arguments); + this.instance.setElement(this.$el); + }, +}); + +return EventRegistrationForm; +}); diff --git a/addons/website_event/static/src/js/website_event_set_customize_options.js b/addons/website_event/static/src/js/website_event_set_customize_options.js new file mode 100644 index 00000000..a6d9f749 --- /dev/null +++ b/addons/website_event/static/src/js/website_event_set_customize_options.js @@ -0,0 +1,122 @@ +odoo.define('website_event.set_customize_options', function (require) { +"use strict"; + +var CustomizeMenu = require('website.customizeMenu'); +var publicWidget = require('web.public.widget'); + +var EventSpecificOptions = publicWidget.Widget.extend({ + template: 'website_event.customize_options', + xmlDependencies: ['/website_event/static/src/xml/customize_options.xml'], + events: { + 'change #display-website-menu': '_onDisplaySubmenuChange', + }, + + /** + * @override + */ + start: function () { + this.$submenuInput = this.$('#display-website-menu'); + this.modelName = this._getEventObject().model; + this.eventId = this._getEventObject().id; + this._initCheckbox(); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + _onDisplaySubmenuChange: function (ev) { + var checkboxValue = this.$submenuInput.is(':checked'); + this._toggleSubmenuDisplay(checkboxValue); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + _getCheckboxFields: function () { + return ['website_menu', 'website_url']; + }, + + _getCheckboxFieldMatch: function (checkboxField) { + if (checkboxField === 'website_menu') { + return this.$submenuInput; + } + }, + + _getEventObject: function() { + var repr = $('html').data('main-object'); + var m = repr.match(/(.+)\((\d+),(.*)\)/); + return { + model: m[1], + id: m[2] | 0, + }; + }, + + _initCheckbox: function () { + var self = this; + this._rpc({ + model: this.modelName, + method: 'read', + args: [ + [this.eventId], + this._getCheckboxFields() + ], + }).then((data) => { + self._initCheckboxCallback(data); + }); + }, + + _initCheckboxCallback: function (rpcData) { + if (rpcData[0]['website_menu']) { + var submenuInput = this._getCheckboxFieldMatch('website_menu'); + submenuInput.attr('checked', 'checked'); + } + this.eventUrl = rpcData[0]['website_url']; + }, + + _reloadEventPage: function () { + window.location = this.eventUrl; + }, + + _toggleSubmenuDisplay: function (val) { + var self = this; + this._rpc({ + model: this.modelName, + method: 'toggle_website_menu', + args: [[this.eventId], val], + }).then(function () { + self._reloadEventPage(); + }); + }, + +}); + +CustomizeMenu.include({ + _getEventObject: function() { + var repr = $('html').data('main-object'); + var m = repr.match(/(.+)\((\d+),(.*)\)/); + return { + model: m[1], + id: m[2] | 0, + }; + }, + + _loadCustomizeOptions: function () { + var self = this; + var def = this._super.apply(this, arguments); + return def.then(function () { + if (!self.__eventOptionsLoaded && self._getEventObject().model === 'event.event') { + self.__eventOptionsLoaded = true; + self.eventOptions = new EventSpecificOptions(self); + self.eventOptions.insertAfter(self.$el.find('.dropdown-divider:first()')); + } + }); + }, +}); + +return { + EventSpecificOptions: EventSpecificOptions, +}; + +}); diff --git a/addons/website_event/static/src/js/website_event_ticket_details.js b/addons/website_event/static/src/js/website_event_ticket_details.js new file mode 100644 index 00000000..8ad2e307 --- /dev/null +++ b/addons/website_event/static/src/js/website_event_ticket_details.js @@ -0,0 +1,55 @@ +odoo.define('website_event.ticket_details', function (require) { + var publicWidget = require('web.public.widget'); + + publicWidget.registry.ticketDetailsWidget = publicWidget.Widget.extend({ + selector: '.o_wevent_js_ticket_details', + events: { + 'click .o_wevent_registration_btn': '_onTicketDetailsClick', + 'change .custom-select': '_onTicketQuantityChange' + }, + start: function (){ + this.foldedByDefault = this.$el.data('foldedByDefault') === 1; + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + */ + _getTotalTicketCount: function (){ + var ticketCount = 0; + this.$('.custom-select').each(function (){ + ticketCount += parseInt($(this).val()); + }); + return ticketCount; + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {*} ev + */ + _onTicketDetailsClick: function (ev){ + ev.preventDefault(); + if (this.foldedByDefault){ + $(ev.currentTarget).toggleClass('btn-primary text-left pl-0'); + $(ev.currentTarget).siblings().toggleClass('d-none'); + this.$('.close').toggleClass('d-none'); + } + }, + /** + * @private + */ + _onTicketQuantityChange: function (){ + this.$('button.btn-primary').attr('disabled', this._getTotalTicketCount() === 0); + } + }); + +return publicWidget.registry.ticketDetailsWidget; +}); diff --git a/addons/website_event/static/src/js/website_geolocation.js b/addons/website_event/static/src/js/website_geolocation.js new file mode 100644 index 00000000..0c93dbbb --- /dev/null +++ b/addons/website_event/static/src/js/website_geolocation.js @@ -0,0 +1,41 @@ +odoo.define('website_event.geolocation', function (require) { +'use strict'; + +var publicWidget = require('web.public.widget'); + +publicWidget.registry.visitor = publicWidget.Widget.extend({ + selector: ".oe_country_events, .country_events", + disabledInEditableMode: false, + + /** + * @override + */ + start: function () { + var defs = [this._super.apply(this, arguments)]; + var self = this; + var $eventList = this.$('.country_events_list'); + this._originalContent = $eventList[0].outerHTML; + defs.push(this._rpc({route: '/event/get_country_event_list'}).then(function (data) { + if (data) { + self._$loadedContent = $(data); + + self._$loadedContent.attr('contentEditable', false); + self._$loadedContent.addClass('o_temp_auto_element'); + self._$loadedContent.attr('data-temp-auto-element-original-content', self._originalContent); + + $eventList.replaceWith(self._$loadedContent); + } + })); + return Promise.all(defs); + }, + /** + * @override + */ + destroy: function () { + this._super.apply(this, arguments); + if (this._$loadedContent) { + this._$loadedContent.replaceWith(this._originalContent); + } + }, +}); +}); diff --git a/addons/website_event/static/src/scss/website_event.scss b/addons/website_event/static/src/scss/website_event.scss new file mode 100644 index 00000000..4cb8bbb9 --- /dev/null +++ b/addons/website_event/static/src/scss/website_event.scss @@ -0,0 +1,254 @@ +.o_wevent_index_topbar_filters { + .dropdown-toggle { + border: $border-width solid gray('400'); + @include o-bg-color(gray('white'), $with-extras: false); + @include border-radius($dropdown-border-radius); + @include hover-focus { + border-color: theme-color('primary'); + color: theme-color('primary'); + text-decoration: none; + } + &:after { + margin-left: 1.2em; + } + .fa { + margin-right: .4em; + color: theme-color('primary'); + } + } + .dropdown-menu { + margin-top: $navbar-padding-y; + min-width: 12rem; + } + .dropdown-item { + &.active .badge { // Invert badge display when the item is active + background-color: color-yiq(theme-color('primary')); + color: theme-color('primary'); + } + } +} + +.o_wevent_social_link { + $o_link_size: 3em; + display: inline-flex; + align-items: center; + justify-content: center; + @include size($o_link_size); + margin: 0 ($spacer * .25) ($spacer * .5) ($spacer * .25); + line-height: $o_link_size; + background-color: gray('100'); + border: $border-width solid $border-color; + border-radius: 50%; + text-align: center; + @include hover-focus { + background-color: gray('300'); + } +} + +.o_wevent_badge { + padding: ($spacer * .5) $spacer; + border-radius: 10rem; + font-weight: $font-weight-normal; +} + +// Index +.o_wevent_index { + // Events List + .o_wevent_events_list { + header { + a { + transition: all .25s ease-in-out; + @include hover-focus { + transform: scale(1.05); + } + } + } + &.opt_event_list_cards_bg { + @if (color('body') == $o-portal-default-body-bg) { + @extend .bg-200; + } + } + .opt_events_list_columns { + header { + height: 200px; + } + } + .opt_events_list_rows { + @include media-breakpoint-down(sm) { + header { + height: 200px; + } + } + } + .o_wevent_badge_event { + @include o-position-absolute($top: 0, $left: 0); + @include border-left-radius(0); + padding: ($spacer * .5) $card-spacer-x; + transform: translateY(-50%); + } + .o_wevent_event_date { + top: $card-spacer-x; + right: $card-spacer-x; + display: flex; + flex-direction: column; + justify-content: center; + @include size(4rem); + border-radius: 50%; + text-align: center; + + .o_wevent_event_day { + font-size: 1.125rem; + font-weight: 300; + line-height: 1; + } + .o_wevent_event_month { + font-size: 0.75rem; + font-weight: $font-weight-bold; + text-transform: uppercase; + } + } + .o_wevent_participating, + .o_wevent_unpublished { + position: absolute; + bottom: 0; + width: 100%; + padding: $card-spacer-y $card-spacer-x; + text-align: right; + } + .card-title { + color: $body-color; + } + } + .o_wevent_sidebar_title { + margin: 0 0 ($spacer * 1.5) 0; + border-bottom: $border-width solid $border-color; + padding: 0 0 ($spacer * .5) 0; + font-weight: $font-weight-bold; + text-transform: uppercase; + } + .o_wevent_sidebar_block { + margin: 0 0 ($spacer * 2.5) 0; + } + .o_wevent_sidebar_figure { + position: relative; + + .figure-img { + margin-bottom: 0; + } + .figure-caption { + @include o-position-absolute($left: 0, $bottom: 0); + width: 100%; + padding: $spacer; + background-color: rgba($color: #000, $alpha: 0.5); + @include border-bottom-radius($border-radius); + color: #fff; + } + } + #o_wevent_index_main_col .form-inline { + width: 100%; + } +} + +.o_wevent_event { + // Multi-line event title, even in mobile mode + nav > div > a.navbar-brand { + text-overflow: revert; + white-space: normal; + overflow: hidden; + max-width: calc(100% - 80px); + } + + // Ensure menu labels are not split + #o_wevent_event_submenu { + li.nav-item { + white-space: nowrap; + } + } + + .o_wevent_event_title { + margin: 3rem 0; + + .o_wevent_event_name { + font-weight: $display4-weight; + line-height: $display-line-height; + @include font-size($display4-size); + } + .o_wevent_event_subtitle { + font-weight: $lead-font-weight; + @include font-size($lead-font-size); + } + } + + .o_wevent_registration_single { + .o_wevent_nowrap { + white-space: nowrap; + } + } + + .o_wevent_registration_btn { + flex: 0 0 100%; + + &.collapsed { + flex: 0 0 33%; + + .close { + display: none; + } + } + .close { + display: block; + } + &:not(.collapsed) { + box-shadow: none; + font-weight: $font-weight-bold; + text-transform: uppercase; + transition: none; + } + } + + .o_wevent_sidebar_title { + margin-bottom: $spacer; + opacity: .5; + text-transform: uppercase; + } + + .o_wevent_sidebar_block { + padding: $spacer * 3; + border-bottom: $border-width solid $border-color; + + &:last-child { + border-bottom: 0; + } + } +} + +.o_wevent_event { + .o_record_cover_container { + overflow: hidden; + z-index: 0; + + .o_record_cover_component { + z-index: -1; + } + &.o_record_has_cover { + .o_record_cover_image { + background-attachment: fixed; + + &::after { + content: ""; + display: block; + @include o-position-absolute(0,0,50%,0); + } + } + .o_wevent_event_title { + color: white; + } + } + } +} + +.modal-open { + > .modal-backdrop { + z-index: $zindex-dropdown - 1; + } +} diff --git a/addons/website_event/static/src/scss/website_event_templates.scss b/addons/website_event/static/src/scss/website_event_templates.scss new file mode 100644 index 00000000..49a9f8ae --- /dev/null +++ b/addons/website_event/static/src/scss/website_event_templates.scss @@ -0,0 +1,161 @@ +// Color tags according to assigned background color. + +.o_wevent_index, .o_wevent_event { + + // Simple colored tags according to assigned background color + @for $size from 1 through length($o-colors) { + .o_tag_color_#{$size - 1} { + @if $size == 1 { + & { + background-color: white; + color: nth($o-colors, $size); + box-shadow: inset 0 0 0 2px nth($o-colors, $size); + } + &::after { + background-color: nth($o-colors, $size); + } + } @else { + &, &::after { + background-color: nth($o-colors, $size); + color: $white; + } + } + } + } + + // Complex colored tags according to assigned background color with hover effect + @for $size from 1 through length($o-colors) { + .o_tag_color_hovered_#{$size - 1} { + $background-color: white; + // no color selected + @if $size == 1 { + & { + color: black; + background-color: $background-color; + box-shadow: inset 0 0 0 1px nth($o-colors, $size); + } + } @else { + $background-color: nth($o-colors, $size); + & { + color: white; + background-color: $background-color; + } + } + @at-root a#{&} { + &:hover { + background-color: darken($background-color, 20%); + } + } + } + } + + /* + * COMMON TO ALL ONLINE-* PAGES + */ + + .o_wevent_online { + // unpublished badge: put opacity to distinguish form other badges + .o_wevent_online_badge_unpublished{ + opacity: 0.4; + } + + &.o_wevent_online_bg { + @if (color('body') == $o-portal-default-body-bg) { + @extend .bg-100; + } + } + + // background color-based for new styling + .event_color_0 { + // bg-100 background but DO NOT extend bg-100 as it messes with text-muted colors + background-color: #F8F9FA; + } + .event_color_1 { + background-color: rgba(240, 96, 80, 0.2); + } + .event_color_2 { + background-color: rgba(244, 164, 96, 0.2); + } + .event_color_3 { + background-color: rgba(247, 205, 31, 0.2); + } + .event_color_4 { + background-color: rgba(108,193,237,0.2); + } + .event_color_5 { + background-color: rgba(129,73,104,0.2); + } + .event_color_6 { + background-color: rgba(235,126,127,0.2); + } + .event_color_7 { + background-color: rgba(44,131,151,0.2); + } + .event_color_8 { + background-color: rgba(71,85,119,0.2); + } + .event_color_9 { + background-color: rgba(214,20,95,0.2); + } + .event_color_10 { + background-color: rgba(48,195,129,0.2); + } + .event_color_11 { + background-color: rgba(147,101,184,0.2); + } + + .o_wevent_online_page_container { + // Widescreen mode + @include media-breakpoint-up(md) { + &:not(.container) { + padding-left: 0.5rem; + padding-right: 0.5rem; + } + } + + // Main panel + .o_wevent_online_page_main { + border: 1px solid $border-color; + + @include media-breakpoint-up(md) { + border-top-width: 0; + } + + .o_wevent_online_page_avatar { + min-width: 64px; + + img { + max-width: 96px; + } + } + } + + // Left panel + .o_wevent_online_page_aside { + + // Left panel: content display + .o_wevent_online_page_aside_content { + border: 1px solid $border-color; + + @include media-breakpoint-up(md) { + border-top-width: 0; + } + + li:not(.nav-item) { + border-bottom: 1px solid $border-color; + &:first-child { + border-top: 1px solid $border-color; + } + &:last-child { + border-bottom: 0px; + } + } + + .o_wevent_online_page_aside_collapse:not(.collapsed) { + transform: rotate(180deg); + } + } + } + } + } +} diff --git a/addons/website_event/static/src/xml/customize_options.xml b/addons/website_event/static/src/xml/customize_options.xml new file mode 100644 index 00000000..539a3ef0 --- /dev/null +++ b/addons/website_event/static/src/xml/customize_options.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<templates xml:space="preserve"> + + <t t-name="website_event.customize_options" id="event_options"> + <li class="dropdown-header">Event Specific</li> + <a href="#" name="display-website-menu" class="dropdown-item" role="menuitem"> + <label class="o_switch" for="display-website-menu"> + <input id="display-website-menu" type="checkbox"/> + <span/> + Event Sub-menu + </label> + </a> + </t> + +</templates> |
