[IMP] settings: Improve general UX (back2basics)

TaskID: 2043133

closes odoo/odoo#35382

Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
jbm-odoo
2019-08-13 12:32:30 +00:00
committed by Yannick Tivisse
parent 054baf94a6
commit 853a773ee4
16 changed files with 181 additions and 270 deletions
@@ -5,7 +5,7 @@
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<!-- add before the Access Rights section -->
<xpath expr="//div[@id='access_rights']" position="before">
<xpath expr="//div[@id='allow_import']" position="before">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
+15 -1
View File
@@ -17,7 +17,7 @@
<field name="state" widget="statusbar"/>
</xpath>
<xpath expr="//sheet/div[@name='button_box']" position="after">
<xpath expr="//sheet" position="before">
<div class="alert alert-success text-center o_form_header" attrs="{'invisible': [('signup_valid', '!=', True)]}" role="status">
<a class="close" data-dismiss="alert" href="#" aria-label="Close">x</a>
<div attrs="{'invisible': [('state', '!=', 'active')]}">
@@ -33,4 +33,18 @@
</field>
</record>
<record id="view_users_state_tree" model="ir.ui.view">
<field name="name">res.users.tree.inherit</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="attributes">
<attribute name="decoration-info">state == 'new'</attribute>
</xpath>
<xpath expr="//field[@name='login_date']" position="after">
<field name="state" invisible="1"/>
</xpath>
</field>
</record>
</odoo>
@@ -42,8 +42,11 @@ class ResConfigSettings(models.TransientModel):
paperformat_id = fields.Many2one(related="company_id.paperformat_id", string='Paper format', readonly=False)
external_report_layout_id = fields.Many2one(related="company_id.external_report_layout_id", readonly=False)
show_effect = fields.Boolean(string="Show Effect", config_parameter='base_setup.show_effect')
company_count = fields.Integer('Number of Companies', readonly=True, compute="_compute_company_count")
company_count = fields.Integer('Number of Companies', compute="_compute_company_count")
active_user_count = fields.Integer('Number of Active Users', compute="_compute_active_user_count")
language_count = fields.Integer('Number of Languages', compute="_compute_language_count")
company_name = fields.Char(related="company_id.display_name", string="Company Name")
company_informations = fields.Text(compute="_compute_company_informations")
@api.model
def get_values(self):
@@ -65,7 +68,11 @@ class ResConfigSettings(models.TransientModel):
'res_model': 'res.company',
'res_id': self.env.company.id,
'target': 'current',
'context': {
'form_view_initial_mode': 'edit',
},
}
def open_default_user(self):
action = self.env.ref('base.action_res_users').read()[0]
action['res_id'] = self.env.ref('base.default_user').id
@@ -95,8 +102,27 @@ class ResConfigSettings(models.TransientModel):
for record in self:
record.company_count = company_count
@api.depends('company_id')
def _compute_active_user_count(self):
active_user_count = self.env['res.users'].sudo().search_count([('share', '=', False)])
for record in self:
record.active_user_count = active_user_count
@api.depends('company_id')
def _compute_language_count(self):
language_count = len(self.env['res.lang'].get_installed())
for record in self:
record.language_count = language_count
@api.depends('company_id')
def _compute_company_informations(self):
informations = '%s\n' % self.company_id.street if self.company_id.street else ''
informations += '%s\n' % self.company_id.street2 if self.company_id.street2 else ''
informations += '%s' % self.company_id.zip if self.company_id.zip else ''
informations += ' - %s\n' % self.company_id.city if self.company_id.city else '\n'
informations += '%s\n' % self.company_id.state_id.display_name if self.company_id.state_id else ''
informations += '%s' % self.company_id.country_id.display_name if self.company_id.country_id else ''
informations += '\nVAT: %s' % self.company_id.vat if self.company_id.vat else ''
for record in self:
record.company_informations = informations
@@ -4,9 +4,7 @@ odoo.define('base_setup.ResConfigInviteUsers', function (require) {
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({
@@ -14,10 +12,8 @@ odoo.define('base_setup.ResConfigInviteUsers', function (require) {
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',
},
@@ -55,12 +51,26 @@ odoo.define('base_setup.ResConfigInviteUsers', function (require) {
//--------------------------------------------------------------------------
/**
* Creates and appends badges for valid and unique email addresses
* @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);
},
/**
* Send invitation for valid and unique email addresses
*
* @private
*/
_createBadges: function () {
_invite: function () {
var self = this;
var $userEmails = this.$('.o_user_emails');
$userEmails.prop('disabled', true);
this.$('.o_web_settings_invite').prop('disabled', true);
var value = $userEmails.val().trim();
if (value) {
// filter out duplicates
@@ -85,84 +95,46 @@ odoo.define('base_setup.ResConfigInviteUsers', function (require) {
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('');
this._rpc({
model: 'res.users',
method: 'web_create_users',
args: [emails],
}).then(function () {
return self.load().then(function () {
self.renderElement();
self.$('.o_user_emails').focus();
});
});
} else {
$userEmails.prop('disabled', false);
this.$('.o_web_settings_invite').prop('disabled', false);
self.$('.o_user_emails').focus();
}
}
},
/**
* 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) {
if (this.$('.o_user_emails').val().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');
});
return this._invite();
}
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickMore: function(ev) {
_onClickMore: function (ev) {
ev.preventDefault();
this.do_action({
name: _t('Users'),
@@ -182,7 +154,7 @@ odoo.define('base_setup.ResConfigInviteUsers', function (require) {
*/
_onClickUser: function (ev) {
ev.preventDefault();
var user_id = $(e.currentTarget).data('user-id');
var user_id = $(ev.currentTarget).data('user-id');
this.do_action({
type: 'ir.actions.act_window',
res_model: 'res.users',
@@ -196,15 +168,10 @@ odoo.define('base_setup.ResConfigInviteUsers', function (require) {
* @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];
var keyCodes = [$.ui.keyCode.TAB, $.ui.keyCode.COMMA, $.ui.keyCode.ENTER];
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'));
this._invite();
}
},
});
@@ -1,67 +1,6 @@
.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;
}
}
.o_setting_container {
.o_web_settings_user {
font-size: 95%;
font-weight: 500;
}
}
@@ -1,54 +1,21 @@
<?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>
<p class="o_form_label">Invite New Users</p>
<div class="d-flex">
<input class="o_user_emails o_input mt8" type="text" placeholder="Enter e-mail address"/>
<button class="btn btn-primary o_web_settings_invite" data-loading-text="Inviting..."><strong>Invite</strong></button>
</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'/>
<t t-if="widget.pending_users.length">
<p class="o_form_label pt-3">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>
<a href="#" class="fa fa-times o_badge_remove" title="Remove Email" aria-label="Remove Email" role="button"/>
</span>
</t>
<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>
</templates>
+1
View File
@@ -2,6 +2,7 @@
<odoo>
<template id="assets_backend" name="dev tool assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/base_setup/static/src/scss/settings.scss"/>
<script type="text/javascript" src="/base_setup/static/src/js/res_config_dev_tool.js"></script>
<script type="text/javascript" src="/base_setup/static/src/js/res_config_edition.js"></script>
<script type="text/javascript" src="/base_setup/static/src/js/res_config_invite_users.js"></script>
@@ -8,45 +8,53 @@
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<div class="app_settings_block" data-string="General Settings" string="General Settings" data-key="general_settings">
<div id='about'>
<h2>About</h2>
<div id="invite_users">
<h2>Users</h2>
<div class="row mt16 o_settings_container">
<div class='col-12 col-lg-6 o_setting_box' id='appstore'>
<div class="d-flex">
<div class="o_setting_right_pane">
<!-- FIXME Those links are defined directly in the template which means that we will have to
update the template code is the link ever changes -->
<a class="d-block mx-auto" href="https://play.google.com/store/apps/details?id=com.odoo.mobile" target="blank">
<img alt="On Google Play" class="d-block mx-auto img img-fluid" src="/base_setup/static/src/img/google_play.png"/>
</a>
</div>
<div>
<a class='d-block mx-auto' href="https://itunes.apple.com/us/app/odoo/id1272543640" target="blank">
<img alt="On Apple Store" class="d-block mx-auto img img-fluid" src="/base_setup/static/src/img/app_store.png"/>
</a>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<span class="fa fa-lg fa-users"/>
<field name='active_user_count' class="w-auto pl-3 font-weight-bold"/>
<span class='o_form_label' attrs="{'invisible':[('active_user_count', '&gt;', '1')]}">
Active User
</span>
<span class='o_form_label' attrs="{'invisible':[('active_user_count', '&lt;=', '1')]}">
Active Users
</span>
<br/>
<button name="%(base.action_res_users)d" icon="fa-arrow-right" type="action" string="Manage Users" class="btn-link o_web_settings_access_rights"/>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<widget name='res_config_invite_users'/>
</div>
</div>
<widget name='res_config_edition'/>
</div>
</div>
<div id='invite_users'>
<h2>Users</h2>
<widget name='res_config_invite_users'/>
</div>
<div id="companies">
<h2>Companies</h2>
<div class='row mt16 o_settings_container'>
<div class='col-xs-12 col-md-6 o_setting_box'>
<div class='o_setting_right_pane'>
<!-- TODO This is not an ideal solution but it looks ok on the interface -->
<div class="w-50">
<field name='company_count' class="w-auto pl-1"/>
<span class='o_form_label'>
companies
</span>
</div>
<div class="row mt16 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<field name="company_name" class="font-weight-bold"/>
<br/>
<field name="company_informations" class="text-muted" style="width: 90%;"/>
<br/>
<button name="open_company" icon="fa-arrow-right" type="object" string="Update Info" class="btn-link"/>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<field name='company_count' class="w-auto pl-1 font-weight-bold"/>
<span class="o_form_label">
Companies
</span>
<br/>
<button name="%(base.action_res_company_form)d" icon="fa-arrow-right" type="action" string="Manage Companies" class="btn-link"/>
</div>
</div>
@@ -60,7 +68,7 @@
<div class='o_setting_right_pane'>
<!-- TODO This is not an ideal solution but it looks ok on the interface -->
<div class="w-50">
<field name="language_count" class="w-auto pl-1"/>
<field name="language_count" class="w-auto pl-1 font-weight-bold"/>
<span class="o_form_label">
Languages
</span>
@@ -153,7 +161,7 @@
<field name="user_default_rights"/>
</div>
<div class="o_setting_right_pane">
<label string="Access Rights" for="user_default_rights"/>
<label string="Default Access Rights" for="user_default_rights"/>
<div class="text-muted">
Set custom access rights for new users
</div>
@@ -164,7 +172,7 @@
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="col-12 col-lg-6 o_setting_box" groups="base.group_no_one" id="allow_import">
<div class="o_setting_left_pane">
<field name="module_base_import" />
</div>
@@ -189,36 +197,17 @@
</div>
<div id="multi_company" groups="base.group_multi_company">
<field name="company_id" invisible="1"/>
<h2>Multi-companies</h2>
<h2>Multi-Company</h2>
<div class="row mt16 o_settings_container" name="multi">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<label string="Multi-companies" for="multi_company"/>
<div class="text-muted">
Manage multiple legal entities with separate accounting
</div>
<div class="content-group">
<div class="mt16">
<button name="%(base.action_res_company_form)d" icon="fa-arrow-right" type="action" string="Companies" class="btn-link"/>
</div>
<div id="company_share_partner">
<field name="company_share_partner" class="oe_inline"/>
<label string="Common Contact Book" class="o_light_label" for="company_share_partner"/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" title="Configure company rules to automatically create SO/PO when one of your company sells/buys to another of your company." id="inter_company">
<div class="o_setting_left_pane">
<field name="module_inter_company_rules" widget="upgrade_boolean"/>
</div>
<div class="o_setting_right_pane">
<label string="Inter Company Flows" for="module_inter_company_rules"/>
<div>
<i class="fa fa-lg fa-building-o"/>
<span class="text-muted">
the creation of documents between your companies
</span>
<label string="Inter-Company Transactions" for="module_inter_company_rules"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific." groups="base.group_multi_company" role="img"/>
<div class="text-muted">
Automatically generate counterpart documents for orders/invoices between companies
</div>
<div class="content-group" attrs="{'invisible': [('module_inter_company_rules','=',False)]}" id="inter_companies_rules">
<div class="mt16 text-warning"><strong>Save</strong> this page and come back here to set up the feature.</div>
@@ -354,6 +343,28 @@
</div>
</div>
<widget name='res_config_dev_tool'/>
<div id='about'>
<h2>About</h2>
<div class="row mt16 o_settings_container">
<div class='col-12 col-lg-6 o_setting_box' id='appstore'>
<div class="d-flex">
<div class="o_setting_right_pane">
<!-- FIXME Those links are defined directly in the template which means that we will have to
update the template code is the link ever changes -->
<a class="d-block mx-auto" href="https://play.google.com/store/apps/details?id=com.odoo.mobile" target="blank">
<img alt="On Google Play" class="d-block mx-auto img img-fluid" src="/base_setup/static/src/img/google_play.png"/>
</a>
</div>
<div>
<a class='d-block mx-auto' href="https://itunes.apple.com/us/app/odoo/id1272543640" target="blank">
<img alt="On Apple Store" class="d-block mx-auto img img-fluid" src="/base_setup/static/src/img/app_store.png"/>
</a>
</div>
</div>
</div>
<widget name='res_config_edition'/>
</div>
</div>
</div>
</xpath>
</field>
+1 -1
View File
@@ -28,7 +28,7 @@ if records:
</div>
</div>
<div class='o_setting_right_pane'>
<button name="%(iap.open_iap_account)d" icon="fa-arrow-right" type="action" string="Go To My Portal" class="btn-link"/>
<button name="%(iap.open_iap_account)d" icon="fa-arrow-right" type="action" string="View My Services" class="btn-link"/>
</div>
</div>
</div>
-1
View File
@@ -25,7 +25,6 @@ It adds two mixins :
""",
'data': [
'security/ir.model.access.csv',
'views/res_company_view.xml',
'views/phone_blacklist_views.xml',
],
'depends': [
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_company_view_form_phone_validation" model="ir.ui.view">
<field name="name">res.company.view.form.phone_validation</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='phone']" position="after">
<field name="phone_international_format" groups="base.group_no_one"/>
</xpath>
</field>
</record>
</odoo>
@@ -7,7 +7,7 @@
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='social_media']" position="replace">
<group string="Social Media" name="social_media">
<group string="Social Media" name="social_media" groups="base.group_no_one">
<field name="social_twitter"/>
<field name="social_facebook"/>
<field name="social_github"/>
+3 -3
View File
@@ -21,7 +21,7 @@ class ResConfigSettings(models.TransientModel):
website_logo = fields.Binary(related='website_id.logo', readonly=False)
language_ids = fields.Many2many(related='website_id.language_ids', relation='res.lang',
readonly=False)
language_count = fields.Integer(string='Number of languages', compute='_compute_language_count', readonly=True)
website_language_count = fields.Integer(string='Number of languages', compute='_compute_website_language_count', readonly=True)
website_default_lang_id = fields.Many2one(
string='Default language', related='website_id.default_lang_id', readonly=False,
relation='res.lang')
@@ -114,9 +114,9 @@ class ResConfigSettings(models.TransientModel):
self.website_default_lang_id = language_ids[0]
@api.depends('language_ids')
def _compute_language_count(self):
def _compute_website_language_count(self):
for config in self:
config.language_count = len(self.language_ids)
config.website_language_count = len(self.language_ids)
def set_values(self):
super(ResConfigSettings, self).set_values()
@@ -38,7 +38,7 @@
</div>
<!-- !! Every fields inside this container should be website specific (related to website record) !! -->
<div class="row mt16 o_settings_container" id="website_settings" attrs="{'invisible': [('website_id', '=', False)]}">
<div class="col-12 o_setting_box" id="website_action_setting">
<div class="col-12 o_setting_box" id="website_action_setting" style="margin-left: 30px; margin-bottom: 16px;">
<button name="website_go_to" type="object" string="Go to Website" class="btn btn-primary" icon="fa-globe"/>
<button name="%(website.action_website_add_features)d" type="action" string="Add features" class="ml-2 btn btn-secondary" icon="fa-plus"/>
</div>
@@ -83,8 +83,8 @@
<field name="language_ids" widget="many2many_tags" options="{'no_create': True, 'no_open': True}"
attrs="{'required': [('website_id', '!=', False)]}"/>
</div>
<field name="language_count" invisible="1"/>
<div class="mt8" attrs="{'invisible':[('language_count', '&lt;', 2)]}">
<field name="website_language_count" invisible="1"/>
<div class="mt8" attrs="{'invisible':[('website_language_count', '&lt;', 2)]}">
<label class="o_light_label mr8" string="Default" for="website_default_lang_id"/>
<field name="website_default_lang_id" widget="selection" attrs="{'required': [('website_id', '!=', False)]}"/>
</div>
+2 -2
View File
@@ -14,8 +14,8 @@
<menuitem id="menu_management" name="Apps" sequence="310" web_icon="base,static/description/modules.png" groups="base.group_system"/>
<menuitem id="menu_administration_shortcut" parent="menu_administration" name="Custom Shortcuts" sequence="50"/>
<!-- FYI The group no_one on 'User & Companies' and 'Translations' is a FP/APR request -->
<menuitem id="menu_users" name="Users &amp; Companies" parent="menu_administration" sequence="0" groups="base.group_no_one"/>
<menuitem id="menu_translation" name="Translations" parent="menu_administration" sequence="1" groups="base.group_no_one"/>
<menuitem id="menu_users" name="Users &amp; Companies" parent="menu_administration" sequence="1"/>
<menuitem id="menu_translation" name="Translations" parent="menu_administration" sequence="2" groups="base.group_no_one"/>
<menuitem id="menu_translation_app" name="Application Terms" parent="menu_translation" sequence="4" groups="base.group_no_one"/>
<menuitem id="menu_translation_export" name="Import / Export" parent="menu_translation" sequence="3" groups="base.group_no_one"/>
<menuitem id="menu_config" name="General Settings" parent="menu_administration" sequence='3'/>
+4 -4
View File
@@ -18,7 +18,7 @@
<page string="General Information">
<group>
<group>
<field name="partner_id" readonly="1" required="0" groups="base.group_no_one"/>
<field name="partner_id" string="Contact" readonly="1" required="0" groups="base.group_no_one"/>
<label for="street" string="Address"/>
<div class="o_address_format">
<field name="street" placeholder="Street..." class="o_address_street"/>
@@ -28,11 +28,11 @@
<field name="zip" placeholder="ZIP" class="o_address_zip"/>
<field name="country_id" placeholder="Country" class="o_address_country" options='{"no_open": True}'/>
</div>
</group>
<group>
<field name="website" widget="url" placeholder="e.g. www.odoo.com"/>
<field name="phone"/>
<field name="email"/>
<field name="website" string="Website" widget="url" placeholder="e.g. www.odoo.com"/>
</group>
<group>
<field name="vat"/>
<field name="company_registry"/>
<field name="currency_id" options="{'no_create': True, 'no_open': True}" id="company_currency" context="{'active_test': False}"/>