+1








0573acae23
This commit is the first phase of the conversion of the web/ JS codebase to the owl framework. The impact of this commit is two-fold. First, it rewrites the framework part of web with a new system of services and registries. Services allow to execute code (e.g. do rpcs, setup things) before launching the application. They can also expose an API to be used by other parts of the application (e.g. a notification service would expose a function to display notifications). Services are often a good extension point for external modules that want to execute code at webclient startup. Registries offer another way to extend the application. They provide well designed extension points to add elements/behaviors from the outside (for instance, to add a systray item, an error handler...). Second, this commit initiates the conversion of the webclient to owl with a top-down approach, around those notions of services and registries. The root of the web application is now an owl application. Among others, the WebClient, ActionManager, Navbar, UserMenu, DebugManager, Dialogs, services (e.g. notification, ajax...) have been converted to the new framework/architecture. Legacy views and client actions are still supported (and used). They will be converted in the next months, and at some point, the support will be dropped. Co-authored-by: Aaron Bohy <aab@odoo.com> Co-authored-by: Bruno Boi <boi@odoo.com> Co-authored-by: Géry Debongnie <ged@odoo.com> Co-authored-by: Samuel Degueldre <sad@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com> Co-authored-by: Simon Genin (ges) <ges@odoo.com> Co-authored-by: Francois (fge) <fge@odoo.com> Co-authored-by: Michael Mattiello (mcm) <mcm@odoo.com> Co-authored-by: Julien Mougenot <jum@odoo.com> Co-authored-by: Lucas Perais (lpe) <lpe@odoo.com> Co-authored-by: Jorge Pinna Puissant <jpp@odoo.com>
315 lines
15 KiB
XML
315 lines
15 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<!-- Call this template instead of "web.assets_tests" to have the proper conditional check -->
|
|
<template id="conditional_assets_tests" name="Tests Assets Bundle">
|
|
<t t-call-assets="web.assets_tests" t-if="'tests' in debug or test_mode_enabled" defer_load="True" />
|
|
</template>
|
|
|
|
<template id="web.layout" name="Web layout"><!DOCTYPE html>
|
|
<html t-att="html_data or {}">
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
|
|
|
<title t-esc="title or 'Odoo'"/>
|
|
<link type="image/x-icon" rel="shortcut icon" t-att-href="x_icon or '/web/static/img/favicon.ico'"/>
|
|
|
|
<script id="web.layout.odooscript" type="text/javascript">
|
|
var odoo = {
|
|
csrf_token: "<t t-esc="request.csrf_token(None)"/>",
|
|
debug: "<t t-esc="debug"/>",
|
|
};
|
|
</script>
|
|
|
|
<t t-out="head or ''"/>
|
|
</head>
|
|
<body t-att-class="body_classname">
|
|
<t t-out="0"/>
|
|
</body>
|
|
</html>
|
|
</template>
|
|
|
|
<template id="web.frontend_layout" name="Frontend Layout" inherit_id="web.layout" primary="True">
|
|
<xpath expr="//head/meta[last()]" position="after">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
</xpath>
|
|
<xpath expr="//head/link[last()]" position="after">
|
|
<link rel="preload" href="/web/static/lib/fontawesome/fonts/fontawesome-webfont.woff2?v=4.7.0" as="font" crossorigin=""/>
|
|
<t t-call-assets="web.assets_common" t-js="false"/>
|
|
<t t-call-assets="web.assets_frontend" t-js="false"/>
|
|
</xpath>
|
|
<xpath expr="//head/script[@id='web.layout.odooscript']" position="after">
|
|
<script type="text/javascript">
|
|
odoo.session_info = <t t-out="json.dumps(request.env['ir.http'].get_frontend_session_info())"/>;
|
|
if (!/(^|;\s)tz=/.test(document.cookie)) {
|
|
const userTZ = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
document.cookie = `tz=${userTZ}; path=/`;
|
|
}
|
|
</script>
|
|
<t t-call-assets="web.assets_common_minimal" t-css="false" defer_load="True"/>
|
|
<t t-call-assets="web.assets_frontend_minimal" t-css="false" defer_load="True"/>
|
|
<t t-call="web.conditional_assets_tests"/>
|
|
<t t-call-assets="web.assets_common_lazy" t-css="false" lazy_load="True"/>
|
|
<t t-call-assets="web.assets_frontend_lazy" t-css="false" lazy_load="True"/>
|
|
</xpath>
|
|
<xpath expr="//t[@t-out='0']" position="replace">
|
|
<div id="wrapwrap" t-attf-class="#{pageName or ''}">
|
|
<header t-if="not no_header" id="top" data-anchor="true">
|
|
<img class="img-responsive d-block mx-auto"
|
|
t-attf-src="/web/binary/company_logo"
|
|
alt="Logo"/>
|
|
</header>
|
|
<main>
|
|
<t t-out="0"/>
|
|
</main>
|
|
<footer t-if="not no_footer" id="bottom" data-anchor="true" t-attf-class="bg-light o_footer">
|
|
<div id="footer"/>
|
|
<div t-if="not no_copyright" class="o_footer_copyright">
|
|
<div class="container py-3">
|
|
<div class="row">
|
|
<div class="col-sm text-center text-sm-left text-muted">
|
|
<t t-call="web.debug_icon"/>
|
|
<span class="o_footer_copyright_name mr-2">Copyright &copy; <span t-field="res_company.name" itemprop="name">Company name</span></span>
|
|
</div>
|
|
<div class="col-sm text-center text-sm-right">
|
|
<t t-call="web.brand_promotion"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
</xpath>
|
|
</template>
|
|
|
|
<template id="brand_promotion_message" name="Brand Promotion Message">
|
|
<t t-set="odoo_logo">
|
|
<a target="_blank"
|
|
t-attf-href="http://www.odoo.com?utm_source=db&utm_medium=#{_utm_medium}"
|
|
class="badge badge-light">
|
|
<img alt="Odoo"
|
|
src="/web/static/img/odoo_logo_tiny.png"
|
|
style="height: 1em; vertical-align: baseline;"/>
|
|
</a>
|
|
</t>
|
|
<t t-set="final_message">Powered by %s%s</t>
|
|
<t t-out="final_message % (odoo_logo, _message and ('- ' + _message) or '')"/>
|
|
</template>
|
|
<template id="brand_promotion" name="Brand Promotion">
|
|
<div class="o_brand_promotion">
|
|
<t t-call="web.brand_promotion_message">
|
|
<t t-set="_message"></t>
|
|
<t t-set="_utm_medium" t-valuef="portal"/>
|
|
</t>
|
|
</div>
|
|
</template>
|
|
|
|
<template id="web.login_layout" name="Login Layout">
|
|
<t t-call="web.frontend_layout">
|
|
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
|
|
<t t-set="body_classname" t-value="'bg-100'"/>
|
|
<t t-set="no_header" t-value="True"/>
|
|
<t t-set="no_footer" t-value="True"/>
|
|
|
|
<div class="container py-5">
|
|
<div t-attf-class="card border-0 mx-auto bg-100 {{login_card_classes}} o_database_list" style="max-width: 300px;">
|
|
<div class="card-body">
|
|
<div t-attf-class="text-center pb-3 border-bottom {{'mb-3' if form_small else 'mb-4'}}">
|
|
<img t-attf-src="/web/binary/company_logo{{ '?dbname='+db if db else '' }}" alt="Logo" style="max-height:120px; max-width: 100%; width:auto"/>
|
|
</div>
|
|
<t t-out="0"/>
|
|
<div class="text-center small mt-4 pt-3 border-top" t-if="not disable_footer">
|
|
<t t-if="not disable_database_manager">
|
|
<a class="border-right pr-2 mr-1" href="/web/database/manager">Manage Databases</a>
|
|
</t>
|
|
<a href="https://www.odoo.com?utm_source=db&utm_medium=auth" target="_blank">Powered by <span>Odoo</span></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</template>
|
|
|
|
<template id="web.login" name="Login">
|
|
<t t-call="web.login_layout">
|
|
<form class="oe_login_form" role="form" t-attf-action="/web/login" method="post" onsubmit="this.action = '/web/login' + location.hash">
|
|
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
|
|
|
<div class="form-group field-db" t-if="databases and len(databases) > 1">
|
|
<label for="db" class="col-form-label">Database</label>
|
|
<div t-attf-class="input-group {{'input-group-sm' if form_small else ''}}">
|
|
<input type="text" name="db" t-att-value="request.db" id="db" t-attf-class="form-control #{'form-control-sm' if form_small else ''}" required="required" readonly="readonly"/>
|
|
<span class="input-group-append">
|
|
<a role="button" href="/web/database/selector" class="btn btn-secondary">Select <i class="fa fa-database" role="img" aria-label="Database" title="Database"></i></a>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group field-login">
|
|
<label for="login">Email</label>
|
|
<input type="text" placeholder="Email" name="login" t-att-value="login" id="login" t-attf-class="form-control #{'form-control-sm' if form_small else ''}" required="required" autofocus="autofocus" autocapitalize="off"/>
|
|
</div>
|
|
|
|
<div class="form-group field-password">
|
|
<label for="password">Password</label>
|
|
<input type="password" placeholder="Password" name="password" id="password" t-attf-class="form-control #{'form-control-sm' if form_small else ''}" required="required" autocomplete="current-password" t-att-autofocus="'autofocus' if login else None" maxlength="4096"/>
|
|
</div>
|
|
|
|
<p class="alert alert-danger" t-if="error" role="alert">
|
|
<t t-esc="error"/>
|
|
</p>
|
|
<p class="alert alert-success" t-if="message" role="status">
|
|
<t t-esc="message"/>
|
|
</p>
|
|
|
|
<div t-attf-class="clearfix oe_login_buttons text-center mb-1 {{'pt-2' if form_small else 'pt-3'}}">
|
|
<button type="submit" class="btn btn-primary btn-block">Log in</button>
|
|
<t t-if="debug">
|
|
<button type="submit" name="redirect" value="/web/become" class="btn btn-link btn-sm btn-block">Log in as superuser</button>
|
|
</t>
|
|
<div class="o_login_auth"/>
|
|
</div>
|
|
|
|
<input type="hidden" name="redirect" t-att-value="redirect"/>
|
|
</form>
|
|
</t>
|
|
</template>
|
|
|
|
<template id="web.test_helpers">
|
|
<t t-call-assets="web.tests_assets" t-js="False"/>
|
|
<style>
|
|
body {
|
|
position: relative; // bootstrap-datepicker needs this
|
|
}
|
|
body:not(.debug) .modal-backdrop, body:not(.debug) .modal, body:not(.debug) .ui-autocomplete {
|
|
opacity: 0 !important;
|
|
}
|
|
#qunit-testrunner-toolbar label {
|
|
font-weight: inherit;
|
|
margin-bottom: inherit;
|
|
}
|
|
#qunit-testrunner-toolbar input[type=text] {
|
|
width: inherit;
|
|
display: inherit;
|
|
}
|
|
</style>
|
|
<t t-call-assets="web.tests_assets" t-css="False"/>
|
|
</template>
|
|
|
|
<template id="web.qunit_suite">
|
|
<t t-call="web.layout">
|
|
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
|
|
<t t-set="title">Web Tests</t>
|
|
<t t-set="head">
|
|
<t t-call-assets="web.assets_common" t-js="false"/>
|
|
<t t-call-assets="web.assets_backend" t-js="false"/>
|
|
<t t-call-assets="web.assets_common" t-css="false"/>
|
|
<t t-call-assets="web.assets_backend" t-css="false"/>
|
|
|
|
<t t-call="web.test_helpers"/>
|
|
|
|
<t t-call-assets="web.qunit_suite_tests" t-js="false"/>
|
|
<t t-call-assets="web.qunit_suite_tests" t-css="false"/>
|
|
</t>
|
|
<div id="qunit"/>
|
|
<div id="qunit-fixture"/>
|
|
</t>
|
|
</template>
|
|
|
|
<template id="web.qunit_mobile_suite">
|
|
<t t-call="web.layout">
|
|
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
|
|
<t t-set="title">Web Mobile Tests</t>
|
|
<t t-set="head">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
|
|
<t t-call-assets="web.assets_common" t-js="false"/>
|
|
<t t-call-assets="web.assets_backend" t-js="false"/>
|
|
<t t-call-assets="web.assets_common" t-css="false"/>
|
|
<t t-call-assets="web.assets_backend" t-css="false"/>
|
|
|
|
<t t-call="web.test_helpers"/>
|
|
|
|
<t t-call-assets="web.qunit_mobile_suite_tests" t-js="false"/>
|
|
<t t-call-assets="web.qunit_mobile_suite_tests" t-css="false"/>
|
|
</t>
|
|
<div id="qunit"/>
|
|
<div id="qunit-fixture"/>
|
|
</t>
|
|
</template>
|
|
|
|
<template id="web.benchmark_suite">
|
|
<t t-call="web.layout">
|
|
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
|
|
<t t-set="title">Web Benchmarks</t>
|
|
<t t-set="head">
|
|
<script type="text/javascript" src="/web/static/lib/benchmarkjs/lodash.js"></script>
|
|
<script type="text/javascript" src="/web/static/lib/benchmarkjs/benchmark.js"></script>
|
|
|
|
<t t-call-assets="web.assets_common" t-js="false"/>
|
|
<t t-call-assets="web.assets_backend" t-js="false"/>
|
|
<t t-call-assets="web.assets_common" t-css="false"/>
|
|
<t t-call-assets="web.assets_backend" t-css="false"/>
|
|
|
|
<t t-call="web.test_helpers"/>
|
|
|
|
<script type="text/javascript">
|
|
QUnit.config.hidepassed = false;
|
|
</script>
|
|
|
|
<style>
|
|
body:not(.debug) .modal-backdrop, body:not(.debug) .modal, body:not(.debug) .ui-autocomplete {
|
|
opacity: 0 !important;
|
|
}
|
|
#qunit-testrunner-toolbar label {
|
|
font-weight: inherit;
|
|
margin-bottom: inherit;
|
|
}
|
|
#qunit-testrunner-toolbar input[type=text] {
|
|
width: inherit;
|
|
display: inherit;
|
|
}
|
|
</style>
|
|
|
|
<script type="text/javascript" src="/web/static/tests/views/list_benchmarks.js"></script>
|
|
<script type="text/javascript" src="/web/static/tests/views/kanban_benchmarks.js"></script>
|
|
<script type="text/javascript" src="/web/static/tests/views/form_benchmarks.js"></script>
|
|
|
|
</t>
|
|
|
|
<div id="qunit"/>
|
|
<div id="qunit-fixture"/>
|
|
</t>
|
|
</template>
|
|
|
|
<template id="web.webclient_bootstrap">
|
|
<t t-call="web.layout">
|
|
<t t-set="head_web">
|
|
<script type="text/javascript">
|
|
odoo.session_info = <t t-out="json.dumps(session_info)"/>;
|
|
odoo.reloadMenus = () => fetch(`/web/webclient/load_menus/${odoo.session_info.cache_hashes.load_menus}`).then(res => res.json());
|
|
odoo.loadMenusPromise = odoo.reloadMenus();
|
|
odoo.loadTemplatesPromise = fetch(`/web/webclient/qweb/${odoo.session_info.cache_hashes.qweb}?bundle=web.assets_qweb`).then(doc => doc.text());
|
|
</script>
|
|
<t t-call-assets="web.assets_common" t-js="false"/>
|
|
<t t-call-assets="web.assets_backend" t-js="false"/>
|
|
<t t-call-assets="web.assets_common" t-css="false"/>
|
|
<t t-call-assets="web.assets_backend" t-css="false"/>
|
|
<t t-call-assets="web.assets_backend_prod_only" t-css="false"/>
|
|
<t t-call="web.conditional_assets_tests"/>
|
|
</t>
|
|
<t t-set="head" t-value="head_web + (head or '')"/>
|
|
<t t-set="body_classname" t-value="'o_web_client'"/>
|
|
</t>
|
|
</template>
|
|
|
|
<template id="debug_icon" name="Debug Icon">
|
|
<t t-if="debug">
|
|
<t t-set="debug_mode_help" t-value="' (%s)' % debug if debug != '1' else ''"/>
|
|
<a t-attf-href="?#{keep_query('*', debug='')}" t-attf-title="Debug mode is activated#{debug_mode_help}. Click here to exit debug mode."
|
|
class="o_debug_mode"><span class="fa fa-bug"/></a>
|
|
</t>
|
|
</template>
|
|
|
|
</odoo>
|