Settings: Save and Cancel buttons instead of saving each change
Changes made in the Settings window show at once but are only kept with the Save button, placed under the tab labels; it takes the accent color while changes are waiting. Cancel goes back to the saved settings, and closing the window (or the page) with unsaved changes asks first. Tags are now sent as a whole list (PUT /api/tags, nothing saved when one is invalid, the error gives its position) and "Restore default tags" shows GET /api/tags/defaults until Save. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
dcb09e619e
commit
194edee6de
8 files changed
+442
-130
No files matched your search
@@ -40,6 +40,8 @@ func (a *API) Routes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("GET /api/dbstats", a.dbStats)
|
||||
mux.HandleFunc("GET /api/tags", a.listTags)
|
||||
mux.HandleFunc("POST /api/tags", a.createTag)
|
||||
mux.HandleFunc("PUT /api/tags", a.replaceTags)
|
||||
mux.HandleFunc("GET /api/tags/defaults", a.defaultTags)
|
||||
mux.HandleFunc("POST /api/tags/reset", a.resetTags)
|
||||
mux.HandleFunc("GET /api/presets", a.listPresets)
|
||||
mux.HandleFunc("PUT /api/tags/{id}", a.updateTag)
|
||||
@@ -531,6 +533,41 @@ func (a *API) purge(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]string{"task_id": id})
|
||||
}
|
||||
|
||||
// PUT /api/tags [tags]: replaces the whole list. On an invalid tag, "index"
|
||||
// gives its position and nothing is saved.
|
||||
func (a *API) replaceTags(w http.ResponseWriter, r *http.Request) {
|
||||
var in []Tag
|
||||
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 1<<20)).Decode(&in); err != nil {
|
||||
writeErr(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
tags, err := a.tags.Replace(in)
|
||||
var le *tagListError
|
||||
switch {
|
||||
case errors.As(err, &le):
|
||||
body := map[string]any{"error": err.Error(), "index": le.index}
|
||||
var ce *codedError
|
||||
if errors.As(err, &ce) {
|
||||
body["code"] = ce.code
|
||||
if ce.detail != "" {
|
||||
body["detail"] = ce.detail
|
||||
}
|
||||
}
|
||||
writeJSON(w, http.StatusBadRequest, body)
|
||||
case errors.Is(err, errTooManyTags):
|
||||
writeErr(w, http.StatusBadRequest, err)
|
||||
case err != nil:
|
||||
writeErr(w, http.StatusInternalServerError, err)
|
||||
default:
|
||||
writeJSON(w, http.StatusOK, tags)
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/tags/defaults: the tags "Restore default tags" shows before saving.
|
||||
func (a *API) defaultTags(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, defaultTags())
|
||||
}
|
||||
|
||||
func (a *API) resetTags(w http.ResponseWriter, r *http.Request) {
|
||||
tags, err := a.tags.Reset()
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user