Merge branch 'view-ui'

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
abrown38andClaude Opus 5.5 committed 2026-10-09 15:17:49 +00:00
commit ca0f148b78
29 files changed
+623 -55

No files matched your search

+3
View File
@@ -15,6 +15,7 @@ import (
"github.com/spf13/cobra"
"jarl/internal/api"
"jarl/internal/model"
"jarl/internal/rr"
)
@@ -71,6 +72,8 @@ func argCompletion(c *cobra.Command) cobra.CompletionFunc {
return lookup(cmd, "zone")
case p == "VIEW":
return lookup(cmd, "view")
case p == "COLOR":
return append([]string{"default"}, model.ViewColors...), cobra.ShellCompDirectiveNoFileComp
case p == "ACL":
return lookup(cmd, "acl")
case p == "USER":
+39 -3
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"io"
"net/url"
"slices"
"strings"
"github.com/spf13/cobra"
@@ -27,9 +28,9 @@ func viewCmd() *cobra.Command {
return err
}
return output(views, func(w io.Writer) {
fmt.Fprintln(w, "#\tID\tVIEW\tMATCH-CLIENTS\tMATCH-DESTINATIONS\tZONES")
fmt.Fprintln(w, "#\tID\tVIEW\tMATCH-CLIENTS\tMATCH-DESTINATIONS\tZONES\tCOLOR")
for i, v := range views {
fmt.Fprintf(w, "%d\t%d\t%s\t%s\t%s\t%d\n", i+1, v.ID, v.Name, orAny(v.MatchClients), orAny(v.MatchDestinations), v.Zones)
fmt.Fprintf(w, "%d\t%d\t%s\t%s\t%s\t%d\t%s\n", i+1, v.ID, v.Name, orAny(v.MatchClients), orAny(v.MatchDestinations), v.Zones, orDefault(v.Color))
}
})
},
@@ -172,10 +173,45 @@ func viewCmd() *cobra.Command {
return report(resp)
},
}
cmd.AddCommand(list, create, update, del, order)
color := &cobra.Command{
Use: "color VIEW COLOR",
Short: "Set the colour the web UI shows a view in",
Long: "Set the colour the web UI shows a view in, so zones of the same view are easy to spot.\n" +
"Colours: default (the link colour), " + strings.Join(model.ViewColors, ", ") + ".\n" +
"This only changes the web UI: it applies at once, with no changeset or deploy.",
Example: ` jarl view color internal green
jarl view color internal default`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
c, err := newClient()
if err != nil {
return err
}
col := strings.ToLower(args[1])
if col == "default" {
col = ""
} else if !slices.Contains(model.ViewColors, col) {
return fmt.Errorf("unknown colour %q: use default, %s", args[1], strings.Join(model.ViewColors, ", "))
}
var v api.View
if err := c.Do(ctx(), "PUT", "/views/"+url.PathEscape(args[0])+"/color", nil, api.ViewColor{Color: col}, &v); err != nil {
return err
}
fmt.Printf("View %s: colour %s\n", v.Name, orDefault(v.Color))
return nil
},
}
cmd.AddCommand(list, create, update, del, order, color)
return cmd
}
func orDefault(s string) string {
if s == "" {
return "default"
}
return s
}
func orAny(list []string) string {
if len(list) == 0 {
return "any"
+1 -1
View File
@@ -225,7 +225,7 @@ Exit codes: 0 ok, 1 error, 3 not authenticated or not allowed, 4 not found,
5 conflict, 6 invalid or rejected by validation, 7 server or BIND error.`,
SilenceUsage: true,
SilenceErrors: true,
Version: version.Version,
Version: version.String(),
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return checkFanOut(cmd)
},