Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cce1f2f0fd |
92
api/index.js
92
api/index.js
@@ -1528,16 +1528,12 @@ function handleAdminResponseData(responseData) {
|
|||||||
function handleConfigQueryResponse(responseData) {
|
function handleConfigQueryResponse(responseData) {
|
||||||
console.log('=== CONFIG QUERY RESPONSE ===');
|
console.log('=== CONFIG QUERY RESPONSE ===');
|
||||||
console.log('Query type:', responseData.query_type);
|
console.log('Query type:', responseData.query_type);
|
||||||
console.log('Total results:', responseData.total_results);
|
console.log('Count:', responseData.count);
|
||||||
console.log('Data:', responseData.data);
|
console.log('Config:', responseData.config);
|
||||||
console.log('Data type:', typeof responseData.data);
|
console.log('Config type:', typeof responseData.config);
|
||||||
console.log('Is array:', Array.isArray(responseData.data));
|
|
||||||
|
|
||||||
// Check if data exists and has content (handle both object and array formats)
|
// Backend returns config as an object with nested objects: {key1: {value: 'x', description: 'y'}, ...}
|
||||||
const hasData = responseData.data && (
|
const hasData = responseData.config && Object.keys(responseData.config).length > 0;
|
||||||
(Array.isArray(responseData.data) && responseData.data.length > 0) ||
|
|
||||||
(!Array.isArray(responseData.data) && Object.keys(responseData.data).length > 0)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hasData) {
|
if (hasData) {
|
||||||
console.log('Converting config response to display format...');
|
console.log('Converting config response to display format...');
|
||||||
@@ -1552,24 +1548,13 @@ function handleConfigQueryResponse(responseData) {
|
|||||||
tags: []
|
tags: []
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert config data to tags format - handle both array and object formats
|
// Convert config object to tags format
|
||||||
if (Array.isArray(responseData.data)) {
|
// Backend format: {key1: {value: 'x', description: 'y'}, key2: {value: 'z'}, ...}
|
||||||
// Array format: [{key: 'x', value: 'y'}, ...]
|
Object.entries(responseData.config).forEach(([key, configEntry]) => {
|
||||||
responseData.data.forEach(config => {
|
if (key && configEntry && configEntry.value !== undefined) {
|
||||||
const key = config.key || config.config_key;
|
syntheticEvent.tags.push([key, configEntry.value]);
|
||||||
const value = config.value || config.config_value;
|
}
|
||||||
if (key && value !== undefined) {
|
});
|
||||||
syntheticEvent.tags.push([key, value]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Object format: {key1: 'value1', key2: 'value2', ...}
|
|
||||||
Object.entries(responseData.data).forEach(([key, value]) => {
|
|
||||||
if (key && value !== undefined) {
|
|
||||||
syntheticEvent.tags.push([key, value]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Synthetic event created:', syntheticEvent);
|
console.log('Synthetic event created:', syntheticEvent);
|
||||||
console.log('Calling displayConfiguration with synthetic event...');
|
console.log('Calling displayConfiguration with synthetic event...');
|
||||||
@@ -1583,9 +1568,7 @@ function handleConfigQueryResponse(responseData) {
|
|||||||
// Initialize toggle buttons with config data
|
// Initialize toggle buttons with config data
|
||||||
initializeToggleButtonsFromConfig(responseData);
|
initializeToggleButtonsFromConfig(responseData);
|
||||||
|
|
||||||
const configCount = Array.isArray(responseData.data) ?
|
const configCount = responseData.count || Object.keys(responseData.config).length;
|
||||||
responseData.data.length :
|
|
||||||
Object.keys(responseData.data).length;
|
|
||||||
log(`Configuration loaded: ${configCount} parameters`, 'INFO');
|
log(`Configuration loaded: ${configCount} parameters`, 'INFO');
|
||||||
} else {
|
} else {
|
||||||
console.log('No configuration data received');
|
console.log('No configuration data received');
|
||||||
@@ -1594,17 +1577,14 @@ function handleConfigQueryResponse(responseData) {
|
|||||||
|
|
||||||
// Also log to test interface for debugging
|
// Also log to test interface for debugging
|
||||||
if (typeof logTestEvent === 'function') {
|
if (typeof logTestEvent === 'function') {
|
||||||
logTestEvent('RECV', `Config query response: ${responseData.query_type}, ${responseData.total_results} results`, 'CONFIG_QUERY');
|
logTestEvent('RECV', `Config query response: ${responseData.query_type}, ${responseData.count} results`, 'CONFIG_QUERY');
|
||||||
|
|
||||||
if (responseData.data && responseData.data.length > 0) {
|
if (responseData.config && Object.keys(responseData.config).length > 0) {
|
||||||
logTestEvent('RECV', '=== CONFIGURATION VALUES ===', 'CONFIG');
|
logTestEvent('RECV', '=== CONFIGURATION VALUES ===', 'CONFIG');
|
||||||
responseData.data.forEach((config, index) => {
|
Object.entries(responseData.config).forEach(([key, configEntry]) => {
|
||||||
const key = config.key || config.config_key || `config_${index}`;
|
const value = configEntry.value || 'undefined';
|
||||||
const value = config.value || config.config_value || 'undefined';
|
const description = configEntry.description || '';
|
||||||
const category = config.category || 'general';
|
logTestEvent('RECV', `${key}: ${value} ${description ? '(' + description + ')' : ''}`, 'CONFIG');
|
||||||
const dataType = config.data_type || 'string';
|
|
||||||
|
|
||||||
logTestEvent('RECV', `${key}: ${value} (${dataType}, ${category})`, 'CONFIG');
|
|
||||||
});
|
});
|
||||||
logTestEvent('RECV', '=== END CONFIGURATION VALUES ===', 'CONFIG');
|
logTestEvent('RECV', '=== END CONFIGURATION VALUES ===', 'CONFIG');
|
||||||
} else {
|
} else {
|
||||||
@@ -1968,8 +1948,9 @@ async function saveIndividualConfig(key, newValue, originalValue, actionsCell) {
|
|||||||
actionsCell.style.cursor = 'not-allowed';
|
actionsCell.style.cursor = 'not-allowed';
|
||||||
actionsCell.onclick = null;
|
actionsCell.onclick = null;
|
||||||
|
|
||||||
// Send single config update
|
// Send single config update via HTTP POST
|
||||||
await sendConfigUpdateCommand([configObj]);
|
const responseData = await sendAdminCommandHTTP(['config_update', [configObj]]);
|
||||||
|
handleConfigUpdateResponse(responseData);
|
||||||
|
|
||||||
// Update the original value on success
|
// Update the original value on success
|
||||||
const input = actionsCell.parentElement.cells[1].querySelector('input');
|
const input = actionsCell.parentElement.cells[1].querySelector('input');
|
||||||
@@ -3688,19 +3669,17 @@ function getRelayInfo() {
|
|||||||
|
|
||||||
// Update stored relay info when config is loaded
|
// Update stored relay info when config is loaded
|
||||||
function updateStoredRelayInfo(configData) {
|
function updateStoredRelayInfo(configData) {
|
||||||
if (configData && configData.data) {
|
if (configData && configData.config) {
|
||||||
// Extract relay info from config data - handle both object and array formats
|
// Extract relay info from config data
|
||||||
|
// Backend format: {key1: {value: 'x', description: 'y'}, ...}
|
||||||
let relayName = 'Blossom';
|
let relayName = 'Blossom';
|
||||||
let relayDescription = 'Blob Storage Server';
|
let relayDescription = 'Blob Storage Server';
|
||||||
|
|
||||||
if (Array.isArray(configData.data)) {
|
if (configData.config.relay_name) {
|
||||||
// Array format: [{key: 'x', value: 'y'}, ...]
|
relayName = configData.config.relay_name.value || 'Blossom';
|
||||||
relayName = configData.data.find(item => item.key === 'relay_name')?.value || 'Blossom';
|
}
|
||||||
relayDescription = configData.data.find(item => item.key === 'relay_description')?.value || 'Blob Storage Server';
|
if (configData.config.relay_description) {
|
||||||
} else {
|
relayDescription = configData.config.relay_description.value || 'Blob Storage Server';
|
||||||
// Object format: {key1: 'value1', key2: 'value2', ...}
|
|
||||||
relayName = configData.data.relay_name || 'Blossom';
|
|
||||||
relayDescription = configData.data.relay_description || 'Blob Storage Server';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
relayInfoData = {
|
relayInfoData = {
|
||||||
@@ -4825,13 +4804,16 @@ function closeSideNav() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function switchPage(pageName) {
|
function switchPage(pageName) {
|
||||||
// Stop statistics polling if leaving statistics page
|
// Keep statistics polling running in background regardless of page
|
||||||
if (currentPage === 'statistics' && pageName !== 'statistics') {
|
// (removed stopStatsPolling call - stats continue updating)
|
||||||
stopStatsPolling();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update current page
|
// Update current page
|
||||||
currentPage = pageName;
|
currentPage = pageName;
|
||||||
|
|
||||||
|
// Start statistics polling if switching TO statistics page and not already running
|
||||||
|
if (pageName === 'statistics' && !statsAutoRefreshInterval) {
|
||||||
|
startStatsPolling();
|
||||||
|
}
|
||||||
|
|
||||||
// Update navigation active state
|
// Update navigation active state
|
||||||
const navItems = document.querySelectorAll('.nav-item');
|
const navItems = document.querySelectorAll('.nav-item');
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
Binary file not shown.
@@ -181,16 +181,23 @@ cJSON* admin_cmd_config_query(cJSON* args) {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if specific keys were requested (args[1] should be array of keys or null for all)
|
// Check if specific keys were requested (args[1] should be array of keys, null, or "all" for all)
|
||||||
cJSON* keys_array = NULL;
|
cJSON* keys_array = NULL;
|
||||||
if (cJSON_GetArraySize(args) >= 2) {
|
if (cJSON_GetArraySize(args) >= 2) {
|
||||||
keys_array = cJSON_GetArrayItem(args, 1);
|
keys_array = cJSON_GetArrayItem(args, 1);
|
||||||
|
// Accept array, null, or string "all" for querying all configs
|
||||||
if (!cJSON_IsArray(keys_array) && !cJSON_IsNull(keys_array)) {
|
if (!cJSON_IsArray(keys_array) && !cJSON_IsNull(keys_array)) {
|
||||||
cJSON_AddStringToObject(response, "status", "error");
|
// Check if it's the string "all"
|
||||||
cJSON_AddStringToObject(response, "error", "Keys parameter must be array or null");
|
if (cJSON_IsString(keys_array) && strcmp(keys_array->valuestring, "all") == 0) {
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
// Treat "all" as null (query all configs)
|
||||||
sqlite3_close(db);
|
keys_array = NULL;
|
||||||
return response;
|
} else {
|
||||||
|
cJSON_AddStringToObject(response, "status", "error");
|
||||||
|
cJSON_AddStringToObject(response, "error", "Keys parameter must be array, null, or \"all\"");
|
||||||
|
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
|
sqlite3_close(db);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,18 +280,18 @@ cJSON* admin_cmd_config_update(cJSON* args) {
|
|||||||
cJSON* response = cJSON_CreateObject();
|
cJSON* response = cJSON_CreateObject();
|
||||||
cJSON_AddStringToObject(response, "query_type", "config_update");
|
cJSON_AddStringToObject(response, "query_type", "config_update");
|
||||||
|
|
||||||
// Expected format: ["config_update", {"key1": "value1", "key2": "value2"}]
|
// Expected format: ["config_update", [{key: "x", value: "y", data_type: "z", category: "w"}]]
|
||||||
if (cJSON_GetArraySize(args) < 2) {
|
if (cJSON_GetArraySize(args) < 2) {
|
||||||
cJSON_AddStringToObject(response, "status", "error");
|
cJSON_AddStringToObject(response, "status", "error");
|
||||||
cJSON_AddStringToObject(response, "error", "Missing config updates object");
|
cJSON_AddStringToObject(response, "error", "Missing config updates array");
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON* updates = cJSON_GetArrayItem(args, 1);
|
cJSON* updates = cJSON_GetArrayItem(args, 1);
|
||||||
if (!cJSON_IsObject(updates)) {
|
if (!cJSON_IsArray(updates)) {
|
||||||
cJSON_AddStringToObject(response, "status", "error");
|
cJSON_AddStringToObject(response, "status", "error");
|
||||||
cJSON_AddStringToObject(response, "error", "Updates must be an object");
|
cJSON_AddStringToObject(response, "error", "Updates must be an array of config objects");
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -311,50 +318,66 @@ cJSON* admin_cmd_config_update(cJSON* args) {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process each update
|
// Process each update - expecting array of config objects
|
||||||
cJSON* updated_keys = cJSON_CreateArray();
|
cJSON* data_array = cJSON_CreateArray();
|
||||||
cJSON* failed_keys = cJSON_CreateArray();
|
|
||||||
int success_count = 0;
|
int success_count = 0;
|
||||||
int fail_count = 0;
|
int fail_count = 0;
|
||||||
|
|
||||||
cJSON* item = NULL;
|
cJSON* config_obj = NULL;
|
||||||
cJSON_ArrayForEach(item, updates) {
|
cJSON_ArrayForEach(config_obj, updates) {
|
||||||
const char* key = item->string;
|
if (!cJSON_IsObject(config_obj)) {
|
||||||
const char* value = cJSON_GetStringValue(item);
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
cJSON_AddItemToArray(failed_keys, cJSON_CreateString(key));
|
|
||||||
fail_count++;
|
fail_count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cJSON* key_item = cJSON_GetObjectItem(config_obj, "key");
|
||||||
|
cJSON* value_item = cJSON_GetObjectItem(config_obj, "value");
|
||||||
|
|
||||||
|
if (!cJSON_IsString(key_item) || !cJSON_IsString(value_item)) {
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* key = key_item->valuestring;
|
||||||
|
const char* value = value_item->valuestring;
|
||||||
|
|
||||||
sqlite3_reset(stmt);
|
sqlite3_reset(stmt);
|
||||||
sqlite3_bind_text(stmt, 1, value, -1, SQLITE_TRANSIENT);
|
sqlite3_bind_text(stmt, 1, value, -1, SQLITE_TRANSIENT);
|
||||||
sqlite3_bind_text(stmt, 2, key, -1, SQLITE_TRANSIENT);
|
sqlite3_bind_text(stmt, 2, key, -1, SQLITE_TRANSIENT);
|
||||||
|
|
||||||
rc = sqlite3_step(stmt);
|
rc = sqlite3_step(stmt);
|
||||||
|
|
||||||
|
// Create result object for this config update
|
||||||
|
cJSON* result_obj = cJSON_CreateObject();
|
||||||
|
cJSON_AddStringToObject(result_obj, "key", key);
|
||||||
|
|
||||||
if (rc == SQLITE_DONE && sqlite3_changes(db) > 0) {
|
if (rc == SQLITE_DONE && sqlite3_changes(db) > 0) {
|
||||||
cJSON_AddItemToArray(updated_keys, cJSON_CreateString(key));
|
cJSON_AddStringToObject(result_obj, "status", "success");
|
||||||
|
cJSON_AddStringToObject(result_obj, "value", value);
|
||||||
|
|
||||||
|
// Add optional fields if present
|
||||||
|
cJSON* data_type_item = cJSON_GetObjectItem(config_obj, "data_type");
|
||||||
|
if (cJSON_IsString(data_type_item)) {
|
||||||
|
cJSON_AddStringToObject(result_obj, "data_type", data_type_item->valuestring);
|
||||||
|
}
|
||||||
|
|
||||||
success_count++;
|
success_count++;
|
||||||
app_log(LOG_INFO, "Updated config key: %s", key);
|
app_log(LOG_INFO, "Updated config key: %s = %s", key, value);
|
||||||
} else {
|
} else {
|
||||||
cJSON_AddItemToArray(failed_keys, cJSON_CreateString(key));
|
cJSON_AddStringToObject(result_obj, "status", "error");
|
||||||
|
cJSON_AddStringToObject(result_obj, "error", "Failed to update");
|
||||||
fail_count++;
|
fail_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cJSON_AddItemToArray(data_array, result_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
|
|
||||||
cJSON_AddStringToObject(response, "status", "success");
|
cJSON_AddStringToObject(response, "status", success_count > 0 ? "success" : "error");
|
||||||
cJSON_AddNumberToObject(response, "updated_count", success_count);
|
cJSON_AddNumberToObject(response, "updates_applied", success_count);
|
||||||
cJSON_AddNumberToObject(response, "failed_count", fail_count);
|
cJSON_AddItemToObject(response, "data", data_array);
|
||||||
cJSON_AddItemToObject(response, "updated_keys", updated_keys);
|
|
||||||
if (fail_count > 0) {
|
|
||||||
cJSON_AddItemToObject(response, "failed_keys", failed_keys);
|
|
||||||
} else {
|
|
||||||
cJSON_Delete(failed_keys);
|
|
||||||
}
|
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,8 @@
|
|||||||
// Version information (auto-updated by build system)
|
// Version information (auto-updated by build system)
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 1
|
#define VERSION_MINOR 1
|
||||||
#define VERSION_PATCH 20
|
#define VERSION_PATCH 21
|
||||||
#define VERSION "v0.1.20"
|
#define VERSION "v0.1.21"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user