[ADD] theme_prime, droggol_theme_common: v14

This commit is contained in:
Abdurrahman Saber 2025-04-29 09:22:39 +03:00
parent 6607a679d1
commit ba94f7f8b8
884 changed files with 26908 additions and 34212 deletions

View File

@ -1,7 +1,7 @@
Most of the files are Most of the files are
Copyright (c) 2019 - present Droggol Infotech Private Limited. Copyright (c) 2019 - present Droggol.
Some javascript files might be from from third Some javascript files might be from from third
parties libraries. In that case the original parties libraries. In that case the original

View File

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from . import controllers
from . import models from . import models
from . import deprecated

View File

@ -1,66 +1,51 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
{ {
'name': 'Droggol Theme Common', 'name': 'Droggol Theme Common',
'description': 'Droggol Theme Common', 'description': 'Droggol Theme Common',
'category': 'eCommerce', 'category': 'eCommerce',
'version': '16.0.0.0.8', 'version': '14.0.0.3.8',
'depends': [ 'depends': [
'sale_product_configurator', 'sale_product_configurator',
'website_sale_comparison', 'website_sale_comparison',
'website_sale_wishlist', 'website_sale_wishlist',
'website_sale_stock', 'website_sale_stock',
'website_sale_stock_wishlist',
], ],
'license': 'OPL-1', 'license': 'OPL-1',
'author': 'Droggol Infotech Private Limited', 'author': 'Droggol',
'company': 'Droggol Infotech Private Limited', 'company': 'Droggol',
'maintainer': 'Droggol Infotech Private Limited', 'maintainer': 'Droggol',
'website': 'https://www.droggol.com/', 'website': 'https://www.droggol.com/',
'price': 10.00, 'price': 15.00,
'currency': 'USD', 'currency': 'USD',
'live_test_url': '', 'live_test_url': '',
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'deprecated/ir.model.access.csv', 'data/groups.xml',
'views/templates.xml', 'views/assets.xml',
'views/backend_templates.xml',
'views/dr_config_template.xml',
# Backend # Backend
'views/backend/menu_label.xml', 'views/backend/menu_label.xml',
'views/backend/website_menu.xml', 'views/backend/website_menu.xml',
'views/backend/product_brand.xml',
'views/backend/product_label.xml', 'views/backend/product_label.xml',
'views/backend/product_tags.xml',
'views/backend/product_template.xml', 'views/backend/product_template.xml',
'views/backend/product_attribute.xml', 'views/backend/product_attribute.xml',
'views/backend/product_brand.xml',
'views/backend/dr_website_content.xml',
'views/backend/product_pricelist.xml', 'views/backend/product_pricelist.xml',
'views/backend/pwa_shortcuts.xml', 'views/backend/pwa_shortcuts.xml',
'views/backend/res_config_settings.xml', 'views/backend/res_config_settings.xml',
'views/backend/dr_theme_config.xml', 'views/backend/dr_config.xml',
'views/backend/category_label.xml', 'views/backend/category_label.xml',
'views/backend/product_category.xml', 'views/backend/product_category.xml',
'views/backend/website.xml',
# Snippets
'views/snippets/s_mega_menu.xml',
], ],
'assets': { 'qweb': [
'web.assets_frontend': [ 'static/src/xml/backend/list_view_brand.xml',
'droggol_theme_common/static/src/scss/variants.scss', ],
],
'web.assets_backend': [
'droggol_theme_common/static/src/scss/variants.scss',
'droggol_theme_common/static/src/js/components/*.xml',
'droggol_theme_common/static/src/js/hooks.js',
],
'website.assets_editor': [
'droggol_theme_common/static/src/js/components/*.js',
'droggol_theme_common/static/src/js/components/*.scss',
'droggol_theme_common/static/src/js/navbar/*.js',
]
},
} }

View File

@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from . import main

View File

@ -1,12 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import http
from odoo.http import request
class DroggolThemeCommon(http.Controller):
@http.route(['/droggol_theme_common/design_content/<model("dr.website.content"):content>'], type='http', website=True, auth='user')
def design_content(self, content, **post):
return request.render('droggol_theme_common.design_content', {'content': content, 'no_header': True, 'no_footer': True})

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="base.group_user" model="res.groups">
<field name="implied_ids" eval="[(4, ref('product.group_product_variant'))]"/>
</record>
</odoo>

View File

@ -1,8 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
# [Files will be removed in a future version]
# Contains deprecated fields and models
from . import deprecated_v16
from . import deprecated_v15

View File

@ -1,66 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import fields, models
from odoo.tools.translate import html_translate
class DrProductBrand(models.Model):
_name = 'dr.product.brand'
_inherit = ['website.multi.mixin']
_description = 'Product Brand'
_order = 'sequence,id'
name = fields.Char(required=True, translate=True)
description = fields.Char(translate=True)
image = fields.Binary()
sequence = fields.Integer(string='Sequence')
active = fields.Boolean(default=True)
class DrProductOffer(models.Model):
_name = 'dr.product.offer'
_description = 'Product Offers'
_order = 'sequence,id'
name = fields.Char(string='Title', required=True, translate=True)
description = fields.Char(string='Description', required=True, translate=True)
icon = fields.Char(default='list')
sequence = fields.Integer(string='Sequence')
dialog_content = fields.Html(sanitize_attributes=False, translate=html_translate, sanitize_form=False)
product_id = fields.Many2one('product.template')
tag_id = fields.Many2one('dr.product.tags')
class DrProductTabs(models.Model):
_name = 'dr.product.tabs'
_description = 'Product Tabs'
_order = 'sequence,id'
name = fields.Char(string='Title', required=True, translate=True)
icon = fields.Char(default='list')
content = fields.Html(sanitize_attributes=False, translate=html_translate, sanitize_form=False)
sequence = fields.Integer(string='Sequence')
product_id = fields.Many2one('product.template')
tag_id = fields.Many2one('dr.product.tags')
class DrProductTagsExt(models.Model):
_inherit = 'dr.product.tags'
dr_tab_ids = fields.One2many('dr.product.tabs', 'tag_id', string='Tabs', help='Display in product detail page on website.')
dr_offer_ids = fields.One2many('dr.product.offer', 'tag_id', string='Offers', help='Display in product detail page on website.')
class ProductTemplate(models.Model):
_inherit = 'product.template'
dr_brand_id = fields.Many2one('dr.product.brand')
dr_offer_ids = fields.One2many('dr.product.offer', 'product_id', help='Display in product detail page on website.')
dr_tab_ids = fields.One2many('dr.product.tabs', 'product_id', help='Display in product detail page on website.')
class WebsiteMenu(models.Model):
_inherit = 'website.menu'
dr_is_special_menu = fields.Boolean()

View File

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import fields, models
class DrProductTags(models.Model):
_name = 'dr.product.tags'
_inherit = ['website.multi.mixin']
_description = 'Product Tags'
name = fields.Char(required=True, translate=True)
product_ids = fields.Many2many('product.template', 'dr_product_tags_rel', 'tag_id', 'product_id', string='Products')
product_count = fields.Integer(compute='_compute_product_count')
active = fields.Boolean(default=True)
class ProductTemplate(models.Model):
_inherit = 'product.template'
dr_tag_ids = fields.Many2many('dr.product.tags', 'dr_product_tags_rel', 'product_id', 'tag_id', string='Tags')

View File

@ -1,8 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_dr_product_brand_manager,dr.product.brand.manager,model_dr_product_brand,sales_team.group_sale_manager,1,1,1,1
access_dr_product_tabs_manager,dr.product.tabs.manager,model_dr_product_tabs,sales_team.group_sale_manager,1,1,1,1
access_dr_product_tabs_public,dr.product.tabs.public,model_dr_product_tabs,,1,0,0,0
access_dr_product_offer_manager,dr.product.offer.manager,model_dr_product_offer,sales_team.group_sale_manager,1,1,1,1
access_dr_product_offer_public,dr.product.offer.public,model_dr_product_offer,,1,0,0,0
access_dr_product_tags_manager,dr.product.tags.manager,model_dr_product_tags,sales_team.group_sale_manager,1,1,1,1
access_dr_product_tags_public,dr.product.tags.public,model_dr_product_tags,,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_dr_product_brand_manager dr.product.brand.manager model_dr_product_brand sales_team.group_sale_manager 1 1 1 1
3 access_dr_product_tabs_manager dr.product.tabs.manager model_dr_product_tabs sales_team.group_sale_manager 1 1 1 1
4 access_dr_product_tabs_public dr.product.tabs.public model_dr_product_tabs 1 0 0 0
5 access_dr_product_offer_manager dr.product.offer.manager model_dr_product_offer sales_team.group_sale_manager 1 1 1 1
6 access_dr_product_offer_public dr.product.offer.public model_dr_product_offer 1 0 0 0
7 access_dr_product_tags_manager dr.product.tags.manager model_dr_product_tags sales_team.group_sale_manager 1 1 1 1
8 access_dr_product_tags_public dr.product.tags.public model_dr_product_tags 1 0 0 0

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from . import dr_cache_mixin
from . import dr_category_label
from . import dr_product_label from . import dr_product_label
from . import dr_pwa_shortcuts from . import dr_product_brand
from . import dr_theme_config from . import dr_product_tags
from . import dr_website_content from . import dr_product_tabs
from . import product_template
from . import dr_website_menu_label from . import dr_website_menu_label
from . import product_attribute from . import product_attribute
from . import product_pricelist_item
from . import product_public_category
from . import product_template
from . import res_config_settings
from . import sale_order
from . import website from . import website
from . import website_menu from . import product_pricelist_item
from . import dr_pwa_shortcuts
from . import res_config_settings
from . import dr_config
from . import dr_category_lable

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import api, models
class DrCacheMixin(models.AbstractModel):
_name = 'dr.cache.mixin'
_description = 'Cache Mixin'
_fields_to_watch = []
@api.model_create_multi
def create(self, vals_list):
self.clear_caches()
return super().create(vals_list)
def write(self, vals):
self.clear_caches()
return super().write(vals)
def unlink(self):
self.clear_caches()
return super().unlink()

View File

@ -1,13 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import fields, models
class DrProductPublicCategoryLabel(models.Model):
_name = 'dr.product.public.category.label'
_description = 'Category Label'
name = fields.Char(required=True, translate=True)
background_color = fields.Char('Background Color', default='#000000')
text_color = fields.Char('Text Color', default='#FFFFFF')

View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import fields, models
class DrWebsiteCategoryLabel(models.Model):
_name = 'dr.product.public.category.label'
_description = 'Category Label'
name = fields.Char(required=True, translate=True)
color = fields.Selection([('green', 'Green'), ('blue', 'Blue'), ('red', 'Red'), ('orange', 'Orange'), ('gray', 'Gray'), ('black', 'Black')])
category_ids = fields.One2many('product.public.category', 'dr_category_label_id')
category_count = fields.Integer(compute='_compute_category_count')
def _compute_category_count(self):
for label in self:
label.category_count = len(label.category_ids)
def action_open_category(self):
self.ensure_one()
action = self.env.ref('website_sale.product_public_category_action').read()[0]
action['domain'] = [('dr_category_label_id', '=', self.id)]
action['context'] = {}
return action
class DrProductPublicCategory(models.Model):
_inherit = 'product.public.category'
dr_category_label_id = fields.Many2one('dr.product.public.category.label', string='Label')
dr_category_cover_image = fields.Binary(string='Cover Image')

View File

@ -1,23 +1,38 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
import json
import logging import logging
import json
from odoo import _, api, fields, models, tools from odoo import _, api, fields, models, tools
from odoo.http import request
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class DrThemeConfig(models.Model): class DrThemeConfig(models.Model):
_name = 'dr.theme.config' _name = 'dr.theme.config'
_inherit = 'dr.cache.mixin'
_description = 'Droggol Theme Config' _description = 'Droggol Theme Config'
_rec_name = 'key' _rec_name = "key"
key = fields.Char(required=True) key = fields.Char(required=True)
value = fields.Char() value = fields.Char()
website_id = fields.Many2one('website') website_id = fields.Many2one('website')
@api.model_create_multi
def create(self, vals_list):
self.clear_caches()
return super(DrThemeConfig, self).create(vals_list)
def write(self, vals):
self.clear_caches()
res = super(DrThemeConfig, self).write(vals)
return res
@api.model @api.model
@tools.ormcache('website_id') @tools.ormcache('website_id')
def _get_all_config(self, website_id): def _get_all_config(self, website_id):
@ -29,7 +44,7 @@ class DrThemeConfig(models.Model):
result_configs[config.key] = config.value == 'True' result_configs[config.key] = config.value == 'True'
elif config.key.startswith('json_'): elif config.key.startswith('json_'):
config_value = json.loads(config.value) config_value = json.loads(config.value)
if isinstance(config_value, dict) and result_configs.get(config.key): if isinstance(config_value, dict):
result_configs[config.key].update(config_value) result_configs[config.key].update(config_value)
else: else:
result_configs[config.key] = config_value result_configs[config.key] = config_value
@ -47,29 +62,64 @@ class DrThemeConfig(models.Model):
def _get_default_theme_config(self, website_id): def _get_default_theme_config(self, website_id):
website = self.env['website'].sudo().browse(website_id) website = self.env['website'].sudo().browse(website_id)
# TODO: Clear cache on website write (when theme is installed)
return { return {
'json_sidebar_config': {'category_sidebar_style': '2', 'category_sidebar_show_count': True, 'menu_sidebar_show_category': True}, 'bool_enable_ajax_load_on_click': False,
'json_shop_layout': {'layout': 'prime', 'show_view_switcher': True, 'default_view_mode': 'grid', 'load_more_products': 'button'},
'json_shop_product_item': {'style': '1', 'image_size': 'default', 'image_fill': 'cover', 'show_add_to_cart': True, 'show_wishlist': True, 'show_compare': True, 'show_quick_view': True, 'show_similar_products': True, 'show_product_preview_swatches': True, 'show_rating': True, 'show_stock_label': False},
'json_shop_category_pills': {'active': True, 'style': '1', 'show_child_categories': True, 'hide_in_desktop': False},
'json_shop_filters': {'lazy_method': True, 'filter_style': '1', 'filter_position': 'left', 'show_in_sidebar': False, 'collapsible_category': True, 'collapsible_attribute': True, 'show_category_count': True, 'show_attribute_count': False, 'hide_extra_attrib_value': False, 'show_rating_filter': True, 'show_availability_filter': False},
'json_zoom': {'zoom_enabled': True, 'zoom_factor': 2},
'bool_enable_ajax_load': False, 'bool_enable_ajax_load': False,
'json_bottom_bar': {'show_bottom_bar': True, 'show_bottom_bar_on_scroll': False, 'filters': True, 'actions': ['tp_home', 'tp_search', 'tp_wishlist', 'tp_offer', 'tp_brands', 'tp_category', 'tp_orders']}, 'bool_show_bottom_bar_onscroll': False,
'bool_display_bottom_bar': True,
'bool_mobile_filters': True,
'json_zoom': {
'zoom_enabled': True,
'zoom_factor': 2,
'disable_small': False
},
'json_category_pills': {
'enable': True,
'enable_child': True,
'hide_desktop': True,
'show_title': True,
'style': 1,
},
'json_grid_product': {
'show_color_preview': True,
'show_quick_view': True,
'show_similar_products': True,
'show_rating': True,
},
'json_shop_filters': {
'in_sidebar': False,
'collapsible': True,
'show_category_count': True,
'show_attrib_count': False,
'hide_attrib_value': False,
'show_price_range_filter': True,
'price_range_display_type': 'sales_price',
'show_rating_filter': True,
'show_brand_search': True,
'show_labels_search': True,
'show_tags_search': True,
'brands_style': 1,
'tags_style': 1,
},
'bool_sticky_add_to_cart': True, 'bool_sticky_add_to_cart': True,
'json_general_language_pricelist_selector': {'hide_country_flag': False}, 'bool_general_show_category_search': True,
'json_b2b_shop_config': {'dr_enable_b2b': False, 'dr_only_assigned_pricelist': False}, 'json_general_language_pricelist_selector': {
'json_mobile': {}, 'hide_country_flag': False,
'json_product_search': {'advance_search': True, 'search_category': True, 'search_attribute': True, 'search_suggestion': True, 'search_limit': 10, 'search_max_product': 3, 'search_fuzzy': True}, },
'json_brands_page': {'disable_brands_grouping': False}, 'json_brands_page': {
'disable_brands_grouping': False,
},
'cart_flow': 'default', 'cart_flow': 'default',
'json_bottom_bar_config': ['tp_home', 'tp_search', 'tp_wishlist', 'tp_offer', 'tp_brands', 'tp_category', 'tp_orders'],
'theme_installed': website.theme_id and website.theme_id.name.startswith('theme_prime') or False, 'theme_installed': website.theme_id and website.theme_id.name.startswith('theme_prime') or False,
'pwa_active': website.dr_pwa_activated, 'pwa_active': website.dr_pwa_activated,
'bool_product_offers': True, 'bool_product_offers': True,
'bool_show_products_nav': True,
} }
def save_config(self, website_id, configs): def _save_config(self, website_id, configs):
all_config = self.search([('website_id', '=', website_id)]) all_config = self.search([('website_id', '=', website_id)])
for key, value in configs.items(): for key, value in configs.items():
key, value = self._prepare_value_for_write(key, value) key, value = self._prepare_value_for_write(key, value)
@ -86,3 +136,14 @@ class DrThemeConfig(models.Model):
elif key.startswith('int_'): elif key.startswith('int_'):
value = value value = value
return key.strip(), value return key.strip(), value
class Http(models.AbstractModel):
_inherit = 'ir.http'
@api.model
def get_dr_theme_config(self):
result = {}
if request.website:
result = request.website._get_dr_theme_config()
return result

View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import api, fields, models
class DrProductBrand(models.Model):
_name = 'dr.product.brand'
_inherit = ['website.multi.mixin']
_description = 'Product Brand'
_order = 'sequence,id'
name = fields.Char(required=True, translate=True)
description = fields.Char(translate=True)
image = fields.Binary()
product_ids = fields.One2many('product.template', 'dr_brand_id')
product_count = fields.Integer(compute='_compute_product_count')
sequence = fields.Integer(string='Sequence')
active = fields.Boolean(default=True)
def _compute_product_count(self):
for brand in self:
brand.product_count = len(brand.product_ids)
def action_open_products(self):
self.ensure_one()
action = self.env.ref('website_sale.product_template_action_website').read()[0]
action['domain'] = [('dr_brand_id', '=', self.id)]
return action
@api.model
def reorder_sequence(self):
sequence = 1
for brand in self.search([], order='name'):
brand.sequence = sequence
sequence += 1

View File

@ -1,38 +1,37 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from PIL import ImageColor
from odoo import api, fields, models from odoo import api, fields, models
class DrProductLabel(models.Model): class DrProductLabel(models.Model):
_name = 'dr.product.label' _name = 'dr.product.label'
_description = 'Product Label' _description = 'Product Label'
_inherit = 'dr.cache.mixin'
name = fields.Char(required=True, translate=True) name = fields.Char(required=True, translate=True)
background_color = fields.Char('Background Color', default='#000000') color = fields.Selection([
background_color_rgb = fields.Char(compute='_compute_background_color_rgb', store=True, string='Background Color RGB') ('green', 'Green'),
text_color = fields.Char('Text Color', default='#FFFFFF') ('blue', 'Blue'),
style = fields.Selection([('1', 'Tag'), ('2', 'Badge'), ('3', 'Circle'), ('4', 'Square')], default='1', required=True) ('orange', 'Orange'),
('red', 'Red'),
('gray', 'Gray'),
('black', 'Black'),
])
style = fields.Selection([
('1', 'Tag'),
('2', 'Badge'),
('3', 'Circle'),
], default='1', required=True)
product_ids = fields.One2many('product.template', 'dr_label_id')
product_count = fields.Integer(compute='_compute_product_count') product_count = fields.Integer(compute='_compute_product_count')
active = fields.Boolean(default=True) active = fields.Boolean(default=True)
def _compute_product_count(self): def _compute_product_count(self):
label_data = self.env['product.template'].read_group([('dr_label_id', 'in', self.ids)], ['dr_label_id'], ['dr_label_id'])
mapped_data = dict([(x['dr_label_id'][0], x['dr_label_id_count']) for x in label_data])
for label in self: for label in self:
label.product_count = mapped_data.get(label.id, 0) label.product_count = len(label.product_ids)
@api.depends('background_color')
def _compute_background_color_rgb(self):
for label in self:
colors = ImageColor.getcolor(label.background_color, 'RGB')
label.background_color_rgb = '%s, %s, %s' % (colors[0], colors[1], colors[2])
def action_open_products(self): def action_open_products(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('website_sale.product_template_action_website').read()[0] action = self.env.ref('website_sale.product_template_action_website').read()[0]
action['domain'] = [('dr_label_id', '=', self.id)] action['domain'] = [('dr_label_id', '=', self.id)]
action['context'] = {}
return action return action

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import api, fields, models
class DrProductTabs(models.Model):
_name = 'dr.product.tabs'
_description = 'Product Tabs'
_order = 'sequence,id'
name = fields.Char(string='Title', required=True, translate=True)
icon = fields.Char(default='list')
content = fields.Html(sanitize_attributes=False, translate=True, sanitize_form=False)
sequence = fields.Integer(string='Sequence')
product_id = fields.Many2one('product.template')
tag_id = fields.Many2one('dr.product.tags')
class DrProductOffer(models.Model):
_name = 'dr.product.offer'
_description = 'Product Offers'
_order = 'sequence,id'
name = fields.Char(string='Title', required=True, translate=True)
description = fields.Char(string='Description', required=True, translate=True)
icon = fields.Char(default='list')
sequence = fields.Integer(string='Sequence')
dialog_content = fields.Html(sanitize_attributes=False, translate=True, sanitize_form=False)
product_id = fields.Many2one('product.template')
tag_id = fields.Many2one('dr.product.tags')

View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import api, fields, models
class DrProductTags(models.Model):
_name = 'dr.product.tags'
_inherit = ['website.multi.mixin']
_description = 'Product Tags'
name = fields.Char(required=True, translate=True)
product_ids = fields.Many2many('product.template', 'dr_product_tags_rel', 'tag_id', 'product_id')
product_count = fields.Integer(compute='_compute_product_count')
active = fields.Boolean(default=True)
dr_tab_ids = fields.One2many('dr.product.tabs', 'tag_id', string='Tabs', help='Display in product detail page on website.')
dr_offer_ids = fields.One2many('dr.product.offer', 'tag_id', string='Offers', help='Display in product detail page on website.')
def _compute_product_count(self):
for tag in self:
tag.product_count = len(tag.product_ids)
def action_open_products(self):
self.ensure_one()
action = self.env.ref('website_sale.product_template_action_website').read()[0]
action['domain'] = [('dr_tag_ids', 'in', self.id)]
return action

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import fields, models from odoo import fields, models, tools
class PWAShortcuts(models.Model): class PWAShortcuts(models.Model):
@ -11,7 +11,7 @@ class PWAShortcuts(models.Model):
website_id = fields.Many2one('website') website_id = fields.Many2one('website')
sequence = fields.Integer() sequence = fields.Integer()
name = fields.Char(required=True, translate=True, help='The human-readable label for the app shortcut when displayed to the user.') name = fields.Char(required=True, translate=True, help='The human-readable label for the app shortcut when displayed to the user.')
short_name = fields.Char('Short Name', translate=True, help='The human-readable label used where space is limited.') short_name = fields.Char(translate=True, help='The human-readable label used where space is limited.')
description = fields.Text(help='The human-readable purpose for the app shortcut.') description = fields.Text(help='The human-readable purpose for the app shortcut.')
url = fields.Char('URL', required=True, help='The URL opened when a user activates the app shortcut.') url = fields.Char('URL', required=True, help='The URL opened when a user activates the app shortcut.')
icon = fields.Binary() icon = fields.Binary()

View File

@ -1,40 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import fields, models
from odoo.tools.translate import html_translate
class DrWebsiteContent(models.Model):
_name = 'dr.website.content'
_description = 'Website Content'
_inherit = 'dr.cache.mixin'
_order = 'sequence,id'
sequence = fields.Integer()
name = fields.Char(required=True, translate=True)
identifier = fields.Char('Extra Label', help="It is just displayed in backend dropdown and breadcrumb")
description = fields.Char(translate=True)
icon = fields.Char(default='list')
content = fields.Html(sanitize_attributes=False, translate=html_translate, sanitize_form=False)
content_type = fields.Selection([('tab', 'Product Tab'), ('offer_popup', 'Offer Popup'), ('attribute_popup', 'Attribute Popup')], default='tab', required=True, string='Type')
dr_tab_products_ids = fields.Many2many('product.template', 'product_template_tab_rel', 'tab_id', 'product_template_id', string='Tab Products')
dr_offer_products_ids = fields.Many2many('product.template', 'product_template_offer_rel', 'offer_id', 'product_template_id', string='Offer Products')
def name_get(self):
result = []
for content in self:
name = content.name
if content.identifier:
name = f'[{content.identifier}] {name}'
result.append((content.id, name))
return result
def open_design_page(self):
self.ensure_one()
return {
'type': 'ir.actions.act_url',
'target': 'new',
'url': '/droggol_theme_common/design_content/%s?enable_editor=1' % (self.id),
}

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import fields, models from odoo import api, fields, models
class DrWebsiteMenuLabel(models.Model): class DrWebsiteMenuLabel(models.Model):
@ -9,5 +9,38 @@ class DrWebsiteMenuLabel(models.Model):
_description = 'Website Menu Label' _description = 'Website Menu Label'
name = fields.Char(required=True, translate=True) name = fields.Char(required=True, translate=True)
background_color = fields.Char('Background Color', default='#000000') color = fields.Selection([
text_color = fields.Char('Text Color', default='#FFFFFF') ('green', 'Green'),
('blue', 'Blue'),
('red', 'Red'),
('orange', 'Orange'),
('gray', 'Gray'),
('black', 'Black'),
])
menu_ids = fields.One2many('website.menu', 'dr_menu_label_id')
menu_count = fields.Integer(compute='_compute_menu_count')
def _compute_menu_count(self):
for label in self:
label.menu_count = len(label.menu_ids)
def action_open_menus(self):
self.ensure_one()
action = self.env.ref('website.action_website_menu').read()[0]
action['domain'] = [('dr_menu_label_id', '=', self.id)]
action['context'] = {}
return action
class WebsiteMenu(models.Model):
_inherit = 'website.menu'
dr_menu_label_id = fields.Many2one('dr.website.menu.label', string='Label')
dr_is_special_menu = fields.Boolean()
@api.model
def get_tree(self, website_id, menu_id=None):
result = super(WebsiteMenu, self).get_tree(website_id, menu_id)
for menu in result['children']:
menu['fields']['dr_is_special_menu'] = self.browse(menu['fields']['id']).dr_is_special_menu
return result

View File

@ -1,14 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import api, fields, models, _ from odoo import api, fields, models
from odoo.exceptions import UserError
class ProductAttribute(models.Model): class ProductAttribute(models.Model):
_name = 'product.attribute' _inherit = 'product.attribute'
_inherit = ['product.attribute', 'dr.cache.mixin']
_fields_to_watch = ['name', 'display_type', 'dr_attribute_popup_id', 'dr_radio_image_style', 'dr_is_brand']
display_type = fields.Selection( display_type = fields.Selection(
selection_add=[ selection_add=[
@ -16,66 +13,17 @@ class ProductAttribute(models.Model):
('radio_square', 'Radio Square'), ('radio_square', 'Radio Square'),
('radio_image', 'Radio Image'), ('radio_image', 'Radio Image'),
], ondelete={'radio_circle': 'cascade', 'radio_square': 'cascade', 'radio_image': 'cascade'}) ], ondelete={'radio_circle': 'cascade', 'radio_square': 'cascade', 'radio_image': 'cascade'})
dr_is_hide_shop_filter = fields.Boolean('Hide in Shop Filter', default=False)
dr_is_show_shop_search = fields.Boolean('Show Searchbar in Shop Filter', default=False) dr_is_show_shop_search = fields.Boolean('Show Searchbar in Shop Filter', default=False)
dr_attribute_popup_id = fields.Many2one('dr.website.content', string='Popup', domain='[("content_type", "=", "attribute_popup")]')
dr_radio_image_style = fields.Selection([
('default', 'Default'),
('image', 'Image'),
('image_text', 'Image + Text'),
], default='default', string='Style')
dr_search_suggestion = fields.Selection([('auto', 'Autocomplete'), ('auto_suggestion', 'Autocomplete & Suggestion')], string='Search suggestion type')
dr_is_brand = fields.Boolean('Is Brand?')
@api.onchange('dr_is_brand')
def _onchange_dr_is_brand(self):
self.display_type = 'radio_image'
@api.constrains('dr_is_brand', 'display_type')
def _constrains_dr_is_brand(self):
for attribute in self:
if attribute.dr_is_brand and not attribute.display_type == 'radio_image':
raise UserError(_('Brand attribute must have display type "Radio Image".'))
def open_create_brand_value(self):
return {
'type': 'ir.actions.act_window',
'name': _('Brand'),
'res_model': 'product.attribute.value',
'view_mode': 'form',
'target': 'new',
'views': [[False, 'form']],
'context': {'default_attribute_id': self.id}
}
class ProductAttributeValue(models.Model): class ProductAttributeValue(models.Model):
_name = 'product.attribute.value' _inherit = 'product.attribute.value'
_inherit = ['product.attribute.value', 'dr.cache.mixin']
_fields_to_watch = ['name', 'html_color', 'dr_image', 'dr_brand_description']
dr_image = fields.Binary('Image') dr_image = fields.Binary(string='Image')
dr_brand_description = fields.Text('Description', translate=True)
ds_name = fields.Char('Search DS Name', compute="_compute_ds_name", search="_search_ds_name")
def _compute_ds_name(self):
for attr in self:
attr.ds_name = attr.name
@api.model
def _search_ds_name(self, operator, value):
return [('name', operator, value)]
class ProductTemplateAttributeValue(models.Model): class ProductTemplateAttributeValue(models.Model):
_name = 'product.template.attribute.value' _inherit = 'product.template.attribute.value'
_inherit = ['product.template.attribute.value', 'dr.cache.mixin']
_fields_to_watch = ['dr_thumb_image']
dr_image = fields.Binary('Image', related='product_attribute_value_id.dr_image') dr_image = fields.Binary('Image', related='product_attribute_value_id.dr_image')
dr_thumb_image = fields.Image('Swatch Image', max_width=128, max_height=128)
class ProductTemplateAttributeLine(models.Model):
_inherit = 'product.template.attribute.line'
dr_attribute_popup_id = fields.Many2one('dr.website.content', string='Website Popup', domain='[("content_type", "=", "attribute_popup")]')

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import fields, models from odoo import api, fields, models
class PricelistItem(models.Model): class PricelistItem(models.Model):

View File

@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
import re
from odoo import fields, models, api
class ProductPublicCategory(models.Model):
_inherit = 'product.public.category'
dr_category_label_id = fields.Many2one('dr.product.public.category.label', string='Label')
dr_category_cover_image = fields.Binary('Cover Image')
dr_category_icon = fields.Binary('Icon Image')
dr_category_sidebar_cover = fields.Binary('Sidebar Cover')
dr_search_formulate = fields.Boolean('Formulated Search', help="Use to search multi level categories \
e.g. Men Shirt (Here men and shirt are diffrent category but will be displayed as one in smart search)")
ds_name = fields.Char('Search DS Name', compute="_compute_ds_name", search="_search_ds_name")
def _compute_ds_name(self):
for category in self:
if self.env.context.get('dr_formulate'):
category.ds_name = ' '.join([categ.name for categ in category.parents_and_self if (category.id == categ.id or categ.dr_search_formulate)])
else:
category.ds_name = category.name
@api.model
def _search_ds_name(self, operator, value):
if not self.env.context.get('dr_formulate'):
return [('name', operator, value)]
# Assumes operator is 'ilike'
domain, website_id = [('dr_search_formulate', '=', False)], self.env.context.get('website_id')
if website_id:
domain += self.env['website'].website_domain(website_id=website_id)
categ_ids = [categ.id for categ in self.search(domain) if re.search(re.escape(value), categ.ds_name, re.IGNORECASE)]
return [('id', 'in', categ_ids)]
@api.model
def _search_get_detail(self, website, order, options):
"Fix the issue of Odoo's search in html fields"
with_image = options['displayImage']
options = options.copy()
options['displayDescription'] = False
result = super()._search_get_detail(website, order, options)
if with_image:
result['mapping']['image_url'] = {'name': 'image_url', 'type': 'html'}
# to fix Odoo's issue Odoo catagory is not multi website compatible
result['base_domain'] = [website.website_domain()]
return result

View File

@ -1,182 +1,44 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import api, fields, models, Command from odoo import api, fields, models
from odoo.addons.website.models import ir_http from odoo.http import request
class ProductTemplate(models.Model): class ProductTemplate(models.Model):
_inherit = 'product.template' _inherit = 'product.template'
dr_label_id = fields.Many2one('dr.product.label', string='Label') dr_label_id = fields.Many2one('dr.product.label', string='Label')
dr_brand_id = fields.Many2one('dr.product.brand', string='Brand')
dr_tag_ids = fields.Many2many('dr.product.tags', 'dr_product_tags_rel', 'product_id', 'tag_id', string='Tags')
dr_tab_ids = fields.One2many('dr.product.tabs', 'product_id', string='Tabs', help='Display in product detail page on website.')
dr_offer_ids = fields.One2many('dr.product.offer', 'product_id', string='Offers', help='Display in product detail page on website.')
dr_product_tab_ids = fields.Many2many('dr.website.content', 'product_template_tab_rel', 'product_template_id', 'tab_id', string='Tabs') @api.onchange('website_id')
dr_product_offer_ids = fields.Many2many('dr.website.content', 'product_template_offer_rel', 'product_template_id', 'offer_id', string='Offers') def _onchange_website_id(self):
self.dr_label_id = False
dr_document_ids = fields.Many2many('ir.attachment', 'product_template_document_attachment_rel', 'product_template_id', 'attachment_id', string='Documents', help='Documents publicly downloadable from eCommerce product page.') self.dr_brand_id = False
dr_brand_value_id = fields.Many2one('product.attribute.value', compute='_compute_dr_brand_value_id', inverse='_inverse_dr_brand_value_id', search='_search_dr_brand_value_id', string='Brand') self.dr_tag_ids = False
dr_brand_attribute_ids = fields.Many2many('product.attribute', compute='_compute_dr_brand_attribute_ids')
dr_free_qty = fields.Float('Free To Use Quantity', compute='_compute_dr_free_qty', search='_search_dr_free_qty', compute_sudo=False, digits='Product Unit of Measure')
dr_show_out_of_stock = fields.Char(compute='_compute_dr_show_out_of_stock', compute_sudo=True)
dr_ptav_ids = fields.One2many('product.template.attribute.value', 'product_tmpl_id')
@api.model_create_multi
def create(self, vals):
res = super().create(vals)
res.dr_document_ids.public = True
return res
def write(self, vals):
res = super().write(vals)
if 'dr_document_ids' in vals:
self.dr_document_ids.public = True
return res
def _search_dr_brand_value_id(self, operator, value):
if operator in ['in', 'not in']:
return [('attribute_line_ids.value_ids', operator, value)]
elif operator in ['ilike', 'not ilike', '=', '!=']:
brand_attribute_id = self._get_brand_attribute()
values = self.env['product.attribute.value'].search([('name', operator, value), ('attribute_id', 'in', brand_attribute_id.ids)])
return [('attribute_line_ids.value_ids', 'in', values.ids)]
# Does not support other cases
return []
def _compute_dr_brand_value_id(self):
for product in self:
brand_lines = product.attribute_line_ids.filtered(lambda x: x.attribute_id.dr_is_brand)
product.dr_brand_value_id = self.env['product.attribute.value']
if brand_lines:
product.dr_brand_value_id = brand_lines[0].value_ids[0]
def _inverse_dr_brand_value_id(self):
brand_value_id = self.dr_brand_value_id
for product in self:
brand_lines = product.attribute_line_ids.filtered(lambda x: x.attribute_id.dr_is_brand)
brand_line = brand_lines and brand_lines[0]
if brand_line and brand_value_id:
brand_line.value_ids = brand_value_id
elif brand_line and not brand_value_id:
brand_line.unlink()
elif brand_value_id:
product.attribute_line_ids = [Command.create({
'attribute_id': brand_value_id.attribute_id.id,
'value_ids': [Command.set(brand_value_id.ids)],
})]
def _compute_dr_brand_attribute_ids(self):
attributes = self._get_brand_attribute()
for product in self:
product.dr_brand_attribute_ids = attributes
def _get_brand_attribute(self):
return self.env['product.attribute'].search([('dr_is_brand', '=', True)])
@api.depends('product_variant_ids.free_qty')
def _compute_dr_free_qty(self):
res = self._compute_dr_free_qty_quantities_dict()
for template in self:
template.dr_free_qty = res[template.id]['free_qty']
def _compute_dr_free_qty_quantities_dict(self):
variants_available = {
p['id']: p for p in self.product_variant_ids.read(['free_qty'])
}
prod_available = {}
for template in self:
free_qty = 0
for p in template.product_variant_ids:
free_qty += variants_available[p.id]['free_qty']
prod_available[template.id] = {
'free_qty': free_qty,
}
return prod_available
def _search_dr_free_qty(self, operator, value):
domain = [('free_qty', operator, value)]
product_variant_query = self.env['product.product'].sudo()._search(domain)
return [('product_variant_ids', 'in', product_variant_query)]
def _compute_dr_show_out_of_stock(self):
website = ir_http.get_request_website()
for product in self:
product.dr_show_out_of_stock = ''
if website and website._get_dr_theme_config('json_shop_product_item').get('show_stock_label') and not product.allow_out_of_stock_order and product.detailed_type == 'product':
free_qty = product.dr_free_qty
if product.show_availability and free_qty <= product.available_threshold:
product.dr_show_out_of_stock = int(free_qty)
if free_qty <= 0:
product.dr_show_out_of_stock = 'OUT_OF_STOCK'
@api.model @api.model
def _search_get_detail(self, website, order, options): def _get_product_colors(self):
res = super()._search_get_detail(website, order, options) color_variants = self.attribute_line_ids.filtered(lambda x: x.attribute_id.display_type == 'color')
# Hide out of stock if len(color_variants) == 1:
if options.get('hide_out_of_stock'): if len(color_variants.value_ids) == 1:
res['base_domain'].append(['|', '|', ('detailed_type', '!=', 'product'), ('allow_out_of_stock_order', '=', True), '&', ('dr_free_qty', '>', 0), ('allow_out_of_stock_order', '=', False)]) return []
# Tag return color_variants.value_ids.mapped('html_color')
tag = options.get('tag') return []
if tag:
res['base_domain'].append([('product_tag_ids', 'in', [int(x) for x in tag])])
# Rating
ratings = options.get('rating')
if ratings:
result = self.env['rating.rating'].sudo().read_group([('res_model', '=', 'product.template')], ['rating:avg'], groupby=['res_id'], lazy=False)
rating_product_ids = []
for rating in ratings:
rating_product_ids.extend([item['res_id'] for item in result if item['rating'] >= int(rating)])
if rating_product_ids:
res['base_domain'].append([('id', 'in', rating_product_ids)])
else:
res['base_domain'].append([('id', 'in', [])])
return res
def _get_image_size_based_grid(self, columns, view_mode):
if view_mode == 'list':
return 'image_1024'
if columns <= 2:
return 'image_1024'
return 'image_512'
def _get_product_preview_swatches(self, limit=3):
swatches = []
for ptav in self.dr_ptav_ids:
if ptav.ptav_active and ptav.ptav_product_variant_ids:
vals = {'id': ptav.id, 'name': ptav.name, 'preview_image': '/web/image/product.product/%s' % ptav.ptav_product_variant_ids.ids[0]}
if ptav.dr_thumb_image:
vals.update({'type': 'image', 'value': '/web/image/product.template.attribute.value/%s/dr_thumb_image' % ptav.id})
swatches.append(vals)
elif ptav.html_color:
vals.update({'type': 'color', 'value': ptav.html_color})
swatches.append(vals)
return {'swatches': swatches[:limit], 'more': len(swatches) - limit}
@api.model
def _get_product_pricelist_offer(self): def _get_product_pricelist_offer(self):
website_id = self.env['website'].get_current_website() partner = self._context.get('partner')
if not website_id._dr_has_b2b_access(): pricelist_id = self._context.get('pricelist')
return False pricelist = self.env['product.pricelist'].browse(pricelist_id)
pricelist_id = website_id.get_current_pricelist()
price_rule = pricelist_id._compute_price_rule(self, 1) price_rule = pricelist._compute_price_rule([(self, 1, partner)])
price_rule_id = price_rule.get(self.id)[1] price_rule_id = price_rule.get(self.id)[1]
if price_rule_id: if price_rule_id:
rule = self.env['product.pricelist.item'].browse(price_rule_id) rule = self.env['product.pricelist.item'].browse([price_rule_id])
if rule and rule.date_end: if rule and rule.date_end:
return {'rule': rule, 'date_end': rule.date_end.strftime('%Y-%m-%d %H:%M:%S')} return {'rule': rule, 'date_end': rule.date_end.strftime('%Y-%m-%d %H:%M:%S')}
return False return False
def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False, only_template=False):
combination_info = super()._get_combination_info(combination=combination, product_id=product_id, add_qty=add_qty, pricelist=pricelist, parent_combination=parent_combination, only_template=only_template)
if combination_info['product_id']:
website = self.env['website'].get_current_website()
theme_id = website.sudo().theme_id
product_variant_id = self.env['product.product'].browse(combination_info['product_id'])
if website and theme_id and theme_id.name.startswith('theme_prime'):
# Render extra fields on product detail page
IrUiView = self.env['ir.ui.view']
combination_info['tp_extra_fields'] = IrUiView._render_template('theme_prime.product_extra_fields', values={'website': website, 'product_variant': product_variant_id, 'product': product_variant_id.product_tmpl_id})
# Hide price per UoM feature for B2B mode
if not website._dr_has_b2b_access():
combination_info['base_unit_price'] = 0
return combination_info

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import api, fields, models, _ from odoo import api, fields, models, _
@ -7,51 +7,38 @@ from odoo import api, fields, models, _
class ResConfigSettings(models.TransientModel): class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings' _inherit = 'res.config.settings'
dr_pwa_activated = fields.Boolean(related='website_id.dr_pwa_activated', readonly=False)
dr_pwa_name = fields.Char(related='website_id.dr_pwa_name', readonly=False)
dr_pwa_short_name = fields.Char(related='website_id.dr_pwa_short_name', readonly=False)
dr_pwa_background_color = fields.Char(related='website_id.dr_pwa_background_color', readonly=False)
dr_pwa_theme_color = fields.Char(related='website_id.dr_pwa_theme_color', readonly=False)
dr_pwa_icon_192 = fields.Binary(related='website_id.dr_pwa_icon_192', readonly=False)
dr_pwa_icon_512 = fields.Binary(related='website_id.dr_pwa_icon_512', readonly=False)
dr_pwa_start_url = fields.Char(related='website_id.dr_pwa_start_url', readonly=False)
dr_pwa_shortcuts = fields.One2many(related='website_id.dr_pwa_shortcuts', readonly=False)
dr_pwa_offline_page = fields.Boolean(related='website_id.dr_pwa_offline_page', readonly=False)
# This has been done in order to fix Odoo's broken behavior for theme customization. # This has been done in order to fix Odoo's broken behavior for theme customization.
# If database already have theme installed, it is impossible to have custom module later. # If database already have theme installed, it is impossible to have custom module later.
dr_has_custom_module = fields.Boolean(compute='_compute_dr_has_custom_module') dr_has_custom_module = fields.Boolean(compute='_compute_dr_has_custom_module')
@api.depends('website_id') @api.depends('website_id')
def _compute_dr_has_custom_module(self): def _compute_dr_has_custom_module(self):
IrModuleModule = self.env['ir.module.module'] theme_list = self._get_droggol_theme_list()
themes = self._get_droggol_theme_list()
for setting in self: for setting in self:
setting.dr_has_custom_module = False if setting.website_id and setting.website_id.theme_id and setting.website_id.theme_id.name in theme_list:
if setting.website_id and setting.website_id.theme_id and setting.website_id.theme_id.name in themes:
search_term = '%s_%%' % setting.website_id.theme_id.name search_term = '%s_%%' % setting.website_id.theme_id.name
has_custom_apps = IrModuleModule.sudo().search([('name', '=ilike', search_term)]) has_custom_apps = self.env['ir.module.module'].sudo().search([('name', '=ilike', search_term)])
setting.dr_has_custom_module = bool(has_custom_apps) if has_custom_apps:
setting.dr_has_custom_module = True
def dr_open_pwa_shortcuts(self): else:
self.website_id._force() setting.dr_has_custom_module = False
action = self.env.ref('droggol_theme_common.dr_pwa_shortcuts_action').read()[0] else:
action['domain'] = [('website_id', '=', self.website_id.id)] setting.dr_has_custom_module = False
action['context'] = {'default_website_id': self.website_id.id}
return action
def dr_open_theme_custom_modules(self): def dr_open_theme_custom_modules(self):
self.ensure_one() self.ensure_one()
themes = self._get_droggol_theme_list() theme_list = self._get_droggol_theme_list()
if self.website_id and self.website_id.theme_id and self.website_id.theme_id.name in themes: if self.website_id and self.website_id.theme_id and self.website_id.theme_id.name in theme_list:
search_term = '%s_%%' % self.website_id.theme_id.name search_term = '%s_%%' % self.website_id.theme_id.name
return { action = {
'name': _('Theme Customizations'), 'name': _('Theme Customizations'),
'view_mode': 'kanban,tree,form', 'view_mode': 'kanban,tree,form',
'res_model': 'ir.module.module', 'res_model': 'ir.module.module',
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'domain': [('name', '=ilike', search_term)] 'domain': [('name', '=ilike', search_term)]
} }
return action
return True return True
def _get_droggol_theme_list(self): def _get_droggol_theme_list(self):

View File

@ -1,16 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import models
class SaleOrder(models.Model):
_inherit = 'sale.order'
def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs):
values = super()._cart_update(product_id=product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty, **kwargs)
if self.website_id and not self.website_id._dr_has_b2b_access():
for line in self.order_line:
new_val = super()._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=-1, set_qty=0, **kwargs)
values.update(new_val)
return values

View File

@ -1,79 +1,70 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from odoo import _, api, fields, models import base64
from odoo import _, fields, models, tools, api
from odoo.osv import expression from odoo.osv import expression
from odoo.tools.translate import html_translate from odoo.modules.module import get_resource_path
class Website(models.Model): class Website(models.Model):
_inherit = 'website' _inherit = 'website'
dr_sale_special_offer = fields.Html('Sale Special Offer', sanitize_attributes=False, translate=html_translate, sanitize_form=False) def _default_footer_logo(self):
image_path = get_resource_path('website', 'static/src/img', 'website_logo.png')
with tools.file_open(image_path, 'rb') as f:
return base64.b64encode(f.read())
dr_pwa_activated = fields.Boolean('PWA Activated') dr_sale_special_offer = fields.Html(sanitize_attributes=False, translate=True)
dr_pwa_name = fields.Char('PWA Name')
dr_pwa_short_name = fields.Char('PWA Short Name')
dr_pwa_background_color = fields.Char('PWA Background Color', default='#000000')
dr_pwa_theme_color = fields.Char('PWA Theme Color', default='#FFFFFF')
dr_pwa_icon_192 = fields.Binary('PWA Icon 192x192')
dr_pwa_icon_512 = fields.Binary('PWA Icon 512x512')
dr_pwa_start_url = fields.Char('PWA Start URL', default='/shop')
dr_pwa_offline_page = fields.Boolean('PWA Offline Page')
dr_pwa_version = fields.Integer('PWA Version')
dr_pwa_shortcuts = fields.One2many('dr.pwa.shortcuts', 'website_id', string='Shortcuts')
def _get_brands(self, domain=[], limit=None, order=None): # PWA
brand_attributes = self._get_brand_attributes().ids dr_pwa_activated = fields.Boolean()
domain = expression.AND([domain, [('attribute_id', 'in', brand_attributes)]]) dr_pwa_name = fields.Char()
return self.env['product.attribute.value'].search(domain, limit=limit, order=order) dr_pwa_short_name = fields.Char()
dr_pwa_background_color = fields.Char(default='#000000')
def _dr_has_b2b_access(self, record=None): dr_pwa_theme_color = fields.Char(default='#FFFFFF')
if self._get_dr_theme_config('json_b2b_shop_config')['dr_enable_b2b']: dr_pwa_icon_192 = fields.Binary()
return not self.env.user.has_group('base.group_public') dr_pwa_icon_512 = fields.Binary()
return True dr_pwa_start_url = fields.Char(default='/shop')
dr_pwa_offline_page = fields.Boolean()
def _get_brand_attributes(self): dr_pwa_version = fields.Integer(default=1)
""" This will preserver the sequence """ dr_pwa_shortcuts = fields.One2many('dr.pwa.shortcuts', 'website_id')
current_website_products = self.env['product.template'].search(self.sale_product_domain())
all_brand_attributes = self.env['product.template']._get_brand_attribute()
return self.env['product.template.attribute.line'].search([('product_tmpl_id', 'in', current_website_products.ids), ('attribute_id', 'in', all_brand_attributes.ids)]).mapped('attribute_id')
def get_dr_theme_config(self):
return self._get_dr_theme_config()
def _get_dr_theme_config(self, key=False): def _get_dr_theme_config(self, key=False):
""" See dr.theme.config for more info""" """ See dr.theme.config for more info"""
self.ensure_one() self.ensure_one()
website_config = self.env['dr.theme.config']._get_all_config(self.id) website_config = self.env['dr.theme.config']._get_all_config(self.id)
website_config['is_public_user'] = not self.env.user.has_group('website.group_website_restricted_editor') website_config['is_public_user'] = not self.env.user.has_group('website.group_website_publisher')
website_config['has_sign_up'] = False
if website_config.get('json_b2b_shop_config')['dr_enable_b2b']:
website_config['has_sign_up'] = self.env['res.users']._get_signup_invitation_scope() == 'b2c'
if key: if key:
return website_config.get(key) return website_config.get(key)
return website_config return website_config
def _get_pricelist_available(self, req, show_visible=False): def _get_theme_prime_shop_config(self):
if self._get_dr_theme_config('json_b2b_shop_config')['dr_only_assigned_pricelist'] and not self.env.user.has_group('base.group_website_designer'):
return self.env.user.partner_id.property_product_pricelist
return super()._get_pricelist_available(req, show_visible=show_visible)
@api.model
def get_theme_prime_shop_config(self):
Website = self.get_current_website() Website = self.get_current_website()
return { result = {
'is_rating_active': Website.sudo().viewref('website_sale.product_comment').active, 'is_rating_active': Website.viewref('website_sale.product_comment').active,
'is_buy_now_active': Website.sudo().viewref('website_sale.product_buy_now').active, 'is_buy_now_active': Website.viewref('website_sale.product_buy_now').active,
'is_multiplier_active': Website.sudo().viewref('website_sale.product_quantity').active, 'is_multiplier_active': Website.viewref('website_sale.product_quantity').active,
'is_wishlist_active': Website.sudo().viewref('website_sale_wishlist.product_add_to_wishlist').active, 'is_wishlist_active': Website.viewref('website_sale_wishlist.add_to_wishlist').active,
'is_comparison_active': Website.sudo().viewref('website_sale_comparison.add_to_compare').active} 'is_comparison_active': Website.viewref('website_sale_comparison.add_to_compare').active,
'is_wishlist_installed': False,
'is_compare_installed': False,
}
modules = self.env['ir.module.module'].sudo().search(expression.OR([[('name', '=', 'website_sale_wishlist')], [('name', '=', 'website_sale_comparison')]]))
for module in modules:
if module.state == 'installed':
if module.name == 'website_sale_comparison':
result['is_compare_installed'] = True
if module.name == 'website_sale_wishlist':
result['is_wishlist_installed'] = True
return result
def _get_website_category(self): def _get_website_category(self):
return self.env['product.public.category'].search([('website_id', 'in', [False, self.id]), ('parent_id', '=', False)]) return self.env['product.public.category'].search([('website_id', 'in', [False, self.id]), ('parent_id', '=', False)])
def _get_theme_prime_rating_template(self, rating_avg, rating_count=False): def _get_theme_prime_rating_template(self, rating_avg, rating_count=False):
return self.env['ir.ui.view']._render_template('theme_prime.d_rating_widget_stars_static', values={ return self.env["ir.ui.view"]._render_template('theme_prime.d_rating_widget_stars_static', values={
'rating_avg': rating_avg, 'rating_avg': rating_avg,
'rating_count': rating_count, 'rating_count': rating_count,
}) })
@ -81,17 +72,54 @@ class Website(models.Model):
@api.model @api.model
def get_theme_prime_bottom_bar_action_buttons(self): def get_theme_prime_bottom_bar_action_buttons(self):
# Add to cart, blog, checkout, pricelist, language, # Add to cart, blog, checkout, pricelist, language,
return {'tp_home': {'name': _("Home"), 'url': '/', 'icon': 'fa fa-home'}, 'tp_search': {'name': _("Search"), 'icon': 'dri dri-search', 'action_class': 'tp-search-sidebar-action'}, 'tp_wishlist': {'name': _("Wishlist"), 'icon': 'dri dri-wishlist', 'url': '/shop/wishlist'}, 'tp_offer': {'name': _("Offers"), 'url': '/offers', 'icon': 'dri dri-bolt'}, 'tp_brands': {'name': _("Brands"), 'icon': 'dri dri-tag-l ', 'url': '/shop/all-brands'}, 'tp_category': {'name': _("Category"), 'icon': 'dri dri-category', 'action_class': 'tp-category-action'}, 'tp_orders': {'name': _("Orders"), 'icon': 'fa fa-file-text-o', 'url': '/my/orders'}, 'tp_cart': {'name': _("Cart"), 'icon': 'dri dri-cart', 'url': '/shop/cart'}, 'tp_lang_selector': {'name': _("Language and Pricelist selector")}} return {
'tp_home': {'name': _("Home"), 'url': '/', 'icon': 'fa fa-home'},
'tp_search': {'name': _("Search"), 'icon': 'dri dri-search', 'action_class': 'tp-search-sidebar-action'},
'tp_wishlist': {'name': _("Wishlist"), 'icon': 'dri dri-wishlist', 'url': '/shop/wishlist'},
'tp_offer': {'name': _("Offers"), 'url': '/offers', 'icon': 'dri dri-bolt'},
'tp_brands': {'name': _("Brands"), 'icon': 'dri dri-tag-l ', 'url': '/shop/all_brands'},
'tp_category': {'name': _("Category"), 'icon': 'dri dri-category', 'action_class': 'tp-category-action'},
'tp_orders': {'name': _("Orders"), 'icon': 'fa fa-file-text-o', 'url': '/my/orders'},
'tp_cart': {'name': _("Cart"), 'icon': 'dri dri-cart', 'url': '/shop/cart'},
'tp_lang_selector': {'name': _("Language and Pricelist selector")},
}
def _is_snippet_used(self, snippet_module, snippet_id, asset_version, asset_type, html_fields): def _convert_currency_price(self, amount, from_base_currency=True, rounding_method=None):
""" There is no versioning for all theme snippets (for the test case)""" """ This function converts amount based website pricelist and company company currency
if snippet_module and snippet_module.startswith('theme_prime'):
return True :param amount: float or int,
return super()._is_snippet_used(snippet_module, snippet_id, asset_version, asset_type, html_fields) :param from_base_currency: If True then coverts amount from company currency to pricelist currency
else it converts pricelist currency to company currency
:param rounding_method: funcation reference to round the final amount
"""
base_currency = self.company_id.currency_id
pricelist_currency = self.get_current_pricelist().currency_id
if base_currency != pricelist_currency:
if from_base_currency:
amount = base_currency._convert(amount, pricelist_currency, self.company_id, fields.Date.today())
else:
amount = pricelist_currency._convert(amount, base_currency, self.company_id, fields.Date.today())
return rounding_method(amount) if rounding_method else amount
class WebsiteSaleExtraField(models.Model): class ResConfigSettings(models.TransientModel):
_inherit = 'website.sale.extra.field' _inherit = 'res.config.settings'
dr_label = fields.Char('Display Label', translate=True) # PWA
field_id = fields.Many2one('ir.model.fields', domain=[('model_id.model', '=', 'product.template'), '|', ('ttype', 'in', ['char', 'binary']), ('name', 'in', ['public_categ_ids'])]) dr_pwa_activated = fields.Boolean(related='website_id.dr_pwa_activated', readonly=False)
dr_pwa_name = fields.Char(related='website_id.dr_pwa_name', readonly=False)
dr_pwa_short_name = fields.Char(related='website_id.dr_pwa_short_name', readonly=False)
dr_pwa_background_color = fields.Char(related='website_id.dr_pwa_background_color', readonly=False)
dr_pwa_theme_color = fields.Char(related='website_id.dr_pwa_theme_color', readonly=False)
dr_pwa_icon_192 = fields.Binary(related='website_id.dr_pwa_icon_192', readonly=False)
dr_pwa_icon_512 = fields.Binary(related='website_id.dr_pwa_icon_512', readonly=False)
dr_pwa_start_url = fields.Char(related='website_id.dr_pwa_start_url', readonly=False)
dr_pwa_shortcuts = fields.One2many(related='website_id.dr_pwa_shortcuts', readonly=False)
dr_pwa_offline_page = fields.Boolean(related='website_id.dr_pwa_offline_page', readonly=False)
def dr_open_pwa_shortcuts(self):
self.website_id._force()
action = self.env.ref('droggol_theme_common.dr_pwa_shortcuts_action').read()[0]
action['domain'] = [('website_id', '=', self.website_id.id)]
action['context'] = {'default_website_id': self.website_id.id}
return action

View File

@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import api, fields, models
class WebsiteMenu(models.Model):
_inherit = 'website.menu'
dr_menu_label_id = fields.Many2one('dr.website.menu.label', string='Label')
dr_highlight_menu = fields.Selection([('solid', 'Solid'), ('soft', 'Soft')], string='Highlight Menu')
@api.model
def get_tree(self, website_id, menu_id=None):
result = super().get_tree(website_id, menu_id=menu_id)
for menu in result['children']:
menu['fields']['dr_highlight_menu'] = self.browse(menu['fields']['id']).dr_highlight_menu
return result

View File

@ -3,8 +3,14 @@ access_dr_product_label_manager,dr.product.label.manager,model_dr_product_label,
access_dr_product_label_public,dr.product.label.public,model_dr_product_label,,1,0,0,0 access_dr_product_label_public,dr.product.label.public,model_dr_product_label,,1,0,0,0
access_dr_product_public_category_label_manager,dr.product.public.category.label.manager,model_dr_product_public_category_label,sales_team.group_sale_manager,1,1,1,1 access_dr_product_public_category_label_manager,dr.product.public.category.label.manager,model_dr_product_public_category_label,sales_team.group_sale_manager,1,1,1,1
access_dr_product_public_category_label_public,dr.product.public.category.label.public,model_dr_product_public_category_label,,1,0,0,0 access_dr_product_public_category_label_public,dr.product.public.category.label.public,model_dr_product_public_category_label,,1,0,0,0
access_dr_website_content_manager,dr.website.content.manager,model_dr_website_content,sales_team.group_sale_manager,1,1,1,1 access_dr_product_brand_manager,dr.product.brand.manager,model_dr_product_brand,sales_team.group_sale_manager,1,1,1,1
access_dr_website_content_public,dr.website.content.public,model_dr_website_content,,1,0,0,0 access_dr_product_brand_public,dr.product.brand.public,model_dr_product_brand,,1,0,0,0
access_dr_product_tags_manager,dr.product.tags.manager,model_dr_product_tags,sales_team.group_sale_manager,1,1,1,1
access_dr_product_tags_public,dr.product.tags.public,model_dr_product_tags,,1,0,0,0
access_dr_product_tabs_manager,dr.product.tabs.manager,model_dr_product_tabs,sales_team.group_sale_manager,1,1,1,1
access_dr_product_tabs_public,dr.product.tabs.public,model_dr_product_tabs,,1,0,0,0
access_dr_product_offer_manager,dr.product.offer.manager,model_dr_product_offer,sales_team.group_sale_manager,1,1,1,1
access_dr_product_offer_public,dr.product.offer.public,model_dr_product_offer,,1,0,0,0
access_dr_website_menu_label_designer,dr.website.menu.label.designer,model_dr_website_menu_label,website.group_website_designer,1,1,1,1 access_dr_website_menu_label_designer,dr.website.menu.label.designer,model_dr_website_menu_label,website.group_website_designer,1,1,1,1
access_dr_website_menu_label,dr.website.menu.label.public,model_dr_website_menu_label,,1,0,0,0 access_dr_website_menu_label,dr.website.menu.label.public,model_dr_website_menu_label,,1,0,0,0
access_dr_pwa_shortcuts_designer,dr.pwa.shortcuts.designer,model_dr_pwa_shortcuts,website.group_website_designer,1,1,1,1 access_dr_pwa_shortcuts_designer,dr.pwa.shortcuts.designer,model_dr_pwa_shortcuts,website.group_website_designer,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_dr_product_label_public dr.product.label.public model_dr_product_label 1 0 0 0
4 access_dr_product_public_category_label_manager dr.product.public.category.label.manager model_dr_product_public_category_label sales_team.group_sale_manager 1 1 1 1
5 access_dr_product_public_category_label_public dr.product.public.category.label.public model_dr_product_public_category_label 1 0 0 0
6 access_dr_website_content_manager access_dr_product_brand_manager dr.website.content.manager dr.product.brand.manager model_dr_website_content model_dr_product_brand sales_team.group_sale_manager 1 1 1 1
7 access_dr_website_content_public access_dr_product_brand_public dr.website.content.public dr.product.brand.public model_dr_website_content model_dr_product_brand 1 0 0 0
8 access_dr_product_tags_manager dr.product.tags.manager model_dr_product_tags sales_team.group_sale_manager 1 1 1 1
9 access_dr_product_tags_public dr.product.tags.public model_dr_product_tags 1 0 0 0
10 access_dr_product_tabs_manager dr.product.tabs.manager model_dr_product_tabs sales_team.group_sale_manager 1 1 1 1
11 access_dr_product_tabs_public dr.product.tabs.public model_dr_product_tabs 1 0 0 0
12 access_dr_product_offer_manager dr.product.offer.manager model_dr_product_offer sales_team.group_sale_manager 1 1 1 1
13 access_dr_product_offer_public dr.product.offer.public model_dr_product_offer 1 0 0 0
14 access_dr_website_menu_label_designer dr.website.menu.label.designer model_dr_website_menu_label website.group_website_designer 1 1 1 1
15 access_dr_website_menu_label dr.website.menu.label.public model_dr_website_menu_label 1 0 0 0
16 access_dr_pwa_shortcuts_designer dr.pwa.shortcuts.designer model_dr_pwa_shortcuts website.group_website_designer 1 1 1 1

View File

@ -4,7 +4,7 @@
<!-- Help START--> <!-- Help START-->
<div class="row pb16 pt16" style="padding: 10px;background-image: url(images/dots_bg.svg);"> <div class="row pb16 pt16" style="padding: 10px;background-image: url(images/dots_bg.svg);">
<a href="https://www.droggol.com/" target="_blank" style="width: 100%; display: block; text-align: center;"> <a href="https://www.droggol.com/" target="_blank" style="width: 100%; display: block; text-align: center;">
<img src="images/logo.svg" style="background-color: #3c4858; padding: 15px; max-width: 150px; text-align: center; margin: auto; border-radius: 8px;"/> <img src="https://www.droggol.com/images/14.0/droggol_theme_common_icon.png" style="background-color: #3c4858; padding: 15px; max-width: 150px; text-align: center; margin: auto; border-radius: 8px;"/>
</a> </a>
<div class="alert alert-warning text-center mt32 mb32" <div class="alert alert-warning text-center mt32 mb32"
style="padding: 21px 51px;background-color: #ffffff;border: 0px;border-top: 3px solid #0080FF;box-shadow: 0px 1px 7px 0px #35353521;color: #414d5c;margin: auto;display: block;border-radius: 1px;min-width: 80%;"> style="padding: 21px 51px;background-color: #ffffff;border: 0px;border-top: 3px solid #0080FF;box-shadow: 0px 1px 7px 0px #35353521;color: #414d5c;margin: auto;display: block;border-radius: 1px;min-width: 80%;">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -0,0 +1,38 @@
odoo.define('droggol_theme_common.list_view_brand', function (require) {
"use strict";
const core = require('web.core');
const Dialog = require('web.Dialog');
const ListController = require('web.ListController');
const ListView = require('web.ListView');
const viewRegistry = require('web.view_registry');
const _t = core._t;
const BrandListController = ListController.extend({
buttons_template: 'BrandListView.buttons',
events: _.extend({}, ListController.prototype.events, {
'click .o_button_reorder': '_onClickReorder',
}),
_onClickReorder: function () {
const self = this;
Dialog.confirm(this, _t('This will reorder sequence of all brands based on alphabetical order (from A to Z).'), {
confirm_callback: function () {
self._rpc({
model: self.modelName,
method: 'reorder_sequence',
}).then(() => self.reload());
}
});
},
});
const BrandListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Controller: BrandListController,
}),
});
viewRegistry.add('dr_list_view_brand', BrandListView);
});

View File

@ -0,0 +1,16 @@
odoo.define('droggol_theme_common.settings', function (require) {
const BaseSettingController = require('base.settings').Controller;
const FormController = require('web.FormController');
BaseSettingController.include({
_onButtonClicked: function (ev) {
if (ev.data.attrs.name === 'dr_open_pwa_shortcuts' || ev.data.attrs.name === 'dr_open_theme_custom_modules') {
FormController.prototype._onButtonClicked.apply(this, arguments);
} else {
this._super.apply(this, arguments);
}
},
});
});

View File

@ -1,273 +0,0 @@
/** @odoo-module **/
import { WebsiteDialog } from '@website/components/dialog/dialog';
import { evaluateExpr } from "@web/core/py_js/py";
const { Component, useState, onWillStart, onWillUpdateProps, toRaw } = owl;
import { useService } from '@web/core/utils/hooks';
import { useCore } from '@droggol_theme_common/js/hooks';
import { _t } from 'web.core';
export class AbstractThemeOption extends Component {
setup() {
this.key = this.props.key;
onWillUpdateProps(nextProps => {
this.updateVal(nextProps);
});
}
updateVal (props) {
if (props.visibilityExpr) {
props['visibility'] = evaluateExpr(props.visibilityExpr, props.source)
}
this.env.updateConfigValue(this.key, props.value)
}
updateSource (value) {
this.env.updateSource(this.key, value)
}
}
export class ThemeOptionTitle extends AbstractThemeOption {}
ThemeOptionTitle.template = 'theme_config.ThemeOptionTitle';
export class ThemeOptionRadio extends AbstractThemeOption {}
ThemeOptionRadio.template = 'theme_config.ThemeOptionRadio';
export class ThemeOptionSelection extends AbstractThemeOption {}
ThemeOptionSelection.template = 'theme_config.Selection';
export class ThemeOptionCheckbox extends AbstractThemeOption {}
ThemeOptionCheckbox.template = 'theme_config.Checkbox';
export class ThemeOptionCardBtnCheckbox extends AbstractThemeOption {}
ThemeOptionCardBtnCheckbox.template = 'theme_config.BtnCheckbox';
export class ThemeOptionNumber extends AbstractThemeOption {}
ThemeOptionNumber.template = 'theme_config.Number';
export class ThemeOptionChar extends AbstractThemeOption {}
ThemeOptionChar.template = 'theme_config.Char';
export class ThemeOptionJson extends AbstractThemeOption {
setup() {
super.setup();
this.updatedValue = this.props.value;
this._coreProps = {
updateConfigValue: this.updateConfigValue.bind(this),
updateSource: this.updateSource.bind(this),
};
useCore({subMode: true});
}
prepareProps (self_props, sub_props) {
var props = sub_props || {};
props['visibility'] = true;
props['source'] = self_props.source[self_props.key];
if (props.visibilityExpr) {
props['visibility'] = evaluateExpr(props.visibilityExpr, props['source'])
}
props['value'] = props['source'][sub_props.key] || false;
return props;
}
updateConfigValue (key, value) {
var rawValue = toRaw(this.updatedValue);
rawValue[key] = value;
this.env.updateConfigValue(this.key, rawValue);
}
updateSource (key, value) {
this.props.source[this.key][key] = value;
this.env.updateSource(this.key, this.props.source[this.key]);
}
}
ThemeOptionJson.template = 'theme_config.JSON';
export class ThemeOptionBottomBar extends AbstractThemeOption {
setup() {
super.setup();
this.orm = useService("orm");
this.state = useState({
'actions': this.props.value
});
onWillStart(async () => {
this.allButtons = await this.orm.call('website', 'get_theme_prime_bottom_bar_action_buttons');
});
}
removeAction (action) {
const index = this.state.actions.indexOf(action);
this.state.actions.splice(index, 1);
this.updateSource(this.state.actions);
}
addAction (action) {
this.state.actions.push(action);
this.updateSource(this.state.actions);
}
}
ThemeOptionBottomBar.template = 'theme_config.BottomBar';
export class ThemeConfigDialog extends Component {
setup() {
this.orm = useService('orm');
this.website = useService('website');
this.title = this.env._t("Theme Configuration");
this.primaryTitle = this.env._t("Save");
this.size = 'md';
this.updatedValue = {};
this.source = useState({});
this._coreProps = {
updateConfigValue: this.updateConfigValue.bind(this),
updateSource: this.updateSource.bind(this)
};
onWillStart(async () => {
var source = await this.orm.call("website", "get_dr_theme_config", [this.website.currentWebsite.id]);
for (var key in source) {
this.source[key] = source[key];
}
});
useCore({});
}
async saveConfig() {
await this.orm.call("dr.theme.config", "save_config", [[], this.website.currentWebsite.id, this.updatedValue]);
window.location.reload();
}
get _tabInfo() {
return [{
name: 'general',
icon: 'fa fa-sliders',
label: _t('General'),
components: [
{ props: { title: _t('Search'), subtitle: _t('Tweak search behavior for your website.'), _classes: 'mt-0'}, componentRef: ThemeOptionTitle },
{ props: { key: 'json_product_search', components: [
{ props: { key: 'advance_search', label: _t('Enable advance search')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'search_category', label: _t('Categories'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'search_attribute', label: _t('Smart Autocomplete'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'search_suggestion', label: _t('Smart Suggestion'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'search_fuzzy', label: _t('Fuzzy search'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'search_max_product', label: _t('Products limit'), tooltip: _("Max 5"), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionNumber },
{ props: { key: 'search_limit', label: _t('Result Limit'), tooltip: _("Min 5 and Max 10"), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionNumber },
]}, componentRef: ThemeOptionJson},
{ props: { key: 'cart_flow_title', title: _t('Cart Flow'), subtitle: _t('You can change how products are being added in cart.')}, key: 'cart_flow_title', componentRef: ThemeOptionTitle},
{ props: { key: 'cart_flow', selection: [['default', 'Default'], ['notification', 'Notification'], ['dialog', 'Dialog'], ['side_cart', 'Open Cart Sidebar']]}, componentRef: ThemeOptionRadio},
{ props: { key: 'brand_title', title: _t('Brand Page')}, componentRef: ThemeOptionTitle},
{ props: { key: 'json_brands_page', components: [
{ props: { key: 'disable_brands_grouping', label: _t('Disable grouping of brands')}, componentRef: ThemeOptionCheckbox }
]}, componentRef: ThemeOptionJson},
{ props: { key: 'lang_title', title: _t('Language/Pricelist Selector')}, componentRef: ThemeOptionTitle},
{ props: { key: 'json_general_language_pricelist_selector', components: [
{ props: { key: 'hide_country_flag', label: _t('Hide country flag')}, componentRef: ThemeOptionCheckbox }
]}, componentRef: ThemeOptionJson},
{ props: { title: _t('B2b Configuration'), subtitle: _t('Tweak your shop behavior.')}, componentRef: ThemeOptionTitle },
{ props: { key: 'json_b2b_shop_config', components: [{ props: { key: 'dr_enable_b2b', label: _t('B2B Mode'), tooltip: _("This option will hide product price for public users and don't allow them to place an order") }, componentRef: ThemeOptionCheckbox }, { props: { key: 'dr_only_assigned_pricelist', label: _t('Pricelist per customer'), tooltip: _("After enabling this option user will only see assigned pricelist to their contact record.") }, componentRef: ThemeOptionCheckbox }]}, componentRef: ThemeOptionJson},
]
}, {
name: 'shop',
icon: 'fa fa-shopping-cart',
label: _t('Shop'),
components: [
{ props: { title: _t('Shop'), subtitle: _t('Shop page main layout.'), _classes: 'mt-0' }, componentRef: ThemeOptionTitle },
{ props: { key: 'json_shop_layout', components: [
{ props: { key: 'layout', label: _t('Layout'), selection: [['prime', 'Prime'], ['default', 'Default']]}, componentRef: ThemeOptionSelection },
{ props: { key: 'show_view_switcher', label: _t('Show view switcher'), visibilityExpr: "layout == 'prime'"}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'default_view_mode', label: _t('Default view mode'), selection: [['grid', 'Grid'], ['list', 'List']], visibilityExpr: "layout == 'prime'"}, componentRef: ThemeOptionSelection },
{ props: { key: 'load_more_products', label: _t('Behavior of load more products'), selection: [['pager', 'Pager'], ['button', 'Load More Button'], ['scroll', 'Infinite Scroll']], visibilityExpr: "layout == 'prime'"}, componentRef: ThemeOptionSelection },
], visibilityKey: 'enable'}, componentRef: ThemeOptionJson},
{ props: { title: _t('Category Pills'), subtitle: _t('Show product category pills on top of the shop page.'), visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionTitle },
{ props: { key: 'json_shop_category_pills', components: [
{ props: { key: 'active', label: _t('Enable category pills')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'style', label: _t('Style'), selection: [['1', 'Card'], ['2', 'Text'], ['3', 'Image + Text'], ['4', 'Image + Text (Rounded)'], ['5', 'Image Only']], visibilityExpr: 'active'}, componentRef: ThemeOptionSelection },
{ props: { key: 'show_child_categories', label: _t('Show child categories pills of active category'), visibilityExpr: 'active'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'hide_in_desktop', label: _t('Hide in desktop device'), visibilityExpr: 'active'}, componentRef: ThemeOptionCheckbox },
], visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionJson},
{ props: { title: _t('Shop Filter'), subtitle: _t('Tweak filters behavior on shop.'), visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionTitle },
{ props: { key: 'json_shop_filters', components: [
{ props: { key: 'lazy_method', label: _t('Apply filters with lazy method') }, componentRef: ThemeOptionCheckbox },
{ props: { key: 'filter_style', label: _t('Filter Style'), selection: [['1', 'Clean'], ['2', 'Underline'], ['3', 'Card'], ['4', 'Bordered'], ['5', 'Boxed']]}, componentRef: ThemeOptionSelection },
{ props: { key: 'show_in_sidebar', label: _t('Show filters in sidebar')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'filter_position', label: _t('Filter Position'), selection: [['left', 'Left'], ['right', 'Right']], visibilityExpr: "show_in_sidebar == false"}, componentRef: ThemeOptionSelection },
{ props: { key: 'collapsible_category', label: _t('Collapsible category')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'collapsible_attribute', label: _t('Collapsible attributes')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'show_category_count', label: _t('Show category count')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'show_attribute_count', label: _t('Show attribute count') }, componentRef: ThemeOptionCheckbox },
{ props: { key: 'hide_extra_attrib_value', label: _t('Hide extra attributes'), tooltip: _("Hide attribute value if it is not matched with any product") }, componentRef: ThemeOptionCheckbox },
{ props: { key: 'show_rating_filter', label: _t('Show rating filter'), tooltip: _("To show rating filter, First you have to activate customers 'Rating' option in product detail page.")}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'show_availability_filter', label: _t('Show availability filter'), tooltip: _("If you have large number of products this option may affect performance.")}, componentRef: ThemeOptionCheckbox },
], visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionJson},
{ props: { title: _t('Product Card'), subtitle: _t('Configure actions and style of product card.'), visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionTitle },
{ props: { key: 'json_shop_product_item', components: [
{ props: { key: 'style', label: _t('Style'), selection: [['1', 'Square'], ['2', 'Rounded']]}, componentRef: ThemeOptionSelection },
{ props: { key: 'image_size', label: _t('Image Size'), selection: [['default', 'Default (1/1)'], ['landscape', 'Landscape (4/3)'], ['portrait', 'Portrait (4/5)'], ['vertical', 'Vertical (2/3)']]}, componentRef: ThemeOptionSelection },
{ props: { key: 'image_fill', label: _t('Image Fill'), selection: [['contain', 'Contain'], ['cover', 'Cover'], ['fill', 'Fill']]}, componentRef: ThemeOptionSelection },
{ props: { title: _t('Product Card Actions'), subtitle: _t('Configure action buttons of product card in shop page.')}, componentRef: ThemeOptionTitle },
{ props: { key: 'show_add_to_cart', icon: 'fa fa-shopping-cart', label: _t('Show add to cart')}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_wishlist', icon: 'fa fa-heart', label: _t('Show wishlist')}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_compare', icon: 'fa fa-retweet', label: _t('Show compare')}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_quick_view', icon: 'fa fa-eye', label: _t('Show quick view')}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_similar_products', icon: 'fa fa-clone', label: _t('Show similar products')}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_product_preview_swatches', icon: 'fa fa-adjust', label: _t('Show product preview swatches')}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_rating', icon: 'fa fa-star', label: _t('Show rating'), tooltip: _("To show rating, First you have to activate customers 'Rating' option in product detail page.")}, componentRef: ThemeOptionCardBtnCheckbox },
{ props: { key: 'show_stock_label', icon: 'fa fa-tag', label: _t('Show stock label')}, componentRef: ThemeOptionCardBtnCheckbox },
], visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionJson},
]
}, {
name: 'product_detail',
icon: 'fa fa-cube',
label: _t('Product Detail'),
components: [
{ props: { title: _t('Zoom Product Images'), subtitle: _t('Zoom product images in product detail page and quick view.'), _classes: 'mt-0' }, componentRef: ThemeOptionTitle },
{ props: { key: 'json_zoom', components: [
{ props: { key: 'zoom_enabled', label: _t('Enable zoom')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'zoom_factor', label: _t('Zoom factor'), visibilityExpr: 'zoom_enabled'}, componentRef: ThemeOptionNumber },
], visibilityKey: 'zoom_enabled'}, componentRef: ThemeOptionJson},
{ props: { title: _t('Sticky Add to Cart'), subtitle: _t("Allows users to follow up product's Add to Cart button until bottom scroll reached."), }, componentRef: ThemeOptionTitle },
{ props: { key: 'bool_sticky_add_to_cart', 'label': _t('Enable sticky add to cart') }, componentRef: ThemeOptionCheckbox},
{ props: { title: _t('Product Offers'), subtitle: _t("You will be able to add offers on product and show details in dialog.")}, componentRef: ThemeOptionTitle },
{ props: { key: 'bool_product_offers', 'label': _t('Enable product offers') }, componentRef: ThemeOptionCheckbox},
{ props: { title: _t('General')}, componentRef: ThemeOptionTitle },
{ props: { key: 'bool_show_products_nav', 'label': _t('Product Navigation'), tooltip: _t("Shows button to see next, previous products based on product sequence.") }, componentRef: ThemeOptionCheckbox},
]
}, {
name: 'mobile',
icon: 'fa fa-mobile',
label: _t('Mobile'),
components: [
{ props: { title: _t('Sidebar'), subtitle: _t('You can change behaviour of sidebars.'), _classes: 'mt-0' }, componentRef: ThemeOptionTitle },
{ props: { key: 'json_sidebar_config', components: [
{ props: { key: 'category_sidebar_style', label: _t('Category sidebar style'), selection: [['1', 'Text'], ['2', 'Image + Text'], ['3', 'Cover']]}, componentRef: ThemeOptionSelection },
{ props: { key: 'category_sidebar_show_count', label: _t('Show product count in category sidebar') }, componentRef: ThemeOptionCheckbox },
{ props: { key: 'menu_sidebar_show_category', label: _t('Show category link in menu sidebar') }, componentRef: ThemeOptionCheckbox },
]}, componentRef: ThemeOptionJson},
{ props: { title: _t('Bottombar'), subtitle: _t("Bottom bar allow movement between primary destinations on the website.")}, componentRef: ThemeOptionTitle },
{ props: { key: 'json_bottom_bar', components: [
{ props: { key: 'show_bottom_bar', label: _t('Show Bottombar')}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'show_bottom_bar_on_scroll', label: _t('Show Bottombar On Scroll'), visibilityExpr: 'show_bottom_bar'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'filters', label: _t('Show sort and filter button on shop'), visibilityExpr: 'show_bottom_bar'}, componentRef: ThemeOptionCheckbox },
{ props: { key: 'actions', label: _t('Buttombar Buttons'), visibilityExpr: 'show_bottom_bar'}, componentRef: ThemeOptionBottomBar },
], visibilityKey: 'show_bottom_bar'}, componentRef: ThemeOptionJson},
]
}
];}
prepareProps (props) {
props = props || {};
props['source'] = this.source;
props['visibility'] = true;
if (props.key) {
props['value'] = this.source[props.key] || false;
}
if (props.visibilityExpr) {
props['visibility'] = evaluateExpr(props.visibilityExpr, this.source)
}
return props;
}
updateConfigValue (key, value) {
this.updatedValue[key] = value;
}
updateSource (key, value) {
this.source[key] = value;
}
}
ThemeConfigDialog.template = 'droggol_theme_common.ThemeConfigDialog';
ThemeConfigDialog.components = { WebsiteDialog };

View File

@ -1,75 +0,0 @@
$tp-setting-color: #0080ff;
.tp_config_dialog {
border-radius: 16px;
.text-primary {
color: $tp-setting-color !important;
}
.bg-tpc-primary {
background-color: $tp-setting-color;
color: #fff;
}
.bg-tpc-primary-dark {
background-color: darken($tp-setting-color, 10%);
color: #fff;
}
.tp-cp {
cursor: pointer;
}
.pe-24 {
padding-right: 24px !important;
}
header {
h4, .btn-close{
display: none;
}
}
.tp-setting-tab{
font-weight: bold;
border-radius: 6px;
letter-spacing: 1px;
color: #000;
&.active {
background-color: rgba($tp-setting-color, 0.15);
color: $tp-setting-color;
}
}
.o_switch {
input + span {
padding-left: 4px;
padding-right: 2px;
width: 37px;
height: 21px;
background: #c1ccdd !important;
&:after {
margin-top: 1px;
display: inline-block;
}
}
input:checked + span {
background: #06bb72 !important;
// background: $tp-setting-color !important;
}
}
.tp-setting-bg {
background-color: #e7f1ff;
border-radius: 10px;
}
.form-check-input:checked {
background-color: $tp-setting-color;
border-color: $tp-setting-color;
}
.btn-outline-primary {
border-color: $tp-setting-color;
color: $tp-setting-color;
&:hover {
background-color: #c1ccdd;
}
}
.btn-check:checked + .btn-outline-primary {
background-color: $tp-setting-color;
border-color: $tp-setting-color;
}
}

View File

@ -1,181 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="droggol_theme_common.ThemeConfigDialog" owl="1">
<WebsiteDialog title="title" size="size" header="true" primaryTitle="primaryTitle" primaryClick="() => this.saveConfig()" close="props.close" contentClass="'tp_config_dialog'">
<t t-portal="'.tp_config_dialog header'">
<div class="row g-0">
<div class="col-3">
<img src="/droggol_theme_common/static/src/images/settings.png" class="img-fluid"/>
</div>
<div class="col-9">
<ul class="nav nav-pills mb-3 float-end mt-3" id="tp-settings-pills-tab" role="tablist">
<t t-foreach="_tabInfo" t-as="tabData" t-key="tabData.name">
<li class="nav-item" role="presentation">
<button t-attf-class="nav-link tp-setting-tab #{tabData_index == 0 ? 'active': ''}" id="pills-home-tab" data-bs-toggle="pill" t-attf-data-bs-target="#pills-#{tabData.name}" type="button" role="tab">
<i t-att-class="tabData.icon" /> <t t-esc="tabData.label"/>
</button>
</li>
</t>
</ul>
</div>
</div>
</t>
<t t-portal="'.tp_config_dialog footer'">
<a class="btn btn-link position-absolute end-0 me-2" href="https://prime-docs-v16-25092021.droggol.com/" target="_blank">
<i class="fa fa-book me-1"/> User Guide
</a>
</t>
<div class="row">
<div class="col-12">
<div class="tab-content" id="tp-settings-pills-tabContent">
<t t-foreach="_tabInfo" t-as="tabData" t-key="tabData.name">
<div t-attf-class="tab-pane #{tabData_index == 0 ? 'fade show active': ''} p-2" t-attf-id="pills-#{tabData.name}" role="tabpanel">
<t t-foreach="tabData.components" t-as="component_data" t-key="component_data_index">
<t t-component="component_data.componentRef" t-props="prepareProps(component_data.props)"/>
</t>
</div>
</t>
</div>
</div>
<!-- <div class="col-6">
<div class="p-2 h-100 tp-setting-bg">
asd
</div>
</div> -->
</div>
</WebsiteDialog>
</t>
<t t-name="theme_config.ThemeOptionTitle" owl="1">
<t t-if="props.visibility">
<h5 t-attf-class="mb-0 text-primary tp-config-title #{props._classes or 'mt-5'}">
<t t-esc="props.title"/>
</h5>
<p t-if="props.subtitle" class="text-muted mt-1 mb-2">
<t t-esc="props.subtitle"/>
</p>
</t>
</t>
<t t-name="theme_config.ThemeOptionRadio" owl="1">
<div t-att-invisible="!props.visibility">
<div class="form-check">
<input class="form-check-input" name="key" type="radio" id="default" value="default" t-model="props.source[key]"/>
<label class="form-check-label" t-attf-for="default">
Default
</label>
</div>
<div class="form-check">
<input class="form-check-input" name="key" type="radio" id="notification" value="notification" t-model="props.source[key]"/>
<label class="form-check-label" t-attf-for="notification">
Notification
</label>
</div>
<div class="form-check">
<input class="form-check-input" name="key" type="radio" id="dialog" value="dialog" t-model="props.source[key]"/>
<label class="form-check-label" t-attf-for="dialog">
Dialog
</label>
</div>
<div class="form-check">
<input class="form-check-input" name="key" type="radio" id="side_cart" value="side_cart" t-model="props.source[key]"/>
<label class="form-check-label" t-attf-for="side_cart">
Open Cart Sidebar
</label>
</div>
</div>
<!-- <t t-foreach="props.selection" t-as="opt" t-key="opt[0]">
<t t-esc="props.source[key]" />
<div class="form-check">
<input class="form-check-input" t-att-name="key" type="radio" t-att-id="opt[0]" t-att-value="opt[0]" t-model="props.source[key]"/>
<label class="form-check-label" t-attf-for="opt[0]">
<t t-esc="opt[1]"/>
</label>
</div>
</t> -->
</t>
<t t-name="theme_config.Selection" owl="1">
<div t-attf-class="row mb-2 #{props._classes or ''}" t-att-expr="props.visibilityExpr" t-if="props.visibility">
<div class="col-6 col-lg-5">
<strong t-esc="props.label"/>
<i t-if="props.tooltip" class="fa fa-info-circle ms-2" t-att-title="props.tooltip"/>
</div>
<div class="col-6 col-lg-7">
<label class="mb-0 d-inline-block" t-att-for="key">
<select t-model="props.source[key]" class="form-select form-select-sm">
<t t-foreach="props.selection" t-as="item" t-key="item_index">
<option t-att-value="item[0]">
<t t-esc="item[1]"/>
</option>
</t>
</select>
</label>
<small t-if="note" class="d-block"><t t-esc="props.note"/></small>
</div>
</div>
</t>
<t t-name="theme_config.Checkbox" t-inherit="theme_config.Selection" t-inherit-mode="primary" owl="1">
<xpath expr="//label" position="replace">
<label class="o_switch mb-0 o_switch_danger_success w-25">
<input type="checkbox" t-model="props.source[key]"/>
<span> </span>
</label>
</xpath>
</t>
<t t-name="theme_config.Number" t-inherit="theme_config.Selection" t-inherit-mode="primary" owl="1">
<xpath expr="//div[hasclass('col-lg-7')]" position="replace">
<div class="col-6 col-lg-3">
<input type="number" class="form-control form-control-sm" t-att-id="props.key" t-model.number="props.source[key]"/>
<small t-if="note" class="d-block"> <t t-esc="props.note"/></small>
</div>
</xpath>
</t>
<t t-name="theme_config.Char" t-inherit="theme_config.Selection" t-inherit-mode="primary" owl="1">
<xpath expr="//div[hasclass('col-lg-7')]" position="replace">
<div class="col-6 col-lg-3">
<input type="text" class="form-control form-control-sm" t-att-id="props.key" t-model="props.source[key]"/>
<small t-if="note" class="d-block"> <t t-esc="props.note"/></small>
</div>
</xpath>
</t>
<t t-name="theme_config.JSON" owl="1">
<t t-if="props.visibility">
<t t-foreach="props.components" t-as="sub_component_data" t-key="sub_component_data_index">
<t t-component="sub_component_data.componentRef" t-props="prepareProps(props, sub_component_data.props)"/>
</t>
</t>
</t>
<t t-name="theme_config.BottomBar" t-inherit="theme_config.Selection" t-inherit-mode="primary" owl="1">
<xpath expr="//label" position="replace">
<div class="border border-1 p-2 pb-0 rounded">
<t t-foreach="state.actions" t-as="action" t-key="action">
<span class="badge bg-tpc-primary d-inline-block p-2 pe-24 mx-1 position-relative overflow-hidden">
<t t-out="allButtons[action].name"/>
<i class="fa fa-times position-absolute top-0 end-0 bg-tpc-primary-dark h-100 px-2 py-2 tp-cp" t-on-click="() => this.removeAction(action)"/>
</span>
</t>
</div>
<div>
<t t-foreach="allButtons" t-as="button" t-key="button">
<span t-if="!state.actions.includes(button)" class="badge bg-300 d-inline-block p-2 px-3 mx-1 mt-1 tp-cp position-relative" t-on-click="() => this.addAction(button)">
<i class="fa fa-plus" /> <t t-out="allButtons[button].name"/>
</span>
</t>
</div>
</xpath>
</t>
<t t-name="theme_config.BtnCheckbox" owl="1">
<input type="checkbox" class="btn-check" t-att-id="key" autocomplete="off" t-model="props.source[key]"/>
<label class="btn btn-outline-primary me-2" t-att-for="key" t-att-title="props.tooltip || props.label"><i t-att-class="props.icon or 'fa fa-users'"/> </label>
</t>
</templates>

View File

@ -1,21 +0,0 @@
/** @odoo-module **/
import { useComponent, useChildSubEnv} from "@odoo/owl";
// We add here a custom hook
function extendUseCore(cc, newCore, subMode) {
if (!subMode) {
const currentCore = Object.create(cc.env);
const newCoreDescriptors = Object.getOwnPropertyDescriptors(newCore);
cc.env = Object.freeze(Object.defineProperties(currentCore, newCoreDescriptors));
}
useChildSubEnv(newCore)
}
export function useCore({core = false, subMode = false}) {
const cc = useComponent();
core = core || cc._coreProps;
if (core) {
extendUseCore(cc, core, subMode)
}
}

View File

@ -1,10 +0,0 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { ThemeConfigDialog } from '../components/theme_config';
registry.category('website_custom_menus').add('droggol_theme_common.menu_theme_prime_config', {
Component: ThemeConfigDialog,
isDisplayed: (env) => !!env.services.website.currentWebsite
&& env.services.website.isDesigner
});

View File

@ -1,56 +1,56 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Variants // Variants
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
.dr-attribute-info-btn { .dr-variant {
display: none; .radio_input_value {
} margin-right: 0.4rem;
.dr-attribute-item { .dr-variant-item {
.dr-value-item { &.circle {
&.circle { padding: 0;
padding: 0; height: 38px;
height: 38px; width: 38px;
width: 38px; line-height: 38px;
line-height: 38px; text-align: center;
text-align: center; border-radius: 50%;
border-radius: 50%;
}
&.square {
padding: 6px 12px;
border-radius: $border-radius;
}
&.circle, &.square {
background-color: o-color('white');
border: 1px solid o-color('300');
transition: 0.2s;
font-weight: $font-weight-normal;
cursor: pointer;
&:hover {
border-color: o-color('primary');
color: o-color('primary');
} }
} &.square {
&.image { padding: 6px 12px;
margin-right: 0.4rem; border-radius: $border-radius;
border-width: 0;
transition: 0.2s;
cursor: pointer;
box-shadow: 0px 0px 0px 2px o-color('300');
&:hover {
box-shadow: 0px 0px 0px 2px o-color('primary');
} }
img { &.circle, &.square {
padding: 2px; background-color: o-color('white');
object-fit: contain; border: 1px solid o-color('300');
height: 40px; transition: 0.2s;
width: 40px; font-weight: $font-weight-normal;
cursor: pointer;
@include hover {
border-color: o-color('primary');
color: o-color('primary');
}
}
&.image {
margin-right: 0.4rem;
border-width: 0;
transition: 0.2s;
cursor: pointer;
box-shadow: 0px 0px 0px 2px o-color('300');
@include hover {
box-shadow: 0px 0px 0px 2px o-color('primary');
}
img {
padding: 2px;
object-fit: contain;
height: 40px;
width: 40px;
}
} }
} }
} }
input:checked ~ .radio_input_value .dr-value-item { input:checked ~ .radio_input_value .dr-variant-item {
&.circle, &.square { &.circle, &.square {
background-color: o-color('primary'); background-color: o-color('primary');
border-color: o-color('primary'); border-color: o-color('primary');
color: color-contrast(o-color('primary')); color: color-yiq(o-color('primary'));
} }
&.image { &.image {
box-shadow: 0px 0px 0px 2px o-color('primary'); box-shadow: 0px 0px 0px 2px o-color('primary');

View File

@ -1,11 +0,0 @@
.s_mega_menu_prime_3 .s_badge {
margin: 0;
margin-left: 0.4rem;
padding: 0.4em 0.6em;
font-size: 0.66rem;
border-radius: 3px;
padding-top: 5px;
i {
margin-right: 0.3rem;
}
}

View File

@ -1,7 +0,0 @@
.s_mega_menu_prime_6 .tp-banner-block {
min-height: 400px;
.tp-banner-text {
@include o-position-absolute($right: 18px, $bottom: 20px, $left: 18px);
padding: 1rem;
}
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-extend="ListView.buttons" t-name="BrandListView.buttons">
<t t-jquery="button.o_list_button_add" t-operation="after">
<button type="button" class="btn btn-secondary o_button_reorder">
Reorder Sequence
</button>
</t>
</t>
</templates>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_frontend" inherit_id="website.assets_frontend">
<xpath expr="//link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/droggol_theme_common/static/src/scss/variants.scss"/>
</xpath>
</template>
<template id="assets_backend" inherit_id="web.assets_backend">
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/droggol_theme_common/static/src/js/backend/list_view_brand.js"/>
<script type="text/javascript" src="/droggol_theme_common/static/src/js/backend/res_config_settings.js"/>
</xpath>
</template>
<template id="assets_backend_inherit_sale" inherit_id="sale.assets_backend_inherit_sale">
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/droggol_theme_common/static/src/scss/variants.scss"/>
</xpath>
</template>
</odoo>

View File

@ -1,18 +1,56 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record id="dr_category_label_view_form" model="ir.ui.view">
<field name="name">dr.product.public.category.label.view.form</field>
<field name="model">dr.product.public.category.label</field>
<field name="arch" type="xml">
<form string="Label">
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="action_open_category" icon="fa-bars" attrs="{'invisible': [('category_count', '=', 0)]}">
<field string="Categories" name="category_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="color"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="dr_category_label_view_tree" model="ir.ui.view"> <record id="dr_category_label_view_tree" model="ir.ui.view">
<field name="name">dr.product.public.category.label.view.tree</field> <field name="name">dr.product.public.category.label.view.tree</field>
<field name="model">dr.product.public.category.label</field> <field name="model">dr.product.public.category.label</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Labels" editable="bottom"> <tree string="Labels">
<field name="name"/> <field name="name"/>
<field name="background_color" widget="color"/> <field name="color"/>
<field name="text_color" widget="color"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="dr_category_label_view_search" model="ir.ui.view">
<field name="name">dr.product.public.category.label.view.search</field>
<field name="model">dr.product.public.category.label</field>
<field name="arch" type="xml">
<search string="Labels">
<field name="name"/>
<field name="color"/>
<group>
<filter string="Color" name="color" domain="" context="{'group_by': 'color'}"/>
</group>
</search>
</field>
</record>
<record id="dr_category_label_action" model="ir.actions.act_window"> <record id="dr_category_label_action" model="ir.actions.act_window">
<field name="name">Category Labels</field> <field name="name">Category Labels</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
@ -20,6 +58,6 @@
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<menuitem id="menu_dr_category_label" action="dr_category_label_action" parent="website_sale.menu_catalog" sequence="5"/> <menuitem id="menu_dr_category_lable" action="dr_category_label_action" parent="website_sale.menu_product_settings" sequence="5"/>
</odoo> </odoo>

View File

@ -21,11 +21,4 @@
<menuitem id="dr_theme_config_menu" name="Droggol Theme Config" action="dr_theme_config_action" parent="base.menu_ir_property"/> <menuitem id="dr_theme_config_menu" name="Droggol Theme Config" action="dr_theme_config_action" parent="base.menu_ir_property"/>
<menuitem id="menu_theme_prime_config"
parent="website.menu_site"
sequence="21"
name="Theme Prime Configuration"
action="website.website_preview"
/>
</odoo> </odoo>

View File

@ -1,88 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="dr_website_content_view_form" model="ir.ui.view">
<field name="name">dr.website.content.view.form</field>
<field name="model">dr.website.content</field>
<field name="arch" type="xml">
<form string="Content">
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="open_design_page" icon="fa-paint-brush">
<div class="o_stat_info">
<span class="o_stat_value">
Design
</span>
<span class="o_stat_text">
Content
</span>
</div>
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="content_type" widget="radio" attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="identifier" groups="base.group_no_one"/>
<field name="description" attrs="{'invisible': [('content_type', 'in', ['tab', 'attribute_popup'])]}"/>
<field name="icon" attrs="{'invisible': [('content_type', 'in', ['attribute_popup'])]}"/>
</group>
</group>
<p attrs="{'invisible': [('content_type', 'in', ['attribute_popup'])]}">You can find icon at <a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">FontAwesome</a>.</p>
<notebook>
<page name="tab_products" string="Products" attrs="{'invisible': [('content_type', 'in', ['offer_popup', 'attribute_popup'])]}">
<field name="dr_tab_products_ids" />
</page>
<page name="offer_products" string="Products" attrs="{'invisible': [('content_type', 'in', ['tab', 'attribute_popup'])]}">
<field name="dr_offer_products_ids" />
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="dr_website_content_view_tree" model="ir.ui.view">
<field name="name">dr.website.content.view.tree</field>
<field name="model">dr.website.content</field>
<field name="arch" type="xml">
<tree string="Content">
<field name="sequence" widget="handle"/>
<field name="content_type" widget="badge" decoration-info="content_type == 'tab'" decoration-success="content_type == 'offer_popup'" decoration-warning="content_type == 'attribute_popup'"/>
<field name="name"/>
</tree>
</field>
</record>
<record id="dr_website_content_view_search" model="ir.ui.view">
<field name="name">dr.website.content.view.search</field>
<field name="model">dr.website.content</field>
<field name="arch" type="xml">
<search string="Content">
<field name="name"/>
<field name="content_type"/>
<group expand="0" string="Group By">
<filter string="Content Type" name="group_by_content_type" domain="[]" context="{'group_by': 'content_type'}"/>
</group>
</search>
</field>
</record>
<record id="dr_website_content_action" model="ir.actions.act_window">
<field name="name">Contents</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">dr.website.content</field>
<field name="view_mode">tree,form</field>
<field name="context">{'search_default_group_by_content_type': True}</field>
</record>
<menuitem id="menu_dr_website_content"
action="dr_website_content_action"
parent="website_sale.menu_catalog" sequence="5"/>
</odoo>

View File

@ -1,18 +1,58 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record id="dr_website_menu_label_view_form" model="ir.ui.view">
<field name="name">dr.website.menu.label.view.form</field>
<field name="model">dr.website.menu.label</field>
<field name="arch" type="xml">
<form string="Label">
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="action_open_menus" icon="fa-bars" attrs="{'invisible': [('menu_count', '=', 0)]}">
<field string="Menus" name="menu_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="color"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="dr_website_menu_label_view_tree" model="ir.ui.view"> <record id="dr_website_menu_label_view_tree" model="ir.ui.view">
<field name="name">dr.website.menu.label.view.tree</field> <field name="name">dr.website.menu.label.view.tree</field>
<field name="model">dr.website.menu.label</field> <field name="model">dr.website.menu.label</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Labels" editable="bottom"> <tree string="Labels">
<field name="name"/> <field name="name"/>
<field name="background_color" widget="color"/> <field name="color"/>
<field name="text_color" widget="color"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="dr_website_menu_label_view_search" model="ir.ui.view">
<field name="name">dr.website.menu.label.view.search</field>
<field name="model">dr.website.menu.label</field>
<field name="arch" type="xml">
<search string="Labels">
<field name="name"/>
<field name="color"/>
<group>
<filter string="Color" name="color" domain="" context="{'group_by': 'color'}"/>
</group>
</search>
</field>
</record>
<record id="dr_website_menu_label_action" model="ir.actions.act_window"> <record id="dr_website_menu_label_action" model="ir.actions.act_window">
<field name="name">Menu Labels</field> <field name="name">Menu Labels</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
@ -21,10 +61,10 @@
</record> </record>
<menuitem name="Menu Labels" <menuitem name="Menu Labels"
id="menu_dr_website_menu_label" id="menu_dr_website_menu_label"
action="dr_website_menu_label_action" action="dr_website_menu_label_action"
parent="website.menu_website_global_configuration" parent="website.menu_website_global_configuration"
sequence="46" sequence="46"
groups="base.group_no_one"/> groups="base.group_no_one"/>
</odoo> </odoo>

View File

@ -4,43 +4,27 @@
<record id="product_attribute_view_form_inherit_droggol_theme_common" model="ir.ui.view"> <record id="product_attribute_view_form_inherit_droggol_theme_common" model="ir.ui.view">
<field name="name">product.attribute.view.form.inherit</field> <field name="name">product.attribute.view.form.inherit</field>
<field name="model">product.attribute</field> <field name="model">product.attribute</field>
<field name="inherit_id" ref="website_sale.product_attribute_view_form"/> <field name="inherit_id" ref="product.product_attribute_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="visibility" position="replace"/> <field name="create_variant" position="after">
<page name="attribute_values" position="after"> <field name="dr_is_hide_shop_filter"/>
<page name="ecommerce" string="eCommerce"> <field name="dr_is_show_shop_search"/>
<group class="o_label_nowrap"> </field>
<group>
<field name="visibility" string="eCommerce Filter Visibility" widget="radio"/>
<field name="dr_is_brand"/>
<field name="dr_is_show_shop_search"/>
<field name="dr_attribute_popup_id" context="{'default_content_type': 'attribute_popup'}"/>
<field name="dr_search_suggestion"/>
</group>
<group>
<field name="dr_radio_image_style" widget="radio" attrs="{'invisible': [('display_type', '!=', 'radio_image')]}"/>
</group>
</group>
</page>
</page>
<xpath expr="//field[@name='value_ids']/tree/field[last()]" position="after"> <xpath expr="//field[@name='value_ids']/tree/field[last()]" position="after">
<field name="dr_brand_description" attrs="{'column_invisible': [('parent.dr_is_brand', '=', False)]}"/> <field name="dr_image" attrs="{'column_invisible': [('parent.display_type', '!=', 'radio_image')]}" widget="image"/>
<field name="dr_image" attrs="{'column_invisible': [('parent.display_type', '!=', 'radio_image')]}" widget="image" class="oe_avatar"/>
</xpath>
<xpath expr="//field[@name='value_ids']/tree/field[@name='is_custom']" position="attributes">
<attribute name="attrs">{'column_invisible': [('parent.dr_is_brand', '=', True)]}</attribute>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="product_template_attribute_value_inherit_droggol_theme_common" model="ir.ui.view"> <record id="product_template_attribute_value_view_form_inherit_droggol_theme_common" model="ir.ui.view">
<field name="name">product.template.attribute.value.view.form.inherit</field> <field name="name">product.template.attribute.value.view.form.inherit</field>
<field name="model">product.template.attribute.value</field> <field name="model">product.template.attribute.value</field>
<field name="inherit_id" ref="product.product_template_attribute_value_view_form"/> <field name="inherit_id" ref="product.product_template_attribute_value_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='html_color']" position="after"> <field name="html_color" position="after">
<field name="dr_thumb_image" widget="image" nolabele="1" attrs="{'invisible': [('display_type', '!=', 'color')]}" class="oe_avatar float-start"/> <field name="dr_image" widget="image" attrs="{'invisible': [('display_type', '!=', 'radio_image')]}"/>
</xpath> </field>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@ -1,68 +1,113 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record id="dr_product_brand_values_view_form" model="ir.ui.view"> <record id="dr_product_brand_view_form" model="ir.ui.view">
<field name="name">product.attribute.value.view.form</field> <field name="name">dr.product.brand.view.form</field>
<field name="model">product.attribute.value</field> <field name="model">dr.product.brand</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Brand" create="false"> <form string="Brand">
<sheet> <sheet>
<field name="dr_image" widget="image" class="oe_avatar"/> <div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="action_open_products" icon="fa-cubes" attrs="{'invisible': [('product_count', '=', 0)]}">
<field string="Products" name="product_count" widget="statinfo"/>
</button>
</div>
<field name="image" widget="image" class="oe_avatar"/>
<div class="oe_title"> <div class="oe_title">
<label for="name" string="Name"/> <label for="name"/>
<h1> <h1>
<field name="name"/> <field name="name"/>
</h1> </h1>
</div> </div>
<group> <group>
<group> <group>
<field name="dr_brand_description"/> <field name="description" widget="text"/>
</group>
<group>
<field name="website_id"/>
<field name="active" invisible="1"/>
</group> </group>
</group> </group>
<notebook>
<page name="products" string="Products">
<field name="product_ids" string="Products" mode="kanban" options="{'create_text':'Add a Product'}" context="{'default_dr_brand_id': active_id, 'default_website_id': website_id}"/>
</page>
</notebook>
</sheet> </sheet>
</form> </form>
</field> </field>
</record> </record>
<record id="dr_product_brand_values_view_tree" model="ir.ui.view"> <record id="dr_product_brand_view_tree" model="ir.ui.view">
<field name="name">product.attribute.value.view.tree</field> <field name="name">dr.product.brand.view.tree</field>
<field name="model">product.attribute.value</field> <field name="model">dr.product.brand</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Brands" expand="1" create="0"> <tree string="Brands" js_class="dr_list_view_brand">
<field name="sequence" widget="handle"/> <field name="sequence" widget="handle"/>
<field name="name" string="Name"/> <field name="name"/>
<field name="attribute_id" invisible="1"/> <field name="description"/>
<groupby name="attribute_id"> <field name="website_id"/>
<button name="open_create_brand_value" string="Add New Brand" type="object" class=""/>
</groupby>
</tree> </tree>
</field> </field>
</record> </record>
<record id="dr_product_brand_values_view_search" model="ir.ui.view"> <record id="dr_product_brand_view_kanban" model="ir.ui.view">
<field name="name">product.attribute.value.view.search</field> <field name="name">dr.product.brand.view.kanban</field>
<field name="model">product.attribute.value</field> <field name="model">dr.product.brand</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Brands"> <kanban>
<field name="id"/>
<field name="name"/> <field name="name"/>
<group expand="0" string="Group By"> <field name="description"/>
<filter string="Attributes" name="group_by_attributes" domain="[]" context="{'group_by': 'attribute_id'}"/> <field name="product_count"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click">
<div class="o_kanban_image mr-3">
<img t-att-src="kanban_image('dr.product.brand', 'image', record.id.raw_value)" alt="Product" class="o_image_64_contain"/>
</div>
<div class="oe_kanban_details">
<h4 class="mb-0">
<field name="name"/>
</h4>
<p class="mb-2" t-esc="record.description.value"/>
<h6 t-if="record.product_count.value > 0" class="rounded-pill d-inline-block border py-2 px-3 mb-0" t-attf-title="#{record.product_count.value} product(s) in this brand.">
<i class="fa fa-cubes" aria-label="Products"/> <span t-esc="record.product_count.value"/>
</h6>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="dr_product_brand_view_search" model="ir.ui.view">
<field name="name">dr.product.brand.view.search</field>
<field name="model">dr.product.brand</field>
<field name="arch" type="xml">
<search string="Product Brand">
<field name="name"/>
<field name="description"/>
<field name="website_id"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group>
<filter string="Website" name="website" domain="" context="{'group_by':'website_id'}"/>
</group> </group>
</search> </search>
</field> </field>
</record> </record>
<record id="dr_product_brand_values_action" model="ir.actions.act_window"> <record id="dr_product_brand_action" model="ir.actions.act_window">
<field name="name">Brands</field> <field name="name">Brands</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">product.attribute.value</field> <field name="res_model">dr.product.brand</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,kanban,form</field>
<field name="domain" eval="[('attribute_id.dr_is_brand', '=', True)]"/>
<field name="context">{'search_default_group_by_attributes': True}</field>
</record> </record>
<menuitem id="menu_dr_product_brand_values" <menuitem id="menu_dr_product_brand"
action="dr_product_brand_values_action" action="dr_product_brand_action"
parent="website_sale.menu_catalog" sequence="5"/> parent="website_sale.menu_product_settings" sequence="4"/>
</odoo> </odoo>

View File

@ -6,23 +6,10 @@
<field name="model">product.public.category</field> <field name="model">product.public.category</field>
<field name="inherit_id" ref="website_sale.product_public_category_form_view"/> <field name="inherit_id" ref="website_sale.product_public_category_form_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<div class="oe_left" position="after"> <xpath expr="//field[@name='website_id']" position="after">
<notebook> <field name="dr_category_label_id"></field>
<page name="theme_prime" string="Theme Prime"> <field name="dr_category_cover_image"></field>
<group> </xpath>
<group>
<field name="dr_category_label_id"/>
<field name="dr_search_formulate" groups="base.group_no_one"/>
</group>
<group>
<field name="dr_category_cover_image" class="oe_avatar" widget="image"/>
<field name="dr_category_icon" class="oe_avatar" widget="image"/>
<field name="dr_category_sidebar_cover" class="oe_avatar" widget="image"/>
</group>
</group>
</page>
</notebook>
</div>
</field> </field>
</record> </record>

View File

@ -12,7 +12,6 @@
<field string="Products" name="product_count" widget="statinfo"/> <field string="Products" name="product_count" widget="statinfo"/>
</button> </button>
</div> </div>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<div class="oe_title"> <div class="oe_title">
<label for="name"/> <label for="name"/>
<h1> <h1>
@ -21,14 +20,16 @@
</div> </div>
<group> <group>
<group> <group>
<field name="background_color" widget="color"/> <field name="color"/>
<field name="text_color" widget="color"/>
</group>
<group>
<field name="style"/> <field name="style"/>
<field name="active" invisible="1"/> <field name="active" invisible="1"/>
</group> </group>
</group> </group>
<notebook>
<page name="products" string="Products">
<field name="product_ids" string="Products" mode="kanban" options="{'create_text':'Add a Product'}" context="{'default_dr_label_id': active_id}"/>
</page>
</notebook>
</sheet> </sheet>
</form> </form>
</field> </field>
@ -40,8 +41,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Labels"> <tree string="Labels">
<field name="name"/> <field name="name"/>
<field name="background_color" widget="color"/> <field name="color"/>
<field name="text_color" widget="color"/>
<field name="style"/> <field name="style"/>
</tree> </tree>
</field> </field>
@ -53,8 +53,11 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Labels"> <search string="Labels">
<field name="name"/> <field name="name"/>
<field name="color"/>
<field name="style"/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/> <filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group> <group>
<filter string="Color" name="color" domain="" context="{'group_by':'color'}"/>
<filter string="Style" name="style" domain="" context="{'group_by':'style'}"/> <filter string="Style" name="style" domain="" context="{'group_by':'style'}"/>
</group> </group>
</search> </search>
@ -70,6 +73,6 @@
<menuitem id="menu_dr_product_label" <menuitem id="menu_dr_product_label"
action="dr_product_label_action" action="dr_product_label_action"
parent="website_sale.menu_catalog" sequence="5"/> parent="website_sale.menu_product_settings" sequence="5"/>
</odoo> </odoo>

View File

@ -6,21 +6,21 @@
<field name="model">product.pricelist.item</field> <field name="model">product.pricelist.item</field>
<field name="inherit_id" ref="product.product_pricelist_item_form_view"/> <field name="inherit_id" ref="product.product_pricelist_item_form_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<group name="pricelist_rule_limits" position="inside"> <xpath expr="//field[@name='date_end']" position="after">
<field name="dr_offer_msg" attrs="{'invisible': ['|', ('date_end', '=', False), ('applied_on', '=', '0_product_variant')], 'required': [('date_end', '!=', False)]}"/> <field name="dr_offer_msg" attrs="{'invisible': [('date_end', '=', False)], 'required': [('date_end', '!=', False)]}"/>
<field name="dr_offer_finish_msg" attrs="{'invisible': ['|', ('date_end', '=', False), ('applied_on', '=', '0_product_variant')], 'required': [('date_end', '!=', False)]}"/> <field name="dr_offer_finish_msg" attrs="{'invisible': [('date_end', '=', False)], 'required': [('date_end', '!=', False)]}"/>
</group> </xpath>
</field> </field>
</record> </record>
<record id="website_sale_pricelist_form_view_inherit_droggol_theme_common" model="ir.ui.view"> <record id="product_pricelist_view_inherit_droggol_theme_common" model="ir.ui.view">
<field name="name">product.pricelist.form.inherit.droggol.theme.common</field> <field name="name">product.pricelist.form.inherit.droggol.theme.common</field>
<field name="model">product.pricelist</field> <field name="model">product.pricelist</field>
<field name="inherit_id" ref="website_sale.website_sale_pricelist_form_view"/> <field name="inherit_id" ref="product.product_pricelist_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='item_ids']/tree/field[@name='date_end']" position="after"> <xpath expr="//field[@name='item_ids']/tree/field[@name='date_end']" position="after">
<field name="dr_offer_msg" optional="hide" attrs="{'invisible': [('date_end', '=', False)], 'required': [('date_end', '!=', False)]}"/> <field name="dr_offer_msg" attrs="{'invisible': [('date_end', '=', False)], 'required': [('date_end', '!=', False)]}"/>
<field name="dr_offer_finish_msg" optional="hide" attrs="{'invisible': [('date_end', '=', False)], 'required': [('date_end', '!=', False)]}"/> <field name="dr_offer_finish_msg" attrs="{'invisible': [('date_end', '=', False)], 'required': [('date_end', '!=', False)]}"/>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="dr_product_tags_view_form" model="ir.ui.view">
<field name="name">dr.product.tags.view.form</field>
<field name="model">dr.product.tags</field>
<field name="arch" type="xml">
<form string="Tag">
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="action_open_products" icon="fa-cubes" attrs="{'invisible': [('product_count', '=', 0)]}">
<field string="Products" name="product_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="website_id"/>
<field name="active" invisible="1"/>
</group>
</group>
<notebook>
<page name="products" string="Products">
<field name="product_ids" string="Products" mode="kanban" options="{'create_text':'Add a Product'}" context="{'default_dr_label_id': active_id, 'default_website_id': website_id}"/>
</page>
<page name="tabs" string="Products Tabs">
<div class="alert alert-info" role="alert">
Below tabs will appear on products having tag.
</div>
<field name="dr_tab_ids">
<tree string="Tabs">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="icon"/>
</tree>
<form>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="icon"/>
</group>
</group>
<notebook>
<page name="content" string="Content">
<field name="content"/>
</page>
</notebook>
</sheet>
</form>
</field>
<div colspan="2" class="text-center">You can find icon at <a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">FontAwesome</a>.</div>
</page>
<page name="offers" string="Products Offers">
<div class="alert alert-info" role="alert">
Below offers will appear on products having tag.
</div>
<field name="dr_offer_ids">
<tree string="Offers" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="description"/>
<field name="icon"/>
</tree>
<form>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="icon"/>
</group>
</group>
<notebook>
<page name="dialog_content" string="Dialog Content">
<field name="dialog_content"/>
</page>
</notebook>
</sheet>
</form>
</field>
<div colspan="2" class="text-center">You can find icon at <a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">FontAwesome</a>.
</div>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="dr_product_tags_view_tree" model="ir.ui.view">
<field name="name">dr.product.tags.view.tree</field>
<field name="model">dr.product.tags</field>
<field name="arch" type="xml">
<tree string="Tags">
<field name="name"/>
<field name="website_id"/>
</tree>
</field>
</record>
<record id="dr_product_tags_view_search" model="ir.ui.view">
<field name="name">dr.product.tags.view.search</field>
<field name="model">dr.product.tags</field>
<field name="arch" type="xml">
<search string="Tags">
<field name="name"/>
<field name="website_id"/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group>
<filter string="Website" name="website" domain="" context="{'group_by':'website_id'}"/>
</group>
</search>
</field>
</record>
<record id="dr_product_tags_action" model="ir.actions.act_window">
<field name="name">Tags</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">dr.product.tags</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_dr_product_tags"
action="dr_product_tags_action"
parent="website_sale.menu_product_settings" sequence="6"/>
</odoo>

View File

@ -6,39 +6,87 @@
<field name="model">product.template</field> <field name="model">product.template</field>
<field name="inherit_id" ref="website_sale.product_template_form_view"/> <field name="inherit_id" ref="website_sale.product_template_form_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<page name="sales" position="after"> <xpath expr="//group[@name='shop']" position="inside">
<page name="theme_prime" string="Theme Prime"> <group string="Theme Prime Configuration">
<group> <field name="dr_brand_id" context="{'default_website_id': website_id}" domain="[('website_id', 'in', (False, website_id))]"/>
<group name="default"> <field name="dr_label_id"/>
<field name="dr_label_id"/> <field name="dr_tag_ids" widget="many2many_tags" context="{'default_website_id': website_id}" domain="[('website_id', 'in', (False, website_id))]"/>
<field name="dr_product_tab_ids" widget="many2many_tags" context="{'default_content_type': 'tab'}" domain="[('content_type', '=', 'tab')]"/> </group>
<field name="dr_product_offer_ids" widget="many2many_tags" context="{'default_content_type': 'offer_popup'}" domain="[('content_type', '=', 'offer_popup')]"/> </xpath>
<field name="dr_document_ids" widget="many2many_binary"/> <xpath expr="//group[@name='shop']" position="after">
</group> <group string="Theme Prime Tabs and Offers">
</group> <field name="dr_tab_ids">
</page> <tree string="Tabs" editable="bottom">
</page> <field name="sequence" widget="handle"/>
</field> <field name="name"/>
</record> <field name="icon"/>
</tree>
<form>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="icon"/>
</group>
</group>
<notebook>
<page name="content" string="Content">
<field name="content"/>
</page>
</notebook>
</sheet>
</form>
</field>
<record id="product_template_only_form_view" model="ir.ui.view"> <field name="dr_offer_ids">
<field name="name">product.template.only.form.inherit.droggol.theme.common</field> <tree string="Offers" editable="bottom">
<field name="model">product.template</field> <field name="sequence" widget="handle"/>
<field name="inherit_id" ref="product.product_template_only_form_view"/> <field name="name"/>
<field name="arch" type="xml"> <field name="description"/>
<xpath expr="//field[@name='attribute_line_ids']/tree/field[@name='value_ids']" position="after"> <field name="icon"/>
<field name="dr_attribute_popup_id" context="{'default_content_type': 'attribute_popup'}" optional="show"/> </tree>
<form>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="icon"/>
</group>
</group>
<notebook>
<page name="dialog_content" string="Dialog Content">
<field name="dialog_content"/>
</page>
</notebook>
</sheet>
</form>
</field>
<div colspan="2" class="text-center">You can find icon at <a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">FontAwesome</a>.</div>
</group>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="product_template_view_tree_inherit_droggol_theme_common" model="ir.ui.view"> <record id="product_template_view_tree_inherit_droggol_theme_common" model="ir.ui.view" >
<field name="name">product.template.view.tree.inherit.droggol.theme.common</field> <field name="name">product.template.view.tree.inherit.droggol.theme.common</field>
<field name="model">product.template</field> <field name="model">product.template</field>
<field name="inherit_id" ref="website_sale.product_template_view_tree"/> <field name="inherit_id" ref="website_sale.product_template_view_tree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="website_id" position="after"> <field name="website_id" position="after">
<field name="dr_label_id" options="{'no_create': True, 'no_open': True}" optional="hide"/> <field name="dr_label_id" options="{'no_create': True, 'no_open': True}" optional="hide"/>
<field name="dr_brand_id" options="{'no_create': True, 'no_open': True}" optional="hide"/>
<field name="dr_tag_ids" widget="many2many_tags" options="{'no_create': True, 'no_open': True}" optional="hide"/>
</field> </field>
</field> </field>
</record> </record>

View File

@ -4,26 +4,14 @@
<record id="res_config_settings_view_form" model="ir.ui.view"> <record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.droggol.theme.common</field> <field name="name">res.config.settings.view.form.inherit.droggol.theme.common</field>
<field name="model">res.config.settings</field> <field name="model">res.config.settings</field>
<field name="inherit_id" ref="website_sale.res_config_settings_view_form"/> <field name="inherit_id" ref="website.res_config_settings_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//button[@name='action_website_create_new']" position="after"> <xpath expr="//button[@name='install_theme_on_current_website']" position="after">
<button name="dr_open_theme_custom_modules" type="object" string="Theme Customizations" class="col-auto btn-info ms-2 text-nowrap" style="line-height: 0.5;" icon="fa-cog" noSaveDialog="true" attrs="{'invisible': [('dr_has_custom_module', '=', False)]}"/> <button name="dr_open_theme_custom_modules" type="object" string="Theme Customizations" class="ml-2 btn-info"
icon="fa-cog" attrs="{'invisible': [('dr_has_custom_module', '=', False)]}"/>
<field name="dr_has_custom_module" invisible="1"/> <field name="dr_has_custom_module" invisible="1"/>
</xpath> </xpath>
<div id="sale_product_catalog_settings" position="inside"> <div id="webmaster_settings" position="after">
<div class="col-12 col-lg-6 o_setting_box" id="discount_sale_order_lines" title="Apply manual discounts on sales order lines or display discounts computed from pricelists (option to activate in the pricelist configuration).">
<div class="o_setting_left_pane">
<field name="group_discount_per_so_line"/>
</div>
<div class="o_setting_right_pane">
<label for="group_discount_per_so_line"/>
<div class="text-muted">
Grant discounts on sales order lines
</div>
</div>
</div>
</div>
<div id="sale_product_catalog_settings" position="after">
<h2>Progressive Web Apps (PWA)</h2> <h2>Progressive Web Apps (PWA)</h2>
<div class="row mt16 o_settings_container" id="pwa_settings"> <div class="row mt16 o_settings_container" id="pwa_settings">
<div class="col-12 o_setting_box"> <div class="col-12 o_setting_box">
@ -41,6 +29,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_name_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_name_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Name" for="dr_pwa_name"/> <label string="Name" for="dr_pwa_name"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
Used in the app install prompt. Used in the app install prompt.
</div> </div>
@ -50,6 +39,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_short_name_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_short_name_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Short Name" for="dr_pwa_short_name"/> <label string="Short Name" for="dr_pwa_short_name"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
Used on the user's home screen, launcher, or other places. Used on the user's home screen, launcher, or other places.
</div> </div>
@ -59,6 +49,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_background_color_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_background_color_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Background Color" for="dr_pwa_background_color"/> <label string="Background Color" for="dr_pwa_background_color"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
Used on the splash screen when the application is first launched. Used on the splash screen when the application is first launched.
</div> </div>
@ -68,6 +59,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_theme_color_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_theme_color_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Theme Color" for="dr_pwa_theme_color"/> <label string="Theme Color" for="dr_pwa_theme_color"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
Used on toolbar, and may be in the app's preview in task switchers. Used on toolbar, and may be in the app's preview in task switchers.
</div> </div>
@ -77,6 +69,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_icon_192_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_icon_192_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Icon (192x192)" for="dr_pwa_icon_192"/> <label string="Icon (192x192)" for="dr_pwa_icon_192"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
These icons are used in places like the home screen, app launcher, task switcher, splash screen, etc. These icons are used in places like the home screen, app launcher, task switcher, splash screen, etc.
</div> </div>
@ -86,6 +79,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_icon_512_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_icon_512_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Icon (512x512)" for="dr_pwa_icon_512"/> <label string="Icon (512x512)" for="dr_pwa_icon_512"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
These icons are used in places like the home screen, app launcher, task switcher, splash screen, etc. These icons are used in places like the home screen, app launcher, task switcher, splash screen, etc.
</div> </div>
@ -95,6 +89,7 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_start_url_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_start_url_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Start URL" for="dr_pwa_start_url"/> <label string="Start URL" for="dr_pwa_start_url"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
Your application will start from this URL when it is launched. Your application will start from this URL when it is launched.
</div> </div>
@ -104,11 +99,12 @@
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_shortcuts_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_shortcuts_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="App Shortcuts" for="dr_pwa_shortcuts"/> <label string="App Shortcuts" for="dr_pwa_shortcuts"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
App shortcuts help users quickly start common or recommended tasks within your web app. App shortcuts help users quickly start common or recommended tasks within your web app.
</div> </div>
<field name="dr_pwa_shortcuts" invisible="1"/> <field name="dr_pwa_shortcuts" invisible="1"/>
<button name="dr_open_pwa_shortcuts" noSaveDialog="true" icon="fa-cogs me-1" type="object" string="Configure Shortcuts" class="btn-link"/> <button name="dr_open_pwa_shortcuts" icon="fa-cogs mr-1" type="object" string="Configure Shortcuts" class="btn-link"/>
</div> </div>
</div> </div>
<div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_offline_page_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}"> <div class="col-12 col-lg-6 o_setting_box" id="dr_pwa_offline_page_setting" attrs="{'invisible': [('dr_pwa_activated', '=', False)]}">
@ -117,6 +113,7 @@
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label string="Enable Offline Page" for="dr_pwa_offline_page"/> <label string="Enable Offline Page" for="dr_pwa_offline_page"/>
<span class="fa fa-lg fa-globe" title="Values set here are website-specific." groups="website.group_multi_website"/>
<div class="text-muted"> <div class="text-muted">
Show offline page when there is no internet. Show offline page when there is no internet.
</div> </div>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--
Due to wrong placemenent odoo test case we need to enable few menus
Sale root menu is mandatory to test product configurator test case.
See: https://github.com/odoo/odoo/blob/15.0/addons/sale_product_configurator/static/tests/tours/product_configurator_advanced_ui.js#L12
-->
<record id="sale.sale_menu_root" model="ir.ui.menu">
<field name="active" eval="True"/>
</record>
<record id="sale.menu_sale_quotations" model="ir.ui.menu">
<field name="active" eval="True"/>
</record>
<record id="view_website_sale_website_form" model="ir.ui.view">
<field name="name">website_sale.website.form</field>
<field name="model">website</field>
<field name="inherit_id" ref="website_sale.view_website_sale_website_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='shop_extra_field_ids']/tree" position="inside">
<field name="dr_label"/>
</xpath>
</field>
</record>
</odoo>

View File

@ -1,27 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record id="website_menus_form_view_inherit_droggol_theme_common" model="ir.ui.view">
<field name="name">website.menu.view.form.inherit</field>
<field name="model">website.menu</field>
<field name="inherit_id" ref="website.website_menus_form_view"/>
<field name="arch" type="xml">
<field name="is_mega_menu" position="after">
<field name="dr_menu_label_id"/>
<field name="dr_highlight_menu"/>
</field>
</field>
</record>
<record id="menu_tree_inherit_droggol_theme_common" model="ir.ui.view"> <record id="menu_tree_inherit_droggol_theme_common" model="ir.ui.view">
<field name="name">website.menu.tree.inherit.droggol.theme.common</field> <field name="name">website.menu.tree.inherit.droggol.theme.common</field>
<field name="model">website.menu</field> <field name="model">website.menu</field>
<field name="inherit_id" ref="website.menu_tree"/> <field name="inherit_id" ref="website.menu_tree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="url" position="after"> <xpath expr="//field[@name='url']" position="after">
<field name="dr_menu_label_id"/> <field name="dr_menu_label_id"/>
<field name="dr_highlight_menu"/> </xpath>
</field>
</field> </field>
</record> </record>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--
============================================================================
Variants
============================================================================
-->
<template id="variants" inherit_id="sale.variants">
<xpath expr="//ul/t/li" position="inside">
<t t-if="ptal.attribute_id.display_type in ['radio_circle', 'radio_square', 'radio_image']">
<ul t-att-data-attribute_id="ptal.attribute_id.id" t-attf-class="list-unstyled d-flex flex-wrap align-items-start dr-variant #{'d-none' if single_and_custom else ''}">
<t t-foreach="ptal.product_template_value_ids._only_active()" t-as="ptav">
<li class="form-group js_attribute_value" style="margin: 0;">
<label>
<div>
<input type="radio"
t-attf-class="js_variant_change radio_input d-none #{ptal.attribute_id.create_variant}"
t-att-checked="ptav in combination"
t-att-name="'ptal-%s' % ptal.id"
t-att-value="ptav.id"
t-att-data-value_id="ptav.id"
t-att-data-value_name="ptav.name"
t-att-data-attribute_name="ptav.attribute_id.name"
t-att-data-is_custom="ptav.is_custom"
t-att-data-is_single_and_custom="single_and_custom" />
<div class="radio_input_value d-flex flex-column align-items-center">
<div t-if="not ptal.attribute_id.display_type == 'radio_image'" t-attf-class="dr-variant-item font-weight-normal #{ptal.attribute_id.display_type == 'radio_circle' and 'circle' or 'square'}" t-field="ptav.name"/>
<div t-else="" class="dr-variant-item image" t-att-title="ptav.name" t-field="ptav.dr_image" t-options="{'widget': 'image'}"/>
<span class="badge badge-pill badge-primary mt-1" t-if="ptav.price_extra">
<t t-esc="ptav.price_extra > 0 and '+' or '-'"/>
<span t-esc="abs(ptav.price_extra)" class="variant_price_extra" style="white-space: nowrap;"
t-options='{
"widget": "monetary",
"from_currency": product.currency_id,
"display_currency": (pricelist or product).currency_id
}'/>
</span>
</div>
</div>
</label>
</li>
</t>
</ul>
</t>
</xpath>
</template>
</odoo>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="frontend_layout" name="Droggol Frontend Layout" inherit_id="web.frontend_layout">
<xpath expr="//head/script" position="after">
<script type="text/javascript">
odoo.dr_theme_config = <t t-raw="json.dumps(request.env['ir.http'].get_dr_theme_config())"/>;
</script>
</xpath>
</template>
<template id="theme_config_page_menu" inherit_id="website.user_navbar">
<xpath expr="//a[@data-action='ace']" position="after">
<a t-if="website._get_dr_theme_config('theme_installed')" data-action="open-theme-prime-config-dialog" href="#" id="tp_prime_config" class="dropdown-item">
<span>Theme Prime Configurations</span>
</a>
</xpath>
</template>
</odoo>

View File

@ -1,513 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="s_mega_menu_prime_1" name="Prime - 1" groups="base.group_user">
<section class="s_mega_menu_prime_1 bg-white p-3 p-lg-4">
<div class="container">
<div class="row g-0 s_nb_column_fixed">
<div class="col-12 col-lg-6">
<div class="row g-0 s_col_no_bgcolor s_nb_column_fixed">
<div class="col-12 col-lg-6">
<h6>
Career
</h6>
<nav class="nav flex-column mb-4">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Listing</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Opening</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Overview</a>
</nav>
<h6>
Company
</h6>
<nav class="nav flex-column mb-4 mb-lg-0">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">About</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Pricing</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Terms</a>
</nav>
</div>
<div class="col-12 col-lg-6">
<h6>
Help center
</h6>
<nav class="nav flex-column mb-4">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Overview</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Article</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Search</a>
</nav>
<h6>
Contact
</h6>
<nav class="nav flex-column mb-4 mb-lg-0">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Basic</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Cover</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Search</a>
</nav>
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="row g-0">
<div class="col-12 col-lg-6">
<h6>
Blog
</h6>
<nav class="nav flex-column mb-4 mb-lg-0">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Rich View</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Article</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Showcase</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Search</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Rich</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Article</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Showcase</a>
</nav>
</div>
<div class="col-12 col-lg-6">
<h6>
Portfolio
</h6>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Masonry</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Grid Rows</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Parallax</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Case Study</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Sidebar</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Sidebar: Fluid</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Basic Grid</a>
</nav>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<template id="s_mega_menu_prime_2" name="Prime - 2" groups="base.group_user">
<section class="s_mega_menu_prime_2 bg-white">
<div class="container">
<div class="row s_nb_column_fixed p-3 p-lg-4">
<div class="col-lg-3 py-3">
<h6 class="mb-1">
Clothing
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Dapibus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Quisque</a>
</nav>
</div>
<div class="col-lg-3 py-3">
<h6 class="mb-1">
Shoes
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin lobortis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec ultrices</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Etiam</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam sed</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec non</a>
</nav>
</div>
<div class="col-lg-3 py-3">
<h6 class="mb-1">
Bags
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nulla vehicula</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin eu</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Quisque</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin lobortis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Quisque</a>
</nav>
</div>
<div class="col-lg-3 py-3">
<h6 class="mb-1">
Accessories
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam mattis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nulla vehicula</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin eu</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Quisque</a>
</nav>
</div>
</div>
</div>
<section class="s_parallax parallax s_parallax_is_fixed pt32 pb32 oe_img_bg o_bg_img_center" data-scroll-background-ratio="0" data-snippet="s_parallax" data-name="Parallax" style="background-image: url('/web/image/theme_prime.s_mega_menu_prime_2_1'); background-position: 50% 0;">
<div class="oe_structure oe_empty">
<section class="s_heading_3 pt32 pb32">
<div class="container pt32 pb32">
<div class="row justify-content-center s_nb_column_fixed">
<div class="col-12 col-lg-8 text-center">
<h2 class="mt-3">Want to explore our products?</h2>
<p class="lead">
See all the products at once.
</p>
<a href="#" class="btn btn-primary mt-4">View all products</a>
</div>
</div>
</div>
</section>
</div>
</section>
</section>
</template>
<template id="s_mega_menu_prime_3" name="Prime - 3" groups="base.group_user">
<section class="s_mega_menu_prime_3 bg-white">
<div class="container">
<div class="row s_nb_column_fixed">
<div class="col-12 col-lg-3 py-3">
<h6 class="mb-1">
Clothing
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Dapibus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin <span class="s_badge badge text-bg-primary"><i class="fa fa-tag"></i>New</span></a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean <span class="s_badge badge text-bg-warning"><i class="fa fa-star"></i>Sale</span></a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
</nav>
</div>
<div class="col-12 col-lg-3 py-3">
<h6 class="mb-1">
Shoes
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam mattis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam <span class="s_badge badge text-bg-warning"><i class="fa fa-magic"></i>Popular</span></a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nulla vehicula</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin eu</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Quisque</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin <span class="s_badge badge text-bg-primary"><i class="fa fa-star"></i>New</span></a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam</a>
</nav>
</div>
<div class="col-12 col-lg-3 py-3">
<h6 class="mb-1">
Accessories
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin lobortis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean <span class="s_badge badge text-bg-primary"><i class="fa fa-star"></i>Sale</span></a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec ultrices</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Etiam</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam sed</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec non</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam mattis <span class="s_badge badge text-bg-success"><i class="fa fa-magic"></i>Exclusive</span></a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
</nav>
</div>
<div class="col-12 col-lg-3 py-3">
<div class="s_shop_offer_4">
<div class="position-relative">
<img src="/web/image/theme_prime.s_mega_menu_prime_3_1" class="img img-fluid" alt="Shop Offer Image 01"/>
<div class="tp-banner-text text-center w-100">
<h3>Newly Launched</h3>
<h5>Limited Collection</h5>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="s_clients_3 container pt8 pb8 tp-editor-bg-color-n-shadow" data-name="Clients">
<div class="row s_nb_column_fixed">
<div t-foreach="list(range(1, 7))" t-as="number" class="col-12 col-md-4 col-lg-2 tp-client-box">
<t t-set="number" t-value="'%02d' % number"/>
<div class="p-4 text-center">
<img class="img img-fluid tp-client-image" t-attf-src="/web/image/theme_prime.s_client_#{number}" t-attf-alt="Client Image #{number}"/>
</div>
</div>
</div>
</div>
</section>
</template>
<template id="s_mega_menu_prime_4" name="Prime - 4" groups="base.group_user">
<section class="s_mega_menu_prime_4 bg-white">
<div class="container px-0">
<div class="row s_nb_column_fixed">
<div class="col-12 col-lg-6">
<section class="s_parallax parallax s_parallax_is_fixed pt64 pb64 oe_img_bg o_bg_img_center" data-scroll-background-ratio="0" data-snippet="s_parallax" data-name="Parallax" style="background-image: url('/web/image/theme_prime.s_mega_menu_prime_4_1'); background-position: 50% 0;">
<div class="oe_structure oe_empty">
<section class="s_heading_3 pt32 pb32">
<div class="container pt32 pb32">
<div class="row justify-content-center s_nb_column_fixed">
<div class="col-12 col-lg-8 text-center">
<h2 class="mt-3">Want to explore our products?</h2>
<p class="lead">
See all the products at once.
</p>
<a href="#" class="btn btn-primary mt-4">View all products</a>
</div>
</div>
</div>
</section>
</div>
</section>
</div>
<div class="col-12 col-lg-6">
<div class="row g-0 p-4">
<div class="col-12 col-lg-4 py-2">
<h6 class="mb-1">
Clothing
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Dapibus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
</nav>
</div>
<div class="col-12 col-lg-4 py-2">
<h6 class="mb-1">
Shoes
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam mattis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Duis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nulla vehicula</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin eu</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Quisque</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Morbi vel</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam</a>
</nav>
</div>
<div class="col-12 col-lg-4 py-2">
<h6 class="mb-1">
Accessories
</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Proin lobortis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec ultrices</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Etiam</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam sed</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec non</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Nullam mattis</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
</nav>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<template id="s_mega_menu_prime_5" name="Prime - 5" groups="base.group_user">
<section class="s_mega_menu_prime_5 bg-white">
<div class="container">
<div class="row">
<t t-set="titles" t-value="['Watches', 'Tablets', 'Gaming', 'Laptops']"/>
<div class="col-12 col-md-6 col-lg-3 pt24 pb24" t-foreach="titles" t-as="title">
<div class="card border-0">
<a class="d-block tp-animation-scale" href="#">
<img class="img img-fluid rounded" t-attf-src="/web/image/theme_prime.s_mega_menu_prime_5_#{title_index + 1}" t-attf-alt="Mega Menu Image 0#{title}"/>
</a>
<div class="card-body">
<h5 t-out="title"/>
<nav class="nav flex-column tp-list-arrow">
<a href="#" class="nav-link py-1" data-name="Menu Item">Proin lobortis</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Donec ultrices</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Etiam</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Nullam sed</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Donec non</a>
<a href="#" class="nav-link py-1" data-name="Menu Item">Nullam mattis</a>
</nav>
</div>
</div>
</div>
</div>
</div>
</section>
<t t-call="theme_prime.s_icon_block_12"/>
</template>
<template id="s_mega_menu_prime_6" name="Prime - 6" groups="base.group_user">
<section class="s_mega_menu_prime_6 bg-white">
<div class="container">
<div class="row">
<div class="col-12 pt24 pb24 col-lg-3">
<div class="position-relative tp-banner-block oe_img_bg tp-editor-bg-image" style="background-image: url('/web/image/theme_prime.s_mega_menu_prime_6_1');">
<div class="tp-banner-text text-center tp-editor-bg-color-n-shadow bg-white-85">
<h6><span style="font-weight: bolder;">Starting at $30</span></h6>
<a href="/shop" class="btn btn-primary btn-sm">Shop Now</a>
</div>
</div>
</div>
<div class="col-12 pt24 pb24 col-lg-6">
<div class="row">
<div class="col-12 col-lg-4 mb-4">
<h6 class="mb-1">Clothing</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">New in</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Coats &amp; Jackets</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Jeans</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Dresses</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Shorts</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Skirts</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec non</a>
</nav>
</div>
<div class="col-12 col-lg-4 mb-4">
<h6 class="mb-1">Shoes</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Boots</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Flats</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Heels</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec ultrices</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Sandals</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Slippers</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Socks</a>
</nav>
</div>
<div class="col-12 col-lg-4 mb-4">
<h6 class="mb-1">Accessories</h6>
<div class="s_hr pt8 pb8" data-name="Separator">
<hr class="w-25 me-auto border-primary"/>
</div>
<nav class="nav flex-column">
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Bags &amp; Purses</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Aenean</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Vivamus</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Scarves &amp; Hats</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Etiam</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Jewelry</a>
<a href="#" class="nav-link px-0 py-1" data-name="Menu Item">Donec non</a>
</nav>
</div>
<div class="col-12 mt-3">
<img class="img img-fluid" src="/web/image/theme_prime.s_mega_menu_prime_6_2" alt="Mega Menu Image 01"/>
</div>
</div>
</div>
<div class="col-12 pt24 pb24 col-lg-3">
<div class="position-relative tp-banner-block oe_img_bg tp-editor-bg-image" style="background-image: url('/web/image/theme_prime.s_mega_menu_prime_6_3');">
<div class="tp-banner-text text-center tp-editor-bg-color-n-shadow bg-white-85">
<h6><span style="font-weight: bolder;">Starting at $40</span></h6>
<a href="/shop" class="btn btn-primary btn-sm">Shop Now</a>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<!-- Mega Menu -->
<template id="s_tp_mega_menu_category_snippet" name="Categories Listing" groups="base.group_user">
<section contenteditable="false" class="s_tp_mega_menu_category_snippet tp-mega-menu-snippet tp-droggol-dynamic-snippet bg-white pt32 pb32" data-tp-snippet-id="s_tp_mega_menu_category_snippet">
<div class="container s_tp_mega_menu_category_snippet_wrapper">
<div class="alert alert-primary w-50 mx-auto text-center" role="alert">
<span class="tp-config-link fw-bold tp-cursor-pointer">Click Here!</span> to configure snippet.
</div>
</div>
</section>
</template>
<template id="s_category_mega_menu_snippet" name="Categories Grids" groups="base.group_user">
<section contenteditable="false" class="tp-droggol-dynamic-snippet tp-mega-menu-snippet bg-white s_category_snippet_wrapper pt64 pb64 " data-tp-snippet-id="s_category_snippet">
<div class="container s_category_snippet dr_not_editable">
<div class="alert alert-primary w-50 mx-auto text-center" role="alert">
<span class="tp-config-link fw-bold tp-cursor-pointer">Click Here!</span> to configure snippet.
</div>
</div>
</section>
</template>
<template id="s_mega_menu_category_tabs_snippet" name="Categories Tabs" groups="base.group_user">
<section contenteditable="false" class="tp-droggol-dynamic-snippet bg-white tp-mega-menu-snippet s_category_tabs_snippet_wrapper" data-tp-snippet-id="s_mega_menu_category_tabs_snippet">
<div class="container-fluid p-0 s_category_tabs_snippet">
<div class="alert alert-primary w-50 mx-auto text-center" role="alert">
<span class="tp-config-link fw-bold tp-cursor-pointer">Click Here!</span> to configure snippet.
</div>
</div>
</section>
</template>
<!-- Assets -->
<record id="droggol_theme_common.s_mega_menu_prime_3_000_scss" model="ir.asset">
<field name="name">Mega Menu Prime 3 000 SCSS</field>
<field name="bundle">web.assets_frontend</field>
<field name="path">droggol_theme_common/static/src/snippets/s_mega_menu_prime_3/000.scss</field>
</record>
<record id="droggol_theme_common.s_mega_menu_prime_6_000_scss" model="ir.asset">
<field name="name">Mega Menu Prime 6 000 SCSS</field>
<field name="bundle">web.assets_frontend</field>
<field name="path">droggol_theme_common/static/src/snippets/s_mega_menu_prime_6/000.scss</field>
</record>
</odoo>

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--
============================================================================
Theme Configuration
============================================================================
-->
<template id="frontend_layout" name="Droggol Frontend Layout" inherit_id="web.frontend_layout">
<xpath expr="//head/script[@id='web.layout.odooscript']" position="after">
<script type="text/javascript">
odoo.dr_theme_config = <t t-out="json.dumps(request.website.get_dr_theme_config())"/>;
</script>
</xpath>
</template>
<!--
============================================================================
Variants
============================================================================
-->
<template id="variants" inherit_id="sale.variants">
<xpath expr="//strong[hasclass('attribute_name')]" position="replace">
<div class="d-flex align-items-center mb-2">
<h6 t-field="ptal.attribute_id.name" class="attribute_name mb-0 pb-0"/>
<t t-set="dr_attribute_popup_id" t-value="ptal.dr_attribute_popup_id or ptal.attribute_id.dr_attribute_popup_id"/>
<a t-if="dr_attribute_popup_id" class="dr-attribute-instruction-btn tp-lazy-dialog link-primary ms-4" style="display: none;" href="#" data-res-model="dr.website.content" t-att-data-res-id="dr_attribute_popup_id.id" data-field="content">
<span t-field="dr_attribute_popup_id.name"/> <i class="fa fa-angle-right"/>
</a>
</div>
</xpath>
<xpath expr="//ul/t/li" position="inside">
<t t-if="ptal.attribute_id.display_type in ['radio_circle', 'radio_square', 'radio_image']">
<ul t-att-data-attribute_id="ptal.attribute_id.id" t-attf-class="list-inline dr-attribute-item o_wsale_product_attribute #{'d-none' if single_and_custom else ''}">
<t t-foreach="ptal.product_template_value_ids._only_active()" t-as="ptav">
<li class="list-inline-item me-1">
<label>
<div>
<input type="radio"
t-attf-class="js_variant_change radio_input d-none #{ptal.attribute_id.create_variant}"
t-att-checked="ptav in combination"
t-att-name="'ptal-%s' % ptal.id"
t-att-value="ptav.id"
t-att-data-value_id="ptav.id"
t-att-data-value_name="ptav.name"
t-att-data-attribute_name="ptav.attribute_id.name"
t-att-data-is_custom="ptav.is_custom"
t-att-data-is_single="single"
t-att-data-is_single_and_custom="single_and_custom" />
<div class="radio_input_value d-flex flex-column align-items-center me-0">
<div t-if="not ptal.attribute_id.display_type == 'radio_image'" t-attf-class="dr-value-item fw-normal #{ptal.attribute_id.display_type == 'radio_circle' and 'circle' or 'square'}" t-field="ptav.name"/>
<div t-else="" class="dr-value-item image" t-att-title="ptav.name" t-field="ptav.dr_image" t-options="{'widget': 'image'}"/>
<t t-call="sale.badge_extra_price"/>
</div>
</div>
</label>
</li>
</t>
</ul>
</t>
</xpath>
<xpath expr="//t[contains(@t-if, 'color')]//label" position="attributes">
<attribute name="t-attf-style">#{'background-image: url(/web/image/product.template.attribute.value/%s/dr_thumb_image); background-size: cover;' % ptav.id if ptav.dr_thumb_image else 'background-color:%s' % (ptav.html_color or ptav.product_attribute_value_id.name if not ptav.is_custom else '')}</attribute>
</xpath>
</template>
<!--
============================================================================
Design Page
============================================================================
-->
<template id="design_content" name="Design Content">
<t t-call="website.layout">
<div id="wrap">
<div t-field="content.content"/>
</div>
</t>
</template>
</odoo>

View File

@ -1,30 +1,99 @@
## [16.0.0.0.7] - 02/02/2023 <!-- # Changelog
### Fixed
- Cart lines issue when loyalty installed
## [16.0.0.0.5] - 07/01/2023 ## [14.0.0.3.7]
### Improved - [FIX] make 404 page dropable and make svg images not editable
- Apply color for mobile menu same as header which containing logo
## [16.0.0.0.4] - 27/12/2022 ## [14.0.0.3.6]
### Fixed - [FIX] tax inc/exc subtotal cart
- Don't cache user info in header - [FIX] submit no variant based on new code
## [16.0.0.0.3] - 26/12/2022 ## [14.0.0.3.5]
### Fixed - [FIX] Resequence brand correctly
- Highlight active menu in menu sidebar
## [16.0.0.0.2] - 22/12/2022 ## [14.0.0.3.4]
### Fixed - [FIX] Trigger click event properly to handle add to cart
- Fix product color preview swatches
## [16.0.0.0.1] - 20/12/2022 ## [14.0.0.3.3]
### Added - [FIX] fix search issue due to last release (performance improvements count)
- User Guide links
### Fixed ## [14.0.0.3.2]
- Open Sidebar for public user - [IMP] performance improvements count
## [16.0.0.0.0] ## [14.0.0.3.1]
### Added - [FIX] fix issue of form builder in custom product tabs
- Initial release.
## [14.0.0.3.0]
- [New] Added a search on all brands page.
- [New] Added new card styles in dynamic brands snippet
- [New] Added option to ajax load products in shop page on button click.
- [New] Make dynamic brands snippet more informative now snippet will able to display product count, brand name etc.
- [Updated] Fetch only brands that are having products in brands page as well as in dynamic brands snippet
- [Updated] Allow to move blocks in "Info Block - 6" snippet
- [FIX] Minor bug fixes and improvements.
## [14.0.0.2.2]
- [FIX] Fix traceback while editing some snippets with border style.
## [14.0.0.2.1]
- [FIX] make HTML fields translatable
## [14.0.0.2]
- [New] Added a new snippet to attach documents.
- [New] Added configuration options for price slider.
- [New] SEO improvements.
- [Updated] Top category snippet improvements.
- [Updated] Better product form view usability.
- [Updated] Make rule builder multi website compatible
- [Updated] Improved product search.
- [Updated] Improved blog snippet.
- [Fixed] Minor bug fixes and improvements.
## [14.0.0.1.5]
- [Fixed] Recent view grid size break on some resolution devices.
## [14.0.0.1.4]
- [Fixed] Show tooltip for color attribute.
## [14.0.0.1.3]
- [Fixed] Pricelist offer timer should consider time.
## [14.0.0.1.2]
- [New] Added option lazy load product snippet.
- [New] Added new style-5 in categories snippet.
- [Updated] SEO improvements.
- [Fixed] Fixed header not render properly in firefox.
## [14.0.0.1.1]
- [Update] Restore blog snippet
## [14.0.0.1]
- [New] Added option to list bestseller products.
- [New] Added option to list discounted products.
- [New] Added rules templates in advance product selector.
- [New] Added option to show offers popup on product page.
- [New] Show offers popups on product page based on tags.
- [New] Revamped portal with elegant new UI.
- [New] Added new cover snippet.
- [New] Added new styles for shop categories pills.
- [New] Add options to show similar products from snippet cards style 3 and 6.
- [New] Add options to show similar products from shop page.
- [New] Added option to hide pre header.
- [New] Added option hide flags from the language selector.
- [New] Allow product mass edit for label, brand, tag.
- [New] Allow dynamic snippets in custom product tabs.
- [New] Added new hotspot style.
- [New] Show image swatches in the shop filters.
- [New] Added option to hide unmatched filters.
- [New] Added brands filter styles in shop.
- [New] Added tags filter styles in shop.
- [New] Added label filter in shop.
- [New] Snippet thumbnail now changes color based on configured theme color.
- [Updated] Product pages loading is 2x faster now.
- [Updated] Improved mega menus.
- [Updated] Improved accessibility.
- [Updated] RTL improvements.
- [Updated] SEO improvements.
- [Updated] PWA improvements.
- [Fixed] Minor bug fixes and improvements.
## [14.0.0.0]
- Initial Release -->

View File

@ -1,7 +1,7 @@
Most of the files are Most of the files are
Copyright (c) 2019 - present Droggol Infotech Private Limited. Copyright (c) 2019 - present Droggol.
Some javascript files might be from from third Some javascript files might be from from third
parties libraries. In that case the original parties libraries. In that case the original

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from . import controllers from . import controllers
from . import models from . import models

View File

@ -1,175 +1,189 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
{ {
'name': 'Theme Prime', 'name': 'Theme Prime',
'description': 'Powerful multipurpose eCommerce theme suitable for all kind of businesses like Electronics, Fashion, Sports, Beauty, Furniture and many more.', 'description': 'Powerful multipurpose eCommerce theme suitable for all kind of businesses like Electronics, Fashion, Sports, Beauty, Furniture and many more.',
'summary': 'Powerful multipurpose eCommerce theme suitable for all kind of businesses like Electronics, Fashion, Sports, Beauty, Furniture and many more.', 'summary': 'Powerful multipurpose eCommerce theme suitable for all kind of businesses like Electronics, Fashion, Sports, Beauty, Furniture and many more.',
'category': 'Theme/eCommerce', 'category': 'Theme/eCommerce',
'version': '16.0.0.0.8', 'version': '14.0.0.3.8',
'depends': ['droggol_theme_common'], 'depends': ['droggol_theme_common'],
'license': 'OPL-1', 'license': 'OPL-1',
'author': 'Droggol Infotech Private Limited', 'author': 'Droggol',
'company': 'Droggol Infotech Private Limited', 'company': 'Droggol',
'maintainer': 'Droggol Infotech Private Limited', 'maintainer': 'Droggol',
'website': 'https://www.droggol.com/', 'website': 'https://www.droggol.com/',
'price': 289.00, 'price': 275.00,
'currency': 'USD', 'currency': 'USD',
'live_test_url': 'https://prime-16-electronics-1.droggol.com/', 'live_test_url': 'https://prime-14-electronics-2.droggol.com/',
'images': [ 'images': [
'static/description/prime_cover.png', 'static/description/prime_cover.png',
'static/description/prime_screenshot.gif', 'static/description/prime_screenshot.gif',
], ],
'data': [ 'data': [
'data/theme.ir.attachment.csv', 'data/data.xml',
'data/images_library.xml',
'views/sidebar.xml', 'views/assets.xml',
'views/templates.xml', 'views/templates.xml',
'views/components.xml', 'views/components.xml',
'views/layout.xml', 'views/layout.xml',
'views/shop_layout.xml',
'views/product_detail_page.xml',
'views/pages.xml', 'views/pages.xml',
'views/snippets.xml', 'views/snippets.xml',
'views/svg_images.xml', 'views/svg_images.xml',
# Headers / Footers # Headers
'views/headers.xml', 'views/headers/style_1.xml',
'views/preheaders.xml', 'views/headers/style_2.xml',
'views/footers.xml', 'views/headers/style_3.xml',
'views/headers/style_4.xml',
'views/headers/style_5.xml',
'views/headers/style_6.xml',
'views/headers/style_7.xml',
'views/headers/style_8.xml',
# Footers
'views/footers/style_1.xml',
'views/footers/style_2.xml',
'views/footers/style_3.xml',
'views/footers/style_4.xml',
'views/footers/style_5.xml',
'views/footers/style_6.xml',
'views/footers/style_7.xml',
'views/footers/style_8.xml',
'views/footers/style_9.xml',
'views/footers/style_10.xml',
# Snippets # Snippets
'views/snippets/dynamic_snippets.xml', 'views/snippets/s_call_to_action_1.xml',
'views/snippets/s_banner.xml', 'views/snippets/s_call_to_action_2.xml',
'views/snippets/s_blog.xml', 'views/snippets/s_call_to_action_3.xml',
'views/snippets/s_clients.xml', 'views/snippets/s_call_to_action_4.xml',
'views/snippets/s_coming_soon.xml', 'views/snippets/s_call_to_action_5.xml',
'views/snippets/s_countdown.xml',
'views/snippets/s_cover.xml', 'views/snippets/s_category_1.xml',
'views/snippets/s_cta.xml', 'views/snippets/s_category_2.xml',
'views/snippets/s_gallery.xml', 'views/snippets/s_category_3.xml',
'views/snippets/s_heading.xml', 'views/snippets/s_category_4.xml',
'views/snippets/s_icon_block.xml',
'views/snippets/s_info_block.xml', # Dynamic
'views/snippets/s_pricing.xml', 'views/snippets/dynamic_snippets/snippets.xml',
'views/snippets/s_shop_offer.xml', 'views/snippets/dynamic_snippets/s_countdown.xml',
'views/snippets/s_stats.xml',
'views/snippets/s_subscribe.xml', # Static
'views/snippets/s_team.xml', 'views/snippets/s_banner_1.xml',
'views/snippets/s_testimonial.xml', 'views/snippets/s_banner_2.xml',
'views/snippets/s_banner_3.xml',
'views/snippets/s_banner_4.xml',
'views/snippets/s_banner_5.xml',
'views/snippets/s_banner_6.xml',
'views/snippets/s_banner_7.xml',
'views/snippets/s_banner_8.xml',
'views/snippets/s_banner_9.xml',
'views/snippets/s_banner_10.xml',
'views/snippets/s_banner_11.xml',
'views/snippets/s_banner_12.xml',
'views/snippets/s_blog_1.xml',
'views/snippets/s_blog_2.xml',
'views/snippets/s_blog_3.xml',
'views/snippets/s_clients_1.xml',
'views/snippets/s_clients_2.xml',
'views/snippets/s_clients_3.xml',
'views/snippets/s_clients_4.xml',
'views/snippets/s_coming_soon_1.xml',
'views/snippets/s_coming_soon_2.xml',
'views/snippets/s_counters_1.xml',
'views/snippets/s_counters_2.xml',
'views/snippets/s_counters_3.xml',
'views/snippets/s_counters_4.xml',
'views/snippets/s_counters_5.xml',
'views/snippets/s_cover_1.xml',
'views/snippets/s_cover_2.xml',
'views/snippets/s_cover_3.xml',
'views/snippets/s_cover_4.xml',
'views/snippets/s_cover_5.xml',
'views/snippets/s_cover_6.xml',
'views/snippets/s_gallery_1.xml',
'views/snippets/s_gallery_2.xml',
'views/snippets/s_gallery_3.xml',
'views/snippets/s_gallery_4.xml',
'views/snippets/s_gallery_5.xml',
'views/snippets/s_heading_1.xml',
'views/snippets/s_heading_2.xml',
'views/snippets/s_heading_3.xml',
'views/snippets/s_heading_4.xml',
'views/snippets/s_heading_5.xml',
'views/snippets/s_heading_6.xml',
'views/snippets/s_icon_block_1.xml',
'views/snippets/s_icon_block_2.xml',
'views/snippets/s_icon_block_3.xml',
'views/snippets/s_icon_block_4.xml',
'views/snippets/s_icon_block_5.xml',
'views/snippets/s_icon_block_6.xml',
'views/snippets/s_icon_block_7.xml',
'views/snippets/s_icon_block_8.xml',
'views/snippets/s_icon_block_9.xml',
'views/snippets/s_icon_block_10.xml',
'views/snippets/s_icon_block_11.xml',
'views/snippets/s_icon_block_12.xml',
'views/snippets/s_icon_block_13.xml',
'views/snippets/s_mega_menu_1.xml',
'views/snippets/s_mega_menu_2.xml',
'views/snippets/s_mega_menu_3.xml',
'views/snippets/s_mega_menu_4.xml',
'views/snippets/s_mega_menu_5.xml',
'views/snippets/s_mega_menu_6.xml',
'views/snippets/s_mega_menu_7.xml',
'views/snippets/s_mega_menu_8.xml',
'views/snippets/s_mega_menu_9.xml',
'views/snippets/s_info_block_1.xml',
'views/snippets/s_info_block_2.xml',
'views/snippets/s_info_block_3.xml',
'views/snippets/s_info_block_4.xml',
'views/snippets/s_info_block_5.xml',
'views/snippets/s_info_block_6.xml',
'views/snippets/s_info_block_7.xml',
'views/snippets/s_offer_1.xml',
'views/snippets/s_offer_2.xml',
'views/snippets/s_offer_3.xml',
'views/snippets/s_offer_4.xml',
'views/snippets/s_pricing_1.xml',
'views/snippets/s_pricing_2.xml',
'views/snippets/s_pricing_3.xml',
'views/snippets/s_pricing_4.xml',
'views/snippets/s_pricing_5.xml',
'views/snippets/s_pricing_6.xml',
'views/snippets/s_subscribe_1.xml',
'views/snippets/s_subscribe_2.xml',
'views/snippets/s_subscribe_3.xml',
'views/snippets/s_subscribe_4.xml',
'views/snippets/s_team_1.xml',
'views/snippets/s_team_2.xml',
'views/snippets/s_team_3.xml',
'views/snippets/s_team_4.xml',
'views/snippets/s_team_5.xml',
'views/snippets/s_testimonial_1.xml',
'views/snippets/s_testimonial_2.xml',
'views/snippets/s_testimonial_3.xml',
'views/snippets/s_testimonial_4.xml',
'views/snippets/s_testimonial_5.xml',
], ],
'assets': {
'web.assets_backend': [
'theme_prime/static/src/components/dialog.xml',
'theme_prime/static/src/components/record_selection.xml',
'theme_prime/static/src/components/ui_component.xml',
'theme_prime/static/src/components/search_input.xml',
'theme_prime/static/src/components/dropdown.xml',
'theme_prime/static/src/components/dialog.js',
'theme_prime/static/src/components/abstract_component.js',
'theme_prime/static/src/components/theme_service.js',
'theme_prime/static/src/components/dialog.scss',
'theme_prime/static/src/components/record_selection.js',
'theme_prime/static/src/components/ui_component.js',
'theme_prime/static/src/components/search_input.js',
],
'web.assets_frontend': [
# Libraries
'theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.carousel.css',
'theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.default.css',
# Frontend
'theme_prime/static/src/js/website.js',
'theme_prime/static/src/js/website_sale.js',
'theme_prime/static/src/js/website_sale_wishlist.js',
'theme_prime/static/src/js/sidebar.js',
'theme_prime/static/src/xml/sidebar.xml',
'theme_prime/static/src/js/suggested_product_slider.js',
'theme_prime/static/src/xml/frontend/suggested_product_slider.xml',
'theme_prime/static/src/js/service_worker_register.js',
'theme_prime/static/src/xml/pwa.xml',
'theme_prime/static/src/js/core/mixins.js',
'theme_prime/static/src/js/frontend/comparison.js',
'theme_prime/static/src/js/frontend/quick_view_dialog.js',
'theme_prime/static/src/js/frontend/bottombar.js',
'theme_prime/static/src/scss/theme.scss',
'theme_prime/static/src/scss/rtl.scss',
'theme_prime/static/src/scss/website.scss',
'theme_prime/static/src/scss/website_sale.scss',
'theme_prime/static/src/scss/sliders.scss',
'theme_prime/static/src/scss/icon-packs/website.scss',
'theme_prime/static/src/scss/utils.scss',
'theme_prime/static/src/scss/snippets/cards.scss',
'theme_prime/static/src/scss/front_end/quick_view.scss',
'theme_prime/static/src/scss/front_end/dynamic_snippets.scss',
'theme_prime/static/src/scss/front_end/category_filters.scss',
'theme_prime/static/src/scss/front_end/image_hotspot.scss',
'theme_prime/static/src/scss/snippets/2_col_deal.scss',
'theme_prime/static/src/scss/snippets/image_products.scss',
'theme_prime/static/src/scss/front_end/bottom_bar.scss',
'theme_prime/static/src/snippets/s_blog_posts/000.scss',
# Core
'theme_prime/static/src/js/core/snippet_root_widget.js',
'theme_prime/static/src/xml/core/snippet_root_widget.xml',
'theme_prime/static/src/js/core/product_root_widget.js',
'theme_prime/static/src/js/core/cart_manager.js',
'theme_prime/static/src/xml/frontend/notification_template.xml',
'theme_prime/static/src/js/core/cart_confirmation_dialog.js',
'theme_prime/static/src/xml/core/cart_confirmation_dialog.xml',
# Snippets
'theme_prime/static/src/snippets/s_tp_countdown/000.xml',
'theme_prime/static/src/js/frontend/dynamic_snippets.js',
'theme_prime/static/src/xml/frontend/dynamic_snippets.xml',
'theme_prime/static/src/xml/cards.xml',
'theme_prime/static/src/xml/listing_cards.xml',
'theme_prime/static/src/xml/frontend/utils.xml',
'theme_prime/static/src/xml/frontend/category_filters.xml',
'theme_prime/static/src/xml/frontend/2_col_deal.xml',
'theme_prime/static/src/xml/frontend/s_image_products.xml',
'theme_prime/static/src/xml/frontend/s_product_grid.xml',
'theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml',
'theme_prime/static/src/xml/frontend/s_category.xml',
'theme_prime/static/src/xml/frontend/brands.xml',
'theme_prime/static/src/xml/frontend/image_hotspot.xml', # TODO: kishan
# Editor
('replace', 'web_editor/static/src/scss/web_editor.frontend.scss', 'theme_prime/static/src/scss/web_editor.frontend.scss'),
# Search
'theme_prime/static/src/js/frontend/search.js',
'theme_prime/static/src/xml/frontend/search_autocomplete.xml',
],
'web._assets_primary_variables': [
'theme_prime/static/src/scss/primary_variables.scss',
'theme_prime/static/src/scss/mixins.scss',
],
'web._assets_frontend_helpers': [
'theme_prime/static/src/scss/bootstrap_overridden.scss',
],
'website.assets_wysiwyg': [
'theme_prime/static/src/js/editor/snippets.editor.js',
'theme_prime/static/src/scss/editor/editor.scss',
# 'theme_prime/static/src/scss/editor/dialogs/dialog_snippet_configurator.scss',
'theme_prime/static/src/xml/editor/dialogs/snippet_configurator_dialog.xml',
'theme_prime/static/src/xml/frontend/image_hotspot.xml',
'theme_prime/static/src/js/editor/snippets/snippets.options.js',
'theme_prime/static/src/js/editor/registries.js',
'theme_prime/static/src/xml/frontend/documents.xml',
],
},
} }

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from . import main from . import main
from . import brand
from . import pwa

View File

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
import string
from collections import defaultdict
from odoo import http
from odoo.http import request
class ThemePrimeBrand(http.Controller):
@http.route('/shop/all_brands', type='http', auth='public', website=True)
def all_brands(self, **args):
brands = request.env['dr.product.brand'].search(request.website.website_domain()).filtered(lambda line: line.product_count)
is_disable_grouping = request.website._get_dr_theme_config('json_brands_page')['disable_brands_grouping']
if is_disable_grouping:
brands_group_by_alphabet = {'All Brands': brands}
else:
alphabet_range = string.ascii_uppercase
brands_group_by_alphabet = defaultdict(list)
brands_group_by_alphabet.update((alphabet, []) for alphabet in alphabet_range)
for brand in brands:
first_char = str.upper(brand.name[:1])
brands_group_by_alphabet[first_char].append(brand)
return request.render('theme_prime.all_brands', {
'is_disable_grouping': is_disable_grouping,
'grouped_brands': brands_group_by_alphabet
})

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
import json
import base64
import io
from functools import partial
from odoo import http
from odoo.http import request
from odoo.modules.module import get_resource_path
from odoo.tools.mimetypes import guess_mimetype
class ThemePrimePWA(http.Controller):
@http.route('/pwa/<int:website_id>/manifest.json', type='http', auth='public', website=True)
def get_pwa_manifest(self, website_id, **kargs):
manifest_data = {"fake": 1}
website = request.website
if website and website.id == website_id and website.dr_pwa_activated:
manifest_data = {
"name": website.dr_pwa_name,
"short_name": website.dr_pwa_short_name,
"display": "standalone",
"background_color": website.dr_pwa_background_color,
"theme_color": website.dr_pwa_theme_color,
"start_url": website.dr_pwa_start_url,
"scope": "/",
"icons": [{
"src": "/web/image/website/%s/dr_pwa_icon_192/192x192" % website.id,
"sizes": "192x192",
"type": "image/png",
}, {
"src": "/web/image/website/%s/dr_pwa_icon_512/512x512" % website.id,
"sizes": "512x512",
"type": "image/png",
}]
}
if website.dr_pwa_shortcuts:
manifest_data['shortcuts'] = [{
"name": shortcut.name,
"short_name": shortcut.short_name or '',
"description": shortcut.description or '',
"url": shortcut.url,
"icons": [{"src": "/web/image/dr.pwa.shortcuts/%s/icon/192x192" % shortcut.id, "sizes": "192x192"}]
} for shortcut in website.dr_pwa_shortcuts]
return request.make_response(
data=json.dumps(manifest_data),
headers=[('Content-Type', 'application/json')]
)
@http.route('/service_worker.js', type='http', auth='public', website=True, sitemap=False)
def get_pwa_service_worker(self, **kargs):
website = request.website
js_folder = partial(get_resource_path, 'theme_prime', 'static', 'src', 'js')
file_path = js_folder('service_worker.js')
offline_bool = 'true' if website.dr_pwa_offline_page else 'false'
data = open(file_path).read()
data = data.replace('"##1##"', str(website.dr_pwa_version))
data = data.replace('"##2##"', offline_bool)
return request.make_response(
data=data,
headers=[('Content-Type', 'text/javascript')]
)
@http.route('/pwa/offline_page', type='http', auth='public', website=True, cors='*', sitemap=False)
def get_pwa_offline_page(self, **kargs):
return request.render('theme_prime.pwa_offline_page', {})
@http.route('/pwa/logo.png', type='http', auth='public', website=True, cors='*', sitemap=False)
def get_pwa_logo(self, **kargs):
website = request.website
imgname = 'logo'
imgext = '.png'
placeholder = partial(get_resource_path, 'web', 'static', 'src', 'img')
if not website.logo:
response = http.send_file(placeholder('nologo.png'))
else:
b64 = website.logo
image_base64 = base64.b64decode(b64)
image_data = io.BytesIO(image_base64)
mimetype = guess_mimetype(image_base64, default='image/png')
imgext = '.' + mimetype.split('/')[1]
if imgext == '.svg+xml':
imgext = '.svg'
response = http.send_file(image_data, filename=imgname + imgext, mimetype=mimetype, mtime=website.write_date)
return response
@http.route('/pwa/is_pwa_actived', type='http', auth='public', website=True, sitemap=False)
def get_pwa_is_actived(self, **kargs):
data = {'pwa': request.website.dr_pwa_activated}
return request.make_response(
data=json.dumps(data),
headers=[('Content-Type', 'application/json')]
)

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- FIXME: Should update priority only for theme view -->
<function model="ir.ui.view" name="write">
<value model="ir.ui.view" eval="obj().with_context(active_test=False).search([('key','=', 'website_sale.products_categories')], limit=1).id"/>
<value eval="{'priority': 15}"/>
</function>
</data>
</odoo>

View File

@ -0,0 +1,599 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="s_banner_1_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_1_1</field>
<field name="name">theme_prime.s_banner_1_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_1_1.jpg</field>
</record>
<record id="s_banner_1_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_1_2</field>
<field name="name">theme_prime.s_banner_1_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_1_2.jpg</field>
</record>
<record id="s_banner_2_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_2_1</field>
<field name="name">theme_prime.s_banner_2_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_2_1.jpg</field>
</record>
<record id="s_banner_2_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_2_2</field>
<field name="name">theme_prime.s_banner_2_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_2_2.jpg</field>
</record>
<record id="s_banner_2_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_2_3</field>
<field name="name">theme_prime.s_banner_2_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_2_3.jpg</field>
</record>
<record id="s_banner_3_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_3_1</field>
<field name="name">theme_prime.s_banner_3_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_3_1.png</field>
</record>
<record id="s_banner_3_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_3_2</field>
<field name="name">theme_prime.s_banner_3_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_3_2.png</field>
</record>
<record id="s_banner_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_4_1</field>
<field name="name">theme_prime.s_banner_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_4_1.png</field>
</record>
<record id="s_banner_4_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_4_2</field>
<field name="name">theme_prime.s_banner_4_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_4_2.png</field>
</record>
<record id="s_banner_4_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_4_3</field>
<field name="name">theme_prime.s_banner_4_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_4_3.png</field>
</record>
<record id="s_banner_4_brand_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_4_brand_1</field>
<field name="name">theme_prime.s_banner_4_brand_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_4_brand_1.png</field>
</record>
<record id="s_banner_4_brand_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_4_brand_2</field>
<field name="name">theme_prime.s_banner_4_brand_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_4_brand_2.png</field>
</record>
<record id="s_banner_4_brand_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_4_brand_3</field>
<field name="name">theme_prime.s_banner_4_brand_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_4_brand_3.png</field>
</record>
<record id="s_banner_5_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_5_1</field>
<field name="name">theme_prime.s_banner_5_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_5_1.png</field>
</record>
<record id="s_banner_6_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_6_1</field>
<field name="name">theme_prime.s_banner_6_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_6_1.png</field>
</record>
<record id="s_banner_6_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_6_2</field>
<field name="name">theme_prime.s_banner_6_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_6_2.png</field>
</record>
<record id="s_banner_7_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_7_1</field>
<field name="name">theme_prime.s_banner_7_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_7_1.jpg</field>
</record>
<record id="s_banner_7_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_7_2</field>
<field name="name">theme_prime.s_banner_7_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_7_2.jpg</field>
</record>
<record id="s_banner_7_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_7_3</field>
<field name="name">theme_prime.s_banner_7_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_7_3.jpg</field>
</record>
<record id="s_banner_7_4" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_7_4</field>
<field name="name">theme_prime.s_banner_7_4</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_7_4.jpg</field>
</record>
<record id="s_banner_8_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_8_1</field>
<field name="name">theme_prime.s_banner_8_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_8_1.jpg</field>
</record>
<record id="s_banner_8_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_8_2</field>
<field name="name">theme_prime.s_banner_8_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_8_2.jpg</field>
</record>
<record id="s_banner_8_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_8_3</field>
<field name="name">theme_prime.s_banner_8_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_8_3.jpg</field>
</record>
<record id="s_banner_9_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_9_1</field>
<field name="name">theme_prime.s_banner_9_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_9_1.jpg</field>
</record>
<record id="s_banner_9_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_9_2</field>
<field name="name">theme_prime.s_banner_9_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_9_2.jpg</field>
</record>
<record id="s_banner_9_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_9_3</field>
<field name="name">theme_prime.s_banner_9_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_9_3.jpg</field>
</record>
<record id="s_banner_10_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_10_1</field>
<field name="name">theme_prime.s_banner_10_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_10_1.jpg</field>
</record>
<record id="s_banner_11_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_11_1</field>
<field name="name">theme_prime.s_banner_11_1</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_11_1.jpg</field>
</record>
<record id="s_banner_11_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_11_2</field>
<field name="name">theme_prime.s_banner_11_2</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_11_2.jpg</field>
</record>
<record id="s_banner_11_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_banner_11_3</field>
<field name="name">theme_prime.s_banner_11_3</field>
<field name="url">/theme_prime/static/src/img/content/s_banner_11_3.jpg</field>
</record>
<record id="s_call_to_action_5_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_call_to_action_5_1</field>
<field name="name">theme_prime.s_call_to_action_5_1</field>
<field name="url">/theme_prime/static/src/img/content/s_call_to_action_5_1.jpg</field>
</record>
<record id="s_category_1_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_category_1_1</field>
<field name="name">theme_prime.s_category_1_1</field>
<field name="url">/theme_prime/static/src/img/content/s_category_1_1.jpg</field>
</record>
<record id="s_category_2_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_category_2_1</field>
<field name="name">theme_prime.s_category_2_1</field>
<field name="url">/theme_prime/static/src/img/content/s_category_2_1.jpg</field>
</record>
<record id="s_category_3_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_category_3_1</field>
<field name="name">theme_prime.s_category_3_1</field>
<field name="url">/theme_prime/static/src/img/content/s_category_3_1.jpg</field>
</record>
<record id="s_category_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_category_4_1</field>
<field name="name">theme_prime.s_category_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_category_4_1.png</field>
</record>
<record id="s_client_01" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_01</field>
<field name="name">theme_prime.s_client_01</field>
<field name="url">/theme_prime/static/src/img/content/s_client_01.png</field>
</record>
<record id="s_client_02" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_02</field>
<field name="name">theme_prime.s_client_02</field>
<field name="url">/theme_prime/static/src/img/content/s_client_02.png</field>
</record>
<record id="s_client_03" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_03</field>
<field name="name">theme_prime.s_client_03</field>
<field name="url">/theme_prime/static/src/img/content/s_client_03.png</field>
</record>
<record id="s_client_04" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_04</field>
<field name="name">theme_prime.s_client_04</field>
<field name="url">/theme_prime/static/src/img/content/s_client_04.png</field>
</record>
<record id="s_client_05" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_05</field>
<field name="name">theme_prime.s_client_05</field>
<field name="url">/theme_prime/static/src/img/content/s_client_05.png</field>
</record>
<record id="s_client_06" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_06</field>
<field name="name">theme_prime.s_client_06</field>
<field name="url">/theme_prime/static/src/img/content/s_client_06.png</field>
</record>
<record id="s_client_07" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_07</field>
<field name="name">theme_prime.s_client_07</field>
<field name="url">/theme_prime/static/src/img/content/s_client_07.png</field>
</record>
<record id="s_client_08" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_08</field>
<field name="name">theme_prime.s_client_08</field>
<field name="url">/theme_prime/static/src/img/content/s_client_08.png</field>
</record>
<record id="s_client_09" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_09</field>
<field name="name">theme_prime.s_client_09</field>
<field name="url">/theme_prime/static/src/img/content/s_client_09.png</field>
</record>
<record id="s_client_10" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_10</field>
<field name="name">theme_prime.s_client_10</field>
<field name="url">/theme_prime/static/src/img/content/s_client_10.png</field>
</record>
<record id="s_client_11" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_11</field>
<field name="name">theme_prime.s_client_11</field>
<field name="url">/theme_prime/static/src/img/content/s_client_11.png</field>
</record>
<record id="s_client_12" model="theme.ir.attachment">
<field name="key">theme_prime.s_client_12</field>
<field name="name">theme_prime.s_client_12</field>
<field name="url">/theme_prime/static/src/img/content/s_client_12.png</field>
</record>
<record id="s_coming_soon_2_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_coming_soon_2_1</field>
<field name="name">theme_prime.s_coming_soon_2_1</field>
<field name="url">/theme_prime/static/src/img/content/s_coming_soon_2_1.png</field>
</record>
<record id="s_coming_soon_2_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_coming_soon_2_2</field>
<field name="name">theme_prime.s_coming_soon_2_2</field>
<field name="url">/theme_prime/static/src/img/content/s_coming_soon_2_2.jpg</field>
</record>
<record id="s_cover_1_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_1_1</field>
<field name="name">theme_prime.s_cover_1_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_1_1.jpg</field>
</record>
<record id="s_cover_1_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_1_2</field>
<field name="name">theme_prime.s_cover_1_2</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_1_2.jpg</field>
</record>
<record id="s_cover_1_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_1_3</field>
<field name="name">theme_prime.s_cover_1_3</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_1_3.jpg</field>
</record>
<record id="s_cover_2_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_2_1</field>
<field name="name">theme_prime.s_cover_2_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_2_1.png</field>
</record>
<record id="s_cover_2_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_2_2</field>
<field name="name">theme_prime.s_cover_2_2</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_2_2.png</field>
</record>
<record id="s_cover_2_brand_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_2_brand_1</field>
<field name="name">theme_prime.s_cover_2_brand_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_2_brand_1.png</field>
</record>
<record id="s_cover_2_brand_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_2_brand_2</field>
<field name="name">theme_prime.s_cover_2_brand_2</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_2_brand_2.png</field>
</record>
<record id="s_cover_3_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_3_1</field>
<field name="name">theme_prime.s_cover_3_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_3_1.jpg</field>
</record>
<record id="s_cover_3_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_3_2</field>
<field name="name">theme_prime.s_cover_3_2</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_3_2.jpg</field>
</record>
<record id="s_cover_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_4_1</field>
<field name="name">theme_prime.s_cover_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_4_1.jpg</field>
</record>
<record id="s_cover_5_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_5_1</field>
<field name="name">theme_prime.s_cover_5_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_5_1.jpg</field>
</record>
<record id="s_cover_5_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_5_2</field>
<field name="name">theme_prime.s_cover_5_2</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_5_2.jpg</field>
</record>
<record id="s_cover_5_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_5_3</field>
<field name="name">theme_prime.s_cover_5_3</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_5_3.jpg</field>
</record>
<record id="s_cover_5_4" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_5_4</field>
<field name="name">theme_prime.s_cover_5_4</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_5_4.jpg</field>
</record>
<record id="s_cover_6_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_cover_6_1</field>
<field name="name">theme_prime.s_cover_6_1</field>
<field name="url">/theme_prime/static/src/img/content/s_cover_6_1.jpg</field>
</record>
<record id="s_offer_1_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_offer_1_1</field>
<field name="name">theme_prime.s_offer_1_1</field>
<field name="url">/theme_prime/static/src/img/content/s_offer_1_1.jpg</field>
</record>
<record id="s_offer_2_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_offer_2_1</field>
<field name="name">theme_prime.s_offer_2_1</field>
<field name="url">/theme_prime/static/src/img/content/s_offer_2_1.jpg</field>
</record>
<record id="s_offer_3_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_offer_3_1</field>
<field name="name">theme_prime.s_offer_3_1</field>
<field name="url">/theme_prime/static/src/img/content/s_offer_3_1.jpg</field>
</record>
<record id="s_offer_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_offer_4_1</field>
<field name="name">theme_prime.s_offer_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_offer_4_1.jpg</field>
</record>
<record id="s_gallery_01" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_01</field>
<field name="name">theme_prime.s_gallery_01</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_01.jpg</field>
</record>
<record id="s_gallery_02" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_02</field>
<field name="name">theme_prime.s_gallery_02</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_02.jpg</field>
</record>
<record id="s_gallery_03" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_03</field>
<field name="name">theme_prime.s_gallery_03</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_03.jpg</field>
</record>
<record id="s_gallery_04" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_04</field>
<field name="name">theme_prime.s_gallery_04</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_04.jpg</field>
</record>
<record id="s_gallery_05" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_05</field>
<field name="name">theme_prime.s_gallery_05</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_05.jpg</field>
</record>
<record id="s_gallery_06" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_06</field>
<field name="name">theme_prime.s_gallery_06</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_06.jpg</field>
</record>
<record id="s_gallery_07" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_07</field>
<field name="name">theme_prime.s_gallery_07</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_07.jpg</field>
</record>
<record id="s_gallery_08" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_08</field>
<field name="name">theme_prime.s_gallery_08</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_08.jpg</field>
</record>
<record id="s_gallery_09" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_09</field>
<field name="name">theme_prime.s_gallery_09</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_09.jpg</field>
</record>
<record id="s_gallery_10" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_10</field>
<field name="name">theme_prime.s_gallery_10</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_10.jpg</field>
</record>
<record id="s_gallery_11" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_11</field>
<field name="name">theme_prime.s_gallery_11</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_11.jpg</field>
</record>
<record id="s_gallery_12" model="theme.ir.attachment">
<field name="key">theme_prime.s_gallery_12</field>
<field name="name">theme_prime.s_gallery_12</field>
<field name="url">/theme_prime/static/src/img/content/s_gallery_12.jpg</field>
</record>
<record id="s_info_block_1_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_1_1</field>
<field name="name">theme_prime.s_info_block_1_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_1_1.jpg</field>
</record>
<record id="s_info_block_2_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_2_1</field>
<field name="name">theme_prime.s_info_block_2_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_2_1.jpg</field>
</record>
<record id="s_info_block_3_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_3_1</field>
<field name="name">theme_prime.s_info_block_3_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_3_1.jpg</field>
</record>
<record id="s_info_block_3_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_3_2</field>
<field name="name">theme_prime.s_info_block_3_2</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_3_2.jpg</field>
</record>
<record id="s_info_block_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_4_1</field>
<field name="name">theme_prime.s_info_block_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_4_1.jpg</field>
</record>
<record id="s_info_block_5_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_5_1</field>
<field name="name">theme_prime.s_info_block_5_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_5_1.jpg</field>
</record>
<record id="s_info_block_5_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_5_2</field>
<field name="name">theme_prime.s_info_block_5_2</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_5_2.jpg</field>
</record>
<record id="s_info_block_6_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_6_1</field>
<field name="name">theme_prime.s_info_block_6_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_6_1.jpg</field>
</record>
<record id="s_info_block_6_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_6_2</field>
<field name="name">theme_prime.s_info_block_6_2</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_6_2.jpg</field>
</record>
<record id="s_info_block_7_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_info_block_7_1</field>
<field name="name">theme_prime.s_info_block_7_1</field>
<field name="url">/theme_prime/static/src/img/content/s_info_block_7_1.jpg</field>
</record>
<record id="s_mega_menu_3_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_3_1</field>
<field name="name">theme_prime.s_mega_menu_3_1</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_3_1.jpg</field>
</record>
<record id="s_mega_menu_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_4_1</field>
<field name="name">theme_prime.s_mega_menu_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_4_1.jpg</field>
</record>
<record id="s_mega_menu_5_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_5_1</field>
<field name="name">theme_prime.s_mega_menu_5_1</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_5_1.jpg</field>
</record>
<record id="s_mega_menu_6_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_6_1</field>
<field name="name">theme_prime.s_mega_menu_6_1</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_6_1.jpg</field>
</record>
<record id="s_mega_menu_6_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_6_2</field>
<field name="name">theme_prime.s_mega_menu_6_2</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_6_2.jpg</field>
</record>
<record id="s_mega_menu_6_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_6_3</field>
<field name="name">theme_prime.s_mega_menu_6_3</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_6_3.jpg</field>
</record>
<record id="s_mega_menu_7_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_7_1</field>
<field name="name">theme_prime.s_mega_menu_7_1</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_7_1.jpg</field>
</record>
<record id="s_mega_menu_8_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_8_1</field>
<field name="name">theme_prime.s_mega_menu_8_1</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_8_1.png</field>
</record>
<record id="s_mega_menu_8_2" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_8_2</field>
<field name="name">theme_prime.s_mega_menu_8_2</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_8_2.jpg</field>
</record>
<record id="s_mega_menu_8_3" model="theme.ir.attachment">
<field name="key">theme_prime.s_mega_menu_8_3</field>
<field name="name">theme_prime.s_mega_menu_8_3</field>
<field name="url">/theme_prime/static/src/img/content/s_mega_menu_8_3.png</field>
</record>
<record id="s_pricing_01" model="theme.ir.attachment">
<field name="key">theme_prime.s_pricing_01</field>
<field name="name">theme_prime.s_pricing_01</field>
<field name="url">/theme_prime/static/src/img/content/s_pricing_01.jpg</field>
</record>
<record id="s_pricing_02" model="theme.ir.attachment">
<field name="key">theme_prime.s_pricing_02</field>
<field name="name">theme_prime.s_pricing_02</field>
<field name="url">/theme_prime/static/src/img/content/s_pricing_02.jpg</field>
</record>
<record id="s_pricing_03" model="theme.ir.attachment">
<field name="key">theme_prime.s_pricing_03</field>
<field name="name">theme_prime.s_pricing_03</field>
<field name="url">/theme_prime/static/src/img/content/s_pricing_03.jpg</field>
</record>
<record id="s_pricing_04" model="theme.ir.attachment">
<field name="key">theme_prime.s_pricing_04</field>
<field name="name">theme_prime.s_pricing_04</field>
<field name="url">/theme_prime/static/src/img/content/s_pricing_04.jpg</field>
</record>
<record id="s_subscribe_4_1" model="theme.ir.attachment">
<field name="key">theme_prime.s_subscribe_4_1</field>
<field name="name">theme_prime.s_subscribe_4_1</field>
<field name="url">/theme_prime/static/src/img/content/s_subscribe_4_1.jpg</field>
</record>
<record id="s_team_01" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_01</field>
<field name="name">theme_prime.s_team_01</field>
<field name="url">/theme_prime/static/src/img/content/s_team_01.png</field>
</record>
<record id="s_team_02" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_02</field>
<field name="name">theme_prime.s_team_02</field>
<field name="url">/theme_prime/static/src/img/content/s_team_02.png</field>
</record>
<record id="s_team_03" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_03</field>
<field name="name">theme_prime.s_team_03</field>
<field name="url">/theme_prime/static/src/img/content/s_team_03.png</field>
</record>
<record id="s_team_04" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_04</field>
<field name="name">theme_prime.s_team_04</field>
<field name="url">/theme_prime/static/src/img/content/s_team_04.png</field>
</record>
<record id="s_team_square_01" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_square_01</field>
<field name="name">theme_prime.s_team_square_01</field>
<field name="url">/theme_prime/static/src/img/content/s_team_square_01.png</field>
</record>
<record id="s_team_square_02" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_square_02</field>
<field name="name">theme_prime.s_team_square_02</field>
<field name="url">/theme_prime/static/src/img/content/s_team_square_02.png</field>
</record>
<record id="s_team_square_03" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_square_03</field>
<field name="name">theme_prime.s_team_square_03</field>
<field name="url">/theme_prime/static/src/img/content/s_team_square_03.png</field>
</record>
<record id="s_team_square_04" model="theme.ir.attachment">
<field name="key">theme_prime.s_team_square_04</field>
<field name="name">theme_prime.s_team_square_04</field>
<field name="url">/theme_prime/static/src/img/content/s_team_square_04.png</field>
</record>
<record id="s_testimonial_author_01" model="theme.ir.attachment">
<field name="key">theme_prime.s_testimonial_author_01</field>
<field name="name">theme_prime.s_testimonial_author_01</field>
<field name="url">/theme_prime/static/src/img/content/s_testimonial_author_01.jpg</field>
</record>
<record id="s_testimonial_author_02" model="theme.ir.attachment">
<field name="key">theme_prime.s_testimonial_author_02</field>
<field name="name">theme_prime.s_testimonial_author_02</field>
<field name="url">/theme_prime/static/src/img/content/s_testimonial_author_02.jpg</field>
</record>
<record id="s_testimonial_author_03" model="theme.ir.attachment">
<field name="key">theme_prime.s_testimonial_author_03</field>
<field name="name">theme_prime.s_testimonial_author_03</field>
<field name="url">/theme_prime/static/src/img/content/s_testimonial_author_03.jpg</field>
</record>
</odoo>

View File

@ -1,117 +0,0 @@
id,key,name,url
s_banner_1_1,theme_prime.s_banner_1_1,theme_prime.s_banner_1_1,/theme_prime/static/src/img/snippets/s_banner_1_1.jpg
s_banner_1_2,theme_prime.s_banner_1_2,theme_prime.s_banner_1_2,/theme_prime/static/src/img/snippets/s_banner_1_2.jpg
s_banner_1_3,theme_prime.s_banner_1_3,theme_prime.s_banner_1_3,/theme_prime/static/src/img/snippets/s_banner_1_3.jpg
s_banner_3_1,theme_prime.s_banner_3_1,theme_prime.s_banner_3_1,/theme_prime/static/src/img/snippets/s_banner_3_1.jpg
s_banner_3_2,theme_prime.s_banner_3_2,theme_prime.s_banner_3_2,/theme_prime/static/src/img/snippets/s_banner_3_2.jpg
s_banner_3_3,theme_prime.s_banner_3_3,theme_prime.s_banner_3_3,/theme_prime/static/src/img/snippets/s_banner_3_3.jpg
s_banner_4_1,theme_prime.s_banner_4_1,theme_prime.s_banner_4_1,/theme_prime/static/src/img/snippets/s_banner_4_1.jpg
s_banner_4_2,theme_prime.s_banner_4_2,theme_prime.s_banner_4_2,/theme_prime/static/src/img/snippets/s_banner_4_2.jpg
s_banner_4_3,theme_prime.s_banner_4_3,theme_prime.s_banner_4_3,/theme_prime/static/src/img/snippets/s_banner_4_3.jpg
s_banner_5_1,theme_prime.s_banner_5_1,theme_prime.s_banner_5_1,/theme_prime/static/src/img/snippets/s_banner_5_1.png
s_banner_5_2,theme_prime.s_banner_5_2,theme_prime.s_banner_5_2,/theme_prime/static/src/img/snippets/s_banner_5_2.png
s_banner_6_1,theme_prime.s_banner_6_1,theme_prime.s_banner_6_1,/theme_prime/static/src/img/snippets/s_banner_6_1.jpg
s_banner_6_2,theme_prime.s_banner_6_2,theme_prime.s_banner_6_2,/theme_prime/static/src/img/snippets/s_banner_6_2.jpg
s_banner_6_3,theme_prime.s_banner_6_3,theme_prime.s_banner_6_3,/theme_prime/static/src/img/snippets/s_banner_6_3.jpg
s_brand_1,theme_prime.s_brand_1,theme_prime.s_brand_1,/theme_prime/static/src/img/snippets/s_brand_1.png
s_brand_2,theme_prime.s_brand_2,theme_prime.s_brand_2,/theme_prime/static/src/img/snippets/s_brand_2.png
s_brand_3,theme_prime.s_brand_3,theme_prime.s_brand_3,/theme_prime/static/src/img/snippets/s_brand_3.png
s_banner_7_1,theme_prime.s_banner_7_1,theme_prime.s_banner_7_1,/theme_prime/static/src/img/snippets/s_banner_7_1.jpg
s_banner_7_2,theme_prime.s_banner_7_2,theme_prime.s_banner_7_2,/theme_prime/static/src/img/snippets/s_banner_7_2.jpg
s_banner_7_3,theme_prime.s_banner_7_3,theme_prime.s_banner_7_3,/theme_prime/static/src/img/snippets/s_banner_7_3.jpg
s_banner_8_1,theme_prime.s_banner_8_1,theme_prime.s_banner_8_1,/theme_prime/static/src/img/snippets/s_banner_8_1.jpg
s_banner_8_2,theme_prime.s_banner_8_2,theme_prime.s_banner_8_2,/theme_prime/static/src/img/snippets/s_banner_8_2.jpg
s_banner_8_3,theme_prime.s_banner_8_3,theme_prime.s_banner_8_3,/theme_prime/static/src/img/snippets/s_banner_8_3.jpg
s_banner_9_1,theme_prime.s_banner_9_1,theme_prime.s_banner_9_1,/theme_prime/static/src/img/snippets/s_banner_9_1.jpg
s_banner_9_2,theme_prime.s_banner_9_2,theme_prime.s_banner_9_2,/theme_prime/static/src/img/snippets/s_banner_9_2.jpg
s_banner_9_3,theme_prime.s_banner_9_3,theme_prime.s_banner_9_3,/theme_prime/static/src/img/snippets/s_banner_9_3.jpg
s_banner_10_1,theme_prime.s_banner_10_1,theme_prime.s_banner_10_1,/theme_prime/static/src/img/snippets/s_banner_10_1.png
s_banner_12_1,theme_prime.s_banner_12_1,theme_prime.s_banner_12_1,/theme_prime/static/src/img/snippets/s_banner_12_1.jpg
s_banner_12_2,theme_prime.s_banner_12_2,theme_prime.s_banner_12_2,/theme_prime/static/src/img/snippets/s_banner_12_2.jpg
s_banner_13_1,theme_prime.s_banner_13_1,theme_prime.s_banner_13_1,/theme_prime/static/src/img/snippets/s_banner_13_1.jpg
s_banner_13_2,theme_prime.s_banner_13_2,theme_prime.s_banner_13_2,/theme_prime/static/src/img/snippets/s_banner_13_2.jpg
s_banner_13_3,theme_prime.s_banner_13_3,theme_prime.s_banner_13_3,/theme_prime/static/src/img/snippets/s_banner_13_3.jpg
s_banner_13_4,theme_prime.s_banner_13_4,theme_prime.s_banner_13_4,/theme_prime/static/src/img/snippets/s_banner_13_4.jpg
s_banner_14_1,theme_prime.s_banner_14_1,theme_prime.s_banner_14_1,/theme_prime/static/src/img/snippets/s_banner_14_1.png
s_banner_14_2,theme_prime.s_banner_14_2,theme_prime.s_banner_14_2,/theme_prime/static/src/img/snippets/s_banner_14_2.png
s_banner_15_1,theme_prime.s_banner_15_1,theme_prime.s_banner_15_1,/theme_prime/static/src/img/snippets/s_banner_15_1.jpg
s_client_01,theme_prime.s_client_01,theme_prime.s_client_01,/theme_prime/static/src/img/snippets/s_client_01.png
s_client_02,theme_prime.s_client_02,theme_prime.s_client_02,/theme_prime/static/src/img/snippets/s_client_02.png
s_client_03,theme_prime.s_client_03,theme_prime.s_client_03,/theme_prime/static/src/img/snippets/s_client_03.png
s_client_04,theme_prime.s_client_04,theme_prime.s_client_04,/theme_prime/static/src/img/snippets/s_client_04.png
s_client_05,theme_prime.s_client_05,theme_prime.s_client_05,/theme_prime/static/src/img/snippets/s_client_05.png
s_client_06,theme_prime.s_client_06,theme_prime.s_client_06,/theme_prime/static/src/img/snippets/s_client_06.png
s_client_07,theme_prime.s_client_07,theme_prime.s_client_07,/theme_prime/static/src/img/snippets/s_client_07.png
s_client_08,theme_prime.s_client_08,theme_prime.s_client_08,/theme_prime/static/src/img/snippets/s_client_08.png
s_client_09,theme_prime.s_client_09,theme_prime.s_client_09,/theme_prime/static/src/img/snippets/s_client_09.png
s_client_10,theme_prime.s_client_10,theme_prime.s_client_10,/theme_prime/static/src/img/snippets/s_client_10.png
s_client_11,theme_prime.s_client_11,theme_prime.s_client_11,/theme_prime/static/src/img/snippets/s_client_11.png
s_client_12,theme_prime.s_client_12,theme_prime.s_client_12,/theme_prime/static/src/img/snippets/s_client_12.png
s_coming_soon_2_1,theme_prime.s_coming_soon_2_1,theme_prime.s_coming_soon_2_1,/theme_prime/static/src/img/snippets/s_coming_soon_2_1.png
s_coming_soon_2_2,theme_prime.s_coming_soon_2_2,theme_prime.s_coming_soon_2_2,/theme_prime/static/src/img/snippets/s_coming_soon_2_2.jpg
s_info_block_1_1,theme_prime.s_info_block_1_1,theme_prime.s_info_block_1_1,/theme_prime/static/src/img/snippets/s_info_block_1_1.jpg
s_info_block_2_1,theme_prime.s_info_block_2_1,theme_prime.s_info_block_2_1,/theme_prime/static/src/img/snippets/s_info_block_2_1.jpg
s_info_block_3_1,theme_prime.s_info_block_3_1,theme_prime.s_info_block_3_1,/theme_prime/static/src/img/snippets/s_info_block_3_1.jpg
s_info_block_3_2,theme_prime.s_info_block_3_2,theme_prime.s_info_block_3_2,/theme_prime/static/src/img/snippets/s_info_block_3_2.jpg
s_info_block_4_1,theme_prime.s_info_block_4_1,theme_prime.s_info_block_4_1,/theme_prime/static/src/img/snippets/s_info_block_4_1.jpg
s_info_block_4_2,theme_prime.s_info_block_4_2,theme_prime.s_info_block_4_2,/theme_prime/static/src/img/snippets/s_info_block_4_2.jpg
s_info_block_4_3,theme_prime.s_info_block_4_3,theme_prime.s_info_block_4_3,/theme_prime/static/src/img/snippets/s_info_block_4_3.jpg
s_info_block_5_1,theme_prime.s_info_block_5_1,theme_prime.s_info_block_5_1,/theme_prime/static/src/img/snippets/s_info_block_5_1.jpg
s_info_block_5_2,theme_prime.s_info_block_5_2,theme_prime.s_info_block_5_2,/theme_prime/static/src/img/snippets/s_info_block_5_2.jpg
s_info_block_6_1,theme_prime.s_info_block_6_1,theme_prime.s_info_block_6_1,/theme_prime/static/src/img/snippets/s_info_block_6_1.jpg
s_info_block_7_1,theme_prime.s_info_block_7_1,theme_prime.s_info_block_7_1,/theme_prime/static/src/img/snippets/s_info_block_7_1.jpeg
s_info_block_8_1,theme_prime.s_info_block_8_1,theme_prime.s_info_block_8_1,/theme_prime/static/src/img/snippets/s_info_block_8_1.png
s_cover_1_1,theme_prime.s_cover_1_1,theme_prime.s_cover_1_1,/theme_prime/static/src/img/snippets/s_cover_1_1.png
s_cover_1_2,theme_prime.s_cover_1_2,theme_prime.s_cover_1_2,/theme_prime/static/src/img/snippets/s_cover_1_2.png
s_cover_1_brand_1,theme_prime.s_cover_1_brand_1,theme_prime.s_cover_1_brand_1,/theme_prime/static/src/img/snippets/s_cover_1_brand_1.png
s_cover_1_brand_2,theme_prime.s_cover_1_brand_2,theme_prime.s_cover_1_brand_2,/theme_prime/static/src/img/snippets/s_cover_1_brand_2.png
s_cover_2_1,theme_prime.s_cover_2_1,theme_prime.s_cover_2_1,/theme_prime/static/src/img/snippets/s_cover_2_1.jpg
s_cover_2_2,theme_prime.s_cover_2_2,theme_prime.s_cover_2_2,/theme_prime/static/src/img/snippets/s_cover_2_2.jpg
s_cover_3_1,theme_prime.s_cover_3_1,theme_prime.s_cover_3_1,/theme_prime/static/src/img/snippets/s_cover_3_1.jpg
s_cover_4_1,theme_prime.s_cover_4_1,theme_prime.s_cover_4_1,/theme_prime/static/src/img/snippets/s_cover_4_1.png
s_cover_4_2,theme_prime.s_cover_4_2,theme_prime.s_cover_4_2,/theme_prime/static/src/img/snippets/s_cover_4_2.png
s_cover_4_3,theme_prime.s_cover_4_3,theme_prime.s_cover_4_3,/theme_prime/static/src/img/snippets/s_cover_4_3.png
s_cover_4_4,theme_prime.s_cover_4_4,theme_prime.s_cover_4_4,/theme_prime/static/src/img/snippets/s_cover_4_4.png
s_cover_4_5,theme_prime.s_cover_4_5,theme_prime.s_cover_4_5,/theme_prime/static/src/img/snippets/s_cover_4_5.png
s_call_to_action_5_1,theme_prime.s_call_to_action_5_1,theme_prime.s_call_to_action_5_1,/theme_prime/static/src/img/snippets/s_call_to_action_5_1.jpg
s_gallery_01,theme_prime.s_gallery_01,theme_prime.s_gallery_01,/theme_prime/static/src/img/snippets/s_gallery_01.jpg
s_gallery_02,theme_prime.s_gallery_02,theme_prime.s_gallery_02,/theme_prime/static/src/img/snippets/s_gallery_02.jpg
s_gallery_03,theme_prime.s_gallery_03,theme_prime.s_gallery_03,/theme_prime/static/src/img/snippets/s_gallery_03.jpg
s_gallery_04,theme_prime.s_gallery_04,theme_prime.s_gallery_04,/theme_prime/static/src/img/snippets/s_gallery_04.jpg
s_gallery_05,theme_prime.s_gallery_05,theme_prime.s_gallery_05,/theme_prime/static/src/img/snippets/s_gallery_05.jpg
s_gallery_06,theme_prime.s_gallery_06,theme_prime.s_gallery_06,/theme_prime/static/src/img/snippets/s_gallery_06.jpg
s_gallery_07,theme_prime.s_gallery_07,theme_prime.s_gallery_07,/theme_prime/static/src/img/snippets/s_gallery_07.jpg
s_gallery_08,theme_prime.s_gallery_08,theme_prime.s_gallery_08,/theme_prime/static/src/img/snippets/s_gallery_08.jpg
s_gallery_09,theme_prime.s_gallery_09,theme_prime.s_gallery_09,/theme_prime/static/src/img/snippets/s_gallery_09.jpg
s_gallery_10,theme_prime.s_gallery_10,theme_prime.s_gallery_10,/theme_prime/static/src/img/snippets/s_gallery_10.jpg
s_gallery_11,theme_prime.s_gallery_11,theme_prime.s_gallery_11,/theme_prime/static/src/img/snippets/s_gallery_11.jpg
s_gallery_12,theme_prime.s_gallery_12,theme_prime.s_gallery_12,/theme_prime/static/src/img/snippets/s_gallery_12.jpg
s_mega_menu_prime_2_1,theme_prime.s_mega_menu_prime_2_1,theme_prime.s_mega_menu_prime_2_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_2_1.jpg
s_mega_menu_prime_3_1,theme_prime.s_mega_menu_prime_3_1,theme_prime.s_mega_menu_prime_3_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_3_1.png
s_mega_menu_prime_4_1,theme_prime.s_mega_menu_prime_4_1,theme_prime.s_mega_menu_prime_4_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_4_1.jpg
s_mega_menu_prime_5_1,theme_prime.s_mega_menu_prime_5_1,theme_prime.s_mega_menu_prime_5_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_1.jpg
s_mega_menu_prime_5_2,theme_prime.s_mega_menu_prime_5_2,theme_prime.s_mega_menu_prime_5_2,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_2.jpg
s_mega_menu_prime_5_3,theme_prime.s_mega_menu_prime_5_3,theme_prime.s_mega_menu_prime_5_3,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_3.jpg
s_mega_menu_prime_5_4,theme_prime.s_mega_menu_prime_5_4,theme_prime.s_mega_menu_prime_5_4,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_4.jpg
s_mega_menu_prime_6_1,theme_prime.s_mega_menu_prime_6_1,theme_prime.s_mega_menu_prime_6_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_6_1.jpg
s_mega_menu_prime_6_2,theme_prime.s_mega_menu_prime_6_2,theme_prime.s_mega_menu_prime_6_2,/theme_prime/static/src/img/snippets/s_mega_menu_prime_6_2.png
s_mega_menu_prime_6_3,theme_prime.s_mega_menu_prime_6_3,theme_prime.s_mega_menu_prime_6_3,/theme_prime/static/src/img/snippets/s_mega_menu_prime_6_3.jpg
s_pricing_01,theme_prime.s_pricing_01,theme_prime.s_pricing_01,/theme_prime/static/src/img/snippets/s_pricing_01.jpg
s_pricing_02,theme_prime.s_pricing_02,theme_prime.s_pricing_02,/theme_prime/static/src/img/snippets/s_pricing_02.jpg
s_pricing_03,theme_prime.s_pricing_03,theme_prime.s_pricing_03,/theme_prime/static/src/img/snippets/s_pricing_03.jpg
s_pricing_04,theme_prime.s_pricing_04,theme_prime.s_pricing_04,/theme_prime/static/src/img/snippets/s_pricing_04.jpg
s_shop_offer_1_1,theme_prime.s_shop_offer_1_1,theme_prime.s_shop_offer_1_1,/theme_prime/static/src/img/snippets/s_shop_offer_1_1.jpg
s_shop_offer_3_1,theme_prime.s_shop_offer_3_1,theme_prime.s_shop_offer_3_1,/theme_prime/static/src/img/snippets/s_shop_offer_3_1.jpg
s_shop_offer_4_1,theme_prime.s_shop_offer_4_1,theme_prime.s_shop_offer_4_1,/theme_prime/static/src/img/snippets/s_shop_offer_4_1.jpg
s_subscribe_4_1,theme_prime.s_subscribe_4_1,theme_prime.s_subscribe_4_1,/theme_prime/static/src/img/snippets/s_subscribe_4_1.jpg
s_team_01,theme_prime.s_team_01,theme_prime.s_team_01,/theme_prime/static/src/img/snippets/s_team_01.png
s_team_02,theme_prime.s_team_02,theme_prime.s_team_02,/theme_prime/static/src/img/snippets/s_team_02.png
s_team_03,theme_prime.s_team_03,theme_prime.s_team_03,/theme_prime/static/src/img/snippets/s_team_03.png
s_team_04,theme_prime.s_team_04,theme_prime.s_team_04,/theme_prime/static/src/img/snippets/s_team_04.png
s_team_square_01,theme_prime.s_team_square_01,theme_prime.s_team_square_01,/theme_prime/static/src/img/snippets/s_team_square_01.png
s_team_square_02,theme_prime.s_team_square_02,theme_prime.s_team_square_02,/theme_prime/static/src/img/snippets/s_team_square_02.png
s_team_square_03,theme_prime.s_team_square_03,theme_prime.s_team_square_03,/theme_prime/static/src/img/snippets/s_team_square_03.png
s_team_square_04,theme_prime.s_team_square_04,theme_prime.s_team_square_04,/theme_prime/static/src/img/snippets/s_team_square_04.png
s_testimonial_author_01,theme_prime.s_testimonial_author_01,theme_prime.s_testimonial_author_01,/theme_prime/static/src/img/snippets/s_testimonial_author_01.jpg
s_testimonial_author_02,theme_prime.s_testimonial_author_02,theme_prime.s_testimonial_author_02,/theme_prime/static/src/img/snippets/s_testimonial_author_02.jpg
s_testimonial_author_03,theme_prime.s_testimonial_author_03,theme_prime.s_testimonial_author_03,/theme_prime/static/src/img/snippets/s_testimonial_author_03.jpg
1 id key name url
2 s_banner_1_1 theme_prime.s_banner_1_1 theme_prime.s_banner_1_1 /theme_prime/static/src/img/snippets/s_banner_1_1.jpg
3 s_banner_1_2 theme_prime.s_banner_1_2 theme_prime.s_banner_1_2 /theme_prime/static/src/img/snippets/s_banner_1_2.jpg
4 s_banner_1_3 theme_prime.s_banner_1_3 theme_prime.s_banner_1_3 /theme_prime/static/src/img/snippets/s_banner_1_3.jpg
5 s_banner_3_1 theme_prime.s_banner_3_1 theme_prime.s_banner_3_1 /theme_prime/static/src/img/snippets/s_banner_3_1.jpg
6 s_banner_3_2 theme_prime.s_banner_3_2 theme_prime.s_banner_3_2 /theme_prime/static/src/img/snippets/s_banner_3_2.jpg
7 s_banner_3_3 theme_prime.s_banner_3_3 theme_prime.s_banner_3_3 /theme_prime/static/src/img/snippets/s_banner_3_3.jpg
8 s_banner_4_1 theme_prime.s_banner_4_1 theme_prime.s_banner_4_1 /theme_prime/static/src/img/snippets/s_banner_4_1.jpg
9 s_banner_4_2 theme_prime.s_banner_4_2 theme_prime.s_banner_4_2 /theme_prime/static/src/img/snippets/s_banner_4_2.jpg
10 s_banner_4_3 theme_prime.s_banner_4_3 theme_prime.s_banner_4_3 /theme_prime/static/src/img/snippets/s_banner_4_3.jpg
11 s_banner_5_1 theme_prime.s_banner_5_1 theme_prime.s_banner_5_1 /theme_prime/static/src/img/snippets/s_banner_5_1.png
12 s_banner_5_2 theme_prime.s_banner_5_2 theme_prime.s_banner_5_2 /theme_prime/static/src/img/snippets/s_banner_5_2.png
13 s_banner_6_1 theme_prime.s_banner_6_1 theme_prime.s_banner_6_1 /theme_prime/static/src/img/snippets/s_banner_6_1.jpg
14 s_banner_6_2 theme_prime.s_banner_6_2 theme_prime.s_banner_6_2 /theme_prime/static/src/img/snippets/s_banner_6_2.jpg
15 s_banner_6_3 theme_prime.s_banner_6_3 theme_prime.s_banner_6_3 /theme_prime/static/src/img/snippets/s_banner_6_3.jpg
16 s_brand_1 theme_prime.s_brand_1 theme_prime.s_brand_1 /theme_prime/static/src/img/snippets/s_brand_1.png
17 s_brand_2 theme_prime.s_brand_2 theme_prime.s_brand_2 /theme_prime/static/src/img/snippets/s_brand_2.png
18 s_brand_3 theme_prime.s_brand_3 theme_prime.s_brand_3 /theme_prime/static/src/img/snippets/s_brand_3.png
19 s_banner_7_1 theme_prime.s_banner_7_1 theme_prime.s_banner_7_1 /theme_prime/static/src/img/snippets/s_banner_7_1.jpg
20 s_banner_7_2 theme_prime.s_banner_7_2 theme_prime.s_banner_7_2 /theme_prime/static/src/img/snippets/s_banner_7_2.jpg
21 s_banner_7_3 theme_prime.s_banner_7_3 theme_prime.s_banner_7_3 /theme_prime/static/src/img/snippets/s_banner_7_3.jpg
22 s_banner_8_1 theme_prime.s_banner_8_1 theme_prime.s_banner_8_1 /theme_prime/static/src/img/snippets/s_banner_8_1.jpg
23 s_banner_8_2 theme_prime.s_banner_8_2 theme_prime.s_banner_8_2 /theme_prime/static/src/img/snippets/s_banner_8_2.jpg
24 s_banner_8_3 theme_prime.s_banner_8_3 theme_prime.s_banner_8_3 /theme_prime/static/src/img/snippets/s_banner_8_3.jpg
25 s_banner_9_1 theme_prime.s_banner_9_1 theme_prime.s_banner_9_1 /theme_prime/static/src/img/snippets/s_banner_9_1.jpg
26 s_banner_9_2 theme_prime.s_banner_9_2 theme_prime.s_banner_9_2 /theme_prime/static/src/img/snippets/s_banner_9_2.jpg
27 s_banner_9_3 theme_prime.s_banner_9_3 theme_prime.s_banner_9_3 /theme_prime/static/src/img/snippets/s_banner_9_3.jpg
28 s_banner_10_1 theme_prime.s_banner_10_1 theme_prime.s_banner_10_1 /theme_prime/static/src/img/snippets/s_banner_10_1.png
29 s_banner_12_1 theme_prime.s_banner_12_1 theme_prime.s_banner_12_1 /theme_prime/static/src/img/snippets/s_banner_12_1.jpg
30 s_banner_12_2 theme_prime.s_banner_12_2 theme_prime.s_banner_12_2 /theme_prime/static/src/img/snippets/s_banner_12_2.jpg
31 s_banner_13_1 theme_prime.s_banner_13_1 theme_prime.s_banner_13_1 /theme_prime/static/src/img/snippets/s_banner_13_1.jpg
32 s_banner_13_2 theme_prime.s_banner_13_2 theme_prime.s_banner_13_2 /theme_prime/static/src/img/snippets/s_banner_13_2.jpg
33 s_banner_13_3 theme_prime.s_banner_13_3 theme_prime.s_banner_13_3 /theme_prime/static/src/img/snippets/s_banner_13_3.jpg
34 s_banner_13_4 theme_prime.s_banner_13_4 theme_prime.s_banner_13_4 /theme_prime/static/src/img/snippets/s_banner_13_4.jpg
35 s_banner_14_1 theme_prime.s_banner_14_1 theme_prime.s_banner_14_1 /theme_prime/static/src/img/snippets/s_banner_14_1.png
36 s_banner_14_2 theme_prime.s_banner_14_2 theme_prime.s_banner_14_2 /theme_prime/static/src/img/snippets/s_banner_14_2.png
37 s_banner_15_1 theme_prime.s_banner_15_1 theme_prime.s_banner_15_1 /theme_prime/static/src/img/snippets/s_banner_15_1.jpg
38 s_client_01 theme_prime.s_client_01 theme_prime.s_client_01 /theme_prime/static/src/img/snippets/s_client_01.png
39 s_client_02 theme_prime.s_client_02 theme_prime.s_client_02 /theme_prime/static/src/img/snippets/s_client_02.png
40 s_client_03 theme_prime.s_client_03 theme_prime.s_client_03 /theme_prime/static/src/img/snippets/s_client_03.png
41 s_client_04 theme_prime.s_client_04 theme_prime.s_client_04 /theme_prime/static/src/img/snippets/s_client_04.png
42 s_client_05 theme_prime.s_client_05 theme_prime.s_client_05 /theme_prime/static/src/img/snippets/s_client_05.png
43 s_client_06 theme_prime.s_client_06 theme_prime.s_client_06 /theme_prime/static/src/img/snippets/s_client_06.png
44 s_client_07 theme_prime.s_client_07 theme_prime.s_client_07 /theme_prime/static/src/img/snippets/s_client_07.png
45 s_client_08 theme_prime.s_client_08 theme_prime.s_client_08 /theme_prime/static/src/img/snippets/s_client_08.png
46 s_client_09 theme_prime.s_client_09 theme_prime.s_client_09 /theme_prime/static/src/img/snippets/s_client_09.png
47 s_client_10 theme_prime.s_client_10 theme_prime.s_client_10 /theme_prime/static/src/img/snippets/s_client_10.png
48 s_client_11 theme_prime.s_client_11 theme_prime.s_client_11 /theme_prime/static/src/img/snippets/s_client_11.png
49 s_client_12 theme_prime.s_client_12 theme_prime.s_client_12 /theme_prime/static/src/img/snippets/s_client_12.png
50 s_coming_soon_2_1 theme_prime.s_coming_soon_2_1 theme_prime.s_coming_soon_2_1 /theme_prime/static/src/img/snippets/s_coming_soon_2_1.png
51 s_coming_soon_2_2 theme_prime.s_coming_soon_2_2 theme_prime.s_coming_soon_2_2 /theme_prime/static/src/img/snippets/s_coming_soon_2_2.jpg
52 s_info_block_1_1 theme_prime.s_info_block_1_1 theme_prime.s_info_block_1_1 /theme_prime/static/src/img/snippets/s_info_block_1_1.jpg
53 s_info_block_2_1 theme_prime.s_info_block_2_1 theme_prime.s_info_block_2_1 /theme_prime/static/src/img/snippets/s_info_block_2_1.jpg
54 s_info_block_3_1 theme_prime.s_info_block_3_1 theme_prime.s_info_block_3_1 /theme_prime/static/src/img/snippets/s_info_block_3_1.jpg
55 s_info_block_3_2 theme_prime.s_info_block_3_2 theme_prime.s_info_block_3_2 /theme_prime/static/src/img/snippets/s_info_block_3_2.jpg
56 s_info_block_4_1 theme_prime.s_info_block_4_1 theme_prime.s_info_block_4_1 /theme_prime/static/src/img/snippets/s_info_block_4_1.jpg
57 s_info_block_4_2 theme_prime.s_info_block_4_2 theme_prime.s_info_block_4_2 /theme_prime/static/src/img/snippets/s_info_block_4_2.jpg
58 s_info_block_4_3 theme_prime.s_info_block_4_3 theme_prime.s_info_block_4_3 /theme_prime/static/src/img/snippets/s_info_block_4_3.jpg
59 s_info_block_5_1 theme_prime.s_info_block_5_1 theme_prime.s_info_block_5_1 /theme_prime/static/src/img/snippets/s_info_block_5_1.jpg
60 s_info_block_5_2 theme_prime.s_info_block_5_2 theme_prime.s_info_block_5_2 /theme_prime/static/src/img/snippets/s_info_block_5_2.jpg
61 s_info_block_6_1 theme_prime.s_info_block_6_1 theme_prime.s_info_block_6_1 /theme_prime/static/src/img/snippets/s_info_block_6_1.jpg
62 s_info_block_7_1 theme_prime.s_info_block_7_1 theme_prime.s_info_block_7_1 /theme_prime/static/src/img/snippets/s_info_block_7_1.jpeg
63 s_info_block_8_1 theme_prime.s_info_block_8_1 theme_prime.s_info_block_8_1 /theme_prime/static/src/img/snippets/s_info_block_8_1.png
64 s_cover_1_1 theme_prime.s_cover_1_1 theme_prime.s_cover_1_1 /theme_prime/static/src/img/snippets/s_cover_1_1.png
65 s_cover_1_2 theme_prime.s_cover_1_2 theme_prime.s_cover_1_2 /theme_prime/static/src/img/snippets/s_cover_1_2.png
66 s_cover_1_brand_1 theme_prime.s_cover_1_brand_1 theme_prime.s_cover_1_brand_1 /theme_prime/static/src/img/snippets/s_cover_1_brand_1.png
67 s_cover_1_brand_2 theme_prime.s_cover_1_brand_2 theme_prime.s_cover_1_brand_2 /theme_prime/static/src/img/snippets/s_cover_1_brand_2.png
68 s_cover_2_1 theme_prime.s_cover_2_1 theme_prime.s_cover_2_1 /theme_prime/static/src/img/snippets/s_cover_2_1.jpg
69 s_cover_2_2 theme_prime.s_cover_2_2 theme_prime.s_cover_2_2 /theme_prime/static/src/img/snippets/s_cover_2_2.jpg
70 s_cover_3_1 theme_prime.s_cover_3_1 theme_prime.s_cover_3_1 /theme_prime/static/src/img/snippets/s_cover_3_1.jpg
71 s_cover_4_1 theme_prime.s_cover_4_1 theme_prime.s_cover_4_1 /theme_prime/static/src/img/snippets/s_cover_4_1.png
72 s_cover_4_2 theme_prime.s_cover_4_2 theme_prime.s_cover_4_2 /theme_prime/static/src/img/snippets/s_cover_4_2.png
73 s_cover_4_3 theme_prime.s_cover_4_3 theme_prime.s_cover_4_3 /theme_prime/static/src/img/snippets/s_cover_4_3.png
74 s_cover_4_4 theme_prime.s_cover_4_4 theme_prime.s_cover_4_4 /theme_prime/static/src/img/snippets/s_cover_4_4.png
75 s_cover_4_5 theme_prime.s_cover_4_5 theme_prime.s_cover_4_5 /theme_prime/static/src/img/snippets/s_cover_4_5.png
76 s_call_to_action_5_1 theme_prime.s_call_to_action_5_1 theme_prime.s_call_to_action_5_1 /theme_prime/static/src/img/snippets/s_call_to_action_5_1.jpg
77 s_gallery_01 theme_prime.s_gallery_01 theme_prime.s_gallery_01 /theme_prime/static/src/img/snippets/s_gallery_01.jpg
78 s_gallery_02 theme_prime.s_gallery_02 theme_prime.s_gallery_02 /theme_prime/static/src/img/snippets/s_gallery_02.jpg
79 s_gallery_03 theme_prime.s_gallery_03 theme_prime.s_gallery_03 /theme_prime/static/src/img/snippets/s_gallery_03.jpg
80 s_gallery_04 theme_prime.s_gallery_04 theme_prime.s_gallery_04 /theme_prime/static/src/img/snippets/s_gallery_04.jpg
81 s_gallery_05 theme_prime.s_gallery_05 theme_prime.s_gallery_05 /theme_prime/static/src/img/snippets/s_gallery_05.jpg
82 s_gallery_06 theme_prime.s_gallery_06 theme_prime.s_gallery_06 /theme_prime/static/src/img/snippets/s_gallery_06.jpg
83 s_gallery_07 theme_prime.s_gallery_07 theme_prime.s_gallery_07 /theme_prime/static/src/img/snippets/s_gallery_07.jpg
84 s_gallery_08 theme_prime.s_gallery_08 theme_prime.s_gallery_08 /theme_prime/static/src/img/snippets/s_gallery_08.jpg
85 s_gallery_09 theme_prime.s_gallery_09 theme_prime.s_gallery_09 /theme_prime/static/src/img/snippets/s_gallery_09.jpg
86 s_gallery_10 theme_prime.s_gallery_10 theme_prime.s_gallery_10 /theme_prime/static/src/img/snippets/s_gallery_10.jpg
87 s_gallery_11 theme_prime.s_gallery_11 theme_prime.s_gallery_11 /theme_prime/static/src/img/snippets/s_gallery_11.jpg
88 s_gallery_12 theme_prime.s_gallery_12 theme_prime.s_gallery_12 /theme_prime/static/src/img/snippets/s_gallery_12.jpg
89 s_mega_menu_prime_2_1 theme_prime.s_mega_menu_prime_2_1 theme_prime.s_mega_menu_prime_2_1 /theme_prime/static/src/img/snippets/s_mega_menu_prime_2_1.jpg
90 s_mega_menu_prime_3_1 theme_prime.s_mega_menu_prime_3_1 theme_prime.s_mega_menu_prime_3_1 /theme_prime/static/src/img/snippets/s_mega_menu_prime_3_1.png
91 s_mega_menu_prime_4_1 theme_prime.s_mega_menu_prime_4_1 theme_prime.s_mega_menu_prime_4_1 /theme_prime/static/src/img/snippets/s_mega_menu_prime_4_1.jpg
92 s_mega_menu_prime_5_1 theme_prime.s_mega_menu_prime_5_1 theme_prime.s_mega_menu_prime_5_1 /theme_prime/static/src/img/snippets/s_mega_menu_prime_5_1.jpg
93 s_mega_menu_prime_5_2 theme_prime.s_mega_menu_prime_5_2 theme_prime.s_mega_menu_prime_5_2 /theme_prime/static/src/img/snippets/s_mega_menu_prime_5_2.jpg
94 s_mega_menu_prime_5_3 theme_prime.s_mega_menu_prime_5_3 theme_prime.s_mega_menu_prime_5_3 /theme_prime/static/src/img/snippets/s_mega_menu_prime_5_3.jpg
95 s_mega_menu_prime_5_4 theme_prime.s_mega_menu_prime_5_4 theme_prime.s_mega_menu_prime_5_4 /theme_prime/static/src/img/snippets/s_mega_menu_prime_5_4.jpg
96 s_mega_menu_prime_6_1 theme_prime.s_mega_menu_prime_6_1 theme_prime.s_mega_menu_prime_6_1 /theme_prime/static/src/img/snippets/s_mega_menu_prime_6_1.jpg
97 s_mega_menu_prime_6_2 theme_prime.s_mega_menu_prime_6_2 theme_prime.s_mega_menu_prime_6_2 /theme_prime/static/src/img/snippets/s_mega_menu_prime_6_2.png
98 s_mega_menu_prime_6_3 theme_prime.s_mega_menu_prime_6_3 theme_prime.s_mega_menu_prime_6_3 /theme_prime/static/src/img/snippets/s_mega_menu_prime_6_3.jpg
99 s_pricing_01 theme_prime.s_pricing_01 theme_prime.s_pricing_01 /theme_prime/static/src/img/snippets/s_pricing_01.jpg
100 s_pricing_02 theme_prime.s_pricing_02 theme_prime.s_pricing_02 /theme_prime/static/src/img/snippets/s_pricing_02.jpg
101 s_pricing_03 theme_prime.s_pricing_03 theme_prime.s_pricing_03 /theme_prime/static/src/img/snippets/s_pricing_03.jpg
102 s_pricing_04 theme_prime.s_pricing_04 theme_prime.s_pricing_04 /theme_prime/static/src/img/snippets/s_pricing_04.jpg
103 s_shop_offer_1_1 theme_prime.s_shop_offer_1_1 theme_prime.s_shop_offer_1_1 /theme_prime/static/src/img/snippets/s_shop_offer_1_1.jpg
104 s_shop_offer_3_1 theme_prime.s_shop_offer_3_1 theme_prime.s_shop_offer_3_1 /theme_prime/static/src/img/snippets/s_shop_offer_3_1.jpg
105 s_shop_offer_4_1 theme_prime.s_shop_offer_4_1 theme_prime.s_shop_offer_4_1 /theme_prime/static/src/img/snippets/s_shop_offer_4_1.jpg
106 s_subscribe_4_1 theme_prime.s_subscribe_4_1 theme_prime.s_subscribe_4_1 /theme_prime/static/src/img/snippets/s_subscribe_4_1.jpg
107 s_team_01 theme_prime.s_team_01 theme_prime.s_team_01 /theme_prime/static/src/img/snippets/s_team_01.png
108 s_team_02 theme_prime.s_team_02 theme_prime.s_team_02 /theme_prime/static/src/img/snippets/s_team_02.png
109 s_team_03 theme_prime.s_team_03 theme_prime.s_team_03 /theme_prime/static/src/img/snippets/s_team_03.png
110 s_team_04 theme_prime.s_team_04 theme_prime.s_team_04 /theme_prime/static/src/img/snippets/s_team_04.png
111 s_team_square_01 theme_prime.s_team_square_01 theme_prime.s_team_square_01 /theme_prime/static/src/img/snippets/s_team_square_01.png
112 s_team_square_02 theme_prime.s_team_square_02 theme_prime.s_team_square_02 /theme_prime/static/src/img/snippets/s_team_square_02.png
113 s_team_square_03 theme_prime.s_team_square_03 theme_prime.s_team_square_03 /theme_prime/static/src/img/snippets/s_team_square_03.png
114 s_team_square_04 theme_prime.s_team_square_04 theme_prime.s_team_square_04 /theme_prime/static/src/img/snippets/s_team_square_04.png
115 s_testimonial_author_01 theme_prime.s_testimonial_author_01 theme_prime.s_testimonial_author_01 /theme_prime/static/src/img/snippets/s_testimonial_author_01.jpg
116 s_testimonial_author_02 theme_prime.s_testimonial_author_02 theme_prime.s_testimonial_author_02 /theme_prime/static/src/img/snippets/s_testimonial_author_02.jpg
117 s_testimonial_author_03 theme_prime.s_testimonial_author_03 theme_prime.s_testimonial_author_03 /theme_prime/static/src/img/snippets/s_testimonial_author_03.jpg

View File

@ -1 +1 @@
The documentation is available at https://prime-docs-v16-25092021.droggol.com/ The documentation is available at https://prime-docs-v14-29101994.droggol.com/

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) # Copyright (c) 2019-Present Droggol. (<https://www.droggol.com/>)
from . import theme_prime from . import theme_prime
from . import ir_http from . import ir_http

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import models from odoo import models

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>)
from odoo import models, fields, api, tools from odoo import models, fields, api, tools
from odoo.tools import float_round
class ProductTemplate(models.Model): class ProductTemplate(models.Model):
@ -71,13 +71,16 @@ class ProductTemplate(models.Model):
for product in self: for product in self:
product.dr_has_discount = False product.dr_has_discount = False
def _get_product_category_count(self, domain=[]): def _get_product_category_count(self, website_ids=[], product_ids=[], domain=[]):
tables, where_clause, where_clause_params = self._dr_prepare_query_parts(domain) query = self._where_calc(domain)
self._apply_ir_rules(query)
tables, where_clause, where_clause_params = query.get_sql()
tables = tables.replace('"product_template"', ' ', 1)
query = """ query = """
SELECT SELECT
count(product_template.id), count(product_template.id),
product_public_category.parent_path as path, min(product_public_category.parent_path) as path,
product_public_category.parent_id as parent_id, min(product_public_category.parent_id) as parent_id,
product_public_category.id as product_public_category_id product_public_category.id as product_public_category_id
FROM product_public_category_product_template_rel FROM product_public_category_product_template_rel
JOIN product_template ON product_template.id = product_public_category_product_template_rel.product_template_id JOIN product_template ON product_template.id = product_public_category_product_template_rel.product_template_id
@ -105,9 +108,11 @@ class ProductTemplate(models.Model):
return result_count return result_count
def _get_product_attrib_count(self, attrib_values, domain=[]): def _get_product_attrib_count(self, website_ids=[], product_ids=[], attrib_values=[], domain=[]):
tables, where_clause, where_clause_params = self._dr_prepare_query_parts(domain) query = self._where_calc(domain)
self._apply_ir_rules(query)
tables, where_clause, where_clause_params = query.get_sql()
tables = tables.replace('"product_template"', ' ', 1)
query = """ query = """
SELECT SELECT
array_agg(product_template_attribute_line.product_tmpl_id) as product_tmpl_ids, array_agg(product_template_attribute_line.product_tmpl_id) as product_tmpl_ids,
@ -143,6 +148,7 @@ class ProductTemplate(models.Model):
attrib_vals_map[line['product_attrib_id']] = [] attrib_vals_map[line['product_attrib_id']] = []
attrib_vals_map[line['product_attrib_id']].append(line['id']) attrib_vals_map[line['product_attrib_id']].append(line['id'])
# Attribute -> active product list # Attribute -> active product list
attrib_p_list = {} attrib_p_list = {}
for line in query_res: for line in query_res:
@ -157,6 +163,7 @@ class ProductTemplate(models.Model):
if value_id_1 in attrib_values_ids: if value_id_1 in attrib_values_ids:
attrib_p_list[attrib_id_1] = attrib_p_list[attrib_id_1] | set(product_ids_1) attrib_p_list[attrib_id_1] = attrib_p_list[attrib_id_1] | set(product_ids_1)
# Attribute -> final list # Attribute -> final list
attrib_product_list = {} attrib_product_list = {}
for line in query_res: for line in query_res:
@ -179,33 +186,3 @@ class ProductTemplate(models.Model):
else: else:
result_count = dict([(line.get('id'), len(line.get('product_tmpl_ids') or [])) for line in query_res]) result_count = dict([(line.get('id'), len(line.get('product_tmpl_ids') or [])) for line in query_res])
return result_count return result_count
def _get_product_rating_count(self, domain=[]):
tables, where_clause, where_clause_params = self._dr_prepare_query_parts(domain)
query = """
SELECT avg_rating, count(*) FROM (
SELECT FLOOR(avg(rating)) as avg_rating, rating_rating.res_id FROM rating_rating JOIN product_template ON product_template.id = rating_rating.res_id """ + tables + """
WHERE (""" + where_clause + """) AND rating_rating.res_model = 'product.template' AND rating_rating.is_internal = False
GROUP BY rating_rating.res_id) AS rating_count group by avg_rating; """
self.env.cr.execute(query, where_clause_params)
query_result = dict(self.env.cr.fetchall())
total = 0
ratings_result = {rating: 0 for rating in range(1, 6)}
for result in range(5, 0, -1):
total += query_result.get(result, 0)
ratings_result[result] = total
return ratings_result
def _dr_prepare_query_parts(self, domain):
query = self._where_calc(domain)
self._apply_ir_rules(query)
tables, where_clause, where_clause_params = query.get_sql()
tables = tables.replace('"product_template"', ' ', 1)
return tables, where_clause, where_clause_params
def _search_render_results(self, fetch_fields, mapping, icon, limit):
current_website = self.env['website'].get_current_website()
if not current_website._dr_has_b2b_access():
mapping.pop("detail", None)
return super()._search_render_results(fetch_fields, mapping, icon, limit)

View File

@ -1,20 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-Present Droggol Infotech Private Limited. (<https://www.droggol.com/>) from odoo import models
from odoo import api, models
class ThemePrime(models.AbstractModel): class ThemePrime(models.AbstractModel):
_inherit = 'theme.utils' _inherit = 'theme.utils'
@api.model def _theme_prime_post_copy(self, mod):
def _reset_default_config(self): pass
header_styles = list(range(1, 9))
for style in header_styles:
self.disable_view('theme_prime.template_header_style_%s' % style)
footer_styles = list(range(1, 11))
for style in footer_styles:
self.disable_view('theme_prime.template_footer_style_%s' % style)
super()._reset_default_config()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Some files were not shown because too many files have changed in this diff Show More