summaryrefslogtreecommitdiff
path: root/addons/pad/static/src/js/pad.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2017-05-10 14:54:05 +0200
committerGéry Debongnie <ged@odoo.com>2017-05-11 09:53:10 +0200
commitc31bf95e4e5e01e9f433ac13c6be33f85a57f9b9 (patch)
tree34960a4a49299cfdad7c3af33631714736ecbbdd /addons/pad/static/src/js/pad.js
parent33710d540c5584926fcc061ed7e6a04d48f8166e (diff)
[FIX] pad: make it work with the new views
The pad widget was partially updated to the new views, but was no longer working. In this commit, we rewrite the widget to make it work. Note that we did some functional changes: - we do only one rpc to check if the server is configured. the result is stored on the prototype, so we do not need to do it again - we do some rpcs with shadow: true, so we will not stop the rest of the ui if the server is slow to respond - we display a loading message in readonly, when the content is not loaded yet.
Diffstat (limited to 'addons/pad/static/src/js/pad.js')
-rw-r--r--addons/pad/static/src/js/pad.js227
1 files changed, 139 insertions, 88 deletions
diff --git a/addons/pad/static/src/js/pad.js b/addons/pad/static/src/js/pad.js
index 8fb09df0173..76f6ad9b9ae 100644
--- a/addons/pad/static/src/js/pad.js
+++ b/addons/pad/static/src/js/pad.js
@@ -3,116 +3,167 @@ odoo.define('pad.pad', function (require) {
var AbstractField = require('web.AbstractField');
var core = require('web.core');
-var field_registry = require('web.field_registry');
+var fieldRegistry = require('web.field_registry');
var _t = core._t;
-
var FieldPad = AbstractField.extend({
template: 'FieldPad',
content: "",
events: {
- 'click .oe_pad_switch': function() {
- this.$el.toggleClass('oe_pad_fullscreen mb0');
- this.$('.oe_pad_switch').toggleClass('fa-expand fa-compress');
- },
+ 'click .oe_pad_switch': '_onToggleFullScreen',
},
supportedFieldTypes: ['char'],
- init: function() {
- var self = this;
- this._super.apply(this, arguments);
- this.configured = false;
- this._configured_deferred = $.Deferred();
- this._url_request_deferred = $.Deferred();
+ /**
+ * @override
+ */
+ willStart: function () {
+ if (this.isPadConfigured === undefined) {
+ return this._rpc({
+ method: 'pad_is_configured',
+ model: this.model,
+ }).then(function (result) {
+ // we write on the prototype to share the information between
+ // all pad widgets instances, across all actions
+ FieldPad.prototype.isPadConfigured = result;
+ });
+ }
+ return $.when();
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ if (!this.isPadConfigured) {
+ this.$(".oe_unconfigured").removeClass('hidden');
+ this.$(".oe_configured").addClass('hidden');
+ return;
+ }
+ return this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
- this.trigger_up('perform_model_rpc', {
- method: 'pad_is_configured',
- model: this.model,
- on_success: function (data) {
- self.set_configured(!!data);
- self._configured_deferred.resolve();
- },
- on_fail: function () {
- self.set_configured(true);
- self._configured_deferred.resolve();
- },
- });
+ /**
+ * If we had to generate an url, we wait for the generation to be completed,
+ * so the current record will be associated with the correct pad url.
+ *
+ * @override
+ */
+ commitChanges: function () {
+ return this.urlDef;
},
- render_readonly: function() {
- var self = this;
- this._configured_deferred.then(function() {
- if (self.configured){
- if (_.str.startsWith(self.value, 'http')) {
- self.trigger_up('perform_model_rpc', {
- method: 'pad_get_content',
- model: self.model,
- args: [self.value],
- on_success: function(data) {
- self.$('.oe_pad_content').removeClass('oe_pad_loading').html('<div class="oe_pad_readonly"><div>');
- self.$('.oe_pad_readonly').html(data);
- },
- on_fail: function() {
- self.$('.oe_pad_content').text(_t('Unable to load pad'));
- }
- });
- } else {
- self.$('.oe_pad_content').addClass('oe_pad_loading').show().text(_t("This pad will be initialized on first edit"));
- }
- }
- });
+ /**
+ * @override
+ */
+ isSet: function () {
+ return true;
},
- render_edit: function() {
- var self = this;
- this._configured_deferred.then(function() {
- if (! self.value || !_.str.startsWith(self.value, 'http')) {
- self.trigger_up('perform_model_rpc', {
- method: 'pad_generate_url',
- model: self.model,
- context: {
- model: self.model,
- field_name: self.name,
- object_id: self.model
- },
- on_success: function(data) {
- if (! data.url) {
- self.set_configured(false);
- } else {
- self.set_value(data.url);
- }
- self._url_request_deferred.resolve();
- },
- });
- } else {
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Note that this method has some serious side effects: performing rpcs and
+ * setting the value of this field. This is not conventional and should not
+ * be copied in other code, unless really necessary.
+ *
+ * @override
+ * @private
+ */
+ _renderEdit: function () {
+ if (_.str.startsWith(this.value, 'http')) {
+ // here, we have a valid url, so we can simply display an iframe
+ // with the correct src attribute
+ var userName = encodeURIComponent(this.getSession().userName);
+ var url = this.value + '?showChat=false&userName=' + userName;
+ var content = '<iframe width="100%" height="100%" frameborder="0" src="' + url + '"></iframe>';
+ this.$('.oe_pad_content').html(content);
+ } else if (this.value) {
+ // it looks like the field does not contain a valid url, so we just
+ // display it (it cannot be edited in that case)
+ this.$('.oe_pad_content').text(this.value);
+ } else {
+ // It is totally discouraged to have a render method that does
+ // non-rendering work, especially since the work in question
+ // involves doing RPCs and changing the value of the field.
+ // However, this is kind of necessary in this case, because the
+ // value of the field is actually only the url of the pad. The
+ // actual content will be loaded in an iframe. We could do this
+ // work in the basic model, but the basic model does not know that
+ // this widget is in edit or readonly, and we really do not want to
+ // create a pad url everytime a task without a pad is viewed.
+ var self = this;
+ this.urlDef = this._rpc({
+ method: 'pad_generate_url',
+ model: this.model,
+ context: {
+ model: this.model,
+ field_name: this.name,
+ object_id: this.res_id
+ },
+ }, {
+ shadow: true
+ }).then(function (result) {
// We need to write the url of the pad to trigger
// the write function which updates the actual value
// of the field to the value of the pad content
- self.set_value(self.value);
- self._url_request_deferred.resolve();
- }
- self._url_request_deferred.then(function() {
- if (_.str.startsWith(self.value, 'http')) {
- var content = '<iframe width="100%" height="100%" frameborder="0" src="' + self.value + '?showChat=false&userName=' + encodeURIComponent(self.session.username) + '"></iframe>';
- self.$('.oe_pad_content').html(content);
- }
- else {
- self.$('.oe_pad_content').text(self.value);
- }
+ self._setValue(result.url);
});
- });
+ }
},
- set_configured: function(configured) {
- this.configured = configured;
- if (!configured) {
- this.$(".oe_unconfigured").removeClass('hidden');
- this.$(".oe_configured").addClass('hidden');
+ /**
+ * @override
+ * @private
+ */
+ _renderReadonly: function () {
+ if (_.str.startsWith(this.value, 'http')) {
+ var self = this;
+ this.$('.oe_pad_content')
+ .addClass('oe_pad_loading')
+ .text(_t("Loading"));
+ this._rpc({
+ method: 'pad_get_content',
+ model: this.model,
+ args: [this.value]
+ }, {
+ shadow: true
+ }).then(function (data) {
+ self.$('.oe_pad_content')
+ .removeClass('oe_pad_loading')
+ .html('<div class="oe_pad_readonly"><div>');
+ self.$('.oe_pad_readonly').html(data);
+ }).fail(function () {
+ self.$('.oe_pad_content').text(_t('Unable to load pad'));
+ });
+ } else {
+ this.$('.oe_pad_content')
+ .addClass('oe_pad_loading')
+ .show()
+ .text(_t("This pad will be initialized on first edit"));
}
},
- is_set: function() {
- return true;
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ * @private
+ */
+ _onToggleFullScreen: function () {
+ this.$el.toggleClass('oe_pad_fullscreen mb0');
+ this.$('.oe_pad_switch').toggleClass('fa-expand fa-compress');
},
});
-field_registry.add('pad', FieldPad);
+fieldRegistry.add('pad', FieldPad);
+
+return FieldPad;
});