2 var DefaultShadow =
"";
7 var CurrentNamedConfig =
"";
11 var EditedValues = {};
12 var ExportTarFileName =
"export";
14 var ConfigVersionData = {};
21 function GenerateUuid() {
23 if (window.performance && typeof window.performance.now ===
"function") {
24 d += performance.now();
26 var uuid =
"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,
function (c) {
27 var r = (d + Math.random() * 16) % 16 | 0;
28 d = Math.floor(d / 16);
29 return (c ===
"x" ? r : (r & 0x3 | 0x8)).toString(16);
34 function UpdateHeader(error, change, text) {
36 $(
"#header").css(
"background-color",
"#D59595").css(
"text-shadow",
"#D99 0 1px 0");
37 $(
"#info").text(text);
38 text =
"ERROR: " + text;
40 $(
"#header").css(
"background-color",
"#E7F29B").css(
"text-shadow",
"#EF9 0 1px 0");
41 $(
"#info").text(text);
42 text =
"CHANGE: " + text;
44 $(
"#header").css(
"background-color", DefaultColor).css(
"text-shadow", DefaultShadow);
45 $(
"#info").text(text);
47 if (text.length > 0) {
52 function ResizeTextAreas() {
53 $(
"textarea").each(
function (i, el) {
54 $(el).height(el.scrollHeight);
58 function GetRadix(value) {
64 if (value.search(
"0x") === 0) {
65 output.value = value.slice(2);
67 if ((
"" + output.value).search(/[^0-9a-fA-F]/) >= 0) { output.radix = -1; }
68 }
else if (value.search(
"0") === 0) {
69 output.value = value.slice(1);
71 if (isNaN(output.value)) { output.radix = -1; }
72 }
else if (value.search(
"b") === value.length - 1) {
73 output.value = value.slice(0, -1);
75 if (isNaN(output.value)) { output.radix = -1; }
76 }
else if (isNaN(value)) {
83 if (output.value ===
" " || (
"" + output.value).length === 0 || (
"" + output.value).indexOf(
".") >= 0) {
90 function CreateRowEditor(row, cellvalue, editor, cellText, width, height) {
91 editor.after(
"<div></div><div></div>");
92 var radixObj = GetRadix(cellText);
93 if (radixObj.radix > 0) {
94 editor.parent().jqxFormattedInput({ radix: radixObj.radix, value: radixObj.value, width: width, height: height, upperCase:
true, dropDown:
true, spinButtons:
true });
98 function InitRowEditor(row, cellvalue, editor) {
99 editor.parent().val(cellvalue);
102 function GetRowEditorValue(row, cellvalue, editor) {
103 if (editor.parent()) {
104 if (editor.val().length === 0) {
105 editor.parent().parent().empty();
108 var radix = editor.parent().jqxFormattedInput(
"radix");
109 if (radix === 2 || radix ===
"binary") {
110 return editor.val() +
"b";
112 if (radix === 16 || radix ===
"hexadecimal") {
113 return "0x" + editor.val().toUpperCase();
115 if (radix === 8 || radix ===
"octal") {
116 if (editor.val()[0] ===
"0") {
119 return "0" + editor.val();
125 function RowEditDialogSave(dataFields, newRowId, grid) {
128 for (var i in dataFields) {
129 if (dataFields.hasOwnProperty(i)) {
130 var name = dataFields[i].name +
"_Editor";
131 var value =
"" + $(
"#" + name).val();
132 if (value ===
"undefined") {
135 row[dataFields[i].name] = value;
140 var currentName = path;
141 var rowData = grid.jqxTreeGrid(
"getRow", newRowId);
142 var parent = rowData.parent;
144 if ((parent === null || parent === undefined) && currentName.indexOf(
"___") >= 0) {
145 var parentSelector = grid.selector.split(
" ").slice(0, -1).join(
" ");
146 var parentRow = $(parentSelector +
" #treeGrid").jqxTreeGrid(
"getRow", currentName.slice(0, -4));
147 parent = parentRow[0];
149 if (parent !== null && parent !== undefined) {
150 currentName = parent.name;
151 path = parent.name +
"/" + path;
152 parent = parent.parent;
154 }
while (parent !== null && parent !== undefined);
156 if (CurrentCollection && CurrentEntity) {
157 path = CurrentCollection +
"/" + CurrentEntity +
"/" + path;
159 var pathTmp = path.split(
'/');
160 var collection = pathTmp.shift();
161 var entity = pathTmp.shift();
162 var collectionTab = $(
".collection-tab[collection-name=\"" + collection +
"\"] a");
163 collectionTab.trigger(
"click");
164 var fileNameTab = $(collectionTab[0].hash).find(
".file-tab[file-name=\"" + entity +
"\"] a");
165 fileNameTab.trigger(
"click");
166 $(
"li.active :visible").parent().addClass(
"editedValue");
167 $(
".configInfo-tab a").trigger(
"click");
168 CurrentCollection = collection;
169 CurrentEntity = entity;
172 grid.jqxTreeGrid(
"updateRow", newRowId, row);
173 EditedValues[CurrentCollection +
"/" + CurrentEntity +
"/" + row.name] =
true;
174 $(
"li.active :visible").parent().addClass(
"editedValue");
175 $(
".configInfo-tab").removeClass(
"editedValue");
178 AjaxPost(
"/db/AddOrUpdate", {
179 configName: CurrentNamedConfig,
184 },
function (retval) {
185 if (retval.Success) {
187 $(
"#changes", $(
".file-tab.active a").attr(
"href")).val(now.toISOString() +
": Edit - Path: " + path +
", Name: " + row.name +
" Dialog Edit - multiple columns may have been changed!");
188 $(
"#masterChanges").val(now.toISOString() +
": Edit - Path: " + path +
", Name: " + row.name +
" Dialog Edit - multiple columns may have been changed!");
190 UpdateHeader(
false,
true,
"There are pending unsaved changes. Please save or discard before closing the editor!");
192 UpdateHeader(
true,
false,
"Sending Update to server failed");
198 function MakeTreeGrid(tag, dataFields, data, columnGroups) {
199 tag.html(TreeGridHtml);
200 var grid = tag.find(
"#treeGrid");
201 var contextMenu = tag.find(
"#Menu");
202 var dialog = tag.find(
"#dialog");
204 var displayColumns = TranslateColumns(dataFields);
207 console.log(
"DisplayColumns is " + JSON.stringify(displayColumns));
208 console.log(
"DataFields is " + JSON.stringify(dataFields));
212 dataFields: dataFields,
218 addRow:
function (rowID, rowData, position, parentID, commit) {
224 var dataAdapter =
new $.jqx.dataAdapter(source, {
225 beforeLoadComplete:
function (records) {
226 var numberFields = [];
227 for (var c in source.dataFields) {
228 if (source.dataFields.hasOwnProperty(c)) {
229 if (source.dataFields[c].dataType ===
"number") {
230 numberFields.push({ name: source.dataFields[c].name, radix: source.dataFields[c].radix });
234 for (var i in records) {
235 if (records.hasOwnProperty(i)) {
236 for (var f in numberFields) {
237 if (numberFields.hasOwnProperty(f)) {
238 var radix = numberFields[f].radix;
242 var value = records[i][numberFields[f].name];
244 if (typeof value ===
"number" || !(value.search(
"0x") === 0 || value.search(
"0") === 0 || value.search(
"b") === value.length - 1)) {
246 value = parseInt(value).toString(radix).toUpperCase();
247 records[i][numberFields[f].name] = value;
249 records[i][numberFields[f].name] +=
"b";
252 records[i][numberFields[f].name] =
"0x" + value;
255 records[i][numberFields[f].name] =
"0" + value;
267 var sequenceTables = [];
269 grid.addClass(
"jqxTreeGrid").jqxTreeGrid(
274 editSettings: { saveOnPageChange:
true, saveOnBlur:
true, saveOnSelectionChange:
true, cancelOnEsc:
true, saveOnEnter:
true, editSingleCell:
true, editOnDoubleClick:
true, editOnF2:
true },
277 columns: displayColumns,
278 columnGroups: columnGroups,
280 rowDetailsRenderer:
function (rowKey, row) {
281 if (row.isSequence) {
282 var indent = (1 + row.level) * 20;
283 var details =
"<div id=\"" + rowKey +
"___Table\" style=\"margin-left: " + indent +
"px;padding-right: 5px\"></div>";
284 sequenceTables.push({ key: rowKey, data: row.table });
290 rendered:
function () {
291 $(
".jqx-tooltip").
remove();
292 var setupRow =
function (rowObject) {
293 if (rowObject[source.comment] && rowObject[source.comment].length > 0 && rowObject[source.comment] !==
" ") {
294 var selector = $(
"tr[data-key=\'" + rowObject.uid +
"\']");
295 if (selector.length) {
296 selector.jqxTooltip({ content: rowObject[source.comment], position:
"mouse" });
299 for (var trow in rowObject.records) {
300 if (rowObject.records.hasOwnProperty(trow)) {
301 setupRow(rowObject.records[trow]);
305 var rows = grid.jqxTreeGrid(
"getRows");
306 for (var ttrow = 0; ttrow < rows.length; ttrow++) {
307 setupRow(rows[ttrow]);
309 for (var seq in sequenceTables) {
310 if (sequenceTables.hasOwnProperty(seq)) {
311 var elem = tag.find(
"#" + sequenceTables[seq].key +
"___Table");
312 var data = sequenceTables[seq].data;
313 MakeTreeGrid(elem, data.columns, data.rows, data.columnGroups);
318 dialog.on(
"close",
function () {
320 grid.jqxTreeGrid({ disabled:
false });
325 position: { left: grid.offset().left + 75, top: grid.offset().top + 35 },
327 showCloseButton:
false
329 dialog.css(
"visibility",
"visible");
334 grid.jqxTreeGrid(
"expandAll");
336 contextMenu.jqxMenu({ width: 200, height: 90, autoOpenPopup:
false, mode:
"popup" });
337 grid.on(
"contextmenu",
function () {
340 grid.on(
"rowClick",
function (event) {
341 var args =
event.args;
342 if (args.originalEvent.button === 2) {
343 var scrollTop = $(window).scrollTop();
344 var scrollLeft = $(window).scrollLeft();
346 if (args.row.type ===
"table" || args.row.type ===
"sequence") {
347 contextMenu.jqxMenu(
"disable",
"edit",
true);
348 contextMenu.jqxMenu(
"disable",
"bitedit",
true);
349 contextMenu.jqxMenu(
"disable",
"add",
false);
351 contextMenu.jqxMenu(
"disable",
"edit",
false);
352 contextMenu.jqxMenu(
"disable",
"bitedit",
false);
353 contextMenu.jqxMenu(
"disable",
"add",
true);
356 contextMenu.jqxMenu(
"open", parseInt(event.args.originalEvent.clientX) + 5 + scrollLeft, parseInt(event.args.originalEvent.clientY) + 5 + scrollTop);
361 var edit =
function (row, key, newRow, x, y, deleteOnCancel) {
364 dialog.jqxWindow(
"setTitle",
"Edit Row: " + row.name);
365 dialog.jqxWindow(
"setContent", DialogContentHtml);
366 dialog.jqxWindow(
"move", x, y);
368 for (var i in dataFields) {
369 if (dataFields.hasOwnProperty(i)) {
370 var name = dataFields[i].name;
371 var value =
"" + row[name];
372 if (value ===
"undefined") {
375 if (dataFields[i].editable || newRow) {
376 var start =
"<tr><td align=\"right\">" + name +
":</td><td align=\"left\">";
377 var editor =
"<input id=\"" + name +
"_Editor\" type=\"text\" value=\"" + value +
"\" />";
379 var radixObj = GetRadix(value);
380 if (name ===
"name") radixObj.radix = -1;
382 if (radixObj.radix > 0) {
383 editor =
"<div id=\"" + name +
"_Editor\"><input type=\"text\" /><div></div><div></div></div>";
385 name: name +
"_Editor",
386 value: radixObj.value,
387 radix: radixObj.radix
390 var end =
"</td></tr>";
391 dialog.find(
"tr:last").before(start + editor + end);
393 dialog.find(
"tr:last").before(
"<tr><td align=\"right\">" + name +
":</td><td align=\"left\"><input id=\"" + name +
"_Editor\" type=\"text\" value=\"" + value +
"\" readonly=\"true\" disabled=\"disabled\" /></td></tr>");
397 var content = dialog.find(
"table").parent().html();
398 dialog.jqxWindow(
"setContent", content);
399 for (var ed in jqEditors) {
400 if (jqEditors.hasOwnProperty(ed)) {
401 dialog.find(
"#" + jqEditors[ed].name).jqxFormattedInput({ radix: jqEditors[ed].radix, value: jqEditors[ed].value, width:
"100%", height: 25, upperCase:
true, dropDown:
true, spinButtons:
true });
404 dialog.find(
"#save").jqxButton({ height: 30, width: 80 });
405 dialog.find(
"#cancel").jqxButton({ height: 30, width: 80 });
406 dialog.find(
"#save").mousedown(
function () {
407 dialog.jqxWindow(
"close");
408 RowEditDialogSave(dataFields, newRowId, grid);
410 dialog.find(
"#cancel").mousedown(
function () {
411 dialog.jqxWindow(
"close");
412 if(deleteOnCancel) grid.jqxTreeGrid(
"deleteRow", newRowId);
414 dialog.jqxWindow(
"open");
415 var newHeight = $(
"#bottomOfDialog").position().top + 100;
416 dialog.jqxWindow({ height: newHeight });
417 dialog.attr(
"data-row", key);
420 grid.jqxTreeGrid({ disabled:
true });
422 var bitedit =
function (row, key, x, y) {
425 dialog.jqxWindow(
"setTitle",
"Bit Editor for Row: " + row.name);
426 dialog.jqxWindow(
"setContent", DialogContentHtml);
427 dialog.jqxWindow(
"move", x, y);
429 for (var i in dataFields) {
430 if (dataFields.hasOwnProperty(i)) {
431 var name = dataFields[i].name;
432 var value =
"" + row[name];
433 if (value ===
"undefined") {
436 dialog.find(
"tr:last").before(
"<input id=\"" + name +
"_Editor\" type=\"hidden\" value=\"" + value +
"\" />");
437 if (dataFields[i].editable) {
438 var radixObj = GetRadix(value);
439 if (radixObj.radix === 2 || radixObj.radix === 8 || radixObj.radix === 16)
445 var selectHtml =
"<select id=bitFieldSelect>";
446 for (var f in fields) {
447 if (fields.hasOwnProperty(f)) {
448 selectHtml +=
"<option id=" + fields[f] +
" value=\"" + fields[f] +
"\">" + fields[f] +
"</option>";
451 selectHtml +=
"</select>";
452 dialog.find(
"tr:last").before(
"<tr><td colspan=\"2\" align=\"right\">" + selectHtml +
"</td></tr>");
453 dialog.find(
"tr:last").before(
'<tr><td colspan="2" align="right"><div id=bitCheckboxes></div></td></tr>');
455 var content = dialog.find(
"table").parent().html();
456 dialog.jqxWindow(
"setContent", content);
457 dialog.find(
"#bitFieldSelect").change(
function () {
458 var currentValue = dialog.find(
"#" + this.value +
"_Editor").val();
459 var radixObj = GetRadix(currentValue);
460 var length = String(radixObj.value).length;
462 switch (radixObj.radix) {
474 var bitFieldCheckboxHtml =
"<table><tr>";
475 for (var i = 0; i < bits; ++i) {
476 if (i > 0 && i % 4 === 0) {
477 bitFieldCheckboxHtml +=
"</tr><tr>";
479 var checkedStr = (currentValue & (1 << i)) !== 0 ?
"checked" :
"";
480 bitFieldCheckboxHtml +=
"<td><input type=\"checkbox\" name=\"" + i +
"\" class=\"bitFieldCheckBox\"" + checkedStr +
">" + i +
"</input></td>";
482 bitFieldCheckboxHtml +=
"</tr></table>";
483 dialog.find(
"#bitCheckboxes").html(bitFieldCheckboxHtml);
484 var newHeight = $(
"#bottomOfDialog").position().top;
485 dialog.jqxWindow({ height: newHeight });
486 $(
".bitFieldCheckBox").change(
function () {
487 var currentValue = String(dialog.find(
"#" + $(
"#bitFieldSelect").val() +
"_Editor").val());
488 var radixObj = GetRadix(currentValue);
489 var bitId = this.name;
490 var digit, rem, curDigit, mask;
491 switch (radixObj.radix) {
493 currentValue = currentValue.substr(0, currentValue.length - bitId - 1) + (this.checked ?
"1" :
"0") + currentValue.substr(currentValue.length - bitId);
496 digit = Math.floor(bitId / 3);
497 rem = bitId - (digit * 3);
498 curDigit = parseInt(currentValue.charAt(currentValue.length - digit - 1), 8);
500 curDigit = curDigit | (1 << rem);
502 mask = 7 - (1 << rem);
503 curDigit = curDigit & mask;
505 currentValue = currentValue.substr(0, currentValue.length - digit - 1) + curDigit.toString(8) + currentValue.substr(currentValue.length - digit);
508 digit = Math.floor(bitId / 4);
509 rem = bitId - (digit * 4);
510 curDigit = parseInt(currentValue.charAt(currentValue.length - digit - 1), 16);
512 curDigit = curDigit | (1 << rem);
514 mask = 15 - (1 << rem);
515 curDigit = curDigit & mask;
517 currentValue = currentValue.substr(0, currentValue.length - digit - 1) + curDigit.toString(16) + currentValue.substr(currentValue.length - digit);
520 dialog.find(
"#" + $(
"#bitFieldSelect").val() +
"_Editor").val(currentValue);
522 }).trigger(
"change");
523 dialog.find(
"#save").jqxButton({ height: 30, width: 80 });
524 dialog.find(
"#cancel").jqxButton({ height: 30, width: 80 });
525 dialog.find(
"#save").mousedown(
function () {
526 dialog.jqxWindow(
"close");
527 RowEditDialogSave(dataFields, newRowId, grid);
529 dialog.find(
"#cancel").mousedown(
function () {
530 dialog.jqxWindow(
"close");
532 dialog.jqxWindow(
"open");
533 var newHeight = $(
"#bottomOfDialog").position().top;
534 dialog.jqxWindow({ height: newHeight });
535 dialog.attr(
"data-row", key);
538 grid.jqxTreeGrid({ disabled:
true });
540 contextMenu.on(
"itemclick",
function (event) {
541 var args =
event.args;
542 var selection = grid.jqxTreeGrid(
"getSelection");
543 var rowid = selection[0].uid;
544 var text = $.trim($(args).text());
545 if (text ===
"Edit Selected Row") {
546 edit(selection[0], rowid,
false, event.pageX, event.pageY,
false);
547 }
else if (text ===
"Bit Editor") {
548 bitedit(selection[0], rowid, event.pageX, event.pageY);
550 var arrayName =
false;
551 if ((
"" + rowid).search(/___/) > 0) {
554 grid.jqxTreeGrid(
"addRow", null, {},
"last", rowid);
556 var idx = newRowId.search(/___/);
557 var num = newRowId.slice(idx + 3, -1);
558 num = parseInt(num) + 1;
559 newRowId = newRowId.slice(0, idx + 3) + num;
562 for (var i in dataFields) {
563 if (dataFields.hasOwnProperty(i)) {
564 obj[dataFields[i].name] =
"";
568 edit(obj, newRowId,
true, event.pageX, event.pageY,
true);
573 grid.on(
"cellEndEdit",
function (event) {
574 var args =
event.args;
576 var rowKey = args.key;
578 var rowData = args.row;
579 var path = rowData.name;
580 var currentName = rowKey;
581 var parent = rowData.parent;
584 if ((parent === null || parent === undefined) && currentName.indexOf(
"___") >= 0) {
585 var parentSelector = tag.selector.split(
" ").slice(0, -1).join(
" ");
586 var parentRow = $(parentSelector +
" #treeGrid").jqxTreeGrid(
"getRow", currentName.slice(0, -4));
587 parent = parentRow[0];
588 while ((parent !== null && parent !== undefined) && parent.constructor === Array) {
592 else if ((parent === null || parent === undefined) && rowData.name.indexOf(
"___") >= 0 && first) {
594 var parentSelector = tag.selector.split(
" ").slice(0, -1).join(
" ");
595 var parentName = tag.selector.split(
" ").slice(-1).join(
" ").slice(1);
596 parentName = parentName.slice(0, parentName.indexOf(
"___"));
597 var parentRow = $(parentSelector +
" #treeGrid").jqxTreeGrid(
"getRow", parentName);
598 parent = parentRow[0];
599 while ((parent !== null && parent !== undefined) && parent.constructor === Array) {
604 if (parent !== null && parent !== undefined) {
605 currentName = parent.name;
606 path = parent.name +
"/" + path;
607 parent = parent.parent;
609 }
while (parent !== null && parent !== undefined);
611 if (CurrentCollection && CurrentEntity) {
612 path = CurrentCollection +
"/" + CurrentEntity +
"/" + path;
614 var pathTmp = path.split(
'/');
615 var collection = pathTmp.shift();
616 var entity = pathTmp.shift();
617 var collectionTab = $(
".collection-tab[collection-name=\"" + collection +
"\"] a");
618 collectionTab.trigger(
"click");
619 var fileNameTab = $(collectionTab[0].hash).find(
".file-tab[file-name=\"" + entity +
"\"] a");
620 fileNameTab.trigger(
"click");
621 $(
"li.active :visible").parent().addClass(
"editedValue");
622 $(
".configInfo-tab a").trigger(
"click");
623 CurrentCollection = collection;
624 CurrentEntity = entity;
626 console.log(
"Path is " + path);
628 var columnDataField = args.dataField;
630 var columnName = args.dataField;
631 for (var i in args.owner._columns) {
632 if (args.owner._columns.hasOwnProperty(i)) {
633 if (args.owner._columns[i].dataField === columnName) {
634 columnName = args.owner._columns[i].text;
639 EditedValues[CurrentCollection +
"/" + CurrentEntity +
"/" + rowKey] =
true;
640 $(
"li.active :visible").parent().addClass(
"editedValue");
641 $(
".configInfo-tab").removeClass(
"editedValue");
643 var value = args.value;
645 AjaxPost(
"/db/Update", {
646 configName: CurrentNamedConfig,
648 column: columnDataField,
653 },
function (retval) {
654 if (retval.Success) {
656 var selector = $(
"#changes", $(
".file-tab.active a").attr(
"href"));
657 selector.val(now.toISOString() +
": Edit - File: " + CurrentCollection +
"/" + CurrentEntity +
", Name: " + rowData.name +
", Column: " + columnName +
", Value: " + value +
"\n" + selector.val());
658 $(
"#masterChanges").val(now.toISOString() +
": Edit - File: " + CurrentCollection +
"/" + CurrentEntity +
", Name: " + rowData.name +
", Column: " + columnName +
", Value: " + value +
"\n" + $(
"#masterChanges").val());
659 UpdateHeader(
false,
true,
"There are pending unsaved changes. Please save or discard before closing the editor!");
661 UpdateHeader(
true,
false,
"Sending Update to server failed");
667 function CellClass(row, dataField, cellText, rowData) {
669 for (var val in EditedValues) {
670 if (EditedValues.hasOwnProperty(val)) {
671 if (val === CurrentCollection +
"/" + CurrentEntity +
"/" + rowData.uid) {
672 edited = EditedValues[val];
678 return "editedValue";
683 function TranslateColumns(columns) {
684 var displayColumns = [];
686 for (var c in columns) {
687 if (columns.hasOwnProperty(c)) {
688 var title = columns[c].title;
689 if (title === undefined || title === null || title.length === 0) {
690 title = columns[c].name.charAt(0).toUpperCase() + columns[c].name.slice(1);
692 if (columns[c].type ===
"string" && columns[c].display) {
693 displayColumns.push({
695 dataField: columns[c].name,
696 editable: columns[c].editable,
697 columnGroup: columns[c].columnGroup,
698 createEditor: CreateRowEditor,
699 initEditor: InitRowEditor,
700 getEditorValue: GetRowEditorValue,
701 cellClassName: CellClass
703 }
else if (columns[c].type ===
"number" && columns[c].display) {
704 columns[c].type =
"string";
705 columns[c].dataType =
"number";
706 displayColumns.push({
708 dataField: columns[c].name,
709 editable: columns[c].editable,
710 columnGroup: columns[c].columnGroup,
711 createEditor: CreateRowEditor,
712 initEditor: InitRowEditor,
713 getEditorValue: GetRowEditorValue,
714 cellClassName: CellClass
719 return displayColumns;
722 function LoadTable(tag) {
724 AjaxPost(
"/db/GetData", { configName: CurrentNamedConfig, entity: CurrentEntity, collection: CurrentCollection, user: UserId },
function (data) {
726 UpdateHeader(
true,
false,
"Fetch of data from database failed");
729 var columns = data.data.columns;
731 MakeTreeGrid(tag, columns, data.data.children);
736 function SetupConfigVersionPicker(element, target) {
738 element.on(
"change",
function () {
739 var thisConfig = element.find(
":selected").text();
740 var configVersionHtml =
"";
741 for (var version in ConfigVersionData[thisConfig]) {
742 if (ConfigVersionData[thisConfig].hasOwnProperty(version)) {
743 configVersionHtml +=
"<option name=\"" + ConfigVersionData[thisConfig][version].name
744 +
"\" value=" + ConfigVersionData[thisConfig][version].data +
">" + ConfigVersionData[thisConfig][version].version +
"</option>";
747 $(
"#" + target).html(configVersionHtml).trigger(
"create").selectmenu(
"refresh");
748 $(
"#" + target).html($(
"#" + target +
" option").sort(
function (a, b) {
749 return parseInt(a.text) === parseInt(b.text) ? 0 : parseInt(a.text) > parseInt(b.text) ? -1 : 1;
751 var option = $(
"#" + target).find(
'option:eq(0)');
752 option.prop(
'selected',
true);
753 $(
"#"+target).trigger(
"create").selectmenu(
"refresh");
757 function GetConfigList() {
758 UpdateHeader(
false,
false,
"");
759 $(
"#masterChanges").val(
"");
761 for (var i = 2; i <= LastTabId; i++) {
762 $(
"#tab" + i).
remove();
763 $(
"#tablink" + i).
remove();
766 $(
"#reloadConfigsButton").text(
"Reload Configurations");
769 AjaxPost(
"/db/NamedConfigs", { configFilter: $(
"#configurationFilter").val(), user: UserId },
function (data) {
771 UpdateHeader(
true,
false,
"Error retrieving Configuration list. Please contact an expert!");
774 var configsHtml =
"";
775 for (var name in data.data) {
776 if (data.data.hasOwnProperty(name)) {
777 configsHtml +=
"<option>" + name +
"</option>";
778 ConfigVersionData[name] = data.data[name];
781 $(
"#configs").html(configsHtml).trigger(
"create").selectmenu(
"refresh");
782 $(
"#oldConfigName").html(configsHtml).trigger(
"create").selectmenu(
"refresh");
783 $(
"#exportConfigName").html(configsHtml).trigger(
"create").selectmenu(
"refresh");
785 SetupConfigVersionPicker($(
"#configs"),
"configversions");
786 $(
"#configs").trigger(
"change");
787 SetupConfigVersionPicker($(
"#oldConfigName"),
"oldConfigVersion");
788 $(
"#oldConfigName").trigger(
"change");
789 SetupConfigVersionPicker($(
"#exportConfigName"),
"exportConfigVersion");
790 $(
"#exportConfigName").trigger(
"change");
792 var config = GetUrlParameter(
"configs");
793 if (config !== undefined) {
794 $(
"#configs").val(config);
797 $(
"#configLoad").collapsible(
"option",
"disabled",
false).collapsible(
"option",
"collapsed",
false);
798 $(
"#configSave").collapsible(
"option",
"disabled",
true).collapsible(
"option",
"collapsed",
true);
799 $(
"#configMetadata").collapsible(
"option",
"disabled",
true).collapsible(
"option",
"collapsed",
true);
800 $(
"#searchConfig").collapsible(
"option",
"disabled",
false);
801 $(
"#exportFile").collapsible(
"option",
"collapsed",
true);
802 $(
"#newConfig").collapsible(
"option",
"collapsed",
true);
805 function RegisterTabFunctions() {
806 $(
".file-tab a").off();
807 $(
".collection-tab a").off();
808 $(
".tabs .tab-links a").off().on(
"click",
function (e) {
809 var currentAttrValue = $(
this).attr(
"href");
810 var tab = $(
this).parent();
811 var div = tab.parent();
813 var left = Math.floor(tab.position().left - 20);
814 div.scrollLeft(left);
816 $(
".tabs " + currentAttrValue).show().siblings().hide();
819 $(
this).parent(
"li").addClass(
"active").siblings().removeClass(
"active");
823 $(
".configInfo-tab a").on(
"click",
function () {
824 CurrentCollection = null;
825 CurrentEntity = null;
827 $(
".collection-tab a").on(
"click",
function () {
828 CurrentCollection = $(
this).text();
830 $(
".file-tab a").on(
"click",
function () {
831 var fileName = $(
this).text();
832 CurrentEntity = fileName;
833 LoadFile($(
this).attr(
"href"));
838 function GetUrlParameter(sParam) {
839 var sUrlVariables = window.location.search.substring(1).split(
"&");
841 for (var i = 0; i < sUrlVariables.length; i++) {
842 var sParameterName = sUrlVariables[i].split(
"=");
844 if (sParameterName[0].search(sParam) >= 0) {
846 return sParameterName[1];
852 function LoadConfigMetadata() {
853 console.log(
"Loading configuration metadata");
855 AjaxPost(
"/db/LoadConfigMetadata", { configName: CurrentNamedConfig, user: UserId },
function (metadata) {
856 if (!metadata.Success) {
857 UpdateHeader(
true,
false,
"Error loading configuration metadata from database");
860 var metadataObj = metadata.data;
863 var displayColumns = [
870 text:
"Collection Name",
871 dataField:
"collection",
876 dataField:
"version",
880 text:
"Edit", cellsAlign:
"center", align:
"center", columnType:
"none", editable:
false, sortable:
false, dataField: null, cellsRenderer:
function (row) {
882 return "<button data-row='" + row +
"' class='editButtons' onclick=''>Edit</button>";
887 { name:
"name", type:
"string", editable:
false, display:
true },
888 { name:
"collection", type:
"string", editable:
false, display:
true },
889 { name:
"file", type:
"string", editable:
false, display:
false },
890 { name:
"version", type:
"string", editable:
false, display:
true }
894 dataFields: dataFields,
899 localData: metadataObj.entities
902 var dataAdapter =
new $.jqx.dataAdapter(source);
904 var grid = $(
"#configurationEntities");
905 grid.addClass(
"jqxTreeGrid").jqxTreeGrid(
912 columns: displayColumns,
913 rendering:
function () {
915 if ($(
".editButtons").length > 0) {
916 $(
".editButtons").jqxButton(
"destroy");
919 rendered:
function () {
920 if ($(
".editButtons").length > 0) {
921 $(
".editButtons").jqxButton();
923 var editClick =
function (event) {
925 var rowKey =
event.target.getAttribute(
"data-row");
926 var row = grid.jqxTreeGrid(
"getRow", rowKey);
927 var collection = row[
"collection"];
928 var collectionTab = $(
".collection-tab[collection-name=\"" + collection +
"\"] a");
929 collectionTab.trigger(
"click");
930 var file = row[
"name"];
931 var fileNameTab = $(collectionTab[0].hash).find(
".file-tab[file-name=\"" + file +
"\"] a");
932 fileNameTab.trigger(
"click");
934 $(
".editButtons").on(
"click",
function (event) {
945 function AddEntityToFile(
id) {
946 var newEntityName = $(
id +
" #newEntityName").val();
947 $(
id +
" #newEntityName").val(
"");
948 if (newEntityName !==
"") {
949 AjaxPost(
"/db/AddEntityToFile", { configName: CurrentNamedConfig, entity: CurrentEntity, collection: CurrentCollection, user: UserId, name: newEntityName },
function (res) {
954 UpdateHeader(
true,
false,
"Error adding Entity to configuration file");
960 function LoadFile(
id) {
962 AjaxPost(
"/db/LoadFileMetadata", { configName: CurrentNamedConfig, entity: CurrentEntity, collection: CurrentCollection, user: UserId },
function (metadata) {
963 if (!metadata.Success) {
964 UpdateHeader(
true,
false,
"Error loading file metadata from database");
967 console.log(
"Loading file metadata");
968 var metadataObj = metadata.data;
969 console.log(metadata);
970 $(
id +
" #metadataCollection").val(metadataObj.collection);
971 $(
id +
" #metadataVersion").val(metadataObj.version);
972 $(
id +
" #changeLog").val(metadataObj.changelog);
974 var displayColumns = [
981 text:
"Date Assigned",
982 dataField:
"assigned",
987 { name:
"name", type:
"string", editable:
false, display:
true },
988 { name:
"assigned", type:
"date", editable:
false, display:
true }
990 var entitiesSource = {
992 dataFields: dataFields,
997 localData: metadataObj.entities
1000 var entitiesDataAdapter =
new $.jqx.dataAdapter(entitiesSource);
1002 $(
id +
" #metadataEntities").addClass(
"jqxTreeGrid").jqxTreeGrid(
1005 source: entitiesDataAdapter,
1008 columnsResize:
true,
1009 columns: displayColumns
1011 var configsSource = {
1013 dataFields: dataFields,
1018 localData: metadataObj.configurations
1021 var configsDataAdapter =
new $.jqx.dataAdapter(configsSource);
1023 $(
id +
" #metadataConfigurations").addClass(
"jqxTreeGrid").jqxTreeGrid(
1026 source: configsDataAdapter,
1029 columnsResize:
true,
1030 columns: displayColumns
1032 LoadTable($(
id +
" #fileTable"));
1036 function SearchCurrentConfig() {
1037 console.log(
"Searching Configuration");
1039 var searchKey = $(
"#searchKey").val();
1040 console.log(
"SearchKey is " + searchKey);
1042 AjaxPost(
"/db/SearchLoadedConfig", { configName: CurrentNamedConfig, user: UserId, searchKey: searchKey },
function (results) {
1043 if (!results.Success) {
1044 UpdateHeader(
true,
false,
"Error searching configuration");
1048 MakeTreeGrid($(
"#searchResults"), results.columns, results.collections);
1052 function LoadConfig() {
1053 console.log(
"Loading Configuration");
1054 $(
"#masterChanges").val(
"");
1055 UpdateHeader(
false,
false,
"");
1056 var selected = $(
"#configversions").find(
":selected");
1057 if (selected.text() ===
"No Configurations Found" || selected.text() ===
"Click \"Load Configurations\" To Load Configuration Names") {
return; }
1058 CurrentNamedConfig = selected.attr(
"name");
1059 $(
"#configName").val(CurrentNamedConfig);
1060 for (var i = 2; i <= LastTabId; i++) {
1061 $(
"#tab" + i).
remove();
1062 $(
"#tablink" + i).
remove();
1066 AjaxPost(
"/db/LoadNamedConfig", { configName: CurrentNamedConfig, query: selected.val(), user: UserId },
function (config) {
1067 if (!config.Success) {
1068 UpdateHeader(
true,
false,
"Error loading configuration files from database");
1072 for (var collection in config.collections) {
1073 if (config.collections.hasOwnProperty(collection)) {
1075 var parentTab = LastTabId;
1076 $(
"#tabLinks").append(
"<li id=\"tablink" + LastTabId +
"\"collection-name=\"" + config.collections[collection].name +
"\" tabNum=\"" + LastTabId +
"\" class=\"collection-tab\"><a href=\"#tab" + LastTabId +
"\">" + config
1077 .collections[collection].name +
"</a></li>");
1078 $(
"#tabContents").append(
"<div id=tab" + LastTabId +
" class=\"tab\"></div>");
1079 $(
"#tab" + LastTabId).html(TableHtml);
1081 for (var file in config.collections[collection].files) {
1082 if (config.collections[collection].files.hasOwnProperty(file)) {
1083 var name = config.collections[collection].files[file];
1086 $(
"#tab" + parentTab +
" #tabLinks").append(
"<li id=\"tablink" + LastTabId +
"\" file-name=\"" + name +
"\" tabNum=\"" + LastTabId +
"\" class=\"file-tab\"><a href=\"#tab" + LastTabId +
"\">" + name +
"</a></li>");
1087 $(
"#tab" + parentTab +
" #tabContents").append(
"<div id=tab" + LastTabId +
" class=\"tab\"></div>");
1088 $(
"#tab" + LastTabId).html(InfoHtml).trigger(
"create");;
1093 $(
"#configLoad").collapsible(
"option",
"disabled",
false).collapsible(
"option",
"collapsed",
true);
1094 $(
"#configSave").collapsible(
"option",
"disabled",
false).collapsible(
"option",
"collapsed",
false);
1095 LoadConfigMetadata();
1096 $(
"#configMetadata").collapsible(
"option",
"disabled",
false).collapsible(
"option",
"collapsed",
false);
1097 $(
"#searchConfig").collapsible(
"option",
"disabled",
false);
1098 RegisterTabFunctions();
1102 function BaseConfig() {
1104 AjaxPost(
"/db/LoadConfigMetadata", { configName: $(
"#oldConfigName :selected").text(), user: UserId },
function (metadata) {
1105 if (!metadata.Success) {
1106 UpdateHeader(
true,
false,
"Error loading configuration metadata from database");
1109 var metadataObj = metadata.data;
1112 $(
"#newConfigName").val($(
"#oldConfigName :selected").text());
1113 var tag = $(
"#configurationPicker");
1114 var rows = tag.find(
"#grid").jqxTreeGrid(
"getRows");
1115 for (var r in rows) {
1116 if (rows.hasOwnProperty(r)) {
1117 var thisRow = rows[r];
1118 var isChecked =
false;
1119 for (var e in metadataObj.entities) {
1120 if (isChecked)
break;
1121 if (metadataObj.entities.hasOwnProperty(e)) {
1122 var entity = metadataObj.entities[e];
1123 if (thisRow.name === entity.collection) {
1124 for (var r in thisRow.records) {
1125 if (thisRow.records.hasOwnProperty(r)) {
1126 var record = thisRow.records[r];
1127 if (record.id === entity.collection + entity.name) {
1128 tag.find(
"#grid").jqxTreeGrid(
"updateRow", record.uid, { name: entity.name, version: entity.version });
1129 tag.find(
"#grid").jqxTreeGrid(
"checkRow", record.uid);
1138 if (!isChecked && thisRow.checked) {
1139 tag.find(
"#grid").jqxTreeGrid(
"uncheckRow", thisRow.uid);
1146 function BaseExportConfig() {
1148 AjaxPost(
"/db/LoadConfigMetadata", { configName: $(
"#exportConfigName :selected").text(), user: UserId },
function (metadata) {
1149 if (!metadata.Success) {
1150 UpdateHeader(
true,
false,
"Error loading configuration metadata from database");
1153 ExportTarFileName = $(
"#exportConfigName :selected").text();
1154 var metadataObj = metadata.data;
1157 var tag = $(
"#filePicker");
1158 var rows = tag.find(
"#grid").jqxTreeGrid(
"getRows");
1159 for (var r in rows) {
1160 if (rows.hasOwnProperty(r)) {
1161 var thisRow = rows[r];
1162 var isChecked =
false;
1163 for (var e in metadataObj.entities) {
1164 if (isChecked)
break;
1165 if (metadataObj.entities.hasOwnProperty(e)) {
1166 var entity = metadataObj.entities[e];
1167 if (thisRow.name === entity.collection) {
1168 for (var r in thisRow.records) {
1169 if (thisRow.records.hasOwnProperty(r)) {
1170 var record = thisRow.records[r];
1171 if (record.id === entity.collection + entity.name) {
1172 tag.find(
"#grid").jqxTreeGrid(
"updateRow", record.uid, { name: entity.name, version: entity.version });
1173 tag.find(
"#grid").jqxTreeGrid(
"checkRow", record.uid);
1182 if (!isChecked && thisRow.checked) {
1183 tag.find(
"#grid").jqxTreeGrid(
"uncheckRow", thisRow.uid);
1191 function SaveNewConfig() {
1192 console.log(
"Saving New Configuration");
1193 var tag = $(
"#configurationPicker");
1194 var rows = tag.find(
"#grid").jqxTreeGrid(
"getCheckedRows");
1199 for (var r in rows) {
1200 if (rows.hasOwnProperty(r) &&
1201 (typeof rows[r].collection !==
"undefined" && rows[r].collection.length > 0) &&
1202 (typeof rows[r].version !==
"undefined" && rows[r].version.length > 0)) {
1203 configObj.entities.push({ name: rows[r].name, version: rows[r].version, collection: rows[r].collection });
1208 AjaxPost(
"/db/MakeNewConfig", { user: UserId, config: JSON.stringify(configObj), name: $(
"#newConfigName").val() },
function (retval) {
1209 if (retval.Success) {
1210 $(
"#newConfig").collapsible(
"option",
"collapsed",
true);
1213 UpdateHeader(
true,
false,
"MakeNewConfig operation failed.");
1218 function ExportFiles() {
1219 console.log(
"Exporting Files");
1220 var tag = $(
"#filePicker");
1221 var rows = tag.find(
"#grid").jqxTreeGrid(
"getCheckedRows");
1226 for (var r in rows) {
1227 if (rows.hasOwnProperty(r) &&
1228 (typeof rows[r].collection !==
"undefined" && rows[r].collection.length > 0) &&
1229 (typeof rows[r].version !==
"undefined" && rows[r].version.length > 0)) {
1230 configObj.entities.push({ name: rows[r].name, version: rows[r].version, collection: rows[r].collection });
1235 var xhr =
new XMLHttpRequest();
1236 xhr.open(
"POST",
"/db/DownloadConfigurationFile",
true);
1237 xhr.responseType =
"arraybuffer";
1238 xhr.onload =
function () {
1239 if (this.status === 200) {
1241 var disposition = xhr.getResponseHeader(
"Content-Disposition");
1242 if (disposition && disposition.indexOf(
"attachment") !== -1) {
1243 var filenameRegex = /filename[^;=\n]*=(([
'"]).*?\2|[^;\n]*)/;
1244 var matches = filenameRegex.exec(disposition);
1245 if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, "");
1247 var type = xhr.getResponseHeader("Content-Type
");
1249 var blob = new Blob([this.response], { type: type });
1250 if (typeof window.navigator.msSaveBlob !== "undefined
") {
1251 // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob
for which they were created. These URLs will no longer resolve as the data backing the URL has been freed.
"
1252 window.navigator.msSaveBlob(blob, filename);
1254 var url = window.URL || window.webkitURL;
1255 var downloadUrl = url.createObjectURL(blob);
1258 // use HTML5 a[download] attribute to specify filename
1259 var a = document.createElement("a
");
1260 // safari doesn't support this yet
1261 if (typeof a.download === "undefined
") {
1262 window.location = downloadUrl;
1264 a.href = downloadUrl;
1265 a.download = filename;
1266 document.body.appendChild(a);
1270 window.location = downloadUrl;
1273 setTimeout(function () { url.revokeObjectURL(downloadUrl); }, 100); // cleanup
1275 } else if (this.status === 500) {
1276 UpdateHeader(true, false, "An error occurred on the server. Contact an expert
if the situation persists
");
1279 xhr.setRequestHeader("Content-type
", "application/x-www-form-urlencoded
");
1280 xhr.send($.param({ user: UserId, config: JSON.stringify(configObj), tarFileName: ExportTarFileName, type: $("#exportFileFormat :selected
").val() }));
1281 ExportTarFileName = "export
";
1284 function AddRowToFileUploader() {
1285 $("#fileUploader
").find("#grid
").jqxTreeGrid("addRow
", null, {});
1288 function SetupFileUploadTable(tag) {
1289 var displayColumns = [
1292 dataField: "fileName
",
1294 cellClassName: CellClass,
1295 columntype: "template",
1296 initEditor: function (row, cellvalue, editor) {
1297 if (cellvalue === "" || cellvalue === "undefined
" || !cellvalue) {
1298 editor.html("<input type=\
"file\" id=\"fileName\"/>");
1300 editor.text(cellvalue);
1303 getEditorValue:
function (row, cellvalue, editor) {
1305 if (cellvalue ===
"" || cellvalue ===
"undefined" || !cellvalue) {
1306 var fileName = editor.find(
"#fileName")[0];
1307 UploadFiles[row] = fileName.files[0];
1308 return fileName.files[0].name;
1315 dataField:
"fileType",
1317 cellClassName: CellClass,
1318 columntype:
"template",
1319 initEditor:
function (row, cellvalue, editor) {
1321 var versionsAdapter =
new $.jqx.dataAdapter({ datatype:
"array", datafields: [{ name:
"name", type:
"string" }, { name:
"value", type:
"string" }], localdata: [{ name:
"FHiCL", value:
"fhicl" }, { name:
"JSON", value:
"json" }] }, { autoBind:
true });
1322 editor.jqxDropDownList({ source: versionsAdapter, displayMember:
"name", valueMember:
"value", selectedIndex: 0 }).jqxDropDownList(
"refresh");
1324 editor.jqxDropDownList(
"selectItem", cellvalue);
1326 getEditorValue:
function (row, cellvalue, editor) {
1328 return editor.val();
1333 dataField:
"collection",
1335 cellClassName: CellClass
1338 text:
"Entity Name",
1339 dataField:
"entity",
1341 cellClassName: CellClass
1345 dataField:
"version",
1347 cellClassName: CellClass
1350 text:
"Remove", cellsAlign:
"center", align:
"center", columnType:
"none", editable:
false, sortable:
false, dataField: null, cellsRenderer:
function (row) {
1352 return "<button data-row='" + row +
"' class='removeButtons' onclick=''>Remove</button>";
1357 tag.html(
"<div id=\"grid\" class=\"jqxTreeGrid\"></div><br>");
1360 { name:
"id", type:
"string", editable:
false, display:
false },
1361 { name:
"fileName", type:
"string", editable:
true, display:
true },
1362 { name:
"fileType", type:
"string", editable:
true, display:
true },
1363 { name:
"collection", type:
"string", editable:
true, display:
true },
1364 { name:
"entity", type:
"string", editable:
true, display:
true },
1365 { name:
"version", type:
"string", editable:
true, display:
true }
1369 dataFields: dataFields,
1377 var dataAdapter =
new $.jqx.dataAdapter(source);
1379 tag.find(
"#grid").jqxTreeGrid({
1381 source: dataAdapter,
1384 columnsResize:
true,
1385 columns: displayColumns,
1386 rendering:
function () {
1388 if ($(
".removeButtons").length > 0) {
1389 $(
".removeButtons").jqxButton(
"destroy");
1392 rendered:
function () {
1393 if ($(
".removeButtons").length > 0) {
1394 $(
".removeButtons").jqxButton();
1396 var removeClick =
function (event) {
1398 var rowKey =
event.target.getAttribute(
"data-row");
1399 delete UploadFiles[rowKey];
1400 tag.find(
"#grid").jqxTreeGrid(
"deleteRow", rowKey);
1402 $(
".removeButtons").on(
"click",
function (event) {
1412 function SetupReader(file) {
1413 var f = UploadFiles[file];
1414 var r =
new FileReader();
1416 r.onload =
function (e) {
1417 var contents = e.target.result;
1418 var thisfile = e.target.fileid;
1419 var row = $(
"#fileUploader").find(
"#grid").jqxTreeGrid(
"getRow", thisfile);
1420 console.log(
"Calling AjaxPost with parameters: Collection: " +
1427 row.fileType +
", fileName: " + row.fileName +
", file.name: " + f.name);
1430 AjaxPost(
"/db/UploadConfigurationFile",
1433 collection: row.collection,
1434 version: row.version,
1441 UpdateHeader(
true,
false,
"File upload failed");
1443 console.log(
"Upload: " + row.fileName +
" returned: " + JSON.stringify(res));
1445 delete UploadFiles[thisfile];
1451 function UploadFhiclFile() {
1452 $(
"#uploadFhiclFileButton").text(
"Uploading... Please Wait.");
1454 var didAnything =
false;
1455 for (var file in UploadFiles) {
1456 if (UploadFiles.hasOwnProperty(file)) {
1458 var f = UploadFiles[file];
1460 var row = $(
"#fileUploader").find(
"#grid").jqxTreeGrid(
"getRow", file);
1462 alert(
"Failed to load file");
1466 if (row.fileType ===
"fhicl" && f.name.search(
".fcl") === -1) {
1467 alert(f.name +
" is not a valid fhicl file.");
1471 if (row.fileType ===
"json" && f.name.search(
".json") === -1) {
1472 alert(f.name +
" is not a valid json file.");
1476 if ((row.fileType !==
"fhicl" &&
1477 row.fileType !==
"json") ||
1478 row.collection ===
"" ||
1479 row.version ===
"" ||
1480 row.entity ===
"") {
1481 alert(f.name +
" missing needed metadata");
1491 $(
"#uploadFile").collapsible(
"option",
"collapsed",
true);
1492 $(
"#uploadFhiclFileButton").text(
"Store File(s) In Database");
1494 setTimeout(
function () { UploadFhiclFile(); }, 1000);
1498 function SetupEntityVersionPicker(tag) {
1500 AjaxGet(
"/db/EntitiesAndVersions",
function (data) {
1501 console.log(JSON.stringify(data));
1502 if (!data.Success) {
1503 UpdateHeader(
true,
false,
"Error retrieving entities and versions lists. Please contact an expert!");
1506 var collectionsObj = data.collections;
1508 var collectionNames = [];
1509 for (var c in collectionsObj) {
1510 if (collectionsObj.hasOwnProperty(c)) {
1511 var collection = [];
1512 var entitiesObj = collectionsObj[c];
1513 for (var e in entitiesObj.entities) {
1514 if (entitiesObj.entities.hasOwnProperty(e)) {
1515 var entity = entitiesObj.entities[e];
1517 var search = entity.versions.search;
1518 for (var v in search) {
1519 if (search.hasOwnProperty(v)) {
1520 versions.push({ name: search[v].name });
1523 collection.push({
id: entitiesObj.name + entity.name, name: entity.name, collection: entity.collection, edited:
false, version: versions[0].name, versions: versions });
1526 dataObj.push({
id: entitiesObj.name, name: entitiesObj.name, entities: collection });
1527 collectionNames.push(entitiesObj.name);
1531 var displayColumns = [
1533 text:
"Entity Name",
1536 cellClassName: CellClass
1540 dataField:
"version",
1542 columntype:
"template",
1543 initEditor:
function (rowKey, cellvalue, editor) {
1544 var row = tag.find(
"#grid").jqxTreeGrid(
"getRow", rowKey);
1547 for (var r in dataObj) {
1548 if (dataObj.hasOwnProperty(r)) {
1549 if (row.id.indexOf(dataObj[r].name) === 0) {
1555 var localData = dataObj[index1];
1556 for (var rr in localData.entities) {
1557 if (localData.entities.hasOwnProperty(rr)) {
1558 if (row.id === localData.entities[rr].id) {
1564 var versionsSource = { datatype:
"array", datafields: [{ name:
"name", type:
"string" }], localdata: dataObj[index1].entities[index2].versions };
1566 var versionsAdapter =
new $.jqx.dataAdapter(versionsSource, { autoBind:
true });
1567 editor.jqxDropDownList({ source: versionsAdapter, displayMember:
"name", valueMember:
"name", selectedIndex: 0 }).jqxDropDownList(
"refresh");
1571 editor.jqxDropDownList(
"selectItem", cellvalue);
1573 getEditorValue:
function (row, cellvalue, editor) {
1575 return editor.val();
1577 cellClassName: CellClass
1581 tag.html(
"<br><button type=\"button\" class=\"miniButton\" id=\"all1\"> Select All </button><button type=\"button\" class=\"miniButton\" id=\"none1\"> Select None </button><br>" +
1582 "<div id=\"grid\" class=\"jqxTreeGrid\"></div><br>" +
1583 "<button type=\"button\" class=\"miniButton\" id=\"all2\"> Select All </button><button type=\"button\" class=\"miniButton\" id=\"none2\"> Select None </button>");
1585 tag.find(
"#none1").jqxButton({ height: 30 });
1586 tag.find(
"#all1").jqxButton({ height: 30 });
1587 tag.find(
"#none2").jqxButton({ height: 30 });
1588 tag.find(
"#all2").jqxButton({ height: 30 });
1591 { name:
"id", type:
"string", editable:
false, display:
false },
1592 { name:
"name", type:
"string", editable:
false, display:
true },
1593 { name:
"version", type:
"string", editable:
true, display:
true },
1594 { name:
"versions", type:
"array", editable:
false, display:
false },
1595 { name:
"edited", type:
"boolean", editable:
false, display:
false },
1596 { name:
"entities", type:
"array", editable:
false, display:
false }
1600 dataFields: dataFields,
1608 var dataAdapter =
new $.jqx.dataAdapter(source);
1610 tag.find(
"#grid").jqxTreeGrid({
1612 source: dataAdapter,
1615 columnsResize:
true,
1617 hierarchicalCheckboxes:
true,
1618 columns: displayColumns
1620 for (var n in collectionNames) {
1621 if (collectionNames.hasOwnProperty(n)) {
1622 tag.find(
"#grid").jqxTreeGrid(
"lockRow", collectionNames[n]);
1628 tag.find(
"#none1").mousedown(
function () {
1629 var rows = tag.find(
"#grid").jqxTreeGrid(
"getRows");
1630 for (var r in rows) {
1631 if (rows.hasOwnProperty(r)) {
1632 if (rows[r].checked) {
1633 tag.find(
"#grid").jqxTreeGrid(
"uncheckRow", rows[r].uid);
1638 tag.find(
"#all1").mousedown(
function () {
1639 var rows = tag.find(
"#grid").jqxTreeGrid(
"getRows");
1640 for (var r in rows) {
1641 if (rows.hasOwnProperty(r)) {
1642 if (!rows[r].checked) {
1643 tag.find(
"#grid").jqxTreeGrid(
"checkRow", rows[r].uid);
1648 tag.find(
"#none2").mousedown(
function () {
1649 var rows = tag.find(
"#grid").jqxTreeGrid(
"getRows");
1650 for (var r in rows) {
1651 if (rows.hasOwnProperty(r)) {
1652 if (rows[r].checked) {
1653 tag.find(
"#grid").jqxTreeGrid(
"uncheckRow", rows[r].uid);
1659 tag.find(
"#all2").mousedown(
function () {
1660 var rows = tag.find(
"#grid").jqxTreeGrid(
"getRows");
1661 for (var r in rows) {
1662 if (rows.hasOwnProperty(r)) {
1663 if (!rows[r].checked) {
1664 tag.find(
"#grid").jqxTreeGrid(
"checkRow", rows[r].uid);
1672 function SaveConfig() {
1673 console.log(
"Saving Configuration Changes");
1675 $(
".file-tab.editedValue a")
1677 var log = $(
"#changes", $(
this).attr(
"href")).val();
1678 var collection = $(
"#metadataCollection", $(
this).attr(
"href")).val();
1680 var rows = $(
"#metadataEntities", $(
this).attr(
"href")).jqxTreeGrid(
'getRows');
1681 for (var i = 0; i < rows.length; i++) {
1683 entities.push(rows[i].name);
1685 var version = $(
"#metadataVersion", $(
this).attr(
"href")).val();
1686 files.push({ entities: entities, changelog: log, collection: collection, version: version });
1689 AjaxPost(
"/db/saveConfig",
1691 oldConfigName: CurrentNamedConfig,
1692 newConfigName: $(
"#configName").val(),
1697 if (res !== null && res !== undefined && res.Success) {
1698 UpdateHeader(
false,
false,
"Configuration Saved.");
1701 UpdateHeader(
true,
false,
"Failed to save configuration!");
1707 function DiscardConfig() {
1708 console.log(
"Discarding Configuration Changes");
1710 $(
".file-tab.editedValue").each(
function () {
1711 files.push({ name: $(
this).text() });
1714 AjaxPost(
"/db/discardConfig", { configName: CurrentNamedConfig, files: files, user: UserId },
function (res) {
1718 UpdateHeader(
true,
false,
"Failed to discard configuration. Make sure you have a valid configuration selected.\nIf this problem persists, call an expert.");
1724 function GetDbConfig() {
1726 AjaxGet(
"/db/getDbConfig",
1729 $(
"#dbType").val(data.dbprovider).trigger(
"change");
1730 $(
"#baseDir").val(data.baseDir);
1731 $(
"#databases").html(data.data.join(
"")).trigger(
"create").selectmenu(
"refresh");
1732 var database = GetUrlParameter(
"database");
1733 if (database !== undefined && database !==
"") {
1734 $(
"#databases").val(database).trigger(
"change");
1736 $(
"#databases").val(data.instanceName).trigger(
"change");
1743 function UpdateDbConfig() {
1745 dbprovider: $(
"#dbType").val(),
1746 baseDir: $(
"#baseDir").val(),
1747 instanceName: $(
"#databases").val()
1750 AjaxPost(
"/db/updateDbConfig",
1758 "Failed to update Database Module Configuration. Please See server logs for more details.");
1764 function MakeNewDatabase() {
1765 var newDBName = { name: $(
"#newDatabaseName").val() };
1766 AjaxPost(
"/db/makeNewDBInstance",
1767 newDBName,
function (res) {
1771 UpdateHeader(
true,
false,
"Failed to create new Database Instance. Please see server logs for more details.");
1777 function RegisterButtonFunctions() {
1778 $(
"#loadConfigButton").on(
"click",
function () { LoadConfig(); });
1779 $(
"#getConfigListButton").on(
"click",
function () { GetConfigList(); });
1780 $(
"#saveConfigButton").on(
"click",
function () { SaveConfig(); });
1781 $(
"#discardConfigButton").on(
"click",
function () { DiscardConfig(); });
1782 $(
"#searchCurrentConfigButton").on(
"click",
function () { SearchCurrentConfig(); });
1783 $(
"#baseConfigButton").on(
"click",
function () { BaseConfig(); });
1784 $(
"#saveNewConfigButton").on(
"click",
function () { SaveNewConfig(); });
1785 $(
"#baseExportConfigButton").on(
"click",
function () { BaseExportConfig(); });
1786 $(
"#exportFilesButton").on(
"click",
function () { ExportFiles(); });
1787 $(
"#addRowToFileUploaderButton").on(
"click",
function () { AddRowToFileUploader(); });
1788 $(
"#uploadFhiclFileButton").on(
"click",
function () { UploadFhiclFile(); });
1789 $(
"#updateDBConfigButton").on(
"click",
function () { UpdateDbConfig(); });
1790 $(
"#createNewDatabaseButton").on(
"click",
function () { MakeNewDatabase(); });
1797 var debounce =
function (func, threshold, execAsap) {
1800 return function debounced() {
1801 var obj =
this, args = arguments;
1802 function delayed() {
1804 func.apply(obj, args);
1809 clearTimeout(timeout);
1811 func.apply(obj, args);
1813 timeout = setTimeout(delayed, threshold || 100);
1818 jQuery.fn[sr] =
function (fn) {
return fn ? this.bind(
"resize", debounce(fn)) : this.trigger(sr); };
1820 })(jQuery,
"smartresize");
1822 $(document).ready(
function () {
1823 DefaultColor = $(
"#header").css(
"background-color");
1824 DefaultShadow = $(
"#header").css(
"text-shadow");
1826 $.get(
"/db/Tables.html",
function (data) {
1830 $.get(
"/db/FileInfo.html",
function (data) {
1834 $.get(
"/db/TreeGrid.html",
function (data) {
1835 TreeGridHtml = data;
1838 $.get(
"/db/Dialog.html",
function (data) { DialogContentHtml = data; });
1840 $(
".configInfo-tab").on(
"click",
function () {
1844 RegisterTabFunctions();
1845 $(
".tabs #tab1").show().siblings().hide();
1847 $(
".triggersModified").change(
function () {
1848 UpdateHeader(
false,
true,
"There are pending unsaved changes. Please save or discard before closing the editor!");
1851 $(window).smartresize(
function () {
1852 $(
".jqxTreeGrid").jqxTreeGrid({ width:
"100%" }).jqxTreeGrid(
"refresh");
1855 $(
"#newConfig").on(
"collapsibleexpand",
function () {
1856 SetupEntityVersionPicker($(
"#configurationPicker"));
1859 $(
"#exportFile").on(
"collapsibleexpand",
function () {
1860 SetupEntityVersionPicker($(
"#filePicker"));
1864 .on(
"collapsibleexpand",
1866 SetupFileUploadTable($(
"#fileUploader"));
1869 $(
"#dbType").on(
"change",
function () {
1870 var dbtype = $(
"#dbType").val();
1871 if (dbtype ===
"filesystem") {
1872 $(
"#filesystemdbConfig").show();
1873 $(
"#mongodbConfig").hide();
1874 }
else if (dbtype ===
"mongo") {
1875 $(
"#filesystemdbConfig").hide();
1876 $(
"#mongodbConfig").show();
1878 }).trigger(
"change");
1880 $(
"#databases").on(
"change",
function () {
1881 var instanceName = $(
"#databases").val();
1882 if (instanceName ===
"NONE") {
1883 $(
"#newDatabaseFS").show();
1885 $(
"#newDatabaseFS").hide();
1888 }).trigger(
"change");
1892 RegisterButtonFunctions();