summaryrefslogtreecommitdiff
path: root/muk_web_theme/static/src/js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 17:14:58 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 17:14:58 +0700
commit1ca3b3df3421961caec3b747a364071c80f5c7da (patch)
tree6778a1f0f3f9b4c6e26d6d87ccde16e24da6c9d6 /muk_web_theme/static/src/js
parentb57188be371d36d96caac4b8d65a40745c0e972c (diff)
initial commit
Diffstat (limited to 'muk_web_theme/static/src/js')
-rw-r--r--muk_web_theme/static/src/js/chrome/actions.js39
-rw-r--r--muk_web_theme/static/src/js/chrome/apps.js96
-rw-r--r--muk_web_theme/static/src/js/chrome/appsbar.js69
-rw-r--r--muk_web_theme/static/src/js/chrome/menu.js101
-rw-r--r--muk_web_theme/static/src/js/core/search.js134
-rw-r--r--muk_web_theme/static/src/js/fields/relational.js64
-rw-r--r--muk_web_theme/static/src/js/libs/scrollbar.js27
-rw-r--r--muk_web_theme/static/src/js/views/form_renderer.js50
-rw-r--r--muk_web_theme/static/src/js/views/form_view.js49
-rw-r--r--muk_web_theme/static/src/js/views/kanban_column.js42
-rw-r--r--muk_web_theme/static/src/js/views/kanban_quick_create.js44
-rw-r--r--muk_web_theme/static/src/js/views/kanban_renderer.js271
12 files changed, 986 insertions, 0 deletions
diff --git a/muk_web_theme/static/src/js/chrome/actions.js b/muk_web_theme/static/src/js/chrome/actions.js
new file mode 100644
index 0000000..37b3c45
--- /dev/null
+++ b/muk_web_theme/static/src/js/chrome/actions.js
@@ -0,0 +1,39 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.ActionManager', function (require) {
+"use strict";
+
+const ActionManager = require('web.ActionManager');
+
+ActionManager.include({
+ _handleAction(action) {
+ return this._super(...arguments).then($.proxy(this, '_hideMenusByAction', action));
+ },
+ _hideMenusByAction(action) {
+ const unique_selection = '[data-action-id=' + action.id + ']';
+ $(_.str.sprintf('.o_menu_apps .dropdown:has(.dropdown-menu.show:has(%s)) > a', unique_selection)).dropdown('toggle');
+ $(_.str.sprintf('.o_menu_sections.show:has(%s)', unique_selection)).collapse('hide');
+ },
+});
+
+});
diff --git a/muk_web_theme/static/src/js/chrome/apps.js b/muk_web_theme/static/src/js/chrome/apps.js
new file mode 100644
index 0000000..8423aa9
--- /dev/null
+++ b/muk_web_theme/static/src/js/chrome/apps.js
@@ -0,0 +1,96 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.AppsMenu', function (require) {
+"use strict";
+
+const core = require('web.core');
+const session = require("web.session");
+
+const AppsMenu = require("web.AppsMenu");
+const MenuSearchMixin = require("muk_web_theme.MenuSearchMixin");
+
+AppsMenu.include(_.extend({}, MenuSearchMixin, {
+ events: _.extend({}, AppsMenu.prototype.events, {
+ "keydown .mk_search_input input": "_onSearchResultsNavigate",
+ "click .mk_menu_search_result": "_onSearchResultChosen",
+ "shown.bs.dropdown": "_onMenuShown",
+ "hidden.bs.dropdown": "_onMenuHidden",
+ "hide.bs.dropdown": "_onMenuHide",
+ }),
+ init(parent, menuData) {
+ this._super(...arguments);
+ for (let n in this._apps) {
+ this._apps[n].web_icon_data = menuData.children[n].web_icon_data;
+ }
+ this._searchableMenus = _.reduce(
+ menuData.children, this._findNames.bind(this), {}
+ );
+ this._search_def = $.Deferred();
+ },
+ start() {
+ this._setBackgroundImage();
+ this.$search_container = this.$(".mk_search_container");
+ this.$search_input = this.$(".mk_search_input input");
+ this.$search_results = this.$(".mk_search_results");
+ return this._super(...arguments);
+ },
+ _onSearchResultChosen(event) {
+ event.preventDefault();
+ const $result = $(event.currentTarget),
+ text = $result.text().trim(),
+ data = $result.data(),
+ suffix = ~text.indexOf("/") ? "/" : "";
+ this.trigger_up("menu_clicked", {
+ action_id: data.actionId,
+ id: data.menuId,
+ previous_menu_id: data.parentId,
+ });
+ const app = _.find(this._apps, (_app) => text.indexOf(_app.name + suffix) === 0);
+ core.bus.trigger("change_menu_section", app.menuID);
+ },
+ _onAppsMenuItemClicked(event) {
+ this._super(...arguments);
+ event.preventDefault();
+ },
+ _setBackgroundImage() {
+ const url = session.url('/web/image', {
+ model: 'res.company',
+ id: session.company_id,
+ field: 'background_image',
+ });
+ this.$('.dropdown-menu').css({
+ "background-size": "cover",
+ "background-image": "url(" + url + ")"
+ });
+ if (session.muk_web_theme_background_blend_mode) {
+ this.$('.o-app-name').css({
+ "mix-blend-mode": session.muk_web_theme_background_blend_mode,
+ });
+ }
+ },
+ _onMenuHide(event) {
+ return $('.oe_wait').length === 0 && !this.$('input').is(':focus');
+ },
+}));
+
+}); \ No newline at end of file
diff --git a/muk_web_theme/static/src/js/chrome/appsbar.js b/muk_web_theme/static/src/js/chrome/appsbar.js
new file mode 100644
index 0000000..eaa91d3
--- /dev/null
+++ b/muk_web_theme/static/src/js/chrome/appsbar.js
@@ -0,0 +1,69 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.AppsBar', function (require) {
+"use strict";
+
+const Widget = require('web.Widget');
+
+const AppsBar = Widget.extend({
+ events: _.extend({}, Widget.prototype.events, {
+ 'click .nav-link': '_onAppsMenuItemClicked',
+ }),
+ template: "muk_web_theme.AppsBarMenu",
+ init(parent, menu) {
+ this._super(...arguments);
+ this._apps = _.map(menu.children, (app) => ({
+ actionID: parseInt(app.action.split(',')[1]),
+ web_icon_data: app.web_icon_data,
+ menuID: app.id,
+ name: app.name,
+ xmlID: app.xmlid,
+ })
+ );
+ },
+ getApps() {
+ return this._apps;
+ },
+ _openApp(app) {
+ this.trigger_up('app_clicked', {
+ action_id: app.actionID,
+ menu_id: app.menuID,
+ });
+ },
+ _onAppsMenuItemClicked(ev) {
+ const $target = $(ev.currentTarget);
+ const actionID = $target.data('action-id');
+ const menuID = $target.data('menu-id');
+ const app = _.findWhere(this._apps, {
+ actionID: actionID,
+ menuID: menuID
+ });
+ this._openApp(app);
+ ev.preventDefault();
+ $target.blur();
+ },
+});
+
+return AppsBar;
+
+}); \ No newline at end of file
diff --git a/muk_web_theme/static/src/js/chrome/menu.js b/muk_web_theme/static/src/js/chrome/menu.js
new file mode 100644
index 0000000..c1e522f
--- /dev/null
+++ b/muk_web_theme/static/src/js/chrome/menu.js
@@ -0,0 +1,101 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.Menu', function (require) {
+"use strict";
+
+const config = require("web.config");
+
+const Menu = require("web.Menu");
+const AppsBar = require("muk_web_theme.AppsBar");
+
+Menu.include({
+ events: _.extend({}, Menu.prototype.events, {
+ "click .o_menu_apps a[data-toggle=dropdown]": "_onAppsMenuClick",
+ "click .mk_menu_mobile_section": "_onMobileSectionClick",
+ "click .o_menu_sections [role=menuitem]": "_hideMobileSubmenus",
+ "show.bs.dropdown .o_menu_systray, .o_menu_apps": "_hideMobileSubmenus",
+ }),
+ menusTemplate: config.device.isMobile ?
+ 'muk_web_theme.MobileMenu.sections' : Menu.prototype.menusTemplate,
+ start() {
+ const res = this._super(...arguments);
+ this.$menu_toggle = this.$(".mk_menu_sections_toggle");
+ this.$menu_apps_sidebar = this.$('.mk_apps_sidebar_panel');
+ this._appsBar = new AppsBar(this, this.menu_data);
+ const appsBarProm = this._appsBar.appendTo(this.$menu_apps_sidebar);
+ appsBarProm.then(() => {
+ this.$menu_apps_sidebar.renderScrollBar();
+ });
+ if (config.device.isMobile) {
+ const menu_ids = _.keys(this.$menu_sections);
+ for (let i = 0; i < menu_ids.length; i++) {
+ const $section = this.$menu_sections[menu_ids[i]];
+ $section.on('click', 'a[data-menu]', this, (ev) => {
+ ev.stopPropagation();
+ });
+ }
+ }
+ return Promise.all([
+ res, appsBarProm
+ ]);
+ },
+ _hideMobileSubmenus() {
+ if (this.$menu_toggle.is(":visible") && $('.oe_wait').length === 0 &&
+ this.$section_placeholder.is(":visible")) {
+ this.$section_placeholder.collapse("hide");
+ }
+ },
+ _updateMenuBrand() {
+ return !config.device.isMobile ? this._super(...arguments) : null;
+ },
+ _onAppsMenuClick(event, checkedCanBeRemoved) {
+ const action_manager = this.getParent().action_manager;
+ const controller = action_manager.getCurrentController();
+ if (controller && !checkedCanBeRemoved) {
+ controller.widget.canBeRemoved().then(() => {
+ $(event.currentTarget).trigger('click', [true]);
+ $(event.currentTarget).off('.bs.dropdown');
+ });
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ },
+ _onMobileSectionClick(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ const $section = $(event.currentTarget);
+ if ($section.hasClass('show')) {
+ $section.removeClass('show');
+ $section.find('.show').removeClass('show');
+ $section.find('.fa-chevron-down').hide();
+ $section.find('.fa-chevron-right').show();
+ } else {
+ $section.addClass('show');
+ $section.find('ul:first').addClass('show');
+ $section.find('.fa-chevron-down:first').show();
+ $section.find('.fa-chevron-right:first').hide();
+ }
+ },
+});
+
+}); \ No newline at end of file
diff --git a/muk_web_theme/static/src/js/core/search.js b/muk_web_theme/static/src/js/core/search.js
new file mode 100644
index 0000000..0bf5996
--- /dev/null
+++ b/muk_web_theme/static/src/js/core/search.js
@@ -0,0 +1,134 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.MenuSearchMixin', function (require) {
+"use strict";
+
+const core = require('web.core');
+const config = require("web.config");
+
+const QWeb = core.qweb;
+
+const MenuSearchMixin = {
+ _findNames(memo, menu) {
+ if (menu.action) {
+ const key = menu.parent_id ? menu.parent_id[1] + "/" : "";
+ memo[key + menu.name] = menu;
+ }
+ if (menu.children.length) {
+ _.reduce(menu.children, this._findNames.bind(this), memo);
+ }
+ return memo;
+ },
+ _menuInfo(key) {
+ const original = this._searchableMenus[key];
+ return _.extend({
+ action_id: parseInt(original.action.split(',')[1], 10),
+ }, original);
+ },
+ _searchFocus() {
+ if (!config.device.isMobile) {
+ this.$search_input.focus();
+ } else {
+ this.$search_input.blur();
+ }
+ },
+ _searchReset() {
+ this.$search_container.removeClass("has-results");
+ this.$search_results.empty();
+ this.$search_input.val("");
+ },
+ _searchMenusSchedule() {
+ this._search_def.reject();
+ this._search_def = $.Deferred();
+ setTimeout(this._search_def.resolve.bind(this._search_def), 50);
+ this._search_def.then(this._searchMenus.bind(this));
+ },
+ _searchMenus() {
+ const query = this.$search_input.val();
+ if (query === "") {
+ this.$search_container.removeClass("has-results");
+ this.$search_results.empty();
+ return;
+ }
+ const results = fuzzy.filter(query, _.keys(this._searchableMenus), {
+ pre: "<b>",
+ post: "</b>",
+ });
+ this.$search_container.toggleClass("has-results", Boolean(results.length));
+ this.$search_results.html(QWeb.render("muk_web_theme.MenuSearchResults", {
+ results: results,
+ widget: this,
+ }));
+ },
+ _onSearchResultsNavigate(event) {
+ if (this.$search_results.html().trim() === "") {
+ this._searchMenusSchedule();
+ return;
+ }
+ const all = this.$search_results.find(".mk_menu_search_result");
+ const key = event.key || String.fromCharCode(event.which);
+ const pre_focused = all.filter(".active") || $(all[0]);
+ const offset = all.index(pre_focused);
+ if (key === "Tab") {
+ event.preventDefault();
+ key = event.shiftKey ? "ArrowUp" : "ArrowDown";
+ }
+ switch (key) {
+ case "Enter":
+ pre_focused.click();
+ break;
+ case "ArrowUp":
+ offset--;
+ break;
+ case "ArrowDown":
+ offset++;
+ break;
+ default:
+ this._searchMenusSchedule();
+ return;
+ }
+ if (offset < 0) {
+ offset = all.length + offset;
+ } else if (offset >= all.length) {
+ offset -= all.length;
+ }
+ const new_focused = $(all[offset]);
+ pre_focused.removeClass("active");
+ new_focused.addClass("active");
+ this.$search_results.scrollTo(new_focused, {
+ offset: {
+ top: this.$search_results.height() * -0.5,
+ },
+ });
+ },
+ _onMenuShown(event) {
+ this._searchFocus();
+ },
+ _onMenuHidden(event) {
+ this._searchReset();
+ },
+};
+
+return MenuSearchMixin;
+
+}); \ No newline at end of file
diff --git a/muk_web_theme/static/src/js/fields/relational.js b/muk_web_theme/static/src/js/fields/relational.js
new file mode 100644
index 0000000..71133ce
--- /dev/null
+++ b/muk_web_theme/static/src/js/fields/relational.js
@@ -0,0 +1,64 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.relational_fields', function (require) {
+"use strict";
+
+const config = require("web.config");
+const fields = require('web.relational_fields');
+
+fields.FieldStatus.include({
+ _setState() {
+ this._super(...arguments);
+ if (config.device.isMobile) {
+ _.map(this.status_information, (value) => {
+ value.fold = true;
+ });
+ }
+ },
+});
+
+fields.FieldOne2Many.include({
+ _renderButtons() {
+ const result = this._super(...arguments);
+ if (config.device.isMobile && this.$buttons) {
+ const $buttons = this.$buttons.find('.btn-secondary');
+ $buttons.addClass('btn-primary mk_mobile_add');
+ $buttons.removeClass('btn-secondary');
+ }
+ return result;
+ }
+});
+
+fields.FieldMany2Many.include({
+ _renderButtons() {
+ const result = this._super(...arguments);
+ if (config.device.isMobile && this.$buttons) {
+ const $buttons = this.$buttons.find('.btn-secondary');
+ $buttons.addClass('btn-primary mk_mobile_add');
+ $buttons.removeClass('btn-secondary');
+ }
+ return result;
+ }
+});
+
+}); \ No newline at end of file
diff --git a/muk_web_theme/static/src/js/libs/scrollbar.js b/muk_web_theme/static/src/js/libs/scrollbar.js
new file mode 100644
index 0000000..3842f53
--- /dev/null
+++ b/muk_web_theme/static/src/js/libs/scrollbar.js
@@ -0,0 +1,27 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+$.fn.renderScrollBar = function() {
+ this.each(function() {
+ new SimpleBar(this);
+ });
+};
diff --git a/muk_web_theme/static/src/js/views/form_renderer.js b/muk_web_theme/static/src/js/views/form_renderer.js
new file mode 100644
index 0000000..87a202d
--- /dev/null
+++ b/muk_web_theme/static/src/js/views/form_renderer.js
@@ -0,0 +1,50 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.FormRenderer', function (require) {
+"use strict";
+
+const core = require('web.core');
+const config = require("web.config");
+
+const FormRenderer = require('web.FormRenderer');
+
+FormRenderer.include({
+ _renderHeaderButtons() {
+ const $buttons = this._super(...arguments);
+ if (
+ !config.device.isMobile ||
+ !$buttons.is(":has(>:not(.o_invisible_modifier))")
+ ) {
+ return $buttons;
+ }
+
+ $buttons.addClass("dropdown-menu");
+ const $dropdown = $(
+ core.qweb.render("muk_web_theme.MenuStatusbarButtons")
+ );
+ $buttons.addClass("dropdown-menu").appendTo($dropdown);
+ return $dropdown;
+ },
+});
+
+}); \ No newline at end of file
diff --git a/muk_web_theme/static/src/js/views/form_view.js b/muk_web_theme/static/src/js/views/form_view.js
new file mode 100644
index 0000000..3bd2610
--- /dev/null
+++ b/muk_web_theme/static/src/js/views/form_view.js
@@ -0,0 +1,49 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.FormView', function (require) {
+"use strict";
+
+const config = require("web.config");
+
+const FormView = require('web.FormView');
+const QuickCreateFormView = require('web.QuickCreateFormView');
+
+FormView.include({
+ init() {
+ this._super(...arguments);
+ if (config.device.isMobile) {
+ this.controllerParams.disableAutofocus = true;
+ }
+ },
+});
+
+QuickCreateFormView.include({
+ init() {
+ this._super(...arguments);
+ if (config.device.isMobile) {
+ this.controllerParams.disableAutofocus = true;
+ }
+ },
+});
+
+});
diff --git a/muk_web_theme/static/src/js/views/kanban_column.js b/muk_web_theme/static/src/js/views/kanban_column.js
new file mode 100644
index 0000000..0cdc8dd
--- /dev/null
+++ b/muk_web_theme/static/src/js/views/kanban_column.js
@@ -0,0 +1,42 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.KanbanColumn', function (require) {
+"use strict";
+
+const config = require('web.config');
+
+const KanbanColumn = require('web.KanbanColumn');
+
+if (!config.device.isMobile) {
+ return;
+}
+
+KanbanColumn.include({
+ init() {
+ this._super(...arguments);
+ this.recordsDraggable = false;
+ this.canBeFolded = false;
+ },
+});
+
+});
diff --git a/muk_web_theme/static/src/js/views/kanban_quick_create.js b/muk_web_theme/static/src/js/views/kanban_quick_create.js
new file mode 100644
index 0000000..b86ed52
--- /dev/null
+++ b/muk_web_theme/static/src/js/views/kanban_quick_create.js
@@ -0,0 +1,44 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.kanban_column_quick_create', function (require) {
+"use strict";
+
+const config = require('web.config');
+
+const KanbanRenderer = require('web.kanban_column_quick_create');
+
+KanbanRenderer.include({
+ init() {
+ this._super(...arguments);
+ this.isMobile = config.device.isMobile;
+ },
+ _cancel() {
+ if (!config.device.isMobile) {
+ this._super(...arguments);
+ } else if (!this.folded) {
+ this.$input.val('');
+ }
+ },
+});
+
+});
diff --git a/muk_web_theme/static/src/js/views/kanban_renderer.js b/muk_web_theme/static/src/js/views/kanban_renderer.js
new file mode 100644
index 0000000..2cdd94d
--- /dev/null
+++ b/muk_web_theme/static/src/js/views/kanban_renderer.js
@@ -0,0 +1,271 @@
+/**********************************************************************************
+*
+* Copyright (c) 2017-today MuK IT GmbH.
+*
+* This file is part of MuK Grid Snippets
+* (see https://mukit.at).
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+**********************************************************************************/
+
+odoo.define('muk_web_theme.KanbanRenderer', function (require) {
+"use strict";
+
+const config = require('web.config');
+const core = require('web.core');
+
+const KanbanRenderer = require('web.KanbanRenderer');
+
+const _t = core._t;
+const qweb = core.qweb;
+
+if (!config.device.isMobile) {
+ return;
+}
+
+KanbanRenderer.include({
+ custom_events: _.extend({}, KanbanRenderer.prototype.custom_events || {}, {
+ quick_create_column_created: '_onColumnAdded',
+ }),
+ events: _.extend({}, KanbanRenderer.prototype.events, {
+ 'click .o_kanban_mobile_tab': '_onMobileTabClicked',
+ 'click .o_kanban_mobile_add_column': '_onMobileQuickCreateClicked',
+ }),
+ ANIMATE: true,
+ init() {
+ this._super.apply(this, arguments);
+ this.activeColumnIndex = 0;
+ this._scrollPosition = null;
+ },
+ on_attach_callback() {
+ if (this._scrollPosition && this.state.groupedBy.length && this.widgets.length) {
+ var $column = this.widgets[this.activeColumnIndex].$el;
+ $column.scrollLeft(this._scrollPosition.left);
+ $column.scrollTop(this._scrollPosition.top);
+ }
+ this._computeTabPosition();
+ this._super.apply(this, arguments);
+ },
+ on_detach_callback() {
+ if (this.state.groupedBy.length && this.widgets.length) {
+ var $column = this.widgets[this.activeColumnIndex].$el;
+ this._scrollPosition = {
+ left: $column.scrollLeft(),
+ top: $column.scrollTop(),
+ };
+ } else {
+ this._scrollPosition = null;
+ }
+ this._super.apply(this, arguments);
+ },
+ addQuickCreate() {
+ if(this._canCreateColumn() && !this.quickCreate.folded) {
+ this._onMobileQuickCreateClicked();
+ }
+ return this.widgets[this.activeColumnIndex].addQuickCreate();
+ },
+ updateColumn(localID) {
+ var index = _.findIndex(this.widgets, {db_id: localID});
+ var $column = this.widgets[index].$el;
+ var scrollTop = $column.scrollTop();
+ return this._super.apply(this, arguments)
+ .then(() => this._layoutUpdate(false))
+ .then(() => $column.scrollTop(scrollTop));
+ },
+ _canCreateColumn: function() {
+ return this.quickCreateEnabled && this.quickCreate && this.widgets.length;
+ },
+ _computeColumnPosition(animate) {
+ if (this.widgets.length) {
+ const rtl = _t.database.parameters.direction === 'rtl';
+ this.$('.o_kanban_group').show();
+ const $columnAfter = this._toNode(this.widgets.filter((widget, index) => index > this.activeColumnIndex));
+ const promiseAfter = this._updateColumnCss($columnAfter, rtl ? {right: '100%'} : {left: '100%'}, animate);
+ const $columnBefore = this._toNode(this.widgets.filter((widget, index) => index < this.activeColumnIndex));
+ const promiseBefore = this._updateColumnCss($columnBefore, rtl ? {right: '-100%'} : {left: '-100%'}, animate);
+ const $columnCurrent = this._toNode(this.widgets.filter((widget, index) => index === this.activeColumnIndex));
+ const promiseCurrent = this._updateColumnCss($columnCurrent, rtl ? {right: '0%'} : {left: '0%'}, animate);
+ promiseAfter
+ .then(promiseBefore)
+ .then(promiseCurrent)
+ .then(() => {
+ $columnAfter.hide();
+ $columnBefore.hide();
+ });
+ }
+ },
+ _computeCurrentColumn() {
+ if (this.widgets.length) {
+ var column = this.widgets[this.activeColumnIndex];
+ if (!column) {
+ return;
+ }
+ var columnID = column.id || column.db_id;
+ this.$('.o_kanban_mobile_tab.o_current, .o_kanban_group.o_current')
+ .removeClass('o_current');
+ this.$('.o_kanban_group[data-id="' + columnID + '"], ' +
+ '.o_kanban_mobile_tab[data-id="' + columnID + '"]')
+ .addClass('o_current');
+ }
+ },
+ _computeTabPosition() {
+ this._computeTabJustification();
+ this._computeTabScrollPosition();
+ },
+ _computeTabScrollPosition() {
+ if (this.widgets.length) {
+ var lastItemIndex = this.widgets.length - 1;
+ var moveToIndex = this.activeColumnIndex;
+ var scrollToLeft = 0;
+ for (var i = 0; i < moveToIndex; i++) {
+ var columnWidth = this._getTabWidth(this.widgets[i]);
+ if (moveToIndex !== lastItemIndex && i === moveToIndex - 1) {
+ var partialWidth = 0.75;
+ scrollToLeft += columnWidth * partialWidth;
+ } else {
+ scrollToLeft += columnWidth;
+ }
+ }
+ this.$('.o_kanban_mobile_tabs').scrollLeft(scrollToLeft);
+ }
+ },
+ _computeTabJustification() {
+ if (this.widgets.length) {
+ var self = this;
+ var widthChilds = this.widgets.reduce(function (total, column) {
+ return total + self._getTabWidth(column);
+ }, 0);
+ var $tabs = this.$('.o_kanban_mobile_tabs');
+ $tabs.toggleClass('justify-content-between', $tabs.outerWidth() >= widthChilds);
+ }
+ },
+ _enableSwipe() {
+ var self = this;
+ var step = _t.database.parameters.direction === 'rtl' ? -1 : 1;
+ this.$el.swipe({
+ excludedElements: ".o_kanban_mobile_tabs",
+ swipeLeft() {
+ var moveToIndex = self.activeColumnIndex + step;
+ if (moveToIndex < self.widgets.length) {
+ self._moveToGroup(moveToIndex, self.ANIMATE);
+ }
+ },
+ swipeRight() {
+ var moveToIndex = self.activeColumnIndex - step;
+ if (moveToIndex > -1) {
+ self._moveToGroup(moveToIndex, self.ANIMATE);
+ }
+ }
+ });
+ },
+ _getTabWidth (column) {
+ var columnID = column.id || column.db_id;
+ return this.$('.o_kanban_mobile_tab[data-id="' + columnID + '"]').outerWidth();
+ },
+ _layoutUpdate (animate) {
+ this._computeCurrentColumn();
+ this._computeTabPosition();
+ this._computeColumnPosition(animate);
+ },
+ _moveToGroup(moveToIndex, animate) {
+ if (moveToIndex < 0 || moveToIndex >= this.widgets.length) {
+ this._layoutUpdate(animate);
+ return Promise.resolve();
+ }
+ this.activeColumnIndex = moveToIndex;
+ var column = this.widgets[this.activeColumnIndex];
+ if (column.data.isOpen) {
+ this._layoutUpdate(animate);
+ } else {
+ this.trigger_up('column_toggle_fold', {
+ db_id: column.db_id,
+ onSuccess: () => this._layoutUpdate(animate)
+ });
+ }
+ this._enableSwipe();
+ return Promise.resolve();
+ },
+ _renderGrouped(fragment) {
+ var self = this;
+ var newFragment = document.createDocumentFragment();
+ this._super.apply(this, [newFragment]);
+ this.defs.push(Promise.all(this.defs).then(function () {
+ var data = [];
+ _.each(self.state.data, function (group) {
+ if (!group.value) {
+ group = _.extend({}, group, {value: _t('Undefined')});
+ data.unshift(group);
+ } else {
+ data.push(group);
+ }
+ });
+
+ var kanbanColumnContainer = document.createElement('div');
+ kanbanColumnContainer.classList.add('o_kanban_columns_content');
+ kanbanColumnContainer.appendChild(newFragment);
+ fragment.appendChild(kanbanColumnContainer);
+ $(qweb.render('KanbanView.MobileTabs', {
+ data: data,
+ quickCreateEnabled: self._canCreateColumn()
+ })).prependTo(fragment);
+ }));
+ },
+ _renderView() {
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ if (self.state.groupedBy.length) {
+ return self._moveToGroup(0);
+ } else {
+ if(self._canCreateColumn()) {
+ self._onMobileQuickCreateClicked();
+ }
+ return Promise.resolve();
+ }
+ });
+ },
+ _toNode(widgets) {
+ const selectorCss = widgets
+ .map(widget => '.o_kanban_group[data-id="' + (widget.id || widget.db_id) + '"]')
+ .join(', ');
+ return this.$(selectorCss);
+ },
+ _updateColumnCss($column, cssProperties, animate) {
+ if (animate) {
+ return new Promise(resolve => $column.animate(cssProperties, 'fast', resolve));
+ } else {
+ $column.css(cssProperties);
+ return Promise.resolve();
+ }
+ },
+ _onColumnAdded() {
+ this._computeTabPosition();
+ if(this._canCreateColumn() && !this.quickCreate.folded) {
+ this.quickCreate.toggleFold();
+ }
+ },
+ _onMobileQuickCreateClicked: function() {
+ this.$('.o_kanban_group').toggle();
+ this.quickCreate.toggleFold();
+ },
+ _onMobileTabClicked(event) {
+ if(this._canCreateColumn() && !this.quickCreate.folded) {
+ this.quickCreate.toggleFold();
+ }
+ this._moveToGroup($(event.currentTarget).index(), true);
+ },
+ _renderExampleBackground() {},
+});
+
+}); \ No newline at end of file