summaryrefslogtreecommitdiff
path: root/addons/pad/static/src/js/pad.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/pad/static/src/js/pad.js')
-rw-r--r--addons/pad/static/src/js/pad.js193
1 files changed, 193 insertions, 0 deletions
diff --git a/addons/pad/static/src/js/pad.js b/addons/pad/static/src/js/pad.js
new file mode 100644
index 00000000..7107c2d6
--- /dev/null
+++ b/addons/pad/static/src/js/pad.js
@@ -0,0 +1,193 @@
+odoo.define('pad.pad', function (require) {
+"use strict";
+
+var AbstractField = require('web.AbstractField');
+var core = require('web.core');
+var fieldRegistry = require('web.field_registry');
+
+var _t = core._t;
+
+var FieldPad = AbstractField.extend({
+ template: 'FieldPad',
+ content: "",
+ events: {
+ 'click .oe_pad_switch': '_onToggleFullScreen',
+ },
+
+ /**
+ * @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 this._super.apply(this, arguments);
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ if (!this.isPadConfigured) {
+ this.$(".oe_unconfigured").removeClass('d-none');
+ this.$(".oe_configured").addClass('d-none');
+ return Promise.resolve();
+ }
+ if (this.mode === 'edit' && typeof(this.value) === 'object') {
+ this.value = this.value.toJSON();
+ }
+ if (this.mode === 'edit' && _.str.startsWith(this.value, 'http')) {
+ this.url = this.value;
+ // please close your eyes and look elsewhere...
+ // Since the pad value (the url) will not change during the edition
+ // process, we have a problem: the description field will not be
+ // properly updated. We need to explicitely write the value each
+ // time someone edit the record in order to force the server to read
+ // the updated value of the pad and put it in the description field.
+ //
+ // However, the basic model optimizes away the changes if they are
+ // not really different from the current value. So, we need to
+ // either add special configuration options to the basic model, or
+ // to trick him into accepting the same value as being different...
+ // Guess what we decided...
+ var url = {};
+ url.toJSON = _.constant(this.url);
+ this._setValue(url, {doNotSetDirty: true});
+ }
+
+ return this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * 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;
+ },
+ /**
+ * @override
+ */
+ isSet: function () {
+ return true;
+ },
+
+ //--------------------------------------------------------------------------
+ // 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 (this.url) {
+ // here, we have a valid url, so we can simply display an iframe
+ // with the correct src attribute
+ var userName = encodeURIComponent(this.getSession().name);
+ var url = this.url + '?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,
+ record: this.recordData,
+ },
+ }, {
+ 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.url = result.url;
+ self._setValue(result.url, {doNotSetDirty: true});
+ });
+ }
+ },
+ /**
+ * @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);
+ }).guardedCatch(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"));
+ }
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ * @private
+ */
+ _onToggleFullScreen: function () {
+ this.$el.toggleClass('oe_pad_fullscreen mb0');
+ this.$('.oe_pad_switch').toggleClass('fa-expand fa-compress');
+ this.$el.parents('.o_touch_device').toggleClass('o_scroll_hidden');
+ },
+});
+
+fieldRegistry.add('pad', FieldPad);
+
+return FieldPad;
+
+});