@@ -0,0 +1,259 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"gardomatic.kleiax.de/lib/client"
|
||||
)
|
||||
|
||||
type gardenForm struct {
|
||||
CSRFToken string `form:"csrf_token"`
|
||||
Name string `form:"name"`
|
||||
Description string `form:"description"`
|
||||
ImageData string `form:"image_data"`
|
||||
ImageID int `form:"image_id"`
|
||||
Errors map[string]string
|
||||
}
|
||||
|
||||
type gardenEditForms struct {
|
||||
Garden gardenForm
|
||||
Invite inviteForm
|
||||
}
|
||||
|
||||
type gardenRoleSettingsForm struct {
|
||||
Name string `form:"name"`
|
||||
Permissions []string `form:"permissions"`
|
||||
}
|
||||
|
||||
func (app *application) gardens(w http.ResponseWriter, r *http.Request) {
|
||||
apiClient := client.FromContext(r.Context())
|
||||
gardens, _, err := apiClient.Gardens(r.Context())
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
if r.URL.Query().Get("auto") == "1" && len(gardens) == 1 {
|
||||
http.Redirect(w, r, webPath("garden.dashboard", gardens[0].ID), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
data := app.newTemplateData(r)
|
||||
data.Filters = collectionFilters(r, "q", "role", "sort")
|
||||
data.Gardens = filterAndSortGardens(gardens, data.Filters)
|
||||
data.Gardens, data.Pagination = paginateCollection(r, data.Gardens)
|
||||
app.render(w, http.StatusOK, "gardens.tmpl", data)
|
||||
}
|
||||
|
||||
func (app *application) gardenCreate(w http.ResponseWriter, r *http.Request) {
|
||||
data := app.newTemplateData(r)
|
||||
data.Form = gardenForm{Errors: make(map[string]string)}
|
||||
app.render(w, http.StatusOK, "garden_new.tmpl", data)
|
||||
}
|
||||
|
||||
func (app *application) gardenCreatePost(w http.ResponseWriter, r *http.Request) {
|
||||
var form gardenForm
|
||||
if err := app.decodePostForm(r, &form); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
form.Name = strings.TrimSpace(form.Name)
|
||||
form.Description = strings.TrimSpace(form.Description)
|
||||
form.Errors = make(map[string]string)
|
||||
if form.Name == "" {
|
||||
form.Errors["name"] = "Ein Name ist erforderlich."
|
||||
}
|
||||
apiClient := client.FromContext(r.Context())
|
||||
if len(form.Errors) == 0 {
|
||||
input := client.CreateGardenInput{Name: form.Name, Description: form.Description, ImageData: form.ImageData}
|
||||
if form.ImageID > 0 {
|
||||
imageID := form.ImageID
|
||||
input.ImageID = &imageID
|
||||
}
|
||||
garden, _, err := apiClient.CreateGarden(r.Context(), input)
|
||||
if err == nil {
|
||||
http.Redirect(w, r, webPath("plants", garden.ID), 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
|
||||
}
|
||||
}
|
||||
data := app.newTemplateData(r)
|
||||
data.Form = form
|
||||
app.render(w, http.StatusUnprocessableEntity, "garden_new.tmpl", data)
|
||||
}
|
||||
|
||||
func (app *application) gardenEdit(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
app.renderGardenEdit(w, r, gardenID, http.StatusOK, gardenEditForms{})
|
||||
}
|
||||
|
||||
func (app *application) gardenEditPost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
var form gardenForm
|
||||
if err := app.decodePostForm(r, &form); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
form.Name, form.Description, form.Errors = strings.TrimSpace(form.Name), strings.TrimSpace(form.Description), map[string]string{}
|
||||
if form.Name == "" {
|
||||
form.Errors["name"] = "Ein Name ist erforderlich."
|
||||
}
|
||||
apiClient := client.FromContext(r.Context())
|
||||
if len(form.Errors) == 0 {
|
||||
name, description, imageData := form.Name, form.Description, form.ImageData
|
||||
input := client.UpdateGardenInput{Name: &name, Description: &description, ImageData: &imageData}
|
||||
if form.ImageID > 0 {
|
||||
imageID := form.ImageID
|
||||
input.ImageID = &imageID
|
||||
}
|
||||
_, _, updateErr := apiClient.UpdateGarden(r.Context(), gardenID, input)
|
||||
if updateErr == nil {
|
||||
http.Redirect(w, r, webPath("gardens"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
var apiError *client.APIError
|
||||
if errors.As(updateErr, &apiError) && apiError.StatusCode == http.StatusUnprocessableEntity {
|
||||
form.Errors = apiError.Validation
|
||||
} else {
|
||||
app.handleAPIError(w, r, updateErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
app.renderGardenEdit(w, r, gardenID, http.StatusUnprocessableEntity, gardenEditForms{Garden: form})
|
||||
}
|
||||
|
||||
func (app *application) gardenDeletePost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
if _, err = client.FromContext(r.Context()).DeleteGarden(r.Context(), gardenID); err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("gardens"), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) gardenRoleSettingsPost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
var form gardenRoleSettingsForm
|
||||
if err = app.decodePostForm(r, &form); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if _, _, err = client.FromContext(r.Context()).UpdateGardenRoleSettings(r.Context(), gardenID, form.Name, form.Permissions); err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("garden.edit", gardenID)+"#garden-role-editor", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) gardenRoleCreatePost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
var form roleSettingsForm
|
||||
if err = app.decodePostForm(r, &form); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
_, _, err = client.FromContext(r.Context()).CreateGardenRole(r.Context(), gardenID, client.RoleInput{Name: strings.TrimSpace(form.Name), Label: strings.TrimSpace(form.Label), Permissions: form.Permissions})
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("garden.edit", gardenID)+"#garden-role-editor", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) gardenRoleDeletePost(w http.ResponseWriter, r *http.Request) {
|
||||
gardenID, err := app.readPathID(r, "gardenID")
|
||||
if err != nil {
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
var form roleSettingsForm
|
||||
if err = app.decodePostForm(r, &form); err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if _, err = client.FromContext(r.Context()).DeleteGardenRole(r.Context(), gardenID, form.Name); err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, webPath("garden.edit", gardenID)+"#garden-role-editor", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (app *application) renderGardenEdit(w http.ResponseWriter, r *http.Request, gardenID, status int, forms gardenEditForms) {
|
||||
apiClient := client.FromContext(r.Context())
|
||||
garden, _, err := apiClient.Garden(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
if forms.Garden.Errors == nil {
|
||||
forms.Garden = gardenForm{Name: garden.Name, Description: garden.Description, ImageData: garden.ImageData, Errors: map[string]string{}}
|
||||
if garden.ImageID != nil {
|
||||
forms.Garden.ImageID = *garden.ImageID
|
||||
}
|
||||
}
|
||||
if forms.Invite.Errors == nil {
|
||||
forms.Invite = inviteForm{Role: "member", Errors: map[string]string{}}
|
||||
}
|
||||
members, _, err := apiClient.GardenMembers(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
invites := []client.GardenInvite{}
|
||||
roleSettings := []client.GardenRoleSetting{}
|
||||
gardenRoles := []client.Role{}
|
||||
if garden.Can("members:write") {
|
||||
invites, _, err = apiClient.GardenInvites(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
roleSettings, _, err = apiClient.GardenRoleSettings(r.Context(), gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
for _, setting := range roleSettings {
|
||||
gardenRoles = append(gardenRoles, setting.Role)
|
||||
}
|
||||
}
|
||||
data := app.newTemplateData(r)
|
||||
data.Garden, data.Members, data.Invites, data.Form = &garden, members, invites, forms
|
||||
data.GardenRoles, data.GardenRoleSettings = gardenRoles, roleSettings
|
||||
data.GardenPermissions = gardenPermissionOptions()
|
||||
if garden.Can("garden:delete") {
|
||||
data.RoleEditors = []roleEditorData{gardenOverrideRoleEditor(gardenID, roleSettings, data.GardenPermissions, data.CSRFToken)}
|
||||
}
|
||||
data.Images, err = app.loadImageLibrary(r, gardenID)
|
||||
if err != nil {
|
||||
app.handleAPIError(w, r, err)
|
||||
return
|
||||
}
|
||||
app.render(w, status, "garden_form.tmpl", data)
|
||||
}
|
||||
Reference in New Issue
Block a user