1package workbench23import (4 "fmt"5 "net/http"6 "strconv"78 "github.com/FelineStateMachine/atlas/internal/authoring"9 "github.com/FelineStateMachine/atlas/internal/workbench/oprunner"10)1112const maxUSAreaFormBytes = 32 << 101314func (w *Workbench) handleProjectUSArea(rw http.ResponseWriter, request *http.Request) {15 if err := oprunner.CheckOrigin(request); err != nil {16 http.Error(rw, err.Error(), http.StatusForbidden)17 return18 }19 request.Body = http.MaxBytesReader(rw, request.Body, maxUSAreaFormBytes)20 if err := request.ParseForm(); err != nil {21 http.Error(rw, err.Error(), http.StatusBadRequest)22 return23 }24 profile, err := usAreaProfileFromForm(request)25 if err != nil {26 http.Error(rw, err.Error(), http.StatusBadRequest)27 return28 }29 project, _, err := authoring.NewAreaProject(profile)30 if err != nil {31 http.Error(rw, err.Error(), http.StatusBadRequest)32 return33 }34 manifest, err := authoring.MarshalProjectYAML(project)35 if err != nil {36 http.Error(rw, err.Error(), http.StatusBadRequest)37 return38 }39 if err := validateAndInstallManifest(w.targets.Project, manifest); err != nil {40 http.Error(rw, err.Error(), http.StatusBadRequest)41 return42 }43 http.Redirect(rw, request, "/project?notice=Official+U.S.+profile+installed", http.StatusSeeOther)44}4546func usAreaProfileFromForm(request *http.Request) (authoring.AreaProfile, error) {47 profile := authoring.DefaultAreaProfile()48 fields := []struct {49 name string50 at int51 }{52 {name: "west", at: 0}, {name: "south", at: 1}, {name: "east", at: 2}, {name: "north", at: 3},53 }54 for _, field := range fields {55 value, err := strconv.ParseFloat(request.FormValue(field.name), 64)56 if err != nil {57 return authoring.AreaProfile{}, fmt.Errorf("%s coordinate is invalid", field.name)58 }59 profile.Bounds[field.at] = value60 }61 detail, err := strconv.Atoi(request.FormValue("detail"))62 if err != nil {63 return authoring.AreaProfile{}, fmt.Errorf("detail zoom is invalid")64 }65 profile.DetailZoom = detail66 profile.IncludeTopo = request.FormValue("topo") == "true"67 profile.IncludeRoads = request.FormValue("roads") == "true"68 profile.IncludeHydro = request.FormValue("hydro") == "true"69 profile.IncludeCounties = request.FormValue("counties") == "true"70 if err := presentationFromForm(request, &profile.Presentation); err != nil {71 return authoring.AreaProfile{}, err72 }73 return profile, nil74}7576func presentationFromForm(request *http.Request, presentation *authoring.AreaPresentation) error {77 presentation.RoadLabel = request.FormValue("road-label")78 presentation.HydroLabel = request.FormValue("hydro-label")79 presentation.CountyLabel = request.FormValue("county-label")80 presentation.RoadColor = request.FormValue("road-color")81 presentation.HydroColor = request.FormValue("hydro-color")82 presentation.HydroFill = request.FormValue("hydro-fill")83 presentation.CountyColor = request.FormValue("county-color")84 presentation.RoadVisible = request.FormValue("road-visible") == "true"85 presentation.HydroVisible = request.FormValue("hydro-visible") == "true"86 presentation.CountyVisible = request.FormValue("county-visible") == "true"87 orders := []struct {88 name string89 to *int6490 }{91 {name: "road-order", to: &presentation.RoadOrder},92 {name: "hydro-order", to: &presentation.HydroOrder},93 {name: "county-order", to: &presentation.CountyOrder},94 }95 for _, order := range orders {96 value, err := strconv.ParseInt(request.FormValue(order.name), 10, 64)97 if err != nil {98 return fmt.Errorf("%s is invalid", order.name)99 }100 *order.to = value101 }102 return nil103}