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 =
'