diff --git a/clarity_backend_theme_bits/__init__.py b/clarity_backend_theme_bits/__init__.py new file mode 100644 index 000000000..72f4562d7 --- /dev/null +++ b/clarity_backend_theme_bits/__init__.py @@ -0,0 +1 @@ +from . import controller \ No newline at end of file diff --git a/clarity_backend_theme_bits/__manifest__.py b/clarity_backend_theme_bits/__manifest__.py new file mode 100644 index 000000000..16f4b43d5 --- /dev/null +++ b/clarity_backend_theme_bits/__manifest__.py @@ -0,0 +1,65 @@ +{ + "name": "Clarity Backend Theme for community", + "version": "17.0.1.0.1", + 'author': "Terabits Technolab", + 'summary': """ + Clarity backend theme + Odoo Backend Theme, Odoo Community Backend Theme, Web backend Theme, Web Responsive Odoo Theme, New theme design, New design, Multi Level Menu, + Web Responsive , Odoo Theme, Odoo Modern Theme, Odoo Modern Backend Theme Odoo, Advance Theme Backend Advanced, Left sidebar menu, + All in one, New advanced Odoo Menu, Sidebar apps, Web menu, Odoo backend menu, Web Responsive menu, Sidebar dark, + Advance Menu Odoo App Menu Apps, Advanced Apps Menu, Elegant Menu, Web App Menu Backend, Menu Odoo Backend, Collapse Menu, Light Sidebar, + Expand Menu, Collapsed Menu, Expanded Menu, New Style Menus, Advanced Sidebar Menu, Advance Sidebar Menu, Responsive Menu Sidebar, Sidebar Theme, + Responsive Sidebar, Hide menu, Show Menu, Hide Sidebar, Show Sidebar, Toggle Menu, Toggle Sidebar, Menu Theme, + Quick Backend Menu, Dropdown Menu, Parent Menus, Shortcut Menus, Menu Icons, Collapsible menu Odoo, + Menu Dynamic Sidebar, Advanced Menu, Backend Odoo Web, Elegant Theme Simple, Advance List View Manager, + Arc Backend Theme, Fully Functional Theme, Flexible Backend Theme, Fast Backend Theme, Advance Material Backend Theme, Customizable Backend Theme, + Attractive Theme for Backend, Elegant Backend Theme, Responsive Web Client, Backend UI, Mobile Responsive for Odoo Community, + Flexible Enterprise Theme, Enterprise Backend Theme + """, + 'description': """ + Clarity backend theme + Odoo Backend Theme, Odoo Community Backend Theme, Web backend Theme, Web Responsive Odoo Theme, New theme design, New design, Multi Level Menu, + Web Responsive , Odoo Theme, Odoo Modern Theme, Odoo Modern Backend Theme Odoo, Advance Theme Backend Advanced, Left sidebar menu, + All in one, New advanced Odoo Menu, Sidebar apps, Web menu, Odoo backend menu, Web Responsive menu, Sidebar dark, + Advance Menu Odoo App Menu Apps, Advanced Apps Menu, Elegant Menu, Web App Menu Backend, Menu Odoo Backend, Collapse Menu, Light Sidebar, + Expand Menu, Collapsed Menu, Expanded Menu, New Style Menus, Advanced Sidebar Menu, Advance Sidebar Menu, Responsive Menu Sidebar, Sidebar Theme, + Responsive Sidebar, Hide menu, Show Menu, Hide Sidebar, Show Sidebar, Toggle Menu, Toggle Sidebar, Menu Theme, + Quick Backend Menu, Dropdown Menu, Parent Menus, Shortcut Menus, Menu Icons, Collapsible menu Odoo, + Menu Dynamic Sidebar, Advanced Menu, Backend Odoo Web, Elegant Theme Simple, Advance List View Manager, + Arc Backend Theme, Fully Functional Theme, Flexible Backend Theme, Fast Backend Theme, Advance Material Backend Theme, Customizable Backend Theme, + Attractive Theme for Backend, Elegant Backend Theme, Responsive Web Client, Backend UI, Mobile Responsive for Odoo Community, + Flexible Enterprise Theme, Enterprise Backend Theme + """, + "sequence": 7, + "license": "OPL-1", + "category": "Themes/Backend", + "website": "https://www.terabits.xyz", + "depends": ["web"], + "data": [ + 'views/res_config_setting.xml', + 'views/res_users.xml', + 'views/webclient_templates.xml' + ], + "assets": { + "web.assets_frontend": [ + 'clarity_backend_theme_bits/static/src/scss/login.scss' + ], + "web.assets_backend": [ + 'clarity_backend_theme_bits/static/src/xml/WebClient.xml', + 'clarity_backend_theme_bits/static/src/xml/navbar/sidebar.xml', + 'clarity_backend_theme_bits/static/src/xml/systray_items/user_menu.xml', + 'clarity_backend_theme_bits/static/src/js/SidebarBottom.js', + 'clarity_backend_theme_bits/static/src/js/WebClient.js', + 'clarity_backend_theme_bits/static/src/scss/layout.scss', + 'clarity_backend_theme_bits/static/src/scss/navbar.scss', + 'clarity_backend_theme_bits/static/src/js/navbar.js', + ], + }, + 'installable': True, + 'application': True, + 'auto_install': False, + 'images': [ + 'static/description/logo.gif', + 'static/description/theme_screenshot.gif', + ], +} diff --git a/clarity_backend_theme_bits/controller/__init__.py b/clarity_backend_theme_bits/controller/__init__.py new file mode 100644 index 000000000..deec4a8b8 --- /dev/null +++ b/clarity_backend_theme_bits/controller/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/clarity_backend_theme_bits/controller/main.py b/clarity_backend_theme_bits/controller/main.py new file mode 100644 index 000000000..64e24857b --- /dev/null +++ b/clarity_backend_theme_bits/controller/main.py @@ -0,0 +1,17 @@ +import datetime +import pytz +from odoo import http, models, fields, api, tools +from odoo.http import request + +class BackThemeBits(http.Controller): + @http.route(['/get/menu_data'], type='json', auth='public') + def get_irmenu_icondata(self, **kw): + menuobj = request.env['ir.ui.menu'] + menu_recs = request.env['ir.ui.menu'].sudo().search( + [('id', 'in', kw.get('menu_ids'))]) + + app_menu_dict = {} + for menu in menu_recs: + menu_dict = menu.read(set(menuobj._fields)) + app_menu_dict[menu.id] = menu_dict + return app_menu_dict \ No newline at end of file diff --git a/clarity_backend_theme_bits/static/description/icon.png b/clarity_backend_theme_bits/static/description/icon.png new file mode 100644 index 000000000..873c613f5 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/icon.png differ diff --git a/clarity_backend_theme_bits/static/description/images/1.png b/clarity_backend_theme_bits/static/description/images/1.png new file mode 100644 index 000000000..14725d098 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/1.png differ diff --git a/clarity_backend_theme_bits/static/description/images/2.png b/clarity_backend_theme_bits/static/description/images/2.png new file mode 100644 index 000000000..b2774c6c2 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/2.png differ diff --git a/clarity_backend_theme_bits/static/description/images/3.png b/clarity_backend_theme_bits/static/description/images/3.png new file mode 100644 index 000000000..c0c1ce1e6 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/3.png differ diff --git a/clarity_backend_theme_bits/static/description/images/4.png b/clarity_backend_theme_bits/static/description/images/4.png new file mode 100644 index 000000000..8b22c4d95 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/4.png differ diff --git a/clarity_backend_theme_bits/static/description/images/5.png b/clarity_backend_theme_bits/static/description/images/5.png new file mode 100644 index 000000000..b72887482 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/5.png differ diff --git a/clarity_backend_theme_bits/static/description/images/6.png b/clarity_backend_theme_bits/static/description/images/6.png new file mode 100644 index 000000000..07b4536b6 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/6.png differ diff --git a/clarity_backend_theme_bits/static/description/images/7.png b/clarity_backend_theme_bits/static/description/images/7.png new file mode 100644 index 000000000..9ce68515a Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/7.png differ diff --git a/clarity_backend_theme_bits/static/description/images/8.png b/clarity_backend_theme_bits/static/description/images/8.png new file mode 100644 index 000000000..c71be2466 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/8.png differ diff --git a/clarity_backend_theme_bits/static/description/images/9.png b/clarity_backend_theme_bits/static/description/images/9.png new file mode 100644 index 000000000..deeb181af Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/9.png differ diff --git a/clarity_backend_theme_bits/static/description/images/analytix_banner.png b/clarity_backend_theme_bits/static/description/images/analytix_banner.png new file mode 100644 index 000000000..ecf241221 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/analytix_banner.png differ diff --git a/clarity_backend_theme_bits/static/description/images/banner.png b/clarity_backend_theme_bits/static/description/images/banner.png new file mode 100644 index 000000000..a37266e5d Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/banner.png differ diff --git a/clarity_backend_theme_bits/static/description/images/blog_feat_bg_02.png b/clarity_backend_theme_bits/static/description/images/blog_feat_bg_02.png new file mode 100644 index 000000000..972b822ba Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/blog_feat_bg_02.png differ diff --git a/clarity_backend_theme_bits/static/description/images/blog_post_bg_01.png b/clarity_backend_theme_bits/static/description/images/blog_post_bg_01.png new file mode 100644 index 000000000..1dbb707aa Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/blog_post_bg_01.png differ diff --git a/clarity_backend_theme_bits/static/description/images/blog_ss_bg_03.png b/clarity_backend_theme_bits/static/description/images/blog_ss_bg_03.png new file mode 100644 index 000000000..a91b96775 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/blog_ss_bg_03.png differ diff --git a/clarity_backend_theme_bits/static/description/images/blogpost_header_img.png b/clarity_backend_theme_bits/static/description/images/blogpost_header_img.png new file mode 100644 index 000000000..e7d216217 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/blogpost_header_img.png differ diff --git a/clarity_backend_theme_bits/static/description/images/clarity_pro_banner.png b/clarity_backend_theme_bits/static/description/images/clarity_pro_banner.png new file mode 100644 index 000000000..d6330b1f1 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/clarity_pro_banner.png differ diff --git a/clarity_backend_theme_bits/static/description/images/icon_img.png b/clarity_backend_theme_bits/static/description/images/icon_img.png new file mode 100644 index 000000000..12db9a72a Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/icon_img.png differ diff --git a/clarity_backend_theme_bits/static/description/images/main-b.png b/clarity_backend_theme_bits/static/description/images/main-b.png new file mode 100644 index 000000000..a988f5d2a Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/main-b.png differ diff --git a/clarity_backend_theme_bits/static/description/images/simplify_banner_bg.png b/clarity_backend_theme_bits/static/description/images/simplify_banner_bg.png new file mode 100644 index 000000000..1b35c6196 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/images/simplify_banner_bg.png differ diff --git a/clarity_backend_theme_bits/static/description/index.html b/clarity_backend_theme_bits/static/description/index.html new file mode 100644 index 000000000..600830385 --- /dev/null +++ b/clarity_backend_theme_bits/static/description/index.html @@ -0,0 +1,676 @@ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+
+ + +
+
+
+ +
+ +
+

+ Clarity Backend Theme +

+

+ Odoo community backend theme +

+

+ The clarity backend theme have amazing appearance on any device and is easy to
+ switch between all screen sizes. Clicking on any menu is made simple with an
+ contemporary and modern sidebar. You can browse across different apps using
+ elegant sidebar menu.The theme is designed, keeping in mind the delivery of
+ great user experience and user-friendly interface to your users. +

+
+ +
+
+
+
+

+ App Drawer design for Community Addition +

+
+
+ +
+
+

+ Login & Signup Redesign +

+
+
+ +
+
+

+ Customized Discuss view design +

+
+
+ +
+
+

+ Show brand's logo in menu +

+
+
+ +
+
+

+ Customzed List, Form, Kanban view design +

+
+
+ +
+
+

+ Responsive sidebar design +

+
+
+ + +
+
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + +
+
+ +
+
+
+ +
+
+

+ Custom discuss view +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Interactive and clean design +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Custom list view design +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Custom kanban view design +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Custom form view design +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Custom sign up design +

+
(The login/signup design will appear only the backend login/signup view. + It will not appear in the website login/signup view.) +
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Custom login design +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Custom reset form design +

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+

+ Set company logo +

+
+
+ +
+ +
+
+ +
+
+
+
+ + + + + +
+

+ Suggested Apps +

+
+ + +
+ +
+ +
+

+ Simplify access management

+

+ "Simplify Access Management can Control permissions for all aspects of your + Odoo + system easily from one place. Save up to 80% of customization time!" +

+ +
+ + Hide menu/sub menu + + + Models access rights + + + Fields access right +
+ +
+ + Buttons/tab access rights + + + Disable developer mode + + + Hide chatter +
+ +
+ + Domain access right + + + Hide filter and groups + + + Readonly users +
+ + +
+ +
+ + + +
+
+ +
+
+
+ + + + + +
+
+ + +
+ +
+ +
+

+ Clarity Pro Backend Theme

+

+ The clarity backend theme have amazing appearance on any device and is easy to switch between all screen sizes. + The theme is designed, keeping in mind the delivery of great user experience and user-friendly interface to your users. +

+ +
+ + Main menu for community + + + Sidebar menu/top menu + + + Multi tabs management +
+ +
+ + Global search + + + Global search in record + + + Global search in menu +
+ +
+ + Multi font style + + + Multi icon style + + + Custom color schemes +
+ +
+ + Full-screen switch + + + Bookmark management + + + Attractive dark mode +
+ +
+ + Kanban & list view style + + + Checkbox & radio style + + + RTL support +
+ + +
+ +
+ + + +
+
+ +
+
+
+ + + + + +
+
+ + +
+ +
+ +
+

+ AnalytiX Dashboard

+

+ "Unlock the true potential of your data with AnalytiX Dashboard, a cutting-edge Odoo + dashboard module designed to revolutionizethe way you visualize & analyze information." +

+ +
+ + Predefined date filter + + + Real-time Analytics + + + Customizable Dashboards +
+ +
+ + Smart Data Visualization + + + User-Friendly Interface + + + Import/Export dashboard +
+ +
+ + Group access control + + + Share your findings + + + Fully responsive layout +
+ + +
+ +
+ + + +
+
+ +
+
+
+ + + + +
+
+
+
+ +
+
+

+ Need a help for this module? +

+

+ Contact me + info@terabits.xyz + for your queries +

+
+
+ + +
+
diff --git a/clarity_backend_theme_bits/static/description/logo.gif b/clarity_backend_theme_bits/static/description/logo.gif new file mode 100644 index 000000000..33625610c Binary files /dev/null and b/clarity_backend_theme_bits/static/description/logo.gif differ diff --git a/clarity_backend_theme_bits/static/description/theme_screenshot.gif b/clarity_backend_theme_bits/static/description/theme_screenshot.gif new file mode 100644 index 000000000..cf48b8fa7 Binary files /dev/null and b/clarity_backend_theme_bits/static/description/theme_screenshot.gif differ diff --git a/clarity_backend_theme_bits/static/img/logo.png b/clarity_backend_theme_bits/static/img/logo.png new file mode 100644 index 000000000..0bb577d97 Binary files /dev/null and b/clarity_backend_theme_bits/static/img/logo.png differ diff --git a/clarity_backend_theme_bits/static/src/js/Headerbar.js b/clarity_backend_theme_bits/static/src/js/Headerbar.js new file mode 100644 index 000000000..541c44cf2 --- /dev/null +++ b/clarity_backend_theme_bits/static/src/js/Headerbar.js @@ -0,0 +1,193 @@ +/** @odoo-module **/ + +import { Dropdown } from "@web/core/dropdown/dropdown"; +import { useService } from "@web/core/utils/hooks"; +import { registry } from "@web/core/registry"; +import { debounce } from "@web/core/utils/timing"; +import { ErrorHandler } from "@web/core/utils/components"; +import { NavBarDropdownItem,MenuDropdown } from '@web/static/src/webclient/navbar/navbar'; +import { + Component, + onWillDestroy, + useExternalListener, + useEffect, + useRef, + onWillUnmount, +} from "@odoo/owl"; +const systrayRegistry = registry.category("systray"); + +const getBoundingClientRect = Element.prototype.getBoundingClientRect; + +export class HeaderBar extends NavBar { + setup() { + this.currentAppSectionsExtra = []; + this.actionService = useService("action"); + this.menuService = useService("menu"); + this.root = useRef("root"); + this.appSubMenus = useRef("appSubMenus"); + const debouncedAdapt = debounce(this.adapt.bind(this), 250); + onWillDestroy(() => debouncedAdapt.cancel()); + useExternalListener(window, "resize", debouncedAdapt); + + let adaptCounter = 0; + const renderAndAdapt = () => { + adaptCounter++; + this.render(); + }; + + systrayRegistry.addEventListener("UPDATE", renderAndAdapt); + this.env.bus.addEventListener("MENUS:APP-CHANGED", renderAndAdapt); + + onWillUnmount(() => { + systrayRegistry.removeEventListener("UPDATE", renderAndAdapt); + this.env.bus.removeEventListener("MENUS:APP-CHANGED", renderAndAdapt); + }); + + // We don't want to adapt every time we are patched + // rather, we adapt only when menus or systrays have changed. + useEffect( + () => { + this.adapt(); + }, + () => [adaptCounter] + ); + } + + handleItemError(error, item) { + // remove the faulty component + item.isDisplayed = () => false; + Promise.resolve().then(() => { + throw error; + }); + } + + get currentApp() { + return this.menuService.getCurrentApp(); + } + + get currentAppSections() { + return ( + (this.currentApp && this.menuService.getMenuAsTree(this.currentApp.id).childrenTree) || + [] + ); + } + + // This dummy setter is only here to prevent conflicts between the + // Enterprise NavBar extension and the Website NavBar patch. + set currentAppSections(_) {} + + get systrayItems() { + return systrayRegistry + .getEntries() + .map(([key, value]) => ({ key, ...value })) + .filter((item) => ("isDisplayed" in item ? item.isDisplayed(this.env) : true)) + .reverse(); + } + + // This dummy setter is only here to prevent conflicts between the + // Enterprise NavBar extension and the Website NavBar patch. + set systrayItems(_) {} + + /** + * Adapt will check the available width for the app sections to get displayed. + * If not enough space is available, it will replace by a "more" menu + * the least amount of app sections needed trying to fit the width. + * + * NB: To compute the widths of the actual app sections, a render needs to be done upfront. + * By the end of this method another render may occur depending on the adaptation result. + */ + async adapt() { + if (!this.root.el) { + /** @todo do we still need this check? */ + // currently, the promise returned by 'render' is resolved at the end of + // the rendering even if the component has been destroyed meanwhile, so we + // may get here and have this.el unset + return; + } + + // ------- Initialize ------- + // Get the sectionsMenu + const sectionsMenu = this.appSubMenus.el; + if (!sectionsMenu) { + // No need to continue adaptations if there is no sections menu. + return; + } + + // Save initial state to further check if new render has to be done. + const initialAppSectionsExtra = this.currentAppSectionsExtra; + const firstInitialAppSectionExtra = [...initialAppSectionsExtra].shift(); + const initialAppId = firstInitialAppSectionExtra && firstInitialAppSectionExtra.appID; + + // Restore (needed to get offset widths) + const sections = [ + ...sectionsMenu.querySelectorAll(":scope > *:not(.o_menu_sections_more)"), + ]; + for (const section of sections) { + section.classList.remove("d-none"); + } + this.currentAppSectionsExtra = []; + + // ------- Check overflowing sections ------- + // use getBoundingClientRect to get unrounded values for width in order to avoid rounding problem + // with offsetWidth. + const sectionsAvailableWidth = getBoundingClientRect.call(sectionsMenu).width; + const sectionsTotalWidth = sections.reduce( + (sum, s) => sum + getBoundingClientRect.call(s).width, + 0 + ); + if (sectionsAvailableWidth < sectionsTotalWidth) { + // Sections are overflowing + // Initial width is harcoded to the width the more menu dropdown will take + let width = 46; + for (const section of sections) { + if (sectionsAvailableWidth < width + section.offsetWidth) { + // Last sections are overflowing + const overflowingSections = sections.slice(sections.indexOf(section)); + overflowingSections.forEach((s) => { + // Hide from normal menu + s.classList.add("d-none"); + // Show inside "more" menu + const sectionId = + s.dataset.section || + s.querySelector("[data-section]").getAttribute("data-section"); + const currentAppSection = this.currentAppSections.find( + (appSection) => appSection.id.toString() === sectionId + ); + this.currentAppSectionsExtra.push(currentAppSection); + }); + break; + } + width += section.offsetWidth; + } + } + + // ------- Final rendering ------- + const firstCurrentAppSectionExtra = [...this.currentAppSectionsExtra].shift(); + const currentAppId = firstCurrentAppSectionExtra && firstCurrentAppSectionExtra.appID; + if ( + initialAppSectionsExtra.length === this.currentAppSectionsExtra.length && + initialAppId === currentAppId + ) { + // Do not render if more menu items stayed the same. + return; + } + return this.render(); + } + + onNavBarDropdownItemSelection(menu) { + if (menu) { + this.menuService.selectMenu(menu); + } + } + + getMenuItemHref(payload) { + const parts = [`menu_id=${payload.id}`]; + if (payload.actionID) { + parts.push(`action=${payload.actionID}`); + } + return "#" + parts.join("&"); + } +} +HeaderBar.template = "web.NavBar"; +HeaderBar.components = { Dropdown, NavBarDropdownItem, MenuDropdown, ErrorHandler }; +HeaderBar.props = {}; diff --git a/clarity_backend_theme_bits/static/src/js/SidebarBottom.js b/clarity_backend_theme_bits/static/src/js/SidebarBottom.js new file mode 100644 index 000000000..be1841539 --- /dev/null +++ b/clarity_backend_theme_bits/static/src/js/SidebarBottom.js @@ -0,0 +1,36 @@ +/** @odoo-module **/ + +import { Dropdown } from "@web/core/dropdown/dropdown"; +import { DropdownItem } from "@web/core/dropdown/dropdown_item"; +import { CheckBox } from "@web/core/checkbox/checkbox"; +import { browser } from "@web/core/browser/browser"; +import { registry } from "@web/core/registry"; +import { useService } from "@web/core/utils/hooks"; + +import { Component } from "@odoo/owl"; + +const userMenuRegistry = registry.category("user_menuitems"); + +export class SidebarBottom extends Component { + setup() { + this.user = useService("user"); + const { origin } = browser.location; + const { userId } = this.user; + this.source = `${origin}/web/image?model=res.users&field=avatar_128&id=${userId}`; + } + getElements() { + const sortedItems = userMenuRegistry + .getAll() + .map((element) => element(this.env)) + .sort((x, y) => { + const xSeq = x.sequence ? x.sequence : 100; + const ySeq = y.sequence ? y.sequence : 100; + return xSeq - ySeq; + }); + return sortedItems; + } +} +SidebarBottom.template = "SidebarBottom"; +SidebarBottom.components = { Dropdown, DropdownItem, CheckBox }; +SidebarBottom.props = {}; + diff --git a/clarity_backend_theme_bits/static/src/js/WebClient.js b/clarity_backend_theme_bits/static/src/js/WebClient.js new file mode 100644 index 000000000..69592f55e --- /dev/null +++ b/clarity_backend_theme_bits/static/src/js/WebClient.js @@ -0,0 +1,89 @@ +/** @odoo-module **/ +import { useService, useState} from "@web/core/utils/hooks"; +import { WebClient } from "@web/webclient/webclient"; +import { patch } from "@web/core/utils/patch"; +import { useRef } from "@odoo/owl"; +import { SidebarBottom } from "./SidebarBottom"; + +patch(WebClient.prototype, { + setup() { + super.setup(); + this.root = useRef("root"); + this.rpc = useService('rpc'); + this.companyService = useService("company"); + this.menuService = useService("menu"); + this.currentCompany = this.companyService.currentCompany; + this.fetch_menu_data(); + }, + toggleSidebar(ev){ + $(ev.currentTarget).toggleClass('visible'); + $('.nav-wrapper-bits').toggleClass('toggle-show'); + }, + fetch_menu_data(){ + var menu_data = this.menuService.getApps() + var self = this; + var rec_ids = [] + menu_data.map(app => rec_ids.push(app.id)) + this.rpc('/get/menu_data',{'menu_ids':rec_ids, + }).then(function(rec) { + console.log(rec); + $.each(menu_data, function( key, menu ) { + var target_elem = '.primary-nav a.main_link[data-menu='+ menu.id+']' + var elem = $(self.root.el).find(target_elem) + + elem.find('.app_icon').empty() + var pr_record = rec[menu.id][0] + menu.id = pr_record.id + menu.use_icon = pr_record.use_icon + menu.icon_class_name = pr_record.icon_class_name + menu.icon_img = pr_record.icon_img + + if (pr_record.use_icon) { + if (pr_record.icon_class_name) { + var icon_image = "" + } else if (pr_record.icon_img) { + var icon_image = "" + } else if (pr_record.web_icon != false) { + var icon_data = pr_record.web_icon.split('/icon.') + if (icon_data[1] == 'svg'){ + var web_svg_icon = pr_record.web_icon.replace(',', '/') + var icon_image = "" + } else { + var icon_image = "" + } + } else{ + var icon_image = "" + } + elem.find('.app_icon').append($(icon_image)) + } else { + if (pr_record.icon_img) { + var icon_image = "" + } else if (pr_record.web_icon != false){ + var icon_data = pr_record.web_icon.split('/icon.') + if (icon_data[1] == 'svg'){ + var web_svg_icon = pr_record.web_icon.replace(',', '/') + var icon_image = "" + } else { + var icon_image = "" + } + } else{ + var icon_image = "" + } + elem.find('.app_icon').append($(icon_image)) + } + }); + }) + }, + BackMenuToggle(ev){ + $(ev.currentTarget).parent().removeClass('show'); + }, + get currentMenuId() { + var actionParams = window.location.hash; + var menu_id = new URLSearchParams(actionParams.substring(1)).get('menu_id'); + return menu_id; + } +}); +patch(WebClient, { + components: { ...WebClient.components, SidebarBottom }, +}); + diff --git a/clarity_backend_theme_bits/static/src/js/navbar.js b/clarity_backend_theme_bits/static/src/js/navbar.js new file mode 100644 index 000000000..9d04758e4 --- /dev/null +++ b/clarity_backend_theme_bits/static/src/js/navbar.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { NavBar } from '@web/webclient/navbar/navbar'; +import { useService, useBus } from '@web/core/utils/hooks'; +import { patch } from "@web/core/utils/patch"; +import { useEnvDebugContext } from "@web/core/debug/debug_context"; + +patch(NavBar.prototype, { + setup() { + super.setup(); + this.debugContext = useEnvDebugContext(); + this.rpc = useService('rpc'); + this.companyService = useService("company"); + this.currentCompany = this.companyService.currentCompany; + this.menuService = useService("menu"); + }, + toggleSidebar(ev){ + $(ev.currentTarget).toggleClass('visible'); + $('.nav-wrapper-bits').toggleClass('toggle-show'); + }, +}); \ No newline at end of file diff --git a/clarity_backend_theme_bits/static/src/scss/layout.scss b/clarity_backend_theme_bits/static/src/scss/layout.scss new file mode 100644 index 000000000..8878a17e2 --- /dev/null +++ b/clarity_backend_theme_bits/static/src/scss/layout.scss @@ -0,0 +1,664 @@ +body.o_web_client{ + flex-flow: row !important; + .wrapper-container-bits{ + display: flex; + width: 100%; + .content-wrapper-bits{ + width: 100%; + overflow-x: clip; + @media (max-width: 1540px) { + height: 100%; + // overflow: auto; + } + .btn-link{ + color: #282828 !important; + } + .btn.btn-primary{ + background-color: #282828 !important; + color: #fff !important; + border-color: #fff; + border: 1px solid #282828; + &:focus,&:active,&:hover{ + background-color: #fff !important; + color: #282828 !important; + border-color: #282828 !important; + } + } + .btn.btn-secondary{ + background-color: #fff !important; + color: #282828 !important; + border-color: #282828; + border: 1px solid #282828; + &:focus,&:active,&:hover{ + background-color: #282828 !important; + color: #fff !important; + border-color: #282828 !important; + } + } + .o_main_navbar{ + padding: 0 10px; + .o_menu_systray{ + align-items: center; + .o_user_menu{ + display: none !important; + } + button.dropdown-toggle{ + background-color: #282828; + margin: 0px 4px; + width: 35px; + height: 35px; + text-align: center; + justify-content: center; + border-radius: 6px; + i{ + color: #fff; + font-size: 16px !important; + } + .badge.rounded-pill{ + position: absolute; + right: -10px; + top: 2px; + background-color: #ffffff; + border-color: #282828; + border: 1px solid #282828; + color: #282828; + } + &.o_mobile_menu_toggle{ + padding: 15px !important; + } + } + .o_mobile_preview{ + a.o_nav_entry{ + + } + } + .o_website_switcher_container,.o_edit_website_container,.o_new_content_container,.o_mobile_preview{ + button.dropdown-toggle,a.o_nav_entry,.o_nav_entry,a.btn{ + width: auto !important; + background-color: #282828 !important; + margin: 0px 4px; + height: 35px !important; + text-align: center; + justify-content: center; + border-radius: 6px !important; + color: #fff !important; + } + + } + .o_menu_systray_item{ + a{ + .d-none.d-md-block.ms-1{ + color: #282828 !important; + } + } + } + // header button popup + .o-mail-DiscussSystray{ + box-shadow: 0px 1px 5px #abababed; + border-radius: 16px; + .o-mail-MessagingMenu-header{ + button.fw-bold{ + border-bottom: 1px solid #282828; + } + } + } + .o_mobile_menu_toggle{ + display: none !important; + } + } + .sidebar-toggler{ + cursor: pointer; + .sidebar-toggle-bits{ + font-size: 12px; + color: #282828; + i.back-arrow{ + width: 0px !important; + visibility: hidden; + opacity: 0; + } + } + &:hover{ + .sidebar-toggle-bits{ + i.toggle{ + width: 0px !important; + display: none !important; + } + i.back-arrow{ + visibility: visible; + opacity: 1; + transition: all 0.2s; + width: 100% !important; + font-size: 18px; + font-weight: 600; + margin-top: 4px; + } + } + } + } + } + .o_action_manager{ + height: 100%; + width: 100%; + .o_control_panel{ + padding: 10px 14px !important; + .o_control_panel_main{ + // create button + .o_control_panel_breadcrumbs{ + .o_control_panel_main_buttons{ + .btn-outline-primary{ + color: #282828 !important; + border-color: #282828 !important; + &:hover,&:focus,&:active{ + color: #fff !important; + background-color: #282828 !important; + } + } + } + .breadcrumb{ + .breadcrumb-item{ + a{ + color: #282828 !important; + } + } + } + } + // action button + .o_control_panel_actions{ + .btn-outline-secondary{ + border-color: #282828 !important; + i{ + color: #282828 !important; + } + span{ + color: #282828 !important; + } + } + .o_cp_searchview .o_searchview{ + border-radius: 8px 1px 1px 8px; + border-color: #282828; + } + .o-dropdown{ + button.o_searchview_dropdown_toggler{ + border-radius: 0px 8px 8px 0px; + } + } + .o_search_bar_menu{ + i{ + color: #282828 !important; + } + } + } + // navigation + .o_control_panel_navigation{ + .o_pager_counter{ + span{ + font-size: 18px; + } + } + button{ + font-size: 0.875rem; + border-radius: 6px !important; + border-color: #282828; + background-color: #fff !important; + color: #282828 !important; + height: 35px; + margin: 0px 3px; + &.active{ + background-color: #2828282e !important; + } + // width: 35px; + @media (max-width: 768px) { + width:auto !important; + } + } + } + } + } + // Discuss module in community + .o-mail-Discuss{ + width: 100%; + } + .o_content{ + overflow: auto !important; + height: 100%; + margin-bottom: 60px; + max-height: calc(100vh - 100px); + } + // config setting view + .o-settings-form-view{ + .o_setting_container{ + .settings_tab{ + .app_name{ + font-size: 15px !important; + } + } + } + } + // form view + .o_form_view_container{ + .o_form_sheet_bg{ + .o_form_statusbar{ + overflow: hidden; + .o_statusbar_buttons{ + .btn-primary{ + background-color: #71639e !important; + border-color: #71639e !important; + &:hover{ + background-color: #fff !important; + } + } + .btn-secondary{ + background-color: #fff !important; + border-color: #71639e !important; + &:hover{ + background-color: #71639e !important; + } + } + } + .o_arrow_button{ + border-color: #71639e !important; + background-color: #fff; + &:after{ + border-color: #fff; + } + } + .o_statusbar_status{ + .o_arrow_button{ + border: none !important; + } + } + //////////////////////////////////////////////////////////////// + .o_statusbar_status { + .o_arrow_button { + font-size: 14px; + text-align: center; + cursor: default; + margin: 0 3px; + padding: 5px 25px; + float: left; + position: relative; + background-color: #d9e3f7 !important; + user-select: none; + transition: background-color 0.2s ease; + &:after,&:before{ + content: " "; + position: absolute; + top: 0; + right: -17px; + width: 0; + height: 0; + border-top: 15px solid transparent; + border-bottom: 15px solid transparent; + border-left: 17px solid #d9e3f7; + z-index: 2; + transition: border-color 0.2s ease; + } + &:hover{ + color: #282828 !important; + } + &:before{ + right: auto; + left: 0; + border-left: 17px solid #f8f9fa; + z-index: 0; + } + &:first-child{ + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + &:before { + border: none; + } + } + &.o_arrow_button_current{ + color: #fff !important; + span{ + color: #fff !important; + } + background-color: #71639e !important; + &:after{ + border-left: 17px solid #71639e; + } + } + } + } + } + //////////////////////////////////////////////////////////////// + .o_form_sheet{ + border-radius: 8px; + box-shadow: 0px 0px 3px #919191; + border: none; + .o_cell{ + label,span,a{ + font-size: 15px !important; + } + } + .o_form_uri{ + span:first-child{ + color: #282828 !important; + } + } + .o_notebook{ + .o_notebook_headers{ + .nav.nav-tabs{ + border-top: 1px solid #dee2e6; + padding: 0px !important; + .nav-item .nav-link{ + color: #484848; + display: block; + border-right: 1px solid #2828286b !important; + padding: 10px; + font-weight: 500; + &:after{ + height: 5px; + background-color: #282828; + } + &:before{ + height: 5px; + background-color: #282828; + } + &.active{ + border-bottom: 2px solid #31485e; + background: #f9f9f9 !important; + font-weight: 600; + } + } + } + } + } + } + .o_list_renderer{ + table{ + a{ + color: #000730 !important; + } + } + } + } + } + // kanban view + .o_kanban_view{ + .o_kanban_record{ + margin: 14px 5px 0px !important; + border-radius: 15px; + .oe_kanban_card,.oe_kanban_global_click{ + border-radius: 8px; + border-color: #2828286e; + border: 1px solid #28282812; + box-shadow: 0px 3px 4px 0px rgba(0, 0, 0, 0.03); + padding: 14px; + } + } + } + // list view + .o_list_view.o_action{ + height: 100%; + .o_content{ + padding: 10px 14px; + } + .o_list_renderer{ + border: 0px !important; + border-radius: 8px; + box-shadow: 0px 0px 3px #919191; + .o_list_table{ + table-layout: auto !important; + thead{ + th{ + padding: 10px 12px; + background-color: #282828; + color: #fff !important; + button{ + color: #fff !important; + } + .form-check-input{ + background-color: #fff !important; + } + } + } + tbody{ + tr{ + border-color: #28282899; + border: none ; + td{ + border: none; + padding: 14px 12px; + color: #282828 !important; + font-size: 15px !important; + font-weight: 500; + } + &.o_data_row{ + border-bottom-width: 1px !important; + border-bottom-style: dashed !important; + } + } + box-shadow: 0px 1px 2px #e2e2e2; + border-radius: 12px; + } + tfoot{ + tr{ + td{ + border: none; + padding: 10px 12px; + color: #282828 !important; + } + } + } + } + .form-check{ + .form-check-input{ + &:checked{ + background-color: #282828 !important; + border-color: #282828 !important; + } + } + } + } + } + // graph view + .o_graph_view { + .o_content { + height: calc(100vh - 100px); + } + } + // discuss view + .o-mail-Discuss{ + background: #fff !important; + .o-mail-DiscussSidebar{ + margin: 7px; + border: none !important; + box-shadow: 0px 1px 4px #9191912e; + border-radius: 14px; + .o-mail-DiscussSidebar-item{ + background: #e3e3e39e; + color: #282828 !important; + border-radius: 7px !important; + margin: 5px 10px; + padding: 10px 0 !important; + font-weight: 600 !important; + } + } + .o-mail-Discuss-content{ + overflow: scroll !important; + .o-mail-Discuss-header{ + border-bottom: none !important; + } + .o-mail-Thread{ + overflow: scroll; + margin: 7px; + box-shadow: 0px 0px 6px #413d3d3b !important; + border: 1px solid #28282800; + border-radius: 14px; + //msg section + .o-mail-Message{ + margin-top: 16px !important; + .o-mail-Message-core{ + //right content / msg content + .o-min-width-0{ + .o-mail-Message-header{ + .o-mail-Message-author{ + font-size: 16px; + margin: 8px 0px; + } + } + .o-mail-Message-content{ + .o-mail-Message-bubble{ + border-radius: 0px 10px 6px 10px !important; + .o-mail-Message-body{ + padding: 15px 25px !important; + } + } + } + } + } + } + } + .o-mail-Composer{ + .o-mail-Composer-coreMain{ + .btn{ + color: #282828 !important; + } + .o-mail-Composer-send{ + background: #282828 !important; + margin: 0 !important; + opacity: 1; + color: #fff !important; + } + + } + } + } + } + } + #terabits-link{ + h2{ + padding: 12px 28px; + background: #eee; + font-size: 15px !important; + } + } + } + } + &.editor_has_snippets_hide_backend_navbar{ + .nav-wrapper-bits{ + display: none; + } + } +} +.menu { + display: block; + width: 250px; + height: 100%; + transition: all 0.45s cubic-bezier(0.77, 0, 0.175, 1); + z-index: 999; + .icon { + position: absolute; + top: 12px; + right: 10px; + pointer-events: none; + width: 24px; + height: 24px; + color: #fff; + } + a { + display: block; + white-space: nowrap; + } +} + +.menu, +.menu a, +.menu a:visited { + color: #aaa; + text-decoration: none!important; + position: relative; +} +.new-wrapper { + position: absolute; + left: 50px; + width: calc(100% - 50px); + transition: transform .45s cubic-bezier(0.77, 0, 0.175, 1); +} + +#menu:checked + ul.menu-dropdown { + left: 0; + -webkit-animation: all .45s cubic-bezier(0.77, 0, 0.175, 1); + animation: all .45s cubic-bezier(0.77, 0, 0.175, 1); +} +.sub-menu-checkbox:checked + ul.sub-menu-dropdown { + display: block!important; + -webkit-animation: grow .45s cubic-bezier(0.77, 0, 0.175, 1); + animation: grow .45s cubic-bezier(0.77, 0, 0.175, 1); +} +.openNav .new-wrapper { + position: absolute; + transform: translate3d(200px, 0, 0); + width: calc(100% - 250px); + transition: transform .45s cubic-bezier(0.77, 0, 0.175, 1); +} + +.downarrow { + background: transparent; + position: absolute; + right: 50px; + top: 12px; + color: #777; + width: 24px; + height: 24px; + text-align: center; + display: block; +} +.downarrow:hover { + color: #fff; +} +.menu-dropdown { + top: 0; + overflow-y: auto; +} +.overflow-container { + position: relative; + height: 100% !important; + overflow-y: auto; + z-index: -1; + display:block; +} +.sub-menu-dropdown { + background-color: #333; +} +.openNav .menu { + top: 73px; + transform: translate3d(200px, 0, 0); + transition: transform .45s cubic-bezier(0.77, 0, 0.175, 1); +} + +/* look and feel only, not needed for core menu*/ + +@-webkit-keyframes grow { + + 0% { + display: none; + opacity: 0; + } + 50% { + display: block; + opacity: 0.5; + } + 100% { + opacity: 1; + } + +} + +@keyframes grow { + + 0% { + display: none; + opacity: 0; + } + 50% { + display: block; + opacity: 0.5; + } + 100% { + opacity: 1 + } + +} \ No newline at end of file diff --git a/clarity_backend_theme_bits/static/src/scss/login.scss b/clarity_backend_theme_bits/static/src/scss/login.scss new file mode 100644 index 000000000..649d9262d --- /dev/null +++ b/clarity_backend_theme_bits/static/src/scss/login.scss @@ -0,0 +1,69 @@ +#wrapwrap{ + .login-view-bits{ + .oe_login_form,.oe_signup_form,.oe_reset_password_form{ + .input-group{ + a.btn{ + background-color: #282828; + color: #fff !important; + border-radius: 0px 8px 8px 0px !important; + display: flex !important; + align-items: center; + i{ + color: #fff !important; + padding-left: 5px; + margin-top: -4px; + } + } + } + input,.form-control{ + display: block; + width: 100%; + padding: 0.775rem 1rem; + font-size: 1.1rem; + font-weight: 500; + line-height: 1.5; + color: #4B5675; + appearance: none; + background-clip: padding-box; + border: 1px solid #DBDFE9; + border-radius: 0.475rem; + transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; + &#db{ + border-radius: 8px 0px 0px 8px !important; + } + } + .col-form-label,.form-label{ + font-size: 14px !important; + font-weight: bold !important; + } + } + .card-body{ + box-shadow: 0px 0px 10px #d2d1d1; + border-radius: 30px; + } + .oe_login_buttons{ + .btn-primary[type=submit]{ + padding: 14px; + border-radius: 8px; + background: #282828; + color: #fff; + font-size: 14px; + &:hover,&:active,&:focus{ + color: #282828; + background: #fff; + border: 1px solid #282828; + } + } + a,button.btn{ + font-size: 12px; + font-weight: 600; + } + } + div.small{ + a,button.btn{ + font-size: 12px; + font-weight: 600; + } + } + } +} \ No newline at end of file diff --git a/clarity_backend_theme_bits/static/src/scss/navbar.scss b/clarity_backend_theme_bits/static/src/scss/navbar.scss new file mode 100644 index 000000000..d2b5f4933 --- /dev/null +++ b/clarity_backend_theme_bits/static/src/scss/navbar.scss @@ -0,0 +1,211 @@ +body.o_web_client{ + .nav-wrapper-bits{ + display: none ; + &.toggle-show{ + display: flex; + flex-direction: column; + justify-content: space-between; + background-color: #282828; + height: 100%; + z-index: 999; + header{ + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + } + .sytray-container-bits{ + margin: 5px 5px; + background-color: none !important; + button{ + width: 100%; + border: none !important; + box-shadow: none !important; + background: #343434; + border-radius: 10px; + img{ + width: 35px; + border-radius: 30px !important; + } + } + mark{ + font-size: 14px; + margin-top: 8px; + background: #fff !important; + padding: 7px; + border-radius: 8px; + } + .o_user_menu{ + .o-dropdown--menu{ + min-width: 15rem !important; + .dropdown-item{ + padding: 5px 20px !important; + } + } + } + .powered-by{ + display: none; + } + &:hover{ + .powered-by{ + display: block !important; + color: #fff; + a{ + color: #aab6ff !important; + } + } + } + } + } + .btm-user-menu{ + z-index: 999; + width: 250px; + } + @media (max-width: 768px) { + position: absolute; + top: 0; + bottom: 0; + height: 100%; + z-index: 11; + } + } + header.o_navbar{ + nav{ + background-color: transparent !important; + border-bottom: none !important; + } + .o_company_logo{ + padding: 8px 20px !important; + display: flex; + align-items: center; + justify-content: space-between; + background: #343434; + border-radius: 10px; + margin: 5px 5px; + i{ + color: #fff !important; + font-size: 20px; + display: none; + @media (max-width: 768px) { + display: block; + } + } + img{ + width: 150px; + height: 70px; + object-fit: contain; + } + } + } + .primary-nav{ + flex: 1 1 0 !important; + overflow-y: auto; + .overflow-container{ + .main_link{ + .app_icon{ + height: 25px !important; + width: 25px !important; + display: inline-flex; + img{ + object-fit: contain; + } + } + } + } + ul#menu-dropdown{ + list-style-type: none !important; + padding-left: 5px !important; + li a.main_link{ + display: flex; + align-items: center !important; + padding: 1em; + font-size: 14px; + } + ul.header-sub-menus.main{ + list-style-type: none !important; + z-index: 3; + position: absolute; + left: 0; + background-color: #282828 !important; + height: 100%; + top: 0; + width: 100%; + padding: 0px 12px; + // &:not(.show){ + // left: 100% !important; + // } + &:not(.show){ + display: none; + width: 0% ; + } + .back_main_menu{ + position: relative; + margin-left: -18px; + h3{ + color: #ffff !important; + cursor: pointer; + } + } + li{ + margin-left: 10px ; + background: #282828; + .header-sub-menus{ + list-style-type: none !important; + border-left: 1px solid #717171; + padding: 0; + } + .sub-main-menu{ + cursor: pointer !important; + font-size: 14px; + color: #fff; + font-weight: 600; + background: #282828; + } + } + @media (max-width: 768px) { + position: relative !important; + .back_main_menu{ + display: none !important; + } + } + // &.show{ + // li{ + // .collapse{ + // display: block; + // } + // } + // } + a{ + padding: 0.5rem !important; + font-size: 12px !important; + } + &.show{ + li{ + .sub-main-menu{ + background: #eeeeee14; + padding: 5px 10px !important; + border-radius: 8px; + margin: 8px 0px; + } + } + } + } + } + ::-webkit-scrollbar-track + { + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); + background-color: #F5F5F5; + } + + ::-webkit-scrollbar + { + width: 6px; + background-color: #F5F5F5; + } + + ::-webkit-scrollbar-thumb + { + background-color: #575757; + } + } +} \ No newline at end of file diff --git a/clarity_backend_theme_bits/static/src/xml/WebClient.xml b/clarity_backend_theme_bits/static/src/xml/WebClient.xml new file mode 100644 index 000000000..9525b68c1 --- /dev/null +++ b/clarity_backend_theme_bits/static/src/xml/WebClient.xml @@ -0,0 +1,42 @@ + + + + + + + +
+ +
+ + + + + + +
+
+
+
+ +
diff --git a/clarity_backend_theme_bits/static/src/xml/navbar/sidebar.xml b/clarity_backend_theme_bits/static/src/xml/navbar/sidebar.xml new file mode 100644 index 000000000..70c58155e --- /dev/null +++ b/clarity_backend_theme_bits/static/src/xml/navbar/sidebar.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/clarity_backend_theme_bits/static/src/xml/systray_items/user_menu.xml b/clarity_backend_theme_bits/static/src/xml/systray_items/user_menu.xml new file mode 100644 index 000000000..bcfdf45df --- /dev/null +++ b/clarity_backend_theme_bits/static/src/xml/systray_items/user_menu.xml @@ -0,0 +1,65 @@ + + + + + + User + + + + +
+ + +
+
+
+ +
+ + + +
+
+ + + +
+
+ Powered ByTerabits Technolab +
+
+
+ + + + + + + + + + + + + + + + + + + diff --git a/clarity_backend_theme_bits/views/res_config_setting.xml b/clarity_backend_theme_bits/views/res_config_setting.xml new file mode 100644 index 000000000..7b63614ef --- /dev/null +++ b/clarity_backend_theme_bits/views/res_config_setting.xml @@ -0,0 +1,29 @@ + + + + res.config.settings.view.form.inherit.base + res.config.settings + + + + + + + + + \ No newline at end of file diff --git a/clarity_backend_theme_bits/views/res_users.xml b/clarity_backend_theme_bits/views/res_users.xml new file mode 100644 index 000000000..228eabe9d --- /dev/null +++ b/clarity_backend_theme_bits/views/res_users.xml @@ -0,0 +1,23 @@ + + + + res.users.form + res.users + + + + +
Don't know how to set correct access rights for multiple users?
+
+
+
Easily set with Simplify Access Management app.
+
+ Live demo available + Access Here. +
+
+
+
+
+
+
\ No newline at end of file diff --git a/clarity_backend_theme_bits/views/webclient_templates.xml b/clarity_backend_theme_bits/views/webclient_templates.xml new file mode 100644 index 000000000..9be923e04 --- /dev/null +++ b/clarity_backend_theme_bits/views/webclient_templates.xml @@ -0,0 +1,32 @@ + + + + + + diff --git a/database_activation_code/README.md b/database_activation_code/README.md new file mode 100644 index 000000000..53e664184 --- /dev/null +++ b/database_activation_code/README.md @@ -0,0 +1,5 @@ +允许通过激活码延长数据库过期时间 + +增加database.partner,数据库合作伙伴系统参数以区分客户 + +此模块为客户使用模块,还有一个激活码签发模块。 \ No newline at end of file diff --git a/database_activation_code/__init__.py b/database_activation_code/__init__.py new file mode 100644 index 000000000..b19ab1b09 --- /dev/null +++ b/database_activation_code/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2014-2016 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import models diff --git a/database_activation_code/__manifest__.py b/database_activation_code/__manifest__.py new file mode 100644 index 000000000..c4390e00e --- /dev/null +++ b/database_activation_code/__manifest__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +{ + "name": "数据库过期时间激活码", + "description": """ +允许通过激活码延长数据库过期时间 + """, + "author": "songbo", + "website": "https://www.pengyuthon.com/", + "category": "Customizations/Studio", + "version": "17.0.0.1", + "depends": ["web_enterprise", "mail"], + "external_dependencies": { + "python": ["rsa"], + }, + "data": ["data/account_report_actions.xml"], + "assets": { + "web.assets_backend": [ + "database_activation_code/static/src/webclient/**/*.xml", + ], + }, + "installable": True, + "auto_install": False, +} diff --git a/database_activation_code/data/account_report_actions.xml b/database_activation_code/data/account_report_actions.xml new file mode 100644 index 000000000..aadebe4bd --- /dev/null +++ b/database_activation_code/data/account_report_actions.xml @@ -0,0 +1,7 @@ + + + + database.partner + base + + diff --git a/database_activation_code/models/__init__.py b/database_activation_code/models/__init__.py new file mode 100644 index 000000000..9e0360ae0 --- /dev/null +++ b/database_activation_code/models/__init__.py @@ -0,0 +1,2 @@ +from . import update +from . import ir_http diff --git a/database_activation_code/models/ir_http.py b/database_activation_code/models/ir_http.py new file mode 100644 index 000000000..be3fcc99d --- /dev/null +++ b/database_activation_code/models/ir_http.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import json + +from odoo import models +from odoo.http import request + + +class Http(models.AbstractModel): + _inherit = "ir.http" + + def session_info(self): + ICP = self.env["ir.config_parameter"].sudo() + User = self.env["res.users"] + + if User.has_group("base.group_system"): + warn_enterprise = "admin" + elif User.has_group("base.group_user"): + warn_enterprise = "user" + else: + warn_enterprise = False + + result = super(Http, self).session_info() + result["support_url"] = "https://www.pengyuthon.com//help" + if warn_enterprise: + result["warning"] = warn_enterprise + result["expiration_date"] = ICP.get_param("database.expiration_date") + result["expiration_reason"] = ICP.get_param("database.expiration_reason") + return result diff --git a/database_activation_code/models/update.py b/database_activation_code/models/update.py new file mode 100644 index 000000000..1ba18a8b4 --- /dev/null +++ b/database_activation_code/models/update.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import datetime +import logging +import rsa +import base64 +from os.path import join as opj +from odoo.modules import get_module_path + +from odoo import api, release, SUPERUSER_ID +from odoo.exceptions import UserError +from odoo.models import AbstractModel + +_logger = logging.getLogger(__name__) + + +class PublisherWarrantyContract(AbstractModel): + _inherit = "publisher_warranty.contract" + + # rsa解密 + def rsaDecrypt(self, str1): + modpath = get_module_path("database_activation_code") + file_path = opj(modpath, "static", "privkey.pem") + with open(file_path) as privatefile: + p = privatefile.read() + # 验证密钥 + try: + privkey = rsa.PrivateKey.load_pkcs1(p) + except: + raise UserError("请联系管理员!") + + try: + str1 = base64.b16decode(str1) + # 私钥解密 + content = rsa.decrypt(str1, privkey) + con = content.decode("utf-8").split("#") + if len(con) != 2: + raise + database_partner = con[0] + old_database_partner = ( + self.sudo().env["ir.config_parameter"].get_param("database.partner") + ) + if database_partner != old_database_partner: + raise + + expiration_date = con[1] + old_enterprise_code = ( + self.sudo() + .env["ir.config_parameter"] + .get_param("database.expiration_date") + ) + except: + raise UserError("激活码错误") + + if expiration_date <= old_enterprise_code: + raise UserError("激活码已过期") + # 设置过期时间 + set_param = self.env["ir.config_parameter"].sudo().set_param + set_param("database.expiration_date", expiration_date) + + def update_notification(self, cron_mode=True): + # 获取激活码 + enterprise_code = ( + self.sudo().env["ir.config_parameter"].get_param("database.enterprise_code") + ) + if enterprise_code: + try: + enterprise_code = str.encode(enterprise_code) + except: + raise UserError("激活码错误") + # 验证激活码 + self.rsaDecrypt(enterprise_code) + return True diff --git a/database_activation_code/static/privkey.pem b/database_activation_code/static/privkey.pem new file mode 100644 index 000000000..118958cc9 --- /dev/null +++ b/database_activation_code/static/privkey.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBAIfrf/oF/janGFgNeu0Y3YWoVg9SB3msMhfKq6q4G1t9gqdodLYs +oc2vNgUd7689231R+vvLGdKzBizDJZVh3tMCAwEAAQJAZTKvX1108AYrNuwaeUuJ +K8mxAckmba4KwfIRLJPUxvUvrKDkRwmQCNQ6/FF8UFiYexwu19wOPSYsdiq4b6eT +qQIjAJCfBBtskYgfT0qdcPu9NlE++vyTG/QZVlXOCEIr4WcB7BUCHwDwmPrY/nOU +nek6/QawqfkUZh7SO7rc/5KMp6V8EUcCImWpMmTow8CxabakyAheMLGaGSq1aqAD +s5nrlAiX+gHD6yUCHwDPZjAmygF8RTt9/Au+UmdCbF15QL/uLel4kjOW5ZUCImOr +yrfsjcjVr3+nXOqYdR+/Q+6q6sMBRC1Nn2+pbgI5dRY= +-----END RSA PRIVATE KEY----- diff --git a/database_activation_code/static/src/webclient/home_menu/expiration_panel.xml b/database_activation_code/static/src/webclient/home_menu/expiration_panel.xml new file mode 100644 index 000000000..60dc0f597 --- /dev/null +++ b/database_activation_code/static/src/webclient/home_menu/expiration_panel.xml @@ -0,0 +1,10 @@ + + + + + + 联系我们. + + + +