commit
c606efd7dc
@ -25,6 +25,7 @@ func ApiRoutes() *http.ServeMux {
|
||||
//Project
|
||||
mux.HandleFunc("POST /project", handlers.CreateProjectHandler)
|
||||
mux.HandleFunc("PATCH /project/{id}", handlers.UpdateProjectHandler)
|
||||
mux.HandleFunc("PATCH /projects", handlers.UpdateProjectsHandler)
|
||||
mux.HandleFunc("GET /project/{id}", handlers.GetProjectHandler)
|
||||
mux.HandleFunc("GET /projects", handlers.GetProjectsHandler)
|
||||
|
||||
|
||||
@ -2,7 +2,10 @@ module openAPI
|
||||
|
||||
go 1.22
|
||||
|
||||
require github.com/a-h/rest v0.0.0-20240504113546-6729b3328f85
|
||||
require (
|
||||
github.com/a-h/respond v0.0.2
|
||||
github.com/a-h/rest v0.0.0-20240504113546-6729b3328f85
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/getkin/kin-openapi v0.124.0 // indirect
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
github.com/a-h/respond v0.0.2 h1:mhBwB2XuM+34gfIFs9LuXGfCCbu00rvaCWpTVNHvkPU=
|
||||
github.com/a-h/respond v0.0.2/go.mod h1:k9UvuVDWmHAb91OsdrqG0xFv7X+HelBpfMJIn9xMYWM=
|
||||
github.com/a-h/rest v0.0.0-20240504113546-6729b3328f85 h1:Lj+OmK3+dKMuR8OdlnUeIrgdt8JkcNlA9isS2Aey5Mg=
|
||||
github.com/a-h/rest v0.0.0-20240504113546-6729b3328f85/go.mod h1:5wH1imbpKnMjll8xpGRdg0Sb0HwH7nYiM5VPm0Zl5Bw=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/a-h/rest"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
@ -15,13 +14,12 @@ func main() {
|
||||
api = rest.NewAPI("portfolio")
|
||||
api.StripPkgPaths = []string{"github.com/a-h/rest/example", "github.com/a-h/respond"}
|
||||
|
||||
api.Get("/nfc/{uid}").
|
||||
HasPathParameter("uid", rest.PathParam{
|
||||
Description: "id of the user",
|
||||
Regexp: `\d+`,
|
||||
}).
|
||||
HasDescription("Get nfc data by uid.").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]())
|
||||
// register models
|
||||
RegisterModels()
|
||||
// register endpoints
|
||||
RegisterGenericEndpoints()
|
||||
RegisterUserEndpoints()
|
||||
RegisterProjectEndpoints()
|
||||
|
||||
// Create the specification.
|
||||
spec, err := api.Spec()
|
||||
|
||||
20
api/docs/openAPI/openApiGenericEndpoints.go
Normal file
20
api/docs/openAPI/openApiGenericEndpoints.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/a-h/respond"
|
||||
"github.com/a-h/rest"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func RegisterGenericEndpoints() {
|
||||
|
||||
api.Get("/check").
|
||||
HasDescription("check for user jwt cookie").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]())
|
||||
|
||||
api.Get("/htmx/canEdit").
|
||||
HasDescription("check if user is allowed to edit").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]())
|
||||
}
|
||||
9
api/docs/openAPI/openApiModels.go
Normal file
9
api/docs/openAPI/openApiModels.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
// ############## MUST DO ########################
|
||||
// local copy of types to fix unintended behaviour
|
||||
// ###############################################
|
||||
|
||||
func RegisterModels() {
|
||||
|
||||
}
|
||||
52
api/docs/openAPI/openApiProjectEndpoints.go
Normal file
52
api/docs/openAPI/openApiProjectEndpoints.go
Normal file
@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/a-h/respond"
|
||||
"github.com/a-h/rest"
|
||||
"net/http"
|
||||
"portfolio/database/ent"
|
||||
)
|
||||
|
||||
func RegisterProjectEndpoints() {
|
||||
api.Post("/project").
|
||||
HasDescription("Create project").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnauthorized, rest.ModelOf[string]())
|
||||
|
||||
api.Patch("/project/{id}").
|
||||
HasPathParameter("id", rest.PathParam{
|
||||
Description: "id of the project",
|
||||
Regexp: `\d+`,
|
||||
}).
|
||||
HasDescription("Update project by id").
|
||||
HasRequestModel(rest.ModelOf[ent.Project]()).
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusBadRequest, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnauthorized, rest.ModelOf[string]())
|
||||
|
||||
api.Patch("/projects").
|
||||
HasDescription("Update projects WIP").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[[]ent.Project]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnauthorized, rest.ModelOf[string]())
|
||||
|
||||
api.Get("/project/{id}").
|
||||
HasPathParameter("id", rest.PathParam{
|
||||
Description: "id of the project",
|
||||
Regexp: `\d+`,
|
||||
}).
|
||||
HasDescription("Get project by id").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[ent.Project]()).
|
||||
HasResponseModel(http.StatusBadRequest, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]())
|
||||
|
||||
api.Get("/projects").
|
||||
HasDescription("Get projects").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[[]ent.Project]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]())
|
||||
}
|
||||
39
api/docs/openAPI/openApiUserEndpoints.go
Normal file
39
api/docs/openAPI/openApiUserEndpoints.go
Normal file
@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/a-h/respond"
|
||||
"github.com/a-h/rest"
|
||||
"net/http"
|
||||
"portfolio/api/types"
|
||||
"portfolio/database/ent"
|
||||
)
|
||||
|
||||
func RegisterUserEndpoints() {
|
||||
api.Get("/user/{uid}").
|
||||
HasPathParameter("id", rest.PathParam{
|
||||
Description: "id of the user",
|
||||
Regexp: `\d+`,
|
||||
}).
|
||||
HasDescription("Get user by uid.").
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[ent.User]()).
|
||||
HasResponseModel(http.StatusBadRequest, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]())
|
||||
|
||||
api.Post("/register").
|
||||
HasDescription("Register.").
|
||||
HasRequestModel(rest.ModelOf[ent.User]()).
|
||||
HasResponseModel(http.StatusCreated, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusBadRequest, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]())
|
||||
|
||||
api.Post("/login").
|
||||
HasDescription("Login.").
|
||||
HasRequestModel(rest.ModelOf[types.LoginUser]()).
|
||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]()).
|
||||
HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnprocessableEntity, rest.ModelOf[respond.Error]()).
|
||||
HasResponseModel(http.StatusUnauthorized, rest.ModelOf[string]())
|
||||
|
||||
}
|
||||
@ -65,23 +65,19 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func CanEdit(w http.ResponseWriter, r *http.Request) {
|
||||
jwtCookie, _ := r.Cookie("jwt")
|
||||
|
||||
if jwtCookie != nil {
|
||||
_, audience, err := jwt.VerifyJWT(jwtCookie.Value)
|
||||
if err != nil {
|
||||
InternalServerErrorHandler(w, err)
|
||||
return
|
||||
}
|
||||
if audience == "owner" || audience == "visitor" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("<button class=\"button is-link\">Edit</button>"))
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(""))
|
||||
}
|
||||
_, audience, err := jwt.VerifyUser(r)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(""))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(""))
|
||||
if audience == "owner" || audience == "visitor" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("<button class=\"button is-link\">Edit</button>"))
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(""))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"portfolio/api/service/jwt"
|
||||
"portfolio/api/service/parse"
|
||||
"portfolio/database/ent"
|
||||
"portfolio/database/query"
|
||||
"strconv"
|
||||
@ -67,6 +68,54 @@ func UpdateProjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateProjectsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
isHtmx := r.Header.Get("HX-Request")
|
||||
|
||||
_, _, err := jwt.VerifyUser(r)
|
||||
if err != nil {
|
||||
UnauthorizedHandler(w)
|
||||
return
|
||||
}
|
||||
|
||||
var newProjects []*ent.Project
|
||||
var p []*ent.Project
|
||||
|
||||
if isHtmx == "true" {
|
||||
p = parse.ParseProjectInput(r)
|
||||
} else {
|
||||
|
||||
p, err = query.GetFullProjects(context.Background())
|
||||
if err != nil {
|
||||
UnprocessableEntityHandler(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&newProjects)
|
||||
if err != nil {
|
||||
InternalServerErrorHandler(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, project := range p {
|
||||
for _, newProject := range newProjects {
|
||||
if project.ID == newProject.ID {
|
||||
// todo add update from api
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, project := range p {
|
||||
err = query.UpdateProject(context.Background(), *project, project.ID)
|
||||
if err != nil {
|
||||
UnprocessableEntityHandler(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetProjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
projectID, err := strconv.Atoi(r.PathValue("id"))
|
||||
|
||||
@ -57,6 +57,7 @@ func GetUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
User, err := query.GetUser(context.Background(), userID)
|
||||
if err != nil {
|
||||
UnprocessableEntityHandler(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -64,6 +65,7 @@ func GetUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewEncoder(w).Encode(User)
|
||||
if err != nil {
|
||||
InternalServerErrorHandler(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,11 @@ import (
|
||||
)
|
||||
|
||||
func VerifyUser(r *http.Request) (int, string, error) {
|
||||
jwtCookie, _ := r.Cookie("jwt")
|
||||
|
||||
if jwtCookie != nil {
|
||||
return VerifyJWT(jwtCookie.Value)
|
||||
}
|
||||
bearerToken := r.Header.Get("Authorization")
|
||||
jwtToken := ""
|
||||
if len(bearerToken) > 7 {
|
||||
|
||||
40
api/service/parse/parseInput.go
Normal file
40
api/service/parse/parseInput.go
Normal file
@ -0,0 +1,40 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"portfolio/database/ent"
|
||||
"portfolio/database/query"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ParseProjectInput(r *http.Request) []*ent.Project {
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
body, err := url.ParseQuery(string(b))
|
||||
|
||||
var projects []*ent.Project
|
||||
|
||||
for x := range body["project_name"] {
|
||||
var p *ent.Project
|
||||
|
||||
projectID, err := strconv.Atoi(body["project_id"][x])
|
||||
|
||||
p, err = query.GetFullProject(context.Background(), projectID)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
p.Name = body["project_name"][x]
|
||||
p.URL = body["project_repo"][x]
|
||||
p.DocURL = body["project_docs"][x]
|
||||
p.Description = body["project_description"][x]
|
||||
projects = append(projects, p)
|
||||
}
|
||||
return projects
|
||||
}
|
||||
@ -3,3 +3,8 @@ package types
|
||||
type Username struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type LoginUser struct {
|
||||
Email string
|
||||
Password string
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
# test
|
||||
# About
|
||||
|
||||
## WIP
|
||||
|
||||
Mijn portfolio website heb ik volledig gemaakt in go. Hiervoor heb ik gebruik gemaakt van gomponents en bijgeleverde plugins. Gomponents is een library waarmee ik binnen go html kan schrijven als object. Voor alle functionaliteit heb ik gebruik gemaakt van htmx.
|
||||
|
||||
Start typing here...
|
||||
@ -18,7 +18,8 @@ func (User) Fields() []ent.Field {
|
||||
Unique(),
|
||||
field.String("email").
|
||||
Unique(),
|
||||
field.String("password"),
|
||||
field.String("password").
|
||||
Sensitive(),
|
||||
field.Enum("role").
|
||||
Values("owner", "admin", "user", "visitor"),
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ type User struct {
|
||||
// Email holds the value of the "email" field.
|
||||
Email string `json:"email,omitempty"`
|
||||
// Password holds the value of the "password" field.
|
||||
Password string `json:"password,omitempty"`
|
||||
Password string `json:"-"`
|
||||
// Role holds the value of the "role" field.
|
||||
Role user.Role `json:"role,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
@ -165,8 +165,7 @@ func (u *User) String() string {
|
||||
builder.WriteString("email=")
|
||||
builder.WriteString(u.Email)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("password=")
|
||||
builder.WriteString(u.Password)
|
||||
builder.WriteString("password=<sensitive>")
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("role=")
|
||||
builder.WriteString(fmt.Sprintf("%v", u.Role))
|
||||
|
||||
@ -69,6 +69,19 @@ func GetFullProject(ctx context.Context, projectID int) (*ent.Project, error) {
|
||||
return p, err
|
||||
}
|
||||
|
||||
func GetFullProjects(ctx context.Context) ([]*ent.Project, error) {
|
||||
|
||||
p, err := database.Client.Project.
|
||||
Query().
|
||||
WithUsers().
|
||||
WithTeams().
|
||||
All(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get project: %w", err)
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
|
||||
func GetProjects(ctx context.Context) (ent.Projects, error) {
|
||||
|
||||
p, err := database.Client.Project.Query().
|
||||
|
||||
2
go.mod
2
go.mod
@ -10,6 +10,7 @@ require (
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/maragudk/gomponents v0.20.2
|
||||
github.com/maragudk/gomponents-htmx v0.5.0
|
||||
github.com/rs/cors v1.11.0
|
||||
github.com/willoma/bulma-gomponents v0.11.1
|
||||
github.com/willoma/gomplements v0.6.1
|
||||
golang.org/x/crypto v0.23.0
|
||||
@ -24,7 +25,6 @@ require (
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/rs/cors v1.11.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.2 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
|
||||
@ -18,7 +18,6 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
|
||||
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
@ -63,23 +62,16 @@ github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY3
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg=
|
||||
k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
|
||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
g "github.com/maragudk/gomponents"
|
||||
hx "github.com/maragudk/gomponents-htmx"
|
||||
. "github.com/maragudk/gomponents/html"
|
||||
b "github.com/willoma/bulma-gomponents"
|
||||
)
|
||||
|
||||
func Edit() g.Node {
|
||||
@ -20,3 +21,15 @@ func Edit() g.Node {
|
||||
hx.Swap("outerHTML")),
|
||||
)
|
||||
}
|
||||
|
||||
func Save() g.Node {
|
||||
return Div(
|
||||
Class("px-3 py-2"),
|
||||
hx.Patch(BaseUrl+"/projects"),
|
||||
hx.Swap("none"),
|
||||
hx.SelectOOB("true"),
|
||||
hx.Include("[name='project_name'], [name='project_repo'], [name='project_docs'], [name='project_description'], [name='project_id']"),
|
||||
hx.Confirm("Are u sure?"),
|
||||
b.Button("Save", b.Link),
|
||||
)
|
||||
}
|
||||
@ -7,6 +7,7 @@ import (
|
||||
b "github.com/willoma/bulma-gomponents"
|
||||
e "github.com/willoma/gomplements"
|
||||
"portfolio/database/ent"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ProjectList(projects []*ent.Project) g.Node {
|
||||
@ -55,17 +56,23 @@ func EditProject(project *ent.Project) g.Node {
|
||||
b.ImgSq64,
|
||||
),
|
||||
),
|
||||
Input(Type("hidden"), Value(strconv.Itoa(project.ID)), Name("project_id")),
|
||||
//b.Label("ID: "+strconv.Itoa(project.ID), Name("project_id")),
|
||||
b.Label("Name"),
|
||||
b.Textarea(project.Name, b.Rows(1)),
|
||||
b.Textarea(project.Name, b.Rows(1), Name("project_name")),
|
||||
b.Subtitle(
|
||||
6,
|
||||
b.Label("Repo"),
|
||||
b.Textarea(project.URL, b.Rows(1)),
|
||||
b.Textarea(project.URL, b.Rows(1), Name("project_repo")),
|
||||
b.Label("Docs"),
|
||||
b.Textarea(project.DocURL, b.Rows(1))),
|
||||
b.Textarea(project.DocURL, b.Rows(1), Name("project_docs"))),
|
||||
),
|
||||
b.Content(
|
||||
b.Textarea(project.Description),
|
||||
b.Textarea(project.Description, Name("project_description")),
|
||||
),
|
||||
|
||||
//b.CardFooter(
|
||||
//Save(),
|
||||
//),
|
||||
)
|
||||
}
|
||||
|
||||
@ -42,5 +42,6 @@ func CreateProjectEditBody(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
Body(
|
||||
components.EditProjectList(projects),
|
||||
components.Save(),
|
||||
).Render(w)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user