[MERGE] new kanban view

This branch introduces the new kanban view.  It is not completely
compatible with the previous version.  Here are a few importants
points to be aware of:
* the kanban view template is rendered directly, not put inside a div.
  It means that if a template has more than one root, chaos will ensue
* kanban view has been split into several files, and various js modules
  have changed.  For example, the KanbanRecord class is now exported by
  the 'web_kanban.Record' module.  So, require statements need to be
  updated
* records do not have access to the view (i.e., record.view.is_action_enabled('edit'))
  You can use the 'editable' and 'deletable' key instead
This commit is contained in:
Géry Debongnie
2015-06-15 16:31:27 +02:00
123 changed files with 3469 additions and 2393 deletions
@@ -1,9 +1,9 @@
odoo.define('journal_dashboard', function (require) {
'use strict';
var kanban_common = require('web_kanban.common');
var kanban_widgets = require('web_kanban.widgets');
var JournalDashboardGraph = kanban_common.AbstractField.extend({
var JournalDashboardGraph = kanban_widgets.AbstractField.extend({
start: function() {
var self = this;
self.graph_type = self.$node.attr('graph_type')
@@ -86,6 +86,6 @@ var JournalDashboardGraph = kanban_common.AbstractField.extend({
});
kanban_common.registry.add('dashboard_graph', JournalDashboardGraph);
kanban_widgets.registry.add('dashboard_graph', JournalDashboardGraph);
});
@@ -194,7 +194,7 @@
<a type="object" name="toggle_favorite"><i t-att-class="(record.show_on_dashboard.raw_value ? 'oe_star_on' : 'oe_star_off') + ' fa fa-star o_dashboard_star'" title="Click to add/remove from favorite"></i></a>
</div>
<div class="col-xs-6 text-right">
<a t-if="widget.view.is_action_enabled('edit')" type="edit">Settings</a>
<a t-if="widget.editable" type="edit">Settings</a>
</div>
</div>
</t>
@@ -79,12 +79,13 @@
<field name="state" widget="statusbar" statusbar_visible="posted,reconciled"/>
</header>
<sheet>
<div class="oe_right oe_button_box">
<button class="oe_inline oe_stat_button" name="button_journal_entries"
string="Journal Items" type="object" groups="account.group_account_manager"
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="button_journal_entries"
string="Journal Items" type="object"
groups="account.group_account_manager"
attrs="{'invisible':[('move_line_ids','=',[])]}" icon="fa-bars"/>
<field name="move_line_ids" invisible="1"/>
<button class="oe_inline oe_stat_button" name="button_invoices"
<button class="oe_stat_button" name="button_invoices"
string="Invoices" type="object"
attrs="{'invisible':[('has_invoices','=',False)]}" icon="fa-bars"/>
<field name="has_invoices" invisible="1"/>
+2 -2
View File
@@ -442,8 +442,8 @@
<field name="state" widget="statusbar" statusbar_visible="open,confirm"/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="import_buttons">
<button class="oe_inline oe_stat_button" name="button_journal_entries"
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="button_journal_entries"
string="Journal Items" type="object"
attrs="{'invisible':[('move_line_ids','=',[])]}" icon="fa-bars"/>
<field name="move_line_ids" invisible="1"/>
+22 -19
View File
@@ -77,7 +77,7 @@
<field name="priority" eval="20"/>
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<div name="button_box" position="inside">
<button type="action"
class="oe_stat_button"
id="invoice_button"
@@ -85,10 +85,13 @@
name="%(account.action_invoice_refund_out_tree)d"
attrs="{'invisible': [('customer', '=', False)]}"
context="{'search_default_partner_id': active_id,'default_partner_id': active_id}">
<div><strong><field name="total_invoiced"/></strong><br/>Invoiced</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_value"><field name="total_invoiced"/></span>
<span class="o_stat_text">Invoiced</span>
</div>
</button>
<field name="currency_id" invisible="1"/>
</xpath>
</div>
</field>
</record>
@@ -99,12 +102,12 @@
<field name="priority" eval="22"/>
<field name="groups_id" eval="[(4, ref('analytic.group_analytic_accounting'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action" name="%(account.action_open_partner_analytic_accounts)d"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(account.action_open_partner_analytic_accounts)d"
icon="fa-book">
<field string="Contracts" name="contracts_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
@@ -132,10 +135,10 @@
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
<field name="arch" type="xml">
<page name="sales_purchases" position="after">
<page string="Accounting" col="4" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<page string="Accounting" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<group>
<group string="Sale" name="acc_sale">
<button name="%(action_account_partner_followup_note)d" type="action" string="Log a followup note"/><br />
<button name="%(action_account_partner_followup_note)d" class="oe_link" type="action" string="Log a followup note" colspan="2"/>
<field name="property_payment_term" widget="selection"/>
<field name="credit"/>
<field name="credit_limit"/>
@@ -154,16 +157,16 @@
</group>
</group>
<group string="Bank Accounts" name="bank_accounts">
<field name="bank_ids" context="{'default_partner_id': active_id, 'form_view_ref': 'base.view_partner_bank_form'}" nolabel="1">
<tree string="Bank Details">
<field name="state" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="acc_number"/>
<field name="bank_name"/>
<field name="owner_name"/>
</tree>
</field>
</group>
<field name="bank_ids" context="{'default_partner_id': active_id, 'form_view_ref': 'base.view_partner_bank_form'}" nolabel="1">
<tree string="Bank Details">
<field name="state" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="acc_number"/>
<field name="bank_name"/>
<field name="owner_name"/>
</tree>
</field>
</group>
</page>
<page string="Accounting" name="accounting_disabled" attrs="{'invisible': ['|',('is_company','=',True),('parent_id','=',False)]}">
<div>
@@ -174,4 +177,4 @@
</field>
</record>
</data>
</openerp>
</openerp>
@@ -374,18 +374,18 @@
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
<field eval="20" name="priority"/>
<field name="arch" type="xml">
<xpath expr='//div[@name="buttons"]' position='inside'>
<button class="oe_inline oe_stat_button"
<div name="button_box" position='inside'>
<button class="oe_stat_button"
string="To invoice"
icon="fa-money"
name="%(action_hr_tree_invoiced_all)d"
type="action"
context="{'search_default_account_id': [active_id], 'default_account_id': active_id}"/>
<button class="oe_inline oe_stat_button" string="Invoices"
<button class="oe_stat_button" string="Invoices"
icon="fa-book"
name="%(action_contract_invoices_all)d"
type="action"/>
</xpath>
</div>
</field>
</record>
@@ -79,12 +79,12 @@
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name= "%(action_product_default_list)d" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button" name= "%(action_product_default_list)d" type="action"
groups="analytic.group_analytic_accounting" icon="fa-xing">
<field string="Analytic Rules" name="rules_count" widget="statinfo" />
</button>
</xpath>
</div>
</field>
</record>
@@ -93,12 +93,12 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name= "action_view_rules" type="object"
<div name="button_box" position="inside">
<button class="oe_stat_button" name= "action_view_rules" type="object"
groups="analytic.group_analytic_accounting" icon="fa-xing">
<field string="Analytic Rules" name="rules_count" widget="statinfo" />
</button>
</xpath>
</div>
</field>
</record>
@@ -99,10 +99,10 @@
<field name="state" widget="statusbar" statusbar_visible="draft,open"/>
</header>
<sheet>
<div class="oe_button_box oe_right">
<button class="oe_inline oe_stat_button" name="open_entries" type="object" icon="fa-pencil">
<field string="Entries" name="entry_count" widget="statinfo" />
</button>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="open_entries" type="object" icon="fa-pencil">
<field string="Entries" name="entry_count" widget="statinfo" />
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
+1 -2
View File
@@ -8,8 +8,7 @@
<field name="arch" type="xml">
<form string="Analytic Account" version="7.0">
<sheet string="Analytic Account">
<div class="oe_right oe_button_box" name="buttons">
</div>
<div class="oe_button_box" name="button_box"/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
+1 -1
View File
@@ -24,7 +24,7 @@
</div>
</xpath>
<!-- add Reset Password button -->
<xpath expr="//div[@class='oe_right oe_button_box']//button" position="replace">
<xpath expr="//div[@name='button_box']//button" position="replace">
<button string="Send Reset Password Instructions"
class="oe_link"
type="object" name="action_reset_password"
+1 -1
View File
@@ -8,7 +8,7 @@
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@class='oe_kanban_partner_categories']" position="inside">
<xpath expr="//div[contains(@class, 'oe_kanban_partner_categories')]" position="inside">
<span class="oe_kanban_list_many2many">
<field name="category_id"/>
</span>
+23 -34
View File
@@ -121,8 +121,8 @@
on_change="onchange_stage_id(stage_id)"/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="buttons">
<button class="oe_inline oe_stat_button" type="action"
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="action"
context="{'default_opportunity_id': active_id, 'search_default_opportunity_id': active_id, 'default_partner_id': partner_id, 'default_duration': 1.0}"
name="%(crm.crm_phonecall_category_phone_incoming0)d" icon="fa-phone">
<field string="Calls" name="calls_count" widget="statinfo"/>
@@ -284,7 +284,7 @@
</field>
</record>
<!-- CRM Lead Kanban View -->
<!-- CRM Lead Kanban View -->
<record model="ir.ui.view" id="crm_case_kanban_view_leads">
<field name="name">CRM - Leads Kanban</field>
<field name="model">crm.lead</field>
@@ -300,15 +300,19 @@
<field name="message_summary"/>
<field name="message_unread"/>
<field name="tag_ids"/>
<field name="partner_id"/>
<templates>
<field name="date_deadline"/>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click">
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Edit Opportunity</a></li></t>
<t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
<div t-attf-class="#{kanban_color(record.color.raw_value)} o_kanban_small oe_kanban_global_click">
<div class="o_dropdown_kanban dropdown">
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable"><li><a type="edit">Edit Opportunity</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><a name="%(mail.action_email_compose_message_wizard)d" type="action" >Send Email</a></li>
<li><a type="action" name="%(crm.crm_phonecall_category_phone_incoming0)d">Calls</a></li>
<li><a name="action_schedule_meeting" type="object">Schedule Meeting</a></li>
@@ -317,32 +321,17 @@
</div>
<div class="oe_kanban_content">
<div>
<strong><field name="name"/></strong>
<t t-if="record.planned_revenue.raw_value">
- <b><t t-esc="record.planned_revenue.value"/>
<field name="company_currency"/></b>
</t>
</div>
<div>
<field name="partner_id"/>
</div>
<div class="oe_deadline">
<t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())" t-set="red">oe_kanban_text_red</t>
<span t-attf-class="#{red || ''}"><field name="date_action"/></span>
<t t-if="record.date_action.raw_value"> : </t>
<field name="title_action"/>
</div>
<div class="oe_kanban_footer_left">
<field name="tag_ids"/>
</div>
<div class="oe_kanban_bottom_left">
<t t-raw="record.message_summary.raw_value"/>
<div>
<strong><field name="name"/></strong>
</div>
<div class="oe_kanban_bottom_right">
<div class="text-muted">
<span t-if="record.planned_revenue.raw_value"><t t-esc="record.planned_revenue.value"/><field name="company_currency"/></span> <span t-if="record.partner_id.value"> - <t t-esc="record.partner_id.value"/></span>
</div>
<div class="o_kanban_footer">
<field name="priority" widget="priority" groups="base.group_user"/> <t t-raw="record.message_summary.raw_value"/>
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar pull-right"/>
<div class="pull-left" groups="base.group_user">
<field name="priority" widget="priority"/>
</div>
</div>
</div>
<div class="oe_clear"></div>
@@ -417,13 +406,13 @@
domain="['&amp;', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"/>
</header>
<sheet>
<div name="buttons" class="oe_right oe_button_box">
<button class="oe_inline oe_stat_button" type="action"
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="action"
name="%(crm.crm_phonecall_category_phone_incoming0)d" icon="fa-phone"
context="{'default_opportunity_id': active_id, 'search_default_opportunity_id': active_id, 'default_partner_id': partner_id, 'default_duration': 1.0}">
<field string="Calls" name="calls_count" widget="statinfo"/>
</button>
<button class="oe_inline oe_stat_button" type="object"
<button class="oe_stat_button" type="object"
context="{'partner_id': partner_id}"
name="action_schedule_meeting" icon="fa-calendar">
<field string="Meetings" name="meeting_count" widget="statinfo"/>
+16 -7
View File
@@ -87,19 +87,28 @@
<field name="state" nolabel="1" widget="statusbar" clickable="True"/>
</header>
<sheet string="Phone Call">
<div class="oe_right oe_button_box">
<button class="oe_inline oe_stat_button" type="object" name="action_button_convert2opportunity"
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="action_button_convert2opportunity"
icon="fa-star" attrs="{'invisible':[ '|', ('opportunity_id','!=',False), ('state', 'not in', ('open', 'done'))]}"
help="Convert To Opportunity">
<div>Convert To<br/>Opportunity</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Convert To</span>
<span class="o_stat_text">Opportunity</span>
</div>
</button>
<button class="oe_inline oe_stat_button" type="action"
<button class="oe_stat_button" type="action"
name="%(phonecall_to_phonecall_act)d" icon="fa-phone">
<div>Schedule<br/>Other Call</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Schedule</span>
<span class="o_stat_text">Other Call</span>
</div>
</button>
<button class="oe_inline oe_stat_button" name="action_make_meeting" type="object" icon="fa-calendar fa-fw">
<div>Schedule<br/>A Meeting</div>
<button class="oe_stat_button" name="action_make_meeting" type="object" icon="fa-calendar fa-fw">
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Schedule</span>
<span class="o_stat_text">A Meeting</span>
</div>
</button>
</div>
<div class="oe_title">
+7 -12
View File
@@ -68,12 +68,8 @@
<field name="meeting_count"/>
</field>
<xpath expr="//div[@class='oe_kanban_partner_links']" position="inside">
<a name="%(relate_partner_opportunities)d" type="action" t-if="record.opportunity_count.value>0">
<t t-esc="record.opportunity_count.value"/> Opportunities
</a>
<a name="%(calendar_event_partner)d" type="action" t-if="record.meeting_count.value>0">
<t t-esc="record.meeting_count.value"/> Meetings
</a>
<span class="badge" t-if="record.opportunity_count.value>0"><i class="fa fa-fw fa-star"/><t t-esc="record.opportunity_count.value"/></span>
<span class="badge" t-if="record.meeting_count.value>0"><i class="fa fa-fw fa-calendar"/><t t-esc="record.meeting_count.value"/></span>
</xpath>
</field>
</record>
@@ -89,31 +85,30 @@
<field name="user_id" position="after">
<field name="team_id" completion="1" groups="base.group_multi_salesteams"/>
</field>
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button o_res_partner_tip_opp" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button o_res_partner_tip_opp" type="action"
attrs="{'invisible': [('customer', '=', False)]}"
name="%(crm.crm_lead_opportunities)d"
icon="fa-star"
context="{'search_default_partner_id': active_id}">
<field string="Opportunities" name="opportunity_count" widget="statinfo"/>
</button>
<button class="oe_inline oe_stat_button" type="object"
<button class="oe_stat_button" type="object"
name="schedule_meeting"
icon="fa-calendar"
context="{'partner_id': active_id}">
<field string="Meetings" name="meeting_count" widget="statinfo"/>
</button>
<button class="oe_inline oe_stat_button" type="action"
<button class="oe_stat_button" type="action"
name="%(crm.crm_phonecall_category_phone_incoming0)d"
icon="fa-phone"
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}">
<field string="Calls" name="phonecall_count" widget="statinfo"/>
</button>
</xpath>
</div>
</data>
</field>
</record>
</data>
</openerp>
+4 -4
View File
@@ -8,14 +8,14 @@
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="priority" eval="50"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action"
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
name="%(crm_claim_category_claim0)d" icon="fa-comments" groups="base.group_sale_salesman">
<field string="Claims" name="claim_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
</data>
</openerp>
</openerp>
@@ -35,14 +35,17 @@
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_leads" />
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action" name="%(convert_lead2projectissue_wizard_action)d" icon="fa-bug"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(convert_lead2projectissue_wizard_action)d" icon="fa-bug"
help="Convert to Issue">
<div>Convert To<br/>Issue</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Convert To</span>
<span class="o_stat_text">Issue</span>
</div>
</button>
</xpath>
</div>
</field>
</record>
</data>
</openerp>
</openerp>
+7 -7
View File
@@ -65,19 +65,19 @@
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/>
</header>
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<div class="oe_right oe_button_box" groups="base.group_user">
<div class="oe_button_box" name="button_box" groups="base.group_user">
<button name="%(event.act_event_registration_from_event)d"
type="action"
class="oe_stat_button oe_inline oe_event_attendee_button"
class="oe_stat_button oe_event_attendee_button"
icon="fa-github"
help="Register with this event">
<field name="seats_reserved" widget="statinfo" string="Attendees"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group name="main_field_group">
<group>
<field name="address_id" context="{'show_address': 1}" options='{"always_reload": True}'/>
@@ -165,7 +165,7 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('delete')">
<t t-if="widget.deletable">
<li><a type="delete">Delete</a></li>
</t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
+14 -14
View File
@@ -190,20 +190,7 @@
<field name="state_id" widget="statusbar" clickable="True" />
</header>
<sheet>
<field name="image_medium" widget='image' class="oe_left oe_avatar"/>
<div class="oe_title">
<label for="model_id" class="oe_edit_only"/>
<h1>
<field name="model_id" class="oe_inline" on_change="on_change_model(model_id)"/>
</h1>
<label for="license_plate" class="oe_edit_only"/>
<h2>
<field name="license_plate" class="oe_inline"/>
</h2>
<label for="tag_ids" class="oe_edit_only"/>
<field name="tag_ids" widget="many2many_tags" />
</div>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button name="return_action_to_open"
type="object"
class="oe_stat_button"
@@ -245,6 +232,19 @@
<field name="odometer_count" widget="statinfo" string="Odometer"/>
</button>
</div>
<field name="image_medium" widget='image' class="oe_left oe_avatar"/>
<div class="oe_title">
<label for="model_id" class="oe_edit_only"/>
<h1>
<field name="model_id" class="oe_inline" on_change="on_change_model(model_id)"/>
</h1>
<label for="license_plate" class="oe_edit_only"/>
<h2>
<field name="license_plate" class="oe_inline"/>
</h2>
<label for="tag_ids" class="oe_edit_only"/>
<field name="tag_ids" widget="many2many_tags" />
</div>
<group col="2" string="General Properties">
<group >
<field name="driver_id" />
+1 -2
View File
@@ -42,8 +42,7 @@
<button string="Grant this Badge" type="action" name="%(action_grant_wizard)d" class="oe_highlight" attrs="{'invisible': [('remaining_sending','=',0)]}" />
</header>
<sheet>
<div class="oe_right oe_button_box">
</div>
<div class="oe_button_box" name="button_box"/>
<field name="image" widget='image' class="oe_left oe_avatar"/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
+13 -10
View File
@@ -40,6 +40,19 @@
<field name="state" widget="statusbar" clickable="True"/>
</header>
<sheet>
<!-- action buttons -->
<div class="oe_button_box" name="button_box">
<button type="action"
name="%(goals_from_challenge_act)d"
class="oe_stat_button"
icon="fa-gift"
attrs="{'invisible': [('state','=','draft')]}">
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Related</span>
<span class="o_stat_text">Goals</span>
</div>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
@@ -53,16 +66,6 @@
</div>
</div>
<!-- action buttons -->
<div class="oe_right oe_button_box">
<button type="action"
name="%(goals_from_challenge_act)d"
class="oe_stat_button"
icon="fa-gift"
attrs="{'invisible': [('state','=','draft')]}">
<div>Related<br/>Goals</div>
</button>
</div>
<group>
<group>
<field name="period" attrs="{'readonly':[('state','!=','draft')]}"/>
+1 -1
View File
@@ -47,7 +47,7 @@
</div>
</div>
<div t-if="widget.view.is_action_enabled('edit')" class="o_kanban_card_manage_settings row">
<div t-if="widget.editable" class="o_kanban_card_manage_settings row">
<div class="col-xs-8">
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</div>
+41 -43
View File
@@ -23,6 +23,7 @@
<field name="arch" type="xml">
<form string="Employee">
<sheet>
<div class="oe_button_box" name="button_box"/>
<field name="image_medium" widget='image' class="oe_left oe_avatar"/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
@@ -36,11 +37,8 @@
<label for="work_phone" class="oe_edit_only"/>
<field name="work_phone"/>
</div>
<div class="oe_right oe_button_box" name="button_box">
<!-- Put here related buttons -->
</div>
<notebook>
<page string="Public Information">
<page name="public" string="Public Information">
<group>
<group string="Contact Information">
<field name="address_id" on_change="onchange_address_id(address_id)"
@@ -141,14 +139,14 @@
</search>
</field>
</record>
<!-- HR Kanban View -->
<!-- HR Kanban View -->
<record model="ir.ui.view" id="hr_kanban_view_employees">
<field name="name">HR - Employess Kanban</field>
<field name="model">hr.employee</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<kanban>
<kanban class="o_hr_employee_kanban">
<field name="last_login"/>
<field name="message_is_follower"/>
<field name="message_follower_ids"/>
@@ -157,40 +155,40 @@
<field name="message_unread"/>
<templates>
<t t-name="kanban-box">
<div class="row oe_employee_details">
<div class="col-md-4">
<a type="open"><img t-att-src="kanban_image('hr.employee', 'image_medium', record.id.value)" class="img-responsive oe_employee_image"/></a>
</div>
<div class="col-md-8">
<h4>
<a type="open"><field name="name"/><t t-if="record.login.raw_value"> (<field name="login"/>)</t></a>
</h4>
<ul>
<li id="last_login">
<span t-if="record.last_login.raw_value &amp;&amp; record.last_login.raw_value.is().today()" class="oe_kanban_button" style="font-size: 100%%">
<t t-esc="moment(record.last_login.raw_value).format('LT')"/>
</span>
</li>
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
<li t-if="record.work_location.raw_value"><field name="work_location"/></li>
<li t-if="record.work_phone.raw_value"><i class="fa fa-phone"></i> <field name="work_phone"/></li>
<li t-if="record.mobile_phone.raw_value"><i class="fa fa-mobile"></i> <field name="mobile_phone"/></li>
<li t-if="record.work_email.raw_value"><i class="fa fa-envelope"></i><a t-attf-href="mailto:#{record.work_email.value}"> <field name="work_email"/></a></li>
</ul>
<div class="oe_kanban_bottom_left">
<t t-raw="record.message_summary.raw_value"/>
<span title='Messages'><i class='fa fa-comments'/><t t-esc="record.message_ids.raw_value.length"/></span>
<span title='Followers'><i class='fa fa-users'/><t t-esc="record.message_follower_ids.raw_value.length"/></span>
</div>
<div class="oe_followers" groups="base.group_user">
<button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="oe_follower oe_following">
<span class="oe_unfollow">Unfollow</span>
<span class="oe_following">Following</span>
</button>
<button t-if="! record.message_is_follower.raw_value" name="action_follow" type="object" class="oe_follower oe_notfollow">Follow</button>
</div>
<div class="o_kanban_two_column oe_kanban_global_click oe_employee_details">
<div class="o_kanban_image">
<img t-att-src="kanban_image('hr.employee', 'image_medium', record.id.value)"/>
<div class="o_employee_summary_icons">
<t t-raw="record.message_summary.raw_value"/>
<span title='Messages'><i class='fa fa-comments'/><t t-esc="record.message_ids.raw_value.length"/></span>
<span title='Followers'><i class='fa fa-users'/><t t-esc="record.message_follower_ids.raw_value.length"/></span>
</div>
</div>
<div class="oe_kanban_details oe_employee_details_content">
<strong>
<field name="name"/><t t-if="record.login.raw_value"> (<field name="login"/>)</t>
</strong>
<ul>
<li id="last_login">
<span t-if="record.last_login.raw_value &amp;&amp; record.last_login.raw_value.is().today()" class="oe_kanban_button" style="font-size: 100%%">
<t t-esc="moment(record.last_login.raw_value).format('LT')"/>
</span>
</li>
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
<li t-if="record.work_location.raw_value"><field name="work_location"/></li>
<li t-if="record.work_email.raw_value"><i class="fa fa-envelope"></i> <field name="work_email"/></li>
<li t-if="record.work_phone.raw_value"><i class="fa fa-phone"></i> <field name="work_phone"/></li>
<li t-if="record.mobile_phone.raw_value"><i class="fa fa-mobile"></i> <field name="mobile_phone"/></li>
</ul>
<div class="oe_followers o_kanban_button">
<button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="o_follow_btn o_following btn btn-primary">
<span class="o_unfollow">Unfollow</span>
<span class="o_following">Following</span>
</button>
<button t-if="!record.message_is_follower.raw_value" name="action_follow" type="object" class="o_follow_btn o_not_following btn btn-primary">Follow</button>
</div>
</div>
</div>
</t>
</templates>
</kanban>
@@ -352,14 +350,14 @@
<field name="state" widget="statusbar" statusbar_visible="recruit,open"/>
</header>
<sheet>
<div class="oe_right" name="button_box"/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name" class="oe_inline"/></h1>
<h1><field name="name"/></h1>
</div>
<div class="oe_right" name="buttons"/>
<group name="employee_data">
<field name="department_id" groups="hr.group_multi_departments" class="oe_inline"/>
<field name="no_of_recruitment" class="oe_inline" />
<field name="department_id" groups="hr.group_multi_departments"/>
<field name="no_of_recruitment"/>
</group>
<div attrs="{'invisible': [('state', '!=', 'recruit')]}">
<label for="description"/>
@@ -520,4 +518,4 @@
groups="group_multi_departments"/>
</data>
</openerp>
</openerp>
-8
View File
@@ -1,8 +0,0 @@
odoo.define('hr.hr', function(require) {
"use strict";
var common = require('web_kanban.common');
});
+10 -6
View File
@@ -1,7 +1,11 @@
.oe_kanban_view.o_kanban_dashboard.o_hr_kanban {
.oe_kanban_record {
max-width: 500px;
min-width: 400px;
min-height: 200px;
}
.o_kanban_view {
.o_kanban_record.oe_employee_details {
.oe_employee_details_content {
padding-left: 16px;
> h4 {
margin-top: 0;
}
}
}
}
-1
View File
@@ -6,7 +6,6 @@
<link rel="stylesheet" href="/hr/static/src/css/hr.css"/>
<link rel="stylesheet" href="/hr/static/src/less/hr_dashboard.less"/>
<script type="text/javascript" src="/hr/static/src/js/suggestions.js"></script>
<script type="text/javascript" src="/hr/static/src/js/hr.js"></script>
</xpath>
</template>
</data>
+2 -2
View File
@@ -19,7 +19,7 @@
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
<data>
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="%(act_hr_employee_2_hr_contract)d"
class="oe_stat_button"
icon="fa-book"
@@ -27,7 +27,7 @@
groups="base.group_hr_manager">
<field name="contracts_count" widget="statinfo" string="Contracts"/>
</button>
</xpath>
</div>
<xpath expr="//field[@name='coach_id']" position="after">
<field name="manager"/>
</xpath>
@@ -92,8 +92,8 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg" />
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Edit...</a></li></t>
<t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
<t t-if="widget.editable"><li><a type="edit">Edit...</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
@@ -192,13 +192,7 @@
<field name="arch" type="xml">
<form string="Equipments">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Name"/>
<h1><field name="name" string="Name"/></h1>
<label for="serial_no" class="oe_edit_only"/>
<field name="serial_no"/>
</div>
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button name="%(hr_equipment_request_action_from_equipment)d"
type="action"
class="oe_stat_button"
@@ -206,6 +200,12 @@
<field string="Maintenance" name="maintenance_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Name"/>
<h1><field name="name" string="Name"/></h1>
<label for="serial_no" class="oe_edit_only"/>
<field name="serial_no"/>
</div>
<group>
<group>
<field name="category_id" groups="base.group_equipment_manager" on_change="1" options="{&quot;no_open&quot;: True}"/>
@@ -265,8 +265,8 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg" />
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Edit...</a></li></t>
<t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
<t t-if="widget.editable"><li><a type="edit">Edit...</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
@@ -392,13 +392,7 @@
<field name="arch" type="xml">
<form string="Equipment Categories">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Category Name"/>
<h1>
<field name="name"/>
</h1>
</div>
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button name="%(hr_equipment_action_from_category_form)d"
class="oe_stat_button"
icon="fa-laptop"
@@ -412,6 +406,12 @@
<field string="Maintenance" name="maintenance_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Category Name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group col="4">
<field name="user_id"/>
+3 -3
View File
@@ -147,14 +147,14 @@
<field name="evaluation_date"/>
</group>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="%(act_hr_employee_2_hr__evaluation_interview)d"
class="oe_stat_button"
icon="fa-sitemap"
type="action">
<field name="appraisal_count" widget="statinfo" string="Appraisals"/>
</button>
</xpath>
</div>
</field>
</record>
@@ -284,7 +284,7 @@
<field name="state" widget="statusbar" statusbar_visible="waiting_answer,done"/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="button_box">
<div class="oe_button_box" name="button_box">
<button string="Send Reminder Email" name="%(mail.action_email_compose_message_wizard)d" type="action"
states="waiting_answer"
context="{'default_body': 'Hello,\n\nKindly post your response for the survey interview.\n\nThanks',
@@ -1,11 +1,11 @@
odoo.define('hr_gamification.hr_gamification', function(require) {
"use strict";
var common = require('web_kanban.common');
var KanbanRecord = require('web_kanban.Record');
common.KanbanRecord.include({
KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'gamification.badge.user') {
if (this.model === 'gamification.badge.user') {
var action = {
type: 'ir.actions.act_window',
res_model: 'gamification.badge',
@@ -7,9 +7,9 @@
<field name="model">gamification.badge</field>
<field name="inherit_id" ref="gamification.badge_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@class='oe_right oe_button_box']" position="inside">
<div name="button_box" position="inside">
<button string="Granted Employees" type="object" name="get_granted_employees" attrs="{'invisible': [('stat_count','=',0)]}" />
</xpath>
</div>
</field>
</record>
+2 -2
View File
@@ -589,7 +589,7 @@
</div>
</group>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="%(act_hr_employee_holiday_request_approved)d"
icon="fa-calendar"
class="oe_stat_button"
@@ -604,7 +604,7 @@
groups="base.group_hr_user">
<field name="leaves_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
+3 -3
View File
@@ -221,7 +221,7 @@
<field name="state" widget="statusbar" statusbar_visible="draft,confirm"/>
</header>
<sheet>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button name="%(act_payslip_lines)d"
class="oe_stat_button"
icon="fa-money"
@@ -391,7 +391,7 @@
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
<data>
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="%(act_hr_employee_payslip_list)d"
class="oe_stat_button"
icon="fa-money"
@@ -399,7 +399,7 @@
groups="base.group_hr_user">
<field name="payslip_count" widget="statinfo" string="Payslips"/>
</button>
</xpath>
</div>
</data>
</field>
</record>
@@ -123,7 +123,7 @@
</div>
</div>
<div t-if="widget.view.is_action_enabled('edit')" class="o_kanban_card_manage_settings row">
<div t-if="widget.editable" class="o_kanban_card_manage_settings row">
<div class="col-xs-8">
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</div>
+55 -50
View File
@@ -62,10 +62,12 @@
<field name="stage_id" widget="statusbar" clickable="True" options="{'fold_field': 'fold'}"/>
</header>
<sheet>
<div class="oe_right oe_button_box">
<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>Meetings</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Meetings</span>
</div>
</button>
<button name="action_start_survey"
class="oe_stat_button"
@@ -74,7 +76,10 @@
help="Answer related job question"
context="{'survey_id': survey}"
attrs="{'invisible':[('survey','=',False)]}">
<div>Start<br/>Interview</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Start</span>
<span class="o_stat_text">Interview</span>
</div>
</button>
<button name="action_print_survey"
class="oe_stat_button"
@@ -82,7 +87,10 @@
type="object"
help="Print interview report"
attrs="{'invisible':[('survey','=',False)]}">
<div>Print<br/>Interview</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Print</span>
<span class="o_stat_text">Interview</span>
</div>
</button>
<button name="action_get_attachment_tree_view"
class="oe_stat_button"
@@ -268,7 +276,7 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><a name="action_makeMeeting" type="object">Schedule Interview</a></li>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
@@ -375,14 +383,11 @@
<field name="arch" type="xml">
<group name="employee_data" position="inside">
<label for="survey_id" groups="base.group_user"/>
<div groups="base.group_user">
<field name="survey_id" class="oe_inline"/>
<button string="Print Interview" name="action_print_survey" type="object" attrs="{'invisible':[('survey_id','=',False)]}" class="oe_inline oe_link"/>
</div>
<label for="address_id"/>
<div>
<field name="address_id" context="{'show_address': 1}" domain= "[('is_company', '=', True )]"/>
<div groups="base.group_user" class="o_row">
<field name="survey_id"/>
<button string="Print Interview" name="action_print_survey" type="object" attrs="{'invisible':[('survey_id','=',False)]}" class="oe_link"/>
</div>
<field name="address_id" context="{'show_address': 1}" domain= "[('is_company', '=', True )]"/>
</group>
<group name="employee_data" position="after">
<notebook>
@@ -392,46 +397,45 @@
</notebook>
</group>
<xpath expr="//field[@name='department_id']" position="after">
<label for="alias_name" string="Specific Email Address" attrs="{'invisible': [('alias_domain', '=', False)]}" help ="Define a specific contact address for this job position. If you keep it empty, the default email address will be used which is in human resources settings"/>
<div name="alias_def" attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_id" class="oe_read_only oe_inline"
string="Email Alias" required="0"/>
<div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;" >
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
<label for="alias_name" string="Specific Email Address" attrs="{'invisible': [('alias_domain', '=', False)]}" help="Define a specific contact address for this job position. If you keep it empty, the default email address will be used which is in human resources settings"/>
<div name="alias_def" attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_id" class="oe_read_only" string="Email Alias" required="0"/>
<div class="oe_edit_only" name="edit_alias">
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
</xpath>
<xpath expr="//field[@name='department_id']" position="after">
<field name="user_id" class="oe_inline"/>
</xpath>
<xpath expr="//div[@name='buttons']" position="inside">
<div class="oe_button_box" >
<button class="oe_stat_button"
icon="fa-file-o"
name="%(action_hr_job_applications)d"
context="{'default_user_id': user_id}"
type="action">
<field name="application_count" widget="statinfo" string="Applications"/>
</button>
<button class="oe_stat_button"
icon="fa-users"
name="%(action_hr_job_no_employee)d"
type="action">
<field name="no_of_employee" widget="statinfo" string="Employees"/>
</button>
<button class="oe_stat_button"
icon="fa-book"
name="action_get_attachment_tree_view"
type="object">
<field name="documents_count" widget="statinfo" string="Documents"/>
</button>
<button class="oe_stat_button" type="action"
name="%(action_hr_job_sources)d" icon="fa-share"
context="{'default_job_id': active_id}">
<div>Trackers</div>
</button>
</div>
</xpath>
<xpath expr="//field[@name='department_id']" position="after">
<field name="user_id"/>
</xpath>
<div name="button_box" position="inside">
<button class="oe_stat_button"
icon="fa-file-o"
name="%(action_hr_job_applications)d"
context="{'default_user_id': user_id}"
type="action">
<field name="application_count" widget="statinfo" string="Applications"/>
</button>
<button class="oe_stat_button"
icon="fa-users"
name="%(action_hr_job_no_employee)d"
type="action">
<field name="no_of_employee" widget="statinfo" string="Employees"/>
</button>
<button class="oe_stat_button"
icon="fa-book"
name="action_get_attachment_tree_view"
type="object">
<field name="documents_count" widget="statinfo" string="Documents"/>
</button>
<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">
<span class="o_stat_text">Trackers</span>
</div>
</button>
</div>
</field>
</record>
@@ -502,6 +506,7 @@
<menuitem
name="Recruitment"
id="menu_hr_recruitment_root"
web_icon="hr_recruitment,static/description/icon.png"
sequence="80"/>
<menuitem id="menu_hr_recruitment_configuration" name="Configuration" parent="menu_hr_recruitment_root"
@@ -695,4 +700,4 @@
</record>
</data>
</openerp>
</openerp>
@@ -1,11 +1,11 @@
odoo.define('hr_recruitment.hr_recruitment', function(require) {
"use strict";
var common = require('web_kanban.common');
var KanbanRecord = require('web_kanban.Record');
common.KanbanRecord.include({
KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'hr.job') {
if (this.model === 'hr.job') {
this.$('.oe_applications a').first().click();
} else {
this._super.apply(this, arguments);
+3 -3
View File
@@ -118,10 +118,10 @@
<field name="invoice_on_timesheets"/>
<label for="invoice_on_timesheets"/>
</xpath>
<xpath expr='//div[@name="buttons"]' position='inside'>
<button class="oe_inline oe_stat_button" type="action" name="%(act_analytic_cost_revenue)d"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(act_analytic_cost_revenue)d"
icon="fa-usd" string="Cost/Revenue" widget="statinfo"/>
</xpath>
</div>
</field>
</record>
@@ -87,12 +87,15 @@
<field name="state" widget="statusbar" statusbar_visible="new,confirm,done"/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button type="action"
name="%(act_hr_timesheet_sheet_sheet_2_hr_analytic_timesheet)d"
class="oe_stat_button"
icon="fa-clock-o">
<div><strong><field name="total_timesheet" widget="float_time"/></strong><br/>Timesheet</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_value"><field name="total_timesheet" widget="float_time"/></span>
<span class="o_stat_text">Timesheet</span>
</div>
</button>
<button type="action" groups="base.group_hr_attendance"
class="oe_stat_button" icon="fa-users"
@@ -378,7 +381,7 @@
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_employee_extd_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="%(act_hr_employee_2_hr_timesheet)d"
type="action"
class="oe_stat_button"
@@ -386,7 +389,7 @@
groups="base.group_hr_manager">
<field name="timesheet_count" widget="statinfo" string="Timesheets"/>
</button>
</xpath>
</div>
</field>
</record>
@@ -71,6 +71,14 @@
<field name="arch" type="xml">
<form>
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="action" attrs="{'invisible':[('nbr_session','=', 0)]}" name="%(im_chat_session_action_from_channel)d" icon="fa-comments">
<field string="Sessions" name="nbr_session" widget="statinfo"/>
</button>
<button name="action_view_rating" attrs="{'invisible':[('rating_percentage_satisfaction','=', -1)]}" class="oe_stat_button" type="object" icon="fa-smile-o">
<field string="% Happy" name="rating_percentage_satisfaction" widget="statinfo"/>
</button>
</div>
<field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_medium"}'/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
@@ -83,14 +91,6 @@
<field name="are_you_inside" invisible="1"/>
</div>
</div>
<div class="oe_right oe_button_box" name="buttons">
<button class="oe_inline oe_stat_button" type="action" attrs="{'invisible':[('nbr_session','=', 0)]}" name="%(im_chat_session_action_from_channel)d" icon="fa-comments">
<field string="Sessions" name="nbr_session" widget="statinfo"/>
</button>
<button name="action_view_rating" attrs="{'invisible':[('rating_percentage_satisfaction','=', -1)]}" class="oe_stat_button" type="object" icon="fa-smile-o">
<field string="% Happy" name="rating_percentage_satisfaction" widget="statinfo"/>
</button>
</div>
<group>
<group string="Operators">
<field name="user_ids" widget="many2many_kanban" nolabel="1" colspan="2">
+2 -2
View File
@@ -9,8 +9,7 @@
<field name="arch" type="xml">
<form string="Alias">
<sheet>
<h2><field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline"/></h2>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button name="open_document" string="Open Document"
type="object" class="oe_link"
attrs="{'invisible': ['|', ('alias_model_id', '=', False), ('alias_force_thread_id', '=', 0)]}"/>
@@ -18,6 +17,7 @@
type="object" class="oe_link"
attrs="{'invisible': ['|', ('alias_parent_model_id', '=', False), ('alias_parent_thread_id', '=', 0)]}"/>
</div>
<h2><field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline"/></h2>
<group>
<field name="alias_model_id"/>
<field name="alias_force_thread_id"/>
+23 -17
View File
@@ -7,6 +7,29 @@
<field name="arch" type="xml">
<form string="Templates">
<sheet>
<div class="oe_button_box" name="button_box">
<field name="ref_ir_act_window" invisible="1"/>
<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">
<span class="o_stat_text">Add</span>
<span class="o_stat_text">Context Action</span>
</div>
</button>
<button name="unlink_action" type="object"
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">
<span class="o_stat_text">Remove</span>
<span class="o_stat_text">Context Action</span>
</div>
</button>
<button class="oe_stat_button" name="%(wizard_email_template_preview)d" icon="fa-search-plus" string="Preview"
type="action" target="new"
context="{'template_id':active_id}"/>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/><h1><field name="name" required="1"/></h1>
<group>
@@ -14,23 +37,6 @@
<field name="model" invisible="1"/>
</group>
</div>
<div class="oe_right oe_button_box" name="buttons">
<field name="ref_ir_act_window" invisible="1"/>
<button class="oe_inline 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>Add<br/>Context Action</div>
</button>
<button name="unlink_action" type="object"
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>Remove<br/>Context Action</div>
</button>
<button class="oe_inline oe_stat_button" name="%(wizard_email_template_preview)d" icon="fa-search-plus" string="Preview"
type="action" target="new"
context="{'template_id':active_id}"/>
</div>
<notebook>
<page string="Content">
<label for="subject"/>
@@ -61,13 +61,16 @@
<field name="state" readonly="1" widget="statusbar" statusbar_visible="draft,running,done"/>
</header>
<sheet string="Campaign">
<div class="oe_right oe_button_box" name="button_box">
<div class="oe_button_box" name="button_box">
<button type="action"
name="%(act_marketing_campaing_stat)d"
class="oe_stat_button"
icon="fa-keyboard-o"
help="Marketing Campaign Statistics">
<div>Campaign<br/>Statistics</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Campaign</span>
<span class="o_stat_text">Statistics</span>
</div>
</button>
<button type="action"
name="%(act_marketing_campaing_segment_opened)d"
@@ -1,14 +1,14 @@
odoo.define('mass_mailing.mass_mailing', function (require) {
var core = require('web.core');
var common = require('web_kanban.common');
var KanbanRecord = require('web_kanban.Record');
var KanbanView = require('web_kanban.KanbanView');
var _t = core._t;
common.KanbanRecord.include({
KanbanRecord.include({
on_card_clicked: function (event) {
if (this.view.dataset.model === 'mail.mass_mailing.campaign') {
if (this.model === 'mail.mass_mailing.campaign') {
this.$('.oe_mailings').click();
} else {
this._super.apply(this, arguments);
+9 -11
View File
@@ -10,6 +10,12 @@
<field name="arch" type="xml">
<form string="Templates">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="%(mail.wizard_email_template_preview)d" string="Preview"
type="action" target="new"
context="{'template_id':active_id}"/>
<br />
</div>
<group>
<group>
<field name="name" required="True"/>
@@ -19,14 +25,6 @@
<field name="model" invisible="True"/>
<field name="use_default_to" invisible="1"/>
</group>
<group>
<div class="oe_right oe_button_box" name="buttons">
<button name="%(mail.wizard_email_template_preview)d" string="Preview"
type="action" target="new"
context="{'template_id':active_id}"/>
<br />
</div>
</group>
</group>
<notebook>
<page string="Body">
@@ -50,11 +48,11 @@
<div t-attf-class="oe_kanban_card oe_kanban_global_click oe_kanban_email_template">
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu" t-if="widget.view.is_action_enabled('edit') or widget.view.is_action_enabled('delete')">
<t t-if="widget.view.is_action_enabled('edit')">
<ul class="oe_dropdown_menu" t-if="widget.editable or widget.deletable">
<t t-if="widget.editable">
<li><a type="edit">Edit</a></li>
</t>
<t t-if="widget.view.is_action_enabled('delete')">
<t t-if="widget.deletable">
<li><a type="delete">Delete</a></li>
</t>
</ul>
+38 -42
View File
@@ -245,9 +245,9 @@
<field name="arch" type="xml">
<form string="Contact List">
<sheet>
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button name="%(mass_mailing.action_view_mass_mailing_contacts_from_list)d"
type="action" icon="fa-user" class="oe_stat_button pull-right">
type="action" icon="fa-user" class="oe_stat_button">
<field name="contact_nbr" string="Recipients" widget="statinfo"/>
</button>
</div>
@@ -392,7 +392,7 @@
</strong></p>
</div>
<sheet>
<div class="oe_button_box pull-right" attrs="{'invisible': [('state', 'in', ('draft','test'))]}">
<div class="oe_button_box" name="button_box" attrs="{'invisible': [('state', 'in', ('draft','test'))]}">
<button name="%(action_view_mail_mail_statistics_mailing)d" type="action"
icon="fa-envelope-o" class="oe_stat_button"
attrs="{'invisible': [('sent', '=', 0)]}" >
@@ -499,7 +499,7 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('delete')">
<t t-if="widget.deletable">
<li><a type="delete">Delete</a></li>
</t>
</ul>
@@ -705,43 +705,39 @@
<span><field name="stage_id" widget="statusbar" clickable="True"/></span>
</header>
<sheet>
<field name="total" invisible="1"/>
<div class="oe_button_box" name="button_box"
attrs="{'invisible': [('total', '=', 0)]}">
<button name="%(action_view_mass_mailings_from_campaign)d"
type="action" class="oe_stat_button" icon="fa-envelope-o">
<field name="total_mailings" widget="statinfo" string="Mailings"/>
</button>
<button name="%(action_view_mail_mail_statistics_mailing)d" type="action"
icon="fa-envelope-o" class="oe_stat_button"
attrs="{'invisible': [('sent', '=', 0)]}" >
<field name="sent" string="Emails Sent" widget="statinfo"/>
</button>
<button name="%(action_view_mass_mailing_contacts)d"
type="action" class="oe_stat_button">
<field name="received_ratio" widget="percentpie" string="Received"/>
</button>
<button name="%(action_view_mass_mailing_contacts)d"
type="action" class="oe_stat_button">
<field name="opened_ratio" widget="percentpie" string="Opened"/>
</button>
<button name="%(action_view_mass_mailing_contacts)d"
type="action" class="oe_stat_button">
<field name="replied_ratio" widget="percentpie" string="Replied"/>
</button>
<button name="%(dropdb snipp)d"
type="action" class="oe_stat_button">
<field name="clicks_ratio" widget="percentpie" string="Clicks"/>
</button>
</div>
<group>
<group>
<field name="name" string="Campaign Name" on_change="on_change_campaign_name(name)"/>
<field name="user_id"/>
<field name="tag_ids" widget="many2many_tags"/>
</group>
<group>
<field name="total" invisible="1"/>
<div class="oe_right oe_button_box" name="buttons"
attrs="{'invisible': [('total', '=', 0)]}">
<button name="%(action_view_mass_mailings_from_campaign)d"
type="action" class="oe_inline oe_stat_button" icon="fa-envelope-o">
<field name="total_mailings" widget="statinfo" string="Mailings"/>
</button>
<button name="%(action_view_mail_mail_statistics_mailing)d" type="action"
icon="fa-envelope-o" class="oe_stat_button"
attrs="{'invisible': [('sent', '=', 0)]}" >
<field name="sent" string="Emails Sent" widget="statinfo"/>
</button>
<button name="%(action_view_mass_mailing_contacts)d"
type="action" class="oe_stat_button oe_inline">
<field name="received_ratio" widget="percentpie" string="Received"/>
</button>
<button name="%(action_view_mass_mailing_contacts)d"
type="action" class="oe_stat_button oe_inline">
<field name="opened_ratio" widget="percentpie" string="Opened"/>
</button>
<button name="%(action_view_mass_mailing_contacts)d"
type="action" class="oe_stat_button oe_inline">
<field name="replied_ratio" widget="percentpie" string="Replied"/>
</button>
<button name="%(dropdb snipp)d"
type="action" class="oe_stat_button">
<field name="clicks_ratio" widget="percentpie" string="Clicks"/>
</button>
</div>
</group>
<field name="name" string="Campaign Name" on_change="on_change_campaign_name(name)"/>
<field name="user_id"/>
<field name="tag_ids" widget="many2many_tags"/>
</group>
<notebook>
<page string="Tracking">
@@ -787,10 +783,10 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')">
<t t-if="widget.editable">
<li><a type="edit">Settings</a></li>
</t>
<t t-if="widget.view.is_action_enabled('delete')">
<t t-if="widget.deletable">
<li><a type="delete">Delete</a></li>
</t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
+6 -6
View File
@@ -1105,12 +1105,12 @@
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="groups_id" eval="[(4, ref('mrp.group_mrp_user'))]"/>
<field name="arch" type="xml">
<div name="buttons" position="inside">
<button class="oe_inline oe_stat_button" name="%(template_open_bom)d" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="%(template_open_bom)d" type="action"
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-flask">
<field string="Bill of Materials" name="bom_count" widget="statinfo" />
</button>
<button class="oe_inline oe_stat_button" name="action_view_mos" type="object"
<button class="oe_stat_button" name="action_view_mos" type="object"
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-list-alt">
<field string="Manufacturing" name="mo_count" widget="statinfo" />
</button>
@@ -1124,12 +1124,12 @@
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="groups_id" eval="[(4, ref('mrp.group_mrp_user'))]"/>
<field name="arch" type="xml">
<div name="buttons" position="inside">
<button class="oe_inline oe_stat_button" name="action_view_bom" type="object"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="action_view_bom" type="object"
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-flask">
<field string="Bill of Materials" name="bom_count" widget="statinfo" />
</button>
<button class="oe_inline oe_stat_button" name="%(act_product_mrp_production)d" type="action"
<button class="oe_stat_button" name="%(act_product_mrp_production)d" type="action"
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-list-alt">
<field string="Manufacturing" name="mo_count" widget="statinfo" />
</button>
+24 -22
View File
@@ -54,32 +54,32 @@
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_global_click_edit oe_semantic_html_override oe_kanban_card">
<div class="oe_dropdown_kanban oe_dropdown_toggle">
<!-- dropdown menu -->
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<li><a type="delete">Delete</a></li>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
<div t-attf-class="#{kanban_color(record.color.raw_value)} oe_kanban_global_click_edit oe_semantic_html_override oe_kanban_card">
<div class="o_dropdown_kanban dropdown">
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><a type="delete">Delete</a></li>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
<div style="display: inline" class="oe_dropdown_kanban">
<span class="oe_dropdown_kanban">
<a name="onclick_note_is_done" type="object" t-if="record.open.raw_value"><i class="fa fa-check"/></a>
<a name="onclick_note_not_done" type="object" t-if="!record.open.raw_value"><i class="fa fa-check"/></a>
</div>
</span>
<!-- kanban note -->
<div t-attf-class="oe_kanban_content #{record.open.raw_value ? '' : 'note_text_line_through'}">
<span t-attf-class="oe_kanban_content #{record.open.raw_value ? '' : 'note_text_line_through'}">
<!-- title -->
<field name="name"/>
</div>
<div class="oe_clear"></div>
</span>
<div class="clearfix"></div>
<field name="tag_ids"/>
<div class="oe_right">
<t t-foreach="record.message_follower_ids.raw_value" t-as="follower">
<img t-att-src="kanban_image('res.partner', 'image_small', follower)" width="24" height="24" class="oe_kanban_avatar" t-att-data-member_id="follower"/>
<img t-att-src="kanban_image('res.partner', 'image_small', follower)" width="24" height="24" class="oe_kanban_avatar pull-right" t-att-data-member_id="follower"/>
</t>
</div>
<div class="oe_clear"></div>
<div class="clearfix"></div>
</div>
</t>
</templates>
@@ -106,12 +106,14 @@
<field name="name">note.note.form</field>
<field name="model">note.note</field>
<field name="arch" type="xml">
<form string="Note" class="oe_form_nomargin">
<form string="Note" class="oe_form_nomargin o_note_form_view">
<header>
<field name="tag_ids" widget="many2many_tags" class="oe_inline" placeholder="Tags"/>
<field name="tag_ids" widget="many2many_tags" placeholder="Tags"/>
<field name="stage_id" domain="[('user_id','=',uid)]" widget="statusbar" clickable="1"/>
</header>
<field name="memo" widget="html" class="oe_memo" editor_height="450px" />
<sheet>
<field name="memo" widget="html" class="oe_memo" editor_height="450px" />
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
@@ -182,9 +184,9 @@
</field>
</record>
<menuitem name="Notes" id="menu_note_notes" sequence="3" action="note.action_note_note"/>
<menuitem name="Notes" id="menu_note_notes" sequence="3" action="note.action_note_note" web_icon="note,static/description/icon.png"/>
<menuitem name="Configuration" id="menu_note_configuration" sequence="100" parent="menu_note_notes" groups="base.group_configuration"/>
<menuitem name="Stages" id="menu_notes_stage" parent="menu_note_configuration" action="note.action_note_stage" sequence="21" />
</data>
</openerp>
</openerp>
+9 -3
View File
@@ -806,14 +806,20 @@
</header>
<sheet>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="%(action_pos_box_in)d"
type="action" states="opened,closing_control" icon="fa-level-down">
<div>Put<br/>Money In</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Put</span>
<span class="o_stat_text">Money In</span>
</div>
</button>
<button class="oe_stat_button" name="%(action_pos_box_out)d"
type="action" states="opened,closing_control" icon="fa-level-up">
<div>Take<br/>Money Out</div>
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Take</span>
<span class="o_stat_text">Money Out</span>
</div>
</button>
</div>
<h1 class="oe_title">
+4 -4
View File
@@ -34,9 +34,9 @@
<field name="state" readonly="1" widget="statusbar" statusbar_visible="draft,confirmed,running,done" />
</header>
<sheet>
<div class="oe_right oe_button_box" name="button_box">
<button name="do_view_procurements" class="oe_stat_button" icon="fa-bars" string="Group's Procurements" type="object"/>
</div>
<div class="oe_button_box" name="button_box">
<button name="do_view_procurements" class="oe_stat_button" icon="fa-bars" string="Group's Procurements" type="object"/>
</div>
<group>
<group>
<field name="product_id" on_change="onchange_product_id(product_id)"/>
@@ -98,7 +98,7 @@
<field name="arch" type="xml">
<form string="Procurement group">
<sheet>
<div class="oe_right oe_button_box" name="button_box">
<div class="oe_button_box" name="button_box">
<button name="%(do_view_procurements)d" string="Procurements" type="action"/>
</div>
<group>
+21 -24
View File
@@ -19,7 +19,7 @@
<field string="Product Variant" name="product_variant_ids" filter_domain="['|', ('product_variant_ids.name','ilike',self), ('product_variant_ids.attribute_value_ids.attribute_id.name','ilike',self)]"/>
<field name="company_id"/>
<field name="pricelist_id" widget="selection" context="{'pricelist': self}" filter_domain="[]" groups="product.group_sale_pricelist"/> <!-- Keep widget=selection on this field to pass numeric `self` value, which is not the case for regular m2o widgets! -->
<group expand='0' string='Group by...'>
<group expand='0' name="group_by" string='Group by...'>
<filter string='Category' domain="[]" context="{'group_by' : 'categ_id'}"/>
<filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}"/>
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/>
@@ -53,18 +53,15 @@
<field name='product_variant_count' invisible='1'/>
<sheet>
<field name="id" invisible="True"/>
<div class="oe_right oe_button_box" style="width: 300px;" name="buttons">
</div>
<div class="oe_left" style="width: 500px;">
<field name="image_medium" widget="image" class="oe_avatar oe_left"/>
<div class="oe_title" style="width: 390px;">
<label class="oe_edit_only" for="name" string="Product Name"/>
<h1><field name="name" class="oe_inline"/></h1>
<div name="options" groups="base.group_user">
<div>
<field name="sale_ok"/>
<label for="sale_ok"/>
</div>
<div class="oe_button_box" name="button_box"/>
<field name="image_medium" widget="image" class="oe_avatar"/>
<div class="oe_title">
<label class="oe_edit_only" for="name" string="Product Name"/>
<h1><field name="name"/></h1>
<div name="options" groups="base.group_user">
<div>
<field name="sale_ok"/>
<label for="sale_ok"/>
</div>
</div>
</div>
@@ -161,7 +158,7 @@
<field name="name" position="after">
<field name="product_tmpl_id" string="Product Template"/>
</field>
<xpath expr="//group[@string='Group by...']" position="inside">
<xpath expr="//group[@name='group_by']" position="inside">
<filter string='Product Template' name="template_id" domain="[]" context="{'group_by' : 'product_tmpl_id'}"/>
</xpath>
</field>
@@ -255,14 +252,14 @@
<field name="barcode" attrs="{'invisible': [('product_variant_count', '>', 1)]}"/>
<field name="default_code" attrs="{'invisible': [('product_variant_count', '>', 1)]}"/>
</field>
<xpath expr="//page[@string='Sales']" position="after">
<div name="button_box" position="inside">
<button class="oe_stat_button" string="Variant Prices" name="%(variants_template_action)d" type="action" icon="fa-strikethrough"/>
<button class="oe_stat_button" name="%(product.product_variant_action)d" type="action" icon="fa-sitemap">
<field string="List of Variants" name="product_variant_count" widget="statinfo" />
</button>
</div>
<xpath expr="//page[@name='sales']" position="after">
<page name="variants" string="Variants">
<div class="oe_right">
<button class="oe_inline oe_stat_button" string="Variant Prices" name="%(variants_template_action)d" type="action" icon="fa-strikethrough"/>
<button class="oe_inline oe_stat_button" name="%(product.product_variant_action)d" type="action" icon="fa-sitemap">
<field string="List of Variants" name="product_variant_count" widget="statinfo" />
</button>
</div>
<p class="oe_grey">
<strong>Warning</strong>: adding or deleting attributes
will delete and recreate existing variants and lead
@@ -291,8 +288,8 @@
<field name="product_variant_ids"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_vignette oe_semantic_html_override">
<a type="open"><img t-att-src="kanban_image('product.template', 'image_small', record.id.value)" class="oe_kanban_image"/></a>
<div class="o_kanban_two_column">
<a type="open"><img t-att-src="kanban_image('product.template', 'image_small', record.id.value)" class="o_kanban_image"/></a>
<div class="oe_kanban_details">
<h4>
<a type="open">
@@ -867,4 +864,4 @@
</record>
</data>
</openerp>
</openerp>
+9 -1
View File
@@ -556,6 +556,12 @@ class task(osv.osv):
res[task.id] = False
return res
def _compute_displayed_image(self, cr, uid, ids, prop, arg, context=None):
res = {}
for line in self.browse(cr, uid, ids, context=context):
res[line.id] = line.attachment_ids and line.attachment_ids.filtered(lambda x: x.file_type_icon == 'webimage')[0] or None
return res
_columns = {
'active': fields.function(_is_template, store=True, string='Not a Template Task', type='boolean', help="This field is computed automatically and have the same behavior than the boolean 'active' field: if the task is linked to a template or unactivated project, it will be hidden unless specifically asked."),
'name': fields.char('Task Summary', track_visibility='onchange', size=128, required=True, select=True),
@@ -592,7 +598,9 @@ class task(osv.osv):
'id': fields.integer('ID', readonly=True),
'color': fields.integer('Color Index'),
'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True),
}
'attachment_ids': fields.one2many('ir.attachment', 'res_id', domain=lambda self: [('res_model', '=', self._name)], auto_join=True, string='Attachments'),
'displayed_image_id': fields.function(_compute_displayed_image, relation='ir.attachment', type="many2one", string='Attachment'),
}
_defaults = {
'stage_id': _get_default_stage_id,
'project_id': lambda self, cr, uid, ctx=None: ctx.get('default_project_id') if ctx is not None else False,
+4 -6
View File
@@ -27,7 +27,7 @@
<span><t t-esc="record.name.value"/></span>
</div>
<div t-if="record.alias_id.raw_value">
<span><i class="fa fa-envelope-o"></i> <t t-esc="record.alias_id.value"/></span>
<span><i class="fa fa-envelope"></i> <t t-esc="record.alias_id.value"/></span>
</div>
</div>
</div><div class="o_kanban_card_manage_pane o_invisible">
@@ -41,16 +41,14 @@
<div>
<a name="%(action_view_task_history_cumulative_filter)d" type="action">Cumulative Flow</a>
</div>
</div>
<div t-if="widget.view.is_action_enabled('edit')" class="o_project_kanban_colorpicker">
<div class="col-xs-12">
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
<div t-if="widget.editable" class="o_project_kanban_colorpicker">
<ul class="oe_kanban_colorpicker" data-field="color"/>
</div>
</div>
</div>
<div class="o_project_kanban_manage">
<div class="text-left">
<a class="o_kanban_manage_toggle_button">More <i class="fa fa-caret-down"/></a>
<a class="o_kanban_manage_toggle_button" href="#">More <i class="fa fa-caret-down"/></a>
</div>
</div>
</div>
+37 -31
View File
@@ -7,6 +7,7 @@
id="base.menu_main_pm"
groups="group_project_manager,group_project_user"
icon="fa-calendar"
web_icon="project,static/description/icon.png"
sequence="50"/>
<menuitem name="Search"
@@ -88,6 +89,15 @@
</header>
<sheet string="Project">
<field name="analytic_account_id" invisible="1" required="0"/>
<div class="oe_button_box" name="button_box" groups="base.group_user">
<button class="oe_stat_button" type="action" attrs="{'invisible':[('use_tasks','=', False)]}"
name="%(act_project_project_2_project_task_all)d" icon="fa-tasks">
<field string="Tasks" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/>
</button>
<button class="oe_stat_button" name="attachment_tree_view" type="object" icon="fa-files-o">
<field string="Documents" name="doc_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Project Name"/>
<h1>
@@ -102,15 +112,6 @@
</div>
</div>
</div>
<div class="oe_right oe_button_box" name="buttons" groups="base.group_user">
<button class="oe_inline oe_stat_button" type="action" attrs="{'invisible':[('use_tasks','=', False)]}"
name="%(act_project_project_2_project_task_all)d" icon="fa-tasks">
<field string="Tasks" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/>
</button>
<button class="oe_inline oe_stat_button" name="attachment_tree_view" type="object" icon="fa-files-o">
<field string="Documents" name="doc_count" widget="statinfo"/>
</button>
</div>
<notebook>
<page string="Emails" attrs="{'invisible': [('alias_domain', '=', False)]}">
<group name="group_alias">
@@ -254,7 +255,6 @@
</record>
<!-- Task -->
<record id="view_task_form2" model="ir.ui.view">
<field name="name">project.task.form</field>
<field name="model">project.task</field>
@@ -266,17 +266,15 @@
options="{'fold_field': 'fold'}"/>
</header>
<sheet string="Task">
<div class="row">
<h1 class="col-xs-11">
<field class="oe_inline oe_left" name="priority" widget="priority"/>
<field name="name" placeholder="Task summary..." class="oe_inline"/>
</h1>
<div class="col-xs-1 text-right">
<field name="kanban_state" class="oe_inline" widget="kanban_state_selection"
<div class="oe_title">
<h1 class="o_row">
<field name="priority" widget="priority"/>
<field name="name" placeholder="Task summary..."/>
<field name="kanban_state" widget="kanban_state_selection"
options='{
"states_legend_field": "stage_id",
"states_legend": {"normal": "legend_normal", "blocked": "legend_blocked", "done": "legend_done"}}'/>
</div>
</h1>
</div>
<group>
<group>
@@ -357,29 +355,35 @@
<field name="date_deadline"/>
<field name="message_summary"/>
<field name="tag_ids"/>
<field name="displayed_image_id"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click">
<div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Edit Task</a></li></t>
<t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
<div class="o_dropdown_kanban dropdown" groups="base.group_user">
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable"><li><a type="edit">Edit Task</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
<div class="oe_kanban_content">
<div><b><field name="name"/></b></div>
<div>
<field name="tag_ids"/>
</div>
<div>
<strong><field name="name"/></strong>
</div>
<div class="text-muted">
<field name="project_id" invisible="context.get('default_project_id', False)"/><br/>
<t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())" t-set="red">oe_kanban_text_red</t>
<span t-attf-class="#{red || ''}"><i><field name="date_deadline"/></i></span>
</div>
<div class="oe_kanban_footer_left" style="margin-top:5px;">
<field name="tag_ids"/>
</div>
<div class="oe_kanban_bottom_left">
<field name="priority" widget="priority"/>
<t t-raw="record.message_summary.raw_value"/>
</div>
<div class="oe_kanban_bottom_right">
@@ -387,10 +391,12 @@
<div class="pull-left" groups="base.group_user">
<field name="kanban_state" widget="kanban_state_selection"
options='{"states_legend": {"normal": "legend_normal", "blocked": "legend_blocked", "done": "legend_done"}}'/>
<field name="priority" widget="priority"/>
</div>
</div>
</div>
<div t-if="record.displayed_image_id.value">
<field name="displayed_image_id" widget="attachment_image"/>
</div>
<div class="oe_clear"></div>
</div>
</t>
@@ -571,7 +577,7 @@
<p class="text-muted" colspan="2">
You can also give a tooltip about the use of the stars available in the kanban and form views.
</p>
<label for="legend_priority" string=" " class="fa fa-star fa-lg oe_star_on oe_project_kanban_legend"/>
<label for="legend_priority" string=" " class="fa fa-star fa-lg o_star_on oe_project_kanban_legend"/>
<field name="legend_priority" nolabel="1"/>
<p class="text-muted" colspan="2">
@@ -685,4 +691,4 @@
<menuitem action="project_tags_action" id="menu_project_tags_act" parent="base.menu_definitions" groups="base.group_no_one"/>
</data>
</openerp>
</openerp>
+5 -7
View File
@@ -10,17 +10,15 @@
<field name="priority" eval="50"/>
<field name="groups_id" eval="[(4, ref('project.group_project_user'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action" name="%(action_view_task)d"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(action_view_task)d"
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
icon="fa-tasks">
<field string="Tasks" name="task_count" widget="statinfo"/>
</button>
</xpath>
</button>
</div>
</field>
</record>
</data>
</openerp>
</openerp>
+3 -3
View File
@@ -1,14 +1,14 @@
odoo.define('project.update_kanban', function (require) {
var kanban_common = require('web_kanban.common');
var KanbanRecord = require('web_kanban.Record');
var KanbanView = require('web_kanban.KanbanView');
var data = require('web.data');
var session = require('web.session');
kanban_common.KanbanRecord.include({
KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'project.project') {
if (this.model === 'project.project') {
this.$('.o_project_kanban_boxes a').first().click();
} else {
this._super.apply(this, arguments);
@@ -1,45 +1,37 @@
.oe_kanban_view.o_kanban_dashboard.o_project_kanban {
@odoo-brand-optional: #21b799;
.o_kanban_view.o_kanban_dashboard.o_project_kanban {
.o_kanban_flexbox {
display: flex;
.o-flex-display();
position: relative;
}
.oe_kanban_record {
.o_kanban_record {
min-width: 300px;
max-width: 350px;
}
/*
.oe_kanban_record:hover .o_project_kanban_manage {
visibility: visible;
}
*/
.o_project_kanban_main {
margin-bottom: 40px; // give space for manage section at the bottom
width: 75%;
// give space for manage section at the bottom
margin-bottom: 40px;
width: 70%;
.o_primary {
font-size: larger;
.o_kanban_card_content {
font-size: 12px;
.o_primary {
font-size: larger;
}
}
.o_project_kanban_manage {
visibility: visible;
position: absolute;
bottom: 0;
margin-left: 10px;
margin-left: 16px;
margin-bottom: 10px;
}
.o_project_kanban_colorpicker {
padding: 8px;
}
.o_kanban_card_manage_pane {
border-color: lightgrey;
border-bottom-style: solid;
border-bottom-width: 1px;
.o_kanban_card_manage_title {
margin: 0;
@@ -48,12 +40,16 @@
}
.o_project_kanban_boxes {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-content: stretch;
.o-flex-display();
.o-flex-flow(column, nowrap);
.o-justify-content(flex-end);
.o-align-content(stretch);
width: 25%;
width: 30%;
> a:hover {
text-decoration: none;
}
.o_value {
font-size: x-large;
@@ -67,11 +63,11 @@
.o_project_kanban_box {
text-align: center;
padding: 15px 0 15px 0;
flex: 1 1 auto;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
.o-flex(1, 1, auto);
.o-flex-display();
.o-align-items(center);
.o-flex-flow(column, nowrap);
.o-justify-content(center);
}
.o_project_kanban_box:nth-child(even) {
background-color: grey;
@@ -80,4 +76,4 @@
background-color: @odoo-brand-optional;
}
}
}
}
+10 -12
View File
@@ -36,7 +36,7 @@
<div name="project">
<field name="project_id" on_change="on_change_project(project_id)" class="oe_inline" context="{'default_use_issues':1}"/>
<field name="can_escalate" invisible="1"/>
<button name="case_escalate" string="Escalate" type="object" class="oe_link" attrs="{'invisible':[('can_escalate','=',False)]}" groups="base.group_user"/>
<button name="case_escalate" string="Escalate" type="object" class="btn-default" attrs="{'invisible':[('can_escalate','=',False)]}" groups="base.group_user"/>
</div>
</group>
<group>
@@ -168,8 +168,8 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Edit Issue</a></li></t>
<t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
<t t-if="widget.editable"><li><a type="edit">Edit Issue</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
@@ -278,12 +278,12 @@
<field name="label_issues" class="oe_inline oe_input_align" attrs="{'invisible': [('use_issues', '=', False)]}"/>
</div>
</xpath>
<xpath expr='//div[@name="buttons"]' position='inside'>
<button class="oe_inline oe_stat_button" type="action" attrs="{'invisible':[('use_issues','=', False)]}"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" attrs="{'invisible':[('use_issues','=', False)]}"
name="%(act_project_project_2_project_issue_all)d" icon="fa-bug">
<field string="Issues" name="issue_count" widget="statinfo" options="{'label_field': 'label_issues'}"/>
</button>
</xpath>
</div>
<xpath expr='//page[@name="project_stages"]' position="attributes">
<attribute name="attrs">{'invisible': [('use_tasks', '=', False),('use_issues','=',False)]}</attribute>
</xpath>
@@ -331,18 +331,16 @@
<field name="priority" eval="50"/>
<field name="groups_id" eval="[(4, ref('project.group_project_user'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action" name="%(action_view_issues)d"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(action_view_issues)d"
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
attrs="{'invisible': [('customer', '=', False)]}"
icon="fa-bug">
<field string="Issues" name="issue_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
</data>
</openerp>
</openerp>
@@ -40,10 +40,10 @@
<field name="effective_hours" widget="float_time"
groups="project.group_time_work_estimation_tasks"/>
</field>
<xpath expr='//div[@name="buttons"]' position="inside">
<button class="oe_inline oe_stat_button" name="open_timesheets" type="object" attrs="{'invisible':[('invoice_on_timesheets','=',False)]}"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="open_timesheets" type="object" attrs="{'invisible':[('invoice_on_timesheets','=',False)]}"
icon="fa-calendar" string="Timesheets"/>
</xpath>
</div>
<xpath expr='//field[@name="partner_id"]' position='after'>
<field name="pricelist_id" invisible="1"/>
</xpath>
+6 -6
View File
@@ -77,12 +77,12 @@
<field name="priority" eval="20"/>
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name="%(purchase.act_res_partner_2_purchase_order)d" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="%(purchase.act_res_partner_2_purchase_order)d" type="action"
attrs="{'invisible': [('supplier', '=', False)]}" icon="fa-shopping-cart">
<field string="Purchases" name="purchase_order_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
@@ -93,12 +93,12 @@
<field name="priority" eval="20"/>
<field name="groups_id" eval="[(4, ref('account.group_account_user'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name="%(purchase.act_res_partner_2_supplier_invoices)d" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="%(purchase.act_res_partner_2_supplier_invoices)d" type="action"
attrs="{'invisible': [('supplier', '=', False)]}" icon="fa-pencil-square-o" help="Supplier Bills">
<field string="Supplier Inv." name="supplier_invoice_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
</data>
+6 -6
View File
@@ -694,12 +694,12 @@
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name="action_view_purchases" type="object"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="action_view_purchases" type="object"
icon="fa-shopping-cart">
<field string="Purchases" name="purchase_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
@@ -709,12 +709,12 @@
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name="action_view_purchases" type="object"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="action_view_purchases" type="object"
icon="fa-shopping-cart">
<field string="Purchases" name="purchase_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
+1 -1
View File
@@ -30,7 +30,7 @@
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//div[contains(@class, 'oe_title')]" position="before">
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button type="object"
name="view_picking"
class="oe_stat_button"
@@ -39,11 +39,14 @@
<field name="state" widget="statusbar" statusbar_visible="draft,in_progress,open,done" statusbar_colors='{"in_progress":"blue"}'/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button name="open_product_line" type="object" string="Product Lines" class="oe_stat_button" icon="fa-list"
attrs="{'invisible': ['|', ('state', 'not in', ('open','done')), ('exclusive', '=', 'exclusive')]}" groups="purchase.group_advance_bidding"/>
<button name="open_rfq" type="object" string="RFQs/Bids" class="oe_stat_button" icon="fa-list-alt"
attrs="{'invisible': [('state', '=', 'draft')]}"/>
<button name="%(action_purchase_requisition_partner)d" type="action"
string="Request a Quotation" icon="gtk-execute"
attrs="{'invisible': ['|', ('line_ids','=',[]),('state', 'in', ('draft' ,'open','done'))]}"/>
</div>
<div class="pull-left">
<label for="name" class="oe_edit_only oe_inline"/>
@@ -89,11 +92,6 @@
</group>
</form>
</field>
<div class="oe_right oe_button_box" style="margin-top: 10px">
<button name="%(action_purchase_requisition_partner)d" type="action"
string="Request a Quotation" icon="gtk-execute"
attrs="{'invisible': ['|', ('line_ids','=',[]),('state', 'in', ('draft' ,'open','done'))]}"/>
</div>
<separator string="Requests for Quotation"/>
<field name="purchase_ids" options="{'reload_on_button': true}">
<tree string="Purchase Order">
+3 -3
View File
@@ -1,11 +1,11 @@
odoo.define('rating.kanban', function(require) {
"use strict";
var common = require('web_kanban.common');
var KanbanRecord = require('web_kanban.Record');
common.KanbanRecord.include({
KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'rating.rating') {
if (this.model === 'rating.rating') {
this.$('a').first().click();
} else {
this._super.apply(this, arguments);
+3 -3
View File
@@ -8,7 +8,7 @@
<field name="inherit_id" ref="project.edit_project"/>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<div name="button_box" position="inside">
<button name="action_view_task_rating"
attrs="{'invisible': ['|', '|', ('is_visible_happy_customer', '=', False), ('use_tasks','=', False), ('percentage_satisfaction_task', '=', -1)]}"
class="oe_stat_button oe_percent"
@@ -16,7 +16,7 @@
icon="fa-smile-o">
<field string="On tasks" name="percentage_satisfaction_task" widget="statinfo"/>
</button>
</xpath>
</div>
<xpath expr="//field[@name='privacy_visibility']" position="after">
<field name="is_visible_happy_customer"/>
</xpath>
@@ -38,4 +38,4 @@
</record>
</data>
</openerp>
</openerp>
@@ -8,7 +8,7 @@
<field name="inherit_id" ref="project.edit_project"/>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<div name="button_box" position="inside">
<button name="action_view_issue_rating"
attrs="{'invisible': ['|', '|', ('use_issues','=', False), ('is_visible_happy_customer','=', False), ('percentage_satisfaction_issue', '=', -1)]}"
class="oe_stat_button oe_percent"
@@ -16,7 +16,7 @@
icon="fa-smile-o">
<field string="On issues" name="percentage_satisfaction_issue" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
+4 -7
View File
@@ -34,9 +34,7 @@
<field name="sale_order_count"/>
</field>
<xpath expr="//div[@class='oe_kanban_partner_links']" position="inside">
<a name="%(sale.act_res_partner_2_sale_order)d" type="action" t-if="record.sale_order_count.value>0">
<t t-esc="record.sale_order_count.value"/> Sales
</a>
<span t-if="record.sale_order_count.value>0" class="badge"><i class="fa fa-fw fa-strikethrough"/><t t-esc="record.sale_order_count.value"/></span>
</xpath>
</field>
</record>
@@ -48,16 +46,15 @@
<field name="priority" eval="20"/>
<field name="groups_id" eval="[(4, ref('base.group_sale_salesman'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action" name="%(sale.act_res_partner_2_sale_order)d"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(sale.act_res_partner_2_sale_order)d"
attrs="{'invisible': [('customer', '=', False)]}"
icon="fa-strikethrough">
<field string="Sales" name="sale_order_count" widget="statinfo"/>
</button>
</xpath>
</div>
</field>
</record>
</data>
</openerp>
+14 -14
View File
@@ -143,14 +143,7 @@
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
</header>
<sheet>
<div class="oe_title">
<h1>
<label string="Quotation " attrs="{'invisible': [('state', 'not in', ('draft', 'sent'))]}"/>
<label string="Sales Order " attrs="{'invisible': [('state', 'in', ('draft', 'sent'))]}"/>
<field name="name" class="oe_inline" readonly="1"/>
</h1>
</div>
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button name="action_view_invoice"
type="object"
class="oe_stat_button"
@@ -159,6 +152,13 @@
<field name="invoice_count" widget="statinfo" string="Invoices"/>
</button>
</div>
<div class="oe_title">
<h1>
<label string="Quotation " attrs="{'invisible': [('state', 'not in', ('draft', 'sent'))]}"/>
<label string="Sales Order " attrs="{'invisible': [('state', 'in', ('draft', 'sent'))]}"/>
<field name="name" class="oe_inline" readonly="1"/>
</h1>
</div>
<group>
<group>
<field name="partner_id" on_change="onchange_partner_id(partner_id, context)" domain="[('customer','=',True)]" context="{'search_default_customer':1, 'show_address': 1}" options='{"always_reload": True}'/>
@@ -591,12 +591,12 @@
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="groups_id" eval="[(4, ref('base.group_sale_salesman'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name="action_view_sales"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="action_view_sales"
type="object" icon="fa-strikethrough">
<field string="Sales" name="sales_count" widget="statinfo" />
</button>
</xpath>
</div>
</field>
</record>
@@ -606,12 +606,12 @@
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="groups_id" eval="[(4, ref('base.group_sale_salesman'))]"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" name="action_view_sales"
<div name="button_box" position="inside">
<button class="oe_stat_button" name="action_view_sales"
type="object" icon="fa-strikethrough">
<field string="Sales" name="sales_count" widget="statinfo" />
</button>
</xpath>
</div>
</field>
</record>
+7 -7
View File
@@ -29,21 +29,21 @@
<button attrs="{'invisible': [('probability', '>', 0)]}" string="New Quotation" name="%(sale_action_quotations_new)d" type="action"
context="{'search_default_partner_id': partner_id, 'default_partner_id': partner_id}"/>
</xpath>
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline oe_stat_button" type="action"
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action"
name="%(sale_action_quotations)d" icon="stat_button_icon fa fa-usd"
context="{'search_default_partner_id': partner_id, 'default_partner_id': partner_id}">
<field name="sale_number" widget="statinfo" string="Quotes"/>
</button>
<button class="oe_inline oe_stat_button" type="action" attrs="{'invisible': [('sale_amount_total', '=', 0)]}"
<button class="oe_stat_button" type="action" attrs="{'invisible': [('sale_amount_total', '=', 0)]}"
name="%(sale_action_quotations)d" icon="stat_button_icon fa fa-usd"
context="{'search_default_partner_id': partner_id, 'default_partner_id': partner_id}">
<div>
<strong><field name="sale_amount_total" class="oe_inline" widget="monetary" options="{'currency_field': 'company_currency'}"/></strong>
<div><field name="sale_number" class="oe_inline"/> Orders</div>
<div class="o_form_field 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>
</button>
</xpath>
</div>
</data>
</field>
</record>
+1 -1
View File
@@ -47,7 +47,7 @@
</div>
</div>
<div t-if="widget.view.is_action_enabled('edit')" class="o_kanban_card_manage_settings row">
<div t-if="widget.editable" class="o_kanban_card_manage_settings row">
<div class="col-xs-8">
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</div>
@@ -2,7 +2,7 @@ odoo.define('sales_team.update_kanban', function (require) {
"use strict";
var KanbanView = require('web_kanban.KanbanView');
var kanban_common = require('web_kanban.common');
var KanbanRecord = require('web_kanban.Record');
var data = require('web.data');
var session = require('web.session');
@@ -40,9 +40,9 @@ KanbanView.include({
},
});
kanban_common.KanbanRecord.include({
KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'crm.team') {
if (this.model === 'crm.team') {
this.$('.oe_kanban_crm_salesteams_list a').first().click();
} else {
this._super.apply(this, arguments);
+10 -10
View File
@@ -222,18 +222,18 @@
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<div name="button_box" position="inside">
<button class="oe_stat_button"
name="%(product_open_quants)d"
icon="fa-building-o"
type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_locations">
<field name="qty_available2" widget="statinfo"/>
</button>
<button class="oe_inline oe_stat_button" string="Moves" name= "%(act_product_stock_move_open)d" type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_stock_user" icon="fa-arrows-v"/>
<button class="oe_inline oe_stat_button" name="%(product_open_orderpoint)d" type="action"
<button class="oe_stat_button" string="Moves" name= "%(act_product_stock_move_open)d" type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_stock_user" icon="fa-arrows-v"/>
<button class="oe_stat_button" name="%(product_open_orderpoint)d" type="action"
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-refresh" string="Reordering Rules"/>
<button class="oe_inline oe_stat_button" name="action_view_routes" string="Routes" type="object" icon="fa-cogs" attrs="{'invisible':[('type', '=', 'service')]}" />
</xpath>
<button class="oe_stat_button" name="action_view_routes" string="Routes" type="object" icon="fa-cogs" attrs="{'invisible':[('type', '=', 'service')]}" />
</div>
</field>
</record>
@@ -242,18 +242,18 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<div name="button_box" position="inside">
<button class="oe_stat_button"
name="action_open_quants"
icon="fa-building-o"
type="object" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_locations">
<field name="qty_available2" widget="statinfo"/>
</button>
<button class="oe_inline oe_stat_button" string="Moves" name= "action_view_stock_moves" type="object" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_stock_user" icon="fa-arrows-v"/>
<button class="oe_inline oe_stat_button" name="action_view_orderpoints" type="object"
<button class="oe_stat_button" string="Moves" name= "action_view_stock_moves" type="object" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_stock_user" icon="fa-arrows-v"/>
<button class="oe_stat_button" name="action_view_orderpoints" type="object"
attrs="{'invisible':[('type', 'in', ('service','consu'))]}" icon="fa-refresh" string="Reordering Rules"/>
<button class="oe_inline oe_stat_button" name="action_view_routes" string="Routes" type="object" icon="fa-cogs" attrs="{'invisible':[('type', '=', 'service')]}" />
</xpath>
<button class="oe_stat_button" name="action_view_routes" string="Routes" type="object" icon="fa-cogs" attrs="{'invisible':[('type', '=', 'service')]}" />
</div>
</field>
</record>
</data>
+1 -1
View File
@@ -100,7 +100,7 @@
</div>
</div>
<div t-if="widget.view.is_action_enabled('edit')" class="o_kanban_card_manage_settings row">
<div t-if="widget.editable" class="o_kanban_card_manage_settings row">
<div class="col-xs-8">
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</div>
+15 -17
View File
@@ -195,7 +195,7 @@
<field name="model">stock.production.lot</field>
<field name="arch" type="xml">
<form string="Serial Number">
<div class="oe_button_box oe_right">
<div class="oe_button_box" name="button_box">
<button name="action_traceability" icon="fa-arrow-up" class="oe_stat_button" string="Traceability" type="object" attrs="{'invisible': [('quant_ids','=',[])]}"/>
</div>
<div class="oe_title">
@@ -316,7 +316,7 @@
<field name="model">stock.location</field>
<field name="arch" type="xml">
<form string="Stock Location">
<div class="oe_right oe_button_box" name="buttons">
<div class="oe_button_box" name="button_box">
<button string="Current Stock"
class="oe_stat_button"
icon="fa-building-o" name="%(location_open_quants)d" type="action"
@@ -532,7 +532,7 @@
<field name="arch" type="xml">
<form string="Warehouse">
<sheet>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button name="view_all_routes_for_wh"
string="Routes"
icon="fa-refresh"
@@ -703,7 +703,7 @@
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,partially_available,assigned,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="button_box">
<div class="oe_button_box" name="button_box">
</div>
<h1>
<field name="name" class="oe_inline" attrs="{'invisible': [('name','=','/')]}" readonly="1"/>
@@ -1564,7 +1564,7 @@
<field name="arch" type="xml">
<form string="Reordering Rules">
<sheet>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button name="action_view_proc_to_process" type="object" string="Procurement Orders to Process"/>
</div>
<group>
@@ -1631,9 +1631,9 @@
<field name="route_ids" widget="many2many_tags"/>
</group>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="do_view_pickings" class="oe_stat_button" icon="fa-bars" string="Group's Pickings" type="object"/>
</xpath>
</div>
<xpath expr="//field[@name='rule_id']" position="replace">
<field name="rule_id" domain="['|', ('location_id', '=', False), ('location_id', '=', location_id)]"/>
<field name="partner_dest_id"/>
@@ -1759,8 +1759,8 @@
<field eval="10" name="priority"/>
<field name="arch" type="xml">
<form string="Quants" create="false" edit="false">
<div class="oe_right oe_button_box">
<button name="action_view_quant_history" type="object" string="Quant History"/>
<div class="oe_button_box" name="button_box">
<button name="action_view_quant_history" type="object" string="Quant History"/>
</div>
<group>
<field name="product_id"/>
@@ -1861,11 +1861,12 @@
<field name="arch" type="xml">
<form string="Package">
<sheet>
<div class="oe_right oe_button_box">
<button class="oe_inline" name="unpack" string="Unpack" type="object"/>
<button class="oe_inline oe_stat_button" name="%(action_picking_tree_all)d"
<div class="oe_button_box" name="button_box">
<button name="unpack" string="Unpack" type="object"/>
<button class="oe_stat_button" name="%(action_picking_tree_all)d"
string="Package Transfers" type="action"
widget="statinfo" icon="fa-dropbox"/>
<button name="get_content_package" type="object" string="View Contained Packages content" icon="gtk-execute" attrs="{'invisible': [('children_ids','=',[])]}"/>
</div>
<div class="oe_title">
<label for="name" string="Package Reference" class="oe_edit_only"/>
@@ -1895,9 +1896,6 @@
</tree>
</field>
<div class="oe_right oe_button_box" style="margin-top: 10px">
<button name="get_content_package" type="object" string="View Contained Packages content" icon="gtk-execute" attrs="{'invisible': [('children_ids','=',[])]}"/>
</div>
<separator string="Contained Packages"/>
<field name="children_ids">
<tree string="Contained Packages">
@@ -2050,9 +2048,9 @@
<field name="model">procurement.group</field>
<field name="inherit_id" ref="procurement.procurement_group_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<div name="button_box" position="inside">
<button name="%(do_view_pickings)d" string="Pickings" type="action"/>
</xpath>
</div>
</field>
</record>
@@ -11,7 +11,7 @@
<field name="state" widget="statusbar" statusbar_visible="in_progress,done"/>
</header>
<sheet>
<div class="oe_right oe_button_box">
<div class="oe_button_box" name="button_box">
<button name="print_picking" string="Print all pickings" type="object"/>
</div>
<div class="oe_title">
+3 -4
View File
@@ -35,8 +35,7 @@
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="button_box">
</div>
<div class="oe_button_box" name="button_box"/>
<group col="2">
<group>
<field name="survey_id"/>
@@ -184,11 +183,11 @@
<field name="public_url" />
<templates>
<div t-name="kanban-box" t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click">
<div class="oe_dropdown_toggle oe_dropdown_kanban" t-if="widget.view.is_action_enabled('edit')">
<div class="oe_dropdown_toggle oe_dropdown_kanban" t-if="widget.editable">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<li><a type="edit">Edit Survey</a></li>
<li t-if="widget.view.is_action_enabled('delete')"><a type="delete">Delete</a></li>
<li t-if="widget.deletable"><a type="delete">Delete</a></li>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
@@ -186,6 +186,11 @@ return {
list_widget_registry: new Registry(),
search_widgets_registry: new Registry(),
search_filters_registry: new Registry(),
// necessary to make the kanban view compatible between
// community and enterprise edition
one2many_view_registry: new Registry(),
};
@@ -285,7 +285,7 @@ var Priority = FieldChar.extend({
},
render_value: function() {
this.priorities = this.prepare_priority();
this.$el.html(QWeb.render("Priority", {'widget': this}));
this.$el.html(QWeb.render("FormPriority", {'widget': this}));
if (!this.get('readonly')){
this.$el.find('li').on('click', this.set_priority.bind(this));
}
@@ -1584,6 +1584,7 @@ var StatInfo = common.AbstractField.extend({
}
}
this.$el.html(QWeb.render("StatInfo", options));
this.$el.addClass('o_stat_info');
},
});
+111
View File
@@ -0,0 +1,111 @@
odoo.define('web.Pager', function (require) {
"use strict";
var Widget = require('web.Widget');
var direction = {
previous: -1,
next: 1,
};
var Pager = Widget.extend({
template: "Pager",
events: {
'click .o-pager-previous': 'previous',
'click .o-pager-next': 'next',
},
// pager goes from 1 to size (included).
// current value is current_min (if limit === 1)
// or the interval [current_min, current_min + limit[ if limit > 1
init: function (parent, size, current_min, limit, options) {
this.state = {
size: size,
current_min: current_min,
limit: limit,
};
Object.defineProperty(this.state, 'current_max', {
get: function() {
return Math.min(this.current_min + this.limit - 1, this.size);
}
});
this.options = options || {};
this._super(parent);
},
start: function () {
this.$content = this.$('.o-pager-value');
this._render();
return this._super();
},
set_state: function (options) {
_.extend(this.state, options);
this._render();
},
previous: function(e) {
this._change_selection(direction.previous);
},
next: function() {
this._change_selection(direction.next);
},
disable: function() {
this.$('button').prop("disabled", true);
},
enable: function() {
this.$('button').prop("disabled", false);
},
_render: function () {
var state;
var size = this.state.size;
var current_min = this.state.current_min;
var current_max = this.state.current_max;
var single_page = 1 === current_min && current_max === size;
if (size === 0 || (single_page && this.options.single_page_hidden)) {
this.$el.hide();
} else {
this.$el.show();
if (single_page) {
this.disable();
} else {
this.enable();
}
if (this.state.limit === 1) {
state = "" + current_min + " / " + size;
} else {
state = "" + current_min + "-" + current_max + " / " + size;
}
this.$content.html(state);
}
},
_change_selection: function (direction) {
var size = this.state.size;
var current_min = this.state.current_min;
var limit = this.state.limit;
current_min = (current_min + limit*direction);
if (current_min > size) {
current_min = 1;
} else if ((current_min < 1) && (limit === 1)) {
current_min = size;
} else if ((current_min < 1) && (limit > 1)) {
current_min = size - ((size % limit) || limit) + 1;
}
this.state.current_min = current_min;
this.trigger('pager_changed', _.clone(this.state));
this._render();
},
});
return Pager;
});
@@ -0,0 +1,195 @@
// ------------------------------------------------------------------
// Odoo
// ------------------------------------------------------------------
// This file is necessary to make the community edition of the Odoo web
// client compatible with the enterprise edition.
// The problem is that we have two web clients in parallel, and every
// addons should behave properly with both.
@odoo-brand-optional-disabled: #6ED0BC; // Specifically used for status bar status arrows
@odoo-brand-primary: #337ab7;
@odoo-brand-optional: @odoo-brand-primary;
@odoo-brand-secondary: #8f8f8f;
@odoo-form-group-cols: 12;
@odoo-horizontal-padding: 16px;
@odoo-list-grey: #e2e2e0; // FIXME: listview thead background color
@odoo-main-color-muted: #a8a8a8;
@odoo-main-text-color: #666666;
@odoo-webclient-background-color: @odoo-brand-secondary;
@odoo-view-background-color: red;
@odoo-shadow-color: #303030;
@brand-primary: @odoo-brand-primary;
.oe-view-manager {
background-color: #f0eeee !important;
}
.o_kanban_view {
background-color: #f0eeee;
.o_kanban_header {
color: black !important;
}
.o_kanban_config i, .o_kanban_quick_add i {
color: #555 !important;
&:hover {
background-color: darken(#f0eeee, 10%) !important;
}
}
.o_column_folded {
background-color: #f0eeee !important;
border: none !important;
span.o_column_title, span.o_column_unfold {
// color: white !important;
}
}
.o_column_quick_create {
background-color: #f0eeee !important;
.o_kanban_add_column, .o_kanban_title {
color: black !important;
}
}
}
.oe_list {
background-color: white !important;
}
.btn-icon {
.btn-default;
}
.openerp .oe_avatar {
float: left;
}
.openerp .oe_button_box {
float: right;
}
@grid-gutter-width: 0;
.oe-control-panel .row {
margin-left: 15px;
margin-right: 15px;
}
.oe_form_field_one2many {
.oe-view-manager {
background-color: white;
.o_kanban_view {
background-color: white;
.o_kanban_record {
box-shadow: none;
}
}
}
}
// Buttons containing only an icon
.o_icon_button {
background-color: transparent;
border: 0;
padding: 0;
outline: none;
}
// Stars
.o_priority {
display: inline-block;
padding: 0;
margin: 0;
> a {
display: inline-block;
}
.o_star_on, .o_star_off {
color: @odoo-main-color-muted !important;
&:hover {
text-decoration: none;
}
}
.o_star_on {
color: gold !important;
}
}
.o_text_overflow {
display: block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top; // To update display context changed by overflow:hidden
}
.oe-o2m-control-panel {
background-color: white;
}
.oe_formview {
.oe_button_box {
.oe_stat_button {
.stat_button_icon {
display: inline-block;
}
// padding: @odoo-statbutton-vpadding @odoo-statbutton-spacing @odoo-statbutton-vpadding 0px;
text-align: left;
.o_button_icon {
// margin-left: @odoo-statbutton-spacing; // To create the button padding left (firefox bug)
display: inline-block;
vertical-align: middle;
&:before {
font-size: x-large;
vertical-align: middle;
}
width: 30%;
}
// .o_form_field_percent_pie {
// margin-left: @odoo-statbutton-spacing; // To create the button padding left (firefox bug)
// }
.o_stat_info { // contains the value and text
display: inline-block;
vertical-align: middle;
max-width: 70%;
// padding-right: @odoo-statbutton-spacing;
line-height: 1.2;
.o_stat_value {
.o_text_overflow;
font-weight: 700;
color: @odoo-brand-primary;
}
.o_stat_text {
.o_text_overflow;
font-size: small;
.o_stat_value {
display: inline;
}
}
}
// Some buttons only display text and directly use the WidgetButton template instead of StatInfo
> span {
.o_stat_info; // layout
font-size: small;
white-space: normal; // text on several lines if needed
}
}
}
}
+189
View File
@@ -0,0 +1,189 @@
// ------------------------------------------------------------------
// Margin
// ------------------------------------------------------------------
.utils-margin-loop(@index) when (@index < 256) {
.o-mt@{index} {margin-top: @index px;}
.o-mb@{index} {margin-bottom: @index px;}
.o-mr@{index} {margin-right: @index px;}
.o-ml@{index} {margin-left: @index px;}
.utils-margin-loop(@index * 2);
}
.utils-margin-loop(2);
// ------------------------------------------------------------------
// Padding
// ------------------------------------------------------------------
.o-webclient-padding(@top: 0px, @right: @odoo-horizontal-padding, @bottom: 0px, @left: @odoo-horizontal-padding) {
padding-top: @top;
padding-right: @right;
padding-bottom: @bottom;
padding-left: @left;
}
// ------------------------------------------------------------------
// Caret
// ------------------------------------------------------------------
.utils-caret-boilerplate() {
content: "";
display: inline-block;
width: 0;
height: 0;
vertical-align: middle;
}
.o-caret-down(@caret-width: @caret-width-base) {
.utils-caret-boilerplate;
border-bottom: 0;
border-left: @caret-width solid transparent;
border-right: @caret-width solid transparent;
border-top: @caret-width solid;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
.o-caret-up(@caret-width: @caret-width-base) {
.utils-caret-boilerplate;
border-bottom: @caret-width solid;
border-left: @caret-width solid transparent;
border-right: @caret-width solid transparent;
border-top: 0;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
.o-caret-left(@caret-width: @caret-width-base) {
.utils-caret-boilerplate;
border-bottom: @caret-width solid transparent;
border-left: 0;
border-right: @caret-width solid;
border-top: @caret-width solid transparent;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
.o-caret-right(@caret-width: @caret-width-base) {
.utils-caret-boilerplate;
border-bottom: @caret-width solid transparent;
border-left: @caret-width solid;
border-right: 0;
border-top: @caret-width solid transparent;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
// ------------------------------------------------------------------
// Vendor prefixes
// ------------------------------------------------------------------
// Flex
.o-flex-display() {
display: -ms-flexbox;
display: -moz-box;
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.o-inline-flex-display() {
display: -ms-inline-flexbox;
display: -moz-inline-box;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: inline-flex;
}
.o-flex-flow(@direction, @wrap) {
-ms-flex-flow: @direction @wrap;
-moz-flex-flow: @direction @wrap;
-webkit-flex-flow: @direction @wrap;
flex-flow: @direction @wrap;
}
.o-flex(@grow, @schrink, @basis) {
-ms-flex: @grow @schrink @basis;
-moz-flex: @grow @schrink @basis;
-webkit-box-flex: @grow;
-webkit-flex: @grow @schrink @basis;
flex: @grow @schrink @basis;
}
.o-justify-content(@justify) {
-moz-justify-content: @justify;
-webkit-justify-content: @justify;
justify-content: @justify;
}
.o-align-content(@align) {
-webkit-align-content: @align;
align-content: @align;
}
.o-align-items(@align) {
-webkit-align-items: @align;
align-items: @align;
}
.o-align-self(@align) {
-webkit-align-self: @align;
align-self: @align;
}
// Background-size
// https://css-tricks.com/perfect-full-page-background-image/
.o-background-size(@size) {
-webkit-background-size: @size;
-moz-background-size: @size;
-o-background-size: @size;
background-size: @size;
}
// ------------------------------------------------------------------
// Dropdowns
// ------------------------------------------------------------------
.o-selected-li() {
li {
position: relative;
> a {
padding: 3px 25px;
color: @odoo-main-text-color;
&:hover {
color: darken(@odoo-main-text-color, 10%);
}
}
&.selected {
> a {
color: darken(@odoo-main-text-color, 10%);
font-weight: bold;
&:before {
font-family: FontAwesome;
position: absolute;
left: 6px;
content: "\f00c";
}
}
}
}
}
// ------------------------------------------------------------------
// Select Appearance
// ------------------------------------------------------------------
.o-appearance(@value) {
-webkit-appearance: @value;
-moz-appearance: @value;
appearance: @value;
}
// ------------------------------------------------------------------
// Transform
// ------------------------------------------------------------------
.o-transform-origin(@x: 50%, @y: 50%, @z: 0) {
-ms-transform-origin: @x @y @z;
-webkit-transform-origin: @x @y @z;
-moz-transform-origin: @x @y @z;
transform-origin: @x @y @z;
}
// ------------------------------------------------------------------
// Position absolute
// ------------------------------------------------------------------
.o-position-absolute(@top: auto, @right: auto, @bottom: auto, @left: auto) {
position: absolute;
top: @top;
left: @left;
bottom: @bottom;
right: @right;
}
+21 -2
View File
@@ -1104,7 +1104,7 @@
</ul>
</div>
</t>
<t t-name="Priority">
<t t-name="FormPriority">
<ul style="list-style: none; padding-left: 2px; display: inline-block;">
<t t-foreach="widget.priorities" t-as="rec" >
<li t-att-data-value="rec.click_value" style="display: inline-block;">
@@ -1116,6 +1116,14 @@
</t>
</ul>
</t>
<t t-name="Priority">
<div class="o_priority">
<t t-foreach="widget.priorities" t-as="rec" >
<a t-if="!widget.get('readonly')" href="#" t-att-data-value="rec.click_value" t-att-title="rec.name" t-att-class="widget.get('value') gte rec.value and 'fa fa-star o_star_on' or 'fa fa-star o_star_off'"/>
<span t-if="widget.get('readonly')" t-att-data-value="rec.click_value" t-att-title="rec.name" t-att-class="widget.get('value') gte rec.value and 'fa fa-star o_star_on' or 'fa fa-star o_star_off'"/>
</t>
</div>
</t>
<t t-name="FieldEmail">
<span class="oe_form_field oe_form_field_email" t-att-style="widget.node.attrs.style">
<a t-if="widget.get('effective_readonly')" href="#" class="oe_form_uri" target="_blank"/>
@@ -1938,14 +1946,25 @@
<a href="javascript:void(0)"><t t-esc="text"/></a>
</t>
<t t-name="StatInfo">
<strong><t t-esc="value"/></strong><br/><t t-esc="text"/>
<span class="o_stat_value"><t t-esc="value"/></span>
<span class="o_stat_text"><t t-esc="text"/></span>
</t>
<button t-name="toggle_button" type="button"
t-att-title="widget.string"
style="box-shadow: none; white-space:nowrap;">
<img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
t-att-alt="widget.string"/>
</button>
<div t-name="Pager">
<span class="o-pager-value"></span>
<span class="btn-group btn-group-sm">
<button type="button" class="fa fa-chevron-left btn btn-icon o-pager-previous" accesskey="O"/>
<button type="button" class="fa fa-chevron-right btn btn-icon o-pager-next" accesskey="P"/>
</span>
</div>
<button t-name="FieldToggleBoolean" type="button"
t-att-title="widget.string" class="oe_toggle_button">
<img t-attf-src="#{_s}/web/static/src/img/icons/#{widget.icon}" t-att-alt="widget.string"/>
+3
View File
@@ -73,6 +73,8 @@
<script type="text/javascript" src="/web/static/lib/select2/select2.js"></script>
<link rel="stylesheet" href='/website/static/src/less/import_bootstrap.less'/>
<link rel="stylesheet" href="/web/static/src/less/enterprise_compatibility.less"/>
<link rel="stylesheet" href="/web/static/src/less/utils.less"/>
<script src="/web/static/lib/bootstrap/js/affix.js"></script>
<script src="/web/static/lib/bootstrap/js/alert.js"></script>
<script src="/web/static/lib/bootstrap/js/button.js"></script>
@@ -138,6 +140,7 @@
<script type="text/javascript" src="/web/static/src/js/widgets/notification.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/sidebar.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/progress_bar.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/pager.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/systray_menu.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/user_menu.js"></script>
<script type="text/javascript" src="/web/static/src/js/framework/dialog.js"></script>
+4 -4
View File
@@ -577,11 +577,11 @@
background: #ffffff;
}
.openerp .oe_popup_form .oe_kanban_buttons .oe_highlight {
.openerp .o_popup_form .oe_kanban_buttons .oe_highlight {
color: #404040;
background: none;
}
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight {
.openerp .o_popup_form .oe_kanban_buttons button.oe_highlight {
background-color: #efefef;
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
background-image: -webkit-linear-gradient(top, #efefef, #d8d8d8);
@@ -593,7 +593,7 @@
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
}
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight:active {
.openerp .o_popup_form .oe_kanban_buttons button.oe_highlight:active {
background-color: #e3e3e3;
background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6));
background-image: -webkit-linear-gradient(top, #e3e3e3, #f6f6f6);
@@ -605,7 +605,7 @@
-webkit-box-shadow: none;
-box-shadow: none;
}
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight:hover {
.openerp .o_popup_form .oe_kanban_buttons button.oe_highlight:hover {
background-color: #f6f6f6;
background-image: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
background-image: -webkit-linear-gradient(top, #f6f6f6, #e3e3e3);
+1 -1
View File
@@ -514,7 +514,7 @@
padding: 0px
background: #ffffff
.openerp
.oe_popup_form
.o_popup_form
.oe_kanban_buttons
.oe_highlight
color: #404040
@@ -1,15 +1,17 @@
odoo.define('web_kanban.compatibility', function (require) {
"use strict";
var common = require('web_kanban.common');
var kanban_widgets = require('web_kanban.widgets');
var KanbanRecord = require('web_kanban.Record');
var KanbanColumn = require('web_kanban.Column');
var KanbanView = require('web_kanban.KanbanView');
return;
openerp = window.openerp || {};
openerp.web_kanban = openerp.web_kanban || {};
openerp.web_kanban.AbstractField = common.AbstractField;
openerp.web_kanban.KanbanGroup = common.KanbanGroup;
openerp.web_kanban.KanbanRecord = common.KanbanRecord;
openerp.web_kanban.AbstractField = kanban_widgets.AbstractField;
openerp.web_kanban.KanbanGroup = KanbanColumn;
openerp.web_kanban.KanbanRecord = KanbanRecord;
openerp.web_kanban.KanbanView = KanbanView;
});
@@ -0,0 +1,245 @@
odoo.define('web_kanban.Column', function (require) {
"use strict";
var core = require('web.core');
var Dialog = require('web.Dialog');
var form_common = require('web.form_common');
var Widget = require('web.Widget');
var quick_create = require('web_kanban.quick_create');
var KanbanRecord = require('web_kanban.Record');
var _t = core._t;
var QWeb = core.qweb;
var RecordQuickCreate = quick_create.RecordQuickCreate;
var KanbanColumn = Widget.extend({
template: "KanbanView.Group",
events: {
'click .o_kanban_toggle_fold': function (e) {
e.preventDefault();
e.stopPropagation();
this.folded = true;
this.update_column();
},
'click .o_column_edit': 'edit_column',
'click .o_column_delete': 'delete_column',
'click .o_kanban_quick_add': 'add_quick_create',
'click .o_kanban_load_more': 'load_more',
},
custom_events: {
'kanban_record_delete': 'delete_record',
'cancel_quick_create': 'cancel_quick_create',
'quick_create_add_record': 'quick_create_add_record',
},
init: function(parent, group_data, options, record_options) {
this._super(parent);
this.data_records = group_data.records;
this.dataset = group_data.dataset;
this.records = [];
this.title = group_data.title;
this.id = group_data.id;
this.folded = group_data.attributes.folded;
this.fields = options.fields;
this.values = group_data.values;
this.quick_create = options.quick_create;
this.grouped_by_m2o = options.grouped_by_m2o;
this.editable = options.editable;
this.deletable = options.deletable;
this.records_editable = options.records_editable;
this.records_deletable = options.records_deletable;
this.relation = options.relation;
this.offset = 0;
this.remaining = this.dataset.size() - this.data_records.length;
this.record_options = _.extend(_.clone(record_options), {
group_info: this.values,
});
},
start: function() {
var self = this;
this.$header = this.$('.o_kanban_header');
for (var i = 0; i < this.data_records.length; i++) {
this.add_record(this.data_records[i], {no_update: true});
}
this.$header.tooltip();
this.update_column();
this.$el.sortable({
connectWith: '.o_kanban_group',
revert: 150,
delay: 100,
items: '> .o_kanban_record',
helper: 'clone',
cursor: 'move',
over: function () {
self.folded = false;
self.update_column();
},
update: function (event, ui) {
var record = ui.item.data('record');
var index = self.records.indexOf(record);
var test2 = $.contains(self.$el[0], record.$el[0]);
if (index >= 0 && test2) {
// resequencing records
record.$el.removeAttr('style'); // jqueryui sortable add display:block inline
self.trigger_up('kanban_column_resequence');
} else if (index >= 0 && !test2) {
// removing record from this column
self.records.splice(self.records.indexOf(record), 1);
self.dataset.remove_ids([record.id]);
} else {
// adding record to this column
self.records.push(record);
record.setParent(self);
self.trigger_up('kanban_column_add_record', {record: record});
}
self.update_column();
}
});
this.$el.click(function (event) {
if (self.$el.hasClass('o_column_folded')) {
event.preventDefault();
self.folded = false;
self.update_column();
}
});
},
is_empty: function () {
return !this.records.length;
},
add_record: function (data, options) {
var record = new KanbanRecord(this, data, this.record_options);
this.records.push(record);
this.dataset.ids = _.uniq(this.dataset.ids.concat(record.id));
if (options.position === 'before') {
record.insertAfter(this.quick_create_widget ? this.quick_create_widget.$el : this.$header);
} else {
var $load_more = this.$('.o_kanban_load_more');
if ($load_more.length) {
record.insertBefore($load_more);
} else {
record.appendTo(this.$el);
}
}
if (!options.no_update) {
this.update_column();
}
},
get_ids: function () {
var ids = [];
this.$('.o_kanban_record').each(function (index, r) {
ids.push($(r).data('record').id);
});
return ids;
},
update_column: function () {
var title = this.folded ? this.title + ' (' + this.records.length + ')' : this.title;
this.$header.find('.o_column_title').text(title);
this.$header.find('.o-kanban-count').text(this.records.length);
this.$el.toggleClass('o_column_folded', this.folded);
var tooltip;
if (this.remaining) {
tooltip = this.records.length + '/' + this.dataset.size() + _t(' records');
} else {
tooltip = this.records.length + _t(' records');
}
this.$header.tooltip().attr('data-original-title', tooltip);
if (!this.remaining) {
this.$('.o_kanban_load_more').remove();
} else {
this.$('.o_kanban_load_more').html(QWeb.render('KanbanView.LoadMore', {widget:this}))
}
},
delete_column: function (event) {
event.preventDefault();
var buttons = [
{
text: _t("Ok"),
classes: 'btn-primary',
close: true,
click: this.trigger_up.bind(this, 'kanban_column_delete')
},
{text: _t("Cancel"), close: true}
];
new Dialog(this, {
size: 'medium',
buttons: buttons,
$content: $('<div>', {
text: _t("Are you sure that you want to remove this column ?")
}),
}).open();
},
edit_column: function (event) {
event.preventDefault();
var dialog = new form_common.FormViewDialog(this, {
res_model: this.relation,
res_id: this.id,
title: _t("Edit Column"),
}).open();
dialog.on('record_saved', this, function () {
this.trigger_up('kanban_reload');
});
},
delete_record: function (event) {
event.stopped = false;
var self = this;
event.data.after = function cleanup () {
var index = self.records.indexOf(event.data.record);
self.records.splice(index, 1);
self.update_column();
};
},
add_quick_create: function () {
if (this.quick_create_widget) {
return;
}
var self = this;
var width = this.records.length ? this.records[0].$el.innerWidth() : this.$el.width() - 8;
this.quick_create_widget = new RecordQuickCreate(this, width);
this.quick_create_widget.insertAfter(this.$header);
this.quick_create_widget.$el.focusout(function () {
setTimeout(function() {
var hasFocus = !! (self.quick_create_widget.$(':focus').length > 0);
if (! hasFocus && self.quick_create_widget) {
self.cancel_quick_create();
}
}, 10);
});
},
cancel_quick_create: function () {
this.quick_create_widget.destroy();
this.quick_create_widget = undefined;
},
quick_create_add_record: function (event) {
this.trigger_up('column_add_record', event.data);
},
load_more: function (event) {
event.preventDefault();
this.trigger_up('kanban_load_more');
},
});
return KanbanColumn;
});
@@ -1,928 +0,0 @@
odoo.define('web_kanban.common', function (require) {
"use strict";
var core = require('web.core');
var data = require('web.data');
var form_common = require('web.form_common');
var formats = require('web.formats');
var framework = require('web.framework');
var ProgressBar = require('web.ProgressBar');
var pyeval = require('web.pyeval');
var Registry = require('web.Registry');
var session = require('web.session');
var time = require('web.time');
var utils = require('web.utils');
var web_client = require('web.web_client');
var Widget = require('web.Widget');
var QWeb = core.qweb;
var _t = core._t;
/**
* Interface to be implemented by kanban fields.
*
*/
var FieldInterface = {
/**
Constructor.
- parent: The widget's parent.
- field: A dictionary giving details about the field, including the current field's value in the
raw_value field.
- $node: The field <field> tag as it appears in the view, encapsulated in a jQuery object.
*/
init: function(parent, field, $node) {},
};
/**
* Abstract class for classes implementing FieldInterface.
*
* Properties:
* - value: useful property to hold the value of the field. By default, the constructor
* sets value property.
*
*/
var AbstractField = Widget.extend(FieldInterface, {
/**
Constructor that saves the field and $node parameters and sets the "value" property.
*/
init: function(parent, field, $node) {
this._super(parent);
this.field = field;
this.$node = $node;
this.options = pyeval.py_eval(this.$node.attr("options") || '{}');
this.set("value", field.raw_value);
},
});
var Priority = AbstractField.extend({
init: function(parent, field, $node) {
this._super.apply(this, arguments);
this.name = $node.attr('name');
this.parent = parent;
},
prepare_priority: function() {
var self = this;
var selection = this.field.selection || [];
var init_value = selection && selection[0][0] || 0;
var data = _.map(selection.slice(1), function(element, index) {
var value = {
'value': element[0],
'name': element[1],
'click_value': element[0],
};
if (index === 0 && self.get('value') == element[0]) {
value.click_value = init_value;
}
return value;
});
return data;
},
renderElement: function() {
this.record_id = this.parent.id;
this.priorities = this.prepare_priority();
var readonly = this.field && this.field.readonly;
if (readonly){
this.set('readonly', true);
}
this.$el = $(QWeb.render("Priority", {'widget': this}));
if (!readonly){
this.$el.find('li').click(this.do_action.bind(this));
}
},
do_action: function(e) {
var self = this;
var li = $(e.target).closest( "li" );
if (li.length) {
var value = {};
value[self.name] = String(li.data('value'));
return self.parent.view.dataset._model.call('write', [[self.record_id], value, self.parent.view.dataset.get_context()]).done(self.reload_record.bind(self.parent));
}
},
reload_record: function() {
this.do_reload();
},
});
var KanbanSelection = AbstractField.extend({
init: function(parent, field, $node) {
this._super.apply(this, arguments);
this.name = $node.attr('name');
this.parent = parent;
},
prepare_dropdown_selection: function() {
var self = this;
var data = [];
_.map(this.field.selection || [], function(res) {
var value = {
'name': res[0],
'tooltip': res[1],
'state_name': res[1],
};
var leg_opt = self.options && self.options.states_legend || null;
if (leg_opt && leg_opt[res[0]] && self.parent.group.values && self.parent.group.values[leg_opt[res[0]]]) {
value['state_name'] = self.parent.group.values[leg_opt[res[0]]];
value['tooltip'] = self.parent.group.values[leg_opt[res[0]]];
}
if (res[0] == 'normal') { value['state_class'] = 'oe_kanban_status'; }
else if (res[0] == 'done') { value['state_class'] = 'oe_kanban_status oe_kanban_status_green'; }
else { value['state_class'] = 'oe_kanban_status oe_kanban_status_red'; }
data.push(value);
});
return data;
},
renderElement: function() {
var self = this;
this.record_id = self.parent.id;
this.states = self.prepare_dropdown_selection();
this.$el = $(QWeb.render("KanbanSelection", {'widget': self}));
this.$el.find('li').click(self.do_action.bind(self));
},
do_action: function(e) {
var self = this;
var li = $(e.target).closest( "li" );
if (li.length) {
var value = {};
value[self.name] = String(li.data('value'));
return self.parent.view.dataset._model.call('write', [[self.record_id], value, self.parent.view.dataset.get_context()]).done(self.reload_record.bind(self.parent));
}
},
reload_record: function() {
this.do_reload();
},
});
/**
* Quick creation view.
*
* Triggers a single event "added" with a single parameter "name", which is the
* name entered by the user
*
* @class
* @type {*}
*/
var QuickCreate = Widget.extend({
template: 'KanbanView.quick_create',
/**
* close_btn: If true, the widget will display a "Close" button able to trigger
* a "close" event.
*/
init: function(parent, dataset, context, buttons) {
this._super(parent);
this._dataset = dataset;
this._buttons = buttons || false;
this._context = context || {};
},
start: function () {
var self = this;
self.$input = this.$el.find('input');
self.$input.keyup(function(event){
if(event.keyCode == 13){
self.quick_add();
}
});
$(".oe_kanban_quick_create").focusout(function (e) {
var val = self.$el.find('input').val();
if (/^\s*$/.test(val)) { self.trigger('close'); }
e.stopImmediatePropagation();
});
$(".oe_kanban_quick_create_add", this.$el).click(function () {
self.quick_add();
self.focus();
});
$(".oe_kanban_quick_create_close", this.$el).click(function (ev) {
ev.preventDefault();
self.trigger('close');
});
self.$input.keyup(function(e) {
if (e.keyCode == 27 && self._buttons) {
self.trigger('close');
}
});
},
focus: function() {
this.$el.find('input').focus();
},
/**
* Handles user event from nested quick creation view
*/
quick_add: function () {
var self = this;
var val = this.$input.val();
if (/^\s*$/.test(val)) { this.$el.remove(); return; }
this._dataset.call(
'name_create', [val, new data.CompoundContext(
this._dataset.get_context(), this._context)])
.then(function(record) {
self.$input.val("");
self.trigger('added', record[0]);
}, function(error, event) {
event.preventDefault();
return self.slow_create();
});
},
slow_create: function() {
var self = this;
var popup = new form_common.SelectCreatePopup(this);
popup.select_element(
self._dataset.model,
{
title: _t("Create: ") + (this.string || this.name),
initial_view: "form",
disable_multiple_selection: true
},
[],
{"default_name": self.$input.val()}
);
popup.on("elements_selected", self, function(element_ids) {
self.$input.val("");
self.trigger('added', element_ids[0]);
});
}
});
var KanbanRecord = Widget.extend({
template: 'KanbanView.record',
events: {
'click .o_kanban_manage_toggle_button': 'toggle_manage_pane',
},
init: function (parent, record) {
this._super(parent);
this.group = parent;
this.view = parent.view;
this.id = null;
this.set_record(record);
if (!this.view.state.records[this.id]) {
this.view.state.records[this.id] = {
folded: false
};
}
this.state = this.view.state.records[this.id];
this.fields = {};
},
set_record: function(record) {
var self = this;
this.id = record.id;
this.values = {};
_.each(record, function(v, k) {
self.values[k] = {
value: v
};
});
this.record = this.transform_record(record);
},
start: function() {
var self = this;
this._super();
this.init_content();
},
init_content: function() {
var self = this;
self.sub_widgets = [];
this.$("[data-field_id]").each(function() {
self.add_widget($(this));
});
this.$el.data('widget', this);
this.bind_events();
},
transform_record: function(record) {
var self = this,
new_record = {};
_.each(record, function(value, name) {
var r = _.clone(self.view.fields_view.fields[name] || {});
if ((r.type === 'date' || r.type === 'datetime') && value) {
r.raw_value = time.auto_str_to_date(value);
} else {
r.raw_value = value;
}
r.value = formats.format_value(value, r);
new_record[name] = r;
});
return new_record;
},
renderElement: function() {
this.qweb_context = {
record: this.record,
widget: this,
read_only_mode: this.view.options.read_only_mode,
};
for (var p in this) {
if (_.str.startsWith(p, 'kanban_')) {
this.qweb_context[p] = _.bind(this[p], this);
}
}
var $el = QWeb.render(this.template, {
'widget': this,
'content': this.view.qweb.render('kanban-box', this.qweb_context)
});
this.replaceElement($el);
this.replace_fields();
},
replace_fields: function() {
var self = this;
this.$("field").each(function() {
var $field = $(this);
var $nfield = $("<span></span");
var id = _.uniqueId("kanbanfield");
self.fields[id] = $field;
$nfield.attr("data-field_id", id);
$field.replaceWith($nfield);
});
},
add_widget: function($node) {
var $orig = this.fields[$node.data("field_id")];
var field = this.record[$orig.attr("name")];
var type = field.type;
type = $orig.attr("widget") ? $orig.attr("widget") : type;
var obj = fields_registry.get(type);
var widget = new obj(this, field, $orig);
this.sub_widgets.push(widget);
widget.replace($node);
},
bind_events: function() {
var self = this;
this.setup_color_picker();
this.$el.find('[title]').each(function(){
$(this).tooltip({
delay: { show: 500, hide: 0},
title: function() {
var template = $(this).attr('tooltip');
if (!self.view.qweb.has_template(template)) {
return false;
}
return self.view.qweb.render(template, self.qweb_context);
},
});
});
// If no draghandle is found, make the whole card as draghandle (provided one can edit)
if (!this.$el.find('.oe_kanban_draghandle').length) {
this.$el.children(':first')
.toggleClass('oe_kanban_draghandle', this.view.is_action_enabled('edit'));
}
this.$el.find('.oe_kanban_action').click(function(ev) {
ev.preventDefault();
var $action = $(this),
type = $action.data('type') || 'button',
method = 'do_action_' + (type === 'action' ? 'object' : type);
if ((type === 'edit' || type === 'delete') && ! self.view.is_action_enabled(type)) {
self.view.open_record(self.id, true);
} else if (_.str.startsWith(type, 'switch_')) {
self.view.do_switch_view(type.substr(7));
} else if (typeof self[method] === 'function') {
self[method]($action);
} else {
self.do_warn("Kanban: no action for type : " + type);
}
});
if (this.$el.find('.oe_kanban_global_click,.oe_kanban_global_click_edit').length) {
this.$el.on('click', function(ev) {
if (!ev.isTrigger && !$._data(ev.target, 'events')) {
var trigger = true;
var elem = ev.target;
var ischild = true;
var children = [];
while (elem) {
var events = $._data(elem, 'events');
if (elem == ev.currentTarget) {
ischild = false;
}
if (ischild) {
children.push(elem);
if (events && events.click) {
// do not trigger global click if one child has a click event registered
trigger = false;
}
}
if (trigger && events && events.click) {
_.each(events.click, function(click_event) {
if (click_event.selector) {
// For each parent of original target, check if a
// delegated click is bound to any previously found children
_.each(children, function(child) {
if ($(child).is(click_event.selector)) {
trigger = false;
}
});
}
});
}
elem = elem.parentElement;
}
if (trigger) {
self.on_card_clicked(ev);
}
}
});
}
},
/* actions when user click on the block with a specific class
* open on normal view : oe_kanban_global_click
* open on form/edit view : oe_kanban_global_click_edit
*/
on_card_clicked: function(ev) {
if (this.$el.find('.oe_kanban_global_click').size() > 0 && this.$el.find('.oe_kanban_global_click').data('routing')) {
framework.redirect(this.$el.find('.oe_kanban_global_click').data('routing') + "/" + this.id);
}
else if (this.$el.find('.oe_kanban_global_click_edit').size()>0)
this.do_action_edit();
else
this.do_action_open();
},
setup_color_picker: function() {
var self = this;
var $el = this.$el.find('ul.oe_kanban_colorpicker');
if ($el.length) {
$el.html(QWeb.render('KanbanColorPicker', {
widget: this
}));
$el.on('click', 'a', function(ev) {
ev.preventDefault();
var color_field = $(this).parents('.oe_kanban_colorpicker').first().data('field') || 'color';
var data = {};
data[color_field] = $(this).data('color');
self.view.dataset.write(self.id, data, {}).done(function() {
self.record[color_field] = $(this).data('color');
self.do_reload();
});
});
}
},
toggle_manage_pane: function(){
this.$('.o_kanban_card_content').toggleClass('o_visible o_invisible');
this.$('.o_kanban_card_manage_pane').toggleClass('o_visible o_invisible');
this.$('.o_kanban_manage_button_section').toggleClass(this.kanban_color((this.values['color'] && this.values['color'].value) || 0));
},
do_action_delete: function($action) {
var self = this;
function do_it() {
return $.when(self.view.dataset.unlink([self.id])).done(function() {
self.group.remove_record(self.id);
self.destroy();
});
}
if (this.view.options.confirm_on_delete) {
if (confirm(_t("Are you sure you want to delete this record ?"))) {
return do_it();
}
} else
return do_it();
},
do_action_edit: function($action) {
this.view.open_record(this.id, true);
},
do_action_open: function($action) {
this.view.open_record(this.id);
},
do_action_object: function ($action) {
var button_attrs = $action.data();
var node_context = button_attrs.context || {};
var context = new data.CompoundContext(node_context);
context.set_eval_context({
active_id: this.id,
active_ids: [this.id],
active_model: this.view.dataset.model
});
var action_data = _.extend({}, button_attrs, {context: context});
this.view.do_execute_action(action_data, this.view.dataset, this.id, this.do_reload);
},
do_action_url: function($action) {
return framework.redirect($action.attr("href"));
},
do_reload: function() {
var self = this;
this.view.dataset.read_ids([this.id], this.view.fields_keys.concat(['__last_update'])).done(function(records) {
_.each(self.sub_widgets, function(el) {
el.destroy();
});
self.sub_widgets = [];
if (records.length) {
self.set_record(records[0]);
self.renderElement();
self.init_content();
self.group.compute_cards_auto_height();
self.view.postprocess_m2m_tags();
} else {
self.destroy();
}
});
},
kanban_getcolor: function(variable) {
var index = 0;
switch (typeof(variable)) {
case 'string':
for (var i=0, ii=variable.length; i<ii; i++) {
index += variable.charCodeAt(i);
}
break;
case 'number':
index = Math.round(variable);
break;
default:
return '';
}
var color = (index % this.view.number_of_color_schemes);
return color;
},
kanban_color: function(variable) {
var color = this.kanban_getcolor(variable);
return color === '' ? '' : 'oe_kanban_color_' + color;
},
kanban_image: function(model, field, id, cache, options) {
options = options || {};
var url;
if (this.record[field] && this.record[field].value && !utils.is_bin_size(this.record[field].value)) {
url = 'data:image/png;base64,' + this.record[field].value;
} else if (this.record[field] && ! this.record[field].value) {
url = "/web/static/src/img/placeholder.png";
} else {
id = JSON.stringify(id);
if (options.preview_image)
field = options.preview_image;
url = session.url('/web/binary/image', {model: model, field: field, id: id});
if (cache !== undefined) {
// Set the cache duration in seconds.
url += '&cache=' + parseInt(cache, 10);
}
}
return url;
},
kanban_text_ellipsis: function(s, size) {
size = size || 160;
if (!s) {
return '';
} else if (s.length <= size) {
return s;
} else {
return s.substr(0, size) + '...';
}
},
kanban_compute_domain: function(domain) {
return data.compute_domain(domain, this.values);
}
});
var KanbanGroup = Widget.extend({
template: 'KanbanView.group_header',
init: function (parent, records, group, dataset) {
var self = this;
this._super(parent);
this.$has_been_started = $.Deferred();
this.view = parent;
this.group = group;
this.dataset = dataset;
this.dataset_offset = 0;
this.value = this.title = this.values = null;
if (this.group) {
this.values = group.values;
this.value = group.get('value');
this.title = group.get('value');
if (this.value instanceof Array) {
this.title = this.value[1];
this.value = this.value[0];
}
var field = this.view.group_by_field;
if (!_.isEmpty(field)) {
try {
this.title = formats.format_value(group.get('value'), field, false);
} catch(e) {}
}
}
if (this.title === false) {
this.title = _t('Undefined');
this.undefined_title = true;
}
var key = this.view.group_by + '-' + this.value;
if (!this.view.state.groups[key]) {
this.view.state.groups[key] = {
folded: group ? group.get('folded') : false
};
}
this.state = this.view.state.groups[key];
this.$records = null;
this.records = [];
this.$has_been_started.done(function() {
self.do_add_records(records);
});
},
start: function() {
var self = this,
def = this._super();
if (! self.view.group_by) {
self.$el.addClass("oe_kanban_no_group");
var QuickCreateClass = self.view.get_quick_create_class();
self.quick = (new QuickCreateClass(this, self.dataset, {}, false))
.on('added', self, self.proxy('quick_created'));
self.quick.replace($(".oe_kanban_no_group_qc_placeholder"));
}
this.$records = $(QWeb.render('KanbanView.group_records_container', { widget : this}));
this.$records.insertBefore(this.view.$el.find('.oe_kanban_groups_records td:last'));
this.$el.on('click', '.oe_kanban_group_dropdown li a', function(ev) {
var fn = 'do_action_' + $(ev.target).data().action;
if (typeof(self[fn]) === 'function') {
self[fn]($(ev.target));
}
});
this.$el.find('.oe_kanban_add').click(function () {
if (self.view.quick) {
self.view.quick.trigger('close');
}
if (self.quick) {
return false;
}
self.view.$el.find('.oe_view_nocontent').hide();
var ctx = {};
ctx['default_' + self.view.group_by] = self.value;
self.quick = new (self.view.get_quick_create_class())(this, self.dataset, ctx, true)
.on('added', self, self.proxy('quick_created'))
.on('close', self, function() {
self.view.$el.find('.oe_view_nocontent').show();
this.quick.destroy();
delete self.view.quick;
delete this.quick;
});
self.quick.appendTo($(".oe_kanban_group_list_header", self.$records));
self.quick.focus();
self.view.quick = self.quick;
});
// Add bounce effect on image '+' of kanban header when click on empty space of kanban grouped column.
this.$records.on('click', '.oe_kanban_show_more', this.do_show_more);
if (this.state.folded) {
this.do_toggle_fold();
}
this.$el.data('widget', this);
this.$records.data('widget', this);
this.$has_been_started.resolve();
var add_btn = this.$el.find('.oe_kanban_add');
add_btn.tooltip({delay: { show: 500, hide:1000 }});
this.$records.find(".oe_kanban_column_cards").click(function (ev) {
if (ev.target == ev.currentTarget) {
if (!self.state.folded) {
add_btn.openerpBounce();
}
}
});
this.is_started = true;
this.fetch_tooltip();
return def;
},
/*
* Form the tooltip, based on optional group_by_tooltip on the grouping field.
* This function goes through the arch of the view, finding the declaration
* of the field used to group. If group_by_tooltip is defined, use the previously
* computed values of the group to form the tooltip. */
fetch_tooltip: function() {
var self = this;
if (! this.group)
return;
var options = null;
var recurse = function(node) {
if (node.tag === "field" && node.attrs.name == self.view.group_by) {
options = pyeval.py_eval(node.attrs.options || '{}');
return;
}
_.each(node.children, function(child) {
recurse(child);
});
};
recurse(this.view.fields_view.arch);
if (options && options.group_by_tooltip) {
this.tooltip = _.compact(
_.union(
[this.title],
_.map(
options.group_by_tooltip,
function (key, value, list) { return self.values && self.values[value] && (key + "\n" + self.values[value]) || ''; }))
).join('\n\n');
this.$(".oe_kanban_group_title_text").attr("title", this.tooltip || this.title || "");
}
},
compute_cards_auto_height: function() {
// oe_kanban_no_auto_height is an empty class used to disable this feature
if (!this.view.group_by) {
var min_height = 0;
var els = [];
_.each(this.records, function(r) {
var $e = r.$el.children(':first:not(.oe_kanban_no_auto_height)').css('min-height', 0);
if ($e.length) {
els.push($e[0]);
min_height = Math.max(min_height, $e.outerHeight());
}
});
$(els).css('min-height', min_height);
}
},
destroy: function() {
this._super();
if (this.$records) {
this.$records.remove();
}
},
do_show_more: function(evt) {
var self = this;
var ids = self.view.dataset.ids.slice(0);
return this.dataset.read_slice(this.view.fields_keys.concat(['__last_update']), {
'limit': self.view.limit,
'offset': self.dataset_offset += self.view.limit
}).then(function(records) {
self.view.dataset.ids = ids.concat(_.difference(self.dataset.ids, ids));
self.do_add_records(records);
self.compute_cards_auto_height();
self.view.postprocess_m2m_tags();
return records;
});
},
do_add_records: function(records, prepend) {
var self = this;
var $list_header = this.$records.find('.oe_kanban_group_list_header');
var $show_more = this.$records.find('.oe_kanban_show_more');
var $cards = this.$records.find('.oe_kanban_column_cards');
_.each(records, function(record) {
var rec = new KanbanRecord(self, record);
if (!prepend) {
rec.appendTo($cards);
self.records.push(rec);
} else {
rec.prependTo($cards);
self.records.unshift(rec);
}
});
if ($show_more.length) {
var size = this.dataset.size();
$show_more.toggle(this.records.length < size).find('.oe_kanban_remaining').text(size - this.records.length);
}
},
remove_record: function(id, remove_from_dataset) {
for (var i = 0; i < this.records.length; i++) {
if (this.records[i]['id'] === id) {
this.records.splice(i, 1);
i--;
}
}
},
do_toggle_fold: function(compute_width) {
this.$el.add(this.$records).toggleClass('oe_kanban_group_folded');
this.state.folded = this.$el.is('.oe_kanban_group_folded');
this.$("ul.oe_kanban_group_dropdown li a[data-action=toggle_fold]").text((this.state.folded) ? _t("Unfold") : _t("Fold"));
},
do_action_toggle_fold: function() {
this.do_toggle_fold();
},
do_action_edit: function() {
var self = this;
self.do_action({
res_id: this.value,
name: _t("Edit column"),
res_model: self.view.group_by_field.relation,
views: [[false, 'form']],
type: 'ir.actions.act_window',
target: "new",
flags: {
action_buttons: true,
headless: true,
}
});
// to do : remove this horrible hack
var am = web_client.action_manager;
var form = am.dialog_widget.views.form.controller;
form.on("on_button_cancel", am.dialog, function() { return am.dialog.$dialog_box.modal('hide'); });
form.on('record_saved', self, function() {
am.dialog.$dialog_box.modal('hide');
self.view.do_reload();
});
},
do_action_delete: function() {
var self = this;
if (confirm(_t("Are you sure to remove this column ?"))) {
(new data.DataSet(self, self.view.group_by_field.relation)).unlink([self.value]).done(function(r) {
self.view.do_reload();
});
}
},
do_save_sequences: function() {
var self = this;
if (_.indexOf(this.view.fields_keys, 'sequence') > -1) {
var new_sequence = _.pluck(this.records, 'id');
self.view.dataset.resequence(new_sequence);
}
},
/**
* Handles a newly created record
*
* @param {id} id of the newly created record
*/
quick_created: function (record) {
var id = record, self = this;
self.view.remove_no_result();
self.trigger("add_record");
this.dataset.read_ids([id], this.view.fields_keys)
.done(function (records) {
self.view.dataset.ids.push(id);
self.do_add_records(records, true);
});
},
highlight: function(show){
if(show){
this.$el.addClass('oe_kanban_column_higlight');
this.$records.addClass('oe_kanban_column_higlight');
}else{
this.$el.removeClass('oe_kanban_column_higlight');
this.$records.removeClass('oe_kanban_column_higlight');
}
}
});
/**
* Kanban widgets: ProgressBar
* options
* - editable: boolean if current_value is editable
* - current_value: get the current_value from the field that must be present in the view
* - max_value: get the max_value from the field that must be present in the view
* - title: title of the gauge, displayed on top of the gauge
* - on_change: action to call when cliking and setting a value
*/
var KanbanProgressBar = AbstractField.extend({
events: {
'click': function() {
if(!this.readonly && this.progressbar.readonly) {
this.toggle_progressbar();
}
}
},
init: function (parent, field, node) {
this._super(parent, field, node);
var record = this.getParent().record;
this.progressbar = new ProgressBar(this, {
readonly: true,
value: record[this.options.current_value].raw_value,
max_value: record[this.options.max_value].raw_value,
title: this.options.title,
edit_max_value: this.options.edit_max_value,
});
this.readonly = !this.options.editable;
this.on_change = this.options.on_change;
},
start: function () {
var self = this;
var def = this.progressbar.appendTo('<div>').done(function() {
self.progressbar.$el.addClass(self.$el.attr('class'));
self.replaceElement(self.progressbar.$el);
});
return $.when(this._super(), def).then(function() {
if(!self.readonly) {
var parent = self.getParent();
self.progressbar.on('change:value change:max_value', self, function(e) {
var value = this.progressbar.get(this.progressbar.edit_max_value ? 'max_value' : 'value') || 0;
if(!isNaN(value)) {
parent.view.dataset.call(this.on_change, [parent.id, value]).then(function() {
self.toggle_progressbar();
});
}
});
}
});
},
toggle_progressbar: function() {
this.progressbar.readonly = !this.progressbar.readonly;
var $div = $('<div/>').insertAfter(this.$el);
this.progressbar.replace($div);
this.setElement(this.progressbar.$el);
},
});
var fields_registry = new Registry();
fields_registry
.add('priority', Priority)
.add('kanban_state_selection', KanbanSelection)
.add("progress", KanbanProgressBar);
return {
AbstractField: AbstractField,
registry: fields_registry,
QuickCreate: QuickCreate,
KanbanRecord: KanbanRecord,
KanbanGroup: KanbanGroup,
};
});
@@ -0,0 +1,127 @@
odoo.define('web_kanban.quick_create', function (require) {
"use strict";
var Widget = require('web.Widget');
var RecordQuickCreate = Widget.extend({
template: "KanbanView.QuickCreate",
events: {
'click .o_kanban_cancel': 'cancel',
'click .o_kanban_add': 'add_record',
'keypress input': function (event) {
if (event.keyCode === 13) {
this.add_record();
}
},
'keydown': function (event) {
if (event.keyCode === 27) {
this.trigger_up('cancel_quick_create');
}
},
},
init: function (parent, width) {
this._super(parent);
this.width = width;
},
start: function () {
this.$el.css({width: this.width});
this.$input = this.$('input');
this.$input.focus();
},
cancel: function () {
this.trigger_up('cancel_quick_create');
},
add_record: function () {
var value = this.$input.val();
this.$input.val('');
if (/^\s*$/.test(value)) { return; }
this.trigger_up('quick_create_add_record', {value: value});
this.$input.focus();
},
});
var ColumnQuickCreate = Widget.extend({
template: 'KanbanView.ColumnQuickCreate',
events: {
'click .o_kanban_add': function (event) {
console.log('click okanbanadd');
event.stopPropagation();
this.add_column();
},
'click .o_kanban_quick_create': function (event) {
console.log('click quickcreate');
event.stopPropagation();
},
'keypress input': function (event) {
if (event.keyCode === 13) {
this.add_column();
}
},
'click .o_kanban_cancel': function (event) {
this.folded = true;
this.update();
},
'keydown': function (event) {
if (event.keyCode === 27) {
this.folded = true;
this.update();
}
},
},
init: function (parent) {
this._super(parent);
this.folded = true;
},
start: function () {
this.$header = this.$('.o_column_header');
this.$quick_create = this.$('.o_kanban_quick_create');
this.$input = this.$('input');
this.$el.click(this.proxy('toggle'));
var self = this;
this.$el.focusout(function () {
setTimeout(function() {
var hasFocus = !! (self.$(':focus').length > 0);
if (! hasFocus) {
self.folded = true;
self.update();
}
}, 10);
});
},
toggle: function () {
this.folded = !this.folded;
this.update();
if (!this.folded) {
this.$input.focus();
}
},
update: function () {
this.$header.toggle(this.folded);
this.$quick_create.toggle(!this.folded);
},
add_column: function () {
var name = this.$input.val();
this.$input.val('');
if (/^\s*$/.test(name)) { return; }
this.trigger_up('quick_create_add_column', {value: name});
this.$input.focus();
}
});
return {
RecordQuickCreate: RecordQuickCreate,
ColumnQuickCreate: ColumnQuickCreate,
};
});
@@ -0,0 +1,275 @@
odoo.define('web_kanban.Record', function (require) {
"use strict";
var core = require('web.core');
var data = require('web.data');
var formats = require('web.formats');
var framework = require('web.framework');
var session = require('web.session');
var time = require('web.time');
var utils = require('web.utils');
var Widget = require('web.Widget');
var kanban_widgets = require('web_kanban.widgets');
var QWeb = core.qweb;
var fields_registry = kanban_widgets.registry;
var KanbanRecord = Widget.extend({
template: 'KanbanView.record',
events: {
'click .oe_kanban_action': 'on_kanban_action_clicked',
'click .o_kanban_manage_toggle_button': 'toggle_manage_pane',
},
custom_events: {
'kanban_update_record': 'update_record',
},
init: function (parent, record, options) {
this._super(parent);
this.fields = options.fields;
this.editable = options.editable;
this.deletable = options.deletable;
this.draggable = options.draggable;
this.read_only_mode = options.read_only_mode;
this.model = options.model;
this.group_info = options.group_info;
this.qweb = options.qweb;
this.sub_widgets = [];
this.init_content(record);
},
init_content: function (record) {
var self = this;
this.id = record.id;
this.values = {};
_.each(record, function(v, k) {
self.values[k] = {
value: v
};
});
this.record = this.transform_record(record);
var qweb_context = {
record: this.record,
widget: this,
read_only_mode: this.read_only_mode,
};
for (var p in this) {
if (_.str.startsWith(p, 'kanban_')) {
qweb_context[p] = _.bind(this[p], this);
}
}
this.content = this.qweb.render('kanban-box', qweb_context);
},
add_widgets: function () {
var self = this;
this.$("field").each(function() {
var $field = $(this);
var field = self.record[$field.attr("name")];
var type = $field.attr("widget") || field.type;
var Widget = fields_registry.get(type);
var widget = new Widget(self, field, $field);
widget.replace($field);
self.sub_widgets.push(widget);
});
},
start: function() {
this.add_widgets();
},
renderElement: function () {
this._super();
this.setup_color_picker();
this.$el.addClass('o_kanban_record');
this.$el.data('record', this);
if (this.$el.hasClass('oe_kanban_global_click') || this.$el.hasClass('oe_kanban_global_click_edit')) {
this.$el.on('click', this.proxy('on_global_click'));
}
},
transform_record: function(record) {
var self = this;
var new_record = {};
_.each(record, function(value, name) {
var r = _.clone(self.fields[name] || {});
if ((r.type === 'date' || r.type === 'datetime') && value) {
r.raw_value = time.auto_str_to_date(value);
} else {
r.raw_value = value;
}
r.value = formats.format_value(value, r);
new_record[name] = r;
});
return new_record;
},
update: function (record) {
_.invoke(this.sub_widgets, 'destroy');
this.sub_widgets = [];
this.init_content(record);
this.renderElement();
this.add_widgets();
},
kanban_image: function(model, field, id, cache, options) {
options = options || {};
var url;
if (this.record[field] && this.record[field].value && !utils.is_bin_size(this.record[field].value)) {
url = 'data:image/png;base64,' + this.record[field].value;
} else if (this.record[field] && ! this.record[field].value) {
url = "/web/static/src/img/placeholder.png";
} else {
id = JSON.stringify(id);
if (options.preview_image)
field = options.preview_image;
url = session.url('/web/binary/image', {model: model, field: field, id: id});
if (cache !== undefined) {
// Set the cache duration in seconds.
url += '&cache=' + parseInt(cache, 10);
}
}
return url;
},
kanban_getcolor: function(variable) {
if (typeof(variable) === 'number') {
return Math.round(variable) % 10;
}
if (typeof(variable) === 'string') {
var index = 0;
for (var i=0; i<variable.length; i++) {
index += variable.charCodeAt(i);
}
return index % 10;
}
return 0;
},
kanban_color: function(variable) {
var color = this.kanban_getcolor(variable);
return 'oe_kanban_color_' + color;
},
on_global_click: function (ev) {
if ($(ev.target).parents('.o_dropdown_kanban').length) {
return;
}
if (!ev.isTrigger) {
var trigger = true;
var elem = ev.target;
var ischild = true;
var children = [];
while (elem) {
var events = $._data(elem, 'events');
if (elem == ev.currentTarget) {
ischild = false;
}
if (ischild) {
children.push(elem);
if (events && events.click) {
// do not trigger global click if one child has a click event registered
trigger = false;
}
}
if (trigger && events && events.click) {
_.each(events.click, function(click_event) {
if (click_event.selector) {
// For each parent of original target, check if a
// delegated click is bound to any previously found children
_.each(children, function(child) {
if ($(child).is(click_event.selector)) {
trigger = false;
}
});
}
});
}
elem = elem.parentElement;
}
if (trigger) {
this.on_card_clicked(ev);
}
}
},
/* actions when user click on the block with a specific class
* open on normal view : oe_kanban_global_click
* open on form/edit view : oe_kanban_global_click_edit
*/
on_card_clicked: function() {
if (this.$el.hasClass('oe_kanban_global_click_edit') && this.$el.data('routing')) {
framework.redirect(this.$el.data('routing') + "/" + this.id);
} else if (this.$el.hasClass('oe_kanban_global_click_edit')) {
this.trigger_up('kanban_record_edit', {id: this.id});
} else {
this.trigger_up('kanban_record_open', {id: this.id});
}
},
toggle_manage_pane: function(event){
event.preventDefault();
this.$('.o_kanban_card_content').toggleClass('o_visible o_invisible');
this.$('.o_kanban_card_manage_pane').toggleClass('o_visible o_invisible');
this.$('.o_kanban_manage_button_section').toggleClass(this.kanban_color((this.values['color'] && this.values['color'].value) || 0));
},
on_kanban_action_clicked: function (ev) {
ev.preventDefault();
var $action = $(ev.currentTarget);
var type = $action.data('type') || 'button';
switch (type) {
case 'edit':
this.trigger_up('kanban_record_edit', {id: this.id});
break;
case 'open':
this.trigger_up('kanban_record_open', {id: this.id});
break;
case 'delete':
this.trigger_up('kanban_record_delete', {record: this});
break;
case 'action':
case 'object':
this.trigger_up('kanban_do_action', $action.data());
break;
default:
this.do_warn("Kanban: no action for type : " + type);
}
},
kanban_compute_domain: function(domain) {
return data.compute_domain(domain, this.values);
},
update_record: function (event) {
this.trigger_up('kanban_record_update', event.data);
},
setup_color_picker: function() {
var self = this;
var $colorpicker = this.$('ul.oe_kanban_colorpicker');
if (!$colorpicker.length) {
return;
}
$colorpicker.html(QWeb.render('KanbanColorPicker', {
widget: this
}));
$colorpicker.on('click', 'a', function(ev) {
ev.preventDefault();
var color_field = $colorpicker.data('field') || 'color';
var data = {};
data[color_field] = $(this).data('color');
self.trigger_up('kanban_record_update', data);
});
},
});
return KanbanRecord;
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,247 @@
odoo.define('web_kanban.widgets', function (require) {
"use strict";
var core = require('web.core');
var ProgressBar = require('web.ProgressBar');
var pyeval = require('web.pyeval');
var Registry = require('web.Registry');
var session = require('web.session');
var Widget = require('web.Widget');
var QWeb = core.qweb;
/**
* Interface to be implemented by kanban fields.
*
*/
var FieldInterface = {
/**
Constructor.
- parent: The widget's parent.
- field: A dictionary giving details about the field, including the current field's value in the
raw_value field.
- $node: The field <field> tag as it appears in the view, encapsulated in a jQuery object.
*/
init: function(parent, field, $node) {},
};
/**
* Abstract class for classes implementing FieldInterface.
*
* Properties:
* - value: useful property to hold the value of the field. By default, the constructor
* sets value property.
*
*/
var AbstractField = Widget.extend(FieldInterface, {
/**
Constructor that saves the field and $node parameters and sets the "value" property.
*/
init: function(parent, field, $node) {
this._super(parent);
this.field = field;
this.$node = $node;
this.options = pyeval.py_eval(this.$node.attr("options") || '{}');
this.set("value", field.raw_value);
},
});
var Priority = AbstractField.extend({
init: function(parent, field, $node) {
this._super.apply(this, arguments);
this.name = $node.attr('name');
},
prepare_priority: function() {
var self = this;
var selection = this.field.selection || [];
var init_value = selection && selection[0][0] || 0;
var data = _.map(selection.slice(1), function(element, index) {
var value = {
'value': element[0],
'name': element[1],
'click_value': element[0],
};
if (index === 0 && self.get('value') == element[0]) {
value.click_value = init_value;
}
return value;
});
return data;
},
renderElement: function() {
this.priorities = this.prepare_priority();
var readonly = this.field && this.field.readonly;
if (readonly){
this.set('readonly', true);
}
this.$el = $(QWeb.render("Priority", {'widget': this}));
if (!readonly){
this.$el.on('click', 'a', this.do_action.bind(this));
}
},
do_action: function(event) {
event.preventDefault();
var $a = $(event.currentTarget);
var data = {};
data[this.name] = String($a.data('value'));
this.trigger_up('kanban_update_record', data);
},
});
var KanbanSelection = AbstractField.extend({
init: function(parent, field, $node) {
this._super.apply(this, arguments);
this.name = $node.attr('name');
this.parent = parent;
},
prepare_dropdown_selection: function() {
var self = this;
var data = [];
_.map(this.field.selection || [], function(res) {
var value = {
'name': res[0],
'tooltip': res[1],
'state_name': res[1],
};
var leg_opt = self.options && self.options.states_legend || null;
if (leg_opt) {
var key = leg_opt[value.name];
var legend = self.parent.group_info[key];
if (legend) {
value.state_name = legend;
value.tooltip = legend;
}
}
if (res[0] == 'normal') { value.state_class = 'oe_kanban_status'; }
else if (res[0] == 'done') { value.state_class = 'oe_kanban_status oe_kanban_status_green'; }
else { value.state_class = 'oe_kanban_status oe_kanban_status_red'; }
data.push(value);
});
return data;
},
renderElement: function() {
var self = this;
this.states = this.prepare_dropdown_selection();
var state;
for(var i = 0 ; i < this.states.length ; i++) {
if(this.states[i].name === this.get('value')) {
state = this.states[i];
}
}
this.$el = $(QWeb.render("KanbanSelection", {'widget': this}));
this.$('a').first().find('span').removeClass().addClass(state.state_class);
this.$('ul li').show().filter(function() {
return ($(this).data('value') === state.name);
}).hide();
this.$('a').click(function (ev) {
ev.preventDefault();
});
this.$('li').click(this.set_kanban_selection.bind(this));
},
set_kanban_selection: function(e) {
e.preventDefault();
var self = this;
var $li = $(e.target).closest( "li" );
if ($li.length) {
var value = {};
value[self.name] = String($li.data('value'));
this.trigger_up('kanban_update_record', value, this);
}
},
});
var KanbanAttachmentImage = AbstractField.extend({
template: 'KanbanAttachmentImage',
});
/**
* Kanban widgets: ProgressBar
* options
* - editable: boolean if current_value is editable
* - current_value: get the current_value from the field that must be present in the view
* - max_value: get the max_value from the field that must be present in the view
* - title: title of the gauge, displayed on top of the gauge
* - on_change: action to call when cliking and setting a value
*/
var KanbanProgressBar = AbstractField.extend({
events: {
'click': function() {
if(!this.readonly && this.progressbar.readonly) {
this.toggle_progressbar();
}
}
},
init: function (parent, field, node) {
this._super(parent, field, node);
var record = this.getParent().record;
this.progressbar = new ProgressBar(this, {
readonly: true,
value: record[this.options.current_value].raw_value,
max_value: record[this.options.max_value].raw_value,
title: this.options.title,
edit_max_value: this.options.edit_max_value,
});
this.readonly = !this.options.editable;
this.on_change = this.options.on_change;
},
start: function () {
var self = this;
var def = this.progressbar.appendTo('<div>').done(function() {
self.progressbar.$el.addClass(self.$el.attr('class'));
self.replaceElement(self.progressbar.$el);
});
return $.when(this._super(), def).then(function() {
if(!self.readonly) {
var parent = self.getParent();
self.progressbar.on('change:value change:max_value', self, function(e) {
var value = this.progressbar.get(this.progressbar.edit_max_value ? 'max_value' : 'value') || 0;
if(!isNaN(value)) {
var data = {
method: this.on_change,
params: [parent.id, value],
callback: self.proxy('toggle_progressbar'),
};
self.trigger_up('kanban_call_method', data);
// parent.view.dataset.call(this.on_change, [parent.id, value]).then(function() {
// self.toggle_progressbar();
// });
}
});
}
});
},
toggle_progressbar: function() {
this.progressbar.readonly = !this.progressbar.readonly;
var $div = $('<div/>').insertAfter(this.$el);
this.progressbar.replace($div);
this.setElement(this.progressbar.$el);
},
});
var fields_registry = new Registry();
fields_registry
.add('priority', Priority)
.add('kanban_state_selection', KanbanSelection)
.add("attachment_image", KanbanAttachmentImage)
.add('progress', KanbanProgressBar);
return {
AbstractField: AbstractField,
registry: fields_registry,
};
});
@@ -1,7 +1,7 @@
.oe_kanban_view {
.o_kanban_view {
&.o_kanban_mobile {
.oe_kanban_record {
.o_kanban_record {
width: 400px;
}
span {
@@ -14,8 +14,6 @@
&.o_kanban_dashboard {
@odoo-brand-optional: #21b799;
.o_visible {
width: 100%;
}
@@ -43,8 +41,8 @@
margin-right: 0px !important;
}
.oe_kanban_colorpicker {
min-height: 21px;
li {
height: 0px;
@@ -52,45 +50,37 @@
}
}
.oe_kanban_record {
padding: 0;
position: relative;
margin: 10px;
// @media (max-width: @grid-float-breakpoint) {
// margin: 10px !important;
// }
}
// if invisible, it will no take more than its original height
// If invisible, elem will no take more than its original height
a, span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
position: relative;
width: 100%;
display: block;
}
.o_kanban_record {
padding: 0;
position: relative;
margin: 4px 8px;
}
a {
// color: @odoo-brand-optional;
color: @odoo-brand-optional;
}
.o_kanban_card_header {
display: flex;
display: -webkit-flex;
.o-flex-display();
background-color: lightgrey;
position: relative;
.o_kanban_card_header_title {
-webkit-flex: 3 0 0;
flex: 3 0 0;
padding: 8px;
.o-flex(3, 0, 0);
padding: 8px 16px;
.o_primary {
// color: @odoo-brand-optional;
font-variant: small-caps;
font-size: large;
color: @odoo-brand-optional;
font-weight: 700;
}
.o_secondary {
@@ -98,12 +88,11 @@
}
.o_kanban_manage_button_section {
-webkit-flex: 1 0 0;
flex: 1 0 0;
.o-flex(1, 0, 0);
padding: 16px;
.o_kanban_manage_toggle_button {
text-align: center;
text-align: right;
}
}
}
@@ -129,6 +118,7 @@
.o_kanban_card_manage_pane {
display: inline-block;
vertical-align: top;
padding: 0 8px;
}
.o_kanban_card_manage_section {
@@ -145,6 +135,7 @@
}
.o_kanban_card_manage_settings {
text-align: right;
padding: 8px;
border-color: lightgrey;
@@ -0,0 +1,500 @@
@o-kanban-record-margin: 4px;
.o_kanban_view {
.o-flex-display();
.o-align-content(stretch);
@media (max-width: @grid-float-breakpoint) {
padding: 0px;
}
.o_kanban_quick_create {
background-color: white;
margin: @o-kanban-record-margin;
box-shadow: 0px 0px 1px 1px lighten(@odoo-main-text-color, 10%);
padding: 3px;
input {
width: 100%;
margin: 4px 0;
}
}
.o_kanban_record {
min-width: 150px;
background-color: white;
margin: 4px 4px 8px 4px;
box-shadow: 0px 0px 1px 1px lighten(@odoo-main-text-color, 10%);
padding: 8px;
&.o_record_dragged {
background-color: @odoo-main-text-color;
}
&.oe_kanban_global_click, &.oe_kanban_global_click_edit {
cursor: pointer;
}
ul {
list-style-type: none;
padding: 0;
}
&.o_kanban_two_column {
.o-flex-display();
.oe_kanban_details {
position: relative;
display: inline-block;
.o-flex(1, 1, auto);
width: 0;
}
}
&.o_kanban_two_column_tags {
.o-flex-display();
.o-flex-flow(row, wrap);
.o_kanban_tags_section {
.o-flex(1, 1, 100%);
}
.o_kanban_image {
.o-flex(1, 1, 25%);
margin-right: 0;
> img {
box-shadow: none;
}
}
.oe_kanban_details {
position: relative;
.o-flex(1, 1, 75%);
ul {
margin-bottom: 0;
}
}
}
.o_kanban_title {
font-weight: bold;
margin-bottom: 3px;
}
.o_kanban_image {
.o-flex(0, 0, auto);
margin-right: 8px;
text-align: center;
img {
width: 64px;
height: 64px;
box-shadow: none;
}
}
.o_kanban_button {
margin-top: 15px;
> button, > a {
position: absolute;
bottom: 0;
right: 0;
}
}
&.ui-sortable-helper {
transform: rotate(3deg);
opacity: 0.9,
}
.o_dropdown_kanban {
float: right;
// Open the dropdown a the left side of the dropdown toggle
> .dropdown-menu {
left: auto;
right: 0;
padding: 3px;
}
> a {
padding: 3px;
color: @odoo-main-text-color;
}
&.open {
visibility: visible;
}
}
.o_kanban_footer {
.o-flex-display();
.o-justify-content(space-between);
> * {
flex: none;
}
}
&:hover {
.o_dropdown_kanban {
visibility: visible;
}
}
.o_dropdown_kanban {
@media (max-width: @grid-float-breakpoint) {
visibility: visible;
}
}
}
&.o_kanban_ungrouped {
.o-flex-flow(row, wrap);
.o-justify-content(flex-start);
padding: @o-kanban-record-margin @odoo-horizontal-padding - @o-kanban-record-margin;
@media (max-width: @grid-float-breakpoint) {
padding: 0;
}
.o_kanban_record {
.o-flex(1, 1, auto);
width: 320px;
@media (max-width: @grid-float-breakpoint) {
margin: 0 0 1px 0;
width: 100vw;
box-shadow: none;
}
}
.o_kanban_ghost {
height: 0;
min-height: 0 !important; // to prevent view writers to override this height
visibility: hidden;
margin-top: 0;
margin-bottom: 0;
padding: 0;
}
}
&.o_kanban_grouped {
min-height: 100%;
padding: 0 @odoo-horizontal-padding - @o-kanban-record-margin;
.o_kanban_record {
width: 300px;
&.o_kanban_small {
width: 240px;
}
}
}
.o_kanban_group {
.o-flex(0, 0, auto);
margin: 0 4px;
&.o_kanban_dragged {
background-color: @odoo-main-text-color;
.o_kanban_record {
visibility: hidden;
}
}
.o_kanban_header + .o_kanban_record {
margin-top: 0; // no margin top from the first card after kanban_header
}
.o_kanban_header {
color: white;
padding: 0 4px;
height: 50px;
line-height: 2.2;
cursor: move;
.o-flex-display();
.o_column_unfold {
display: none;
}
.o_column_title {
font-size: 18px;
font-weight: 300;
.o-flex(1, 1, auto);
white-space: nowrap;
padding-top: 5px;
}
.o-kanban-icon() {
// Share the style of `.o_kanban_quick_add` and `o_kanban_config`.
height: 50px;
width: 50px;
line-height: 1.8;
text-align: center;
color: white;
padding: 8px;
font-size: 22px;
cursor: pointer;
}
.o_kanban_quick_add i {
.o-kanban-icon;
&:hover {
background-color: @odoo-brand-optional;
}
}
.o_kanban_config i {
.o-kanban-icon;
&:hover {
background-color: darken(@gray-light, 10%);
}
}
.o_kanban_number {
color: @odoo-main-text-color;
text-align: center;
}
}
.o_kanban_record {
&.o_kanban_dragged {
> * {
visibility: hidden;
}
background-color: @odoo-main-text-color;
}
}
&.o_column_folded {
position: relative;
border-right: 1px solid @odoo-main-text-color;
margin: 0;
.o_column_title {
line-height: 1.3;
text-transform: uppercase;
transform-origin: left bottom;
transform: rotate(90deg);
top: 40px;
left: 15px;
position: absolute;
}
> .o_kanban_record, .o_kanban_quick_add, .o_kanban_config, .o_kanban_load_more {
display: none;
}
&:hover {
cursor: pointer;
background-color: darken(@gray-light, 10%);
}
.o_column_unfold {
display: block;
padding: 0 10px;
> i {
font-size: 22px;
padding-top: 15px;
}
}
background-color: @gray-light;
}
.o_kanban_load_more {
text-align: center;
a {
color: white;
font-weight: 300;
}
}
}
.oe_kanban_color_0 {
background-color: #FFFFFF;
color: #5a5a5a;
}
.oe_kanban_color_1 {
background-color: #d8d8d8;
color: #5e5e5e;
}
.oe_kanban_color_2 {
background-color: #e5d8e3;
color: #7a3737;
}
.oe_kanban_color_3 {
background-color: #ece9c2;
color: #756832;
}
.oe_kanban_color_4 {
background-color: #dee180;
color: #5d6937;
}
.oe_kanban_color_5 {
background-color: #abd4cc;
color: #1a7759;
}
.oe_kanban_color_6 {
background-color: #b8e3e8;
color: #1a5d83;
}
.oe_kanban_color_7 {
background-color: #f4ddab;
color: #5e5e5e;
}
.oe_kanban_color_8 {
background-color: #7f637d;
color: #a5a5a5;
}
.oe_kanban_color_9 {
background-color: #d8c5d5;
color: #5e5e5e;
}
.oe_kanban_color_10 {
background-color: #46C265;
color: #639B89;
}
.oe_tags {
display: block;
}
.o_kanban_tags {
margin-left: -8px;
.o_tag{
width: 50px;
height: 9px;
display: inline-block;
vertical-align: top;
}
}
.o_kanban_footer {
width: 100%;
}
.oe_kanban_avatar {
border-radius: 12px;
border: 1px solid @odoo-main-color-muted;
}
.o_progressbar {
.o_progressbar_title {
width: 20%;
}
.o_progress {
width: 60%;
height: 15px;
}
.o_progressbar_value {
width: 20%;
text-align: right;
}
}
.o_kanban_attachment_image {
// The image should take the hole card
margin: -8px;
> img {
width: 100%;
}
}
}
.oe_kanban_colorpicker {
li {
float: left;
&:first-child a {
border: 1px solid #ccc;
}
a {
width: 15px;
height: 16px;
display: inline-block;
border: 1px solid white;
}
}
}
.o_dropdown_kanban {
visibility: hidden;
}
.oe_kanban_avatar_smallbox {
height: 40px;
width: 40px;
box-shadow: 0 1px 4px @gray-light;
// border: 1px solid
// border-color: #e5e5e5 #dbdbdb #d2d2d2
// @include radius(3px)
// @include box-shadow(0 1px 2px rgba(0,0,0,0.2))
}
.o_kanban_shadow {
background-color: @odoo-main-text-color;
miw-width: 100px;
}
.o_column_quick_create {
.o-flex(0, 0, auto);
margin: 0;
padding: 8px;
position: relative;
background-color: @odoo-main-text-color;
cursor: pointer;
&:hover {
background-color: darken(@gray-light, 10%);
}
.o_column_header {
.o_kanban_add_column {
padding: 0 10px;
color: white;
> i {
font-size: 22px;
padding-top: 7px;
}
}
.o_kanban_title {
font-size: 18px;
font-weight: 300;
white-space: nowrap;
color: @gray-lighter;
text-transform: uppercase;
transform-origin: left bottom;
transform: rotate(90deg);
top: 40px;
left: 15px;
position: absolute;
}
}
.o_kanban_quick_create {
display: none;
width: 180px;
}
}
.oe_kanban_footer_left {
float: left;
}
.oe_kanban_bottom_right {
float: right;
}
.oe_kanban_bottom_left {
float: left;
}
.oe_kanban_status {
display: inline-block;
height: 12px;
width: 12px;
border-radius: 6px;
background-color: @odoo-brand-secondary;
&.oe_kanban_status_green {
background-color: @brand-success;
}
&.oe_kanban_status_red {
background-color: @brand-danger;
}
}
.o_form_field_one2many .oe_view_nocontent {
display: none;
}
+64 -80
View File
@@ -1,90 +1,72 @@
<template>
<t t-name="KanbanView">
<div class="oe_kanban_view">
<div class="oe_kanban_buttons"/>
<table class="oe_kanban_groups">
<tr class="oe_kanban_groups_headers">
<td class="oe_kanban_dummy_cell"><div/></td>
</tr>
<tr class="oe_kanban_groups_records">
<td class="oe_kanban_dummy_cell"><div/></td>
</tr>
</table>
</div>
</t>
<t t-name="KanbanView.buttons">
<t t-if="display">
<div class="oe_kanban_buttons">
<button type="button" class="oe_kanban_button_new btn btn-primary btn-sm">
<div>
<button type="button" class="btn btn-primary btn-sm o-kanban-button-new">
<t t-esc="widget.options.create_text || _t('Create')"/>
</button>
<span t-if="widget.is_action_enabled('group_create')" class="oe_alternative" style="display: none">
<span class="oe_fade">or</span>
<div class="oe_bounce_container">
<a href="#" class="oe_kanban_add_column text-info">Add a new column</a>
</div>
</span>
</div>
</t>
</t>
<t t-name="KanbanView.group_header">
<td class="oe_kanban_group_header">
<t t-if="widget.view.group_by">
<t t-set="parent" t-value="(widget.getParent())"/>
<div class="oe_kanban_header oe_semantic_html_override">
<t t-if="widget.view._is_quick_create_enabled()">
<div><i class="oe_kanban_add fa fa-plus" title="Quick create"/></div>
</t>
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<div class="oe_kanban_group_length">
<span class="oe_tag">
<t t-if="widget.group.get('length') &gt; 99"> 99+ </t><t t-if="widget.group.get('length') &lt;= 99"> <t t-esc="widget.group.get('length')"/> </t>
</span>
</div>
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu oe_kanban_group_dropdown">
<li><a data-action="toggle_fold" href="#">Fold</a></li>
<t t-if="widget.view.grouped_by_m2o and widget.value">
<li t-if="parent &amp;&amp; parent.is_action_enabled('group_edit')"><a data-action="edit" href="#">Edit</a></li>
<li t-if="parent &amp;&amp; parent.is_action_enabled('group_delete')"><a data-action="delete" href="#">Delete</a></li>
</t>
</ul>
</div>
<div class="oe_fold_column">
<div t-attf-class="oe_kanban_group_title #{widget.undefined_title ? 'oe_kanban_group_title_undefined' : ''}">
<div class="oe_kanban_group_title_text" t-att-title="widget.title"><t t-esc="widget.title"/></div>
</div>
<div class="oe_kanban_group_length oe_tag">
<t t-if="widget.group.get('length') &gt; 99"> 99+ </t><t t-if="widget.group.get('length') &lt;= 99"> <t t-esc="widget.group.get('length')"/> </t>
</div>
</div>
<span t-if="widget.title" class="oe_kanban_group_title_vertical">
<t t-esc="widget.title"/>
</span>
</div>
</t>
<t t-if="! widget.view.group_by &amp;&amp; widget.view._is_quick_create_enabled()">
<span class="oe_kanban_no_group_qc_placeholder"/>
</t>
</td>
</t>
<t t-name="KanbanView.group_records_container">
<td class="oe_kanban_column">
<div class="oe_kanban_group_list_header"/>
<div class="oe_kanban_column_cards"/>
<div class="oe_kanban_folded_column_cards"/>
<div class="oe_kanban_show_more">
<button class="oe_button">Show more... (<span class="oe_kanban_remaining"></span> remaining)</button>
<t t-name="KanbanView.Group">
<div class="o_kanban_group" t-att-data-id="widget.id">
<div class="o_kanban_header" t-att-title="widget.data_records.length + ' records'">
<span class="o_column_title"><t t-esc="widget.title"/></span>
<span class="o_column_unfold"><i class="fa fa-arrows-h"/></span>
<span class="o_kanban_config dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-gear"/></a>
<ul class="dropdown-menu" role="menu">
<li><a class="o_kanban_toggle_fold" href="#">Fold</a></li>
<t t-if="widget.grouped_by_m2o">
<li t-if="widget.editable and widget.id"><a class="o_column_edit" href="#">Edit</a></li>
<li t-if="widget.deletable and widget.id"><a class="o_column_delete" href="#">Delete</a></li>
</t>
</ul>
</span>
<t t-if="widget.quick_create">
<span class="o_kanban_quick_add"><i class="fa fa-plus"/></span>
</t>
</div>
<div t-if="widget.remaining > 0" class="o_kanban_load_more">
<t t-call="KanbanView.LoadMore"/>
</div>
</td>
</t>
<t t-name="KanbanView.record">
<div class="oe_fold_column oe_kanban_record">
<t t-raw="content"/>
</div>
</t>
<t t-name="KanbanView.LoadMore">
<a href="#">Load more... (<t t-esc="widget.remaining"/> remaining)</a>
</t>
<t t-name="KanbanView.ColumnQuickCreate">
<div class="o_column_quick_create">
<div class="o_column_header">
<span class="o_kanban_add_column"><i class="fa fa-chevron-right"/></span>
<span class="o_kanban_title">Add new Column</span>
</div>
<div class="o_kanban_quick_create">
<input type="text" placeholder="Add"/>
<button class="btn btn-primary o_kanban_add">Add</button>
<button class="btn btn-default o_kanban_cancel">Cancel</button>
</div>
</div>
</t>
<t t-name="KanbanView.record">
<t t-raw="widget.content"/>
</t>
<t t-name="KanbanView.QuickCreate">
<div class="o_kanban_quick_create">
<input type="text" placeholder="Add"/>
<button class="btn btn-primary o_kanban_add">Add</button>
<button class="btn btn-default o_kanban_cancel">Cancel</button>
</div>
</t>
<t t-name="KanbanColorPicker">
<li t-foreach="widget.view.number_of_color_schemes" t-as="color">
<li t-foreach="10" t-as="color">
<a href="#" t-att-data-color="color_index" t-attf-class="oe_kanban_color_#{color}"/>
</li>
</t>
@@ -98,11 +80,13 @@
</t>
</div>
<t t-name="KanbanView.nocontent">
<div class="oe_view_nocontent" style="position:absolute;">
<div class="oe_view_nocontent_bg"></div>
<div class="oe_view_nocontent_content">
<t t-raw="content"/>
</div>
<div class="oe_view_nocontent">
<t t-raw="content"/>
</div>
</t>
<t t-name="KanbanAttachmentImage">
<div class="o_kanban_attachment_image">
<img t-att-src="'/web/binary/image?model=ir.attachment&amp;field=datas&amp;id=' + widget.field.raw_value[0]"/>
</div>
</t>
</template>
+5 -2
View File
@@ -3,11 +3,14 @@
<data>
<template id="assets_backend" name="web_kanban assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/web_kanban/static/src/css/kanban.css"/>
<link rel="stylesheet" href="/web_kanban/static/src/less/kanban_dashboard.less"/>
<link rel="stylesheet" href="/web_kanban/static/src/less/kanban_view.less"/>
<script type="text/javascript" src="/web_kanban/static/src/js/kanban_record.js"></script>
<script type="text/javascript" src="/web_kanban/static/src/js/kanban_quick_create.js"></script>
<script type="text/javascript" src="/web_kanban/static/src/js/kanban_column.js"></script>
<script type="text/javascript" src="/web_kanban/static/src/js/kanban_view.js"></script>
<script type="text/javascript" src="/web_kanban/static/src/js/kanban_common.js"></script>
<script type="text/javascript" src="/web_kanban/static/src/js/kanban_widgets.js"></script>
<script type="text/javascript" src="/web_kanban/static/src/js/compatibility.js"></script>
</xpath>
</template>
@@ -2,10 +2,10 @@ odoo.define('web_kanban_gauge.widget', function (require) {
"use strict";
var core = require('web.core');
var kanban_common = require('web_kanban.common');
var kanban_widgets = require('web_kanban.widgets');
var AbstractField = kanban_common.AbstractField;
var fields_registry = kanban_common.registry;
var AbstractField = kanban_widgets.AbstractField;
var fields_registry = kanban_widgets.registry;
var _t = core._t;
/**
+1 -1
View File
@@ -11,4 +11,4 @@ class TestUi(openerp.tests.HttpCase):
def test_03_js_public(self):
self.phantom_js('/',"console.log('ok')","console")
def test_04_js_admin(self):
self.phantom_js('/web',"console.log('ok')","openerp.client.action_manager.inner_widget", login='admin')
self.phantom_js('/web',"console.log('ok')","odoo.__DEBUG__.services['web.web_client'].action_manager", login='admin')
@@ -1,7 +1,7 @@
.oe_WidgetWebsiteButton.danger .oe_publish {
display: none;
.oe_stat_button .o_stat_info:not(.published) > .o_stat_text.oe_publish {
display: none;
}
.oe_WidgetWebsiteButton.success .oe_unpublish {
.oe_stat_button .o_stat_info.published > .o_stat_text.oe_unpublish {
display: none;
}
.oe_form_field_html_frame iframe {
@@ -9,10 +9,13 @@ var form_widgets = require('web.form_widgets'); // required to guarantee that
var WidgetWebsiteButton = form_common.AbstractField.extend({
template: 'WidgetWebsiteButton',
render_value: function() {
// Hack to replace false value by unpublished because falsy form fields
// have classname o_form_field_empty and are hidden
if (!this.get_value()) {
this.set_value('unpublished');
}
this._super();
this.$()
.toggleClass("success", this.get_value())
.toggleClass("danger", !this.get_value());
this.$el.toggleClass("published", this.get_value() === true);
if (this.node.attrs.class) {
this.$el.addClass(this.node.attrs.class);
}
@@ -1,12 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="WidgetWebsiteButton">
<div class="oe_WidgetWebsiteButton success">
<strong class="oe_unpublish text-danger">Not<br/>Published</strong>
<strong class="oe_publish text-success">Published</strong>
</div>
</t>
<div t-name="WidgetWebsiteButton" class="o_stat_info published">
<span class="o_stat_text oe_unpublish text-danger">Not Published</span>
<span class="o_stat_text oe_publish text-success">Published</span>
</div>
<t t-name="FieldTextHtmlFrame">
<div class="oe_form_field oe_form_field_html_frame oe_form_embedded_html" t-att-style="widget.node.attrs.style">
@@ -52,8 +52,8 @@
<field name="arch" type="xml">
<form string="Blog Post">
<sheet>
<div class="oe_right oe_button_box">
<button class="oe_inline oe_stat_button" name="open_website_url"
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="open_website_url"
type="object" icon="fa-globe">
<field name="website_published" widget="website_button"/>
</button>

Some files were not shown because too many files have changed in this diff Show More