summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2015-06-15 16:31:27 +0200
committerGéry Debongnie <ged@odoo.com>2015-06-15 16:31:27 +0200
commit2c7367a8cc8d9e200b1fa2083ce0d80f8f4e4bd3 (patch)
treeaf916cff4d94554b1e9667913e3feb331ec81a13 /addons/web
parent5cb10d4fc9594f0c6825757c24d66d63664ce026 (diff)
parent82186a93bb3f93c36667835df68fa31dcacf97a2 (diff)
[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
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/static/src/js/framework/core.js5
-rw-r--r--addons/web/static/src/js/views/form_widgets.js3
-rw-r--r--addons/web/static/src/js/widgets/pager.js111
-rw-r--r--addons/web/static/src/less/enterprise_compatibility.less195
-rw-r--r--addons/web/static/src/less/utils.less189
-rw-r--r--addons/web/static/src/xml/base.xml23
-rw-r--r--addons/web/views/webclient_templates.xml3
7 files changed, 526 insertions, 3 deletions
diff --git a/addons/web/static/src/js/framework/core.js b/addons/web/static/src/js/framework/core.js
index 7bd4800ec98..30138102663 100644
--- a/addons/web/static/src/js/framework/core.js
+++ b/addons/web/static/src/js/framework/core.js
@@ -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(),
+
};
diff --git a/addons/web/static/src/js/views/form_widgets.js b/addons/web/static/src/js/views/form_widgets.js
index ee04f8376b4..760ea703d35 100644
--- a/addons/web/static/src/js/views/form_widgets.js
+++ b/addons/web/static/src/js/views/form_widgets.js
@@ -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');
},
});
diff --git a/addons/web/static/src/js/widgets/pager.js b/addons/web/static/src/js/widgets/pager.js
new file mode 100644
index 00000000000..c195aaf530d
--- /dev/null
+++ b/addons/web/static/src/js/widgets/pager.js
@@ -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;
+
+}); \ No newline at end of file
diff --git a/addons/web/static/src/less/enterprise_compatibility.less b/addons/web/static/src/less/enterprise_compatibility.less
new file mode 100644
index 00000000000..1cfd5120c34
--- /dev/null
+++ b/addons/web/static/src/less/enterprise_compatibility.less
@@ -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
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/less/utils.less b/addons/web/static/src/less/utils.less
new file mode 100644
index 00000000000..8b8d02898e6
--- /dev/null
+++ b/addons/web/static/src/less/utils.less
@@ -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;
+} \ No newline at end of file
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 00406837a47..52a7c8130a6 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -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"/>
diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml
index 3b935733230..b99979f2b04 100644
--- a/addons/web/views/webclient_templates.xml
+++ b/addons/web/views/webclient_templates.xml
@@ -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>