| 1 | diff --git a/internal/webui/agents_test.go b/internal/webui/agents_test.go |
| 2 | index 248124b..5f3154b 100644 |
| 3 | --- a/internal/webui/agents_test.go |
| 4 | +++ b/internal/webui/agents_test.go |
| 5 | @@ -27,6 +27,7 @@ var ( |
| 6 | |
| 7 | func (b *agentsBackend) Query(_ context.Context, method string, params []json.RawMessage, actor string) (any, error) { |
| 8 | b.calls = append(b.calls, method+":"+actor) |
| 9 | + b.params = params |
| 10 | owner := b.policy.Owner |
| 11 | now := time.Now().Unix() |
| 12 | scope := func(rooms []string, repos []map[string]any, wiki string, kinds []int) map[string]any { |
| 13 | @@ -121,6 +122,9 @@ func TestAgentsPageRendersTableCardsActivityAndGrantForm(t *testing.T) { |
| 14 | if got := strings.Join(backend.calls, " "); got != "listagents:"+backend.policy.Owner+" browseagent:"+backend.policy.Owner { |
| 15 | t.Fatalf("backend calls = %s", got) |
| 16 | } |
| 17 | + if !strings.Contains(string(backend.params[0]), agentActive) { |
| 18 | + t.Fatalf("default selection should be the first active agent: %s", backend.params[0]) |
| 19 | + } |
| 20 | // ?agent= selects whose activity shows. |
| 21 | backend.calls = nil |
| 22 | recorder = httptest.NewRecorder() |
| 23 | diff --git a/internal/webui/manage.html b/internal/webui/manage.html |
| 24 | index 92f9d41..d2c149c 100644 |
| 25 | --- a/internal/webui/manage.html |
| 26 | +++ b/internal/webui/manage.html |
| 27 | @@ -41,7 +41,7 @@ |
| 28 | <agent-card id="agent-{{$pk}}"> |
| 29 | <h3>{{agentLabel $a}} <small><span data-state="{{$state}}">{{$state}}</span> | signed by {{if eq (str (index $a "owner")) $.Actor}}you{{else}}{{template "nostrKey" (str (index $a "owner"))}}{{end}} | expires {{short (index $a "expires")}}</small></h3> |
| 30 | <table> |
| 31 | -<tr><th>key</th><td>{{template "nostrKey" $pk}} <code>{{$pk}}</code></td></tr> |
| 32 | +<tr><th>key</th><td><nostr-key hex="{{$pk}}" title="{{$pk}}">{{$pk}}</nostr-key> <small>click to copy</small></td></tr> |
| 33 | <tr><th>rooms</th><td>{{or (scopeList $a "rooms") "none"}}</td></tr> |
| 34 | <tr><th>repositories</th><td>{{range $i, $r := index $scope "repos"}}{{$repo := asMap $r}}{{if $i}}<br>{{end}}<code>{{str (index $repo "identifier")}}</code> {{str (index $repo "level")}}, owner {{template "nostrKey" (str (index $repo "owner"))}}{{else}}none{{end}}</td></tr> |
| 35 | <tr><th>wiki</th><td>{{or (str (index $scope "wiki")) "none"}}</td></tr> |
| 36 | diff --git a/internal/webui/style.css b/internal/webui/style.css |
| 37 | index 0a46694..2eb0b71 100644 |
| 38 | --- a/internal/webui/style.css |
| 39 | +++ b/internal/webui/style.css |
| 40 | @@ -141,7 +141,8 @@ agent-card table{border-collapse:collapse;font:13px var(--mono);width:auto;margi |
| 41 | agent-card th{text-align:left;font-weight:normal;color:var(--muted);width:9em;padding:3px 0;border:0;vertical-align:top}agent-card td{padding:3px 0;border:0;overflow-wrap:anywhere} |
| 42 | agent-card td code{color:var(--muted)} |
| 43 | agent-card p{margin:8px 0 0}agent-card rpc-form{display:inline-block;border:0;padding:0;margin:0 8px 0 0;vertical-align:top}agent-card rpc-form output:empty{display:none} |
| 44 | -agent-card p>a{font:12px var(--mono)} |
| 45 | +agent-card p>a{display:inline-block;font:12px var(--mono);line-height:29px;vertical-align:top} |
| 46 | +#rows:has(td[data-state]){table-layout:fixed}#rows:has(td[data-state]) td:nth-child(3){width:110px}#rows:has(td[data-state]) td:last-child{width:150px} |
| 47 | [data-state=active],#rows td[data-state=active]{color:var(--accent)}[data-state=paused],#rows td[data-state=paused]{color:var(--bark)}[data-state=revoked],#rows td[data-state=revoked]{color:var(--alert)} |
| 48 | agent-grant{display:block;border-bottom:1px solid var(--line);padding:10px 0;max-width:720px} |
| 49 | agent-grant label{display:inline-block;margin:0 10px 6px 0;vertical-align:top;font:13px var(--sans);color:var(--muted)} |
| 50 | @@ -232,6 +233,6 @@ html,body{overflow:auto} |
| 51 | #navigation-status:not(:empty),#session-status:not(:empty){position:absolute;bottom:100%;left:0;right:0;padding:6px 12px;background:var(--rail);border-top:1px solid var(--line);white-space:normal} |
| 52 | #split,#split>tbody,#split>tbody>tr,#split>tbody>tr>td{display:block;width:auto} |
| 53 | #tree{border-right:0;border-bottom:1px solid var(--line)} |
| 54 | -#rows{table-layout:fixed}#rows td{white-space:normal;overflow-wrap:anywhere;height:auto;padding:8px 6px;line-height:1.35}#rows td:first-child{width:90px}#rows td:last-child{width:80px}connect-list #rows td:nth-child(2),connect-list #rows th:nth-child(2){display:none}connect-list #rows td:nth-child(3),connect-list #rows td:last-child{width:auto}connect-list #rows td:last-child{white-space:normal}connect-list #rows td:last-child button{margin:2px 0} |
| 55 | +#rows{table-layout:fixed}#rows td{white-space:normal;overflow-wrap:anywhere;height:auto;padding:8px 6px;line-height:1.35}#rows td:first-child{width:90px}#rows td:last-child{width:80px}#rows:has(td[data-state]) td:nth-child(3),#rows:has(td[data-state]) th:nth-child(3){display:none}#rows:has(td[data-state]) td:last-child{width:80px}connect-list #rows td:nth-child(2),connect-list #rows th:nth-child(2){display:none}connect-list #rows td:nth-child(3),connect-list #rows td:last-child{width:auto}connect-list #rows td:last-child{white-space:normal}connect-list #rows td:last-child button{margin:2px 0} |
| 56 | #grid,#gridhead,h2:has(+#gridhead){display:none} |
| 57 | } |
| 58 | diff --git a/internal/webui/webui.go b/internal/webui/webui.go |
| 59 | index e89cd0b..19d5ba1 100644 |
| 60 | --- a/internal/webui/webui.go |
| 61 | +++ b/internal/webui/webui.go |
| 62 | @@ -840,8 +840,16 @@ func (a *App) agentsPage(request *http.Request, actor string, data *PageData) { |
| 63 | } |
| 64 | data.Feed = browseRows(result) |
| 65 | selected := request.URL.Query().Get("agent") |
| 66 | - if selected == "" && len(data.Feed) > 0 { |
| 67 | - selected = plainString(valueMap(data.Feed[0])["pubkey"]) |
| 68 | + if selected == "" { |
| 69 | + // Without a choice, show the first agent that can still publish. |
| 70 | + for _, agent := range data.Feed { |
| 71 | + if selected == "" || agentState(agent) == "active" { |
| 72 | + selected = plainString(valueMap(agent)["pubkey"]) |
| 73 | + } |
| 74 | + if agentState(agent) == "active" { |
| 75 | + break |
| 76 | + } |
| 77 | + } |
| 78 | } |
| 79 | if selected == "" { |
| 80 | return |