From dda8e408e8179619ce14f60bfd06883b7b8739d0 Mon Sep 17 00:00:00 2001 From: Nuno Duque Nunes Date: Wed, 27 May 2026 02:05:32 +0000 Subject: [PATCH 1/3] merge master --- core/lib/__pycache__/__init__.cpython-311.pyc | Bin 150 -> 150 bytes core/lib/__pycache__/peers.cpython-311.pyc | Bin 10998 -> 10998 bytes core/lib/__pycache__/util.cpython-311.pyc | Bin 11308 -> 11308 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/core/lib/__pycache__/__init__.cpython-311.pyc b/core/lib/__pycache__/__init__.cpython-311.pyc index ebc61115a5f7724d02970cc7b1142fbab51a1890..d0172e7196780f1163614bc668cb7a59e0ac3f10 100644 GIT binary patch delta 19 ZcmbQnIE|5eIWI340}zM@icRG11^^|J1F8T3 delta 19 ZcmbQnIE|5eIWI340}$*87n#W24FD-_1Wy0} diff --git a/core/lib/__pycache__/peers.cpython-311.pyc b/core/lib/__pycache__/peers.cpython-311.pyc index 38844356fd8567ceef74855ea61ceb9540bf5dda..074623fd2250b0eaea7686c611dc7fd62fa63fda 100644 GIT binary patch delta 20 acmews`Yn`uIWI340}zM@if!b6tpxx?wgtQZ delta 20 acmews`Yn`uIWI340}$*87um@DS_=S4HwIw< diff --git a/core/lib/__pycache__/util.cpython-311.pyc b/core/lib/__pycache__/util.cpython-311.pyc index 4e3a658cbcecd7f09b9fdf7710b5869675382e72..efefd09d482d18cdaa7e5e05085a4d047820f72a 100644 GIT binary patch delta 20 acmZ1zu_l6hIWI340}zM@if!ap)BylElmun~ delta 20 acmZ1zu_l6hIWI340}$*87um?Ir~?2!6$J|b From 7a544f90192e499ebf658005fd00b45a3f838827 Mon Sep 17 00:00:00 2001 From: Nuno Duque Nunes Date: Wed, 27 May 2026 02:48:51 +0000 Subject: [PATCH 2/3] feat: display config system, table/compact toggle - modules/display.module.sh: display config loader - .wgctl/config/display.json: per-view style configuration - ctx::display: points to .wgctl/config/display.json - json_helper: display_load() reads view styles - list: display::render dispatcher, _render_table with dynamic widths/colors - ui::peer::_row_color/status_color: shared by both table and compact - table layout: aligned columns, colored status/rows, dynamic separator --- commands/list.command.sh | 69 +++++++++++++++---- core/context.sh | 1 + core/json_helper.py | 17 +++++ core/lib/__pycache__/events.cpython-311.pyc | Bin 34012 -> 34012 bytes daemon/endpoint_cache.json | 4 +- modules/display.module.sh | 72 ++++++++++++++++++++ wgctl | 1 + 7 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 modules/display.module.sh diff --git a/commands/list.command.sh b/commands/list.command.sh index e4779f4..cfee902 100644 --- a/commands/list.command.sh +++ b/commands/list.command.sh @@ -226,8 +226,11 @@ function cmd::list::run() { case "$style" in table) cmd::list::_render_table ;; - compact) cmd::list::_render_compact "$collected_rows" ;; - *) cmd::list::_render_compact "$collected_rows" ;; + compact) display::render "peer_list" "$collected_rows" \ + "cmd::list::_render_compact" "cmd::list::_render_table" ;; + + *) display::render "peer_list" "$collected_rows" \ + "cmd::list::_render_compact" "cmd::list::_render_table" ;; esac } @@ -346,19 +349,59 @@ function cmd::list::_render_compact() { # ============================================ function cmd::list::_render_table() { - declare -A rule_counts=() group_counts=() - _list_header_printed=false + local rows="${1:-}" + [[ -z "$rows" ]] && log::wg_warning "No results found" && return 0 - cmd::list::_iter_confs_table + # Measure column widths from data (same as compact) + local w_name=16 w_ip=13 w_type=8 w_rule=10 w_group=10 w_status=10 w_last=20 + while IFS='|' read -r name ip type rule group status last_seen is_blocked is_restricted; do + [[ -z "$name" ]] && continue + (( ${#name} > w_name )) && w_name=${#name} + (( ${#ip} > w_ip )) && w_ip=${#ip} + (( ${#type} > w_type )) && w_type=${#type} + (( ${#rule} > w_rule )) && w_rule=${#rule} + (( ${#group} > w_group )) && w_group=${#group} + (( ${#last_seen} > w_last )) && w_last=${#last_seen} + local cs +cs=$(printf "%s" "$status" | sed 's/\x1b\[[0-9;]*m//g') +(( ${#cs} > w_status )) && w_status=${#cs} + echo "DEBUG cs='$cs' name='$name'" >&2 + done <<< "$rows" + (( w_name += 2 )); (( w_ip += 2 )) + (( w_type += 2 )); (( w_rule += 2 )) + (( w_group += 2 )); (( w_last += 2 )) - if [[ "$_list_header_printed" == "true" ]]; then - cmd::list::_render_footer $has_groups - local group_summary="" - cmd::list::_build_group_summary - printf "\n Showing peers\n\n" - else - log::wg_warning "No results found" - fi + # Header + printf "\n %-${w_name}s %-${w_ip}s %-${w_type}s %-${w_rule}s %-${w_group}s %-${w_status}s %s\n" \ + "NAME" "IP" "TYPE" "RULE" "GROUP" "STATUS" "LAST SEEN" + printf " %s\n" "$(printf '─%.0s' {1..115})" + + # Rows + while IFS='|' read -r name ip type rule group status last_seen is_blocked is_restricted; do + [[ -z "$name" ]] && continue + local clean_status + clean_status=$(echo "$status" | sed 's/\x1b\[[0-9;]*m//g') + local status_pad_n=$(( w_status - ${#clean_status} )) + [[ $status_pad_n -lt 0 ]] && status_pad_n=0 + + local row_color status_color + row_color=$(ui::peer::_row_color "$is_blocked" "$is_restricted" "$clean_status") + status_color=$(ui::peer::status_color "$is_blocked" "$is_restricted" "$clean_status") + + local status_colored="${status_color}${clean_status}\033[0m" + + if [[ -n "$row_color" ]]; then + printf " %b%-${w_name}s %-${w_ip}s %-${w_type}s %-${w_rule}s %-${w_group}s %-${w_status}s %s\033[0m\n" \ + "$row_color" "$name" "$ip" "$type" "$rule" "$group" "$clean_status" "$last_seen" + else + printf " %-${w_name}s %-${w_ip}s %-${w_type}s %-${w_rule}s %-${w_group}s %b%*s\033[0m %s\n" \ + "$name" "$ip" "$type" "$rule" "$group" \ + "$status_color${clean_status}" "$status_pad_n" "" "$last_seen" + fi + done <<< "$rows" + + printf " %s\n" "$(printf '─%.0s' {1..115})" + cmd::list::_render_summary_from_rows "$rows" } function cmd::list::_iter_confs_table() { diff --git a/core/context.sh b/core/context.sh index f14ea7e..811a9d2 100644 --- a/core/context.sh +++ b/core/context.sh @@ -74,6 +74,7 @@ function ctx::policies() { echo "$_CTX_POLICIES"; } # Config files function ctx::config_file() { echo "$_CTX_CONFIG_FILE"; } +function ctx::display() { echo "${_CTX_CONFIG}/display.json"; } # Daemon files function ctx::events_log() { echo "${_CTX_DAEMON}/events.log"; } diff --git a/core/json_helper.py b/core/json_helper.py index c5a5a21..972f1f5 100644 --- a/core/json_helper.py +++ b/core/json_helper.py @@ -1611,6 +1611,22 @@ def config_load(file): print(f"Error: {e}", file=sys.stderr) sys.exit(1) +def display_load(file): + """ + Load display.json and output view=style pairs. + Output: view_name=style per line + """ + try: + with open(file) as f: + d = json.load(f) + views = d.get('views', {}) + for view_name, view_config in views.items(): + style = view_config.get('style', 'compact') + print(f"{view_name}={style}") + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + # ====================================================== def _net_read(file): @@ -1981,6 +1997,7 @@ commands = { 'batch_resolve': lambda args: batch_resolve(args[0], args[1], *args[2:]), 'peer_history_lookup': lambda args: peer_history_lookup(args[0], args[1]), 'config_load': lambda args: config_load(args[0]), + 'display_load': lambda args: display_load(args[0]), } # ── Main ───────────────────────────────────────────────────────────────────── diff --git a/core/lib/__pycache__/events.cpython-311.pyc b/core/lib/__pycache__/events.cpython-311.pyc index 98fb0ac9f01e581380555951c72aace5f00d2cd5..42921bd633e05cd8a6616a02979c8533e9b924ea 100644 GIT binary patch delta 22 ccmcc9$#kcaiF-LOFBbz4hzE*o/dev/null) +} + +# ============================================ +# Accessors +# ============================================ + +# display::style +# Returns: compact | table | minimal (default: compact) +function display::style() { + local view="${1:-}" + display::_load + echo "${_DISPLAY_STYLES[$view]:-compact}" +} + +# display::is_compact +function display::is_compact() { + [[ "$(display::style "$1")" == "compact" ]] +} + +# display::is_table +function display::is_table() { + [[ "$(display::style "$1")" == "table" ]] +} + +# ============================================ +# display::render [extra_args...] +# Generic dispatcher — calls compact or table render function +# ============================================ + +function display::render() { + local view="${1:-}" data="${2:-}" compact_fn="${3:-}" table_fn="${4:-}" + shift 4 || true + + case "$(display::style "$view")" in + table) + declare -f "$table_fn" >/dev/null 2>&1 && \ + "$table_fn" "$data" "$@" || \ + "$compact_fn" "$data" "$@" # fallback to compact if no table fn + ;; + *) + "$compact_fn" "$data" "$@" + ;; + esac +} \ No newline at end of file diff --git a/wgctl b/wgctl index dbfdc82..919f79d 100755 --- a/wgctl +++ b/wgctl @@ -11,6 +11,7 @@ LOG_LEVEL=DEBUG load_module ip load_module ui +load_module display load_module config load_module keys load_module peers From 1a78dcf5da2a487638914593b7a88a55e8c5ec1c Mon Sep 17 00:00:00 2001 From: Nuno Duque Nunes Date: Wed, 27 May 2026 03:32:31 +0000 Subject: [PATCH 3/3] feat: display config, table layouts for all commands - display.module.sh: style toggle per view (compact/table) - display.json: default config with all views set to compact - ctx::display: points to .wgctl/config/display.json - list: _render_table with dynamic widths, colors, shared row_color/status_color - group/identity/net/hosts/activity: _render_table added - rule/subnet/policy: table UI functions + _render_table - ui::peer::status_color: \033[2m for offline (dimmer, more readable) - note: individual table layout refinements pending cleanup pass - note: configurable colors per field deferred to display config v2 --- commands/activity.command.sh | 35 +++++++++++++- commands/group.command.sh | 16 +++++++ commands/hosts.command.sh | 23 ++++----- commands/identity.command.sh | 22 ++++++++- commands/list.command.sh | 14 ++++-- commands/net.command.sh | 18 ++++++- commands/policy.command.sh | 18 +++++++ commands/rule.command.sh | 17 +++++++ commands/subnet.command.sh | 17 +++++++ core/lib/__pycache__/activity.cpython-311.pyc | Bin 7451 -> 7451 bytes modules/ui/peer.module.sh | 2 +- modules/ui/policy.module.sh | 45 ++++++++++++++++++ modules/ui/rule.module.sh | 18 +++++++ modules/ui/subnet.module.sh | 43 +++++++---------- 14 files changed, 241 insertions(+), 47 deletions(-) create mode 100644 modules/ui/policy.module.sh diff --git a/commands/activity.command.sh b/commands/activity.command.sh index 207286e..54e9002 100644 --- a/commands/activity.command.sh +++ b/commands/activity.command.sh @@ -143,7 +143,12 @@ function cmd::activity::run() { log::section "Activity Monitor (last ${hours_display})" echo "" - + + if display::is_table "activity"; then + cmd::activity::_render_table "$data" + return 0 + fi + local first_peer=true skip_peer=false while IFS='|' read -r record_type rest; do @@ -195,6 +200,34 @@ function cmd::activity::run() { echo "" } +function cmd::activity::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + ui::activity::header_table + local skip_peer=false + while IFS='|' read -r record_type rest; do + case "$record_type" in + peer) + local name rx tx drops + IFS='|' read -r name rx tx drops <<< "$rest" + skip_peer=false + local rx_fmt tx_fmt + rx_fmt=$(fmt::bytes "$rx") + tx_fmt=$(fmt::bytes "$tx") + ui::activity::peer_row_table "$name" "$rx_fmt" "$tx_fmt" "$drops" "" + ;; + service) + $skip_peer && continue + local peer dest count + IFS='|' read -r peer dest count <<< "$rest" + ui::activity::service_row_table "$dest" "$count" "drops" + ;; + esac + done <<< "$data" +} + + function cmd::activity::_output_json() { local hours="${1:-24}" local data diff --git a/commands/group.command.sh b/commands/group.command.sh index 7cd4751..fed88cc 100644 --- a/commands/group.command.sh +++ b/commands/group.command.sh @@ -147,6 +147,11 @@ function cmd::group::list() { log::section "Groups" echo "" + if display::is_table "group_list"; then + cmd::group::_render_table "$data" "$w_name" "$w_desc" + return 0 + fi + while IFS="|" read -r name desc total blocked; do [[ -z "$name" ]] && continue ui::group::list_row "$name" "$desc" "$total" "$blocked" "$w_name" "$w_desc" @@ -223,6 +228,17 @@ function cmd::group::show() { printf "\n" } +function cmd::group::_render_table() { + local data="${1:-}" w_name="${2:-20}" w_desc="${3:-20}" + [[ -z "$data" ]] && return 0 + + ui::group::list_header_table + while IFS='|' read -r name desc total blocked; do + [[ -z "$name" ]] && continue + ui::group::list_row_table "$name" "$desc" "$total" "$blocked" + done <<< "$data" +} + # ============================================ # Add # ============================================ diff --git a/commands/hosts.command.sh b/commands/hosts.command.sh index cd9e10c..8b9ebc9 100644 --- a/commands/hosts.command.sh +++ b/commands/hosts.command.sh @@ -146,6 +146,11 @@ function cmd::hosts::list() { log::section "Host Mappings" echo "" + if display::is_table "hosts_list"; then + cmd::hosts::_render_table "$data" + return 0 + fi + local last_type="" found=false while IFS='|' read -r type key name desc tags; do [[ -z "$type" ]] && continue @@ -167,19 +172,15 @@ function cmd::hosts::list() { echo "" } -# Table version (kept for future display config) -function cmd::hosts::_list_table() { - local hosts_file="${1:-}" - printf "\n %-6s %-18s %-16s %-30s %s\n" \ - "TYPE" "KEY" "NAME" "DESCRIPTION" "TAGS" - printf " %s\n" "$(printf '─%.0s' {1..80})" - +function cmd::hosts::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + ui::hosts::list_header_table while IFS='|' read -r type key name desc tags; do [[ -z "$type" ]] && continue - printf " %-6s %-18s %-16s %-30s %s\n" \ - "$type" "$key" "$name" "${desc:-—}" "${tags:-—}" - done < <(json::hosts_list "$hosts_file" 2>/dev/null) - printf "\n" + ui::hosts::list_row_table "$type" "$key" "$name" "$desc" "$tags" + done <<< "$data" } # ============================================ diff --git a/commands/identity.command.sh b/commands/identity.command.sh index 3f4517f..bf92ebc 100644 --- a/commands/identity.command.sh +++ b/commands/identity.command.sh @@ -111,7 +111,12 @@ function cmd::identity::_list() { log::info "No identities found. Run 'wgctl identity migrate' to create from existing peers." return 0 fi - + + if display::is_table "identity_list"; then + cmd::identity::_render_table "$data" + return 0 + fi + echo "" while IFS='|' read -r name peer_count types rules policy; do local rules_display @@ -185,6 +190,21 @@ function cmd::identity::_show() { echo "" } +function cmd::identity::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + printf "\n %-20s %-8s %-20s %s\n" "NAME" "PEERS" "RULES" "POLICY" + printf " %s\n" "$(printf '─%.0s' {1..65})" + while IFS='|' read -r name peer_count types rules policy; do + [[ -z "$name" ]] && continue + local rules_display + rules_display=$(echo "$rules" | sed 's/,/, /g') + ui::identity::list_row_table "$name" "$peer_count" "$rules_display" "$policy" + done <<< "$data" + printf " %s\n\n" "$(printf '─%.0s' {1..65})" +} + function cmd::identity::_device_status() { local peer_name="${1:-}" local -n _handshakes="${2:-__empty_map}" diff --git a/commands/list.command.sh b/commands/list.command.sh index cfee902..eedade9 100644 --- a/commands/list.command.sh +++ b/commands/list.command.sh @@ -363,9 +363,8 @@ function cmd::list::_render_table() { (( ${#group} > w_group )) && w_group=${#group} (( ${#last_seen} > w_last )) && w_last=${#last_seen} local cs -cs=$(printf "%s" "$status" | sed 's/\x1b\[[0-9;]*m//g') -(( ${#cs} > w_status )) && w_status=${#cs} - echo "DEBUG cs='$cs' name='$name'" >&2 + cs=$(printf "%s" "$status" | sed 's/\x1b\[[0-9;]*m//g') + (( ${#cs} > w_status )) && w_status=${#cs} done <<< "$rows" (( w_name += 2 )); (( w_ip += 2 )) (( w_type += 2 )); (( w_rule += 2 )) @@ -390,13 +389,18 @@ cs=$(printf "%s" "$status" | sed 's/\x1b\[[0-9;]*m//g') local status_colored="${status_color}${clean_status}\033[0m" + local last_seen_colored="$last_seen" + [[ -n "$row_color" ]] && last_seen_colored="${row_color}${last_seen}\033[0m" \ + || last_seen_colored="${status_color}${last_seen}\033[0m" + if [[ -n "$row_color" ]]; then printf " %b%-${w_name}s %-${w_ip}s %-${w_type}s %-${w_rule}s %-${w_group}s %-${w_status}s %s\033[0m\n" \ "$row_color" "$name" "$ip" "$type" "$rule" "$group" "$clean_status" "$last_seen" else - printf " %-${w_name}s %-${w_ip}s %-${w_type}s %-${w_rule}s %-${w_group}s %b%*s\033[0m %s\n" \ + printf " %-${w_name}s %-${w_ip}s %-${w_type}s %-${w_rule}s %-${w_group}s %b%*s\033[0m %b\n" \ "$name" "$ip" "$type" "$rule" "$group" \ - "$status_color${clean_status}" "$status_pad_n" "" "$last_seen" + "$status_color${clean_status}" "$status_pad_n" "" \ + "$last_seen_colored" fi done <<< "$rows" diff --git a/commands/net.command.sh b/commands/net.command.sh index b36ed01..66f531a 100644 --- a/commands/net.command.sh +++ b/commands/net.command.sh @@ -129,7 +129,7 @@ function cmd::net::list() { log::wg_warning "No services configured" return 0 } - + # Measure column widths local w_name=12 w_ip=13 w_ports=16 while IFS="|" read -r name ip desc tags ports; do @@ -144,6 +144,11 @@ function cmd::net::list() { log::section "Network Services" echo "" + + if display::is_table "net_list"; then + cmd::net::_render_table "$filtered_data" + return 0 + fi while IFS="|" read -r name ip desc tags ports; do [[ -z "$name" ]] && continue @@ -162,6 +167,17 @@ function cmd::net::list() { echo "" } +function cmd::net::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + ui::net::list_header_table + while IFS='|' read -r name ip desc tags port_count; do + [[ -z "$name" ]] && continue + ui::net::list_row_table "$name" "$ip" "$desc" "$tags" "$port_count" + done <<< "$data" +} + # ============================================ # Show # ============================================ diff --git a/commands/policy.command.sh b/commands/policy.command.sh index db2927a..82ee741 100644 --- a/commands/policy.command.sh +++ b/commands/policy.command.sh @@ -113,6 +113,11 @@ function cmd::policy::_list() { return 0 fi + if display::is_table "policy_list"; then + cmd::policy::_render_table "$data" + return 0 + fi + echo "" while IFS='|' read -r name tunnel default_rule strict auto desc; do ui::policy::list_row "$name" "$default_rule" "$strict" "$auto" @@ -120,6 +125,19 @@ function cmd::policy::_list() { echo "" } +function cmd::policy::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + ui::policy::list_header_table + while IFS='|' read -r name tunnel default_rule strict auto desc; do + [[ -z "$name" ]] && continue + ui::policy::list_row_table "$name" "$tunnel" "$default_rule" "$strict" "$auto" + done <<< "$data" + printf "\n" +} + + function cmd::policy::_show() { local name="" while [[ $# -gt 0 ]]; do diff --git a/commands/rule.command.sh b/commands/rule.command.sh index e5b2611..46ecf1b 100644 --- a/commands/rule.command.sh +++ b/commands/rule.command.sh @@ -181,6 +181,11 @@ function cmd::rule::list() { log::section "Firewall Rules" echo "" + if display::is_table "rule_list"; then + cmd::rule::_render_table "$data" + return 0 + fi + local current_group="" printing_base=false found_any=false while IFS="|" read -r name desc n_allows n_blocks \ @@ -240,6 +245,18 @@ function cmd::rule::list() { echo "" } +function cmd::rule::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + ui::rule::list_header_table + while IFS='|' read -r name desc n_allows n_blocks peer_count extends is_base group; do + [[ -z "$name" ]] && continue + ui::rule::list_row_table "$name" "$n_allows" "$n_blocks" "$peer_count" "$extends" "$group" + done <<< "$data" + printf "\n" +} + # ============================================ # Show # ============================================ diff --git a/commands/subnet.command.sh b/commands/subnet.command.sh index af7e494..40b1f63 100644 --- a/commands/subnet.command.sh +++ b/commands/subnet.command.sh @@ -99,6 +99,11 @@ function cmd::subnet::_list() { return 0 fi + if display::is_table "subnet_list"; then + cmd::subnet::_render_table "$data" + return 0 + fi + echo "" local prev_group="" while IFS='|' read -r display_name subnet type_key tunnel_mode desc is_group group_parent; do @@ -120,6 +125,18 @@ function cmd::subnet::_list() { echo "" } +function cmd::subnet::_render_table() { + local data="${1:-}" + [[ -z "$data" ]] && return 0 + + ui::subnet::list_header_table + while IFS='|' read -r type cidr display_name tunnel desc is_group group_parent; do + [[ -z "$type" ]] && continue + ui::subnet::list_row_table "$type" "$cidr" "$tunnel" "$desc" + done <<< "$data" + printf "\n" +} + function cmd::subnet::_maybe_group_separator() { local is_group="${1:-}" group_parent="${2:-}" prev_group="${3:-}" if [[ "$is_group" == "true" && "$group_parent" != "$prev_group" && -n "$prev_group" ]]; then diff --git a/core/lib/__pycache__/activity.cpython-311.pyc b/core/lib/__pycache__/activity.cpython-311.pyc index 847be3c4df7505a05d73df7843d73494f2484f1e..418761117b7ce11fd5e7754b6234ee9b25f6d17d 100644 GIT binary patch delta 20 acmbPjHQS1NIWI340}zM@if!Z;kOcrSr32^y delta 20 acmbPjHQS1NIWI340}$*87um=yAPWFCCIpQD diff --git a/modules/ui/peer.module.sh b/modules/ui/peer.module.sh index 34d378d..c58ab6c 100644 --- a/modules/ui/peer.module.sh +++ b/modules/ui/peer.module.sh @@ -31,7 +31,7 @@ function ui::peer::status_color() { elif [[ "$status" == "online"* ]]; then echo "\033[1;32m" else - echo "\033[2;37m" + echo "\033[2m" fi } diff --git a/modules/ui/policy.module.sh b/modules/ui/policy.module.sh new file mode 100644 index 0000000..a1c93bc --- /dev/null +++ b/modules/ui/policy.module.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +function ui::policy::list_row() { + local name="${1:-}" default_rule="${2:-}" strict="${3:-}" auto="${4:-}" + + local rule_val="-" + [[ -n "$default_rule" ]] && rule_val="$default_rule" + + local rule_padded + rule_padded=$(printf "%-16s" "$rule_val") + + local strict_display + [[ "$strict" == "true" ]] && strict_display="yes" || strict_display="no" + local strict_padded + strict_padded=$(printf "%-4s" "$strict_display") + + local auto_display="" + [[ "$auto" == "false" ]] && auto_display=" \033[2mauto:\033[0m no" + + printf " %-14s \033[2mrule:\033[0m %s \033[2mstrict:\033[0m %s%s\n" \ + "$name" "$rule_padded" "$strict_padded" "$auto_display" +} + +function ui::policy::detail_field() { + local key="${1:-}" value="${2:-}" + ui::row "$key" "$value" +} + +# ====================================================== +# Table view +# ====================================================== + +function ui::policy::list_header_table() { + printf "\n %-16s %-8s %-14s %-8s %s\n" \ + "NAME" "TUNNEL" "DEFAULT RULE" "STRICT" "AUTO" + printf " %s\n" "$(printf '─%.0s' {1..60})" +} + +function ui::policy::list_row_table() { + local name="${1:-}" tunnel="${2:-}" default_rule="${3:-}" \ + strict="${4:-}" auto="${5:-}" + printf " %-16s %-8s %-14s %-8s %s\n" \ + "$name" "$tunnel" "${default_rule:--}" "$strict" "$auto" +} + \ No newline at end of file diff --git a/modules/ui/rule.module.sh b/modules/ui/rule.module.sh index 8a9dc57..558d154 100644 --- a/modules/ui/rule.module.sh +++ b/modules/ui/rule.module.sh @@ -392,6 +392,24 @@ function ui::rule::list_extends_detailed() { done } +# ====================================================== +# Table view +# ====================================================== + +function ui::rule::list_header_table() { + printf "\n %-20s %-6s %-6s %-8s %-20s %s\n" \ + "NAME" "ALLOW" "BLOCK" "PEERS" "EXTENDS" "GROUP" + printf " %s\n" "$(printf '─%.0s' {1..75})" +} + +function ui::rule::list_row_table() { + local name="${1:-}" n_allows="${2:-0}" n_blocks="${3:-0}" \ + peer_count="${4:-0}" extends="${5:-}" group="${6:-}" + printf " %-20s %-6s %-6s %-8s %-20s %s\n" \ + "$name" "+${n_allows}" "-${n_blocks}" "$peer_count" \ + "${extends:--}" "${group:--}" +} + # ====================================================== # Show helpers # ====================================================== diff --git a/modules/ui/subnet.module.sh b/modules/ui/subnet.module.sh index 9c7d9c5..0f528ce 100644 --- a/modules/ui/subnet.module.sh +++ b/modules/ui/subnet.module.sh @@ -8,33 +8,6 @@ function ui::subnet::header() { ui::divider 70 } -function ui::policy::list_row() { - local name="${1:-}" default_rule="${2:-}" strict="${3:-}" auto="${4:-}" - - local rule_val="-" - [[ -n "$default_rule" ]] && rule_val="$default_rule" - - local rule_padded - rule_padded=$(printf "%-16s" "$rule_val") - - local strict_display - [[ "$strict" == "true" ]] && strict_display="yes" || strict_display="no" - local strict_padded - strict_padded=$(printf "%-4s" "$strict_display") - - local auto_display="" - [[ "$auto" == "false" ]] && auto_display=" \033[2mauto:\033[0m no" - - printf " %-14s \033[2mrule:\033[0m %s \033[2mstrict:\033[0m %s%s\n" \ - "$name" "$rule_padded" "$strict_padded" "$auto_display" -} - -function ui::policy::detail_field() { - local key="${1:-}" value="${2:-}" - ui::row "$key" "$value" -} - - function ui::subnet::row() { local display_name="${1:-}" subnet="${2:-}" type_key="${3:-}" \ tunnel_mode="${4:-}" desc="${5:-}" is_group="${6:-false}" @@ -210,4 +183,20 @@ function ui::subnet::show_peers_annotated() { for peer in "${no_identity[@]}"; do printf " · %b\n" "$peer" done +} + +# ====================================================== +# Table view +# ====================================================== + +function ui::subnet::list_header_table() { + printf "\n %-14s %-20s %-8s %s\n" \ + "TYPE" "CIDR" "TUNNEL" "DESCRIPTION" + printf " %s\n" "$(printf '─%.0s' {1..65})" +} + +function ui::subnet::list_row_table() { + local type="${1:-}" cidr="${2:-}" tunnel="${3:-}" desc="${4:-}" + printf " %-14s %-20s %-8s %s\n" \ + "$type" "$cidr" "$tunnel" "${desc:--}" } \ No newline at end of file