mirror of
https://github.com/getredash/redash.git
synced 2025-12-20 01:47:39 -05:00
161 lines
5.0 KiB
JavaScript
161 lines
5.0 KiB
JavaScript
import 'brace';
|
|
import 'brace/mode/python';
|
|
import 'brace/mode/sql';
|
|
import 'brace/mode/json';
|
|
import 'brace/ext/language_tools';
|
|
import 'brace/ext/searchbox';
|
|
import { map } from 'lodash';
|
|
|
|
// By default Ace will try to load snippet files for the different modes and fail.
|
|
// We don't need them, so we use these placeholders until we define our own.
|
|
function defineDummySnippets(mode) {
|
|
window.ace.define(`ace/snippets/${mode}`, ['require', 'exports', 'module'], (require, exports) => {
|
|
exports.snippetText = '';
|
|
exports.scope = mode;
|
|
});
|
|
}
|
|
|
|
defineDummySnippets('python');
|
|
defineDummySnippets('sql');
|
|
defineDummySnippets('json');
|
|
|
|
function queryEditor(QuerySnippet, $timeout) {
|
|
return {
|
|
restrict: 'E',
|
|
scope: {
|
|
query: '=',
|
|
schema: '=',
|
|
syntax: '=',
|
|
},
|
|
template: '<div ui-ace="editorOptions" ng-model="query.query"></div>',
|
|
link: {
|
|
pre($scope) {
|
|
$scope.syntax = $scope.syntax || 'sql';
|
|
|
|
$scope.editorOptions = {
|
|
mode: 'json',
|
|
// require: ['ace/ext/language_tools'],
|
|
advanced: {
|
|
behavioursEnabled: true,
|
|
enableSnippets: true,
|
|
enableBasicAutocompletion: true,
|
|
enableLiveAutocompletion: true,
|
|
autoScrollEditorIntoView: true,
|
|
},
|
|
onLoad(editor) {
|
|
$scope.$on('query-editor.command', ($event, command, ...args) => {
|
|
switch (command) {
|
|
case 'focus': {
|
|
editor.focus();
|
|
break;
|
|
}
|
|
case 'paste': {
|
|
const [text] = args;
|
|
editor.session.doc.replace(editor.selection.getRange(), text);
|
|
const range = editor.selection.getRange();
|
|
$scope.query.query = editor.session.getValue();
|
|
$timeout(() => {
|
|
editor.selection.setRange(range);
|
|
});
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Release Cmd/Ctrl+L to the browser
|
|
editor.commands.bindKey('Cmd+L', null);
|
|
editor.commands.bindKey('Ctrl+P', null);
|
|
editor.commands.bindKey('Ctrl+L', null);
|
|
|
|
QuerySnippet.query((snippets) => {
|
|
window.ace.acequire(['ace/snippets'], (snippetsModule) => {
|
|
const snippetManager = snippetsModule.snippetManager;
|
|
const m = {
|
|
snippetText: '',
|
|
};
|
|
m.snippets = snippetManager.parseSnippetFile(m.snippetText);
|
|
snippets.forEach((snippet) => {
|
|
m.snippets.push(snippet.getSnippet());
|
|
});
|
|
|
|
snippetManager.register(m.snippets || [], m.scope);
|
|
});
|
|
});
|
|
|
|
editor.$blockScrolling = Infinity;
|
|
editor.getSession().setUseWrapMode(true);
|
|
editor.setShowPrintMargin(false);
|
|
|
|
$scope.$watch('syntax', (syntax) => {
|
|
const newMode = `ace/mode/${syntax}`;
|
|
editor.getSession().setMode(newMode);
|
|
});
|
|
|
|
$scope.$watch('schema', (newSchema, oldSchema) => {
|
|
if (newSchema !== oldSchema) {
|
|
if (newSchema === undefined) {
|
|
return;
|
|
}
|
|
const tokensCount = newSchema.reduce((totalLength, table) => totalLength + table.columns.length, 0);
|
|
// If there are too many tokens we disable live autocomplete,
|
|
// as it makes typing slower.
|
|
if (tokensCount > 5000) {
|
|
editor.setOption('enableLiveAutocompletion', false);
|
|
} else {
|
|
editor.setOption('enableLiveAutocompletion', true);
|
|
}
|
|
}
|
|
});
|
|
|
|
$scope.$parent.$on('angular-resizable.resizing', () => {
|
|
editor.resize();
|
|
});
|
|
|
|
editor.focus();
|
|
},
|
|
};
|
|
|
|
const schemaCompleter = {
|
|
getCompletions(state, session, pos, prefix, callback) {
|
|
if (prefix.length === 0 || !$scope.schema) {
|
|
callback(null, []);
|
|
return;
|
|
}
|
|
|
|
if (!$scope.schema.keywords) {
|
|
const keywords = {};
|
|
|
|
$scope.schema.forEach((table) => {
|
|
keywords[table.name] = 'Table';
|
|
|
|
table.columns.forEach((c) => {
|
|
keywords[c] = 'Column';
|
|
keywords[`${table.name}.${c}`] = 'Column';
|
|
});
|
|
});
|
|
|
|
$scope.schema.keywords = map(keywords, (v, k) => ({
|
|
name: k,
|
|
value: k,
|
|
score: 0,
|
|
meta: v,
|
|
}));
|
|
}
|
|
callback(null, $scope.schema.keywords);
|
|
},
|
|
};
|
|
|
|
window.ace.acequire(['ace/ext/language_tools'], (langTools) => {
|
|
langTools.addCompleter(schemaCompleter);
|
|
});
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
export default function init(ngModule) {
|
|
ngModule.directive('queryEditor', queryEditor);
|
|
}
|