diff --git a/muk_web_appsbar/LICENSE b/muk_web_appsbar/LICENSE deleted file mode 100644 index 0a041280b..000000000 --- a/muk_web_appsbar/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/muk_web_appsbar/__init__.py b/muk_web_appsbar/__init__.py deleted file mode 100644 index df1b93441..000000000 --- a/muk_web_appsbar/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from . import models - -import base64 - -from odoo.tools import file_open - - -def _setup_module(env): - if env.ref('base.main_company', False): - with file_open('base/static/img/res_company_logo.png', 'rb') as file: - env.ref('base.main_company').write({ - 'appbar_image': base64.b64encode(file.read()) - }) - \ No newline at end of file diff --git a/muk_web_appsbar/__manifest__.py b/muk_web_appsbar/__manifest__.py deleted file mode 100644 index 0b0829c8d..000000000 --- a/muk_web_appsbar/__manifest__.py +++ /dev/null @@ -1,72 +0,0 @@ -{ - 'name': 'MuK AppsBar', - 'summary': 'Adds a sidebar to the main screen', - 'description': ''' - This module adds a sidebar to the main screen. The sidebar has a list - of all installed apps similar to the home menu to ease navigation. - ''', - 'version': '17.0.1.1.1', - 'category': 'Tools/UI', - 'license': 'LGPL-3', - 'author': 'MuK IT', - 'website': 'http://www.mukit.at', - 'live_test_url': 'https://mukit.at/demo', - 'contributors': [ - 'Mathias Markl ', - ], - 'depends': [ - 'base_setup', - 'web', - ], - 'data': [ - 'templates/webclient.xml', - 'views/res_users.xml', - 'views/res_config_settings.xml', - ], - 'assets': { - 'web._assets_primary_variables': [ - 'muk_web_appsbar/static/src/scss/variables.scss', - ], - 'web._assets_backend_helpers': [ - 'muk_web_appsbar/static/src/scss/mixins.scss', - ], - 'web.assets_web_dark': [ - ( - 'after', - 'muk_web_appsbar/static/src/scss/variables.scss', - 'muk_web_appsbar/static/src/scss/variables.dark.scss', - ), - ], - 'web.assets_backend': [ - ( - 'after', - 'web/static/src/webclient/webclient.js', - 'muk_web_appsbar/static/src/webclient/webclient.js', - ), - ( - 'after', - 'web/static/src/webclient/webclient.xml', - 'muk_web_appsbar/static/src/webclient/webclient.xml', - ), - ( - 'after', - 'web/static/src/webclient/webclient.js', - 'muk_web_appsbar/static/src/webclient/menus/app_menu_service.js', - ), - ( - 'after', - 'web/static/src/webclient/webclient.js', - 'muk_web_appsbar/static/src/webclient/appsbar/appsbar.js', - ), - 'muk_web_appsbar/static/src/webclient/appsbar/appsbar.xml', - 'muk_web_appsbar/static/src/webclient/appsbar/appsbar.scss', - ], - }, - 'images': [ - 'static/description/banner.png', - ], - 'installable': True, - 'application': False, - 'auto_install': False, - 'post_init_hook': '_setup_module', -} diff --git a/muk_web_appsbar/doc/changelog.rst b/muk_web_appsbar/doc/changelog.rst deleted file mode 100644 index 659d822e0..000000000 --- a/muk_web_appsbar/doc/changelog.rst +++ /dev/null @@ -1,9 +0,0 @@ -`1.1.0` -------- - -- Use CSS Grid - -`1.0.0` -------- - -- Initial Release diff --git a/muk_web_appsbar/doc/index.rst b/muk_web_appsbar/doc/index.rst deleted file mode 100644 index 8f6f787e3..000000000 --- a/muk_web_appsbar/doc/index.rst +++ /dev/null @@ -1,59 +0,0 @@ -=========== -MuK AppsBar -=========== - -This module adds a sidebar to the main screen. The sidebar has a list -of all installed apps similar to the home menu to ease navigation. - -Installation -============ - -To install this module, you need to: - -Download the module and add it to your Odoo addons folder. Afterward, log on to -your Odoo server and go to the Apps menu. Trigger the debug mode and update the -list by clicking on the "Update Apps List" link. Now install the module by -clicking on the install button. - -Upgrade -============ - -To upgrade this module, you need to: - -Download the module and add it to your Odoo addons folder. Restart the server -and log on to your Odoo server. Select the Apps menu and upgrade the module by -clicking on the upgrade button. - -Configuration -============= - -Each user can define in their profile the display of the sidebar. The options -are to show the large version, the small version, or hide the sidebar completely. -In addition, an image can be added for each company, which is displayed at the -bottom of the sidebar. - -Usage -============= - -Is the sidebar is activated it will be automatically displayed on the left side of -the systems UI. - -Credits -======= - -Contributors ------------- - -* Mathias Markl - -Author & Maintainer -------------------- - -This module is maintained by the `MuK IT GmbH `_. - -MuK IT is an Austrian company specialized in customizing and extending Odoo. -We develop custom solutions for your individual needs to help you focus on -your strength and expertise to grow your business. - -If you want to get in touch please contact us via mail -(sale@mukit.at) or visit our website (https://mukit.at). diff --git a/muk_web_appsbar/i18n/de.po b/muk_web_appsbar/i18n/de.po deleted file mode 100644 index a9410bca4..000000000 --- a/muk_web_appsbar/i18n/de.po +++ /dev/null @@ -1,79 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * muk_web_appsbar -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 17.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-29 16:14+0000\n" -"PO-Revision-Date: 2023-11-29 16:14+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: muk_web_appsbar -#: model:ir.model.fields,field_description:muk_web_appsbar.field_res_company__appbar_image -#: model:ir.model.fields,field_description:muk_web_appsbar.field_res_config_settings__appbar_image -msgid "Apps Menu Footer Image" -msgstr "Apps Menü Fusszeilen Bild" - -#. module: muk_web_appsbar -#: model_terms:ir.ui.view,arch_db:muk_web_appsbar.view_res_config_settings_form -msgid "AppsBar" -msgstr "AppsLeiste" - -#. module: muk_web_appsbar -#: model:ir.model,name:muk_web_appsbar.model_res_company -msgid "Companies" -msgstr "Unternehmen" - -#. module: muk_web_appsbar -#: model:ir.model,name:muk_web_appsbar.model_res_config_settings -msgid "Config Settings" -msgstr "Konfigurationseinstellungen" - -#. module: muk_web_appsbar -#: model:ir.model,name:muk_web_appsbar.model_ir_http -msgid "HTTP Routing" -msgstr "HTTP-Routing" - -#. module: muk_web_appsbar -#: model:ir.model.fields.selection,name:muk_web_appsbar.selection__res_users__sidebar_type__invisible -msgid "Invisible" -msgstr "Unsichtbar" - -#. module: muk_web_appsbar -#: model:ir.model.fields.selection,name:muk_web_appsbar.selection__res_users__sidebar_type__large -msgid "Large" -msgstr "Groß" - -#. module: muk_web_appsbar -#. odoo-javascript -#: code:addons/muk_web_appsbar/static/src/webclient/appsbar/appsbar.xml:0 -#, python-format -msgid "Logo" -msgstr "Logo" - -#. module: muk_web_appsbar -#: model_terms:ir.ui.view,arch_db:muk_web_appsbar.view_res_config_settings_form -msgid "Set your own Logo for the appsbar" -msgstr "Legen Sie ihr eigenes Logo für die Appsleiste fest" - -#. module: muk_web_appsbar -#: model:ir.model.fields,field_description:muk_web_appsbar.field_res_users__sidebar_type -msgid "Sidebar Type" -msgstr "Seitenleiste Typ" - -#. module: muk_web_appsbar -#: model:ir.model.fields.selection,name:muk_web_appsbar.selection__res_users__sidebar_type__small -msgid "Small" -msgstr "Klein" - -#. module: muk_web_appsbar -#: model:ir.model,name:muk_web_appsbar.model_res_users -msgid "User" -msgstr "Benutzer" diff --git a/muk_web_appsbar/models/__init__.py b/muk_web_appsbar/models/__init__.py deleted file mode 100644 index 49f6c60bd..000000000 --- a/muk_web_appsbar/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import ir_http -from . import res_users -from . import res_company -from . import res_config_settings diff --git a/muk_web_appsbar/models/ir_http.py b/muk_web_appsbar/models/ir_http.py deleted file mode 100644 index 2c6a7231d..000000000 --- a/muk_web_appsbar/models/ir_http.py +++ /dev/null @@ -1,20 +0,0 @@ -from odoo import models -from odoo.http import request - - -class IrHttp(models.AbstractModel): - - _inherit = "ir.http" - - #---------------------------------------------------------- - # Functions - #---------------------------------------------------------- - - def session_info(self): - result = super(IrHttp, self).session_info() - if request.env.user._is_internal(): - for company in request.env.user.company_ids.with_context(bin_size=True): - result['user_companies']['allowed_companies'][company.id].update({ - 'has_appsbar_image': bool(company.appbar_image), - }) - return result diff --git a/muk_web_appsbar/models/res_company.py b/muk_web_appsbar/models/res_company.py deleted file mode 100644 index b55d9afda..000000000 --- a/muk_web_appsbar/models/res_company.py +++ /dev/null @@ -1,15 +0,0 @@ -from odoo import models, fields - - -class ResCompany(models.Model): - - _inherit = 'res.company' - - #---------------------------------------------------------- - # Fields - #---------------------------------------------------------- - - appbar_image = fields.Binary( - string='Apps Menu Footer Image', - attachment=True - ) diff --git a/muk_web_appsbar/models/res_config_settings.py b/muk_web_appsbar/models/res_config_settings.py deleted file mode 100644 index 94e72feee..000000000 --- a/muk_web_appsbar/models/res_config_settings.py +++ /dev/null @@ -1,15 +0,0 @@ -from odoo import api, fields, models - - -class ResConfigSettings(models.TransientModel): - - _inherit = 'res.config.settings' - - #---------------------------------------------------------- - # Fields - #---------------------------------------------------------- - - appbar_image = fields.Binary( - related='company_id.appbar_image', - readonly=False - ) diff --git a/muk_web_appsbar/models/res_users.py b/muk_web_appsbar/models/res_users.py deleted file mode 100644 index 06f821091..000000000 --- a/muk_web_appsbar/models/res_users.py +++ /dev/null @@ -1,37 +0,0 @@ -from odoo import models, fields, api - - -class ResUsers(models.Model): - - _inherit = 'res.users' - - #---------------------------------------------------------- - # Properties - #---------------------------------------------------------- - - @property - def SELF_READABLE_FIELDS(self): - return super().SELF_READABLE_FIELDS + [ - 'sidebar_type', - ] - - @property - def SELF_WRITEABLE_FIELDS(self): - return super().SELF_WRITEABLE_FIELDS + [ - 'sidebar_type', - ] - - #---------------------------------------------------------- - # Fields - #---------------------------------------------------------- - - sidebar_type = fields.Selection( - selection=[ - ('invisible', 'Invisible'), - ('small', 'Small'), - ('large', 'Large') - ], - string="Sidebar Type", - default='large', - required=True, - ) diff --git a/muk_web_appsbar/static/description/banner.png b/muk_web_appsbar/static/description/banner.png deleted file mode 100644 index d00c06a1a..000000000 Binary files a/muk_web_appsbar/static/description/banner.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/icon.png b/muk_web_appsbar/static/description/icon.png deleted file mode 100644 index fa9ac0efb..000000000 Binary files a/muk_web_appsbar/static/description/icon.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/icon.svg b/muk_web_appsbar/static/description/icon.svg deleted file mode 100644 index 9518f0e06..000000000 --- a/muk_web_appsbar/static/description/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/muk_web_appsbar/static/description/index.html b/muk_web_appsbar/static/description/index.html deleted file mode 100644 index 5c48b09ec..000000000 --- a/muk_web_appsbar/static/description/index.html +++ /dev/null @@ -1,139 +0,0 @@ -
-
-

MuK Colors

-

Customize your Odoo colors

- -

MuK IT GmbH - www.mukit.at

-
- - Community - - - Enterprise - -
-
- -
-
-
- -
-
-
-

Overview

-

- This module adds a sidebar to the main screen. The sidebar has a list of all - installed apps similar to the home menu to ease navigation. Each user can define - in their profile the display of the sidebar. The options are to show the large - version, the small version, or hide the sidebar completely. In addition, an image - can be added for each company, which is displayed at the bottom of the sidebar. -

-
-
-
- -
-
-

- Want more? -

-

- Are you having troubles with your Odoo integration? Or do you feel - your system lacks of essential features?
If your answer is YES - to one of the above questions, feel free to contact us at anytime - with your inquiry.
We are looking forward to discuss your - needs and plan the next steps with you.
-

-
- -
- -
-
-

Our Services

-
-
-
-
- -
-

- Odoo
Development -

-
-
-
-
-
- -
-

- Odoo
Integration -

-
-
-
-
-
- -
-

- Odoo
Infrastructure -

-
-
-
-
-
- -
-

- Odoo
Training -

-
-
-
-
-
- -
-

- Odoo
Support -

-
-
-
-
-
diff --git a/muk_web_appsbar/static/description/logo.png b/muk_web_appsbar/static/description/logo.png deleted file mode 100644 index 9427ce33e..000000000 Binary files a/muk_web_appsbar/static/description/logo.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/screenshot.png b/muk_web_appsbar/static/description/screenshot.png deleted file mode 100644 index 66e6a72d6..000000000 Binary files a/muk_web_appsbar/static/description/screenshot.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/service_development.png b/muk_web_appsbar/static/description/service_development.png deleted file mode 100644 index d64b66bda..000000000 Binary files a/muk_web_appsbar/static/description/service_development.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/service_infrastructure.png b/muk_web_appsbar/static/description/service_infrastructure.png deleted file mode 100644 index b899a3104..000000000 Binary files a/muk_web_appsbar/static/description/service_infrastructure.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/service_integration.png b/muk_web_appsbar/static/description/service_integration.png deleted file mode 100644 index 76c5e80f4..000000000 Binary files a/muk_web_appsbar/static/description/service_integration.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/service_support.png b/muk_web_appsbar/static/description/service_support.png deleted file mode 100644 index 4c530fafd..000000000 Binary files a/muk_web_appsbar/static/description/service_support.png and /dev/null differ diff --git a/muk_web_appsbar/static/description/service_training.png b/muk_web_appsbar/static/description/service_training.png deleted file mode 100644 index 19ea76e63..000000000 Binary files a/muk_web_appsbar/static/description/service_training.png and /dev/null differ diff --git a/muk_web_appsbar/static/src/scss/mixins.scss b/muk_web_appsbar/static/src/scss/mixins.scss deleted file mode 100644 index dcd23ea4b..000000000 --- a/muk_web_appsbar/static/src/scss/mixins.scss +++ /dev/null @@ -1,7 +0,0 @@ -@mixin mk-disable-scrollbar { - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } -} diff --git a/muk_web_appsbar/static/src/scss/variables.dark.scss b/muk_web_appsbar/static/src/scss/variables.dark.scss deleted file mode 100644 index c773cdc6a..000000000 --- a/muk_web_appsbar/static/src/scss/variables.dark.scss +++ /dev/null @@ -1,2 +0,0 @@ -$mk-appbar-color: #E4E4E4 !default; -$mk-appbar-background: #3C3E4B !default; diff --git a/muk_web_appsbar/static/src/scss/variables.scss b/muk_web_appsbar/static/src/scss/variables.scss deleted file mode 100644 index 19921046e..000000000 --- a/muk_web_appsbar/static/src/scss/variables.scss +++ /dev/null @@ -1,6 +0,0 @@ -$mk-appbar-color: #dee2e6 !default; -$mk-appbar-active: $o-brand-primary !default; -$mk-appbar-background: #111827 !default; - -$mk-sidebar-large-width: 146px !default; -$mk-sidebar-small-width: 46px !default; diff --git a/muk_web_appsbar/static/src/webclient/appsbar/appsbar.js b/muk_web_appsbar/static/src/webclient/appsbar/appsbar.js deleted file mode 100644 index b4d2b7a83..000000000 --- a/muk_web_appsbar/static/src/webclient/appsbar/appsbar.js +++ /dev/null @@ -1,33 +0,0 @@ -/** @odoo-module **/ - -import { url } from '@web/core/utils/urls'; -import { useService } from '@web/core/utils/hooks'; - -import { Component, onWillUnmount } from '@odoo/owl'; - -export class AppsBar extends Component { - static template = 'muk_web_appsbar.AppsBar'; - static props = {}; - setup() { - this.companyService = useService('company'); - this.appMenuService = useService('app_menu'); - if (this.companyService.currentCompany.has_appsbar_image) { - this.sidebarImageUrl = url('/web/image', { - model: 'res.company', - field: 'appbar_image', - id: this.companyService.currentCompany.id, - }); - } - const renderAfterMenuChange = () => { - this.render(); - }; - this.env.bus.addEventListener( - 'MENUS:APP-CHANGED', renderAfterMenuChange - ); - onWillUnmount(() => { - this.env.bus.removeEventListener( - 'MENUS:APP-CHANGED', renderAfterMenuChange - ); - }); - } -} diff --git a/muk_web_appsbar/static/src/webclient/appsbar/appsbar.scss b/muk_web_appsbar/static/src/webclient/appsbar/appsbar.scss deleted file mode 100644 index 21be9a7e1..000000000 --- a/muk_web_appsbar/static/src/webclient/appsbar/appsbar.scss +++ /dev/null @@ -1,115 +0,0 @@ -.o_web_client { - display: grid !important; - grid-template-areas: - "banner banner" - "navbar navbar" - "sidebar content" - "components components"; - grid-template-rows: auto auto 1fr auto; - grid-template-columns: auto 1fr; - > div:has(#oe_neutralize_banner) { - grid-area: banner; - } - > .o_navbar { - grid-area: navbar; - } - > .mk_apps_sidebar_panel { - grid-area: sidebar; - } - > .o_action_manager { - grid-area: content; - } - > .o-main-components-container { - grid-area: components; - } -} - -.mk_apps_sidebar_panel { - @include mk-disable-scrollbar(); - background-color: $mk-appbar-background; - width: var(--mk-sidebar-width, 0); - overflow-y: auto; - .mk_apps_sidebar { - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - white-space: nowrap; - .mk_apps_sidebar_menu { - padding: 0; - > li > a { - cursor: pointer; - font-size: 13px; - font-weight: 300; - overflow: hidden; - padding: 8px 11px; - text-decoration: none; - color: $mk-appbar-color; - text-overflow: ellipsis; - .mk_apps_sidebar_icon { - width: 22px; - height: 22px; - margin-right: 5px; - } - } - > li.active > a { - background: $mk-appbar-active; - } - > li:hover > a { - background: $mk-appbar-active; - } - } - } -} - -.mk_sidebar_type_large { - --mk-sidebar-width: #{$mk-sidebar-large-width}; -} - -.mk_sidebar_type_small { - --mk-sidebar-width: #{$mk-sidebar-small-width}; - .mk_apps_sidebar_name { - display: none; - } - .mk_apps_sidebar_icon { - margin-right: 0 !important; - } - .mk_apps_sidebar_logo { - display: none; - } -} - -.mk_sidebar_type_invisible { - --mk-sidebar-width: 0; -} - -.editor_has_snippets_hide_backend_navbar, -.o_home_menu_background, -.o_fullscreen { - --mk-sidebar-width: 0; -} - -.editor_has_snippets_hide_backend_navbar .mk_apps_sidebar_panel { - transition: width 300ms; -} - -@include media-breakpoint-only(md) { - .mk_sidebar_type_large { - --mk-sidebar-width: #{$mk-sidebar-small-width}; - .mk_apps_sidebar_name { - display: none; - } - .mk_apps_sidebar_icon { - margin-right: 0 !important; - } - .mk_apps_sidebar_logo { - display: none; - } - } -} - -@include media-breakpoint-down(md) { - .mk_sidebar_type_large, .mk_sidebar_type_small { - --mk-sidebar-width: 0; - } -} diff --git a/muk_web_appsbar/static/src/webclient/appsbar/appsbar.xml b/muk_web_appsbar/static/src/webclient/appsbar/appsbar.xml deleted file mode 100644 index 99c3428d2..000000000 --- a/muk_web_appsbar/static/src/webclient/appsbar/appsbar.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - -
-
- - -
-
-
- -
diff --git a/muk_web_appsbar/static/src/webclient/menus/app_menu_service.js b/muk_web_appsbar/static/src/webclient/menus/app_menu_service.js deleted file mode 100644 index d261de494..000000000 --- a/muk_web_appsbar/static/src/webclient/menus/app_menu_service.js +++ /dev/null @@ -1,47 +0,0 @@ -/** @odoo-module **/ - -import { registry } from "@web/core/registry"; - -export const appMenuService = { - dependencies: ["menu"], - async start(env, { menu }) { - return { - getCurrentApp () { - return menu.getCurrentApp(); - }, - getAppsMenuItems() { - const menuItems = menu.getApps().map((item) => { - const appsMenuItem = { - id: item.id, - name: item.name, - xmlid: item.xmlid, - appID: item.appID, - actionID: item.actionID, - action: () => menu.selectMenu(item), - }; - if (item.webIconData) { - const prefix = ( - item.webIconData.startsWith('P') ? - 'data:image/svg+xml;base64,' : - 'data:image/png;base64,' - ); - appsMenuItem.webIconData = ( - item.webIconData.startsWith('data:image') ? - item.webIconData : - prefix + item.webIconData.replace(/\s/g, '') - ); - } - const hrefParts = [`menu_id=${item.id}`]; - if (item.actionID) { - hrefParts.push(`action=${item.actionID}`); - } - appsMenuItem.href = "#" + hrefParts.join("&"); - return appsMenuItem; - }); - return menuItems; - }, - }; - }, -}; - -registry.category("services").add("app_menu", appMenuService); diff --git a/muk_web_appsbar/static/src/webclient/navbar/navbar.js b/muk_web_appsbar/static/src/webclient/navbar/navbar.js deleted file mode 100644 index 1f2c0a117..000000000 --- a/muk_web_appsbar/static/src/webclient/navbar/navbar.js +++ /dev/null @@ -1,45 +0,0 @@ -/** @odoo-module */ - -import { patch } from '@web/core/utils/patch'; - -import { NavBar } from '@web/webclient/navbar/navbar'; -import { AppsBar } from '@muk_web_appsbar/webclient/appsbar/appsbar'; - -patch(NavBar.prototype, { - getAppsMenuItems() { - const currentApp = this.menuService.getCurrentApp(); - const menuItems = this.menuService.getApps().map((menu) => { - const appsMenuItem = { - id: menu.id, - name: menu.name, - xmlid: menu.xmlid, - appID: menu.appID, - actionID: menu.actionID, - href: this.getMenuItemHref(menu), - action: () => this.menuService.selectMenu(menu), - active: currentApp && menu.id === currentApp.id, - }; - if (menu.webIconData) { - const prefix = ( - menu.webIconData.startsWith('P') ? - 'data:image/svg+xml;base64,' : - 'data:image/png;base64,' - ); - appsMenuItem.webIconData = ( - menu.webIconData.startsWith('data:image') ? - menu.webIconData : - prefix + menu.webIconData.replace(/\s/g, '') - ); - } - return appsMenuItem; - }); - return menuItems; - }, -}); - -patch(NavBar, { - components: { - ...NavBar.components, - AppsBar, - }, -}); diff --git a/muk_web_appsbar/static/src/webclient/navbar/navbar.xml b/muk_web_appsbar/static/src/webclient/navbar/navbar.xml deleted file mode 100644 index 3915668a2..000000000 --- a/muk_web_appsbar/static/src/webclient/navbar/navbar.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/muk_web_appsbar/static/src/webclient/webclient.js b/muk_web_appsbar/static/src/webclient/webclient.js deleted file mode 100644 index 5e97fc72d..000000000 --- a/muk_web_appsbar/static/src/webclient/webclient.js +++ /dev/null @@ -1,13 +0,0 @@ -/** @odoo-module */ - -import { patch } from '@web/core/utils/patch'; - -import { WebClient } from '@web/webclient/webclient'; -import { AppsBar } from '@muk_web_appsbar/webclient/appsbar/appsbar'; - -patch(WebClient, { - components: { - ...WebClient.components, - AppsBar, - }, -}); diff --git a/muk_web_appsbar/static/src/webclient/webclient.xml b/muk_web_appsbar/static/src/webclient/webclient.xml deleted file mode 100644 index 45bd36f45..000000000 --- a/muk_web_appsbar/static/src/webclient/webclient.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/muk_web_appsbar/templates/webclient.xml b/muk_web_appsbar/templates/webclient.xml deleted file mode 100644 index 742f06dfc..000000000 --- a/muk_web_appsbar/templates/webclient.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/muk_web_appsbar/views/res_config_settings.xml b/muk_web_appsbar/views/res_config_settings.xml deleted file mode 100644 index 76edd1b6d..000000000 --- a/muk_web_appsbar/views/res_config_settings.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - res.config.settings.form - res.config.settings - - - - -
- -
-
-
-
-
- -
diff --git a/muk_web_appsbar/views/res_users.xml b/muk_web_appsbar/views/res_users.xml deleted file mode 100644 index 4897a4a12..000000000 --- a/muk_web_appsbar/views/res_users.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - res.users.form - res.users - - - - - - - - - diff --git a/muk_web_chatter/LICENSE b/muk_web_chatter/LICENSE deleted file mode 100644 index 0a041280b..000000000 --- a/muk_web_chatter/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/muk_web_chatter/__init__.py b/muk_web_chatter/__init__.py deleted file mode 100644 index 0650744f6..000000000 --- a/muk_web_chatter/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import models diff --git a/muk_web_chatter/__manifest__.py b/muk_web_chatter/__manifest__.py deleted file mode 100644 index 6bf2db027..000000000 --- a/muk_web_chatter/__manifest__.py +++ /dev/null @@ -1,47 +0,0 @@ -{ - 'name': 'MuK Chatter', - 'summary': 'Adds options for the chatter', - 'description': ''' - This module improves the design of the chatter and adds a user - preference to set the position of the chatter in the form view. - ''', - 'version': '17.0.1.0.1', - 'category': 'Tools/UI', - 'license': 'LGPL-3', - 'author': 'MuK IT', - 'website': 'http://www.mukit.at', - 'live_test_url': 'https://mukit.at/demo', - 'contributors': [ - 'Mathias Markl ', - ], - 'depends': [ - 'mail', - ], - 'data': [ - 'views/res_users.xml', - ], - 'assets': { - 'web._assets_primary_variables': [ - ( - 'after', - 'web/static/src/scss/primary_variables.scss', - 'muk_web_chatter/static/src/scss/variables.scss' - ), - ], - 'web.assets_backend': [ - ( - 'after', - 'mail/static/src/views/web/form/form_compiler.js', - 'muk_web_chatter/static/src/views/form/form_compiler.js' - ), - 'muk_web_chatter/static/src/core/**/*.xml', - 'muk_web_chatter/static/src/core/**/*.scss', - ], - }, - 'images': [ - 'static/description/banner.png', - ], - 'installable': True, - 'application': False, - 'auto_install': False, -} diff --git a/muk_web_chatter/doc/changelog.rst b/muk_web_chatter/doc/changelog.rst deleted file mode 100644 index 4d9690ede..000000000 --- a/muk_web_chatter/doc/changelog.rst +++ /dev/null @@ -1,4 +0,0 @@ -`1.0.0` -------- - -- Initial Release diff --git a/muk_web_chatter/doc/index.rst b/muk_web_chatter/doc/index.rst deleted file mode 100644 index 7984aeb7b..000000000 --- a/muk_web_chatter/doc/index.rst +++ /dev/null @@ -1,57 +0,0 @@ -=========== -MuK Chatter -=========== - -This module improves the design of the chatter and adds a user -preference to set the position of the chatter in the form view. - -Installation -============ - -To install this module, you need to: - -Download the module and add it to your Odoo addons folder. Afterward, log on to -your Odoo server and go to the Apps menu. Trigger the debug mode and update the -list by clicking on the "Update Apps List" link. Now install the module by -clicking on the install button. - -Upgrade -============ - -To upgrade this module, you need to: - -Download the module and add it to your Odoo addons folder. Restart the server -and log on to your Odoo server. Select the Apps menu and upgrade the module by -clicking on the upgrade button. - -Configuration -============= - -Each user can define in their profile the display of the chatter. The options -are to show the chatter on the side or at the bottom. - -Usage -============= - -The design improvements are automatically activated as soon as the module -is installed. - -Credits -======= - -Contributors ------------- - -* Mathias Markl - -Author & Maintainer -------------------- - -This module is maintained by the `MuK IT GmbH `_. - -MuK IT is an Austrian company specialized in customizing and extending Odoo. -We develop custom solutions for your individual needs to help you focus on -your strength and expertise to grow your business. - -If you want to get in touch please contact us via mail -(sale@mukit.at) or visit our website (https://mukit.at). diff --git a/muk_web_chatter/i18n/de.po b/muk_web_chatter/i18n/de.po deleted file mode 100644 index cba77e154..000000000 --- a/muk_web_chatter/i18n/de.po +++ /dev/null @@ -1,55 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * muk_web_chatter -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 17.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-30 09:55+0000\n" -"PO-Revision-Date: 2023-11-30 09:55+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: muk_web_chatter -#: model:ir.model.fields.selection,name:muk_web_chatter.selection__res_users__chatter_position__bottom -msgid "Bottom" -msgstr "Unten" - -#. module: muk_web_chatter -#: model:ir.model.fields,field_description:muk_web_chatter.field_res_users__chatter_position -msgid "Chatter Position" -msgstr "Chatterposition" - -#. module: muk_web_chatter -#: model:ir.model,name:muk_web_chatter.model_ir_http -msgid "HTTP Routing" -msgstr "HTTP-Routing" - -#. module: muk_web_chatter -#. odoo-javascript -#: code:addons/muk_web_chatter/static/src/core/chatter/chatter.xml:0 -#, python-format -msgid "Log note" -msgstr "Log-Notiz" - -#. module: muk_web_chatter -#. odoo-javascript -#: code:addons/muk_web_chatter/static/src/core/chatter/chatter.xml:0 -#, python-format -msgid "Send message" -msgstr "Nachricht senden" - -#. module: muk_web_chatter -#: model:ir.model.fields.selection,name:muk_web_chatter.selection__res_users__chatter_position__side -msgid "Side" -msgstr "Seite" - -#. module: muk_web_chatter -#: model:ir.model,name:muk_web_chatter.model_res_users -msgid "User" -msgstr "Benutzer" \ No newline at end of file diff --git a/muk_web_chatter/models/__init__.py b/muk_web_chatter/models/__init__.py deleted file mode 100644 index 5d0cb8306..000000000 --- a/muk_web_chatter/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import ir_http -from . import res_users diff --git a/muk_web_chatter/models/ir_http.py b/muk_web_chatter/models/ir_http.py deleted file mode 100644 index 9ece1eaf2..000000000 --- a/muk_web_chatter/models/ir_http.py +++ /dev/null @@ -1,16 +0,0 @@ -from odoo import models -from odoo.http import request - - -class IrHttp(models.AbstractModel): - - _inherit = "ir.http" - - #---------------------------------------------------------- - # Functions - #---------------------------------------------------------- - - def session_info(self): - result = super(IrHttp, self).session_info() - result['chatter_position'] = self.env.user.chatter_position - return result diff --git a/muk_web_chatter/models/res_users.py b/muk_web_chatter/models/res_users.py deleted file mode 100644 index 16a349855..000000000 --- a/muk_web_chatter/models/res_users.py +++ /dev/null @@ -1,36 +0,0 @@ -from odoo import models, fields, api - - -class ResUsers(models.Model): - - _inherit = 'res.users' - - #---------------------------------------------------------- - # Properties - #---------------------------------------------------------- - - @property - def SELF_READABLE_FIELDS(self): - return super().SELF_READABLE_FIELDS + [ - 'chatter_position', - ] - - @property - def SELF_WRITEABLE_FIELDS(self): - return super().SELF_WRITEABLE_FIELDS + [ - 'chatter_position', - ] - - #---------------------------------------------------------- - # Fields - #---------------------------------------------------------- - - chatter_position = fields.Selection( - selection=[ - ('side', 'Side'), - ('bottom', 'Bottom'), - ], - string="Chatter Position", - default='side', - required=True, - ) diff --git a/muk_web_chatter/static/description/banner.png b/muk_web_chatter/static/description/banner.png deleted file mode 100644 index 12860cbe7..000000000 Binary files a/muk_web_chatter/static/description/banner.png and /dev/null differ diff --git a/muk_web_chatter/static/description/icon.png b/muk_web_chatter/static/description/icon.png deleted file mode 100644 index 20619a74e..000000000 Binary files a/muk_web_chatter/static/description/icon.png and /dev/null differ diff --git a/muk_web_chatter/static/description/icon.svg b/muk_web_chatter/static/description/icon.svg deleted file mode 100644 index 5e1e7e56f..000000000 --- a/muk_web_chatter/static/description/icon.svg +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/muk_web_chatter/static/description/index.html b/muk_web_chatter/static/description/index.html deleted file mode 100644 index a3d76210d..000000000 --- a/muk_web_chatter/static/description/index.html +++ /dev/null @@ -1,138 +0,0 @@ -
-
-

MuK Chatter

-

Adds options for the chatter

- -

MuK IT GmbH - www.mukit.at

-
- - Community - - - Enterprise - -
-
- -
-
-
- -
-
-
-

Overview

-

- This module improves the design of the chatter and adds a user preference - to set the position of the chatter in the form view. Each user can define in - their profile the display of the chatter. The options are to show the chatter - on the side or at the bottom. -

-
-
-
- -
-
-

- Want more? -

-

- Are you having troubles with your Odoo integration? Or do you feel - your system lacks of essential features?
If your answer is YES - to one of the above questions, feel free to contact us at anytime - with your inquiry.
We are looking forward to discuss your - needs and plan the next steps with you.
-

-
- -
- -
-
-

Our Services

-
-
-
-
- -
-

- Odoo
Development -

-
-
-
-
-
- -
-

- Odoo
Integration -

-
-
-
-
-
- -
-

- Odoo
Infrastructure -

-
-
-
-
-
- -
-

- Odoo
Training -

-
-
-
-
-
- -
-

- Odoo
Support -

-
-
-
-
-
diff --git a/muk_web_chatter/static/description/logo.png b/muk_web_chatter/static/description/logo.png deleted file mode 100644 index 9427ce33e..000000000 Binary files a/muk_web_chatter/static/description/logo.png and /dev/null differ diff --git a/muk_web_chatter/static/description/screenshot.png b/muk_web_chatter/static/description/screenshot.png deleted file mode 100644 index 9ca0f787c..000000000 Binary files a/muk_web_chatter/static/description/screenshot.png and /dev/null differ diff --git a/muk_web_chatter/static/description/service_development.png b/muk_web_chatter/static/description/service_development.png deleted file mode 100644 index d64b66bda..000000000 Binary files a/muk_web_chatter/static/description/service_development.png and /dev/null differ diff --git a/muk_web_chatter/static/description/service_infrastructure.png b/muk_web_chatter/static/description/service_infrastructure.png deleted file mode 100644 index b899a3104..000000000 Binary files a/muk_web_chatter/static/description/service_infrastructure.png and /dev/null differ diff --git a/muk_web_chatter/static/description/service_integration.png b/muk_web_chatter/static/description/service_integration.png deleted file mode 100644 index 76c5e80f4..000000000 Binary files a/muk_web_chatter/static/description/service_integration.png and /dev/null differ diff --git a/muk_web_chatter/static/description/service_support.png b/muk_web_chatter/static/description/service_support.png deleted file mode 100644 index 4c530fafd..000000000 Binary files a/muk_web_chatter/static/description/service_support.png and /dev/null differ diff --git a/muk_web_chatter/static/description/service_training.png b/muk_web_chatter/static/description/service_training.png deleted file mode 100644 index 19ea76e63..000000000 Binary files a/muk_web_chatter/static/description/service_training.png and /dev/null differ diff --git a/muk_web_chatter/static/src/core/chatter/chatter.scss b/muk_web_chatter/static/src/core/chatter/chatter.scss deleted file mode 100644 index c0a35c15c..000000000 --- a/muk_web_chatter/static/src/core/chatter/chatter.scss +++ /dev/null @@ -1,3 +0,0 @@ -.o-mail-Chatter-top:has(.o-mail-Chatter-sendMessage.active) .o-mail-Composer-send { - @extend .btn-danger -} diff --git a/muk_web_chatter/static/src/core/chatter/chatter.xml b/muk_web_chatter/static/src/core/chatter/chatter.xml deleted file mode 100644 index c7b613831..000000000 --- a/muk_web_chatter/static/src/core/chatter/chatter.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/muk_web_chatter/static/src/scss/variables.scss b/muk_web_chatter/static/src/scss/variables.scss deleted file mode 100644 index e3adfc499..000000000 --- a/muk_web_chatter/static/src/scss/variables.scss +++ /dev/null @@ -1,2 +0,0 @@ -$o-form-renderer-max-width: 3840px; -$o-form-view-sheet-max-width: 2560px; diff --git a/muk_web_chatter/static/src/views/form/form_compiler.js b/muk_web_chatter/static/src/views/form/form_compiler.js deleted file mode 100644 index 7df247e21..000000000 --- a/muk_web_chatter/static/src/views/form/form_compiler.js +++ /dev/null @@ -1,51 +0,0 @@ -/** @odoo-module **/ - -import { session } from '@web/session'; -import { patch } from '@web/core/utils/patch'; -import { append, setAttributes } from '@web/core/utils/xml'; - -import {FormCompiler} from '@web/views/form/form_compiler'; - -patch(FormCompiler.prototype, { - compile(node, params) { - const res = super.compile(node, params); - if (session.chatter_position === 'bottom') { - const chatterContainerHookXml = res.querySelector( - '.o_form_renderer > .o-mail-Form-chatter' - ); - const formSheetBgXml = res.querySelector('.o_form_sheet_bg'); - if (!chatterContainerHookXml || !formSheetBgXml?.parentNode) { - return res; - } - const webClientViewAttachmentViewHookXml = res.querySelector( - '.o_attachment_preview' - ); - const chatterContainerXml = chatterContainerHookXml.querySelector( - "t[t-component='__comp__.mailComponents.Chatter']" - ); - const sheetBgChatterContainerHookXml = chatterContainerHookXml.cloneNode(true); - const sheetBgChatterContainerXml = sheetBgChatterContainerHookXml.querySelector( - "t[t-component='__comp__.mailComponents.Chatter']" - ); - sheetBgChatterContainerHookXml.classList.add('o-isInFormSheetBg', 'w-auto'); - append(formSheetBgXml, sheetBgChatterContainerHookXml); - setAttributes(sheetBgChatterContainerXml, { - isInFormSheetBg: 'true', - isChatterAside: 'false', - }); - setAttributes(chatterContainerXml, { - isInFormSheetBg: 'true', - isChatterAside: 'false', - }); - setAttributes(chatterContainerHookXml, { - 't-if': 'false', - }); - if (webClientViewAttachmentViewHookXml) { - setAttributes(webClientViewAttachmentViewHookXml, { - 't-if': 'false', - }); - } - } - return res; - }, -}); \ No newline at end of file diff --git a/muk_web_chatter/views/res_users.xml b/muk_web_chatter/views/res_users.xml deleted file mode 100644 index 9c6ab71bb..000000000 --- a/muk_web_chatter/views/res_users.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - res.users.form - res.users - - - - - - - - - diff --git a/muk_web_colors/LICENSE b/muk_web_colors/LICENSE deleted file mode 100644 index 0a041280b..000000000 --- a/muk_web_colors/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/muk_web_colors/__init__.py b/muk_web_colors/__init__.py deleted file mode 100644 index d71f6b120..000000000 --- a/muk_web_colors/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from . import models - - -def _uninstall_cleanup(env): - env['res.config.settings']._reset_light_color_assets() - env['res.config.settings']._reset_dark_color_assets() diff --git a/muk_web_colors/__manifest__.py b/muk_web_colors/__manifest__.py deleted file mode 100644 index 8e2b307ca..000000000 --- a/muk_web_colors/__manifest__.py +++ /dev/null @@ -1,48 +0,0 @@ -{ - 'name': 'MuK Colors', - 'summary': 'Customize your Odoo colors', - 'description': ''' - This module gives you options to customize the theme colors. - ''', - 'version': '17.0.1.0.3', - 'category': 'Tools/UI', - 'license': 'LGPL-3', - 'author': 'MuK IT', - 'website': 'http://www.mukit.at', - 'live_test_url': 'https://mukit.at/demo', - 'contributors': [ - 'Mathias Markl ', - ], - 'depends': [ - 'base_setup', - 'web_editor', - ], - 'data': [ - 'templates/webclient.xml', - 'views/res_config_settings.xml', - ], - 'assets': { - 'web._assets_primary_variables': [ - ('prepend', 'muk_web_colors/static/src/scss/colors.scss'), - ( - 'before', - 'muk_web_colors/static/src/scss/colors.scss', - 'muk_web_colors/static/src/scss/colors_light.scss' - ), - ], - 'web.assets_web_dark': [ - ( - 'after', - 'muk_web_colors/static/src/scss/colors.scss', - 'muk_web_colors/static/src/scss/colors_dark.scss' - ), - ], - }, - 'images': [ - 'static/description/banner.png', - ], - 'installable': True, - 'application': False, - 'auto_install': False, - 'uninstall_hook': '_uninstall_cleanup', -} diff --git a/muk_web_colors/doc/changelog.rst b/muk_web_colors/doc/changelog.rst deleted file mode 100644 index 4d9690ede..000000000 --- a/muk_web_colors/doc/changelog.rst +++ /dev/null @@ -1,4 +0,0 @@ -`1.0.0` -------- - -- Initial Release diff --git a/muk_web_colors/doc/index.rst b/muk_web_colors/doc/index.rst deleted file mode 100644 index fe2d4ba2e..000000000 --- a/muk_web_colors/doc/index.rst +++ /dev/null @@ -1,57 +0,0 @@ -========== -MuK Colors -========== - -This module gives you options to customize the color schema of your Odoo system. -You have options to edit the brand and the primary color as well as the context -colors (info, success, warning, danger). The options are also available for the -dark mode on Odoo Enterprise. - -Installation -============ - -To install this module, you need to: - -Download the module and add it to your Odoo addons folder. Afterward, log on to -your Odoo server and go to the Apps menu. Trigger the debug mode and update the -list by clicking on the "Update Apps List" link. Now install the module by -clicking on the install button. - -Upgrade -============ - -To upgrade this module, you need to: - -Download the module and add it to your Odoo addons folder. Restart the server -and log on to your Odoo server. Select the Apps menu and upgrade the module by -clicking on the upgrade button. - -Configuration -============= - -The colors can be set in the general settings using a color picker. - -Usage -============= - -Once the colors a set the system will adapt for all users. - -Credits -======= - -Contributors ------------- - -* Mathias Markl - -Author & Maintainer -------------------- - -This module is maintained by the `MuK IT GmbH `_. - -MuK IT is an Austrian company specialized in customizing and extending Odoo. -We develop custom solutions for your individual needs to help you focus on -your strength and expertise to grow your business. - -If you want to get in touch please contact us via mail -(sale@mukit.at) or visit our website (https://mukit.at). diff --git a/muk_web_colors/i18n/de.po b/muk_web_colors/i18n/de.po deleted file mode 100644 index 7972e261e..000000000 --- a/muk_web_colors/i18n/de.po +++ /dev/null @@ -1,161 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * muk_web_colors -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 17.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-30 10:07+0000\n" -"PO-Revision-Date: 2023-11-30 10:07+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: muk_web_colors -#: model:ir.model,name:muk_web_colors.model_ir_asset -msgid "Asset" -msgstr "" - -#. module: muk_web_colors -#: model:ir.model,name:muk_web_colors.model_web_editor_assets -msgid "Assets Utils" -msgstr "" - -#. module: muk_web_colors -#: model:ir.model,name:muk_web_colors.model_ir_attachment -msgid "Attachment" -msgstr "" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Brand" -msgstr "Marke" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_brand_dark -msgid "Brand Dark Color" -msgstr "Marke dunkle Farbe" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_brand_light -msgid "Brand Light Color" -msgstr "Marke helle Farbe" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Branding" -msgstr "Branding" - -#. module: muk_web_colors -#: model:ir.model,name:muk_web_colors.model_res_config_settings -msgid "Config Settings" -msgstr "Konfigurationseinstellungen" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Customize the look and feel of the dark mode" -msgstr "Passen Sie Aussehen und Handhabung des dunklen Modus an" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Customize the look and feel of the light mode" -msgstr "Passen Sie Aussehen und Handhabung des hellen Modus an" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Danger" -msgstr "Gefahr" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_danger_dark -msgid "Danger Dark Color" -msgstr "Gefahr dunkle Farbe" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_danger_light -msgid "Danger Light Color" -msgstr "Gefahr helle Farbe" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Dark Mode Colors" -msgstr "Farben dunkler Modus" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Info" -msgstr "Information" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_info_dark -msgid "Info Dark Color" -msgstr "Information dunkle Farbe" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_info_light -msgid "Info Light Color" -msgstr "Information helle Farbe" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Light Mode Colors" -msgstr "Farben heller Modus" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Primary" -msgstr "Primär" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_primary_dark -msgid "Primary Dark Color" -msgstr "Primäre dunkle Farbe" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_primary_light -msgid "Primary Light Color" -msgstr "Primäre helle Farbe" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Reset Dark Colors" -msgstr "dunkle Farbe zurücksetzen" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Reset Light Colors" -msgstr "helle Farbe zurücksetzen" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Success" -msgstr "Erfolg" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_success_dark -msgid "Success Dark Color" -msgstr "Erfolg dunkle Farbe" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_success_light -msgid "Success Light Color" -msgstr "Erfolg helle Farbe" - -#. module: muk_web_colors -#: model_terms:ir.ui.view,arch_db:muk_web_colors.view_res_config_settings_form -msgid "Warning" -msgstr "Warnung" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_warning_dark -msgid "Warning Dark Color" -msgstr "Warnung dunkle Farbe" - -#. module: muk_web_colors -#: model:ir.model.fields,field_description:muk_web_colors.field_res_config_settings__color_warning_light -msgid "Warning Light Color" -msgstr "Warnung helle Farbe" \ No newline at end of file diff --git a/muk_web_colors/models/__init__.py b/muk_web_colors/models/__init__.py deleted file mode 100644 index 7e64849c8..000000000 --- a/muk_web_colors/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import res_config_settings -from . import web_editor_assets -from . import ir_attachment -from . import ir_asset diff --git a/muk_web_colors/models/ir_asset.py b/muk_web_colors/models/ir_asset.py deleted file mode 100644 index ca4fcc1ce..000000000 --- a/muk_web_colors/models/ir_asset.py +++ /dev/null @@ -1,17 +0,0 @@ -from odoo import models, fields, api - - -class IrAsset(models.Model): - - _inherit = 'ir.asset' - - # ---------------------------------------------------------- - # ORM - # ---------------------------------------------------------- - - @api.model_create_multi - def create(self, vals_list): - if self.env.context.get('set_color_variables', False): - for vals in vals_list: - vals.pop('website_id', False) - return super().create(vals_list) diff --git a/muk_web_colors/models/ir_attachment.py b/muk_web_colors/models/ir_attachment.py deleted file mode 100644 index 615eb3ffe..000000000 --- a/muk_web_colors/models/ir_attachment.py +++ /dev/null @@ -1,17 +0,0 @@ -from odoo import models, fields, api - - -class IrAttachment(models.Model): - - _inherit = 'ir.attachment' - - # ---------------------------------------------------------- - # ORM - # ---------------------------------------------------------- - - @api.model_create_multi - def create(self, vals_list): - if self.env.context.get('set_color_variables', False): - for vals in vals_list: - vals.pop('website_id', False) - return super().create(vals_list) diff --git a/muk_web_colors/models/res_config_settings.py b/muk_web_colors/models/res_config_settings.py deleted file mode 100644 index 2bb787cd1..000000000 --- a/muk_web_colors/models/res_config_settings.py +++ /dev/null @@ -1,213 +0,0 @@ -from odoo import api, fields, models - - -class ResConfigSettings(models.TransientModel): - - _inherit = 'res.config.settings' - - # ---------------------------------------------------------- - # Properties - # ---------------------------------------------------------- - - @property - def COLOR_FIELDS(self): - return [ - 'color_brand', - 'color_primary', - 'color_success', - 'color_info', - 'color_warning', - 'color_danger', - ] - - @property - def COLOR_ASSET_LIGHT_URL(self): - return '/muk_web_colors/static/src/scss/colors_light.scss' - - @property - def COLOR_BUNDLE_LIGHT_NAME(self): - return 'web._assets_primary_variables' - - @property - def COLOR_ASSET_DARK_URL(self): - return '/muk_web_colors/static/src/scss/colors_dark.scss' - - @property - def COLOR_BUNDLE_DARK_NAME(self): - return 'web.assets_web_dark' - - #---------------------------------------------------------- - # Fields Light Mode - #---------------------------------------------------------- - - color_brand_light = fields.Char( - string='Brand Light Color' - ) - - color_primary_light = fields.Char( - string='Primary Light Color' - ) - - color_success_light = fields.Char( - string='Success Light Color' - ) - - color_info_light = fields.Char( - string='Info Light Color' - ) - - color_warning_light = fields.Char( - string='Warning Light Color' - ) - - color_danger_light = fields.Char( - string='Danger Light Color' - ) - - #---------------------------------------------------------- - # Fields Dark Mode - #---------------------------------------------------------- - - color_brand_dark = fields.Char( - string='Brand Dark Color' - ) - - color_primary_dark = fields.Char( - string='Primary Dark Color' - ) - - color_success_dark = fields.Char( - string='Success Dark Color' - ) - - color_info_dark = fields.Char( - string='Info Dark Color' - ) - - color_warning_dark = fields.Char( - string='Warning Dark Color' - ) - - color_danger_dark = fields.Char( - string='Danger Dark Color' - ) - - #---------------------------------------------------------- - # Helper - #---------------------------------------------------------- - - def _get_light_color_values(self): - return self.env['web_editor.assets'].get_color_variables_values( - self.COLOR_ASSET_LIGHT_URL, - self.COLOR_BUNDLE_LIGHT_NAME, - self.COLOR_FIELDS - ) - - def _get_dark_color_values(self): - return self.env['web_editor.assets'].get_color_variables_values( - self.COLOR_ASSET_DARK_URL, - self.COLOR_BUNDLE_DARK_NAME, - self.COLOR_FIELDS - ) - - def _set_light_color_values(self, values): - colors = self._get_light_color_values() - for var, value in colors.items(): - values[f'{var}_light'] = value - return values - - def _set_dark_color_values(self, values): - colors = self._get_dark_color_values() - for var, value in colors.items(): - values[f'{var}_dark'] = value - return values - - def _detect_light_color_change(self): - colors = self._get_light_color_values() - return any( - self[f'{var}_light'] != val - for var, val in colors.items() - ) - - def _detect_dark_color_change(self): - colors = self._get_dark_color_values() - return any( - self[f'{var}_dark'] != val - for var, val in colors.items() - ) - - def _replace_light_color_values(self): - variables = [ - { - 'name': field, - 'value': self[f'{field}_light'] - } - for field in self.COLOR_FIELDS - ] - return self.env['web_editor.assets'].replace_color_variables_values( - self.COLOR_ASSET_LIGHT_URL, - self.COLOR_BUNDLE_LIGHT_NAME, - variables - ) - - def _replace_dark_color_values(self): - variables = [ - { - 'name': field, - 'value': self[f'{field}_dark'] - } - for field in self.COLOR_FIELDS - ] - return self.env['web_editor.assets'].replace_color_variables_values( - self.COLOR_ASSET_DARK_URL, - self.COLOR_BUNDLE_DARK_NAME, - variables - ) - - def _reset_light_color_assets(self): - self.env['web_editor.assets'].reset_asset( - self.COLOR_ASSET_LIGHT_URL, - self.COLOR_BUNDLE_LIGHT_NAME, - ) - - def _reset_dark_color_assets(self): - self.env['web_editor.assets'].reset_asset( - self.COLOR_ASSET_DARK_URL, - self.COLOR_BUNDLE_DARK_NAME, - ) - - #---------------------------------------------------------- - # Action - #---------------------------------------------------------- - - def action_reset_light_color_assets(self): - self._reset_light_color_assets() - return { - 'type': 'ir.actions.client', - 'tag': 'reload', - } - - def action_reset_dark_color_assets(self): - self._reset_dark_color_assets() - return { - 'type': 'ir.actions.client', - 'tag': 'reload', - } - - #---------------------------------------------------------- - # Functions - #---------------------------------------------------------- - - def get_values(self): - res = super().get_values() - res = self._set_light_color_values(res) - res = self._set_dark_color_values(res) - return res - - def set_values(self): - res = super().set_values() - if self._detect_light_color_change(): - self._replace_light_color_values() - if self._detect_dark_color_change(): - self._replace_dark_color_values() - return res diff --git a/muk_web_colors/models/web_editor_assets.py b/muk_web_colors/models/web_editor_assets.py deleted file mode 100644 index d894555d4..000000000 --- a/muk_web_colors/models/web_editor_assets.py +++ /dev/null @@ -1,51 +0,0 @@ -import re - -from odoo import models, fields, api - - -class ScssEditor(models.AbstractModel): - - _inherit = 'web_editor.assets' - - # ---------------------------------------------------------- - # Helper - # ---------------------------------------------------------- - - def _get_color_variable(self, content, variable): - value = re.search(fr'\$mk_{variable}\:?\s(.*?);', content) - return value and value.group(1) - - def _get_color_variables(self, content, variables): - return { - var: self._get_color_variable(content, var) - for var in variables - } - - def _replace_color_variables(self, content, variables): - for variable in variables: - content = re.sub( - fr'{variable["name"]}\:?\s(.*?);', - f'{variable["name"]}: {variable["value"]};', - content - ) - return content - - # ---------------------------------------------------------- - # Functions - # ---------------------------------------------------------- - - def get_color_variables_values(self, url, bundle, variables): - custom_url = self._make_custom_asset_url(url, bundle) - content = self._get_content_from_url(custom_url) - if not content: - content = self._get_content_from_url(url) - return self._get_color_variables( - content.decode('utf-8'), variables - ) - - def replace_color_variables_values(self, url, bundle, variables): - original = self._get_content_from_url(url).decode('utf-8') - content = self._replace_color_variables(original, variables) - self.with_context(set_color_variables=True).save_asset( - url, bundle, content, 'scss' - ) diff --git a/muk_web_colors/static/description/banner.png b/muk_web_colors/static/description/banner.png deleted file mode 100644 index 045918fc8..000000000 Binary files a/muk_web_colors/static/description/banner.png and /dev/null differ diff --git a/muk_web_colors/static/description/icon.png b/muk_web_colors/static/description/icon.png deleted file mode 100644 index 44302d686..000000000 Binary files a/muk_web_colors/static/description/icon.png and /dev/null differ diff --git a/muk_web_colors/static/description/icon.svg b/muk_web_colors/static/description/icon.svg deleted file mode 100644 index 4a324b91d..000000000 --- a/muk_web_colors/static/description/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/muk_web_colors/static/description/index.html b/muk_web_colors/static/description/index.html deleted file mode 100644 index 4f5d340f8..000000000 --- a/muk_web_colors/static/description/index.html +++ /dev/null @@ -1,138 +0,0 @@ -
-
-

MuK Colors

-

Customize your Odoo colors

- -

MuK IT GmbH - www.mukit.at

-
- - Community - - - Enterprise - -
-
- -
-
-
- -
-
-
-

Overview

-

- This module gives you options to customize the color schema of your Odoo system. - You have options to edit the brand and the primary color as well as the context - colors (info, success, warning, danger). The options are also available for the - dark mode on Odoo Enterprise. -

-
-
-
- -
-
-

- Want more? -

-

- Are you having troubles with your Odoo integration? Or do you feel - your system lacks of essential features?
If your answer is YES - to one of the above questions, feel free to contact us at anytime - with your inquiry.
We are looking forward to discuss your - needs and plan the next steps with you.
-

-
- -
- -
-
-

Our Services

-
-
-
-
- -
-

- Odoo
Development -

-
-
-
-
-
- -
-

- Odoo
Integration -

-
-
-
-
-
- -
-

- Odoo
Infrastructure -

-
-
-
-
-
- -
-

- Odoo
Training -

-
-
-
-
-
- -
-

- Odoo
Support -

-
-
-
-
-
diff --git a/muk_web_colors/static/description/logo.png b/muk_web_colors/static/description/logo.png deleted file mode 100644 index 9427ce33e..000000000 Binary files a/muk_web_colors/static/description/logo.png and /dev/null differ diff --git a/muk_web_colors/static/description/screenshot.png b/muk_web_colors/static/description/screenshot.png deleted file mode 100644 index e8338a1d4..000000000 Binary files a/muk_web_colors/static/description/screenshot.png and /dev/null differ diff --git a/muk_web_colors/static/description/service_development.png b/muk_web_colors/static/description/service_development.png deleted file mode 100644 index d64b66bda..000000000 Binary files a/muk_web_colors/static/description/service_development.png and /dev/null differ diff --git a/muk_web_colors/static/description/service_infrastructure.png b/muk_web_colors/static/description/service_infrastructure.png deleted file mode 100644 index b899a3104..000000000 Binary files a/muk_web_colors/static/description/service_infrastructure.png and /dev/null differ diff --git a/muk_web_colors/static/description/service_integration.png b/muk_web_colors/static/description/service_integration.png deleted file mode 100644 index 76c5e80f4..000000000 Binary files a/muk_web_colors/static/description/service_integration.png and /dev/null differ diff --git a/muk_web_colors/static/description/service_support.png b/muk_web_colors/static/description/service_support.png deleted file mode 100644 index 4c530fafd..000000000 Binary files a/muk_web_colors/static/description/service_support.png and /dev/null differ diff --git a/muk_web_colors/static/description/service_training.png b/muk_web_colors/static/description/service_training.png deleted file mode 100644 index 19ea76e63..000000000 Binary files a/muk_web_colors/static/description/service_training.png and /dev/null differ diff --git a/muk_web_colors/static/src/scss/colors.scss b/muk_web_colors/static/src/scss/colors.scss deleted file mode 100644 index 8022f8b5c..000000000 --- a/muk_web_colors/static/src/scss/colors.scss +++ /dev/null @@ -1 +0,0 @@ -// Color Assets \ No newline at end of file diff --git a/muk_web_colors/static/src/scss/colors_dark.scss b/muk_web_colors/static/src/scss/colors_dark.scss deleted file mode 100644 index 6a323c507..000000000 --- a/muk_web_colors/static/src/scss/colors_dark.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Colors - -$mk_color_brand: #243742; -$mk_color_primary: #5D8DA8; - -$mk_color_success: #1DC959; -$mk_color_info: #6AB5FB; -$mk_color_warning: #FBB56A; -$mk_color_danger: #FF5757; - -// Override - -$o-community-color: $mk-color-brand; -$o-enterprise-color: $mk-color-brand; -$o-enterprise-action-color: $mk-color-primary; - -$o-brand-odoo: $mk-color-brand; -$o-brand-primary: $mk-color-primary; - -$o-success: $mk-color-success; -$o-info: $mk-color-info; -$o-warning: $mk-color-warning; -$o-danger: $mk-color-danger; - -$o-theme-text-colors: ( - "primary": $mk-color-brand, - "success": $o-success, - "info": $o-info, - "warning": $o-warning, - "danger": $o-danger, -); diff --git a/muk_web_colors/static/src/scss/colors_light.scss b/muk_web_colors/static/src/scss/colors_light.scss deleted file mode 100644 index 771a75b0d..000000000 --- a/muk_web_colors/static/src/scss/colors_light.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Colors - -$mk_color_brand: #243742; -$mk_color_primary: #5D8DA8; - -$mk_color_success: #28A745; -$mk_color_info: #17A2B8; -$mk_color_warning: #FFAC00; -$mk_color_danger: #DC3545; - -// Override - -$o-community-color: $mk-color-brand; -$o-enterprise-color: $mk-color-brand; -$o-enterprise-action-color: $mk-color-primary; - -$o-brand-odoo: $mk-color-brand; -$o-brand-primary: $mk-color-primary; - -$o-success: $mk-color-success; -$o-info: $mk-color-info; -$o-warning: $mk-color-warning; -$o-danger: $mk-color-danger; - -$o-theme-text-colors: ( - "primary": $mk-color-brand, - "success": $o-success, - "info": $o-info, - "warning": $o-warning, - "danger": $o-danger, -); diff --git a/muk_web_colors/templates/webclient.xml b/muk_web_colors/templates/webclient.xml deleted file mode 100644 index 7664a7a83..000000000 --- a/muk_web_colors/templates/webclient.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - diff --git a/muk_web_colors/views/res_config_settings.xml b/muk_web_colors/views/res_config_settings.xml deleted file mode 100644 index 20b9c280b..000000000 --- a/muk_web_colors/views/res_config_settings.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - res.config.settings.form - res.config.settings - - - - - -
-
-
-
-
-
-
-
-
-
-
-
- - -
- - - diff --git a/muk_web_dialog/views/res_users.xml b/muk_web_dialog/views/res_users.xml deleted file mode 100644 index 77443e881..000000000 --- a/muk_web_dialog/views/res_users.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - res.users.form - res.users - - - - - - - - - diff --git a/muk_web_enterprise_theme/LICENSE b/muk_web_enterprise_theme/LICENSE deleted file mode 100644 index 0a041280b..000000000 --- a/muk_web_enterprise_theme/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/muk_web_enterprise_theme/__init__.py b/muk_web_enterprise_theme/__init__.py deleted file mode 100644 index 22bcbaa0c..000000000 --- a/muk_web_enterprise_theme/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -from . import models - -import base64 - -from odoo.tools import file_open - - -def _setup_module(env): - if env.ref('base.main_company', False): - with file_open('web/static/img/favicon.ico', 'rb') as file: - env.ref('base.main_company').write({ - 'favicon': base64.b64encode(file.read()) - }) - - -def _uninstall_cleanup(env): - env['res.config.settings']._reset_light_theme_color_assets() - env['res.config.settings']._reset_dark_theme_color_assets() diff --git a/muk_web_enterprise_theme/__manifest__.py b/muk_web_enterprise_theme/__manifest__.py deleted file mode 100644 index 4c19b969a..000000000 --- a/muk_web_enterprise_theme/__manifest__.py +++ /dev/null @@ -1,65 +0,0 @@ -{ - 'name': 'MuK Backend Theme', - 'summary': 'Odoo Enterprise Backend Theme', - 'description': ''' - This module offers a mobile compatible design for Odoo Enterprise. - Furthermore it allows the user to define some design preferences. - ''', - 'version': '17.0.1.2.1', - 'category': 'Themes/Backend', - 'license': 'LGPL-3', - 'author': 'MuK IT', - 'website': 'http://www.mukit.at', - 'live_test_url': 'https://mukit.at/demo', - 'contributors': [ - 'Mathias Markl ', - ], - 'depends': [ - 'web_enterprise', - 'muk_web_chatter', - 'muk_web_dialog', - 'muk_web_appsbar', - 'muk_web_colors', - ], - 'data': [ - 'templates/web_layout.xml', - 'views/res_config_settings.xml', - ], - 'assets': { - 'web._assets_primary_variables': [ - ( - 'before', - 'muk_web_colors/static/src/scss/colors.scss', - 'muk_web_enterprise_theme/static/src/scss/colors_light.scss' - ), - ( - 'after', - 'web/static/src/scss/primary_variables.scss', - 'muk_web_enterprise_theme/static/src/scss/variables.scss' - ), - ], - 'web.assets_backend': [ - 'muk_web_enterprise_theme/static/src/webclient/**/*.xml', - 'muk_web_enterprise_theme/static/src/webclient/**/*.js', - 'muk_web_enterprise_theme/static/src/views/**/*.scss', - ('remove', 'muk_web_enterprise_theme/static/src/**/*.dark.scss'), - ], - "web.assets_web_dark": [ - ( - 'after', - 'muk_web_colors/static/src/scss/colors.scss', - 'muk_web_enterprise_theme/static/src/scss/colors_dark.scss' - ), - 'muk_web_enterprise_theme/static/src/**/*.dark.scss', - ], - }, - 'images': [ - 'static/description/banner.png', - 'static/description/theme_screenshot.png' - ], - 'installable': True, - 'application': False, - 'auto_install': False, - 'post_init_hook': '_setup_module', - 'uninstall_hook': '_uninstall_cleanup', -} diff --git a/muk_web_enterprise_theme/doc/changelog.rst b/muk_web_enterprise_theme/doc/changelog.rst deleted file mode 100644 index 875824205..000000000 --- a/muk_web_enterprise_theme/doc/changelog.rst +++ /dev/null @@ -1,14 +0,0 @@ -`1.2.0` -------- - -- Add Dialog Module - -`1.1.0` -------- - -- Add Chatter Module - -`1.0.0` -------- - -- Initial Release diff --git a/muk_web_enterprise_theme/doc/index.rst b/muk_web_enterprise_theme/doc/index.rst deleted file mode 100644 index 772194f94..000000000 --- a/muk_web_enterprise_theme/doc/index.rst +++ /dev/null @@ -1,58 +0,0 @@ -================= -MuK Backend Theme -================= - -This module offers a mobile compatible design for Odoo Enterprise. Furthermore it -allows the user to define some design preferences. Each user can choose the size -of the sidebar. In addition, the background image of the home menu can be set -for each company. - -Installation -============ - -To install this module, you need to: - -Download the module and add it to your Odoo addons folder. Afterward, log on to -your Odoo server and go to the Apps menu. Trigger the debug mode and update the -list by clicking on the "Update Apps List" link. Now install the module by -clicking on the install button. - -Upgrade -============ - -To upgrade this module, you need to: - -Download the module and add it to your Odoo addons folder. Restart the server -and log on to your Odoo server. Select the Apps menu and upgrade the module by -clicking on the upgrade button. - -Configuration -============= - -To further customize the theme several settings are available in the general -settings page. - -Usage -============= - -After the module is installed, the design is adjusted accordingly. - -Credits -======= - -Contributors ------------- - -* Mathias Markl - -Author & Maintainer -------------------- - -This module is maintained by the `MuK IT GmbH `_. - -MuK IT is an Austrian company specialized in customizing and extending Odoo. -We develop custom solutions for your individual needs to help you focus on -your strength and expertise to grow your business. - -If you want to get in touch please contact us via mail -(sale@mukit.at) or visit our website (https://mukit.at). diff --git a/muk_web_enterprise_theme/i18n/de.po b/muk_web_enterprise_theme/i18n/de.po deleted file mode 100644 index 5970b7dbb..000000000 --- a/muk_web_enterprise_theme/i18n/de.po +++ /dev/null @@ -1,119 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * muk_web_enterprise_theme -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 17.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-30 13:34+0000\n" -"PO-Revision-Date: 2023-11-30 13:34+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_company__background_image_dark -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_background_image_dark -msgid "Apps Menu Background Dark Image" -msgstr "dunkles Hintergrundbild Appsmenü" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_company__background_image_light -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_background_image_light -msgid "Apps Menu Background Light Image" -msgstr "helles Hintergrundbild Appsmenü" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Apps Text" -msgstr "Appstext" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "AppsBar" -msgstr "Appsleiste" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_color_appbar_background_dark -msgid "AppsBar Background Dark Color" -msgstr "dunkle Hintergrundfarbe Appsleiste" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_color_appbar_background_light -msgid "AppsBar Background Light Color" -msgstr "helle Hintergrundfarbe Appsleiste" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_color_appbar_text_dark -msgid "AppsBar Text Dark Color" -msgstr "dunkle Textfarbe Appsleiste" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_color_appbar_text_light -msgid "AppsBar Text Light Color" -msgstr "helle Textfarbe Appsleiste" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Backend Theme" -msgstr "Backend-Theme" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Background" -msgstr "Hintergrund" - -#. module: muk_web_enterprise_theme -#: model:ir.model,name:muk_web_enterprise_theme.model_res_company -msgid "Companies" -msgstr "Unternehmen" - -#. module: muk_web_enterprise_theme -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_company__favicon -#: model:ir.model.fields,field_description:muk_web_enterprise_theme.field_res_config_settings__theme_favicon -msgid "Company Favicon" -msgstr "Unternehmens Favicon" - -#. module: muk_web_enterprise_theme -#: model:ir.model,name:muk_web_enterprise_theme.model_res_config_settings -msgid "Config Settings" -msgstr "Konfigurationseinstellungen" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Dark Mode Background Image" -msgstr "Hintergrundbild dunkler Modus" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Favicon" -msgstr "Favicon" - -#. module: muk_web_enterprise_theme -#: model:ir.model,name:muk_web_enterprise_theme.model_ir_http -msgid "HTTP Routing" -msgstr "HTTP-Routing" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Light Mode Background Image" -msgstr "Hintergrundbild heller Modus" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Set the background image for the apps menu" -msgstr "Legen Sie das Hintergrundbild für das Appsmenü fest" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Set your own Logo for the appsbar" -msgstr "Legen Sie ihr eigenes Logo für die Appsleiste fest" - -#. module: muk_web_enterprise_theme -#: model_terms:ir.ui.view,arch_db:muk_web_enterprise_theme.view_res_config_settings_colors_form -msgid "Set your own favicon" -msgstr "Legen Sie ihr eigenes Favicon fest" \ No newline at end of file diff --git a/muk_web_enterprise_theme/models/__init__.py b/muk_web_enterprise_theme/models/__init__.py deleted file mode 100644 index c674f0db6..000000000 --- a/muk_web_enterprise_theme/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import ir_http -from . import res_company -from . import res_config_settings diff --git a/muk_web_enterprise_theme/models/ir_http.py b/muk_web_enterprise_theme/models/ir_http.py deleted file mode 100644 index ae9b0ee93..000000000 --- a/muk_web_enterprise_theme/models/ir_http.py +++ /dev/null @@ -1,21 +0,0 @@ -from odoo import models -from odoo.http import request - - -class IrHttp(models.AbstractModel): - - _inherit = "ir.http" - - #---------------------------------------------------------- - # Functions - #---------------------------------------------------------- - - def session_info(self): - result = super(IrHttp, self).session_info() - if request.env.user._is_internal(): - for company in request.env.user.company_ids.with_context(bin_size=True): - result['user_companies']['allowed_companies'][company.id].update({ - 'has_background_image_light': bool(company.background_image_light), - 'has_background_image_dark': bool(company.background_image_dark), - }) - return result diff --git a/muk_web_enterprise_theme/models/res_company.py b/muk_web_enterprise_theme/models/res_company.py deleted file mode 100644 index ba591813d..000000000 --- a/muk_web_enterprise_theme/models/res_company.py +++ /dev/null @@ -1,26 +0,0 @@ -from odoo import models, fields - - -class ResCompany(models.Model): - - _inherit = 'res.company' - - #---------------------------------------------------------- - # Fields - #---------------------------------------------------------- - - favicon = fields.Binary( - string="Company Favicon", - attachment=True - ) - - background_image_light = fields.Binary( - string='Apps Menu Background Light Image', - attachment=True - ) - - background_image_dark = fields.Binary( - string='Apps Menu Background Dark Image', - attachment=True - ) - diff --git a/muk_web_enterprise_theme/models/res_config_settings.py b/muk_web_enterprise_theme/models/res_config_settings.py deleted file mode 100644 index 5f8ec4c05..000000000 --- a/muk_web_enterprise_theme/models/res_config_settings.py +++ /dev/null @@ -1,187 +0,0 @@ -from odoo import api, fields, models - - -class ResConfigSettings(models.TransientModel): - - _inherit = 'res.config.settings' - - @property - def THEME_COLOR_FIELDS(self): - return [ - 'color_appbar_text', - 'color_appbar_active', - 'color_appbar_background', - ] - - @property - def COLOR_ASSET_THEME_LIGHT_URL(self): - return '/muk_web_enterprise_theme/static/src/scss/colors_light.scss' - - @property - def COLOR_BUNDLE_THEME_LIGHT_NAME(self): - return 'web._assets_primary_variables' - - @property - def COLOR_ASSET_THEME_DARK_URL(self): - return '/muk_web_enterprise_theme/static/src/scss/colors_dark.scss' - - @property - def COLOR_BUNDLE_THEME_DARK_NAME(self): - return 'web.assets_web_dark' - - #---------------------------------------------------------- - # Fields - #---------------------------------------------------------- - - theme_favicon = fields.Binary( - related='company_id.favicon', - readonly=False - ) - - theme_background_image_light = fields.Binary( - related='company_id.background_image_light', - readonly=False - ) - - theme_background_image_dark = fields.Binary( - related='company_id.background_image_dark', - readonly=False - ) - - theme_color_appbar_text_light = fields.Char( - string='AppsBar Text Light Color' - ) - - theme_color_appbar_active_light = fields.Char( - string='AppsBar Active Light Color' - ) - - theme_color_appbar_background_light = fields.Char( - string='AppsBar Background Light Color' - ) - - theme_color_appbar_text_dark = fields.Char( - string='AppsBar Text Dark Color' - ) - - theme_color_appbar_active_dark = fields.Char( - string='AppsBar Active Dark Color' - ) - - theme_color_appbar_background_dark = fields.Char( - string='AppsBar Background Dark Color' - ) - - #---------------------------------------------------------- - # Helper - #---------------------------------------------------------- - - def _get_light_theme_color_values(self): - return self.env['web_editor.assets'].get_color_variables_values( - self.COLOR_ASSET_THEME_LIGHT_URL, - self.COLOR_BUNDLE_THEME_LIGHT_NAME, - self.THEME_COLOR_FIELDS - ) - - def _get_dark_theme_color_values(self): - return self.env['web_editor.assets'].get_color_variables_values( - self.COLOR_ASSET_THEME_DARK_URL, - self.COLOR_BUNDLE_THEME_DARK_NAME, - self.THEME_COLOR_FIELDS - ) - - def _set_light_theme_color_values(self, values): - colors = self._get_light_theme_color_values() - for var, value in colors.items(): - values[f'theme_{var}_light'] = value - return values - - def _set_dark_theme_color_values(self, values): - colors = self._get_dark_theme_color_values() - for var, value in colors.items(): - values[f'theme_{var}_dark'] = value - return values - - def _detect_light_theme_color_change(self): - colors = self._get_light_theme_color_values() - return any( - self[f'theme_{var}_light'] != val - for var, val in colors.items() - ) - - def _detect_dark_theme_color_change(self): - colors = self._get_dark_theme_color_values() - return any( - self[f'theme_{var}_dark'] != val - for var, val in colors.items() - ) - - def _replace_light_theme_color_values(self): - variables = [ - { - 'name': field, - 'value': self[f'theme_{field}_light'] - } - for field in self.THEME_COLOR_FIELDS - ] - return self.env['web_editor.assets'].replace_color_variables_values( - self.COLOR_ASSET_THEME_LIGHT_URL, - self.COLOR_BUNDLE_THEME_LIGHT_NAME, - variables - ) - - def _replace_dark_theme_color_values(self): - variables = [ - { - 'name': field, - 'value': self[f'theme_{field}_dark'] - } - for field in self.THEME_COLOR_FIELDS - ] - return self.env['web_editor.assets'].replace_color_variables_values( - self.COLOR_ASSET_THEME_DARK_URL, - self.COLOR_BUNDLE_THEME_DARK_NAME, - variables - ) - - def _reset_light_theme_color_assets(self): - self.env['web_editor.assets'].reset_asset( - self.COLOR_ASSET_THEME_LIGHT_URL, - self.COLOR_BUNDLE_THEME_LIGHT_NAME, - ) - - def _reset_dark_theme_color_assets(self): - self.env['web_editor.assets'].reset_asset( - self.COLOR_ASSET_THEME_DARK_URL, - self.COLOR_BUNDLE_THEME_DARK_NAME, - ) - - #---------------------------------------------------------- - # Action - #---------------------------------------------------------- - - def action_reset_light_color_assets(self): - self._reset_light_theme_color_assets() - return super().action_reset_light_color_assets() - - def action_reset_dark_color_assets(self): - self._reset_dark_theme_color_assets() - return super().action_reset_dark_color_assets() - - #---------------------------------------------------------- - # Functions - #---------------------------------------------------------- - - def get_values(self): - res = super().get_values() - res = self._set_light_theme_color_values(res) - res = self._set_dark_theme_color_values(res) - return res - - def set_values(self): - res = super().set_values() - if self._detect_light_theme_color_change(): - self._replace_light_theme_color_values() - if self._detect_dark_theme_color_change(): - self._replace_dark_theme_color_values() - return res diff --git a/muk_web_enterprise_theme/static/description/banner.png b/muk_web_enterprise_theme/static/description/banner.png deleted file mode 100644 index f75f9a8dd..000000000 Binary files a/muk_web_enterprise_theme/static/description/banner.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/icon.png b/muk_web_enterprise_theme/static/description/icon.png deleted file mode 100644 index 88f65d4e4..000000000 Binary files a/muk_web_enterprise_theme/static/description/icon.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/icon.svg b/muk_web_enterprise_theme/static/description/icon.svg deleted file mode 100644 index 5eddf161f..000000000 --- a/muk_web_enterprise_theme/static/description/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/muk_web_enterprise_theme/static/description/index.html b/muk_web_enterprise_theme/static/description/index.html deleted file mode 100644 index c38f9d91d..000000000 --- a/muk_web_enterprise_theme/static/description/index.html +++ /dev/null @@ -1,138 +0,0 @@ -
-
-

MuK Backend Theme

-

Odoo Enterprise Backend Theme

- -

MuK IT GmbH - www.mukit.at

-
- - Community - - - Enterprise - -
-
- -
-
-
- -
-
-
-

Overview

-

- This module offers a mobile compatible design for Odoo Enterprise. Furthermore it - allows the user to define some design preferences. Each user can choose the size - of the sidebar. In addition, the background image of the home menu can be set - for each company. -

-
-
-
- -
-
-

- Want more? -

-

- Are you having troubles with your Odoo integration? Or do you feel - your system lacks of essential features?
If your answer is YES - to one of the above questions, feel free to contact us at anytime - with your inquiry.
We are looking forward to discuss your - needs and plan the next steps with you.
-

-
- -
- -
-
-

Our Services

-
-
-
-
- -
-

- Odoo
Development -

-
-
-
-
-
- -
-

- Odoo
Integration -

-
-
-
-
-
- -
-

- Odoo
Infrastructure -

-
-
-
-
-
- -
-

- Odoo
Training -

-
-
-
-
-
- -
-

- Odoo
Support -

-
-
-
-
-
diff --git a/muk_web_enterprise_theme/static/description/logo.png b/muk_web_enterprise_theme/static/description/logo.png deleted file mode 100644 index 9427ce33e..000000000 Binary files a/muk_web_enterprise_theme/static/description/logo.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/screenshot.png b/muk_web_enterprise_theme/static/description/screenshot.png deleted file mode 100644 index b4a14d74c..000000000 Binary files a/muk_web_enterprise_theme/static/description/screenshot.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/service_development.png b/muk_web_enterprise_theme/static/description/service_development.png deleted file mode 100644 index d64b66bda..000000000 Binary files a/muk_web_enterprise_theme/static/description/service_development.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/service_infrastructure.png b/muk_web_enterprise_theme/static/description/service_infrastructure.png deleted file mode 100644 index b899a3104..000000000 Binary files a/muk_web_enterprise_theme/static/description/service_infrastructure.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/service_integration.png b/muk_web_enterprise_theme/static/description/service_integration.png deleted file mode 100644 index 76c5e80f4..000000000 Binary files a/muk_web_enterprise_theme/static/description/service_integration.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/service_support.png b/muk_web_enterprise_theme/static/description/service_support.png deleted file mode 100644 index 4c530fafd..000000000 Binary files a/muk_web_enterprise_theme/static/description/service_support.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/service_training.png b/muk_web_enterprise_theme/static/description/service_training.png deleted file mode 100644 index 19ea76e63..000000000 Binary files a/muk_web_enterprise_theme/static/description/service_training.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/description/theme_screenshot.png b/muk_web_enterprise_theme/static/description/theme_screenshot.png deleted file mode 100644 index e6aa515cb..000000000 Binary files a/muk_web_enterprise_theme/static/description/theme_screenshot.png and /dev/null differ diff --git a/muk_web_enterprise_theme/static/src/scss/colors_dark.scss b/muk_web_enterprise_theme/static/src/scss/colors_dark.scss deleted file mode 100644 index 5f06207ea..000000000 --- a/muk_web_enterprise_theme/static/src/scss/colors_dark.scss +++ /dev/null @@ -1,11 +0,0 @@ -// Colors - -$mk_color_appbar_text: #E4E4E4; -$mk_color_appbar_active: #5D8DA8; -$mk_color_appbar_background: #3C3E4B; - -// Override - -$mk-appbar-color: $mk_color_appbar_text; -$mk-appbar-active: $mk_color_appbar_active; -$mk-appbar-background: $mk_color_appbar_background; diff --git a/muk_web_enterprise_theme/static/src/scss/colors_light.scss b/muk_web_enterprise_theme/static/src/scss/colors_light.scss deleted file mode 100644 index 05d7384df..000000000 --- a/muk_web_enterprise_theme/static/src/scss/colors_light.scss +++ /dev/null @@ -1,11 +0,0 @@ -// Colors - -$mk_color_appbar_text: #DEE2E6; -$mk_color_appbar_active: #5D8DA8; -$mk_color_appbar_background: #111827; - -// Override - -$mk-appbar-color: $mk_color_appbar_text; -$mk-appbar-active: $mk_color_appbar_active; -$mk-appbar-background: $mk_color_appbar_background; \ No newline at end of file diff --git a/muk_web_enterprise_theme/static/src/scss/variables.scss b/muk_web_enterprise_theme/static/src/scss/variables.scss deleted file mode 100644 index 07250f79a..000000000 --- a/muk_web_enterprise_theme/static/src/scss/variables.scss +++ /dev/null @@ -1 +0,0 @@ -$o-navbar-badge-bg: $o-brand-primary; diff --git a/muk_web_enterprise_theme/static/src/views/form/form.dark.scss b/muk_web_enterprise_theme/static/src/views/form/form.dark.scss deleted file mode 100644 index dd884cb3e..000000000 --- a/muk_web_enterprise_theme/static/src/views/form/form.dark.scss +++ /dev/null @@ -1,8 +0,0 @@ -.o_form_view { - &:not(.o_field_highlight) .o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) { - --o-input-border-color: #{$gray-400}; - } - &:not(.o_field_highlight) .o_required_modifier.o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) { - --o-input-border-color: #{$gray-600}; - } -} \ No newline at end of file diff --git a/muk_web_enterprise_theme/static/src/views/form/form.scss b/muk_web_enterprise_theme/static/src/views/form/form.scss deleted file mode 100644 index 3efa72fd2..000000000 --- a/muk_web_enterprise_theme/static/src/views/form/form.scss +++ /dev/null @@ -1,8 +0,0 @@ -.o_form_view { - &:not(.o_field_highlight) .o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) { - --o-input-border-color: #{$gray-200}; - } - &:not(.o_field_highlight) .o_required_modifier.o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) { - --o-input-border-color: #{$gray-400}; - } -} \ No newline at end of file diff --git a/muk_web_enterprise_theme/static/src/webclient/home_menu/home_menu.js b/muk_web_enterprise_theme/static/src/webclient/home_menu/home_menu.js deleted file mode 100644 index 383eebe76..000000000 --- a/muk_web_enterprise_theme/static/src/webclient/home_menu/home_menu.js +++ /dev/null @@ -1,31 +0,0 @@ -/** @odoo-module **/ - -import { url } from "@web/core/utils/urls"; -import { patch } from "@web/core/utils/patch"; -import { cookie } from "@web/core/browser/cookie"; - -import { HomeMenu } from "@web_enterprise/webclient/home_menu/home_menu"; - -patch(HomeMenu.prototype, { - setup() { - super.setup(); - if ( - cookie.get("color_scheme") === "dark" && - this.env.services.company.currentCompany.has_background_image_dark - ) { - this.backgroundImageUrl = url('/web/image', { - model: 'res.company', - field: 'background_image_dark', - id: this.env.services.company.currentCompany.id, - }); - } else if ( - this.env.services.company.currentCompany.has_background_image_light - ) { - this.backgroundImageUrl = url('/web/image', { - model: 'res.company', - field: 'background_image_light', - id: this.env.services.company.currentCompany.id, - }); - } - }, -}); diff --git a/muk_web_enterprise_theme/static/src/webclient/home_menu/home_menu.xml b/muk_web_enterprise_theme/static/src/webclient/home_menu/home_menu.xml deleted file mode 100644 index 8ba97081f..000000000 --- a/muk_web_enterprise_theme/static/src/webclient/home_menu/home_menu.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - {{ backgroundImageUrl ? "background-size: cover; background-position: center; background-image: url(" + backgroundImageUrl + ");" : "" }} - - - - - - - - - - \ No newline at end of file diff --git a/muk_web_enterprise_theme/templates/web_layout.xml b/muk_web_enterprise_theme/templates/web_layout.xml deleted file mode 100644 index 0d6b85232..000000000 --- a/muk_web_enterprise_theme/templates/web_layout.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/muk_web_enterprise_theme/views/res_config_settings.xml b/muk_web_enterprise_theme/views/res_config_settings.xml deleted file mode 100644 index fe863188e..000000000 --- a/muk_web_enterprise_theme/views/res_config_settings.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - res.config.settings.form - res.config.settings - - - - 1 - - - - - - res.config.settings.form - res.config.settings - - - - Backend Theme - - -
-
-
-
-
-
-
- -
-
-
-
-
-
-
- - - - - - - - -
- -
-
- -
- -
-
-
-
-
- -
diff --git a/tianhe_approvals/models/overtime_approval.py b/tianhe_approvals/models/overtime_approval.py index 02aec3151..242b8bfc4 100644 --- a/tianhe_approvals/models/overtime_approval.py +++ b/tianhe_approvals/models/overtime_approval.py @@ -15,26 +15,30 @@ class OvertimeApprovals(models.Model): if self.approval_category_name == 'overtime_approval': users_data_list = [] default_datetime = datetime.combine(datetime.now().date(), time(hour=17, minute=30)) - timedelta(hours=8), - self.overtime_user_ids.unlink() + users_list = [] + for user in self.overtime_user_ids: + users_list.append(user.user_id.id) for over in self: if not over.overtime_department_id: - users_data_list.append((0, 0, { - 'approval_request_id': over.id, - 'user_id': over.request_owner_id.id, - 'start_time': default_datetime[0], - 'type_overtime': 'work', - 'compensation_mode': 'salary', - })) - else: - employee_ids = self.env['hr.employee'].search([('department_id', '=', self.overtime_department_id.id)]) - for user in employee_ids: + if over.request_owner_id.id not in users_list: users_data_list.append((0, 0, { 'approval_request_id': over.id, - 'user_id': user.user_id.id, + 'user_id': over.request_owner_id.id, 'start_time': default_datetime[0], 'type_overtime': 'work', 'compensation_mode': 'salary', })) + else: + employee_ids = self.env['hr.employee'].search([('department_id', '=', self.overtime_department_id.id)]) + for user in employee_ids: + if user.user_id.id not in users_list: + users_data_list.append((0, 0, { + 'approval_request_id': over.id, + 'user_id': user.user_id.id, + 'start_time': default_datetime[0], + 'type_overtime': 'work', + 'compensation_mode': 'salary', + })) over.overtime_user_ids = users_data_list @@ -54,3 +58,6 @@ class OvertimeUserLine(models.Model): compensation_mode = fields.Selection([('salary', '薪资',), ('rest', '调休',)], string="补偿方式", default="salary") is_male_pay = fields.Boolean(string="加班餐费") user_attendance = fields.Char(string="考勤信息") + + def attendance_button(self): + return [] diff --git a/xy_wechat-master/.gitignore b/xy_wechat-master/.gitignore deleted file mode 100644 index 3b516ebf3..000000000 --- a/xy_wechat-master/.gitignore +++ /dev/null @@ -1,145 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ -local.conf -poetry.lock -local-addons/* -!local-addons/README.md -!local-addons/__init__.py -.project.yml -.DS_Store -.idea diff --git a/xy_wechat-master/LICENSE.md b/xy_wechat-master/LICENSE.md deleted file mode 100644 index 63b4b681c..000000000 --- a/xy_wechat-master/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) [year] [fullname] - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/xy_wechat-master/README.md b/xy_wechat-master/README.md deleted file mode 100644 index 3ea650c0a..000000000 --- a/xy_wechat-master/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# xy_wechat -适用于Odoo16版本的企业微信模块 - -
- -[![GitHub license](https://img.shields.io/github/license/xunonxyz/xy_wechat)](https://github.com/xunonxyz/xy_wechat/blob/master/LICENSE.md) -[![GitHub issues](https://img.shields.io/github/issues/xunonxyz/xy_wechat)](https://github.com/xunonxyz/xy_wechat/issues) -[![Odoo version](https://img.shields.io/badge/Odoo-16-brightgreen)](https://github.com/odoo/odoo/tree/16.0) - -
- -## ✨ 特点 - -- 采用python升级特性协程进行同步,速度比多线程更快。同步50人公司组织架构只需10s左右 -- 仅inherit了少量model,避免多层inherit冗余嵌套影响加载性能 -- 支持Odoo多公司切换,每个公司可设置多个企业微信应用 -- 使用Hr模块为基础进行员工管理,而不是直接res.users,充分利用Odoo原生模块功能 -- 完整的i18n简中翻译,默认使用英文 -- 包含企业微信内建应用必备功能,去掉了其余冗余而普遍用不上的功能,减少模块大小 - -## 🖥 环境支持 - -- Odoo16版本 -- postgresql12及以上版本(Odoo16的hr模块中使用了Json字段,需要数据库有Json函数支持) -- python3.7及以上(使用了协程特性) -- 安装python的`aiohttp`和`pycrypto`库 - -## 📦 安装 - -在Odoo的应用里找到`Wechat Enterprise`模块激活即可安装,安装后模块名称翻译会被加载变成「企业微信」 - -## ✨ 包含功能 - -| 功能名称 | 是否支持 | -| :-----------------------------------: | :------: | -| 多公司用户切换 | √ | -| 企业微信应用access_token获取并缓存 | √ | -| WW_verify_xxx.txt域名校验文件一键配置 | √ | -| 企业微信应用通讯录部门、成员一键同步 | √ | -| 企业微信通讯录部门、成员变更回调 | √ | -| 企业微信二维码扫码登录系统 | √ | -| 企业微信网页跳转登录系统 | √ | -| 向企业微信上传临时素材、永久图片 | √ | -| 推送、撤回企业微信各类型消息 | √ | - -## 🔨 使用 - -### 配置企业微信应用参数 - -在「Odoo系统 - 设置 - 用户&公司」页面,选中公司后切换到「企业微信应用」选项卡进行参数配置 - -注:如果勾选了应用中的「同步员工到res.user」则在保存hr.employee记录时也会创建res.users记录,否则仅创建hr.employee - -![./static/img/setting.png](./static/img/setting.png) - -### 同步 - -配置完参数后点击「同步组织架构」按钮即可。同步是在后端异步进行,不会阻塞当前操作,但尽量不要进行用户、部门的变更、创建、删除等操作。 - -同步完成或失败后均会有通知窗进行通知。 - -![./static/img/notice.png](./static/img/notice.png) - -### 同步日志 - -每次同步的结果、报错代码栈、花费的时间等信息均可以进行查看。 - -在「员工 - 企业微信模块日志」页面可进行查看 - -![./static/img/log.png](./static/img/log.png) - -## ❤️ 支持 - -富能通企业官网:https://www.funenc.com/ - -免费后端培训视频系列:https://www.bilibili.com/video/BV1rP411G7CZ/ - -知识星球Odoo源码解读: - - - -更多模块或进群交流欢迎加微信: - - \ No newline at end of file diff --git a/xy_wechat-master/__init__.py b/xy_wechat-master/__init__.py deleted file mode 100644 index 511a0ca3a..000000000 --- a/xy_wechat-master/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import controllers -from . import models \ No newline at end of file diff --git a/xy_wechat-master/__manifest__.py b/xy_wechat-master/__manifest__.py deleted file mode 100644 index 173b67072..000000000 --- a/xy_wechat-master/__manifest__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': "Wechat Enterprise", - - 'summary': 'Wechat Enterprise', - - 'description': """ - Api and methods for Wechat Enterprise , which is used in Internal Enterprise Applications. - Use pycrypto to replace Crypto. - Need python version >= 3.7 - """, - - 'author': "funenc", - 'website': "https://www.funenc.com", - - 'external_dependencies': { - 'python': ['aiohttp', 'Crypto'], - }, - - # Categories can be used to filter modules in modules listing - # Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml - # for the full list - 'category': 'Uncategorized', - 'version': '0.1', - - # any module necessary for this one to work correctly - 'depends': ['base', 'hr'], - 'assets': { - 'web.assets_backend': [ - 'wechat_enterprise/static/src/js/we_qrcode_widget.js', - ] - }, - # always loaded - 'data': [ - 'security/ir.model.access.csv', - 'views/company.xml', - 'views/app.xml', - 'views/log.xml', - ], - 'application': True -} diff --git a/xy_wechat-master/common/__init__.py b/xy_wechat-master/common/__init__.py deleted file mode 100644 index 2c24d6f3e..000000000 --- a/xy_wechat-master/common/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import token_store -from . import we_request -from . import custom_encrypt -from . import callback diff --git a/xy_wechat-master/common/callback/WXBizMsgCrypt.py b/xy_wechat-master/common/callback/WXBizMsgCrypt.py deleted file mode 100644 index 24a618962..000000000 --- a/xy_wechat-master/common/callback/WXBizMsgCrypt.py +++ /dev/null @@ -1,280 +0,0 @@ -#!/usr/bin/env python -# -*- encoding:utf-8 -*- - -""" 对企业微信发送给企业后台的消息加解密示例代码. -@copyright: Copyright (c) 1998-2014 Tencent Inc. - -""" -# ------------------------------------------------------------------------ -import logging -import base64 -import random -import hashlib -import time -import struct -from Crypto.Cipher import AES -import xml.etree.cElementTree as ET -import socket - -from . import ierror - - -""" -关于Crypto.Cipher模块,ImportError: No module named 'Crypto'解决方案 -请到官方网站 https://www.dlitz.net/software/pycrypto/ 下载pycrypto。 -下载后,按照README中的“Installation”小节的提示进行pycrypto安装。 -""" - - -class FormatException(Exception): - pass - - -def throw_exception(message, exception_class=FormatException): - """my define raise exception function""" - raise exception_class(message) - - -class SHA1: - """计算企业微信的消息签名接口""" - - def getSHA1(self, token, timestamp, nonce, encrypt): - """用SHA1算法生成安全签名 - @param token: 票据 - @param timestamp: 时间戳 - @param encrypt: 密文 - @param nonce: 随机字符串 - @return: 安全签名 - """ - try: - sortlist = [token, timestamp, nonce, encrypt] - sortlist.sort() - sha = hashlib.sha1() - sha.update("".join(sortlist).encode()) - return ierror.WXBizMsgCrypt_OK, sha.hexdigest() - except Exception as e: - logger = logging.getLogger() - logger.error(e) - return ierror.WXBizMsgCrypt_ComputeSignature_Error, None - - -class XMLParse: - """提供提取消息格式中的密文及生成回复消息格式的接口""" - - # xml消息模板 - AES_TEXT_RESPONSE_TEMPLATE = """ - - -%(timestamp)s - -""" - - def extract(self, xmltext): - """提取出xml数据包中的加密消息 - @param xmltext: 待提取的xml字符串 - @return: 提取出的加密消息字符串 - """ - try: - xml_tree = ET.fromstring(xmltext) - encrypt = xml_tree.find("Encrypt") - return ierror.WXBizMsgCrypt_OK, encrypt.text - except Exception as e: - logger = logging.getLogger() - logger.error(e) - return ierror.WXBizMsgCrypt_ParseXml_Error, None - - def generate(self, encrypt, signature, timestamp, nonce): - """生成xml消息 - @param encrypt: 加密后的消息密文 - @param signature: 安全签名 - @param timestamp: 时间戳 - @param nonce: 随机字符串 - @return: 生成的xml字符串 - """ - resp_dict = { - 'msg_encrypt': encrypt, - 'msg_signaturet': signature, - 'timestamp': timestamp, - 'nonce': nonce, - } - resp_xml = self.AES_TEXT_RESPONSE_TEMPLATE % resp_dict - return resp_xml - - -class PKCS7Encoder(): - """提供基于PKCS7算法的加解密接口""" - - block_size = 32 - - def encode(self, text): - """ 对需要加密的明文进行填充补位 - @param text: 需要进行填充补位操作的明文 - @return: 补齐明文字符串 - """ - text_length = len(text) - # 计算需要填充的位数 - amount_to_pad = self.block_size - (text_length % self.block_size) - if amount_to_pad == 0: - amount_to_pad = self.block_size - # 获得补位所用的字符 - pad = chr(amount_to_pad) - return text + (pad * amount_to_pad).encode() - - def decode(self, decrypted): - """删除解密后明文的补位字符 - @param decrypted: 解密后的明文 - @return: 删除补位字符后的明文 - """ - pad = ord(decrypted[-1]) - if pad < 1 or pad > 32: - pad = 0 - return decrypted[:-pad] - - -class Prpcrypt(object): - """提供接收和推送给企业微信消息的加解密接口""" - - def __init__(self, key): - - # self.key = base64.b64decode(key+"=") - self.key = key - # 设置加解密模式为AES的CBC模式 - self.mode = AES.MODE_CBC - - def encrypt(self, text, receiveid): - """对明文进行加密 - @param text: 需要加密的明文 - @return: 加密得到的字符串 - """ - # 16位随机字符串添加到明文开头 - text = text.encode() - text = self.get_random_str() + struct.pack("I", socket.htonl(len(text))) + text + receiveid.encode() - - # 使用自定义的填充方式对明文进行补位填充 - pkcs7 = PKCS7Encoder() - text = pkcs7.encode(text) - # 加密 - cryptor = AES.new(self.key, self.mode, self.key[:16]) - try: - ciphertext = cryptor.encrypt(text) - # 使用BASE64对加密后的字符串进行编码 - return ierror.WXBizMsgCrypt_OK, base64.b64encode(ciphertext) - except Exception as e: - logger = logging.getLogger() - logger.error(e) - return ierror.WXBizMsgCrypt_EncryptAES_Error, None - - def decrypt(self, text, receiveid): - """对解密后的明文进行补位删除 - @param text: 密文 - @return: 删除填充补位后的明文 - """ - try: - cryptor = AES.new(self.key, self.mode, self.key[:16]) - # 使用BASE64对密文进行解码,然后AES-CBC解密 - plain_text = cryptor.decrypt(base64.b64decode(text)) - except Exception as e: - logger = logging.getLogger() - logger.error(e) - return ierror.WXBizMsgCrypt_DecryptAES_Error, None - try: - pad = plain_text[-1] - # 去掉补位字符串 - # pkcs7 = PKCS7Encoder() - # plain_text = pkcs7.encode(plain_text) - # 去除16位随机字符串 - content = plain_text[16:-pad] - xml_len = socket.ntohl(struct.unpack("I", content[: 4])[0]) - xml_content = content[4: xml_len + 4] - from_receiveid = content[xml_len + 4:] - except Exception as e: - logger = logging.getLogger() - logger.error(e) - return ierror.WXBizMsgCrypt_IllegalBuffer, None - - if from_receiveid.decode('utf8') != receiveid: - return ierror.WXBizMsgCrypt_ValidateCorpid_Error, None - return 0, xml_content - - def get_random_str(self): - """ 随机生成16位字符串 - @return: 16位字符串 - """ - return str(random.randint(1000000000000000, 9999999999999999)).encode() - - -class WXBizMsgCrypt(object): - # 构造函数 - def __init__(self, sToken, sEncodingAESKey, sReceiveId): - try: - self.key = base64.b64decode(sEncodingAESKey + "=") - assert len(self.key) == 32 - except: - throw_exception("[error]: EncodingAESKey unvalid !", FormatException) - # return ierror.WXBizMsgCrypt_IllegalAesKey,None - self.m_sToken = sToken - self.m_sReceiveId = sReceiveId - - # 验证URL - # @param sMsgSignature: 签名串,对应URL参数的msg_signature - # @param sTimeStamp: 时间戳,对应URL参数的timestamp - # @param sNonce: 随机串,对应URL参数的nonce - # @param sEchoStr: 随机串,对应URL参数的echostr - # @param sReplyEchoStr: 解密之后的echostr,当return返回0时有效 - # @return:成功0,失败返回对应的错误码 - - def VerifyURL(self, sMsgSignature, sTimeStamp, sNonce, sEchoStr): - sha1 = SHA1() - ret, signature = sha1.getSHA1(self.m_sToken, sTimeStamp, sNonce, sEchoStr) - if ret != 0: - return ret, None - if not signature == sMsgSignature: - return ierror.WXBizMsgCrypt_ValidateSignature_Error, None - pc = Prpcrypt(self.key) - ret, sReplyEchoStr = pc.decrypt(sEchoStr, self.m_sReceiveId) - return ret, sReplyEchoStr - - def EncryptMsg(self, sReplyMsg, sNonce, timestamp=None): - # 将企业回复用户的消息加密打包 - # @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串 - # @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp,如为None则自动用当前时间 - # @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce - # sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串, - # return:成功0,sEncryptMsg,失败返回对应的错误码None - pc = Prpcrypt(self.key) - ret, encrypt = pc.encrypt(sReplyMsg, self.m_sReceiveId) - encrypt = encrypt.decode('utf8') - if ret != 0: - return ret, None - if timestamp is None: - timestamp = str(int(time.time())) - # 生成安全签名 - sha1 = SHA1() - ret, signature = sha1.getSHA1(self.m_sToken, timestamp, sNonce, encrypt) - if ret != 0: - return ret, None - xmlParse = XMLParse() - return ret, xmlParse.generate(encrypt, signature, timestamp, sNonce) - - def DecryptMsg(self, sPostData, sMsgSignature, sTimeStamp, sNonce): - # 检验消息的真实性,并且获取解密后的明文 - # @param sMsgSignature: 签名串,对应URL参数的msg_signature - # @param sTimeStamp: 时间戳,对应URL参数的timestamp - # @param sNonce: 随机串,对应URL参数的nonce - # @param sPostData: 密文,对应POST请求的数据 - # xml_content: 解密后的原文,当return返回0时有效 - # @return: 成功0,失败返回对应的错误码 - # 验证安全签名 - xmlParse = XMLParse() - ret, encrypt = xmlParse.extract(sPostData) - if ret != 0: - return ret, None - sha1 = SHA1() - ret, signature = sha1.getSHA1(self.m_sToken, sTimeStamp, sNonce, encrypt) - if ret != 0: - return ret, None - if not signature == sMsgSignature: - return ierror.WXBizMsgCrypt_ValidateSignature_Error, None - pc = Prpcrypt(self.key) - ret, xml_content = pc.decrypt(encrypt, self.m_sReceiveId) - return ret, xml_content diff --git a/xy_wechat-master/common/callback/__init__.py b/xy_wechat-master/common/callback/__init__.py deleted file mode 100644 index c298ce9ec..000000000 --- a/xy_wechat-master/common/callback/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import ierror -from . import WXBizMsgCrypt diff --git a/xy_wechat-master/common/callback/ierror.py b/xy_wechat-master/common/callback/ierror.py deleted file mode 100644 index 6c7ca1221..000000000 --- a/xy_wechat-master/common/callback/ierror.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -######################################################################### -# Author: jonyqin -# Created Time: Thu 11 Sep 2014 01:53:58 PM CST -# File Name: ierror.py -# Description:定义错误码含义 -######################################################################### -WXBizMsgCrypt_OK = 0 -WXBizMsgCrypt_ValidateSignature_Error = -40001 -WXBizMsgCrypt_ParseXml_Error = -40002 -WXBizMsgCrypt_ComputeSignature_Error = -40003 -WXBizMsgCrypt_IllegalAesKey = -40004 -WXBizMsgCrypt_ValidateCorpid_Error = -40005 -WXBizMsgCrypt_EncryptAES_Error = -40006 -WXBizMsgCrypt_DecryptAES_Error = -40007 -WXBizMsgCrypt_IllegalBuffer = -40008 -WXBizMsgCrypt_EncodeBase64_Error = -40009 -WXBizMsgCrypt_DecodeBase64_Error = -40010 -WXBizMsgCrypt_GenReturnXml_Error = -40011 diff --git a/xy_wechat-master/common/custom_encrypt.py b/xy_wechat-master/common/custom_encrypt.py deleted file mode 100644 index 3a84dcdf3..000000000 --- a/xy_wechat-master/common/custom_encrypt.py +++ /dev/null @@ -1,28 +0,0 @@ -import hashlib -import random - -salt_list = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - - -def get_random_str(): - salt = '' - for i in range(16): - salt += random.choice(salt_list) - return salt - - -class CustomEncrypt(object): - """ - custom encrypt, use md5 to encrypt password, and add salt to password. has not decrypt function - """ - salt = get_random_str() - - @staticmethod - def encrypt(password): - obj = hashlib.md5(CustomEncrypt.salt.encode("utf-8")) - obj.update(password.encode('utf-8')) - return obj.hexdigest() - - @staticmethod - def is_equal(password, encode_password): - return CustomEncrypt.encrypt(password) == encode_password diff --git a/xy_wechat-master/common/token_store.py b/xy_wechat-master/common/token_store.py deleted file mode 100644 index 754f34413..000000000 --- a/xy_wechat-master/common/token_store.py +++ /dev/null @@ -1,70 +0,0 @@ -import time - -token_temp = {} - - -class TokenStore(object): - def __init__(self, secret): - """ - secret is used to distinguish different WE apps - :param secret: - """ - self.secret = secret - - def save(self, token, expires_in, create_time=None): - """ - save token - :param token: token - :param expires_in: how long the token is valid, unit is second - :param create_time: if create_time is None, use current time - :return: - """ - current_time = time.time() - token_temp[self.secret] = { - 'token': token, - 'expires_in': expires_in, - 'update_time': current_time, - 'create_time': create_time or current_time - } - - def get(self): - """ - if token is expires, clear it and return None - :return: - """ - if self.secret in token_temp: - token = token_temp[self.secret] - if time.time() - token['update_time'] > token['expires_in']: - token_temp.pop(self.secret) - return None - return token['token'] - return None - - def refresh(self, expires_in): - """ - refresh token if it exists - :param expires_in: how long the token is valid, unit is second - :return: - """ - if self.secret in token_temp: - token_dict = token_temp[self.secret] - self.save(token_dict['token'], expires_in, token_dict['create_time']) - - @staticmethod - def clean(secret): - """ - clean token by secret - :param secret: string - :return: - """ - if secret in token_temp: - token_temp.pop(secret) - - @staticmethod - def clean_all(): - """ - clean all token - :return: - """ - for key in token_temp: - token_temp.pop(key) diff --git a/xy_wechat-master/common/we_request.py b/xy_wechat-master/common/we_request.py deleted file mode 100644 index 6cf85b598..000000000 --- a/xy_wechat-master/common/we_request.py +++ /dev/null @@ -1,228 +0,0 @@ -import aiohttp -from urllib import parse - -from .token_store import TokenStore - - -def check_response_error(response, error_code=0, error_msg_key='errmsg'): - if response['errcode'] != error_code: - raise Exception(response[error_msg_key]) - - -def join_url(base_url, *args): - if not args: - return base_url - return parse.urljoin(base_url, ''.join(args)) - - -class WeRequest(object): - url_prefix = 'https://qyapi.weixin.qq.com/cgi-bin/' - - def __init__(self, corp_id, secret): - """ - set WE corp_id and secret - :param corp_id: WE app corp_id - :param secret: WE app secret - """ - self.corp_id = corp_id - self.secret = secret - self.token_store = TokenStore(secret) - - async def refresh_token(self): - """ - refresh token if it expires - :return: - """ - current_token = self.token_store.get() - if not current_token: - token = await self.get_token() - self.token_store.save(token['token'], token['expires_in']) - - async def latest_token(self): - """ - get latest token - :return: - """ - await self.refresh_token() - return self.token_store.get() - - @staticmethod - async def get_response(url, params=None, response_callback=None): - """ - get response from server - :param url: url join with url_prefix - :param params: - :param response_callback: response callback function - :return: - """ - conn = aiohttp.TCPConnector(ssl=False) - async with aiohttp.ClientSession(connector=conn) as session: - async with session.get(url, params=params) as response: - return await response_callback(response) if response_callback else await response.json() - - @staticmethod - async def post_response(url, json, data=None, response_callback=None): - """ - post response to server, if json is not None, use json, else use data - :param url: url join with url_prefix - :param data: json data - :param json: form data - :param response_callback: response callback function - :return: - """ - conn = aiohttp.TCPConnector(ssl=False) - async with aiohttp.ClientSession(connector=conn) as session: - async with session.post(url, json=json, data=data) as response: - return await response_callback(response) if response_callback else await response.json() - - async def get_token(self): - """ - get token from server - :return: - """ - response = await self.get_response(join_url(self.url_prefix, 'gettoken'), { - 'corpid': self.corp_id, - 'corpsecret': self.secret - }) - check_response_error(response) - return { - 'token': response['access_token'], - 'expires_in': response['expires_in'] - } - - async def department_simplelist(self, id=None): - """ - get department simplelist from server - :param id: parent department id, if None, get all department - :return: - """ - response = await self.get_response(join_url(self.url_prefix, 'department/simplelist'), { - 'access_token': await self.latest_token(), - 'id': id or '' - }) - check_response_error(response) - return response['department_id'] - - async def department_detail(self, id): - """ - get department detail from server - :param id: department id, required - :return: - """ - assert id, 'id is required' - response = await self.get_response(join_url(self.url_prefix, 'department/get'), { - 'access_token': await self.latest_token(), - 'id': id - }) - check_response_error(response) - return response['department'] - - async def department_users(self, dep_id): - """ - get department users from server - :param dep_id: department id, required - :return: - """ - assert dep_id, 'dep_id is required' - response = await self.get_response(join_url(self.url_prefix, 'user/list'), { - 'access_token': await self.latest_token(), - 'department_id': dep_id - }) - check_response_error(response) - return response['userlist'] - - async def get_userid(self, code): - """ - get userid from server - :param code: user code by scan qrcode - :return: - """ - assert code, 'code is required' - response = await self.get_response(join_url(self.url_prefix, 'auth/getuserinfo'), { - 'access_token': await self.latest_token(), - 'code': code - }) - check_response_error(response) - return response.get('userid', None) or response.get('openid', None) - - async def send_message(self, message): - """ - send message to user - :param message: message dict - :return: - """ - assert message and isinstance(message, dict), 'message is required and must be dict' - response = await self.post_response( - join_url(self.url_prefix, f'message/send?access_token={await self.latest_token()}'), message) - check_response_error(response) - return response.get('msgid', None) - - async def recall_message(self, msg_id): - """ - recall message - :param msg_id: message id - :return: - """ - assert msg_id, 'msg_id is required' - response = await self.post_response( - join_url(self.url_prefix, f'message/recall?access_token={await self.latest_token()}'), {'msgid': msg_id}) - check_response_error(response) - return response.get('errmsg', None) - - async def upload_media(self, media_type, media_file, filename): - """ - upload temporary media to server, it only save 3 days, the file size has limit, - reference: https://developer.work.weixin.qq.com/document/path/91054 - :param media_type: image, voice, video, file - :param media_file: file content bytes - :param filename: file name - :return: media_id - """ - data = aiohttp.FormData() - data.add_field('media', media_file, filename=filename, content_type='application/octet-stream') - response = await self.post_response( - join_url(self.url_prefix, f'media/upload?access_token={await self.latest_token()}&type={media_type}'), - None, data) - check_response_error(response) - return response.get('media_id', None) - - async def upload_image(self, media_file, filename): - """ - upload image to server, it can save permanently, the file size has limit, - reference: https://developer.work.weixin.qq.com/document/path/91054 - :param media_file: file content bytes - :param filename: file name - :return: file url - """ - data = aiohttp.FormData() - data.add_field(filename, media_file, filename=filename, content_type='application/octet-stream') - response = await self.post_response( - join_url(self.url_prefix, f'media/uploadimg?access_token={await self.latest_token()}'), - None, data) - check_response_error(response) - return response.get('url', None) - - async def get_media(self, media_id): - """ - get media from server - :param media_id: media id - :return: media content bytes - """ - async def _cb(res): - return await res.read() - - response = await self.get_response(join_url(self.url_prefix, f'media/get'), { - 'access_token': await self.latest_token(), - 'media_id': media_id - }, response_callback=_cb) - return response - - -def we_request_instance(corp_id, secret): - """ - if you want to use custom WeRequest class or Store class, you can set monkey patch to this function - :param corp_id: - :param secret: - :return: - """ - return WeRequest(corp_id, secret) diff --git a/xy_wechat-master/controllers/__init__.py b/xy_wechat-master/controllers/__init__.py deleted file mode 100644 index 457bae27e..000000000 --- a/xy_wechat-master/controllers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import controllers \ No newline at end of file diff --git a/xy_wechat-master/controllers/controllers.py b/xy_wechat-master/controllers/controllers.py deleted file mode 100644 index 8e4674be2..000000000 --- a/xy_wechat-master/controllers/controllers.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -import asyncio -import base64 -from urllib import parse -import warnings -import xml.etree.cElementTree as ET - -from odoo import http -from odoo.http import route, request -from ..common.we_request import we_request_instance, join_url -from ..models.res_users import ResUsers -from ..common.custom_encrypt import CustomEncrypt -from ..common.callback.WXBizMsgCrypt import WXBizMsgCrypt - -# Crypto will show warning, ignore it -warnings.filterwarnings("ignore", category=DeprecationWarning) - - -class WechatEnterprise(http.Controller): - scan_oauth_url = 'https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid={corp_id}&agentid={agentid}&redirect_uri={redirect_uri}' - web_oauth_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid={corp_id}&redirect_uri={redirect_uri}&response_type=code&scope={scope}&agentid={agentid}#wechat_redirect' - - @http.route('/WW_verify_.txt', type='http', auth="none", methods=['GET']) - def load_file(self, filename=None): - """ - load verify file, easily to verify wechat enterprise redirect url - :param filename: - :return: - """ - app = request.env['wechat.enterprise.app'].sudo().search( - [('verify_txt_filename', '=', f'WW_verify_{filename}.txt')], - limit=1 - ) - if len(app) == 0: - content = None - else: - content = base64.b64decode(app[0].verify_txt).decode('utf-8') - return content - - @route('/we/oauth2/info', type='json', auth='public') - def get_we_oauth2_info(self, app_id, redirect_uri=None): - """ - get info for build Wechat Enterprise QRCode to login - :param app_id: - :param redirect_uri: redirect url after login, don't need host - :return: - """ - app = request.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - host = request.httprequest.host_url - return { - 'agentid': app.agentid, - 'corp_id': app.corp_id, - 'redirect_uri': join_url(host, f'we/oauth2/login/{app_id}') if redirect_uri is None else - join_url(host, redirect_uri) - } - - @route('/we/oauth2/login/', type='http', auth='public') - def login_by_oauth2(self, code, app_id): - """ - login by wechat enterprise oauth2 - :param code: - :param app_id: - :return: - """ - app = request.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - we_request = we_request_instance(app.corp_id, app.secret) - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - get_userid_task = loop.create_task(we_request.get_userid(code)) - loop.run_until_complete(get_userid_task) - loop.close() - we_id = get_userid_task.result() - employee = request.env['hr.employee'].sudo().search([('we_id', '=', we_id)]) - if employee.user_id.id: - secret_dict = { - 'npa': True, - 'type': 'we', - 'password': CustomEncrypt.encrypt(ResUsers.we_auth_secret) - } - request.session.authenticate(request.session.db, employee.user_id.login, secret_dict) - return request.redirect('/web') - - @route('/we/oauth2/build//', type='http', auth='public') - def we_oauth2(self, oauth_type, app_id, scope='snsapi_base'): - """ - build wechat enterprise oauth2 url - :param oauth_type: scan or web, scan is build to qrcode, web is build to redirect url - :param app_id: authenticate used app id - :param scope: snsapi_base or snsapi_privateinfo - :return: - """ - oauth2_info = self.get_we_oauth2_info(app_id) - corp_id = oauth2_info['corp_id'] - agentid = oauth2_info['agentid'] - redirect_uri = parse.quote(oauth2_info['redirect_uri']) - - _redirect_uri = '' - if oauth_type == 'scan': - _redirect_uri = WechatEnterprise.scan_oauth_url.format( - corp_id=corp_id, - agentid=agentid, - redirect_uri=redirect_uri - ) - elif oauth_type == 'web': - _redirect_uri = WechatEnterprise.web_oauth_url.format( - corp_id=corp_id, - agentid=agentid, - redirect_uri=redirect_uri, - scope=scope - ) - return request.redirect(_redirect_uri, 303, False) - - @route('/we/mail_list/callback', type='http', auth='public', csrf=False) - def we_callback(self, msg_signature, timestamp, nonce, echostr=''): - if request.httprequest.method == 'GET': - result = None - company_list = request.env['res.company'].sudo().search([]) - for company in company_list: - if company.we_cb_token and company.we_cb_encoding_AES_key: - wxcpt = WXBizMsgCrypt(company.we_cb_token, company.we_cb_encoding_AES_key, company.we_corp_id) - ret, s_echo_str = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr) - if ret == 0: - result = s_echo_str - break - return result - else: - data = request.httprequest.data.decode('utf-8') - # get ToUserName to match company corp_id - temp_xml_tree = ET.fromstring(data) - corp_id = temp_xml_tree.find('ToUserName').text - company = request.env['res.company'].sudo().search([('we_corp_id', '=', corp_id)]) - - wxcpt = WXBizMsgCrypt(company.we_cb_token, company.we_cb_encoding_AES_key, company.we_corp_id) - ret, result = wxcpt.DecryptMsg(data, msg_signature, timestamp, nonce) - if ret == 0: - xml_tree = ET.fromstring(result) - change_type = xml_tree.find('ChangeType').text - # change_type may be xxx_user or xxx_party - suffix = change_type.split('_')[1] - model = request.env['hr.employee'] if suffix == 'user' else request.env['hr.department'] - # method need return 'success' or empty string - func = getattr(model, f'on_we_{change_type}', None) - if func: - return func(xml_tree, company) - return '' diff --git a/xy_wechat-master/i18n/zh_CN.po b/xy_wechat-master/i18n/zh_CN.po deleted file mode 100644 index 379be37ca..000000000 --- a/xy_wechat-master/i18n/zh_CN.po +++ /dev/null @@ -1,235 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * wechat_enterprise -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 16.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-08 09:36+0000\n" -"PO-Revision-Date: 2022-11-08 09:36+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: base -#: model:ir.module.module,shortdesc:base.module_wechat_enterprise -#: model:ir.module.module,summary:base.module_wechat_enterprise -msgid "Wechat Enterprise" -msgstr "企业微信" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__agentid -msgid "Agent ID" -msgstr "应用ID" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_res_company__app_ids -msgid "Apps" -msgstr "企业微信应用" - -#. module: wechat_enterprise -#: model_terms:ir.ui.view,arch_db:wechat_enterprise.we_company_extend -msgid "Callback Settings" -msgstr "通讯录回调设置" - -#. module: wechat_enterprise -#: model:ir.model,name:wechat_enterprise.model_res_company -msgid "Companies" -msgstr "公司" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__company_id -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__company_id -msgid "Company" -msgstr "公司" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_res_company__we_corp_id -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__corp_id -msgid "Corp ID" -msgstr "企业ID" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__create_uid -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__create_uid -msgid "Created by" -msgstr "创建人" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__create_date -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__create_date -msgid "Created on" -msgstr "创建时间" - -#. module: wechat_enterprise -#: model:ir.model,name:wechat_enterprise.model_hr_department -msgid "Department" -msgstr "部门" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__description -msgid "Description" -msgstr "说明" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__detail -msgid "Detail" -msgstr "详情" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__display_name -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__display_name -msgid "Display Name" -msgstr "显示名称" - -#. module: wechat_enterprise -#: model:ir.model,name:wechat_enterprise.model_hr_employee -msgid "Employee" -msgstr "员工" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_res_company__we_cb_encoding_AES_key -msgid "EncodingAESKey" -msgstr "" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__id -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__id -msgid "ID" -msgstr "" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app____last_update -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log____last_update -msgid "Last Modified on" -msgstr "最后修改时间" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__write_uid -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__write_uid -msgid "Last Updated by" -msgstr "最后更新人" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__write_date -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__write_date -msgid "Last Updated on" -msgstr "最后更新时间" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__name -msgid "Name" -msgstr "名称" - -#. module: wechat_enterprise -#: code:addons/wechat_enterprise/models/employee.py:0 -#, python-format -msgid "Please select the user or department to send the message!" -msgstr "请选择发送message的用户或部门!" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__secret -msgid "Secret" -msgstr "" - -#. module: wechat_enterprise -#: code:addons/wechat_enterprise/models/app.py:0 -#, python-format -msgid "Start sync organization now, please wait......" -msgstr "开始同步组织架构,请稍候......" - -#. module: wechat_enterprise -#: model_terms:ir.ui.view,arch_db:wechat_enterprise.we_company_extend -msgid "Sync Organization" -msgstr "同步组织架构" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__sync_with_user -msgid "Sync with res.user" -msgstr "同步员工到res.user" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_res_company__we_cb_token -msgid "Token" -msgstr "" - -#. module: wechat_enterprise -#: model_terms:ir.ui.view,arch_db:wechat_enterprise.wechat_enterprise_app_form -msgid "Url Verify Settings" -msgstr "域名验证设置" - -#. module: wechat_enterprise -#: model:ir.model,name:wechat_enterprise.model_res_users -msgid "User" -msgstr "用户" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__verify_txt_filename -msgid "Verify Txt Filename" -msgstr "网页授权验证文件名" - -#. module: wechat_enterprise -#: model:ir.model,name:wechat_enterprise.model_wechat_enterprise_app -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_log__we_app_id -msgid "Wechat Enterprise App" -msgstr "企业微信应用" - -#. module: wechat_enterprise -#: model_terms:ir.ui.view,arch_db:wechat_enterprise.we_company_extend -msgid "Wechat Enterprise Apps" -msgstr "企业微信应用" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_department__we_id -msgid "Wechat Enterprise Department ID" -msgstr "企业微信部门ID" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_department__we_order -msgid "Wechat Enterprise Department Order" -msgstr "企业微信部门排序" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_employee__we_department_ids -msgid "Wechat Enterprise Departments" -msgstr "企业微信部门" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_department__we_employee_ids -msgid "Wechat Enterprise Employees" -msgstr "企业微信员工" - -#. module: wechat_enterprise -#: model:ir.model,name:wechat_enterprise.model_wechat_enterprise_log -msgid "Wechat Enterprise Log" -msgstr "企业微信日志" - -#. module: wechat_enterprise -#: model:ir.actions.act_window,name:wechat_enterprise.wechat_enterprise_log_act_window -#: model:ir.ui.menu,name:wechat_enterprise.menu_wechat_enterprise_log -msgid "Wechat Enterprise Logs" -msgstr "企业微信模块日志" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_department__we_parent_id -msgid "Wechat Enterprise Parent Department ID" -msgstr "企业微信父部门ID" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_employee__we_extattr -msgid "Wechat Enterprise User Extattr" -msgstr "企业微信用户扩展属性" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_hr_employee__we_id -msgid "Wechat Enterprise User ID" -msgstr "企业微信用户ID" - -#. module: wechat_enterprise -#: model:ir.model.fields,field_description:wechat_enterprise.field_wechat_enterprise_app__verify_txt -msgid "verify_txt" -msgstr "网页授权验证文件" diff --git a/xy_wechat-master/models/__init__.py b/xy_wechat-master/models/__init__.py deleted file mode 100644 index 1348d3312..000000000 --- a/xy_wechat-master/models/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -from . import app -from . import company -from . import department -from . import employee -from . import log -from . import res_users - diff --git a/xy_wechat-master/models/app.py b/xy_wechat-master/models/app.py deleted file mode 100644 index 677256a88..000000000 --- a/xy_wechat-master/models/app.py +++ /dev/null @@ -1,129 +0,0 @@ -import asyncio -import threading -import time -import datetime -import traceback - -from odoo import models, fields, api -from odoo.tools.translate import _ - -from ..common.we_request import we_request_instance - - -def get_now_time_str(): - return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') - - -class App(models.Model): - _name = 'wechat.enterprise.app' - _description = 'Wechat Enterprise App' - - name = fields.Char(string='Name', required=True) - description = fields.Text(string='Description') - corp_id = fields.Char(string='Corp ID', related='company_id.we_corp_id', readonly=True) - secret = fields.Char(string='Secret', required=True) - agentid = fields.Char(string='Agent ID', required=True) - sync_with_user = fields.Boolean(string='Sync with res.user', default=True) - company_id = fields.Many2one('res.company', string='Company', required=True) - # use in verify url - verify_txt_filename = fields.Char(string='Verify Txt Filename', readonly=True) - verify_txt = fields.Binary('verify_txt') - - def run_sync(self): - self.env['bus.bus']._sendone(self.env.user.partner_id, 'simple_notification', { - 'title': 'Sync Start......', - 'message': _('Start sync organization now, please wait......'), - 'warning': True - }) - - # create a threading to avoid odoo ui blocking - def _sync(): - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - asyncio.run(self.sync_organization()) - - thread = threading.Thread(target=_sync) - thread.start() - - async def sync_organization(self): - start = time.time() - uid = self.env.uid - is_success = True - with self.env.registry.cursor() as new_cr: - self.env = api.Environment(new_cr, uid, self.env.context) - - detail_log = f'start sync at {get_now_time_str()}......' - try: - we_request = we_request_instance(self.corp_id, self.secret) - - await self.env['hr.department'].with_context( - self.env.context, we_app=self, we_request=we_request - ).sync_department() - detail_log += f'\nsync success!' - except Exception: - is_success = False - detail_log += f'\nsync failed, error: \n{traceback.format_exc()}' - finally: - detail_log += f'\nsync end at {get_now_time_str()}, cost {round(time.time() - start, 2)}s' - company_id = self.company_id.id - self.env['wechat.enterprise.log'].create({ - 'company_id': company_id, - 'we_app_id': self.id, - 'detail': detail_log - }) - self.env['bus.bus']._sendone(self.env.user.partner_id, 'simple_notification', { - 'title': 'Sync End......', - 'message': f'Sync organization end, {"success" if is_success else "failed"}', - 'warning': True if is_success else False - }) - - def upload_media(self, app_id, media_type, file_content, filename): - """ - upload temp media to wechat server - :param app_id: save at which app server - :param media_type: image, voice, video, file - :param file_content: file content bytes - :param filename: file name - :return: media_id in wechat server - """ - app = self.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - we_request = we_request_instance(app.corp_id, app.secret) - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - upload_media_task = loop.create_task(we_request.upload_media(media_type, file_content, filename)) - loop.run_until_complete(upload_media_task) - loop.close() - return upload_media_task.result() - - def upload_image(self, app_id, file_content, filename): - """ - upload permanently image to wechat server - :param app_id: save at which app server - :param file_content: file content bytes - :param filename: file name - :return: file_url in wechat server - """ - app = self.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - we_request = we_request_instance(app.corp_id, app.secret) - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - upload_img_task = loop.create_task(we_request.upload_image(file_content, filename)) - loop.run_until_complete(upload_img_task) - loop.close() - return upload_img_task.result() - - def get_media(self, app_id, media_id): - """ - get media from wechat server - :param app_id: save in which app server - :param media_id: media id in wechat server - :return: file content bytes - """ - app = self.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - we_request = we_request_instance(app.corp_id, app.secret) - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - get_media_task = loop.create_task(we_request.get_media(media_id)) - loop.run_until_complete(get_media_task) - loop.close() - return get_media_task.result() diff --git a/xy_wechat-master/models/company.py b/xy_wechat-master/models/company.py deleted file mode 100644 index 1a0351f18..000000000 --- a/xy_wechat-master/models/company.py +++ /dev/null @@ -1,11 +0,0 @@ -from odoo import models, fields - - -class Company(models.Model): - _inherit = 'res.company' - - we_corp_id = fields.Char(string='Corp ID', required=True, default='Wechat Enterprise corp id') - app_ids = fields.One2many('wechat.enterprise.app', 'company_id', string='Apps') - # use in WE callback - we_cb_token = fields.Char(string='Token') - we_cb_encoding_AES_key = fields.Char(string='EncodingAESKey') diff --git a/xy_wechat-master/models/department.py b/xy_wechat-master/models/department.py deleted file mode 100644 index f106bb31f..000000000 --- a/xy_wechat-master/models/department.py +++ /dev/null @@ -1,137 +0,0 @@ -import asyncio - -from odoo import models, fields - - -class Department(models.Model): - _inherit = 'hr.department' - - we_id = fields.Char(string='Wechat Enterprise Department ID') - we_parent_id = fields.Char(string='Wechat Enterprise Parent Department ID') - we_order = fields.Integer(string='Wechat Enterprise Department Order') - '''because a Wechat Enterprise user can have multi departments, so we need a many2many field, - the department_id field is only main department''' - we_employee_ids = fields.Many2many('hr.employee', 'we_employee_department_rel', 'department_id', 'employee_id', - string='Wechat Enterprise Employees') - - async def get_server_depart_tree(self): - """ - get Wechat Enterprise server department tree, root parentid is 1 - :return: - """ - we_request = self.env.context.get('we_request') - departments = await we_request.department_simplelist() - - def get_tree_data(arr, parent_id): - tree = [] - for item in arr: - if item['parentid'] == parent_id: - tree.append({ - 'id': item['id'], - 'parentid': item['parentid'], - 'order': item['order'], - 'children': get_tree_data(arr, item['id']) - }) - - return tree - - return get_tree_data(departments, 1) - - async def sync_department(self): - """ - sync department from wechat enterprise - :return: - """ - we_request = self.env.context.get('we_request') - we_app = self.env.context.get('we_app') - - depart_tree = await self.get_server_depart_tree() - - tasks = [] - - async def _sync_dep(server_dep, parent_id): - _tasks = [] - dep_detail = await we_request.department_detail(server_dep['id']) - - dep = self.search([('we_id', '=', dep_detail['id'])]) - # dep need commit to db because sync user need use it - modify_data = { - 'company_id': we_app.company_id.id, - 'name': dep_detail['name'], - 'we_id': dep_detail['id'], - 'parent_id': parent_id, - 'we_parent_id': dep_detail['parentid'], - 'we_order': dep_detail['order'], - 'manager_id': False - } - - if dep.id is False: - dep = self.create(modify_data) - else: - # change where the employee in the department status to active = False - self.env['hr.employee'].search([('we_department_ids.we_id', '=', dep_detail['id'])]).write( - {'active': False}) - dep.write(modify_data) - - await self.env['hr.employee'].sync_user(dep, dep_detail['id']) - - if len(server_dep['children']) > 0: - for child in server_dep['children']: - _tasks.append(_sync_dep(child, dep.id)) - await asyncio.gather(*_tasks) - - for department in depart_tree: - tasks.append(_sync_dep(department, False)) - - await asyncio.gather(*tasks) - - def on_we_create_party(self, xml_tree, company): - """ - on wechat enterprise create department event, only has Id and ParentId, no Name or Other fields - :param xml_tree: ET.fromstring(str) instance - :param company: receive company - :return: - """ - we_id = xml_tree.find('Id').text - we_parent_id = xml_tree.find('ParentId').text - parent_dep = self.sudo().search([('we_id', '=', we_parent_id), ('company_id', '=', company.id)]) - self.sudo().create({ - 'company_id': company.id, - 'name': f'we_id_{we_id}', - 'we_id': we_id, - 'parent_id': parent_dep.id, - 'we_parent_id': we_parent_id, - 'manager_id': False - }) - return 'success' - - def on_we_update_party(self, xml_tree, company): - """ - on wechat enterprise update department event, only has Id and ParentId, no Name or Other fields - :param xml_tree: ET.fromstring(str) instance - :param company: receive company - :return: - """ - we_id = xml_tree.find('Id').text - we_parent_id = xml_tree.find('ParentId').text - dep = self.sudo().search([('we_id', '=', we_id), ('company_id', '=', company.id)]) - if dep.id is not False: - parent_dep = self.sudo().search([('we_id', '=', we_parent_id), ('company_id', '=', company.id)]) - dep.write({ - 'parent_id': parent_dep.id, - 'we_parent_id': we_parent_id - }) - return 'success' - - def on_we_delete_party(self, xml_tree, company): - """ - on wechat enterprise delete department event, only has Id and ParentId, no Name or Other fields - :param xml_tree: ET.fromstring(str) instance - :param company: receive company - :return: - """ - we_id = xml_tree.find('Id').text - dep = self.sudo().search([('we_id', '=', we_id), ('company_id', '=', company.id)]) - if dep.id is not False: - dep.unlink() - return 'success' diff --git a/xy_wechat-master/models/employee.py b/xy_wechat-master/models/employee.py deleted file mode 100644 index ffe49f641..000000000 --- a/xy_wechat-master/models/employee.py +++ /dev/null @@ -1,234 +0,0 @@ -import asyncio - -from odoo import models, fields -from odoo.exceptions import UserError -from odoo.tools.translate import _ - -from ..common.we_request import we_request_instance - -USER_STATUS = { - 'active': [1, 4], - 'not_active': [2, 5] -} - - -def send_list_to_str(send_list): - """ - convert send list to str - :param send_list: wx_id list or string of @all - :return: - """ - if send_list == 'all' or send_list is None: - return send_list - return '|'.join(send_list) - - -class Employee(models.Model): - _inherit = 'hr.employee' - - we_id = fields.Char(string='Wechat Enterprise User ID') - we_department_ids = fields.Many2many('hr.department', 'we_employee_department_rel', 'employee_id', 'department_id', - string='Wechat Enterprise Departments') - we_extattr = fields.Json(string='Wechat Enterprise User Extattr') - - def write_with_user(self, val): - if self.user_id.id is False: - user = self.env['res.users'].create({ - 'name': val['name'], - 'login': val['we_id'], - 'company_id': val['company_id'], - 'company_ids': [(4, val['company_id'])], - 'groups_id': [(6, 0, [self.env.ref('base.group_user').id])], - 'active': val['active'] - }) - val['user_id'] = user.id - else: - self.user_id.write({ - 'name': val['name'], - 'active': val['active'] - }) - self.write(val) - - def create_with_user(self, val_list): - for val in val_list: - user = self.env['res.users'].search([('login', '=', val['we_id']), ('active', 'in', [True, False])]) - if user.id is False: - user = self.env['res.users'].create({ - 'name': val['name'], - 'login': val['we_id'], - 'company_id': val['company_id'], - 'company_ids': [(4, val['company_id'])], - 'groups_id': [(6, 0, [self.env.ref('base.group_user').id])], - 'active': val['active'] - }) - val['user_id'] = user.id - - return self.create(val_list) - - async def sync_user(self, we_department, server_dep_id): - we_request = self.env.context.get('we_request') - we_app = self.env.context.get('we_app') - sync_with_user = we_app.sync_with_user - - user_list = await we_request.department_users(server_dep_id) - create_users = [] - manager_id = None - - for user in user_list: - # job - job = self.env['hr.job'].search( - [('name', '=', user['position']), ('company_id', '=', we_app.company_id.id)]) - if job.id is False: - job = self.env['hr.job'].create({ - 'name': user['position'], - 'company_id': we_app.company_id.id - }) - - employee = self.search([('we_id', '=', user['userid']), ('active', 'in', [True, False])]) - main_department = we_department.search([('we_id', '=', user['main_department'])]) - - modify_data = { - 'name': user['name'], - 'we_id': user['userid'], - 'company_id': we_app.company_id.id, - 'department_id': main_department.id, - 'we_department_ids': [(4, we_department.id)], - 'job_id': job.id, - 'we_extattr': user['extattr'], - 'active': user['status'] in USER_STATUS['active'] - } - - if employee.id is False: - modify_data['marital'] = False - modify_data['work_phone'] = False - modify_data['parent_id'] = False - create_users.append(modify_data) - else: - employee.write_with_user(modify_data) if sync_with_user else employee.write(modify_data) - - # set department manager - if user['isleader'] == 1 and not manager_id: - manager_id = user['userid'] - - if len(create_users) > 0: - # create users limit 500 - limit = 500 - for i in range(0, len(create_users), limit): - create_vals = create_users[i:i + limit] - # if config set not sync user, not create user - self.create_with_user(create_vals) if sync_with_user else self.create(create_vals) - if manager_id: - we_department.write({'manager_id': self.search([('we_id', '=', manager_id)]).id}) - - def send_we_message(self, app_id, to_users, to_departments=None, msgtype='text', **kwargs): - """ - send message in Wechat Enterprise - because sync's info has no tag, so we can't send message to tag, only can send to the single app, - the existing parameters are 'to_users', 'to_departments', 'msgtype', 'agentid' - :param app_id: wechat enterprise app id used to send message - :param to_users: wechat enterprise user we_id list, if to all user, set to '@all' - :param to_departments: wechat enterprise department we_id list, if to all department, set to '@all' - :param msgtype: message type, reference https://developer.work.weixin.qq.com/document/path/90236 - :param kwargs: other parameters, reference https://developer.work.weixin.qq.com/document/path/90236 - :return: message id - """ - assert app_id, 'app_id is required' - if len(to_users) == 0 and len(to_departments) == 0: - raise UserError(_('Please select the user or department to send the message!')) - - app = self.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - we_request = we_request_instance(app.corp_id, app.secret) - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - send_message_task = loop.create_task(we_request.send_message(dict( - touser=send_list_to_str(to_users), - toparty=send_list_to_str(to_departments), - msgtype=msgtype, - agentid=app.agentid, - **kwargs - ))) - loop.run_until_complete(send_message_task) - loop.close() - return send_message_task.result() - - def recall_we_message(self, app_id, msg_id): - """ - recall message in Wechat Enterprise - :param app_id: wechat enterprise app id used to recall message - :param msg_id: Has been sent message id - :return: True or False - """ - assert app_id, 'app_id is required' - assert msg_id, 'msg_id is required' - app = self.env['wechat.enterprise.app'].sudo().browse(int(app_id)) - we_request = we_request_instance(app.corp_id, app.secret) - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - recall_message_task = loop.create_task(we_request.recall_message(msg_id)) - loop.run_until_complete(recall_message_task) - loop.close() - return recall_message_task.result() == 'ok' - - def on_we_create_user(self, xml_tree, company): - """ - on wechat enterprise create user event, only has UserID and Department, no Other fields - :param xml_tree: ET.fromstring(str) instance - :param company: receive company - :return: - """ - we_id = xml_tree.find('UserID').text - # multi dep_id is split by ',' - we_dep_id = xml_tree.find('Department').text - dep_id_list = we_dep_id.split(',') - we_departments = self.env['hr.department'].sudo().search( - [('we_id', 'in', dep_id_list), ('company_id', '=', company.id)]) - - self.sudo().create({ - 'name': f'we_id_{we_id}', - 'we_id': we_id, - 'company_id': company.id, - # use first department as main department temporarily - 'department_id': we_departments[0].id if len(we_departments) > 0 else False, - 'we_department_ids': [(6, 0, we_departments.ids)], - 'active': True - }) - return 'success' - - def on_we_update_user(self, xml_tree, company): - """ - on wechat enterprise update user event, only has UserID and Department and NewUserId, no Other fields, - only trigger when user change department or user_id - :param xml_tree: ET.fromstring(str) instance - :param company: receive company - :return: - """ - we_id = xml_tree.find('UserID').text - new_we_id = xml_tree.find('NewUserId').text if xml_tree.find('NewUserId') else None - # multi dep_id is split by ',' - we_dep_id = xml_tree.find('Department').text - dep_id_list = we_dep_id.split(',') - we_departments = self.env['hr.department'].sudo().search( - [('we_id', 'in', dep_id_list), ('company_id', '=', company.id)]) - - employee = self.sudo().search([('we_id', '=', we_id), ('company_id', '=', company.id)]) - if employee.id is not False: - employee.write({ - 'we_id': new_we_id or we_id, - # use first department as main department temporarily - 'department_id': we_departments[0].id if len(we_departments) > 0 else False, - 'we_department_ids': [(6, 0, we_departments.ids)] - }) - return 'success' - - def on_we_delete_user(self, xml_tree, company): - """ - on wechat enterprise delete user event, only has UserID, no Other fields - :param xml_tree: ET.fromstring(str) instance - :param company: receive company - :return: - """ - we_id = xml_tree.find('UserID').text - employee = self.sudo().search([('we_id', '=', we_id), ('company_id', '=', company.id)]) - if employee.id is not False: - employee.write({'active': False}) - return 'success' diff --git a/xy_wechat-master/models/log.py b/xy_wechat-master/models/log.py deleted file mode 100644 index 724a7a209..000000000 --- a/xy_wechat-master/models/log.py +++ /dev/null @@ -1,11 +0,0 @@ -from odoo import models, fields - - -class WechatEnterpriseLog(models.Model): - _name = 'wechat.enterprise.log' - _description = 'Wechat Enterprise Log' - _order = 'create_date desc' - - company_id = fields.Many2one('res.company', string='Company') - we_app_id = fields.Many2one('wechat.enterprise.app', string='Wechat Enterprise App') - detail = fields.Text(string='Detail') diff --git a/xy_wechat-master/models/res_users.py b/xy_wechat-master/models/res_users.py deleted file mode 100644 index 7aa67a2a9..000000000 --- a/xy_wechat-master/models/res_users.py +++ /dev/null @@ -1,34 +0,0 @@ -from odoo import models -from odoo.exceptions import AccessDenied - -from ..common.custom_encrypt import CustomEncrypt - - -class ResUsers(models.Model): - _inherit = 'res.users' - we_auth_secret = 'RZDeROZp' - - def _check_credentials(self, password, env): - """ - if password is dict and the key of Non password authentication(npa) is True, then authentication by custom - :param password: - :param env: - :return: - """ - if isinstance(password, dict) and password.get('npa', False) is True: - if not self.authentication_by_non_password(password, env): - raise AccessDenied() - else: - super()._check_credentials(password, env) - - def authentication_by_non_password(self, secret_dict, env): - """ - authentication by custom, can override this method to implement others authentication - :param secret_dict: {'npa': True, 'type': 'we', 'password': 'xxxx'}, can add more type to implement others - :param env: - :return: - """ - real_password = secret_dict.get('password', None) - if secret_dict.get('type', None) == 'we': - return CustomEncrypt.is_equal(ResUsers.we_auth_secret, real_password) - return False diff --git a/xy_wechat-master/security/ir.model.access.csv b/xy_wechat-master/security/ir.model.access.csv deleted file mode 100644 index 569899093..000000000 --- a/xy_wechat-master/security/ir.model.access.csv +++ /dev/null @@ -1,4 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_wechat_enterprise_app,wechat.enterprise.app,model_wechat_enterprise_app,base.group_system,1,1,1,1 - -access_wechat_enterprise_log,wechat.enterprise.log,model_wechat_enterprise_log,base.group_system,1,1,1,1 \ No newline at end of file diff --git a/xy_wechat-master/static/description/icon.png b/xy_wechat-master/static/description/icon.png deleted file mode 100644 index 394162386..000000000 Binary files a/xy_wechat-master/static/description/icon.png and /dev/null differ diff --git a/xy_wechat-master/static/img/knowledge_star.png b/xy_wechat-master/static/img/knowledge_star.png deleted file mode 100644 index 6523919d7..000000000 Binary files a/xy_wechat-master/static/img/knowledge_star.png and /dev/null differ diff --git a/xy_wechat-master/static/img/log.png b/xy_wechat-master/static/img/log.png deleted file mode 100644 index 7acd88081..000000000 Binary files a/xy_wechat-master/static/img/log.png and /dev/null differ diff --git a/xy_wechat-master/static/img/notice.png b/xy_wechat-master/static/img/notice.png deleted file mode 100644 index 3fb8b12e2..000000000 Binary files a/xy_wechat-master/static/img/notice.png and /dev/null differ diff --git a/xy_wechat-master/static/img/setting.png b/xy_wechat-master/static/img/setting.png deleted file mode 100644 index b60c4b099..000000000 Binary files a/xy_wechat-master/static/img/setting.png and /dev/null differ diff --git a/xy_wechat-master/static/img/wx_qrcode.png b/xy_wechat-master/static/img/wx_qrcode.png deleted file mode 100644 index 98fd503f9..000000000 Binary files a/xy_wechat-master/static/img/wx_qrcode.png and /dev/null differ diff --git a/xy_wechat-master/static/src/js/we_qrcode_widget.js b/xy_wechat-master/static/src/js/we_qrcode_widget.js deleted file mode 100644 index dd4638e7a..000000000 --- a/xy_wechat-master/static/src/js/we_qrcode_widget.js +++ /dev/null @@ -1,46 +0,0 @@ -/** @odoo-module */ - -import {registry} from "@web/core/registry"; - -const {Component, xml, useEffect, onWillStart} = owl; -import {loadJS} from "@web/core/assets"; -import {useService} from "@web/core/utils/hooks"; - -class WEQrcode extends Component { - setup() { - this.rpc = useService("rpc"); - - onWillStart(() => loadJS("http://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.7.js")); - - useEffect(async () => { - // to safety, we can not request by search_read, so we use rpc - const app = await this.rpc('/we/oauth2/info', { - app_id: this.props.appId - }) - - new WwLogin({ - "id": "wx_reg", - "appid": app.corp_id, - "agentid": app.agentid, - "redirect_uri": encodeURIComponent(app.redirect_uri), - }); - }, () => []) - } -} - -WEQrcode.template = xml` -
-
-
-`; - -WEQrcode.defaultProps = { - appId: "", -}; -WEQrcode.extractProps = ({attrs}) => { - return { - appId: attrs.app_id, - }; -}; - -registry.category("view_widgets").add("we_qrcode", WEQrcode); \ No newline at end of file diff --git a/xy_wechat-master/views/app.xml b/xy_wechat-master/views/app.xml deleted file mode 100644 index c8e5c9bfc..000000000 --- a/xy_wechat-master/views/app.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - wechat.enterprise.app.form - wechat.enterprise.app - -
- - - - - - - - - - - - - - - - -

Url Verify Settings

- - - - - -
-
-
-
-
diff --git a/xy_wechat-master/views/company.xml b/xy_wechat-master/views/company.xml deleted file mode 100644 index 66aae73ea..000000000 --- a/xy_wechat-master/views/company.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - we.company.extend - res.company - - primary - 2 - - - - - - - -

Callback Settings

- - - - - - - - - - - - - - -