[MERGE] portal, *: redesign portal screens
This commit redesigns all portal screens, improve bootstrap compliance and increases maintainability. See sub-commits for details. Closes https://github.com/odoo/odoo/pull/26849
This commit is contained in:
@@ -1,134 +1,130 @@
|
||||
<odoo>
|
||||
<template id="portal_my_home_menu_invoice" name="Portal layout : invoice menu entries" inherit_id="portal.portal_layout" priority="30">
|
||||
<template id="portal_my_home_menu_invoice" name="Portal layout : invoice menu entries" inherit_id="portal.portal_breadcrumbs" priority="30">
|
||||
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
|
||||
<li t-if="page_name == 'invoice'" class="breadcrumb-item active">
|
||||
<li t-if="page_name == 'invoice'" t-attf-class="breadcrumb-item #{'active ' if not invoice else ''}">
|
||||
<a t-if="invoice" t-attf-href="/my/invoices?{{ keep_query() }}">Invoices</a>
|
||||
<t t-else="">Invoices</t>
|
||||
</li>
|
||||
<li t-if="invoice" class="breadcrumb-item">
|
||||
<li t-if="invoice" class="breadcrumb-item active">
|
||||
<t t-esc="invoice.number" t-if="invoice.number"/>
|
||||
<t t-else="">Draft Invoice</t>
|
||||
<t t-else=""><em>Draft Invoice</em></t>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_home_invoice" name="Portal My Home : invoice entries" inherit_id="portal.portal_my_home" priority="30">
|
||||
<xpath expr="//ul[hasclass('o_portal_docs')]" position="inside">
|
||||
<li t-if="invoice_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="invoice_count"/>
|
||||
<a href="/my/invoices">Invoices</a>
|
||||
</li>
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
|
||||
<t t-if="invoice_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">Invoices</t>
|
||||
<t t-set="url" t-value="'/my/invoices'"/>
|
||||
<t t-set="count" t-value="invoice_count"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_invoices" name="My Invoices and Payments">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">Invoices</t>
|
||||
</t>
|
||||
<t t-if="not invoices">
|
||||
<p>There are currently no invoices and payments for your account.</p>
|
||||
</t>
|
||||
<div t-if="invoices" class="card">
|
||||
<div class="table-responsive"><table class="table table-hover o_portal_my_doc_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<t t-if="invoices" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Invoice #</th>
|
||||
<th>Invoice Date</th>
|
||||
<th class='d-none d-md-table-cell'>Due Date</th>
|
||||
<th></th>
|
||||
<th>Amount Due</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<th/>
|
||||
<th class="text-right">Amount Due</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="invoices" t-as="invoice">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="invoice.get_portal_url()" t-att-title="invoice.number">
|
||||
<t t-esc="invoice.number" t-if="invoice.number"/>
|
||||
<t t-else="">Draft Invoice</t>
|
||||
<em t-else="">Draft Invoice</em>
|
||||
</a>
|
||||
</td>
|
||||
<td><span t-field="invoice.date_invoice"/></td>
|
||||
<td class='d-none d-md-table-cell'><span t-field="invoice.date_due"/></td>
|
||||
<td class="tx_status">
|
||||
<t t-if="invoice.state == 'open'">
|
||||
<span class="badge badge-info"><i class="fa fa-fw fa-clock-o" aria-label="Opened" title="Opened" role="img"></i><span class="d-none d-md-inline"> Waiting for Payment</span></span>
|
||||
<span class="badge badge-pill badge-info"><i class="fa fa-fw fa-clock-o" aria-label="Opened" title="Opened" role="img"></i><span class="d-none d-md-inline"> Waiting for Payment</span></span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'paid'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-check" aria-label="Paid" title="Paid" role="img"></i><span class="d-none d-md-inline"> Paid</span></span>
|
||||
<span class="badge badge-pill badge-success"><i class="fa fa-fw fa-check" aria-label="Paid" title="Paid" role="img"></i><span class="d-none d-md-inline"> Paid</span></span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'cancel'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-remove" aria-label="Cancelled" title="Cancelled" role="img"></i><span class="d-none d-md-inline"> Cancelled</span></span>
|
||||
<span class="badge badge-pill badge-warning"><i class="fa fa-fw fa-remove" aria-label="Cancelled" title="Cancelled" role="img"></i><span class="d-none d-md-inline"> Cancelled</span></span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="-invoice.residual if invoice.type == 'out_refund' else invoice.residual" t-options='{"widget": "monetary", "display_currency": invoice.currency_id}'/></td>
|
||||
<td class="text-right"><span t-esc="-invoice.residual if invoice.type == 'out_refund' else invoice.residual" t-options='{"widget": "monetary", "display_currency": invoice.currency_id}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table></div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
</div>
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_invoice_page" name="Invoice Portal Template" inherit_id="portal.portal_sidebar" primary="True">
|
||||
<xpath expr="//div[hasclass('o_portal_sidebar')]" position="inside">
|
||||
<t t-set="wrapwrap_classes" t-value="'o_portal_bg_dark'"/>
|
||||
|
||||
<div class="row mt16 o_portal_invoice_sidebar">
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-3 d-print-none">
|
||||
<div class="bs-sidebar mb16" id="sidebar_content">
|
||||
<div class="text-center pt16 o_account_portal_sidebar">
|
||||
<h2 class="media-heading">
|
||||
<strong>
|
||||
<span t-if="invoice.residual > 0" t-field="invoice.residual"/>
|
||||
<span t-else="1" t-field="invoice.amount_total"/>
|
||||
</strong>
|
||||
</h2>
|
||||
<div class="mb4" t-if="invoice.state != 'paid' and invoice.type == 'out_invoice'"><i class="fa fa-clock-o"/><span class="o_portal_sidebar_timeago ml4" t-att-datetime="invoice.date_due"/></div>
|
||||
</div>
|
||||
<div class="o_payment_button">
|
||||
<div class="text-center mb8 ml16 mr16 o_download_pdf">
|
||||
<a class="btn btn-secondary btn-block o_download_btn" t-att-href="invoice.get_portal_url(report_type='pdf', download=True)" title="Download"><i class="fa fa-download"/> Download</a>
|
||||
<a class="btn btn-secondary btn-block d-none d-lg-inline-block o_print_btn o_portal_invoice_print" t-att-href="invoice.get_portal_url(report_type='pdf')" id="print_invoice_report" title="Print"><i class="fa fa-print"/> Print</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr t-if="invoice.user_id" class="mt0 mb0"/>
|
||||
<div class="pb8 ml16 mr16 container">
|
||||
<t t-if="invoice.user_id">
|
||||
<div><strong>Your Contact:</strong></div>
|
||||
<div class="d-flex h-100">
|
||||
<div class="align-self-center">
|
||||
<img class="rounded-circle mr4 float-left o_portal_contact_img" t-if="invoice.user_id.image" t-attf-src="data:image/png;base64,#{invoice.user_id.image}" alt="Contact"/>
|
||||
<img class="rounded-circle mr4 float-left o_portal_contact_img" t-if="not invoice.user_id.image" src="/web/static/src/img/placeholder.png" alt="Contact"/>
|
||||
<t t-call="portal.portal_record_sidebar">
|
||||
<t t-set="classes" t-value="'col-12 col-lg flex-lg-grow-0 d-print-none'"/>
|
||||
<t t-set="title">
|
||||
<h2 class="mb-0">
|
||||
<b t-if="invoice.residual > 0" t-field="invoice.residual"/>
|
||||
<b t-else="1" t-field="invoice.amount_total"/>
|
||||
</h2>
|
||||
<div class="small" t-if="invoice.state != 'paid' and invoice.type == 'out_invoice'"><i class="fa fa-clock-o"/><span class="o_portal_sidebar_timeago ml4" t-att-datetime="invoice.date_due"/></div>
|
||||
</t>
|
||||
|
||||
<t t-set="entries">
|
||||
<ul class="list-group list-group-flush flex-wrap flex-row flex-lg-column">
|
||||
<li class="list-group-item o_payment_button flex-grow-1 flex-sm-grow-0">
|
||||
<div class="o_download_pdf btn-toolbar flex-sm-nowrap">
|
||||
<div class="btn-group flex-grow-1 mr-1 mb-1">
|
||||
<a class="btn btn-secondary btn-block o_download_btn" t-att-href="invoice.get_portal_url(report_type='pdf', download=True)" title="Download"><i class="fa fa-download"/> Download</a>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<span t-field="invoice.user_id" t-options='{"widget": "contact", "fields": ["name", "phone"], "no_marker": True}'/>
|
||||
<a data-toggle="modal" href="#" data-target="#invoice_chatter"><i class="fa fa-comment"></i> Contact us</a>
|
||||
<div class="btn-group flex-grow-1 mb-1">
|
||||
<a class="btn btn-secondary btn-block o_print_btn o_portal_invoice_print" t-att-href="invoice.get_portal_url(report_type='pdf')" id="print_invoice_report" title="Print"><i class="fa fa-print"/> Print</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li t-if="invoice.user_id" class="list-group-item flex-grow-1 o_portal_contact_block">
|
||||
<div class="small mb-1"><strong class="text-muted">Your Contact:</strong></div>
|
||||
<div class="row">
|
||||
<div class="col flex-grow-0 pr-2">
|
||||
<img t-if="invoice.user_id.image" class="rounded-circle mt-1 o_portal_contact_img" t-attf-src="data:image/png;base64,#{invoice.user_id.image}" alt="Contact"/>
|
||||
<img t-else="" class="rounded-circle mt-1 o_portal_contact_img" src="/web/static/src/img/user_menu_avatar.png" alt="Contact"/>
|
||||
</div>
|
||||
<div class="col pl-0">
|
||||
<span t-field="invoice.user_id" t-options='{"widget": "contact", "fields": ["name", "phone"], "no_marker": True}'/>
|
||||
<a data-toggle="modal" href="#" data-target="#invoice_chatter" class="small"><i class="fa fa-fw fa-comments"/><b>Send message</b></a>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<div t-if="not invoice.user_id" class="text-center mr16">
|
||||
<a data-toggle="modal" href="#" data-target="#invoice_chatter"><i class="fa fa-comment"></i> Contact us</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center d-none d-md-block o_portal_brand">
|
||||
Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=portal">Odoo</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Page Content -->
|
||||
<div id="invoice_content" class="col-lg-9 o_portal_page_content d-print-none">
|
||||
<div t-ignore="true" class="float-md-right css_editable_mode_hidden d-print-none">
|
||||
<ul class="list-inline">
|
||||
<li groups="sales_team.group_sale_salesman" class="list-inline-item">
|
||||
<a role="button" class="btn btn-info mt16 mr16" t-att-href="'/web#return_label=Website&model=%s&id=%s&action=%s&view_type=form' % (invoice._name, invoice.id, invoice.env.ref('account.action_invoice_tree1').id)"><t t-if="invoice.state == 'draft'">Edit Invoice</t><t t-else="">Leave Portal</t></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div id="invoice_content" class="o_portal_page_content col-12 col-lg d-flex justify-content-end">
|
||||
<t t-if="error or warning" t-call="account.portal_invoice_error"/>
|
||||
<t t-if="success and (not error and not warning)" t-call="account.portal_invoice_success"/>
|
||||
<div class="o_portal_html_view">
|
||||
<div class="o_portal_html_view shadow">
|
||||
<div class="o_portal_html_loader text-center">
|
||||
<i class="fa fa-circle-o-notch fa-spin fa-2x fa-fw text-black-50"></i>
|
||||
</div>
|
||||
<iframe id="invoice_html" class="mt8 mb8" width="100%" height="100%" frameborder="0" scrolling="no" t-att-src="invoice.get_portal_url(report_type='html')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<odoo>
|
||||
<template id="portal_my_invoices_payment" name="Payment on My Invoices" inherit_id="account.portal_my_invoices">
|
||||
<xpath expr="//table[hasclass('o_portal_my_doc_table')]/thead/tr/th[last()]" position="before">
|
||||
<th>Status</th>
|
||||
<xpath expr="//t[@t-call='portal.portal_table']/thead/tr/th[last()]" position="before">
|
||||
<th class="text-center">Status</th>
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-foreach='invoices']/tr/td[last()]" position="before">
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<t t-set="tx_ids" t-value="invoice.transaction_ids.filtered(lambda tx: tx.state in ('pending', 'authorized', 'done'))"/>
|
||||
<t t-set="pending_manual_txs" t-value="tx_ids.filtered(lambda tx: tx.state == 'pending' and tx.acquirer_id.provider in ('transfer', 'manual'))"/>
|
||||
<a t-if="invoice.state == 'open' and invoice.amount_total and invoice.type == 'out_invoice' and (pending_manual_txs or not tx_ids)"
|
||||
t-att-href="invoice.get_portal_url(anchor='portal_pay')" title="Pay now" aria-label="Pay now" class="btn btn-sm btn-primary" role="button">
|
||||
t-att-href="invoice.get_portal_url(anchor='portal_pay')" title="Pay now" aria-label="Pay now" class="btn btn-sm btn-success" role="button">
|
||||
<i class="fa fa-arrow-circle-right"/><span class='d-none d-md-inline'> Pay Now</span>
|
||||
</a>
|
||||
</td>
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-foreach='invoices']/tr/td[hasclass('tx_status')]" position="replace">
|
||||
<t t-set="last_tx" t-value="invoice.get_portal_last_transaction()"/>
|
||||
<td class="tx_status">
|
||||
<td class="tx_status text-center">
|
||||
<t t-if="invoice.state == 'open' and (last_tx.state not in ['pending', 'authorized', 'done', 'cancel'] or (last_tx.state == 'pending' and last_tx.acquirer_id.provider in ('transfer', 'manual')))">
|
||||
<span class="badge badge-info"><i class="fa fa-fw fa-clock-o"></i><span class="d-none d-md-inline"> Waiting for Payment</span></span>
|
||||
<span class="badge badge-pill badge-info"><i class="fa fa-fw fa-clock-o"></i><span class="d-none d-md-inline"> Waiting for Payment</span></span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'open' and last_tx.state == 'authorized'">
|
||||
<span class="badge badge-success"><i class="fa fa-fw fa-check"/><span class="d-none d-md-inline"> Authorized</span></span>
|
||||
<span class="badge badge-pill badge-primary"><i class="fa fa-fw fa-check"/><span class="d-none d-md-inline"> Authorized</span></span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'open' and last_tx.state == 'pending' and last_tx.acquirer_id.provider not in ('transfer', 'manual')">
|
||||
<span class="badge badge-warning"><span class="d-none d-md-inline"> Pending</span></span>
|
||||
<span class="badge badge-pill badge-warning"><span class="d-none d-md-inline"> Pending</span></span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'paid' or last_tx.state == 'done'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-check"></i><span class="d-none d-md-inline"> Paid</span></span>
|
||||
<span class="badge badge-pill badge-success"><i class="fa fa-fw fa-check"></i><span class="d-none d-md-inline"> Paid</span></span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'cancel'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-remove"></i><span class="d-none d-md-inline"> Cancelled</span></span>
|
||||
<span class="badge badge-pill badge-danger"><i class="fa fa-fw fa-remove"></i><span class="d-none d-md-inline"> Cancelled</span></span>
|
||||
</t>
|
||||
</td>
|
||||
</xpath>
|
||||
@@ -67,22 +67,20 @@
|
||||
</template>
|
||||
|
||||
<template id="portal_invoice_page_inherit_payment" name="Payment on My Invoices" inherit_id="account.portal_invoice_page">
|
||||
<xpath expr="//div[@id='sidebar_content']//div[hasclass('o_download_pdf')]" position="before">
|
||||
<xpath expr="//t[@t-call='portal.portal_record_sidebar']//div[hasclass('o_download_pdf')]" position="before">
|
||||
<t t-set="tx_ids" t-value="invoice.transaction_ids.filtered(lambda tx: tx.state in ('pending', 'authorized', 'done'))"/>
|
||||
<t t-set="pending_manual_txs" t-value="tx_ids.filtered(lambda tx: tx.state == 'pending' and tx.acquirer_id.provider in ('transfer', 'manual'))"/>
|
||||
<div class="mb8 ml16 mr16">
|
||||
<a t-if="invoice.state == 'open' and invoice.amount_total and invoice.type == 'out_invoice' and (pending_manual_txs or not tx_ids)"
|
||||
class="btn btn-primary btn-block" data-toggle="modal" data-target="#pay_with">
|
||||
<i class="fa fa-arrow-circle-right"/> Pay Now
|
||||
</a>
|
||||
<a t-if="tx_ids and not pending_manual_txs and invoice.state != 'paid'"
|
||||
class="btn btn-warning btn-block" disabled="disabled">
|
||||
<i class="fa fa-check-circle"/> Pending
|
||||
</a>
|
||||
<a t-if="invoice.state == 'paid'"
|
||||
class="btn btn-success btn-block" disabled="disabled">
|
||||
<i class="fa fa-check-circle"/> Paid
|
||||
<div>
|
||||
<a href="#" t-if="invoice.state == 'open' and invoice.amount_total and invoice.type == 'out_invoice' and (pending_manual_txs or not tx_ids)"
|
||||
class="btn btn-success btn-block mb-2" data-toggle="modal" data-target="#pay_with">
|
||||
<i class="fa fa-fw fa-arrow-circle-right"/> Pay Now
|
||||
</a>
|
||||
<div t-if="tx_ids and not pending_manual_txs and invoice.state != 'paid'" class="alert alert-info py-1 mb-2" >
|
||||
<i class="fa fa-fw fa-check-circle"/> Pending
|
||||
</div>
|
||||
<div t-if="invoice.state == 'paid'" class="alert alert-success py-1 mb-2" >
|
||||
<i class="fa fa-fw fa-check-circle"/> Paid
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//div[@id='invoice_content']//div[hasclass('o_portal_html_view')]" position="before">
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="portal_my_task" inherit_id="project.portal_my_task" name="Portal: My Task with imesheets">
|
||||
<xpath expr="//div[hasclass('card-body')]" position="inside">
|
||||
<template id="portal_my_task" inherit_id="project.portal_my_task" name="Portal: My Task with Timesheets">
|
||||
<xpath expr="//t[@t-set='card_body']" position="inside">
|
||||
<div class="container" t-if="task.timesheet_ids">
|
||||
<hr/>
|
||||
<table class="table table-hover">
|
||||
<hr class="mt-4 mb-1"/>
|
||||
<h5 class="mt-2 mb-2">Timesheets</h5>
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th class="col-lg-6">Description</th>
|
||||
<th>Description</th>
|
||||
<th>Responsible</th>
|
||||
<th>Duration</th>
|
||||
<th class="text-right">Duration</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr t-foreach="task.timesheet_ids" t-as="timesheet">
|
||||
<td><t t-esc="timesheet.date"/></td>
|
||||
<td><t t-esc="timesheet.name"/></td>
|
||||
<td><t t-esc="timesheet.sudo().user_id.name"/></td>
|
||||
<td><span t-field="timesheet.unit_amount" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/></td>
|
||||
<td class="text-right"><span t-field="timesheet.unit_amount" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -15,9 +15,6 @@ var PortalSidebar = Widget.extend({
|
||||
start: function () {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
// Window Handlers
|
||||
$(window).on('resize', _.throttle(self._onUpdateSidebarPosition.bind(self), 200, {leading: false}));
|
||||
this._onUpdateSidebarPosition();
|
||||
this._setDelayLabel();
|
||||
},
|
||||
|
||||
@@ -69,22 +66,6 @@ var PortalSidebar = Widget.extend({
|
||||
this.printContent.get(0).contentWindow.print();
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when the window is resized or on loadoing widget
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onUpdateSidebarPosition: function () {
|
||||
var $sidebar = this.$el.find('.bs-sidebar, .o_portal_brand');
|
||||
$sidebar.css({
|
||||
width: config.device.size_class >= config.device.SIZES.MD ? $sidebar.outerWidth() : '',
|
||||
});
|
||||
},
|
||||
});
|
||||
return PortalSidebar;
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ tour.register('portal_load_homepage', {
|
||||
[
|
||||
{
|
||||
content: "Check portal is loaded",
|
||||
trigger: 'a[href*="/my/account"]:contains("Change"):first',
|
||||
trigger: 'a[href*="/my/account"]:contains("Edit"):first',
|
||||
},
|
||||
{
|
||||
content: "Load my account details",
|
||||
|
||||
@@ -3,8 +3,24 @@
|
||||
/// rules.
|
||||
///
|
||||
|
||||
// ====== Variables =========
|
||||
$-navbar-height: $nav-link-height !default;
|
||||
|
||||
// Portal toolbar (filters, search bar)
|
||||
$o-portal-mobile-toolbar: true; // Enable/Disable custom design
|
||||
$o-portal-mobile-toolbar-border: $border-color;
|
||||
$o-portal-mobile-toolbar-bg: $gray-200;
|
||||
|
||||
// Portal Tables
|
||||
$o-portal-table-th-pt: map-get($spacers, 2) !default; // bts4 pt-2
|
||||
$o-portal-table-th-pb: map-get($spacers, 2) !default; // bts4 pb-2
|
||||
$o-portal-table-td-pt: map-get($spacers, 1) !default; // bts4 pt-1
|
||||
$o-portal-table-td-pb: map-get($spacers, 1) !default; // bts4 pb-1
|
||||
|
||||
// Page custom bg (eg. 'Invoice')
|
||||
$o-portal-bg: true; // Enable/Disable page custom bg.
|
||||
$o-portal-bg-color: desaturate($gray-200, 100%);
|
||||
|
||||
// Resize and vertically align navbar’s items relative to navbar
|
||||
@mixin o-w-fill-navbar($ratio: 1) {
|
||||
height: round($-navbar-height * $ratio * 100) / 100;
|
||||
@@ -158,6 +174,14 @@ hr {
|
||||
color: color-yiq($list-group-bg);
|
||||
}
|
||||
|
||||
%o-portal-breadcrumbs {
|
||||
background-color: transparent;
|
||||
|
||||
.breadcrumb-item {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces old BS3 page-header class
|
||||
%o-page-header {
|
||||
margin-bottom: $headings-margin-bottom * 2;
|
||||
@@ -165,6 +189,7 @@ hr {
|
||||
border-bottom-width: $border-width;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: $border-color;
|
||||
line-height: 2.1rem;
|
||||
}
|
||||
.o_page_header {
|
||||
@extend %o-page-header;
|
||||
@@ -297,14 +322,19 @@ img.o_we_custom_image {
|
||||
}
|
||||
|
||||
// Portal specific
|
||||
|
||||
// === Page custom bg (eg. 'Invoice') ===
|
||||
// This could have been achieved easily using a class (eg. bg-200), but we
|
||||
// don't want to force the design because of themes.
|
||||
@if ($o-portal-bg) {
|
||||
#wrapwrap.o_portal_bg_dark {
|
||||
@include o-bg-color($o-portal-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
.o_portal {
|
||||
.breadcrumb {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.record_pager {
|
||||
padding: 8px 0px;
|
||||
@extend %o-portal-breadcrumbs;
|
||||
}
|
||||
|
||||
> tbody.o_portal_report_tbody {
|
||||
@@ -317,77 +347,83 @@ img.o_we_custom_image {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.o_portal_my_doc_table {
|
||||
td, th {
|
||||
text-align: right;
|
||||
}
|
||||
tr > :first-child {
|
||||
text-align: left;
|
||||
.o_portal_navbar {
|
||||
.breadcrumb {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
@extend %o-portal-breadcrumbs;
|
||||
|
||||
.breadcrumb-item.active {
|
||||
// In this context, active breadcrumb act as title
|
||||
color: $headings-color;
|
||||
line-height: $h5-font-size/$font-size-base;
|
||||
font: {size: $h5-font-size; weight: $headings-font-weight};
|
||||
|
||||
&:before {
|
||||
// Restore breadcrumb divider to default
|
||||
color: $breadcrumb-divider-color;
|
||||
line-height: $line-height-base;
|
||||
font: {size: $font-size-base; weight: $font-weight-base};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_portal_navbar {
|
||||
.navbar-brand {
|
||||
margin: 0;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
padding: $navbar-padding-y $navbar-padding-x 0 0;
|
||||
}
|
||||
.o_portal_my_doc_table {
|
||||
th {
|
||||
padding-top: $o-portal-table-th-pt;
|
||||
padding-bottom: $o-portal-table-th-pb;
|
||||
}
|
||||
|
||||
// ===== Default portal navbar design =====
|
||||
&.o_portal_navbar_default {
|
||||
margin-bottom: 8px;
|
||||
td {
|
||||
padding-top: $o-portal-table-td-pt;
|
||||
padding-bottom: $o-portal-table-td-pb;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: $navbar-padding-y $navbar-padding-x 0 0;
|
||||
td, th {
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
address {
|
||||
span[itemprop="name"] {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
div[itemprop="address"] > div {
|
||||
position: relative;
|
||||
|
||||
span[itemprop="streetAddress"] {
|
||||
line-height: 1.2;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.navbar-header .dropdown-menu {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
.fa {
|
||||
@include o-position-absolute(0, $left: 0);
|
||||
line-height: $line-height-base;
|
||||
|
||||
.navbar-toggle {
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
background-color: $table-active-bg;
|
||||
padding: 6px 10px $navbar-padding-y;
|
||||
border-width: 1px 1px 0 1px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
z-index: 1;
|
||||
|
||||
&.collapsed {
|
||||
padding:6px 10px;
|
||||
border-width: 1px;
|
||||
border-radius: $btn-border-radius;
|
||||
background-color: transparent;
|
||||
+ span {
|
||||
display: block;
|
||||
// FontAwesome '.fa-fw' fixed-with + margin
|
||||
padding-left: 1.28571429em + 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
.navbar-collapse {
|
||||
z-index: 0;
|
||||
background-color: $table-active-bg;
|
||||
border-radius: $btn-border-radius;
|
||||
border-top-right-radius: 0;
|
||||
transform: translateY(-2px);
|
||||
.o_my_sidebar div[itemprop="address"] > div {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
&.in {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
> .container-fluid {
|
||||
padding: 0;
|
||||
|
||||
.navbar-form {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
@if ($o-portal-mobile-toolbar) {
|
||||
#o_portal_navbar_content {
|
||||
@include media-breakpoint-down(md) {
|
||||
margin: $navbar-padding-y (-$navbar-padding-x) 0;
|
||||
padding: $navbar-padding-y $navbar-padding-x ;
|
||||
border-top: $border-width solid $o-portal-mobile-toolbar-border;
|
||||
background-color: $o-portal-mobile-toolbar-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,19 +480,31 @@ img.o_we_custom_image {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.o_portal_contact_img {
|
||||
width: 2.3em;
|
||||
height: 2.3em;
|
||||
}
|
||||
|
||||
.o_portal_sidebar {
|
||||
.bs-sidebar {
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
background-color: $light;
|
||||
}
|
||||
.o_portal_contact_img {
|
||||
width: 3.7em;
|
||||
height: 3.7em;
|
||||
.o_portal_contact_block {
|
||||
@include media-breakpoint-down(md) {
|
||||
border-left: $border-width solid $border-color;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.o_portal_html_view {
|
||||
border: 1px solid gray('300');
|
||||
border-radius: 5px;
|
||||
padding-right: 1px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
max-width: 210mm; // A4 page's width
|
||||
background: white;
|
||||
|
||||
.o_portal_html_loader {
|
||||
@include o-position-absolute(45%, 0, auto, 0);
|
||||
}
|
||||
|
||||
iframe {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<t t-set="head" t-value="head_website + (head or '')"/>
|
||||
|
||||
<t t-set="direction" t-value="request.env['res.lang'].search([('code', '=', request.env.lang)]).direction"/>
|
||||
<div id="wrapwrap" t-attf-class="#{pageName or ''} #{direction == 'rtl' and 'o_rtl' or ''}">
|
||||
<div id="wrapwrap" t-attf-class="#{pageName or ''} #{direction == 'rtl' and 'o_rtl' or ''} #{wrapwrap_classes or ''}">
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||
<div class="container">
|
||||
@@ -66,34 +66,46 @@
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_breadcrumbs" name="Portal Breadcrumbs">
|
||||
<ol t-if="page_name != 'home'" class="o_portal_submenu breadcrumb mb-0 py-2 flex-grow-1">
|
||||
<li class="breadcrumb-item"><a href="/my/home" aria-label="Home" title="Home"><i class="fa fa-home"/></a></li>
|
||||
<li t-if="page_name == 'my_details'" class="breadcrumb-item">Your Details</li>
|
||||
</ol>
|
||||
</template>
|
||||
|
||||
<template id="portal_layout" name="Portal Layout">
|
||||
<t t-call="portal.frontend_layout">
|
||||
<div class="container mt16 mb16 o_portal">
|
||||
<div class="oe_structure">
|
||||
<div t-if="not no_breadcrumbs" class="row">
|
||||
<div t-attf-class="col-md-12">
|
||||
<t t-call='portal.record_pager'/>
|
||||
<ol t-if="page_name != 'home'" class="breadcrumb o_portal_submenu">
|
||||
<li class="breadcrumb-item"><a href="/my/home" aria-label="Home" title="Home"><i class="fa fa-home"/></a></li>
|
||||
<li t-if="page_name == 'my_details'" class="breadcrumb-item">Your Details</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div t-if="o_portal_fullwidth_alert" class="alert alert-info alert-dismissible rounded-0 fade show d-print-none css_editable_mode_hidden">
|
||||
<div class="container">
|
||||
<t t-raw="o_portal_fullwidth_alert"/>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> × </button>
|
||||
</div>
|
||||
|
||||
<div t-if="not no_breadcrumbs and not my_details and not breadcrumbs_searchbar" class="o_portal container mt-3">
|
||||
<div class="row align-items-center bg-white no-gutters border rounded-top">
|
||||
<div class="col">
|
||||
<t t-call="portal.portal_breadcrumbs"></t>
|
||||
</div>
|
||||
<div t-if="prev_record or next_record" class="col flex-grow-0">
|
||||
<t t-call='portal.record_pager'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wrap" class='o_portal_wrap'>
|
||||
<div class="container mb64">
|
||||
<t t-if="my_details">
|
||||
<div class="row">
|
||||
<div t-attf-class="col-lg-9 col-xl-8">
|
||||
<div class="row justify-content-between mt-4">
|
||||
<div t-attf-class="col-12 col-md col-lg-6">
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
<div id="o_my_sidebar" class="col-lg-3 offset-xl-1 o_my_sidebar">
|
||||
<div id="o_my_sidebar" class="col-12 col-md col-lg-4 col-xl-3 o_my_sidebar">
|
||||
<div class="o_my_contact" t-if="sales_user">
|
||||
<t t-call="portal.portal_contact"/>
|
||||
</div>
|
||||
<div class="o_portal_my_details">
|
||||
<h3 class="o_page_header">Your Details <a role="button" href="/my/account" class="btn btn-secondary btn-sm">Change</a></h3>
|
||||
<h4>Your Details <a role="button" href="/my/account" class="btn btn-sm btn-link"><i class="fa fa-pencil"/> Edit</a></h4>
|
||||
<hr class="mt-1 mb-0"/>
|
||||
<div t-field="user_id.partner_id" t-options='{"widget": "contact", "fields": ["email", "phone", "address", "name"]}'/>
|
||||
</div>
|
||||
<div class="o_my_archives" t-if="archive_groups">
|
||||
@@ -126,14 +138,46 @@
|
||||
<t t-set="my_details" t-value="True"/>
|
||||
<div class="o_portal_my_home">
|
||||
<div class="oe_structure"></div>
|
||||
<h3 class="o_page_header">Your Documents</h3>
|
||||
<ul class="o_portal_docs list-group">
|
||||
</ul>
|
||||
<h3>Your Documents</h3>
|
||||
<div class="o_portal_docs list-group">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12 oe_structure"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_docs_entry" name="My Portal Docs Entry">
|
||||
<a t-att-href="url" t-att-title="title" class="list-group-item list-group-item-action d-flex align-items-center justify-content-between">
|
||||
<t t-esc="title"/>
|
||||
<span class="badge badge-secondary badge-pill" t-esc="count"/>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<template id="portal_table" name="My Portal Table">
|
||||
<div t-attf-class="table-responsive border border-top-0 #{classes if classes else ''}">
|
||||
<table class="table mb-0 o_portal_my_doc_table">
|
||||
<t t-raw="0"/>
|
||||
</table>
|
||||
</div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="portal_record_sidebar" name="My Portal Record Sidebar">
|
||||
<div t-attf-class="col-12 col-lg flex-lg-grow-0 #{classes}">
|
||||
<div class="card bg-white mb-4" id="sidebar_content">
|
||||
<div t-if="title" class="card-body text-center pb-2 pt-3">
|
||||
<t t-raw="title"/>
|
||||
</div>
|
||||
<t t-if="entries" t-raw="entries"/>
|
||||
<div class="card-footer small text-center text-muted border-top-0 pt-1 pb-1 d-none d-lg-block">
|
||||
Powered by <a target="_blank" href="http://www.odoo.com?utm_source=db&utm_medium=portal" title="odoo"><img src="/web/static/src/img/logo.png" alt="Odoo Logo" height="15"/></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!--
|
||||
The search bar is composed of 2 buttons : a "filter by" and a "sort by". Changing the 'sortby'
|
||||
criteria will keep the number of page, query params, ... Changing the 'filterby' param will
|
||||
@@ -149,28 +193,33 @@
|
||||
{'open': {'label': _('In Progress'), 'domain': [('state', '=', 'open')]}}
|
||||
:param string filterby : name of the filter criteria
|
||||
:param default_url : the base url of the pages (like '/my/orders')
|
||||
:param boolean breadcrumbs_searchbar : set to True to show breadcrumbs rather than the title
|
||||
:param boolean o_portal_search_panel : set to True to active the input search
|
||||
:param html $0 : content of the t-call, <li class="float-left">Link</li>
|
||||
:param html $0 : content of the t-call
|
||||
:param title : bavbar title
|
||||
:param classes : navbar classes
|
||||
-->
|
||||
<template id="portal_searchbar" name="Portal Search Bar">
|
||||
<nav t-attf-class="navbar o_portal_navbar {{classes if classes else 'o_portal_navbar_default'}}">
|
||||
<div class="container-fluid">
|
||||
<!-- Navbar title only -->
|
||||
<div class="navbar-header float-left">
|
||||
<t t-set="no_title">No title</t>
|
||||
<h3 class="navbar-brand"><t t-esc="title or no_title"/></h3>
|
||||
</div>
|
||||
<nav t-attf-class="navbar navbar-light navbar-expand-lg border py-0 o_portal_navbar {{classes if classes else ''}} {{'mt-4 rounded-top border-bottom-0' if breadcrumbs_searchbar else 'border-top-0 mb-2'}}">
|
||||
<!-- Navbar breadcrumb or title -->
|
||||
<t t-if="breadcrumbs_searchbar">
|
||||
<t t-call="portal.portal_breadcrumbs"/>
|
||||
</t>
|
||||
<span t-else="" class="navbar-brand mb-0 h1 mr-auto" t-esc="title or 'No title'"/>
|
||||
|
||||
<!-- Non-collapsing menu item(s) -->
|
||||
<div class="navbar-header navbar-right float-right">
|
||||
<ul class="nav float-left">
|
||||
<t t-raw="0"/>
|
||||
<li t-if="searchbar_sortings" class="dropdown float-left ml16">
|
||||
<button id="portal_searchbar_sortby" data-toggle="dropdown" class="btn btn-secondary dropdown-toggle navbar-btn">
|
||||
<span class="fa fa-sort"/>
|
||||
<span class="d-none d-lg-inline"><t t-esc="searchbar_sortings[sortby].get('label', 'Newest')"/></span>
|
||||
<!-- Collapse button -->
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#o_portal_navbar_content" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle filters">
|
||||
<span class="navbar-toggler-icon small"/>
|
||||
</button>
|
||||
|
||||
<!-- Collapsable content -->
|
||||
<div class="collapse navbar-collapse" id="o_portal_navbar_content">
|
||||
<div class="nav flex-column flex-lg-row ml-auto p-0 mb-3 mb-lg-0 mt-1 mt-lg-0">
|
||||
<div t-if="searchbar_sortings" class="form-inline">
|
||||
<span class="small mr-1 navbar-text">Sort By:</span>
|
||||
<div class="btn-group">
|
||||
<button id="portal_searchbar_sortby" data-toggle="dropdown" class="btn btn-secondary btn-sm dropdown-toggle">
|
||||
<t t-esc="searchbar_sortings[sortby].get('label', 'Newest')"/>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="portal_searchbar_sortby">
|
||||
<t t-foreach="searchbar_sortings" t-as="option">
|
||||
@@ -180,11 +229,13 @@
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</li>
|
||||
<li t-if="searchbar_filters" class="dropdown float-left ml4">
|
||||
<button id="portal_searchbar_filters" data-toggle="dropdown" class="btn btn-secondary dropdown-toggle navbar-btn">
|
||||
<span class="fa fa-filter"/>
|
||||
<span class="d-none d-lg-inline"><t t-esc="searchbar_filters[filterby].get('label', 'All')"/></span>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="searchbar_filters" class="form-inline ml-lg-2">
|
||||
<span class="small mr-1 navbar-text">Filter By:</span>
|
||||
<div class="btn-group">
|
||||
<button id="portal_searchbar_filters" data-toggle="dropdown" class="btn btn-secondary btn-sm dropdown-toggle">
|
||||
<t t-esc="searchbar_filters[filterby].get('label', 'All')"/>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="portal_searchbar_filters">
|
||||
<t t-foreach="searchbar_filters" t-as="option">
|
||||
@@ -194,11 +245,13 @@
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</li>
|
||||
<li t-if="searchbar_groupby" class="dropdown float-left ml4">
|
||||
<button id="portal_searchbar_groupby" data-toggle="dropdown" class="btn btn-secondary dropdown-toggle navbar-btn">
|
||||
<span class="fa fa-object-group"/>
|
||||
<span class="d-none d-lg-inline"><t t-esc="searchbar_groupby[groupby].get('label', 'None')"/></span>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="searchbar_groupby" class="form-inline ml-lg-2">
|
||||
<span class="small mr-1 navbar-text">Group By:</span>
|
||||
<div class="btn-group">
|
||||
<button id="portal_searchbar_groupby" data-toggle="dropdown" class="btn btn-secondary btn-sm dropdown-toggle">
|
||||
<t t-esc="searchbar_groupby[groupby].get('label', 'None')"/>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="portal_searchbar_groupby">
|
||||
<t t-foreach="searchbar_groupby" t-as="option">
|
||||
@@ -208,46 +261,64 @@
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<button t-if='searchbar_inputs' type="button" class="navbar-toggle collapsed btn ml16" data-toggle="collapse" data-target="#o_portal_searchbar_collapse"><span class="fa fa-search"/></button>
|
||||
</div>
|
||||
<div t-if='searchbar_inputs' class="d-block d-md-none clearfix"/>
|
||||
|
||||
<!-- Collapsing content (searchbar_inputs) -->
|
||||
<div t-if='searchbar_inputs' class="collapse navbar-collapse text-right" id="o_portal_searchbar_collapse">
|
||||
<div class="navbar-form o_portal_search_panel">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown">
|
||||
<span id="search_label" class="d-none d-md-inline mr4">Search</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<t t-foreach='searchbar_inputs' t-as='input'>
|
||||
<a t-att-href="'#' + searchbar_inputs[input]['input']"
|
||||
t-attf-class="dropdown-item#{search_in == searchbar_inputs[input]['input'] and ' active' or ''}">
|
||||
<span t-raw="searchbar_inputs[input]['label']"/>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" class="form-control" t-att-value='search' name="search"/>
|
||||
<span class="input-group-append">
|
||||
<button class="btn btn-secondary search-submit" type="button"><span class="fa fa-search d-none d-md-inline-block"/><span class="fa fa-arrow-right d-inline-block d-md-none"/></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
</div> <!-- /.container-fluid -->
|
||||
<form t-if="searchbar_inputs" class="form-inline o_portal_search_panel ml-lg-4">
|
||||
<div class="input-group input-group-sm w-100">
|
||||
<div class="input-group-prepend">
|
||||
<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown"/>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<t t-foreach='searchbar_inputs' t-as='input'>
|
||||
<a t-att-href="'#' + searchbar_inputs[input]['input']"
|
||||
t-attf-class="dropdown-item#{search_in == searchbar_inputs[input]['input'] and ' active' or ''}">
|
||||
<span t-raw="searchbar_inputs[input]['label']"/>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-sm" placeholder="Search" t-att-value='search' name="search"/>
|
||||
<span class="input-group-append">
|
||||
<button class="btn btn-secondary search-submit" type="button">
|
||||
<span class="fa fa-search"/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<template id="portal_record_layout" name="Portal single record layout">
|
||||
<div t-attf-class="card mt-0 border-top-0 rounded-0 rounded-bottom #{classes if classes else ''}">
|
||||
<div t-if="card_header" t-attf-class="card-header #{header_classes if header_classes else ''}">
|
||||
<t t-raw="card_header"/>
|
||||
</div>
|
||||
<div t-if="card_body" t-attf-class="card-body #{body_classes if body_classes else ''}">
|
||||
<t t-raw="card_body"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="portal_contact" name="Contact">
|
||||
<h3 class="o_page_header"><t t-esc="title"/></h3>
|
||||
<h5 t-esc="sales_user.name"/>
|
||||
<p><a t-att-href="'mailto:'+sales_user.email" t-esc="sales_user.email"/></p>
|
||||
<p t-esc="sales_user.phone"/>
|
||||
<p t-esc="sales_user.city"/>
|
||||
<div class="o_portal_contact_details mb-5">
|
||||
<h4><t t-if="title" t-esc="title"/><t t-else="">Your contact</t></h4>
|
||||
<hr class="mt-1 mb0"/>
|
||||
<h6 class="mb-1"><b t-esc="sales_user.name"/></h6>
|
||||
<div class="d-flex align-items-center mb-1">
|
||||
<div class="fa fa-envelope fa-fw mr-1"></div>
|
||||
<a t-att-href="'mailto:'+sales_user.email" t-esc="sales_user.email"/>
|
||||
</div>
|
||||
<div class="d-flex flex-nowrap align-items-center mb-1">
|
||||
<div class="fa fa-phone fa-fw mr-1"></div>
|
||||
<span t-esc="sales_user.phone"/>
|
||||
</div>
|
||||
<div class="d-flex flex-nowrap align-items-center mb-1">
|
||||
<div class="fa fa-map-marker fa-fw mr-1"></div>
|
||||
<span t-esc="sales_user.city"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="portal_archive_groups" name="Portal Archive Groups">
|
||||
@@ -357,10 +428,10 @@
|
||||
|
||||
<template id="record_pager" name="Portal Record Pager">
|
||||
<t t-if='prev_record or next_record'>
|
||||
<div class="ml8 record_pager btn-group btn-group-xs float-md-right" role="group">
|
||||
<a role="button" t-att-class="'btn btn-secondary %s' % ('disabled' if not prev_record else '')" t-att-href="prev_record or '#'" ><i class="fa fa-arrow-left" role="img" aria-label="Previous" title="Previous"></i></a>
|
||||
<a role="button" t-att-class="'btn btn-secondary %s' % ('disabled' if not next_record else '')" t-att-href="next_record or '#'" ><i class="fa fa-arrow-right" role="img" aria-label="Next" title="Previous"></i></a>
|
||||
</div>
|
||||
<div class="record_pager btn-group" role="group">
|
||||
<a role="button" t-att-class="'btn btn-link %s' % ('disabled' if not prev_record else '')" t-att-href="prev_record or '#'" ><i class="fa fa-chevron-left" role="img" aria-label="Previous" title="Previous"></i></a>
|
||||
<a role="button" t-att-class="'btn btn-link %s' % ('disabled' if not next_record else '')" t-att-href="next_record or '#'" ><i class="fa fa-chevron-right" role="img" aria-label="Next" title="Previous"></i></a>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,39 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="portal_layout" name="Portal layout: project menu entry" inherit_id="portal.portal_layout" priority="40">
|
||||
<template id="portal_layout" name="Portal layout: project menu entry" inherit_id="portal.portal_breadcrumbs" priority="40">
|
||||
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
|
||||
<li t-if="page_name == 'project' or project" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'project' or project" t-attf-class="breadcrumb-item #{'active ' if not project else ''}">
|
||||
<a t-if="project" t-attf-href="/my/projects?{{ keep_query() }}">Projects</a>
|
||||
<t t-else="">Projects</t>
|
||||
</li>
|
||||
<li t-if="project" class="breadcrumb-item">
|
||||
<li t-if="project" class="breadcrumb-item active">
|
||||
<t t-esc="project.name"/>
|
||||
</li>
|
||||
<li t-if="page_name == 'task' or task" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'task' or task" t-attf-class="breadcrumb-item #{'active ' if not task else ''}">
|
||||
<a t-if="task" t-attf-href="/my/tasks?{{ keep_query() }}">Tasks</a>
|
||||
<t t-else="">Tasks</t>
|
||||
</li>
|
||||
<li t-if="task" class="breadcrumb-item">
|
||||
<li t-if="task" class="breadcrumb-item active">
|
||||
<span t-field="task.name"/>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_home" name="Portal My Home: project entries" inherit_id="portal.portal_my_home" priority="40">
|
||||
<xpath expr="//ul[hasclass('o_portal_docs')]" position="inside">
|
||||
<li t-if="project_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="project_count"/>
|
||||
<a href="/my/projects">Projects</a>
|
||||
</li>
|
||||
<li t-if="task_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="task_count"/>
|
||||
<a href="/my/tasks">Tasks</a>
|
||||
</li>
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
|
||||
<t t-if="project_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">Projects</t>
|
||||
<t t-set="url" t-value="'/my/projects'"/>
|
||||
<t t-set="count" t-value="project_count"/>
|
||||
</t>
|
||||
<t t-if="task_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">Tasks</t>
|
||||
<t t-set="url" t-value="'/my/tasks'"/>
|
||||
<t t-set="count" t-value="task_count"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_projects" name="My Projects">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">Projects</t>
|
||||
</t>
|
||||
@@ -42,80 +46,87 @@
|
||||
There are no projects.
|
||||
</div>
|
||||
</t>
|
||||
<div t-if="projects" class="card">
|
||||
<div class="table-responsive"><table class="table table-hover o_portal_my_doc_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th class="col-lg-6">Name</th>
|
||||
<th>Tasks</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="projects" t-as="project">
|
||||
<td>
|
||||
<a t-attf-href="/my/project/#{project.id}?{{ keep_query() }}"><span t-field="project.name"/></a>
|
||||
</td>
|
||||
<td>
|
||||
<a t-attf-href="/my/tasks?{{keep_query('debug', filterby=project.id)}}">
|
||||
<t t-esc="project.task_count" />
|
||||
<t t-esc="project.label_tasks" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
<t t-if="projects" t-call="portal.portal_table">
|
||||
<tbody>
|
||||
<tr t-foreach="projects" t-as="project">
|
||||
<td>
|
||||
<a t-attf-href="/my/project/#{project.id}?{{ keep_query() }}"><span t-field="project.name"/></a>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a t-attf-href="/my/tasks?{{keep_query('debug', filterby=project.id)}}">
|
||||
<t t-esc="project.task_count" />
|
||||
<t t-esc="project.label_tasks" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_project" name="My Project">
|
||||
<t t-call="portal.portal_layout">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h4>
|
||||
Project - <span t-field="project.name"/>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<t t-set="wrapwrap_classes" t-value="'o_portal_bg_dark'"/>
|
||||
|
||||
<t t-set="o_portal_fullwidth_alert" groups="project.group_project_user">
|
||||
<div t-ignore="true" class="text-center">
|
||||
This is a preview of the customer portal <i class="fa fa-chevron-right"/>
|
||||
<a title="Edit in the backend" target="_blank" t-att-href="'/web#return_label=Website&model=project.project&id=%s&view_type=form' % (project.id)">
|
||||
<b>Back in edit mode</b>.
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class='row'>
|
||||
<div class="col-lg-6">
|
||||
<t t-if="project.partner_id">
|
||||
<strong>Customer</strong>
|
||||
<div t-if="project.partner_id">
|
||||
<address t-field="project.partner_id" t-options='{"widget": "contact", "fields": ["name", "email"]}'/>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">×</button>
|
||||
</t>
|
||||
|
||||
<t t-call="portal.portal_record_layout">
|
||||
<t t-set="card_header">
|
||||
<h5 class="mb-0">
|
||||
<small class="text-muted">Project - </small><span t-field="project.name"/>
|
||||
<span class="float-right">
|
||||
<a role="button" t-attf-href="/my/tasks?filterby=#{project.id}" class="btn btn-sm btn-secondary">
|
||||
<span class="fa fa-tasks" role="img" aria-label="Tasks" title="Tasks"/>
|
||||
<span t-esc="project.task_count" />
|
||||
<span t-field="project.label_tasks" />
|
||||
</a>
|
||||
</span>
|
||||
</h5>
|
||||
</t>
|
||||
<t t-set="card_body">
|
||||
<div class="row">
|
||||
<div t-if="project.partner_id" class="col-12 col-md-6 mb-2 mb-md-0">
|
||||
<h6>Customer</h6>
|
||||
<div class="row">
|
||||
<div class="col flex-grow-0 pr-3">
|
||||
<img t-if="project.partner_id.image" class="rounded-circle mt-1 o_portal_contact_img" t-attf-src="data:image/png;base64,#{project.partner_id.image}" alt="Contact"/>
|
||||
<img t-else="" class="rounded-circle mt-1 o_portal_contact_img" src="/web/static/src/img/user_menu_avatar.png" alt="Contact"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="project.user_id">
|
||||
<strong>Project Manager</strong>
|
||||
<div>
|
||||
<div class="col pl-sm-0">
|
||||
<address t-field="project.partner_id" t-options='{"widget": "contact", "fields": ["name", "email", "phone"]}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="project.user_id" class="col-12 col-md-6">
|
||||
<h6>Project Manager</h6>
|
||||
<div class="row">
|
||||
<div class="col flex-grow-0 pr-3">
|
||||
<img t-if="project.user_id.image" class="rounded-circle mt-1 o_portal_contact_img" t-attf-src="data:image/png;base64,#{project.user_id.image}" alt="Contact"/>
|
||||
<img t-else="" class="rounded-circle mt-1 o_portal_contact_img" src="/web/static/src/img/user_menu_avatar.png" alt="Contact"/>
|
||||
</div>
|
||||
<div class="col pl-sm-0">
|
||||
<address t-field="project.user_id" t-options='{"widget": "contact", "fields": ["name", "email", "phone"]}'/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="float-right">
|
||||
<a role="button" t-attf-href="/my/tasks?filterby=#{project.id}" class="btn btn-secondary btn-lg">
|
||||
<span class="fa fa-tasks" role="img" aria-label="Tasks" title="Tasks"/>
|
||||
<span t-esc="project.task_count" />
|
||||
<span t-field="project.label_tasks" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_tasks" name="My Tasks">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">Tasks</t>
|
||||
</t>
|
||||
@@ -124,121 +135,141 @@
|
||||
There are no tasks.
|
||||
</div>
|
||||
</t>
|
||||
<div t-if="grouped_tasks" class="card">
|
||||
<div class="table-responsive">
|
||||
<t t-if="grouped_tasks">
|
||||
<t t-call="portal.portal_table">
|
||||
<t t-foreach="grouped_tasks" t-as="tasks">
|
||||
<table class="table table-hover o_portal_my_doc_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th t-if="groupby == 'none'" class="col-lg-9">Name</th>
|
||||
<th t-else="" class="col-lg-9"><span t-field="tasks[0].sudo().project_id.label_tasks"/> for project: <span t-field="tasks[0].sudo().project_id.name"/></th>
|
||||
<th class="col-lg-2">Stage</th>
|
||||
<th>Ref</th>
|
||||
<thead>
|
||||
<tr t-attf-class="{{'thead-light' if not groupby == 'none' else ''}}">
|
||||
<th t-if="groupby == 'none'">Name</th>
|
||||
<th t-else="">
|
||||
<em class="font-weight-normal text-muted"><span t-field="tasks[0].sudo().project_id.label_tasks"/> for project:</em>
|
||||
<span t-field="tasks[0].sudo().project_id.name"/></th>
|
||||
<th class="text-center">Stage</th>
|
||||
<th class="text-left">Ref</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="tasks" t-as="task">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-attf-href="/my/task/#{task.id}?{{ keep_query() }}"><span t-field="task.name"/></a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="badge badge-pill badge-info" title="Current stage of the task" t-esc="task.stage_id.name" />
|
||||
</td>
|
||||
<td class="text-left">
|
||||
#<span t-esc="task.id"/>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="tasks" t-as="task">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-attf-href="/my/task/#{task.id}?{{ keep_query() }}"><span t-field="task.name"/></a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-info" title="Current stage of the task" t-esc="task.stage_id.name" />
|
||||
</td>
|
||||
<td>
|
||||
<span t-esc="task.id"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
</tbody>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_task" name="My Task">
|
||||
<t t-call="portal.portal_layout">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h4>
|
||||
Task - <span t-field="task.name"/> (#<span t-esc="task.id"/>)
|
||||
<span t-field="task.stage_id.name" class="float-right badge badge-info" title="Current stage of this task"/>
|
||||
<a role="button" class="btn btn-info" t-att-href="'/web#return_label=Website&model=project.task&id=%s&view_type=form' % (task.id)" groups="project.group_project_user">Edit Task</a>
|
||||
</h4>
|
||||
<t t-set="wrapwrap_classes" t-value="'o_portal_bg_dark'"/>
|
||||
|
||||
<t t-set="o_portal_fullwidth_alert" groups="project.group_project_user">
|
||||
<div t-ignore="true" class="text-center">
|
||||
This is a preview of the customer portal <i class="fa fa-chevron-right"/>
|
||||
<a title="Edit in the backend" target="_blank" t-att-href="'/web#return_label=Website&model=project.task&id=%s&view_type=form' % (task.id)">
|
||||
<b>Back in edit mode</b>.
|
||||
</a>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">×</button>
|
||||
</t>
|
||||
|
||||
<t t-call="portal.portal_record_layout">
|
||||
<t t-set="card_header">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-md">
|
||||
<h5 class="mb-1 mb-md-0">
|
||||
<span t-field="task.name"/>
|
||||
<small class="text-muted"> (#<span t-field="task.id"/>)</small>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-md text-md-right">
|
||||
<small class="text-right">Status:</small>
|
||||
<span t-field="task.stage_id.name" class=" badge badge-pill badge-info" title="Current stage of this task"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb8" t-if="user.partner_id.id in task.sudo().project_id.message_partner_ids.ids">
|
||||
</t>
|
||||
<t t-set="card_body">
|
||||
<div class="mb-1" t-if="user.partner_id.id in task.sudo().project_id.message_partner_ids.ids">
|
||||
<strong>Project:</strong> <a t-attf-href="/my/project/#{task.project_id.id}" t-field="task.project_id.name"/>
|
||||
</div>
|
||||
|
||||
<div class='row'>
|
||||
<div class="col-lg-6">
|
||||
<div class="mb8">
|
||||
<strong>Date:</strong> <span t-field="task.create_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-12 col-md-6 mb-1">
|
||||
<strong>Date:</strong> <span t-field="task.create_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class="col-12 col-md-6" t-if="task.date_deadline">
|
||||
<strong>Deadline:</strong> <span t-field="task.date_deadline" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-if="task.user_id">
|
||||
<strong>Assigned to</strong>
|
||||
<div>
|
||||
<address t-field="task.user_id" t-options='{"widget": "contact", "fields": ["name", "email", "phone"]}'/>
|
||||
<div class="row mb-4" t-if="task.user_id or task.partner_id">
|
||||
<div class="col-12 col-md-6 pb-2" t-if="task.user_id">
|
||||
<strong>Assigned to</strong>
|
||||
<div class="row">
|
||||
<div class="col flex-grow-0 pr-3">
|
||||
<img t-if="task.user_id.image" class="rounded-circle mt-1 o_portal_contact_img" t-attf-src="data:image/png;base64,#{task.user_id.image}" alt="Contact"/>
|
||||
<img t-else="" class="rounded-circle mt-1 o_portal_contact_img" src="/web/static/src/img/user_menu_avatar.png" alt="Contact"/>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="task.attachment_ids" class='card-footer'>
|
||||
<strong>
|
||||
<t t-if='len(task.attachment_ids)>1'>Attachments</t>
|
||||
<t t-else="">Attachment</t>
|
||||
</strong>
|
||||
<div class='row'>
|
||||
<div class="col-lg-2 col-md-3 text-center oe_attachments" t-foreach='task.attachment_ids' t-as='attachment'>
|
||||
<a t-attf-href="/web/content/#{attachment.id}?download=true&access_token=#{attachment.generate_access_token()}" target="_blank">
|
||||
<div class='oe_attachment_embedded o_image o_image_small' t-att-title="attachment.name" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/50x40"/>
|
||||
<div class='oe_attachment_name'><t t-esc='attachment.name' /></div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col pl-md-0">
|
||||
<div t-field="task.user_id" t-options='{"widget": "contact", "fields": ["name", "email", "phone"]}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="mb8" t-if="task.date_deadline">
|
||||
<strong>Deadline:</strong> <span t-field="task.date_deadline" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div t-if="task.partner_id">
|
||||
<strong>Reported by</strong>
|
||||
<div>
|
||||
<address t-field="task.partner_id" t-options='{"widget": "contact", "fields": ["name", "email"]}'/>
|
||||
<div class="coll-12 col-md-6 pb-2" t-if="task.partner_id">
|
||||
<strong>Reported by</strong>
|
||||
<div class="row">
|
||||
<div class="col flex-grow-0 pr-3">
|
||||
<img t-if="task.partner_id.image" class="rounded-circle mt-1 o_portal_contact_img" t-attf-src="data:image/png;base64,#{task.partner_id.image}" alt="Contact"/>
|
||||
<img t-else="" class="rounded-circle mt-1 o_portal_contact_img" src="/web/static/src/img/user_menu_avatar.png" alt="Contact"/>
|
||||
</div>
|
||||
<div class="col pl-md-0">
|
||||
<div t-field="task.partner_id" t-options='{"widget": "contact", "fields": ["name", "email", "phone"]}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="task.description">
|
||||
<div class="col-lg-12">
|
||||
<strong>Description</strong>
|
||||
<div t-field="task.description"/>
|
||||
<div class="row" t-if="task.description or task.attachment_ids">
|
||||
<div t-if="task.description" t-attf-class="col-12 col-lg-7 mb-4 mb-md-0 {{'col-lg-7' if task.attachment_ids else 'col-lg-12'}}">
|
||||
<hr class="mb-1"/>
|
||||
<strong class="d-block mb-2">Description</strong>
|
||||
<div class="py-1 px-2 bg-100 small" t-field="task.description"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt32">
|
||||
<div class="col-lg-12">
|
||||
<h4><strong>Message and communication history</strong></h4>
|
||||
</div>
|
||||
<div class="col-lg-10 offset-lg-1 mt16">
|
||||
<t t-call="portal.message_thread">
|
||||
<t t-set="object" t-value="task"/>
|
||||
<t t-set="token" t-value="task.access_token"/>
|
||||
<t t-set="pid" t-value="pid"/>
|
||||
<t t-set="hash" t-value="hash"/>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="task.attachment_ids" t-attf-class="col-12 col-lg-5 o_project_portal_attachments {{'col-lg-5' if task.description else 'col-lg-12'}}">
|
||||
<hr class="mb-1 d-none d-lg-block"/>
|
||||
<strong class="d-block mb-2">Attachments</strong>
|
||||
<div class="row">
|
||||
<div t-attf-class="col {{'col-lg-6' if not task.description else 'col-lg-12'}}">
|
||||
<ul class="list-group">
|
||||
<a class="list-group-item list-group-item-action d-flex align-items-center oe_attachments py-1 px-2" t-foreach='task.attachment_ids' t-as='attachment' t-attf-href="/web/content/#{attachment.id}" target="_blank">
|
||||
<div class='oe_attachment_embedded o_image o_image_small mr-2 mr-lg-3' t-att-title="attachment.name" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/50x40"/>
|
||||
<div class='oe_attachment_name text-truncate'><t t-esc='attachment.name'/></div>
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<div class="mt32">
|
||||
<h4><strong>Message and communication history</strong></h4>
|
||||
<t t-call="portal.message_thread">
|
||||
<t t-set="object" t-value="task"/>
|
||||
<t t-set="token" t-value="task.access_token"/>
|
||||
<t t-set="pid" t-value="pid"/>
|
||||
<t t-set="hash" t-value="hash"/>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="portal_my_home_menu_purchase" name="Portal layout : purchase menu entries" inherit_id="portal.portal_layout" priority="25">
|
||||
<template id="portal_my_home_menu_purchase" name="Portal layout : purchase menu entries" inherit_id="portal.portal_breadcrumbs" priority="25">
|
||||
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
|
||||
<li t-if="page_name == 'purchase' or purchase_order" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'purchase' or purchase_order" t-attf-class="breadcrumb-item #{'active ' if not purchase_order else ''}">
|
||||
<a t-if="purchase_order" t-attf-href="/my/purchase?{{ keep_query() }}">Purchase Orders</a>
|
||||
<t t-else="">Purchase Orders</t>
|
||||
</li>
|
||||
<li t-if="purchase_order" class="breadcrumb-item">
|
||||
<li t-if="purchase_order" class="breadcrumb-item active">
|
||||
<t t-esc="purchase_order.name"/>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_home_purchase" name="Portal My Home : purchase entry" inherit_id="portal.portal_my_home" priority="25">
|
||||
<xpath expr="//ul[hasclass('o_portal_docs')]" position="inside">
|
||||
<li t-if="purchase_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="purchase_count"/>
|
||||
<a href="/my/purchase">Purchase Orders</a>
|
||||
</li>
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
|
||||
<t t-if="purchase_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">Purchase Orders</t>
|
||||
<t t-set="url" t-value="'/my/purchase'"/>
|
||||
<t t-set="count" t-value="purchase_count"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
@@ -27,8 +28,7 @@
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">Purchase Orders</t>
|
||||
</t>
|
||||
<div t-if="orders" class="card">
|
||||
<div class="table-responsive"><table class="table table-hover o_portal_my_doc_table">
|
||||
<t t-if="orders" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Purchase Orders #</th>
|
||||
@@ -37,29 +37,24 @@
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-attf-href="/my/purchase/#{order.id}?#{keep_query()}"><t t-esc="order.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="order.date_order"/></td>
|
||||
<td>
|
||||
<t t-if="order.invoice_status == 'to invoice'">
|
||||
<span class="badge badge-info"><i class="fa fa-fw fa-file-text"/> Waiting for Bill</span>
|
||||
</t>
|
||||
<t t-if="order.state == 'cancel'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-field="order.amount_total" t-options='{"widget": "monetary", "display_currency": order.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</table></div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
</div>
|
||||
<tbody>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr>
|
||||
<td><a t-attf-href="/my/purchase/#{order.id}?#{keep_query()}"><t t-esc="order.name"/></a></td>
|
||||
<td><span t-field="order.date_order"/></td>
|
||||
<td>
|
||||
<t t-if="order.invoice_status == 'to invoice'">
|
||||
<span class="badge badge-info"><i class="fa fa-fw fa-file-text"/> Waiting for Bill</span>
|
||||
</t>
|
||||
<t t-if="order.state == 'cancel'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-field="order.amount_total" t-options='{"widget": "monetary", "display_currency": order.currency_id}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -76,11 +76,11 @@ var SalePortalSidebar = PortalSidebar.extend({
|
||||
lastUL = null,
|
||||
$bsSidenav = this.$el.find('.bs-sidenav');
|
||||
|
||||
$("[id^=quote_header_], [id^=quote_]", this.spyWatched).attr("id", "");
|
||||
_.each(this.spyWatched.find("h1, h2"), function (el) {
|
||||
$("#quote_content [id^=quote_header_], #quote_content [id^=quote_]", this.spyWatched).attr("id", "");
|
||||
_.each(this.spyWatched.find("#quote_content h2, #quote_content h3"), function (el) {
|
||||
var id, text;
|
||||
switch (el.tagName.toLowerCase()) {
|
||||
case "h1":
|
||||
case "h2":
|
||||
id = self._setElementId('quote_header_', el);
|
||||
text = self._extractText($(el));
|
||||
if (!text) {
|
||||
@@ -89,7 +89,7 @@ var SalePortalSidebar = PortalSidebar.extend({
|
||||
lastLI = $("<li class='nav-item'>").append($('<a class="nav-link" href="#' + id + '"/>').text(text)).appendTo($bsSidenav);
|
||||
lastUL = false;
|
||||
break;
|
||||
case "h2":
|
||||
case "h3":
|
||||
id = self._setElementId('quote_', el);
|
||||
text = self._extractText($(el));
|
||||
if (!text) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="portal_my_home_menu_sale" name="Portal layout : sales menu entries" inherit_id="portal.portal_layout" priority="20">
|
||||
<template id="portal_my_home_menu_sale" name="Portal layout : sales menu entries" inherit_id="portal.portal_breadcrumbs" priority="20">
|
||||
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
|
||||
<li t-if="page_name == 'quote' or sale_order and sale_order.state in ('sent', 'cancel')" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'quote' or sale_order and sale_order.state in ('sent', 'cancel')" t-attf-class="breadcrumb-item #{'active ' if not sale_order else ''}">
|
||||
<a t-if="sale_order" t-attf-href="/my/quotes?{{ keep_query() }}">Quotations</a>
|
||||
<t t-else="">Quotations</t>
|
||||
</li>
|
||||
<li t-if="page_name == 'order' or sale_order and sale_order.state not in ('sent', 'cancel')" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'order' or sale_order and sale_order.state not in ('sent', 'cancel')" t-attf-class="breadcrumb-item #{'active ' if not sale_order else ''}">
|
||||
<a t-if="sale_order" t-attf-href="/my/orders?{{ keep_query() }}">Sales Orders</a>
|
||||
<t t-else="">Sales Orders</t>
|
||||
</li>
|
||||
<li t-if="sale_order" class="breadcrumb-item">
|
||||
<li t-if="sale_order" class="breadcrumb-item active">
|
||||
<span t-field="sale_order.type_name"/>
|
||||
<t t-esc="sale_order.name"/>
|
||||
</li>
|
||||
@@ -19,216 +19,212 @@
|
||||
</template>
|
||||
|
||||
<template id="portal_my_home_sale" name="Portal My Home : sales entries" inherit_id="portal.portal_my_home" priority="20">
|
||||
<xpath expr="//ul[hasclass('o_portal_docs')]" position="inside">
|
||||
<li t-if="quotation_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="quotation_count"/>
|
||||
<a href="/my/quotes">Quotations</a>
|
||||
</li>
|
||||
<li t-if="order_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="order_count"/>
|
||||
<a href="/my/orders">Sales Orders</a>
|
||||
</li>
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
|
||||
<t t-if="quotation_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">Quotations</t>
|
||||
<t t-set="url" t-value="'/my/quotes'"/>
|
||||
<t t-set="count" t-value="quotation_count"/>
|
||||
</t>
|
||||
<t t-if="order_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">Sales Orders</t>
|
||||
<t t-set="url" t-value="'/my/orders'"/>
|
||||
<t t-set="count" t-value="order_count"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_quotations" name="My Quotations">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">Quotations</t>
|
||||
</t>
|
||||
<t t-if="not quotations">
|
||||
<p>There are currently no quotations for your account.</p>
|
||||
</t>
|
||||
<div t-if="quotations" class="card">
|
||||
<div class="table-responsive"><table class="table table-hover o_portal_my_doc_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Quotation #</th>
|
||||
<th>Order Date</th>
|
||||
<th>Valid Until</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="quotations" t-as="quotation">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="quotation.get_portal_url()"><t t-esc="quotation.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="quotation.date_order"/></td>
|
||||
<td><span t-field="quotation.validity_date"/></td>
|
||||
<td>
|
||||
<t t-if="quotation.state == 'cancel'">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
<t t-if="quotation.is_expired">
|
||||
<span class="badge badge-secondary"><i class="fa fa-fw fa-clock-o"/> Expired</span>
|
||||
</t>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="quotation.amount_total"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</table></div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="quotations" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Quotation #</th>
|
||||
<th class="text-right">Order Date</th>
|
||||
<th class="text-right">Valid Until</th>
|
||||
<th class="text-center"/>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="quotations" t-as="quotation">
|
||||
<tr>
|
||||
<td><a t-att-href="quotation.get_portal_url()"><t t-esc="quotation.name"/></a></td>
|
||||
<td class="text-right"><span t-field="quotation.date_order"/></td>
|
||||
<td class="text-right"><span t-field="quotation.validity_date"/></td>
|
||||
<td class="text-center">
|
||||
<span t-if="quotation.state == 'cancel'" class="badge badge-pill badge-secondary"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
<span t-if="quotation.is_expired" class="badge badge-pill badge-secondary"><i class="fa fa-fw fa-clock-o"/> Expired</span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="quotation.amount_total"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_orders" name="My Sales Orders">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">Sales Orders</t>
|
||||
</t>
|
||||
<t t-if="not orders">
|
||||
<p>There are currently no orders for your account.</p>
|
||||
</t>
|
||||
<div t-if="orders" class="card">
|
||||
<div class="table-responsive"><table class="table table-hover o_portal_my_doc_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>
|
||||
<span class='d-none d-md-inline'>Sales Order #</span>
|
||||
<span class='d-block d-md-none'>Ref.</span>
|
||||
</th>
|
||||
<th>Order Date</th>
|
||||
<th ></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="order.get_portal_url()"><t t-esc="order.name"/></a>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="order.date_order" t-options="{'widget': 'date'}"/>&nbsp;
|
||||
<span class='d-none d-md-inline' t-field="order.date_order" t-options="{'time_only': True}"/>
|
||||
</td>
|
||||
<td>
|
||||
<t t-if="order.state == 'done'">
|
||||
<span class="badge badge-success d-none d-md-inline-block"><i class="fa fa-fw fa-check" role="img" aria-label="Done" title="Done"></i><span class="d-none d-md-inline"> Done</span></span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-field="order.amount_total"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table></div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="portal.pager"/>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="orders" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>
|
||||
<span class='d-none d-md-inline'>Sales Order #</span>
|
||||
<span class='d-block d-md-none'>Ref.</span>
|
||||
</th>
|
||||
<th class="text-right">Order Date</th>
|
||||
<th class="text-center"/>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr>
|
||||
<td><a t-att-href="order.get_portal_url()"><t t-esc="order.name"/></a></td>
|
||||
<td class="text-right">
|
||||
<span t-field="order.date_order" t-options="{'widget': 'date'}"/>&nbsp;
|
||||
<span class='d-none d-md-inline' t-field="order.date_order" t-options="{'time_only': True}"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-if="order.state == 'done'" class="badge badge-pill badge-success">
|
||||
<i class="fa fa-fw fa-check" role="img" aria-label="Done" title="Done"/>Done
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-right"><span t-field="order.amount_total"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Complete page of the sale_order -->
|
||||
<template id="sale_order_portal_template" name="Sales Order Portal Template" inherit_id="portal.portal_sidebar" primary="True">
|
||||
<xpath expr="//div[hasclass('o_portal_sidebar')]" position="inside">
|
||||
<t t-set="wrapwrap_classes" t-value="'o_portal_bg_dark'"/>
|
||||
|
||||
<t t-set="o_portal_fullwidth_alert" groups="sales_team.group_sale_salesman">
|
||||
<div t-ignore="true" class="text-center">
|
||||
This is a preview of the customer portal <i class="fa fa-chevron-right"/>
|
||||
<a t-att-href="'/web#return_label=Website&model=%s&id=%s&action=%s&view_type=form' % (sale_order._name, sale_order.id, sale_order.env.ref('sale.action_quotations').id)">
|
||||
<b>Back in edit mode</b>.
|
||||
</a>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> × </button>
|
||||
</t>
|
||||
|
||||
<div class="row mt16 o_portal_sale_sidebar">
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-3 d-print-none">
|
||||
<div class="bs-sidebar mb16">
|
||||
<div class="text-center pt16 o_account_portal_sidebar">
|
||||
<h2 class="media-heading">
|
||||
<strong>
|
||||
<span t-field="sale_order.amount_total"/>
|
||||
</strong>
|
||||
</h2>
|
||||
</div>
|
||||
<t t-if="sale_order.team_id.team_type != 'website'">
|
||||
<div class="text-center" t-if="sale_order.state in ('draft', 'sent', 'waiting_date')" style="padding: 10px">
|
||||
<t t-set="show_hr" t-value="False"/>
|
||||
<a role="button" t-if="not sale_order.is_expired and not sale_order.signature and sale_order.has_to_be_signed()" class="btn btn-primary btn-block" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"/> Accept
|
||||
<t t-set="show_hr" t-value="True"/>
|
||||
</a>
|
||||
<a role="button" t-elif="not sale_order.is_expired and sale_order.has_to_be_paid()" class="btn btn-primary btn-block" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"/> <t t-if="not sale_order.signature">Accept & </t>Pay
|
||||
<t t-set="show_hr" t-value="True"/>
|
||||
</a>
|
||||
<a role="button" t-if="sale_order.is_expired" href="#discussion" class="btn btn-info btn-block o_normalwhitespace">
|
||||
<strong>This offer expired!</strong><br/>
|
||||
Contact us for new quotation.
|
||||
<t t-set="show_hr" t-value="True"/>
|
||||
</a>
|
||||
<hr class="mb0" t-if="show_hr"/>
|
||||
</div>
|
||||
<div class="text-center" t-if="need_payment or (sale_order.state in ('sale') and sale_order.has_to_be_paid() and tx_state != 'done')" style="padding: 10px">
|
||||
<a role="button" class="btn btn-primary btn-block" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"></i> Pay Now
|
||||
</a>
|
||||
<hr class="mb0"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-call="portal.portal_record_sidebar">
|
||||
<t t-set="classes" t-value="'col-12 col-lg flex-lg-grow-0 d-print-none'"/>
|
||||
|
||||
<div class="navspy" t-ignore="true" role="complementary">
|
||||
<ul class="nav flex-column bs-sidenav" data-id="quote_sidebar"></ul>
|
||||
</div>
|
||||
<t t-set="title">
|
||||
<h2 class="mb-0"><b t-field="sale_order.amount_total"/> </h2>
|
||||
</t>
|
||||
|
||||
<div t-if="not sale_order.is_expired and sale_order.state in ['draft', 'sent']" class="pl-3 pr-3">
|
||||
<input type="hidden" t-att-value="sale_order.validity_date" id="validity_date"/>
|
||||
<div class="mt8" t-if="sale_order.remaining_validity_days > 0">
|
||||
<hr class="mb0"/>
|
||||
<strong>This offer expires in</strong>
|
||||
<div class="day_counter mt8 mb16">
|
||||
<i class="fa fa-clock-o" aria-title="Dates" title="Dates"></i>
|
||||
<t t-esc="sale_order.remaining_validity_days"/>
|
||||
<t t-if="sale_order.remaining_validity_days > 1">
|
||||
days
|
||||
<t t-set="entries">
|
||||
<ul class="list-group list-group-flush flex-wrap flex-row flex-lg-column">
|
||||
<li class="list-group-item flex-grow-1">
|
||||
<a role="button" class="btn btn-block btn-secondary" target="_blank" t-att-href="sale_order.get_portal_url(report_type='pdf')"><i class="fa fa-print mr-1"/>Print</a>
|
||||
|
||||
<t t-if="sale_order.state in ('draft', 'sent', 'waiting_date')">
|
||||
<t t-set="to_accept" t-value="not sale_order.is_expired and not sale_order.signature and sale_order.has_to_be_signed()"/>
|
||||
<t t-set="to_accept_and_pay" t-value="not sale_order.is_expired and sale_order.has_to_be_paid()"/>
|
||||
|
||||
<t t-if="to_accept or to_accept_and_pay or sale_order.is_expired">
|
||||
<a role="button" t-if="to_accept" class="btn btn-primary btn-block" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"/> Accept
|
||||
</a>
|
||||
<a role="button" t-elif="to_accept_and_pay" class="btn btn-success btn-block" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"/> <t t-if="not sale_order.signature">Accept & </t>Pay
|
||||
</a>
|
||||
<t t-if="sale_order.is_expired">
|
||||
<div class="alert alert-warning small mt-3 mb-1 py-1 px-2"><b class="d-block mb-1">This offer expired!</b>
|
||||
<a role="button" href="#discussion" class="btn btn-info btn-block py-1 o_normalwhitespace"> Get a new quotation.</a>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="sale_order.remaining_validity_days <= 1">
|
||||
day
|
||||
</t>
|
||||
|
||||
<t t-if="need_payment or (sale_order.state in ('sale') and sale_order.has_to_be_paid() and tx_state != 'done')">
|
||||
<a role="button" class="btn btn-success btn-block" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"></i> Pay Now
|
||||
</a>
|
||||
</t>
|
||||
</li>
|
||||
|
||||
<li class="navspy list-group-item pl-0 d-none d-lg-block" t-ignore="true" role="complementary">
|
||||
<ul class="nav flex-column bs-sidenav" data-id="quote_sidebar"></ul>
|
||||
</li>
|
||||
|
||||
<t t-if="not sale_order.is_expired and sale_order.state in ['draft', 'sent']">
|
||||
<input type="hidden" t-att-value="sale_order.validity_date" id="validity_date"/>
|
||||
<li t-if="sale_order.remaining_validity_days > 0" class="list-group-item">
|
||||
<small><b class="text-muted">This offer expires in</b></small>
|
||||
<div class="day_counter">
|
||||
<i class="fa fa-clock-o" aria-title="Dates" title="Dates"></i>
|
||||
<t t-esc="sale_order.remaining_validity_days"/>
|
||||
day<t t-if="sale_order.remaining_validity_days > 1">s</t>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li t-if="sale_order.amount_undiscounted > sale_order.amount_untaxed" class="list-group-item">
|
||||
<small><b class="text-muted">Your advantage</b></small>
|
||||
<t t-if="sale_order.amount_untaxed == sale_order.amount_total">
|
||||
<small>
|
||||
<b t-field="sale_order.amount_undiscounted"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
style="text-decoration: line-through"
|
||||
class="d-block mt-1"/>
|
||||
</small>
|
||||
<h4 t-field="sale_order.amount_total" class="text-success"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="sale_order.amount_untaxed != sale_order.amount_total">
|
||||
<small>
|
||||
<strong t-field="sale_order.amount_undiscounted"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
style="text-decoration: line-through"
|
||||
class="d-block mt-1"/>
|
||||
</small>
|
||||
<h4 t-field="sale_order.amount_untaxed" class="text-success mb-0"/>
|
||||
<small>(<span t-field="sale_order.amount_total"/> Incl. tax)</small>
|
||||
</t>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
|
||||
<div class="mb16" t-if="sale_order.amount_undiscounted > sale_order.amount_untaxed">
|
||||
<hr class="mb0"/>
|
||||
<p class="text-muted mb8">Your advantage:</p>
|
||||
<t t-if="sale_order.amount_untaxed == sale_order.amount_total">
|
||||
<strong t-field="sale_order.amount_total"/>
|
||||
<strong t-field="sale_order.amount_undiscounted"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
style="text-decoration: line-through"
|
||||
class="text-danger"/>
|
||||
</t>
|
||||
<t t-if="sale_order.amount_untaxed != sale_order.amount_total">
|
||||
<strong t-field="sale_order.amount_untaxed"/>
|
||||
<strong t-field="sale_order.amount_undiscounted"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
style="text-decoration: line-through"
|
||||
class="text-danger"/>
|
||||
<br />
|
||||
(<span t-field="sale_order.amount_total"/> Incl. tax)
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pb8 ml16 mr16" t-if="sale_order.user_id">
|
||||
<hr class="mb0"/>
|
||||
<div><strong>Your Contact:</strong></div>
|
||||
<div class="d-flex h-100">
|
||||
<div class="align-self-center">
|
||||
<img class="rounded-circle mr4 float-left o_portal_contact_img" t-if="sale_order.user_id.image" t-attf-src="data:image/png;base64,#{sale_order.user_id.image}" alt="Contact"/>
|
||||
<img class="rounded-circle mr4 float-left o_portal_contact_img" t-if="not sale_order.user_id.image" src="/web/static/src/img/placeholder.png" alt="Contact"/>
|
||||
<li t-if="sale_order.user_id" class="list-group-item flex-grow-1 o_portal_contact_block">
|
||||
<div class="small mb-1"><strong class="text-muted">Your Contact:</strong></div>
|
||||
<div class="row flex-nowrap">
|
||||
<div class="col flex-grow-0 pr-2">
|
||||
<img class="rounded-circle mr4 float-left o_portal_contact_img" t-if="sale_order.user_id.image" t-attf-src="data:image/png;base64,#{sale_order.user_id.image}" alt="Contact"/>
|
||||
<img class="rounded-circle mr4 float-left o_portal_contact_img" t-if="not sale_order.user_id.image" src="/web/static/src/img/placeholder.png" alt="Contact"/>
|
||||
</div>
|
||||
<div class="col pl-0" style="min-width: 150px">
|
||||
<span t-field="sale_order.user_id" t-options='{"widget": "contact", "fields": ["name", "phone"], "no_marker": True}'/>
|
||||
<a href="#discussion" class="small"><i class="fa fa-comment"></i> Send message</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<span t-field="sale_order.user_id" t-options='{"widget": "contact", "fields": ["name", "phone"], "no_marker": True}'/>
|
||||
<a href="#discussion"><i class="fa fa-comment"></i> Contact us</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center d-none d-md-block o_portal_brand">
|
||||
Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=portal">Odoo</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Page content -->
|
||||
<div id="quote_content" class="col-lg-9">
|
||||
<div id="quote_content" class="col-12 col-lg justify-content-end">
|
||||
|
||||
<div class="alert alert-success alert-dismissable" t-if="message==1" role="status">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">&times;</button>
|
||||
@@ -339,47 +335,43 @@
|
||||
<strong>This quotation has been canceled.</strong> Contact us to get a new quotation.
|
||||
</div>
|
||||
|
||||
<t t-call="sale.sale_order_portal_content"/>
|
||||
<div t-attf-class="card #{'pb-5' if report_type == 'html' else ''}">
|
||||
<div t-call="sale.sale_order_portal_content"/>
|
||||
</div>
|
||||
|
||||
<t t-if="sale_order.team_id.team_type != 'website'">
|
||||
<t t-if="sale_order.state in ('draft', 'sent', 'waiting_date')">
|
||||
<t t-set="to_accept" t-value="not sale_order.is_expired and not sale_order.signature and sale_order.has_to_be_signed()"/>
|
||||
<t t-set="to_accept_and_pay" t-value="not sale_order.is_expired and not sale_order.signature and sale_order.has_to_be_signed()"/>
|
||||
</t>
|
||||
<t t-set="to_pay" t-value="need_payment or (sale_order.state in ('sale') and sale_order.has_to_be_paid() and tx_state != 'done')"/>
|
||||
|
||||
<div class="row justify-content-center text-center d-print-none mt8 mb16" t-if="sale_order.state in ('draft', 'sent', 'waiting_date')">
|
||||
<t t-set="show_buttons" t-value="False"/>
|
||||
<div t-if="to_accept or to_accept_and_pay or to_pay" class="row justify-content-center text-center d-print-none pt-1 pb-4">
|
||||
<div class="col-sm-auto mt8">
|
||||
<a role="button" class="btn btn-primary" data-toggle="modal" data-target="#modalaccept" t-if="not sale_order.is_expired and not sale_order.signature and sale_order.has_to_be_signed()" href="#">
|
||||
<i class="fa fa-check"></i> Accept
|
||||
<t t-set="show_buttons" t-value="True"/>
|
||||
</a>
|
||||
<a role="button" class="btn btn-primary" data-toggle="modal" data-target="#modalaccept" t-elif="not sale_order.is_expired and sale_order.has_to_be_paid()" href="#">
|
||||
<i class="fa fa-check"/> <t t-if="not sale_order.signature">Accept & </t>Pay
|
||||
<t t-set="show_buttons" t-value="True"/>
|
||||
</a>
|
||||
<a t-if="to_accept" role="button" class="btn btn-primary" data-toggle="modal" data-target="#modalaccept" href="#"><i class="fa fa-check"/> Accept</a>
|
||||
<a t-elif="to_accept_and_pay" role="button" class="btn btn-primary" data-toggle="modal" data-target="#modalaccept" href="#"><i class="fa fa-check"/> <t t-if="not sale_order.signature">Accept & </t>Pay</a>
|
||||
</div>
|
||||
<div class="col-sm-auto mt8">
|
||||
<a role="button" class="btn btn-secondary" type="submit" href="#discussion" t-if="show_buttons">
|
||||
<i class="fa fa-comment"></i> Feedback
|
||||
</a>
|
||||
<t t-if="to_accept or to_accept_and_pay">
|
||||
<div class="col-sm-auto mt8">
|
||||
<a role="button" class="btn btn-info" type="submit" href="#discussion"><i class="fa fa-comment"/> Feedback</a>
|
||||
</div>
|
||||
<div class="col-sm-auto mt8">
|
||||
<a role="button" class="btn btn-warning" data-toggle="modal" data-target="#modaldecline" href="#"> <i class="fa fa-times"/> Reject</a>
|
||||
</div>
|
||||
</t>
|
||||
<div t-if="to_pay" class="col-sm-auto mt8">
|
||||
<a role="button" class="btn btn-success" data-toggle="modal" data-target="#modalaccept" href="#"><i class="fa fa-check"/> Pay Now</a>
|
||||
</div>
|
||||
<div class="col-sm-auto mt8">
|
||||
<a role="button" class="btn btn-danger" data-toggle="modal" data-target="#modaldecline" href="#" t-if="show_buttons">
|
||||
<i class="fa fa-times"></i> Reject
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center" t-if="need_payment or (sale_order.state in ('sale') and sale_order.has_to_be_paid() and tx_state != 'done')" style="padding: 10px">
|
||||
<a role="button" class="btn btn-primary" data-toggle="modal" data-target="#modalaccept" href="#">
|
||||
<i class="fa fa-check"></i> Pay Now
|
||||
</a>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div id="sale_order_communication">
|
||||
<h1 class="o_page_header">Communication</h1>
|
||||
<div id="sale_order_communication" class="mt-4">
|
||||
<h2>Communication</h2>
|
||||
<t t-call="portal.message_thread">
|
||||
<t t-set="object" t-value="sale_order"/>
|
||||
</t>
|
||||
</div>
|
||||
</div><!-- //col-lg-9 -->
|
||||
</div><!-- // #quote_content -->
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -391,252 +383,246 @@
|
||||
-->
|
||||
<template id="sale_order_portal_content" name="Sales Order Portal Content">
|
||||
<!-- Intro -->
|
||||
<div id="introduction" class="o_page_header mt16">
|
||||
<h1>
|
||||
<div id="introduction" t-attf-class="pb-2 pt-3 #{'card-header bg-white' if report_type == 'html' else ''}">
|
||||
<h2 class="my-0">
|
||||
<span t-field="sale_order.type_name"></span>
|
||||
<em t-esc="sale_order.name"/>
|
||||
<div t-ignore="true" class="float-md-right css_editable_mode_hidden d-print-none">
|
||||
<ul class="list-inline">
|
||||
<li groups="sales_team.group_sale_salesman" class="list-inline-item">
|
||||
<a role="button" class="btn btn-info" t-att-href="'/web#return_label=Website&model=%s&id=%s&action=%s&view_type=form' % (sale_order._name, sale_order.id, sale_order.env.ref('sale.action_quotations').id)">
|
||||
<t t-if="sale_order.state in ('draft', 'sent', 'cancel')">Edit Quotation</t>
|
||||
<t t-else="">Edit Sales Order</t>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<a role="button" class="btn btn-info" target="_blank" t-att-href="sale_order.get_portal_url(report_type='pdf')">Print</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</h1>
|
||||
</h2>
|
||||
</div>
|
||||
<!-- Informations -->
|
||||
<div id="informations">
|
||||
<div t-if="sale_order.transaction_ids and not invoices and sale_order.state in ('sent', 'sale') and portal_confirmation == 'pay' and not success and not error" t-att-data-order-id="sale_order.id">
|
||||
<t t-if="sale_order.transaction_ids">
|
||||
<t t-call="payment.payment_confirmation_status">
|
||||
<t t-set="payment_tx_id" t-value="sale_order.get_portal_last_transaction()"/>
|
||||
|
||||
<div t-attf-class="#{'card-body' if report_type == 'html' else ''}">
|
||||
<!-- Informations -->
|
||||
<div id="informations">
|
||||
<div t-if="sale_order.transaction_ids and not invoices and sale_order.state in ('sent', 'sale') and portal_confirmation == 'pay' and not success and not error" t-att-data-order-id="sale_order.id">
|
||||
<t t-if="sale_order.transaction_ids">
|
||||
<t t-call="payment.payment_confirmation_status">
|
||||
<t t-set="payment_tx_id" t-value="sale_order.get_portal_last_transaction()"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mb8">
|
||||
<strong>Date:</strong> <span t-field="sale_order.create_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class="mb8" t-if="sale_order.validity_date">
|
||||
<strong>Expiration Date:</strong> <span t-field="sale_order.validity_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="col-lg-6">
|
||||
<div>
|
||||
<strong>Invoicing Address</strong>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<strong>Date:</strong> <span t-field="sale_order.create_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class="mb-3" t-if="sale_order.validity_date">
|
||||
<strong>Expiration Date:</strong> <span t-field="sale_order.validity_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<strong class="d-block mb-1">Invoicing Address</strong>
|
||||
<address t-field="sale_order.partner_invoice_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="shipping_address" class="col-lg-6" groups="sale.group_delivery_invoice_address">
|
||||
<div>
|
||||
<strong>Shipping Address</strong>
|
||||
</div>
|
||||
<div>
|
||||
<div id="shipping_address" class="col-lg-6" groups="sale.group_delivery_invoice_address">
|
||||
<strong class="d-block mb-1">Shipping Address</strong>
|
||||
<address t-field="sale_order.partner_shipping_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<t t-set="invoices" t-value="[i for i in sale_order.invoice_ids if i.state not in ['draft', 'cancel']]"/>
|
||||
<t t-if="invoices">
|
||||
<div>
|
||||
<strong>Invoices</strong>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<t t-set="invoices" t-value="[i for i in sale_order.invoice_ids if i.state not in ['draft', 'cancel']]"/>
|
||||
<div t-if="invoices" class="row">
|
||||
<div class="col">
|
||||
<strong class="d-block mb-1">Invoices</strong>
|
||||
<ul class="list-group mb-4">
|
||||
<t t-foreach="invoices" t-as="i">
|
||||
<t t-set="report_url" t-value="i.get_portal_url(report_type='pdf', download=True)"/>
|
||||
<div>
|
||||
<a t-att-href="report_url"><span class="fa fa-download" role="img" aria-label="Download" title="Download"/></a>
|
||||
<a t-att-href="report_url"><span t-esc="i.number"/></a>
|
||||
<span class="text-muted" t-field="i.date_invoice"/>
|
||||
<t t-if="i.state == 'paid'">
|
||||
<span class="badge badge-success orders_label_text_align"><i class="fa fa-fw fa-check"/> Paid</span>
|
||||
</t>
|
||||
<t t-if="i.state != 'paid'">
|
||||
<span class="badge badge-info orders_label_text_align"><i class="fa fa-fw fa-clock-o"/> Waiting Payment</span>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section id="details" style="page-break-inside: auto;">
|
||||
<h1 class="o_page_header" id="details">Details</h1>
|
||||
|
||||
<t t-set="display_discount" t-value="True in [line.discount > 0 for line in sale_order.order_line]"/>
|
||||
|
||||
<table class="table" id="sales_order_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<t t-set="colspan" t-value="7"/>
|
||||
<th class="d-none d-xl-table-cell"></th>
|
||||
<th class="text-left">Products</th>
|
||||
<th class="text-left">Quantity</th>
|
||||
<th t-attf-class="text-right {{ 'd-none d-sm-table-cell' if report_type == 'html' else '' }}">Unit Price</th>
|
||||
<th t-if="display_discount" class="text-right">
|
||||
<span>Discount</span>
|
||||
<t t-set="colspan" t-value="colspan+1"/>
|
||||
</th>
|
||||
<th t-attf-class="text-left {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">Taxes</th>
|
||||
<th class="text-right" >
|
||||
<span groups="account.group_show_line_subtotals_tax_excluded">Amount</span>
|
||||
<span groups="account.group_show_line_subtotals_tax_included">Total Price</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="sale_tbody">
|
||||
|
||||
<t t-set="current_subtotal" t-value="0"/>
|
||||
|
||||
<t t-foreach="sale_order.order_line" t-as="line">
|
||||
|
||||
<t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
|
||||
<t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
|
||||
|
||||
<tr t-attf-class="{{ 'o_is_' + line.display_type if line.display_type else '' }}">
|
||||
<t t-if="not line.display_type">
|
||||
<td class="text-center d-none d-xl-table-cell">
|
||||
<a class="list-group-item list-group-item-action d-flex flex-wrap align-items-center justify-content-between py-2 px-3" t-att-href="report_url">
|
||||
<div>
|
||||
<span t-field="line.product_image" t-options="{'widget': 'image', 'class': 'rounded', 'style':'width: 48px;height:48px'}" />
|
||||
<i class="fa fa-download mr-1" role="img" aria-label="Download" title="Download"/>
|
||||
<span t-esc="i.number" class="mr-lg-3"/>
|
||||
<div class="small d-lg-inline-block">Date: <span class="text-muted" t-field="i.date_invoice"/></div>
|
||||
</div>
|
||||
</td>
|
||||
<td id="product_name"><span t-field="line.name"/></td>
|
||||
<td>
|
||||
<div id="quote_qty">
|
||||
<span t-field="line.product_uom_qty"/>
|
||||
<span t-field="line.product_uom" groups="uom.group_uom"/>
|
||||
<span t-if="i.state == 'paid'" class="small text-success orders_label_text_align"><i class="fa fa-fw fa-check"/> <b>Paid</b></span>
|
||||
<span t-else="" class="small text-info orders_label_text_align"><i class="fa fa-fw fa-clock-o"/> <b>Waiting Payment</b></span>
|
||||
</a>
|
||||
</t>
|
||||
</ul>
|
||||
<t t-if="invoices2">
|
||||
<strong class="text-muted d-block mb-1">Invoices</strong>
|
||||
<div>
|
||||
<t t-foreach="invoices" t-as="i">
|
||||
<t t-set="report_url" t-value="i.get_portal_url(report_type='pdf', download=True)"/>
|
||||
<div>
|
||||
<a t-att-href="report_url"><span class="fa fa-download" role="img" aria-label="Download" title="Download"/></a>
|
||||
<a t-att-href="report_url"><span t-esc="i.number"/></a>
|
||||
<span class="text-muted" t-field="i.date_invoice"/>
|
||||
<t t-if="i.state == 'paid'">
|
||||
<span class="badge badge-success orders_label_text_align"><i class="fa fa-fw fa-check"/> Paid</span>
|
||||
</t>
|
||||
<t t-if="i.state != 'paid'">
|
||||
<span class="badge badge-info orders_label_text_align"><i class="fa fa-fw fa-clock-o"/> Waiting Payment</span>
|
||||
</t>
|
||||
</div>
|
||||
</td>
|
||||
<td t-attf-class="text-right {{ 'd-none d-sm-table-cell' if report_type == 'html' else '' }}">
|
||||
<div
|
||||
t-field="line.price_unit"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
t-att-style="line.discount and 'text-decoration: line-through' or None"
|
||||
t-att-class="(line.discount and 'text-danger' or '') + ' text-right'"
|
||||
/>
|
||||
<div t-if="line.discount">
|
||||
<t t-esc="(1-line.discount / 100.0) * line.price_unit" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</div>
|
||||
</td>
|
||||
<td t-if="display_discount">
|
||||
<strong t-if="line.discount" class="text-info text-right">
|
||||
<t t-esc="((line.discount % 1) and '%s' or '%d') % line.discount"/>% discount
|
||||
</strong>
|
||||
</td>
|
||||
<td t-attf-class="text-left {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">
|
||||
<span t-esc="', '.join(map(lambda x: (x.description or x.name), line.tax_id))"/>
|
||||
</td>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section id="details" style="page-break-inside: auto;">
|
||||
<h3 id="details">Details</h3>
|
||||
|
||||
<t t-set="display_discount" t-value="True in [line.discount > 0 for line in sale_order.order_line]"/>
|
||||
|
||||
<table class="table table-sm" id="sales_order_table">
|
||||
<thead class="bg-100">
|
||||
<tr>
|
||||
<t t-set="colspan" t-value="7"/>
|
||||
<th class="d-none d-xl-table-cell"></th>
|
||||
<th class="text-left">Products</th>
|
||||
<th class="text-right">Quantity</th>
|
||||
<th t-attf-class="text-right {{ 'd-none d-sm-table-cell' if report_type == 'html' else '' }}">Unit Price</th>
|
||||
<th t-if="display_discount" class="text-left">
|
||||
<span>Discount</span>
|
||||
<t t-set="colspan" t-value="colspan+1"/>
|
||||
</th>
|
||||
<th t-attf-class="text-right {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">Taxes</th>
|
||||
<th class="text-right" >
|
||||
<span groups="account.group_show_line_subtotals_tax_excluded">Amount</span>
|
||||
<span groups="account.group_show_line_subtotals_tax_included">Total Price</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="sale_tbody">
|
||||
|
||||
<t t-set="current_subtotal" t-value="0"/>
|
||||
|
||||
<t t-foreach="sale_order.order_line" t-as="line">
|
||||
|
||||
<t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
|
||||
<t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
|
||||
|
||||
<tr t-attf-class="{{ 'o_is_' + line.display_type if line.display_type else '' }}">
|
||||
<t t-if="not line.display_type">
|
||||
<td class="text-center d-none d-xl-table-cell" style="height:48px; vertical-align: middle">
|
||||
<span t-field="line.product_image" t-options="{'widget': 'image', 'class': 'rounded', 'style':'max-width: 48px;max-height:48px'}" />
|
||||
</td>
|
||||
<td id="product_name"><span t-field="line.name"/></td>
|
||||
<td class="text-right">
|
||||
<div id="quote_qty">
|
||||
<span t-field="line.product_uom_qty"/>
|
||||
<span t-field="line.product_uom" groups="uom.group_uom"/>
|
||||
</div>
|
||||
</td>
|
||||
<td t-attf-class="text-right {{ 'd-none d-sm-table-cell' if report_type == 'html' else '' }}">
|
||||
<div
|
||||
t-field="line.price_unit"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
t-att-style="line.discount and 'text-decoration: line-through' or None"
|
||||
t-att-class="(line.discount and 'text-danger' or '') + ' text-right'"
|
||||
/>
|
||||
<div t-if="line.discount">
|
||||
<t t-esc="(1-line.discount / 100.0) * line.price_unit" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</div>
|
||||
</td>
|
||||
<td t-if="display_discount" class="text-left">
|
||||
<strong t-if="line.discount" class="text-info">
|
||||
<t t-esc="((line.discount % 1) and '%s' or '%d') % line.discount"/>% discount
|
||||
</strong>
|
||||
</td>
|
||||
<td t-attf-class="text-right {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">
|
||||
<span t-esc="', '.join(map(lambda x: (x.description or x.name), line.tax_id))"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
|
||||
<span t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-if="line.display_type == 'line_section'">
|
||||
<td t-att-colspan="colspan">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
<t t-set="current_section" t-value="line"/>
|
||||
<t t-set="current_subtotal" t-value="0"/>
|
||||
</t>
|
||||
<t t-if="line.display_type == 'line_note'">
|
||||
<td t-att-colspan="colspan">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
|
||||
<t t-if="current_section and (line_last or sale_order.order_line[line_index+1].display_type == 'line_section')">
|
||||
<tr class="is-subtotal text-right">
|
||||
<td t-att-colspan="colspan">
|
||||
<strong class="mr16">Subtotal</strong>
|
||||
<span
|
||||
t-esc="current_subtotal"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="total" class="row" name="total" style="page-break-inside: avoid;">
|
||||
<div t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto">
|
||||
<table class="table table-sm">
|
||||
<tr class="border-black" style="border-bottom:1px solid #dddddd;">
|
||||
<td><strong>Subtotal</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
|
||||
<span t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-if="line.display_type == 'line_section'">
|
||||
<td t-att-colspan="colspan">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
<t t-set="current_section" t-value="line"/>
|
||||
<t t-set="current_subtotal" t-value="0"/>
|
||||
</t>
|
||||
<t t-if="line.display_type == 'line_note'">
|
||||
<td t-att-colspan="colspan">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
|
||||
<t t-if="current_section and (line_last or sale_order.order_line[line_index+1].display_type == 'line_section')">
|
||||
<tr class="is-subtotal text-right">
|
||||
<td t-att-colspan="colspan">
|
||||
<strong class="mr16">Subtotal</strong>
|
||||
<span
|
||||
t-esc="current_subtotal"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
|
||||
data-id="total_amount"
|
||||
t-field="sale_order.amount_untaxed"
|
||||
t-options='{"widget": "monetary","display_currency": sale_order.pricelist_id.currency_id}'
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="total" class="row" name="total" style="page-break-inside: avoid;">
|
||||
<div t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto">
|
||||
<table class="table table-sm">
|
||||
<tr class="border-black" style="border-bottom:1px solid #dddddd;">
|
||||
<td><strong>Subtotal</strong></td>
|
||||
<td class="text-right">
|
||||
<span
|
||||
data-id="total_amount"
|
||||
t-field="sale_order.amount_untaxed"
|
||||
t-options='{"widget": "monetary","display_currency": sale_order.pricelist_id.currency_id}'
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-foreach="sale_order.amount_by_group" t-as="amount_by_group">
|
||||
<tr style="border-bottom:1px solid #dddddd;">
|
||||
<t t-if="amount_by_group[3] == 1 and sale_order.amount_untaxed == amount_by_group[2]">
|
||||
<td>
|
||||
<span t-esc="amount_by_group[0]"/>
|
||||
<span>&nbsp;<span>on</span>&nbsp;<t t-esc="amount_by_group[2]" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/></span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-esc="amount_by_group[1]"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else ="">
|
||||
<td>
|
||||
<span t-esc="amount_by_group[0]"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-esc="amount_by_group[1]"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-foreach="sale_order.amount_by_group" t-as="amount_by_group">
|
||||
<tr style="border-bottom:1px solid #dddddd;">
|
||||
<t t-if="amount_by_group[3] == 1 and sale_order.amount_untaxed == amount_by_group[2]">
|
||||
<td>
|
||||
<span t-esc="amount_by_group[0]"/>
|
||||
<span>&nbsp;<span>on</span>&nbsp;<t t-esc="amount_by_group[2]" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/></span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-esc="amount_by_group[1]"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else ="">
|
||||
<td>
|
||||
<span t-esc="amount_by_group[0]"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-esc="amount_by_group[1]"
|
||||
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
<tr class="border-black">
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span data-id="total_amount" t-field="sale_order.amount_total" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr class="border-black">
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span data-id="total_amount" t-field="sale_order.amount_total" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="terms" class="container" t-if="sale_order.note">
|
||||
<h2 class="o_page_header">Terms & Conditions</h2>
|
||||
<p t-field="sale_order.note"/>
|
||||
</section>
|
||||
|
||||
<section t-if="sale_order.signature" id="signature" name="Signature">
|
||||
<div class="row mt64" name="signature">
|
||||
<div class="offset-8 col-4">
|
||||
<strong>Signature</strong>
|
||||
</div>
|
||||
<div class="offset-8 col-4">
|
||||
<img t-att-src="'data:image/png;base64,%s' % to_text(sale_order.signature)" style="max-height: 4cm; max-width: 8cm;"/>
|
||||
</div>
|
||||
<div class="offset-8 col-4 text-center">
|
||||
<p t-field="sale_order.signed_by"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section t-if="sale_order.signature" id="signature" name="Signature">
|
||||
<div class="row mt-4" name="signature">
|
||||
<div class="offset-8 col-4">
|
||||
<strong>Signature</strong>
|
||||
</div>
|
||||
<div class="offset-8 col-4">
|
||||
<img t-att-src="'data:image/png;base64,%s' % to_text(sale_order.signature)" style="max-height: 4cm; max-width: 8cm;"/>
|
||||
</div>
|
||||
<div class="offset-8 col-4 text-center">
|
||||
<p t-field="sale_order.signed_by"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="terms" class="mt-5" t-if="sale_order.note">
|
||||
<h3 class="">Terms & Conditions</h3>
|
||||
<hr class="mt-0 mb-1"/>
|
||||
<em t-field="sale_order.note"/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
<xpath expr="//section[@id='signature']" position="after">
|
||||
<t t-if="any([(not option.line_id) for option in sale_order.sale_order_option_ids])">
|
||||
<section>
|
||||
<h1 class="o_page_header">Optional Products</h1>
|
||||
<h3>Optional Products</h3>
|
||||
<t t-set="display_discount" t-value="True in [option.discount for option in sale_order.sale_order_option_ids]"/>
|
||||
<table class="table table-hover">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left">Product</th>
|
||||
|
||||
+288
-245
@@ -185,9 +185,9 @@
|
||||
<script type="text/javascript" src="/website_crm_partner_assign/static/src/js/crm_partner_assign.js" />
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="portal_my_home_menu_lead" name="Portal layout : lead menu entry" inherit_id="portal.portal_layout" priority="15">
|
||||
<template id="portal_my_home_menu_lead" name="Portal layout : lead menu entry" inherit_id="portal.portal_breadcrumbs" priority="15">
|
||||
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
|
||||
<li t-if="page_name == 'lead' or lead" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'lead' or lead" t-attf-class="breadcrumb-item #{'active ' if not lead else ''}">
|
||||
<a t-if="lead" t-attf-href="/my/leads?{{ keep_query() }}">
|
||||
My Leads
|
||||
</a>
|
||||
@@ -195,10 +195,10 @@
|
||||
My Leads
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="lead" class="breadcrumb-item">
|
||||
<li t-if="lead" class="breadcrumb-item active">
|
||||
<span t-field="lead.name"/>
|
||||
</li>
|
||||
<li t-if="page_name == 'opportunity' or opportunity" class="breadcrumb-item">
|
||||
<li t-if="page_name == 'opportunity' or opportunity" t-attf-class="breadcrumb-item #{'active ' if not opportunity else ''}">
|
||||
<a t-if="opportunity" t-attf-href="/my/opportunities?{{ keep_query() }}">
|
||||
My Opportunities
|
||||
</a>
|
||||
@@ -206,22 +206,24 @@
|
||||
My Opportunities
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="opportunity" class="breadcrumb-item">
|
||||
<li t-if="opportunity" class="breadcrumb-item active">
|
||||
<span t-field="opportunity.name"/>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_home_lead" name="Portal My Home : lead entries" inherit_id="portal.portal_my_home" priority="15">
|
||||
<xpath expr="//ul[hasclass('o_portal_docs')]" position="inside">
|
||||
<li t-if="lead_count" class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="lead_count"/>
|
||||
<a href="/my/leads">My Leads</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span class="badge badge-secondary badge-pill float-right" t-esc="opp_count"/>
|
||||
<a href="/my/opportunities">My Opportunities</a>
|
||||
</li>
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
|
||||
<t t-if="lead_count" t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">My Leads</t>
|
||||
<t t-set="url" t-value="'/my/leads'"/>
|
||||
<t t-set="count" t-value="lead_count"/>
|
||||
</t>
|
||||
<t t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">My Opportunities</t>
|
||||
<t t-set="url" t-value="'/my/opportunities'"/>
|
||||
<t t-set="count" t-value="opp_count"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
@@ -233,38 +235,41 @@
|
||||
<div t-if="not leads" class="alert alert-warning mt8" role="alert">
|
||||
There are no leads.
|
||||
</div>
|
||||
<div t-if="leads" class="card">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th class="col-2">Date</th>
|
||||
<th class="col-5">Name</th>
|
||||
<th>Contact Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="leads" t-as="lead">
|
||||
<td><span t-field="lead.create_date" t-options='{"widget": "date"}' /></td>
|
||||
<td>
|
||||
<a t-attf-href="/my/lead/#{lead.id}"><span t-field="lead.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="lead.contact_name" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
<t t-if="leads" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th class="w-75">Name</th>
|
||||
<th>Contact Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="leads" t-as="lead">
|
||||
<td><span t-field="lead.create_date" t-options='{"widget": "date"}' /></td>
|
||||
<td>
|
||||
<a t-attf-href="/my/lead/#{lead.id}"><span t-field="lead.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="lead.contact_name" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_opportunities" name="My Opportunities">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">My Opportunities</t>
|
||||
<li class="float-left"><button t-if="request.env.user.partner_id.grade_id or request.env.user.commercial_partner_id.grade_id" name='new_opp' data-toggle="modal" data-target=".modal_new_opp" class="btn btn-secondary navbar-btn ml16" title="Add an opportunity" aria-label="Add an opportunity"><i class="fa fa-plus"/></button></li>
|
||||
|
||||
<div class="form-inline ml-lg-4" t-if="request.env.user.partner_id.grade_id or request.env.user.commercial_partner_id.grade_id">
|
||||
<button class="btn btn-success btn-sm" name='new_opp' data-toggle="modal" data-target=".modal_new_opp" title="Add an opportunity" aria-label="Add an opportunity">
|
||||
<i class="fa fa-plus"/> Create New
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="modal fade modal_new_opp" role="form">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" class="modal-content js_website_submit_form new_opp_form">
|
||||
@@ -299,37 +304,32 @@
|
||||
There are no opportunities.
|
||||
</div>
|
||||
</t>
|
||||
<div class="card" t-if="opportunities">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th class="col-2">Date</th>
|
||||
<th class="col-lg-4">Name</th>
|
||||
<th class="col-lg-2">Expected</th>
|
||||
<th>Contact Name</th>
|
||||
<th>Stage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="opportunities" t-as="opp">
|
||||
<td><span t-field="opp.create_date" t-options='{"widget": "date"}' /></td>
|
||||
<td>
|
||||
<a t-attf-href="/my/opportunity/#{opp.id}"><span t-field="opp.name"/></a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-nowrap" t-esc="opp.planned_revenue" t-options="{'widget': 'monetary', 'display_currency': opp.company_currency}"/> at <span t-field="opp.probability" />%
|
||||
</td>
|
||||
<td><span t-field="opp.contact_name" /></td>
|
||||
<td>
|
||||
<span class="badge badge-primary" title="Current stage of the opportunity" t-esc="opp.stage_id.name" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
<t t-if="opportunities" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Date</th>
|
||||
<th class="w-50">Name</th>
|
||||
<th>Contact</th>
|
||||
<th>Expected</th>
|
||||
<th>Stage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="opportunities" t-as="opp">
|
||||
<td><span t-field="opp.create_date" t-options='{"widget": "date"}' /></td>
|
||||
<td>
|
||||
<a t-attf-href="/my/opportunity/#{opp.id}"><span t-field="opp.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="opp.contact_name" /></td>
|
||||
<td>
|
||||
<span class="text-nowrap" t-esc="opp.planned_revenue" t-options="{'widget': 'monetary', 'display_currency': opp.company_currency}"/> at <span t-field="opp.probability" />%
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-info badge-pill" title="Current stage of the opportunity" t-esc="opp.stage_id.name" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
@@ -501,42 +501,224 @@
|
||||
|
||||
<template id="portal_my_opportunity" name="My Opportunity">
|
||||
<t t-call="portal.portal_layout">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h4 style="display:inline-block">
|
||||
Opportunity - <span t-field="opportunity.name"/>
|
||||
</h4>
|
||||
<span class="btn-group float-right" role="group">
|
||||
<t t-foreach="stages" t-as="stage">
|
||||
<button type="button" t-att-data="stage.id" t-att-opp="opportunity.id" t-attf-class="float-right btn opp-stage-button #{'btn-secondary' if opportunity.stage_id.name != stage.name else 'disabled btn-primary'}">
|
||||
<t t-set="wrapwrap_classes" t-value="'o_portal_bg_dark'"/>
|
||||
<t t-call="portal.portal_record_layout">
|
||||
<t t-set="card_header">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-md">
|
||||
<h5 class="mb-2 mb-md-0">
|
||||
<small class="text-muted">Opportunity - </small>
|
||||
<span t-field="opportunity.name"/>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-md text-md-right">
|
||||
<div class="d-inline-block">
|
||||
<small class="mr-2"><b>Stage:</b></small>
|
||||
<div t-foreach="stages" t-as="stage" class="float-right">
|
||||
<button type="button" t-att-data="stage.id" t-att-opp="opportunity.id" t-attf-class="btn btn-sm px-2 opp-stage-button #{'btn-secondary' if opportunity.stage_id.name != stage.name else 'btn-primary disabled'}">
|
||||
<span t-field="stage.name"/>
|
||||
</button>
|
||||
</t>
|
||||
</span>
|
||||
<i t-if="not stage_first" class="fa fa-chevron-right ml-1 mr-2 small" style="opacity: 0.5"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-set="card_body">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<strong><span class="text-nowrap" t-esc="opportunity.planned_revenue" t-options="{'widget': 'monetary', 'display_currency': opportunity.company_currency}"/> at <span t-field="opportunity.probability"/>%</strong>
|
||||
<div class="col-lg-5 mb-4 mb-lg-0">
|
||||
<div class="border-bottom d-flex justify-content-between py-2 mb-3 align-items-center">
|
||||
<h5 class="mb-0">
|
||||
<span class="text-nowrap" t-esc="opportunity.planned_revenue" t-options="{'widget': 'monetary', 'display_currency': opportunity.company_currency}"/> at
|
||||
<span class="badge badge-info badge-pill"><span t-field="opportunity.probability"/>%</span>
|
||||
</h5>
|
||||
<button type="button" data-toggle="modal" data-target=".modal_edit_opp" class="btn btn-link btn-sm"><i class="fa fa-pencil mr-1"/>Edit</button>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<strong class="col-12 col-sm-4">Deadline</strong>
|
||||
<div class="col">
|
||||
<span t-if="opportunity.date_deadline" t-field="opportunity.date_deadline"/>
|
||||
<span t-else="" class="text-muted"> - </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<strong class="col-12 col-sm-4">Priority</strong>
|
||||
<div class="col">
|
||||
<span class="" title="Rating" role="img" t-attf-aria-label="Rating: #{opportunity.priority} on 4">
|
||||
<t t-foreach="range(1, 4)" t-as="i">
|
||||
<span t-attf-class="fa text-warning fa-lg fa-star#{'' if i <= int(opportunity.priority) else '-o'}" role="img" t-att-aria-label="'Star %d of 3' % i"/>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<strong class="col-12 col-sm-4">Next Activity</strong>
|
||||
<div class="col" t-if="user_activity">
|
||||
<span t-field="user_activity.activity_type_id"/>
|
||||
<span t-if="user_activity.date_deadline"> on </span>
|
||||
<span t-field="user_activity.date_deadline"/>
|
||||
<em class="d-block" t-field="user_activity.summary"/>
|
||||
</div>
|
||||
<div class="col" t-else="">
|
||||
<span class="text-muted"> - </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<strong>Expected Closing: <span t-field="opportunity.date_deadline" /></strong>
|
||||
|
||||
<div class="col-lg-6 offset-lg-1 col-xl-5 offset-xl-2">
|
||||
<div class="d-flex justify-content-between py-2 mb-3 border-bottom align-items-center">
|
||||
<h5 class="card-title mb-0">Contact</h5>
|
||||
<button type="button" data-toggle="modal" data-target=".modal_edit_contact" class="btn btn-link btn-sm"><i class="fa fa-pencil mr-1"/>Edit</button>
|
||||
</div>
|
||||
<div class="row mb-3" t-if="opportunity.partner_name or opportunity.email_from or opportunity.contact_name">
|
||||
<strong class="col-12 col-sm-3">Customer</strong>
|
||||
<div class="col">
|
||||
<div>
|
||||
<span class="fa fa-user fa-fw" role="img" aria-label="User" title="User"/>
|
||||
<strong class="font-italic" t-if="opportunity.partner_name" itemprop="name" t-field="opportunity.partner_name" />
|
||||
<strong class="font-italic" t-else="" itemprop="name" t-field="opportunity.contact_name" />
|
||||
</div>
|
||||
<div>
|
||||
<span class="fa fa-phone fa-fw" role="img" aria-label="Phone" title="Phone"/>
|
||||
<span t-if="opportunity.phone" itemprop="telephone" t-field="opportunity.phone"/>
|
||||
<span t-else="" class="text-muted"> - </span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="fa fa-mobile fa-fw" role="img" aria-label="Mobile" title="Mobile"/>
|
||||
<span t-if="opportunity.mobile" itemprop="mobile" t-field="opportunity.mobile"/>
|
||||
<span t-else="" class="text-muted"> - </span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="fa fa-envelope fa-fw" role="img" aria-label="Email" title="Email"/>
|
||||
<span t-if="opportunity.email_from" itemprop="email" t-field="opportunity.email_from"/>
|
||||
<span t-else="" class="text-muted"> - </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<strong class="col-12 col-sm-3">Address</strong>
|
||||
<address class="col d-flex align-items-baseline mb-0">
|
||||
<span class="fa fa-map-marker fa-fw" role="img" aria-label="Address" title="Address"/>
|
||||
<div>
|
||||
<div t-if="opportunity.street"><span t-field="opportunity.street"/></div>
|
||||
<span t-else="" class="text-muted"> - </span>
|
||||
<div t-if="opportunity.street2"><span t-field="opportunity.street2"/></div>
|
||||
<div t-if="opportunity.city or opportunity.zip">
|
||||
<span t-field="opportunity.city"/> <span t-field="opportunity.zip"/>
|
||||
</div>
|
||||
<div t-if="opportunity.state_id or country_id">
|
||||
<span t-field="opportunity.state_id"/> <span t-field="opportunity.country_id"/>
|
||||
</div>
|
||||
</div>
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<span class="float-right" title="Rating" role="img" t-attf-aria-label="Rating: #{opportunity.priority} on 4">
|
||||
<t t-foreach="range(1, 4)" t-as="i">
|
||||
<span t-attf-class="fa fa-lg fa-star#{'' if i <= int(opportunity.priority) else '-o'}" role="img" t-att-aria-label="'Star %d of 3' % i"/>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="col-lg-6">
|
||||
|
||||
<!-- ==== MODALS ==== -->
|
||||
<div>
|
||||
<button type="button" data-toggle="modal" data-target=".modal_edit_contact" class="btn btn-primary" style="margin-bottom: 10px;">Edit Contact</button>
|
||||
<div role="dialog" class="modal fade modal_edit_opp">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" class="js_accept_json modal-content js_website_submit_form edit_opp_form">
|
||||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||||
<input type="hidden" name="opportunity_id" class="opportunity_id" t-att-value="opportunity.id"/>
|
||||
<header class="modal-header">
|
||||
<h4 class="modal-title">Edit Opportunity</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">&times;</button>
|
||||
</header>
|
||||
<main class="modal-body" id="sign-dialog">
|
||||
<div class="form-group">
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-auto flex-grow-1">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text"><span class="text-nowrap" t-esc="opportunity.company_currency.symbol"/></div>
|
||||
</div>
|
||||
<input type="text" name="planned_revenue" class="form-control planned_revenue" t-att-value="opportunity.planned_revenue" placeholder="Planned Revenue"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">at</div>
|
||||
<div class="col-auto">
|
||||
<div class="input-group">
|
||||
<input type="text" name="probability" class="form-control probability" t-att-value="opportunity.probability" placeholder="Probability"/>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label>Priority:</label>
|
||||
<div class="input-group">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="PriorityRadioOptions" value="0" t-att-checked="opportunity.priority not in ['1','2','3']" aria-label="Rating: 0 on 3" title="Rating: 0 on 3"/>
|
||||
<i class="ml-1 fa fa-star-o"></i>
|
||||
</label>
|
||||
<label class="radio-inline ml-2">
|
||||
<input type="radio" name="PriorityRadioOptions" value="1" t-att-checked="opportunity.priority == '1'" aria-label="Rating: 1 on 3" title="Rating: 1 on 3"/>
|
||||
<i class="ml-1 fa text-warning fa-star"></i>
|
||||
</label>
|
||||
<label class="radio-inline ml-2">
|
||||
<input type="radio" name="PriorityRadioOptions" value="2" t-att-checked="opportunity.priority == '2'" aria-label="Rating: 2 on 3" title="Rating: 2 on 3"/>
|
||||
<i class="ml-1 fa text-warning fa-star"></i>
|
||||
<i class="ml-1 fa text-warning fa-star"></i>
|
||||
</label>
|
||||
<label class="radio-inline ml-2">
|
||||
<input type="radio" name="PriorityRadioOptions" value="3" t-att-checked="opportunity.priority == '3'" aria-label="Rating: 3 on 3" title="Rating: 3 on 3"/>
|
||||
<i class="ml-1 fa text-warning fa-star"></i>
|
||||
<i class="ml-1 fa text-warning fa-star"></i>
|
||||
<i class="ml-1 fa text-warning fa-star"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label>Deadline:</label>
|
||||
<div class="input-group date">
|
||||
<input type="text" name="date_deadline" t-att-value="opportunity.date_deadline" class="form-control date_deadline" data-date-format="YYYY-MM-DD" t-att-name="prefix" placeholder="YYYY-MM-DD"/>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<span class="fa fa-calendar" role="img" aria-label="Calendar"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="next_activity">Next Activity</label>
|
||||
<select class="form-control next_activity" name="next_activity">
|
||||
<t t-foreach="activity_types" t-as="activity_type">
|
||||
<option t-att-data="activity_type.id" t-att-selected="activity_type.id == user_activity.activity_type_id.id" t-att-name="activity_type.name" t-att-summary="activity_type.summary"><t t-esc="activity_type.name"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="activity_summary">Details Next Activity</label>
|
||||
<textarea row="3" name="activity_summary" class="form-control activity_summary"><t t-esc="user_activity.summary"/></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="activity_date_deadline">Next Activity Date</label>
|
||||
<div class="input-group date">
|
||||
<input type="text" name="activity_date_deadline" t-att-value="user_activity.date_deadline" class="form-control activity_date_deadline" data-date-format="YYYY-MM-DD" t-att-name="prefix" placeholder="YYYY-MM-DD"/>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<span class="fa fa-calendar" role="img" aria-label="Calendar" title="Calendar"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="modal-footer">
|
||||
<button t-attf-class="btn btn-primary edit_opp_confirm">Confirm</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="dialog" class="modal fade modal_edit_contact">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" class="js_accept_json modal-content js_website_submit_form edit_contact_form">
|
||||
@@ -588,7 +770,7 @@
|
||||
<option>States...</option>
|
||||
<t t-foreach="states or []" t-as="state">
|
||||
<option class="state" t-att-value="state.id" t-att-country="state.country_id.id" t-att-selected="state.id == opportunity.state_id.id">
|
||||
<t t-esc="state.name" />
|
||||
<t t-esc="state.name"/>
|
||||
</option>
|
||||
</t>
|
||||
</select>
|
||||
@@ -603,7 +785,7 @@
|
||||
<option>Countries...</option>
|
||||
<t t-foreach="countries or []" t-as="country">
|
||||
<option t-att-value="country.id" t-att-selected="country.id == opportunity.country_id.id">
|
||||
<t t-esc="country.name" />
|
||||
<t t-esc="country.name"/>
|
||||
</option>
|
||||
</t>
|
||||
</select>
|
||||
@@ -617,153 +799,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" t-if="opportunity.partner_name or opportunity.email_from or opportunity.contact_name">
|
||||
<label class="col-4">Customer</label>
|
||||
<address class="col-8">
|
||||
<div>
|
||||
<span t-if="opportunity.partner_name" itemprop="name" t-field="opportunity.partner_name" />
|
||||
<span t-if="not opportunity.partner_name" itemprop="name" t-field="opportunity.contact_name" />
|
||||
</div>
|
||||
<div t-if="opportunity.phone">
|
||||
<span class="fa fa-phone" role="img" aria-label="Phone" title="Phone"/> <span itemprop="telephone" t-field="opportunity.phone" />
|
||||
</div>
|
||||
<div t-if="opportunity.mobile">
|
||||
<span class="fa fa-mobile" role="img" aria-label="Mobile" title="Mobile"/> <span itemprop="mobile" t-field="opportunity.mobile" />
|
||||
</div>
|
||||
<div t-if="opportunity.email_from">
|
||||
<span class="fa fa-envelope" role="img" aria-label="Email" title="Email"/> <span itemprop="email" t-field="opportunity.email_from" />
|
||||
</div>
|
||||
</address>
|
||||
</div>
|
||||
<div class="row" t-if="opportunity.street or opportunity.street2 or opportunity.city or opportunity.state_id or opportunity.country_id">
|
||||
<label class="col-4">Address</label>
|
||||
<address class="col-8">
|
||||
<div t-if="opportunity.street"><span t-field="opportunity.street"/></div>
|
||||
<div t-if="opportunity.street2"><span t-field="opportunity.street2"/></div>
|
||||
<div t-if="opportunity.city or opportunity.zip">
|
||||
<span t-field="opportunity.city"/> <span t-field="opportunity.zip"/>
|
||||
</div>
|
||||
<div t-if="opportunity.state_id or country_id">
|
||||
<span t-field="opportunity.state_id"/> <span t-field="opportunity.country_id"/>
|
||||
</div>
|
||||
</address>
|
||||
</div>
|
||||
<!-- === / MODALS === -->
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div>
|
||||
<button type="button" data-toggle="modal" data-target=".modal_edit_opp" class="btn btn-primary" style="margin-bottom: 10px;">Edit Opportunity</button>
|
||||
<div role="dialog" class="modal fade modal_edit_opp">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" class="js_accept_json modal-content js_website_submit_form edit_opp_form">
|
||||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||||
<input type="hidden" name="opportunity_id" class="opportunity_id" t-att-value="opportunity.id"/>
|
||||
<header class="modal-header">
|
||||
<h4 class="modal-title">Edit Opportunity</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">&times;</button>
|
||||
</header>
|
||||
<main class="modal-body" id="sign-dialog">
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text"><span class="text-nowrap" t-esc="opportunity.company_currency.symbol"/></div>
|
||||
</div>
|
||||
<input type="text" name="planned_revenue" class="form-control planned_revenue" t-att-value="opportunity.planned_revenue" placeholder="Planned Revenue"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<span>at </span>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="input-group">
|
||||
<input type="text" name="probability" class="form-control probability" t-att-value="opportunity.probability" placeholder="Probability"/>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label>Priority: </label>
|
||||
<div class="input-group">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="PriorityRadioOptions" value="0" t-att-checked="opportunity.priority not in ['1','2','3']" aria-label="Rating: 0 on 3" title="Rating: 0 on 3"/><i class="fa fa-star-o"></i>
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="PriorityRadioOptions" value="1" t-att-checked="opportunity.priority == '1'" aria-label="Rating: 1 on 3" title="Rating: 1 on 3"/><i class="fa fa-star"></i>
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="PriorityRadioOptions" value="2" t-att-checked="opportunity.priority == '2'" aria-label="Rating: 2 on 3" title="Rating: 2 on 3"/><i class="fa fa-star"></i><i class="fa fa-star"></i>
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="PriorityRadioOptions" value="3" t-att-checked="opportunity.priority == '3'" aria-label="Rating: 3 on 3" title="Rating: 3 on 3"/><i class="fa fa-star"></i><i class="fa fa-star"></i><i class="fa fa-star"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label>Deadline: </label>
|
||||
<div class='input-group date'>
|
||||
<input type="text" name="date_deadline" t-att-value="opportunity.date_deadline" class="form-control date_deadline" data-date-format="YYYY-MM-DD" t-att-name="prefix" placeholder="YYYY-MM-DD" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><span class="fa fa-calendar" role="img" aria-label="Calendar"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="next_activity">Next Activity</label>
|
||||
<select class="form-control next_activity" name="next_activity">
|
||||
<t t-foreach="activity_types" t-as="activity_type">
|
||||
<option t-att-data="activity_type.id" t-att-selected="activity_type.id == user_activity.activity_type_id.id" t-att-name="activity_type.name" t-att-days="activity_type.days" t-att-summary="activity_type.summary"><t t-esc="activity_type.name"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="activity_summary">Details Next Activity</label>
|
||||
<textarea row="3" name="activity_summary" class="form-control activity_summary"><t t-esc="user_activity.summary"/></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="activity_date_deadline">Next Activity Date</label>
|
||||
<div class='input-group date'>
|
||||
<input type="text" name="activity_date_deadline" t-att-value="user_activity.date_deadline" class="form-control activity_date_deadline" data-date-format="YYYY-MM-DD" t-att-name="prefix" placeholder="YYYY-MM-DD" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><span class="fa fa-calendar" role="img" aria-label="Calendar" title="Calendar"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="modal-footer">
|
||||
<button t-attf-class="btn btn-primary edit_opp_confirm">Confirm</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" t-if="user_activity">
|
||||
<label class="col-4">Next Activity</label>
|
||||
<span class="col-8">
|
||||
<span t-field="user_activity.activity_type_id"/>
|
||||
<span t-if="user_activity.date_deadline"> on </span>
|
||||
<span t-field="user_activity.date_deadline"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row" t-if="user_activity">
|
||||
<span class="col-8 offset-4" t-field="user_activity.summary"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt32">
|
||||
<div class="col-lg-12">
|
||||
<h4><strong>Message and communication history</strong></h4>
|
||||
</div>
|
||||
<div class="col-lg-10 offset-lg-1 mt16">
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<div class="mt32">
|
||||
<h4><strong>Message and communication history</strong></h4>
|
||||
<div class="mt16">
|
||||
<t t-call="portal.message_thread">
|
||||
<t t-set="object" t-value="opportunity"/>
|
||||
</t>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<div itemprop="address" itemscope="itemscope" itemtype="http://schema.org/PostalAddress">
|
||||
<div t-if="address and 'address' in fields">
|
||||
<i t-if="not options.get('no_marker')" class='fa fa-map-marker fa-fw' role="img" aria-label="Address" title="Address"/>
|
||||
<span itemprop="streetAddress" t-raw="address.replace('\n', options.get('no_tag_br') and ', ' or ('<br/>%s' % ('' if options.get('no_marker') else '&nbsp; &nbsp; ')))"/>
|
||||
<span itemprop="streetAddress" t-raw="address.replace('\n', options.get('no_tag_br') and ', ' or ('<br/>%s' % ('' if options.get('no_marker') else '')))"/>
|
||||
</div>
|
||||
<div t-if="city and 'city' in fields">
|
||||
<i t-if="not options.get('no_marker')" class='fa fa-map-marker fa-fw' role="img" aria-label="Address" title="Address"/>
|
||||
|
||||
Reference in New Issue
Block a user