mirror of
https://github.com/navidrome/navidrome.git
synced 2026-11-03 08:57:53 +01:00
refactor: share the explain kind list and time format, trim the DTO
The explainable-kind list and the report's time format each existed twice, kept in sync by a comment pointing at the other copy. Both now live in core/artwork beside their siblings. FormatAgents returned a CLI-worded sentence, so the web UI rendered starred agents with no legend at all. It now reports a bool and each caller words its own note. Drop kind, id, chainOrigin and the numeric priority from the explain response: all four were serialized and never read, and chainOrigin is derivable from stored.attemptedAt on an endpoint that never walks. ExpandInfoDialog takes an optional resource instead of a node-or-map content prop. A page mounts one dialog per resource, which removes the silent blank-dialog failure mode when a map was missing a key. Outcome chips read the MUI palette rather than hardcoded hex, so they follow the dark theme.
This commit is contained in:
parent
f283da0630
commit
8ba8e7f2d7
13 changed files with 142 additions and 136 deletions
|
|
@ -13,13 +13,6 @@ import (
|
|||
"github.com/navidrome/navidrome/model"
|
||||
)
|
||||
|
||||
// explainableKinds is every kind the endpoint accepts, matching the CLI's explainKinds: a kind
|
||||
// with no chain to walk still has stored state and config to report.
|
||||
var explainableKinds = []model.Kind{
|
||||
model.KindArtistArtwork, model.KindAlbumArtwork, model.KindDiscArtwork,
|
||||
model.KindMediaFileArtwork, model.KindPlaylistArtwork, model.KindRadioArtwork,
|
||||
}
|
||||
|
||||
type traceStepDTO struct {
|
||||
Candidate string `json:"candidate"`
|
||||
Outcome string `json:"outcome"`
|
||||
|
|
@ -33,7 +26,6 @@ type storedDTO struct {
|
|||
}
|
||||
|
||||
type queuedDTO struct {
|
||||
Priority int `json:"priority"`
|
||||
PriorityName string `json:"priorityName"`
|
||||
Attempts int `json:"attempts"`
|
||||
RetryAt string `json:"retryAt,omitempty"`
|
||||
|
|
@ -45,11 +37,8 @@ type configDTO struct {
|
|||
}
|
||||
|
||||
type explainDTO struct {
|
||||
Kind string `json:"kind"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Result string `json:"result"`
|
||||
ChainOrigin string `json:"chainOrigin"`
|
||||
Steps []traceStepDTO `json:"steps"`
|
||||
Stored *storedDTO `json:"stored,omitempty"`
|
||||
Queued *queuedDTO `json:"queued,omitempty"`
|
||||
|
|
@ -57,6 +46,7 @@ type explainDTO struct {
|
|||
GaveUpAfter []traceStepDTO `json:"gaveUpAfter,omitempty"`
|
||||
Config *configDTO `json:"config,omitempty"`
|
||||
Agents string `json:"agents,omitempty"`
|
||||
AgentsIncomplete bool `json:"agentsIncomplete,omitempty"`
|
||||
}
|
||||
|
||||
func (api *Router) addArtworkExplainRoute(r chi.Router) {
|
||||
|
|
@ -67,7 +57,7 @@ func (api *Router) explainArtwork() http.HandlerFunc {
|
|||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
kind, ok := model.ParseKind(r.URL.Query().Get("kind"))
|
||||
if !ok || !slices.Contains(explainableKinds, kind) {
|
||||
if !ok || !slices.Contains(artwork.ExplainKinds, kind) {
|
||||
http.Error(w, "invalid artwork kind", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
|
@ -110,13 +100,11 @@ func toStepDTOs(steps []artwork.TraceStep) []traceStepDTO {
|
|||
|
||||
func toExplainDTO(rep artwork.ExplainReport) explainDTO {
|
||||
dto := explainDTO{
|
||||
Kind: rep.Kind.Prefix(),
|
||||
ID: rep.ID,
|
||||
Name: rep.Name,
|
||||
Result: rep.Result(),
|
||||
ChainOrigin: rep.ChainOrigin(),
|
||||
Steps: toStepDTOs(rep.Steps),
|
||||
Agents: rep.Agents,
|
||||
Name: rep.Name,
|
||||
Result: rep.Result(),
|
||||
Steps: toStepDTOs(rep.Steps),
|
||||
Agents: rep.Agents,
|
||||
AgentsIncomplete: rep.AgentsIncomplete,
|
||||
}
|
||||
if rep.Stored != nil {
|
||||
dto.Stored = &storedDTO{
|
||||
|
|
@ -127,7 +115,6 @@ func toExplainDTO(rep artwork.ExplainReport) explainDTO {
|
|||
}
|
||||
if rep.Queued != nil {
|
||||
dto.Queued = &queuedDTO{
|
||||
Priority: rep.Queued.Priority,
|
||||
PriorityName: artwork.PriorityName(rep.Queued.Priority),
|
||||
Attempts: rep.Queued.Attempts,
|
||||
RetryAt: rfc3339(rep.Queued.RetryAt),
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ var _ = Describe("GET /artwork/explain", func() {
|
|||
Expect(json.Unmarshal(w.Body.Bytes(), &got)).To(Succeed())
|
||||
Expect(got["name"]).To(Equal("Radiohead"))
|
||||
Expect(got["result"]).To(Equal("resolved from external:deezer"))
|
||||
Expect(got["chainOrigin"]).To(ContainSubstring("recorded"))
|
||||
Expect(got["config"]).To(HaveKeyWithValue("setting", "ArtistArtPriority"))
|
||||
|
||||
Expect(got["stored"]).To(Equal(map[string]any{
|
||||
|
|
@ -127,7 +126,6 @@ var _ = Describe("GET /artwork/explain", func() {
|
|||
var got map[string]any
|
||||
Expect(json.Unmarshal(w.Body.Bytes(), &got)).To(Succeed())
|
||||
Expect(got["queued"]).To(Equal(map[string]any{
|
||||
"priority": float64(model.ArtworkPriorityScan),
|
||||
"priorityName": "scan",
|
||||
"attempts": float64(1),
|
||||
"retryAt": retryAt.Format(time.RFC3339),
|
||||
|
|
@ -149,6 +147,6 @@ var _ = Describe("GET /artwork/explain", func() {
|
|||
Expect(got).ToNot(HaveKey("queued"))
|
||||
Expect(got).ToNot(HaveKey("lastAttemptFailed"))
|
||||
Expect(got).ToNot(HaveKey("gaveUpAfter"))
|
||||
Expect(got["chainOrigin"]).To(Equal("not recorded"))
|
||||
Expect(got).ToNot(HaveKey("chainOrigin"))
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue