[FIX] web, base_setup: template didn't exist because of deps

An enterprise without apps would crash on launch because of a template
web_enterprise would inherit but was only there with base_setup
installed.

closes odoo/odoo#97017

Related: odoo/enterprise#29919
Signed-off-by: Simon Genin (ges@odoo) <ges@odoo.com>
This commit is contained in:
Simon Genin (ges)
2022-07-28 21:01:50 +02:00
parent 528ee16956
commit df2562e4f0
10 changed files with 6 additions and 11 deletions
@@ -1,20 +0,0 @@
/** @odoo-modules */
import { registry } from "@web/core/registry";
export const demoDataService = {
dependencies: ["rpc"],
async start(env, { rpc }) {
let isDemoDataActiveProm;
return {
isDemoDataActive() {
if (!isDemoDataActiveProm) {
isDemoDataActiveProm = rpc("/base_setup/demo_active");
}
return isDemoDataActiveProm;
},
};
},
};
registry.category("services").add("demo_data", demoDataService);
@@ -1,37 +0,0 @@
/** @odoo-module */
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
const { Component, onWillStart } = owl;
/**
* Widget in the settings that handles the "Developer Tools" section.
* Can be used to enable/disable the debug modes.
* Can be used to load the demo data.
*/
class ResConfigDevTool extends Component {
setup() {
this.isDebug = Boolean(odoo.debug);
this.isAssets = odoo.debug.includes("assets");
this.isTests = odoo.debug.includes("tests");
this.action = useService("action");
this.demo = useService("demo_data");
onWillStart(async () => {
this.isDemoDataActive = await this.demo.isDemoDataActive();
});
}
/**
* Forces demo data to be installed in a database without demo data installed.
*/
onClickForceDemo() {
this.action.doAction("base.demo_force_install_action");
}
}
ResConfigDevTool.template = "res_config_dev_tool";
registry.category("view_widgets").add("res_config_dev_tool", ResConfigDevTool);
@@ -1,24 +0,0 @@
/** @odoo-module */
import { registry } from "@web/core/registry";
import { session } from "@web/session";
const { Component } = owl;
const { DateTime } = luxon;
/**
* Widget in the settings that handles a part of the "About" section.
* Contains info about the odoo version, database expiration date and copyrights.
*/
class ResConfigEdition extends Component {
setup() {
this.serverVersion = session.server_version;
this.expirationDate = session.expiration_date
? DateTime.fromSQL(session.expirationDate).toLocaleString(DateTime.DATE_FULL)
: DateTime.now().plus({ days: 30 }).toLocaleString(DateTime.DATE_FULL);
}
}
ResConfigEdition.template = "res_config_edition";
registry.category("view_widgets").add("res_config_edition", ResConfigEdition);
@@ -1,124 +0,0 @@
/** @odoo-module */
import { registry } from "@web/core/registry";
import { _t } from "@web/core/l10n/translation";
import { unique } from "@web/core/utils/arrays";
import { useService } from "@web/core/utils/hooks";
const { Component, useState, onWillStart } = owl;
class ResConfigInviteUsers extends Component {
setup() {
this.orm = useService("orm");
this.invite = useService("user_invite");
this.action = useService("action");
this.notification = useService("notification");
this.state = useState({
status: "idle", // idle, inviting
emails: "",
invite: null,
});
onWillStart(async () => {
this.state.invite = await this.invite.fetchData();
});
}
/**
* @param {string} email
* @returns {boolean} true if the given email address is valid
*/
validateEmail(email) {
const re = /^([a-z0-9][-a-z0-9_\+\.]*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,63}(?:\.[a-z]{2})?)$/i;
return re.test(email);
}
get emails() {
return unique(
this.state.emails
.split(/[ ,;\n]+/)
.map((email) => email.trim())
.filter((email) => email.length)
);
}
validate() {
if (!this.emails.length) {
throw new Error(_t("Empty email address"));
}
const invalidEmails = [];
for (const email of this.emails) {
if (!this.validateEmail(email)) {
invalidEmails.push(email);
}
}
if (invalidEmails.length) {
throw new Error(`${_t("Invalid email address")}${ invalidEmails.length > 1 ? "es" : "" }: ${invalidEmails.join(", ")}`);
}
}
get inviteButtonText() {
if (this.state.status === "inviting") {
return _t("Inviting...");
}
return _t("Invite");
}
onClickMore(ev) {
this.action.doAction(this.state.invite.action_pending_users);
}
onClickUser(ev, user) {
const action = Object.assign({}, this.state.invite.action_pending_users, {
res_id: user[0],
});
this.action.doAction(action);
}
onKeydownUserEmails(ev) {
const keys = ["Enter", "Tab", ","];
if (keys.includes(ev.key)) {
if (ev.key === "Tab" && !this.emails.length) {
return;
}
ev.preventDefault();
this.sendInvite();
}
}
/**
* Send invitation for valid and unique email addresses
*
* @private
*/
async sendInvite() {
try {
this.validate();
} catch (e) {
this.notification.add(e.message, { type: "danger" });
return;
}
this.state.status = "inviting";
const pendingUserEmails = this.state.invite.pending_users.map((user) => user[1]);
const emailsLeftToProcess = this.emails.filter(
(email) => !pendingUserEmails.includes(email)
);
try {
if (emailsLeftToProcess) {
await this.orm.call("res.users", "web_create_users", [emailsLeftToProcess]);
this.state.invite = await this.invite.fetchData(true);
}
} finally {
this.state.emails = "";
this.state.status = "idle";
}
}
}
ResConfigInviteUsers.template = "res_config_invite_users";
registry.category("view_widgets").add("res_config_invite_users", ResConfigInviteUsers);
@@ -1,20 +0,0 @@
/** @odoo-modules */
import { registry } from "@web/core/registry";
export const userInviteService = {
dependencies: ["rpc"],
async start(env, { rpc }) {
let dataProm;
return {
fetchData(reload = false) {
if (!dataProm || reload) {
dataProm = rpc("/base_setup/data");
}
return dataProm;
},
};
},
};
registry.category("services").add("user_invite", userInviteService);
@@ -1,17 +0,0 @@
.o_setting_container {
.o_web_settings_user {
font-size: 95%;
font-weight: 500;
}
}
.o_doc_link {
text-decoration: none;
font-weight: normal;
&::after{
content: "\f059"; //fa-question-circle
font-family: 'FontAwesome';
font-size: 1.2rem;
}
}
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<template>
<div t-name='res_config_dev_tool' owl="1">
<div id="developer_tool">
<h2>Developer Tools</h2>
<div class="row mt16 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box" id="devel_tool">
<div class="o_setting_right_pane">
<a t-if="!isDebug" class="d-block" href="?debug=1">Activate the developer mode</a>
<a t-if="!isAssets" class="d-block" href="?debug=assets">Activate the developer mode (with assets)</a>
<a t-if="!isTests" class="d-block" href="?debug=assets,tests">Activate the developer mode (with tests assets)</a>
<a t-if="isDebug" class="d-block" href="?debug=">Deactivate the developer mode</a>
<a t-if="isDebug and !isDemoDataActive" t-on-click.prevent="onClickForceDemo" class="o_web_settings_force_demo" href="#">Load demo data</a>
</div>
</div>
</div>
</div>
</div>
</template>
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<template>
<div t-name='res_config_edition' owl="1">
<div class="col-12 o_setting_box" id="edition">
<div class="o_setting_right_pane">
<div class="user-heading">
<h3 class="px-0">
Odoo <t t-esc="serverVersion"/>
(Community Edition)
</h3>
</div>
<div>
<div class="tab-content">
<div role="tabpanel" id="settings" class="tab-pane active text-muted o_web_settings_compact_subtitle">
<small>Copyright © 2004 <a target="_blank" href="https://www.odoo.com" style="text-decoration: underline;">Odoo S.A.</a> <a id="license" target="_blank" href="http://www.gnu.org/licenses/lgpl.html" style="text-decoration: underline;">GNU LGPL Licensed</a></small>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<templates>
<div t-name='res_config_invite_users' owl="1">
<p class="o_form_label">Invite New Users</p>
<div class="d-flex">
<input t-model="state.emails" t-att-disabled="state.status != 'idle'" class="o_user_emails o_input mt8" t-on-keydown="onKeydownUserEmails" type="text" placeholder="Enter e-mail address"/>
<button t-att-disabled="state.status != 'idle'" class="btn btn-primary o_web_settings_invite" t-on-click="sendInvite"><strong><t t-esc="inviteButtonText"/></strong></button>
</div>
<t t-if="state.invite.pending_users.length">
<p class="o_form_label pt-3">Pending Invitations:</p>
<span t-foreach="state.invite.pending_users" t-as="pending" t-key="pending[0]">
<a href="#" class="badge rounded-pill text-primary o_web_settings_user" t-on-click.prevent="(ev) => this.onClickUser(ev, pending)"> <t t-esc="pending[1]"/> </a>
</span>
<t t-if="state.invite.pending_users.length &lt; state.invite.pending_count">
<br/>
<a href="#" class="o_web_settings_more" t-on-click.prevent="onClickMore"><t t-esc="state.invite.pending_count - state.invite.pending_users.length"/> more </a>
</t>
</t>
</div>
</templates>