From e92d1bb0adf2bc138e2b1f18a55d62c9e59786ae Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Wed, 4 Dec 2024 21:03:35 +1100 Subject: [PATCH] Icon selector --- front/css/app.css | 46 +++++ front/deviceDetails.php | 171 ++++++++++-------- front/deviceDetailsEdit.php | 26 +-- front/js/ui_components.js | 83 +++++++++ front/php/components/device_cards.php | 64 ++++--- front/php/templates/language/en_us.json | 1 + server/__main__.py | 4 +- server/graphql_server/graphql_server_start.py | 2 +- 8 files changed, 272 insertions(+), 125 deletions(-) diff --git a/front/css/app.css b/front/css/app.css index 34667f60..65b9f168 100755 --- a/front/css/app.css +++ b/front/css/app.css @@ -1226,6 +1226,52 @@ input[readonly] { /* Devices page */ /* ----------------------------------------------------------------- */ +.modal-header .close +{ + display: flex; +} + +.modal-title +{ + display: inline; +} + +#iconList +{ + padding: 10px; + padding-bottom:30px; +} + +.iconPreviewSelector:hover +{ + backdrop-filter: brightness(50%); +} + +.iconPreviewSelector +{ + text-align: center; + padding: 15px; + height: 80px; + margin-bottom: 15px; +} + +.iconList +{ + display: flex; +} + +.iconPreviewSelector svg +{ + width:40px; + height: 40px; +} + +.iconPreviewSelector i +{ + font-size: 30px; + height: 40px; +} + .iconPreview { min-width: 40px; } diff --git a/front/deviceDetails.php b/front/deviceDetails.php index 8fa2562e..2683ff20 100755 --- a/front/deviceDetails.php +++ b/front/deviceDetails.php @@ -16,6 +16,7 @@ require 'php/templates/header.php'; ?> +
@@ -214,9 +215,7 @@ switch ($UI_THEME) { ?> - + + diff --git a/front/deviceDetailsEdit.php b/front/deviceDetailsEdit.php index 633db4f9..a912b81a 100755 --- a/front/deviceDetailsEdit.php +++ b/front/deviceDetailsEdit.php @@ -180,6 +180,15 @@ `; } + + // handle generate IP for new device + if (setting.setKey == "NEWDEV_devIcon") { + inlineControl += ` + + `; + } // Generate the input field HTML @@ -412,14 +421,6 @@ , function(msg) { showMessage (msg); - - - // clear session storage - setCache("#dropdownOwner",""); - setCache("#dropdownDeviceType",""); - setCache("#dropdownGroup",""); - setCache("#dropdownLocation",""); - setCache("#dropdownNetworkNodeMac",""); // Remove navigation prompt "Are you sure you want to leave..." window.onbeforeunload = null; @@ -438,15 +439,6 @@ }); } - // Helper function to clear dropdown cache - function clearDropdownCache() { - setCache("#dropdownOwner", ""); - setCache("#dropdownDeviceType", ""); - setCache("#dropdownGroup", ""); - setCache("#dropdownLocation", ""); - setCache("#dropdownNetworkNodeMac", ""); - } - //----------------------------------------------------------------------------------- // Disables or enables network configuration for the root node function toggleNetworkConfiguration(disable) { diff --git a/front/js/ui_components.js b/front/js/ui_components.js index 6ec3a788..fa23d287 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -387,6 +387,89 @@ function addIconAsBase64 (el) { } + +function showIconSelection() { + const selectElement = document.getElementById('NEWDEV_devIcon'); + const modalId = 'dynamicIconModal'; + + // Create modal HTML dynamically + const modalHTML = ` + + `; + + // Append the modal to the body + document.body.insertAdjacentHTML('beforeend', modalHTML); + + const iconList = document.getElementById('iconList'); + + // Populate the icon list + Array.from(selectElement.options).forEach(option => { + if (option.value != "") { + + + const value = option.value; + + // Decode the base64 value + let decodedValue; + try { + decodedValue = atob(value); + } catch (e) { + console.warn(`Skipping invalid base64 value: ${value}`); + return; + } + + // Create an icon container + const iconDiv = document.createElement('div'); + iconDiv.classList.add('iconPreviewSelector','col-md-2' , 'col-sm-3', 'col-xs-4'); + iconDiv.style.cursor = 'pointer'; + + // Render the SVG or HTML content + const iconContainer = document.createElement('div'); + iconContainer.innerHTML = decodedValue; + + // Append the icon to the div + iconDiv.appendChild(iconContainer); + iconList.appendChild(iconDiv); + + // Add click event to select icon + iconDiv.addEventListener('click', () => { + selectElement.value = value; // Update the select element value + $(`#${modalId}`).modal('hide'); // Hide the modal + updateIconPreview(); + }); + } + }); + + // Show the modal using AJAX + $(`#${modalId}`).modal('show'); + + // Remove modal from DOM after it's hidden + $(`#${modalId}`).on('hidden.bs.modal', function () { + document.getElementById(modalId).remove(); + }); + + // + +} + + + + + // ----------------------------------------------------------------------------- // initialize // ----------------------------------------------------------------------------- diff --git a/front/php/components/device_cards.php b/front/php/components/device_cards.php index 564fa08f..e131b7e1 100755 --- a/front/php/components/device_cards.php +++ b/front/php/components/device_cards.php @@ -3,51 +3,57 @@ require '../server/init.php'; //------------------------------------------------------------------------------ -// check if authenticated +// Check if authenticated require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php'; function renderSmallBox($params) { - $onclickEvent = isset($params['onclickEvent']) ? $params['onclickEvent'] : ''; - $color = isset($params['color']) ? $params['color'] : ''; - $headerId = isset($params['headerId']) ? $params['headerId'] : ''; - $headerStyle = isset($params['headerStyle']) ? $params['headerStyle'] : ''; - $labelLang = isset($params['labelLang']) ? $params['labelLang'] : ''; - $iconId = isset($params['iconId']) ? $params['iconId'] : ''; - $iconClass = isset($params['iconClass']) ? $params['iconClass'] : ''; - $dataValue = isset($params['dataValue']) ? $params['dataValue'] : ''; + $onclickEvent = isset($params['onclickEvent']) ? $params['onclickEvent'] : ''; + $color = isset($params['color']) ? $params['color'] : ''; + $headerId = isset($params['headerId']) ? $params['headerId'] : ''; + $headerStyle = isset($params['headerStyle']) ? $params['headerStyle'] : ''; + $labelLang = isset($params['labelLang']) ? $params['labelLang'] : ''; + $iconId = isset($params['iconId']) ? $params['iconId'] : ''; + $iconClass = isset($params['iconClass']) ? $params['iconClass'] : ''; + $dataValue = isset($params['dataValue']) ? $params['dataValue'] : ''; - return ' - '; + return ' + '; } // Load default data from JSON file $defaultDataFile = 'device_cards_defaults.json'; $defaultData = file_exists($defaultDataFile) ? json_decode(file_get_contents($defaultDataFile), true) : []; -// Check if 'items' parameter exists and is valid JSON -$items = isset($_POST['items']) ? json_decode($_POST['items'], true) : []; +// Decode raw JSON input from body +$requestBody = file_get_contents('php://input'); +$data = json_decode($requestBody, true); -// Use default data if 'items' is not provided or cannot be decoded -if (empty($items)) { - $items = $defaultData; +// Debugging logs +if (json_last_error() !== JSON_ERROR_NONE) { + error_log('JSON Decode Error: ' . json_last_error_msg()); + error_log('Raw body: ' . $requestBody); + $data = null; } +// Extract 'items' or fall back to default data +$items = isset($data['items']) ? $data['items'] : $defaultData; + // Generate HTML $html = '
'; foreach ($items as $item) { - $html .= renderSmallBox($item); + $html .= renderSmallBox($item); } $html .= '
'; diff --git a/front/php/templates/language/en_us.json b/front/php/templates/language/en_us.json index 28b1783d..6fbad952 100755 --- a/front/php/templates/language/en_us.json +++ b/front/php/templates/language/en_us.json @@ -309,6 +309,7 @@ "Gen_Saved": "Saved", "Gen_Search": "Search", "Gen_SelectToPreview": "Select to preview", + "Gen_Select": "Select", "Gen_Selected_Devices": "Selected Devices:", "Gen_Switch": "Switch", "Gen_Upd": "Updated successfully", diff --git a/server/__main__.py b/server/__main__.py index c8a0e2f9..3df81ff1 100755 --- a/server/__main__.py +++ b/server/__main__.py @@ -186,11 +186,11 @@ def main (): # Footer - mylog('verbose', ['[MAIN] Process: Wait']) + mylog('verbose', ['[MAIN] Process: Idle']) else: # do something # mylog('verbose', ['[MAIN] Waiting to start next loop']) - updateState("Process: Wait") + updateState("Process: Idle") #loop diff --git a/server/graphql_server/graphql_server_start.py b/server/graphql_server/graphql_server_start.py index 9a02321e..5a9b1c2b 100755 --- a/server/graphql_server/graphql_server_start.py +++ b/server/graphql_server/graphql_server_start.py @@ -64,4 +64,4 @@ def start_server(graphql_port, app_state): thread.start() # Update the state to indicate the server has started - app_state = updateState("Process: Wait", None, None, None, 1) \ No newline at end of file + app_state = updateState("Process: Idle", None, None, None, 1) \ No newline at end of file