[REF] web, *: restore views design
Since the new views merge, a lot of design elements were broken. This was particularly impacting the fields in the editable list view; indeed the editable list view is not using an inline form view anymore so the fields in the list were not properly styled as the LESS was still defined assuming the form view environment (for example the invalid fields were red for o2m fields in form view but not in editable list view even though they got the right CSS class). This commit refactor the LESS following these rules: - No more division of non-layout and layout rules. Dividing LESS rules in x_layout.less and x.less was a mistake. Many rules can be considered to be layout and not layout at the same time, developers always have to switch from one file part to the other, many CSS selectors (and rules!) are duplicated for nothing, ... - Field style is extracted from x_view.less and put in the new fields.less file. As before, the fields_extra.less will contain the rules specific to community so that the enterprise repo can override those by replacing the whole file. - Many classes have been renamed so that o_form_x_y becomes o_x_y as many classes can now be applied outside of form view. These classes should not be used in templates anyway. The commit also changes the DOM of fields so that it is more minimalist (no useless parent div, etc). Input elements are not automatically styled anymore, they have to get the o_input class explicitely. This allows to fix lots of small style bugs of previous versions (required monetary field had not the proper style, readonly m2m tags appeared as editable, ...). This also improves the LESS code. The editable list view should also completely stop flickering on chrome and firefox. The commit also removes the orange outline on list view dirty cells. The commit also removes deprecated static xml, LESS and other code. Notice there are still styles to restore/fix and LESS to improve.
This commit is contained in:
@@ -55,7 +55,7 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, {
|
||||
{mode: 'edit'});
|
||||
|
||||
self.name.appendTo(self.$('.statement_name_edition')).then(function () {
|
||||
self.name.$el.addClass('o_form_required');
|
||||
self.name.$el.addClass('o_required_modifier');
|
||||
});
|
||||
self.$('.statement_name').text(self._initialState.bank_statement_id.display_name);
|
||||
});
|
||||
@@ -458,7 +458,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
|
||||
self.$('.create').append($create);
|
||||
|
||||
function addRequiredStyle(widget) {
|
||||
widget.$el.addClass('o_form_required');
|
||||
widget.$el.addClass('o_required_modifier');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<a role="button" tabindex="0" class="js_payment_info fa fa-info-circle" t-att-index="line.index" style="margin-right:5px;"></a>
|
||||
</td>
|
||||
<td>
|
||||
<i class="o_form_field text-right o_payment_label">Paid on <t t-esc="line.date"></t></i>
|
||||
<i class="o_field_widget text-right o_payment_label">Paid on <t t-esc="line.date"></t></i>
|
||||
</td>
|
||||
</t>
|
||||
<td style="text-align:right;">
|
||||
|
||||
@@ -62,20 +62,20 @@ QUnit.module('account', {
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name="payments_widget"]').text().replace(/[\s\n\r]+/g, ' '),
|
||||
assert.strictEqual(form.$('.o_field_widget[name="payments_widget"]').text().replace(/[\s\n\r]+/g, ' '),
|
||||
" Paid on 04/25/2017 $ 555.00 ",
|
||||
"should display payment information");
|
||||
|
||||
form.$('.o_form_field[name="outstanding_credits_debits_widget"] .outstanding_credit_assign').trigger('click');
|
||||
form.$('.o_field_widget[name="outstanding_credits_debits_widget"] .outstanding_credit_assign').trigger('click');
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name="outstanding_credits_debits_widget"]').text().replace(/[\s\n\r]+/g, ' '),
|
||||
assert.strictEqual(form.$('.o_field_widget[name="outstanding_credits_debits_widget"]').text().replace(/[\s\n\r]+/g, ' '),
|
||||
" Outstanding credits Add INV/2017/0004 $ 100.00 ",
|
||||
"should display outstanding information");
|
||||
|
||||
form.$('.o_form_field[name="payments_widget"] .js_payment_info').trigger('focus');
|
||||
form.$('.o_field_widget[name="payments_widget"] .js_payment_info').trigger('focus');
|
||||
form.$('.popover .js_open_payment').trigger('click');
|
||||
|
||||
form.$('.o_form_field[name="payments_widget"] .js_payment_info').trigger('focus');
|
||||
form.$('.o_field_widget[name="payments_widget"] .js_payment_info').trigger('focus');
|
||||
form.$('.popover .js_unreconcile_payment').trigger('click');
|
||||
|
||||
form.destroy();
|
||||
|
||||
@@ -512,7 +512,7 @@ QUnit.module('account', {
|
||||
assert.strictEqual(widget.$('.create').length, 1, "should have 'create' panel");
|
||||
|
||||
assert.strictEqual(widget.$('thead').text().replace(/[\n\r\s]+/g, ' '), " 101401 2017-01-01 SAJ/2014/002 and SAJ/2014/003 $ 1,175.00 ", "should display the line information");
|
||||
assert.ok(widget.$('caption .o_form_field.o_form_field_many2one').length, "should display the many2one with to select a partner");
|
||||
assert.ok(widget.$('caption .o_field_many2one').length, "should display the many2one with to select a partner");
|
||||
|
||||
assert.strictEqual(clientAction.$('[data-mode="inactive"]').length, 3, "should be as 'inactive' mode by default");
|
||||
assert.strictEqual(widget.$el.data('mode'), 'match', "the first one should automatically switch to match mode");
|
||||
@@ -540,12 +540,12 @@ QUnit.module('account', {
|
||||
|
||||
var widget = clientAction.widgets[0];
|
||||
|
||||
assert.strictEqual(widget.$('.o_form_input_dropdown input').val(), "Agrolait", "the partner many2one should display agrolait");
|
||||
assert.strictEqual(clientAction.widgets[2].$('.o_form_input_dropdown input').val(), "Camptocamp", "the partner many2one should display Camptocamp");
|
||||
assert.strictEqual(widget.$('.o_input_dropdown input').val(), "Agrolait", "the partner many2one should display agrolait");
|
||||
assert.strictEqual(clientAction.widgets[2].$('.o_input_dropdown input').val(), "Camptocamp", "the partner many2one should display Camptocamp");
|
||||
widget.$('.accounting_view tfoot td:first').trigger('click');
|
||||
assert.strictEqual(widget.$('.create .o_form_input').length, 6,
|
||||
assert.strictEqual(widget.$('.create .o_input').length, 6,
|
||||
"create panel should display 5 fields (account_id, tax_id, analytic_account_id, label, amount)");
|
||||
assert.strictEqual(widget.$('.create .create_account_id .o_form_required, .create .create_label .o_form_required, .create .create_amount .o_form_required').length, 3,
|
||||
assert.strictEqual(widget.$('.create .create_account_id .o_required_modifier, .create .create_label .o_required_modifier, .create .create_amount .o_required_modifier').length, 3,
|
||||
"account_id, label and amount should be required fields");
|
||||
assert.strictEqual(widget.$('.create .create_label input').val(), 'SAJ/2014/002 and SAJ/2014/003',
|
||||
"should use the name of the reconciliation line for the default label value");
|
||||
|
||||
@@ -312,7 +312,7 @@ FormRenderer.include({
|
||||
var commands = {};
|
||||
commands.barcode = function () {return $.when();};
|
||||
commands['O-BTN.' + node.attrs.barcode_trigger] = function () {
|
||||
if (!$button.hasClass('o_form_invisible')) {
|
||||
if (!$button.hasClass('o_invisible_modifier')) {
|
||||
$button.click();
|
||||
}
|
||||
return $.when();
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
}
|
||||
|
||||
// Override border of many2manytags defined for form_views
|
||||
.o_kanban_view .o_kanban_record .oe_kanban_list_many2many .o_form_field_many2manytags {
|
||||
.o_kanban_view .o_kanban_record .oe_kanban_list_many2many .o_field_many2manytags {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,16 +62,16 @@ QUnit.module('calendar', {
|
||||
},
|
||||
});
|
||||
|
||||
assert.ok(form.$('.o_form_field[name="partner_ids"]').hasClass('o_form_field_many2manytags'));
|
||||
assert.strictEqual(form.$('.o_form_field[name="partner_ids"] > span').length, 2,
|
||||
assert.ok(form.$('.o_field_widget[name="partner_ids"]').hasClass('o_field_many2manytags'));
|
||||
assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] > span').length, 2,
|
||||
"there should be 2 tags");
|
||||
assert.strictEqual(form.$('.o_form_field[name="partner_ids"] > span:first').text().trim(), "Jesus",
|
||||
assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] > span:first').text().trim(), "Jesus",
|
||||
"the tag should be correctly named");
|
||||
assert.ok(form.$('.o_form_field[name="partner_ids"] > span:first .o_calendar_invitation').hasClass('accepted'),
|
||||
assert.ok(form.$('.o_field_widget[name="partner_ids"] > span:first .o_calendar_invitation').hasClass('accepted'),
|
||||
"Jesus should attend the meeting");
|
||||
assert.strictEqual(form.$('.o_form_field[name="partner_ids"] > span[data-id="2"]').text().trim(), "Mahomet",
|
||||
assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] > span[data-id="2"]').text().trim(), "Mahomet",
|
||||
"the tag should be correctly named");
|
||||
assert.ok(form.$('.o_form_field[name="partner_ids"] > span[data-id="2"] .o_calendar_invitation').hasClass('needsAction'),
|
||||
assert.ok(form.$('.o_field_widget[name="partner_ids"] > span[data-id="2"] .o_calendar_invitation').hasClass('needsAction'),
|
||||
"Mohamet should still confirm his attendance to the meeting");
|
||||
|
||||
form.destroy();
|
||||
|
||||
@@ -45,7 +45,7 @@ tour.register('crm_tour', {
|
||||
content: _t("Schedule an activity by clicking here"),
|
||||
position: "bottom"
|
||||
}, {
|
||||
trigger: ".modal-body .o_form_field_many2one",
|
||||
trigger: ".modal-body .o_field_many2one",
|
||||
extra_trigger: ".o_opportunity_kanban",
|
||||
content: _t("<p>You will be able to customize your followup activities. Examples:</p><ol><li>introductory email</li><li>call 10 days after</li><li>second call 3 days after, ...</li></ol><p class='mb0'><i>Select a standard activity for now on.</i></p>"),
|
||||
position: "bottom",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@name='toggle_active']" position="before">
|
||||
<button class="oe_stat_button" type="action" name="%(convert_lead2projectissue_wizard_action)d" icon="fa-bug" help="Convert to Issue">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Convert To</span>
|
||||
<span class="o_stat_text">Issue</span>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
class="oe_stat_button"
|
||||
icon="fa-gift"
|
||||
attrs="{'invisible': [('state','=','draft')]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Related</span>
|
||||
<span class="o_stat_text">Goals</span>
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
@tmp-gap-base: @o-org-chart-entry-pic-size*0.7;
|
||||
|
||||
// ORGANIGRAM LINES
|
||||
.o_form_field, .o_org_chart_group_up, .o_org_chart_group_down {
|
||||
.o_field_widget, .o_org_chart_group_up, .o_org_chart_group_down {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_makeMeeting" class="oe_stat_button" icon="fa-calendar" type="object"
|
||||
help="Schedule interview with this applicant">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Meetings</span>
|
||||
</div>
|
||||
</button>
|
||||
@@ -478,7 +478,7 @@
|
||||
<button class="oe_stat_button" type="action"
|
||||
name="%(action_hr_job_sources)d" icon="fa-share"
|
||||
context="{'default_job_id': active_id}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Trackers</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
help="Answer related job question"
|
||||
context="{'survey_id': survey_id}"
|
||||
attrs="{'invisible':[('survey_id','=',False)]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Start</span>
|
||||
<span class="o_stat_text">Interview</span>
|
||||
</div>
|
||||
@@ -36,7 +36,7 @@
|
||||
type="object"
|
||||
help="Print interview report"
|
||||
attrs="{'invisible':[('survey_id','=',False)]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Print</span>
|
||||
<span class="o_stat_text">Interview</span>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
name="%(hr_timesheet_attendance.act_hr_timesheet_sheet_sheet_2_hr_analytic_timesheet)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-clock-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="total_timesheet" widget="float_time"/></span>
|
||||
<span class="o_stat_text">Timesheet</span>
|
||||
</div>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
.o-flex-display();
|
||||
.o-align-items(center);
|
||||
|
||||
.o_form_field_many2one {
|
||||
.o_field_many2one {
|
||||
min-width: 200px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ QUnit.module('lunch', {
|
||||
},
|
||||
});
|
||||
|
||||
var widgetText = form.$('.o_form_field[name="previous_order_widget"]').text();
|
||||
var widgetText = form.$('.o_field_widget[name="previous_order_widget"]').text();
|
||||
assert.ok(widgetText.indexOf('This is the first time you order a meal') !== -1,
|
||||
"the widget should display its no content text");
|
||||
assert.strictEqual(form.$('.o_lunch_vignette').length, 0,
|
||||
|
||||
@@ -357,7 +357,7 @@
|
||||
name="%(lunch_cashmove_action_account)d"
|
||||
icon="fa-money"
|
||||
type="action">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="cash_move_balance" widget="monetary"/></span>
|
||||
<span class="o_stat_text">Balance</span>
|
||||
</div>
|
||||
|
||||
@@ -351,7 +351,7 @@ var BasicComposer = Widget.extend(chat_mixin, {
|
||||
events: {
|
||||
"keydown .o_composer_input textarea": "on_keydown",
|
||||
"keyup .o_composer_input": "on_keyup",
|
||||
"change input.o_form_input_file": "on_attachment_change",
|
||||
"change input.o_input_file": "on_attachment_change",
|
||||
"click .o_composer_button_send": "send_message",
|
||||
"click .o_composer_button_add_attachment": "on_click_add_attachment",
|
||||
"click .o_attachment_delete": "on_attachment_delete",
|
||||
@@ -508,7 +508,7 @@ var BasicComposer = Widget.extend(chat_mixin, {
|
||||
|
||||
// Events
|
||||
on_click_add_attachment: function () {
|
||||
this.$('input.o_form_input_file').click();
|
||||
this.$('input.o_input_file').click();
|
||||
this.$input.focus();
|
||||
},
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Common */
|
||||
.o_mail_activity {
|
||||
&.o_form_field {
|
||||
&.o_field_widget {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ QUnit.test('chatter is not rendered in mode === create', function (assert) {
|
||||
assert.strictEqual(form.$('.o_chatter').length, 0,
|
||||
"chatter should not be displayed");
|
||||
|
||||
form.$('.o_form_input').val('coucou').trigger('input');
|
||||
form.$('.o_field_char').val('coucou').trigger('input');
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_chatter').length, 1,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<button class="oe_stat_button" name="create_action" type="object"
|
||||
attrs="{'invisible':[('ref_ir_act_window','!=',False)]}" icon="fa-plus"
|
||||
help="Display an option on related documents to open a composition wizard with this template">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Add</span>
|
||||
<span class="o_stat_text">Context Action</span>
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@
|
||||
class="oe_stat_button" icon="fa-minus"
|
||||
attrs="{'invisible':[('ref_ir_act_window','=',False)]}"
|
||||
help="Remove the contextual action to use this template on related documents" widget="statinfo">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Remove</span>
|
||||
<span class="o_stat_text">Context Action</span>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
class="oe_stat_button"
|
||||
icon="fa-calculator"
|
||||
help="Marketing Campaign Statistics">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Campaign</span>
|
||||
<span class="o_stat_text">Statistics</span>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.o_form_view {
|
||||
.o_form_field_pdfviewer {
|
||||
.o_field_pdfviewer {
|
||||
width: 100%;
|
||||
height: 450px;
|
||||
border: 0;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="FieldPdfViewer">
|
||||
<div class="o_form_field_pdfviewer">
|
||||
<div class="o_field_pdfviewer">
|
||||
<div t-if="widget.mode !== 'readonly'" class="o_form_pdf_controls mt8">
|
||||
<span class="o_form_binary_progress">Uploading...</span>
|
||||
<button type="button" class="btn btn-sm btn-primary o_select_file_button" title="Select">Upload your file</button>
|
||||
<button class="btn btn-sm btn-default fa fa-pencil o_select_file_button" title="Select" type="button"></button>
|
||||
<button class="btn btn-sm btn-default fa fa-trash-o o_clear_file_button" title="Clear" type="button"></button>
|
||||
</div>
|
||||
<iframe class="o_pdfview_iframe o_form_field_pdfviewer"/>
|
||||
<iframe class="o_pdfview_iframe o_field_pdfviewer"/>
|
||||
<t t-call="HiddenInputPDFFile">
|
||||
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
|
||||
<t t-set="fileupload_style" t-translation="off">overflow-x: hidden</t>
|
||||
@@ -17,7 +17,7 @@
|
||||
</t>
|
||||
<t t-extend="HiddenInputFile" t-name="HiddenInputPDFFile">
|
||||
<t t-jquery="input[type='file']:first" t-operation="replace">
|
||||
<input type="file" class="o_form_input_file" name="ufile" accept="application/pdf" />
|
||||
<input type="file" class="o_input_file" name="ufile" accept="application/pdf" />
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -43,10 +43,10 @@ QUnit.module('mrp', {
|
||||
'</form>',
|
||||
});
|
||||
|
||||
assert.ok(form.$('.o_form_field').hasClass('o_form_field_pdfviewer'));
|
||||
assert.ok(form.$('.o_field_widget').hasClass('o_field_pdfviewer'));
|
||||
assert.strictEqual(form.$('.o_select_file_button:not(.o_hidden)').length, 1,
|
||||
"there should be a visible 'Upload' button");
|
||||
assert.ok(form.$('.o_form_field iframe.o_pdfview_iframe').hasClass('o_hidden'),
|
||||
assert.ok(form.$('.o_field_widget iframe.o_pdfview_iframe').hasClass('o_hidden'),
|
||||
"there should be an invisible iframe");
|
||||
|
||||
form.destroy();
|
||||
@@ -72,12 +72,12 @@ QUnit.module('mrp', {
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(form.$('.o_form_field').hasClass('o_form_field_pdfviewer'));
|
||||
assert.ok(form.$('.o_field_widget').hasClass('o_field_pdfviewer'));
|
||||
assert.strictEqual(form.$('.o_select_file_button:not(.o_hidden)').length, 0,
|
||||
"there should not be a any visible 'Upload' button");
|
||||
assert.notOk(form.$('.o_form_field iframe.o_pdfview_iframe').hasClass('o_hidden'),
|
||||
assert.notOk(form.$('.o_field_widget iframe.o_pdfview_iframe').hasClass('o_hidden'),
|
||||
"there should be an visible iframe");
|
||||
assert.strictEqual(form.$('.o_form_field iframe.o_pdfview_iframe').attr('src'),
|
||||
assert.strictEqual(form.$('.o_field_widget iframe.o_pdfview_iframe').attr('src'),
|
||||
'#test:/web/static/lib/pdfjs/web/viewer.html?file=%2Fweb%2Fimage%3Fmodel%3Dpartner%26field%3Ddocument%26id%3D1',
|
||||
"the src attribute should be correctly set on the iframe");
|
||||
|
||||
@@ -98,9 +98,9 @@ QUnit.module('mrp', {
|
||||
'</form>',
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field').text(), "Waiting Materials",
|
||||
assert.strictEqual(form.$('.o_field_widget').text(), "Waiting Materials",
|
||||
"the widget should be correctly named");
|
||||
assert.strictEqual(form.$('.o_form_field .label-danger').length, 1,
|
||||
assert.strictEqual(form.$('.o_field_widget .label-danger').length, 1,
|
||||
"the label should be danger");
|
||||
|
||||
form.destroy();
|
||||
@@ -133,7 +133,7 @@ QUnit.module('mrp', {
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name="duration"]').text(), "02:30:00",
|
||||
assert.strictEqual(form.$('.o_field_widget[name="duration"]').text(), "02:30:00",
|
||||
"the timer should be correctly set");
|
||||
|
||||
form.destroy();
|
||||
|
||||
@@ -60,14 +60,14 @@
|
||||
<field name="unreserve_visible" invisible="1"/>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="%(action_mrp_workorder_production_specific)d" type="action" attrs="{'invisible': [('workorder_count', '=', 0)]}" class="oe_stat_button" icon="fa-play-circle-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="workorder_done_count" widget="statinfo" nolabel="1"/> / <field name="workorder_count" widget="statinfo" nolabel="1"/></span>
|
||||
<span class="o_stat_text">Work Orders</span>
|
||||
</div>
|
||||
</button>
|
||||
<button name="%(action_mrp_production_moves)d" type="action" string="Inventory Moves" class="oe_stat_button" icon="fa-arrows-v" attrs="{'invisible': [('state', 'not in', ('progress', 'cancel', 'done'))]}"/>
|
||||
<button class="oe_stat_button" name="action_see_move_scrap" type="object" icon="fa-arrows-v" attrs="{'invisible': [('scrap_count', '=', 0)]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="scrap_count"/></span>
|
||||
<span class="o_stat_text">Scraps</span>
|
||||
</div>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="%(action_mrp_routing_time)d" type="action" class="oe_stat_button" icon="fa-clock-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Time<br/> Analysis</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -255,25 +255,25 @@
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="%(mrp_workcenter_productivity_report_oee)d" type="action" class="oe_stat_button" icon="fa-pie-chart">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="oee" widget="statinfo" nolabel="1"/>%</span>
|
||||
<span class="o_stat_text">OEE</span>
|
||||
</div>
|
||||
</button>
|
||||
<button name="%(mrp_workcenter_productivity_report_blocked)d" type="action" class="oe_stat_button" icon="fa-bar-chart">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="blocked_time" widget="statinfo" nolabel="1"/> hour(s)</span>
|
||||
<span class="o_stat_text">Lost</span>
|
||||
</div>
|
||||
</button>
|
||||
<button name="%(action_mrp_workcenter_load_report_graph)d" type="action" class="oe_stat_button" icon="fa-bar-chart" context="{'search_default_workcenter_id': active_id}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="workcenter_load" widget="statinfo" nolabel="1"/> minute(s)</span>
|
||||
<span class="o_stat_text">Work Center Load</span>
|
||||
</div>
|
||||
</button>
|
||||
<button name="%(mrp_workorder_report)d" type="action" class="oe_stat_button" icon="fa-bar-chart" context="{'search_default_workcenter_id': active_id, 'search_default_thisyear': True}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="performance" widget="statinfo" nolabel="1"/>%</span>
|
||||
<span class="o_stat_text">Performance</span>
|
||||
</div>
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" name="action_see_move_scrap" type="object" icon="fa-arrows-v" attrs="{'invisible': [('scrap_count', '=', 0)]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="scrap_count"/></span>
|
||||
<span class="o_stat_text">Scraps</span>
|
||||
</div>
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
<field name="module_state" invisible="1"/>
|
||||
<div class="oe_button_box" name="button_box" attrs="{'invisible': ['&', ('module_id', '!=', False), ('module_state', '!=', 'installed')]}">
|
||||
<button attrs="{'invisible': [('environment', '=', 'test')]}" class="oe_stat_button" name="toggle_enviroment_value" type="object" icon="fa-play">
|
||||
<div class="o_stat_info o_form_field">
|
||||
<div class="o_stat_info o_field_widget">
|
||||
<span class="text-success">Production</span>
|
||||
<span class="o_stat_text">Environment</span>
|
||||
</div>
|
||||
</button>
|
||||
<button attrs="{'invisible': [('environment', '=', 'prod')]}" class="oe_stat_button" name="toggle_enviroment_value" type="object" icon="fa-stop">
|
||||
<div class="o_stat_info o_form_field">
|
||||
<div class="o_stat_info o_field_widget">
|
||||
<span class="o_warning_text">Test</span>
|
||||
<span class="o_stat_text">Environment</span>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<button class="oe_stat_button" name="%(action_pos_box_in)d"
|
||||
type="action" icon="fa-level-down"
|
||||
attrs="{'invisible': ['|', ('cash_control', '=', False), ('state', 'not in', ['opened', 'closing_control'])]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Put</span>
|
||||
<span class="o_stat_text">Money In</span>
|
||||
</div>
|
||||
@@ -43,7 +43,7 @@
|
||||
<button class="oe_stat_button" name="%(action_pos_box_out)d"
|
||||
type="action" icon="fa-level-up"
|
||||
attrs="{'invisible': ['|', ('cash_control', '=', False), ('state', 'not in', ['opened', 'closing_control'])]}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Take</span>
|
||||
<span class="o_stat_text">Money Out</span>
|
||||
</div>
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
icon="fa-th-list"
|
||||
type="action"
|
||||
context="{'search_default_categ_id': active_id}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="product_count"/></span>
|
||||
<span class="o_stat_text"> Products</span>
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@ tour.register('project_tour', {
|
||||
content: _t('Click on this button to modify the task.'),
|
||||
position: "bottom"
|
||||
}, {
|
||||
trigger: ".o_form_field.o_task_user_field",
|
||||
trigger: ".o_form_view .o_task_user_field",
|
||||
extra_trigger: '.o_form_project_tasks.o_form_editable',
|
||||
content: _t('<b>Assign the task</b> to someone. <i>You can create and invite a new user on the fly.</i>'),
|
||||
position: "bottom",
|
||||
|
||||
@@ -24,7 +24,7 @@ tour.register('sale_tour', {
|
||||
content: _t("Let's create a new quotation.<br/><i>Note that colored buttons usually point to the next logical actions.</i>"),
|
||||
position: "right",
|
||||
}, {
|
||||
trigger: ".o_form_required input",
|
||||
trigger: ".o_required_modifier input",
|
||||
extra_trigger: ".o_sale_order",
|
||||
content: _t("Write the name of your customer to create one on the fly, or select an existing one."),
|
||||
position: "top",
|
||||
@@ -34,12 +34,12 @@ tour.register('sale_tour', {
|
||||
auto: true,
|
||||
in_modal: false,
|
||||
}, {
|
||||
trigger: ".o_form_field_x2many_list_row_add > a",
|
||||
trigger: ".o_field_x2many_list_row_add > a",
|
||||
extra_trigger: ".o_sale_order",
|
||||
content: _t("Click here to add some lines to your quotations."),
|
||||
position: "bottom",
|
||||
}, {
|
||||
trigger: ".modal-body .o_form_required input, .o_list_view .o_form_required input",
|
||||
trigger: ".modal-body .o_required_modifier input, .o_list_view .o_required_modifier input",
|
||||
extra_trigger: ".o_sale_order",
|
||||
content: _t("Select a product, or create a new one on the fly. The product will define the default sales price (that you can change), taxes and description automatically."),
|
||||
position: "right",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<button class="oe_stat_button" type="action" attrs="{'invisible': [('sale_amount_total', '=', 0)]}"
|
||||
name="%(sale_action_quotations)d" icon="fa-usd"
|
||||
context="{'search_default_partner_id': partner_id, 'default_partner_id': partner_id, 'search_default_sales': 1}">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="sale_amount_total" widget="monetary" options="{'currency_field': 'company_currency'}"/></span>
|
||||
<span class="o_stat_text"> Orders</span>
|
||||
</div>
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
name="%(stock.action_stock_level_forecast_report_product)d"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="virtual_available" widget="statinfo" nolabel="1"/>
|
||||
<span attrs="{'invisible':[('outgoing_qty', '=', 0),('incoming_qty','=',0)]}">
|
||||
(-<field name="outgoing_qty" widget="statinfo" nolabel="1"/>
|
||||
@@ -318,11 +318,11 @@
|
||||
<button name="%(product_open_orderpoint)d" type="action"
|
||||
attrs="{'invisible':['|',('type', 'not in', ['product', 'consu']),('nbr_reordering_rules', '!=', 1)]}"
|
||||
class="oe_stat_button" icon="fa-refresh">
|
||||
<div class="o_form_field o_stat_info mr4">
|
||||
<div class="o_field_widget o_stat_info mr4">
|
||||
<span class="o_stat_text">Min :</span>
|
||||
<span class="o_stat_text">Max:</span>
|
||||
</div>
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="reordering_min_qty"/></span>
|
||||
<span class="o_stat_value"><field name="reordering_max_qty"/></span>
|
||||
</div>
|
||||
@@ -357,7 +357,7 @@
|
||||
name="%(stock.action_stock_level_forecast_report_template)d"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="virtual_available" widget="integer"/>
|
||||
<span attrs="{'invisible':[('outgoing_qty', '=', 0),('incoming_qty','=',0)]}" groups="base.group_no_one">
|
||||
(-<field name="outgoing_qty" widget="integer"/>+<field name="incoming_qty" widget="integer"/>)
|
||||
@@ -382,11 +382,11 @@
|
||||
name="action_view_orderpoints"
|
||||
attrs="{'invisible':['|',('type', '!=', 'product'),('nbr_reordering_rules', '!=', 1)]}"
|
||||
class="oe_stat_button" icon="fa-refresh">
|
||||
<div class="o_form_field o_stat_info mr4">
|
||||
<div class="o_field_widget o_stat_info mr4">
|
||||
<span class="o_stat_text">Min:</span>
|
||||
<span class="o_stat_text">Max:</span>
|
||||
</div>
|
||||
<div class="o_form_field o_stat_info">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="reordering_min_qty"/></span>
|
||||
<span class="o_stat_value"><field name="reordering_max_qty"/></span>
|
||||
</div>
|
||||
|
||||
@@ -946,12 +946,6 @@ class View(http.Controller):
|
||||
})
|
||||
return {'result': True}
|
||||
|
||||
class TreeView(View):
|
||||
|
||||
@http.route('/web/treeview/action', type='json', auth="user")
|
||||
def action(self, model, id):
|
||||
return load_actions_from_ir_values('tree_but_open', model, id)
|
||||
|
||||
class Binary(http.Controller):
|
||||
|
||||
def placeholder(self, image='placeholder.png'):
|
||||
|
||||
@@ -46,7 +46,7 @@ various situations:
|
||||
|
||||
Action button (``button`` tag in the view) inside the cell
|
||||
|
||||
``.o_readonly``
|
||||
``.o_readonly_modifier``
|
||||
|
||||
Readonly field cell
|
||||
|
||||
|
||||
@@ -56,7 +56,12 @@ return {
|
||||
if ($textarea.data("auto_resize")) {
|
||||
return;
|
||||
}
|
||||
function resize () {
|
||||
|
||||
var $fixedTextarea;
|
||||
var minHeight;
|
||||
|
||||
function resize() {
|
||||
$fixedTextarea.insertAfter($textarea);
|
||||
var heightOffset;
|
||||
var style = window.getComputedStyle($textarea[0], null);
|
||||
if (style.boxSizing === 'content-box') {
|
||||
@@ -64,28 +69,25 @@ return {
|
||||
} else {
|
||||
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
|
||||
}
|
||||
$fixed_text_area.width($textarea.width());
|
||||
$fixed_text_area.val($textarea.val());
|
||||
var height = $fixed_text_area[0].scrollHeight;
|
||||
$textarea.css({height: Math.max(height + heightOffset, min_height)});
|
||||
$fixedTextarea.width($textarea.width());
|
||||
$fixedTextarea.val($textarea.val());
|
||||
var height = $fixedTextarea[0].scrollHeight;
|
||||
$textarea.css({height: Math.max(height + heightOffset, minHeight)});
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
minHeight = (options && options.min_height) || 50;
|
||||
|
||||
var $fixed_text_area;
|
||||
var min_height = (options && options.min_height) || 50;
|
||||
if (!$fixed_text_area) {
|
||||
$fixed_text_area = $('<textarea disabled>').css({
|
||||
position: 'absolute',
|
||||
opacity: 0,
|
||||
height: 10,
|
||||
top: -10000,
|
||||
left: -10000,
|
||||
});
|
||||
$fixed_text_area.addClass($textarea[0].className);
|
||||
$fixed_text_area.insertAfter($textarea);
|
||||
$fixed_text_area.data("auto_resize", true);
|
||||
}
|
||||
$fixedTextarea = $('<textarea disabled>', {
|
||||
class: $textarea[0].className,
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
opacity: 0,
|
||||
height: 10,
|
||||
top: -10000,
|
||||
left: -10000,
|
||||
});
|
||||
$fixedTextarea.data("auto_resize", true);
|
||||
|
||||
var style = window.getComputedStyle($textarea[0], null);
|
||||
if (style.resize === 'vertical') {
|
||||
@@ -101,7 +103,6 @@ return {
|
||||
core.bus.on('DOM_updated', options.parent, resize);
|
||||
core.bus.on('view_shown', options.parent, resize);
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* Detaches widgets from the DOM and performs their on_detach_callback()
|
||||
|
||||
@@ -34,7 +34,6 @@ var field_utils = require('web.field_utils');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
var AbstractField = Widget.extend({
|
||||
className: 'o_field_widget',
|
||||
events: {
|
||||
'keydown': '_onKeydown',
|
||||
},
|
||||
@@ -151,6 +150,7 @@ var AbstractField = Widget.extend({
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function () {
|
||||
self.$el.attr('name', self.name);
|
||||
self.$el.addClass('o_field_widget');
|
||||
return self._render();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -184,7 +184,7 @@ var InputField = DebouncedField.extend({
|
||||
*/
|
||||
_prepareInput: function ($input) {
|
||||
this.$input = $input || $("<input/>");
|
||||
this.$input.addClass('o_form_input');
|
||||
this.$input.addClass('o_input');
|
||||
this.$input.attr({
|
||||
type: 'text',
|
||||
placeholder: this.attrs.placeholder || "",
|
||||
@@ -261,12 +261,13 @@ var InputField = DebouncedField.extend({
|
||||
});
|
||||
|
||||
var FieldChar = InputField.extend({
|
||||
supportedFieldTypes: ['char'],
|
||||
className: 'o_field_char',
|
||||
tagName: 'span',
|
||||
supportedFieldTypes: ['char'],
|
||||
});
|
||||
|
||||
var FieldDate = InputField.extend({
|
||||
className: "o_form_field_date",
|
||||
className: "o_field_date",
|
||||
tagName: "span",
|
||||
supportedFieldTypes: ['date'],
|
||||
|
||||
@@ -411,7 +412,8 @@ var FieldDateTime = FieldDate.extend({
|
||||
});
|
||||
|
||||
var FieldMonetary = InputField.extend({
|
||||
className: 'o_form_field_monetary o_list_number',
|
||||
className: 'o_field_monetary o_field_number',
|
||||
tagName: 'span',
|
||||
supportedFieldTypes: ['float', 'monetary'],
|
||||
resetOnAnyFieldChange: true, // Have to listen to currency changes
|
||||
|
||||
@@ -436,6 +438,7 @@ var FieldMonetary = InputField.extend({
|
||||
|
||||
if (this.mode === 'edit' && this.currency) {
|
||||
this.tagName = 'div';
|
||||
this.className += ' o_input';
|
||||
}
|
||||
},
|
||||
|
||||
@@ -554,28 +557,18 @@ var FieldBoolean = AbstractField.extend({
|
||||
/**
|
||||
* The actual checkbox is designed in css to have full control over its
|
||||
* appearance, as opposed to letting the browser and the os decide how
|
||||
* a checkbox should look. The actual input is disabled and hidden.
|
||||
* a checkbox should look. The actual input is disabled and hidden. In
|
||||
* readonly mode, the checkbox is disabled.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_renderReadonly: function () {
|
||||
_render: function () {
|
||||
var $checkbox = this._formatValue(this.value);
|
||||
this.$input = $checkbox.find('input');
|
||||
this.$el.empty().append($checkbox);
|
||||
},
|
||||
|
||||
/**
|
||||
* The actual checkbox is designed in css to have full control over its
|
||||
* appearance, as opposed to letting the browser and the os decide how
|
||||
* a checkbox should look. The actual input is hidden.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_renderEdit: function () {
|
||||
this._renderReadonly();
|
||||
this.$input.prop('disabled', false);
|
||||
this.$input.prop('disabled', this.mode === 'readonly');
|
||||
this.$el.addClass($checkbox.attr('class'));
|
||||
this.$el.empty().append($checkbox.contents());
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -591,7 +584,6 @@ var FieldBoolean = AbstractField.extend({
|
||||
_onChange: function () {
|
||||
this._setValue(this.$input[0].checked);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implement keyboard movements. Mostly useful for its environment, such
|
||||
* as a list view.
|
||||
@@ -624,6 +616,8 @@ var FieldBoolean = AbstractField.extend({
|
||||
});
|
||||
|
||||
var FieldInteger = InputField.extend({
|
||||
className: 'o_field_integer o_field_number',
|
||||
tagName: 'span',
|
||||
supportedFieldTypes: ['integer'],
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -669,6 +663,8 @@ var FieldInteger = InputField.extend({
|
||||
});
|
||||
|
||||
var FieldFloat = InputField.extend({
|
||||
className: 'o_field_float o_field_number',
|
||||
tagName: 'span',
|
||||
supportedFieldTypes: ['float'],
|
||||
|
||||
/**
|
||||
@@ -696,22 +692,6 @@ var FieldFloat = InputField.extend({
|
||||
isSet: function () {
|
||||
return this.value === 0 || this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Format value according to precision parameter.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_renderReadonly: function () {
|
||||
var value = this._formatValue(this.value);
|
||||
var $span = $('<span>').addClass('o_form_field o_form_field_number').text(value);
|
||||
this.$el.html($span);
|
||||
},
|
||||
});
|
||||
|
||||
var FieldFloatTime = FieldFloat.extend({
|
||||
@@ -743,21 +723,28 @@ var FieldFloatTime = FieldFloat.extend({
|
||||
});
|
||||
|
||||
var FieldText = DebouncedField.extend({
|
||||
className: 'o_field_text',
|
||||
supportedFieldTypes: ['text'],
|
||||
|
||||
/**
|
||||
* In edit mode, the text widget contains a textarea. We append it in
|
||||
* start() instead of _renderEdit() to keep the same textarea even
|
||||
* if several _renderEdit are done. This allows to keep the cursor
|
||||
* position and to autoresize only once.
|
||||
* @constructor
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
if (this.mode === 'edit') {
|
||||
this.tagName = 'textarea';
|
||||
this.className += ' o_input';
|
||||
}
|
||||
},
|
||||
/**
|
||||
* As it it done in the start function, the autoresize is done only once.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.addClass('o_list_text o_form_textarea');
|
||||
|
||||
if (this.mode === 'edit') {
|
||||
this.$textarea = $('<textarea>').appendTo(this.$el);
|
||||
this.$textarea = this.$el;
|
||||
if (this.attrs.placeholder) {
|
||||
this.$textarea.attr('placeholder', this.attrs.placeholder);
|
||||
}
|
||||
@@ -816,13 +803,14 @@ var FieldText = DebouncedField.extend({
|
||||
* Displays a handle to modify the sequence.
|
||||
*/
|
||||
var HandleWidget = AbstractField.extend({
|
||||
tagName: 'span',
|
||||
className: 'o_row_handle fa fa-arrows ui-sortable-handle',
|
||||
tagName: 'span',
|
||||
description: "",
|
||||
supportedFieldTypes: ['integer'],
|
||||
});
|
||||
|
||||
var EmailWidget = InputField.extend({
|
||||
var FieldEmail = InputField.extend({
|
||||
className: 'o_field_email',
|
||||
prefix: 'mailto',
|
||||
supportedFieldTypes: ['char'],
|
||||
|
||||
@@ -853,7 +841,8 @@ var EmailWidget = InputField.extend({
|
||||
}
|
||||
});
|
||||
|
||||
var FieldPhone = EmailWidget.extend({
|
||||
var FieldPhone = FieldEmail.extend({
|
||||
className: 'o_field_phone',
|
||||
prefix: 'tel',
|
||||
|
||||
/**
|
||||
@@ -907,6 +896,7 @@ var FieldPhone = EmailWidget.extend({
|
||||
});
|
||||
|
||||
var UrlWidget = InputField.extend({
|
||||
className: 'o_field_url',
|
||||
supportedFieldTypes: ['char'],
|
||||
|
||||
/**
|
||||
@@ -939,9 +929,9 @@ var UrlWidget = InputField.extend({
|
||||
|
||||
var AbstractFieldBinary = AbstractField.extend({
|
||||
events: _.extend({}, AbstractField.prototype.events, {
|
||||
'change .o_form_input_file': 'on_file_change',
|
||||
'change .o_input_file': 'on_file_change',
|
||||
'click .o_select_file_button': function () {
|
||||
this.$('.o_form_input_file').click();
|
||||
this.$('.o_input_file').click();
|
||||
},
|
||||
'click .o_clear_file_button': 'on_clear',
|
||||
}),
|
||||
@@ -1084,8 +1074,8 @@ var FieldBinaryFile = AbstractFieldBinary.extend({
|
||||
this.on_save_as(event);
|
||||
}
|
||||
},
|
||||
'click .o_form_input': function () { // eq[0]
|
||||
this.$('.o_form_input_file').click();
|
||||
'click .o_input': function () { // eq[0]
|
||||
this.$('.o_input_file').click();
|
||||
},
|
||||
}),
|
||||
supportedFieldTypes: ['binary'],
|
||||
@@ -1106,7 +1096,7 @@ var FieldBinaryFile = AbstractFieldBinary.extend({
|
||||
if (this.value) {
|
||||
this.$el.children().removeClass('o_hidden');
|
||||
this.$('.o_select_file_button').first().addClass('o_hidden');
|
||||
this.$('.o_form_input').eq(0).val(this.filename_value || this.value);
|
||||
this.$('.o_input').eq(0).val(this.filename_value || this.value);
|
||||
} else {
|
||||
this.$el.children().addClass('o_hidden');
|
||||
this.$('.o_select_file_button').first().removeClass('o_hidden');
|
||||
@@ -1727,8 +1717,8 @@ var FieldToggleBoolean = AbstractField.extend({
|
||||
* @private
|
||||
*/
|
||||
_render: function () {
|
||||
var class_name = this.value ? 'o_toggle_button_success' : 'text-muted';
|
||||
this.$('i').attr('class', ('fa fa-circle ' + class_name));
|
||||
var className = this.value ? 'o_toggle_button_success' : 'text-muted';
|
||||
this.$('i').addClass('fa fa-circle ' + className);
|
||||
var title = this.value ? this.attrs.options.active : this.attrs.options.inactive;
|
||||
this.$el.attr('title', title);
|
||||
},
|
||||
@@ -1747,7 +1737,6 @@ var FieldToggleBoolean = AbstractField.extend({
|
||||
event.stopPropagation();
|
||||
this._setValue(!this.value);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var JournalDashboardGraph = AbstractField.extend({
|
||||
@@ -1891,7 +1880,7 @@ var FieldDomain = AbstractField.extend({
|
||||
|
||||
events: _.extend({}, AbstractField.prototype.events, {
|
||||
"click .o_domain_show_selection_button": "_onShowSelectionButtonClick",
|
||||
"click .o_form_field_domain_dialog_button": "_onDialogEditButtonClick",
|
||||
"click .o_field_domain_dialog_button": "_onDialogEditButtonClick",
|
||||
}),
|
||||
custom_events: {
|
||||
"domain_changed": "_onDomainSelectorValueChange",
|
||||
@@ -1907,7 +1896,7 @@ var FieldDomain = AbstractField.extend({
|
||||
this.inDialog = !!this.nodeOptions.in_dialog;
|
||||
this.fsFilters = this.nodeOptions.fs_filters || {};
|
||||
|
||||
this.className = "o_form_field_domain";
|
||||
this.className = "o_field_domain";
|
||||
if (this.mode === "edit") {
|
||||
this.className += " o_edit_mode";
|
||||
}
|
||||
@@ -2190,7 +2179,7 @@ var AceEditor = DebouncedField.extend({
|
||||
|
||||
return {
|
||||
DebouncedField: DebouncedField,
|
||||
EmailWidget: EmailWidget,
|
||||
FieldEmail: FieldEmail,
|
||||
FieldBinaryFile: FieldBinaryFile,
|
||||
FieldBinaryImage: FieldBinaryImage,
|
||||
FieldBoolean: FieldBoolean,
|
||||
|
||||
@@ -29,7 +29,7 @@ registry
|
||||
.add('float', basic_fields.FieldFloat)
|
||||
.add('char', basic_fields.FieldChar)
|
||||
.add('handle', basic_fields.HandleWidget)
|
||||
.add('email', basic_fields.EmailWidget)
|
||||
.add('email', basic_fields.FieldEmail)
|
||||
.add('phone', basic_fields.FieldPhone)
|
||||
.add('url', basic_fields.UrlWidget)
|
||||
.add('image', basic_fields.FieldBinaryImage)
|
||||
|
||||
@@ -35,13 +35,16 @@ var _t = core._t;
|
||||
* @returns {jQueryElement}
|
||||
*/
|
||||
function formatBoolean(value) {
|
||||
var $input = $('<input type="checkbox">')
|
||||
.prop('checked', value)
|
||||
.prop('disabled', true);
|
||||
return $('<div>')
|
||||
.addClass('o_checkbox')
|
||||
.append($input)
|
||||
.append($('<span>'));
|
||||
var $input = $('<input/>', {
|
||||
type: 'checkbox',
|
||||
}).prop({
|
||||
checked: value,
|
||||
disabled: true,
|
||||
});
|
||||
var $div = $('<div/>', {
|
||||
class: 'o_checkbox',
|
||||
});
|
||||
return $div.append($input, '<span/>');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,7 +345,7 @@ function parseDateTime(value, field, options) {
|
||||
var pattern2 = datePatternWoZero + ' ' + timePatternWoZero;
|
||||
var datetime;
|
||||
if (options && options.isUTC) {
|
||||
// phatomjs crash if we don't use this format
|
||||
// phatomjs crash if we don't use this format
|
||||
datetime = moment.utc(value.replace(' ', 'T') + 'Z');
|
||||
} else {
|
||||
datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601], true);
|
||||
|
||||
@@ -81,9 +81,9 @@ var FieldMany2One = AbstractField.extend({
|
||||
'search_create_popup': '_onSearchCreatePopup',
|
||||
},
|
||||
events: _.extend({}, AbstractField.prototype.events, {
|
||||
'click .o_form_input': '_onInputClick',
|
||||
'focusout .o_form_input': '_onInputFocusout',
|
||||
'keyup .o_form_input': '_onInputKeyup',
|
||||
'click input': '_onInputClick',
|
||||
'focusout input': '_onInputFocusout',
|
||||
'keyup input': '_onInputKeyup',
|
||||
'click .o_external_button': '_onExternalButtonClick',
|
||||
'click': '_onClick',
|
||||
}),
|
||||
@@ -106,7 +106,7 @@ var FieldMany2One = AbstractField.extend({
|
||||
// what is 'this.floating' for? add a comment!
|
||||
this.floating = false;
|
||||
|
||||
this.$input = this.$('.o_form_input');
|
||||
this.$input = this.$('input');
|
||||
this.$external_button = this.$('.o_external_button');
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
@@ -713,7 +713,7 @@ var FieldX2Many = AbstractField.extend({
|
||||
onFailure: def.reject.bind(def),
|
||||
});
|
||||
} else {
|
||||
self.renderer.setRowMode(recordID, 'readonly', true);
|
||||
self.renderer.setRowMode(recordID, 'readonly');
|
||||
def.resolve();
|
||||
}
|
||||
});
|
||||
@@ -819,7 +819,7 @@ var FieldX2Many = AbstractField.extend({
|
||||
});
|
||||
|
||||
var FieldOne2Many = FieldX2Many.extend({
|
||||
className: 'o_form_field_one2many',
|
||||
className: 'o_field_one2many',
|
||||
supportedFieldTypes: ['one2many'],
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -937,7 +937,7 @@ var FieldOne2Many = FieldX2Many.extend({
|
||||
});
|
||||
|
||||
var FieldMany2Many = FieldX2Many.extend({
|
||||
className: 'o_form_field_many2many',
|
||||
className: 'o_field_many2many',
|
||||
supportedFieldTypes: ['many2many'],
|
||||
|
||||
/**
|
||||
@@ -1019,7 +1019,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
|
||||
events: {
|
||||
'click .o_attach': '_onAttach',
|
||||
'click .oe_delete': '_onDelete',
|
||||
'change .o_form_input_file': '_onFileChanged',
|
||||
'change .o_input_file': '_onFileChanged',
|
||||
},
|
||||
/**
|
||||
* @constructor
|
||||
@@ -1102,7 +1102,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
|
||||
_onAttach: function () {
|
||||
// This widget uses a hidden form to upload files. Clicking on 'Attach'
|
||||
// will simulate a click on the related input.
|
||||
this.$('.o_form_input_file').click();
|
||||
this.$('.o_input_file').click();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -1196,7 +1196,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
|
||||
|
||||
var FieldMany2ManyTags = AbstractField.extend({
|
||||
tag_template: "FieldMany2ManyTag",
|
||||
className: "o_form_field o_form_field_many2manytags",
|
||||
className: "o_field_many2manytags",
|
||||
supportedFieldTypes: ['many2many'],
|
||||
custom_events: {
|
||||
field_changed: '_onFieldChanged',
|
||||
@@ -1204,13 +1204,24 @@ var FieldMany2ManyTags = AbstractField.extend({
|
||||
},
|
||||
events: _.extend({}, AbstractField.prototype.events, {
|
||||
'click .o_delete': '_onDeleteTag',
|
||||
'keydown .o_form_field_many2one input': '_onKeyDown',
|
||||
'keydown .o_field_many2one input': '_onKeyDown',
|
||||
}),
|
||||
fieldsToFetch: {
|
||||
color: {type: 'integer'},
|
||||
display_name: {type: 'char'},
|
||||
},
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
if (this.mode === 'edit') {
|
||||
this.className += ' o_input';
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -1310,7 +1321,7 @@ var FieldMany2ManyTags = AbstractField.extend({
|
||||
this.many2one._getSearchBlacklist = function () {
|
||||
return self.value.res_ids;
|
||||
};
|
||||
this.many2one.appendTo(this.$el);
|
||||
return this.many2one.appendTo(this.$el);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -1445,7 +1456,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
|
||||
var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({
|
||||
_render: function () {
|
||||
var self = this;
|
||||
this.$el.addClass('o_form_field_many2manytags o_kanban_tags');
|
||||
this.$el.addClass('o_field_many2manytags o_kanban_tags');
|
||||
_.each(this.value.data, function (m2m) {
|
||||
// 10th color is invisible
|
||||
if ('color' in m2m.data && m2m.data.color !== 10) {
|
||||
|
||||
@@ -52,7 +52,7 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
if (!canBeSaved) {
|
||||
invalidFields.push(widget.name);
|
||||
}
|
||||
widget.$el.toggleClass('o_form_invalid', !canBeSaved);
|
||||
widget.$el.toggleClass('o_field_invalid', !canBeSaved);
|
||||
});
|
||||
return invalidFields;
|
||||
},
|
||||
@@ -249,9 +249,9 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
}
|
||||
|
||||
// Toggle modifiers CSS classes if necessary
|
||||
element.$el.toggleClass("o_form_invisible", !!modifiers.invisible);
|
||||
element.$el.toggleClass("o_readonly", !!modifiers.readonly);
|
||||
element.$el.toggleClass("o_form_required", !!modifiers.required);
|
||||
element.$el.toggleClass("o_invisible_modifier", !!modifiers.invisible);
|
||||
element.$el.toggleClass("o_readonly_modifier", !!modifiers.readonly);
|
||||
element.$el.toggleClass("o_required_modifier", !!modifiers.required);
|
||||
|
||||
// Call associated callback
|
||||
if (element.callback) {
|
||||
@@ -495,7 +495,15 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
// Update the modifiers registration by associating the widget and by
|
||||
// giving the modifiers options now (as the potential callback is
|
||||
// associated to new widget)
|
||||
this._registerModifiers(node, record, widget, modifiersOptions);
|
||||
this._registerModifiers(node, record, widget, _.extend({
|
||||
callback: (function (element, modifiers, record) {
|
||||
element.$el.toggleClass('o_field_empty', !!(
|
||||
record.data.id
|
||||
&& (modifiers.readonly || this.mode === 'readonly')
|
||||
&& !element.widget.isSet()
|
||||
));
|
||||
}).bind(this),
|
||||
}, modifiersOptions || {}));
|
||||
|
||||
return widget;
|
||||
},
|
||||
|
||||
@@ -8,10 +8,6 @@ var core = require('web.core');
|
||||
var _t = core._t;
|
||||
var qweb = core.qweb;
|
||||
|
||||
var FIELD_CLASSES = {
|
||||
'one2many': 'o_field_one2many',
|
||||
};
|
||||
|
||||
var FormRenderer = BasicRenderer.extend({
|
||||
className: "o_form_view",
|
||||
/**
|
||||
@@ -27,7 +23,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Extend the method so that labels also receive the 'o_form_invalid' class
|
||||
* Extend the method so that labels also receive the 'o_field_invalid' class
|
||||
* if necessary.
|
||||
*
|
||||
* @override
|
||||
@@ -40,14 +36,14 @@ var FormRenderer = BasicRenderer.extend({
|
||||
var fieldNames = this._super.apply(this, arguments);
|
||||
|
||||
var $labels = this.$('label');
|
||||
$labels.removeClass('o_form_invalid');
|
||||
$labels.removeClass('o_field_invalid');
|
||||
|
||||
_.each(fieldNames, function (fieldName) {
|
||||
var idForLabel = self.idsForLabels[fieldName];
|
||||
if (idForLabel) {
|
||||
$labels
|
||||
.filter('[for=' + idForLabel + ']')
|
||||
.addClass('o_form_invalid');
|
||||
.addClass('o_field_invalid');
|
||||
}
|
||||
});
|
||||
return fieldNames;
|
||||
@@ -66,7 +62,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
_.each(resetWidgets, function (widget) {
|
||||
self._setIDForLabel(widget, self.idsForLabels[widget.name]);
|
||||
});
|
||||
return resetWidgets
|
||||
return resetWidgets;
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -105,7 +101,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
var name = $notebook.data('name');
|
||||
if (name in state) {
|
||||
var $page = $notebook.find('> ul > li').eq(state[name]);
|
||||
if (!$page.hasClass('o_form_invisible')) {
|
||||
if (!$page.hasClass('o_invisible_modifier')) {
|
||||
$page.find('a[data-toggle="tab"]').click();
|
||||
}
|
||||
}
|
||||
@@ -137,15 +133,6 @@ var FormRenderer = BasicRenderer.extend({
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds the adequate classnames to a field widget's $el.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} widget a field widget
|
||||
*/
|
||||
_addFieldClassNames: function (widget) {
|
||||
widget.$el.addClass('o_form_field'); // TODO will be removed in the CSS update
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {jQueryElement} $el
|
||||
@@ -207,7 +194,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
}
|
||||
});
|
||||
var buttons_partition = _.partition(buttons, function ($button) {
|
||||
return $button.is('.o_form_invisible');
|
||||
return $button.is('.o_invisible_modifier');
|
||||
});
|
||||
var invisible_buttons = buttons_partition[0];
|
||||
var visible_buttons = buttons_partition[1];
|
||||
@@ -261,22 +248,8 @@ var FormRenderer = BasicRenderer.extend({
|
||||
* @returns {AbstractField}
|
||||
*/
|
||||
_renderFieldWidget: function (node, record, options, modifiersOptions) {
|
||||
var self = this;
|
||||
modifiersOptions = _.extend({
|
||||
callback: function (element, modifiers, record) {
|
||||
element.$el.toggleClass('o_form_field_empty', !!( // FIXME condition is evaluated twice (label AND widget...)
|
||||
record.data.id
|
||||
&& (modifiers.readonly || self.mode === 'readonly')
|
||||
&& !element.widget.isSet()
|
||||
));
|
||||
},
|
||||
}, modifiersOptions || {});
|
||||
|
||||
var widget = this._super(node, record, options, modifiersOptions);
|
||||
var widget = this._super.apply(this, arguments);
|
||||
this._setIDForLabel(widget, this._getIDForLabel(node.attrs.name));
|
||||
|
||||
widget.$el.addClass(FIELD_CLASSES[record.fields[node.attrs.name].type]);
|
||||
this._addFieldClassNames(widget);
|
||||
this._handleAttributes(widget.$el, node);
|
||||
if (JSON.parse(node.attrs.default_focus || "0")) {
|
||||
this.defaultFocusField = widget;
|
||||
@@ -344,7 +317,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
});
|
||||
this._registerModifiers(node, this.state, $label, {
|
||||
callback: function (element, modifiers, record) {
|
||||
element.$el.toggleClass('o_form_label_empty', !!(
|
||||
element.$el.toggleClass('o_form_label_empty', !!( // FIXME condition is evaluated twice (label AND widget...)
|
||||
record.data.id
|
||||
&& (modifiers.readonly || self.mode === 'readonly')
|
||||
&& !widget.isSet() // getting like this because it could have been re-rendered...
|
||||
@@ -656,7 +629,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
if (modifiers.invisible && element.$el.hasClass('active')) {
|
||||
element.$el.removeClass('active');
|
||||
tab.$page.removeClass('active');
|
||||
var $firstVisibleTab = $headers.find('li:not(.o_form_invisible):first()');
|
||||
var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first()');
|
||||
$firstVisibleTab.addClass('active');
|
||||
$pages.find($firstVisibleTab.find('a').attr('href')).addClass('active');
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ ListRenderer.include({
|
||||
'click tbody tr:not(.o_data_row)': '_onEmptyRowClick',
|
||||
'click tfoot': '_onFooterClick',
|
||||
'click tr .o_list_record_delete': '_onTrashIconClick',
|
||||
'click .o_form_field_x2many_list_row_add a': '_onAddRecord',
|
||||
'click .o_field_x2many_list_row_add a': '_onAddRecord',
|
||||
}),
|
||||
/**
|
||||
* @override
|
||||
@@ -89,31 +89,6 @@ ListRenderer.include({
|
||||
}
|
||||
return this._super(recordID);
|
||||
},
|
||||
/**
|
||||
* @see BasicRenderer.confirmChange
|
||||
*
|
||||
* We also react to changes by adding the 'o_field_dirty' css class,
|
||||
* which changes its style to a visible orange outline. It allows the user
|
||||
* to have a visual feedback on which fields changed, and on which fields
|
||||
* have been saved.
|
||||
*
|
||||
* @todo maybe should be a basic behavior
|
||||
*
|
||||
* @override
|
||||
* @param {Object} state - a record resource (the new full state)
|
||||
* @param {string} id - the local id for the changed record
|
||||
* @param {string[]} fields - list of modified fields
|
||||
* @param {OdooEvent} e - the event that triggered the change
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
confirmChange: function (state, id, fields, e) {
|
||||
return this._super.apply(this, arguments).then(function (resetWidgets) {
|
||||
_.each(resetWidgets, function (widget) {
|
||||
var $td = widget.$el.parent();
|
||||
$td.addClass('o_field_dirty');
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* This method is called by the controller when the user has clicked 'save',
|
||||
* and the model as actually saved the current changes. We then need to
|
||||
@@ -172,9 +147,8 @@ ListRenderer.include({
|
||||
*
|
||||
* @param {string} recordID
|
||||
* @param {string} mode
|
||||
* @param {boolean} [keepDirtyFlag=false]
|
||||
*/
|
||||
setRowMode: function (recordID, mode, keepDirtyFlag) {
|
||||
setRowMode: function (recordID, mode) {
|
||||
var self = this;
|
||||
var rowIndex = _.findIndex(this.state.data, {id: recordID});
|
||||
if (rowIndex < 0) {
|
||||
@@ -185,12 +159,18 @@ ListRenderer.include({
|
||||
|
||||
this.currentRow = editMode ? rowIndex : null;
|
||||
var $row = this.$('.o_data_row:nth(' + rowIndex + ')');
|
||||
$row.toggleClass('o_selected_row', editMode);
|
||||
|
||||
if (editMode) {
|
||||
// Instantiate column widgets and destroy potential readonly ones
|
||||
var oldWidgets = _.clone(this.allFieldWidgets[record.id]);
|
||||
var $tds = $row.children('.o_data_cell');
|
||||
// Force the size of each cell to its current value so that it
|
||||
// won't change if its content changes, to prevent the view from
|
||||
// flickering
|
||||
$tds.each(function () {
|
||||
var $td = $(this);
|
||||
$td.css({width: $td.outerWidth()});
|
||||
});
|
||||
_.each(this.columns, function (node, colIndex) {
|
||||
var $td = $tds.eq(colIndex);
|
||||
var $newTd = self._renderBodyCell(record, node, colIndex, {
|
||||
@@ -203,18 +183,16 @@ ListRenderer.include({
|
||||
self._unregisterModifiersElement(node, record, $td.children());
|
||||
}
|
||||
|
||||
// Force the width of each cell to its current value so that it
|
||||
// won't change if its content changes, to prevent the view from
|
||||
// flickering
|
||||
$td.width($td.width());
|
||||
$td.empty().append($newTd.contents());
|
||||
});
|
||||
_.each(oldWidgets, this._destroyFieldWidget.bind(this, record));
|
||||
} else {
|
||||
for (var colIndex = 0; colIndex < this.columns.length; colIndex++) {
|
||||
this._setCellValue(rowIndex, colIndex, keepDirtyFlag || false);
|
||||
this._setCellValue(rowIndex, colIndex);
|
||||
}
|
||||
}
|
||||
|
||||
$row.toggleClass('o_selected_row', editMode); // Toggle here so that style is applied at the end
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -310,7 +288,7 @@ ListRenderer.include({
|
||||
var $a = $('<a href="#">').text(_t("Add an item"));
|
||||
var $td = $('<td>')
|
||||
.attr('colspan', this._getNumberOfCols())
|
||||
.addClass('o_form_field_x2many_list_row_add')
|
||||
.addClass('o_field_x2many_list_row_add')
|
||||
.append($a);
|
||||
var $tr = $('<tr>').append($td);
|
||||
$rows.push($tr);
|
||||
@@ -398,17 +376,13 @@ ListRenderer.include({
|
||||
*
|
||||
* @param {integer} rowIndex
|
||||
* @param {integer} colIndex
|
||||
* @param {boolean} keepDirtyFlag
|
||||
*/
|
||||
_setCellValue: function (rowIndex, colIndex, keepDirtyFlag) {
|
||||
_setCellValue: function (rowIndex, colIndex) {
|
||||
var record = this.state.data[rowIndex];
|
||||
var node = this.columns[colIndex];
|
||||
|
||||
var $oldTd = this.$('.o_data_row:nth(' + rowIndex + ') > .o_data_cell:nth(' + colIndex + ')');
|
||||
var $newTd = this._renderBodyCell(record, node, colIndex, {mode: 'readonly'});
|
||||
if (keepDirtyFlag && $oldTd.hasClass('o_field_dirty')) {
|
||||
$newTd.addClass('o_field_dirty');
|
||||
}
|
||||
this._unregisterModifiersElement(node, record, $oldTd);
|
||||
$oldTd.replaceWith($newTd);
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ var SwitchCompanyMenu = Widget.extend({
|
||||
_.each(session.user_companies.allowed_companies, function(company) {
|
||||
var a = '';
|
||||
if (company[0] === session.user_companies.current_company[0]) {
|
||||
a = '<i class="fa fa-check o_current_company"></i>';
|
||||
a = '<i class="fa fa-check mr8"></i>';
|
||||
} else {
|
||||
a = '<span class="o_company"/>';
|
||||
a = '<span class="mr24"/>';
|
||||
}
|
||||
companies_list += '<li><a href="#" data-menu="company" data-company-id="' + company[0] + '">' + a + company[1] + '</a></li>';
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/************** DEFINITION of ANIMATIONS *************/
|
||||
/************** DEFINITION of ANIMATIONS **************/
|
||||
// 'marked' effects
|
||||
@keyframes markAnim {
|
||||
0% {
|
||||
@@ -145,51 +145,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
/************** MIXINS for ANIMATIONS *************/
|
||||
/************** MIXINS for ANIMATIONS **************/
|
||||
.o-display-marked(@content, @top, @left, @color) {
|
||||
position: absolute;
|
||||
top: @top;
|
||||
left: @left;
|
||||
.o-position-absolute(@top: @top, @left: @left);
|
||||
font-size: 300px;
|
||||
font-family: "FontAwesome";
|
||||
content: @content;
|
||||
color: @color;
|
||||
animation: markAnim ease-in-out 1s;
|
||||
animation-iteration-count: 1;
|
||||
transform-origin: 50% 50%;
|
||||
animation-fill-mode:forwards; /*when the spec is finished*/
|
||||
-webkit-animation: markAnim ease-in-out 1s;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
-webkit-transform-origin: 50% 50%;
|
||||
-webkit-animation-fill-mode:forwards; /*Chrome 16+, Safari 4+*/
|
||||
-moz-animation: markAnim ease-in-out 1s;
|
||||
-moz-animation-iteration-count: 1;
|
||||
-moz-transform-origin: 50% 50%;
|
||||
-moz-animation-fill-mode:forwards; /*FF 5+*/
|
||||
-o-animation: markAnim ease-in-out 1s;
|
||||
-o-animation-iteration-count: 1;
|
||||
-o-transform-origin: 50% 50%;
|
||||
-o-animation-fill-mode:forwards; /*Not implemented yet*/
|
||||
-ms-animation: markAnim ease-in-out 1s;
|
||||
-ms-animation-iteration-count: 1;
|
||||
-ms-transform-origin: 50% 50%;
|
||||
-ms-animation-fill-mode:forwards; /*IE 10+*/
|
||||
.o-transform-origin();
|
||||
.o-animation(markAnim, 1s, ease-in-out, 0s, 1, normal, forwards);
|
||||
|
||||
@media (max-width: 992px) {
|
||||
@media (max-width: @screen-sm-max) {
|
||||
left: 40%;
|
||||
font-size: 30vw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************** USAGE of ANIMATIONS *************/
|
||||
/************** USAGE of ANIMATIONS **************/
|
||||
// Animation on wow button
|
||||
// TODO the only difference here is the "content" property, just make an
|
||||
// 'o_wow' class for the other properties to avoid generating useless CSS
|
||||
.o_wow_thumbs:after {
|
||||
.o-display-marked("\f164", 20%, 40%, #21b799);
|
||||
.o-display-marked("\f164", 20%, 40%, @odoo-brand-optional);
|
||||
}
|
||||
.o_wow_peace:after {
|
||||
.o-display-marked("\f118", 20%, 40%, #21b799);
|
||||
.o-display-marked("\f118", 20%, 40%, @odoo-brand-optional);
|
||||
}
|
||||
.o_wow_heart:after {
|
||||
.o-display-marked("\f004", 20%, 40%, #21b799);
|
||||
.o-display-marked("\f004", 20%, 40%, @odoo-brand-optional);
|
||||
}
|
||||
|
||||
@@ -1,63 +1,109 @@
|
||||
@breadcrumb-height: 30px;
|
||||
|
||||
.o_control_panel {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(row, wrap);
|
||||
border-bottom: 1px solid @odoo-main-color-muted;
|
||||
.o-webclient-padding(@top: 10px, @bottom: 10px);
|
||||
background-color: @odoo-control-panel-background-color;
|
||||
border-bottom: 1px solid @odoo-main-color-muted;
|
||||
.breadcrumb {
|
||||
font-size: 18px;
|
||||
|
||||
> .breadcrumb {
|
||||
width: 50%;
|
||||
margin: 0px;
|
||||
> li > a {
|
||||
color: @odoo-brand-optional;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: darken(@odoo-brand-optional, 10%);
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
|
||||
> li {
|
||||
.o-text-overflow(@max-width: 90%);
|
||||
|
||||
> a {
|
||||
color: @odoo-brand-optional;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: darken(@odoo-brand-optional, 10%);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar
|
||||
.o_cp_sidebar {
|
||||
padding-right: 10px;
|
||||
&.o_breadcrumb_full > .breadcrumb {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.o_hidden_input_file {
|
||||
position: relative;
|
||||
input.o_form_input_file {
|
||||
> .o_cp_searchview {
|
||||
width: 50%;
|
||||
min-height: @breadcrumb-height;
|
||||
}
|
||||
|
||||
.btn.o_enable_searchview {
|
||||
width: 10%;
|
||||
margin-left: 2%;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
> .o_cp_left {
|
||||
.o-flex-display();
|
||||
.o-justify-content(space-between);
|
||||
width: 50%;
|
||||
margin-top: 5px;
|
||||
|
||||
> .o_cp_sidebar {
|
||||
padding-right: 10px;
|
||||
|
||||
.o_hidden_input_file {
|
||||
position: relative;
|
||||
input.o_input_file {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
}
|
||||
.o_form_binary_form span {
|
||||
padding: 3px 25px;
|
||||
color: @btn-default-color;
|
||||
}
|
||||
.o_form_binary_form:hover {
|
||||
background-color: @table-bg-hover;
|
||||
}
|
||||
}
|
||||
.o_sidebar_delete_attachment {
|
||||
padding: 0px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
.o_form_binary_form span {
|
||||
padding: 3px 25px;
|
||||
color: @btn-default-color;
|
||||
}
|
||||
.o_form_binary_form:hover {
|
||||
background-color: @table-bg-hover;
|
||||
}
|
||||
}
|
||||
.o_sidebar_delete_attachment {
|
||||
padding: 0px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// Pager
|
||||
.o_cp_pager {
|
||||
text-align: center;
|
||||
padding-left: 5px;
|
||||
.user-select(none);
|
||||
}
|
||||
> .o_cp_right {
|
||||
.o-flex-display();
|
||||
width: 50%;
|
||||
margin-top: 5px;
|
||||
|
||||
// View Switcher
|
||||
.o_cp_switch_buttons {
|
||||
padding-left: 5px;
|
||||
> .o_cp_pager {
|
||||
margin: auto 0 auto auto;
|
||||
padding-left: 5px;
|
||||
text-align: center;
|
||||
.user-select(none);
|
||||
}
|
||||
|
||||
> .o_cp_switch_buttons {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_x2m_control_panel {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(row, wrap);
|
||||
|
||||
.o_cp_buttons, .o_cp_pager {
|
||||
.o-flex-display();
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.o_cp_buttons > div {
|
||||
margin-top: 5px;
|
||||
}
|
||||
@@ -68,7 +114,14 @@
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
text-align: right;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.o_control_panel {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
@breadcrumb-height: 30px;
|
||||
|
||||
.o_control_panel {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(row, wrap);
|
||||
|
||||
.breadcrumb {
|
||||
width: 50%;
|
||||
|
||||
> li {
|
||||
.o_text_overflow;
|
||||
max-width: 90%;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_breadcrumb_full {
|
||||
.breadcrumb {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.o_cp_searchview {
|
||||
width: 50%;
|
||||
min-height: @breadcrumb-height;
|
||||
}
|
||||
|
||||
.btn.o_enable_searchview {
|
||||
width: 10%;
|
||||
margin-left: 2%;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.o_cp_left {
|
||||
width: 50%;
|
||||
margin-top: 5px;
|
||||
.o-flex-display();
|
||||
.o-justify-content(space-between);
|
||||
}
|
||||
|
||||
.o_cp_right {
|
||||
width: 50%;
|
||||
margin-top: 5px;
|
||||
.o-flex-display();
|
||||
|
||||
.o_cp_pager {
|
||||
margin: auto 0 auto auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_x2m_control_panel {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(row, wrap);
|
||||
|
||||
.o_cp_buttons {
|
||||
.o-flex-display();
|
||||
margin-right: auto;
|
||||
}
|
||||
.o_cp_pager {
|
||||
.o-flex-display();
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.o_control_panel {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
//
|
||||
// This file regroups all the rules which apply to field widgets wherever they
|
||||
// are in the DOM, in both community and enterprise versions.
|
||||
//
|
||||
|
||||
// Invalid
|
||||
.o_field_invalid {
|
||||
&.o_input, .o_input, &.o_form_label {
|
||||
color: @brand-danger!important;
|
||||
border-color: @brand-danger!important; // enterprise o_required_modifier rule overrides this without !important
|
||||
}
|
||||
}
|
||||
|
||||
// Empty
|
||||
.o_field_empty {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
// Numbers
|
||||
.o_field_number {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Fields
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
.o_field_widget {
|
||||
display: inline-block;
|
||||
|
||||
// Block fields
|
||||
&.note-editor, &.oe_form_field_html, &.oe_form_field_html_text, &.oe_form_field_text, &.o_view_manager_content, &.o_field_domain {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Flex fields (inline)
|
||||
&.o_field_many2one, &.o_field_radio, &.o_field_many2manytags, &.o_field_percent_pie, &.o_field_monetary, &.o_field_binary_file {
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.o-inline-flex-display();
|
||||
}
|
||||
> span, > button {
|
||||
.o-flex(0, 0, auto);
|
||||
}
|
||||
}
|
||||
|
||||
// Dropdowns input (many2one, ...)
|
||||
.o_input_dropdown {
|
||||
.o-flex(1, 0, auto);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
> input {
|
||||
height: 100%;
|
||||
padding-right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_dropdown_button {
|
||||
.o-position-absolute(0, 0);
|
||||
pointer-events: none;
|
||||
&:after {
|
||||
.o-caret-down;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input in field
|
||||
input[type="text"] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// Text
|
||||
&.o_field_text, &.oe_form_field_text .oe_form_text_content {
|
||||
width: 100%;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
// Monetary
|
||||
&.o_field_monetary {
|
||||
&.o_input {
|
||||
.o-align-items(baseline);
|
||||
|
||||
> input {
|
||||
width: 100px;
|
||||
.o-flex(1, 0, auto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Many2many tags
|
||||
&.o_field_many2manytags {
|
||||
.o-flex-flow(row, wrap);
|
||||
.o-align-items(baseline);
|
||||
|
||||
> .o_field_widget {
|
||||
.o-flex(1, 0, 100px);
|
||||
position: initial;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
> .badge {
|
||||
.o-flex(0, 0, auto);
|
||||
border: 0;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
|
||||
&.o_tag_color_0 { background-color: #4D4D4D; }
|
||||
&.o_tag_color_1 { background-color: #61BD4F; }
|
||||
&.o_tag_color_2 { background-color: #F2D600; }
|
||||
&.o_tag_color_3 { background-color: #FFAB4A; }
|
||||
&.o_tag_color_4 { background-color: #EB5A46; }
|
||||
&.o_tag_color_5 { background-color: #875A7B; }
|
||||
&.o_tag_color_6 { background-color: #0079BF; }
|
||||
&.o_tag_color_7 { background-color: #00C2E0; }
|
||||
&.o_tag_color_8 { background-color: #4CD98E; }
|
||||
&.o_tag_color_9 { background-color: #FF80CE; }
|
||||
&.o_tag_color_10 { background-color: #B6BBBF; }
|
||||
|
||||
> .o_badge_text {
|
||||
.o-text-overflow(inline-block);
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
> ul {
|
||||
@colored-tag-width: 45px;
|
||||
width: 5*@colored-tag-width + 3px;
|
||||
> li {
|
||||
float: left;
|
||||
color: black;
|
||||
> span {
|
||||
border-radius: 6px;
|
||||
width: @colored-tag-width;
|
||||
height: 30px;
|
||||
display: inline-block;
|
||||
border: 2px solid white;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
> li:last-child {
|
||||
margin-top: 7px;
|
||||
cursor: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.o_delete {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stars
|
||||
&.o_priority {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
> .o_priority_star {
|
||||
display: inline-block;
|
||||
font-size: 1.35em;
|
||||
&:hover, &:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
+ .o_priority_star {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
&.fa-star-o {
|
||||
color: @odoo-main-color-muted;
|
||||
}
|
||||
&.fa-star {
|
||||
color: gold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Status
|
||||
&.o_selection .o_status {
|
||||
display: inline-block;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
border-radius: 6px;
|
||||
vertical-align: middle;
|
||||
|
||||
background-color: @odoo-brand-secondary;
|
||||
|
||||
&.o_status_green {
|
||||
background-color: @brand-success;
|
||||
}
|
||||
&.o_status_red {
|
||||
background-color: @brand-danger;
|
||||
}
|
||||
}
|
||||
|
||||
// Specific success color for toggle_button widget
|
||||
.fa.o_toggle_button_success {
|
||||
color: @brand-success;
|
||||
}
|
||||
|
||||
// Many2One
|
||||
&.o_field_many2one {
|
||||
.o-inline-flex-display();
|
||||
> span, > button {
|
||||
.o-flex(0, 0, auto);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle widget
|
||||
&.o_row_handle {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
// Radio buttons
|
||||
&.o_field_radio {
|
||||
.o_radio_input {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.o_radio_item {
|
||||
.o-flex(0, 0, auto);
|
||||
.o-flex-display();
|
||||
.o-align-items(center);
|
||||
|
||||
> input {
|
||||
.o-flex(0, 0, auto);
|
||||
margin: 0 @odoo-form-spacing-unit 0 0;
|
||||
}
|
||||
> label {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_horizontal {
|
||||
.o_radio_item {
|
||||
margin-right: @odoo-form-spacing-unit * 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_vertical {
|
||||
.o-flex-flow(column, nowrap);
|
||||
.o_radio_item {
|
||||
margin-bottom: @odoo-form-spacing-unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Percent pie
|
||||
&.o_field_percent_pie {
|
||||
.o-align-items(center);
|
||||
|
||||
> .o_pie {
|
||||
position: relative;
|
||||
margin-right: 10px;
|
||||
border-radius: 100%;
|
||||
overflow: hidden;
|
||||
background-color: @odoo-brand-optional;
|
||||
|
||||
&:after { // Outside pie border to go over border-radius irregularities
|
||||
content: " ";
|
||||
.o-position-absolute(0, 0);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.o_mask {
|
||||
.o-position-absolute(0, 0);
|
||||
.o-transform-origin(0);
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background-color: @odoo-view-background-color;
|
||||
&.o_full {
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.o_pie_value {
|
||||
.o-flex-display();
|
||||
.o-justify-content(center);
|
||||
.o-align-items(center);
|
||||
|
||||
border-radius: 100%;
|
||||
|
||||
font-weight: 700;
|
||||
color: @odoo-brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ace editor
|
||||
&.o_ace_view_editor {
|
||||
width: 100%;
|
||||
.ace-view-editor {
|
||||
height: 300px;
|
||||
padding: 0 1em;
|
||||
}
|
||||
}
|
||||
|
||||
// Image
|
||||
&.o_field_image {
|
||||
position: relative;
|
||||
|
||||
.o_form_image_controls {
|
||||
.o-position-absolute(0, 0);
|
||||
width: 100%;
|
||||
|
||||
color: white;
|
||||
background-color: @odoo-brand-optional;
|
||||
opacity: 0;
|
||||
transition: opacity ease 400ms;
|
||||
|
||||
> .fa {
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@media (max-width: @screen-xs-min) {
|
||||
.o_form_image_controls{
|
||||
position: initial;
|
||||
opacity: 1;
|
||||
> .fa{
|
||||
width: 50%;
|
||||
padding: 6px;
|
||||
margin: 0px;
|
||||
text-align: center;
|
||||
&.o_select_file_button{
|
||||
background: @odoo-brand-optional;
|
||||
}
|
||||
&.o_clear_file_button{
|
||||
background: @brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .o_form_image_controls {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
// Input loading/file
|
||||
.o_form_binary_progress, .o_hidden_input_file .o_input_file {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Domain
|
||||
&.o_field_domain {
|
||||
> .o_field_domain_panel {
|
||||
margin-top: 8px;
|
||||
}
|
||||
&.o_inline_mode.o_edit_mode {
|
||||
position: relative;
|
||||
|
||||
> .o_field_domain_panel {
|
||||
.o-position-absolute(0, 0);
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// This file regroups all the rules which apply to field widgets wherever they
|
||||
// are in the DOM, in the community version.
|
||||
//
|
||||
|
||||
// Required
|
||||
.o_required_modifier {
|
||||
&.o_input, .o_input {
|
||||
background-color: #D2D2FF;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Fields
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
.o_field_widget {
|
||||
// Dropdowns input carret
|
||||
.o_input_dropdown .o_dropdown_button {
|
||||
.o-position-absolute(2px, 4px);
|
||||
}
|
||||
|
||||
// Many2one
|
||||
&.o_field_many2one .o_external_button {
|
||||
padding: 0;
|
||||
margin-left: 2px;
|
||||
font-size: 19px;
|
||||
color: #7C7BAD;
|
||||
border: none;
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// Percent pie field
|
||||
&.o_field_percent_pie {
|
||||
@pie-dimension: 34px;
|
||||
@pie-ring-width: 4px;
|
||||
|
||||
.o_pie {
|
||||
width: @pie-dimension;
|
||||
height: @pie-dimension;
|
||||
margin-left: 5px;
|
||||
|
||||
&:after { // Outside pie border to go over border-radius irregularities
|
||||
border: 1px solid @odoo-brand-primary;
|
||||
}
|
||||
|
||||
.o_pie_value {
|
||||
.o-position-absolute(@pie-ring-width, @pie-ring-width);
|
||||
width: @pie-dimension - 2 * @pie-ring-width;
|
||||
height: @pie-dimension - 2 * @pie-ring-width;
|
||||
border: 1px solid white;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
.o_form_view {
|
||||
background-color: @odoo-view-background-color;
|
||||
|
||||
// Utility classes (+ oe_edit_only, oe_read_only, o_label_nowrap, o_text_overflow)
|
||||
.o_form_invisible, .o_form_field_empty {
|
||||
display: none!important;
|
||||
}
|
||||
// Utility classes
|
||||
.oe_form_box_info {
|
||||
.bg-info;
|
||||
.o-webclient-padding(@top: 5px, @bottom: 5px);
|
||||
@@ -21,11 +18,72 @@
|
||||
.oe_grey {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.oe_inline {
|
||||
width: auto!important;
|
||||
@media (min-width: @screen-xs-min) {
|
||||
&.o_inner_group {
|
||||
width: 1px!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.oe_left {
|
||||
.oe_inline;
|
||||
float: left!important;
|
||||
}
|
||||
.oe_right {
|
||||
.oe_inline;
|
||||
float: right!important;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-xs-min) {
|
||||
.o_row {
|
||||
&, &.o_field_widget { // Some field may want to use o_row as root and these rules must prevalue
|
||||
.o-flex-display();
|
||||
width: auto!important;
|
||||
}
|
||||
|
||||
.o-align-items(baseline);
|
||||
min-width: 50px;
|
||||
margin: 0 -@odoo-form-spacing-unit/2;
|
||||
|
||||
> div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule
|
||||
.o-flex(0, 0, auto);
|
||||
width: auto!important;
|
||||
margin-right: @odoo-form-spacing-unit/2;
|
||||
margin-left: @odoo-form-spacing-unit/2;
|
||||
}
|
||||
|
||||
> .o_row {
|
||||
margin: 0;
|
||||
}
|
||||
> .btn {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
> .o_field_boolean {
|
||||
.o-align-self(center);
|
||||
}
|
||||
}
|
||||
|
||||
.o_row .o_field_many2one, .o_field_many2one.oe_inline {
|
||||
&.o_with_button:not(:last-child) { // If invisible element as last child, this line has no effect but that's not very important
|
||||
margin-right: (35px + (@odoo-form-spacing-unit/2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_row > div > .o_field_widget {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Readonly specific rules
|
||||
&.o_form_readonly {
|
||||
.oe_edit_only {
|
||||
.o_form_invisible;
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
.o_row, .o_row > div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.o_form_uri { // FIXME maybe global?
|
||||
@@ -47,42 +105,63 @@
|
||||
// Editable specific rules
|
||||
&.o_form_editable {
|
||||
.oe_read_only {
|
||||
.o_form_invisible;
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
.o_form_field_many2manytags {
|
||||
.o-input();
|
||||
.oe_title {
|
||||
max-width: @container-sm - (2 * @odoo-horizontal-padding);
|
||||
}
|
||||
|
||||
> .o_form_field {
|
||||
.o-flex(1, 0, 100px);
|
||||
position: initial;
|
||||
max-width: 100%;
|
||||
@media (min-width: @screen-xs-min) {
|
||||
.o_row {
|
||||
> .o_field_widget, > div {
|
||||
.o-flex(1, 1, auto);
|
||||
width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0)
|
||||
|
||||
> .o_form_input_dropdown > .o_form_input {
|
||||
border-style: none!important;
|
||||
&.o_field_boolean, &.o_priority {
|
||||
.o-flex(0, 0, auto);
|
||||
width: auto!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field_monetary {
|
||||
.o-input();
|
||||
.o-align-items(baseline);
|
||||
|
||||
> .o_form_input {
|
||||
border-style: none!important;
|
||||
width: 100px;
|
||||
.o-flex(1, 0, auto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Header containing status/workflow buttons
|
||||
// Statusbar
|
||||
.o_form_statusbar {
|
||||
background-color: @odoo-view-background-color;
|
||||
.o-flex(0, 0, auto);
|
||||
position: relative; // Needed for the "More" dropdown
|
||||
.o-flex-display();
|
||||
.o-justify-content(space-between);
|
||||
padding-left: @odoo-horizontal-padding;
|
||||
border-bottom: 1px solid @odoo-brand-secondary;
|
||||
background-color: @odoo-view-background-color;
|
||||
|
||||
> .o_statusbar_buttons, > .o_statusbar_status {
|
||||
.o-flex-display();
|
||||
.o-align-items(center);
|
||||
.o-align-content(space-around);
|
||||
}
|
||||
|
||||
> .o_field_widget {
|
||||
.o-align-self(center);
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
> .o_statusbar_buttons {
|
||||
.o-flex-flow(row, wrap);
|
||||
|
||||
> .btn {
|
||||
margin: 2px 3px 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
> .o_statusbar_status {
|
||||
.o-flex-flow(row-reverse, wrap-reverse);
|
||||
.o-align-self(stretch);
|
||||
.o-align-items(stretch);
|
||||
overflow-x: hidden; // to prevent horizontal scroll due to last arrow
|
||||
|
||||
> .o_arrow_button {
|
||||
min-height: @odoo-statusbar-height;
|
||||
font-size: 11px;
|
||||
@@ -152,6 +231,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o-status-more {
|
||||
.o-position-absolute(100%, 0);
|
||||
min-width: 100px;
|
||||
@@ -161,6 +241,26 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Touch device mode
|
||||
> .o_statusbar_buttons > .btn-group {
|
||||
> .dropdown-toggle {
|
||||
&:after {
|
||||
.o-caret-down();
|
||||
margin-left: @odoo-form-spacing-unit;
|
||||
}
|
||||
}
|
||||
|
||||
> .dropdown-menu {
|
||||
padding: 5px 0 2px 0;
|
||||
min-width: 100px;
|
||||
|
||||
> li > .btn {
|
||||
min-width: 100%;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Button box
|
||||
@@ -177,6 +277,12 @@
|
||||
|
||||
// Title
|
||||
.oe_title {
|
||||
> h1, > h2, > h3 {
|
||||
width: 100%; // Needed because inline-block when is a hx.o_row
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
line-height: inherit;
|
||||
}
|
||||
.o_priority > .o_priority_star {
|
||||
font-size: inherit;
|
||||
}
|
||||
@@ -184,25 +290,62 @@
|
||||
|
||||
// Groups
|
||||
.o_group {
|
||||
&.o_label_nowrap {
|
||||
.o_form_label {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
|
||||
// o_group contains nested groups
|
||||
.o-generate-groups(@odoo-form-group-cols);
|
||||
.o-generate-groups(@n, @i: 1) when (@i =< @n) {
|
||||
.o_group_col_@{i} {
|
||||
display: inline-block;
|
||||
width: floor(100% / 12 * @i);
|
||||
vertical-align: top;
|
||||
}
|
||||
.o-generate-groups(@n, @i + 1);
|
||||
}
|
||||
|
||||
&.o_inner_group {
|
||||
display: inline-table;
|
||||
|
||||
> tbody > tr > td {
|
||||
&.o_td_label {
|
||||
width: 0%;
|
||||
padding: 0 15px 0 0;
|
||||
min-width: 150px;
|
||||
}
|
||||
vertical-align: top;
|
||||
|
||||
span, .o_field_boolean, .oe_avatar, .o_form_uri {
|
||||
&.o_field_widget {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.o_field_widget {
|
||||
width: 100%;
|
||||
|
||||
> .btn {
|
||||
.o-flex(0, 0, auto);
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_label_nowrap .o_form_label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.o_td_label .o_form_label {
|
||||
font-weight: bold;
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
&.oe_form_configuration {
|
||||
.o_group .o_form_label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// Separators
|
||||
.o_horizontal_separator {
|
||||
@@ -213,78 +356,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Notebooks
|
||||
.o_notebook {
|
||||
clear: both; // For the notebook not to have alongside floating elements
|
||||
margin-top: @odoo-form-spacing-unit * 2;
|
||||
|
||||
.nav-tabs > .tab-pane {
|
||||
min-height: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
// Labels
|
||||
.o_form_label {
|
||||
margin: 0 @odoo-form-spacing-unit 0 0;
|
||||
font-size: @font-size-base; // The label muse have the same size whatever their position
|
||||
line-height: @line-height-base;
|
||||
margin-right: @odoo-form-spacing-unit;
|
||||
&.o_form_invalid {
|
||||
color: @brand-danger;
|
||||
}
|
||||
|
||||
// Form fields
|
||||
.o_field_widget {
|
||||
margin-bottom: @odoo-form-spacing-unit;
|
||||
}
|
||||
.o_field_widget, .btn {
|
||||
.o_field_widget {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
// ace editor RO
|
||||
.oe_form_field_text .oe_form_text_content {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
// Tags
|
||||
.o_form_field_many2manytags {
|
||||
.badge {
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
border: 0;
|
||||
|
||||
> ul {
|
||||
@colored-tag-width: 45px;
|
||||
width: 5*@colored-tag-width + 3px;
|
||||
> li {
|
||||
float: left;
|
||||
color: black;
|
||||
> span {
|
||||
border-radius: 6px;
|
||||
width: @colored-tag-width;
|
||||
height: 30px;
|
||||
display: inline-block;
|
||||
border: 2px solid white;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
> li:last-child {
|
||||
margin-top: 7px;
|
||||
cursor: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_invalid {
|
||||
&.o_form_input, .o_form_input, &.o_form_textarea, .o_form_textarea {
|
||||
border-color: @brand-danger!important; // enterprise o_form_required rule overrides this without !important
|
||||
}
|
||||
}
|
||||
|
||||
// Boolean
|
||||
.o_form_field_boolean {
|
||||
margin: 0 @odoo-form-spacing-unit 0 0;
|
||||
}
|
||||
|
||||
// Numbers
|
||||
.o_form_field_number {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Radio buttons
|
||||
.o_form_field_radio .o_form_radio {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Translate icon
|
||||
.o_field_translate {
|
||||
padding: 0;
|
||||
@@ -299,160 +397,32 @@
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.o_form_field.o_form_invisible + .o_field_translate {
|
||||
.o_field_widget.o_invisible_modifier + .o_field_translate {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Dropdowns input (many2one, ...)
|
||||
.o_form_input_dropdown {
|
||||
.o-flex(1, 0, auto);
|
||||
position: relative;
|
||||
|
||||
> input {
|
||||
padding-right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_dropdown_button {
|
||||
pointer-events: none;
|
||||
&:after {
|
||||
.o-caret-down;
|
||||
}
|
||||
// Text field with oe_inline class
|
||||
.o_field_text.oe_inline {
|
||||
width: 100%!important;
|
||||
@media (min-width: @screen-xs-min) {
|
||||
width: 45%!important;
|
||||
}
|
||||
}
|
||||
|
||||
// Many2many tags
|
||||
.badge .o_delete {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// Image
|
||||
.o_form_field_image {
|
||||
position: relative;
|
||||
|
||||
.o_form_image_controls {
|
||||
.o-position-absolute(0, 0);
|
||||
// One2Many, Many2Many outside of group
|
||||
.o_field_widget {
|
||||
&.o_view_manager_content, &.o_field_one2many, &.o_field_many2many {
|
||||
width: 100%;
|
||||
|
||||
color: white;
|
||||
background-color: @odoo-brand-optional;
|
||||
opacity: 0;
|
||||
transition: opacity ease 400ms;
|
||||
|
||||
> .fa {
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@media (max-width: @screen-xs-min) {
|
||||
.o_form_image_controls{
|
||||
position: initial;
|
||||
opacity: 1;
|
||||
> .fa{
|
||||
width: 50%;
|
||||
padding: 6px;
|
||||
margin: 0px;
|
||||
text-align: center;
|
||||
&.o_select_file_button{
|
||||
background: @odoo-brand-optional;
|
||||
}
|
||||
&.o_clear_file_button{
|
||||
background: @brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .o_form_image_controls {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
// Input loading/file
|
||||
.o_form_binary_progress, .o_hidden_input_file .o_form_input_file {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Timezone widget warning
|
||||
.o_tz_warning {
|
||||
color: @brand-danger;
|
||||
cursor: help;
|
||||
position: absolute;
|
||||
margin-left: -40px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
// One2Many Kanban views
|
||||
.o_form_field .o_kanban_view.o_kanban_ungrouped {
|
||||
padding: 0;
|
||||
.o_kanban_record {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
// One2Many List views
|
||||
.o_form_field .o_list_view {
|
||||
margin-bottom: 10px;
|
||||
|
||||
> tfoot > tr > td {
|
||||
padding: 3px;
|
||||
color: @odoo-main-text-color;
|
||||
}
|
||||
}
|
||||
&.o_form_readonly .o_form_field .o_list_view .o_row_handle {
|
||||
display: none; // Hide the handler in non-edit mode
|
||||
}
|
||||
|
||||
// Percent pie field
|
||||
.o_form_field_percent_pie {
|
||||
.o_pie {
|
||||
position: relative;
|
||||
border-radius: 100%;
|
||||
overflow: hidden;
|
||||
background-color: @odoo-brand-optional;
|
||||
|
||||
&:after { // Outside pie border to go over border-radius irregularities
|
||||
content: " ";
|
||||
.o-position-absolute(0, 0);
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.o_mask {
|
||||
.o-position-absolute(0, 0);
|
||||
.o-transform-origin(0);
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background-color: @odoo-view-background-color;
|
||||
&.o_full {
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.o_pie_value {
|
||||
.o-flex-display();
|
||||
.o-justify-content(center);
|
||||
.o-align-items(center);
|
||||
|
||||
border-radius: 100%;
|
||||
|
||||
font-weight: 700;
|
||||
color: @odoo-brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attachments
|
||||
.oe_attachment {
|
||||
display: inline-block;
|
||||
border: 1px solid @odoo-brand-lightsecondary;
|
||||
margin: 0 @odoo-form-spacing-unit @odoo-form-spacing-unit 0;
|
||||
padding: @odoo-form-spacing-unit;
|
||||
}
|
||||
|
||||
// Specific style classes
|
||||
.o_group.o_inner_group.oe_subtotal_footer {
|
||||
.oe_right;
|
||||
|
||||
> tbody > tr > td {
|
||||
padding: 0;
|
||||
|
||||
@@ -470,7 +440,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field {
|
||||
.o_field_widget {
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -518,7 +488,7 @@
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
> span.o_form_field {
|
||||
> span.o_field_widget {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
@@ -556,12 +526,55 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Notebooks
|
||||
.o_notebook {
|
||||
.nav-tabs {
|
||||
> .tab-pane {
|
||||
min-height: 100px;
|
||||
}
|
||||
// Boolean
|
||||
.o_field_boolean {
|
||||
margin: 0 @odoo-form-spacing-unit 0 0;
|
||||
}
|
||||
|
||||
// Timezone widget warning
|
||||
.o_tz_warning {
|
||||
color: @brand-danger;
|
||||
cursor: help;
|
||||
position: absolute;
|
||||
margin-left: -40px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
// One2Many Kanban views
|
||||
.o_field_widget .o_kanban_view.o_kanban_ungrouped {
|
||||
padding: 0;
|
||||
.o_kanban_record {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
// One2Many List views
|
||||
.o_field_widget .o_list_view {
|
||||
margin-bottom: 10px;
|
||||
|
||||
> tfoot > tr > td {
|
||||
padding: 3px;
|
||||
color: @odoo-main-text-color;
|
||||
}
|
||||
}
|
||||
&.o_form_readonly .o_field_widget .o_list_view .o_row_handle {
|
||||
display: none; // Hide the handler in non-edit mode
|
||||
}
|
||||
|
||||
// Attachments
|
||||
.oe_attachment {
|
||||
display: inline-block;
|
||||
border: 1px solid @odoo-brand-lightsecondary;
|
||||
margin: 0 @odoo-form-spacing-unit @odoo-form-spacing-unit 0;
|
||||
padding: @odoo-form-spacing-unit;
|
||||
}
|
||||
|
||||
&.oe_form_configuration {
|
||||
.o_group .o_form_label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 32px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -569,16 +582,30 @@
|
||||
// Overriden style when form view in modal
|
||||
.modal .modal-dialog {
|
||||
.o_form_view {
|
||||
.o_form_sheet {
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
max-width: none;
|
||||
.o_form_sheet_bg {
|
||||
padding: 0;
|
||||
|
||||
> .o_form_sheet {
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
.oe_chatter {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&:not(.modal-lg) .o_form_view {
|
||||
.o_group {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_invisible {
|
||||
display: none!important;
|
||||
@media print {
|
||||
.oe_button_box, .o_form_statusbar {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,10 +646,10 @@ label.o_light_label, .o_light_label label {
|
||||
margin-left: 30px;
|
||||
border-left: 1px solid #bbbbbb;
|
||||
padding-left: 10px;
|
||||
.o_form_input_dropdown > .o_form_input {
|
||||
.o_input_dropdown > .o_input {
|
||||
width: 100%;
|
||||
}
|
||||
.o_form_field {
|
||||
.o_field_widget {
|
||||
width: 50%;
|
||||
}
|
||||
button.btn-link {
|
||||
@@ -631,7 +658,3 @@ label.o_light_label, .o_light_label label {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oe_form_configuration h2 {
|
||||
margin-top: 32px !important;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
@sheet-max-width: 860px;
|
||||
@sheet-min-width: 650px;
|
||||
@sheet-padding: 16px;
|
||||
|
||||
.o_form_view {
|
||||
.o_form_sheet_bg {
|
||||
background: url(/web/static/src/img/form_sheetbg.png);
|
||||
position: relative;
|
||||
padding: @sheet-padding 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
background: url(/web/static/src/img/form_sheetbg.png);
|
||||
|
||||
.o_form_sheet {
|
||||
min-width: @sheet-min-width;
|
||||
max-width: @sheet-max-width;
|
||||
min-height: 330px;
|
||||
margin: 0 auto;
|
||||
padding: 16px;
|
||||
border: 1px solid #c8c8d3;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||||
background: white;
|
||||
|
||||
.ui-tabs {
|
||||
margin: 0 -16px;
|
||||
}
|
||||
.oe_notebook_page {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +36,59 @@
|
||||
.btn-default;
|
||||
}
|
||||
}
|
||||
&.o_form_nosheet > header {
|
||||
margin: -16px -16px 0 -16px;
|
||||
&.o_form_nosheet {
|
||||
padding: 16px;
|
||||
&.oe_form_nomargin {
|
||||
margin: 0;
|
||||
}
|
||||
> header {
|
||||
margin: -16px -16px 0 -16px;
|
||||
}
|
||||
}
|
||||
|
||||
// Button box
|
||||
.oe_button_box {
|
||||
width: 400px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
|
||||
&, & + .oe_avatar {
|
||||
+ .oe_title {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.oe_stat_button {
|
||||
text-align: left;
|
||||
width: 132px !important;
|
||||
height: 40px;
|
||||
margin: 0px -1px -1px 0px;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
border-color: #ccc;
|
||||
background: white;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.o_button_icon {
|
||||
display: inline-block;
|
||||
width: 37px;
|
||||
padding: 0px 3px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
color: #7C7BAD;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.o_stat_info { // contains the value and text
|
||||
// Some buttons only display text and directly use the WidgetButton template instead of StatInfo
|
||||
.o_stat_info, > span { // contains the value and text
|
||||
display: inline-block;
|
||||
max-width: 70%;
|
||||
line-height: 1.2;
|
||||
|
||||
.o_stat_value {
|
||||
.o-text-overflow(block);
|
||||
font-weight: 700;
|
||||
@@ -50,19 +103,34 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some buttons only display text and directly use the WidgetButton template instead of StatInfo
|
||||
> span {
|
||||
font-size: small;
|
||||
white-space: normal; // text on several lines if needed
|
||||
}
|
||||
|
||||
> div {
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
line-height: 120%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Avatar
|
||||
.oe_avatar > img {
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
|
||||
border: none;
|
||||
.oe_avatar {
|
||||
float: left;
|
||||
> img {
|
||||
max-height: 90px;
|
||||
max-width: 90px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
|
||||
border: none;
|
||||
}
|
||||
+ .oe_title {
|
||||
padding-left: 95px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
// Groups
|
||||
@@ -70,31 +138,15 @@
|
||||
.o_td_label {
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
// All required form fields
|
||||
.o_form_required {
|
||||
&.o_form_input, .o_form_input, &.o_form_textarea, .o_form_textarea {
|
||||
background-color: #D2D2FF;
|
||||
.o_td_label + td {
|
||||
padding: 2px 36px 2px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field.o_form_field_many2one .o_external_button {
|
||||
padding: 0;
|
||||
margin-left: 2px;
|
||||
font-size: 19px;
|
||||
color: #7C7BAD;
|
||||
border: none;
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
.o_field_widget.o_text_overflow {
|
||||
width: 1px!important; // hack to make the table layout believe it is a small element (so that the table does not grow too much) ...
|
||||
min-width: 100%; // ... but in fact it takes the whole table space
|
||||
}
|
||||
}
|
||||
|
||||
// Dropdowns input carret
|
||||
.o_form_input_dropdown .o_dropdown_button {
|
||||
.o-position-absolute(2px, 4px);
|
||||
}
|
||||
|
||||
// Separators
|
||||
.o_horizontal_separator {
|
||||
color: @odoo-brand-optional;
|
||||
@@ -106,30 +158,6 @@
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
// Percent pie field
|
||||
.o_form_field_percent_pie {
|
||||
@pie-dimension: 34px;
|
||||
@pie-ring-width: 4px;
|
||||
|
||||
.o_pie {
|
||||
width: @pie-dimension;
|
||||
height: @pie-dimension;
|
||||
margin-left: 5px;
|
||||
|
||||
&:after { // Outside pie border to go over border-radius irregularities
|
||||
border: 1px solid @odoo-brand-primary;
|
||||
}
|
||||
|
||||
.o_pie_value {
|
||||
.o-position-absolute(@pie-ring-width, @pie-ring-width);
|
||||
width: @pie-dimension - 2 * @pie-ring-width;
|
||||
height: @pie-dimension - 2 * @pie-ring-width;
|
||||
border: 1px solid white;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Specific style classes
|
||||
.o_group.o_inner_group.oe_subtotal_footer {
|
||||
.oe_subtotal_footer_separator {
|
||||
@@ -139,6 +167,15 @@
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Chatter
|
||||
.oe_chatter {
|
||||
display: block;
|
||||
min-width: @sheet-min-width + 2* @sheet-padding;
|
||||
max-width: @sheet-max-width + 2* @sheet-padding;
|
||||
margin: 0 auto;
|
||||
padding: 16px 16px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
// Overriden style when form view in modal
|
||||
|
||||
@@ -1,373 +0,0 @@
|
||||
.o_form_view {
|
||||
.oe_inline {
|
||||
width: auto!important;
|
||||
@media (min-width: @screen-xs-min) {
|
||||
&.o_inner_group {
|
||||
width: 1px!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.oe_left {
|
||||
.oe_inline;
|
||||
float: left!important;
|
||||
}
|
||||
.oe_right {
|
||||
.oe_inline;
|
||||
float: right!important;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-xs-min) {
|
||||
.o_row {
|
||||
&, &.o_form_field { // Some field may want to use o_row as root and these rules must prevalue
|
||||
.o-flex-display();
|
||||
width: auto!important;
|
||||
}
|
||||
|
||||
.o-align-items(baseline);
|
||||
min-width: 50px;
|
||||
margin: 0 -@odoo-form-spacing-unit/2;
|
||||
|
||||
> div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule
|
||||
.o-flex(0, 0, auto);
|
||||
width: auto!important;
|
||||
margin-right: @odoo-form-spacing-unit/2;
|
||||
margin-left: @odoo-form-spacing-unit/2;
|
||||
}
|
||||
|
||||
> .o_row {
|
||||
margin: 0;
|
||||
}
|
||||
> .btn {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
> .o_form_field_boolean {
|
||||
.o-align-self(center);
|
||||
}
|
||||
}
|
||||
|
||||
.o_row .o_form_field_many2one, .o_form_field_many2one.oe_inline {
|
||||
&.o_with_button:not(:last-child) { // If invisible element as last child, this line has no effect but that's not very important
|
||||
margin-right: (35px + (@odoo-form-spacing-unit/2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_row > div > .o_form_field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Readonly specific rules
|
||||
&.o_form_readonly {
|
||||
.o_row {
|
||||
display: inline-block;
|
||||
> div {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Editable specific rules
|
||||
&.o_form_editable {
|
||||
@media (min-width: @screen-xs-min) {
|
||||
.o_row {
|
||||
> .o_form_field, > div {
|
||||
.o-flex(1, 1, auto);
|
||||
width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0)
|
||||
|
||||
&.o_form_field_boolean, &.o_priority {
|
||||
.o-flex(0, 0, auto);
|
||||
width: auto!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oe_title {
|
||||
max-width: @container-sm - (2 * @odoo-horizontal-padding);
|
||||
}
|
||||
}
|
||||
|
||||
// Header containing status/workflow buttons
|
||||
.o_form_statusbar {
|
||||
.o-flex(0, 0, auto);
|
||||
.o-flex-display();
|
||||
.o-justify-content(space-between);
|
||||
|
||||
padding-left: @odoo-horizontal-padding;
|
||||
|
||||
> .o_statusbar_buttons, > .o_statusbar_status {
|
||||
.o-flex-display();
|
||||
.o-align-items(center);
|
||||
.o-align-content(space-around);
|
||||
}
|
||||
|
||||
> .o_form_field {
|
||||
.o-align-self(center);
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
> .o_statusbar_buttons {
|
||||
.o-flex-flow(row, wrap);
|
||||
|
||||
> .btn {
|
||||
margin: 2px 3px 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
> .o_statusbar_status {
|
||||
.o-flex-flow(row-reverse, wrap-reverse);
|
||||
.o-align-self(stretch);
|
||||
.o-align-items(stretch);
|
||||
overflow-x: hidden; // to prevent horizontal scroll due to last arrow
|
||||
}
|
||||
|
||||
// Touch device mode
|
||||
> .o_statusbar_buttons > .btn-group {
|
||||
> .dropdown-toggle {
|
||||
&:after {
|
||||
.o-caret-down();
|
||||
margin-left: @odoo-form-spacing-unit;
|
||||
}
|
||||
}
|
||||
|
||||
> .dropdown-menu {
|
||||
padding: 5px 0 2px 0;
|
||||
min-width: 100px;
|
||||
|
||||
> li > .btn {
|
||||
min-width: 100%;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Title
|
||||
.oe_title {
|
||||
> h1, > h2, > h3 {
|
||||
width: 100%; // Needed because inline-block when is a hx.o_row
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// Groups
|
||||
.o_group {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
|
||||
// o_group contains nested groups
|
||||
.o-generate-groups(@odoo-form-group-cols);
|
||||
.o-generate-groups(@n, @i: 1) when (@i =< @n) {
|
||||
.o_group_col_@{i} {
|
||||
display: inline-block;
|
||||
width: floor(100% / 12 * @i);
|
||||
vertical-align: top;
|
||||
}
|
||||
.o-generate-groups(@n, @i + 1);
|
||||
}
|
||||
|
||||
&.o_inner_group {
|
||||
display: inline-table;
|
||||
|
||||
> tbody > tr > td {
|
||||
&.o_td_label {
|
||||
width: 0%;
|
||||
padding: 0 15px 0 0;
|
||||
min-width: 150px;
|
||||
}
|
||||
vertical-align: top;
|
||||
|
||||
span, .o_form_field_boolean, .oe_avatar, .o_form_uri {
|
||||
&.o_form_field {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field {
|
||||
width: 100%;
|
||||
|
||||
> .btn {
|
||||
.o-flex(0, 0, auto);
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notebooks
|
||||
.o_notebook {
|
||||
clear: both; // For the notebook not to have alongside floating elements
|
||||
margin-top: @odoo-form-spacing-unit * 2;
|
||||
}
|
||||
|
||||
// Labels
|
||||
.o_form_label {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// Form fields
|
||||
.o_form_field {
|
||||
display: inline-block;
|
||||
margin-bottom: @odoo-form-spacing-unit;
|
||||
}
|
||||
|
||||
// Block fields
|
||||
.note-editor, .oe_form_field_html, .oe_form_field_html_text, .oe_form_field_text, .o_view_manager_content, .o_form_field_domain {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Flex fields
|
||||
.o_form_field_many2one, .o_form_field_radio, .o_form_field_many2manytags, .o_form_field_percent_pie, .o_form_field_monetary, .o_form_field_binary_file {
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.o-inline-flex-display();
|
||||
}
|
||||
> span, > button {
|
||||
.o-flex(0, 0, auto);
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field, .btn {
|
||||
.o_form_field {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
// Input in field
|
||||
.o_form_field {
|
||||
.o_form_input_dropdown {
|
||||
width: 100%;
|
||||
}
|
||||
.o_form_input {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
// Textarea
|
||||
.o_form_textarea {
|
||||
white-space: pre-wrap;
|
||||
width: 100%;
|
||||
&.oe_inline {
|
||||
width: 100%!important;
|
||||
@media (min-width: @screen-xs-min) {
|
||||
width: 45%!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Radio buttons
|
||||
.o_form_field_radio {
|
||||
.o_radio_item {
|
||||
.o-flex(0, 0, auto);
|
||||
.o-flex-display();
|
||||
.o-align-items(center);
|
||||
|
||||
> input {
|
||||
.o-flex(0, 0, auto);
|
||||
margin: 0 @odoo-form-spacing-unit 0 0;
|
||||
}
|
||||
> label {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_horizontal {
|
||||
.o_radio_item {
|
||||
margin-right: @odoo-form-spacing-unit * 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_vertical {
|
||||
.o-flex-flow(column, nowrap);
|
||||
.o_radio_item {
|
||||
margin-bottom: @odoo-form-spacing-unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// One2Many, Many2Many outside of group
|
||||
.o_form_field {
|
||||
&.o_view_manager_content, &.o_form_field_one2many, &.o_form_field_many2many {
|
||||
width: 100%;
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Many2many tags
|
||||
.o_form_field_many2manytags {
|
||||
.o-flex-flow(row, wrap);
|
||||
.o-align-items(baseline);
|
||||
.badge {
|
||||
.o-flex(0, 0, auto);
|
||||
> .o_badge_text {
|
||||
.o-text-overflow(inline-block);
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Percent pie
|
||||
.o_form_field_percent_pie {
|
||||
.o-align-items(center);
|
||||
> .o_pie {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// Specific style classes
|
||||
.o_group.o_inner_group.oe_subtotal_footer {
|
||||
.oe_right;
|
||||
}
|
||||
|
||||
//ace
|
||||
.o_ace_view_editor {
|
||||
width: 100%;
|
||||
.ace-view-editor {
|
||||
height: 300px;
|
||||
padding: 0 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field_domain {
|
||||
> .o_form_field_domain_panel {
|
||||
margin-top: 8px;
|
||||
}
|
||||
&.o_inline_mode.o_edit_mode {
|
||||
position: relative;
|
||||
|
||||
> .o_form_field_domain_panel {
|
||||
.o-position-absolute(0, 0);
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Overriden style when form view in modal
|
||||
.modal .modal-dialog {
|
||||
.o_form_view {
|
||||
.o_form_sheet_bg {
|
||||
padding: 0;
|
||||
}
|
||||
.oe_chatter {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&:not(.modal-lg) .o_form_view {
|
||||
.o_group {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.oe_button_box {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
@sheet-max-width: 860px;
|
||||
@sheet-min-width: 650px;
|
||||
@sheet-padding: 16px;
|
||||
|
||||
.o_form_view {
|
||||
&.o_form_nosheet {
|
||||
padding: 16px;
|
||||
&.oe_form_nomargin {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.o_form_sheet_bg {
|
||||
position: relative;
|
||||
padding: @sheet-padding 0;
|
||||
.o_form_sheet {
|
||||
min-width: @sheet-min-width;
|
||||
max-width: @sheet-max-width;
|
||||
min-height: 330px;
|
||||
background: white;
|
||||
padding: 16px;
|
||||
margin: 0 auto;
|
||||
.ui-tabs {
|
||||
margin: 0 -16px;
|
||||
}
|
||||
.oe_notebook_page {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Button box
|
||||
.oe_button_box {
|
||||
width: 400px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
.oe_stat_button {
|
||||
text-align: left;
|
||||
width: 132px !important;
|
||||
height: 40px;
|
||||
margin: 0px -1px -1px 0px;
|
||||
padding: 0;
|
||||
> div {
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
line-height: 120%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.o_button_icon {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
padding: 0px 3px;
|
||||
width: 37px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.o_stat_info { // contains the value and text
|
||||
display: inline-block;
|
||||
max-width: 70%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
// Some buttons only display text and directly use the WidgetButton template instead of StatInfo
|
||||
> span {
|
||||
.o_stat_info; // layout
|
||||
}
|
||||
}
|
||||
|
||||
&, & + .oe_avatar {
|
||||
+ .oe_title {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Groups
|
||||
.o_group {
|
||||
.o_td_label + td {
|
||||
padding: 2px 36px 2px 8px;
|
||||
}
|
||||
.o_form_field.o_text_overflow {
|
||||
width: 1px!important; // hack to make the table layout believe it is a small element (so that the table does not grow too much) ...
|
||||
min-width: 100%; // ... but in fact it takes the whole table space
|
||||
}
|
||||
}
|
||||
|
||||
// Avatar
|
||||
.oe_avatar {
|
||||
float: left;
|
||||
> img {
|
||||
max-height: 90px;
|
||||
max-width: 90px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
+ .oe_title {
|
||||
padding-left: 95px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
// Chatter
|
||||
.oe_chatter {
|
||||
display: block;
|
||||
min-width: @sheet-min-width + 2* @sheet-padding;
|
||||
max-width: @sheet-max-width + 2* @sheet-padding;
|
||||
margin: 0 auto;
|
||||
padding: 16px 16px 48px;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_form_field_many2manytags {
|
||||
.o_field_many2manytags {
|
||||
display: block;
|
||||
}
|
||||
.oe_kanban_text_red {
|
||||
@@ -552,3 +552,8 @@
|
||||
color: #639B89;
|
||||
}
|
||||
}
|
||||
|
||||
// Introduced with new views (TODO check)
|
||||
.o_kanban {
|
||||
height: 100%; // required for grouped kanban views
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@odoo-list-group-header-color: lighten(@odoo-brand-lightsecondary, 10%);
|
||||
|
||||
.o_list_view {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background-color: @odoo-view-background-color;
|
||||
margin-bottom: 0px;
|
||||
@@ -12,7 +14,6 @@
|
||||
|
||||
thead {
|
||||
color: @odoo-main-text-color;
|
||||
background-color: #eee;
|
||||
border-bottom: 1px solid #cacaca;
|
||||
> tr > th {
|
||||
border-left: 1px solid #dfdfdf;
|
||||
@@ -46,23 +47,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_record_selector {
|
||||
.o_list_record_selector, .o_list_record_delete, .o_handle_cell {
|
||||
width: 1px; // to prevent the column to expand
|
||||
> input {
|
||||
margin-left: 3px;
|
||||
.hidden-xs();
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_record_delete {
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
.o_handle_cell {
|
||||
width: 1px; // to prevent the column to expand
|
||||
.o_row_handle {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
}
|
||||
|
||||
// Decoration of the row
|
||||
@@ -80,8 +66,6 @@
|
||||
tbody > tr.o_group_header {
|
||||
height: 31px;
|
||||
|
||||
.o-vertical-gradient(#fcfcfc, #dedede);
|
||||
|
||||
.o_group_name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -106,108 +90,77 @@
|
||||
border-top: none; // Override bootstrap for grouped list views
|
||||
}
|
||||
|
||||
.o_list_number {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.o_list_text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_editable {
|
||||
position: relative;
|
||||
|
||||
.o_temp_visible {
|
||||
opacity: 0;
|
||||
display: block!important;
|
||||
|
||||
&.o_form_invisible {
|
||||
display: block!important;
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_view {
|
||||
.o_row_edition > td {
|
||||
visibility: hidden; // Hide row's content during edition
|
||||
&.o_list_record_selector, &.o_list_record_delete, &.o_list_button {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
&.o_list_record_delete {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.o_readonly {
|
||||
visibility: visible;
|
||||
color: transparent;
|
||||
|
||||
> .o_checkbox {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_view.o_list_editable_form {
|
||||
padding: 0;
|
||||
> .o_form_field {
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
// Values styling
|
||||
.o_data_cell {
|
||||
&.o_list_number, &.o_field_integer, &.o_field_float, &.o_field_monetary {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
&.o_form_textarea {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
&.o_list_text, &.o_field_text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Edition
|
||||
//--------------------------------------------------------------------------
|
||||
.o_data_row.o_selected_row > .o_data_cell:not(.o_readonly_modifier) {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
|
||||
// Field widgets override
|
||||
> .o_field_widget {
|
||||
.o-position-absolute(0, 0, auto, 0);
|
||||
min-height: 100%;
|
||||
|
||||
&:not(.o_field_text) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.o_form_field, .badge { // Many2Many tags
|
||||
|
||||
.o_field_widget, .badge { // Many2Many tags
|
||||
display: block;
|
||||
float: left;
|
||||
white-space: normal;
|
||||
max-width: 100%; // Fix a chrome bug where badge would not break on multiple lines
|
||||
}
|
||||
|
||||
&.o_readonly:not(.o_checkbox) {
|
||||
background-color: transparent;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
> .o_field_translate {
|
||||
position: absolute;
|
||||
width: 16px; // to have some space on the right
|
||||
}
|
||||
.o_form_input_dropdown {
|
||||
height: 100%;
|
||||
.o_input {
|
||||
padding: 4px; // bootstrap cell - 1px of border
|
||||
background-color: white;
|
||||
|
||||
.o_input {
|
||||
padding: 0!important;
|
||||
}
|
||||
}
|
||||
.o_form_input {
|
||||
height: 100%;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
.o_input_dropdown {
|
||||
min-height: 100%;
|
||||
}
|
||||
.o_form_input, .o_form_textarea, .o_form_field_many2manytags, .o_form_field_monetary {
|
||||
border-style: solid;
|
||||
}
|
||||
.o_form_field_monetary .o_form_input {
|
||||
.o_field_monetary input {
|
||||
width: 0;
|
||||
}
|
||||
.o_checkbox {
|
||||
padding: 7px 0 0 5px;
|
||||
background: transparent;
|
||||
}
|
||||
.o_form_textarea {
|
||||
.o_field_widget {
|
||||
min-width: 0;
|
||||
}
|
||||
.o_with_button .o_form_input_dropdown {
|
||||
.o_with_button .o_input_dropdown {
|
||||
width: 1%; // Hack so that the sibling button is not overlapped
|
||||
}
|
||||
.o_form_input_dropdown, .o_datepicker {
|
||||
> .o_form_input {
|
||||
.o_input_dropdown, .o_datepicker {
|
||||
> .o_input {
|
||||
padding-right: 15px; // To prevent caret overlapping
|
||||
}
|
||||
> .o_dropdown_button, .o_datepicker_button {
|
||||
.o-position-absolute(20%, 5px);
|
||||
}
|
||||
}
|
||||
.o_form_field > .o_external_button {
|
||||
.o_field_widget > .o_external_button {
|
||||
padding: 0;
|
||||
background-color: inherit;
|
||||
margin-left: 3px;
|
||||
@@ -215,24 +168,15 @@
|
||||
.o_row_handle {
|
||||
visibility: hidden; // Hide sequence when editing
|
||||
}
|
||||
.o_form_field_boolean {
|
||||
.o_field_boolean {
|
||||
width: auto!important; // Override the width computed in JS (needed for Chrome)
|
||||
}
|
||||
.o_form_field_number {
|
||||
.o_field_number {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround a bug in safari mobile where the inputs are not displayed correctly.
|
||||
.modal {
|
||||
.o_list_editable {
|
||||
.o_form_view.o_list_editable_form {
|
||||
-webkit-overflow-scrolling: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons in ControlPanel
|
||||
.o_list_buttons {
|
||||
.o_list_button_save, .o_list_button_discard {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
.o_list_view {
|
||||
thead {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
tbody > tr.o_group_header {
|
||||
.o-vertical-gradient(#fcfcfc, #dedede);
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,6 @@
|
||||
}
|
||||
|
||||
&.o_edit_mode {
|
||||
.o-input();
|
||||
|
||||
> .o_field_selector_controls::after {
|
||||
.o-caret-down();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
.o_main_navbar {
|
||||
position: relative;
|
||||
height: @odoo-navbar-height;
|
||||
border: 1px solid @odoo-navbar-inverse-link-hover-bg;
|
||||
background-color: @odoo-brand-primary;
|
||||
color: white;
|
||||
.box-shadow(0px 0px 8px @odoo-main-text-color);
|
||||
|
||||
> a, > button {
|
||||
float: left;
|
||||
@@ -29,6 +29,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .o_menu_brand {
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 35px;
|
||||
.user-select(none);
|
||||
color: white;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
line-height: @odoo-navbar-height - 2;
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
float: none;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid @odoo-navbar-inverse-link-hover-bg;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
> .o_menu_toggle {
|
||||
margin-right: 5px;
|
||||
}
|
||||
@@ -60,6 +78,37 @@
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_extra_menu_items {
|
||||
> a {
|
||||
width: @odoo-navbar-height - 2;
|
||||
text-align: center;
|
||||
}
|
||||
&.open > ul {
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
> a {
|
||||
background-color: @odoo-brand-primary;
|
||||
color: white;
|
||||
border-bottom: 1px solid @odoo-brand-lightsecondary;
|
||||
|
||||
&.dropdown-toggle {
|
||||
background-color: lighten(@odoo-brand-primary, 15%);
|
||||
pointer-events: none; // hack to prevent clicking on it because dropdown always opened
|
||||
}
|
||||
}
|
||||
> ul { // remove dropdown-menu default style as it is nested in another one
|
||||
position: static;
|
||||
float: none;
|
||||
display: block;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
max-height: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.o_menu_systray {
|
||||
@@ -71,10 +120,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.o_menu_brand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.open .dropdown-menu {
|
||||
max-height: 90vh; // the dropdown should not overstep the viewport
|
||||
overflow: auto;
|
||||
@@ -89,6 +134,10 @@
|
||||
.o-menu-indentation(3);
|
||||
}
|
||||
|
||||
.oe_topbar_avatar {
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o-transition(height, 200ms, linear);
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
.o_kanban {
|
||||
height: 100%; // required for grouped kanban views
|
||||
}
|
||||
|
||||
.o_list_view {
|
||||
tr.o_selected_row {
|
||||
outline: 1px solid lightgray;
|
||||
|
||||
> td:not(.o_readonly):not(.o_list_button) {
|
||||
position: relative;
|
||||
background-color: white;
|
||||
|
||||
> .o_field_widget, > .o_form_field_many2one {
|
||||
.o-position-absolute(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.o_form_field_many2one .o_form_input_dropdown {
|
||||
.o-flex(1, 1, auto);
|
||||
|
||||
.o_form_input {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.o_dropdown_button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_field_many2manytags {
|
||||
.o_form_field_many2one {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.o_field_boolean {
|
||||
.o-flex-display();
|
||||
.o-align-items(center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td.o_field_dirty {
|
||||
outline: 1px solid orange;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Rules on fields moved from form_view(_layout).less (community or enterprise)
|
||||
// so that they also apply outside a form_view
|
||||
|
||||
// Many2One
|
||||
.o_form_field_many2one {
|
||||
.o-inline-flex-display();
|
||||
> span, > button {
|
||||
.o-flex(0, 0, auto);
|
||||
}
|
||||
}
|
||||
// Many2ManyTags
|
||||
.o_form_field_many2manytags .badge {
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
border: 0;
|
||||
}
|
||||
// Dropdowns input (many2one, ...)
|
||||
.o_form_input_dropdown {
|
||||
.o-flex(1, 0, auto);
|
||||
position: relative;
|
||||
|
||||
> input {
|
||||
padding-right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_dropdown_button {
|
||||
pointer-events: none;
|
||||
&:after {
|
||||
.o-caret-down;
|
||||
}
|
||||
.o-position-absolute(0, 0); // ENTERPRISE ONLY
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
.o_searchview_facet_label {
|
||||
background-color: @gray-light;
|
||||
}
|
||||
|
||||
|
||||
.o_facet_remove {
|
||||
color: @gray-light;
|
||||
&:hover {
|
||||
@@ -40,5 +40,4 @@
|
||||
input[type="text"], select {
|
||||
.form-control();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.o_company {
|
||||
margin-right:23px;
|
||||
}
|
||||
.o_current_company {
|
||||
margin-right:10px;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
.o_treeview_table {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
border-collapse: collapse;
|
||||
|
||||
thead {
|
||||
color: @odoo-main-text-color;
|
||||
background-color: @odoo-brand-lightsecondary;
|
||||
> tr > th {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
> tr {
|
||||
border: 1px solid @odoo-brand-lightsecondary;
|
||||
&:hover {
|
||||
background-color: lighten(@odoo-brand-lightsecondary, 15%);
|
||||
}
|
||||
> td {
|
||||
border: 1px solid @odoo-brand-lightsecondary;
|
||||
cursor: pointer;
|
||||
height: 40px;
|
||||
padding: 0 4px;
|
||||
&.oe_number {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.treeview-tr, .treeview-td {
|
||||
&.o_treeview_first > span {
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
.treeview-tr.o_treeview_first {
|
||||
position: relative;
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
.o-caret-right(6px);
|
||||
}
|
||||
}
|
||||
.o_open .treeview-tr.o_treeview_first {
|
||||
&:before {
|
||||
top: 16px;
|
||||
.o-caret-down(6px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,9 +209,9 @@
|
||||
// ------------------------------------------------------------------
|
||||
// Text overflow
|
||||
// ------------------------------------------------------------------
|
||||
.o-text-overflow(@display: inline-block) {
|
||||
.o-text-overflow(@display: inline-block, @max-width: 100%) {
|
||||
display: @display;
|
||||
max-width: 100%;
|
||||
max-width: @max-width;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
@@ -1,87 +1,7 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// This file contains rules applying on elements shared between views
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Many2many tags
|
||||
.o_form_field_many2manytags {
|
||||
.o_tag_color_0 {
|
||||
background-color: #4D4D4D;
|
||||
}
|
||||
.o_tag_color_1 {
|
||||
background-color: #61BD4F;
|
||||
}
|
||||
.o_tag_color_2 {
|
||||
background-color: #F2D600;
|
||||
}
|
||||
.o_tag_color_3 {
|
||||
background-color: #FFAB4A;
|
||||
}
|
||||
.o_tag_color_4 {
|
||||
background-color: #EB5A46;
|
||||
}
|
||||
.o_tag_color_5 {
|
||||
background-color: #875A7B;
|
||||
}
|
||||
.o_tag_color_6 {
|
||||
background-color: #0079BF;
|
||||
}
|
||||
.o_tag_color_7 {
|
||||
background-color: #00C2E0;
|
||||
}
|
||||
.o_tag_color_8 {
|
||||
background-color: #4CD98E;
|
||||
}
|
||||
.o_tag_color_9 {
|
||||
background-color: #FF80CE;
|
||||
}
|
||||
.o_tag_color_10 {
|
||||
background-color: #B6BBBF;
|
||||
}
|
||||
}
|
||||
|
||||
// Stars
|
||||
.o_priority {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
> .o_priority_star {
|
||||
display: inline-block;
|
||||
font-size: 1.35em;
|
||||
&:hover, &:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
+ .o_priority_star {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
&.fa-star-o {
|
||||
color: @odoo-main-color-muted;
|
||||
}
|
||||
&.fa-star {
|
||||
color: gold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_status {
|
||||
display: inline-block;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
border-radius: 6px;
|
||||
vertical-align: middle;
|
||||
|
||||
background-color: @odoo-brand-secondary;
|
||||
|
||||
&.o_status_green {
|
||||
background-color: @brand-success;
|
||||
}
|
||||
&.o_status_red {
|
||||
background-color: @brand-danger;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This file regroups the rules which apply on elements which are shared between
|
||||
* all renderers. For field default rules, see the fields.less file.
|
||||
*/
|
||||
|
||||
// No content helper
|
||||
.oe_view_nocontent {
|
||||
@@ -92,15 +12,12 @@
|
||||
display: inline!important;
|
||||
}
|
||||
}
|
||||
// Hide view_nocontent in x2many fields
|
||||
.o_form_field .oe_view_nocontent {
|
||||
display: none;
|
||||
}
|
||||
.o_field_widget .oe_view_nocontent,
|
||||
.o_cannot_create .oe_view_nocontent_create {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Specific success color for toggle_button widget
|
||||
.fa.o_toggle_button_success {
|
||||
color: @brand-success;
|
||||
// Invisible modifier (can be inside the view, the button area, ...)
|
||||
.o_invisible_modifier {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
.o_calendar_filter {
|
||||
padding: 8px;
|
||||
border-top: 1px solid lightgray;
|
||||
.o_form_field_many2one {
|
||||
.o_field_many2one {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// ------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// Checkboxes
|
||||
// ------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
div.o_checkbox {
|
||||
display: inline-block;
|
||||
vertical-align: sub;
|
||||
@@ -9,29 +9,32 @@ div.o_checkbox {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Inputs and selects
|
||||
// ------------------------------------------------------------------
|
||||
.o-input() {
|
||||
//------------------------------------------------------------------------------
|
||||
// Inputs and selects (note: put the o_input class to have the style)
|
||||
//------------------------------------------------------------------------------
|
||||
[type="text"], [type="password"], [type="number"], textarea, select {
|
||||
width: 100%;
|
||||
display: block;
|
||||
outline: none;
|
||||
}
|
||||
.o_input {
|
||||
border: 1px solid @odoo-form-lightsecondary;
|
||||
border-radius: @border-radius-base;
|
||||
padding: 2px 4px;
|
||||
color: #1f1f1f;
|
||||
}
|
||||
input[type="text"], input[type="password"], input[type="number"], textarea, select {
|
||||
.o-input();
|
||||
|
||||
width: 100%;
|
||||
outline: none;
|
||||
display: block;
|
||||
.o_input {
|
||||
border: none!important;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
select {
|
||||
background: white;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// Loading
|
||||
// ------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
.o_loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -45,9 +48,9 @@ select {
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// User menu in navbar
|
||||
// ------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
#oe_main_menu_navbar .oe_user_menu_placeholder .o_user_menu .oe_topbar_name {
|
||||
.o-text-overflow();
|
||||
max-width: 150px;
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<div t-name="EmptyComponent"/>
|
||||
|
||||
<div t-name="Loading" class="o_loading"/>
|
||||
|
||||
<t t-name="Notification">
|
||||
<div t-attf-class="o_notification #{className}" t-translation="off">
|
||||
<a t-if="widget.sticky" class="fa fa-times o_close" href="#"/>
|
||||
@@ -49,15 +51,15 @@
|
||||
<table class="o_group o_inner_group o_label_nowrap">
|
||||
<tr>
|
||||
<td class="o_td_label"><label for="old_pwd" class="o_form_label">Old Password</label></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="old_pwd" minlength="1" autofocus="autofocus" autocomplete="current-password"/></td>
|
||||
<td width="100%"><input type="password" class="o_field_widget o_input" name="old_pwd" minlength="1" autofocus="autofocus" autocomplete="current-password"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="o_td_label"><label for="new_password" class="o_form_label">New Password</label></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="new_password" minlength="1" autocomplete="new-password"/></td>
|
||||
<td width="100%"><input type="password" class="o_field_widget o_input" name="new_password" minlength="1" autocomplete="new-password"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="o_td_label"><label for="confirm_pwd" class="o_form_label">Confirm New Password</label></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="confirm_pwd" minlength="1" autocomplete="new-password"/></td>
|
||||
<td width="100%"><input type="password" class="o_field_widget o_input" name="confirm_pwd" minlength="1" autocomplete="new-password"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -83,7 +85,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="X2ManyControlPanel">
|
||||
<div class="o_x2m_control_panel">
|
||||
<div class="o_cp_buttons"/>
|
||||
@@ -108,7 +109,6 @@
|
||||
<ul class="dropdown-menu o_debug_dropdown" role="menu"/>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
<t t-name="WebClient.DebugManager.Global">
|
||||
<li><a href="#" data-action="perform_js_tests">Run JS Tests</a></li>
|
||||
<li><a href="#" data-action="select_view">Open View</a></li>
|
||||
@@ -255,48 +255,6 @@
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="TreeView">
|
||||
<select t-if="toolbar" style="width: 30%"/>
|
||||
<table class="o_treeview_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th t-foreach="fields_view" t-as="field"
|
||||
t-if="!field.attrs.modifiers.tree_invisible"
|
||||
class="treeview-header">
|
||||
<t t-esc="field_value.attrs.string || fields[field.attrs.name].string" />
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
<tr t-name="TreeView.rows"
|
||||
t-foreach="records" t-as="record"
|
||||
t-att-id="'treerow_' + record.id"
|
||||
t-att-data-id="record.id" t-att-data-level="level + 1"
|
||||
t-att-data-row-parent-id="row_parent_id">
|
||||
<t t-set="children" t-value="record[children_field]"/>
|
||||
<t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/>
|
||||
<t t-set="rank" t-value="'o_treeview_first'"/>
|
||||
<t t-set="style" t-value="'background-position: ' + 19*(level) + 'px; padding-left: ' + (4 + 19*(level)) + 'px;'"/>
|
||||
|
||||
<td t-foreach="fields_view" t-as="field"
|
||||
t-if="!field.attrs.modifiers.tree_invisible"
|
||||
t-att-data-id="record.id"
|
||||
t-att-style="color_for(record) + style "
|
||||
t-attf-class="#{class} #{rank} #{(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer') or (fields[field.attrs.name].type === 'monetary')? 'oe_number' : ''}">
|
||||
|
||||
<span t-if="!field.attrs.modifiers.invisible" >
|
||||
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
|
||||
</span>
|
||||
|
||||
<t t-set="class" t-value="'treeview-td'"/>
|
||||
<t t-set="rank" t-value="''"/>
|
||||
<t t-set="style" t-value="''"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<div t-name="ListView" class="table-responsive">
|
||||
<table class="o_list_view table table-condensed table-striped">
|
||||
<t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
|
||||
@@ -332,7 +290,6 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<t t-name="ListView.buttons">
|
||||
<div class="o_list_buttons">
|
||||
<t t-if="widget.is_action_enabled('create')">
|
||||
@@ -349,60 +306,6 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ListView.rows" t-foreach="records.length" t-as="index">
|
||||
<t t-call="ListView.row">
|
||||
<t t-set="record" t-value="records.at(index)"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<tr t-name="ListView.row"
|
||||
t-att-data-id="record.get('id')"
|
||||
t-attf-style="#{(view.fonts || view.colors) ? view.style_for(record) : ''}"
|
||||
t-attf-class="#{view.compute_decoration_classnames(record)}">
|
||||
<t t-set="asData" t-value="record.toForm().data"/>
|
||||
<t t-foreach="columns" t-as="column">
|
||||
<td t-if="column.meta"> </td>
|
||||
</t>
|
||||
<td t-if="options.selectable" class="o_list_record_selector">
|
||||
<t t-set="checked" t-value="options.select_view_id == record.get('id') ? 'checked' : null"/>
|
||||
<input t-if="options.radio" type="radio" name="radiogroup" t-att-checked="checked"/>
|
||||
<div t-if="!options.radio" class="o_checkbox">
|
||||
<input type="checkbox" name="radiogroup" t-att-checked="checked"/><span/>
|
||||
</div>
|
||||
</td>
|
||||
<t t-foreach="columns" t-as="column">
|
||||
<t t-set="number" t-value="column.type === 'integer' or column.type == 'float' or column.type == 'monetary'"/>
|
||||
<t t-set="text" t-value="column.type === 'text'"/>
|
||||
<t t-set="modifiers" t-value="column.modifiers_for(asData)"/>
|
||||
<td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help"
|
||||
t-attf-class="#{modifiers.readonly ? 'o_readonly' : ''} #{number ? 'o_list_number' : ''} #{text ? 'o_list_text' : ''} #{column.id === 'sequence' ? 'o_handle_cell' : ''} #{column.tag === 'button' ? 'o_list_button' : ''}"
|
||||
t-att-data-field="column.id"
|
||||
><t t-raw="render_cell(record, column)"/></td>
|
||||
</t>
|
||||
<td t-if="options.deletable" class='o_list_record_delete'>
|
||||
<span name="delete" class="fa fa-trash-o"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<button t-name="ListView.row.text_button" type="button"
|
||||
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
||||
t-att-class="disabled ? 'oe_list_button_disabled btn_txt oe_link' : 'btn_txt oe_link'"
|
||||
><t t-esc="widget.string"/></button>
|
||||
<button t-name="ListView.row.button" type="button"
|
||||
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
||||
t-attf-class="o_icon_button #{disabled ? 'oe_list_button_disabled' : ''}"
|
||||
><i t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/>
|
||||
</button>
|
||||
<t t-extend="ListView.row">
|
||||
<!-- adds back padding to row being rendered after edition, if necessary
|
||||
(if not deletable add back padding), otherwise the row being added is
|
||||
missing columns
|
||||
-->
|
||||
<t t-jquery="> :last" t-operation="after">
|
||||
<td t-if="edited and !options.deletable" class="oe-listview-padding"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="FormView.buttons">
|
||||
<div class="o_form_buttons_view">
|
||||
<button t-if="widget.is_action_enabled('edit')" type="button"
|
||||
@@ -546,7 +449,6 @@
|
||||
<button class="btn btn-default fa fa-pie-chart o_graph_button" title="Pie Chart" data-mode="pie"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div t-name="GraphView.error" class="oe_view_nocontent" >
|
||||
<p><strong><t t-esc="title"/></strong></p>
|
||||
<p><t t-esc="description"/></p>
|
||||
@@ -555,7 +457,6 @@
|
||||
<div t-name="PivotView" class="o_pivot">
|
||||
<div class="o_field_selection"/>
|
||||
</div>
|
||||
|
||||
<t t-name="PivotView.buttons">
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
@@ -575,7 +476,6 @@
|
||||
<button class="btn btn-default fa fa-download o_pivot_download" title="Download xls"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="PivotView.FieldSelection">
|
||||
<ul class="dropdown-menu o_pivot_field_menu" role="menu">
|
||||
<t t-foreach="fields" t-as="field">
|
||||
@@ -601,7 +501,6 @@
|
||||
</t>
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
<div t-name="PivotView.nodata" class="oe_view_nocontent" >
|
||||
<p><strong>No data to display.</strong></p>
|
||||
<p>
|
||||
@@ -610,24 +509,10 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
<t t-name="Widget">
|
||||
Unhandled widget
|
||||
<t t-js="dict">console.warn('Unhandled widget', dict.widget);</t>
|
||||
</t>
|
||||
<t t-name="FieldChar">
|
||||
<span t-if="widget.get('effective_readonly')"/>
|
||||
|
||||
<input t-if="!widget.get('effective_readonly')" class="o_form_input"
|
||||
t-att-barcode_events="widget.options.barcode_events"
|
||||
t-att-type="widget.password ? 'password' : 'text'"
|
||||
t-att-id="widget.idForLabel"
|
||||
t-att-tabindex="widget.node.attrs.tabindex"
|
||||
t-att-autofocus="widget.node.attrs.autofocus"
|
||||
t-att-placeholder="widget.node.attrs.placeholder"
|
||||
t-att-autocomplete="widget.password ? 'new-password' : widget.node.attrs.autocomplete"
|
||||
t-att-maxlength="widget.field.size"/>
|
||||
</t>
|
||||
<t t-name="FormSelection">
|
||||
<div class="btn-group o_selection">
|
||||
<a href="#" data-toggle="dropdown"><span class="o_status"/></a>
|
||||
@@ -643,29 +528,8 @@
|
||||
</a>
|
||||
</li>
|
||||
</t>
|
||||
<t t-name="FieldEmail" t-extend="FieldChar">
|
||||
<t t-jquery="span" t-operation="replace">
|
||||
<t t-if="widget.get('effective_readonly')">
|
||||
<a t-if="widget.clickable" class="o_form_uri o_text_overflow" href="#" target="_blank"/>
|
||||
<span t-if="!widget.clickable" class="o_text_overflow"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
<t t-name="FieldText">
|
||||
<span t-if="widget.get('effective_readonly')" class="o_form_textarea"/>
|
||||
|
||||
<textarea t-if="!widget.get('effective_readonly')"
|
||||
class="o_form_textarea"
|
||||
rows="6"
|
||||
t-att-name="widget.name"
|
||||
t-att-tabindex="widget.node.attrs.tabindex"
|
||||
t-att-autofocus="widget.node.attrs.autofocus"
|
||||
t-att-placeholder="!widget.get('effective_readonly') ? widget.node.attrs.placeholder : ''"
|
||||
t-att-maxlength="widget.field.size"/>
|
||||
</t>
|
||||
|
||||
<t t-name="FieldDomain.content">
|
||||
<div t-if="hasModel" class="o_form_field_domain_panel">
|
||||
<div t-if="hasModel" class="o_field_domain_panel">
|
||||
<i class="fa fa-arrow-right"/>
|
||||
|
||||
<button t-if="isValid" class="btn btn-xs btn-default o_domain_show_selection_button" type="button">
|
||||
@@ -673,11 +537,10 @@
|
||||
</button>
|
||||
<span t-else="" class="text-warning"><i class="fa fa-exclamation-triangle"/> Invalid domain</span>
|
||||
|
||||
<button t-if="inDialogEdit" class="btn btn-xs btn-primary o_form_field_domain_dialog_button">Edit domain</button>
|
||||
<button t-if="inDialogEdit" class="btn btn-xs btn-primary o_field_domain_dialog_button">Edit domain</button>
|
||||
</div>
|
||||
<div t-else="">Select a model to add a filter.</div>
|
||||
</t>
|
||||
|
||||
<t t-name="DomainNode.ControlPanel">
|
||||
<div t-if="!widget.readonly && !widget.noControlPanel" class="o_domain_node_control_panel">
|
||||
<button class="btn o_domain_delete_node_button"><i class="fa fa-times"/></button>
|
||||
@@ -800,8 +663,7 @@
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-name="ModelFieldSelector" t-attf-class="o_field_selector#{!widget.options.readonly ? ' o_edit_mode' : ''}">
|
||||
<div t-name="ModelFieldSelector" t-attf-class="o_field_selector#{!widget.options.readonly ? ' o_edit_mode o_input' : ''}">
|
||||
<div class="o_field_selector_value" tabindex="0"/>
|
||||
<div class="o_field_selector_controls" tabindex="0">
|
||||
<i class="fa fa-exclamation-triangle o_field_selector_warning hidden" title="Invalid field chain"/>
|
||||
@@ -816,7 +678,7 @@
|
||||
<ul class="o_field_selector_page"/>
|
||||
</div>
|
||||
<div t-if="widget.options.debugMode" class="o_field_selector_popover_footer">
|
||||
<input type="text"/>
|
||||
<input type="text" class="o_input"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -842,12 +704,11 @@
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
|
||||
<t t-name="web.datepicker">
|
||||
<t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/>
|
||||
<div class="o_datepicker">
|
||||
<input type="text"
|
||||
class="o_datepicker_input"
|
||||
class="o_datepicker_input o_input"
|
||||
t-att-name="widget.name"
|
||||
t-att-placeholder="placeholder"/>
|
||||
<span class="o_datepicker_button"/>
|
||||
@@ -857,7 +718,7 @@
|
||||
<span t-if="widget.mode === 'readonly'"/>
|
||||
|
||||
<select t-if="widget.mode !== 'readonly'"
|
||||
class="o_form_input"
|
||||
class="o_input"
|
||||
t-att-name="widget.name"
|
||||
t-att-tabindex="widget.attrs.tabindex"
|
||||
t-att-autofocus="widget.attrs.autofocus"
|
||||
@@ -866,9 +727,9 @@
|
||||
<t t-name="FieldRadio">
|
||||
<span t-if="widget.mode === 'readonly'"/>
|
||||
|
||||
<div t-if="widget.mode !== 'readonly'" t-attf-class="o_form_field_radio #{widget.nodeOptions.horizontal ? 'o_horizontal' : 'o_vertical'}">
|
||||
<div t-if="widget.mode !== 'readonly'" t-attf-class="o_field_radio #{widget.nodeOptions.horizontal ? 'o_horizontal' : 'o_vertical'}">
|
||||
<div t-foreach="widget.values" t-as="value" class="o_radio_item">
|
||||
<input type="radio" class="o_form_radio" t-att-id="widget.unique_id + '_' + value[0]" t-att-name="widget.unique_id" t-att-data-value="value[0]"/>
|
||||
<input type="radio" class="o_radio_input" t-att-id="widget.unique_id + '_' + value[0]" t-att-name="widget.unique_id" t-att-data-value="value[0]"/>
|
||||
<label t-if="!widget.nodeOptions.no_radiolabel" class="o_form_label" t-att-for="widget.unique_id + '_' + value[0]"><t t-esc="value[1]"/></label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -878,9 +739,9 @@
|
||||
<a t-if="!widget.nodeOptions.no_open" class="o_form_uri" href="#"/>
|
||||
<span t-if="widget.nodeOptions.no_open"/>
|
||||
</t>
|
||||
<div t-if="widget.mode === 'edit'" class="o_form_field o_form_field_many2one">
|
||||
<div class="o_form_input_dropdown">
|
||||
<input type="text" class="o_form_input"
|
||||
<div t-if="widget.mode === 'edit'" class="o_field_widget o_field_many2one">
|
||||
<div class="o_input_dropdown">
|
||||
<input type="text" class="o_input"
|
||||
t-att-barcode_events="widget.nodeOptions.barcode_events"
|
||||
t-att-tabindex="widget.attrs.tabindex"
|
||||
t-att-autofocus="widget.attrs.autofocus"
|
||||
@@ -891,9 +752,6 @@
|
||||
<button type="button" t-if="!widget.nodeOptions.no_open" class="fa fa-external-link btn btn-default o_external_button" tabindex="-1" draggable="false"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Many2OneButton.cell">
|
||||
<i t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/>
|
||||
</t>
|
||||
<t t-name="FieldMany2ManyTag">
|
||||
<t t-foreach="elements" t-as="el">
|
||||
<span t-attf-class="badge dropdown o_tag_color_#{el.color || 10}" t-att-data-color="el.color || 10" t-att-data-index="el_index" t-att-data-id="el.id">
|
||||
@@ -915,19 +773,6 @@
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
<t t-name="FieldBoolean">
|
||||
<div class="o_checkbox o_form_field_boolean">
|
||||
<input type="checkbox"
|
||||
t-att-id="widget.idForLabel"
|
||||
t-att-name="widget.name"
|
||||
t-att-tabindex="widget.node.attrs.tabindex"
|
||||
t-att-autofocus="widget.node.attrs.autofocus"/>
|
||||
<span/>
|
||||
</div>
|
||||
</t>
|
||||
<div t-name="FieldUpgradeBoolean" class="o_form_field o_form_field_boolean">
|
||||
<t t-call="FieldBoolean"/>
|
||||
</div>
|
||||
<t t-name="ProgressBar">
|
||||
<div class="o_progressbar">
|
||||
<div t-if="widget.title" class="o_progressbar_title"><t t-esc="widget.title"/></div><div class="o_progress">
|
||||
@@ -936,7 +781,7 @@
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="FieldPercentPie">
|
||||
<div class="o_form_field_percent_pie">
|
||||
<div class="o_field_percent_pie">
|
||||
<div class="o_pie">
|
||||
<div class="o_mask"/>
|
||||
<div class="o_mask"/>
|
||||
@@ -966,7 +811,7 @@
|
||||
</button>
|
||||
</t>
|
||||
<t t-name="FieldBinaryImage">
|
||||
<div class="o_form_field_image">
|
||||
<div class="o_field_image">
|
||||
<t t-if="widget.mode !== 'readonly'">
|
||||
<div class="o_form_image_controls">
|
||||
<span class="fa fa-pencil fa-lg pull-left o_select_file_button" title="Edit"/>
|
||||
@@ -997,8 +842,8 @@
|
||||
<t t-name="FieldBinaryFile">
|
||||
<a t-if="widget.mode === 'readonly'" href="javascript:void(0)" class="o_form_uri"/>
|
||||
|
||||
<div t-if="widget.mode !== 'readonly'" class="o_form_field_binary_file">
|
||||
<input type="text" class="o_form_input"
|
||||
<div t-if="widget.mode !== 'readonly'" class="o_field_binary_file">
|
||||
<input type="text" class="o_input"
|
||||
readonly="readonly"
|
||||
t-att-name="widget.name"
|
||||
t-att-tabindex="widget.attrs.tabindex"
|
||||
@@ -1022,8 +867,8 @@
|
||||
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
|
||||
<input type="hidden" name="session_id" value="" t-if="widget.getSession().override_session"/>
|
||||
<input type="hidden" name="callback" t-att-value="fileupload_id"/>
|
||||
<input t-if="widget.image_only" type="file" class="o_form_input_file" name="ufile" accept="image/*"/>
|
||||
<input t-if="!widget.image_only" type="file" class="o_form_input_file" name="ufile" t-att="{'multiple': multi_upload ? 'multiple' : null}"/>
|
||||
<input t-if="widget.image_only" type="file" class="o_input_file" name="ufile" accept="image/*"/>
|
||||
<input t-if="!widget.image_only" type="file" class="o_input_file" name="ufile" t-att="{'multiple': multi_upload ? 'multiple' : null}"/>
|
||||
<t t-raw="0"/>
|
||||
</form>
|
||||
<iframe t-att-id="fileupload_id" t-att-name="fileupload_id" style="display: none"/>
|
||||
@@ -1089,7 +934,6 @@
|
||||
<t t-name="SearchView.autocomplete">
|
||||
<ul class="dropdown-menu o_searchview_autocomplete" role="menu"></ul>
|
||||
</t>
|
||||
|
||||
<div t-name="SearchView.FilterMenu" class="btn-group o_dropdown">
|
||||
<button class="o_dropdown_toggler_btn btn btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="fa fa-filter"/> Filters <span class="caret"/>
|
||||
@@ -1198,7 +1042,6 @@
|
||||
</option>
|
||||
</select>
|
||||
</t>
|
||||
|
||||
<div t-name="SearchView.GroupByMenu" class="btn-group hidden-xs o_dropdown">
|
||||
<button class="o_dropdown_toggler_btn btn btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="fa fa-bars"/> Group By <span class="caret"/>
|
||||
@@ -1220,7 +1063,6 @@
|
||||
<button type="button" class="btn btn-primary btn-sm o_add_group o_select_group">Apply</button>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
<div t-name="SearchView.FavoriteMenu" class="btn-group o_dropdown">
|
||||
<button class="o_dropdown_toggler_btn btn btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="fa fa-star"/> Favorites <span class="caret"/>
|
||||
@@ -1334,13 +1176,6 @@
|
||||
Name: <input class="oe_form_m2o_input_name" type="text"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="FieldMonetary" t-extend="FieldChar">
|
||||
<t t-jquery="input">
|
||||
var $div = $(document.createElement('div')).attr('t-if', this.attr('t-if')).addClass('o_form_field_monetary');
|
||||
this.clone(true).appendTo($div);
|
||||
this.replaceWith($div);
|
||||
</t>
|
||||
</t>
|
||||
<t t-name="FieldMany2ManyCheckBoxes">
|
||||
<div>
|
||||
<div t-foreach="widget.m2mValues" t-as="m2m_value">
|
||||
@@ -1352,31 +1187,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="X2ManyCounter">
|
||||
<a href="javascript:void(0)"><t t-esc="text"/></a>
|
||||
</t>
|
||||
<t t-name="StatInfo">
|
||||
<span class="o_stat_value"><t t-esc="value"/></span>
|
||||
<span class="o_stat_text"><t t-esc="text"/></span>
|
||||
</t>
|
||||
|
||||
<t t-name="toggle_button">
|
||||
<button type="button" class="o_icon_button" t-att-title="widget.string">
|
||||
<i t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
<t t-name="BooleanButton">
|
||||
<t t-if="widget.get_value()">
|
||||
<span class="o_stat_text o_not_hover text-success"><t t-esc="widget.string_true"/></span>
|
||||
<span class="o_stat_text o_hover text-danger"><t t-esc="widget.hover_true"/></span>
|
||||
</t>
|
||||
<t t-if="!widget.get_value()">
|
||||
<span class="o_stat_text o_not_hover text-danger"><t t-esc="widget.string_false"/></span>
|
||||
<span class="o_stat_text o_hover text-success"><t t-esc="widget.hover_false"/></span>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<div t-name="Pager">
|
||||
<span class="o_pager_counter">
|
||||
<span class="o_pager_value"></span> / <span class="o_pager_limit"></span>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -198,15 +198,15 @@ QUnit.module('Views', {
|
||||
var $attendeesFilter = $sidebar.find('.o_calendar_filter:has(h3:contains(attendees))');
|
||||
assert.ok($attendeesFilter.length, "should display 'attendees' filter");
|
||||
assert.strictEqual($attendeesFilter.find('.o_calendar_filter_item').length, 3, "should display 3 filter items for 'attendees' who use write_model (2 saved + Everything)");
|
||||
assert.ok($attendeesFilter.find('.o_form_field_many2one').length, "should display one2many search bar for 'attendees' filter");
|
||||
assert.ok($attendeesFilter.find('.o_field_many2one').length, "should display one2many search bar for 'attendees' filter");
|
||||
|
||||
// test search bar in filter
|
||||
|
||||
$sidebar.find('input.o_form_input').trigger('click');
|
||||
$sidebar.find('input[type="text"]').trigger('click');
|
||||
assert.strictEqual($('ul.ui-autocomplete li:not(.o_m2o_dropdown_option)').length, 2, "should display 2 choices in one2many autocomplete"); // TODO: remove :not(.o_m2o_dropdown_option) because can't have "create & edit" choice
|
||||
$('ul.ui-autocomplete li:first').trigger('click');
|
||||
assert.strictEqual($sidebar.find('.o_calendar_filter:has(h3:contains(attendees)) .o_calendar_filter_item').length, 4, "should display 4 filter items for 'attendees'");
|
||||
$sidebar.find('input.o_form_input').trigger('click');
|
||||
$sidebar.find('input[type="text"]').trigger('click');
|
||||
assert.strictEqual($('ul.ui-autocomplete li:not(.o_m2o_dropdown_option)').text(), "partner 4", "should display the last choice in one2many autocomplete"); // TODO: remove :not(.o_m2o_dropdown_option) because can't have "create & edit" choice
|
||||
$sidebar.find('.o_calendar_filter_item[data-id="1"] .o_remove').trigger('click');
|
||||
assert.ok($('.modal button.btn:contains(Ok)').length, "should display the confirm message");
|
||||
@@ -503,28 +503,28 @@ QUnit.module('Views', {
|
||||
$('.modal input:first').val('new event').trigger('input');
|
||||
$('.modal button.btn:contains(Edit)').trigger('click');
|
||||
|
||||
assert.strictEqual($('.o_form_field[name="start"] input').val(), "12/13/2016 08:00:00",
|
||||
assert.strictEqual($('.o_field_widget[name="start"] input').val(), "12/13/2016 08:00:00",
|
||||
"should display the datetime");
|
||||
|
||||
$('.modal-lg .o_field_boolean[name="allday"] input').trigger('click');
|
||||
|
||||
assert.strictEqual($('.o_form_field[name="start_date"] input').val(), "12/13/2016",
|
||||
assert.strictEqual($('.o_field_widget[name="start_date"] input').val(), "12/13/2016",
|
||||
"should display the date");
|
||||
|
||||
$('.modal-lg .o_field_boolean[name="allday"] input').trigger('click');
|
||||
|
||||
assert.strictEqual($('.o_form_field[name="start"] input').val(), "12/13/2016 02:00:00",
|
||||
assert.strictEqual($('.o_field_widget[name="start"] input').val(), "12/13/2016 02:00:00",
|
||||
"should display the datetime from the date with the timezone");
|
||||
|
||||
// use datepicker to enter a date: 12/13/2016 08:00:00
|
||||
$('.o_form_field[name="start"] input').trigger('click');
|
||||
$('.o_field_widget[name="start"] input').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .picker-switch a[data-action="togglePicker"]').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .timepicker .timepicker-hour').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .timepicker-hours td.hour:contains(08)').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .picker-switch a[data-action="close"]').trigger('click');
|
||||
|
||||
// use datepicker to enter a date: 12/13/2016 10:00:00
|
||||
$('.o_form_field[name="stop"] input').trigger('click');
|
||||
$('.o_field_widget[name="stop"] input').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .picker-switch a[data-action="togglePicker"]').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .timepicker .timepicker-hour').trigger('click');
|
||||
$('.bootstrap-datetimepicker-widget .timepicker-hours td.hour:contains(10)').trigger('click');
|
||||
|
||||
@@ -141,7 +141,7 @@ QUnit.module('Views', {
|
||||
|
||||
assert.strictEqual(form.$('.o_group .o_group:first').attr('style'), 'background-color: red',
|
||||
"should apply style attribute on groups");
|
||||
assert.strictEqual(form.$('.o_form_field[name=foo]').attr('style'), 'color: blue',
|
||||
assert.strictEqual(form.$('.o_field_widget[name=foo]').attr('style'), 'color: blue',
|
||||
"should apply style attribute on fields");
|
||||
|
||||
assert.strictEqual(form.$('label:contains(something_id)').length, 0,
|
||||
@@ -226,11 +226,11 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('label.o_form_invisible:contains(Foo)').length, 1,
|
||||
assert.strictEqual(form.$('label.o_invisible_modifier:contains(Foo)').length, 1,
|
||||
"should not contain label Foo");
|
||||
assert.strictEqual(form.$('span.o_form_invisible:contains(yop)').length, 1,
|
||||
assert.strictEqual(form.$('span.o_invisible_modifier:contains(yop)').length, 1,
|
||||
"should not contain span with field value");
|
||||
assert.strictEqual(form.$('.o_form_field.o_form_invisible:contains(0.4)').length, 1,
|
||||
assert.strictEqual(form.$('.o_field_widget.o_invisible_modifier:contains(0.4)').length, 1,
|
||||
"field qux should be invisible");
|
||||
form.destroy();
|
||||
});
|
||||
@@ -257,9 +257,9 @@ QUnit.module('Views', {
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
});
|
||||
assert.strictEqual(form.$('.o_notebook li.o_form_invisible a:contains(invisible)').length, 1,
|
||||
assert.strictEqual(form.$('.o_notebook li.o_invisible_modifier a:contains(invisible)').length, 1,
|
||||
"should not display tab invisible");
|
||||
assert.strictEqual(form.$('table.o_inner_group.o_form_invisible td:contains(invgroup)').length, 1,
|
||||
assert.strictEqual(form.$('table.o_inner_group.o_invisible_modifier td:contains(invgroup)').length, 1,
|
||||
"should not display invisible groups");
|
||||
form.destroy();
|
||||
});
|
||||
@@ -287,14 +287,14 @@ QUnit.module('Views', {
|
||||
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.ok(form.$('.foo_field').hasClass('o_form_invisible'), 'should not display foo field');
|
||||
assert.ok(form.$('.bar_field').hasClass('o_form_invisible'), 'should not display bar field');
|
||||
assert.ok(form.$('.foo_field').hasClass('o_invisible_modifier'), 'should not display foo field');
|
||||
assert.ok(form.$('.bar_field').hasClass('o_invisible_modifier'), 'should not display bar field');
|
||||
|
||||
// set a value on the m2o
|
||||
var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_form_field_many2one input').click();
|
||||
var $dropdown = form.$('.o_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_field_many2one input').click();
|
||||
$dropdown.find('li:first()').click();
|
||||
assert.ok(!form.$('.foo_field').hasClass('o_form_invisible'), 'should display foo field');
|
||||
assert.ok(!form.$('.foo_field').hasClass('o_invisible_modifier'), 'should display foo field');
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
@@ -324,16 +324,16 @@ QUnit.module('Views', {
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.ok(form.$('.o_notebook .nav li:first()').hasClass('active'),
|
||||
'first tab should be active');
|
||||
assert.ok(!form.$('.o_notebook .nav li:first()').hasClass('o_form_invisible'),
|
||||
assert.ok(!form.$('.o_notebook .nav li:first()').hasClass('o_invisible_modifier'),
|
||||
'first tab should be visible');
|
||||
|
||||
// set a value on the m2o
|
||||
var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_form_field_many2one input').click();
|
||||
var $dropdown = form.$('.o_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_field_many2one input').click();
|
||||
$dropdown.find('li:first()').click();
|
||||
assert.ok(!form.$('.o_notebook .nav li:first()').hasClass('active'),
|
||||
'first tab should not be active');
|
||||
assert.ok(form.$('.o_notebook .nav li:first()').hasClass('o_form_invisible'),
|
||||
assert.ok(form.$('.o_notebook .nav li:first()').hasClass('o_invisible_modifier'),
|
||||
'first tab should be invisible');
|
||||
assert.ok(form.$('.o_notebook .nav li:nth(1)').hasClass('active'),
|
||||
'second tab should be active');
|
||||
@@ -365,7 +365,7 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.ok(form.$('.o_notebook .nav li:first()').hasClass('o_form_invisible'),
|
||||
assert.notOk(form.$('.o_notebook .nav li:first()').is(':visible'),
|
||||
'first tab should be invisible');
|
||||
assert.ok(form.$('.o_notebook .nav li:nth(1)').hasClass('active'),
|
||||
'second tab should be active');
|
||||
@@ -452,7 +452,7 @@ QUnit.module('Views', {
|
||||
|
||||
assert.strictEqual(form.$('button.oe_stat_button').length, 2,
|
||||
"should have 2 stat buttons");
|
||||
assert.strictEqual(form.$('button.oe_stat_button.o_form_invisible').length, 1,
|
||||
assert.strictEqual(form.$('button.oe_stat_button.o_invisible_modifier').length, 1,
|
||||
"should have 1 invisible stat buttons");
|
||||
|
||||
var count = 0;
|
||||
@@ -547,29 +547,29 @@ QUnit.module('Views', {
|
||||
res_id: 2,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field.o_form_field_empty').length, 2,
|
||||
assert.strictEqual(form.$('.o_field_widget.o_field_empty').length, 2,
|
||||
"should have 2 empty fields with correct class");
|
||||
assert.strictEqual(form.$('.o_form_label_empty').length, 2,
|
||||
"should have 2 muted labels (for the empty fieds) in readonly");
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_empty').length, 1,
|
||||
"in edit mode, only empty readonly fields should have the o_form_field_empty class");
|
||||
assert.strictEqual(form.$('.o_field_empty').length, 1,
|
||||
"in edit mode, only empty readonly fields should have the o_field_empty class");
|
||||
assert.strictEqual(form.$('.o_form_label_empty').length, 1,
|
||||
"in edit mode, only labels associated to empty readonly fields should have the o_form_label_empty class");
|
||||
|
||||
form.$('input[name="foo"]').val("test").trigger("input");
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_empty').length, 0,
|
||||
"after readonly modifier change, the o_form_field_empty class should have been removed");
|
||||
assert.strictEqual(form.$('.o_field_empty').length, 0,
|
||||
"after readonly modifier change, the o_field_empty class should have been removed");
|
||||
assert.strictEqual(form.$('.o_form_label_empty').length, 0,
|
||||
"after readonly modifier change, the o_form_label_empty class should have been removed");
|
||||
|
||||
form.$('input[name="foo"]').val("hello").trigger("input");
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_empty').length, 1,
|
||||
"after value changed to false for a readonly field, the o_form_field_empty class should have been added");
|
||||
assert.strictEqual(form.$('.o_field_empty').length, 1,
|
||||
"after value changed to false for a readonly field, the o_field_empty class should have been added");
|
||||
assert.strictEqual(form.$('.o_form_label_empty').length, 1,
|
||||
"after value changed to false for a readonly field, the o_form_label_empty class should have been added");
|
||||
|
||||
@@ -596,7 +596,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
assert.strictEqual(form.$('.o_form_label_empty').length, 0,
|
||||
"no empty class on label");
|
||||
assert.strictEqual(form.$('.o_form_field_empty').length, 0,
|
||||
assert.strictEqual(form.$('.o_field_empty').length, 0,
|
||||
"no empty class on field");
|
||||
form.destroy();
|
||||
});
|
||||
@@ -657,19 +657,19 @@ QUnit.module('Views', {
|
||||
});
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('input[name="foo"].o_form_required').length, 1,
|
||||
assert.strictEqual(form.$('input[name="foo"].o_required_modifier').length, 1,
|
||||
"the foo field widget should be required");
|
||||
form.$('.o_field_boolean input').click();
|
||||
assert.strictEqual(form.$('input[name="foo"]:not(.o_form_required)').length, 1,
|
||||
assert.strictEqual(form.$('input[name="foo"]:not(.o_required_modifier)').length, 1,
|
||||
"the foo field widget should now have been marked as non-required");
|
||||
form.$('.o_field_boolean input').click();
|
||||
assert.strictEqual(form.$('input[name="foo"].o_form_required').length, 1,
|
||||
assert.strictEqual(form.$('input[name="foo"].o_required_modifier').length, 1,
|
||||
"the foo field widget should now have been marked as required again");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('required fields should have o_form_required in readonly mode', function (assert) {
|
||||
QUnit.test('required fields should have o_required_modifier in readonly mode', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
this.data.partner.fields.foo.required = true;
|
||||
@@ -687,12 +687,12 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('span.o_form_required').length, 1,
|
||||
"should have 1 span with o_form_required class");
|
||||
assert.strictEqual(form.$('span.o_required_modifier').length, 1,
|
||||
"should have 1 span with o_required_modifier class");
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('input.o_form_required').length, 1,
|
||||
"in edit mode, should have 1 input with o_form_required");
|
||||
assert.strictEqual(form.$('input.o_required_modifier').length, 1,
|
||||
"in edit mode, should have 1 input with o_required_modifier");
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
@@ -1186,7 +1186,7 @@ QUnit.module('Views', {
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
}).then(function (form) {
|
||||
assert.ok(form.$('.o_form_input').val(), 'aaa',
|
||||
assert.ok(form.$('input').val(), 'aaa',
|
||||
'default value should be correctly displayed');
|
||||
assert.strictEqual(nameGetCount, 1, 'should have done one name_get');
|
||||
form.destroy();
|
||||
@@ -1464,12 +1464,12 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop');
|
||||
assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop');
|
||||
|
||||
// click on discard
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
assert.ok(!$('.modal:visible').length, 'no confirm modal should be displayed');
|
||||
assert.strictEqual(form.$('.o_form_field').text(), 'yop', 'field in readonly should display yop');
|
||||
assert.strictEqual(form.$('.o_field_widget').text(), 'yop', 'field in readonly should display yop');
|
||||
|
||||
assert.strictEqual(nbWrite, 0, 'no write RPC should have been done');
|
||||
form.destroy();
|
||||
@@ -1495,21 +1495,21 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode and edit the foo field
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop');
|
||||
form.$('.o_form_input').val('new value').trigger('input');
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain new value');
|
||||
assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop');
|
||||
form.$('input').val('new value').trigger('input');
|
||||
assert.strictEqual(form.$('input').val(), 'new value', 'input should contain new value');
|
||||
|
||||
// click on discard and cancel the confirm request
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
assert.ok($('.modal').length, 'a confirm modal should be displayed');
|
||||
$('.modal .modal-footer .btn-default').click(); // click on cancel
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should still contain new value');
|
||||
assert.strictEqual(form.$('input').val(), 'new value', 'input should still contain new value');
|
||||
|
||||
// click on discard and confirm
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
assert.ok($('.modal').length, 'a confirm modal should be displayed');
|
||||
$('.modal .modal-footer .btn-primary').click(); // click on confirm
|
||||
assert.strictEqual(form.$('.o_form_field').text(), 'yop', 'field in readonly should display yop');
|
||||
assert.strictEqual(form.$('.o_field_widget').text(), 'yop', 'field in readonly should display yop');
|
||||
|
||||
assert.strictEqual(nbWrite, 0, 'no write RPC should have been done');
|
||||
form.destroy();
|
||||
@@ -1524,7 +1524,6 @@ QUnit.module('Views', {
|
||||
// then parsed into string, which is wrong.
|
||||
|
||||
this.data.partner.fields.date.default = "2017-01-25";
|
||||
var nbWrite = 0;
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
@@ -1580,12 +1579,12 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode and edit the p field
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_field_x2many_list_row_add a').click();
|
||||
form.$('.o_form_field_many2one input').click();
|
||||
var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
form.$('.o_field_many2one input').click();
|
||||
var $dropdown = form.$('.o_field_many2one input').autocomplete('widget');
|
||||
$dropdown.find('li:first()').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'xphone', 'input should contain xphone');
|
||||
assert.strictEqual(form.$('input').val(), 'xphone', 'input should contain xphone');
|
||||
|
||||
// click on discard and confirm
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
@@ -1615,7 +1614,7 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode and edit the foo field
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should contain ABC');
|
||||
assert.strictEqual(form.$('input').val(), 'ABC', 'input should contain ABC');
|
||||
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
|
||||
@@ -1647,25 +1646,24 @@ QUnit.module('Views', {
|
||||
},
|
||||
});
|
||||
|
||||
// switch to edit mode and edit the foo field
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should contain ABC');
|
||||
form.$('.o_form_input').val('DEF').trigger('input');
|
||||
// edit the foo field
|
||||
assert.strictEqual(form.$('input').val(), 'ABC', 'input should contain ABC');
|
||||
form.$('input').val('DEF').trigger('input');
|
||||
|
||||
// discard the changes and check it has properly been discarded
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
assert.strictEqual($('.modal').length, 1,
|
||||
'there should be a confirm modal');
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'DEF', 'input should be DEF');
|
||||
assert.strictEqual(form.$('input').val(), 'DEF', 'input should be DEF');
|
||||
$('.modal .modal-footer .btn-primary').click(); // click on confirm
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should now be ABC');
|
||||
assert.strictEqual(form.$('input').val(), 'ABC', 'input should now be ABC');
|
||||
|
||||
// redirty and discard the field foo (to make sure initial changes haven't been lost)
|
||||
form.$('.o_form_input').val('GHI').trigger('input');
|
||||
form.$('input').val('GHI').trigger('input');
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'GHI', 'input should be GHI');
|
||||
assert.strictEqual(form.$('input').val(), 'GHI', 'input should be GHI');
|
||||
$('.modal .modal-footer .btn-primary').click(); // click on confirm
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should now be ABC');
|
||||
assert.strictEqual(form.$('input').val(), 'ABC', 'input should now be ABC');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
@@ -1694,7 +1692,7 @@ QUnit.module('Views', {
|
||||
|
||||
form.sidebar.$('a:contains(Duplicate)').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'tralala', 'input should contain ABC');
|
||||
assert.strictEqual(form.$('input').val(), 'tralala', 'input should contain ABC');
|
||||
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
|
||||
@@ -1731,24 +1729,24 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop');
|
||||
assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop');
|
||||
|
||||
// edit the foo field
|
||||
form.$('.o_form_input').val('new value').trigger('input');
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain new value');
|
||||
form.$('input').val('new value').trigger('input');
|
||||
assert.strictEqual(form.$('input').val(), 'new value', 'input should contain new value');
|
||||
|
||||
// click on the pager to switch to the next record and cancel the confirm request
|
||||
form.pager.$('.o_pager_next').click(); // click on next
|
||||
assert.ok($('.modal').length, 'a confirm modal should be displayed');
|
||||
$('.modal .modal-footer .btn-default').click(); // click on cancel
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should still contain new value');
|
||||
assert.strictEqual(form.$('input').val(), 'new value', 'input should still contain new value');
|
||||
assert.strictEqual(form.pager.$('.o_pager_value').text(), "1", 'pager value should still be 1');
|
||||
|
||||
// click on the pager to switch to the next record and confirm
|
||||
form.pager.$('.o_pager_next').click(); // click on next
|
||||
assert.ok($('.modal').length, 'a confirm modal should be displayed');
|
||||
$('.modal .modal-footer .btn-primary').click(); // click on confirm
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'blip', 'input should contain blip');
|
||||
assert.strictEqual(form.$('input').val(), 'blip', 'input should contain blip');
|
||||
assert.strictEqual(form.pager.$('.o_pager_value').text(), "2", 'pager value should be 2');
|
||||
|
||||
assert.strictEqual(nbWrite, 0, 'no write RPC should have been done');
|
||||
@@ -1776,11 +1774,11 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop');
|
||||
assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop');
|
||||
|
||||
// edit the foo field
|
||||
form.$('.o_form_input').val('new value').trigger('input');
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain new value');
|
||||
form.$('input').val('new value').trigger('input');
|
||||
assert.strictEqual(form.$('input').val(), 'new value', 'input should contain new value');
|
||||
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
|
||||
@@ -1803,10 +1801,10 @@ QUnit.module('Views', {
|
||||
|
||||
// switch to edit mode
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain yop');
|
||||
assert.strictEqual(form.$('input').val(), 'new value', 'input should contain yop');
|
||||
|
||||
// edit the foo field
|
||||
form.$('.o_form_input').val('wrong value').trigger('input');
|
||||
form.$('input').val('wrong value').trigger('input');
|
||||
|
||||
form.$buttons.find('.o_form_button_cancel').click();
|
||||
assert.strictEqual($('.modal').length, 1, 'a confirm modal should be displayed');
|
||||
@@ -1976,12 +1974,12 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_empty').length, 1,
|
||||
assert.strictEqual(form.$('.o_field_empty').length, 1,
|
||||
'readonly field should be invisible on an existing record');
|
||||
|
||||
form.$buttons.find('.o_form_button_create').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_empty').length, 0,
|
||||
assert.strictEqual(form.$('.o_field_empty').length, 0,
|
||||
'readonly field should be visible on a new record');
|
||||
form.destroy();
|
||||
});
|
||||
@@ -2119,15 +2117,15 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
assert.ok(form.$('label').hasClass('o_form_invalid'),
|
||||
assert.ok(form.$('label').hasClass('o_field_invalid'),
|
||||
"label should be tagged as invalid");
|
||||
assert.ok(form.$('input').hasClass('o_form_invalid'),
|
||||
assert.ok(form.$('input').hasClass('o_field_invalid'),
|
||||
"input should be tagged as invalid");
|
||||
|
||||
form.$('input').val("tralala").trigger('input');
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_invalid').length, 0,
|
||||
assert.strictEqual(form.$('.o_field_invalid').length, 0,
|
||||
"nothing should be marked as invalid");
|
||||
form.destroy();
|
||||
});
|
||||
@@ -2224,12 +2222,12 @@ QUnit.module('Views', {
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_input[name=int_field]').val(), '9',
|
||||
assert.strictEqual(form.$('input[name=int_field]').val(), '9',
|
||||
"'int_field' value should be 9 before the change");
|
||||
|
||||
form.$('input').first().val("tralala").trigger('input');
|
||||
|
||||
assert.strictEqual(form.$('.o_form_input[name=int_field]').val(), '10',
|
||||
assert.strictEqual(form.$('input[name=int_field]').val(), '10',
|
||||
"the onchange should have been correctly applied");
|
||||
|
||||
form.destroy();
|
||||
@@ -2273,7 +2271,7 @@ QUnit.module('Views', {
|
||||
|
||||
// go to edit mode, click to add a record in the o2m
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_field_x2many_list_row_add a').click();
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
assert.strictEqual(form.$('tr.o_data_row').length, 0,
|
||||
"should not have added a line");
|
||||
form.destroy();
|
||||
@@ -2379,15 +2377,15 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_one2many .o_data_row').length, 1,
|
||||
assert.strictEqual(form.$('.o_field_one2many .o_data_row').length, 1,
|
||||
"there should be one one2many record linked at first");
|
||||
assert.strictEqual(form.$('.o_form_field_one2many .o_data_row td:first').text(), 'aaa',
|
||||
assert.strictEqual(form.$('.o_field_one2many .o_data_row td:first').text(), 'aaa',
|
||||
"the 'display_name' of the one2many record should be correct");
|
||||
|
||||
// switch to edit mode
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_input').val('let us trigger an onchange').trigger('input');
|
||||
var $o2m = form.$('.o_form_field_one2many');
|
||||
form.$('input').val('let us trigger an onchange').trigger('input');
|
||||
var $o2m = form.$('.o_field_one2many');
|
||||
assert.strictEqual($o2m.find('.o_data_row').length, 2,
|
||||
"there should be two linked record");
|
||||
assert.strictEqual($o2m.find('.o_data_row:first td:first').text(), 'updated record',
|
||||
@@ -2479,13 +2477,13 @@ QUnit.module('Views', {
|
||||
res_id: 2,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field_many2many .o_data_row').length, 0,
|
||||
assert.strictEqual(form.$('.o_field_many2many .o_data_row').length, 0,
|
||||
"there should be no many2many record linked at first");
|
||||
|
||||
// switch to edit mode
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_input').val('let us trigger an onchange').trigger('input');
|
||||
var $m2m = form.$('.o_form_field_many2many');
|
||||
form.$('input').val('let us trigger an onchange').trigger('input');
|
||||
var $m2m = form.$('.o_field_many2many');
|
||||
assert.strictEqual($m2m.find('.o_data_row').length, 2,
|
||||
"there should be two linked records");
|
||||
assert.strictEqual($m2m.find('.o_data_row:first td:first').text(), 'gold',
|
||||
@@ -2526,24 +2524,24 @@ QUnit.module('Views', {
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name=date]').text(),
|
||||
assert.strictEqual(form.$('.o_field_widget[name=date]').text(),
|
||||
'01/25/2017', "the initial date should be correct");
|
||||
assert.strictEqual(form.$('.o_form_field[name=datetime]').text(),
|
||||
assert.strictEqual(form.$('.o_field_widget[name=datetime]').text(),
|
||||
'12/12/2016 12:55:05', "the initial datetime should be correct");
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name=date] input').val(),
|
||||
assert.strictEqual(form.$('.o_field_widget[name=date] input').val(),
|
||||
'01/25/2017', "the initial date should be correct in edit");
|
||||
assert.strictEqual(form.$('.o_form_field[name=datetime] input').val(),
|
||||
assert.strictEqual(form.$('.o_field_widget[name=datetime] input').val(),
|
||||
'12/12/2016 12:55:05', "the initial datetime should be correct in edit");
|
||||
|
||||
// trigger the onchange
|
||||
form.$('.o_form_field[name="foo"]').val("coucou").trigger('input');
|
||||
form.$('.o_field_widget[name="foo"]').val("coucou").trigger('input');
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name=date] input').val(),
|
||||
assert.strictEqual(form.$('.o_field_widget[name=date] input').val(),
|
||||
'12/12/2021', "the initial date should be correct in edit");
|
||||
assert.strictEqual(form.$('.o_form_field[name=datetime] input').val(),
|
||||
assert.strictEqual(form.$('.o_field_widget[name=datetime] input').val(),
|
||||
'12/12/2021 12:55:05', "the initial datetime should be correct in edit");
|
||||
|
||||
form.destroy();
|
||||
@@ -2653,7 +2651,7 @@ QUnit.module('Views', {
|
||||
|
||||
// save, and check that the int_field input is marked as invalid
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
assert.ok(form.$('input[name="int_field"]').hasClass('o_form_invalid'),
|
||||
assert.ok(form.$('input[name="int_field"]').hasClass('o_field_invalid'),
|
||||
"input int_field is marked as invalid");
|
||||
|
||||
assert.verifySteps(['read', 'onchange']);
|
||||
@@ -2769,7 +2767,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_input:first').val('trigger an onchange').trigger('input');
|
||||
form.$('input:first').val('trigger an onchange').trigger('input');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
@@ -2830,7 +2828,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_input:first').val('trigger an onchange').trigger('input');
|
||||
form.$('input:first').val('trigger an onchange').trigger('input');
|
||||
|
||||
assert.strictEqual(form.$('.o_data_row td:first').text(), 'foo changed',
|
||||
"onchange should have been correctly applied on field in o2m list");
|
||||
@@ -2890,13 +2888,13 @@ QUnit.module('Views', {
|
||||
assert.strictEqual(form.$('.o_data_row td:first').text(), 'My little Foo Value',
|
||||
"the initial value should be the default one");
|
||||
|
||||
form.$('.o_form_input:first').val('trigger an onchange').trigger('input');
|
||||
form.$('input:first').val('trigger an onchange').trigger('input');
|
||||
|
||||
assert.strictEqual(form.$('.o_data_row td:first').text(), 'foo changed',
|
||||
"onchange should have been correctly applied on field in o2m list");
|
||||
|
||||
form.$('.o_data_row').click(); // edit the o2m in the dialog
|
||||
assert.strictEqual($('.modal .o_form_field').val(), 'foo changed',
|
||||
assert.strictEqual($('.modal .o_field_widget').val(), 'foo changed',
|
||||
"the onchange value hasn't been discarded when opening the o2m");
|
||||
|
||||
form.destroy();
|
||||
@@ -2943,7 +2941,7 @@ QUnit.module('Views', {
|
||||
"onchange should have been correctly applied");
|
||||
|
||||
// create a new o2m record
|
||||
form.$('.o_form_field_x2many_list_row_add a').click();
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
assert.strictEqual(form.$('.o_data_row input:first').val(), '[blip] 14',
|
||||
"onchange should have been correctly applied after default get");
|
||||
|
||||
@@ -2988,16 +2986,16 @@ QUnit.module('Views', {
|
||||
"the initial value should be the default one");
|
||||
|
||||
form.$('.o_data_row td:first').click(); // edit the o2m in a dialog
|
||||
$('.modal .o_form_input:nth(1)').val(77).trigger('input');
|
||||
assert.strictEqual($('.modal .o_form_input:first').val(), '[blip] 77',
|
||||
$('.modal input:nth(1)').val(77).trigger('input');
|
||||
assert.strictEqual($('.modal input:first').val(), '[blip] 77',
|
||||
"onchange should have been correctly applied");
|
||||
$('.modal .modal-footer .btn-primary').click(); // save the dialog
|
||||
assert.strictEqual(form.$('.o_data_row td:first').text(), '[blip] 77',
|
||||
"onchange should have been correctly applied");
|
||||
|
||||
// create a new o2m record
|
||||
form.$('.o_form_field_x2many_list_row_add a').click();
|
||||
assert.strictEqual($('.modal .o_form_input:first').val(), '[blip] 14',
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
assert.strictEqual($('.modal input:first').val(), '[blip] 14',
|
||||
"onchange should have been correctly applied after default get");
|
||||
$('.modal .modal-footer .btn-primary').click(); // save the dialog
|
||||
assert.strictEqual(form.$('.o_data_row:nth(1) td:first').text(), '[blip] 14',
|
||||
@@ -3035,7 +3033,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_input:first').val('coucou').trigger('input');
|
||||
form.$('input:first').val('coucou').trigger('input');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
@@ -3260,10 +3258,10 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
// add a o2m subrecord with a m2m tag
|
||||
form.$('.o_form_field_x2many_list_row_add a').click();
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
form.$('.o_many2many_tags_cell').click();
|
||||
form.$('.o_form_field_many2one input').click();
|
||||
var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_field_many2one input').click();
|
||||
var $dropdown = form.$('.o_field_many2one input').autocomplete('widget');
|
||||
$dropdown.find('li:first()').click(); // select the first tag
|
||||
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
@@ -3345,13 +3343,13 @@ QUnit.module('Views', {
|
||||
// could be saved, even if in its field description it is readonly
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_input').length, 1,
|
||||
assert.strictEqual(form.$('input[name="foo"]').length, 1,
|
||||
"foo field should be editable");
|
||||
form.$('.o_form_input').val('New foo value').trigger('input');
|
||||
form.$('input[name="foo"]').val('New foo value').trigger('input');
|
||||
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_field[name=foo]').text(), 'New foo value',
|
||||
assert.strictEqual(form.$('.o_field_widget[name=foo]').text(), 'New foo value',
|
||||
"new value for foo field should have been saved");
|
||||
|
||||
form.destroy();
|
||||
@@ -3388,7 +3386,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
form.$('.o_form_field_x2many_list_row_add a').click();
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
@@ -3428,7 +3426,7 @@ QUnit.module('Views', {
|
||||
form.destroy();
|
||||
|
||||
function getVisibleButtonTexts() {
|
||||
var $visibleButtons = form.$buttons.find('button').not('.o_form_invisible *');
|
||||
var $visibleButtons = form.$buttons.find('button:visible');
|
||||
return _.map($visibleButtons, function (el) {
|
||||
return el.innerHTML.trim();
|
||||
});
|
||||
@@ -3525,11 +3523,11 @@ QUnit.module('Views', {
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
var row = form.$('.o_form_field_one2many .o_list_view .o_data_row');
|
||||
var row = form.$('.o_field_one2many .o_list_view .o_data_row');
|
||||
assert.strictEqual(row.children()[1].textContent, '1 record',
|
||||
"the cell should contains the number of record: 1");
|
||||
row.click();
|
||||
var modal_row = $('.modal-body .o_form_sheet .o_form_field_one2many .o_list_view .o_data_row');
|
||||
var modal_row = $('.modal-body .o_form_sheet .o_field_one2many .o_list_view .o_data_row');
|
||||
assert.strictEqual(modal_row.children().length, 2,
|
||||
"the row should contains the 2 fields defined in the form view");
|
||||
assert.strictEqual($(modal_row).text(), "gold2",
|
||||
@@ -3554,9 +3552,9 @@ QUnit.module('Views', {
|
||||
});
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_form_input[name="foo"]')[0], document.activeElement,
|
||||
assert.strictEqual(form.$('input[name="foo"]')[0], document.activeElement,
|
||||
"foo field should have focus");
|
||||
assert.strictEqual(form.$('.o_form_input[name="foo"]')[0].selectionStart, 3,
|
||||
assert.strictEqual(form.$('input[name="foo"]')[0].selectionStart, 3,
|
||||
"cursor should be at the end");
|
||||
|
||||
form.destroy();
|
||||
@@ -3576,7 +3574,7 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('.o_form_input[name="foo"]')[0], document.activeElement,
|
||||
assert.strictEqual(form.$('input[name="foo"]')[0], document.activeElement,
|
||||
"foo field should have focus");
|
||||
|
||||
form.destroy();
|
||||
@@ -3646,7 +3644,7 @@ QUnit.module('Views', {
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
var row = form.$('.o_form_field_one2many .o_list_view .o_data_row');
|
||||
var row = form.$('.o_field_one2many .o_list_view .o_data_row');
|
||||
row.click();
|
||||
assert.verifySteps(['read', 'read', 'read'],
|
||||
"there should be 3 read rpcs");
|
||||
@@ -3809,16 +3807,16 @@ QUnit.module('Views', {
|
||||
assert.strictEqual($('.modal').length, 1,
|
||||
"One FormViewDialog should be opened");
|
||||
var $firstModal = $('.modal');
|
||||
assert.strictEqual($firstModal.find('.o_form_input').val(), 'xphone',
|
||||
assert.strictEqual($firstModal.find('input').val(), 'xphone',
|
||||
"display_name should be correctly displayed");
|
||||
|
||||
// Open second dialog
|
||||
$firstModal.find('.o_form_field_x2many_list_row_add a').click();
|
||||
$firstModal.find('.o_field_x2many_list_row_add a').click();
|
||||
assert.strictEqual($('.modal').length, 2,
|
||||
"two FormViewDialogs should be opened");
|
||||
var $secondModal = $('.modal:nth(1)');
|
||||
// Add new value
|
||||
$secondModal.find('.o_form_input').val('xtv').trigger('input');
|
||||
$secondModal.find('input').val('xtv').trigger('input');
|
||||
$secondModal.find('.modal-footer button:first').click(); // Save & close
|
||||
assert.strictEqual($('.modal').length, 1,
|
||||
"last opened dialog should be closed");
|
||||
@@ -3858,7 +3856,7 @@ QUnit.module('Views', {
|
||||
},
|
||||
});
|
||||
|
||||
form.$('.o_form_input:first').click(); // trigger the name_search
|
||||
form.$('input:first').click(); // trigger the name_search
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
@@ -3889,21 +3887,21 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_notebook ul li:not(.o_form_invisible)').length, 2,
|
||||
assert.strictEqual(form.$('.o_notebook ul li:not(.o_invisible_modifier)').length, 2,
|
||||
"both tabs should be visible");
|
||||
assert.ok(form.$('.o_notebook ul li:first').hasClass('active'),
|
||||
"first tab should be active");
|
||||
|
||||
// click on the pager to switch to the next record
|
||||
form.pager.$('.o_pager_next').click();
|
||||
assert.strictEqual(form.$('.o_notebook ul li:not(.o_form_invisible)').length, 1,
|
||||
assert.strictEqual(form.$('.o_notebook ul li:not(.o_invisible_modifier)').length, 1,
|
||||
"only the second tab should be visible");
|
||||
assert.ok(form.$('.o_notebook ul li:not(.o_form_invisible)').hasClass('active'),
|
||||
assert.ok(form.$('.o_notebook ul li:not(.o_invisible_modifier)').hasClass('active'),
|
||||
"the visible tab should be active");
|
||||
|
||||
// click on the pager to switch back to the previous record
|
||||
form.pager.$('.o_pager_previous').click();
|
||||
assert.strictEqual(form.$('.o_notebook ul li:not(.o_form_invisible)').length, 2,
|
||||
assert.strictEqual(form.$('.o_notebook ul li:not(.o_invisible_modifier)').length, 2,
|
||||
"both tabs should be visible again");
|
||||
assert.ok(form.$('.o_notebook ul li:nth(1)').hasClass('active'),
|
||||
"second tab should be active");
|
||||
@@ -4013,7 +4011,7 @@ QUnit.module('Views', {
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.ok(form.$('.o_form_field_one2many tbody tr:first td:contains(yop)').length,
|
||||
assert.ok(form.$('.o_field_one2many tbody tr:first td:contains(yop)').length,
|
||||
"record 1 should be first");
|
||||
|
||||
form.destroy();
|
||||
|
||||
@@ -403,11 +403,11 @@ QUnit.module('Views', {
|
||||
|
||||
assert.strictEqual($('.modal .o_form_view.o_form_editable').length, 1,
|
||||
"a form view dialog should have been opened (in edit)");
|
||||
assert.strictEqual($('.modal .o_form_field_many2one input').val(), 'hello',
|
||||
assert.strictEqual($('.modal .o_field_many2one input').val(), 'hello',
|
||||
"the correct product_id should already be set");
|
||||
|
||||
// specify a name and save
|
||||
$('.modal .o_form_input[name=foo]').val('test').trigger('input');
|
||||
$('.modal input[name=foo]').val('test').trigger('input');
|
||||
$('.modal-footer .btn-primary').click();
|
||||
|
||||
assert.strictEqual($('.modal').length, 0, "the modal should be closed");
|
||||
@@ -445,7 +445,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
var $first_record = kanban.$('.o_kanban_record:first()');
|
||||
assert.strictEqual($first_record.find('.o_form_field_many2manytags .o_tag').length, 2,
|
||||
assert.strictEqual($first_record.find('.o_field_many2manytags .o_tag').length, 2,
|
||||
'first record should contain 2 tags');
|
||||
assert.ok($first_record.find('.o_tag:first()').hasClass('o_tag_color_2'),
|
||||
'first tag should have color 2');
|
||||
@@ -751,9 +751,9 @@ QUnit.module('Views', {
|
||||
// edit the title of column [5, 'xmo'] and close without saving
|
||||
kanban.$('.o_kanban_group[data-id=5] .o_column_edit').click(); // click on 'Edit'
|
||||
assert.ok($('.modal .o_form_editable').length, 'a form view should be open in a modal');
|
||||
assert.strictEqual($('.modal .o_form_editable .o_form_input').val(), 'xmo',
|
||||
assert.strictEqual($('.modal .o_form_editable input').val(), 'xmo',
|
||||
'the name should be "xmo"');
|
||||
$('.modal .o_form_editable .o_form_input').val('ged').trigger('input'); // change the value
|
||||
$('.modal .o_form_editable input').val('ged').trigger('input'); // change the value
|
||||
nbRPCs = 0;
|
||||
$('.modal .modal-header .close').click(); // click on the cross to close the modal
|
||||
assert.ok(!$('.modal').length, 'the modal should be closed');
|
||||
@@ -763,7 +763,7 @@ QUnit.module('Views', {
|
||||
|
||||
// edit the title of column [5, 'xmo'] and discard
|
||||
kanban.$('.o_kanban_group[data-id=5] .o_column_edit').click(); // click on 'Edit'
|
||||
$('.modal .o_form_editable .o_form_input').val('ged').trigger('input'); // change the value
|
||||
$('.modal .o_form_editable input').val('ged').trigger('input'); // change the value
|
||||
nbRPCs = 0;
|
||||
$('.modal .modal-footer .btn-default').click(); // click on discard
|
||||
assert.ok(!$('.modal').length, 'the modal should be closed');
|
||||
@@ -773,7 +773,7 @@ QUnit.module('Views', {
|
||||
|
||||
// edit the title of column [5, 'xmo'] and save
|
||||
kanban.$('.o_kanban_group[data-id=5] .o_column_edit').click(); // click on 'Edit'
|
||||
$('.modal .o_form_editable .o_form_input').val('ged').trigger('input'); // change the value
|
||||
$('.modal .o_form_editable input').val('ged').trigger('input'); // change the value
|
||||
nbRPCs = 0;
|
||||
$('.modal .modal-footer .btn-primary').click(); // click on save
|
||||
assert.ok(!$('.modal').length, 'the modal should be closed');
|
||||
|
||||
@@ -302,17 +302,17 @@ QUnit.module('Views', {
|
||||
$td.click();
|
||||
assert.ok($td.parent().hasClass('o_selected_row'),
|
||||
"row should be in edit mode");
|
||||
assert.ok($td.hasClass('o_readonly'),
|
||||
assert.ok($td.hasClass('o_readonly_modifier'),
|
||||
"foo cell should be readonly in edit mode");
|
||||
assert.ok(!$second_td.hasClass('o_readonly'),
|
||||
assert.ok(!$second_td.hasClass('o_readonly_modifier'),
|
||||
"bar cell should be editable");
|
||||
assert.ok($third_td.hasClass('o_readonly'),
|
||||
assert.ok($third_td.hasClass('o_readonly_modifier'),
|
||||
"int_field cell should be readonly in edit mode");
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('basic operations for editable list renderer', function (assert) {
|
||||
assert.expect(4);
|
||||
assert.expect(2);
|
||||
|
||||
var list = createView({
|
||||
View: ListView,
|
||||
@@ -325,9 +325,6 @@ QUnit.module('Views', {
|
||||
assert.ok(!$td.parent().hasClass('o_selected_row'), "td should not be in edit mode");
|
||||
$td.click();
|
||||
assert.ok($td.parent().hasClass('o_selected_row'), "td should be in edit mode");
|
||||
assert.ok(!$td.hasClass('o_field_dirty'), "td should not be dirty");
|
||||
$td.find('input').val('abc').trigger('input');
|
||||
assert.ok($td.hasClass('o_field_dirty'), "td should be dirty");
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
@@ -1085,9 +1082,9 @@ QUnit.module('Views', {
|
||||
|
||||
// edit first row
|
||||
list.$('tbody tr:nth(0) td:nth(2)').click(); // click on first row to edit it
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(4) input.o_form_invisible').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(4) input.o_invisible_modifier').length, 1,
|
||||
"td that contains an invisible field should not be empty in edition");
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > button.o_form_invisible').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > button.o_invisible_modifier').length, 1,
|
||||
"td that contains an invisible button should not be empty in edition");
|
||||
list.$buttons.find('.o_list_button_discard').click(); // leave edition
|
||||
|
||||
@@ -1161,16 +1158,16 @@ QUnit.module('Views', {
|
||||
arch: '<tree editable="bottom"><field name="foo"/><field name="int_field"/></tree>',
|
||||
});
|
||||
|
||||
assert.ok(list.$('.o_data_row:first td:nth(1)').hasClass('o_readonly'),
|
||||
"foo field cells should have class 'o_readonly'");
|
||||
assert.ok(list.$('.o_data_row:first td:nth(1)').hasClass('o_readonly_modifier'),
|
||||
"foo field cells should have class 'o_readonly_modifier'");
|
||||
|
||||
// edit the first row
|
||||
list.$('.o_data_row:first td:nth(1)').click();
|
||||
assert.ok(list.$('.o_data_row:first').hasClass('o_selected_row'),
|
||||
"first row should be selected");
|
||||
var $cell = list.$('.o_data_row:first td:nth(1)');
|
||||
assert.ok($cell.hasClass('o_readonly') && $cell.parent().hasClass('o_selected_row'),
|
||||
"foo field cells should have class 'o_readonly' and the row should be in edition");
|
||||
assert.ok($cell.hasClass('o_readonly_modifier') && $cell.parent().hasClass('o_selected_row'),
|
||||
"foo field cells should have class 'o_readonly_modifier' and the row should be in edition");
|
||||
assert.strictEqual(list.$('.o_data_row:first td:nth(1) span').text(), 'yop',
|
||||
"a widget should have been rendered for readonly fields");
|
||||
assert.ok(list.$('.o_data_row:first td:nth(2)').parent().hasClass('o_selected_row'),
|
||||
@@ -1415,32 +1412,32 @@ QUnit.module('Views', {
|
||||
'</tree>',
|
||||
});
|
||||
|
||||
assert.strictEqual(list.$('tbody td.o_form_invisible').length, 3,
|
||||
assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 3,
|
||||
"there should be 3 invisible foo cells in readonly mode");
|
||||
|
||||
// Make first line editable
|
||||
list.$('tbody tr:nth(0) td:nth(1)').click();
|
||||
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_invisible').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_invisible_modifier').length, 1,
|
||||
"the foo field widget should have been rendered as invisible");
|
||||
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_form_invisible)').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_invisible_modifier)').length, 1,
|
||||
"the foo field widget should have been marked as non-invisible");
|
||||
assert.strictEqual(list.$('tbody td.o_form_invisible').length, 2,
|
||||
assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 2,
|
||||
"the foo field widget parent cell should not be invisible anymore");
|
||||
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_invisible').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_invisible_modifier').length, 1,
|
||||
"the foo field widget should have been marked as invisible again");
|
||||
assert.strictEqual(list.$('tbody td.o_form_invisible').length, 3,
|
||||
assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 3,
|
||||
"the foo field widget parent cell should now be invisible again");
|
||||
|
||||
// Reswitch the cell to editable and save the row
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
list.$('thead').click();
|
||||
|
||||
assert.strictEqual(list.$('tbody td.o_form_invisible').length, 2,
|
||||
assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 2,
|
||||
"there should be 2 invisible foo cells in readonly mode");
|
||||
|
||||
list.destroy();
|
||||
@@ -1460,7 +1457,7 @@ QUnit.module('Views', {
|
||||
'</tree>',
|
||||
});
|
||||
|
||||
assert.strictEqual(list.$('tbody td.o_readonly').length, 3,
|
||||
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 3,
|
||||
"there should be 3 readonly foo cells in readonly mode");
|
||||
|
||||
// Make first line editable
|
||||
@@ -1472,20 +1469,20 @@ QUnit.module('Views', {
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]').length, 1,
|
||||
"the foo field widget should have been rerendered as editable");
|
||||
assert.strictEqual(list.$('tbody td.o_readonly').length, 2,
|
||||
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2,
|
||||
"the foo field widget parent cell should not be readonly anymore");
|
||||
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > span[name="foo"]').length, 1,
|
||||
"the foo field widget should have been rerendered as readonly");
|
||||
assert.strictEqual(list.$('tbody td.o_readonly').length, 3,
|
||||
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 3,
|
||||
"the foo field widget parent cell should now be readonly again");
|
||||
|
||||
// Reswitch the cell to editable and save the row
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
list.$('thead').click();
|
||||
|
||||
assert.strictEqual(list.$('tbody td.o_readonly').length, 2,
|
||||
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2,
|
||||
"there should be 2 readonly foo cells in readonly mode");
|
||||
|
||||
list.destroy();
|
||||
@@ -1505,32 +1502,32 @@ QUnit.module('Views', {
|
||||
'</tree>',
|
||||
});
|
||||
|
||||
assert.strictEqual(list.$('tbody td.o_form_required').length, 3,
|
||||
assert.strictEqual(list.$('tbody td.o_required_modifier').length, 3,
|
||||
"there should be 3 required foo cells in readonly mode");
|
||||
|
||||
// Make first line editable
|
||||
list.$('tbody tr:nth(0) td:nth(1)').click();
|
||||
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_required').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_required_modifier').length, 1,
|
||||
"the foo field widget should have been rendered as required");
|
||||
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_form_required)').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_required_modifier)').length, 1,
|
||||
"the foo field widget should have been marked as non-required");
|
||||
assert.strictEqual(list.$('tbody td.o_form_required').length, 2,
|
||||
assert.strictEqual(list.$('tbody td.o_required_modifier').length, 2,
|
||||
"the foo field widget parent cell should not be required anymore");
|
||||
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_required').length, 1,
|
||||
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_required_modifier').length, 1,
|
||||
"the foo field widget should have been marked as required again");
|
||||
assert.strictEqual(list.$('tbody td.o_form_required').length, 3,
|
||||
assert.strictEqual(list.$('tbody td.o_required_modifier').length, 3,
|
||||
"the foo field widget parent cell should now be required again");
|
||||
|
||||
// Reswitch the cell to editable and save the row
|
||||
list.$('tbody tr:nth(0) td:nth(2) input').click();
|
||||
list.$('thead').click();
|
||||
|
||||
assert.strictEqual(list.$('tbody td.o_form_required').length, 2,
|
||||
assert.strictEqual(list.$('tbody td.o_required_modifier').length, 2,
|
||||
"there should be 2 required foo cells in readonly mode");
|
||||
|
||||
list.destroy();
|
||||
@@ -1571,7 +1568,7 @@ QUnit.module('Views', {
|
||||
"first line should still be in edition as invalid");
|
||||
assert.strictEqual(list.$('tbody tr.o_selected_row').length, 1,
|
||||
"no other line should be in edition");
|
||||
assert.strictEqual($firstFooTd.find('input.o_form_invalid').length, 1,
|
||||
assert.strictEqual($firstFooTd.find('input.o_field_invalid').length, 1,
|
||||
"the required field should be marked as invalid");
|
||||
assert.strictEqual(warnings, 1,
|
||||
"a warning should have been displayed");
|
||||
|
||||
@@ -14,19 +14,17 @@
|
||||
<t t-call="web.less_helpers"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/web/static/lib/jquery.ui/jquery-ui.css"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/web/static/lib/fontawesome/css/font-awesome.css"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/fonts.less"/>
|
||||
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/navbar.less"/>
|
||||
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/mimetypes.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/animation.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/datepicker.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/lib/bootstrap-datetimepicker/src/less/_bootstrap-datetimepicker.less"/>
|
||||
<link rel="stylesheet" type="text/css" href="/web/static/lib/select2/select2.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/web/static/lib/select2-bootstrap-css/select2-bootstrap.css"/>
|
||||
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/fonts.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/navbar.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/mimetypes.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/animation.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/datepicker.less"/>
|
||||
|
||||
<script type="text/javascript" src="/web/static/lib/es5-shim/es5-shim.min.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/underscore.string/lib/underscore.string.js"></script>
|
||||
@@ -101,31 +99,27 @@
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/model_field_selector.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/progress_bar.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/dropdown.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/dropdown_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/tooltip.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/debug_manager.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/control_panel.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/control_panel_layout.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/fields.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/fields_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/views.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/views_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/pivot_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/graph_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/tree_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/form_view_layout.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/form_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/list_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/new_views.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/search_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/modal.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/data_export.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/switch_company_menu.less"/>
|
||||
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/dropdown_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/views_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/form_view_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/form_view_layout_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/search_view_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/list_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/list_view_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/kanban_dashboard.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/kanban_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/web_calendar.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/search_view.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/search_view_extra.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/modal.less"/>
|
||||
<link rel="stylesheet" type="text/less" href="/web/static/src/less/data_export.less"/>
|
||||
|
||||
<script type="text/javascript" src="/web/static/lib/jquery.scrollTo/jquery.scrollTo.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/nvd3/d3.v3.js"></script>
|
||||
|
||||
@@ -216,7 +216,7 @@ var FieldTextHtml = AbstractField.extend({
|
||||
// init resize
|
||||
this.resize = function resize() {
|
||||
if (self.mode === 'edit') {
|
||||
if ($("body").hasClass("o_form_FieldTextHtml_fullscreen")) {
|
||||
if ($("body").hasClass("o_field_widgetTextHtml_fullscreen")) {
|
||||
self.$iframe.css('height', (document.body.clientHeight - self.$iframe.offset().top) + 'px');
|
||||
} else {
|
||||
self.$iframe.css("height", (self.$body.find("#oe_snippets").length ? 500 : 300) + "px");
|
||||
@@ -348,8 +348,8 @@ var FieldTextHtml = AbstractField.extend({
|
||||
$(QWeb.render('web_editor.FieldTextHtml.fullscreen'))
|
||||
.appendTo($to)
|
||||
.on('click', '.o_fullscreen', function () {
|
||||
$("body").toggleClass("o_form_FieldTextHtml_fullscreen");
|
||||
var full = $("body").hasClass("o_form_FieldTextHtml_fullscreen");
|
||||
$("body").toggleClass("o_field_widgetTextHtml_fullscreen");
|
||||
var full = $("body").hasClass("o_field_widgetTextHtml_fullscreen");
|
||||
self.$iframe.parents().toggleClass('o_form_fullscreen_ancestor', full);
|
||||
$(window).trigger("resize"); // induce a resize() call and let other backend elements know (the navbar extra items management relies on this)
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
min-height: -webkit-calc(100vh - 170px);
|
||||
min-height: calc(100vh - 170px);
|
||||
}
|
||||
.o_form_FieldTextHtml_fullscreen {
|
||||
.o_field_widgetTextHtml_fullscreen {
|
||||
.oe_form_field_html.o_form_fullscreen_ancestor iframe {
|
||||
position: absolute !important;
|
||||
left: 0 !important;
|
||||
|
||||
@@ -155,9 +155,6 @@ var RunningTourActionHelper = core.Class.extend({
|
||||
values.$element.text(text);
|
||||
}
|
||||
values.$element.trigger("change");
|
||||
if (values.$element.is('.o_field_widget.o_form_input.o_form_field')) {
|
||||
values.$element.focusout();
|
||||
}
|
||||
},
|
||||
_drag_and_drop: function (values, to) {
|
||||
var $to = $(to || document.body);
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
<button type="button" class="fa fa-bars pull-right visible-xs-block o_mobile_menu_toggle"/>
|
||||
|
||||
<div class="o_menu_brand">Website</div>
|
||||
|
||||
<ul class="o_menu_sections" groups="website.group_website_designer">
|
||||
<!-- Content -->
|
||||
<li class="dropdown content" t-if="editable">
|
||||
|
||||
@@ -19,47 +19,47 @@ odoo.define('web.test.x2many', function (require) {
|
||||
trigger: 'button.o_list_button_add',
|
||||
}, {
|
||||
content: "insert content",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
run: 'text test',
|
||||
}, { // try to add a user with one2many form
|
||||
content: "click on moderator one2many drop down",
|
||||
trigger: 'tr:contains(Moderator) .o_form_input_dropdown > input',
|
||||
trigger: 'tr:contains(Moderator) .o_input_dropdown > input',
|
||||
run: 'click',
|
||||
}, {
|
||||
content: "click on 'Create and Edit...'",
|
||||
trigger: '.ui-autocomplete .o_m2o_dropdown_option:last',
|
||||
}, {
|
||||
content: "insert a name into the modal form",
|
||||
trigger: 'input.o_form_field.o_form_required:first',
|
||||
trigger: 'input.o_field_widget.o_required_modifier:first',
|
||||
extra_trigger: '.modal:visible',
|
||||
run: function (action_helper) {
|
||||
action_helper.text('user_test_' + (inc = new Date().getTime()));
|
||||
}
|
||||
}, {
|
||||
content: "insert an email into the modal form",
|
||||
extra_trigger: 'input.o_form_field.o_form_required:propValueContains(user_test)',
|
||||
trigger: 'input.o_form_field.o_form_required:eq(1)',
|
||||
extra_trigger: 'input.o_field_widget.o_required_modifier:propValueContains(user_test)',
|
||||
trigger: 'input.o_field_widget.o_required_modifier:eq(1)',
|
||||
run: function (action_helper) {
|
||||
action_helper.text('user_test_' + inc + '@test');
|
||||
}
|
||||
}, {
|
||||
content: "save the modal content and create the new moderator",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: 'input.o_form_field.o_form_required:propValueContains(@test)',
|
||||
extra_trigger: 'input.o_field_widget.o_required_modifier:propValueContains(@test)',
|
||||
}, {
|
||||
content: "check if the modal is saved",
|
||||
trigger: 'tr:contains(Moderator) .o_form_field_many2one input:propValueContains(user_test)',
|
||||
trigger: 'tr:contains(Moderator) .o_field_many2one input:propValueContains(user_test)',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check the onchange from the o2m to the m2m",
|
||||
trigger: '.o_content:has(.tab-pane:eq(2) .o_form_field tbody tr td:contains(user_test))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(2) .o_field_widget tbody tr td:contains(user_test))',
|
||||
run: function () {}, // it's a check
|
||||
}, { // add ourself as participant
|
||||
content: "change tab to Participants",
|
||||
trigger: '[data-toggle="tab"]:contains(Participants)'
|
||||
}, {
|
||||
content: "click to add participants",
|
||||
trigger: '.tab-pane:eq(2).active .o_form_field_x2many_list_row_add a'
|
||||
trigger: '.tab-pane:eq(2).active .o_field_x2many_list_row_add a'
|
||||
}, {
|
||||
content: "select Admin",
|
||||
trigger: 'tr:has(td:containsExact(Administrator)) .o_list_record_selector input[type="checkbox"]'
|
||||
@@ -70,7 +70,7 @@ odoo.define('web.test.x2many', function (require) {
|
||||
}, { // save
|
||||
content: "save discussion",
|
||||
trigger: 'button.o_form_button_save',
|
||||
extra_trigger: '.tab-pane:eq(2) .o_form_field tbody tr:has(td:containsExact(Administrator))',
|
||||
extra_trigger: '.tab-pane:eq(2) .o_field_widget tbody tr:has(td:containsExact(Administrator))',
|
||||
}, { // edit
|
||||
content: "edit discussion",
|
||||
trigger: 'button.o_form_button_edit',
|
||||
@@ -79,71 +79,71 @@ odoo.define('web.test.x2many', function (require) {
|
||||
trigger: 'a[role=tab]:first',
|
||||
}, {
|
||||
content: "create new message a",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a'
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a'
|
||||
}, {
|
||||
content: "insert body a",
|
||||
trigger: '.modal-body .o_form_textarea textarea:first',
|
||||
trigger: '.modal-body textarea:first',
|
||||
run: 'text a',
|
||||
}, {
|
||||
content: "save new message a",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.modal-body .o_form_textarea textarea:first:propValue(a)',
|
||||
extra_trigger: '.modal-body textarea:first:propValue(a)',
|
||||
}, { // add message b
|
||||
content: "create new message b",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a',
|
||||
extra_trigger: '.o_web_client:has(.o_form_textarea[name="message_concat"] textarea:propValue([test] Administrator:a))',
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a',
|
||||
extra_trigger: '.o_web_client:has(textarea[name="message_concat"]:propValue([test] Administrator:a))',
|
||||
}, {
|
||||
content: "insert body b",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text b',
|
||||
}, {
|
||||
content: "save new message b",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(b)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(b)',
|
||||
}, { // change content to trigger on change
|
||||
content: "insert content",
|
||||
trigger: 'input.o_form_required',
|
||||
extra_trigger: '.o_form_textarea[name="message_concat"] textarea:first:propValue([test] Administrator:a\n[test] Administrator:b)',
|
||||
trigger: 'input.o_required_modifier',
|
||||
extra_trigger: 'textarea[name="message_concat"]:first:propValue([test] Administrator:a\n[test] Administrator:b)',
|
||||
run: 'text test_trigger',
|
||||
}, {
|
||||
content: "blur the content field",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
run: 'text test_trigger',
|
||||
}, {
|
||||
content: "check onchange",
|
||||
trigger: '.o_form_textarea[name="message_concat"] textarea:first:propValue([test_trigger] Administrator:a\n[test_trigger] Administrator:b)',
|
||||
trigger: 'textarea[name="message_concat"]:first:propValue([test_trigger] Administrator:a\n[test_trigger] Administrator:b)',
|
||||
run: function () {},
|
||||
}, { // change message b
|
||||
content: "edit message b",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:containsExact(b)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2))) .tab-pane:eq(0) .o_form_field tbody tr td:contains([test_trigger] )',
|
||||
trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:containsExact(b)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2))) .tab-pane:eq(0) .o_field_widget tbody tr td:contains([test_trigger] )',
|
||||
}, {
|
||||
content: "change the body",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text bbb',
|
||||
}, {
|
||||
content: "save changes",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(bbb)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(bbb)',
|
||||
}, { // add message c
|
||||
content: "create new message c",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a',
|
||||
extra_trigger: '.o_form_textarea[name="message_concat"] textarea:propValue([test_trigger] Administrator:a\n[test_trigger] Administrator:bbb)',
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a',
|
||||
extra_trigger: 'textarea[name="message_concat"]:propValue([test_trigger] Administrator:a\n[test_trigger] Administrator:bbb)',
|
||||
}, {
|
||||
content: "insert body",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text c',
|
||||
}, {
|
||||
content: "save new message c",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(c)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(c)',
|
||||
}, { // add participants
|
||||
content: "change tab to Participants",
|
||||
trigger: '[data-toggle="tab"]:contains(Participants)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
}, {
|
||||
content: "click to add participants",
|
||||
trigger: '.tab-pane:eq(2).active .o_form_field_x2many_list_row_add a',
|
||||
trigger: '.tab-pane:eq(2).active .o_field_x2many_list_row_add a',
|
||||
}, {
|
||||
content: "select Demo User",
|
||||
trigger: 'tr:has(td:containsExact(Demo User)) .o_list_record_selector input[type="checkbox"]',
|
||||
@@ -154,20 +154,20 @@ odoo.define('web.test.x2many', function (require) {
|
||||
}, { // save
|
||||
content: "save discussion",
|
||||
trigger: 'button.o_form_button_save',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(2) .o_form_field tbody .o_data_row:eq(3))) .tab-pane:eq(2) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(2) .o_field_widget tbody .o_data_row:eq(3))) .tab-pane:eq(2) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
}, { // check saved data
|
||||
content: "check data 1",
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2))',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(3)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2))',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(3)))',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check data 2",
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_form_field tr:has(td:containsExact(bbb)):has(td:containsExact([test_trigger] Administrator)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_field_widget tr:has(td:containsExact(bbb)):has(td:containsExact([test_trigger] Administrator)))',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check data 3",
|
||||
trigger: '.o_content:has(.tab-pane:eq(2) .o_form_field tbody .o_data_row:eq(2))',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(2) .o_form_field tbody .o_data_row:eq(3)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(2) .o_field_widget tbody .o_data_row:eq(2))',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(2) .o_field_widget tbody .o_data_row:eq(3)))',
|
||||
run: function () {}, // it's a check
|
||||
}, { // edit
|
||||
content: "edit discussion",
|
||||
@@ -178,47 +178,47 @@ odoo.define('web.test.x2many', function (require) {
|
||||
extra_trigger: '.o_form_editable',
|
||||
}, { // add message d
|
||||
content: "create new message d",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a',
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a',
|
||||
extra_trigger: 'li.active a[data-toggle="tab"]:contains(Messages)',
|
||||
}, {
|
||||
content: "insert body",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text d',
|
||||
}, {
|
||||
content: "save new message d",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(d)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(d)',
|
||||
}, { // add message e
|
||||
content: "create new message e",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:containsExact(d)',
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:containsExact(d)',
|
||||
}, {
|
||||
content: "insert body",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text e',
|
||||
}, {
|
||||
content: "save new message e",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(e)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(e)',
|
||||
}, { // change message a
|
||||
content: "edit message a",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:containsExact(a)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:containsExact(e)',
|
||||
trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:containsExact(a)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:containsExact(e)',
|
||||
}, {
|
||||
content: "change the body",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text aaa',
|
||||
}, {
|
||||
content: "save changes",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(aaa)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(aaa)',
|
||||
}, { // change message e
|
||||
content: "edit message e",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:containsExact(e)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:contains(aaa)',
|
||||
trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:containsExact(e)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:contains(aaa)',
|
||||
}, {
|
||||
content: "open the many2one to select another user",
|
||||
trigger: '.o_form_input_dropdown > input',
|
||||
trigger: '.o_input_dropdown > input',
|
||||
run: 'text Demo',
|
||||
}, {
|
||||
content: "select another user",
|
||||
@@ -226,11 +226,11 @@ odoo.define('web.test.x2many', function (require) {
|
||||
in_modal: false,
|
||||
}, {
|
||||
content: "test one2many's line onchange after many2one",
|
||||
trigger: '.o_form_field:contains([test_trigger] Demo User)',
|
||||
trigger: '.o_field_widget:contains([test_trigger] Demo User)',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "test one2many field not triggered onchange",
|
||||
trigger: '.o_form_textarea[name="message_concat"] textarea:first:propValueContains([test_trigger] Administrator:e)',
|
||||
trigger: 'textarea[name="message_concat"]:first:propValueContains([test_trigger] Administrator:e)',
|
||||
in_modal: false,
|
||||
run: function () {}, // don't change texarea content
|
||||
}, {
|
||||
@@ -238,16 +238,16 @@ odoo.define('web.test.x2many', function (require) {
|
||||
trigger: '.modal-footer button:contains(Save):contains(Close)'
|
||||
}, {
|
||||
content: "test one2many triggered the onchange on save for the line",
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_form_field tbody tr td.o_readonly:contains([test_trigger] Demo User))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_field_widget tbody tr td.o_readonly_modifier:contains([test_trigger] Demo User))',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "test one2many triggered the onchange on save",
|
||||
trigger: '.o_form_textarea[name="message_concat"] textarea:first:propValueContains([test_trigger] Demo User:e)',
|
||||
trigger: 'textarea[name="message_concat"]:first:propValueContains([test_trigger] Demo User:e)',
|
||||
run: function () {}, // don't change texarea content
|
||||
}, { // remove
|
||||
content: "remove b",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field tbody tr:has(td:containsExact(bbb)) .o_list_record_delete',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody tr td:containsExact(aaa)',
|
||||
trigger: '.tab-pane:eq(0) .o_field_widget tbody tr:has(td:containsExact(bbb)) .o_list_record_delete',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody tr td:containsExact(aaa)',
|
||||
}, {
|
||||
content: "remove e",
|
||||
trigger: 'tr:has(td:containsExact(e)) .o_list_record_delete',
|
||||
@@ -258,32 +258,32 @@ odoo.define('web.test.x2many', function (require) {
|
||||
extra_trigger: 'body:not(:has(tr:has(td:containsExact(e))))',
|
||||
}, { // check saved data
|
||||
content: "check data 4",
|
||||
trigger: '.o_content:not(:has(.tab-pane:eq(0) .o_form_field tbody tr:has(.o_list_record_delete):eq(4)))',
|
||||
trigger: '.o_content:not(:has(.tab-pane:eq(0) .o_field_widget tbody tr:has(.o_list_record_delete):eq(4)))',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check data 5",
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_form_field tbody:has(tr td:containsExact(aaa)):has(tr td:containsExact(c)):has(tr td:containsExact(d)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_field_widget tbody:has(tr td:containsExact(aaa)):has(tr td:containsExact(c)):has(tr td:containsExact(d)))',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check data 6",
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_form_field tbody tr:has(td:containsExact([test_trigger] Administrator)):has(td:containsExact(aaa)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_field_widget tbody tr:has(td:containsExact([test_trigger] Administrator)):has(td:containsExact(aaa)))',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check data 7",
|
||||
trigger: '.o_content:has(.tab-pane:eq(2) .o_form_field tbody .o_data_row:eq(2))',
|
||||
extra_trigger: '.o_content:not(:has(.tab-pane:eq(2) .o_form_field tbody tr[date-id]:eq(3)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(2) .o_field_widget tbody .o_data_row:eq(2))',
|
||||
extra_trigger: '.o_content:not(:has(.tab-pane:eq(2) .o_field_widget tbody tr[date-id]:eq(3)))',
|
||||
run: function () {}, // it's a check
|
||||
}, { // edit
|
||||
content: "edit discussion",
|
||||
trigger: 'button.o_form_button_edit',
|
||||
}, { // add message ddd
|
||||
content: "create new message ddd",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody tr:has(td:containsExact(d))',
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody tr:has(td:containsExact(d))',
|
||||
}, {
|
||||
content: "select another user",
|
||||
trigger: '.o_form_field_many2one .o_form_input_dropdown > input',
|
||||
extra_trigger: 'body:has(.modal) .tab-pane:eq(0) .o_form_field tbody tr:has(td:containsExact(d))',
|
||||
trigger: '.o_field_many2one .o_input_dropdown > input',
|
||||
extra_trigger: 'body:has(.modal) .tab-pane:eq(0) .o_field_widget tbody tr:has(td:containsExact(d))',
|
||||
run: 'text Demo',
|
||||
}, {
|
||||
content: "select demo user",
|
||||
@@ -291,33 +291,33 @@ odoo.define('web.test.x2many', function (require) {
|
||||
in_modal: false,
|
||||
}, {
|
||||
content: "test one2many's line onchange after many2one",
|
||||
trigger: '.o_form_field:contains([test_trigger] Demo User)',
|
||||
trigger: '.o_field_widget:contains([test_trigger] Demo User)',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "insert body",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text ddd',
|
||||
}, {
|
||||
content: "save new message ddd",
|
||||
trigger: '.modal-footer button:contains(Save):first',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValue(ddd)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValue(ddd)',
|
||||
}, { // trigger onchange
|
||||
content: "blur the one2many",
|
||||
trigger: 'input.o_form_required',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody:has(tr td:containsExact(ddd))',
|
||||
trigger: 'input.o_required_modifier',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody:has(tr td:containsExact(ddd))',
|
||||
}, { // check onchange data
|
||||
content: "check data 8",
|
||||
trigger: '.o_form_textarea[name="message_concat"] textarea:propValueContains([test_trigger] Administrator:aaa\n[test_trigger] Administrator:c\n[test_trigger] Administrator:d\n[test_trigger] Demo User:ddd)',
|
||||
trigger: 'textarea[name="message_concat"]:propValueContains([test_trigger] Administrator:aaa\n[test_trigger] Administrator:c\n[test_trigger] Administrator:d\n[test_trigger] Demo User:ddd)',
|
||||
run: function () {}, // don't change texarea content
|
||||
}, {
|
||||
content: "check data 9",
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(3))',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(4)))',
|
||||
trigger: '.o_content:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(3))',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(4)))',
|
||||
run: function () {}, // it's a check
|
||||
}, { // cancel
|
||||
content: "cancel change",
|
||||
trigger: '.o_cp_buttons .o_form_button_cancel',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody:has(tr td:containsExact(ddd))',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody:has(tr td:containsExact(ddd))',
|
||||
run: 'click',
|
||||
}, {
|
||||
content: "confirm cancel change",
|
||||
@@ -331,12 +331,12 @@ odoo.define('web.test.x2many', function (require) {
|
||||
{
|
||||
content: "switch to the second form view to test one2many with editable list (toggle menu dropdown)",
|
||||
trigger: '.o_sub_menu .oe_secondary_submenu .oe_menu_leaf .oe_menu_text:containsExact(Discussions)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
edition: 'community'
|
||||
}, {
|
||||
content: "switch to the second form view to test one2many with editable list (toggle menu dropdown)",
|
||||
trigger: 'nav .o_menu_sections li a:containsExact(Discussions)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
edition: 'enterprise'
|
||||
}, {
|
||||
content: "switch to the second form view to test one2many with editable list (open submenu)",
|
||||
@@ -355,7 +355,7 @@ odoo.define('web.test.x2many', function (require) {
|
||||
trigger: '.o_cp_buttons .o_form_button_edit',
|
||||
}, {
|
||||
content: "edit content",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
extra_trigger: ".o_form_editable",
|
||||
run: 'text test_trigger2'
|
||||
}, {
|
||||
@@ -367,11 +367,11 @@ odoo.define('web.test.x2many', function (require) {
|
||||
extra_trigger: '.o_list_view:contains(test_trigger2)',
|
||||
}, {
|
||||
content: "change text value",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text ccc'
|
||||
}, {
|
||||
content: "click on other field (trigger the line onchange)",
|
||||
trigger: '.o_list_view .o_form_field_many2one[name="author"] input',
|
||||
trigger: '.o_list_view .o_field_many2one[name="author"] input',
|
||||
run: 'click'
|
||||
}, {
|
||||
content: "test one2many's line onchange",
|
||||
@@ -379,7 +379,7 @@ odoo.define('web.test.x2many', function (require) {
|
||||
run: function () {}, // don't blur the many2one
|
||||
}, {
|
||||
content: "open the many2one to select an other user",
|
||||
trigger: '.o_list_view .o_form_field_many2one[name="author"] .o_form_input_dropdown > input',
|
||||
trigger: '.o_list_view .o_field_many2one[name="author"] .o_input_dropdown > input',
|
||||
run: 'text Demo',
|
||||
}, {
|
||||
content: "select an other user",
|
||||
@@ -390,19 +390,19 @@ odoo.define('web.test.x2many', function (require) {
|
||||
run: function () {}, // don't blur the many2one
|
||||
}, {
|
||||
content: "change text value",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text ccccc',
|
||||
}, { // check onchange
|
||||
content: "click outside to trigger one2many onchange",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
run: 'click'
|
||||
}, {
|
||||
content: "test one2many onchange",
|
||||
trigger: '.o_form_textarea[name="message_concat"] textarea:first:propValueContains([test_trigger2] Demo User:ccccc)',
|
||||
trigger: 'textarea[name="message_concat"]:first:propValueContains([test_trigger2] Demo User:ccccc)',
|
||||
run: function () {}, // don't change texarea content
|
||||
}, {
|
||||
content: "click outside to trigger one2many onchange",
|
||||
trigger: '.o_form_field_many2manytags .o_form_input_dropdown > input',
|
||||
trigger: '.o_field_many2manytags .o_input_dropdown > input',
|
||||
}, {
|
||||
content: "add a tag",
|
||||
trigger: '.ui-autocomplete a:first',
|
||||
@@ -419,36 +419,36 @@ odoo.define('web.test.x2many', function (require) {
|
||||
extra_trigger: 'body:not(:has(tr:has(td:containsExact(d))))',
|
||||
}, { // check saved data
|
||||
content: "check data 10",
|
||||
trigger: '.o_form_textarea:containsExact([test_trigger2] Administrator:aaa\n[test_trigger2] Demo User:ccccc)',
|
||||
trigger: '.o_field_text:containsExact([test_trigger2] Administrator:aaa\n[test_trigger2] Demo User:ccccc)',
|
||||
run: function () {}, // don't change texarea content
|
||||
}, {
|
||||
content: "check data 11",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(1)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)))',
|
||||
trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(1)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)))',
|
||||
run: function () {},
|
||||
}, { // edit
|
||||
content: "edit discussion",
|
||||
trigger: 'button.o_form_button_edit'
|
||||
}, { // add message eee
|
||||
content: "create new message eee",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field_x2many_list_row_add a',
|
||||
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a',
|
||||
extra_trigger: 'li.active a[data-toggle="tab"]:contains(Messages)',
|
||||
}, {
|
||||
content: "change text value",
|
||||
trigger: '.o_form_textarea[name="body"] textarea:first',
|
||||
trigger: 'textarea[name="body"]:first',
|
||||
run: 'text eee'
|
||||
}, { // save
|
||||
content: "save discussion",
|
||||
trigger: 'button.o_form_button_save',
|
||||
extra_trigger: '.o_form_textarea[name="body"] textarea:first:propValueContains(eee)',
|
||||
extra_trigger: 'textarea[name="body"]:first:propValueContains(eee)',
|
||||
}, { // check saved data
|
||||
content: "check data 12",
|
||||
trigger: '.o_form_textarea[name="message_concat"]:containsExact([test_trigger2] Administrator:aaa\n[test_trigger2] Demo User:ccccc\n[test_trigger2] Administrator:eee)',
|
||||
trigger: '.o_field_text[name="message_concat"]:containsExact([test_trigger2] Administrator:aaa\n[test_trigger2] Demo User:ccccc\n[test_trigger2] Administrator:eee)',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check data 13",
|
||||
trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(3)))',
|
||||
trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
extra_trigger: 'body:not(:has(.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(3)))',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
|
||||
@@ -459,12 +459,12 @@ odoo.define('web.test.x2many', function (require) {
|
||||
{
|
||||
content: "switch to the third form view to test onchange changing one2many (toggle menu dropdown)",
|
||||
trigger: '.o_sub_menu .oe_secondary_submenu .oe_menu_leaf .oe_menu_text:containsExact(Discussions)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
edition: 'community'
|
||||
}, {
|
||||
content: "switch to the third form view to test onchange changing one2many (toggle menu dropdown)",
|
||||
trigger: 'nav .o_menu_sections li a:containsExact(Discussions)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_form_field tbody .o_data_row:eq(2)',
|
||||
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
|
||||
edition: 'enterprise'
|
||||
}, {
|
||||
content: "switch to the thied form view to test onchange changing one2many (open submenu)",
|
||||
@@ -482,33 +482,33 @@ odoo.define('web.test.x2many', function (require) {
|
||||
trigger: 'button.o_list_button_add',
|
||||
}, {
|
||||
content: "set discussion title to generate dummy message",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
run: 'text {generate_dummy_message}',
|
||||
}, {
|
||||
content: "check new dummy message happened",
|
||||
trigger: '.o_form_field[name=messages] .o_data_row .o_list_number:containsExact(13)',
|
||||
extra_trigger: '.o_form_field[name=important_messages] .o_data_row .o_list_number:containsExact(13)',
|
||||
trigger: '.o_field_widget[name=messages] .o_data_row .o_list_number:containsExact(13)',
|
||||
extra_trigger: '.o_field_widget[name=important_messages] .o_data_row .o_list_number:containsExact(13)',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check field not in embedded view received correctly",
|
||||
trigger: '.o_form_field[name=messages] .o_data_row input[type="checkbox"]:propChecked',
|
||||
trigger: '.o_field_widget[name=messages] .o_data_row input[type="checkbox"]:propChecked',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "empty discussion title",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
run: 'text removed_title',
|
||||
}, {
|
||||
content: "onchange happened",
|
||||
trigger: '.o_form_field[name=messages] .o_data_row td:contains([removed_title])',
|
||||
trigger: '.o_field_widget[name=messages] .o_data_row td:contains([removed_title])',
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "set discussion title to generate dummy message",
|
||||
trigger: 'input.o_form_required',
|
||||
trigger: 'input.o_required_modifier',
|
||||
run: 'text {generate_dummy_message}',
|
||||
}, {
|
||||
content: "chuck update and new dummy message happened",
|
||||
trigger: '.o_form_field[name=messages] .o_data_row .o_list_number:containsExact(22)',
|
||||
extra_trigger: '.o_form_field[name=important_messages] .o_data_row .o_list_number:containsExact(22)',
|
||||
trigger: '.o_field_widget[name=messages] .o_data_row .o_list_number:containsExact(22)',
|
||||
extra_trigger: '.o_field_widget[name=important_messages] .o_data_row .o_list_number:containsExact(22)',
|
||||
run: function () {}, // it's a check
|
||||
}, { // cancel
|
||||
content: "cancel change",
|
||||
|
||||
Reference in New Issue
Block a user