summaryrefslogtreecommitdiff
path: root/addons/base_setup/static
diff options
context:
space:
mode:
authoraca <aca@odoo.com>2019-06-19 09:14:43 +0000
committerYannick Tivisse <yti@odoo.com>2019-07-26 09:53:46 +0000
commit78565b1dc933692abba46a73f2298b7ea8e03c88 (patch)
tree05006de48a2099a35c39dc5571d4929ab0135a3b /addons/base_setup/static
parenta8893ad2994aad05961bdddcecb3e2c55f301ed5 (diff)
[REM] web_settings_dashboard: Merge module into base_setup
Purpose ======= Currently, when we click on “Settings” on the Home Dashboard, we arrive on a new Dashboard with several pieces of information like Installed Apps, invite new users, or translations. Some informations are reachable in several ways, which is not necessary. We would like to remove this page and replace it with the General Settings page directly. That makes more sense to the user who click on “Settings”. The present informations will be dispatched in the menu or in the general settings for a better usability. Specification ============= This commit move code from web_settings_dashboard in order to put the features in settings directly. To do so, we choose to move code to base_setup, and create widget on the settings form view to keep features. Concerned features are: invite users, dev tools, odoo edition number and IAP account link. TaskID: 2006910 closes odoo/odoo#34290 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Diffstat (limited to 'addons/base_setup/static')
-rw-r--r--addons/base_setup/static/src/img/app_store.pngbin0 -> 14016 bytes
-rw-r--r--addons/base_setup/static/src/img/google_play.pngbin0 -> 16858 bytes
-rw-r--r--addons/base_setup/static/src/js/res_config_dev_tool.js31
-rw-r--r--addons/base_setup/static/src/js/res_config_edition.js21
-rw-r--r--addons/base_setup/static/src/js/res_config_invite_users.js214
-rw-r--r--addons/base_setup/static/src/scss/settings.scss67
-rw-r--r--addons/base_setup/static/src/xml/res_config_dev_tool.xml19
-rw-r--r--addons/base_setup/static/src/xml/res_config_edition.xml24
-rw-r--r--addons/base_setup/static/src/xml/res_config_invite_users.xml54
9 files changed, 430 insertions, 0 deletions
diff --git a/addons/base_setup/static/src/img/app_store.png b/addons/base_setup/static/src/img/app_store.png
new file mode 100644
index 00000000000..65320714c06
--- /dev/null
+++ b/addons/base_setup/static/src/img/app_store.png
Binary files differ
diff --git a/addons/base_setup/static/src/img/google_play.png b/addons/base_setup/static/src/img/google_play.png
new file mode 100644
index 00000000000..229d939d728
--- /dev/null
+++ b/addons/base_setup/static/src/img/google_play.png
Binary files differ
diff --git a/addons/base_setup/static/src/js/res_config_dev_tool.js b/addons/base_setup/static/src/js/res_config_dev_tool.js
new file mode 100644
index 00000000000..b407a731a35
--- /dev/null
+++ b/addons/base_setup/static/src/js/res_config_dev_tool.js
@@ -0,0 +1,31 @@
+odoo.define('base_setup.ResConfigDevTool', function (require) {
+ "use strict";
+
+ var config = require('web.config');
+ var Widget = require('web.Widget');
+ var widget_registry = require('web.widget_registry');
+
+ var ResConfigDevTool = Widget.extend({
+ template: 'res_config_dev_tool',
+
+ init: function () {
+ this._super.apply(this, arguments);
+ this.isDebug = config.isDebug();
+ this.isAssets = config.isDebug("assets");
+ this.isTests = config.isDebug("tests");
+ },
+
+ willStart: function () {
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ return self._rpc({
+ route: '/base_setup/demo_active',
+ }).then(function (demo_active) {
+ self.demo_active = demo_active;
+ });
+ });
+ },
+ });
+
+ widget_registry.add('res_config_dev_tool', ResConfigDevTool);
+});
diff --git a/addons/base_setup/static/src/js/res_config_edition.js b/addons/base_setup/static/src/js/res_config_edition.js
new file mode 100644
index 00000000000..bdc3f434f88
--- /dev/null
+++ b/addons/base_setup/static/src/js/res_config_edition.js
@@ -0,0 +1,21 @@
+odoo.define('base_setup.ResConfigEdition', function (require) {
+ "use strict";
+
+ var Widget = require('web.Widget');
+ var widget_registry = require('web.widget_registry');
+ var session = require ('web.session');
+
+ var ResConfigEdition = Widget.extend({
+ template: 'res_config_edition',
+
+ /**
+ * @override
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ this.server_version = session.server_version;
+ },
+ });
+
+ widget_registry.add('res_config_edition', ResConfigEdition);
+});
diff --git a/addons/base_setup/static/src/js/res_config_invite_users.js b/addons/base_setup/static/src/js/res_config_invite_users.js
new file mode 100644
index 00000000000..653a130868c
--- /dev/null
+++ b/addons/base_setup/static/src/js/res_config_invite_users.js
@@ -0,0 +1,214 @@
+odoo.define('base_setup.ResConfigInviteUsers', function (require) {
+ "use strict";
+
+ var Widget = require('web.Widget');
+ var widget_registry = require('web.widget_registry');
+ var core = require('web.core');
+ var framework = require('web.framework');
+
+ var QWeb = core.qweb;
+ var _t = core._t;
+
+ var ResConfigInviteUsers = Widget.extend({
+ template: 'res_config_invite_users',
+
+ events: {
+ 'click .o_web_settings_invite': '_onClickInvite',
+ 'click .o_web_settings_access_rights': '_onClickAccessRights',
+ 'click .o_web_settings_user': '_onClickUser',
+ 'click .o_web_settings_more': '_onClickMore',
+ 'click .o_badge_remove': '_onClickBadgeRemove',
+ 'keydown .o_user_emails': '_onKeydownUserEmails',
+ },
+
+ /**
+ * @override
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ this.emails = [];
+ },
+
+ willStart: function () {
+ var self = this;
+
+ return this._super.apply(this, arguments).then(function () {
+ return self.load();
+ });
+ },
+
+ load: function () {
+ var self = this;
+
+ return this._rpc({
+ route: '/base_setup/data',
+ }).then(function (data) {
+ self.active_users = data.active_users;
+ self.pending_users = data.pending_users;
+ self.pending_count = data.pending_count;
+ self.resend_invitation = data.resend_invitation || false;
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Creates and appends badges for valid and unique email addresses
+ *
+ * @private
+ */
+ _createBadges: function () {
+ var $userEmails = this.$('.o_user_emails');
+ var value = $userEmails.val().trim();
+ if (value) {
+ // filter out duplicates
+ var emails = _.uniq(value.split(/[ ,;\n]+/));
+
+ // filter out invalid email addresses
+ var invalidEmails = _.reject(emails, this._validateEmail);
+ if (invalidEmails.length) {
+ this.do_warn(_.str.sprintf(_t('The following email addresses are invalid: %s.'), invalidEmails.join(', ')));
+ }
+ emails = _.difference(emails, invalidEmails);
+
+ if (!this.resend_invitation) {
+ // filter out already processed or pending addresses
+ var pendingEmails = _.map(this.pending_users, function (info) {
+ return info[1];
+ });
+ var existingEmails = _.intersection(emails, this.emails.concat(pendingEmails));
+ if (existingEmails.length) {
+ this.do_warn(_.str.sprintf(_t('The following email addresses already exist: %s.'), existingEmails.join(', ')));
+ }
+ emails = _.difference(emails, existingEmails);
+ }
+
+ // add valid email addresses, if any
+ if (emails.length) {
+ this.emails = this.emails.concat(emails);
+ this.$('.o_web_settings_invitation_form').append(QWeb.render('EmailBadge', {emails: emails}));
+ $userEmails.val('');
+ }
+ }
+ },
+ /**
+ * Removes a given badge from the DOM, and its associated email address
+ *
+ * @private
+ * @param {jQueryElement} $badge
+ */
+ _removeBadge: function ($badge) {
+ var email = $badge.text().trim();
+ this.emails = _.without(this.emails, email);
+ $badge.remove();
+ },
+ /**
+ * @private
+ * @param {string} email
+ * @returns {boolean} true if the given email address is valid
+ */
+ _validateEmail: function (email) {
+ var re = /^([a-z0-9][-a-z0-9_\+\.]*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,63}(?:\.[a-z]{2})?)$/i;
+ return re.test(email);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickAccessRights: function (e) {
+ e.preventDefault();
+ this.do_action('base.action_res_users');
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickBadgeRemove: function (ev) {
+ var $badge = $(ev.target).closest('.badge');
+ this._removeBadge($badge);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickInvite: function (ev) {
+ var self = this;
+ this._createBadges();
+ if (this.emails.length) {
+ var $button = $(ev.target);
+ $button.button('loading');
+ this._rpc({
+ model: 'res.users',
+ method: 'web_create_users',
+ args: [this.emails],
+ }).then(function () {
+ return self.load().then(function () {
+ self.renderElement();
+ });
+ }).guardedCatch(function () {
+ // NOTE Not sure that this is needed
+ $button.button('reset');
+ });
+ }
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickMore: function(ev) {
+ ev.preventDefault();
+ this.do_action({
+ name: _t('Users'),
+ type: 'ir.actions.act_window',
+ view_mode: 'tree,form',
+ res_model: 'res.users',
+ domain: [['log_ids', '=', false]],
+ context: {
+ search_default_no_share: true,
+ },
+ views: [[false, 'list'], [false, 'form']],
+ });
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickUser: function (ev) {
+ ev.preventDefault();
+ var user_id = $(e.currentTarget).data('user-id');
+ this.do_action({
+ type: 'ir.actions.act_window',
+ res_model: 'res.users',
+ view_mode: 'form',
+ views: [[false, 'form']],
+ res_id: user_id,
+ });
+ },
+ /**
+ * @private
+ * @param {KeyboardEvent} ev
+ */
+ _onKeydownUserEmails: function (ev) {
+ var $userEmails = this.$('.o_user_emails');
+ var keyCodes = [$.ui.keyCode.TAB, $.ui.keyCode.COMMA, $.ui.keyCode.ENTER, $.ui.keyCode.SPACE];
+ if (_.contains(keyCodes, ev.which)) {
+ ev.preventDefault();
+ this._createBadges();
+ }
+ // remove last badge on backspace
+ if (ev.which === $.ui.keyCode.BACKSPACE && this.emails.length && !$userEmails.val()) {
+ this._removeBadge(this.$('.o_web_settings_invitation_form .badge:last'));
+ }
+ },
+ });
+
+ widget_registry.add('res_config_invite_users', ResConfigInviteUsers);
+
+});
diff --git a/addons/base_setup/static/src/scss/settings.scss b/addons/base_setup/static/src/scss/settings.scss
new file mode 100644
index 00000000000..2f385a3ad10
--- /dev/null
+++ b/addons/base_setup/static/src/scss/settings.scss
@@ -0,0 +1,67 @@
+.o_web_settings {
+
+ $bg-dashboard-col: #FFF;
+
+ @mixin o-web-settings-card-card {
+ box-shadow: 0 1px 2px 0 rgba(0,0,0,.14);
+ background: $bg-dashboard-col;
+ border-radius: 2px;
+ }
+
+ background: #F7F7F7;
+ height: 100%;
+
+ .o_web_settings_col {
+ > div > hr {
+ margin: 12px -18px 15px -18px;
+ border-color: #CBCBCB;
+ }
+
+ > div {
+ @include o-web-settings-card-card;
+ padding: 25px 18px 18px 18px;
+
+ .o_web_settings_header {
+ font-size: 22px;
+ margin-bottom: 8px;
+ }
+ }
+ .btn.o_browse_apps, .btn.o_web_settings_invitations {
+ margin-top: 12px;
+ }
+ .o_web_settings_compact_subtitle {
+ line-height: 12px;
+ display: block;
+ }
+ .o_web_settings_invitations {
+ .o_web_settings_invitation_form {
+ text-align: left;
+ > textarea {
+ resize: vertical;
+ width: 100%;
+ }
+ }
+ }
+ .o_web_settings_planner {
+ .progress {
+ height: 10px;
+ background-color: darken($bg-dashboard-col, 15%);
+ cursor: pointer;
+ margin-bottom: 30px;
+ }
+ .o_web_settings_planner_progress_text {
+ font-size: 18px;
+ padding-right: 0px;
+ padding-top: 3px;
+ }
+ .o_web_settings_planner_progress_bar {
+ padding-left: 10px;
+ }
+ .o_web_settings_progress_title {
+ font-weight: bold;
+ cursor: pointer;
+ color: $o-brand-primary;
+ }
+ }
+ }
+}
diff --git a/addons/base_setup/static/src/xml/res_config_dev_tool.xml b/addons/base_setup/static/src/xml/res_config_dev_tool.xml
new file mode 100644
index 00000000000..ab108bd2518
--- /dev/null
+++ b/addons/base_setup/static/src/xml/res_config_dev_tool.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<template>
+ <div t-name='res_config_dev_tool'>
+ <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="!widget.isDebug" class="d-block" href="?debug=1">Activate the developer mode</a>
+ <a t-if="!widget.isAssets" class="d-block" href="?debug=assets">Activate the developer mode (with assets)</a>
+ <a t-if="!widget.isTests" class="d-block" href="?debug=assets,tests">Activate the developer mode (with tests assets)</a>
+ <a t-if="widget.isDebug" class="d-block" href="?debug=">Deactivate the developer mode</a>
+ <a t-if="!widget.isDebug &amp;&amp; !widget.demo_active" class="o_web_settings_force_demo" href="#">Load demo data</a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/addons/base_setup/static/src/xml/res_config_edition.xml b/addons/base_setup/static/src/xml/res_config_edition.xml
new file mode 100644
index 00000000000..31485c33ab9
--- /dev/null
+++ b/addons/base_setup/static/src/xml/res_config_edition.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- TODO See if this has to be editable in some way, see if it is easy for someone to change this -->
+<!-- TODO Also see what is done to override the (Community Edition) -->
+<template>
+ <div t-name='res_config_edition'>
+ <div class="col-12 o_setting_box" id="edition">
+ <div class="o_setting_right_pane">
+ <div class="user-heading">
+ <h3>
+ Odoo <t t-esc="widget.server_version"/>
+ (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 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>
diff --git a/addons/base_setup/static/src/xml/res_config_invite_users.xml b/addons/base_setup/static/src/xml/res_config_invite_users.xml
new file mode 100644
index 00000000000..ba9bd5fbc7e
--- /dev/null
+++ b/addons/base_setup/static/src/xml/res_config_invite_users.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<templates>
+ <div t-name='res_config_invite_users'>
+ <div class="row mt16 o_settings_container">
+ <div class='col-12 col-lg-6 o_setting_box'>
+ <div class='o_setting_right_pane'>
+ <t t-if="widget.active_users">
+ <div class='o_form_label'>
+ <t t-esc="widget.active_users"></t>
+ <t t-if="widget.active_users &lt;= 1"> Active User</t>
+ <t t-if="widget.active_users &gt; 1">Active Users</t>
+ </div>
+ </t>
+ <br/>
+ <a href="#" class="o_web_settings_access_rights d-flex">
+ <i class='fa fa-fw o_button_icon fa-arrow-right'></i>
+ Manage Users
+ </a>
+ </div>
+ </div>
+ <div class="col-12 col-lg-6 o_setting_box">
+ <div class="o_setting_right_pane">
+ <t t-if="widget.pending_users.length">
+ <p class="o_form_label">Pending Invitations:</p>
+ <span t-foreach="widget.pending_users" t-as="pending">
+ <a href="#" class="badge badge-pill o_web_settings_user" t-att-data-user-id="pending[0]"> <t t-esc="pending[1]"/> </a>
+ </span>
+ <t t-if="widget.pending_users.length &lt; widget.pending_count">
+ <br/>
+ <a href="#" class="o_web_settings_more"><t t-esc="widget.pending_count - widget.pending_users.length"/> more </a>
+ </t>
+ </t>
+ </div>
+ </div>
+ <div class='col-12 col-lg-6 o_setting_box'>
+ <div class='o_setting_right_pane'>
+ <span class="o_form_label">Invite New Users:</span>
+ <span class="o_web_settings_invitation_form"/>
+ <input class="o_user_emails o_input mt8" type="text" placeholder="Enter e-mail addresses"/>
+ <button class="btn btn-primary btn-block o_web_settings_invite mt16" data-loading-text="Inviting..."><strong>Invite</strong></button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <t t-name="EmailBadge">
+ <span t-foreach="emails" t-as="email" class="badge badge-pill">
+ <span class="o_badge_text">
+ <t t-esc='email'/>
+ </span>
+ <a href="#" class="fa fa-times o_badge_remove" title="Remove Email" aria-label="Remove Email" role="button"/>
+ </span>
+ </t>
+</templates>