summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js5
-rw-r--r--addons/web/static/src/js/views/qweb/qweb_view.js202
-rw-r--r--addons/web/static/src/scss/webclient.scss7
3 files changed, 213 insertions, 1 deletions
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index 57b3771427b..ba00b4dbab7 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -456,7 +456,10 @@ var AbstractController = mvc.Controller.extend(ActionMixin, {
}
});
} else if ($target.attr('name')) {
- this.do_action($target.attr('name'));
+ this.do_action(
+ $target.attr('name'),
+ data.context && {additional_context: data.context}
+ );
} else {
this.do_action({
name: $target.attr('title') || _.str.strip($target.text()),
diff --git a/addons/web/static/src/js/views/qweb/qweb_view.js b/addons/web/static/src/js/views/qweb/qweb_view.js
new file mode 100644
index 00000000000..9e79ecf19d2
--- /dev/null
+++ b/addons/web/static/src/js/views/qweb/qweb_view.js
@@ -0,0 +1,202 @@
+/**
+ * Client-side implementation of a qweb view.
+ */
+odoo.define('web.qweb', function (require) {
+"use strict";
+
+var core = require('web.core');
+var AbstractView = require('web.AbstractView');
+var AbstractModel = require('web.AbstractModel');
+var AbstractRenderer = require('web.AbstractRenderer');
+var AbstractController = require('web.AbstractController');
+var registry = require('web.view_registry');
+
+var _lt = core._lt;
+
+/**
+ * model
+ */
+var Model = AbstractModel.extend({
+ /**
+ * init
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ this._state = {
+ viewId: false,
+ modelName: false,
+ body: '',
+ context: {},
+ domain: [],
+ };
+ },
+ /**
+ * fetches the rendered qweb view
+ */
+ _fetch: function () {
+ var state = this._state;
+ return this._rpc({
+ model: state.modelName,
+ method: 'qweb_render_view',
+ kwargs: {
+ view_id: state.viewId,
+ domain: state.domain,
+ context: state.context
+ }
+ }).then(function (r) {
+ state.body = r;
+ return state.viewId;
+ });
+ },
+ /**
+ * get
+ */
+ get: function () {
+ return this._state;
+ },
+ /**
+ * load
+ */
+ load: function (params) {
+ _.extend(this._state, _.pick(params, ['viewId', 'modelName', 'domain', 'context']));
+
+ return this._fetch();
+ },
+ /**
+ * reload
+ */
+ reload: function (_id, _params) {
+ // FIXME: update this._state or something?
+ return this._fetch();
+ }
+});
+/**
+ * renderer
+ */
+var Renderer = AbstractRenderer.extend({
+ /**
+ * render
+ */
+ _render: function () {
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ self.$el.html(self.state.body);
+ });
+ }
+});
+/**
+ * controller
+ */
+var Controller = AbstractController.extend({
+ events: _.extend({}, AbstractController.prototype.events, {
+ 'click [type="toggle"]': '_onLazyToggle',
+ }),
+
+ init: function () {
+ this._super.apply(this, arguments);
+ this._$buttons = $('<nav>').on('click', '[type="action"]', this.proxy('_onActionClicked'));
+ },
+
+ renderButtons: function ($node) {
+ this._super($node);
+ $node.append(this._$buttons);
+ },
+ _update: function () {
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ // move control panel buttons from the view to the control panel
+ // area
+ var $cp_buttons = self.renderer.$('nav.o_qweb_cp_buttons');
+ $cp_buttons.children().appendTo(self._$buttons.empty());
+ $cp_buttons.remove();
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Lazy toggle. Content is not remembered between unfolds.
+ */
+ _onLazyToggle: function (e) {
+ // TODO: add support for view (possibly action as well?)
+ var $target = $(e.target);
+ var $t = $target.closest('[data-model]');
+ if (!($target.hasClass('fa-caret-down') || $target.hasClass('fa-caret-right'))) {
+ $target = $t.find('.fa-caret-down, .fa-caret-right');
+ }
+
+ var data = $t.data();
+ if (this._fold($t)) {
+ $target.removeClass('fa-caret-down').addClass('fa-caret-right');
+ return;
+ }
+
+ // NB: $.data() automatically parses json attributes, but does not
+ // automatically parse lone float literals in data-*, so a
+ // data-args (as a json object) is very convenient
+ var args = data.args || _.omit(data, 'model', 'method', 'id');
+
+ return this._rpc({
+ model: data.model,
+ method: data.method,
+ args: data.id ? [data.id] : undefined,
+ kwargs: args // FIXME: context?
+ }).then(function (s) {
+ return $(s);
+ }).then(function ($newcontent) {
+ $t.data('children', $newcontent).after($newcontent);
+ $target.removeClass('fa-caret-right').addClass('fa-caret-down');
+ });
+ },
+ /**
+ * Attempts to fold the parameter, returns whether that happened.
+ */
+ _fold: function ($el) {
+ var $children = $el.data('children');
+ if (!$children) {
+ return false;
+ }
+
+ var self = this;
+ $children.each(function (_i, e) {
+ self._fold($(e));
+ }).remove();
+ $el.removeData('children');
+ return true;
+ }
+});
+
+/**
+ * view
+ */
+var QWebView = AbstractView.extend({
+ display_name: _lt('Freedom View'),
+ icon: 'fa-file-picture-o',
+ viewType: 'qweb',
+ // groupable?
+ enableTimeRangeMenu: true,
+ config: {
+ Model: Model,
+ Renderer: Renderer,
+ Controller: Controller,
+ },
+
+ /**
+ * init method
+ */
+ init: function (viewInfo, params) {
+ this._super.apply(this, arguments);
+ this.loadParams.viewId = viewInfo.view_id;
+ }
+});
+
+registry.add('qweb', QWebView);
+return {
+ View: QWebView,
+ Controller: Controller,
+ Renderer: Renderer,
+ Model: Model
+};
+});
diff --git a/addons/web/static/src/scss/webclient.scss b/addons/web/static/src/scss/webclient.scss
index 3dfebe8deed..436c8074302 100644
--- a/addons/web/static/src/scss/webclient.scss
+++ b/addons/web/static/src/scss/webclient.scss
@@ -182,3 +182,10 @@ div.o_boolean_toggle.custom-control.custom-checkbox {
overflow-x: initial;
}
}
+
+//== Action manager
+// ensure special links are styled as pointers even when they don't
+// have an href
+[type="action"], [type="toggle"] {
+ cursor: pointer !important;
+}