UNIFIAPI v0.3 FE setings done

This commit is contained in:
jokob-sk
2025-08-11 15:00:22 +10:00
parent 1319c3380d
commit 1c4e6c7e38
4 changed files with 126 additions and 117 deletions

View File

@@ -167,11 +167,10 @@ function showModalPopupForm(
message, message,
btnCancel = getString("Gen_Cancel"), btnCancel = getString("Gen_Cancel"),
btnOK = getString("Gen_Okay"), btnOK = getString("Gen_Okay"),
curValue = "", curValue = null,
callbackFunction = null,
triggeredBy = null,
popupFormJson = null, popupFormJson = null,
parentSettingKey = null parentSettingKey = null,
triggeredBy = null
) { ) {
// set captions // set captions
prefix = "modal-form"; prefix = "modal-form";
@@ -182,8 +181,11 @@ function showModalPopupForm(
$(`#${prefix}-cancel`).html(btnCancel); $(`#${prefix}-cancel`).html(btnCancel);
$(`#${prefix}-OK`).html(btnOK); $(`#${prefix}-OK`).html(btnOK);
if (triggeredBy != null) { // if curValue not null
$('#'+prefix).attr("data-myparam-triggered-by", triggeredBy)
if (curValue)
{
initialValues = JSON.parse(atob(curValue));
} }
outputHtml = ""; outputHtml = "";
@@ -191,17 +193,24 @@ function showModalPopupForm(
if (Array.isArray(popupFormJson)) { if (Array.isArray(popupFormJson)) {
popupFormJson.forEach((field, index) => { popupFormJson.forEach((field, index) => {
// You'll need to define these or map them from `field` // You'll need to define these or map them from `field`
const setName = field.name?.find(n => n.language_code === "en_us")?.string || setKey; const setKey = field.function || `field_${index}`;
const setName = getString(`${parentSettingKey}_popupform_${setKey}_name`);
const labelClasses = "col-sm-2"; // example, or from your obj.labelClasses const labelClasses = "col-sm-2"; // example, or from your obj.labelClasses
const inputClasses = "col-sm-10"; // example, or from your obj.inputClasses const inputClasses = "col-sm-10"; // example, or from your obj.inputClasses
const fieldData = field.default_value ?? ""; let initialValue = '';
const fieldOptionsOverride = field.type?.elements[0]?.elementOptions || []; if (curValue && Array.isArray(initialValues)) {
const match = initialValues.find(
v => v[1] == setKey
);
if (match) {
initialValue = match[3];
}
}
const setKey = field.function || `field_${index}`; const fieldOptionsOverride = field.type?.elements[0]?.elementOptions || [];
const setValue = field.default_value ?? ""; const setValue = initialValue;
const setType = JSON.stringify(field.type); const setType = JSON.stringify(field.type);
const setEvents = field.events || []; // default to empty array if missing const setEvents = field.events || []; // default to empty array if missing
const setObj = { setKey, setValue, setType, setEvents }; const setObj = { setKey, setValue, setType, setEvents };
// Generate the input field HTML // Generate the input field HTML
@@ -218,7 +227,7 @@ function showModalPopupForm(
${generateFormHtml( ${generateFormHtml(
null, // settingsData only required for datatables null, // settingsData only required for datatables
setObj, setObj,
fieldData.toString(), null,
fieldOptionsOverride, fieldOptionsOverride,
null null
)} )}
@@ -233,11 +242,6 @@ function showModalPopupForm(
$(`#modal-form-plc`).html(outputHtml); $(`#modal-form-plc`).html(outputHtml);
// $(`#${prefix}-field`).val(curValue);
// setTimeout(function () {
// $(`#${prefix}-field`).focus();
// }, 500);
// Bind OK button click event // Bind OK button click event
$(`#${prefix}-OK`).off("click").on("click", function() { $(`#${prefix}-OK`).off("click").on("click", function() {
let settingsArray = []; let settingsArray = [];
@@ -245,13 +249,38 @@ function showModalPopupForm(
popupFormJson.forEach(field => { popupFormJson.forEach(field => {
collectSetting( collectSetting(
`${parentSettingKey}_popupform`, // prefix `${parentSettingKey}_popupform`, // prefix
field.function + '_in', // setCodeName + sourceSuffixes field.function, // setCodeName
field.type, // setType (object) field.type, // setType (object)
settingsArray settingsArray
); );
}); });
} }
// Encode settings
const jsonData = JSON.stringify(settingsArray);
const encodedValue = btoa(jsonData);
// Get label from the FIRST field (value in 4th column)
const label = settingsArray[0][3]
// Add new option to target select
const selectId = parentSettingKey;
// If triggered by an option, update it; otherwise append new
if (triggeredBy && $(triggeredBy).is("option")) {
// Update existing option
$(triggeredBy)
.attr("value", encodedValue)
.text(label);
} else {
const newOption = $("<option class='interactable-option'></option>")
.attr("value", encodedValue)
.text(label);
$("#" + selectId).append(newOption);
initListInteractionOptions(newOption);
}
console.log("Collected popup form settings:", settingsArray); console.log("Collected popup form settings:", settingsArray);
if (typeof modalCallbackFunction === "function") { if (typeof modalCallbackFunction === "function") {
@@ -259,9 +288,7 @@ function showModalPopupForm(
} }
$(`#${prefix}`).modal("hide"); $(`#${prefix}`).modal("hide");
}); });
// Show modal // Show modal
$(`#${prefix}`).modal("show"); $(`#${prefix}`).modal("show");

View File

@@ -246,13 +246,6 @@ function settingsCollectedCorrectly(settingsArray, settingsJSON_DB) {
// Manipulating Editable List options // Manipulating Editable List options
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// ---------------------------------------------------------
// Add row to datatable
function addDataTableRow(el)
{
alert("a")
}
// --------------------------------------------------------- // ---------------------------------------------------------
// Clone datatable row // Clone datatable row
function cloneDataTableRow(el){ function cloneDataTableRow(el){
@@ -311,42 +304,32 @@ function removeDataTableRow(el) {
// --------------------------------------------------------- // ---------------------------------------------------------
// Add item via pop up form dialog // Add item via pop up form dialog
function addViaPopupForm(element) { function addViaPopupForm(element) {
console.log(element) console.log(element);
const fromId = $(element).attr("my-input-from");
const toId = $(element).attr("my-input-to"); const toId = $(element).attr("my-input-to");
const curValue = $(`#${fromId}`).val(); const curValue = $(`#${toId}`).val();
const triggeredBy = $(element).attr("id"); const parsed = JSON.parse(atob($(`#${toId}`).data("elementoptionsbase64")));
const parsed = JSON.parse(atob($(element).data("elementoptionsbase64")));
const popupFormJson = parsed.find(obj => "popupForm" in obj)?.popupForm ?? null; const popupFormJson = parsed.find(obj => "popupForm" in obj)?.popupForm ?? null;
console.log(`fromId | toId | triggeredBy | curValue: ${fromId} | ${toId} | ${triggeredBy} | ${curValue}`); console.log(`toId | curValue: ${toId} | ${curValue}`);
showModalPopupForm( showModalPopupForm(
`<i class="fa fa-pen-to-square"></i> ${getString( `<i class="fa fa-pen-to-square"></i> ${getString(
"Gen_Update_Value" "Gen_Update_Value"
)}`, // title )}`, // title
getString("settings_update_item_warning"), // message getString("settings_update_item_warning"), // message
getString("Gen_Cancel"), // btnCancel getString("Gen_Cancel"), // btnCancel
getString("Gen_Add"), // btnOK getString("Gen_Add"), // btnOK
curValue, // curValue null, // curValue
null, // callbackFunction popupFormJson, // popupform
triggeredBy, // triggeredBy toId, // parentSettingKey
popupFormJson, // popupform element // triggeredBy
toId // parentSettingKey
); );
}
// ---------------------------------------------------------
// Add item to list via popup form
function addViaPopupFormToList(element, clearInput = true) {
// flag something changes to prevent navigating from page // flag something changes to prevent navigating from page
settingsChanged(); settingsChanged();
} }
// --------------------------------------------------------- // ---------------------------------------------------------
// Add item to list // Add item to list
function addList(element, clearInput = true) { function addList(element, clearInput = true) {
@@ -475,18 +458,43 @@ function initListInteractionOptions(element) {
// Perform action based on click count // Perform action based on click count
if (clickCounter === 1) { if (clickCounter === 1) {
// Single-click action // Single-click action
showModalFieldInput(
`<i class="fa fa-pen-to-square"></i> ${getString( const $parent = $option.parent();
"Gen_Update_Value" const transformers = $parent.attr("my-transformers");
)}`,
getString("settings_update_item_warning"), if (transformers && transformers === "name|base64") {
getString("Gen_Cancel"), // Parent has my-transformers="name|base64"
getString("Gen_Update"), const toId = $parent.attr("id");
$option.html(), const curValue = $option.val();
function () { const parsed = JSON.parse(atob($parent.data("elementoptionsbase64")));
updateOptionItem($option, $(`#modal-field-input-field`).val()); const popupFormJson = parsed.find(obj => "popupForm" in obj)?.popupForm ?? null;
}
); showModalPopupForm(
`<i class="fa fa-pen-to-square"></i> ${getString(
"Gen_Update_Value"
)}`, // title
getString("settings_update_item_warning"), // message
getString("Gen_Cancel"), // btnCancel
getString("Gen_Update"), // btnOK
curValue, // curValue
popupFormJson, // popupform
toId, // parentSettingKey
this // triggeredBy
);
} else {
// Fallback to normal field input
showModalFieldInput(
`<i class="fa fa-pen-to-square"></i> ${getString("Gen_Update_Value")}`,
getString("settings_update_item_warning"),
getString("Gen_Cancel"),
getString("Gen_Update"),
$option.html(),
function () {
updateOptionItem($option, $(`#modal-field-input-field`).val());
}
);
}
} else if (clickCounter === 2) { } else if (clickCounter === 2) {
// Double-click action // Double-click action
removeOptionItem($option); removeOptionItem($option);
@@ -718,7 +726,7 @@ function applyTransformers(val, transformers) {
} }
// ------------------------------------------------------------ // ------------------------------------------------------------
// Function to reverse transformers applied to a value // Function to reverse transformers applied to a value - returns the LABEL
function reverseTransformers(val, transformers) { function reverseTransformers(val, transformers) {
transformers.reverse().forEach((transformer) => { transformers.reverse().forEach((transformer) => {
switch (transformer) { switch (transformer) {
@@ -733,10 +741,10 @@ function reverseTransformers(val, transformers) {
} }
break; break;
case "name|base64": case "name|base64":
// // Implement base64 decoding logic // Implement base64 decoding logic
// if (isBase64(val)) { if (isBase64(val)) {
// val = atob(val); val = JSON.parse(atob(val))[0][3];
// } }
val = val; // probably TODO ⚠ val = val; // probably TODO ⚠
break; break;
case "getString": case "getString":
@@ -1089,7 +1097,6 @@ function collectSetting(prefix, setCodeName, setType, settingsArray) {
function generateFormHtml(settingsData, set, overrideValue, overrideOptions, originalSetKey) { function generateFormHtml(settingsData, set, overrideValue, overrideOptions, originalSetKey) {
let inputHtml = ''; let inputHtml = '';
isEmpty(overrideValue) ? inVal = set['setValue'] : inVal = overrideValue; isEmpty(overrideValue) ? inVal = set['setValue'] : inVal = overrideValue;
const setKey = set['setKey']; const setKey = set['setKey'];
const setType = set['setType']; const setType = set['setType'];
@@ -1104,7 +1111,7 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
// } // }
// Parse the setType JSON string // Parse the setType JSON string
console.log(processQuotes(setType)); // console.log(processQuotes(setType));
const setTypeObject = JSON.parse(processQuotes(setType)) const setTypeObject = JSON.parse(processQuotes(setType))
const dataType = setTypeObject.dataType; const dataType = setTypeObject.dataType;
@@ -1166,6 +1173,7 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
my-customparams="${customParams}" my-customparams="${customParams}"
my-customid="${customId}" my-customid="${customId}"
my-originalSetKey="${originalSetKey}" my-originalSetKey="${originalSetKey}"
data-elementoptionsbase64="${elementOptionsBase64}"
${multi} ${multi}
${readOnly ? "disabled" : ""}> ${readOnly ? "disabled" : ""}>
<option value="" id="${setKey + "_temp_"}"></option> <option value="" id="${setKey + "_temp_"}"></option>

View File

@@ -7,7 +7,7 @@ Unifi import plugin using the Site Manager API.
### Quick setup guide ### Quick setup guide
Navigate to your UniFi Site Manager _⚙️ Settings -> Control Plane -> Integrations_. Navigate to your UniFi Site Manager _Settings -> Control Plane -> Integrations_.
- `api_key` : You can generate your API key under the _Your API Keys_ section. - `api_key` : You can generate your API key under the _Your API Keys_ section.
- `base_url` : You can find your base url in the _API Request Format_ section, e.g. `https://192.168.100.1/proxy/network/integration/` - `base_url` : You can find your base url in the _API Request Format_ section, e.g. `https://192.168.100.1/proxy/network/integration/`

View File

@@ -208,9 +208,7 @@
"elementType": "button", "elementType": "button",
"elementOptions": [ "elementOptions": [
{ {
"sourceSuffixes": [ "sourceSuffixes": []
"_in"
]
}, },
{ {
"separator": "" "separator": ""
@@ -223,6 +221,22 @@
}, },
{ {
"getStringKey": "Gen_Add" "getStringKey": "Gen_Add"
}
],
"transformers": []
},
{
"elementType": "select",
"elementHasInputValue": 1,
"elementOptions": [
{
"multiple": "true"
},
{
"readonly": "true"
},
{
"editable": "true"
}, },
{ {
"popupForm": [ "popupForm": [
@@ -237,14 +251,8 @@
{ {
"placeholder": "Enter value" "placeholder": "Enter value"
}, },
{
"suffix": "_in"
},
{ {
"cssClasses": "col-sm-10" "cssClasses": "col-sm-10"
},
{
"prefillValue": "null"
} }
], ],
"transformers": [] "transformers": []
@@ -281,14 +289,8 @@
{ {
"placeholder": "https://host_ip/proxy/network/integration/" "placeholder": "https://host_ip/proxy/network/integration/"
}, },
{
"suffix": "_in"
},
{ {
"cssClasses": "col-sm-10" "cssClasses": "col-sm-10"
},
{
"prefillValue": "null"
} }
], ],
"transformers": [] "transformers": []
@@ -315,7 +317,7 @@
] ]
}, },
{ {
"function": "version", "function": "api_version",
"type": { "type": {
"dataType": "string", "dataType": "string",
"elements": [ "elements": [
@@ -325,14 +327,8 @@
{ {
"placeholder": "v1" "placeholder": "v1"
}, },
{
"suffix": "_in"
},
{ {
"cssClasses": "col-sm-10" "cssClasses": "col-sm-10"
},
{
"prefillValue": "null"
} }
], ],
"transformers": [] "transformers": []
@@ -369,14 +365,8 @@
{ {
"placeholder": "Enter value" "placeholder": "Enter value"
}, },
{
"suffix": "_in"
},
{ {
"cssClasses": "col-sm-10" "cssClasses": "col-sm-10"
},
{
"prefillValue": "null"
} }
], ],
"transformers": [] "transformers": []
@@ -403,7 +393,7 @@
] ]
}, },
{ {
"function": "hide.site.verify_ssl", "function": "verify_ssl",
"type": { "type": {
"dataType": "boolean", "dataType": "boolean",
"elements": [ "elements": [
@@ -441,22 +431,6 @@
"transformers": [] "transformers": []
} }
], ],
"transformers": []
},
{
"elementType": "select",
"elementHasInputValue": 1,
"elementOptions": [
{
"multiple": "true"
},
{
"readonly": "true"
},
{
"editable": "true"
}
],
"transformers": [ "transformers": [
"name|base64" "name|base64"
] ]
@@ -520,7 +494,7 @@
"description": [ "description": [
{ {
"language_code": "en_us", "language_code": "en_us",
"string": "UniFi sites" "string": "UniFi site configurations. Use a unique name for each site. You can find necessary details to configure this in your controller under <i>Settings -> Control Plane -> Integrations</i>."
} }
] ]
} }