2020-10-02 15:10:00 +00:00
|
|
|
var _ = require('underscore');
|
|
|
|
var ko = require('knockout');
|
|
|
|
var BackboneEvents = require('backbone').Events;
|
|
|
|
|
|
|
|
var dispose = require('../lib/dispose');
|
|
|
|
var dom = require('../lib/dom');
|
|
|
|
var kd = require('../lib/koDom');
|
|
|
|
|
|
|
|
// Rather than require the whole of highlight.js, require just the core with the one language we
|
|
|
|
// need, to keep our bundle smaller and the build faster.
|
|
|
|
var hljs = require('highlight.js/lib/highlight');
|
|
|
|
hljs.registerLanguage('python', require('highlight.js/lib/languages/python'));
|
|
|
|
|
|
|
|
function CodeEditorPanel(gristDoc) {
|
|
|
|
this._gristDoc = gristDoc;
|
|
|
|
this._schema = ko.observable('');
|
2021-05-27 13:18:57 +00:00
|
|
|
this._denied = ko.observable(false);
|
2020-10-02 15:10:00 +00:00
|
|
|
|
|
|
|
this.listenTo(this._gristDoc, 'schemaUpdateAction', this.onSchemaAction);
|
|
|
|
this.onSchemaAction(); // Fetch the schema to initialize
|
|
|
|
}
|
|
|
|
dispose.makeDisposable(CodeEditorPanel);
|
|
|
|
_.extend(CodeEditorPanel.prototype, BackboneEvents);
|
|
|
|
|
|
|
|
CodeEditorPanel.prototype.buildDom = function() {
|
|
|
|
// The tabIndex enables the element to gain focus, and the .clipboard class prevents the
|
|
|
|
// Clipboard module from re-grabbing it. This is a quick fix for the issue where clipboard
|
|
|
|
// interferes with text selection. TODO it should be possible for the Clipboard to never
|
|
|
|
// interfere with text selection even for un-focusable elements.
|
|
|
|
return dom('div.g-code-panel.clipboard',
|
|
|
|
{tabIndex: "-1"},
|
2021-05-27 13:18:57 +00:00
|
|
|
kd.maybe(this._denied, () => dom('div.g-code-panel-denied',
|
|
|
|
dom('h2', kd.text('Access denied')),
|
|
|
|
dom('div', kd.text('Code View is available only when you have full document access.')),
|
|
|
|
)),
|
2020-10-02 15:10:00 +00:00
|
|
|
kd.scope(this._schema, function(schema) {
|
|
|
|
// The reason to scope and rebuild instead of using `kd.text(schema)` is because
|
|
|
|
// hljs.highlightBlock(elem) replaces `elem` with a whole new dom tree.
|
2021-05-23 17:43:11 +00:00
|
|
|
if (!schema) { return null; }
|
2020-10-02 15:10:00 +00:00
|
|
|
return dom(
|
|
|
|
'code.g-code-viewer.python',
|
|
|
|
schema,
|
|
|
|
dom.hide,
|
|
|
|
dom.defer(function(elem) {
|
|
|
|
hljs.highlightBlock(elem);
|
|
|
|
dom.show(elem);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2021-05-27 13:18:57 +00:00
|
|
|
CodeEditorPanel.prototype.onSchemaAction = async function(actions) {
|
|
|
|
try {
|
|
|
|
const schema = await this._gristDoc.docComm.fetchTableSchema();
|
2020-10-02 15:10:00 +00:00
|
|
|
if (!this.isDisposed()) {
|
|
|
|
this._schema(schema);
|
2021-05-27 13:18:57 +00:00
|
|
|
this._denied(false);
|
2020-10-02 15:10:00 +00:00
|
|
|
}
|
2021-05-27 13:18:57 +00:00
|
|
|
} catch (err) {
|
|
|
|
if (!String(err).match(/Cannot view code/)) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
if (!this.isDisposed()) {
|
|
|
|
this._schema('');
|
|
|
|
this._denied(true);
|
|
|
|
}
|
|
|
|
}
|
2020-10-02 15:10:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = CodeEditorPanel;
|