diff --git a/odoo_health_report/README.rst b/odoo_health_report/README.rst new file mode 100644 index 000000000..0e31adacc --- /dev/null +++ b/odoo_health_report/README.rst @@ -0,0 +1,46 @@ +.. image:: https://img.shields.io/badge/license-OPL--1-red.svg + :target: https://www.odoo.com/documentation/18.0/legal/licenses.html#odoo-apps + :alt: License: OPL-1 + +Odoo Health Report +================= +This module allows you to display Odoo app module details and print them as a PDF report. + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +======= +Odoo Proprietary License v1.0 (OPL-1) +(https://www.odoo.com/documentation/18.0/legal/licenses.html#odoo-apps) + +Credits +------- +Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/odoo_health_report/__init__.py b/odoo_health_report/__init__.py new file mode 100644 index 000000000..554e2bf83 --- /dev/null +++ b/odoo_health_report/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +###################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies 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 NON INFRINGEMENT. +# 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. +# +###################################################################################### +from . import models +from . import reports diff --git a/odoo_health_report/__manifest__.py b/odoo_health_report/__manifest__.py new file mode 100644 index 000000000..92b987c64 --- /dev/null +++ b/odoo_health_report/__manifest__.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +###################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies 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 NON INFRINGEMENT. +# 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. +# +###################################################################################### +{ + 'name': 'Odoo Health Report', + 'version': '18.0.1.0.1', + 'category': 'Productivity', + 'summary': "Odoo Module Health Monitoring Tool", + 'description': 'Displays odoo apps report in the menu and as a PDF report.', + 'license': 'OPL-1', + 'author': "Cybrosys Techno Solutions", + 'website': "https://www.cybrosys.com", + 'company': "Cybrosys Techno Solutions", + 'maintainer': "Cybrosys Techno Solutions", + 'depends': ['base', 'web'], + 'external_dependencies': { + 'python': [ + 'isort', + 'black', + 'bandit', + 'radon', + 'pylint', + 'flake8' + ], + }, + 'data': [ + 'security/ir.model.access.csv', + 'reports/ir_actions_report.xml', + 'reports/odoo_health_report.xml', + 'views/odoo_health_report_menus.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'https://cdn.jsdelivr.net/npm/chart.js', + 'https://cdnjs.cloudflare.com/ajax/libs/iconify/2.0.0/iconify.min.js', + 'https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Public+Sans:ital,wght@0,100..900;1,100..900&display=swap.css', + 'odoo_health_report/static/src/css/main.css', + 'odoo_health_report/static/src/js/module_quality.js', + 'odoo_health_report/static/src/js/health_dashboard.js', + 'odoo_health_report/static/src/js/dashboard_wrapper.js', + 'odoo_health_report/static/src/xml/module_quality.xml', + 'odoo_health_report/static/src/xml/health_dashboard.xml', + 'odoo_health_report/static/src/xml/dashboard_wrapper.xml', + ], + }, + 'images': ['static/description/banner.png'], + 'application': True, + 'installable': True, + 'auto_install': False, +} diff --git a/odoo_health_report/doc/RELEASE_NOTES.md b/odoo_health_report/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..cd3c045bb --- /dev/null +++ b/odoo_health_report/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 02.07.2025 +#### Version 18.0.1.0.1 +#### ADD +- Initial Commit for Odoo Health Report diff --git a/odoo_health_report/models/__init__.py b/odoo_health_report/models/__init__.py new file mode 100644 index 000000000..81ac82c07 --- /dev/null +++ b/odoo_health_report/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +###################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies 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 NON INFRINGEMENT. +# 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. +# +###################################################################################### +from . import module_quality_package diff --git a/odoo_health_report/models/module_quality_package.py b/odoo_health_report/models/module_quality_package.py new file mode 100644 index 000000000..acc870931 --- /dev/null +++ b/odoo_health_report/models/module_quality_package.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +###################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies 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 NON INFRINGEMENT. +# 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. +# +###################################################################################### + +from odoo import api, models +from .check_python_violations import installed_modules, count_module_lines, module_and_icons, violations_report, get_violations + + +class ModuleQuality(models.AbstractModel): + """Class for analyzing the quality of installed modules""" + _name = 'module.quality.package' + _description = "Module Quality Metrics" + + def get_installed_modules(self): + """Function to fetch installed modules""" + return installed_modules(self) + + @api.model + def count_lines_of_code_in_modules(self): + """Count lines of Python, JavaScript, and XML code in all installed Odoo modules.""" + return count_module_lines(self) + + @api.model + def fields_and_apps_overview(self): + """Get the count of fields in database""" + # apps in percentage + all_apps = self.env['ir.module.module'].search_count([]) + installed_apps = self.env['ir.module.module'].search_count([('state', '=', 'installed')]) + percentage = (installed_apps/all_apps) * 100 + + total = self.env['ir.model.fields'].search([]) + non_stored = len(total.filtered(lambda x: not x.store)) + model_stored = len(total.filtered(lambda x: x.store)) + + return { + "critical_overview": { + "overall_percentage": { + "label": "Overall Apps Installed ratio", + "value": round(percentage, 2), + "description": "Displays the percentage of installed apps in Odoo compared to the total available apps." + }, + "total_fields": { + "label": "Total fields", + "value": len(total), + "description": "shows the total number of fields", + }, + "stored": { + "label": "Stored fields", + "value": model_stored, + "description": + "Shows the total count of stored fields in the database", + }, + "non_stored": { + "label": "Non stored fields", + "value": non_stored, + "description": "Shows the total count of non-stored fields in the database", + }, + }, + } + + @api.model + def get_module_and_icons(self): + """Retrieve all custom module name and icon as a dictionary""" + return module_and_icons(self) + + @api.model + def check_violations_report(self, module): + """Check the violations for PDF report""" + return violations_report(self, module) + + @api.model + def check_violations(self, module): + """Check the violations and standards""" + return get_violations(module) \ No newline at end of file diff --git a/odoo_health_report/reports/__init__.py b/odoo_health_report/reports/__init__.py new file mode 100644 index 000000000..420298623 --- /dev/null +++ b/odoo_health_report/reports/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +###################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies 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 NON INFRINGEMENT. +# 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. +# +###################################################################################### +from . import odoo_health_report diff --git a/odoo_health_report/reports/ir_actions_report.xml b/odoo_health_report/reports/ir_actions_report.xml new file mode 100644 index 000000000..a90a86bba --- /dev/null +++ b/odoo_health_report/reports/ir_actions_report.xml @@ -0,0 +1,28 @@ + + + + A4 Health Report + + custom + 297 + 210 + Portrait + 10.00 + 10.00 + 10.0 + 10.0 + + 35 + 125 + + + + Odoo Health Report + module.quality.package + qweb-pdf + odoo_health_report.odoo_health_report + odoo_health_report.odoo_health_report + + Odoo Health Report + + diff --git a/odoo_health_report/reports/odoo_health_report.py b/odoo_health_report/reports/odoo_health_report.py new file mode 100644 index 000000000..936e57fd5 --- /dev/null +++ b/odoo_health_report/reports/odoo_health_report.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +###################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies 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 NON INFRINGEMENT. +# 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. +# +###################################################################################### +import copy + +from odoo import models, api + + +class OdooHealthReport(models.AbstractModel): + _name = "report.odoo_health_report.odoo_health_report" + _description = "Odoo Health Report" + + @api.model + def _get_report_values(self, docids, data=None): + module_quality_dict = {} + data_dict = data.get('context', {}).get('data') or data + if 'module' in data_dict.get('selected'): + ModuleQualityPackage = self.env['module.quality.package'] + module_quality_dict['field_details'] = ModuleQualityPackage.fields_and_apps_overview() + module_quality_dict['count_lines'] = ModuleQualityPackage.count_lines_of_code_in_modules() + + selected_modules = [key for key, value in data_dict.get('module_selected', {}).items() if value] + + violations_list = [] + if selected_modules: + for selected_module in selected_modules: + module_violations = ModuleQualityPackage.check_violations_report(selected_module) + violations_list.append(copy.deepcopy(module_violations)) + else: + all_installed_modules = ModuleQualityPackage.get_installed_modules().mapped('name') + for module in all_installed_modules: + violations_list.append(ModuleQualityPackage.check_violations_report(module)) + module_quality_dict['violations'] = violations_list + else: + module_quality_dict = None + + return { + 'module_quality': module_quality_dict, + 'doc_ids': docids, + 'doc_model': 'module.quality', + 'docs': self, + 'selected_module': selected_modules + } diff --git a/odoo_health_report/reports/odoo_health_report.xml b/odoo_health_report/reports/odoo_health_report.xml new file mode 100644 index 000000000..ca77924e1 --- /dev/null +++ b/odoo_health_report/reports/odoo_health_report.xml @@ -0,0 +1,180 @@ + + + + \ No newline at end of file diff --git a/odoo_health_report/security/ir.model.access.csv b/odoo_health_report/security/ir.model.access.csv new file mode 100644 index 000000000..a8a92e4d2 --- /dev/null +++ b/odoo_health_report/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_module_quality_package,access.module.quality.package,model_module_quality_package,base.group_user,1,1,1,1 diff --git a/odoo_health_report/static/description/assets/icons/arrows-repeat.svg b/odoo_health_report/static/description/assets/icons/arrows-repeat.svg new file mode 100644 index 000000000..1d7efabc5 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/arrows-repeat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/banner-1.png b/odoo_health_report/static/description/assets/icons/banner-1.png new file mode 100644 index 000000000..c180db172 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/banner-1.png differ diff --git a/odoo_health_report/static/description/assets/icons/banner-2.svg b/odoo_health_report/static/description/assets/icons/banner-2.svg new file mode 100644 index 000000000..e606d97d9 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/banner-2.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/banner-bg.png b/odoo_health_report/static/description/assets/icons/banner-bg.png new file mode 100644 index 000000000..a8238d3c0 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/banner-bg.png differ diff --git a/odoo_health_report/static/description/assets/icons/banner-bg.svg b/odoo_health_report/static/description/assets/icons/banner-bg.svg new file mode 100644 index 000000000..b1378103e --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/banner-bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/banner-call.svg b/odoo_health_report/static/description/assets/icons/banner-call.svg new file mode 100644 index 000000000..96c687e81 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/banner-call.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_health_report/static/description/assets/icons/banner-mail.svg b/odoo_health_report/static/description/assets/icons/banner-mail.svg new file mode 100644 index 000000000..cbf0d158d --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/banner-mail.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_health_report/static/description/assets/icons/banner-pattern.svg b/odoo_health_report/static/description/assets/icons/banner-pattern.svg new file mode 100644 index 000000000..9c1c7e101 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/banner-pattern.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/banner-promo.svg b/odoo_health_report/static/description/assets/icons/banner-promo.svg new file mode 100644 index 000000000..d52791b11 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/banner-promo.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/brand-pair.svg b/odoo_health_report/static/description/assets/icons/brand-pair.svg new file mode 100644 index 000000000..d8db7fc1e --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/brand-pair.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/check.png b/odoo_health_report/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/check.png differ diff --git a/odoo_health_report/static/description/assets/icons/chevron.png b/odoo_health_report/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/chevron.png differ diff --git a/odoo_health_report/static/description/assets/icons/close-icon.svg b/odoo_health_report/static/description/assets/icons/close-icon.svg new file mode 100644 index 000000000..df8cce37a --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/close-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_health_report/static/description/assets/icons/cogs.png b/odoo_health_report/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/cogs.png differ diff --git a/odoo_health_report/static/description/assets/icons/collabarate-icon.svg b/odoo_health_report/static/description/assets/icons/collabarate-icon.svg new file mode 100644 index 000000000..dd4e10518 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/collabarate-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/description/assets/icons/consultation.png b/odoo_health_report/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/consultation.png differ diff --git a/odoo_health_report/static/description/assets/icons/cybro-logo.png b/odoo_health_report/static/description/assets/icons/cybro-logo.png new file mode 100644 index 000000000..ff4b78220 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/cybro-logo.png differ diff --git a/odoo_health_report/static/description/assets/icons/down.svg b/odoo_health_report/static/description/assets/icons/down.svg new file mode 100644 index 000000000..f21c36271 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odoo_health_report/static/description/assets/icons/ecom-black.png b/odoo_health_report/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/ecom-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/education-black.png b/odoo_health_report/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/education-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/faq.png b/odoo_health_report/static/description/assets/icons/faq.png new file mode 100644 index 000000000..4250b5b81 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/faq.png differ diff --git a/odoo_health_report/static/description/assets/icons/feature-icon.svg b/odoo_health_report/static/description/assets/icons/feature-icon.svg new file mode 100644 index 000000000..fa0ea6850 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/feature-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/feature.png b/odoo_health_report/static/description/assets/icons/feature.png new file mode 100644 index 000000000..ac7a785c0 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/feature.png differ diff --git a/odoo_health_report/static/description/assets/icons/gear.svg b/odoo_health_report/static/description/assets/icons/gear.svg new file mode 100644 index 000000000..0cc66b6ea --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/gear.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/hero.gif b/odoo_health_report/static/description/assets/icons/hero.gif new file mode 100644 index 000000000..380654dfe Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/hero.gif differ diff --git a/odoo_health_report/static/description/assets/icons/hire-odoo.svg b/odoo_health_report/static/description/assets/icons/hire-odoo.svg new file mode 100644 index 000000000..e1ac089b0 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/hire-odoo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/hotel-black.png b/odoo_health_report/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/hotel-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/license.png b/odoo_health_report/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/license.png differ diff --git a/odoo_health_report/static/description/assets/icons/life-ring-icon.svg b/odoo_health_report/static/description/assets/icons/life-ring-icon.svg new file mode 100644 index 000000000..3ae6e1d89 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/life-ring-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/lifebuoy.png b/odoo_health_report/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/lifebuoy.png differ diff --git a/odoo_health_report/static/description/assets/icons/mail.svg b/odoo_health_report/static/description/assets/icons/mail.svg new file mode 100644 index 000000000..1eedde695 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/mail.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/description/assets/icons/manufacturing-black.png b/odoo_health_report/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/manufacturing-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/notes.png b/odoo_health_report/static/description/assets/icons/notes.png new file mode 100644 index 000000000..ee5e95404 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/notes.png differ diff --git a/odoo_health_report/static/description/assets/icons/notification icon.svg b/odoo_health_report/static/description/assets/icons/notification icon.svg new file mode 100644 index 000000000..053189973 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/notification icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/odoo-consultancy.svg b/odoo_health_report/static/description/assets/icons/odoo-consultancy.svg new file mode 100644 index 000000000..e05f65bde --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/odoo-consultancy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/odoo_health_report/static/description/assets/icons/odoo-licencing.svg b/odoo_health_report/static/description/assets/icons/odoo-licencing.svg new file mode 100644 index 000000000..2606c88b0 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/odoo-licencing.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/description/assets/icons/odoo-logo.png b/odoo_health_report/static/description/assets/icons/odoo-logo.png new file mode 100644 index 000000000..0e4d0eb5a Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/odoo-logo.png differ diff --git a/odoo_health_report/static/description/assets/icons/patter.svg b/odoo_health_report/static/description/assets/icons/patter.svg new file mode 100644 index 000000000..25c9c0a8f --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/patter.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/pattern1.png b/odoo_health_report/static/description/assets/icons/pattern1.png new file mode 100644 index 000000000..09ab0fb2d Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/pattern1.png differ diff --git a/odoo_health_report/static/description/assets/icons/pos-black.png b/odoo_health_report/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/pos-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/puzzle-piece-icon.svg b/odoo_health_report/static/description/assets/icons/puzzle-piece-icon.svg new file mode 100644 index 000000000..3e9ad9373 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/puzzle-piece-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/puzzle.png b/odoo_health_report/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/puzzle.png differ diff --git a/odoo_health_report/static/description/assets/icons/replace-icon.svg b/odoo_health_report/static/description/assets/icons/replace-icon.svg new file mode 100644 index 000000000..d0e3a7af1 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/replace-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/restaurant-black.png b/odoo_health_report/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/restaurant-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/screenshot-main.png b/odoo_health_report/static/description/assets/icons/screenshot-main.png new file mode 100644 index 000000000..575f8e676 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/screenshot-main.png differ diff --git a/odoo_health_report/static/description/assets/icons/screenshot.png b/odoo_health_report/static/description/assets/icons/screenshot.png new file mode 100644 index 000000000..cef272529 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/screenshot.png differ diff --git a/odoo_health_report/static/description/assets/icons/service-black.png b/odoo_health_report/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/service-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/skype-fill.svg b/odoo_health_report/static/description/assets/icons/skype-fill.svg new file mode 100644 index 000000000..c17423639 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/skype-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/skype.png b/odoo_health_report/static/description/assets/icons/skype.png new file mode 100644 index 000000000..51b409fb3 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/skype.png differ diff --git a/odoo_health_report/static/description/assets/icons/skype.svg b/odoo_health_report/static/description/assets/icons/skype.svg new file mode 100644 index 000000000..df3dad39b --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/skype.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/description/assets/icons/star-1.svg b/odoo_health_report/static/description/assets/icons/star-1.svg new file mode 100644 index 000000000..7e55ab162 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/star-1.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/star-2.svg b/odoo_health_report/static/description/assets/icons/star-2.svg new file mode 100644 index 000000000..5ae9f507a --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/star-2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/support.png b/odoo_health_report/static/description/assets/icons/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/support.png differ diff --git a/odoo_health_report/static/description/assets/icons/test-1 - Copy.png b/odoo_health_report/static/description/assets/icons/test-1 - Copy.png new file mode 100644 index 000000000..f6a902663 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/test-1 - Copy.png differ diff --git a/odoo_health_report/static/description/assets/icons/test-1.png b/odoo_health_report/static/description/assets/icons/test-1.png new file mode 100644 index 000000000..0908add2b Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/test-1.png differ diff --git a/odoo_health_report/static/description/assets/icons/test-2.png b/odoo_health_report/static/description/assets/icons/test-2.png new file mode 100644 index 000000000..4671fe91e Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/test-2.png differ diff --git a/odoo_health_report/static/description/assets/icons/trading-black.png b/odoo_health_report/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/trading-black.png differ diff --git a/odoo_health_report/static/description/assets/icons/training.png b/odoo_health_report/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/training.png differ diff --git a/odoo_health_report/static/description/assets/icons/translate.svg b/odoo_health_report/static/description/assets/icons/translate.svg new file mode 100644 index 000000000..af9c8a1aa --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/translate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/update.png b/odoo_health_report/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/update.png differ diff --git a/odoo_health_report/static/description/assets/icons/user.png b/odoo_health_report/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/user.png differ diff --git a/odoo_health_report/static/description/assets/icons/video.png b/odoo_health_report/static/description/assets/icons/video.png new file mode 100644 index 000000000..576705b17 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/video.png differ diff --git a/odoo_health_report/static/description/assets/icons/whatsapp.png b/odoo_health_report/static/description/assets/icons/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/whatsapp.png differ diff --git a/odoo_health_report/static/description/assets/icons/wrench-icon.svg b/odoo_health_report/static/description/assets/icons/wrench-icon.svg new file mode 100644 index 000000000..174b5a465 --- /dev/null +++ b/odoo_health_report/static/description/assets/icons/wrench-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/description/assets/icons/wrench.png b/odoo_health_report/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/odoo_health_report/static/description/assets/icons/wrench.png differ diff --git a/odoo_health_report/static/description/assets/modules/1.gif b/odoo_health_report/static/description/assets/modules/1.gif new file mode 100644 index 000000000..ae3a880a2 Binary files /dev/null and b/odoo_health_report/static/description/assets/modules/1.gif differ diff --git a/odoo_health_report/static/description/assets/modules/2.gif b/odoo_health_report/static/description/assets/modules/2.gif new file mode 100644 index 000000000..d19e2b352 Binary files /dev/null and b/odoo_health_report/static/description/assets/modules/2.gif differ diff --git a/odoo_health_report/static/description/assets/modules/3.png b/odoo_health_report/static/description/assets/modules/3.png new file mode 100644 index 000000000..8513873ea Binary files /dev/null and b/odoo_health_report/static/description/assets/modules/3.png differ diff --git a/odoo_health_report/static/description/assets/modules/4.png b/odoo_health_report/static/description/assets/modules/4.png new file mode 100644 index 000000000..3bedf7981 Binary files /dev/null and b/odoo_health_report/static/description/assets/modules/4.png differ diff --git a/odoo_health_report/static/description/assets/modules/5.png b/odoo_health_report/static/description/assets/modules/5.png new file mode 100644 index 000000000..0e311ca87 Binary files /dev/null and b/odoo_health_report/static/description/assets/modules/5.png differ diff --git a/odoo_health_report/static/description/assets/modules/6.jpg b/odoo_health_report/static/description/assets/modules/6.jpg new file mode 100644 index 000000000..67c7f7062 Binary files /dev/null and b/odoo_health_report/static/description/assets/modules/6.jpg differ diff --git a/odoo_health_report/static/description/assets/screenshots/gif.gif b/odoo_health_report/static/description/assets/screenshots/gif.gif new file mode 100644 index 000000000..a5acabdf1 Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/gif.gif differ diff --git a/odoo_health_report/static/description/assets/screenshots/img1.png b/odoo_health_report/static/description/assets/screenshots/img1.png new file mode 100644 index 000000000..2dc823ed0 Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img1.png differ diff --git a/odoo_health_report/static/description/assets/screenshots/img2.png b/odoo_health_report/static/description/assets/screenshots/img2.png new file mode 100644 index 000000000..a120e597d Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img2.png differ diff --git a/odoo_health_report/static/description/assets/screenshots/img3.png b/odoo_health_report/static/description/assets/screenshots/img3.png new file mode 100644 index 000000000..b1907f34a Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img3.png differ diff --git a/odoo_health_report/static/description/assets/screenshots/img4.png b/odoo_health_report/static/description/assets/screenshots/img4.png new file mode 100644 index 000000000..3e7f6fe27 Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img4.png differ diff --git a/odoo_health_report/static/description/assets/screenshots/img5.png b/odoo_health_report/static/description/assets/screenshots/img5.png new file mode 100644 index 000000000..4b315945f Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img5.png differ diff --git a/odoo_health_report/static/description/assets/screenshots/img6.png b/odoo_health_report/static/description/assets/screenshots/img6.png new file mode 100644 index 000000000..1d27fd4ce Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img6.png differ diff --git a/odoo_health_report/static/description/assets/screenshots/img7.png b/odoo_health_report/static/description/assets/screenshots/img7.png new file mode 100644 index 000000000..7c0425a06 Binary files /dev/null and b/odoo_health_report/static/description/assets/screenshots/img7.png differ diff --git a/odoo_health_report/static/description/banner.png b/odoo_health_report/static/description/banner.png new file mode 100644 index 000000000..b39ac272a Binary files /dev/null and b/odoo_health_report/static/description/banner.png differ diff --git a/odoo_health_report/static/description/icon.png b/odoo_health_report/static/description/icon.png new file mode 100644 index 000000000..4a4b29d2e Binary files /dev/null and b/odoo_health_report/static/description/icon.png differ diff --git a/odoo_health_report/static/description/index.html b/odoo_health_report/static/description/index.html new file mode 100644 index 000000000..e26d37d31 --- /dev/null +++ b/odoo_health_report/static/description/index.html @@ -0,0 +1,1017 @@ + + + + + + Employee Bonus + + + + + + + + + + +
+
+ + + +
+
+ Community +
+ + + + + + + + +
+
+ +
+
+
+
+

+ It helps understand the quality of modules. +

+

Odoo Health Report +

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

Key + Highlights

+
+
+
+
+ +
+
+ Complete overview of all quality issues for each custom module in one place. +
+

+

+
+
+
+
+
+ +
+
+ Displays a complete overview of all fields. +
+

+ +

+
+
+
+
+
+ +
+
+ Easily generate and download a report of module quality and code health for review +
+

+ +

+
+
+
+
+
+ +
+
+ Automatically calculates and shows lines of code (Python, XML, JS) for all modules, categorized by author. +
+

+ +

+
+
+
+
+ +
+
+
+ Odoo Health Report +

+ Are your modules up to standard? +
Run a quick quality check and find out! +

+ +
+
+ +
+
+
+ + + + +
+
+ +
+
+
+
+ acc_bg +
+ +
+
+
+
+

+ Overview + +

+
+
+

+ The module displays and a general overview of the apps and fields in the header section. +

+
+
+
+ +
+
+ +
+

+ This section shows the author based classeified modules, along with the count of their JS, Python, and XML lines of code. +

+
+
+
+ +
+
+ +
+

+ This section lists all custom modules present in the database. +

+
+
+
+ +
+
+ + +
+

+ When we click on a module, it displays the violations under two sections: Style & Linting Check and Code Formatting Check. +

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

+ + Print PDF +

+
+
+

+ Click the Report button in the header to open the wizard for printing the PDF. +

+
+
+
+ +
+
+ +
+

+ To print the report, select the 'Module Quality' option and choose the modules you want to include in the report. +

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

+ Effortless module quality evaluation

+
+ +
+
+
+
+
+
+ +
+

+ Shows clear line counts of Python, XML, and JS for each module, grouped by author.

+
+
+
+
+
+
+
+ +
+

+ Highlights detailed style and linting and Code Formatting violations.

+
+
+
+
+
+
+
+ +
+

+ Compiles all these details into a comprehensive report. +

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

+ This app provides a comprehensive quality check of Odoo modules by analyzing code line by line. +

+
+
+ +
+ +
+

+ The app helps by evaluating modules line by line, highlighting violations, showing module lines of code by author, and providing a complete overview about all fields. +

+
+
+ +
+ +
+

+ Yes, the app allows you to print the report features and violations, with the option to select specific modules. +

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

+ Latest Release 18.0.1.0.1 +

+ + 2nd July, 2025 + +
+
+
+
+
+ Add +
+
+
+
    +
  • + Initial Commit +
  • + +
+
+
+
+
+
+
+
+
+
+ + + +
+

+ Related Products +

+ +
+ + +
+

+ Our Services

+ +
+ +
+
+ .... +
+
+ +
+ + +
+
+ + + + + + diff --git a/odoo_health_report/static/src/assets/images/icons/arrow-right.svg b/odoo_health_report/static/src/assets/images/icons/arrow-right.svg new file mode 100644 index 000000000..b89731a62 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons/arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons/arrow_down.svg b/odoo_health_report/static/src/assets/images/icons/arrow_down.svg new file mode 100644 index 000000000..06bd8be5b --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons/arrow_down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odoo_health_report/static/src/assets/images/icons/arrow_right.svg b/odoo_health_report/static/src/assets/images/icons/arrow_right.svg new file mode 100644 index 000000000..775fa5124 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons/arrow_right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odoo_health_report/static/src/assets/images/icons/cross.svg b/odoo_health_report/static/src/assets/images/icons/cross.svg new file mode 100644 index 000000000..4723f4ca4 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons/cross.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/odoo_health_report/static/src/assets/images/icons/play-icon.svg b/odoo_health_report/static/src/assets/images/icons/play-icon.svg new file mode 100644 index 000000000..cafb32741 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons/play-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons/tick.svg b/odoo_health_report/static/src/assets/images/icons/tick.svg new file mode 100644 index 000000000..2f8f65615 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons/tick.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/box.png b/odoo_health_report/static/src/assets/images/icons_report/box.png new file mode 100644 index 000000000..7730d2fe3 Binary files /dev/null and b/odoo_health_report/static/src/assets/images/icons_report/box.png differ diff --git a/odoo_health_report/static/src/assets/images/icons_report/cybro.svg b/odoo_health_report/static/src/assets/images/icons_report/cybro.svg new file mode 100644 index 000000000..be104db03 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/cybro.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/globe.svg b/odoo_health_report/static/src/assets/images/icons_report/globe.svg new file mode 100644 index 000000000..d184ba9e3 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/globe.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/graph.png b/odoo_health_report/static/src/assets/images/icons_report/graph.png new file mode 100644 index 000000000..99983b753 Binary files /dev/null and b/odoo_health_report/static/src/assets/images/icons_report/graph.png differ diff --git a/odoo_health_report/static/src/assets/images/icons_report/hour-glass.svg b/odoo_health_report/static/src/assets/images/icons_report/hour-glass.svg new file mode 100644 index 000000000..9ff29cc14 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/hour-glass.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/left.svg b/odoo_health_report/static/src/assets/images/icons_report/left.svg new file mode 100644 index 000000000..74d2974a8 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/left.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/list.svg b/odoo_health_report/static/src/assets/images/icons_report/list.svg new file mode 100644 index 000000000..62d30da5d --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/list.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/note.svg b/odoo_health_report/static/src/assets/images/icons_report/note.svg new file mode 100644 index 000000000..1c40bc61a --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/note.svg @@ -0,0 +1,4 @@ + + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/right.svg b/odoo_health_report/static/src/assets/images/icons_report/right.svg new file mode 100644 index 000000000..4d8099b3f --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/right.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/tick1.svg b/odoo_health_report/static/src/assets/images/icons_report/tick1.svg new file mode 100644 index 000000000..f754a5624 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/tick1.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/odoo_health_report/static/src/assets/images/icons_report/untick.svg b/odoo_health_report/static/src/assets/images/icons_report/untick.svg new file mode 100644 index 000000000..c52138cb4 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/icons_report/untick.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_health_report/static/src/assets/images/illustrations/3d-women.svg b/odoo_health_report/static/src/assets/images/illustrations/3d-women.svg new file mode 100644 index 000000000..d2eb86d25 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/illustrations/3d-women.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_health_report/static/src/assets/images/illustrations/card-bg.svg b/odoo_health_report/static/src/assets/images/illustrations/card-bg.svg new file mode 100644 index 000000000..81fdf6885 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/illustrations/card-bg.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_health_report/static/src/assets/images/illustrations/sidebar-bg.svg b/odoo_health_report/static/src/assets/images/illustrations/sidebar-bg.svg new file mode 100644 index 000000000..aa9548cc9 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/illustrations/sidebar-bg.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_health_report/static/src/assets/images/logo/logo.svg b/odoo_health_report/static/src/assets/images/logo/logo.svg new file mode 100644 index 000000000..49de4f883 --- /dev/null +++ b/odoo_health_report/static/src/assets/images/logo/logo.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_health_report/static/src/css/main.css b/odoo_health_report/static/src/css/main.css new file mode 100644 index 000000000..715dd6f54 --- /dev/null +++ b/odoo_health_report/static/src/css/main.css @@ -0,0 +1,2525 @@ +.health_report h1, h2, h3, h4, h5, h6 { + font-family: "Public Sans", sans-serif !important; +} + +.health_report body { + font-family: "Open Sans", sans-serif !important; +} + +.health_report .w-30 { + width: 30% !important; +} + +.health_report .w-70 { + width: 70% !important; +} + +.health_report .w-65 { + width: 65% !important; +} +@media screen and (max-width: 768px) { + .health_report .w-65 { + width: 100% !important; + } +} + +.health_report .w-35 { + width: 35% !important; +} +@media screen and (max-width: 768px) { + .health_report .w-35 { + width: 100% !important; + } +} + +.health_report { + max-height: 100vh; + overflow-y:auto; +} + +.hr-sidenav_menus-bg { + position: relative; + background-image: url("/odoo_health_report/static/src/assets/images/illustrations/sidebar-bg.svg"); + height: 470px; + background-repeat: no-repeat; +} + +.hr-sidenav-menu { + width: 110px; +} +@media (max-width: 768px) { + .hr-sidenav-menu { + display: none; + } +} + +.hr-sidenav-menu-sticky { + position: fixed; + width: 130px; + top: 50%; + left: 0; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 99; +} +@media (max-width: 768px) { + .hr-sidenav-menu-sticky { + display: none; + } +} + +.hr-sidebar-menu-position { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.hr-sidenav_menus { + width: 100%; + padding: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + gap: 24px; +} +.hr-sidenav_menus .hr-sidenav_item { + list-style: none; +} + +/* Active menu item */ +.hr-sidenav_item.active { + background: rgba(255, 255, 255, 0.3); + border-radius: 12px; +} + +.hr-sidenav_item:hover { + background: rgba(255, 255, 255, 0.5); /* Slightly different for hover */ + border-radius: 12px; + cursor: pointer; +} + +.hr-sidenav_item.active svg { + fill: #ffffff; + stroke: none; + padding: 4px; +} + +.hr-sidenav_menus .hr-sidenav_item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} + +@media (min-width: 768px) { + .hr-mobile-menu_sticky { + display: none; + } +} +.hr-mobile-menu_sticky { + position: fixed; + width: 100%; + bottom: 0; + z-index: 99; + left: 0; +} + +.hr-mobile-menu_bg { + background-color: #0065ff; + padding: 22px 0; + border-radius: 24px 24px 0 0; +} + +.hr-mobile_menus { + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 20px; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin-bottom: 0; + padding: 0 30px; +} +.hr-mobile_menus .hr-mobile-menu_item { + list-style: none; +} + +.health_report .menu-item.current-menu-item.active a { + color: #0065ff !important; +} + +.hr-header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + width: 100%; + padding: 20px 0; +} +.hr-header__logo { + width: auto; +} + +.hr-custom-select { + background-color: #fff; + border: none; + -webkit-box-shadow: 0px 2px 7.4px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px rgba(43, 127, 255, 0.2); + border-radius: 16px; + padding: 17px 24px 17px 16px; + color: #bebebe; + font-size: 16px; + width: 300px; +} +@media (max-width: 768px) { + .hr-custom-select { + width: 100%; + } +} + +.health_report html, +.health_report body { + background-color: #eff6fc !important; +} + +.hr-main-section { + width: 100VW; + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +.hr-dashboard-cards { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 16px; + background-color: #eef6ff; + margin-bottom: 24px; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +@media (max-width: 768px) { + .hr-dashboard-cards { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } +} +.hr-dashboard-cards .hr-dashboard-card__status, +.hr-dashboard-cards .hr-dashboard-card__page-size, +.hr-dashboard-cards .hr-dashboard-card__load-time { + background: -webkit-gradient(linear, left top, left bottom, from(#f8faff), to(#e9f2ff)); + background: linear-gradient(to bottom, #f8faff, #e9f2ff); + border-radius: 12px; + padding: 16px; + -webkit-box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: start; + gap: 12px; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + border-radius: 12px; + background: -webkit-gradient(linear, left top, left bottom, from(#d8e8ff), to(#f3e8ff)); + background: linear-gradient(180deg, #d8e8ff 0%, #f3e8ff 100%); + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + border: none; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} +.hr-dashboard-cards .hr-dashboard-card__status-content, +.hr-dashboard-cards .hr-dashboard-card__page-size-content, +.hr-dashboard-cards .hr-dashboard-card__load-time-content { + width: 100%; +} +.hr-dashboard-cards .hr-dashboard-card__status-content .status-up, +.hr-dashboard-cards .hr-dashboard-card__page-size-content .status-up, +.hr-dashboard-cards .hr-dashboard-card__load-time-content .status-up { + background-color: #2b7fff; + color: #fff; + border-radius: 12px; + padding: 2px 6px; + font-weight: 400; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 6px; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; + text-transform: uppercase; +} +.hr-dashboard-cards .hr-dashboard-card__status-content h4, +.hr-dashboard-cards .hr-dashboard-card__page-size-content h4, +.hr-dashboard-cards .hr-dashboard-card__load-time-content h4 { + font-size: 16px; + color: #202224; + opacity: 0.7; + font-weight: 700; +} +.hr-dashboard-cards .hr-dashboard-card__status-content p, +.hr-dashboard-cards .hr-dashboard-card__page-size-content p, +.hr-dashboard-cards .hr-dashboard-card__load-time-content p { + font-size: 24px; + font-style: normal; + font-weight: 700; +} +.hr-dashboard-cards .hr-dashboard-card__status .icon, +.hr-dashboard-cards .hr-dashboard-card__page-size .icon, +.hr-dashboard-cards .hr-dashboard-card__load-time .icon { + background-color: #007bff; + color: #fff; + padding: 10px; + border-radius: 20px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + font-size: 18px; +} +.hr-dashboard-cards .hr-dashboard-card__overview { + -webkit-box-flex: 2; + -ms-flex: 2; + flex: 2; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: start; + padding: 20px; + background-image: url("/odoo_health_report/static/src/assets/images/illustrations/card-bg.svg"); + background-repeat: no-repeat; + background-size: cover; + border-radius: 12px; + padding: 16px; + position: relative; +} +.hr-dashboard-cards .hr-dashboard-card__overview-content h3 { + font-size: 18px; + margin-bottom: 10px; + color: #fff; +} +.hr-dashboard-cards .hr-dashboard-card__overview-content img { + width: 165px; + position: absolute; + right: 0; + bottom: 0; +} +.hr-dashboard-cards .hr-dashboard-card__overview #gaugeChart { + width: 100px; +} + +.hr-seo-analysis-section { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 32px; + margin-bottom: 24px; +} +@media (max-width: 768px) { + .hr-seo-analysis-section { + padding: 20px; + } +} +.hr-seo-analysis-section .hr-seo-analysis-title { + padding-bottom: 18px; + color: #000; + font-size: 18px; + font-weight: 700; +} + +.hr-secondary-card { + border-radius: 12px; + border: 1px solid #dedede; + background: #f8f8f8; + padding: 24px; + height: 100%; +} +.hr-secondary-card h5 { + color: #000; + font-size: 18px; + font-weight: 700; +} +.hr-secondary-card span { + color: #000; + font-size: 14px; + font-weight: 400; +} +.hr-secondary-card p { + color: #f00; + font-size: 14px; + font-style: normal; + font-weight: 400; +} +.hr-secondary-card .hr-secondary-card_note { + color: #000; + font-size: 14px; + font-weight: 400; +} +.hr-secondary-card__number { + background-color: #ddf66b; + padding: 4px 12px; + border-radius: 15px; + font-size: 12px; + font-weight: 600 !important; +} +.hr-secondary-card__content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 5px; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: center; + padding-top: 12px; +} + +.hr-secondary-card_search { + padding: 12px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} +.hr-secondary-card_search h5 { + text-align: center; +} +.hr-secondary-card_search span { + text-align: center; +} +.hr-secondary-card_search img { + width: 40px; +} + +.hr-empty_state { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} +.hr-empty_state__number { + background-color: #ddf66b; + padding: 4px 12px; + border-radius: 15px; + font-size: 12px; + font-weight: 600 !important; +} +.hr-empty_state__content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 5px; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: center; + padding-top: 12px; +} + +.hr-security-analysis-section { + margin-bottom: 24px; +} + +.hr-security_policy-card { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 20px; + height: 100%; +} +.hr-security_policy-card .hr-security_policy-content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 15px; +} +@media (max-width: 768px) { + .hr-security_policy-card .hr-security_policy-content { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + gap: 16px; + } +} + +.hr-security-policy-lists { + padding-left: 0; +} +.hr-security-policy-lists-item { + list-style: none; + padding-bottom: 10px; +} +.hr-security-policy-lists-item span { + font-size: 14px; + font-weight: 400; +} + +.hr-security-policy-title { + font-size: 18px; + font-weight: 700; + padding-bottom: 18px; +} + +.hr-links-section { + margin-bottom: 24px; +} + +.hr-links-card { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 20px; + height: 100%; +} +.hr-links-card .hr-links-card_title { + font-size: 18px; + font-weight: 700; + padding-bottom: 18px; +} +.hr-links-card .hr-links-card_actions { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 10px; + margin-bottom: 24px; +} +.hr-links-card .hr-links-card_actions .hr-select { + border-radius: 6px; + border: 1px solid #dedede; + background: #fff; + padding: 4px 10px; +} +.hr-links-card .hr-links-card_actions .hr-links_count { + color: #0047b3; + border-radius: 6px; + background: #e6f0ff; + padding: 2px 12px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-wrap: nowrap; +} +.hr-links-card .hr-links_note { + color: #d8a300; + font-size: 14px; + font-weight: 400; +} +.hr-links-card .hr-links_listing { + padding-left: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + gap: 15px; +} +.hr-links-card .hr-links_listing li { + list-style: none; +} +.hr-links-card .hr-links_listing li .hr-link { + text-decoration: none; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 10px; +} +.hr-links-card .hr-links_listing li .hr-link .dot { + background-color: #0065ff; + width: 14px; + height: 14px; + border-radius: 15px; + padding: 7px; +} +.hr-links-card .hr-links_listing li .hr-link p { + font-size: 14px; + font-weight: 400; + color: #000; + margin: 0; + overflow: hidden; + text-wrap-mode: nowrap; + text-overflow: ellipsis; + max-width: 500px; +} + +.hr-socialmedia-section .hr-socialmedia_card { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 20px; +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia-title { + font-size: 18px; + font-weight: 700; + padding-bottom: 18px; +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links { + padding-left: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + gap: 8px; +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li { + list-style: none; +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li .hr-socialmedia_link { + list-style: none; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 18px; + padding: 6px 12px; + color: #000; + border-radius: 12px; + text-decoration: none; +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li .hr-instagram-link { + background-color: rgba(201, 65, 249, 0.12); +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li .hr-linkedin-link { + background-color: rgba(10, 102, 194, 0.29); +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li .hr-whatsapp-link { + background-color: rgba(96, 214, 105, 0.23); +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li .hr-facebook-link { + background-color: rgba(24, 119, 242, 0.17); +} +.hr-socialmedia-section .hr-socialmedia_card .hr-socialmedia_links li .hr-pintrest-link { + background-color: rgba(203, 31, 39, 0.15); +} + +.health_report #gaugeText { + position: absolute; + width: 100%; + bottom: 0; + font-size: 16px; + color: #fff; + position: absolute; + top: 50%; +} + +.health_report .parent { + display: -ms-grid; + display: grid; + -ms-grid-columns: 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr; + grid-template-columns: repeat(9, 1fr); + -ms-grid-rows: 1fr 20px 1fr 20px 1fr; + grid-template-rows: repeat(3, 1fr); + gap: 20px; + height: 460px; +} + +.health_report .parent > *:nth-child(1) { + -ms-grid-row: 1; + -ms-grid-column: 1; +} + +.health_report .parent > *:nth-child(2) { + -ms-grid-row: 1; + -ms-grid-column: 3; +} + +.health_report .parent > *:nth-child(3) { + -ms-grid-row: 1; + -ms-grid-column: 5; +} + +.health_report .parent > *:nth-child(4) { + -ms-grid-row: 1; + -ms-grid-column: 7; +} + +.health_report .parent > *:nth-child(5) { + -ms-grid-row: 1; + -ms-grid-column: 9; +} + +.health_report .parent > *:nth-child(6) { + -ms-grid-row: 1; + -ms-grid-column: 11; +} + +.health_report .parent > *:nth-child(7) { + -ms-grid-row: 1; + -ms-grid-column: 13; +} + +.health_report .parent > *:nth-child(8) { + -ms-grid-row: 1; + -ms-grid-column: 15; +} + +.health_report .parent > *:nth-child(9) { + -ms-grid-row: 1; + -ms-grid-column: 17; +} + +.health_report .parent > *:nth-child(10) { + -ms-grid-row: 3; + -ms-grid-column: 1; +} + +.health_report .parent > *:nth-child(11) { + -ms-grid-row: 3; + -ms-grid-column: 3; +} + +.health_report .parent > *:nth-child(12) { + -ms-grid-row: 3; + -ms-grid-column: 5; +} + +.health_report .parent > *:nth-child(13) { + -ms-grid-row: 3; + -ms-grid-column: 7; +} + +.health_report .parent > *:nth-child(14) { + -ms-grid-row: 3; + -ms-grid-column: 9; +} + +.health_report .parent > *:nth-child(15) { + -ms-grid-row: 3; + -ms-grid-column: 11; +} + +.health_report .parent > *:nth-child(16) { + -ms-grid-row: 3; + -ms-grid-column: 13; +} + +.health_report .parent > *:nth-child(17) { + -ms-grid-row: 3; + -ms-grid-column: 15; +} + +.health_report .parent > *:nth-child(18) { + -ms-grid-row: 3; + -ms-grid-column: 17; +} + +.health_report .parent > *:nth-child(19) { + -ms-grid-row: 5; + -ms-grid-column: 1; +} + +.health_report .parent > *:nth-child(20) { + -ms-grid-row: 5; + -ms-grid-column: 3; +} + +.health_report .parent > *:nth-child(21) { + -ms-grid-row: 5; + -ms-grid-column: 5; +} + +.health_report .parent > *:nth-child(22) { + -ms-grid-row: 5; + -ms-grid-column: 7; +} + +.health_report .parent > *:nth-child(23) { + -ms-grid-row: 5; + -ms-grid-column: 9; +} + +.health_report .parent > *:nth-child(24) { + -ms-grid-row: 5; + -ms-grid-column: 11; +} + +.health_report .parent > *:nth-child(25) { + -ms-grid-row: 5; + -ms-grid-column: 13; +} + +.health_report .parent > *:nth-child(26) { + -ms-grid-row: 5; + -ms-grid-column: 15; +} + +.health_report .parent > *:nth-child(27) { + -ms-grid-row: 5; + -ms-grid-column: 17; +} +@media (max-width: 991px) { + .health_report .parent { + -ms-grid-columns: (1fr)[1]; + grid-template-columns: repeat(1, 1fr); + -ms-grid-rows: (1fr)[1]; + grid-template-rows: repeat(1, 1fr); + height: auto; + } + .health_report .parent > *:nth-child(1) { + -ms-grid-row: 1; + -ms-grid-column: 1; + } +} +@media (max-width: 1199px) { + .health_report .parent { + height: auto; + } +} + +.div1 { + -ms-grid-column-span: 3; + grid-column: span 3/span 3; +} +@media (max-width: 991px) { + .div1 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + } +} + +.div2 { + -ms-grid-column-span: 3; + grid-column: span 3/span 3; + -ms-grid-column: 4; + grid-column-start: 4; +} +@media (max-width: 991px) { + .div2 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + -ms-grid-column: 1; + grid-column-start: 1; + } +} + +.div3 { + -ms-grid-column: 7; + grid-column-start: 7; +} +@media (max-width: 991px) { + .div3 { + -ms-grid-column: 1; + grid-column-start: 1; + } +} + +.div4 { + -ms-grid-column-span: 2; + grid-column: span 2/span 2; + -ms-grid-column: 8; + grid-column-start: 8; +} +@media (max-width: 991px) { + .div4 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + -ms-grid-column: 1; + grid-column-start: 1; + } +} + +.div6 { + -ms-grid-column-span: 3; + grid-column: span 3/span 3; + -ms-grid-row-span: 2; + grid-row: span 2/span 2; + -ms-grid-row: 2; + grid-row-start: 2; +} +@media (max-width: 991px) { + .div6 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + -ms-grid-row-span: 1; + grid-row: span 1/span 1; + -ms-grid-row: auto; + grid-row-start: auto; + } +} + +.div7 { + -ms-grid-column-span: 3; + grid-column: span 3/span 3; + -ms-grid-row-span: 2; + grid-row: span 2/span 2; + -ms-grid-column: 4; + grid-column-start: 4; + -ms-grid-row: 2; + grid-row-start: 2; +} +@media (max-width: 991px) { + .div7 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + grid-row: auto; + -ms-grid-row: auto; + grid-row-start: auto; + -ms-grid-column: 1; + grid-column-start: 1; + } +} + +.div8 { + -ms-grid-column-span: 3; + grid-column: span 3/span 3; + -ms-grid-column: 7; + grid-column-start: 7; + -ms-grid-row: 2; + grid-row-start: 2; +} +@media (max-width: 991px) { + .div8 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + -ms-grid-column: 1; + grid-column-start: 1; + -ms-grid-row: auto; + grid-row-start: auto; + } +} + +.div9 { + -ms-grid-column-span: 3; + grid-column: span 3/span 3; + -ms-grid-column: 7; + grid-column-start: 7; + -ms-grid-row: 3; + grid-row-start: 3; +} +@media (max-width: 991px) { + .div9 { + -ms-grid-column-span: 1; + grid-column: span 1/span 1; + -ms-grid-column: 1; + grid-column-start: 1; + -ms-grid-row: 1; + grid-row-start: 1; + } +} + +.hr-module-table-container { + padding-top: 22px; + padding-left: 32px; + padding-right: 32px; + background-color: #f8f8f8; + margin-top: 10px; + border-radius: 12px; + border: 1px solid #e5e5e5; +} +.hr-module-table-container-title { + color: #000; + font-size: 18px; + font-weight: 700; +} + +.hr-accordion-item { + margin: 0 0 20px 0; + overflow: hidden; + background-color: #fff; + border-radius: 10px; +} + +.hr-accordion-item div.mt-4 { + max-height: 500px; + overflow-y: scroll; +} + +.hr-accordion-item div.mt-4 h3 { + position: sticky; + top: 0; +} + +.hr-accordion-item .hr-accordion-header { + width: 100%; + border: 1px solid #e5e5e5; + border-radius: 10px; + background-color: #fff; + padding: 15px 35px; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 16px; + font-weight: bold; + cursor: pointer; + outline: none; + text-align: left; + -webkit-transition: background 0.3s; + transition: background 0.3s; +} +.hr-accordion-item .hr-accordion-header:hover { + background-color: #f8f8f8; +} +.hr-accordion-item .icon { + font-size: 20px; +} +.hr-accordion-item .icon-box { + margin-right: 10px; +} +.hr-accordion-item h4 { + margin-bottom: unset; +} +.hr-accordion-item .hr-accordion-content { + display: none; + background-color: #fff; +} +.hr-accordion-item .show { + display: block; +} + +.hr-grid-row-2 { + display: -ms-grid; + display: grid; + -ms-grid-columns: 2fr 20px 1fr; + grid-template-columns: 2fr 1fr; + gap: 20px; +} +@media screen and (max-width: 768px) { + .hr-grid-row-2 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + margin-bottom: 20px; + } +} + +.hrl-btn { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 10px; +} +.hrl-btn span { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 7px; +} +.hrl-btn span ion-icon { + font-size: 22px; +} + +a.hrl-primary-button, +button.hrl-primary-button { + position: relative; + -webkit-box-sizing: border-box; + box-sizing: border-box; + border: 1px solid #0065ff; + outline: 0; + padding: 1rem 3rem; + font-size: 1em; + font-weight: 600; + color: #fff; + cursor: pointer; + border-radius: 50px; + background-color: #0065ff; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; +} +a.hrl-primary-button::before, +button.hrl-primary-button::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 50px; + border: 2px solid #0065ff; + -webkit-transform: translate(5px, 5px); + transform: translate(5px, 5px); + -webkit-transition: 0.25s ease; + transition: 0.25s ease; + z-index: -1; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +a.hrl-primary-button:hover, +button.hrl-primary-button:hover { + -webkit-transform: translate(3px, 3px); + transform: translate(3px, 3px); + border: 1px solid #0065ff; +} +a.hrl-primary-button:hover::before, +button.hrl-primary-button:hover::before { + -webkit-transform: translate(0px, 0px); + transform: translate(0px, 0px); + border: 1px solid #0065ff; +} +a.hrl-primary-button:active, +button.hrl-primary-button:active { + -webkit-transform: scale(0.95); + transform: scale(0.95); +} + +a.hrl-secondary-button, +button.hrl-secondary-button { + position: relative; + -webkit-box-sizing: border-box; + box-sizing: border-box; + border: 1px solid #1c1c1c; + outline: 0; + padding: 1rem 3rem; + font-size: 1em; + background-color: #fff; + font-weight: 600; + color: #1c1c1c; + cursor: pointer; + border-radius: 50px; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +a.hrl-secondary-button::before, +button.hrl-secondary-button::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 50px; + border: 1px solid #1c1c1c; + color: #1c1c1c; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-transform: translate(5px, 5px); + transform: translate(5px, 5px); + -webkit-transition: 0.2s ease; + transition: 0.2s ease; + z-index: -1; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +a.hrl-secondary-button:hover, +button.hrl-secondary-button:hover { + -webkit-transform: translate(3px, 3px); + transform: translate(3px, 3px); + background-color: #fff; +} +a.hrl-secondary-button:hover::before, +button.hrl-secondary-button:hover::before { + -webkit-transform: translate(0px, 0px); + transform: translate(0px, 0px); + border: none; +} +a.hrl-secondary-button:active, +button.hrl-secondary-button:active { + -webkit-transform: scale(0.95); + transform: scale(0.95); +} + +.hrl-heo__actions { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin: 0 auto; + gap: 20px; +} +@media (max-width: 767.98px) { + .hrl-heo__actions { + width: 100%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.hrl-owl-carousel-navigation button.hrl-owl-carousel-prev::before { + -webkit-transform: translate(-3px, 3px) !important; + transform: translate(-3px, 3px) !important; +} +.hrl-owl-carousel-navigation button.hrl-owl-carousel-prev:hover { + -webkit-transform: translate(-3px, 3px) !important; + transform: translate(-3px, 3px) !important; +} +.hrl-owl-carousel-navigation button.hrl-owl-carousel-prev:hover::before { + -webkit-transform: translate(0px, 0px) !important; + transform: translate(0px, 0px) !important; + border: none; +} +.hrl-owl-carousel-navigation button.hrl-nav-button { + position: relative; + -webkit-box-sizing: border-box; + box-sizing: border-box; + border: 0.5px solid #0065ff; + outline: 0; + padding: 7px; + margin: auto; + width: 48px !important; + height: 44px !important; + font-size: 1.5rem; + font-weight: 600; + background-color: #0065ff; + color: #fff; + cursor: pointer; + border-radius: 50px; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.hrl-owl-carousel-navigation button.hrl-nav-button::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 50px; + border: 0.5px solid #0065ff; + color: #1c1c1c; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-transform: translate(3px, 3px); + transform: translate(3px, 3px); + -webkit-transition: 0.2s ease; + transition: 0.2s ease; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.hrl-owl-carousel-navigation button.hrl-nav-button:hover { + -webkit-transform: translate(3px, 3px); + transform: translate(3px, 3px); +} +.hrl-owl-carousel-navigation button.hrl-nav-button:hover::before { + -webkit-transform: translate(0px, 0px); + transform: translate(0px, 0px); + border: none; +} +.hrl-owl-carousel-navigation button.hrl-nav-button:active { + -webkit-transform: scale(0.95); + transform: scale(0.95); +} + +.hrl-owl-carousel-navigation button:disabled { + background-color: transparent !important; + border: #a1a1a1 0.5px solid !important; + cursor: not-allowed; + color: #a1a1a1 !important; +} +.hrl-owl-carousel-navigation button:disabled::before { + border: 0.5px solid #a1a1a1 !important; + color: #1c1c1c; +} + +.hrl-link { + position: relative; +} + +.hrl-link--primary { + color: hsl(8, 77%, 56%); +} + +.hrl-link--primary:focus, +.hrl-link--primary:focus-visible, +.hrl-link--primary:hover { + color: hsl(8, 77%, 45%); +} + +.hrl-link--title-font { + font-family: "Poppins", "Helvetica Neue", "Helvetica", "Arial", sans-serif; +} + +.hrl-link--bold { + font-weight: 600; +} + +.hrl-link--arrow:after { + content: ""; + position: absolute; + top: 0px; + right: -25px; + width: 20px; + height: 20px; + background: url("data:image/svg+xml,%3csvg width='46' height='20' viewBox='0 0 46 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M35.7975 2L44 10L35.7975 18M42.8608 10H1.5' stroke='%23E54F38' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e") no-repeat; + background-position: center; + background-size: contain; + -webkit-transition: all 0.4s ease-in-out; + transition: all 0.4s ease-in-out; +} + +.hrl-link--arrow:hover:after { + right: -30px; + -webkit-transition: all 0.4s ease-in-out; + transition: all 0.4s ease-in-out; +} + +.hrl-docs-module-label { + max-width: 100%; + font-size: 16px; + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + height: 28px; + color: #fff !important; + background-color: #0065ff; + border-radius: 16px; + text-decoration: none; + vertical-align: middle; + margin-bottom: 1rem; +} + +.hrl-docs-module-label span { + overflow: hidden; + text-overflow: ellipsis; + padding-left: 8px; + padding-right: 8px; + white-space: nowrap; +} +.hrl-docs-module-label span a { + color: #fff !important; + padding: 25px 15px; +} + +.hrl-docs-module-label span { + font-weight: 500; +} +.hr-modal-title { + font-family: "Public Sans"; + font-size: 18px; + font-style: normal; + font-weight: 700; +} + +.hr-modal .modal-header { + border-bottom: none; + padding: 24px !important; + padding-bottom: 0 !important; + border: none !important; +} + +.hr-modal-body { + padding: 24px !important; +} +.hr-modal-body .form-check { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: self-end; + -ms-flex-align: self-end; + align-items: self-end; + gap: 8px; +} +.hr-modal-body .hr-form_input { + border: 1px solid #2B7FFF; + border-radius: 3px; + width: 24px; + height: 24px; +} +.hr-modal-body .hr-form_input:focus { + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.hr-modal-body .hr-form_label { + font-family: "Open Sans"; + font-size: 14px; + font-style: normal; + font-weight: 400; +} + +.hr-multi_select { + width: 100%; + z-index: 999; +} + +.select2-container { + margin-bottom: 20px !important; +} + +.select2-results__option { + padding: 8px 12px !important; +} + +/* Prevent clipping */ +.select2-container { + z-index: 9999 !important; +} + +/* Match modal input styles if needed */ +.select2-selection { + border-radius: 6px !important; + min-height: 42px; + padding: 6px 10px; + border: 1px solid #ccc; +} + +.select2-container--default.select2-container--focus .select2-selection--multiple { + border: 1px solid #2B7FFF !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} + +.select2-search__field { + width: auto !important; +} + +.select2-search { + width: auto !important; +} + +/* Remove red border from error state */ +.select2-container--default .select2-selection--multiple { + border-radius: 12px !important; + padding: 6px 10px; + background-color: #fff; + min-height: 42px; + -webkit-transition: border-color 0.3s ease; + transition: border-color 0.3s ease; + border: 1px solid #D9D9D9 !important; +} + +/* On focus */ +.select2-container--default.select2-container--focus .select2-selection--multiple { + border-color: #4a90e2 !important; + -webkit-box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2); + box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2); +} + +/* Selected item style */ +.select2-container--default .select2-selection--multiple .select2-selection__choice { + color: #000; + border: none !important; + border-radius: 12px !important; + background-color: #EAF3FE !important; + padding: 6px 10px !important; + margin-top: 0 !important; + margin: 0px 4px; + font-size: 14px; + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + -webkit-box-orient: horizontal !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + gap: 8px !important; + -webkit-box-align: center !important; + -ms-flex-align: center !important; + align-items: center !important; +} + +/* Hover delete button */ +.select2-container--default .select2-selection--multiple .select2-selection__choice__remove { + color: white; + margin-right: 5px; + background-color: #2B7FFF !important; + width: 24px !important; + height: 24px !important; + text-align: center !important; + color: #fff !important; + border-radius: 4px !important; +} + +/* Dropdown list styling */ +.select2-container--default .select2-results > .select2-results__options { + max-height: 220px; + overflow-y: auto; + border-radius: 0px 0px 12px 12px; + background: #FFF; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 16px !important; +} + +.select2-results__options .select2-results__option:first-child { + border-bottom: 1px solid #DEDEDE !important; + margin-bottom: 12px; + padding-bottom: 12px !important; + padding-top: 12px !important; +} + +/* Optional: hover style */ +.select2-results__option--highlighted[aria-selected] { + background-color: #f0f8ff; + color: #333; +} + +.select2-container--open .select2-dropdown--below { + border: none !important; +} + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: #EAF3FE !important; + color: #000 !important; +} + +.select2-container--default .select2-results__option[aria-selected=true] { + background-color: transparent !important; +} + +.hr-primary_btn { + padding: 10px; + border-radius: 12px; + background-color: #2B7FFF; + color: #fff; + border: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +.hr-secondary_btn { + border: 1px solid #2B7FFF; + color: #000; + padding: 10px; + border-radius: 12px; + background-color: transparent; +} + +.hr-modal-footer { + border-top: 1px solid #DBDBDB; + padding-top: 14px; +} + +.hrl-owl-carousel-container { + position: relative; + padding-top: 5rem; +} +.hrl-owl-carousel-container h4 { + text-align: center; + font-size: 40px; + width: 75%; + margin: auto; + margin-bottom: 50px; +} + +.owl-stage { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 1rem; + margin: 0 15px; +} + +.hrl-owl-carousel-count { + margin: 10px 0; + font-size: 18px; + font-weight: 500; +} + +.hrl-owl-carousel-progress { + width: 100%; + background-color: #ddd; + height: 5px; + position: relative; + border-radius: 3px; + margin-top: 10px; +} + +.hrl-owl-carousel-progress-bar { + height: 100%; + background-color: #0065ff; + width: 0%; + -webkit-transition: width 0.3s ease; + transition: width 0.3s ease; + border-radius: 3px; +} + +.hrl-owl-carousel-header { + font-size: 24px; + margin-bottom: 20px; +} + +.hrl-owl-carousel-navigation { + position: absolute; + bottom: 15px; + right: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 10px; +} + +.hrl-owl-carousel-navigation button:disabled { + background-color: #ddd; + cursor: not-allowed; +} + +.hr-card { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 32px; + margin-bottom: 24px; + height: 100%; +} +.hr-card-title { + padding-bottom: 18px; + color: #000; + font-size: 18px; + font-weight: 700; +} +.hr-card .hr-accordion.scrollbar { + margin-top: 15px; + max-height: 700px; + overflow-y: scroll; +} +.hr-graph { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 20px; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} +@media screen and (max-width: 768px) { + .hr-graph { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.hr-graph-card { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 34px; + width: 48%; + height: 350px; +} +@media screen and (max-width: 768px) { + .hr-graph-card { + width: 100%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } +} +.hr-graph-card__title { + margin-bottom: 28px; + padding-bottom: 20px; + color: #000; + font-size: 16px; + font-weight: 500; +} +.hr-graph-card canvas { + margin-top: 30px; +} + +.hr-inner-card { + border-radius: 12px; + background: #fff; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + padding: 32px; + margin-bottom: 24px; + height: 250px; +} +@media screen and (max-width: 768px) { + .hr-inner-card { + height: unset; + } +} + +.hr-stack-card { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + gap: 10px; +} +@media screen and (max-width: 768px) { + .hr-stack-card { + padding: 0 !important; + } +} +.hr-stack-card__content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + gap: 25px; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 13px 18px; + border-radius: 12px; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); +} +@media screen and (max-width: 768px) { + .hr-stack-card__content { + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + gap: unset; + } +} +.hr-stack-card__content-icon { + width: 40px; + height: 40px; + background-color: #11c30a; + border-radius: 50%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.hr-stack-card__content-title { + font-size: 16px; + font-weight: 600; + margin: 0; +} +@media screen and (max-width: 768px) { + .hr-stack-card__content-title { + font-size: 14px; + } +} +.hr-stack-card__content-value { + font-size: 16px; + font-weight: 700; +} +@media screen and (max-width: 768px) { + .hr-stack-card__content-value { + font-size: 14px; + } +} +.hr-stack-card__content-status { + font-size: 16px; + font-weight: 700; + color: #11c30a; +} +@media screen and (max-width: 768px) { + .hr-stack-card__content-status { + font-size: 14px; + } +} + +.hr-img-card { + background-image: url("/odoo_health_report/static/src/assets/images/edition-bg.png"); + background-size: cover; + background-position: center; + border-radius: 12px; + -webkit-box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + box-shadow: 0px 2px 7.4px 0px rgba(43, 127, 255, 0.2); + height: 100%; + padding: 32px; +} +@media screen and (max-width: 768px) { + .hr-img-card { + margin-top: 32px3; + } +} +.hr-img-card__title { + padding-bottom: 18px; + color: #fff; + font-size: 18px; + font-weight: 700; +} +.hr-img-card p { + margin: 0; +} +.hr-img-card__subtitle { + color: #fff; + font-size: 18px; + font-weight: 500; +} +.hr-img-card__subtitle2 { + color: #fff; + font-size: 16px; + font-weight: 400; + margin-top: 10px; +} +.hr-img-card__img { + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.hr-grid-row-5-4 { + display: -ms-grid; + display: grid; + gap: 20px; + -ms-grid-columns: 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr; + grid-template-columns: repeat(10, 1fr); + -ms-grid-rows: auto 20px auto; + grid-template-rows: auto auto; + grid-auto-flow: row; + grid-template-areas: "one one two two three three four four five five" "six six seven seven eight eight eight nine nine nine"; +} +.hr-grid-row-5-4 .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 3; + grid-area: one; +} +.hr-grid-row-5-4 .two { + -ms-grid-row: 1; + -ms-grid-column: 5; + -ms-grid-column-span: 3; + grid-area: two; +} +.hr-grid-row-5-4 .three { + -ms-grid-row: 1; + -ms-grid-column: 9; + -ms-grid-column-span: 3; + grid-area: three; +} +.hr-grid-row-5-4 .four { + -ms-grid-row: 1; + -ms-grid-column: 13; + -ms-grid-column-span: 3; + grid-area: four; +} +.hr-grid-row-5-4 .five { + -ms-grid-row: 1; + -ms-grid-column: 17; + -ms-grid-column-span: 3; + grid-area: five; +} +.hr-grid-row-5-4 .six { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 3; + grid-area: six; +} +.hr-grid-row-5-4 .seven { + -ms-grid-row: 3; + -ms-grid-column: 5; + -ms-grid-column-span: 3; + grid-area: seven; +} +.hr-grid-row-5-4 .eight { + -ms-grid-row: 3; + -ms-grid-column: 9; + -ms-grid-column-span: 5; + grid-area: eight; +} +.hr-grid-row-5-4 .nine { + -ms-grid-row: 3; + -ms-grid-column: 15; + -ms-grid-column-span: 5; + grid-area: nine; +} +@media screen and (max-width: 768px) { + .hr-grid-row-5-4 { + -ms-grid-columns: 1fr 10px 1fr; + grid-template-columns: repeat(2, 1fr); + -ms-grid-rows: auto 10px auto 10px auto 10px auto 10px auto; + grid-template-rows: repeat(5, auto); + gap: 10px; + grid-template-areas: "one two" "three four" "five six" "seven eight" "nine nine"; + } + .hr-grid-row-5-4 .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .three { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .four { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .five { + -ms-grid-row: 5; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .six { + -ms-grid-row: 5; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .seven { + -ms-grid-row: 7; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .eight { + -ms-grid-row: 7; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-5-4 .nine { + -ms-grid-row: 9; + -ms-grid-column: 1; + -ms-grid-column-span: 3; + } +} + +.hr-grid-row-4-4 { + display: -ms-grid; + display: grid; + gap: 20px; + -ms-grid-columns: 1fr 20px 1fr 20px 1fr 20px 1fr; + grid-template-columns: repeat(4, 1fr); + -ms-grid-rows: auto 20px auto; + grid-template-rows: auto auto; + grid-auto-flow: row; + grid-template-areas: "one two three four" "five six seven eight"; +} +.hr-grid-row-4-4 .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + grid-area: one; +} +.hr-grid-row-4-4 .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + grid-area: two; +} +.hr-grid-row-4-4 .three { + -ms-grid-row: 1; + -ms-grid-column: 5; + -ms-grid-column-span: 1; + grid-area: three; +} +.hr-grid-row-4-4 .four { + -ms-grid-row: 1; + -ms-grid-column: 7; + -ms-grid-column-span: 1; + grid-area: four; +} +.hr-grid-row-4-4 .five { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + grid-area: five; +} +.hr-grid-row-4-4 .six { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + grid-area: six; +} +.hr-grid-row-4-4 .seven { + -ms-grid-row: 3; + -ms-grid-column: 5; + -ms-grid-column-span: 1; + grid-area: seven; +} +.hr-grid-row-4-4 .eight { + -ms-grid-row: 3; + -ms-grid-column: 7; + -ms-grid-column-span: 1; + grid-area: eight; +} +@media screen and (max-width: 768px) { + .hr-grid-row-4-4 { + -ms-grid-columns: 1fr 20px 1fr; + grid-template-columns: repeat(2, 1fr); + -ms-grid-rows: auto 20px auto 20px auto 20px auto; + grid-template-rows: repeat(4, auto); + gap: 20px; + grid-template-areas: "one two" "three four" "five six" "seven eight"; + } + .hr-grid-row-4-4 > .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .three { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .four { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .five { + -ms-grid-row: 5; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .six { + -ms-grid-row: 5; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .seven { + -ms-grid-row: 7; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .eight { + -ms-grid-row: 7; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .three { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .four { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .five { + -ms-grid-row: 5; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .six { + -ms-grid-row: 5; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .seven { + -ms-grid-row: 7; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .eight { + -ms-grid-row: 7; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } +} + +.hr-grid-row-4 { + display: -ms-grid; + display: grid; + -ms-grid-columns: auto 20px auto 20px auto 20px auto; + grid-template-columns: repeat(4, auto); + gap: 20px; + grid-auto-flow: row; + grid-template-areas: "one two three four"; +} +@media screen and (max-width: 768px) { + .hr-grid-row-4 { + -ms-grid-columns: (auto)[2]; + grid-template-columns: repeat(2, auto); + grid-template-areas: "one two " "three four"; + } + .hr-grid-row-4 > .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .two { + -ms-grid-row: 1; + -ms-grid-column: 2; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .three { + -ms-grid-row: 2; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .four { + -ms-grid-row: 2; + -ms-grid-column: 2; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .two { + -ms-grid-row: 1; + -ms-grid-column: 2; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .three { + -ms-grid-row: 2; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .four { + -ms-grid-row: 2; + -ms-grid-column: 2; + -ms-grid-column-span: 1; + } +} +.hr-grid-row-4 .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + grid-area: one; +} +.hr-grid-row-4 .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + grid-area: two; +} +.hr-grid-row-4 .three { + -ms-grid-row: 1; + -ms-grid-column: 5; + -ms-grid-column-span: 1; + grid-area: three; +} +.hr-grid-row-4 .four { + -ms-grid-row: 1; + -ms-grid-column: 7; + -ms-grid-column-span: 1; + grid-area: four; +} +@media screen and (max-width: 768px){ + .hr-grid-row-4-4 .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .three { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .four { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .five { + -ms-grid-row: 5; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .six { + -ms-grid-row: 5; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .seven { + -ms-grid-row: 7; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 .eight { + -ms-grid-row: 7; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .one { + -ms-grid-row: 1; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .two { + -ms-grid-row: 1; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .two { + -ms-grid-row: 1; + -ms-grid-column: 2; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 .three { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .three { + -ms-grid-row: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .three { + -ms-grid-row: 2; + -ms-grid-column: 1; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 .four { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4-4 > .four { + -ms-grid-row: 3; + -ms-grid-column: 3; + -ms-grid-column-span: 1; + } + .hr-grid-row-4 > .four { + -ms-grid-row: 2; + -ms-grid-column: 2; + -ms-grid-column-span: 1; + } +} + +.scrollbar { + /* Scrollbar Styling */ +} +.scrollbar ::-webkit-scrollbar { + width: 7px; +} +.scrollbar ::-webkit-scrollbar-track { + background-color: #ebebeb; + border-radius: 10px; +} +.scrollbar ::-webkit-scrollbar-thumb { + border-radius: 10px; + background: #bababa; +} + +.table-container { + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + overflow-y: scroll; + max-height: 500px; +} + +table { + width: 100%; + border-collapse: collapse; + text-align: left; +} +table thead { + background-color: #d0e97b; + position: sticky; + top: 0px; +} +table thead th { + padding: 12px; + border-bottom: 2px solid #ddd; + font-size: 16px; +} +table thead th:first-child { + border-top-left-radius: 10px; +} +table thead th:last-child { + border-top-right-radius: 10px; +} +table .error { + color: #ff0000; +} +table tbody tr { + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; + font-size: 14px; +} +table tbody tr { + border-bottom: 1px solid #ddd; +} +table tbody tr:hover { + background-color: #f9f9f9; +} +table tbody tr td { + padding: 12px; +} + +.hr-website-not-available { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + text-align: center; + padding: 30px 60px; + border-radius: 20px; + -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + background-color: #ffffff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} +.hr-website-not-available__content { + max-width: 600px; + margin: 0 auto; + padding: 40px 20px; +} +.hr-website-not-available__content h1 { + font-size: 28px; + font-weight: 600; + color: #333; + margin-bottom: 30px; +} +.hr-website-not-available__content img { + max-width: 300px; + margin: 30px 0; +} +.hr-website-not-available__content p { + font-size: 14px; + line-height: 1.6; + color: #666; + margin-bottom: 0; +} + + +.health_report .spinner-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + flex-direction: column; + padding: 20px; +} + +.health_report .spinner { + border: 4px solid rgba(255, 255, 255, 0.3); + border-top: 4px solid white; + border-radius: 50%; + width: 40px; + height: 40px; + animation: spin 0.8s linear infinite; + margin-bottom: 10px; +} +.health_report .loading-text { + font-size: 14px; + color: #555; + font-style: italic; + text-align: center; + max-width: 250px; +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + + +.o_dashboard_loader_wrapper { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + height: 100%; + background-color: #f4f5f7; + color: #444; + font-family: 'Inter', sans-serif; + animation: fadeIn 0.3s ease-in-out; +} + +.o_loader_spinner { + border: 6px solid #e0e0e0; + border-top: 6px solid #007bff; + border-radius: 50%; + width: 60px; + height: 60px; + animation: spin 1s linear infinite; + margin-bottom: 15px; +} + +.o_loader_text { + font-size: 18px; + font-weight: 500; + color: #007bff; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.text-orange { color: #fd7e14; } + +.text-dark-red { color: #8B0000; } diff --git a/odoo_health_report/static/src/js/dashboard_wrapper.js b/odoo_health_report/static/src/js/dashboard_wrapper.js new file mode 100644 index 000000000..e9f959e76 --- /dev/null +++ b/odoo_health_report/static/src/js/dashboard_wrapper.js @@ -0,0 +1,17 @@ +/** @odoo-module **/ +import { Component, useState, onMounted } from "@odoo/owl"; +import { registry } from "@web/core/registry"; +import { HealthDashboard } from "./health_dashboard"; + +export class DashboardWrapper extends Component { + setup() { + this.state = useState({ dashboard_loading: true }); + onMounted(async () => { + await new Promise((r) => setTimeout(r, 1)); + this.state.dashboard_loading = false; + }); + } + static components = { HealthDashboard }; + static template = "odoo_health_report.DashboardWrapper"; +} +registry.category("actions").add("odoo_health_report.dashboard_wrapper", DashboardWrapper); diff --git a/odoo_health_report/static/src/js/health_dashboard.js b/odoo_health_report/static/src/js/health_dashboard.js new file mode 100644 index 000000000..721c2b237 --- /dev/null +++ b/odoo_health_report/static/src/js/health_dashboard.js @@ -0,0 +1,92 @@ +/** @odoo-module **/ +import { Component, useState, onMounted } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; +import { registry } from "@web/core/registry"; +import { ModuleQuality } from "./module_quality"; + + +export class HealthDashboard extends Component { + static components = { ModuleQuality }; + + setup() { + const lastComponent = localStorage.getItem("activeComponent"); + const activeId = lastComponent ? parseInt(lastComponent) : 3; + this.orm = useService('orm'); + this.action = useService('action'); + this.notification = useService('notification'); + + this.state = useState({ + activeComponent: activeId, + activeMenu: activeId, + loading: false, + module : false, + module_selected: {}, + module_selected_desc: {}, + showOptions: false, + select_module: [], + value: [], + checked_module: '', + }); + + onMounted(async () => { + this.state.select_module = await this.orm.searchRead("ir.module.module", [['state', '=', 'installed'], + ['name', '!=', 'odoo_health_report']]); + }); + + this.setActiveComponent = async (id) => { + this.state.loading = true; + this.state.activeMenu = id; + + localStorage.setItem("activeComponent", id); + await new Promise((resolve) => setTimeout(resolve, 100)) + + this.state.activeComponent = id; + this.state.loading = false; + }; + } + + exitDashboard() { + const baseUrl = window.location.origin; + window.location.href = baseUrl+"/odoo/apps"; + } + + onModuleSelectDesc(ev) { + ev.stopPropagation() + let module = ev.target.dataset.modName + this.state.module_selected[module] = false + delete this.state.module_selected_desc[module] + } + + onModuleSelect(event) { + const checked = event.target.checked; + const moduleName = event.target.dataset.modName; + const moduleShortdesc = event.target.dataset.modShortdesc; + this.state.module_selected[moduleName] = checked; + this.state.module_selected_desc[moduleName] = moduleShortdesc; + if (checked == false){delete this.state.module_selected_desc[moduleName]} + } + + async onGenerateReport() { + const selected = []; + if (this.state.module) selected.push("module"); + + const validOptions = ['module']; + const hasValidOption = validOptions.some(opt => selected.includes(opt)); + if (!hasValidOption) { + this.notification.add("Please select at least one option", { type: 'danger' }); + return; + } + + const data = { + selected, + module_quality: this.state.module, + module_selected: this.state.module_selected, + }; + + await this.action.doAction("odoo_health_report.action_odoo_health_report", { + additionalContext: { data } + }) + } +} +HealthDashboard.template = "odoo_health_report.health_dashboard"; +registry.category("actions").add("health_dashboard_tag", HealthDashboard); diff --git a/odoo_health_report/static/src/js/module_quality.js b/odoo_health_report/static/src/js/module_quality.js new file mode 100644 index 000000000..0e53bb7e0 --- /dev/null +++ b/odoo_health_report/static/src/js/module_quality.js @@ -0,0 +1,190 @@ +/** @odoo-module **/ +import { registry } from "@web/core/registry"; +import { Component, useRef, onWillUnmount, useState, onWillStart, useEffect } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; + + +export class ModuleQuality extends Component { + + setup() { + super.setup(); + + this.orm = useService('orm'); + this.action = useService("action"); + this.notification = useService("notification"); + this.setActiveComponent = this.props.setActiveComponent; + + this.overview = useRef('overview'); + this.overviewText = useRef('overview_text'); + this.selectRef = useRef("select"); + + this.state = useState({ + field : {}, + quality_monitoring : {}, + loading: true, + all_modules : {}, + loading_accordian: false, + expanded_accordian: false, + }); + + this.orm = useService("orm"); + this.notification = useService("notification"); + + onWillStart(async () => { + this.moduleLineOfCode(); + this.getAllModulesAndIcon(); + this.countFields(); + this.state.selectedAuthor = null; + }); + useEffect(() => { + this.renderOverviewChart(); + }); + + } + + // lines of code in modules + async moduleLineOfCode() { + this.orm.call("module.quality.package", "count_lines_of_code_in_modules", [], {}).then((result) => { + this.state.quality_monitoring = result.result + }); + } + + // module lines toggle function + async displayAuthorModules(author) { + if (this.state.selectedAuthor === author) { + this.state.selectedAuthor = null; + } else { + this.state.selectedAuthor = author; + } + } + + // fields and apps overview + async countFields() { + this.orm.call("module.quality.package", "fields_and_apps_overview", [], {}).then((result) => { + this.state.field = result + }); + } + + // report function for violations + async getAllModulesAndIcon() { + try { + const result = await this.orm.call("module.quality.package", "get_module_and_icons", [], {}); + this.state.all_modules = result; + } catch (error) { + console.error("Error fetching PEP standard template:", error); + } + } + + // module violation function + async checkModuleViolations(name) { + try { + if (!this.state.expanded_accordian) { + this.state.loading_accordian = true; + this.state.expanded_accordian = true; + this.state.selectedModule = name; + const result = await this.orm.call("module.quality.package", "check_violations", [name], {}); + this.state.module_selected = result; + this.state.loading_accordian = false; + } else { + this.state.expanded_accordian = false; + } + } catch (error) { + console.error("Error fetching violations:", error); + } + } + + displayViolations(name) { + // If clicking the same module again, toggle the table visibility + if (this.state.selectedModule === name) { + this.state.selectedModule = null; + this.state.module_selected = null; + } else { + this.checkModuleViolations(name); + } + } + + async renderOverviewChart() { + const canvas = this.overview?.el; + if (!canvas) { + return; + } + + const ctx = canvas.getContext("2d"); + + if (this.gaugeChart) { + this.gaugeChart.destroy(); + } + + if (this.state?.field !== undefined && this.state?.field !== null) { + const gaugeValue = this.state.field.critical_overview.overall_percentage['value']; // Example: 80 + const totalAngle = 180; // Half-circle + const pointerAngle = (gaugeValue / 100) * totalAngle - 90; + + // Determine dot color based on value + let dotColor = "#f36c21"; // Default Red + if (gaugeValue >= 75) dotColor = "#EA973D"; // Orange + else if (gaugeValue >= 50) dotColor = "#f8d31d"; // Yellow + + // Draw the gauge chart + this.gaugeChart = new Chart(ctx, { + type: "doughnut", + data: { + datasets: [ + { + data: [40, 40, 20, 20], // Segment values + backgroundColor: ["#f36c21", "#f8d31d", "#EA973D", "#75C57F"], + borderWidth: 0, + borderRadius: 5, + }, + ], + }, + options: { + responsive: false, + maintainAspectRatio: false, + rotation: -90, + circumference: 180, + cutout: "90%", + plugins: { + legend: { display: false }, + tooltip: { enabled: false }, + }, + }, + }); + + // Remove any existing dots (in case of re-render) + const oldDot = canvas.parentElement.querySelector(".gauge-dot"); + if (oldDot) oldDot.remove(); + + // Create the dot indicator + const dot = document.createElement("div"); + dot.className = "gauge-dot"; // for easy removal later + dot.style.position = "absolute"; + dot.style.width = "14px"; + dot.style.height = "14px"; + dot.style.background = dotColor; + dot.style.borderRadius = "50%"; + dot.style.border = "3px solid white"; + dot.style.boxShadow = "0px 0px 5px rgba(0,0,0,0.2)"; + dot.style.transformOrigin = "center"; + + const outerRadius = 85; + const innerRadius = 55; + const dotRadius = (outerRadius + innerRadius) / 2; + const radians = pointerAngle * (Math.PI / 180); + + const xOffset = dotRadius * Math.cos(radians); + const yOffset = dotRadius * Math.sin(radians); + + dot.style.left = `calc(50% + ${xOffset}px - 7px)`; + dot.style.top = `calc(55% - ${yOffset}px - 7px)`; + + } else { + if (this.overviewText?.el) { + this.overviewText.el.innerText = 'Loading...'; + } + } + } +} + +ModuleQuality.template = "odoo_health_report.module_quality_template" +registry.category('actions').add('module_quality_tag', ModuleQuality); diff --git a/odoo_health_report/static/src/xml/dashboard_wrapper.xml b/odoo_health_report/static/src/xml/dashboard_wrapper.xml new file mode 100644 index 000000000..d08b6559f --- /dev/null +++ b/odoo_health_report/static/src/xml/dashboard_wrapper.xml @@ -0,0 +1,14 @@ + + + + +
+
+
Loading dashboard...
+
+ + + + + + diff --git a/odoo_health_report/static/src/xml/health_dashboard.xml b/odoo_health_report/static/src/xml/health_dashboard.xml new file mode 100644 index 000000000..17a11622c --- /dev/null +++ b/odoo_health_report/static/src/xml/health_dashboard.xml @@ -0,0 +1,137 @@ + + + +
+ +
+ +
+
+
+
+
    +
  • + + + + +
  • +
  • + + + +
  • +
+
+
+
+
+ +
+
+
    +
  • + + + + +
  • +
  • + + + +
  • +
+
+
+ +
+ +
+
+
Fetching the data... This may take a few moments. Please be patient.
+
+ + + + + + + + + +
+ +
+
+
\ No newline at end of file diff --git a/odoo_health_report/static/src/xml/module_quality.xml b/odoo_health_report/static/src/xml/module_quality.xml new file mode 100644 index 000000000..1fee0da50 --- /dev/null +++ b/odoo_health_report/static/src/xml/module_quality.xml @@ -0,0 +1,248 @@ + + + + +
+
+ + Module dashboard +
+ + +
+ +
+
+ + +
+
+
+ +

+ +

+
+ +
+ % Overall +
+
+ +
+ + Loading..... + +
+
+ +
+
+

+ +

+

+ +

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

+ +

+

+ +

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

+ +

+

+ +

+
+
+ + + +
+
+
+ + +
+
+ Module Lines of Code +
+ + + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + +
ModuleTechnical NameJavaScript LinesPython LinesXML Lines
+ + + + + + + + + +
+
+
+
+
+
+
+
+
+ + +
+
+ All Modules +
+ + +
+ + + +
+ Loading... +
+
+ + + + +
+

Style & Linting Check for:

+ + + + + + + + + + + + + + + +
File NameLine NumberViolation Message
+ + + +
+ + No issues found + +
+ + +
+

Code Formatting Check for:

+ + + + + + + + + + + + + +
File NameAction
+ +
+
+ +
+
+
+
+
+
+ +
+

No violations found for modules

+
+
+
+
+
+
+
diff --git a/odoo_health_report/views/odoo_health_report_menus.xml b/odoo_health_report/views/odoo_health_report_menus.xml new file mode 100644 index 000000000..1e5750471 --- /dev/null +++ b/odoo_health_report/views/odoo_health_report_menus.xml @@ -0,0 +1,14 @@ + + + + Health Dashboard + odoo_health_report.dashboard_wrapper + fullscreen + health-dashboard + + + +