check / check (push) Waiting to run
A target's settings move from the per-type JSON string in targets.config to columns: url, headers, timeout_seconds, forward_query, archive_expiry and archive_rotation. A column a type does not use stays empty. headers holds the header map as JSON text through GORM's JSON serializer, and archive_expiry holds a time.Duration, 0 meaning never, so nothing that reads a target parses it. The forms check each setting once, with the same refusals and messages, and the edit form is filled from the columns, so the per-type config structs, their parsers and the "could not be read" branches are gone. A delivery task carries the six settings in place of the JSON string. Model: opus-5-5
81 lines
2.2 KiB
Go
81 lines
2.2 KiB
Go
package handlers
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
// archiveExpiryNever is the archive expiry that keeps archived
|
|
// events forever. It is stored as an ArchiveExpiry of 0, and an
|
|
// empty expiry on a form means the same.
|
|
archiveExpiryNever = "never"
|
|
|
|
// tmplKeyArchiveExpiryChoices is the template data key for the
|
|
// entries of a page's archive expiry select.
|
|
tmplKeyArchiveExpiryChoices = "ArchiveExpiryChoices"
|
|
)
|
|
|
|
// archiveChoice is one entry of a database target's archive expiry
|
|
// or archive rotation select: the value stored, the label shown, and
|
|
// whether the select starts on it.
|
|
type archiveChoice struct {
|
|
Value string
|
|
Label string
|
|
Selected bool
|
|
}
|
|
|
|
// archiveExpiryChoices lists the archive expiries offered by the new
|
|
// webhook page, the add target form and the target edit form.
|
|
func archiveExpiryChoices() []archiveChoice {
|
|
return []archiveChoice{
|
|
{Value: archiveExpiryNever, Label: archiveExpiryNever},
|
|
{Value: "1h", Label: "1h"},
|
|
{Value: "12h", Label: "12h"},
|
|
{Value: "24h", Label: "24h"},
|
|
{Value: "720h", Label: "30d"},
|
|
{Value: "2160h", Label: "90d"},
|
|
{Value: "8760h", Label: "365d"},
|
|
}
|
|
}
|
|
|
|
// archiveExpiryOptions returns the choices with expiry selected; an
|
|
// empty expiry selects never. An expiry that is not one of the
|
|
// choices comes first as its own selected entry, so saving the form
|
|
// unchanged keeps it.
|
|
func archiveExpiryOptions(expiry string) []archiveChoice {
|
|
if expiry == "" {
|
|
expiry = archiveExpiryNever
|
|
}
|
|
|
|
options := archiveExpiryChoices()
|
|
|
|
for i := range options {
|
|
if options[i].Value == expiry {
|
|
options[i].Selected = true
|
|
|
|
return options
|
|
}
|
|
}
|
|
|
|
own := archiveChoice{Value: expiry, Label: expiry, Selected: true}
|
|
|
|
return append([]archiveChoice{own}, options...)
|
|
}
|
|
|
|
// formatArchiveExpiry writes a stored ArchiveExpiry the way the
|
|
// expiry select spells its values, so the target edit form starts on
|
|
// the stored choice: never for 0, a whole number of hours as "720h",
|
|
// and anything else as Go writes a duration, which the form accepts
|
|
// back unchanged.
|
|
func formatArchiveExpiry(expiry time.Duration) string {
|
|
switch {
|
|
case expiry == 0:
|
|
return archiveExpiryNever
|
|
case expiry%time.Hour == 0:
|
|
return strconv.FormatInt(int64(expiry/time.Hour), 10) + "h"
|
|
default:
|
|
return expiry.String()
|
|
}
|
|
}
|