217 lines
8.1 KiB
JavaScript
217 lines
8.1 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
var globalEditor;
|
|
|
|
var hash = "#advanced-view-editor";
|
|
|
|
var website = openerp.website;
|
|
website.templates.push('/website/static/src/xml/website.ace.xml');
|
|
|
|
website.ready().then(function () {
|
|
if (window.location.hash.indexOf(hash) >= 0) {
|
|
launch();
|
|
}
|
|
});
|
|
|
|
function launch () {
|
|
if (globalEditor) {
|
|
globalEditor.open();
|
|
} else {
|
|
globalEditor = new website.ace.ViewEditor(this);
|
|
globalEditor.appendTo($(document.body));
|
|
}
|
|
}
|
|
|
|
website.EditorBar.include({
|
|
events: _.extend({}, website.EditorBar.prototype.events, {
|
|
'click a[data-action=ace]': 'launchAce',
|
|
}),
|
|
launchAce: function (e) {
|
|
e.preventDefault();
|
|
launch();
|
|
},
|
|
});
|
|
|
|
website.ace = {};
|
|
|
|
website.ace.XmlDocument = openerp.Class.extend({
|
|
init: function (text) {
|
|
this.xml = text;
|
|
},
|
|
isWellFormed: function () {
|
|
if (document.implementation.createDocument) {
|
|
var dom = new DOMParser().parseFromString(this.xml, "text/xml");
|
|
return dom.getElementsByTagName("parsererror").length === 0;
|
|
} else if (window.ActiveXObject) {
|
|
// TODO test in IE
|
|
var msDom = new ActiveXObject("Microsoft.XMLDOM");
|
|
msDom.async = false;
|
|
return !msDom.loadXML(this.xml);
|
|
}
|
|
return true;
|
|
},
|
|
format: function () {
|
|
return vkbeautify.xml(this.xml, 4);
|
|
},
|
|
});
|
|
|
|
website.ace.ViewOption = openerp.Widget.extend({
|
|
template: 'website.ace_view_option',
|
|
init: function (parent, options) {
|
|
this.view_id = options.id;
|
|
this.view_name = options.name;
|
|
this._super(parent);
|
|
},
|
|
});
|
|
|
|
website.ace.ViewEditor = openerp.Widget.extend({
|
|
template: 'website.ace_view_editor',
|
|
events: {
|
|
'change #ace-view-list': 'displaySelectedView',
|
|
'click button[data-action=save]': 'saveViews',
|
|
'click button[data-action=format]': 'formatXml',
|
|
'click button[data-action=close]': 'close',
|
|
},
|
|
init: function (parent) {
|
|
this.buffers = {};
|
|
this._super(parent);
|
|
},
|
|
start: function () {
|
|
var self = this;
|
|
self.aceEditor = ace.edit(self.$('#ace-view-editor')[0]);
|
|
self.aceEditor.setTheme("ace/theme/monokai");
|
|
var viewId = $(document.documentElement).data('view-xmlid');
|
|
openerp.jsonRpc('/website/customize_template_get', 'call', {
|
|
'xml_id': viewId,
|
|
'optional': false,
|
|
}).then(function (views) {
|
|
self.loadViews.call(self, views);
|
|
self.open.call(self);
|
|
});
|
|
},
|
|
loadViews: function (views) {
|
|
var self = this;
|
|
var activeViews = _.filter(views, function (view) {
|
|
return view.active;
|
|
});
|
|
var $viewList = self.$('#ace-view-list');
|
|
_.each(activeViews, function (view) {
|
|
if (view.id) {
|
|
new website.ace.ViewOption(self, view).appendTo($viewList);
|
|
self.loadView(view.id);
|
|
}
|
|
});
|
|
},
|
|
loadView: function (id) {
|
|
var viewId = parseInt(id, 10);
|
|
var self = this;
|
|
openerp.jsonRpc('/web/dataset/call', 'call', {
|
|
model: 'ir.ui.view',
|
|
method: 'read',
|
|
args: [[viewId], ['arch'], website.get_context()],
|
|
}).then(function(result) {
|
|
var editingSession = self.buffers[viewId] = new ace.EditSession(result[0].arch);;
|
|
editingSession.setMode("ace/mode/xml");
|
|
editingSession.setUndoManager(new ace.UndoManager());
|
|
editingSession.on("change", function () {
|
|
setTimeout(function () {
|
|
var $option = self.$('#ace-view-list').find('[value='+viewId+']');
|
|
var bufferName = $option.text();
|
|
var dirtyMarker = " (unsaved changes)";
|
|
var isDirty = editingSession.getUndoManager().hasUndo();
|
|
if (isDirty && bufferName.indexOf(dirtyMarker) < 0) {
|
|
$option.text(bufferName + dirtyMarker);
|
|
} else if (!isDirty && bufferName.indexOf(dirtyMarker) > 0) {
|
|
$option.text(bufferName.substring(0, bufferName.indexOf(dirtyMarker)));
|
|
}
|
|
}, 1);
|
|
});
|
|
if (viewId === self.selectedViewId()) {
|
|
self.displayView.call(self, viewId);
|
|
}
|
|
});
|
|
},
|
|
selectedViewId: function () {
|
|
return parseInt(this.$('#ace-view-list').val(), 10);
|
|
},
|
|
displayView: function (id) {
|
|
var viewId = parseInt(id, 10);
|
|
var editingSession = this.buffers[viewId];
|
|
if (editingSession) {
|
|
this.aceEditor.setSession(editingSession);
|
|
}
|
|
},
|
|
displaySelectedView: function () {
|
|
this.displayView(this.selectedViewId());
|
|
this.updateHash();
|
|
},
|
|
formatXml: function () {
|
|
var xml = new website.ace.XmlDocument(this.aceEditor.getValue());
|
|
this.aceEditor.setValue(xml.format());
|
|
},
|
|
saveViews: function () {
|
|
var self = this;
|
|
var toSave = _.filter(_.map(self.buffers, function (editingSession, viewId) {
|
|
return {
|
|
id: parseInt(viewId, 10),
|
|
isDirty: editingSession.getUndoManager().hasUndo(),
|
|
text: editingSession.getValue(),
|
|
};
|
|
}), function (session) {
|
|
return session.isDirty;
|
|
});
|
|
var requests = _.map(toSave, self.saveView);
|
|
$.when.apply($, requests).then(function () {
|
|
self.reloadPage.call(self);
|
|
}).fail(function (source, error) {
|
|
var message = (error.data.arguments[0] === "Access Denied") ? "Access denied: please sign in" : error.message;
|
|
self.displayError.call(self, message);
|
|
});
|
|
},
|
|
saveView: function (session) {
|
|
var xml = new website.ace.XmlDocument(session.text);
|
|
if (xml.isWellFormed()) {
|
|
return openerp.jsonRpc('/web/dataset/call', 'call', {
|
|
model: 'ir.ui.view',
|
|
method: 'write',
|
|
args: [[session.id], { 'arch': xml.xml }, website.get_context()],
|
|
});
|
|
} else {
|
|
return $.Deferred().fail("Malformed XML document");
|
|
}
|
|
},
|
|
updateHash: function () {
|
|
window.location.hash = hash + "?view=" + this.selectedViewId();
|
|
},
|
|
reloadPage: function () {
|
|
this.updateHash();
|
|
window.location.reload();
|
|
},
|
|
displayError: function (error) {
|
|
// TODO Improve feedback (e.g. update 'Save' button + tooltip)
|
|
alert(error);
|
|
},
|
|
open: function () {
|
|
this.$el.removeClass('oe_ace_closed').addClass('oe_ace_open');
|
|
var curentHash = window.location.hash;
|
|
var indexOfView = curentHash.indexOf("?view=");
|
|
if (indexOfView >= 0) {
|
|
var viewId = parseInt(curentHash.substring(indexOfView + 6, curentHash.length), 10);
|
|
this.$('#ace-view-list').val(viewId).change();
|
|
} else {
|
|
window.location.hash = hash;
|
|
}
|
|
},
|
|
close: function () {
|
|
window.location.hash = "";
|
|
var self = this;
|
|
this.$el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
|
|
globalEditor = null;
|
|
self.destroy.call(self);
|
|
}).removeClass('oe_ace_open').addClass('oe_ace_closed');
|
|
},
|
|
});
|
|
|
|
})();
|