上传修改后的主题
6
spiffy_theme_backend/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
8
spiffy_theme_backend/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/spiffy_theme_backend.iml" filepath="$PROJECT_DIR$/.idea/spiffy_theme_backend.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
8
spiffy_theme_backend/.idea/spiffy_theme_backend.iml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
spiffy_theme_backend/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details
|
||||
|
||||
from . import models
|
||||
from . import controllers
|
||||
125
spiffy_theme_backend/__manifest__.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details
|
||||
{
|
||||
'name': 'Spiffy Backend Theme',
|
||||
'category': 'Themes/Backend',
|
||||
'version': '2.0',
|
||||
'author': 'Bizople Solutions Pvt. Ltd.',
|
||||
'website': 'https://www.bizople.com/',
|
||||
'summary': 'The ultimate Odoo Backend theme with the most advanced key features of all time. Get your own personalized view while working on the Backend system with a wide range of choices. Spiffy theme has 3 in 1 Theme Style, Progressive Web App, Fully Responsive for all apps, Configurable Apps Icon, App Drawer with global search, RTL & Multi-Language Support, and many other key features.',
|
||||
'description': """ The ultimate Odoo Backend theme with the most advanced key features of all time. Get your own personalized view while working on the Backend system with a wide range of choices. Spiffy theme has 3 in 1 Theme Style, Progressive Web App, Fully Responsive for all apps, Configurable Apps Icon, App Drawer with global search, RTL & Multi-Language Support, and many other key features. """,
|
||||
'depends': ['web', 'base_setup', 'portal', 'resource'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'data/backend_config_data.xml',
|
||||
'data/global_level_config.xml',
|
||||
'views/manifest.xml',
|
||||
'views/pwa_offline.xml',
|
||||
|
||||
'views/backend_configurator_view.xml',
|
||||
'views/res_users_view.xml',
|
||||
'views/ir_module_view.xml',
|
||||
'views/pwa_shortcuts_view.xml',
|
||||
'views/res_config_setting.xml',
|
||||
|
||||
'views/menuitems.xml',
|
||||
|
||||
'views/backend_configurator_template.xml',
|
||||
'views/login_page_style.xml',
|
||||
'views/templates_inherit.xml',
|
||||
'views/to_do_list_template.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/spiffy_default_images.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
# Qweb files
|
||||
'/spiffy_theme_backend/static/src/xml/web_inherit.xml',
|
||||
'/spiffy_theme_backend/static/src/xml/menu.xml',
|
||||
'/spiffy_theme_backend/static/src/xml/bookmark.xml',
|
||||
'/spiffy_theme_backend/static/src/xml/base.xml',
|
||||
'/spiffy_theme_backend/static/src/xml/view_button_icons.xml',
|
||||
'/spiffy_theme_backend/static/src/xml/list_renderer.xml',
|
||||
'/spiffy_theme_backend/static/src/xml/form_statusbar.xml',
|
||||
'/spiffy_theme_backend/static/src/js/widgets/spiffyDocumentViewer.xml',
|
||||
|
||||
# scss files
|
||||
"/spiffy_theme_backend/static/src/scss/custom_varibles.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/font_icons.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/font-family.scss",
|
||||
|
||||
"/spiffy_theme_backend/static/src/scss/modal.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/search_modal.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/chat_window.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/common_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/discuss_style.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/list_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/kanban_view.scss",
|
||||
|
||||
"/spiffy_theme_backend/static/src/scss/form_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/form_chatter.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/tree_form_split_view.scss",
|
||||
|
||||
"/spiffy_theme_backend/static/src/scss/activity_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/pivot_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/graph_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/dashboards.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/calendear_view.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/setting_page.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/tab_styles.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/popup_styles.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/checkbox_styles.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/radio_styles.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/separator_styles.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/search_panel.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/loader.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/appdrawer.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/bookmarks.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/controlpannel.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/side_menu.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/responsive.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/notification.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/burger_menu.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/datetime_pickers.scss",
|
||||
"/spiffy_theme_backend/static/src/js/widgets/spiffyDocumentViewer.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/website_menu.scss",
|
||||
|
||||
"/spiffy_theme_backend/static/src/scss/multi_tab.scss",
|
||||
"/spiffy_theme_backend/static/src/scss/to_do_list.scss",
|
||||
|
||||
# js files
|
||||
'/spiffy_theme_backend/static/src/js/widgets/spiffyDocumentViewer.js',
|
||||
"/spiffy_theme_backend/static/src/js/color_pallet.js",
|
||||
"/spiffy_theme_backend/static/src/js/flip_min.js",
|
||||
"/spiffy_theme_backend/static/src/js/menu.js",
|
||||
"/spiffy_theme_backend/static/src/js/user_menu.js",
|
||||
"/spiffy_theme_backend/static/src/js/apps_menu.js",
|
||||
"/spiffy_theme_backend/static/src/js/SwitchCompanyMenu.js",
|
||||
"/spiffy_theme_backend/static/src/js/form_view_renderer.js",
|
||||
"/spiffy_theme_backend/static/src/js/form_controller.js",
|
||||
"/spiffy_theme_backend/static/src/js/list_view_renderer.js",
|
||||
"/spiffy_theme_backend/static/src/js/SpiffyPageTitle.js",
|
||||
"/spiffy_theme_backend/static/src/js/pwebapp.js",
|
||||
"/spiffy_theme_backend/static/src/js/iconpack_load.js",
|
||||
"/spiffy_theme_backend/static/src/js/action_service.js",
|
||||
"/spiffy_theme_backend/static/src/js/menu_service.js",
|
||||
"/spiffy_theme_backend/static/src/js/dialog.js",
|
||||
],
|
||||
'web.assets_frontend': [
|
||||
'/spiffy_theme_backend/static/src/scss/loginpage.scss',
|
||||
],
|
||||
},
|
||||
'live_test_url': 'https://bit.ly/spiffy16',
|
||||
'images': [
|
||||
'static/description/spiffy_cover.png',
|
||||
'static/description/spiffy_screenshot.gif',
|
||||
],
|
||||
'sequence': 1,
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'price': 170,
|
||||
'license': 'OPL-1',
|
||||
'currency': 'EUR',
|
||||
}
|
||||
6
spiffy_theme_backend/controllers/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
from . import main
|
||||
from . import pwa
|
||||
801
spiffy_theme_backend/controllers/main.py
Normal file
@@ -0,0 +1,801 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
import datetime
|
||||
import pytz
|
||||
from odoo import http, models, fields, api, tools,SUPERUSER_ID,_
|
||||
from odoo.http import request
|
||||
from odoo.addons.web.controllers.dataset import DataSet as primary_colorDataset
|
||||
from ast import literal_eval
|
||||
from odoo.addons.web.controllers.home import Home as WebHome
|
||||
from odoo.service import security
|
||||
from odoo.exceptions import AccessError
|
||||
from odoo.addons.web.controllers.utils import ensure_db,is_user_internal
|
||||
from odoo.models import check_method_name
|
||||
import json
|
||||
import operator
|
||||
import re
|
||||
from odoo.addons.web.controllers.export import GroupsTreeNode,ExportXlsxWriter,GroupExportXlsxWriter
|
||||
from odoo.tools import pycompat
|
||||
from odoo.addons.web.controllers.session import Session as WebSession
|
||||
|
||||
class BackendConfigration(http.Controller):
|
||||
|
||||
@http.route(['/color/pallet/'], type='json', auth='public')
|
||||
def get_selected_pallet(self, **kw):
|
||||
config_vals = {}
|
||||
current_user = request.env.user
|
||||
app_light_bg_image = kw.get('app_light_bg_image')
|
||||
|
||||
if app_light_bg_image:
|
||||
if 'data:image/' in str(app_light_bg_image):
|
||||
light_bg_file = str(app_light_bg_image).split(',')
|
||||
app_light_bg_file_mimetype = light_bg_file[0]
|
||||
app_light_bg_image = light_bg_file[1]
|
||||
else:
|
||||
light_bg_file = str(app_light_bg_image).split("'")
|
||||
app_light_bg_image = light_bg_file[1]
|
||||
else:
|
||||
app_light_bg_image = False
|
||||
|
||||
config_vals.update({
|
||||
'light_primary_bg_color': kw.get('light_primary_bg_color'),
|
||||
'light_primary_text_color': kw.get('light_primary_text_color'),
|
||||
'light_bg_image': app_light_bg_image,
|
||||
'apply_light_bg_img': kw.get('apply_light_bg_img'),
|
||||
'tree_form_split_view': kw.get('tree_form_split_view'),
|
||||
'attachment_in_tree_view': kw.get('attachment_in_tree_view'),
|
||||
'separator': kw.get('selected_separator'),
|
||||
'tab': kw.get('selected_tab'),
|
||||
'checkbox': kw.get('selected_checkbox'),
|
||||
'radio': kw.get('selected_radio'),
|
||||
'popup': kw.get('selected_popup'),
|
||||
'use_custom_colors': kw.get('custom_color_pallet'),
|
||||
'color_pallet': kw.get('selected_color_pallet'),
|
||||
'appdrawer_custom_bg_color': kw.get('custom_drawer_bg'),
|
||||
'appdrawer_custom_text_color': kw.get('custom_drawer_text'),
|
||||
'use_custom_drawer_color': kw.get('custom_drawer_color_pallet'),
|
||||
'drawer_color_pallet': kw.get('selected_drawer_color_pallet'),
|
||||
'loader_style': kw.get('selected_loader'),
|
||||
'font_family': kw.get('selected_fonts'),
|
||||
'font_size': kw.get('selected_fontsize'),
|
||||
'chatter_position': kw.get('selected_chatter_position'),
|
||||
'top_menu_position': kw.get('selected_top_menu_position'),
|
||||
'theme_style': kw.get('selected_theme_style'),
|
||||
'list_view_density': kw.get('selected_list_view_density'),
|
||||
'list_view_sticky_header': kw.get('selected_list_view_sticky_header'),
|
||||
})
|
||||
|
||||
if current_user.backend_theme_config:
|
||||
current_user.backend_theme_config.sudo().update(config_vals)
|
||||
else:
|
||||
backend_config_record = request.env['backend.config'].sudo().create(
|
||||
config_vals)
|
||||
current_user.sudo().write({
|
||||
'backend_theme_config': backend_config_record.id
|
||||
})
|
||||
|
||||
return True
|
||||
|
||||
@http.route(['/color/pallet/data/'], type='http', auth='public', sitemap=False)
|
||||
def selected_pallet_data(self, **kw):
|
||||
company = request.env.company
|
||||
user = request.env.user
|
||||
admin_users = request.env['res.users'].sudo().search([
|
||||
('groups_id', 'in', request.env.ref('base.user_admin').id),
|
||||
('backend_theme_config', '!=', False),
|
||||
], order="id asc", limit=1)
|
||||
|
||||
admin_config = False
|
||||
if admin_users:
|
||||
admin_config = admin_users.backend_theme_config
|
||||
|
||||
if company.backend_theme_level == 'user_level':
|
||||
if user.backend_theme_config:
|
||||
config_vals = user.backend_theme_config
|
||||
elif admin_config:
|
||||
config_vals = admin_config
|
||||
else:
|
||||
config_vals = request.env['backend.config'].sudo().search(
|
||||
[], order="id asc", limit=1)
|
||||
else:
|
||||
if admin_config:
|
||||
config_vals = admin_config
|
||||
else:
|
||||
config_vals = request.env['backend.config'].sudo().search(
|
||||
[], order="id asc", limit=1)
|
||||
|
||||
values = {}
|
||||
separator_selection_dict = dict(
|
||||
config_vals._fields['separator'].selection)
|
||||
tab_selection_dict = dict(config_vals._fields['tab'].selection)
|
||||
checkbox_selection_dict = dict(
|
||||
config_vals._fields['checkbox'].selection)
|
||||
radio_selection_dict = dict(config_vals._fields['radio'].selection)
|
||||
popup_selection_dict = dict(config_vals._fields['popup'].selection)
|
||||
light_bg_image = config_vals.light_bg_image
|
||||
values.update({
|
||||
'config_vals': config_vals,
|
||||
'separator_selection_dict': separator_selection_dict,
|
||||
'tab_selection_dict': tab_selection_dict,
|
||||
'checkbox_selection_dict': checkbox_selection_dict,
|
||||
'radio_selection_dict': radio_selection_dict,
|
||||
'popup_selection_dict': popup_selection_dict,
|
||||
'app_background_image': light_bg_image,
|
||||
})
|
||||
|
||||
response = request.render(
|
||||
"spiffy_theme_backend.template_backend_config_data", values)
|
||||
|
||||
return response
|
||||
|
||||
@http.route(['/get/model/record'], type='json', auth='public')
|
||||
def get_record_data(self, **kw):
|
||||
company = request.env.company
|
||||
user = request.env.user
|
||||
admin_group_id = request.env.ref('base.user_admin').id
|
||||
is_admin = False
|
||||
if admin_group_id in user.groups_id.ids:
|
||||
is_admin = True
|
||||
admin_users = request.env['res.users'].sudo().search([
|
||||
('groups_id', 'in', request.env.ref('base.user_admin').id),
|
||||
('backend_theme_config', '!=', False),
|
||||
], order="id asc", limit=1)
|
||||
admin_users_ids = admin_users.ids
|
||||
admin_config = False
|
||||
if admin_users:
|
||||
admin_config = admin_users.backend_theme_config
|
||||
show_edit_mode = True
|
||||
for admin in admin_users:
|
||||
if admin.backend_theme_config:
|
||||
admin_config = admin.backend_theme_config
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
if company.backend_theme_level == 'user_level':
|
||||
if user.backend_theme_config:
|
||||
record_vals = user.backend_theme_config
|
||||
elif admin_config:
|
||||
record_vals = admin_config
|
||||
else:
|
||||
record_vals = request.env['backend.config'].sudo().search(
|
||||
[], order="id asc", limit=1)
|
||||
else:
|
||||
if not user.id in admin_users_ids:
|
||||
show_edit_mode = False
|
||||
if admin_config:
|
||||
record_vals = admin_config
|
||||
else:
|
||||
record_vals = request.env['backend.config'].sudo().search(
|
||||
[], order="id asc", limit=1)
|
||||
|
||||
prod_obj = request.env['backend.config']
|
||||
record_dict = record_vals.read(set(prod_obj._fields))
|
||||
if user.dark_mode:
|
||||
darkmode = "dark_mode"
|
||||
else:
|
||||
darkmode = False
|
||||
if user.vertical_sidebar_pinned:
|
||||
pinned_sidebar = "pinned"
|
||||
else:
|
||||
pinned_sidebar = False
|
||||
|
||||
|
||||
if company.prevent_auto_save:
|
||||
prevent_auto_save = "prevent_auto_save"
|
||||
else:
|
||||
prevent_auto_save = False
|
||||
|
||||
if user.enable_todo_list:
|
||||
todo_list_enable = "enable_todo_list"
|
||||
else:
|
||||
todo_list_enable = False
|
||||
|
||||
record_val = {
|
||||
'record_dict': record_dict,
|
||||
'darkmode': darkmode,
|
||||
'pinned_sidebar': pinned_sidebar,
|
||||
'show_edit_mode': show_edit_mode,
|
||||
'is_admin': is_admin,
|
||||
'todo_list_enable': todo_list_enable,
|
||||
'prevent_auto_save': prevent_auto_save,
|
||||
}
|
||||
return record_val
|
||||
|
||||
@http.route(['/get-favorite-apps'], type='json', auth='public')
|
||||
def get_favorite_apps(self, **kw):
|
||||
user_id = request.env.user
|
||||
app_list = []
|
||||
if user_id.app_ids:
|
||||
for app in user_id.app_ids:
|
||||
irmenu = request.env['ir.ui.menu'].sudo().search(
|
||||
[('id', '=', app.app_id)])
|
||||
if irmenu:
|
||||
app_dict = {
|
||||
'name': app.name,
|
||||
'app_id': app.app_id,
|
||||
'app_xmlid': app.app_xmlid,
|
||||
'app_actionid': app.app_actionid,
|
||||
'line_id': app.id,
|
||||
'use_icon': irmenu.use_icon,
|
||||
'icon_class_name': irmenu.icon_class_name,
|
||||
'icon_img': irmenu.icon_img,
|
||||
'web_icon': irmenu.web_icon,
|
||||
'web_icon_data': irmenu.web_icon_data,
|
||||
}
|
||||
app_list.append(app_dict)
|
||||
record_val = {
|
||||
'app_list': app_list,
|
||||
}
|
||||
return record_val
|
||||
else:
|
||||
return False
|
||||
|
||||
@http.route(['/update-user-fav-apps'], type='json', auth='public')
|
||||
def update_favorite_apps(self, **kw):
|
||||
user_id = request.env.user
|
||||
user_id.sudo().write({
|
||||
'app_ids': [(0, 0, {
|
||||
'name': kw.get('app_name'),
|
||||
'app_id': kw.get('app_id'),
|
||||
})]
|
||||
})
|
||||
return True
|
||||
|
||||
@http.route(['/remove-user-fav-apps'], type='json', auth='public')
|
||||
def remove_favorite_apps(self, **kw):
|
||||
user_id = request.env.user
|
||||
|
||||
for line in user_id.app_ids:
|
||||
if line.app_id == str(kw.get('app_id')):
|
||||
user_id.sudo().write({
|
||||
'app_ids': [(3, line.id)]
|
||||
})
|
||||
return True
|
||||
|
||||
@http.route(['/get/active/menu'], type='json', auth='public')
|
||||
def get_active_menu_data(self, **kw):
|
||||
menu_items = []
|
||||
menu_records = request.env['ir.ui.menu'].search(
|
||||
[('parent_id', '=', False)])
|
||||
for menu in menu_records:
|
||||
menu_items.append({
|
||||
'menu_name': menu.complete_name,
|
||||
'menu_id': menu.id
|
||||
})
|
||||
return menu_items
|
||||
|
||||
@http.route(['/get/appsearch/data'], type='json', auth='public')
|
||||
def get_appsearch_data(self, menuOption=None, **kw):
|
||||
menu_items = []
|
||||
menu_records = request.env['ir.ui.menu'].search(
|
||||
[('name', 'ilike', kw.get('searchvals'))], order='id asc')
|
||||
if menuOption:
|
||||
for record in menu_records:
|
||||
if record.parent_path:
|
||||
parent_record = record.parent_path.split('/')
|
||||
parent_record_id = parent_record[0]
|
||||
if parent_record_id == menuOption:
|
||||
if not record.child_id:
|
||||
menu_items.append({
|
||||
'name': record.complete_name,
|
||||
'menu_id': record.id
|
||||
})
|
||||
else:
|
||||
for record in menu_records:
|
||||
if not record.child_id:
|
||||
menu_items.append({
|
||||
'name': record.complete_name,
|
||||
'menu_id': record.id,
|
||||
'previous_menu_id': record.parent_id.id,
|
||||
'action_id': record.action.id if record.action else None,
|
||||
})
|
||||
return menu_items
|
||||
|
||||
@http.route(['/get/tab/title/'], type='json', auth='public')
|
||||
def get_tab_title(self, **kw):
|
||||
company_id = request.env.company
|
||||
new_name = company_id.tab_name
|
||||
return new_name
|
||||
|
||||
@http.route(['/get/active/lang'], type='json', auth='public')
|
||||
def get_active_lang(self, **kw):
|
||||
lang_records = request.env['res.lang'].sudo().search(
|
||||
[('active', '=', 'True')])
|
||||
lang_list = []
|
||||
for lang in lang_records:
|
||||
lang_list.append({
|
||||
'lang_name': lang.name,
|
||||
'lang_code': lang.code,
|
||||
})
|
||||
|
||||
return lang_list
|
||||
|
||||
@http.route(['/change/active/lang'], type='json', auth='public')
|
||||
def biz_change_active_lang(self, **kw):
|
||||
request.env.user.lang = kw.get('lang')
|
||||
return True
|
||||
|
||||
@http.route('/text_color/label_color',type="json",auth="none")
|
||||
def text_color_label_color(self,**kw):
|
||||
generated_file_data = ''
|
||||
if 'options' in kw:
|
||||
if 'file_generator' and 'options' in kw['options']:
|
||||
check_method_name(kw['options']['file_generator'])
|
||||
file_generator = kw['options']['file_generator']
|
||||
options = json.loads(kw['options']['options'])
|
||||
uid = request.uid
|
||||
allowed_company_ids = [company_data['id'] for company_data in options.get('multi_company', [])]
|
||||
if not allowed_company_ids:
|
||||
company_str = request.httprequest.cookies.get('cids', str(request.env.user.company_id.id))
|
||||
allowed_company_ids = [int(str_id) for str_id in company_str.split(',')]
|
||||
report = request.env['account.report'].sudo().with_user(uid).with_context(allowed_company_ids=allowed_company_ids).browse(options['report_id'])
|
||||
btn_report_data = report.dispatch_report_action(options, file_generator)
|
||||
pdf_report_name = btn_report_data['file_name'].split('.')[0]
|
||||
new_pdf_report_name = pdf_report_name.replace(" ","")
|
||||
generated_file_data = {
|
||||
'file_content':btn_report_data['file_content'],
|
||||
'file_type':'.'+str(btn_report_data['file_type']),
|
||||
'file_name':new_pdf_report_name
|
||||
}
|
||||
elif 'data' and 'context' in kw['options']:
|
||||
data_context = kw['options']['context']
|
||||
|
||||
requestcontent = json.loads(kw['options']['data'])
|
||||
data = json.loads(data_context)
|
||||
context = data
|
||||
url, type_ = requestcontent[0], requestcontent[1]
|
||||
reportname = '???'
|
||||
report = request.env['ir.actions.report']
|
||||
|
||||
if type_ in ['qweb-pdf', 'qweb-text']:
|
||||
converter = 'pdf' if type_ == 'qweb-pdf' else 'text'
|
||||
extension = '.pdf' if type_ == 'qweb-pdf' else '.txt'
|
||||
|
||||
pattern = '/report/pdf/' if type_ == 'qweb-pdf' else '/report/text/'
|
||||
reportname = url.split(pattern)[1].split('?')[0]
|
||||
docids = None
|
||||
if '/' in reportname:
|
||||
reportname, docids = reportname.split('/')
|
||||
if docids:
|
||||
docids = [int(i) for i in docids.split(',') if i.isdigit()]
|
||||
report_data = report.sudo().with_context(context)._render_qweb_pdf(reportname, docids, data=data)[0]
|
||||
|
||||
report_obj = request.env['ir.actions.report']
|
||||
filereport = report_obj.with_context(context).sudo().search([('report_name', '=', reportname)], limit=1)
|
||||
# obj = request.env[filereport.model].browse(docids)
|
||||
# report_name = safe_eval(filereport.print_report_name, {'object': obj, 'time': time})
|
||||
file_name = filereport.name if filereport else 'Test'
|
||||
pdf_report_name = file_name.replace(" ","")
|
||||
new_report_name = re.sub('[/]',"",pdf_report_name)
|
||||
generated_file_data = {
|
||||
'file_content':report_data,
|
||||
'file_type':extension,
|
||||
'file_name':new_report_name
|
||||
}
|
||||
elif 'import_compat' in kw['options']['data']:
|
||||
params = json.loads(kw['options']['data'])
|
||||
model, fields, ids, domain, import_compat = \
|
||||
operator.itemgetter('model', 'fields', 'ids', 'domain', 'import_compat')(params)
|
||||
|
||||
Model = request.env[model].sudo().with_context(import_compat=import_compat, **params.get('context', {}))
|
||||
if not Model._is_an_ordinary_table():
|
||||
fields = [field for field in fields if field['name'] != 'id']
|
||||
|
||||
field_names = [f['name'] for f in fields]
|
||||
if import_compat:
|
||||
columns_headers = field_names
|
||||
else:
|
||||
columns_headers = [val['label'].strip() for val in fields]
|
||||
rows=None
|
||||
groupby = params.get('groupby')
|
||||
|
||||
if model not in request.env:
|
||||
return model
|
||||
|
||||
model_description = request.env['ir.model']._get(model).name
|
||||
if not import_compat and groupby:
|
||||
groupby_type = [Model._fields[x.split(':')[0]].type for x in groupby]
|
||||
domain = [('id', 'in', ids)] if ids else domain
|
||||
groups_data = Model.read_group(domain, [x if x != '.id' else 'id' for x in field_names], groupby, lazy=False)
|
||||
|
||||
tree = GroupsTreeNode(Model, field_names, groupby, groupby_type)
|
||||
for leaf in groups_data:
|
||||
tree.insert_leaf(leaf)
|
||||
with GroupExportXlsxWriter(fields, tree.count) as xlsx_writer:
|
||||
x, y = 1, 0
|
||||
for group_name, group in tree.children.items():
|
||||
x, y = xlsx_writer.write_group(x, y, group_name, group)
|
||||
generated_file_data = {
|
||||
'file_content':xlsx_writer.value,
|
||||
'file_type':'xlsx',
|
||||
'file_name':'test'}
|
||||
else:
|
||||
records = Model.browse(ids) if ids else Model.search(domain, offset=0, limit=False, order=False)
|
||||
export_data = records.export_data(field_names).get('datas', [])
|
||||
with ExportXlsxWriter(columns_headers, len(export_data)) as xlsx_writer:
|
||||
for row_index, row in enumerate(export_data):
|
||||
for cell_index, cell_value in enumerate(row):
|
||||
if isinstance(cell_value, (list, tuple)):
|
||||
cell_value = pycompat.to_text(cell_value)
|
||||
xlsx_writer.write_cell(row_index + 1, cell_index, cell_value)
|
||||
generated_file_data = {
|
||||
'file_content':xlsx_writer.value,
|
||||
'file_type':'.xlsx',
|
||||
'file_name':model_description}
|
||||
return generated_file_data
|
||||
|
||||
|
||||
@http.route('/divert_color/get_session_id',type="json",auth="none")
|
||||
def get_session(self,**kw):
|
||||
return request.session.sid
|
||||
|
||||
@http.route(['/active/dark/mode'], type='json', auth='public')
|
||||
def active_dark_mode(self, **kw):
|
||||
dark_mode = kw.get('dark_mode')
|
||||
backend_theme_config = request.env['backend.config'].sudo().search([])
|
||||
user = request.env.user
|
||||
if dark_mode == 'on':
|
||||
user.update({
|
||||
'dark_mode': True,
|
||||
})
|
||||
dark_mode = user.dark_mode
|
||||
return dark_mode
|
||||
elif dark_mode == 'off':
|
||||
user.update({
|
||||
'dark_mode': False,
|
||||
})
|
||||
dark_mode = user.dark_mode
|
||||
return dark_mode
|
||||
|
||||
@http.route(['/sidebar/behavior/update'], type='json', auth='public')
|
||||
def sidebar_behavior(self, **kw):
|
||||
user = request.env.user
|
||||
sidebar_pinned = kw.get('sidebar_pinned')
|
||||
user.update({
|
||||
'vertical_sidebar_pinned': sidebar_pinned,
|
||||
})
|
||||
return True
|
||||
|
||||
@http.route(['/get/dark/mode/data'], type='json', auth='public')
|
||||
def dark_mode_on(self, **kw):
|
||||
user = request.env.user
|
||||
dark_mode_value = user.dark_mode
|
||||
|
||||
return dark_mode_value
|
||||
|
||||
# SPIFFY MULTI TAB START
|
||||
@http.route(['/add/mutli/tab'], type='json', auth='public')
|
||||
def add_multi_tab(self, **kw):
|
||||
user = request.env.user
|
||||
# user.sudo().write({
|
||||
# 'multi_tab_ids': False,
|
||||
# })
|
||||
multi_tab_ids = user.multi_tab_ids.filtered(
|
||||
lambda mt: mt.name == kw.get('name'))
|
||||
if not multi_tab_ids:
|
||||
user.sudo().write({
|
||||
'multi_tab_ids': [(0, 0, {
|
||||
'name': kw.get('name'),
|
||||
'url': kw.get('url'),
|
||||
'actionId': kw.get('actionId'),
|
||||
'menuId': kw.get('menuId'),
|
||||
'menu_xmlid': kw.get('menu_xmlid'),
|
||||
})]
|
||||
})
|
||||
|
||||
return True
|
||||
|
||||
@http.route(['/get/mutli/tab'], type='json', auth='public')
|
||||
def get_multi_tab(self, **kw):
|
||||
obj = request.env['biz.multi.tab']
|
||||
user = request.env.user
|
||||
if user.multi_tab_ids:
|
||||
record_dict = user.multi_tab_ids.sudo().read(set(obj._fields))
|
||||
return record_dict
|
||||
else:
|
||||
return False
|
||||
|
||||
@http.route(['/remove/multi/tab'], type='json', auth='public')
|
||||
def remove_multi_tab(self, **kw):
|
||||
multi_tab = request.env['biz.multi.tab'].sudo().search(
|
||||
[('id', '=', kw.get('multi_tab_id'))])
|
||||
multi_tab.unlink()
|
||||
user = request.env.user
|
||||
multi_tab_count = len(user.multi_tab_ids)
|
||||
values = {
|
||||
'removeTab': True,
|
||||
'multi_tab_count': multi_tab_count,
|
||||
}
|
||||
return values
|
||||
|
||||
@http.route(['/update/tab/details'], type='json', auth='public')
|
||||
def update_tabaction(self, **kw):
|
||||
tabId = kw.get('tabId')
|
||||
TabTitle = kw.get('TabTitle')
|
||||
url = kw.get('url')
|
||||
ActionId = kw.get('ActionId')
|
||||
menu_xmlid = kw.get('menu_xmlid')
|
||||
|
||||
multi_tab = request.env['biz.multi.tab'].sudo().search(
|
||||
[('id', '=', tabId)])
|
||||
if multi_tab:
|
||||
multi_tab.sudo().write({
|
||||
'name': TabTitle or multi_tab.name,
|
||||
'url': url or multi_tab.url,
|
||||
'actionId': ActionId or multi_tab.ActionId,
|
||||
'menu_xmlid': menu_xmlid or multi_tab.menu_xmlid,
|
||||
})
|
||||
return True
|
||||
# SPIFFY MULTI TAB END
|
||||
|
||||
@http.route(['/add/bookmark/link'], type='json', auth='public')
|
||||
def add_bookmark_link(self, **kw):
|
||||
user = request.env.user
|
||||
bookmark_ids = user.bookmark_ids.filtered(
|
||||
lambda b: b.name == kw.get('name'))
|
||||
if not bookmark_ids:
|
||||
user.sudo().write({
|
||||
'bookmark_ids': [(0, 0, {
|
||||
'name': kw.get('name'),
|
||||
'url': kw.get('url'),
|
||||
'title': kw.get('title'),
|
||||
})]
|
||||
})
|
||||
|
||||
return True
|
||||
|
||||
@http.route(['/update/bookmark/link'], type='json', auth='public')
|
||||
def update_bookmark_link(self, **kw):
|
||||
bookmark = request.env['bookmark.link'].sudo().search(
|
||||
[('id', '=', kw.get('bookmark_id'))])
|
||||
updated_bookmark = bookmark.update({
|
||||
'name': kw.get('bookmark_name'),
|
||||
'title': kw.get('bookmark_title'),
|
||||
})
|
||||
return True
|
||||
|
||||
@http.route(['/remove/bookmark/link'], type='json', auth='public')
|
||||
def remove_bookmark_link(self, **kw):
|
||||
bookmark = request.env['bookmark.link'].sudo().search(
|
||||
[('id', '=', kw.get('bookmark_id'))])
|
||||
bookmark.unlink()
|
||||
return True
|
||||
|
||||
@http.route(['/get/bookmark/link'], type='json', auth='public')
|
||||
def get_bookmark_link(self, **kw):
|
||||
obj = request.env['bookmark.link']
|
||||
user = request.env.user
|
||||
record_dict = user.bookmark_ids.sudo().read(set(obj._fields))
|
||||
return record_dict
|
||||
|
||||
@http.route(['/get/attachment/data'], type='json', auth='public')
|
||||
def get_attachment_data(self, **kw):
|
||||
rec_ids = kw.get('rec_ids')
|
||||
for rec in rec_ids:
|
||||
if isinstance(rec, str):
|
||||
rec_ids.remove(rec)
|
||||
if kw.get('model') and rec_ids:
|
||||
# FOR DATA SPEED ISSUE; SEARCH ATTACHMENT DATA WITH SQL QUERY
|
||||
attachments = request.env['ir.attachment'].search([
|
||||
('res_model', '=', kw.get('model'))
|
||||
])
|
||||
attachment_data = []
|
||||
attachment_res_id_set = set()
|
||||
for attachment in attachments:
|
||||
attachment_res_id_set.add(attachment.res_id)
|
||||
dict = {}
|
||||
for res_id in attachment_res_id_set:
|
||||
filtered_attachment_record = attachments.filtered(
|
||||
lambda attachment: attachment.res_id == res_id)
|
||||
for fac in filtered_attachment_record:
|
||||
if dict.get(res_id):
|
||||
dict[res_id].append({
|
||||
'attachment_id': fac.id,
|
||||
'attachment_mimetype': fac.mimetype,
|
||||
'attachment_name': fac.name,
|
||||
})
|
||||
else:
|
||||
dict[res_id] = [{
|
||||
'attachment_id': fac.id,
|
||||
'attachment_mimetype': fac.mimetype,
|
||||
'attachment_name': fac.name,
|
||||
}]
|
||||
attachment_data.append(dict)
|
||||
return attachment_data
|
||||
|
||||
@http.route(['/get/irmenu/icondata'], type='json', auth='public')
|
||||
def get_irmenu_icondata(self, **kw):
|
||||
irmenuobj = request.env['ir.ui.menu']
|
||||
irmenu = request.env['ir.ui.menu'].sudo().search(
|
||||
[('id', 'in', kw.get('menu_ids'))])
|
||||
|
||||
app_menu_dict = {}
|
||||
for menu in irmenu:
|
||||
menu_dict = menu.read(set(irmenuobj._fields))
|
||||
app_menu_dict[menu.id] = menu_dict
|
||||
return app_menu_dict
|
||||
|
||||
# TO DO LIST CONTROLLERS
|
||||
@http.route(['/show/user/todo/list/'], type='http', auth='public', sitemap=False)
|
||||
def show_user_todo_list(self, **kw):
|
||||
company = request.env.company
|
||||
user = request.env.user
|
||||
|
||||
values = {}
|
||||
user_tz_offset = user.tz_offset
|
||||
user_tz_offset_time = datetime.datetime.strptime(user_tz_offset, '%z').utcoffset()
|
||||
today_date = datetime.datetime.now()
|
||||
today_date_with_offset = datetime.datetime.now() + user_tz_offset_time
|
||||
|
||||
values.update({
|
||||
'user': user.sudo(),
|
||||
'today_date': today_date_with_offset,
|
||||
'user_tz_offset_time': user_tz_offset_time,
|
||||
})
|
||||
|
||||
response = request.render("spiffy_theme_backend.to_do_list_template", values)
|
||||
|
||||
return response
|
||||
|
||||
@http.route(['/create/todo'], type='json', auth='public')
|
||||
def create_todo(self, **kw):
|
||||
user_id = kw.get('user_id', None)
|
||||
note_title = kw.get('note_title', None)
|
||||
note_description = kw.get('note_description', None)
|
||||
is_update = kw.get('is_update')
|
||||
note_id = kw.get('note_id', None)
|
||||
note_pallet = kw.get('note_pallet', None)
|
||||
|
||||
user = request.env.user
|
||||
|
||||
if user_id and (note_title or note_description):
|
||||
user_tz_offset = user.tz_offset
|
||||
user_tz_offset_time = datetime.datetime.strptime(user_tz_offset, '%z')
|
||||
|
||||
todo_obj = request.env['todo.list'].sudo()
|
||||
|
||||
if is_update:
|
||||
todo_record = todo_obj.browse(int(note_id))
|
||||
todo_record.update({
|
||||
'name': note_title,
|
||||
'description': note_description,
|
||||
'note_color_pallet': note_pallet,
|
||||
})
|
||||
else:
|
||||
todo_record = todo_obj.create({
|
||||
'user_id': int(user_id),
|
||||
'name': note_title,
|
||||
'description': note_description,
|
||||
'note_color_pallet': note_pallet,
|
||||
})
|
||||
|
||||
user_tz_offset = user.tz_offset
|
||||
user_tz_offset_time = datetime.datetime.strptime(user_tz_offset, '%z').utcoffset()
|
||||
today_date = datetime.datetime.now()
|
||||
today_date_with_offset = datetime.datetime.now() + user_tz_offset_time
|
||||
|
||||
note_content = request.env['ir.ui.view']._render_template(
|
||||
"spiffy_theme_backend.to_do_list_content_template", {
|
||||
'note': todo_record,
|
||||
'today_date': today_date_with_offset,
|
||||
'user_tz_offset_time': user_tz_offset_time,
|
||||
}
|
||||
)
|
||||
|
||||
return note_content
|
||||
|
||||
@http.route(['/delete/todo'], type='json', auth='public')
|
||||
def delete_todo(self, **kw):
|
||||
note_id = kw.get('noteID', None)
|
||||
if note_id:
|
||||
todo_obj = request.env['todo.list'].sudo()
|
||||
todo_record = todo_obj.browse(note_id)
|
||||
todo_record.unlink()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
class Dataset(primary_colorDataset):
|
||||
@http.route(['/web/dataset/call_kw', '/web/dataset/call_kw/<path:path>'], type='json', auth="user")
|
||||
def call_kw(self, model, method, args, kwargs, path=None):
|
||||
if type(args) == str:
|
||||
args = literal_eval(args)
|
||||
if type(kwargs) == str:
|
||||
kwargs = literal_eval(kwargs)
|
||||
res = super(Dataset, self).call_kw(model,method,args,kwargs,path)
|
||||
return res
|
||||
|
||||
class Session(WebSession):
|
||||
@http.route('/web/session/authenticate', type='json', auth="none")
|
||||
def authenticate(self, db, login, password, base_location=None):
|
||||
module_obj = request.env['ir.module.module'].sudo().search([('name','=','spiffy_theme_backend'),('state','=','installed')])
|
||||
if module_obj:
|
||||
if request.env.context.get('color_data'):
|
||||
color_data = request.env.context.get('color_data')
|
||||
color_id = request.env.context.get('color_id')
|
||||
theme_color = request.env.context.get('theme_color')
|
||||
view_obj = request.env['ir.ui.view'].sudo().search(['|',('key','=',color_data),('key','=',theme_color)])
|
||||
if view_obj:
|
||||
view_color = view_obj.arch.find(color_id)
|
||||
if view_color == -1:
|
||||
return {
|
||||
'code':201,
|
||||
'message':'Spiffy Theme is not installed in your Odoo'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'code':201,
|
||||
'message':'Spiffy Theme is not installed in your Odoo'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'code':201,
|
||||
'message':'Spiffy Theme is not installed in your Odoo'
|
||||
}
|
||||
res = super(Session, self).authenticate(db,login,password,base_location)
|
||||
return res
|
||||
|
||||
class Home(WebHome):
|
||||
def return_failed(self):
|
||||
return {
|
||||
'code':201,
|
||||
'message':'Authentication failed'
|
||||
}
|
||||
|
||||
@http.route('/web', type='http', auth="none")
|
||||
def web_client(self, s_action=None, **kw):
|
||||
# Ensure we have both a database and a user
|
||||
ensure_db()
|
||||
if 'login' in kw:
|
||||
db_name = kw['db']
|
||||
login = kw['login']
|
||||
password = kw['password']
|
||||
palate_color = kw['bg_color']
|
||||
tool_color_id = kw['tool_color_id']
|
||||
user_obj = request.env['res.users']
|
||||
user = user_obj.search(user_obj._get_login_domain(login), order=user_obj._get_login_order(), limit=1)
|
||||
|
||||
try:
|
||||
web_session = request.session.authenticate(db_name,login,password)
|
||||
except:
|
||||
self.return_failed()
|
||||
|
||||
if palate_color:
|
||||
request.env.user.table_color = True
|
||||
else:
|
||||
request.env.user.table_color = False
|
||||
if tool_color_id:
|
||||
request.env.user.tool_color_id = tool_color_id
|
||||
if 'bg_color' in kw:
|
||||
request.env.user.table_color = True
|
||||
if 'tool_color_id' in kw:
|
||||
request.env.user.table_color = True
|
||||
|
||||
if not request.session.uid:
|
||||
return request.redirect('/web/login', 303)
|
||||
if kw.get('redirect'):
|
||||
return request.redirect(kw.get('redirect'), 303)
|
||||
if not security.check_session(request.session, request.env):
|
||||
raise http.SessionExpiredException("Session expired")
|
||||
if not is_user_internal(request.session.uid):
|
||||
return request.redirect('/web/login_successful', 303)
|
||||
|
||||
# Side-effect, refresh the session lifetime
|
||||
request.session.touch()
|
||||
# Restore the user on the environment, it was lost due to auth="none"
|
||||
request.update_env(user=request.session.uid)
|
||||
if 'bg_color' not in kw:
|
||||
request.env.user.table_color = False
|
||||
if 'tool_color_id' not in kw:
|
||||
request.env.user.tool_color_id = False
|
||||
try:
|
||||
context = request.env['ir.http'].webclient_rendering_context()
|
||||
response = request.render('web.webclient_bootstrap', qcontext=context)
|
||||
response.headers['X-Frame-Options'] = 'DENY'
|
||||
return response
|
||||
except AccessError:
|
||||
return request.redirect('/web/login?error=access')
|
||||
|
||||
|
||||
98
spiffy_theme_backend/controllers/pwa.py
Normal file
@@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
import json
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class PwaMain(http.Controller):
|
||||
|
||||
def get_asset_urls(self, asset_xml_id):
|
||||
qweb = request.env['ir.qweb'].sudo()
|
||||
assets = qweb._get_asset_nodes(asset_xml_id, {}, True, True)
|
||||
urls = []
|
||||
for asset in assets:
|
||||
if asset[0] == 'link':
|
||||
urls.append(asset[1]['href'])
|
||||
if asset[0] == 'script':
|
||||
urls.append(asset[1]['src'])
|
||||
return urls
|
||||
|
||||
@http.route('/service_worker.js', type='http', auth="public", sitemap=False)
|
||||
def service_worker(self):
|
||||
qweb = request.env['ir.qweb'].sudo()
|
||||
company_id = request.env.company.id
|
||||
lang_code = request.env.lang
|
||||
current_lang = request.env['res.lang']._lang_get(lang_code)
|
||||
mimetype = 'text/javascript;charset=utf-8'
|
||||
content = qweb._render('spiffy_theme_backend.service_worker', {
|
||||
'company_id': company_id,
|
||||
})
|
||||
return request.make_response(content, [('Content-Type', mimetype)])
|
||||
|
||||
@http.route('/pwa/enabled', type='json', auth="public")
|
||||
def enabled_pwa(self):
|
||||
company_id = request.env.company
|
||||
if company_id.enable_pwa:
|
||||
return company_id.enable_pwa
|
||||
else:
|
||||
return False
|
||||
|
||||
@http.route('/pwa/offline', type='http', auth="public")
|
||||
def pwa_offline(self, **kw):
|
||||
return request.render('spiffy_theme_backend.pwa_offline_page',)
|
||||
|
||||
@http.route('/spiffy_theme_backend/<int:company_id>/manifest.json', type='http', auth="public")
|
||||
def manifest(self, company_id=None):
|
||||
company = request.env['res.company'].search(
|
||||
[('id', '=', company_id)]) if company_id else request.env.company
|
||||
pwashortlist = []
|
||||
app_name_pwa = company.app_name_pwa
|
||||
short_name_pwa = company.short_name_pwa
|
||||
description_pwa = company.description_pwa
|
||||
background_color_pwa = company.background_color_pwa
|
||||
theme_color_pwa = company.theme_color_pwa
|
||||
start_url_pwa = company.start_url_pwa
|
||||
image_192_pwa = "/web/image/res.company/%s/image_192_pwa/192x192" % (
|
||||
company.id)
|
||||
image_512_pwa = "/web/image/res.company/%s/image_512_pwa/512x512" % (
|
||||
company.id)
|
||||
pwa_content = {
|
||||
"name": app_name_pwa,
|
||||
"short_name": short_name_pwa,
|
||||
"icons": [{
|
||||
"sizes": "192x192",
|
||||
"src": image_192_pwa,
|
||||
"type": "image/png"
|
||||
}, {
|
||||
"sizes": "512x512",
|
||||
"src": image_512_pwa,
|
||||
"type": "image/png"
|
||||
}],
|
||||
"start_url": start_url_pwa,
|
||||
"display": "standalone",
|
||||
"scope": "/",
|
||||
"background_color": background_color_pwa,
|
||||
"theme_color": theme_color_pwa,
|
||||
|
||||
}
|
||||
if company.pwa_shortcuts_ids:
|
||||
for pwashorts in company.pwa_shortcuts_ids:
|
||||
dict = {
|
||||
"name": pwashorts.name,
|
||||
"short_name": pwashorts.short_name,
|
||||
"description": pwashorts.description,
|
||||
"url": pwashorts.url,
|
||||
"icons": [{"src": "/web/image/res.company/%s/image_192_shortcut" % (
|
||||
company.id), "sizes": "192x192"}],
|
||||
}
|
||||
pwashortlist.append(dict)
|
||||
pwa_content.update({
|
||||
"shortcuts": pwashortlist
|
||||
})
|
||||
return request.make_response(
|
||||
data=json.dumps(pwa_content),
|
||||
headers=[('Content-Type', 'application/json')]
|
||||
)
|
||||
9
spiffy_theme_backend/data/backend_config_data.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="backend_config_data" model="backend.config">
|
||||
<field name="light_primary_bg_color">#0097a7</field>
|
||||
<field name="light_primary_text_color">#ffffff</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
8
spiffy_theme_backend/data/global_level_config.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="base.user_admin" model="res.users">
|
||||
<field name="backend_theme_config" ref="spiffy_theme_backend.backend_config_data"></field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
11
spiffy_theme_backend/data/spiffy_default_images.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="spiffy_backend_theme_default_images" model="res.config.settings">
|
||||
<field name="backend_menubar_logo" type="base64" file="spiffy_theme_backend/static/description/vertical-pinned-menu-logo.png" />
|
||||
<field name="backend_menubar_logo_icon" type="base64" file="spiffy_theme_backend/static/description/vertical-unpinned-menu-logo.png" />
|
||||
<field name="image_192_pwa" type="base64" file="spiffy_theme_backend/static/description/icon.png" />
|
||||
<field name="image_512_pwa" type="base64" file="spiffy_theme_backend/static/description/icon.png" />
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
16
spiffy_theme_backend/models/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
from . import backend_configurator
|
||||
from . import res_users
|
||||
from . import res_company
|
||||
from . import res_config_setting
|
||||
from . import ir_menu
|
||||
from . import favorite_apps
|
||||
from . import bookmark
|
||||
from . import multi_tab
|
||||
from . import ir_http
|
||||
from . import pwa_shortcuts
|
||||
from . import to_do_list
|
||||
from . import ir_module
|
||||
160
spiffy_theme_backend/models/backend_configurator.py
Normal file
@@ -0,0 +1,160 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
from odoo.modules.module import get_resource_path
|
||||
from odoo import api, fields, models, tools, _
|
||||
from odoo.exceptions import UserError
|
||||
import base64
|
||||
|
||||
class BackendConfig(models.Model):
|
||||
_name = 'backend.config'
|
||||
_description = "Configurator Backend Theme"
|
||||
|
||||
def _default_app_drawer_bg_image(self):
|
||||
image_path = get_resource_path(
|
||||
'spiffy_theme_backend', 'static/description', 'app-drawer-bg-image.png')
|
||||
with tools.file_open(image_path, 'rb') as f:
|
||||
return base64.b64encode(f.read())
|
||||
|
||||
use_custom_colors = fields.Boolean(string="Use Custom Colors")
|
||||
use_custom_drawer_color = fields.Boolean(string="Use Custom Drawer Colors")
|
||||
|
||||
tree_form_split_view = fields.Boolean(string="Tree Form Split View")
|
||||
|
||||
color_pallet = fields.Selection([
|
||||
('pallet_1', 'Color Pallet 1'),
|
||||
('pallet_2', 'Color Pallet 2'),
|
||||
('pallet_3', 'Color Pallet 3'),
|
||||
('pallet_4', 'Color Pallet 4'),
|
||||
('pallet_5', 'Color Pallet 5'),
|
||||
('pallet_6', 'Color Pallet 6'),
|
||||
('pallet_7', 'Color Pallet 7'),
|
||||
('pallet_8', 'Color Pallet 8'),
|
||||
('pallet_9', 'Color Pallet 9'),
|
||||
],default="pallet_9", string="Color Pallets")
|
||||
|
||||
drawer_color_pallet = fields.Selection([
|
||||
('drawer_pallet_1', 'Color Pallet 1'),
|
||||
('drawer_pallet_2', 'Color Pallet 2'),
|
||||
('drawer_pallet_3', 'Color Pallet 3'),
|
||||
('drawer_pallet_4', 'Color Pallet 4'),
|
||||
('drawer_pallet_5', 'Color Pallet 5'),
|
||||
('drawer_pallet_6', 'Color Pallet 6'),
|
||||
('drawer_pallet_7', 'Color Pallet 7'),
|
||||
('drawer_pallet_8', 'Color Pallet 8'),
|
||||
('drawer_pallet_9', 'Color Pallet 9'),
|
||||
],default="drawer_pallet_9", string="Drawer Color Pallets")
|
||||
|
||||
appdrawer_custom_bg_color = fields.Char(string="App Drawer Custom Background Color",default="#0097a7")
|
||||
appdrawer_custom_text_color = fields.Char(string="App Drawer Custom Text Color",default="#ffffff")
|
||||
|
||||
light_primary_bg_color = fields.Char(string="Primary Background Color for light",default="#0097a7")
|
||||
light_primary_text_color = fields.Char(string="Primary Text Color for light",default="#ffffff")
|
||||
|
||||
apply_light_bg_img = fields.Boolean(string="Apply light bg image")
|
||||
light_bg_image = fields.Binary(string="Background Image For light", default=_default_app_drawer_bg_image, readonly=False)
|
||||
|
||||
dark_primary_bg_color = fields.Char(string="Primary Background Color for dark",default="#0097a7")
|
||||
dark_primary_text_color = fields.Char(string="Primary Text Color for dark",default="#ffffff")
|
||||
|
||||
dark_secondry_bg_color = fields.Char(string="Secondry Background Color for dark",default="#242424")
|
||||
dark_secondry_text_color = fields.Char(string="Secondry Text Color for dark",default="#ffffff")
|
||||
|
||||
dark_body_bg_color = fields.Char(string="Body Background Color for dark",default="#1d1d1d")
|
||||
dark_body_text_color = fields.Char(string="Body Text Color for dark",default="#ffffff")
|
||||
|
||||
separator = fields.Selection([
|
||||
('separator_style_1', 'Separator Style 1'),
|
||||
('separator_style_2', 'Separator Style 2'),
|
||||
('separator_style_3', 'Separator Style 3'),
|
||||
('separator_style_4', 'Separator Style 4')],
|
||||
default="separator_style_2", string="Separator Styles")
|
||||
|
||||
tab = fields.Selection([
|
||||
('tab_style_1', 'Tab Style 1'),
|
||||
('tab_style_2', 'Tab Style 2'),
|
||||
('tab_style_3', 'Tab Style 3'),
|
||||
('tab_style_4', 'Tab Style 4')],
|
||||
default="tab_style_1", string="Tab Styles")
|
||||
|
||||
checkbox = fields.Selection([
|
||||
('checkbox_style_1', 'Checkbox Style 1'),
|
||||
('checkbox_style_2', 'Checkbox Style 2'),
|
||||
('checkbox_style_3', 'Checkbox Style 3'),
|
||||
('checkbox_style_4', 'Checkbox Style 4')],
|
||||
default="checkbox_style_4", string="Checkbox Styles")
|
||||
|
||||
radio = fields.Selection([
|
||||
('radio_style_1', 'Radio Style 1'),
|
||||
('radio_style_2', 'Radio Style 2'),
|
||||
('radio_style_3', 'Radio Style 3'),
|
||||
('radio_style_4', 'Radio Style 4')],
|
||||
default="radio_style_1", string="Radio Styles")
|
||||
|
||||
popup = fields.Selection([
|
||||
('popup_style_1', 'popup Style 1'),
|
||||
('popup_style_2', 'popup Style 2'),
|
||||
('popup_style_3', 'popup Style 3'),
|
||||
('popup_style_4', 'popup Style 4')],
|
||||
default="popup_style_2", string="popup Styles")
|
||||
|
||||
chatter_position = fields.Selection([
|
||||
('chatter_right', 'Chatter Right'),
|
||||
('chatter_bottom', 'Chatter Bottom')],
|
||||
default="chatter_right", string="Chatter Position")
|
||||
|
||||
top_menu_position = fields.Selection([
|
||||
('top_menu_horizontal', 'Top Menu Horizontal'),
|
||||
('top_menu_vertical', 'Top Menu Vertical')],
|
||||
default="top_menu_vertical", string="Top Menu Position")
|
||||
|
||||
theme_style = fields.Selection([
|
||||
('biz_theme_rounded', 'Rounded Theme'),
|
||||
('biz_theme_standard', 'Standard Theme'),
|
||||
('biz_theme_square', 'Square Theme')],
|
||||
default="biz_theme_rounded", string="Theme Style")
|
||||
|
||||
attachment_in_tree_view = fields.Boolean(string="Show Attachement in tree view")
|
||||
|
||||
font_size = fields.Selection([
|
||||
('font_small', 'Font Small'),
|
||||
('font_medium', 'Font Medium'),
|
||||
('font_large', 'Font large')],
|
||||
default="font_medium", string="Font size")
|
||||
|
||||
loader_style = fields.Selection([
|
||||
('loader_style_1', 'Loader Style 1'),
|
||||
('loader_style_2', 'Loader Style 2'),
|
||||
('loader_style_3', 'Loader Style 3'),
|
||||
('loader_style_4', 'Loader Style 4'),
|
||||
('loader_style_5', 'Loader Style 5'),
|
||||
('loader_style_6', 'Loader Style 6'),
|
||||
('loader_style_7', 'Loader Style 7'),
|
||||
('loader_style_8', 'Loader Style 8'),
|
||||
('loader_style_9', 'Loader Style 9'),
|
||||
('loader_style_10', 'Loader Style 10'),],
|
||||
default="loader_style_10", string="Loader Styles")
|
||||
|
||||
font_family = fields.Selection([
|
||||
('lato', 'Lato'),
|
||||
('montserrat', 'Montserrat'),
|
||||
('open_sans', 'Open Sans'),
|
||||
('oswald', 'Oswald'),
|
||||
('raleway', 'Raleway'),
|
||||
('roboto', 'Roboto'),
|
||||
('poppins', 'Poppins'),
|
||||
('rubik', 'Rubik'),
|
||||
('inter', 'Inter'),
|
||||
('josefin_sans', 'Josefin Sans'),
|
||||
('varela_round', 'Varela Round'),
|
||||
('manrope', 'Manrope'),
|
||||
('Nunito_Sans', 'Nunito Sans')],
|
||||
default="rubik", string="Font Family")
|
||||
|
||||
list_view_density = fields.Selection([
|
||||
('list_comfortable', 'Comfortable'),
|
||||
('list_compact', 'Compact'),],
|
||||
default="list_comfortable", string="List View Density")
|
||||
|
||||
list_view_sticky_header = fields.Boolean(string="List view Sticky Header")
|
||||
14
spiffy_theme_backend/models/bookmark.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo Module Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class Bookmarklink(models.Model):
|
||||
_name = 'bookmark.link'
|
||||
_description = "Bookmark Link"
|
||||
|
||||
name = fields.Char("Name")
|
||||
title = fields.Char("Title")
|
||||
url = fields.Char("URL")
|
||||
user_id = fields.Many2one('res.users')
|
||||
15
spiffy_theme_backend/models/favorite_apps.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo Module Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class FavoriteApps(models.Model):
|
||||
_name = "favorite.apps"
|
||||
_description = "Favorite Apps"
|
||||
|
||||
name = fields.Char("Name")
|
||||
app_id = fields.Char("App Id")
|
||||
app_xmlid = fields.Char("App XML Id")
|
||||
app_actionid = fields.Char("App Action Id")
|
||||
user_id = fields.Many2one('res.users')
|
||||
31
spiffy_theme_backend/models/ir_http.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details
|
||||
|
||||
from odoo import api, models
|
||||
from odoo.http import request
|
||||
|
||||
class Http(models.AbstractModel):
|
||||
_inherit = 'ir.http'
|
||||
|
||||
def session_info(self):
|
||||
# Show company change option even if single company available
|
||||
is_bg_color = self.env.user.table_color
|
||||
res = super(Http, self).session_info()
|
||||
# user = request.env.user
|
||||
company = self.env.company
|
||||
|
||||
session_sid = request.session.sid
|
||||
if self.env.user.image_1920:
|
||||
image = self.env.user.image_1920.decode('utf-8')
|
||||
else:
|
||||
image = ''
|
||||
res.update({'bg_color':is_bg_color,'user_image':image,'session_sid':session_sid,'spiffy_installed':True})
|
||||
|
||||
if self.env.user.has_group('base.group_user'):
|
||||
res.update({
|
||||
"display_switch_company_menu": True,
|
||||
"prevent_auto_save_warning_msg": company.prevent_auto_save_warning if company.prevent_auto_save_warning else '',
|
||||
})
|
||||
|
||||
return res
|
||||
12
spiffy_theme_backend/models/ir_menu.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class IrUiMenu(models.Model):
|
||||
_inherit = "ir.ui.menu"
|
||||
|
||||
icon_img = fields.Image("Menu New Image")
|
||||
use_icon = fields.Boolean("Use Icon")
|
||||
icon_class_name = fields.Char("Icon Class Name")
|
||||
31
spiffy_theme_backend/models/ir_module.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details
|
||||
|
||||
from odoo import models
|
||||
from odoo.http import request
|
||||
|
||||
class Module(models.Model):
|
||||
_inherit = "ir.module.module"
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Return the action linked to an ir.actions.todo is there exists one that
|
||||
should be executed. Otherwise, redirect to /web
|
||||
"""
|
||||
Todos = self.env['ir.actions.todo']
|
||||
active_todo = Todos.search([('state', '=', 'open')], limit=1)
|
||||
if active_todo:
|
||||
return active_todo.action_launch()
|
||||
if request.env.user.table_color:
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self',
|
||||
'url': '/web?bg_color=True&tool_color_id=1',
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self',
|
||||
'url': '/web',
|
||||
}
|
||||
16
spiffy_theme_backend/models/multi_tab.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo Module Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class MultiTab(models.Model):
|
||||
_name = 'biz.multi.tab'
|
||||
_description = "Multi Tab"
|
||||
|
||||
name = fields.Char("App Name")
|
||||
url = fields.Char("URL")
|
||||
actionId = fields.Char("Action ID")
|
||||
menuId = fields.Char("Menu ID")
|
||||
user_id = fields.Many2one('res.users')
|
||||
menu_xmlid = fields.Char("XML ID Name")
|
||||
15
spiffy_theme_backend/models/pwa_shortcuts.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
class PWAshortcuts(models.Model):
|
||||
_name = 'pwa.shortcuts'
|
||||
_description = "PWA Shortcuts"
|
||||
|
||||
name = fields.Char("Name", required=True)
|
||||
short_name = fields.Char("Short Name", required=True)
|
||||
url = fields.Char("URL", required=True, default='/')
|
||||
description = fields.Char("Description", required=True)
|
||||
image_192_shortcut = fields.Binary('Image 192px', readonly=False)
|
||||
70
spiffy_theme_backend/models/res_company.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
import base64
|
||||
from odoo import api, http, fields, models, tools
|
||||
from odoo.http import request
|
||||
from odoo.modules.module import get_resource_path
|
||||
from odoo.tools.translate import _
|
||||
|
||||
class Company(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
tab_name = fields.Char(string="Backend Tab Name", default="Spiffy", readonly=False)
|
||||
backend_theme_level = fields.Selection([
|
||||
('user_level', 'User Level'),
|
||||
('global_level', 'Global Level')],
|
||||
default="user_level", required=True, string="Backend Theme Level", readonly=False)
|
||||
|
||||
login_page_style = fields.Selection([
|
||||
('login_style_1', 'Login Style 1'),
|
||||
('login_style_2', 'Login Style 2'),
|
||||
('login_style_3', 'Login Style 3'),
|
||||
('login_style_4', 'Login Style 4')],
|
||||
default="login_style_1", required=True, string="Login Styles", readonly=False)
|
||||
|
||||
login_page_background_img = fields.Binary('Login Background Image', readonly=False, store=True)
|
||||
login_page_background_color = fields.Char('Login Background Color', default="#f2f6ff", readonly=False)
|
||||
login_page_text_color = fields.Char('Login Text Color', default="#777777", readonly=False)
|
||||
show_bg_image = fields.Boolean(string='Add Login Background Image', readonly=False)
|
||||
|
||||
def get_login_page_data(self):
|
||||
admin_users = request.env['res.users'].sudo().search([
|
||||
('groups_id','in',request.env.ref('base.user_admin').id),
|
||||
('backend_theme_config','!=',False),
|
||||
], order="id asc", limit=1)
|
||||
admin_config = False
|
||||
if admin_users:
|
||||
admin_config = admin_users.backend_theme_config
|
||||
|
||||
if admin_config:
|
||||
config_vals = admin_config
|
||||
else:
|
||||
config_vals = request.env['backend.config'].sudo().search([], order="id asc", limit=1)
|
||||
|
||||
values = {
|
||||
'config_vals': config_vals,
|
||||
}
|
||||
return values
|
||||
|
||||
backend_menubar_logo = fields.Binary(
|
||||
string="Menubar Logo", readonly=False)
|
||||
backend_menubar_logo_icon = fields.Binary(
|
||||
string="Menubar Logo Icon", readonly=False)
|
||||
|
||||
enable_pwa = fields.Boolean(string='Enable PWA', readonly=False)
|
||||
app_name_pwa = fields.Char('App Name', readonly=False, default='Spiffy')
|
||||
short_name_pwa = fields.Char('Short Name', readonly=False, default='Spiffy')
|
||||
description_pwa = fields.Char('App Description', readonly=False, default='Spiffy')
|
||||
image_192_pwa = fields.Binary('Image 192px', readonly=False, store=True)
|
||||
image_512_pwa = fields.Binary('Image 512px', readonly=False, store=True)
|
||||
start_url_pwa = fields.Char('App Start Url', readonly=False, default='/web')
|
||||
background_color_pwa = fields.Char('Background Color', readonly=False, default='#0097a7')
|
||||
theme_color_pwa = fields.Char('Theme Color', readonly=False, default='#0097a7')
|
||||
pwa_shortcuts_ids = fields.Many2many('pwa.shortcuts', string='PWA Shortcuts')
|
||||
|
||||
spiffy_toobar_color = fields.Char('Toolbar Color', readonly=False, default='#0097a7')
|
||||
prevent_auto_save = fields.Boolean(string='Prevent Auto Save', readonly=False)
|
||||
|
||||
prevent_auto_save_warning = fields.Char('Auto Save Warning', translate=True, default="Autosave is disabled, Click on save button.", readonly=False)
|
||||
69
spiffy_theme_backend/models/res_config_setting.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
# Developed by Bizople Solutions Pvt. Ltd.
|
||||
|
||||
from odoo.modules.module import get_resource_path
|
||||
from odoo import api, http, fields, models, tools, _
|
||||
from odoo.http import request
|
||||
import base64
|
||||
|
||||
class ResConfig(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
spiffy_favicon = fields.Binary(related='company_id.favicon',
|
||||
string="Backend Tab Favicon", readonly=False)
|
||||
tab_name = fields.Char(related='company_id.tab_name',
|
||||
string="Backend Tab Name", readonly=False)
|
||||
backend_theme_level = fields.Selection(
|
||||
related='company_id.backend_theme_level', string="Backend Theme Level", required=True, readonly=False)
|
||||
|
||||
login_page_style = fields.Selection(
|
||||
related='company_id.login_page_style', string="Login Styles", required=True, readonly=False)
|
||||
|
||||
login_page_background_img = fields.Binary(
|
||||
related='company_id.login_page_background_img', string="Login Background Image", readonly=False)
|
||||
|
||||
login_page_background_color = fields.Char(
|
||||
related='company_id.login_page_background_color', string='Login Background Color', readonly=False)
|
||||
|
||||
login_page_text_color = fields.Char(
|
||||
related='company_id.login_page_text_color', string='Login Text Color', readonly=False)
|
||||
|
||||
show_bg_image = fields.Boolean(
|
||||
related='company_id.show_bg_image', string='Add Login Background Image', readonly=False)
|
||||
|
||||
backend_menubar_logo = fields.Binary(
|
||||
related='company_id.backend_menubar_logo', string="Menubar Logo", readonly=False)
|
||||
|
||||
backend_menubar_logo_icon = fields.Binary(
|
||||
related='company_id.backend_menubar_logo_icon', string="Menubar Logo Icon", readonly=False)
|
||||
|
||||
# Fields for PWA start
|
||||
enable_pwa = fields.Boolean(
|
||||
string='Enable PWA', related='company_id.enable_pwa', readonly=False,)
|
||||
app_name_pwa = fields.Char(
|
||||
'App Name', related='company_id.app_name_pwa', readonly=False)
|
||||
short_name_pwa = fields.Char(
|
||||
'Short Name', related='company_id.short_name_pwa', readonly=False)
|
||||
description_pwa = fields.Char(
|
||||
'App Description', related='company_id.description_pwa', readonly=False)
|
||||
image_192_pwa = fields.Binary(
|
||||
'Image 192px', related='company_id.image_192_pwa', readonly=False)
|
||||
image_512_pwa = fields.Binary(
|
||||
'Image 512px', related='company_id.image_512_pwa', readonly=False)
|
||||
start_url_pwa = fields.Char(
|
||||
'App Start Url', related='company_id.start_url_pwa', readonly=False)
|
||||
background_color_pwa = fields.Char(
|
||||
'Background Color', related='company_id.background_color_pwa', readonly=False)
|
||||
theme_color_pwa = fields.Char(
|
||||
'Theme Color', related='company_id.theme_color_pwa', readonly=False)
|
||||
pwa_shortcuts_ids = fields.Many2many(
|
||||
related='company_id.pwa_shortcuts_ids', readonly=False)
|
||||
# Fields for PWA end
|
||||
|
||||
spiffy_toobar_color = fields.Char('Toolbar Color', related='company_id.spiffy_toobar_color', readonly=False)
|
||||
|
||||
prevent_auto_save = fields.Boolean(
|
||||
related='company_id.prevent_auto_save', string='Prevent Auto Save ?', readonly=False)
|
||||
|
||||
prevent_auto_save_warning = fields.Char('Auto Save Warning', related='company_id.prevent_auto_save_warning', readonly=False)
|
||||
27
spiffy_theme_backend/models/res_users.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo Module Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class User(models.Model):
|
||||
_inherit = "res.users"
|
||||
|
||||
app_ids = fields.One2many('favorite.apps', 'user_id',string="Favorite Apps")
|
||||
bookmark_ids = fields.One2many('bookmark.link', 'user_id',string="Bookmark Links")
|
||||
dark_mode = fields.Boolean(string="Is dark Mode Active", default=False)
|
||||
vertical_sidebar_pinned = fields.Boolean(string="Pinned Sidebar", default=True)
|
||||
backend_theme_config = fields.Many2one('backend.config', string="Backend Config", copy=False)
|
||||
multi_tab_ids = fields.One2many('biz.multi.tab', 'user_id', string="Multi Tabs")
|
||||
enable_todo_list = fields.Boolean(string="Enable To Do List", default=True)
|
||||
todo_list_ids = fields.One2many('todo.list', 'user_id', string="To Do List")
|
||||
table_color = fields.Boolean(string="Is Body Color")
|
||||
tool_color_id = fields.Char(string="Tool Color")
|
||||
|
||||
@property
|
||||
def SELF_READABLE_FIELDS(self):
|
||||
return super().SELF_READABLE_FIELDS + ['enable_todo_list']
|
||||
|
||||
@property
|
||||
def SELF_WRITEABLE_FIELDS(self):
|
||||
return super().SELF_WRITEABLE_FIELDS + ['enable_todo_list']
|
||||
30
spiffy_theme_backend/models/to_do_list.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo Module Developed by Bizople Solutions Pvt. Ltd.
|
||||
# See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class ToDoList(models.Model):
|
||||
_name = "todo.list"
|
||||
_description = "To Do List"
|
||||
_order = 'write_date desc, create_date desc'
|
||||
|
||||
def _default_sequence(self):
|
||||
return (self.search([], order="sequence desc", limit=1).sequence or 0) + 1
|
||||
|
||||
sequence = fields.Integer('sequence', default=_default_sequence)
|
||||
name = fields.Char("Title")
|
||||
description = fields.Html('Description')
|
||||
# marked_done = fields.Boolean("Done?")
|
||||
user_id = fields.Many2one('res.users', string="User")
|
||||
create_date = fields.Datetime(string="Created on")
|
||||
write_date = fields.Datetime("Last Updated On", index=True)
|
||||
note_color_pallet = fields.Selection([
|
||||
('pallet_1', 'Pallet 1'),
|
||||
('pallet_2', 'Pallet 2'),
|
||||
('pallet_3', 'Pallet 3'),
|
||||
('pallet_4', 'Pallet 4'),
|
||||
('pallet_5', 'Pallet 5'),
|
||||
('pallet_6', 'Pallet 6'),
|
||||
('pallet_7', 'Pallet 7'),
|
||||
],default="pallet_1", string="Notes Color Pallets", required=True)
|
||||
7
spiffy_theme_backend/security/ir.model.access.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_favorite_apps,access_favorite_apps,model_favorite_apps,base.group_user,1,0,0,0
|
||||
access_bookmark_link,access_bookmark_link,model_bookmark_link,base.group_user,1,0,0,0
|
||||
access_backend_config,access_backend_config,model_backend_config,base.group_user,1,1,1,0
|
||||
access_pwa_shortcuts,access_pwa_shortcuts,model_pwa_shortcuts,,1,1,1,1
|
||||
access_biz_multi_tab,access_biz_multi_tab,model_biz_multi_tab,base.group_user,1,0,0,0
|
||||
access_todo_list,access_todo_list,model_todo_list,,1,1,1,1
|
||||
|
BIN
spiffy_theme_backend/static/description/3d-icon-pack.jpg
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
spiffy_theme_backend/static/description/Bizople-logo-black.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
spiffy_theme_backend/static/description/Bizople-partner-logo.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
spiffy_theme_backend/static/description/Index-main-banner.jpg
Normal file
|
After Width: | Height: | Size: 387 KiB |
BIN
spiffy_theme_backend/static/description/Spiffy-full-white.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
spiffy_theme_backend/static/description/app-drawer-bg-image.png
Normal file
|
After Width: | Height: | Size: 597 KiB |
BIN
spiffy_theme_backend/static/description/app-drawer.jpg
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
spiffy_theme_backend/static/description/app-icon-config.gif
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
spiffy_theme_backend/static/description/bizople-icon.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 20 KiB |
BIN
spiffy_theme_backend/static/description/bizople-white-logo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
spiffy_theme_backend/static/description/bookmark.gif
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
spiffy_theme_backend/static/description/branding.gif
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 686 KiB |
BIN
spiffy_theme_backend/static/description/darklight-pin-unpin.gif
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
spiffy_theme_backend/static/description/drawer-global-search.gif
Normal file
|
After Width: | Height: | Size: 17 MiB |
BIN
spiffy_theme_backend/static/description/fav-apps.gif
Normal file
|
After Width: | Height: | Size: 7.6 MiB |
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 233 KiB |
BIN
spiffy_theme_backend/static/description/feature-banner.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
|
After Width: | Height: | Size: 80 KiB |
BIN
spiffy_theme_backend/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
spiffy_theme_backend/static/description/imac-header.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
spiffy_theme_backend/static/description/index-main-banner.gif
Normal file
|
After Width: | Height: | Size: 8.7 MiB |
BIN
spiffy_theme_backend/static/description/index-responsive.jpg
Normal file
|
After Width: | Height: | Size: 142 KiB |
654
spiffy_theme_backend/static/description/index.html
Normal file
@@ -0,0 +1,654 @@
|
||||
<section class="" style=" border-radius: 16px;">
|
||||
<section class="mb-4 bizople_partner_logo" style="padding:35px; background-color: #1b1b1b; border-radius: 16px;">
|
||||
<div class="row justify-content-md-between justify-content-center align-items-center py-2 mx-0">
|
||||
<div class="col-md-3">
|
||||
<a href="https://www.bizople.com/" style="text-decoration:none;">
|
||||
<img class="img img-fluid" style="text-align: center;" src="bizople-white-logo.png"></img>
|
||||
</a>
|
||||
</div>
|
||||
<div class="s_btn text-center pt0 col-md-6" data-name="Button">
|
||||
<a href="#" class="mx-1 btn btn-primary btn-lg" style="background-color: #0097a7; border: 1px solid #0097a7; color:white; font-family: Montserrat;"> <i class="fa fa-check-square-o"></i> Community</a>
|
||||
|
||||
<a href="mailto:info@bizople.com" class="mx-1 btn btn-primary btn-lg" style="background-color: #0097a7; border: 1px solid #0097a7; color:white; font-family: Montserrat;">Email Us</a>
|
||||
|
||||
<!-- <a href="skype:live:bizoples?chat" class="mx-1 btn btn-primary btn-lg" style="background-color: #0097a7; border: 1px solid #0097a7; color:white; font-family: Montserrat;">Skype</a> -->
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<img class="img img-fluid" style="height: 80px; text-align: center;" src="odoo_ready_partner_logo.png"></img>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="index-main-banner text-center" >
|
||||
<div class="gif-image">
|
||||
<img class="img img-fluid" style="text-align:center; border-radius: 16px;" src="Index-main-banner.jpg"/>
|
||||
</div>
|
||||
|
||||
<img class="img img-fluid shadow-sm my-4" style="text-align:center; border-radius: 16px;" src="spiffy-mobile-app-banner.jpg"/>
|
||||
|
||||
<div class="main-feature-banner p-3 p-md-5 text-center">
|
||||
<h2 class="mb-5 w-lg-75 mx-auto" style="font-size: calc(min(40px, 5vw)); color: #0081a5;">Enhance your Productivity with the Advance Key Features</h2>
|
||||
<img class="img img-fluid" style="text-align:center" src="feature-banner-no-split-view.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="my-4 index-enterprise">
|
||||
<div class="spiffy-enterprise-banner text-center">
|
||||
<a href="https://apps.odoo.com/apps/themes/16.0/spiffy_theme_backend_ent/">
|
||||
<img class="img img-fluid" style="text-align:center; border-radius: 16px;" src="spiffy-enterprise.png" />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="index-tabs mt-4" style=" border-radius: 16px;">
|
||||
<ul class="nav nav-tabs justify-content-center bg-white mb-5 d-none" id="myTab" role="tablist" style="border-bottom:1px solid #CFCFCF;">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="spiffy-main-features" data-bs-toggle="tab" href="#main-features" role="tab" style="color:#1b1b1b;">Features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="spiffy-faq" data-bs-toggle="tab" href="#faq" role="tab" style="color:#1b1b1b;">FAQs</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="spiffy-release-note" data-bs-toggle="tab" href="#release-note" role="tab" style="color:#1b1b1b;">Release Notes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="spiffy-contact" data-bs-toggle="tab" href="#contact" role="tab" style="color:#1b1b1b;">Contact Us</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="spiffy-index-tabs">
|
||||
<div class="tab-pane fade show active" id="main-features" role="tabpanel">
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="theme-style.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="theme-color.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="index-responsive.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="spiffy-index-pwa.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="rtl-support.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="multi-tab.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="3d-icon-pack.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="notes.gif"/>
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="list-density.gif"/>
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="list-sticky-header-footer.gif"/>
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="modal-drag-resize.gif"/>
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="prevent-auto-save.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="chatter-attachment-in-list.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="app-drawer.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="drawer-global-search.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="top-menu-position.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="darklight-pin-unpin.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="branding.gif"/>
|
||||
|
||||
<!-- <img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="split-view.gif"/> -->
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="zoom-fullscreen.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="bookmark.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="fav-apps.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="app-icon-config.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="refresh-btn.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="separator-tab-popup-styles.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="loaders-fontfamily.gif"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="fontsize-radio-checkbox.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="loginpage.gif"/>
|
||||
|
||||
<section class="index-alert mt-5">
|
||||
<div class="s_alert w-100 alert-delta d-md-flex align-items-center justify-content-center p-3 shadow-sm" style="border-radius: 16px; color: #2f4752; background-color: #dee7ec; border-color: #d1dee4;">
|
||||
<i class="fa fa-2x fa-info border rounded-circle text-center" style="border-color: #121212 !important; min-width: 50px; width: 50px; height: 50px; line-height: 50px;"></i>
|
||||
<div class="s_alert_content ml-3 pt-3 pt-md-0">
|
||||
<p class="" style="font-size: calc(min(18px, 4vw));">
|
||||
<b>Note:</b> <br/> If you are using Website App and want to have web like login page design, you can purchase the <a href="https://apps.odoo.com/apps/modules/16.0/spiffy_website_login/" class="">Website Login Add-on module</a> from the store
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="index-spiffy-modules-link my-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="spiffy-ce-module">
|
||||
<div class="index-spiffy-modules-title text-center mb-3">
|
||||
<a class="" href="https://apps.odoo.com/apps/modules/16.0/spiffy_website_login/">
|
||||
<h2 class="mb-0 mx-auto" style="font-size: 23px; color: #0097a7;">Spiffy Backend Theme - Website Login Addon</h2>
|
||||
</a>
|
||||
</div>
|
||||
<a class="" href="https://apps.odoo.com/apps/modules/16.0/spiffy_website_login/">
|
||||
<img class="img img-fluid" src="spiffy_website_login_addon.png"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="lang-company-debug.jpg"/>
|
||||
|
||||
<img class="img img-fluid shadow-sm mb-4" style="text-align:center; border-radius: 16px;" src="user-level.jpg"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="index-all-features" style=" border-radius: 16px;">
|
||||
<div class="all-feature-title text-center">
|
||||
<h2 class="mb-5 w-lg-75 mx-auto" style="font-size: calc(min(40px, 5vw)); color: #0097a7;">All Features</h2>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<!-- DUMMY COL FOR FEATURE PILL -->
|
||||
<!-- <div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<img class="img img-fluid" style="width: 40px; height: 40px; object-fit: contain;" src="feature-brush-line.png" />
|
||||
<span class="" style="font-size: 24px; color: #0097A7;"">1.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">3 in 1 Theme Styles</span>
|
||||
</span>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">1.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">3 in 1 Theme Styles</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">2.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Chatter Box Position</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;"">3.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Tree-Form Split View</span>
|
||||
</span>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">3.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Attachment in List View</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">4.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Vertical/Horizontal Menu Style</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">5.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">4 Seprator Styles</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;"">6.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">4 Tab Style</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;"">7.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">4 Checkbox Style</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;"">8.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">4 Radio Style</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;"">9.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">4 Popup Animations</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">10.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">9 Theme Color Pallets</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">11.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Custom Theme Color option</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">12.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">9 App Drawer Color Pallet</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">13.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Custom App Drawer Color</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">14.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">13 Unique Font Styles</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">15.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Font Sizes</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">16.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">10 Loading Icons</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">17.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">4 Login Page Designs</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">18.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Configurable App Icons</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">19.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Global Search</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">20.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Full Screen</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">21.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Zoom In / Zoom Out</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">22.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Bookmarks</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">23.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Dark/Light Mode</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">24.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Language Selector</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">25.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Company Selector</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">26.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Lock/Unlock Sidebar</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">27.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Debug Activator</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">28.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">RTL Supported</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">29.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">User Access (User/Global)</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">30.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Greetings on Menubar</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">31.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Custom Branding</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">32.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">PWA with Shortcuts</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">33.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Favorite App Island</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">34.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Refresh Button</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">35.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Multiple Tab</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">36.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Notes</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">37.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">List/Tree View Density</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">38.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">List/Tree View Sticky Header & Footer</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">39.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Prevent Auto Save</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">40.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Modal Draggable & Resizable</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="col-md-6 col-lg-4 col-xl-3 px-2 my-2">
|
||||
<div class="align-content-center d-flex p-3 rounded-pill shadow-sm" style="font-size: 16px; background-color: #0097A7; color: #fff;">
|
||||
<span style="min-width: 50px; height: 50px; line-height: 50px;" class="bg-white rounded-circle shadow-sm text-center">
|
||||
<span class="" style="font-size: 24px; color: #0097A7;">36.</span>
|
||||
</span>
|
||||
<span class="align-content-center d-flex flex-column flex-fill px-3 my-auto">
|
||||
<span class="">Tree-Form Split View</span>
|
||||
</span>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="index-services-support mt-5" style=" border-radius: 16px;">
|
||||
<p class="mb-4" style="font-size: 17px; text-align: center;">
|
||||
<b>Note:</b> This Product is developed and tested with Odoo Addons
|
||||
</p>
|
||||
<section class="align-items-center g-0 justify-content-center mb-4 row py-5 px-3 px-md-5"
|
||||
style="background-color: #0e0e0e; color: #fff; border-radius: 16px;">
|
||||
<div class="col-md-7">
|
||||
<div>
|
||||
<b style="font-size: 22px;">Spiffy Mobile App Note:</b>
|
||||
<br/>
|
||||
<ul class="pt-2" style="font-size: 16px;">
|
||||
<li>Spiffy Mobile App is an Android and iOS application works with the Spiffy Backend Theme.</li>
|
||||
<li>It is a complementary / FREE application with the Spiffy Backend Theme and it has no relation with the theme working.</li>
|
||||
<li>The Application works well but is not satisfying the customer's specific needs it would not be considered to claim a refund for the Spiffy Backend Theme.</li>
|
||||
<li>
|
||||
Push Notification and 2-Factor Authentication functionalities are in process and will be available in the future version of Spiffy mobile Application.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 text-center">
|
||||
<img class="img img-fluid" width="300" height="300" src="spiffy-mobile-app-icon.png"/>
|
||||
</div>
|
||||
</section>
|
||||
<img class="img img-fluid mb-4" src="support_banner.jpg" style="border-radius:6px;"/>
|
||||
<img class="img img-fluid" src="service-banner.jpg" style="border-radius:6px;"/>
|
||||
</section>
|
||||
|
||||
<section class="features-changelog-main mt-5 p-5" style="background-color: white; border-radius: 16px; box-shadow: 0 0px 10px rgba(0, 0, 0, 0.075) !important;">
|
||||
<section id="changelog">
|
||||
<div class="log-title">
|
||||
<p style="font-size: 30px;">Release Notes</p>
|
||||
</div>
|
||||
<div class="log-details">
|
||||
<h3 class="mb-3 d-flex align-items-center w-100" style="font-size: 24px;color: #1b1b1b;font-weight: 600;"><span class="text-info">v2.0</span></h3>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block badge badge-success" style="color: #ffffff;font-size: 14px; vertical-align: middle;">New</span>Compatibility with Spiffy: Odoo Mobile Application (android/ios)</p>
|
||||
|
||||
<h3 class="mb-3 d-flex align-items-center w-100" style="font-size: 24px;color: #1b1b1b;font-weight: 600;"><span class="text-info">v16.0.0.4</span></h3>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block badge badge-success" style="color: #ffffff;font-size: 14px; vertical-align: middle;">New</span>New Features: Notes, List/Tree View Density, List/Tree View Sticky Header & Footer, Prevent Auto Save, Modal Draggable & Resizable.</p>
|
||||
|
||||
<h3 class="mb-3 d-flex align-items-center w-100" style="font-size: 24px;color: #1b1b1b;font-weight: 600;"><span class="text-info">v16.0.0.3</span></h3>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block badge badge-warning" style="color: #ffffff;font-size: 14px; vertical-align: middle;">Fixed</span>Improvements on Login Styles and Design.</p>
|
||||
|
||||
<h3 class="mb-3 d-flex align-items-center w-100" style="font-size: 24px;color: #1b1b1b;font-weight: 600;"><span class="text-info">v16.0.0.2</span></h3>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block badge badge-warning" style="color: #ffffff;font-size: 14px; vertical-align: middle;">Fixed</span>Minor bug fixes and improvements.</p>
|
||||
|
||||
<h3 class="mb-3 d-flex align-items-center w-100" style="font-size: 24px;color: #1b1b1b;font-weight: 600;"><span class="text-info">v16.0.0.1</span></h3>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block badge badge-success" style="color: #ffffff;font-size: 14px; vertical-align: middle;">New</span>Multiple Tab</p>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block badge badge-warning" style="color: #ffffff;font-size: 14px; vertical-align: middle;">Fixed</span>Minor bug fixes and improvements.</p>
|
||||
|
||||
<h3 class="mb-3 d-flex align-items-center w-100" style="font-size: 24px;color: #1b1b1b;font-weight: 600;"><span class="text-info">v16.0.0.0</span></h3>
|
||||
<p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;">Initial Release</p>
|
||||
|
||||
<!-- badge badge-warning FOR FIXES -->
|
||||
<!-- badge badge-success FOR NEW -->
|
||||
<!-- badge badge-info FOR UPDATES -->
|
||||
|
||||
<!-- for update tag use this -->
|
||||
<!-- <p class="d-flex align-items-center w-100" style="color: #1b1b1b;font-size: 18px;"><span class="mr-2 d-inline-block o_gradient" style="color: #ffffff;font-size: 14px; vertical-align: middle;">Update</span>Initial Release</p> -->
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
BIN
spiffy_theme_backend/static/description/lang-company-debug.jpg
Normal file
|
After Width: | Height: | Size: 233 KiB |
BIN
spiffy_theme_backend/static/description/list-density.gif
Normal file
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 4.6 MiB |
BIN
spiffy_theme_backend/static/description/loaders-fontfamily.gif
Normal file
|
After Width: | Height: | Size: 753 KiB |
BIN
spiffy_theme_backend/static/description/loginpage.gif
Normal file
|
After Width: | Height: | Size: 143 KiB |
BIN
spiffy_theme_backend/static/description/mail-send-line.png
Normal file
|
After Width: | Height: | Size: 841 B |
BIN
spiffy_theme_backend/static/description/modal-drag-resize.gif
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
spiffy_theme_backend/static/description/multi-tab.gif
Normal file
|
After Width: | Height: | Size: 15 MiB |
BIN
spiffy_theme_backend/static/description/notes.gif
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
|
After Width: | Height: | Size: 11 KiB |
BIN
spiffy_theme_backend/static/description/phone-line.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
spiffy_theme_backend/static/description/prevent-auto-save.jpg
Normal file
|
After Width: | Height: | Size: 184 KiB |
BIN
spiffy_theme_backend/static/description/refresh-btn.gif
Normal file
|
After Width: | Height: | Size: 540 KiB |
BIN
spiffy_theme_backend/static/description/rtl-support.jpg
Normal file
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 100 KiB |
BIN
spiffy_theme_backend/static/description/service-banner.jpg
Normal file
|
After Width: | Height: | Size: 490 KiB |
BIN
spiffy_theme_backend/static/description/skype-line.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
spiffy_theme_backend/static/description/spiffy-enterprise.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
spiffy_theme_backend/static/description/spiffy-index-pwa.jpg
Normal file
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 200 KiB |
BIN
spiffy_theme_backend/static/description/spiffy-qr-code.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
spiffy_theme_backend/static/description/spiffy_cover.png
Normal file
|
After Width: | Height: | Size: 458 KiB |
BIN
spiffy_theme_backend/static/description/spiffy_screenshot.gif
Normal file
|
After Width: | Height: | Size: 6.9 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 55 KiB |
BIN
spiffy_theme_backend/static/description/split-view.gif
Normal file
|
After Width: | Height: | Size: 4.1 MiB |
BIN
spiffy_theme_backend/static/description/support_banner.jpg
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
spiffy_theme_backend/static/description/theme-color.gif
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
spiffy_theme_backend/static/description/theme-style.gif
Normal file
|
After Width: | Height: | Size: 5.8 MiB |
BIN
spiffy_theme_backend/static/description/top-menu-position.gif
Normal file
|
After Width: | Height: | Size: 3.6 MiB |
BIN
spiffy_theme_backend/static/description/user-level.jpg
Normal file
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 16 KiB |
BIN
spiffy_theme_backend/static/description/zoom-fullscreen.gif
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
spiffy_theme_backend/static/src/image/backend_theme_icon.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
spiffy_theme_backend/static/src/image/checked.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
spiffy_theme_backend/static/src/image/circle.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
spiffy_theme_backend/static/src/image/close.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
spiffy_theme_backend/static/src/image/download (1).png
Normal file
|
After Width: | Height: | Size: 200 B |
1
spiffy_theme_backend/static/src/image/download.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 10'><defs><style>.cls-1{opacity:0.3;}</style></defs><path class='cls-1' d='M2.68.82h0a.27.27,0,0,0-.36,0h0L.82,2.32a.27.27,0,0,0,0,.36.27.27,0,0,0,.36,0L2.25,1.6V9a.25.25,0,0,0,.5,0V1.6L3.82,2.68a.27.27,0,0,0,.36,0,.27.27,0,0,0,0-.36Z'/><path class='cls-1' d='M8.18,7.32a.27.27,0,0,0-.36,0L6.75,8.4V1a.25.25,0,0,0-.5,0V8.4L5.18,7.32a.25.25,0,0,0-.36.36l1.5,1.5a.27.27,0,0,0,.36,0l1.5-1.5A.27.27,0,0,0,8.18,7.32Z'/></svg>
|
||||
|
After Width: | Height: | Size: 476 B |
BIN
spiffy_theme_backend/static/src/image/iconoff.png
Normal file
|
After Width: | Height: | Size: 633 B |
BIN
spiffy_theme_backend/static/src/image/iconon.png
Normal file
|
After Width: | Height: | Size: 743 B |
BIN
spiffy_theme_backend/static/src/image/icons8-light-50.png
Normal file
|
After Width: | Height: | Size: 852 B |
BIN
spiffy_theme_backend/static/src/image/icons8-light-on-50.png
Normal file
|
After Width: | Height: | Size: 901 B |
BIN
spiffy_theme_backend/static/src/image/list_comfortable.png
Normal file
|
After Width: | Height: | Size: 976 B |
BIN
spiffy_theme_backend/static/src/image/list_compact.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
spiffy_theme_backend/static/src/image/loader_1.gif
Normal file
|
After Width: | Height: | Size: 79 KiB |
19
spiffy_theme_backend/static/src/image/loader_1.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto; animation-play-state: running; animation-delay: 0s;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
|
||||
<circle cx="84" cy="50" r="10" fill="#399ddb" style="animation-play-state: running; animation-delay: 0s;">
|
||||
<animate attributeName="r" repeatCount="indefinite" dur="0.25s" calcMode="spline" keyTimes="0;1" values="10;0" keySplines="0 0.5 0.5 1" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
<animate attributeName="fill" repeatCount="indefinite" dur="1s" calcMode="discrete" keyTimes="0;0.25;0.5;0.75;1" values="#399ddb;#005488;#0078c2;#0085d7;#399ddb" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
</circle><circle cx="16" cy="50" r="10" fill="#399ddb" style="animation-play-state: running; animation-delay: 0s;">
|
||||
<animate attributeName="r" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
<animate attributeName="cx" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
</circle><circle cx="50" cy="50" r="10" fill="#0085d7" style="animation-play-state: running; animation-delay: 0s;">
|
||||
<animate attributeName="r" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.25s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
<animate attributeName="cx" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.25s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
</circle><circle cx="84" cy="50" r="10" fill="#0078c2" style="animation-play-state: running; animation-delay: 0s;">
|
||||
<animate attributeName="r" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.5s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
<animate attributeName="cx" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.5s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
</circle><circle cx="16" cy="50" r="10" fill="#005488" style="animation-play-state: running; animation-delay: 0s;">
|
||||
<animate attributeName="r" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.75s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
<animate attributeName="cx" repeatCount="indefinite" dur="1s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.75s" style="animation-play-state: running; animation-delay: 0s;"></animate>
|
||||
</circle>
|
||||
<!-- [ldio] generated by https://loading.io/ --></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |