mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-21 23:35:09 +00:00
feat(easy-docker): add production stack wizard flow and modularize tui screens
This commit is contained in:
parent
c2c90e62aa
commit
37122d20c1
5 changed files with 374 additions and 64 deletions
|
|
@ -1,14 +1,95 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
get_easy_docker_repo_root() {
|
||||||
|
local app_lib_dir=""
|
||||||
|
app_lib_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
(cd "${app_lib_dir}/../../../.." && pwd)
|
||||||
|
}
|
||||||
|
|
||||||
|
get_easy_docker_stacks_dir() {
|
||||||
|
printf '%s/.easy-docker/stacks\n' "$(get_easy_docker_repo_root)"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_valid_stack_name() {
|
||||||
|
local stack_name="${1}"
|
||||||
|
|
||||||
|
if [ -z "${stack_name}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${stack_name}" in
|
||||||
|
*[!A-Za-z0-9._-]*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
create_stack_env_file() {
|
||||||
|
local result_var="${1}"
|
||||||
|
local stack_name="${2}"
|
||||||
|
local stacks_dir=""
|
||||||
|
local env_path=""
|
||||||
|
|
||||||
|
stacks_dir="$(get_easy_docker_stacks_dir)"
|
||||||
|
env_path="${stacks_dir}/${stack_name}.env"
|
||||||
|
|
||||||
|
if ! mkdir -p "${stacks_dir}"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "${env_path}" ]; then
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
: >"${env_path}"
|
||||||
|
|
||||||
|
printf -v "${result_var}" "%s" "${env_path}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_stack_name_with_cancel() {
|
||||||
|
local result_var="${1}"
|
||||||
|
local input_value=""
|
||||||
|
local input_status=0
|
||||||
|
|
||||||
|
input_value="$(prompt_new_stack_name)"
|
||||||
|
input_status=$?
|
||||||
|
if [ "${input_status}" -ne 0 ]; then
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
input_value="$(printf '%s' "${input_value}" | tr -d '\r\n')"
|
||||||
|
|
||||||
|
case "${input_value}" in
|
||||||
|
/cancel | /CANCEL | /Cancel)
|
||||||
|
return 3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf -v "${result_var}" "%s" "${input_value}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
run_easy_docker_app() {
|
run_easy_docker_app() {
|
||||||
local action=""
|
local action=""
|
||||||
local local_env_action=""
|
local local_env_action=""
|
||||||
|
local local_production_action=""
|
||||||
|
local local_production_sub_action=""
|
||||||
|
local stack_name=""
|
||||||
|
local stack_env_path=""
|
||||||
|
local create_stack_status=0
|
||||||
|
local stack_input_status=0
|
||||||
|
|
||||||
enter_alt_screen
|
enter_alt_screen
|
||||||
render_main_screen 1
|
render_main_screen 1
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
local_env_action=""
|
local_env_action=""
|
||||||
|
local_production_action=""
|
||||||
|
local_production_sub_action=""
|
||||||
action="$(show_main_menu || true)"
|
action="$(show_main_menu || true)"
|
||||||
|
|
||||||
if [ -z "${action}" ]; then
|
if [ -z "${action}" ]; then
|
||||||
|
|
@ -16,6 +97,96 @@ run_easy_docker_app() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "${action}" in
|
case "${action}" in
|
||||||
|
"Production setup")
|
||||||
|
while true; do
|
||||||
|
local_production_action="$(show_production_setup_menu || true)"
|
||||||
|
case "${local_production_action}" in
|
||||||
|
"Create new stack")
|
||||||
|
while true; do
|
||||||
|
stack_name=""
|
||||||
|
if ! prompt_stack_name_with_cancel stack_name; then
|
||||||
|
stack_input_status=$?
|
||||||
|
if [ "${stack_input_status}" -eq 3 ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
show_warning_message "Input canceled."
|
||||||
|
sleep 1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${stack_name}" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! is_valid_stack_name "${stack_name}"; then
|
||||||
|
show_warning_message "Invalid stack name. Use letters, numbers, dot, underscore, or hyphen."
|
||||||
|
sleep 2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
stack_env_path=""
|
||||||
|
if create_stack_env_file stack_env_path "${stack_name}"; then
|
||||||
|
local_production_sub_action="$(show_create_stack_created "${stack_name}" "${stack_env_path}" || true)"
|
||||||
|
else
|
||||||
|
create_stack_status=$?
|
||||||
|
if [ "${create_stack_status}" -eq 2 ]; then
|
||||||
|
show_warning_message "Stack already exists: ${stack_name}"
|
||||||
|
sleep 2
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
show_warning_message "Could not create stack env file for: ${stack_name}"
|
||||||
|
sleep 2
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${local_production_sub_action}" in
|
||||||
|
"Continue stack wizard")
|
||||||
|
show_warning_message "Next wizard step is coming soon."
|
||||||
|
sleep 2
|
||||||
|
;;
|
||||||
|
"Back to production setup" | "") ;;
|
||||||
|
*)
|
||||||
|
show_warning_message "Unknown create-stack action: ${local_production_sub_action}"
|
||||||
|
sleep 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
"Manage existing stacks")
|
||||||
|
local_production_sub_action="$(show_manage_stacks_placeholder || true)"
|
||||||
|
case "${local_production_sub_action}" in
|
||||||
|
"Back to production setup") ;;
|
||||||
|
"Back to main menu" | "")
|
||||||
|
render_main_screen 1
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"Exit and close easy-docker")
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
show_warning_message "Unknown manage-stacks action: ${local_production_sub_action}"
|
||||||
|
sleep 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
"Back to main menu" | "")
|
||||||
|
render_main_screen 1
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"Exit and close easy-docker")
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
show_warning_message "Unknown production action: ${local_production_action}"
|
||||||
|
sleep 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
;;
|
||||||
"Environment check")
|
"Environment check")
|
||||||
local_env_action="$(show_environment_status || true)"
|
local_env_action="$(show_environment_status || true)"
|
||||||
case "${local_env_action}" in
|
case "${local_env_action}" in
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,15 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
render_main_screen() {
|
load_ui_screen_modules() {
|
||||||
local clear_screen="${1:-0}"
|
local screens_dir=""
|
||||||
local header_text=""
|
screens_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/screens"
|
||||||
|
|
||||||
if [ "${clear_screen}" = "1" ]; then
|
# shellcheck source=scripts/easy-docker/lib/ui/screens/base.sh
|
||||||
clear
|
source "${screens_dir}/base.sh"
|
||||||
fi
|
# shellcheck source=scripts/easy-docker/lib/ui/screens/production.sh
|
||||||
|
source "${screens_dir}/production.sh"
|
||||||
header_text="$(printf "Easy Frappe Docker\nManage Docker setups quickly and easily")"
|
# shellcheck source=scripts/easy-docker/lib/ui/screens/environment.sh
|
||||||
|
source "${screens_dir}/environment.sh"
|
||||||
gum style \
|
|
||||||
--border rounded \
|
|
||||||
--border-foreground 63 \
|
|
||||||
--padding "1 2" \
|
|
||||||
--margin "1 2" \
|
|
||||||
--foreground 252 \
|
|
||||||
"${header_text}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
show_main_menu() {
|
load_ui_screen_modules
|
||||||
gum choose \
|
|
||||||
--height 7 \
|
|
||||||
--header "Choose an action" \
|
|
||||||
--cursor.foreground 63 \
|
|
||||||
--selected.foreground 45 \
|
|
||||||
"Environment check" \
|
|
||||||
"Exit"
|
|
||||||
}
|
|
||||||
|
|
||||||
show_environment_status() {
|
|
||||||
local docker_status="not installed"
|
|
||||||
local docker_daemon_status="not running"
|
|
||||||
local status_text=""
|
|
||||||
|
|
||||||
if command_exists docker; then
|
|
||||||
docker_status="installed"
|
|
||||||
|
|
||||||
if docker_daemon_running; then
|
|
||||||
docker_daemon_status="running"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
render_main_screen 1 >&2
|
|
||||||
|
|
||||||
status_text="$(printf "Environment status\n\n- docker: %s\n- docker daemon: %s" "${docker_status}" "${docker_daemon_status}")"
|
|
||||||
|
|
||||||
gum style \
|
|
||||||
--border rounded \
|
|
||||||
--border-foreground 63 \
|
|
||||||
--padding "1 2" \
|
|
||||||
--margin "0 2" \
|
|
||||||
--foreground 252 \
|
|
||||||
"${status_text}" >&2
|
|
||||||
|
|
||||||
gum choose \
|
|
||||||
--height 6 \
|
|
||||||
--header "Environment actions" \
|
|
||||||
--cursor.foreground 63 \
|
|
||||||
--selected.foreground 45 \
|
|
||||||
"Back to main menu" \
|
|
||||||
"Exit and close easy-docker"
|
|
||||||
}
|
|
||||||
|
|
||||||
show_warning_message() {
|
|
||||||
local message="${1}"
|
|
||||||
gum style --foreground 214 "${message}"
|
|
||||||
}
|
|
||||||
|
|
|
||||||
89
scripts/easy-docker/lib/ui/screens/base.sh
Executable file
89
scripts/easy-docker/lib/ui/screens/base.sh
Executable file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
get_terminal_cols() {
|
||||||
|
local cols="80"
|
||||||
|
|
||||||
|
if command_exists tput; then
|
||||||
|
cols="$(tput cols 2>/dev/null || printf "80")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ "${cols}" =~ ^[0-9]+$ ]] || [ "${cols}" -le 0 ]; then
|
||||||
|
cols="80"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s\n' "${cols}"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_box_wrap_width() {
|
||||||
|
local cols=""
|
||||||
|
local width=""
|
||||||
|
|
||||||
|
cols="$(get_terminal_cols)"
|
||||||
|
width="$((cols - 16))"
|
||||||
|
|
||||||
|
if [ "${width}" -lt 12 ]; then
|
||||||
|
width="12"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s\n' "${width}"
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap_box_text() {
|
||||||
|
local raw_text="${1}"
|
||||||
|
local wrap_width=""
|
||||||
|
|
||||||
|
wrap_width="$(get_box_wrap_width)"
|
||||||
|
|
||||||
|
if command_exists fold; then
|
||||||
|
printf '%s' "${raw_text}" | fold -s -w "${wrap_width}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s' "${raw_text}"
|
||||||
|
}
|
||||||
|
|
||||||
|
render_box_message() {
|
||||||
|
local raw_text="${1}"
|
||||||
|
local margin="${2:-0 2}"
|
||||||
|
local padding="${3:-0 1}"
|
||||||
|
local wrapped_text=""
|
||||||
|
|
||||||
|
wrapped_text="$(wrap_box_text "${raw_text}")"
|
||||||
|
|
||||||
|
gum style \
|
||||||
|
--border rounded \
|
||||||
|
--border-foreground 63 \
|
||||||
|
--padding "${padding}" \
|
||||||
|
--margin "${margin}" \
|
||||||
|
--foreground 252 \
|
||||||
|
"${wrapped_text}"
|
||||||
|
}
|
||||||
|
|
||||||
|
render_main_screen() {
|
||||||
|
local clear_screen="${1:-0}"
|
||||||
|
local header_text=""
|
||||||
|
|
||||||
|
if [ "${clear_screen}" = "1" ]; then
|
||||||
|
clear
|
||||||
|
fi
|
||||||
|
|
||||||
|
header_text="$(printf "Easy Frappe Docker\nManage Docker setups quickly and easily")"
|
||||||
|
|
||||||
|
render_box_message "${header_text}" "1 2" "0 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_main_menu() {
|
||||||
|
gum choose \
|
||||||
|
--height 7 \
|
||||||
|
--header "Choose an action" \
|
||||||
|
--cursor.foreground 63 \
|
||||||
|
--selected.foreground 45 \
|
||||||
|
"Production setup" \
|
||||||
|
"Environment check" \
|
||||||
|
"Exit"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_warning_message() {
|
||||||
|
local message="${1}"
|
||||||
|
gum style --foreground 214 "${message}"
|
||||||
|
}
|
||||||
29
scripts/easy-docker/lib/ui/screens/environment.sh
Executable file
29
scripts/easy-docker/lib/ui/screens/environment.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
show_environment_status() {
|
||||||
|
local docker_status="not installed"
|
||||||
|
local docker_daemon_status="not running"
|
||||||
|
local status_text=""
|
||||||
|
|
||||||
|
if command_exists docker; then
|
||||||
|
docker_status="installed"
|
||||||
|
|
||||||
|
if docker_daemon_running; then
|
||||||
|
docker_daemon_status="running"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
render_main_screen 1 >&2
|
||||||
|
|
||||||
|
status_text="$(printf "Environment status\n\n- docker: %s\n- docker daemon: %s" "${docker_status}" "${docker_daemon_status}")"
|
||||||
|
|
||||||
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
|
gum choose \
|
||||||
|
--height 6 \
|
||||||
|
--header "Environment actions" \
|
||||||
|
--cursor.foreground 63 \
|
||||||
|
--selected.foreground 45 \
|
||||||
|
"Back to main menu" \
|
||||||
|
"Exit and close easy-docker"
|
||||||
|
}
|
||||||
75
scripts/easy-docker/lib/ui/screens/production.sh
Executable file
75
scripts/easy-docker/lib/ui/screens/production.sh
Executable file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
show_production_setup_menu() {
|
||||||
|
local status_text=""
|
||||||
|
|
||||||
|
render_main_screen 1 >&2
|
||||||
|
|
||||||
|
status_text="$(printf "Production setup\n\nChoose whether to create a new stack or manage an existing one.")"
|
||||||
|
|
||||||
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
|
gum choose \
|
||||||
|
--height 8 \
|
||||||
|
--header "Production setup actions" \
|
||||||
|
--cursor.foreground 63 \
|
||||||
|
--selected.foreground 45 \
|
||||||
|
"Create new stack" \
|
||||||
|
"Manage existing stacks" \
|
||||||
|
"Back to main menu" \
|
||||||
|
"Exit and close easy-docker"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_new_stack_name() {
|
||||||
|
local status_text=""
|
||||||
|
|
||||||
|
render_main_screen 1 >&2
|
||||||
|
|
||||||
|
status_text="$(printf "Create new stack\n\nEnter a stack name.\nType /cancel or press Ctrl+C to abort.")"
|
||||||
|
|
||||||
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
|
gum input \
|
||||||
|
--header "Stack name (/cancel to abort)" \
|
||||||
|
--prompt "name> " \
|
||||||
|
--placeholder "my-production-stack"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_create_stack_created() {
|
||||||
|
local stack_name="${1}"
|
||||||
|
local env_path="${2}"
|
||||||
|
local status_text=""
|
||||||
|
|
||||||
|
render_main_screen 1 >&2
|
||||||
|
|
||||||
|
status_text="$(printf "Create new stack\n\nStack created: %s\nEnv file: %s" "${stack_name}" "${env_path}")"
|
||||||
|
|
||||||
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
|
gum choose \
|
||||||
|
--height 6 \
|
||||||
|
--header "Create stack actions" \
|
||||||
|
--cursor.foreground 63 \
|
||||||
|
--selected.foreground 45 \
|
||||||
|
"Continue stack wizard" \
|
||||||
|
"Back to production setup"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_manage_stacks_placeholder() {
|
||||||
|
local status_text=""
|
||||||
|
|
||||||
|
render_main_screen 1 >&2
|
||||||
|
|
||||||
|
status_text="$(printf "Manage existing stacks")"
|
||||||
|
|
||||||
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
|
gum choose \
|
||||||
|
--height 7 \
|
||||||
|
--header "Manage stacks actions" \
|
||||||
|
--cursor.foreground 63 \
|
||||||
|
--selected.foreground 45 \
|
||||||
|
"Back to production setup" \
|
||||||
|
"Back to main menu" \
|
||||||
|
"Exit and close easy-docker"
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue