diff --git a/docs/ICONS.md b/docs/ICONS.md index 989ecd2d..b8cc92f2 100755 --- a/docs/ICONS.md +++ b/docs/ICONS.md @@ -29,11 +29,11 @@ Copying the HTML code from [Font Awesome](https://fontawesome.com/search?o=r&m=f ![preview](/docs/img/ICONS/device_add_icon.png) -3. Paste in the copied HTML or SVG code. +3. Paste in the copied HTML or SVG code and click "OK": -4. Click "OK" +![Paste SVG](/docs/img/ICONS/paste-svg.png) -5. "Save" the device +6. "Save" the device > [!NOTE] > If you want to mass-apply an icon to all devices of the same device type (Field: Type), you can click the mass-copy button (next to the "+" button). A confirmation prompt is displayed. If you proceed, icons of all devices set to the same device type as the current device, will be overwritten with the current device's icon. diff --git a/docs/img/ICONS/paste-svg.png b/docs/img/ICONS/paste-svg.png new file mode 100755 index 00000000..1c732529 Binary files /dev/null and b/docs/img/ICONS/paste-svg.png differ diff --git a/front/deviceDetails.php b/front/deviceDetails.php index fa8be620..9a5c560e 100755 --- a/front/deviceDetails.php +++ b/front/deviceDetails.php @@ -748,28 +748,13 @@ function main () { // Show device icon as it changes $('#txtIcon').on('change input', function() { - updateIconPreview() + updateIconPreview('#txtIcon') }); } -// ----------------------------------------------------------------------------- -function updateIconPreview () { - // update icon - iconInput = $('#txtIcon') - - value = iconInput.val() - - iconInput.on('change input', function() { - $('#txtIconFA').html(atob(value)) - }); - - $('#txtIconFA').html(atob(value)) - -} - // ----------------------------------------------------------------------------- function initializeTabs () { // Activate panel @@ -839,12 +824,12 @@ function initializeCombos () { // nameTransformer) // callback to transform name - initSettingDropdown("NEWDEV_dev_Icon", [], "dropdownIcon_tmp", genDevDetailsList, 'txtIcon', atob ) - initSettingDropdown("NEWDEV_dev_DeviceType", [], "dropdownDeviceType_tmp", genDevDetailsList, 'txtDeviceType' ) - initSettingDropdown("NEWDEV_dev_Owner", [], "dropdownOwner_tmp", genDevDetailsList, 'txtOwner' ) - initSettingDropdown("NEWDEV_dev_Group", [], "dropdownGroup_tmp", genDevDetailsList, 'txtGroup' ) - initSettingDropdown("NEWDEV_dev_Location", [], "dropdownLocation_tmp", genDevDetailsList, 'txtLocation' ) - initSettingDropdown("NEWDEV_dev_Network_Node_MAC_ADDR", [], "dropdownNetworkNodeMac_tmp", genDevDetailsList, 'txtNetworkNodeMac' ) + initSettingDropdown("NEWDEV_dev_Icon", [], "dropdownIcon_tmp", genListWithInputSet, 'txtIcon', atob ) + initSettingDropdown("NEWDEV_dev_DeviceType", [], "dropdownDeviceType_tmp", genListWithInputSet, 'txtDeviceType' ) + initSettingDropdown("NEWDEV_dev_Owner", [], "dropdownOwner_tmp", genListWithInputSet, 'txtOwner' ) + initSettingDropdown("NEWDEV_dev_Group", [], "dropdownGroup_tmp", genListWithInputSet, 'txtGroup' ) + initSettingDropdown("NEWDEV_dev_Location", [], "dropdownLocation_tmp", genListWithInputSet, 'txtLocation' ) + initSettingDropdown("NEWDEV_dev_Network_Node_MAC_ADDR", [], "dropdownNetworkNodeMac_tmp", genListWithInputSet, 'txtNetworkNodeMac' ) // Initialize static combos initializeComboSkipRepeated (); @@ -1155,7 +1140,7 @@ function initializeCalendar () { showSpinner() } else { setTimeout(() => { - updateIconPreview() + updateIconPreview('#txtIcon') }, 100); hideSpinner() @@ -1673,7 +1658,7 @@ function addAsBase64 () { $('#txtIcon').val(iconHtmlBase64); - updateIconPreview() + updateIconPreview('#txtIcon') } diff --git a/front/js/ui_components.js b/front/js/ui_components.js index 018580d4..d50e0c39 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -186,13 +186,25 @@ function hideUIelements(settingKey) { // ----------------------------------------------------------------------------- // Processor to generate options for a dropdown menu -function generateDropdownOptions(data, valuesArray) { +function generateDropdownOptions(data, valuesArray, targetField, nameTransformer) { var optionsHtml = ""; data.forEach(function(item) { + labelName = item.name + + // console.log(nameTransformer); + // console.log(labelName); + + // if(nameTransformer && nameTransformer != '' && labelName != '❌None') + // { + // console.log(labelName); + // labelName = nameTransformer(labelName) + // console.log(labelName); + // } + let selected = valuesArray.includes(item.id) ? 'selected' : ''; - optionsHtml += ``; + optionsHtml += ``; }); return `${optionsHtml}`; } @@ -200,21 +212,28 @@ function generateDropdownOptions(data, valuesArray) { // ----------------------------------------------------------------------------- // Processor to generate a list -function generateList(data, valuesArray) { +function generateList(data, valuesArray, targetField, nameTransformer) { var listHtml = ""; data.forEach(function(item) { + labelName = item.name + + if(nameTransformer && nameTransformer != '' && labelName != '❌None') + { + labelName = nameTransformer(labelName) + } + let selected = valuesArray.includes(item.id) ? 'selected' : ''; - listHtml += `
  • ${item.name}
  • `; + listHtml += `
  • ${labelName}
  • `; }); return listHtml; } // ----------------------------------------------------------------------------- -// Processor to generate a list in teh deviceDetails page -function genDevDetailsList(data, valuesArray, targetField, nameTransformer) { +// Processor to generate a list in the deviceDetails page +function genListWithInputSet(data, valuesArray, targetField, nameTransformer) { var listHtml = ""; @@ -227,7 +246,7 @@ function genDevDetailsList(data, valuesArray, targetField, nameTransformer) { labelName = item.name - if(nameTransformer && labelName != '❌None') + if(nameTransformer && nameTransformer != '' && labelName != '❌None') { labelName = nameTransformer(labelName) } @@ -242,7 +261,21 @@ function genDevDetailsList(data, valuesArray, targetField, nameTransformer) { } +// ----------------------------------------------------------------------------- +// Updates the icon preview +function updateIconPreview (inputId) { + // update icon + iconInput = $(inputId) + value = iconInput.val() + + iconInput.on('change input', function() { + $('#txtIconFA').html(atob(value)) + }); + + $('#txtIconFA').html(atob(value)) + +} // ----------------------------------------------------------------------------- // initialize diff --git a/front/multiEditCore.php b/front/multiEditCore.php index 0f797410..7c78f2b8 100755 --- a/front/multiEditCore.php +++ b/front/multiEditCore.php @@ -105,8 +105,7 @@ default: inputType = 'text'; break; - } - + } if (inputType === 'text.select') { @@ -114,12 +113,30 @@ initSettingDropdown(columns[j].Code_Name, [], targetLocation, generateDropdownOptions) - input = ` ` + + } else{ + + input = `` + } + + } else { // Add classes specifically for checkboxes diff --git a/front/php/templates/footer.php b/front/php/templates/footer.php index 46a0e76c..efa278f2 100755 --- a/front/php/templates/footer.php +++ b/front/php/templates/footer.php @@ -18,7 +18,7 @@ © - 2020 Puche (2022+ jokob-sk) | : + Author: jokob-sk (Based on 2020 PiAlert) | : | Version: | Docs diff --git a/front/php/templates/language/en_us.json b/front/php/templates/language/en_us.json index 976e38bd..defbbe0e 100755 --- a/front/php/templates/language/en_us.json +++ b/front/php/templates/language/en_us.json @@ -613,7 +613,9 @@ "TIMEZONE_name": "Time zone", "UI_DEV_SECTIONS_description": "Select which UI elements to hide in the Devices pages.", "UI_DEV_SECTIONS_name": "Hide Devices Sections", - "UI_LANG_description": "Select the preferred UI language. Help translating or suggest languages in the online portal of Weblate.", + "UI_ICONS_description": "Select which UI elements to hide in the Devices pages.", + "UI_ICONS_name": "Pre-defined icons", + "UI_LANG_description": "A list of pre-defined icons. Proceed with caution, the preferred way to add icons is described in the Icons documentation. You can add a base64-encoded SVG HTML or Font-awesome HTML tag.", "UI_LANG_name": "UI Language", "UI_MY_DEVICES_description": "Devices of which statuses should be shown in the default My Devices view. (CTRL + Click to select/deselect)", "UI_MY_DEVICES_name": "Show in My Devices view", diff --git a/front/plugins/newdev_template/config.json b/front/plugins/newdev_template/config.json index 62847e68..6ac9b477 100755 --- a/front/plugins/newdev_template/config.json +++ b/front/plugins/newdev_template/config.json @@ -589,7 +589,7 @@ { "name" : "value", "type" : "sql", - "value" : "SELECT DISTINCT '❌None' AS name, '' AS id UNION SELECT Dev_Icon AS name, Dev_Icon AS id FROM Devices WHERE Dev_Icon <> '';" + "value" : "WITH RECURSIVE SettingsIcons AS (SELECT REPLACE(REPLACE(REPLACE(Value, '[', ''), ']', ''), '''', '') AS icon_list FROM Settings WHERE Code_Name = 'UI_ICONS'), SplitIcons AS (SELECT TRIM(SUBSTR(icon_list, 1, INSTR(icon_list || ',', ',') - 1)) AS icon, SUBSTR(icon_list, INSTR(icon_list || ',', ',') + 1) AS remaining_icons FROM SettingsIcons WHERE icon_list <> '' UNION ALL SELECT TRIM(SUBSTR(remaining_icons, 1, INSTR(remaining_icons || ',', ',') - 1)) AS icon, SUBSTR(remaining_icons, INSTR(remaining_icons || ',', ',') + 1) AS remaining_icons FROM SplitIcons WHERE remaining_icons <> '') SELECT DISTINCT * FROM (SELECT icon as name, icon as id FROM SplitIcons UNION SELECT '❌None' AS name, '' AS id UNION SELECT Dev_Icon AS name, Dev_Icon AS id FROM Devices WHERE Dev_Icon <> '') AS combined_results;" } ], "localized": ["name", "description"], diff --git a/server/database.py b/server/database.py index 64e42a24..2f98f7c0 100755 --- a/server/database.py +++ b/server/database.py @@ -7,11 +7,9 @@ import base64 from const import fullDbPath, sql_devices_stats, sql_devices_all from logger import mylog -from helper import json_obj, initOrSetParam, row_to_json, timeNowTZ, split_string #, updateState +from helper import json_obj, initOrSetParam, row_to_json, timeNowTZ#, split_string #, updateState from appevent import AppEvent_obj - - class DB(): """ DB Class to provide the basic database interactions. @@ -82,13 +80,7 @@ class DB(): """ Check the current tables in the DB and upgrade them if neccessary """ - - # Registering UDF (User Defined Functions) - # - resultUDF = self.sql_connection.create_function("split_string", 2, split_string) # Register the UDF - mylog('none',f'[upgradeDB] resultUDF: {resultUDF}') - - + # indicates, if Online_History table is available onlineHistoryAvailable = self.sql.execute(""" SELECT name FROM sqlite_master WHERE type='table' diff --git a/server/helper.py b/server/helper.py index 67e253d3..edcb6704 100755 --- a/server/helper.py +++ b/server/helper.py @@ -597,12 +597,6 @@ def cleanDeviceName(str, match_IP): # String manipulation methods #------------------------------------------------------------------------------- -#------------------------------------------------------------------------------- -# Define the split_string function -def split_string(input_str, delimiter): - # remove any wrapping brackets - input_str = input_str.replace('[','').replace(']','') - return input_str.split(delimiter) #------------------------------------------------------------------------------- diff --git a/server/initialise.py b/server/initialise.py index 4613c329..e16975e2 100755 --- a/server/initialise.py +++ b/server/initialise.py @@ -110,7 +110,7 @@ def importConfigs (db): conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', 'text.multiselect', "['Tile Cards', 'Device Presence']", 'General') conf.UI_MY_DEVICES = ccd('UI_MY_DEVICES', ['online', 'offline', 'archived', 'new', 'down'] , c_d, 'Include in My Devices', 'text.multiselect', "['online', 'offline', 'archived', 'new', 'down']", 'General') conf.UI_NOT_RANDOM_MAC = ccd('UI_NOT_RANDOM_MAC', [] , c_d, 'Exlude from Random Prefix', 'list', "", 'General') - conf.UI_ICONS = ccd('UI_ICONS', ['PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k', 'PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k', 'PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4', 'PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k', 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI', 'PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI', 'PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI', 'PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4'] , c_d, 'Icons', 'list', "", 'General') + conf.UI_ICONS = ccd('UI_ICONS', ['PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4', 'PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4'] , c_d, 'Icons', 'list', "", 'General') conf.UI_REFRESH = ccd('UI_REFRESH', 0 , c_d, 'Refresh interval', 'integer', "", 'General') conf.DAYS_TO_KEEP_EVENTS = ccd('DAYS_TO_KEEP_EVENTS', 90 , c_d, 'Delete events days', 'integer', '', 'General') conf.HRS_TO_KEEP_NEWDEV = ccd('HRS_TO_KEEP_NEWDEV', 0 , c_d, 'Keep new devices for', 'integer', "0", 'General')