var gLastValidateResult = true; function setupVariablesPanel() { $("#varType input").checkboxradio(); $("#varScope input").checkboxradio(); $("#varProps input").checkboxradio(); $("#varEditor") .dialog({ autoOpen: false, title: "Update variable", height: "auto", width: "auto", autoResize: true, resizable: false, modal: true, closeOnEscase: true, draggable: true, open: function() { if ($("#scalarEditor").css("display") != "none") $(this) .find("input:visible,textarea:visible") .first() .focus(); if ($("#collectionEditor").css("display") != "none") { $("#collectionTableEditor").handsontable("render"); var a = $("#collectionTableEditor").handsontable("getData"); } }, buttons: [ { text: "Save", disabled: !canUpdateDB(), click: function() { if (!gLastValidateResult || !canUpdateDB()) return; var varName = $("#varEditor #varName") .val() .trim(); var varDescription = $("#varEditor #varDescription") .val() .trim(); var varType = $("#varEditor #varType :checked").val(); var varScope = $("#varEditor #varScope :checked").val(); var varTracked = $("#varEditor #varTracked").is(":checked"); var varSystem = $("#varEditor #varSystem").is(":checked"); var varPublic = $("#varEditor #varPublic").is(":checked"); var varTable = $("#varEditor #varTable").is(":checked"); var varValue = $("#varEditor #varValue") .val() .trim(); // check var name var $tr = $(this).data("vp3VarTR"); if (!$tr) { // new var var exp = new RegExp("^[a-zA-Z_][a-zA-Z0-9_.]*$"); if (!exp.test(varName)) { $("#varEditor .ui-state-error") .text("Invalid variable name") .show(); return; } if (variabeExists(varName)) { $("#varEditor .ui-state-error") .text("Variable '" + varName + "' already exists") .show(); return; } } // check value switch (varType) { case "integer": if (isNaN(parseInt(varValue, 10))) { $("#varEditor .ui-state-error") .text("Invalid number format") .show(); return; } break; case "string": varValue = varValue.trim(); if (varValue) { if (varValue.charAt(0) !== '"') varValue = '"' + varValue; if (varValue.charAt(varValue.length - 1) !== '"') varValue = varValue + '"'; } break; } saveVariable($tr, varName, varDescription, varType, varScope, varTracked, varSystem, varPublic, varValue, varTable); $(this).dialog("close"); } }, { text: "Cancel", click: function() { $(this).dialog("close"); } } ] }) .keydown(function(event) { if (event.which == $.ui.keyCode.ENTER) return false; return true; }); if (gEgo && gEgo !== "all" && canUpdateDB()) $("#createNewVariableButton") .button() .click(function() { editVariable(null); }); else $("#createNewVariableButton").hide(); $("#varEditor #typecollection").click(function() { $("#varEditor").dialog("close"); editVariable($("#varEditor").data("vp3VarTR"), true); }); setupVariableTable(); displayTags($("#variablesTags"), setupVariableTable); } function setupVariableTable() { setupNiceTable($("#variablesTable"), { headers: {3: {sorter: "shortDate"}}, dblClick: editVariable, cmenuDelegate: ".variableRow", cmenu: [ { title: canUpdateDB() ? "Edit" : "View", uiIcon: "ui-icon-pencil", disabled: gEgo === "all", action: function(event, ui) { setTimeout(function() { editVariable($niceTableCurrentTR); }, 0); } }, { title: "New Editor", uiIcon: "ui-icon-pencil", disabled: gEgo === "all", action: function(event, ui) { setTimeout(function() { var name = $niceTableCurrentTR .find(".varName") .text() .trim(); let theEgo = $niceTableCurrentTR.attr("vp3:ego"); var url = getVariableCollectionUrl() + "/" + name + "/edit?ego=" + theEgo; window.open(url, name); }, 0); } }, { title: "Create new variable", uiIcon: "ui-icon-plus", disabled: gEgo === "all" || !canUpdateDB(), action: function(event, ui) { setTimeout(function() { editVariable(null); }, 0); } }, { title: "View history", uiIcon: "ui-icon-clock", action: function(event, ui) { setTimeout(function() { getVarHistory($niceTableCurrentTR); }, 0); } }, {title: "Duplicate", uiIcon: "ui-icon-copy", disabled: true}, { title: gEgo === "base" ? "Delete" : "Use base value", disabled: !canUpdateDB() || gEgo === "all" || (gEgo !== "base" && $niceTableCurrentTR && $niceTableCurrentTR.attr("vp3:ego") === "base"), uiIcon: "ui-icon-trash", action: function(event, ui) { setTimeout(function() { deleteVariable($niceTableCurrentTR); }, 0); } }, { title: "Rename", uiIcon: "ui-icon-grip-dotted-horizontal", disabled: !canUpdateDB(), action: function(event, ui) { setTimeout(function() { var name = $niceTableCurrentTR .find(".varName") .text() .trim(); if (name) renameEntity(name, "variable"); }); } }, {title: "---"}, { title: "Use bot value", uiIcon: "ui-icon-arrowstop-1-w", disabled: !canUpdateDB() || gEgo === "all" || gEgo === "base" || ($niceTableCurrentTR != null && $niceTableCurrentTR.attr("vp3:ego") !== "base"), action: function(event, ui) { var name = $niceTableCurrentTR .find(".varName") .text() .trim(); if (name) setTimeout(copyToEgo($niceTableCurrentTR, name), 0); } }, { title: "Referenced by", uiIcon: "ui-icon-arrowstop-1-w", disabled: !canUpdateDB(), action: function(event, ui) { var name = $niceTableCurrentTR .find(".varName") .text() .trim(); if (name) setTimeout(performSearch(name, "v"), 0); } } ] }); setupDraggingOnTable(); $("#variablesTable").tooltip({ items: ".numbackrefs", track: "true", hide: false, show: false, content: function(callback) { if ($(this).text() === "0") return; var entId = $(this).attr("vp3-key"); $.get(formatEndpoint(getPersonalityUrl() + "/backrefs/" + entId), function(data) { var doc = xslTransform(data, gVariablesXslt); callback($(doc).find("#variablesBackrefs")[0]); }); }, open: function(event, ui) { $(".ui-tooltip").each(function() { if (this !== ui.tooltip[0]) $(this).remove(); }); } }); } function editVariableByName(name) { $("#agentTabs").tabs("option", "active", 1); setTimeout(function() { var $varTR = $("#variablesTable .varName") .filter(function() { return $(this).text() === name; }) .first() .closest("tr"); if ($varTR) editVariable($varTR); }, 1000); } function editVariable($tr, asCollection) { if (gEgo === "all") return; var varName = ""; var varDescription = ""; var varType = asCollection ? "collection" : "integer"; var varScope = "session"; var varTracked = false; var varSystem = false; var varPublic = false; var varTable = false; if ($tr) { varName = $tr .find(".varName") .text() .trim(); varDescription = $tr .find(".varDescription") .text() .trim(); if (!varName) return; if (!asCollection) varType = $tr .find(".varType") .text() .trim() .toLowerCase(); varScope = $tr .find(".varScope") .text() .trim() .toLowerCase(); var $props = $tr.find(".varProps"); if ($props.length) { var propsStr = $tr .find(".varProps") .text() .trim() .toLowerCase(); varTracked = propsStr.indexOf("tracked") != -1; varSystem = propsStr.indexOf("system") != -1; varPublic = propsStr.indexOf("public") != -1; varTable = propsStr.indexOf("table") != -1; } $("#varEditor").dialog("option", "title", (canUpdateDB() ? "Update" : "View") + " variable '" + varName + "'"); $("#varEditor #varNameDiv").hide(); } else { // create a new variable if (!canUpdateDB()) return; $("#varEditor").dialog("option", "title", "Create new variable"); $("#varEditor #varName").val(""); $("#varEditor #varNameDiv").show(); } $("#varEditor").data("vp3VarTR", $tr); $("#varEditor #varDescription").val(varDescription); $("#varEditor :radio") .prop("disabled", false) .prop("checked", false) .button("refresh"); $("#varEditor #type" + varType) .prop("checked", true) .button("refresh"); $("#varEditor #scope" + varScope) .prop("checked", true) .button("refresh"); $("#varEditor #varTracked") .prop("checked", varTracked) .button("refresh"); $("#varEditor #varSystem") .prop("checked", varSystem) .button("option", "disabled", !!gParent) .button("refresh"); $("#varEditor #varPublic") .prop("checked", varPublic) .button("option", "disabled", !!gParent) .button("refresh"); $("#varEditor #varTable") .prop("checked", varTable) .button("refresh"); $("#varEditor .ui-state-error").hide(); if (varType == "collection") { $("#scalarEditor").hide(); $("#collectionEditor").show(); $("#varTable") .button("widget") .show(); $("#varEditor #varType :radio") .prop("disabled", true) .button("refresh"); var collectionObj = [{key: "", value: ""}, {key: "", value: ""}]; $("#collectionTableEditor").handsontable({ data: collectionObj, stretchH: "last", multiSelect: true, fillHandle: false, currentRowClassName: "collectionCurrentRow", allowInvalid: false, outsideClickDeselects: true, colHeaders: ["Key", "Value"], contextMenu: ["row_below", "remove_row"], columns: [ { data: "key", validator: function(value, callback) { value = value.trim(); if (value) { var data = $("#collectionTableEditor").handsontable("getData"); var len = data.length; for (var i = 0; i < len; ++i) { if (i != this.row && data[i].key == value) { callback(false); return; } } } callback(true); } }, { data: "value", allowInvalid: false, validator: function(value, callback) { value = value.trim(); if (value == "") callback(true); else if (/^"[^"]+\"$/.test(value)) callback(true); else callback(!isNaN(value)); } } ], afterValidate: function(isValid) { gLastValidateResult = isValid; } }); if ($tr) // update existing $.get(formatEndpoint(getVarUrl(varName), "ego=" + gEgo), function(data) { varXmlToObject(data, collectionObj); $("#collectionTableEditor").handsontable("loadData", collectionObj); $("#varEditor").dialog("open"); }); else { // create new collectionObj.push({key: "", value: ""}); collectionObj.push({key: "", value: ""}); collectionObj.push({key: "", value: ""}); $("#collectionTableEditor").handsontable("loadData", collectionObj); $("#varEditor").dialog("open"); } } else { $("#scalarEditor").show(); $("#collectionEditor").hide(); $("#varTable") .button("widget") .hide(); var varValue = $tr ? $tr .find(".varValue") .text() .trim() : "0"; var $field = $("#varEditor #varValue"); $field.prop("rows", "1"); $field.css("min-width:10em"); $field.val(varValue); $("#varEditor").dialog("open"); } } function copyToEgo($tr, varName) { if (gEgo == "base" || gEgo == "all" || $tr.attr("vp3:ego") != "base") return; $.get(formatEndpoint(getVarUrl(varName), "ego=base"), function(data) { $.ajax({ type: "PUT", url: formatEndpoint(getVarUrl(varName), "ego=" + gEgo), processData: false, data: data, contentType: "xml", success: function(data, textStatus, jqXHR) { switch (data.severity) { case "information": if ($tr) { $tr.find(".base-ego").removeClass("base-ego"); $tr.attr("vp3:ego", gEgo); } showInfo("Variable values successfuly moved to '" + gEgo + "'"); break; case "error": showError(data.message); break; case "warning": showWarning(data.message); break; } }, error: function(jqXHR, textStatus, errorThrown) { showError("Cannot save variable - " + errorThrown); } }); }); } function deleteVariable($tr) { if (gEgo == "all" || (gEgo != "base" && $tr && $tr.attr("vp3:ego") == "base")) return; var varName = $tr .find(".varName") .text() .trim(); if (!varName) return; showDialog( "Are you sure you want to delete " + (gEgo != "base" ? "the values of " : "") + "variable '" + varName + "'?", "Confirm Delete", "highlight", { Cancel: function() { $(this).dialog("close"); }, "Yes, Delete!": function() { $(this).dialog("close"); $.ajax({ type: "DELETE", url: formatEndpoint(getVarUrl(varName), "ego=" + gEgo), success: function(data, textStatus, jqXHR) { switch (data.severity) { case "information": if (gEgo == "base") $tr.remove(); else $tr.find(".varValue").addClass("base-ego"); showInfo(data.message); break; case "error": showError(data.message); break; case "warning": showWarning(data.message); break; } }, error: function(jqXHR, textStatus, errorThrown) { showError("Cannot delete variable - " + errorThrown); } }); } } ); } function saveVariable($tr, varName, varDescription, varType, varScope, varTracked, varSystem, varPublic, varValue, varTable) { var action; var ego; if ($tr) { // update varName = $tr .find(".varName") .text() .trim(); if (!varName) return; action = "PUT"; ego = $tr.attr("vp3:ego"); } else { // create action = "POST"; ego = "base"; // all new variables are created in base } $.ajax({ type: action, url: formatEndpoint(getVarUrl(varName), "ego=" + ego), processData: false, data: varDataToXml(varName, varDescription, varType, varScope, varTracked, varSystem, varPublic, varValue, varTable), contentType: "xml", success: function(data, textStatus, jqXHR) { switch (data.severity) { case "information": let isNew = false; if (!$tr) { // create a new one isNew = true; var $firstRow = $(".variableRow:first"); $tr = $firstRow.clone().insertBefore($firstRow); $tr.find(".varName").text(varName); } var propsStr = varTracked ? "tracked" : ""; if (varSystem) { if (propsStr) propsStr += ","; propsStr += "system"; } if (varPublic) { if (propsStr) propsStr += ","; propsStr += "public"; } if (varTable) { if (propsStr) propsStr += ","; propsStr += "table"; } $tr.find(".varDescription").text(varDescription); $tr.find(".varType").text(varType); $tr.find(".varScope").text(varScope); $tr.find(".varProps").text(propsStr); $tr.find(".varValue").text(varValue); $tr.find(".updateTime").text(new Date(data.serverTime).toLocaleString()); $tr.find(".updateUser").text(data.serverUser); if (isNew) setupVariableTable(); showInfo(data.message); break; case "error": showError(data.message); break; case "warning": showWarning(data.message); break; } }, error: function(jqXHR, textStatus, errorThrown) { showError("Cannot save variable - " + errorThrown); } }); } function varDataToXml(varName, varDescription, varType, varScope, varTracked, varSystem, varPublic, varValue, varTable) { var str = '"; var xmlDoc = loadXmlFromText(str); var xmlVar = xmlDoc.documentElement; if (varType === "collection") { // get the data from the table varValue = $("#collectionTableEditor").handsontable("getData"); varValue.sort(function(a, b) { return a.key.localeCompare(b.key); }); varValue = varValue.filter(function(item, pos, ary) { return !pos || item.key != ary[pos - 1].key; }); $.each(varValue, function() { if (this.key) { var key = '"' + this.key.trim() + '"'; var xmlVal = xmlDoc.createElement("value"); xmlVal.textContent = key; xmlVar.appendChild(xmlVal); if (this.value) $(xmlVal).attr("translation", this.value); } }); } else { var xmlVal = xmlDoc.createElement("value"); xmlVal.textContent = varValue.trim(); xmlVar.appendChild(xmlVal); } return xmlDoc; } function varXmlToObject(xml, result) { $(xml) .find("value") .each(function() { var key = this.textContent; if (key.charAt(0) == '"') key = key.slice(1, key.length - 1); var obj = {key: key, value: $(this).attr("translation")}; result.push(obj); }); if (!result.length) result.push({key: "sample key", value: '"sample value"'}); result.sort(function(a, b) { return a.key.localeCompare(b.key); }); } function variabeExists(varName) { var result = false; $(".varName:contains('" + varName + "')").each(function() { if ( $(this) .text() .trim() === varName ) { // check for exact match result = true; return false; } }); return result; } function getVarHistory($tr) { var varName = $tr .find(".varName") .text() .trim(); var url = getVarUrl(varName) + "/changelogs"; $.when($.get(formatEndpoint(url)), $.get("/html/changelogs.xslt")).then( function(data, styleSheet) { var newDoc = xslTransform(data[0], styleSheet[0]); var $div = $("
"); $div.html(newDoc.body.innerHTML); $div.dialog({ height: "300", maxHeight: "500", width: "auto", collision: "fit", title: "Change log for variable '" + varName + "'", position: {my: "top", at: "top", of: $tr}, buttons: { Close: function() { $(this).dialog("close"); } } }); setupChangelogsPanel($div); }, function(s) { showError("An AJAX error occured: " + s.statusText); } ); }