-
-
Notifications
You must be signed in to change notification settings - Fork 35
[UX/UI] Add interactive checklist shell script modules for package management #530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Tearran
wants to merge
29
commits into
main
Choose a base branch
from
web-browsers
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
ac6ff62
new file: tools/modules/functions/interface_checklist.sh
Tearran b96b968
renamed
Tearran 6e1c60c
Update tools/modules/software/module_aptwizard.sh
Tearran cdd0368
Update tools/modules/software/module_aptwizard.sh
Tearran f081e79
fix typo
Tearran c0d5c33
test remove all but mising pack and exspected error
Tearran a6fffff
typo fix
Tearran c7ef88f
fix typo
Tearran 4a43399
templaing _checklist_proftpd
Tearran b94d03c
replace dpkg i with ai sugeted
Tearran 1c65e1b
nitpick fix and templating
Tearran 0079578
comment Scaffold
Tearran dee6505
oops
Tearran b359ab9
oops webmin
Tearran be58e1f
fix quote
Tearran d4adb83
king typo fix spam
Tearran 92b43e1
nitpick fix moulare replace array with read
Tearran afce610
reuse
Tearran 7a5446a
Update tools/modules/software/module_aptwizard.sh
Tearran bdb1dbb
typo
Tearran 28db510
rename
Tearran 64e62d1
Add module_aptwizard to json
Tearran 1de1214
style
Tearran 5306c0e
Update tools/modules/functions/interface_checklist.sh
Tearran e8c6123
📝 CodeRabbit Chat: Add test_interface_checklist.sh to tools/modules/t…
coderabbitai[bot] d6f62c8
Removed test
Tearran 736d6c1
Merge branch 'main' into web-browsers
Tearran 4c06e60
modified: tools/modules/software/module_aptwizard.sh
Tearran 7175468
Merge branch 'main' into web-browsers
Tearran File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
ENABLED=true | ||
RELEASE="bookworm:jammy:noble" | ||
TESTNAME="AptWizard" | ||
|
||
testcase() {( | ||
set -e | ||
./bin/armbian-config --api module_aptwizard help | ||
)} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
module_options+=( | ||
["interface_checklist,author"]="@Tearran" | ||
["interface_checklist,maintainer"]="@Tearran" | ||
["interface_checklist,feature"]="interface_checklist" | ||
["interface_checklist,example"]="interface_checklist <title> <prompt> <options_array>" | ||
["interface_checklist,desc"]="Reusable helper function to display a checklist using whiptail, dialog, or read." | ||
["interface_checklist,status"]="Active" | ||
["interface_checklist,group"]="Helpers" | ||
["interface_checklist,arch"]="arm64" | ||
) | ||
# Helper function to display a checklist using whiptail/dialog/read | ||
function interface_checklist() { | ||
local title="$1" | ||
local prompt="$2" | ||
local -n options_array="$3" # Use a nameref to pass the array by reference | ||
local dialog_height=20 | ||
local dialog_width=78 | ||
local menu_height=10 | ||
|
||
# Prepare options for the checklist | ||
local checklist_items=() | ||
for ((i = 0; i < ${#options_array[@]}; i += 3)); do | ||
checklist_items+=("${options_array[i]}" "${options_array[i+1]}" "${options_array[i+2]}") | ||
done | ||
|
||
# Display the checklist based on the dialog tool | ||
local selected_items="" | ||
case $DIALOG in | ||
"whiptail") | ||
selected_items=$(whiptail --title "$title" --checklist \ | ||
"$prompt" $dialog_height $dialog_width $menu_height \ | ||
"${checklist_items[@]}" 3>&1 1>&2 2>&3) | ||
;; | ||
"dialog") | ||
selected_items=$(dialog --title "$title" --checklist \ | ||
"$prompt" $dialog_height $dialog_width $menu_height \ | ||
"${checklist_items[@]}" 2>&1 >/dev/tty) | ||
;; | ||
"read") | ||
echo "$title" | ||
echo "$prompt" | ||
for ((i = 0; i < ${#options_array[@]}; i += 3)); do | ||
echo "$((i / 3 + 1)). ${options_array[i]} - ${options_array[i+1]} (Default: ${options_array[i+2]})" | ||
done | ||
echo "Enter the numbers of the items you want to select, separated by spaces:" | ||
read -r selected_indexes | ||
selected_items="" | ||
for index in $selected_indexes; do | ||
selected_items+=" ${options_array[((index - 1) * 3)]}" | ||
done | ||
;; | ||
esac | ||
Tearran marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Return the selected items | ||
if [[ -z "$selected_items" ]]; then | ||
echo "Checklist canceled." | ||
return 1 | ||
fi | ||
|
||
echo "$selected_items" | ||
} | ||
|
||
module_options+=( | ||
["process_package_selection,author"]="@Tearran" | ||
["process_package_selection,maintainer"]="@Tearran" | ||
["process_package_selection,feature"]="process_package_selection" | ||
["process_package_selection,example"]="process_package_selection <title> <prompt> <checklist_options_array>" | ||
["process_package_selection,desc"]="Reusable helper function to process user-selected packages for installation or removal." | ||
["process_package_selection,status"]="Active" | ||
["process_package_selection,group"]="Helpers" | ||
["process_package_selection,arch"]="x86-64 arm64 armhf" | ||
) | ||
# | ||
function process_package_selection() { | ||
local title="$1" | ||
local prompt="$2" | ||
local -a checklist_options=("${!3}") # Accept checklist array as reference | ||
|
||
# Display checklist to user and get selected packages | ||
local selected_packages | ||
selected_packages=$(interface_checklist "$title Management" "$prompt" checklist_options) | ||
|
||
# Check if user canceled or made no selection | ||
if [[ $? -ne 0 ]]; then | ||
echo "No changes made." | ||
return 1 | ||
fi | ||
|
||
# Processing all packages from the checklist | ||
echo "Processing package selections..." | ||
for ((i = 0; i < ${#checklist_options[@]}; i += 3)); do | ||
local package="${checklist_options[i]}" | ||
local current_state="${checklist_options[i+2]}" # Current state in checklist (ON/OFF) | ||
local is_selected="OFF" # Default to OFF | ||
|
||
# Check if the package is in the selected list | ||
if [[ "$selected_packages" == *"$package"* ]]; then | ||
is_selected="ON" | ||
fi | ||
|
||
# Compare current state with selected state and act accordingly | ||
if [[ "$is_selected" == "ON" && "$current_state" == "OFF" ]]; then | ||
# Package is selected but not installed, install it | ||
echo "Installing $package..." | ||
if ! pkg_install "$package"; then | ||
echo "Failed to install $package." >&2 | ||
fi | ||
elif [[ "$is_selected" == "OFF" && "$current_state" == "ON" ]]; then | ||
# Package is deselected but installed, remove it | ||
echo "Removing $package..." | ||
if ! pkg_remove "$package"; then | ||
echo "Failed to remove $package." >&2 | ||
fi | ||
fi | ||
done | ||
|
||
echo "Package management complete." | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
module_options+=( | ||
Tearran marked this conversation as resolved.
Show resolved
Hide resolved
|
||
["_checklist_proftpd,author"]="@Tearran" | ||
["_checklist_proftpd,maintainer"]="@Tearran" | ||
["_checklist_proftpd,feature"]="_checklist_proftpd" | ||
["_checklist_proftpd,example"]="" | ||
["_checklist_proftpd,desc"]="Dynamic ProFTPD package management with install/remove toggle." | ||
["_checklist_proftpd,status"]="Active" | ||
["_checklist_proftpd,group"]="Internet" | ||
["_checklist_proftpd,arch"]="x86-64 arm64 armhf" | ||
) | ||
Tearran marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Scaffold for an app that has multiple candidates, such as ProFTPD and modules. | ||
function _checklist_proftpd() { | ||
local title="proftpd" | ||
|
||
# Convert the example string to an array | ||
local commands | ||
IFS=' ' read -r -a commands <<< "${module_options["_checklist_proftpd,example"]}" | ||
|
||
## Dynamically manage ProFTPD packages | ||
echo "Fetching $title-related packages..." | ||
local package_list | ||
# get a list of all packages | ||
package_list=$(apt-cache search "$title" | awk '{print $1}') | ||
if [[ -z "$package_list" ]]; then | ||
echo "No $title-related packages found." | ||
return 1 | ||
fi | ||
|
||
# Prepare checklist options dynamically | ||
local checklist_options=() | ||
for package in $package_list; do | ||
if dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q "^install ok installed$"; then | ||
checklist_options+=("$package" "Installed" "ON") | ||
else | ||
checklist_options+=("$package" "Not installed" "OFF") | ||
fi | ||
done | ||
|
||
process_package_selection "$title" "Select $title packages to install/remove:" checklist_options[@] | ||
} | ||
|
||
|
||
module_options+=( | ||
["_checklist_browsers,author"]="@Tearran" | ||
["_checklist_browsers,maintainer"]="@Tearran" | ||
["_checklist_browsers,feature"]="_checklist_browsers" | ||
["_checklist_browsers,example"]="" | ||
["_checklist_browsers,desc"]="Browser installation and management (Firefox-ESR and Chromium and more)." | ||
["_checklist_browsers,status"]="Active" | ||
["_checklist_browsers,group"]="Internet" | ||
["_checklist_browsers,arch"]="x86-64 arm64 armhf" | ||
) | ||
# Scaffold for app with specific single or dummy candidates. | ||
function _checklist_browsers() { | ||
local title="Browsers" | ||
|
||
# List of base browser packages to manage | ||
# | ||
local browser_packages=( | ||
"firefox-esr" | ||
"chromium" | ||
"lynx" | ||
"google-chrome" | ||
) | ||
|
||
# Manage browser installation/removal | ||
echo "Fetching browser package details..." | ||
|
||
# Prepare checklist options dynamically with descriptions | ||
local checklist_options=() | ||
for base_package in "${browser_packages[@]}"; do | ||
# Find the main package and exclude auxiliary or irrelevant ones | ||
local main_package | ||
main_package=$(apt-cache search "^${base_package}$" | awk -F' - ' '{print $1 " - " $2}') | ||
|
||
# Check if the main package exists and fetch its description | ||
if [[ -n "$main_package" ]]; then | ||
local package_name package_description | ||
package_name=$(echo "$main_package" | awk -F' - ' '{print $1}') | ||
package_description=$(echo "$main_package" | awk -F' - ' '{print $2}') | ||
|
||
# Check if the package is installed and set its state | ||
if dpkg-query -W -f='${Status}' "$package_name" 2>/dev/null | grep -q "^install ok installed$"; then | ||
checklist_options+=("$package_name" "$package_description" "ON") | ||
else | ||
checklist_options+=("$package_name" "$package_description" "OFF") | ||
fi | ||
fi | ||
done | ||
if [[ ${#checklist_options[@]} -eq 0 ]]; then | ||
echo "No $title packages found." | ||
return 1 | ||
fi | ||
|
||
process_package_selection "$title" "Select packages to install/remove:" checklist_options[@] | ||
} | ||
|
||
module_options+=( | ||
["_checklist_editors,author"]="@Tearran" | ||
["_checklist_editors,maintainer"]="@Tearran" | ||
["_checklist_editors,feature"]="_checklist_editors" | ||
["_checklist_editors,example"]="nano code codium notepadqq" | ||
["_checklist_editors,desc"]="Editor installation and management (codium notepadqq and more)." | ||
["_checklist_editors,status"]="Active" | ||
["_checklist_editors,group"]="Internet" | ||
["_checklist_editors,arch"]="x86-64 arm64 armhf" | ||
) | ||
|
||
# Scaffold for app with specific single or dummy candidates. | ||
function _checklist_editors() { | ||
local title="Editors" | ||
local self="${module_options["_checklist_editors,feature"]}" | ||
local _packages | ||
IFS=' ' read -r -a _packages <<< "${module_options["$self,example"]}" | ||
|
||
# Manage editor installation/removal | ||
echo "Fetching $title package details..." | ||
|
||
# Prepare checklist options dynamically with descriptions | ||
local checklist_options=() | ||
for base_package in "${_packages[@]}"; do | ||
# Find the main package and exclude auxiliary or irrelevant ones | ||
local main_package | ||
main_package=$(apt-cache search "^${base_package}$" | awk -F' - ' '{print $1 " - " $2}') | ||
|
||
# Check if the main package exists and fetch its description | ||
if [[ -n "$main_package" ]]; then | ||
local package_name package_description | ||
package_name=$(echo "$main_package" | awk -F' - ' '{print $1}') | ||
package_description=$(echo "$main_package" | awk -F' - ' '{print $2}') | ||
|
||
# Check if the package is installed and set its state | ||
if dpkg-query -W -f='${Status}' "$package_name" 2>/dev/null | grep -q "^install ok installed$"; then | ||
checklist_options+=("$package_name" "$package_description" "ON") | ||
else | ||
checklist_options+=("$package_name" "$package_description" "OFF") | ||
fi | ||
fi | ||
done | ||
if [[ ${#checklist_options[@]} -eq 0 ]]; then | ||
echo "No $title packages found." | ||
return 1 | ||
fi | ||
|
||
process_package_selection "$title" "Select packages to install/remove:" checklist_options[@] | ||
} | ||
|
||
module_options+=( | ||
["_checklist_imaging,author"]="@Tearran" | ||
["_checklist_imaging,maintainer"]="@Tearran" | ||
["_checklist_imaging,feature"]="_checklist_imaging" | ||
["_checklist_imaging,example"]="inkscape gimp" | ||
["_checklist_imaging,desc"]="Imaging Editor installation and management (gimp inkscape)." | ||
["_checklist_imaging,status"]="Active" | ||
["_checklist_imaging,group"]="Internet" | ||
["_checklist_imaging,arch"]="x86-64 arm64 armhf" | ||
) | ||
# Scaffold for app with specific single or dummy candidates. | ||
function _checklist_imaging() { | ||
local title="Imaging" | ||
local self="${module_options["_checklist_imaging,feature"]}" | ||
local _packages | ||
IFS=' ' read -r -a _packages <<< "${module_options["$self,example"]}" | ||
|
||
# Manage editor installation/removal | ||
echo "Fetching $title package details..." | ||
|
||
# Prepare checklist options dynamically with descriptions | ||
local checklist_options=() | ||
for base_package in "${_packages[@]}"; do | ||
# Find the main package and exclude auxiliary or irrelevant ones | ||
local main_package | ||
main_package=$(apt-cache search "^${base_package}$" | awk -F' - ' '{print $1 " - " $2}') | ||
|
||
# Check if the main package exists and fetch its description | ||
if [[ -n "$main_package" ]]; then | ||
local package_name package_description | ||
package_name=$(echo "$main_package" | awk -F' - ' '{print $1}') | ||
package_description=$(echo "$main_package" | awk -F' - ' '{print $2}') | ||
|
||
# Check if the package is installed and set its state | ||
if dpkg-query -W -f='${Status}' "$package_name" 2>/dev/null | grep -q "^install ok installed$"; then | ||
checklist_options+=("$package_name" "$package_description" "ON") | ||
else | ||
checklist_options+=("$package_name" "$package_description" "OFF") | ||
fi | ||
fi | ||
done | ||
if [[ ${#checklist_options[@]} -eq 0 ]]; then | ||
echo "No $title packages found." | ||
return 1 | ||
fi | ||
|
||
process_package_selection "$title" "Select packages to install/remove:" checklist_options[@] | ||
} | ||
|
||
module_options+=( | ||
["module_aptwizard,author"]="@Tearran" | ||
["module_aptwizard,maintainer"]="@Tearran" | ||
["module_aptwizard,feature"]="module_aptwizard" | ||
["module_aptwizard,example"]="help Editors Browsers Proftpd Imaging" | ||
["module_aptwizard,desc"]="Apt wizard TUI deb packages similar to softy" | ||
["module_aptwizard,status"]="Active" | ||
["module_aptwizard,doc_link"]="" | ||
["module_aptwizard,group"]="aptwizard" | ||
["module_aptwizard,port"]="" | ||
["module_aptwizard,arch"]="x86-64 arm64 armhf" | ||
) | ||
# Scafold for software module tites | ||
function module_aptwizard() { | ||
local title="Packages" | ||
local self="${module_options["module_aptwizard,feature"]}" | ||
# Convert the example string to an array | ||
local commands | ||
IFS=' ' read -r -a commands <<< "${module_options["$self,example"]}" | ||
|
||
case "$1" in | ||
"${commands[0]}") | ||
## help/menu options for the module | ||
echo -e "\nUsage: $self <command>" | ||
echo -e "Commands: ${module_options["$self,example"]}" | ||
echo "Available commands:" | ||
# Loop through all commands (starting from index 1) | ||
for ((i = 1; i < ${#commands[@]}; i++)); do | ||
printf "\t%-10s - Manage %s %s\n" "${commands[i]}" "${commands[i]}" "$title" | ||
#echo -e "\t${commands[i]}\t- Manage ${commands[i]} $title." | ||
done | ||
echo | ||
;; | ||
"${commands[1]}") | ||
_checklist_editors | ||
;; | ||
"${commands[2]}") | ||
_checklist_browsers | ||
;; | ||
|
||
"${commands[3]}") | ||
_checklist_proftpd | ||
;; | ||
"${commands[4]}") | ||
_checklist_imaging | ||
;; | ||
*) | ||
echo "Invalid command. Try one of: ${module_options["$self,example"]}" | ||
|
||
;; | ||
esac | ||
} | ||
Tearran marked this conversation as resolved.
Show resolved
Hide resolved
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.