diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/portal/views | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/portal/views')
| -rw-r--r-- | addons/portal/views/assets.xml | 33 | ||||
| -rw-r--r-- | addons/portal/views/portal_templates.xml | 584 |
2 files changed, 617 insertions, 0 deletions
diff --git a/addons/portal/views/assets.xml b/addons/portal/views/assets.xml new file mode 100644 index 00000000..2fbcf61d --- /dev/null +++ b/addons/portal/views/assets.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <template id="_assets_primary_variables" inherit_id="web._assets_primary_variables"> + <xpath expr="//link[last()]" position="after"> + <link rel="stylesheet" type="text/scss" href="/portal/static/src/scss/primary_variables.scss"/> + </xpath> + </template> + <template id="_assets_frontend_helpers" inherit_id="web_editor._assets_frontend_helpers"> + <xpath expr="//link" position="before"> + <link rel="stylesheet" type="text/scss" href="/portal/static/src/scss/bootstrap_overridden.scss"/> + </xpath> + </template> + + <template id="assets_frontend" inherit_id="web_editor.assets_frontend" name="Portal Assets" priority="15"> + <xpath expr="//link[last()]" position="after"> + <link rel="stylesheet" type="text/scss" href="/portal/static/src/scss/bootstrap.extend.scss"/> + <link rel="stylesheet" type="text/scss" href="/portal/static/src/scss/portal.scss"/> + </xpath> + <xpath expr="//script[last()]" position="after"> + <script type="text/javascript" src="/portal/static/src/js/portal.js"></script> + <script type="text/javascript" src="/portal/static/src/js/portal_chatter.js"></script> + <script type="text/javascript" src="/portal/static/src/js/portal_composer.js"></script> + <script type="text/javascript" src="/portal/static/src/js/portal_signature.js"></script> + <script type="text/javascript" src="/portal/static/src/js/portal_sidebar.js"></script> + </xpath> + </template> + + <template id="assets_tests" name="Portal Assets Tests" inherit_id="web.assets_tests"> + <xpath expr="." position="inside"> + <script type="text/javascript" src="/portal/static/tests/tours/portal.js"></script> + </xpath> + </template> +</odoo> diff --git a/addons/portal/views/portal_templates.xml b/addons/portal/views/portal_templates.xml new file mode 100644 index 00000000..371391c2 --- /dev/null +++ b/addons/portal/views/portal_templates.xml @@ -0,0 +1,584 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <template id="frontend_layout" name="Main Frontend Layout" inherit_id="web.frontend_layout"> + <xpath expr="//div[@id='wrapwrap']" position="attributes"> + <attribute name="t-attf-class" add="#{request.env['res.lang']._lang_get(request.env.lang).direction == 'rtl' and 'o_rtl' or ''}" separator=" "/> + <attribute name="t-attf-class" add="#{'o_portal' if is_portal else ''}" separator=" "/> + </xpath> + <xpath expr="//div[@id='wrapwrap']/header/img" position="replace"> + <nav class="navbar navbar-expand navbar-light bg-light"> + <div class="container"> + <a href="/" class="navbar-brand logo"> + <img t-att-src="'/logo.png?company=%s' % res_company.id" t-att-alt="'Logo of %s' % res_company.name" t-att-title="res_company.name"/> + </a> + <ul id="top_menu" class="nav navbar-nav ml-auto"> + <t t-call="portal.placeholder_user_sign_in"> + <t t-set="_item_class" t-value="'nav-item'"/> + <t t-set="_link_class" t-value="'nav-link'"/> + </t> + <t t-call="portal.user_dropdown"> + <t t-set="_user_name" t-value="true"/> + <t t-set="_item_class" t-value="'nav-item dropdown'"/> + <t t-set="_link_class" t-value="'nav-link'"/> + <t t-set="_dropdown_menu_class" t-value="'dropdown-menu-right'"/> + </t> + </ul> + </div> + </nav> + </xpath> + <xpath expr="//div[@id='wrapwrap']/main/t[@t-raw='0']" position="before"> + <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> + </div> + </xpath> + </template> + + <!-- Added by another template so that it can be disabled if needed --> + <template id="footer_language_selector" inherit_id="portal.frontend_layout" name="Footer Language Selector"> + <xpath expr="//*[hasclass('o_footer_copyright_name')]" position="after"> + <t id="language_selector_call" t-call="portal.language_selector"> + <t t-set="_div_classes" t-value="(_div_classes or '') + ' dropup'"/> + </t> + </xpath> + </template> + + <template id="language_selector" name="Language Selector"> + <t t-set="active_lang" t-value="list(filter(lambda lg : lg[0] == lang, languages))[0]"/> + <t t-set="language_selector_visible" t-value="len(languages) > 1"/> + <div t-attf-class="js_language_selector #{_div_classes}" t-if="language_selector_visible"> + <button class="btn btn-sm btn-outline-secondary border-0 dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> + <span t-if="not no_text" + class="align-middle" + t-esc="active_lang[2].split('/').pop()"/> + </button> + <div class="dropdown-menu" role="menu"> + <t t-foreach="languages" t-as="lg"> + <a t-att-href="url_for(request.httprequest.path + '?' + keep_query(), lang_code=lg[0])" + class="dropdown-item js_change_lang" + t-att-data-url_code="lg[1]"> + <span t-if="not no_text" + t-esc="lg[2].split('/').pop()"/> + </a> + </t> + </div> + </div> + </template> + + <template id="user_dropdown" name="Portal User Dropdown"> + <t t-set="is_connected" t-value="not user_id._is_public()"/> + <li t-if="is_connected" t-attf-class="#{_item_class} o_no_autohide_item"> + <a href="#" role="button" data-toggle="dropdown" t-attf-class="dropdown-toggle #{_link_class}"> + <t t-if="_avatar"> + <t t-if="user_id.image_256" t-set="avatar_source" t-value="image_data_uri(user_id.image_256)"/> + <t t-else="" t-set="avatar_source" t-value="'/web/static/src/img/placeholder.png'"/> + <img t-att-src="avatar_source" t-attf-class="rounded-circle #{_avatar_class}" width="24" height="24" alt="" loading="eager"/> + </t> + <i t-if="_icon" t-attf-class="fa fa-1x fa-fw fa-user-circle-o #{_icon_class}"/> + <span t-if="_user_name" t-attf-class="#{_user_name_class}" t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) > 25 else user_id.name"/> + </a> + <div t-attf-class="dropdown-menu js_usermenu #{_dropdown_menu_class}" role="menu"> + <div id="o_logout_divider" class="dropdown-divider"/> + <a t-attf-href="/web/session/logout?redirect=/" role="menuitem" id="o_logout" class="dropdown-item">Logout</a> + </div> + </li> + </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 row"> + <li class="breadcrumb-item ml-1"><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">Details</li> + </ol> + </template> + + <template id="portal_back_in_edit_mode" name="Back to edit mode"> + <div t-ignore="true" class="text-center"> + <t t-if="custom_html" t-raw="custom_html"/> + <t t-else="">This is a preview of the customer portal.</t> + <a t-att-href="backend_url"><i class="fa fa-arrow-right mr-1"/>Back to edit mode</a> + </div> + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> × </button> + </template> + + <template id="portal_layout" name="Portal Layout"> + <t t-call="portal.frontend_layout"> + <t t-set="is_portal" t-value="True"/> + + <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"> + <div class="col-10"> + <t t-call="portal.portal_breadcrumbs"></t> + </div> + <div t-if="prev_record or next_record" class="col-2 flex-grow-0 text-center"> + <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 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="pt-3 pt-lg-0 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"> + <h4>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_portal_my_security mt-3"> + <h4>Account Security </h4> + <hr class="mt-1 mb-1"/> + <a href="/my/security"><i class="fa fa-pencil mx-1"/>Edit Security Settings</a> + </div> + </div> + </div> + </t> + <t t-else=""> + <t t-raw="0"/> + </t> + </div> + </div> + </t> + </template> + + <template id="placeholder_user_sign_in" name="User Sign In Placeholder"/> + + <template id="user_sign_in" name="User Sign In" inherit_id="portal.placeholder_user_sign_in"> + <xpath expr="." position="inside"> + <li groups="base.group_public" t-attf-class="#{_item_class} o_no_autohide_item"> + <a t-attf-href="/web/login" t-attf-class="#{_link_class}">Sign in</a> + </li> + </xpath> + </template> + + <template id="portal_my_home" name="My Portal"> + <t t-call="portal.portal_layout"> + <t t-set="my_details" t-value="True"/> + <div class="o_portal_my_home"> + <div class="oe_structure" id="oe_structure_portal_my_home_1"/> + <h3>Documents</h3> + <div class="o_portal_docs list-group"> + </div> + </div> + <div class="oe_structure" id="oe_structure_portal_my_home_2"/> + </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"/> + <t t-if='count'> + <span class="badge badge-secondary badge-pill" t-esc="count"/> + </t> + <t t-elif="placeholder_count"> + <span class="badge badge-secondary badge-pill" t-att-data-placeholder_count="placeholder_count"> + <i class="fa fa-spin fa-spinner"></i> + </span> + </t> + </a> + </template> + + <template id="portal_table" name="My Portal Table"> + <div t-attf-class="table-responsive border rounded border-top-0 #{classes if classes else ''}"> + <table class="table rounded mb-0 bg-white 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="#{classes}"> + <div class="card bg-white mb-4 sticky-top" 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 + redirect the user to the beginning of document list, keeping query parameters. + + These 2 buttons can be prepended by a advanced search input, to activate it, search_input need + to be initialized at 'True' and the content of the t-call is the list of li elements searchable. + + :param dict searchbar_sortings : containing the sort criteria like + {'date': {'label': _('Newest'), 'order': 'create_date desc'}} + :param string sortby : name of the sort criteria + :param dict searchbar_filters : containing the filter criteria like + {'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 + :param title : bavbar title + :param classes : navbar classes + --> + <template id="portal_searchbar" name="Portal Search Bar"> + <nav t-attf-class="navbar navbar-light navbar-expand-lg border py-0 mb-2 o_portal_navbar {{classes if classes else ''}} {{'mt-3 rounded' if breadcrumbs_searchbar else 'border-top-0' }}"> + <!-- 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'"/> + + <!-- 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"> + <a t-att-href="request.httprequest.path + '?' + keep_query('*', sortby=option)" + t-attf-class="dropdown-item#{sortby == option and ' active' or ''}"> + <span t-esc="searchbar_sortings[option].get('label')"/> + </a> + </t> + </div> + </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.get(filterby,searchbar_filters.get('all')).get('label', 'All')"/> + </button> + <div class="dropdown-menu" aria-labelledby="portal_searchbar_filters"> + <t t-foreach="searchbar_filters" t-as="option"> + <a t-att-href="default_url + '?' + keep_query('*', filterby=option)" + t-attf-class="dropdown-item#{filterby == option and ' active' or ''}"> + <span t-esc="searchbar_filters[option].get('label')"/> + </a> + </t> + </div> + </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"> + <a t-att-href="default_url + '?' + keep_query('*', groupby=option)" + t-attf-class="dropdown-item#{groupby == option and ' active' or ''}"> + <span t-esc="searchbar_groupby[option].get('label')"/> + </a> + </t> + </div> + </div> + </div> + <t t-raw="0"/> + </div> + <form t-if="searchbar_inputs" class="form-inline o_portal_search_panel ml-lg-4 col-xl-4 col-md-5"> + <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"> + <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_my_details"> + <t t-call="portal.portal_layout"> + <t t-set="additional_title">Contact Details</t> + <form action="/my/account" method="post"> + <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> + <div class="row o_portal_details"> + <div class="col-lg-8"> + <div class="row"> + <t t-set="partner_can_edit_vat" t-value="partner.can_edit_vat()"/> + <div class="col-lg-12"> + <div t-if="error_message" class="alert alert-danger" role="alert"> + <t t-foreach="error_message" t-as="err"><t t-esc="err"/><br /></t> + </div> + </div> + <div t-attf-class="form-group #{error.get('name') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label" for="name">Name</label> + <input type="text" name="name" t-attf-class="form-control #{error.get('name') and 'is-invalid' or ''}" t-att-value="name or partner.name" /> + </div> + <div t-attf-class="form-group #{error.get('email') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label" for="email">Email</label> + <input type="email" name="email" t-attf-class="form-control #{error.get('email') and 'is-invalid' or ''}" t-att-value="email or partner.email" /> + </div> + + <div class="clearfix" /> + <div t-attf-class="form-group #{error.get('company_name') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label label-optional" for="company_name">Company Name</label> + <!-- The <input> is replace by a <p> to avoid sending an unauthorized value on form submit. + The user might not have rights to change company_name but should still be able to see it. + --> + <p t-if="not partner_can_edit_vat" t-attf-class="form-control" readonly="1" t-esc="partner.commercial_company_name" title="Changing company name is not allowed once document(s) have been issued for your account. Please contact us directly for this operation."/> + <input t-else="" type="text" name="company_name" t-attf-class="form-control #{error.get('company_name') and 'is-invalid' or ''}" t-att-value="company_name or partner.commercial_company_name"/> + </div> + <div t-attf-class="form-group #{error.get('vat') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label label-optional" for="vat">VAT Number</label> + <t t-set="vat_not_editable_message">Changing VAT number is not allowed once document(s) have been issued for your account. Please contact us directly for this operation.</t> + <input type="text" name="vat" t-attf-class="form-control #{error.get('vat') and 'is-invalid' or ''}" t-att-value="vat or partner.vat" t-att-readonly="None if partner_can_edit_vat else '1'" t-att-title="None if partner_can_edit_vat else vat_not_editable_message" /> + </div> + <div t-attf-class="form-group #{error.get('phone') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label" for="phone">Phone</label> + <input type="tel" name="phone" t-attf-class="form-control #{error.get('phone') and 'is-invalid' or ''}" t-att-value="phone or partner.phone" /> + </div> + + <div class="clearfix" /> + <div t-attf-class="form-group #{error.get('street') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label" for="street">Street</label> + <input type="text" name="street" t-attf-class="form-control #{error.get('street') and 'is-invalid' or ''}" t-att-value="street or partner.street"/> + </div> + <div t-attf-class="form-group #{error.get('city') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label" for="city">City</label> + <input type="text" name="city" t-attf-class="form-control #{error.get('city') and 'is-invalid' or ''}" t-att-value="city or partner.city" /> + </div> + <div t-attf-class="form-group #{error.get('zip') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label label-optional" for="zipcode">Zip / Postal Code</label> + <input type="text" name="zipcode" t-attf-class="form-control #{error.get('zip') and 'is-invalid' or ''}" t-att-value="zipcode or partner.zip" /> + </div> + <div t-attf-class="form-group #{error.get('country_id') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label" for="country_id">Country</label> + <select name="country_id" t-attf-class="form-control #{error.get('country_id') and 'is-invalid' or ''}"> + <option value="">Country...</option> + <t t-foreach="countries or []" t-as="country"> + <option t-att-value="country.id" t-att-selected="country.id == int(country_id) if country_id else country.id == partner.country_id.id"> + <t t-esc="country.name" /> + </option> + </t> + </select> + </div> + <div t-attf-class="form-group #{error.get('state_id') and 'o_has_error' or ''} col-xl-6"> + <label class="col-form-label label-optional" for="state_id">State / Province</label> + <select name="state_id" t-attf-class="form-control #{error.get('state_id') and 'is-invalid' or ''}"> + <option value="">select...</option> + <t t-foreach="states or []" t-as="state"> + <option t-att-value="state.id" style="display:none;" t-att-data-country_id="state.country_id.id" t-att-selected="state.id == partner.state_id.id"> + <t t-esc="state.name" /> + </option> + </t> + </select> + </div> + <input type="hidden" name="redirect" t-att-value="redirect"/> + </div> + <div class="clearfix"> + <button type="submit" class="btn btn-primary float-right mb32 "> + Confirm + <span class="fa fa-long-arrow-right" /> + </button> + </div> + </div> + </div> + </form> + </t> + </template> + + <template id="portal_my_security"> + <t t-call="portal.portal_layout"><div class="o_portal_security_body"> + <t t-set="additional_title">Security</t> + <t t-set="no_breadcrumbs" t-value="1"/> + <div class="alert alert-danger" role="alert" t-if="get_error(errors)"> + <t t-esc="errors"/> + </div> + <section> + <h3>Change Password</h3> + <t t-set="path">password</t> + <div class="alert alert-success" role="alert" t-if="success and success.get('password')"> + Password Updated! + </div> + <div class="alert alert-danger" role="alert" t-if="get_error(errors, 'password')"> + <t t-esc="errors['password']"/> + </div> + <form action="/my/security" method="post" class="oe_reset_password_form"> + <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> + <input type="hidden" name="op" value="password"/> + <div class="form-group"> + <label for="current">Password:</label> + <input type="password" t-attf-class="form-control form-control-sm {{ 'is-invalid' if get_error(errors, 'password.old') else '' }}" + id="current" name="old" + autocomplete="current-password" required="required"/> + <div class="invalid-feedback"> + <t t-esc="get_error(errors, 'password.old')"/> + </div> + </div> + <div class="form-group"> + <label for="new">New Password:</label> + <input type="password" t-attf-class="form-control form-control-sm {{ 'is-invalid' if get_error(errors, 'password.new1') else '' }}" + id="new" name="new1" + autocomplete="new-password" required="required"/> + <div class="invalid-feedback"> + <t t-esc="get_error(errors, 'password.new1')"/> + </div> + </div> + <div class="form-group"> + <label for="new2">Verify New Password:</label> + <input type="password" t-attf-class="form-control form-control-sm {{ 'is-invalid' if get_error(errors, 'password.new2') else '' }}" + id="new2" name="new2" + autocomplete="new-password" required="required"/> + <div class="invalid-feedback"> + <t t-esc="get_error(errors, 'password.new2')"/> + </div> + </div> + <button type="submit" class="btn btn-danger">Change Password</button> + </form> + </section> + </div></t> + </template> + + <template id="record_pager" name="Portal Record Pager"> + <t t-if='prev_record or next_record'> + <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="Next"></i></a> + </div> + </t> + </template> + + <template id="pager" name="Pager"> + <ul t-if="pager['page_count'] > 1" t-attf-class="#{ classname or '' } pagination m-0 #{_classes}" t-att-style="style or None"> + <li t-attf-class="page-item #{'disabled' if pager['page']['num'] == 1 else ''}"> + <a t-att-href=" pager['page_previous']['url'] if pager['page']['num'] != 1 else None" t-attf-class="page-link #{extraLinkClass}">Prev</a> + </li> + <t t-foreach="pager['pages']" t-as="page"> + <li t-attf-class="page-item #{'active' if page['num'] == pager['page']['num'] else ''}"> <a t-att-href="page['url']" t-attf-class="page-link #{extraLinkClass}" t-raw="page['num']"></a></li> + </t> + <li t-attf-class="page-item #{'disabled' if pager['page']['num'] == pager['page_count'] else ''}"> + <a t-att-href="pager['page_next']['url'] if pager['page']['num'] != pager['page_count'] else None" t-attf-class="page-link #{extraLinkClass}">Next</a> + </li> + </ul> + </template> + + <template id="my_account_link" name="Link to frontend portal" inherit_id="portal.user_dropdown"> + <xpath expr="//*[@id='o_logout_divider']" position="before"> + <a href="/my/home" role="menuitem" class="dropdown-item">My Account</a> + </xpath> + </template> + + <!-- + Generic chatter template for the frontend + This template provide the container of the chatter. The rest is done in js. + To use this template, you need to call it after setting the following variable in your template or in your controller: + :object browserecord : the mail_thread object + :message_per_page int (optional): number of message per chatter page + :token string (optional): if you want your chatter to be available for non-logged user, + you can use a token to verify the identity of the user; + the message will be posted with the identity of the partner_id of the object + :hash : signed token with the partner_id using `_sign_token` method (on mail.thread) + :pid : identifier of the partner signing the token + --> + <template id="message_thread"> + <div id="discussion" data-anchor="true" class="d-print-none o_portal_chatter o_not_editable p-0" + t-att-data-token="token" t-att-data-res_model="object._name" t-att-data-pid="pid" t-att-data-hash="hash" t-att-data-res_id="object.id" t-att-data-pager_step="message_per_page or 10" t-att-data-allow_composer="'0' if disable_composer else '1'"> + </div> + </template> + + <!-- + Snippet to request user signature in the portal. The feature comes with + the JS file `portal_signature.js`. + + The following variable has to be set: + - {string} call_url: url where to send the name and signature by RPC + The url should contain a query string if additional parameters + have to be sent, such as an access token. + + The following variables are optional: + - {string} default_name: the default name to display + - {string} mode: 'draw', 'auto', or 'load' + - {string} send_label: label of the send button + - {number} signature_ratio: ratio of the signature area + - {string} signature_type: 'signature' or 'initial' + + For the default values and more information, see init() of the widgets + SignatureForm and NameAndSignature. + --> + <template id="portal.signature_form" name="Ask Signature"> + <div class="o_portal_signature_form" + t-att-data-call-url="call_url" + t-att-data-default-name="default_name" + t-att-data-mode="mode" + t-att-data-send-label="send_label" + t-att-data-signature-ratio="signature_ratio" + t-att-data-signature-type="signature_type" + t-att-data-font-color="font_color" + /> + </template> + + <template id="portal_sidebar" name="Sidebar"> + <t t-call="portal.portal_layout"> + <body data-spy="scroll" data-target=".navspy" data-offset="50"> + <div class="container o_portal_sidebar"></div> + <div class="oe_structure mb32" id="oe_structure_portal_sidebar_1"/> + </body> + </t> + </template> +</odoo> |
