17 |
18 |
19 |
20 |
21 |
22 |  |
23 | |
25 | |
27 |
28 | |
29 |
30 |
31 |
34 | |
35 |
36 |
37 |
64 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 |
2 | const TerminusUI = require('./TerminusUI');
3 | const TerminusViewer =require('./html/TerminusViewer')
4 | module.exports={TerminusUI:TerminusUI,
5 | TerminusViewer:TerminusViewer}
6 |
--------------------------------------------------------------------------------
/src/plugins/codemirror.terminus.js:
--------------------------------------------------------------------------------
1 | function Codemirror(text, format, config){
2 | this.textdom = text;
3 | this.mode = format;
4 | if(objectIsEmpty(config)) this.darkMode = config.darkMode;
5 | if(this.jsonldCheck(format)) this.mode = 'javascript';
6 | }
7 | // checks if a json object is empty
8 | function objectIsEmpty(arg) {
9 | for (var item in arg) {
10 | return false;
11 | }
12 | return true;
13 | }
14 |
15 | function autocomplete(){
16 | var orig = CodeMirror.hint.javascript = function (cm) {
17 | var list = [];//"limit()","start()","triple()"];//Session.get(Template.strSessionDistinctFields) || [];
18 | var cursor = cm.getCursor();
19 | var currentLine = cm.getLine(cursor.line);
20 | var start = cursor.ch;
21 | var end = start;
22 | while (end < currentLine.length && /[\w$]+/.test(currentLine.charAt(end))) ++end;
23 | while (start && /[\w$]+/.test(currentLine.charAt(start - 1))) --start;
24 | var curWord = start != end && currentLine.slice(start, end);
25 | var regex = new RegExp('^' + curWord, 'i');
26 | var result = {
27 | list: (!curWord ? list : list.filter(function (item) {
28 | return item.match(regex);
29 | })).sort(),
30 | from: CodeMirror.Pos(cursor.line, start),
31 | to: CodeMirror.Pos(cursor.line, end)
32 | };
33 | return result;
34 | };
35 | // codeMirror.hint.sql is defined when importing codemirror/addon/hint/sql-hint
36 | // (this is mentioned in codemirror addon documentation)
37 | // Reference the hint function imported here when including other hint addons
38 | // or supply your own
39 | //cm.replaceSelection(".");
40 | //codeMirror.showHint(cm, CodeMirror.hint.javascript, hintOptions);
41 | }
42 |
43 | /*
44 | txtar : editor is attached to textar
45 | mode : format for highlighting, ex: json, html etc.
46 | editable : readOnly false/ nocursor is special value in code editor to set readonly true */
47 | Codemirror.prototype.colorizeTextArea = function(dimensions){
48 | //initize auto complete
49 | /*CodeMirror.commands.autocomplete = function(cm) {
50 | cm.showHint({hint: CodeMirror.hint.anyword});
51 | }*/
52 |
53 | // initialise code editor on text area
54 | var editor = CodeMirror.fromTextArea(this.textdom, {
55 | mode : this.mode,
56 | firstLineNumber : 1,
57 | lineNumbers : true,
58 | styleActiveLine : true,
59 | lineWrapping : true,
60 | smartIndent : true,
61 | indentWithTabs : true,
62 | newlineAndIndent : true,
63 | autoCloseBrackets : true,
64 | matchBrackets : {afterCursor: true},
65 | extraKeys : {"Ctrl-F": "find",
66 | //"Tab": "autocomplete",
67 | "Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
68 | refresh : true,
69 | foldGutter : true,
70 | gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
71 | });
72 | editor.foldCode(CodeMirror.Pos(13, 0));
73 | if(false && !(objectIsEmpty(dimensions))){
74 | editor.setSize(dimensions.width, dimensions.height);
75 | }
76 | else this.setCodemirrorSize(editor, dimensions);
77 | editor.defaultCharWidth('20px');
78 | if(true || this.darkMode) editor.setOption("theme", 'erlang-dark');
79 | else editor.setOption("theme", 'neo');
80 | return editor;
81 | } // colorizeTextArea()
82 |
83 | /*
84 | set editor size according to screens
85 | editor : code mirror editor Object
86 | mode : editor being viewed from schema/ doc/ query page*/
87 | Codemirror.prototype.setCodemirrorSize = function(editor, dimensions){
88 | switch(dimensions){
89 | case 'query':
90 | editor.setSize('auto', '400');
91 | break;
92 | case 'schema':
93 | editor.setSize('auto', '1550');
94 | break;
95 | case 'document':
96 | editor.setSize('765', '500');
97 | break;
98 | case 'api-doc':
99 | editor.setSize('800', '500');
100 | break;
101 | case 'doc-json':
102 | editor.setSize('1410', 'auto');
103 | break;
104 | case 'doc-json-create':
105 | editor.setSize('1410', '500');
106 | break;
107 | } // switch(dimensions)
108 | } // setCodemirrorSize()
109 |
110 | // updateTextArea(): highlights new changes on editor
111 | Codemirror.prototype.updateTextArea = function(editor){
112 | editor.save();
113 | setTimeout(function() {
114 | editor.refresh();
115 | },1);
116 | // save changes of code mirror editor
117 | editor.on('change', function(){
118 | editor.save();
119 | });
120 | } //updateTextArea()
121 |
122 | /*
123 | colorizePre() to colorise pre tags (read only mode)
124 | text (string) : The document to run through the highlighter.
125 | mode (mode spec) : format to highlight color
126 | output (DOM node): The tokens will be converted to spans as in an editor,
127 | and inserted into the node (through innerHTML).*/
128 | Codemirror.prototype.colorizePre = function(){
129 | CodeMirror.runMode(this.textdom.innerText, this.mode, this.textdom);
130 | if(true || this.darkMode)
131 | var theme = 'cm-s-erlang-dark';
132 | else var theme = 'cm-s-neo';
133 | this.textdom.setAttribute('class', 'CodeMirror CodeMirror-wrap ' + theme + ' terminus-wrap-text terminus-wrapper-height ');
134 | return this.textdom;
135 | } // colorizePre()
136 |
137 | Codemirror.prototype.jsonldCheck = function(format){
138 | if(format == 'jsonld') return true;
139 | }
140 |
141 | module.exports=Codemirror
142 |
--------------------------------------------------------------------------------
/src/plugins/datatables.terminus.js:
--------------------------------------------------------------------------------
1 | const TerminusClient = require('@terminusdb/terminus-client');
2 | const HTMLHelper = require('../html/HTMLHelper');
3 | const UTILS= require('../Utils')
4 |
5 | /*** client side processing ***/
6 | function CspDatatables(ui){
7 | this.ui = ui;
8 | }
9 |
10 | CspDatatables.prototype.convertToDatatable = function(tab){
11 | var dt = this;
12 | var table = jQuery(tab).DataTable({
13 | searching : false,
14 | pageLength: 25,
15 | lengthMenu: [10, 25, 50, 75, 100],
16 | paging : true,
17 | select : true,
18 | initComplete: function(settings) {
19 | var ict =settings.oInstance.api();
20 | ict.$('td').each(function(){
21 | this.setAttribute('title', $(this).html())
22 | })},
23 | columnDefs:[{targets:'_all',className:"truncate"}],
24 | createdRow: function(row) {
25 | var td = $(row).find(".truncate");
26 | td.attr("title", td.html());}
27 | }); //jQuery(tab)
28 |
29 | // on click of row connect to db, on click of 5th column delete db
30 | jQuery(tab, 'tbody').on('click', 'td', function(){
31 | if(table.cell(this).index().column == 5){
32 | var dbInfo = table.row(jQuery(this).parents('tr')).data();
33 | var dbId = UTILS.extractValueFromCell(dbInfo[0]);
34 | dt.ui.deleteDatabase(dbId);
35 | return;
36 | }
37 | else dt.ui.showDBMainPage();
38 | }); // on click
39 |
40 | tab.setAttribute('class' , 'stripe dataTable terminus-db-size');
41 | tab.setAttribute('cellpadding', '1');
42 | tab.setAttribute('cellspacing', '0');
43 | tab.setAttribute('border' , '0');
44 | return tab;
45 | }
46 |
47 | CspDatatables.prototype.draw = function(dtResult){
48 | return(this.convertToDatatable(dtResult));
49 | }
50 |
51 | /*** server side processing ***/
52 | function Datatables(wResViewer, qPage){
53 | this.wrViewer = wResViewer;
54 | this.wQuery = wResViewer.wQuery;
55 | this.ui = wResViewer.ui;
56 | this.qPage = qPage;
57 | this.currDTSettings = wResViewer.settings;
58 | }
59 |
60 | /*
61 | query: new woqlquery with current pagination changes
62 | pageInfo: current drawCallBack page change info
63 | resultDOM: result dom on veiwer page
64 | */
65 | Datatables.prototype.executeQuery = function(qObj, pageInfo, resultDOM){
66 | var self = this;
67 | // return this.wQuery.execute(query)
68 | return qObj.execute(this.ui.client)
69 | .then(function(result){
70 | var dtResult = {};
71 | var wqRes = new TerminusClient.WOQLResult(result, qObj);
72 | dtResult = self.wrViewer.formatResultsForDatatableDisplay(result.bindings, pageInfo)
73 | return dtResult.data;
74 | })
75 | .catch(function(err){
76 | console.error(err);
77 | self.ui.showError(err);
78 | });
79 | }
80 |
81 | /* get query string based on datatable pagination and current query */
82 | /*Datatables.prototype.getQueryOnPagination = function(wq, settings){
83 | switch(settings.query){
84 | case 'Show_All_Documents':
85 | return wq.getAllDocumentQuery(null, settings.pageLength, settings.start);
86 | break;
87 | case 'Show_All_Data':
88 | return wq.getEverythingQuery(null, settings.pageLength, settings.start);
89 | break;
90 | case 'Show_All_Schema_Elements':
91 | return wq.getElementMetaDataQuery(null, settings.pageLength, settings.start);
92 | break;
93 | case 'Show_Document_Classes':
94 | var sqp = wq.getConcreteDocumentClassPattern("Class");
95 | return wq.getClassMetaDataQuery(sqp);
96 | break;
97 | case 'Show_All_Properties':
98 | return wq.getPropertyListQuery(null, settings.pageLength, settings.start);
99 | break;
100 | case 'Show_All_Classes':
101 | return wq.getClassMetaDataQuery(null, settings.pageLength, settings.start);
102 | break;
103 | case 'Show_Data_Class':
104 | return wq.getDataOfChosenClassQuery(settings.chosenValue, settings.pageLength, settings.start);
105 | break;
106 | case 'Show_Property_Class':
107 | return wq.getDataOfChosenPropertyQuery(settings.chosenValue, settings.pageLength, settings.start);
108 | break;
109 | case 'Show_Document_Info_by_Id':
110 | return wq.getDocumentQuery(settings.chosenValue, settings.pageLength, settings.start);
111 | break;
112 | case 'Show_All_Document_classes':
113 | return wq.getClassesQuery(settings.pageLength, settings.start);
114 | break;
115 | default:
116 | console.log('Invalid woql option passed');
117 | break;
118 |
119 | }
120 | } */
121 | /*
122 | pageInfo: current drawCallBack page change info
123 | */
124 | Datatables.prototype.generateNewQueryOnPageChange = function(pageInfo){
125 | if(this.qPage) UTILS.deleteStylizedEditor(this.ui, pageInfo.qTextDom);
126 | var qObj = UTILS.getCurrentWoqlQueryObject(null, pageInfo);
127 | //var query = this.getQueryOnPagination(this.wQuery, pageInfo)
128 | if(this.qPage) {
129 | if(pageInfo.queryMode.value == 'woql')
130 | pageInfo.qTextDom.value = JSON.stringify(qObj.prettyPrint(), undefined, 2);
131 | else pageInfo.qTextDom.value = JSON.stringify(qObj, undefined, 2);
132 | UTILS.stylizeEditor(this.ui, pageInfo.qTextDom, 'query', 'javascript');
133 | }
134 | //return query;
135 | return qObj;
136 | }
137 |
138 | /*
139 | dt: Datatable reference
140 | len : current number of records to display
141 | */
142 | Datatables.prototype.getCallbackSettings = function(dt, dtAPIChangeSettings){
143 | var pageInfo = {};
144 | pageInfo.pageLength = dtAPIChangeSettings._iDisplayLength;
145 | pageInfo.start = dtAPIChangeSettings._iDisplayStart;
146 | pageInfo.draw = dtAPIChangeSettings.iDraw;
147 | pageInfo.qTextDom = dt.qTextDom;
148 | pageInfo.queryMode = dt.queryMode;
149 | if(this.qPage) pageInfo.query = dt.query;
150 | else pageInfo.query = 'Show_All_Document_classes';
151 | pageInfo.chosenValue = dt.chosenValue;
152 | return pageInfo;
153 | }
154 |
155 | /*
156 | tab: datatable table dom
157 | settings : settings from woql txt generator
158 | resultDOM: result dom of viewer
159 | */
160 | Datatables.prototype.setUp = function(tab, settings, resultDOM){
161 | // delete previous datatable
162 | HTMLHelper.removeChildren(this.dtdom);
163 | this.dtdom = document.createElement('div');
164 | this.dtdom.appendChild(tab);
165 | resultDOM.appendChild(this.dtdom);
166 | // saving query text box dom to change limit value on change of datatable page length
167 | this.qTextDom = settings.qTextDom;
168 | this.query = settings.query;
169 | this.chosenValue = settings.chosenValue;
170 | this.queryMode = settings.queryMode;
171 | }
172 |
173 | // update datatables settings so it can be reused in WOQLTextboxGenerator to re write query in woql/ jsonld
174 | Datatables.prototype.updateCurrDTSettings = function(pageInfo){
175 | this.currDTSettings.pageLength = pageInfo.pageLength;
176 | this.currDTSettings.start = pageInfo.start;
177 | }
178 |
179 | Datatables.prototype.getNewDataOnChange = function(drawnTab, aSettings, resultDOM){
180 | var pageInfo = this.getCallbackSettings(this, aSettings);
181 | this.updateCurrDTSettings(pageInfo);
182 | // var query = this.generateNewQueryOnPageChange(pageInfo);
183 | var qObj = this.generateNewQueryOnPageChange(pageInfo);
184 | return this.executeQuery(qObj, pageInfo, resultDOM);
185 | //return this.executeQuery(query, pageInfo, resultDOM);
186 | //return dtResult.result.data;
187 | }
188 |
189 | Datatables.prototype.getDataFromServer = function(dtResult, resultDOM){
190 | var dt = this;
191 | var tab = dtResult.tab;
192 | this.setUp(tab, this.wrViewer.settings, resultDOM);
193 | // initialize datatables
194 | var table = jQuery(tab).DataTable({
195 | searching : false,
196 | pageLength : dt.wrViewer.settings.pageLength,
197 | serverSide : true,
198 | processing : true,
199 | lengthMenu : [25, 50, 75, 100],
200 | dom : 'RBlftip',
201 | columns : dtResult.result.columns,
202 | paging : true,
203 | select : true,
204 | autoWidth : true,
205 | ajax : function (data, callback, settings) {
206 | if(Object.entries(dtResult.result.data).length > 0){
207 | // first draw is loaded
208 | var res = dtResult.result.data;
209 | dtResult.result.data = {};
210 | callback(res);
211 | }
212 | else{
213 | dt.getNewDataOnChange(this, settings, resultDOM)
214 | .then(function(result){
215 | callback(result);
216 | })
217 | }
218 | },
219 | buttons : [{ extend: 'copy', text: 'Copy to clipboard' },
220 | { extend: 'excel', text: 'Export to Excel' }],
221 | columnDefs : [{ targets:'_all',
222 | className:"truncate"}],
223 | createdRow : function(row){
224 | var td = $(row).find(".truncate");
225 | td.attr("title", td.html());},
226 | scrollX : true
227 | }); //jQuery(tab)
228 |
229 | // on click of doc
230 | jQuery(tab, 'tbody').on('click', 'td', function(){
231 | if(table.cell(this).data){
232 | if(this.innerText.substring(0, 4) == "doc:"){
233 | if(dt.wrViewer.result.ui) {
234 | dt.wrViewer.result.ui.showDocument(this.innerText);
235 | dt.wrViewer.result.ui.redraw();
236 | dt.wrViewer.selectDocumentNavBar(dt.ui);
237 | }
238 | }
239 | }
240 | }); // on click
241 |
242 | //styling
243 | tab.setAttribute('class' , 'stripe dataTable');
244 | tab.setAttribute('style' , 'margin: 0!important');
245 | tab.setAttribute('cellpadding', '1');
246 | tab.setAttribute('cellspacing', '1');
247 | tab.setAttribute('border' , '0');
248 |
249 | return tab;
250 | }
251 |
252 | /*
253 | serverside: true or false
254 | */
255 | Datatables.prototype.draw = function(dtResult, resultDOM){
256 | return(this.getDataFromServer(dtResult, resultDOM));
257 | }
258 |
259 | module.exports={Datatables, CspDatatables}
260 |
--------------------------------------------------------------------------------
/src/test.js:
--------------------------------------------------------------------------------
1 | var TerminusDashboard = require('./index.js');
2 |
3 | var TerminusUI= TerminusDashboard.WOQL;
4 |
5 | console.log(TerminusDashboard.WOQL.limit(10).json())
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebPackPlugin = require("html-webpack-plugin");
3 | const CopyWebPackPlugin = require("copy-webpack-plugin");
4 | require("@babel/register");
5 | const Dotenv = require('dotenv-webpack');
6 | var PACKAGE = require('./package.json');
7 | var version = `v${PACKAGE.version}`;
8 |
9 |
10 | // Webpack Configuration
11 | const config = {
12 |
13 | // Entry
14 | entry: path.resolve(__dirname, 'src/index.js'),
15 | // Output
16 | output: {
17 | path: path.resolve(__dirname, `public_pages/${version}/dist`),
18 | filename: 'terminus-dashboard.min.js',
19 | sourceMapFilename: 'terminus-dashboard.min.js.map',
20 | libraryTarget: 'var',
21 | library: 'TerminusDashboard',
22 | },
23 | node: {
24 | //process: false
25 | fs: "empty"
26 | },
27 | // Loaders
28 |
29 |
30 | module: {
31 | rules : [
32 | // JavaScript/JSX Files
33 | {
34 | test: /\.js$/,
35 | exclude: /node_modules/,
36 | loader: 'babel-loader'
37 | }
38 | ]
39 | },
40 | devtool :'source-map',
41 | // Plugins
42 | };
43 |
44 | module.exports = function(env, argv){
45 |
46 |
47 | if (argv.mode === 'development') {
48 | // webpack-dev-server configuration
49 | config.devServer={
50 | // Can be omitted unless you are using 'docker'
51 | contentBase: path.resolve(__dirname,'dist'),
52 | // 'Live-reloading' happens when you make changes to code
53 | // dependency pointed to by 'entry' parameter explained earlier.
54 | // To make live-reloading happen even when changes are made
55 | // to the static html pages in 'contentBase', add
56 | // 'watchContentBase'
57 | watchContentBase: true,
58 | compress: true
59 | }
60 | }
61 |
62 | config.plugins= [
63 | new Dotenv(),
64 | new HtmlWebPackPlugin({
65 | inject: false,
66 | template: path.resolve(__dirname, 'src/index.html'),
67 | bundleFileName:"terminus-dashboard.min.js"
68 | }),
69 | new CopyWebPackPlugin([
70 | { from: path.resolve(__dirname, 'src/css'), to: 'css' },
71 | { from: path.resolve(__dirname, 'src/UIconfig.json'), to:'./' }
72 | ])
73 | ]
74 |
75 | return config;
76 | };
77 |
78 | // Exports
79 | //module.exports = config;
80 |
--------------------------------------------------------------------------------