commit
c606efd7dc
@ -25,6 +25,7 @@ func ApiRoutes() *http.ServeMux {
|
|||||||
//Project
|
//Project
|
||||||
mux.HandleFunc("POST /project", handlers.CreateProjectHandler)
|
mux.HandleFunc("POST /project", handlers.CreateProjectHandler)
|
||||||
mux.HandleFunc("PATCH /project/{id}", handlers.UpdateProjectHandler)
|
mux.HandleFunc("PATCH /project/{id}", handlers.UpdateProjectHandler)
|
||||||
|
mux.HandleFunc("PATCH /projects", handlers.UpdateProjectsHandler)
|
||||||
mux.HandleFunc("GET /project/{id}", handlers.GetProjectHandler)
|
mux.HandleFunc("GET /project/{id}", handlers.GetProjectHandler)
|
||||||
mux.HandleFunc("GET /projects", handlers.GetProjectsHandler)
|
mux.HandleFunc("GET /projects", handlers.GetProjectsHandler)
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,10 @@ module openAPI
|
|||||||
|
|
||||||
go 1.22
|
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 (
|
require (
|
||||||
github.com/getkin/kin-openapi v0.124.0 // indirect
|
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 h1:Lj+OmK3+dKMuR8OdlnUeIrgdt8JkcNlA9isS2Aey5Mg=
|
||||||
github.com/a-h/rest v0.0.0-20240504113546-6729b3328f85/go.mod h1:5wH1imbpKnMjll8xpGRdg0Sb0HwH7nYiM5VPm0Zl5Bw=
|
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=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/a-h/rest"
|
"github.com/a-h/rest"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,13 +14,12 @@ func main() {
|
|||||||
api = rest.NewAPI("portfolio")
|
api = rest.NewAPI("portfolio")
|
||||||
api.StripPkgPaths = []string{"github.com/a-h/rest/example", "github.com/a-h/respond"}
|
api.StripPkgPaths = []string{"github.com/a-h/rest/example", "github.com/a-h/respond"}
|
||||||
|
|
||||||
api.Get("/nfc/{uid}").
|
// register models
|
||||||
HasPathParameter("uid", rest.PathParam{
|
RegisterModels()
|
||||||
Description: "id of the user",
|
// register endpoints
|
||||||
Regexp: `\d+`,
|
RegisterGenericEndpoints()
|
||||||
}).
|
RegisterUserEndpoints()
|
||||||
HasDescription("Get nfc data by uid.").
|
RegisterProjectEndpoints()
|
||||||
HasResponseModel(http.StatusOK, rest.ModelOf[string]())
|
|
||||||
|
|
||||||
// Create the specification.
|
// Create the specification.
|
||||||
spec, err := api.Spec()
|
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,12 +65,11 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CanEdit(w http.ResponseWriter, r *http.Request) {
|
func CanEdit(w http.ResponseWriter, r *http.Request) {
|
||||||
jwtCookie, _ := r.Cookie("jwt")
|
|
||||||
|
|
||||||
if jwtCookie != nil {
|
_, audience, err := jwt.VerifyUser(r)
|
||||||
_, audience, err := jwt.VerifyJWT(jwtCookie.Value)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalServerErrorHandler(w, err)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte(""))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if audience == "owner" || audience == "visitor" {
|
if audience == "owner" || audience == "visitor" {
|
||||||
@ -81,7 +80,4 @@ func CanEdit(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write([]byte(""))
|
w.Write([]byte(""))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write([]byte(""))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"portfolio/api/service/jwt"
|
"portfolio/api/service/jwt"
|
||||||
|
"portfolio/api/service/parse"
|
||||||
"portfolio/database/ent"
|
"portfolio/database/ent"
|
||||||
"portfolio/database/query"
|
"portfolio/database/query"
|
||||||
"strconv"
|
"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) {
|
func GetProjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
projectID, err := strconv.Atoi(r.PathValue("id"))
|
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)
|
User, err := query.GetUser(context.Background(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
UnprocessableEntityHandler(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ func GetUserHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
err = json.NewEncoder(w).Encode(User)
|
err = json.NewEncoder(w).Encode(User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
InternalServerErrorHandler(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func VerifyUser(r *http.Request) (int, string, error) {
|
func VerifyUser(r *http.Request) (int, string, error) {
|
||||||
|
jwtCookie, _ := r.Cookie("jwt")
|
||||||
|
|
||||||
|
if jwtCookie != nil {
|
||||||
|
return VerifyJWT(jwtCookie.Value)
|
||||||
|
}
|
||||||
bearerToken := r.Header.Get("Authorization")
|
bearerToken := r.Header.Get("Authorization")
|
||||||
jwtToken := ""
|
jwtToken := ""
|
||||||
if len(bearerToken) > 7 {
|
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 {
|
type Username struct {
|
||||||
Name string
|
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(),
|
Unique(),
|
||||||
field.String("email").
|
field.String("email").
|
||||||
Unique(),
|
Unique(),
|
||||||
field.String("password"),
|
field.String("password").
|
||||||
|
Sensitive(),
|
||||||
field.Enum("role").
|
field.Enum("role").
|
||||||
Values("owner", "admin", "user", "visitor"),
|
Values("owner", "admin", "user", "visitor"),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ type User struct {
|
|||||||
// Email holds the value of the "email" field.
|
// Email holds the value of the "email" field.
|
||||||
Email string `json:"email,omitempty"`
|
Email string `json:"email,omitempty"`
|
||||||
// Password holds the value of the "password" field.
|
// 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 holds the value of the "role" field.
|
||||||
Role user.Role `json:"role,omitempty"`
|
Role user.Role `json:"role,omitempty"`
|
||||||
// Edges holds the relations/edges for other nodes in the graph.
|
// 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("email=")
|
||||||
builder.WriteString(u.Email)
|
builder.WriteString(u.Email)
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
builder.WriteString("password=")
|
builder.WriteString("password=<sensitive>")
|
||||||
builder.WriteString(u.Password)
|
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
builder.WriteString("role=")
|
builder.WriteString("role=")
|
||||||
builder.WriteString(fmt.Sprintf("%v", u.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
|
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) {
|
func GetProjects(ctx context.Context) (ent.Projects, error) {
|
||||||
|
|
||||||
p, err := database.Client.Project.Query().
|
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/lib/pq v1.10.9
|
||||||
github.com/maragudk/gomponents v0.20.2
|
github.com/maragudk/gomponents v0.20.2
|
||||||
github.com/maragudk/gomponents-htmx v0.5.0
|
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/bulma-gomponents v0.11.1
|
||||||
github.com/willoma/gomplements v0.6.1
|
github.com/willoma/gomplements v0.6.1
|
||||||
golang.org/x/crypto v0.23.0
|
golang.org/x/crypto v0.23.0
|
||||||
@ -24,7 +25,6 @@ require (
|
|||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
|
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v1.0.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
|
github.com/zclconf/go-cty v1.14.2 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/text v0.15.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/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 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
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 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
||||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
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=
|
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 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
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 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
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 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
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 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
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 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
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 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg=
|
||||||
k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
|
k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
|
||||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
g "github.com/maragudk/gomponents"
|
g "github.com/maragudk/gomponents"
|
||||||
hx "github.com/maragudk/gomponents-htmx"
|
hx "github.com/maragudk/gomponents-htmx"
|
||||||
. "github.com/maragudk/gomponents/html"
|
. "github.com/maragudk/gomponents/html"
|
||||||
|
b "github.com/willoma/bulma-gomponents"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Edit() g.Node {
|
func Edit() g.Node {
|
||||||
@ -20,3 +21,15 @@ func Edit() g.Node {
|
|||||||
hx.Swap("outerHTML")),
|
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"
|
b "github.com/willoma/bulma-gomponents"
|
||||||
e "github.com/willoma/gomplements"
|
e "github.com/willoma/gomplements"
|
||||||
"portfolio/database/ent"
|
"portfolio/database/ent"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProjectList(projects []*ent.Project) g.Node {
|
func ProjectList(projects []*ent.Project) g.Node {
|
||||||
@ -55,17 +56,23 @@ func EditProject(project *ent.Project) g.Node {
|
|||||||
b.ImgSq64,
|
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.Label("Name"),
|
||||||
b.Textarea(project.Name, b.Rows(1)),
|
b.Textarea(project.Name, b.Rows(1), Name("project_name")),
|
||||||
b.Subtitle(
|
b.Subtitle(
|
||||||
6,
|
6,
|
||||||
b.Label("Repo"),
|
b.Label("Repo"),
|
||||||
b.Textarea(project.URL, b.Rows(1)),
|
b.Textarea(project.URL, b.Rows(1), Name("project_repo")),
|
||||||
b.Label("Docs"),
|
b.Label("Docs"),
|
||||||
b.Textarea(project.DocURL, b.Rows(1))),
|
b.Textarea(project.DocURL, b.Rows(1), Name("project_docs"))),
|
||||||
),
|
),
|
||||||
b.Content(
|
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)
|
w.WriteHeader(http.StatusOK)
|
||||||
Body(
|
Body(
|
||||||
components.EditProjectList(projects),
|
components.EditProjectList(projects),
|
||||||
|
components.Save(),
|
||||||
).Render(w)
|
).Render(w)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user