@@ -0,0 +1,525 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gardomatic.kleiax.de/lib/client"
|
||||
)
|
||||
|
||||
type plantForm struct {
|
||||
CSRFToken string `form:"csrf_token"`
|
||||
Name string `form:"name"`
|
||||
SpeciesID int `form:"species_id"`
|
||||
LocationIDs []int `form:"location_id"`
|
||||
Quantities []int `form:"quantity"`
|
||||
AssignmentIDs []int `form:"assignment_id"`
|
||||
Assignments []plantAssignmentForm `form:"-"`
|
||||
TaskIDs []int `form:"plant_task_id"`
|
||||
TaskRowKeys []string `form:"plant_task_row_key"`
|
||||
TaskTitles []string `form:"plant_task_title"`
|
||||
TaskDescriptions []string `form:"plant_task_description"`
|
||||
TaskDueAtStarts []string `form:"plant_task_due_at_start"`
|
||||
TaskDueAtEnds []string `form:"plant_task_due_at_end"`
|
||||
TaskPriorities []int `form:"plant_task_priority"`
|
||||
TaskPlantIDs []int `form:"plant_task_plant_id"`
|
||||
TaskLocationIDs []int `form:"plant_task_location_id"`
|
||||
TaskRecurrences []string `form:"plant_task_recurrence"`
|
||||
TaskRecurrenceIntervals []int `form:"plant_task_recurrence_interval"`
|
||||
TaskKeywords []string `form:"plant_task_keywords"`
|
||||
TaskStatuses []string `form:"plant_task_status_on_completion"`
|
||||
TaskActives []bool `form:"plant_task_active"`
|
||||
TaskDeletes []bool `form:"plant_task_delete"`
|
||||
Tasks []plantTaskForm `form:"-"`
|
||||
Notes string `form:"notes"`
|
||||
ImageData string `form:"image_data"`
|
||||
ImageID int `form:"image_id"`
|
||||
AcquiredAt string `form:"acquired_at"`
|
||||
Status string `form:"status"`
|
||||
Keywords string `form:"keywords"`
|
||||
Errors map[string]string
|
||||
}
|
||||
|
||||
type plantTaskForm struct {
|
||||
ID, Priority, PlantID, LocationID, RecurrenceInterval int
|
||||
RowKey string
|
||||
Title, Description, Recurrence, Keywords, PlantStatusOnCompletion string
|
||||
PendingPlantName string
|
||||
DueAtStart, DueAtEnd string
|
||||
Active, Delete bool
|
||||
Errors map[string]string
|
||||
}
|
||||
|
||||
type plantAssignmentForm struct {
|
||||
AssignmentID int
|
||||
LocationID int
|
||||
Quantity int
|
||||
}
|
||||
|
||||
func (form *plantForm) buildAssignments() {
|
||||
form.Assignments = make([]plantAssignmentForm, len(form.LocationIDs))
|
||||
for i, locationID := range form.LocationIDs {
|
||||
form.Assignments[i].LocationID = locationID
|
||||
if i < len(form.Quantities) {
|
||||
form.Assignments[i].Quantity = form.Quantities[i]
|
||||
}
|
||||
if i < len(form.AssignmentIDs) {
|
||||
form.Assignments[i].AssignmentID = form.AssignmentIDs[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (form *plantForm) buildTasks() {
|
||||
form.Tasks = make([]plantTaskForm, len(form.TaskTitles))
|
||||
for i := range form.TaskTitles {
|
||||
form.Tasks[i].Title = strings.TrimSpace(form.TaskTitles[i])
|
||||
if i < len(form.TaskIDs) {
|
||||
form.Tasks[i].ID = form.TaskIDs[i]
|
||||
}
|
||||
if i < len(form.TaskRowKeys) {
|
||||
form.Tasks[i].RowKey = form.TaskRowKeys[i]
|
||||
}
|
||||
if i < len(form.TaskDescriptions) {
|
||||
form.Tasks[i].Description = strings.TrimSpace(form.TaskDescriptions[i])
|
||||
}
|
||||
if i < len(form.TaskDueAtStarts) {
|
||||
form.Tasks[i].DueAtStart = form.TaskDueAtStarts[i]
|
||||
}
|
||||
if i < len(form.TaskDueAtEnds) {
|
||||
form.Tasks[i].DueAtEnd = form.TaskDueAtEnds[i]
|
||||
}
|
||||
if i < len(form.TaskPriorities) {
|
||||
form.Tasks[i].Priority = form.TaskPriorities[i]
|
||||
}
|
||||
if i < len(form.TaskPlantIDs) {
|
||||
form.Tasks[i].PlantID = form.TaskPlantIDs[i]
|
||||
}
|
||||
if i < len(form.TaskLocationIDs) {
|
||||
form.Tasks[i].LocationID = form.TaskLocationIDs[i]
|
||||
}
|
||||
if i < len(form.TaskRecurrences) {
|
||||
form.Tasks[i].Recurrence = form.TaskRecurrences[i]
|
||||
}
|
||||
if i < len(form.TaskRecurrenceIntervals) {
|
||||
form.Tasks[i].RecurrenceInterval = form.TaskRecurrenceIntervals[i]
|
||||
}
|
||||
if i < len(form.TaskKeywords) {
|
||||
form.Tasks[i].Keywords = form.TaskKeywords[i]
|
||||
}
|
||||
if i < len(form.TaskStatuses) {
|
||||
form.Tasks[i].PlantStatusOnCompletion = form.TaskStatuses[i]
|
||||
}
|
||||
if i < len(form.TaskActives) {
|
||||
form.Tasks[i].Active = form.TaskActives[i]
|
||||
}
|
||||
if i < len(form.TaskDeletes) {
|
||||
form.Tasks[i].Delete = form.TaskDeletes[i]
|
||||
}
|
||||
if form.Tasks[i].RowKey == "" {
|
||||
form.Tasks[i].RowKey = "task-" + strconv.Itoa(form.Tasks[i].ID) + "-" + strconv.Itoa(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (app *application) plants(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
apiClient := client.FromContext(r.Context())
|
||||
garden, _, err := apiClient.Garden(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
plants, _, err := apiClient.Plants(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
species, _, err := apiClient.SpeciesForGarden(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
data := app.newTemplateData(r)
|
||||
data.Garden = &garden
|
||||
data.Plants = plants
|
||||
data.Species = species
|
||||
locations, _, err := apiClient.Locations(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
data.Locations = locations
|
||||
data.LocationNames = make(map[int]string, len(locations))
|
||||
for _, location := range locations {
|
||||
data.LocationNames[location.ID] = location.Name
|
||||
}
|
||||
data.PlantLocations = make(map[int][]client.PlantLocation, len(plants))
|
||||
for _, plant := range plants {
|
||||
assignments, _, assignmentErr := apiClient.PlantLocations(r.Context(), gardenID, plant.ID)
|
||||
if assignmentErr != nil {
|
||||
app.handleAPIError(w, r, assignmentErr)
|
||||
return
|
||||
}
|
||||
data.PlantLocations[plant.ID] = assignments
|
||||
}
|
||||
data.Filters = collectionFilters(r, "q", "status", "species", "location", "sort")
|
||||
data.Plants = filterAndSortPlants(plants, data.PlantLocations, data.Filters)
|
||||
data.Plants, data.Pagination = paginateCollection(r, data.Plants)
|
||||
app.render(w, http.StatusOK, "plant.tmpl", data)
|
||||
}
|
||||
|
||||
func (app *application) plantCreate(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
locationID, _ := strconv.Atoi(r.URL.Query().Get("location_id"))
|
||||
app.renderPlantForm(w, r, gardenID, plantForm{Status: "alive", Assignments: []plantAssignmentForm{{LocationID: locationID, Quantity: 1}}, Errors: make(map[string]string)}, http.StatusOK)
|
||||
}
|
||||
|
||||
func (app *application) plantCreatePost(w http.ResponseWriter, r *http.Request) {
|
||||
app.plantSave(w, r)
|
||||
}
|
||||
|
||||
func (app *application) plantEdit(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
plantID, err := app.readPathID(r, "plantID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
apiClient := client.FromContext(r.Context())
|
||||
plant, _, err := apiClient.Plant(r.Context(), gardenID, plantID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
form := plantForm{Name: plant.Name, Notes: plant.Notes, ImageData: plant.ImageData, Status: plant.Status, Keywords: strings.Join(plant.Tags, ", "), Errors: map[string]string{}}
|
||||
if plant.ImageID != nil {
|
||||
form.ImageID = *plant.ImageID
|
||||
}
|
||||
if plant.SpeciesID != nil {
|
||||
form.SpeciesID = *plant.SpeciesID
|
||||
}
|
||||
if plant.AcquiredAt != nil {
|
||||
form.AcquiredAt = plant.AcquiredAt.Format("2006-01-02")
|
||||
}
|
||||
assignments, _, err := apiClient.PlantLocations(r.Context(), gardenID, plantID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
for _, assignment := range assignments {
|
||||
form.Assignments = append(form.Assignments, plantAssignmentForm{AssignmentID: assignment.ID, LocationID: assignment.LocationID, Quantity: assignment.Quantity})
|
||||
}
|
||||
if len(form.Assignments) == 0 {
|
||||
form.Assignments = []plantAssignmentForm{{Quantity: 1}}
|
||||
}
|
||||
app.renderPlantForm(w, r, gardenID, form, http.StatusOK, plantID)
|
||||
}
|
||||
|
||||
func (app *application) plantEditPost(w http.ResponseWriter, r *http.Request) { app.plantSave(w, r) }
|
||||
|
||||
func (app *application) plantSave(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
plantID := 0
|
||||
if id, readErr := app.readPathID(r, "plantID"); readErr == nil {
|
||||
plantID = id
|
||||
}
|
||||
var form plantForm
|
||||
if err := app.decodePostForm(r, &form); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
form.buildAssignments()
|
||||
form.buildTasks()
|
||||
form.Name = strings.TrimSpace(form.Name)
|
||||
form.Notes = strings.TrimSpace(form.Notes)
|
||||
form.Errors = make(map[string]string)
|
||||
if form.Name == "" {
|
||||
form.Errors["name"] = "Ein Name ist erforderlich."
|
||||
}
|
||||
if form.Status == "" {
|
||||
form.Status = "alive"
|
||||
}
|
||||
for i, assignment := range form.Assignments {
|
||||
if assignment.LocationID > 0 && assignment.Quantity < 1 {
|
||||
form.Errors["quantity_"+strconv.Itoa(i)] = "Die Anzahl muss mindestens 1 sein."
|
||||
}
|
||||
}
|
||||
for i, task := range form.Tasks {
|
||||
if task.Delete {
|
||||
continue
|
||||
}
|
||||
if task.Title == "" {
|
||||
form.Errors["plant_task_title_"+strconv.Itoa(i)] = "Ein Titel ist erforderlich."
|
||||
}
|
||||
start, _ := parseTaskTime(task.DueAtStart, "plant_task_due_at_start_"+strconv.Itoa(i), form.Errors)
|
||||
end, _ := parseTaskTime(task.DueAtEnd, "plant_task_due_at_end_"+strconv.Itoa(i), form.Errors)
|
||||
if start != nil && end != nil && start.After(*end) {
|
||||
form.Errors["plant_task_due_at_end_"+strconv.Itoa(i)] = "Das Ende darf nicht vor dem Beginn liegen."
|
||||
}
|
||||
}
|
||||
var acquiredAt *time.Time
|
||||
if form.AcquiredAt != "" {
|
||||
parsed, parseErr := time.Parse("2006-01-02", form.AcquiredAt)
|
||||
if parseErr != nil {
|
||||
form.Errors["acquired_at"] = "Das Datum ist ungültig."
|
||||
} else {
|
||||
acquiredAt = &parsed
|
||||
}
|
||||
}
|
||||
if len(form.Errors) == 0 {
|
||||
name, notes, status := form.Name, form.Notes, form.Status
|
||||
imageData := form.ImageData
|
||||
input := client.PlantInput{Name: &name, Notes: ¬es, ImageData: &imageData, Status: &status, AcquiredAt: acquiredAt, ClearAcquiredAt: acquiredAt == nil, Tags: parseKeywords(form.Keywords)}
|
||||
if form.ImageID > 0 {
|
||||
imageID := form.ImageID
|
||||
input.ImageID = &imageID
|
||||
}
|
||||
if form.SpeciesID > 0 {
|
||||
speciesID := form.SpeciesID
|
||||
input.SpeciesID = &speciesID
|
||||
} else {
|
||||
input.ClearSpeciesID = true
|
||||
}
|
||||
apiClient := client.FromContext(r.Context())
|
||||
var plant client.Plant
|
||||
if plantID > 0 {
|
||||
plant, _, err = apiClient.UpdatePlant(r.Context(), gardenID, plantID, input)
|
||||
} else {
|
||||
plant, _, err = apiClient.CreatePlant(r.Context(), gardenID, input)
|
||||
}
|
||||
if err == nil {
|
||||
for _, assignment := range form.Assignments {
|
||||
if assignment.LocationID == 0 {
|
||||
if assignment.AssignmentID > 0 {
|
||||
_, err = apiClient.DeletePlantLocation(r.Context(), gardenID, plant.ID, assignment.AssignmentID)
|
||||
}
|
||||
} else {
|
||||
locationID, quantity := assignment.LocationID, assignment.Quantity
|
||||
assignmentInput := client.PlantLocationInput{LocationID: &locationID, Quantity: &quantity, PlantedAt: acquiredAt, ClearPlantedAt: acquiredAt == nil}
|
||||
if assignment.AssignmentID > 0 {
|
||||
_, _, err = apiClient.UpdatePlantLocation(r.Context(), gardenID, plant.ID, assignment.AssignmentID, assignmentInput)
|
||||
} else {
|
||||
_, _, err = apiClient.CreatePlantLocation(r.Context(), gardenID, plant.ID, assignmentInput)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = app.savePlantTasks(r, gardenID, plant.ID, form.Tasks)
|
||||
}
|
||||
if err == nil && form.SpeciesID > 0 {
|
||||
err = app.savePlantTemplateStates(r, gardenID, plant.ID, form.SpeciesID)
|
||||
}
|
||||
if err != nil && plantID == 0 {
|
||||
_, _ = apiClient.DeletePlant(r.Context(), gardenID, plant.ID)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
http.Redirect(w, r, webPath("plants", gardenID), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
var apiError *client.APIError
|
||||
if errors.As(err, &apiError) && apiError.StatusCode == http.StatusUnprocessableEntity {
|
||||
form.Errors = apiError.Validation
|
||||
} else {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
app.renderPlantForm(w, r, gardenID, form, http.StatusUnprocessableEntity, plantID)
|
||||
}
|
||||
|
||||
func (app *application) plantStatusPost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
plantID, err := app.readPathID(r, "plantID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
if err = r.ParseForm(); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
status := r.PostForm.Get("status")
|
||||
if status != "alive" && status != "dead" && status != "removed" && status != "infested" && status != "harvested" && status != "dormant" {
|
||||
app.clientError(w, http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
if _, _, err = client.FromContext(r.Context()).UpdatePlant(r.Context(), gardenID, plantID, client.PlantInput{Status: &status}); err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("plants", gardenID), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) plantDelete(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
plantID, err := app.readPathID(r, "plantID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
if _, err := client.FromContext(r.Context()).DeletePlant(r.Context(), gardenID, plantID); err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("plants", gardenID), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) plantTemplateOptOutPost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
plantID, err := app.readPathID(r, "plantID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
templateID, err := app.readPathID(r, "templateID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
if err = r.ParseForm(); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
optedOut := r.PostForm.Get("opted_out") != "false"
|
||||
if _, err = client.FromContext(r.Context()).SetTaskTemplateOptOut(r.Context(), gardenID, plantID, templateID, optedOut); err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("plant.edit", gardenID, plantID), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) renderPlantForm(w http.ResponseWriter, r *http.Request, gardenID int, form plantForm, status int, plantIDs ...int) {
|
||||
apiClient := client.FromContext(r.Context())
|
||||
garden, _, err := apiClient.Garden(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
species, _, err := apiClient.SpeciesForGarden(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
data := app.newTemplateData(r)
|
||||
data.Garden = &garden
|
||||
data.Species = species
|
||||
priorities, _, err := apiClient.TaskPriorities(r.Context())
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
data.TaskPriorities = priorities
|
||||
locations, _, err := apiClient.Locations(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
data.Locations = locations
|
||||
images, err := app.loadImageLibrary(r, gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
data.Images = images
|
||||
data.Form = form
|
||||
data.SpeciesID = form.SpeciesID
|
||||
data.TaskTemplates = map[int][]client.SpeciesTaskTemplate{}
|
||||
data.TemplateOptOuts = map[int]bool{}
|
||||
if len(plantIDs) > 0 {
|
||||
data.PlantID = plantIDs[0]
|
||||
plant, _, plantErr := apiClient.Plant(r.Context(), gardenID, data.PlantID)
|
||||
if plantErr != nil {
|
||||
app.handleAPIError(w, r, plantErr)
|
||||
return
|
||||
}
|
||||
data.PlantCreatedBy = plant.CreatedBy
|
||||
if form.Tasks == nil {
|
||||
tasks, _, taskErr := apiClient.Tasks(r.Context(), gardenID)
|
||||
var apiError *client.APIError
|
||||
if taskErr != nil && !(errors.As(taskErr, &apiError) && apiError.StatusCode == http.StatusNotFound) {
|
||||
app.handleAPIError(w, r, taskErr)
|
||||
return
|
||||
}
|
||||
for _, task := range tasks {
|
||||
if task.PlantID == nil || *task.PlantID != data.PlantID || task.TemplateID != nil {
|
||||
continue
|
||||
}
|
||||
active := task.Active == nil || *task.Active
|
||||
item := plantTaskForm{ID: task.ID, PlantID: data.PlantID, RowKey: "task-" + strconv.Itoa(task.ID), Title: task.Title, Description: task.Description, Priority: task.Priority, Active: active, Recurrence: task.Recurrence, RecurrenceInterval: task.RecurrenceInterval, Keywords: strings.Join(task.Tags, ", ")}
|
||||
if task.LocationID != nil {
|
||||
item.LocationID = *task.LocationID
|
||||
}
|
||||
if task.PlantStatusOnCompletion != nil {
|
||||
item.PlantStatusOnCompletion = *task.PlantStatusOnCompletion
|
||||
}
|
||||
if task.DueAtStart != nil {
|
||||
item.DueAtStart = task.DueAtStart.Local().Format("2006-01-02")
|
||||
}
|
||||
if task.DueAtEnd != nil {
|
||||
item.DueAtEnd = task.DueAtEnd.Local().Format("2006-01-02")
|
||||
}
|
||||
form.Tasks = append(form.Tasks, item)
|
||||
}
|
||||
data.Form = form
|
||||
}
|
||||
if form.SpeciesID > 0 {
|
||||
ids, _, optErr := apiClient.TaskTemplateOptOuts(r.Context(), gardenID, data.PlantID)
|
||||
if optErr != nil {
|
||||
app.handleAPIError(w, r, optErr)
|
||||
return
|
||||
}
|
||||
for _, id := range ids {
|
||||
data.TemplateOptOuts[id] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if form.SpeciesID > 0 {
|
||||
templates, _, templateErr := apiClient.SpeciesTaskTemplates(r.Context(), gardenID, form.SpeciesID)
|
||||
if templateErr != nil {
|
||||
app.handleAPIError(w, r, templateErr)
|
||||
return
|
||||
}
|
||||
data.TaskTemplates[form.SpeciesID] = templates
|
||||
for _, item := range templates {
|
||||
if values, present := r.PostForm["plant_template_active_"+strconv.Itoa(item.ID)]; present {
|
||||
data.TemplateOptOuts[item.ID] = len(values) == 0 || values[len(values)-1] != "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
app.render(w, status, "plant_form.tmpl", data)
|
||||
}
|
||||
Reference in New Issue
Block a user