datastar/site/routes_examples_bulk_update.go

129 lines
2.8 KiB
Go

package site
import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/go-chi/chi/v5"
datastar "github.com/starfederation/datastar/sdk/go"
)
type ContactActive struct {
ID int `json:"id"`
IsActive bool `json:"isActive"`
Name string `json:"name"`
Email string `json:"email"`
}
func starterActiveContacts() []*ContactActive {
return []*ContactActive{
{
ID: 0,
Name: "Joe Smith",
Email: "joe@smith.org",
IsActive: true,
},
{
ID: 1,
Name: "Angie MacDowell",
Email: "angie@macdowell.org",
IsActive: true,
},
{
ID: 2,
Name: "Fuqua Tarkenton",
Email: "fuqua@tarkenton.org",
IsActive: true,
},
{
ID: 3,
Name: "Kim Yee",
Email: "kim@yee.org",
IsActive: false,
},
}
}
type BulkUpdateSelectionSignals struct {
Selections map[string]bool `json:"selections"`
}
func setupExamplesBulkUpdate(examplesRouter chi.Router) error {
contacts := starterActiveContacts()
defaultSelectionSignals := func() *BulkUpdateSelectionSignals {
selections := map[string]bool{
"all": false,
}
for i := range contacts {
key := fmt.Sprintf("contact_%d", i)
selections[key] = false
}
return &BulkUpdateSelectionSignals{
Selections: selections,
}
}
examplesRouter.Route("/bulk_update/data", func(dataRouter chi.Router) {
dataRouter.Get("/", func(w http.ResponseWriter, r *http.Request) {
sse := datastar.NewSSE(w, r)
sse.MergeFragmentTempl(bulkUpdateContacts(defaultSelectionSignals(), contacts))
})
setActivation := func(w http.ResponseWriter, r *http.Request, isActive bool) {
signals := &BulkUpdateSelectionSignals{}
if err := datastar.ReadSignals(r, signals); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// logJSON("incoming", signals)
sse := datastar.NewSSE(w, r)
for key, wasSelected := range signals.Selections {
const prefix = "contact_"
if strings.HasPrefix(key, prefix) {
idStr := strings.TrimPrefix(key, prefix)
i, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
c := contacts[i]
wasChanged := c.IsActive != isActive
if wasSelected {
if wasChanged {
c.IsActive = isActive
}
}
sse.MergeFragmentTempl(
bulkUpdateContact(i, c, wasChanged && wasSelected),
)
}
}
// Reset all selections
for k := range signals.Selections {
signals.Selections[k] = false
}
// logJSON("outgoing", signals)
sse.MarshalAndMergeSignals(signals)
}
dataRouter.Put("/activate", func(w http.ResponseWriter, r *http.Request) {
setActivation(w, r, true)
})
dataRouter.Put("/deactivate", func(w http.ResponseWriter, r *http.Request) {
setActivation(w, r, false)
})
})
return nil
}