@ -0,0 +1,47 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
App Category View |
|||
================ |
|||
This module helps you to style home screen dashboard accorindg to category you give |
|||
|
|||
Configuration |
|||
============= |
|||
* No additional configurations needed |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
Credits |
|||
------- |
|||
* Developers: Cybrosys Techno Solutions odoo@cybrosys.com |
|||
Version 16: Mruthul @cybrosys |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
License |
|||
------- |
|||
General Public License, Version 3 (AGPL v3). |
|||
(http://www.gnu.org/licenses/agpl-3.0-standalone.html) |
|||
|
|||
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 <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Mruthul (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from . import models |
@ -0,0 +1,52 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Mruthul (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
{ |
|||
'name': 'App Category View', |
|||
'version': '16.0.1.0.0', |
|||
'category': 'Extra Tools', |
|||
'summary': 'Make Apps category wise as you need', |
|||
'description': 'The "App Category View" app allows users to efficiently' |
|||
'categorize and organize the apps based on specific ' |
|||
'category.', |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solution', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'website': 'https://www.cybrosys.com', |
|||
'license': 'AGPL-3', |
|||
'depends': ['base', 'web_enterprise'], |
|||
'data': ['security/ir.model.access.csv', |
|||
'data/ir_sequence.xml', |
|||
'views/ir_app_category_views.xml', |
|||
], |
|||
'assets': { |
|||
'web.assets_backend': [ |
|||
'app_category_view/static/src/xml/home_dashboard_templates.xml', |
|||
'app_category_view/static/src/js/home_menu.js', |
|||
'app_category_view/static/src/js/app_move.js', |
|||
'app_category_view/static/src/css/home_dashboard.css']}, |
|||
'images': [ |
|||
'static/description/banner.jpg' |
|||
], |
|||
'installable': True, |
|||
'application': False, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Definition of a new sequence record for the model "ir.app.category" --> |
|||
<record id="app_category_sequence" model="ir.sequence"> |
|||
<field name="name">App Category</field> |
|||
<field name="code">ir.app.category</field> |
|||
<field name="active">True</field> |
|||
<field name="number_increment">1</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,6 @@ |
|||
## Module <app_category_view> |
|||
|
|||
#### 21.12.2023 |
|||
#### Version 16.0.1.0.0 |
|||
##### ADD |
|||
- Initial Commit for App Category View |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Mruthul (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from . import ir_app_category |
@ -0,0 +1,118 @@ |
|||
"""Modle for app category""" |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Mruthul (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from odoo import _, api, fields, models |
|||
from odoo.exceptions import UserError |
|||
|
|||
|
|||
class IrAppCategory(models.Model): |
|||
""" |
|||
Model representing the category of installed apps in the home menu. |
|||
""" |
|||
_name = 'ir.app.category' |
|||
_description = 'category' |
|||
|
|||
name = fields.Char(string='Name', help='Enter category name') |
|||
installed_apps_ids = fields.Many2many('ir.ui.menu', |
|||
string='Apps Installed', |
|||
domain=[('parent_id', '=', False)], |
|||
help="You can add the installed apps " |
|||
"to display under the category " |
|||
"here", required=True) |
|||
sequence = fields.Integer(string="Sequence", help='Number sequence') |
|||
|
|||
@api.constrains('name') |
|||
def name_check(self): |
|||
"""Check the same category name""" |
|||
names = self.env['ir.app.category'].search([]).mapped('name') |
|||
print(names) |
|||
if self.name in names: |
|||
existing_category = self.search([('name', '=', self.name)]) |
|||
if len(existing_category) > 1: |
|||
raise UserError( |
|||
_('Try different name,Already a category in this name')) |
|||
else: |
|||
pass |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
"""The `sequence` field will be automatically set to the next value in |
|||
the 'ir.sequence' sequence for 'ir.app.category.' |
|||
|
|||
:param vals: A dictionary of field values for the new record |
|||
:return: the new 'ir.app.category' Creates a new app category record. |
|||
""" |
|||
vals['sequence'] = self.env['ir.sequence'].next_by_code( |
|||
'ir.app.category') |
|||
return super(IrAppCategory, self).create(vals) |
|||
|
|||
@api.model |
|||
def get_home_dashboard(self): |
|||
"""Return the home dashboard configuration as a list of dictionaries. |
|||
|
|||
Each dictionary contains information about a category, including its |
|||
name and the IDs of the installed apps associated with it. The |
|||
categories are sorted by their sequence attribute. |
|||
Returns: |
|||
list: A list of dictionaries containing category information. |
|||
""" |
|||
categories = self.env['ir.app.category'].search([], order='sequence') |
|||
return [{'name': record.name, |
|||
'installed_apps': record.installed_apps_ids.ids} for record in |
|||
categories] |
|||
|
|||
@api.model |
|||
def get_other_apps(self): |
|||
"""Retrieve the IDs of apps that are not assigned to any category. |
|||
Returns: |
|||
list: List of IDs unassigned apps. |
|||
""" |
|||
installed_apps = self.env['ir.app.category'].search( |
|||
[]).installed_apps_ids.ids |
|||
return self.env['ir.ui.menu'].search( |
|||
[('id', 'not in', installed_apps), ('parent_id', '=', False)]).ids |
|||
|
|||
@api.model |
|||
def apps_switching(self, menu_1, menu_2): |
|||
"""Switches the sequence of two app menu items.""" |
|||
menu_item_1 = self.env['ir.ui.menu'].browse(int(menu_1)) |
|||
menu_item_2 = self.env['ir.ui.menu'].browse(int(menu_2)) |
|||
menu_item_1.sequence, menu_item_2.sequence = menu_item_2.sequence, menu_item_1.sequence |
|||
|
|||
@api.model |
|||
def category_change(self, menu_id, category_name): |
|||
"""Moves an app from its current category to a new category.""" |
|||
current_category = self.env['ir.app.category'].search( |
|||
[('installed_apps_ids', 'in', int(menu_id))]) |
|||
if category_name != 'OtherApps': |
|||
category_id = self.env['ir.app.category'].search( |
|||
[('name', '=', category_name)]) |
|||
if category_id: |
|||
if current_category: |
|||
current_category.write( |
|||
{'installed_apps_ids': [(3, int(menu_id))]}) |
|||
category_id.write({'installed_apps_ids': [(4, int(menu_id))]}) |
|||
elif current_category: |
|||
current_category.write( |
|||
{'installed_apps_ids': [(3, int(menu_id))]}) |
|||
else: |
|||
current_category.write({'installed_apps_ids': [(3, int(menu_id))]}) |
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 967 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 2.8 MiB |
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 8.7 MiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,647 @@ |
|||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;"> |
|||
<!-- TITLE BAR --> |
|||
<div class="d-flex align-items-center justify-content-between" |
|||
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> |
|||
<img src="assets/misc/cybrosys-logo.png" width="42" height="42" |
|||
style="width: 42px; height: 42px;"/> |
|||
<div> |
|||
<div |
|||
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Community |
|||
</div> |
|||
<div style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Enterprise |
|||
</div> |
|||
<div |
|||
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Odoo.sh |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF TITLE BAR --> |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12"> |
|||
<!-- APP HERO --> |
|||
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> |
|||
App Category View</h1> |
|||
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> |
|||
You can personalize apps to different categories as you |
|||
wish </p> |
|||
<!-- END OF APP HERO --> |
|||
<img src="assets/screenshots/hero.gif" class="img-responsive" |
|||
style="width: 100%; margin-left: auto; margin-right: auto;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
|
|||
<!-- NAVIGATION SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/compass.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Explore This |
|||
Module</h2> |
|||
</div> |
|||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#overview"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn |
|||
more about this |
|||
module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#features"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View |
|||
features of this |
|||
module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#screenshots"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View |
|||
screenshots for this |
|||
module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<!-- END OF NAVIGATION SECTION --> |
|||
|
|||
<!-- OVERVIEW SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/pie-chart.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Overview |
|||
</h2> |
|||
</div> |
|||
<div class="row" |
|||
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> |
|||
<div class="col-sm-12 py-4"> |
|||
This module in Odoo 16 Enterprise home dashboard is a |
|||
user-friendly feature that allows users to easily manage their apps and |
|||
categories. This module enables users to drag and drop their apps into |
|||
different categories, as well as create and rename categories. |
|||
</div> |
|||
</div> |
|||
<!-- END OF OVERVIEW SECTION --> |
|||
|
|||
<!-- FEATURES SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/features.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Features |
|||
</h2> |
|||
</div> |
|||
<div class="row" |
|||
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 40px; margin-bottom: 40px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Drag and drop app to other categories</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Drag categories to different position</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Add app under categories from setting</span> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available in Odoo 16 Enterprise.</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF FEATURES SECTION --> |
|||
|
|||
<!-- SCREENSHOTS SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="screenshots"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/pictures.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Screenshots |
|||
</h2> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12"> |
|||
|
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Create category from App Category |
|||
</h3> |
|||
<img src="assets/screenshots/menu.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Create category |
|||
</h3> |
|||
<img src="assets/screenshots/category.png" class="img-thumbnail"> |
|||
</div> |
|||
|
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Created categories will be displayed in the home menu |
|||
</h3> |
|||
<img src="assets/screenshots/categories.png" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Also, we can drag and drop these apps to different categories and switch their positions |
|||
</h3> |
|||
<img src="assets/screenshots/scrnli_01_09_2023_15-41-35.gif" |
|||
class="img-thumbnail"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF SCREENSHOTS SECTION --> |
|||
|
|||
<!-- RELATED PRODUCTS --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/categories.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Related |
|||
Products |
|||
</h2> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12"> |
|||
<div id="demo1" class="row carousel slide" data-ride="carousel"> |
|||
<!-- The slideshow --> |
|||
<div class="carousel-inner" style="padding: 30px;"> |
|||
<div class="carousel-item" style="min-height: 198.656px;"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/dynamic_accounts_report/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/1.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/custom_gantt_view/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/2.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/project_custom_gantt/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/3.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item active" |
|||
style="min-height: 198.656px;"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/account_reports_xlsx/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/4.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/base_accounting_kit/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/5.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/hr_payroll_community/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/6.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Left and right controls --> |
|||
<a class="carousel-control-prev" href="#demo1" data-slide="prev" |
|||
style="width:35px; color:#000"> <span |
|||
class="carousel-control-prev-icon"><i |
|||
class="fa fa-chevron-left" |
|||
style="font-size:24px"></i></span> |
|||
</a> <a class="carousel-control-next" href="#demo1" |
|||
data-slide="next" style="width:35px; color:#000"> |
|||
<span class="carousel-control-next-icon"><i |
|||
class="fa fa-chevron-right" |
|||
style="font-size:24px"></i></span> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF RELATED PRODUCTS --> |
|||
|
|||
<!-- OUR SERVICES --> |
|||
|
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/star.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Our Services |
|||
</h2> |
|||
</div> |
|||
|
|||
<div class="container my-5"> |
|||
<div class="row"> |
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/cogs.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Customization</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/wrench.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/lifebuoy.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Support</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/user.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Hire |
|||
Odoo |
|||
Developer</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/puzzle.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Integration</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/update.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Migration</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/consultation.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Consultancy</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/training.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/license.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Licensing Consultancy</h6> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- END OF OUR SERVICES --> |
|||
|
|||
<!-- OUR INDUSTRIES --> |
|||
|
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/corporate.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Our |
|||
Industries |
|||
</h2> |
|||
</div> |
|||
|
|||
<div class="container my-5"> |
|||
<div class="row"> |
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/trading-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Trading |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easily procure |
|||
and |
|||
sell your products</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/pos-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
POS |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easy |
|||
configuration |
|||
and convivial experience</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/education-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Education |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
A platform for |
|||
educational management</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/manufacturing-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Manufacturing |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Plan, track and |
|||
schedule your operations</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/ecom-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
E-commerce & Website |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Mobile |
|||
friendly, |
|||
awe-inspiring product pages</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/service-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Service Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Keep track of |
|||
services and invoice</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/restaurant-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Restaurant |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Run your bar or |
|||
restaurant methodically</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="assets/icons/hotel-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Hotel Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
An |
|||
all-inclusive |
|||
hotel management application</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- END OF OUR INDUSTRIES --> |
|||
|
|||
<!-- SUPPORT --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/customer-support.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Support |
|||
</h2> |
|||
</div> |
|||
<div class="container mt-5"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> |
|||
<div class="mr-4 d-flex justify-content-center align-items-center" |
|||
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> |
|||
<img src="assets/misc/support.png" height="48" width="48" |
|||
style="width: 42px; height: 42px;"/> |
|||
</div> |
|||
<div> |
|||
<h4>Need Help?</h4> |
|||
<p style="line-height: 100%;">Got questions or need help? |
|||
Get in touch.</p> |
|||
<a href="mailto:odoo@cybrosys.com"> |
|||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> |
|||
odoo@cybrosys.com</p> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6"> |
|||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> |
|||
<div class="mr-4 d-flex justify-content-center align-items-center" |
|||
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> |
|||
<img src="assets/misc/whatsapp.png" height="52" width="52" |
|||
style="width: 52px; height: 52px;"/> |
|||
</div> |
|||
<div> |
|||
<h4>WhatsApp</h4> |
|||
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p> |
|||
<a href="https://api.whatsapp.com/send?phone=918606827707"> |
|||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> |
|||
+91 86068 |
|||
27707</p> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> |
|||
<img src="assets/misc/logo.png" width="144" height="31" |
|||
style="width:144px; height: 31px; margin-top: 40px;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF SUPPORT --> |
@ -0,0 +1,84 @@ |
|||
.o_home_menu_scrollable{ |
|||
align-items: stretch !important; |
|||
} |
|||
.collapse:not(.show) { |
|||
display: none !important; |
|||
} |
|||
.category-apps { |
|||
width: 29%; |
|||
position: relative; |
|||
backdrop-filter: blur(5px); /* Adjust the blur value to your preference */ |
|||
text-align: center; |
|||
cursor: pointer; |
|||
color: white; |
|||
overflow-y: scroll; |
|||
max-height: 100%; |
|||
} |
|||
.ui-state-highlight { |
|||
height: 10.5em; line-height: 20px; |
|||
background: blue; |
|||
} |
|||
.apps-sortable-div{ |
|||
border: none; |
|||
outline: none; |
|||
padding: 10px 16px; |
|||
cursor: pointer; |
|||
font-size: 18px; |
|||
} |
|||
.active-category, .apps-sortable-div:hover { |
|||
background-color: #362f2f38; |
|||
color: white; |
|||
} |
|||
.category-apps::-webkit-scrollbar-track { |
|||
padding: 2px 0; |
|||
background-color: #0000002b; |
|||
} |
|||
|
|||
.category-apps::-webkit-scrollbar { |
|||
width: 10px; |
|||
} |
|||
.category-apps::-webkit-scrollbar-thumb { |
|||
border-radius: 10px; |
|||
box-shadow: inset 0 0 6px rgba(0,0,0,.3); |
|||
background-color: black; |
|||
border: 1px solid #000; |
|||
} |
|||
@keyframes begindrag { |
|||
0% { |
|||
transform: rotate(0deg) |
|||
} |
|||
10% { |
|||
transform: rotate(-8deg) |
|||
} |
|||
30% { |
|||
transform: rotate(6deg) |
|||
} |
|||
55% { |
|||
transform: rotate(-3deg) |
|||
} |
|||
80% { |
|||
transform: rotate(1deg) |
|||
} |
|||
100% { |
|||
transform: rotate(-1deg) |
|||
} |
|||
} |
|||
@keyframes bye { |
|||
0% { |
|||
transform: scale(1) rotate(-1deg) |
|||
} |
|||
50% { |
|||
transform: scale(1.1) rotate(-2deg) |
|||
} |
|||
100% { |
|||
transform: scale(0) rotate(3deg) |
|||
} |
|||
} |
|||
.beginDrag { |
|||
animation: begindrag .8s ease forwards; |
|||
} |
|||
.bye { |
|||
opacity: 1; |
|||
transition: opacity .5s ease; |
|||
animation: bye .4s ease forwards; |
|||
} |
@ -0,0 +1,70 @@ |
|||
/** @odoo-module **/ |
|||
import { patch } from "@web/core/utils/patch"; |
|||
import { HomeMenu } from "@web_enterprise/webclient/home_menu/home_menu" |
|||
var rpc = require('web.rpc'); |
|||
// Patch the HomeMenu prototype to add draggable_menu functionality
|
|||
patch(HomeMenu.prototype, "menu_item_draggable.draggable_menu", { |
|||
// Call the original setup method and add onMounted hook
|
|||
setup() { |
|||
this._super.apply(); |
|||
}, |
|||
/** |
|||
* Toggle the active class for the clicked category. |
|||
*/ |
|||
_active: async function(ev) { |
|||
if (ev.currentTarget.closest('.apps-sortable-div')) { |
|||
const currentActiveDiv = ev.currentTarget.closest('.apps-sortable-div'); |
|||
const allDivs = currentActiveDiv.parentElement.querySelectorAll('.apps-sortable-div'); |
|||
allDivs.forEach(div => { |
|||
if (div !== currentActiveDiv) { |
|||
div.classList.remove('active-category'); |
|||
} |
|||
}); |
|||
currentActiveDiv.classList.add('active-category'); |
|||
} |
|||
}, |
|||
/** |
|||
* Handle the drag start event. |
|||
*/ |
|||
dragStart: async function(e) { |
|||
e.dataTransfer.setData('Menu_id', e.target.id) |
|||
e.dataTransfer.effectAllowed = 'move'; |
|||
e.target.classList.add('beginDrag'); |
|||
}, |
|||
/** |
|||
* Handle the dropped event after dragging. |
|||
*/ |
|||
dropped: async function(e) { |
|||
// get new and old index
|
|||
var dragged_menu = e.dataTransfer.getData('Menu_id') |
|||
var previousElement = e.dataTransfer.getData('Element') |
|||
var dropped_menu = e.target.id |
|||
var categoryName = e.target.attributes[1].nodeValue |
|||
if (dragged_menu && dropped_menu) { |
|||
e.target.classList.add('bye') |
|||
await rpc.query({ |
|||
model: 'ir.app.category', |
|||
method: 'apps_switching', |
|||
args: [dragged_menu, dropped_menu] |
|||
}).then(function() { |
|||
window.location.reload() |
|||
}) |
|||
} else if (dragged_menu && categoryName) { |
|||
await rpc.query({ |
|||
model: 'ir.app.category', |
|||
method: 'category_change', |
|||
args: [dragged_menu, categoryName] |
|||
}).then(function() { |
|||
window.location.reload() |
|||
}) |
|||
} |
|||
}, |
|||
/** |
|||
* Prevent the default behavior of the event. |
|||
*/ |
|||
cancelDefault: async function(e) { |
|||
e.preventDefault() |
|||
e.stopPropagation() |
|||
return false |
|||
}, |
|||
}); |
@ -0,0 +1,28 @@ |
|||
/**@odoo-module**/ |
|||
import { patch } from "@web/core/utils/patch"; |
|||
import { url } from "@web/core/utils/urls"; |
|||
import { HomeMenu } from "@web_enterprise/webclient/home_menu/home_menu" |
|||
const { onMounted } = owl; |
|||
var rpc = require('web.rpc'); |
|||
patch(HomeMenu.prototype, "home_menu.AppCategory", { |
|||
async setup() { |
|||
this._super(...arguments); |
|||
const self = this; |
|||
await rpc.query({ |
|||
model: "ir.app.category", |
|||
method: "get_home_dashboard", |
|||
args: [] |
|||
}).then(function(data) { |
|||
self.appCategory = data; |
|||
self.render(); |
|||
}); |
|||
await rpc.query({ |
|||
model: "ir.app.category", |
|||
method: "get_other_apps", |
|||
args: [] |
|||
}).then(function(otherApps) { |
|||
self.otherApps = otherApps; |
|||
self.render(); |
|||
}); |
|||
}, |
|||
}); |
@ -0,0 +1,172 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<templates xml:space="preserve"> |
|||
<!-- This template is used to display the home dashboard for app categories --> |
|||
<t t-name="app_category_view.home_dashboard" |
|||
t-inherit="web_enterprise.HomeMenu" t-inherit-mode="extension" |
|||
owl="1"> |
|||
<!-- Replaces the existing apps container with the app categories and their corresponding apps --> |
|||
<xpath expr="div[hasclass('o_home_menu')]/div[hasclass('container')]" |
|||
position="replace"> |
|||
<input t-ref="input" type="text" |
|||
class="o_search_hidden visually-hidden w-auto" |
|||
data-allow-hotkeys="true" t-on-input="_onInputSearch" |
|||
t-on-blur="_onInputBlur" |
|||
t-on-compositionstart="_onCompositionStart"/> |
|||
<!-- When the subscription has expired, the expiration panel is show over the whole UI instead of here --> |
|||
<ExpirationPanel |
|||
t-if="subscription.warningType and !subscription.isWarningHidden and subscription.daysLeft <= 30 and subscription.daysLeft > 0"/> |
|||
<!-- Display all other apps that do not belong to any category --> |
|||
<div t-if="displayedApps.length" |
|||
class="row accordion accordion-flush mt-5" |
|||
style="max-height: 100%;display: flex;flex-wrap: nowrap;align-items: start;" |
|||
id="accordion"> |
|||
<div class="category-apps"> |
|||
<div class="apps-sortable-div collapsed active-category" |
|||
style="padding:1%;" |
|||
t-on-click="(ev) => this._active(ev)" |
|||
data-bs-toggle="collapse" |
|||
t-attf-data-bs-target="#otherApps" type="button" |
|||
t-att-aria-expanded="true" |
|||
t-att-aria-controls="otherApps" |
|||
t-on-dragover="(e)=>this.cancelDefault(e)" |
|||
t-on-drop="(e)=>this.dropped(e)"> |
|||
<a class="col" |
|||
data-toggle="collapse"> |
|||
<h1 style="position:relative;z-index:9999;color: white;" |
|||
name="OtherApps">All Apps |
|||
</h1> |
|||
<span class="arrow"/> |
|||
</a> |
|||
</div> |
|||
<t t-if="appCategory"> |
|||
<t t-foreach="appCategory" t-as="category" |
|||
t-key="category.name"> |
|||
<div class="apps-sortable-div collapsed" |
|||
t-on-click="(ev) => this._active(ev)" |
|||
data-bs-toggle="collapse" |
|||
t-att-data-bs-target="'#'+category.name" |
|||
role="button" |
|||
t-att-aria-expanded="false" |
|||
t-att-aria-controls="category.name" |
|||
t-on-dragover="(e)=>this.cancelDefault(e)" |
|||
t-on-drop="(e)=>this.dropped(e)" |
|||
t-att-name="category.name"> |
|||
<a class="col home_category_header"> |
|||
<h1 t-esc="category.name" |
|||
t-att-name="category.name" |
|||
style="position:relative;z-index:9999;color: white;"/> |
|||
</a> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</div> |
|||
<div style="width:55%;float:left;"> |
|||
<div role="listbox" |
|||
class="o_apps row user-select-none accordion-collapse collapse show" |
|||
data-bs-parent="#accordion" |
|||
style="max-height:10%;" |
|||
id="otherApps"> |
|||
<t t-foreach="displayedApps" t-as="app" |
|||
t-key="app.id"> |
|||
<a t-att-id="app.id" |
|||
role="option" |
|||
style="display:flex;flex-wrap:inherit;justify-content:center;" |
|||
t-att-aria-selected="state.focusedIndex === app_index ? 'true' : 'false'" |
|||
class="o_app o_menuitem p-2 mb-3 col-lg-2" |
|||
t-att-class="{o_focused: state.focusedIndex === app_index}" |
|||
t-att-data-menu-xmlid="app.xmlid" |
|||
t-att-href="app.href || ('#menu_id='+app.id+'&action_id='+app.actionID)" |
|||
t-on-click.prevent="() => this._onAppClick(app)" |
|||
t-key="app.id" |
|||
draggable="true" |
|||
t-on-dragstart="(e)=>this.dragStart(e)" |
|||
t-on-drop="(e)=>this.dropped(e)" |
|||
t-on-dragenter="(e)=>this.cancelDefault(e)" |
|||
t-on-dragover="(e)=>this.cancelDefault(e)"> |
|||
<img t-if="app.webIconData" |
|||
t-att-id="app.id" |
|||
class="o_app_icon rounded" |
|||
t-attf-src="{{app.webIconData}}"/> |
|||
<div t-else="" |
|||
t-att-id="app.id" |
|||
class="o_app_icon rounded d-flex p-2 justify-content-center align-items-center" |
|||
t-attf-style="background-color: {{app.webIcon.backgroundColor}};"> |
|||
<i t-att-class="app.webIcon.iconClass" |
|||
t-att-id="app.id" |
|||
t-attf-style="color: {{app.webIcon.color}};"/> |
|||
</div> |
|||
<div class="o_caption w-100 text-center text-truncate mt-2" |
|||
t-att-id="app.id" |
|||
t-esc="app.label or app.name"/> |
|||
</a> |
|||
</t> |
|||
</div> |
|||
<t t-if="appCategory"> |
|||
<t t-foreach="appCategory" t-as="category" |
|||
t-key="category.name"> |
|||
<div role="listbox" |
|||
class="o_apps row user-select-none accordion-collapse collapse app-data" |
|||
style="max-height:10%;" |
|||
data-bs-parent="#accordion" |
|||
t-att-id="category.name"> |
|||
<t t-if="!category.installed_apps.length"> |
|||
<div id="no_apps_in_category" |
|||
style="margin-top: 25%;margin-left: 36%;font-size: xxx-large;" |
|||
role="option" aria-selected="true" |
|||
class="o_no_result"> |
|||
No Apps |
|||
</div> |
|||
</t> |
|||
<t t-foreach="displayedApps" t-as="app" |
|||
t-key="app.id"> |
|||
<t t-foreach="category.installed_apps" |
|||
t-as="id" t-key="id"> |
|||
<t t-if="app.id == id"> |
|||
<a t-att-id="app.id" |
|||
style="display:flex;flex-wrap:inherit;justify-content:center;" |
|||
role="option" |
|||
draggable="true" |
|||
t-on-dragstart="(e)=>this.dragStart(e)" |
|||
t-on-drop="(e)=>this.dropped(e)" |
|||
t-on-dragenter="(e)=>this.cancelDefault(e)" |
|||
t-on-dragover="(e)=>this.cancelDefault(e)" |
|||
t-att-name="category.name" |
|||
t-att-aria-selected="state.focusedIndex === app_index ? 'true' : 'false'" |
|||
class="o_app o_menuitem p-2 mb-3 col-lg-2" |
|||
t-att-class="{o_focused: state.focusedIndex === app_index}" |
|||
t-att-data-menu-xmlid="app.xmlid" |
|||
t-att-href="app.href || ('#menu_id='+app.id+'&action_id='+app.actionID)" |
|||
t-key="app.id" |
|||
t-on-click.prevent="() => this._onAppClick(app)"> |
|||
<img t-if="app.webIconData" |
|||
t-att-id="app.id" |
|||
class="o_app_icon rounded" |
|||
t-attf-src="{{app.webIconData}}"/> |
|||
<div t-else="" |
|||
t-att-id="app.id" |
|||
class="o_app_icon rounded d-flex p-2 justify-content-center align-items-center" |
|||
t-attf-style="background-color: {{app.webIcon.backgroundColor}};"> |
|||
<i t-att-class="app.webIcon.iconClass" |
|||
t-att-id="app.id" |
|||
t-attf-style="color: {{app.webIcon.color}};"/> |
|||
</div> |
|||
<div class="o_caption w-100 text-center text-truncate mt-2" |
|||
t-att-id="app.id" |
|||
t-esc="app.label or app.name"/> |
|||
</a> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</div> |
|||
</div> |
|||
<div t-elif="!displayedApps.length" id="result_menu_0" |
|||
role="option" |
|||
aria-selected="true" class="o_no_result"> |
|||
No result |
|||
</div> |
|||
</xpath> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,51 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Define a form view for the 'ir.app.category' model --> |
|||
<record id="ir_app_category_view_form" model="ir.ui.view"> |
|||
<field name="name">ir.app.category.view.form</field> |
|||
<field name="model">ir.app.category</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<!-- Show the 'name' field and make it required --> |
|||
<field name="name" required="true"/> |
|||
<!-- Use a 'many2many_tags' widget for the 'installed_apps_ids' field, |
|||
and disable the option to create new items --> |
|||
<field name="installed_apps_ids" |
|||
widget="many2many_tags" |
|||
options="{'no_create': True}"/> |
|||
<!-- Show the 'sequence' field --> |
|||
<field name="sequence"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Define a tree view for the 'ir.app.category' model --> |
|||
<record id="ir_app_category_view_tree" model="ir.ui.view"> |
|||
<field name="name">ir.app.category.view.tree</field> |
|||
<field name="model">ir.app.category</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<!-- Show the 'name' field --> |
|||
<field name="name"/> |
|||
<!-- Use a 'many2many_tags' widget for the 'installed_apps_ids' field --> |
|||
<field name="installed_apps_ids" widget="many2many_tags"/> |
|||
<!-- Use a 'handle' widget for the 'sequence' field --> |
|||
<field name="sequence" widget="handle"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<!-- Define an action to open the 'ir.app.category' model in tree and form views --> |
|||
<record id="actions_ir_app_category_view" model="ir.actions.act_window"> |
|||
<field name="name">App Category</field> |
|||
<field name="res_model">ir.app.category</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
<!-- Define a menu item to access the 'ir.app.category' model --> |
|||
<menuitem parent="base.next_id_2" name="App Category" |
|||
id="menu_ir_app_category" |
|||
action="actions_ir_app_category_view" |
|||
sequence="6"/> |
|||
</odoo> |