Refactor and update Chennora theme to Shivasakthi branding
- Removed obsolete XML views related to product templates and configuration settings. - Deleted shop page layout and snippets XML files to streamline theme structure. - Added new logo and slider images for Shivasakthi theme. - Updated SCSS styles for improved footer design and added pre-footer food slider. - Modified layout XML to incorporate new logo and enhanced footer with social links and contact information. - Removed premium auto-sliding gallery section from pages XML. - Updated site metadata and canonical links in HTML files to reflect Shivasakthi branding. - Adjusted Docker Compose configuration for new database and volume names.
28
README.md
@ -1,4 +1,4 @@
|
||||
# Dine360 Odoo Addons_New by mohan1
|
||||
# Dine360 Odoo Addons_New by mohan1
|
||||
|
||||
This repository contains custom Odoo 17 addons for the Dine360 Restaurant Suite. It includes a website theme, a custom login/dashboard experience, and a restaurant role-based access module, all bundled by a meta module for one-click install.
|
||||
|
||||
@ -46,22 +46,22 @@ Key files:
|
||||
- `addons/dine360_restaurant/security/*`
|
||||
- `addons/dine360_restaurant/views/*`
|
||||
|
||||
### 3) `dine360_theme_chennora`
|
||||
### 3) `dine360_theme_shivasakthi`
|
||||
Custom website theme and page content (homepage + contact us).
|
||||
|
||||
Key files:
|
||||
- `addons/dine360_theme_chennora/views/layout.xml`
|
||||
- `addons/dine360_theme_chennora/views/pages.xml`
|
||||
- `addons/dine360_theme_chennora/static/src/scss/*`
|
||||
- `addons/dine360_theme_chennora/static/src/img/*`
|
||||
- `addons/dine360_theme_shivasakthi/views/layout.xml`
|
||||
- `addons/dine360_theme_shivasakthi/views/pages.xml`
|
||||
- `addons/dine360_theme_shivasakthi/static/src/scss/*`
|
||||
- `addons/dine360_theme_shivasakthi/static/src/img/*`
|
||||
|
||||
### 4) `Dine360_Chennora` (meta module)
|
||||
### 4) `Dine360_Shivasakthi` (meta module)
|
||||
Install this single module to pull in all required addons.
|
||||
|
||||
Depends on:
|
||||
- `dine360_dashboard`
|
||||
- `dine360_restaurant`
|
||||
- `dine360_theme_chennora`
|
||||
- `dine360_theme_shivasakthi`
|
||||
|
||||
## Standard Install / Upgrade
|
||||
|
||||
@ -78,20 +78,20 @@ docker-compose up -d
|
||||
|
||||
### Upgrade the suite (after code changes)
|
||||
```bash
|
||||
docker exec odoo_client1 odoo -u Dine360_Chennora -d chennora_db --db_host db --db_user odoo --db_password odoo --stop-after-init
|
||||
docker exec odoo_client1 odoo -u Dine360_Shivasakthi -d shivasakthi_db --db_host db --db_user odoo --db_password odoo --stop-after-init
|
||||
```
|
||||
|
||||
### Upgrade a single addon
|
||||
```bash
|
||||
docker exec odoo_client1 odoo -u dine360_dashboard -d chennora_db --db_host db --db_user odoo --db_password odoo --stop-after-init
|
||||
docker exec odoo_client1 odoo -u dine360_dashboard -d shivasakthi_db --db_host db --db_user odoo --db_password odoo --stop-after-init
|
||||
```
|
||||
|
||||
## Logos (Apps icons)
|
||||
Place PNGs here (128x128 or 256x256 recommended):
|
||||
- `addons/Dine360_Chennora/static/description/icon.png`
|
||||
- `addons/Dine360_Shivasakthi/static/description/icon.png`
|
||||
- `addons/dine360_dashboard/static/description/icon.png`
|
||||
- `addons/dine360_restaurant/static/description/icon.png`
|
||||
- `addons/dine360_theme_chennora/static/description/icon.png`
|
||||
- `addons/dine360_theme_shivasakthi/static/description/icon.png`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@ -100,7 +100,7 @@ Place PNGs here (128x128 or 256x256 recommended):
|
||||
- Restart Odoo: `docker-compose restart odoo`
|
||||
- Hard refresh browser (Ctrl + F5)
|
||||
|
||||
### Old modules still present (home_dashboard, restaurant_management, theme_chennora)
|
||||
### Old modules still present (home_dashboard, restaurant_management, theme_shivasakthi)
|
||||
If you renamed modules, uninstall the old ones in Apps to avoid conflicts.
|
||||
|
||||
## Utilities
|
||||
@ -109,5 +109,5 @@ Helper scripts for view diagnostics and homepage issues:
|
||||
- `resolve_homepage.py`, `fix_homepage.py`, `force_inherit.py`
|
||||
|
||||
## Notes
|
||||
- Homepage content is fully overridden in `addons/dine360_theme_chennora/views/pages.xml`.
|
||||
- Homepage content is fully overridden in `addons/dine360_theme_shivasakthi/views/pages.xml`.
|
||||
- If theme changes don’t appear, check for COW (customized) views masking the theme.
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
# Meta module for Dine360 Chennora
|
||||
from .hooks import uninstall_hook
|
||||
@ -1,45 +0,0 @@
|
||||
{
|
||||
'name': 'Dine360 Restaurant Suite',
|
||||
'version': '1.0.0',
|
||||
'license': 'LGPL-3',
|
||||
'category': 'Website',
|
||||
'summary': 'Installs all Dine360 Restaurant modules',
|
||||
'author': 'Dine360',
|
||||
'depends': [
|
||||
'dine360_restaurant',
|
||||
'dine360_order_channels',
|
||||
'dine360_dashboard',
|
||||
'dine360_theme_chennora',
|
||||
'dine360_kds',
|
||||
'dine360_reservation',
|
||||
'dine360_uber',
|
||||
'dine360_recipe',
|
||||
'dine360_self_order',
|
||||
'dine360_online_orders',
|
||||
'dine360_pos_navbar',
|
||||
'mail',
|
||||
'calendar',
|
||||
'contacts',
|
||||
'crm',
|
||||
'sale_management',
|
||||
'board',
|
||||
'point_of_sale',
|
||||
'account',
|
||||
'website',
|
||||
'purchase',
|
||||
'stock',
|
||||
'hr',
|
||||
],
|
||||
'uninstall_hook': 'uninstall_hook',
|
||||
'data': [
|
||||
'views/apps_kanban_menu.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'Dine360_Chennora/static/src/css/apps_kanban_fix.css',
|
||||
],
|
||||
},
|
||||
'installable': True,
|
||||
'application': True,
|
||||
}
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
def uninstall_hook(env):
|
||||
"""
|
||||
Synchronized uninstallation: When Dine360 Restaurant Suite is uninstalled,
|
||||
automatically trigger uninstallation for all its core sub-modules.
|
||||
"""
|
||||
modules_to_uninstall = [
|
||||
'dine360_dashboard',
|
||||
'dine360_restaurant',
|
||||
'dine360_theme_chennora',
|
||||
'dine360_kds',
|
||||
'dine360_reservation'
|
||||
]
|
||||
|
||||
# Search for these modules if they are installed
|
||||
modules = env['ir.module.module'].search([
|
||||
('name', 'in', modules_to_uninstall),
|
||||
('state', '=', 'installed')
|
||||
])
|
||||
|
||||
if modules:
|
||||
# Mark modules for uninstallation
|
||||
modules.button_uninstall()
|
||||
|
Before Width: | Height: | Size: 22 KiB |
@ -1,31 +0,0 @@
|
||||
/* Fix Apps kanban icon sizing and dropdown overlap */
|
||||
.o_modules_kanban .oe_module_vignette,
|
||||
.o_modules_kanban .o_kanban_record {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.o_modules_kanban .o_kanban_record {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.o_modules_kanban .oe_module_icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.o_modules_kanban .oe_module_icon img {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.o_modules_kanban .oe_module_vignette .dropdown-menu {
|
||||
right: 0;
|
||||
left: auto;
|
||||
min-width: 160px;
|
||||
z-index: 1060;
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="dine360_apps_kanban_menu" inherit_id="base.module_view_kanban" name="Dine360 Apps Kanban Menu">
|
||||
<xpath expr="//t[@t-name='kanban-menu']" position="replace">
|
||||
<t t-name="kanban-menu">
|
||||
<t t-set="installed" t-value="record.state.raw_value == 'installed'"/>
|
||||
<a type="edit" class="dropdown-item">Module Info</a>
|
||||
<a t-if="record.website.raw_value" role="menuitem" class="dropdown-item o-hidden-ios" t-att-href="record.website.raw_value" target="_blank">Learn More</a>
|
||||
<a t-if="installed" name="button_immediate_upgrade" type="object" role="menuitem" class="dropdown-item" groups="base.group_system">Upgrade</a>
|
||||
<a t-if="installed" name="button_uninstall_wizard" type="object" role="menuitem" class="dropdown-item" groups="base.group_system">Uninstall</a>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="base_title_param" model="ir.config_parameter">
|
||||
<field name="key">web.base_title</field>
|
||||
<field name="value">Chennora</field>
|
||||
<field name="value">Shivasakthi</field>
|
||||
</record>
|
||||
</data>
|
||||
<data>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
height: 100vh !important;
|
||||
width: 100vw !important;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/dine360_theme_chennora/static/src/img/chen-banner-2.webp') !important;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/dine360_theme_shivasakthi/static/src/img/chen-banner-2.webp') !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: center center !important;
|
||||
background-size: cover !important;
|
||||
@ -255,7 +255,7 @@ body.o_custom_login_body .o_login_main_wrapper {
|
||||
height: 100vh !important;
|
||||
/* width: 100vw !important; */
|
||||
overflow: hidden !important;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/dine360_theme_chennora/static/src/img/chen-banner-2.webp') no-repeat center center !important;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/dine360_theme_shivasakthi/static/src/img/chen-banner-2.webp') no-repeat center center !important;
|
||||
background-size: cover !important;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* ========================================
|
||||
CHENNORA RUSH MODE - POS THEME (ULTRA PREMIUM)
|
||||
/* ========================================
|
||||
SHIVASAKTHI RUSH MODE - POS THEME (ULTRA PREMIUM)
|
||||
======================================== */
|
||||
|
||||
:root {
|
||||
|
||||
@ -2,17 +2,30 @@
|
||||
|
||||
import { WebClient } from "@web/webclient/webclient";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { onMounted } from "@odoo/owl";
|
||||
|
||||
patch(WebClient.prototype, {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.title.setParts({ brand: "Chennora" });
|
||||
try {
|
||||
this.title.setParts({ brand: "Shivasakthi" });
|
||||
} catch (e) {
|
||||
// title service not ready yet, ignore
|
||||
}
|
||||
|
||||
// Redirect to main dashboard if landing on backend root (common after module upgrade/install)
|
||||
onMounted(() => {
|
||||
try {
|
||||
// Only redirect to home dashboard if the URL has no meaningful hash
|
||||
// (i.e., user just typed /web or /web# directly)
|
||||
const hash = window.location.hash;
|
||||
if (!hash || hash === "#home") {
|
||||
const path = window.location.pathname;
|
||||
if (path === "/web" && (!hash || hash === "#" || hash === "#home")) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore redirect errors
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<odoo>
|
||||
<odoo>
|
||||
<template id="image_home_template" name="Home Page Icons">
|
||||
<t t-call="web.frontend_layout">
|
||||
<t t-set="no_footer" t-value="True"/>
|
||||
@ -10,7 +10,7 @@
|
||||
<!-- Top Bar -->
|
||||
<div class="o_home_top_bar">
|
||||
<div class="o_top_bar_island">
|
||||
<a href="/" class="o_top_item" title="Chennora Home" style="width: auto; padding: 0 10px;">
|
||||
<a href="/" class="o_top_item" title="Shivasakthi Home" style="width: auto; padding: 0 10px;">
|
||||
<img t-attf-src="/web/binary/company_logo" style="height: 24px; width: auto; object-fit: contain;"/>
|
||||
</a>
|
||||
<div class="o_bar_divider" style="margin: 0 5px;"></div>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<odoo>
|
||||
<template id="chennora_web_layout" inherit_id="web.layout" name="Chennora Title">
|
||||
<template id="shivasakthi_web_layout" inherit_id="web.layout" name="Shivasakthi Title">
|
||||
<xpath expr="//title" position="replace">
|
||||
<title>Chennora</title>
|
||||
<title>Shivasakthi</title>
|
||||
</xpath>
|
||||
<xpath expr="//link[@rel='shortcut icon']" position="replace">
|
||||
<link rel="shortcut icon" href="/dine360_theme_chennora/static/description/icon.png" type="image/x-icon"/>
|
||||
<link rel="shortcut icon" href="/dine360_theme_shivasakthi/static/description/icon.png" type="image/x-icon"/>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//body" position="inside">
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/** @odoo-module */
|
||||
/** @odoo-module */
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { ReceiptScreen } from "@point_of_sale/app/screens/receipt_screen/receipt_screen";
|
||||
@ -273,7 +273,7 @@ async function buildEscPosReceipt(order, pos) {
|
||||
builder.align("center");
|
||||
builder.bold(true);
|
||||
builder.size("doubleHeight");
|
||||
builder.line(company.name || "Chennora");
|
||||
builder.line(company.name || "Shivasakthi");
|
||||
builder.size("normal");
|
||||
builder.bold(false);
|
||||
if (company.street) builder.line(company.street);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from odoo import http, _
|
||||
from odoo import http, _
|
||||
from odoo.http import request
|
||||
import datetime
|
||||
import pytz
|
||||
@ -304,19 +304,19 @@ class TableReservationController(http.Controller):
|
||||
|
||||
# 2. Notify the Customer
|
||||
customer_mail_values = {
|
||||
'subject': "Reservation Confirmation - Chennora",
|
||||
'subject': "Reservation Confirmation - Shivasakthi",
|
||||
'body_html': f"""
|
||||
<div style="font-family: Arial, sans-serif; padding: 20px;">
|
||||
<h2 style="color: #2BB1A5;">Reservation Confirmed!</h2>
|
||||
<p>Dear {customer_name},</p>
|
||||
<p>Your table reservation at <b>Chennora Indian Kitchen Bar</b> has been confirmed successfully!</p>
|
||||
<p>Your table reservation at <b>Shivasakthi Indian Kitchen Bar</b> has been confirmed successfully!</p>
|
||||
<table style="width:100%; border-collapse: collapse; margin-top: 15px;">
|
||||
<tr><td style="padding:8px; font-weight:bold;">Number of Guests:</td><td style="padding:8px;">{num_people}</td></tr>
|
||||
<tr><td style="padding:8px; font-weight:bold;">Reservation Time:</td><td style="padding:8px;">{start_time_str}</td></tr>
|
||||
</table>
|
||||
<p style="margin-top:20px;">If you need to make any changes or have questions, please reply to this email or call us at <b>+1(647)856-2878</b>.</p>
|
||||
<p>We look forward to seeing you!</p>
|
||||
<p>Thank you,<br><b>Chennora Indian Kitchen Bar</b></p>
|
||||
<p>Thank you,<br><b>Shivasakthi Indian Kitchen Bar</b></p>
|
||||
</div>
|
||||
""",
|
||||
'email_to': email,
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<template id="reservation_page_template" name="Table Reservation Form">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="oe_structure oe_empty">
|
||||
<section class="s_reservation_form pt64 pb64" style="background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('/dine360_theme_chennora/static/src/img/bg_reservation.jpg') center/cover no-repeat;">
|
||||
<section class="s_reservation_form pt64 pb64" style="background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('/dine360_theme_shivasakthi/static/src/img/bg_reservation.jpg') center/cover no-repeat;">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-7">
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
from . import controllers
|
||||
from . import models
|
||||
@ -1,41 +0,0 @@
|
||||
{
|
||||
'name': 'Dine360 Theme Chennora',
|
||||
'description': 'Custom theme for Dine360 Chennora website',
|
||||
'category': 'Theme/Website',
|
||||
'version': '1.0',
|
||||
'author': 'Dine360',
|
||||
'depends': ['website', 'website_sale', 'website_crm'],
|
||||
'data': [
|
||||
'views/layout.xml', # Header, Footer, and Global Layout changes
|
||||
'views/pages.xml', # specific page content (Home, About, etc.)
|
||||
'views/about_page.xml', # About Page
|
||||
'views/contact_page.xml',# Contact Page
|
||||
'views/faq_page.xml', # FAQ Page
|
||||
'views/blog_page.xml', # Blog Page
|
||||
'views/blog_detail_page.xml', # Blog Detail Page
|
||||
'views/shop_page.xml', # Shop Page
|
||||
'views/checkout_address.xml', # Checkout Address page (remove Company/VAT)
|
||||
'views/product_details_page.xml', # Customized Product Details Page
|
||||
'views/product_views.xml', # Product Form custom fields
|
||||
'views/snippets.xml', # Custom Building Blocks
|
||||
'views/options.xml', # Options for snippets (if any)
|
||||
'views/res_config_settings_views.xml', # Backend Settings
|
||||
'data/website_data.xml', # Data for creating pages
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_frontend': [
|
||||
'dine360_theme_chennora/static/src/scss/primary_variables.scss',
|
||||
'dine360_theme_chennora/static/src/scss/theme.scss',
|
||||
'dine360_theme_chennora/static/src/scss/shop.scss',
|
||||
'dine360_theme_chennora/static/src/js/deal_switcher.js',
|
||||
'dine360_theme_chennora/static/src/js/category_slider.js',
|
||||
],
|
||||
},
|
||||
'images': [
|
||||
'static/description/cover.png',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
from . import main
|
||||
@ -1,132 +0,0 @@
|
||||
from markupsafe import Markup
|
||||
import json
|
||||
import os
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
# Helper to load blogs from JSON
|
||||
def get_blogs():
|
||||
json_path = os.path.join(os.path.dirname(__file__), '../data/blogs.json')
|
||||
if os.path.exists(json_path):
|
||||
with open(json_path, 'r', encoding='utf-8-sig') as f:
|
||||
blogs = json.load(f)
|
||||
# Reversing so the last added blog appears first
|
||||
return blogs[::-1] if isinstance(blogs, list) else blogs
|
||||
return []
|
||||
|
||||
class ContactController(http.Controller):
|
||||
@http.route('/contactus/submit', type='http', auth="public", website=True, csrf=True)
|
||||
def contact_submit(self, **post):
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
name = post.get('name')
|
||||
email = post.get('email_from')
|
||||
phone = post.get('phone')
|
||||
subject = post.get('subject')
|
||||
message = post.get('description')
|
||||
|
||||
# Format the email content
|
||||
email_content = f"""
|
||||
<div style="font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
|
||||
<h2 style="color: #2BB1A5; border-bottom: 2px solid #FECD4F; padding-bottom: 10px;">New Contact Form Submission</h2>
|
||||
<table style="width: 100%; border-collapse: collapse; margin-top: 15px;">
|
||||
<tr>
|
||||
<td style="padding: 8px; font-weight: bold; width: 30%;">Full Name:</td>
|
||||
<td style="padding: 8px;">{name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 8px; font-weight: bold;">Email:</td>
|
||||
<td style="padding: 8px;">{email}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 8px; font-weight: bold;">Phone:</td>
|
||||
<td style="padding: 8px;">{phone}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 8px; font-weight: bold;">Subject:</td>
|
||||
<td style="padding: 8px;">{subject}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 20px; padding: 15px; background-color: #F8F9FA; border-left: 4px solid #2BB1A5;">
|
||||
<strong style="display: block; margin-bottom: 10px;">Message:</strong>
|
||||
<div style="white-space: pre-wrap;">{message}</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
company_email = request.env['res.company'].sudo().search([], limit=1).email or 'noreply@chennora.com'
|
||||
|
||||
mail_values = {
|
||||
'subject': f"Contact Form: {subject or 'Inquiry'} from {name}",
|
||||
'body_html': email_content,
|
||||
'email_to': 'alaguraj0361@gmail.com',
|
||||
'email_from': company_email,
|
||||
'reply_to': email,
|
||||
}
|
||||
|
||||
# Create and send the mail
|
||||
try:
|
||||
mail = request.env['mail.mail'].sudo().create(mail_values)
|
||||
mail.send()
|
||||
_logger.info("Contact form email sent successfully to %s", mail_values['email_to'])
|
||||
except Exception as e:
|
||||
_logger.error("Failed to send contact form email: %s", str(e))
|
||||
|
||||
return request.render('dine360_theme_chennora.contact_thank_you')
|
||||
|
||||
class BlogController(http.Controller):
|
||||
@http.route(['/blog', '/blog/page/<int:page>'], type='http', auth='public', website=True)
|
||||
def blog_list(self, page=1, **post):
|
||||
all_blogs = get_blogs()
|
||||
|
||||
# Pagination Settings
|
||||
per_page = 12
|
||||
total = len(all_blogs)
|
||||
|
||||
# Odoo's built-in pager
|
||||
pager = request.website.pager(
|
||||
url='/blog',
|
||||
total=total,
|
||||
page=page,
|
||||
step=per_page,
|
||||
scope=5,
|
||||
url_args=post,
|
||||
)
|
||||
|
||||
# Extract blogs for current page
|
||||
start = (page - 1) * per_page
|
||||
end = start + per_page
|
||||
blogs_paged = all_blogs[start:end]
|
||||
|
||||
return request.render('dine360_theme_chennora.blog_page', {
|
||||
'blog_posts': blogs_paged,
|
||||
'pager': pager,
|
||||
})
|
||||
|
||||
@http.route(['/blog/<string:slug>'], type='http', auth='public', website=True)
|
||||
def blog_detail(self, slug, **post):
|
||||
all_blogs = get_blogs()
|
||||
blog_post = next((b for b in all_blogs if b['slug'] == slug), None)
|
||||
|
||||
if not blog_post:
|
||||
return request.not_found()
|
||||
|
||||
recent_posts = [b for b in all_blogs if b['slug'] != slug][:3]
|
||||
|
||||
# Get categories and counts
|
||||
categories = {}
|
||||
for b in all_blogs:
|
||||
cat = b.get('category', 'Restaurant')
|
||||
categories[cat] = categories.get(cat, 0) + 1
|
||||
|
||||
return request.render('dine360_theme_chennora.blog_detail_layout', {
|
||||
'blog_title': blog_post.get('title'),
|
||||
'blog_img': blog_post.get('image'),
|
||||
'blog_date': blog_post.get('date'),
|
||||
'blog_category': blog_post.get('category'),
|
||||
'blog_content': Markup(blog_post.get('content') or ''),
|
||||
'recent_posts': recent_posts,
|
||||
'categories': categories,
|
||||
})
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Create the /about page explicitly and link it to the standard About Us view
|
||||
which our theme modifies in views/pages.xml -->
|
||||
<record id="about_page_chennora" model="website.page">
|
||||
<field name="url">/about</field>
|
||||
<field name="is_published">True</field>
|
||||
<field name="view_id" ref="dine360_theme_chennora.about_page"/>
|
||||
<field name="name">About Us</field>
|
||||
<field name="website_indexed" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="faq_page_chennora" model="website.page">
|
||||
<field name="url">/faq</field>
|
||||
<field name="is_published">True</field>
|
||||
<field name="view_id" ref="dine360_theme_chennora.faq_page"/>
|
||||
<field name="name">FAQ</field>
|
||||
<field name="website_indexed" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="blog_page_chennora" model="website.page">
|
||||
<field name="url">/blog</field>
|
||||
<field name="is_published">True</field>
|
||||
<field name="view_id" ref="dine360_theme_chennora.blog_page"/>
|
||||
<field name="name">Blog</field>
|
||||
<field name="website_indexed" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import product_template
|
||||
from . import website
|
||||
from . import res_config_settings
|
||||
@ -1,7 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
is_popular_deal = fields.Boolean(string='Is Popular Deal', default=False, help='Check this to show this product in Popular Deals section on Homepage')
|
||||
@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
enable_delivery_option = fields.Boolean(
|
||||
related='website_id.enable_delivery_option',
|
||||
readonly=False,
|
||||
string='Enable Delivery Option'
|
||||
)
|
||||
@ -1,29 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
import os
|
||||
from odoo import models, fields, modules
|
||||
|
||||
class Website(models.Model):
|
||||
_inherit = 'website'
|
||||
|
||||
enable_delivery_option = fields.Boolean(
|
||||
string='Enable Delivery Option',
|
||||
default=True,
|
||||
help='If disabled, customers will not see the Delivery option on the checkout page.'
|
||||
)
|
||||
|
||||
def get_recent_blogs(self, limit=3):
|
||||
"""Reads blog posts from blogs.json and returns the latest slice."""
|
||||
addon_path = modules.get_module_path('dine360_theme_chennora')
|
||||
json_path = os.path.join(addon_path, 'data', 'blogs.json')
|
||||
|
||||
if os.path.exists(json_path):
|
||||
try:
|
||||
with open(json_path, 'r', encoding='utf-8-sig') as f:
|
||||
blogs = json.load(f)
|
||||
if isinstance(blogs, list):
|
||||
return blogs[::-1][:limit]
|
||||
return blogs[:limit] if isinstance(blogs, list) else []
|
||||
except Exception:
|
||||
return []
|
||||
return []
|
||||
|
Before Width: | Height: | Size: 11 MiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 569 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 643 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 643 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 481 KiB |
|
Before Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 316 KiB |
|
Before Width: | Height: | Size: 431 KiB |
|
Before Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 648 KiB |
|
Before Width: | Height: | Size: 897 KiB |
|
Before Width: | Height: | Size: 906 KiB |
|
Before Width: | Height: | Size: 752 KiB |
|
Before Width: | Height: | Size: 883 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 541 KiB |
|
Before Width: | Height: | Size: 541 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 281 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 367 KiB |
|
Before Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 865 KiB |
|
Before Width: | Height: | Size: 623 KiB |
|
Before Width: | Height: | Size: 865 KiB |