Prompt families to refresh photos and facts that have aged (#7)
This commit is contained in:
@@ -72,6 +72,19 @@ var overrideColumns = []string{
|
||||
"Is Student", "Is Parent", "Is Staff", "New to Helios", "Pronouns", "Facts",
|
||||
"Grade", "Classroom", "Crew", "Phone", "Job Title", "Department", "Grade Band", "Room Parent",
|
||||
"Address", "Family Phone", "Family Photo Caption", "Opted Out",
|
||||
"Photo Updated", "Facts Updated", "Family Photo Updated",
|
||||
}
|
||||
|
||||
const updatedFormat = "2006-01-02"
|
||||
|
||||
func checkUpdated(email, column, cell string) error {
|
||||
if cell == "" || cell == "-" {
|
||||
return nil
|
||||
}
|
||||
if _, err := time.Parse(updatedFormat, cell); err != nil {
|
||||
return fmt.Errorf("overrides row %s has invalid %s %q", email, column, cell)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BlobChecker interface {
|
||||
@@ -115,8 +128,8 @@ type household struct {
|
||||
}
|
||||
|
||||
type familyCells struct {
|
||||
address, phone, caption string
|
||||
hasAddress, hasPhone, hasCaption bool
|
||||
address, phone, caption, photoUpdated string
|
||||
hasAddress, hasPhone, hasCaption, hasPhotoUpdated bool
|
||||
}
|
||||
|
||||
func exactColumns(table string, header, wanted []string) error {
|
||||
@@ -447,6 +460,14 @@ func (l *loader) applyOverrides() error {
|
||||
}
|
||||
apply(row["Pronouns"], &p.Pronouns)
|
||||
apply(row["Facts"], &p.Facts)
|
||||
if err := checkUpdated(email, "Facts Updated", row["Facts Updated"]); err != nil {
|
||||
return err
|
||||
}
|
||||
apply(row["Facts Updated"], &p.FactsUpdated)
|
||||
if err := checkUpdated(email, "Photo Updated", row["Photo Updated"]); err != nil {
|
||||
return err
|
||||
}
|
||||
apply(row["Photo Updated"], &p.PhotoUpdated)
|
||||
if cell := row["Grade"]; cell != "" && cell != "-" && !added && gradeBands[cell] == "" {
|
||||
return fmt.Errorf("overrides row %s has unknown grade %q", email, cell)
|
||||
}
|
||||
@@ -486,7 +507,16 @@ func (l *loader) applyOverrides() error {
|
||||
cells.caption = cell
|
||||
}
|
||||
}
|
||||
if cells.hasAddress || cells.hasPhone || cells.hasCaption {
|
||||
if cell := row["Family Photo Updated"]; cell != "" {
|
||||
if err := checkUpdated(email, "Family Photo Updated", cell); err != nil {
|
||||
return err
|
||||
}
|
||||
cells.hasPhotoUpdated = true
|
||||
if cell != "-" {
|
||||
cells.photoUpdated = cell
|
||||
}
|
||||
}
|
||||
if cells.hasAddress || cells.hasPhone || cells.hasCaption || cells.hasPhotoUpdated {
|
||||
l.familyOverrides[email] = cells
|
||||
}
|
||||
|
||||
@@ -558,6 +588,9 @@ func (l *loader) buildFamilies() error {
|
||||
if cells.hasCaption {
|
||||
family.PhotoCaption = cells.caption
|
||||
}
|
||||
if cells.hasPhotoUpdated {
|
||||
family.PhotoUpdated = cells.photoUpdated
|
||||
}
|
||||
l.model.Families[key] = family
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -19,8 +19,10 @@ type Person struct {
|
||||
IsNew bool `json:"isNew,omitempty"`
|
||||
Pronouns string `json:"pronouns,omitempty"`
|
||||
Facts string `json:"facts,omitempty"`
|
||||
FactsUpdated string `json:"factsUpdated,omitempty"`
|
||||
PronunciationURL string `json:"pronunciationUrl,omitempty"`
|
||||
PhotoURL string `json:"photoUrl,omitempty"`
|
||||
PhotoUpdated string `json:"photoUpdated,omitempty"`
|
||||
Grade string `json:"grade,omitempty"`
|
||||
Classroom string `json:"classroom,omitempty"`
|
||||
Crew string `json:"crew,omitempty"`
|
||||
@@ -45,6 +47,7 @@ type Family struct {
|
||||
Lng float64 `json:"lng,omitempty"`
|
||||
PhotoURL string `json:"photoUrl,omitempty"`
|
||||
PhotoCaption string `json:"photoCaption,omitempty"`
|
||||
PhotoUpdated string `json:"photoUpdated,omitempty"`
|
||||
PronunciationURL string `json:"pronunciationUrl,omitempty"`
|
||||
AdultEmails []string `json:"adultEmails,omitempty"`
|
||||
KidEmails []string `json:"kidEmails,omitempty"`
|
||||
|
||||
@@ -66,6 +66,10 @@ func RegisterUpload(mux *http.ServeMux, cache *Cache, sheet *data.Sheet, store *
|
||||
mux.HandleFunc("POST /api/directory/edit", u.edit)
|
||||
}
|
||||
|
||||
func today() string {
|
||||
return time.Now().UTC().Format(updatedFormat)
|
||||
}
|
||||
|
||||
func clearable(value string) string {
|
||||
if value == "" {
|
||||
return "-"
|
||||
@@ -197,11 +201,13 @@ func (u uploader) facts(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "not allowed to edit this record", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
old := ""
|
||||
old, oldUpdated := "", ""
|
||||
if p := model.Person(key); p != nil {
|
||||
old = p.Facts
|
||||
old, oldUpdated = p.Facts, p.FactsUpdated
|
||||
}
|
||||
if !u.applyOverride(w, me, key, "facts update", map[string]string{"Facts": facts}, map[string]string{"Facts": old}) {
|
||||
cells := map[string]string{"Facts": facts, "Facts Updated": today()}
|
||||
previous := map[string]string{"Facts": old, "Facts Updated": oldUpdated}
|
||||
if !u.applyOverride(w, me, key, "facts update", cells, previous) {
|
||||
return
|
||||
}
|
||||
log.Printf("facts: %s set %s (%d chars)", me, key, len(facts))
|
||||
@@ -260,7 +266,16 @@ func (u uploader) upload(w http.ResponseWriter, r *http.Request) {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
if err := u.cache.Refresh(); err != nil {
|
||||
if kind == "photo" {
|
||||
row, column, previous := key, "Photo Updated", model.Person(key).PhotoUpdated
|
||||
if target == "family" {
|
||||
row, column, previous = strings.ToLower(me), "Family Photo Updated", model.Families[key].PhotoUpdated
|
||||
}
|
||||
if !u.applyOverride(w, me, row, "photo upload",
|
||||
map[string]string{column: today()}, map[string]string{column: previous}) {
|
||||
return
|
||||
}
|
||||
} else if err := u.cache.Refresh(); err != nil {
|
||||
serverError(w, fmt.Errorf("refresh model after upload: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user