add templ engine
This commit is contained in:
1
.task/checksum/generate
Normal file
1
.task/checksum/generate
Normal file
@ -0,0 +1 @@
|
|||||||
|
cf55887b91f81f789d59205c41f8368
|
||||||
12
Taskfile.yml
12
Taskfile.yml
@ -18,12 +18,24 @@ tasks:
|
|||||||
install_tools:
|
install_tools:
|
||||||
cmds:
|
cmds:
|
||||||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2
|
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2
|
||||||
|
- go install github.com/a-h/templ/cmd/templ@v0.2.513
|
||||||
|
generate:
|
||||||
|
cmds:
|
||||||
|
- "$GOBIN/templ generate"
|
||||||
|
sources:
|
||||||
|
- "internal/kurious/ports/http/templ/*.templ"
|
||||||
|
generates:
|
||||||
|
- "internal/kurious/ports/http/templ/*.go"
|
||||||
check:
|
check:
|
||||||
cmds:
|
cmds:
|
||||||
- "$GOBIN/golangci-lint run ./..."
|
- "$GOBIN/golangci-lint run ./..."
|
||||||
|
deps:
|
||||||
|
- generate
|
||||||
test:
|
test:
|
||||||
cmds:
|
cmds:
|
||||||
- go test ./internal/...
|
- go test ./internal/...
|
||||||
|
deps:
|
||||||
|
- generate
|
||||||
build_web:
|
build_web:
|
||||||
cmds:
|
cmds:
|
||||||
- go build -o $GOBIN/kuriousweb -v -ldflags '{{.LDFLAGS}}' cmd/kuriweb/*.go
|
- go build -o $GOBIN/kuriousweb -v -ldflags '{{.LDFLAGS}}' cmd/kuriweb/*.go
|
||||||
|
|||||||
@ -93,13 +93,16 @@ func app(ctx context.Context) error {
|
|||||||
defer xcontext.LogInfo(ctx, log, "finished bprocess")
|
defer xcontext.LogInfo(ctx, log, "finished bprocess")
|
||||||
|
|
||||||
bgProcess.Run()
|
bgProcess.Run()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
xcontext.LogInfo(ctx, log, "running cancelation waiter")
|
xcontext.LogInfo(ctx, log, "running cancelation waiter")
|
||||||
defer xcontext.LogInfo(ctx, log, "finished cancelation waiter")
|
defer xcontext.LogInfo(ctx, log, "finished cancelation waiter")
|
||||||
|
|
||||||
<-egctx.Done()
|
<-egctx.Done()
|
||||||
|
|
||||||
sdctx, sdcancel := context.WithTimeout(context.Background(), time.Second*15)
|
sdctx, sdcancel := context.WithTimeout(context.Background(), time.Second*15)
|
||||||
defer sdcancel()
|
defer sdcancel()
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,8 @@ import (
|
|||||||
func makePathTemplate(params ...string) string {
|
func makePathTemplate(params ...string) string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
for _, param := range params {
|
for _, param := range params {
|
||||||
|
sb.Grow(len(param) + 3)
|
||||||
|
|
||||||
sb.WriteRune('/')
|
sb.WriteRune('/')
|
||||||
sb.WriteRune('{')
|
sb.WriteRune('{')
|
||||||
sb.WriteString(param)
|
sb.WriteString(param)
|
||||||
@ -26,14 +28,21 @@ func makePathTemplate(params ...string) string {
|
|||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupHTTP(cfg config.HTTP, srv xhttp.Server, log *slog.Logger) *http.Server {
|
func setupHTTPWithTempl(srv xhttp.Server, router *mux.Router, log *slog.Logger) {
|
||||||
router := mux.NewRouter()
|
coursesRouter := router.PathPrefix("/courses").Subrouter().StrictSlash(true)
|
||||||
|
|
||||||
|
coursesAPI := srv.CoursesByTempl()
|
||||||
|
|
||||||
|
coursesRouter.HandleFunc("/", coursesAPI.List).Methods(http.MethodGet)
|
||||||
|
coursesListLearningOnlyPath := makePathTemplate(xhttp.LearningTypePathParam)
|
||||||
|
coursesRouter.HandleFunc(coursesListLearningOnlyPath, coursesAPI.List).Methods(http.MethodGet)
|
||||||
|
coursesListFullPath := makePathTemplate(xhttp.LearningTypePathParam, xhttp.ThematicTypePathParam)
|
||||||
|
coursesRouter.HandleFunc(coursesListFullPath, coursesAPI.List).Methods(http.MethodGet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupHTTPWithGoTemplates(srv xhttp.Server, router *mux.Router, log *slog.Logger) {
|
||||||
coursesAPI := srv.Courses()
|
coursesAPI := srv.Courses()
|
||||||
|
|
||||||
router.Use(mux.CORSMethodMiddleware(router))
|
|
||||||
router.Use(middlewareLogger(log))
|
|
||||||
// router.HandleFunc("/updatedesc", coursesAPI.UdpateDescription).Methods(http.MethodPost)
|
|
||||||
coursesRouter := router.PathPrefix("/courses").Subrouter().StrictSlash(true)
|
coursesRouter := router.PathPrefix("/courses").Subrouter().StrictSlash(true)
|
||||||
coursesRouter.HandleFunc("/", coursesAPI.List).Methods(http.MethodGet)
|
coursesRouter.HandleFunc("/", coursesAPI.List).Methods(http.MethodGet)
|
||||||
coursesListLearningOnlyPath := makePathTemplate(xhttp.LearningTypePathParam)
|
coursesListLearningOnlyPath := makePathTemplate(xhttp.LearningTypePathParam)
|
||||||
@ -46,6 +55,23 @@ func setupHTTP(cfg config.HTTP, srv xhttp.Server, log *slog.Logger) *http.Server
|
|||||||
courseRouter.HandleFunc("/short", coursesAPI.GetShort).Methods(http.MethodGet)
|
courseRouter.HandleFunc("/short", coursesAPI.GetShort).Methods(http.MethodGet)
|
||||||
courseRouter.HandleFunc("/editdesc", coursesAPI.RenderEditDescription).Methods(http.MethodGet)
|
courseRouter.HandleFunc("/editdesc", coursesAPI.RenderEditDescription).Methods(http.MethodGet)
|
||||||
courseRouter.HandleFunc("/description", coursesAPI.UpdateCourseDescription).Methods(http.MethodPut)
|
courseRouter.HandleFunc("/description", coursesAPI.UpdateCourseDescription).Methods(http.MethodPut)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupHTTP(cfg config.HTTP, srv xhttp.Server, log *slog.Logger) *http.Server {
|
||||||
|
router := mux.NewRouter()
|
||||||
|
|
||||||
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
|
router.Use(mux.CORSMethodMiddleware(router))
|
||||||
|
router.Use(middlewareLogger(log, cfg.Engine))
|
||||||
|
|
||||||
|
if cfg.Engine == "templ" {
|
||||||
|
setupHTTPWithTempl(srv, router, log)
|
||||||
|
} else {
|
||||||
|
setupHTTPWithGoTemplates(srv, router, log)
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.MountLive {
|
if cfg.MountLive {
|
||||||
fs := http.FileServer(http.Dir("./assets/kurious/static/"))
|
fs := http.FileServer(http.Dir("./assets/kurious/static/"))
|
||||||
@ -85,7 +111,7 @@ func setupHTTP(cfg config.HTTP, srv xhttp.Server, log *slog.Logger) *http.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func middlewareLogger(log *slog.Logger) mux.MiddlewareFunc {
|
func middlewareLogger(log *slog.Logger, engine string) mux.MiddlewareFunc {
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@ -93,7 +119,11 @@ func middlewareLogger(log *slog.Logger) mux.MiddlewareFunc {
|
|||||||
if requestID == "" {
|
if requestID == "" {
|
||||||
requestID = generator.RandomInt64ID()
|
requestID = generator.RandomInt64ID()
|
||||||
}
|
}
|
||||||
ctx = xcontext.WithLogFields(ctx, slog.String("request_id", requestID))
|
ctx = xcontext.WithLogFields(
|
||||||
|
ctx,
|
||||||
|
slog.String("request_id", requestID),
|
||||||
|
slog.String("engine", engine),
|
||||||
|
)
|
||||||
|
|
||||||
xcontext.LogInfo(
|
xcontext.LogInfo(
|
||||||
ctx, log, "incoming request",
|
ctx, log, "incoming request",
|
||||||
|
|||||||
1
go.mod
1
go.mod
@ -15,6 +15,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/a-h/templ v0.2.513 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/uuid v1.4.0 // indirect
|
github.com/google/uuid v1.4.0 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -515,6 +515,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/a-h/templ v0.2.513 h1:ZmwGAOx4NYllnHy+FTpusc4+c5msoMpPIYX0Oy3dNqw=
|
||||||
|
github.com/a-h/templ v0.2.513/go.mod h1:9gZxTLtRzM3gQxO8jr09Na0v8/jfliS97S9W5SScanM=
|
||||||
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
||||||
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
|
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
|
|||||||
@ -3,4 +3,5 @@ package config
|
|||||||
type HTTP struct {
|
type HTTP struct {
|
||||||
ListenAddr string `json:"listen_addr"`
|
ListenAddr string `json:"listen_addr"`
|
||||||
MountLive bool `json:"mount_live"`
|
MountLive bool `json:"mount_live"`
|
||||||
|
Engine string `json:"engine"`
|
||||||
}
|
}
|
||||||
|
|||||||
139
internal/kurious/ports/http/coursev2.go
Normal file
139
internal/kurious/ports/http/coursev2.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.loyso.art/frx/kurious/internal/common/xslices"
|
||||||
|
"git.loyso.art/frx/kurious/internal/kurious/app/query"
|
||||||
|
"git.loyso.art/frx/kurious/internal/kurious/domain"
|
||||||
|
xtempl "git.loyso.art/frx/kurious/internal/kurious/ports/http/templ"
|
||||||
|
"git.loyso.art/frx/kurious/internal/kurious/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
type courseTemplServer struct {
|
||||||
|
app service.Application
|
||||||
|
log *slog.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTemplListCoursesParams(in ...domain.Course) xtempl.ListCoursesParams {
|
||||||
|
coursesBySubcategory := make(map[string][]xtempl.CourseInfo, len(in))
|
||||||
|
subcategoriesByCategories := make(map[string]map[string]struct{}, len(in))
|
||||||
|
categoryByID := make(map[string]xtempl.CategoryBaseInfo, len(in))
|
||||||
|
|
||||||
|
xslices.ForEach(in, func(c domain.Course) {
|
||||||
|
courseInfo := xtempl.CourseInfo{
|
||||||
|
ID: c.ID,
|
||||||
|
Name: c.Name,
|
||||||
|
FullPrice: int(c.FullPrice),
|
||||||
|
ImageLink: c.ImageLink,
|
||||||
|
OriginLink: c.OriginLink,
|
||||||
|
}
|
||||||
|
|
||||||
|
coursesBySubcategory[c.ThematicID] = append(coursesBySubcategory[c.ThematicID], courseInfo)
|
||||||
|
|
||||||
|
if _, ok := subcategoriesByCategories[c.LearningTypeID]; !ok {
|
||||||
|
subcategoriesByCategories[c.LearningTypeID] = map[string]struct{}{}
|
||||||
|
}
|
||||||
|
subcategoriesByCategories[c.LearningTypeID][c.ThematicID] = struct{}{}
|
||||||
|
|
||||||
|
if _, ok := categoryByID[c.LearningTypeID]; !ok {
|
||||||
|
categoryByID[c.LearningTypeID] = xtempl.CategoryBaseInfo{
|
||||||
|
ID: c.LearningTypeID,
|
||||||
|
Name: c.LearningType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := categoryByID[c.ThematicID]; !ok {
|
||||||
|
categoryByID[c.ThematicID] = xtempl.CategoryBaseInfo{
|
||||||
|
ID: c.ThematicID,
|
||||||
|
Name: c.Thematic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var out xtempl.ListCoursesParams
|
||||||
|
for categoryID, subcategoriesID := range subcategoriesByCategories {
|
||||||
|
outCategory := xtempl.CategoryContainer{
|
||||||
|
CategoryBaseInfo: categoryByID[categoryID],
|
||||||
|
}
|
||||||
|
|
||||||
|
for subcategoryID := range subcategoriesID {
|
||||||
|
outSubcategory := xtempl.SubcategoryContainer{
|
||||||
|
CategoryBaseInfo: categoryByID[subcategoryID],
|
||||||
|
Courses: coursesBySubcategory[subcategoryID],
|
||||||
|
}
|
||||||
|
|
||||||
|
outCategory.Subcategories = append(outCategory.Subcategories, outSubcategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Categories = append(out.Categories, outCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c courseTemplServer) List(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
|
stats := xtempl.MakeNewStats(10_240, 2_560_000, 1800)
|
||||||
|
|
||||||
|
pathParams, err := parseListCoursesParams(r)
|
||||||
|
if handleError(ctx, err, w, c.log, "unable to parse list courses params") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
listCoursesResult, err := c.app.Queries.ListCourses.Handle(ctx, query.ListCourse{
|
||||||
|
CourseThematic: pathParams.courseThematic,
|
||||||
|
LearningType: pathParams.learningType,
|
||||||
|
Limit: pathParams.perPage,
|
||||||
|
NextPageToken: pathParams.nextPageToken,
|
||||||
|
})
|
||||||
|
if handleError(ctx, err, w, c.log, "unable to list courses") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params := makeTemplListCoursesParams(listCoursesResult.Courses...)
|
||||||
|
|
||||||
|
learningTypeResult, err := c.app.Queries.ListLearningTypes.Handle(ctx, query.ListLearningTypes{})
|
||||||
|
if handleError(ctx, err, w, c.log, "unable to list learning types") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params.FilterForm.AvailableLearningTypes = xslices.Map(learningTypeResult.LearningTypes, func(in query.LearningType) xtempl.Category {
|
||||||
|
outcategory := xtempl.Category{
|
||||||
|
ID: in.ID,
|
||||||
|
Name: in.Name,
|
||||||
|
}
|
||||||
|
if in.ID == pathParams.learningType {
|
||||||
|
params.FilterForm.BreadcrumbsParams.ActiveLearningType = outcategory
|
||||||
|
}
|
||||||
|
|
||||||
|
return outcategory
|
||||||
|
})
|
||||||
|
|
||||||
|
if pathParams.learningType != "" {
|
||||||
|
courseThematicsResult, err := c.app.Queries.ListCourseThematics.Handle(ctx, query.ListCourseThematics{
|
||||||
|
LearningTypeID: pathParams.learningType,
|
||||||
|
})
|
||||||
|
if handleError(ctx, err, w, c.log, "unab;e to list course thematics") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params.FilterForm.AvailableCourseThematics = xslices.Map(courseThematicsResult.CourseThematics, func(in query.CourseThematic) xtempl.Category {
|
||||||
|
outcategory := xtempl.Category{
|
||||||
|
ID: in.ID,
|
||||||
|
Name: in.Name,
|
||||||
|
}
|
||||||
|
if pathParams.courseThematic == in.ID {
|
||||||
|
params.FilterForm.BreadcrumbsParams.ActiveCourseThematic = outcategory
|
||||||
|
}
|
||||||
|
|
||||||
|
return outcategory
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
err = xtempl.ListCourses(stats, params).Render(ctx, w)
|
||||||
|
if handleError(ctx, err, w, c.log, "unable to render list courses") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -27,6 +27,10 @@ func (s Server) Courses() courseServer {
|
|||||||
return courseServer(s)
|
return courseServer(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Server) CoursesByTempl() courseTemplServer {
|
||||||
|
return courseTemplServer(s)
|
||||||
|
}
|
||||||
|
|
||||||
func handleError(ctx context.Context, err error, w http.ResponseWriter, log *slog.Logger, msg string) bool {
|
func handleError(ctx context.Context, err error, w http.ResponseWriter, log *slog.Logger, msg string) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
|
|||||||
22
internal/kurious/ports/http/templ/common.templ
Normal file
22
internal/kurious/ports/http/templ/common.templ
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package templ
|
||||||
|
|
||||||
|
templ button(title string, attributes templ.Attributes) {
|
||||||
|
<button class="button" { attributes... }>{ title }</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ buttonRedirect(id, title string, linkTo string) {
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
id={ "origin-link-" + id }
|
||||||
|
>
|
||||||
|
{ title }
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@onclickRedirect("origin-link-" + id, linkTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
script onclickRedirect(id, to string) {
|
||||||
|
document.getElementById(id).onclick = () => {
|
||||||
|
location.href = to
|
||||||
|
}
|
||||||
|
}
|
||||||
116
internal/kurious/ports/http/templ/common_templ.go
Normal file
116
internal/kurious/ports/http/templ/common_templ.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.513
|
||||||
|
package templ
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func button(title string, attributes templ.Attributes) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"button\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attributes)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 string
|
||||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/common.templ`, Line: 3, Col: 49}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func buttonRedirect(id, title string, linkTo string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var3 == nil {
|
||||||
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"button\" id=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString("origin-link-" + id))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var4 string
|
||||||
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/common.templ`, Line: 11, Col: 8}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = onclickRedirect("origin-link-"+id, linkTo).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func onclickRedirect(id, to string) templ.ComponentScript {
|
||||||
|
return templ.ComponentScript{
|
||||||
|
Name: `__templ_onclickRedirect_47ae`,
|
||||||
|
Function: `function __templ_onclickRedirect_47ae(id, to){document.getElementById(id).onclick = () => {
|
||||||
|
location.href = to
|
||||||
|
}}`,
|
||||||
|
Call: templ.SafeScript(`__templ_onclickRedirect_47ae`, id, to),
|
||||||
|
CallInline: templ.SafeScriptInline(`__templ_onclickRedirect_47ae`, id, to),
|
||||||
|
}
|
||||||
|
}
|
||||||
62
internal/kurious/ports/http/templ/header.templ
Normal file
62
internal/kurious/ports/http/templ/header.templ
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package templ
|
||||||
|
|
||||||
|
templ head() {
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<title>Courses Aggregator</title>
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.8.0"></script>
|
||||||
|
<script src="https://unpkg.com/htmx.org/dist/ext/json-enc.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"/>
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/>
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/>
|
||||||
|
<link rel="manifest" href="/site.webmanifest"/>
|
||||||
|
</head>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ navigation() {
|
||||||
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="navbar-brand">
|
||||||
|
Courses
|
||||||
|
</div>
|
||||||
|
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false">
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
<div id="navbarBasicExample" class="navbar-menu">
|
||||||
|
<div class="navbar-start">
|
||||||
|
<a class="navbar-item">
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
<a class="navbar-item">
|
||||||
|
Find
|
||||||
|
</a>
|
||||||
|
<div class="navbar-item has-dropdown is-hoverable">
|
||||||
|
<a class="navbar-link">
|
||||||
|
More
|
||||||
|
</a>
|
||||||
|
<div class="navbar-dropdown">
|
||||||
|
<a class="navbar-item">
|
||||||
|
About
|
||||||
|
</a>
|
||||||
|
<a class="navbar-item">
|
||||||
|
Contact
|
||||||
|
</a>
|
||||||
|
<hr class="navbar-divider"/>
|
||||||
|
<a class="navbar-item">
|
||||||
|
Report an issue
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ footer() {
|
||||||
|
<footer>
|
||||||
|
Here will be a footer
|
||||||
|
</footer>
|
||||||
|
}
|
||||||
182
internal/kurious/ports/http/templ/header_templ.go
Normal file
182
internal/kurious/ports/http/templ/header_templ.go
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.513
|
||||||
|
package templ
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func head() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var2 := `Courses Aggregator`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title><script src=\"https://unpkg.com/htmx.org@1.8.0\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var3 := ``
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</script><script src=\"https://unpkg.com/htmx.org/dist/ext/json-enc.js\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var4 := ``
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</script><link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css\"><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\"><link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\"><link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/favicon-16x16.png\"><link rel=\"manifest\" href=\"/site.webmanifest\"></head>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func navigation() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var5 == nil {
|
||||||
|
templ_7745c5c3_Var5 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"navbar\" role=\"navigation\" aria-label=\"main navigation\"><div class=\"navbar-brand\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var6 := `Courses`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><a role=\"button\" class=\"navbar-burger\" aria-label=\"menu\" aria-expanded=\"false\"><span aria-hidden=\"true\"></span> <span aria-hidden=\"true\"></span> <span aria-hidden=\"true\"></span></a><div id=\"navbarBasicExample\" class=\"navbar-menu\"><div class=\"navbar-start\"><a class=\"navbar-item\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var7 := `Home`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> <a class=\"navbar-item\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var8 := `Find`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a><div class=\"navbar-item has-dropdown is-hoverable\"><a class=\"navbar-link\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var9 := `More`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a><div class=\"navbar-dropdown\"><a class=\"navbar-item\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var10 := `About`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> <a class=\"navbar-item\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var11 := `Contact`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a><hr class=\"navbar-divider\"><a class=\"navbar-item\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var12 := `Report an issue`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div></div></div></div></nav>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func footer() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var13 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var13 == nil {
|
||||||
|
templ_7745c5c3_Var13 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<footer>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var14 := `Here will be a footer`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</footer>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
209
internal/kurious/ports/http/templ/list.templ
Normal file
209
internal/kurious/ports/http/templ/list.templ
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package templ
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
script breadcrumbsLoad() {
|
||||||
|
const formFilterOnSubmit = event => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const lt = document.getElementById('learning-type-filter');
|
||||||
|
const ct = document.getElementById('course-thematic-filter');
|
||||||
|
|
||||||
|
const prefix = (lt !== null && lt.value !== '') ? `/courses/${lt.value}` : `/courses`;
|
||||||
|
const out = (ct !== null && ct.value !== '') ? `${prefix}/${ct.value}` : prefix;
|
||||||
|
|
||||||
|
document.location.assign(out);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const ff = document.getElementById('filter-form');
|
||||||
|
if (ff === null) return;
|
||||||
|
ff.addEventListener('submit', formFilterOnSubmit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
templ breadcrumbItem(enabled bool, link string, isLink bool, title string) {
|
||||||
|
if enabled {
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
if !isEmpty(link) {
|
||||||
|
href={ templ.SafeURL("/courses" + link) }
|
||||||
|
itemprop="url"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
itemprop="title"
|
||||||
|
if isEmpty(link) {
|
||||||
|
itemprop="url"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ title }
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
templ listCourseHeader(params FilterFormParams) {
|
||||||
|
<div class="container block">
|
||||||
|
@breadcrumb(params.BreadcrumbsParams)
|
||||||
|
@filterForm(params)
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ breadcrumb(params BreadcrumbsParams) {
|
||||||
|
<nav
|
||||||
|
class="breadcrumb"
|
||||||
|
aria-label="breadcrumbs"
|
||||||
|
itemprop="breadcrumb"
|
||||||
|
itemtype="https://schema.org/BreadcrumbList"
|
||||||
|
itemscope
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
@breadcrumbItem(true, "/courses", !isEmpty(params.ActiveLearningType.ID), "Курсы")
|
||||||
|
@breadcrumbItem(!params.ActiveLearningType.Empty(), "/" + params.ActiveLearningType.ID, !params.ActiveCourseThematic.Empty(), params.ActiveLearningType.Name)
|
||||||
|
@breadcrumbItem(!params.ActiveCourseThematic.Empty(), "", false, params.ActiveCourseThematic.Name)
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ filterForm(params FilterFormParams) {
|
||||||
|
<form id="filter-form" class="columns">
|
||||||
|
<div class="select">
|
||||||
|
<select id="learning-type-filter" name="learning_type">
|
||||||
|
<option value="">All learnings</option>
|
||||||
|
for _, item := range params.AvailableLearningTypes {
|
||||||
|
<option
|
||||||
|
value={ item.ID }
|
||||||
|
if item.ID == params.ActiveLearningType.ID {
|
||||||
|
selected
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ item.Name }
|
||||||
|
</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
if !params.ActiveLearningType.Empty() {
|
||||||
|
<div class="select">
|
||||||
|
<select id="course-thematic-filter" name="course_thematic">
|
||||||
|
<option value="">All course thematics</option>
|
||||||
|
for _, item := range params.AvailableCourseThematics {
|
||||||
|
<option
|
||||||
|
value={ item.ID }
|
||||||
|
if item.ID == params.ActiveCourseThematic.ID {
|
||||||
|
selected
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ item.Name }
|
||||||
|
</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@button("goto", templ.Attributes{"id": "go-to-filter"})
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ listCoursesContainer(categories []CategoryContainer) {
|
||||||
|
<div id="category-course-list" class="container">
|
||||||
|
for _, category := range categories {
|
||||||
|
<div class="box">
|
||||||
|
<div class="title is-3">
|
||||||
|
<a href={ templ.URL("/courses/" + category.ID) }>{ category.Name }</a>
|
||||||
|
</div>
|
||||||
|
<div class="subtitle is-6">
|
||||||
|
This category contains a lot of interesing courses. Check them out!
|
||||||
|
</div>
|
||||||
|
for _, subcategory := range category.Subcategories {
|
||||||
|
<div class="box">
|
||||||
|
<div class="title is-4">
|
||||||
|
<a href={ templ.URL(fmt.Sprintf("/courses/%s/%s", category.ID, subcategory.ID)) }>
|
||||||
|
{ subcategory.Name }
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="columns is-multiline">
|
||||||
|
for _, course := range subcategory.Courses {
|
||||||
|
@courseInfoElement(course)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ ListCourses(s stats, params ListCoursesParams) {
|
||||||
|
@root(s) {
|
||||||
|
@listCourseHeader(params.FilterForm)
|
||||||
|
@listCoursesContainer(params.Categories)
|
||||||
|
|
||||||
|
<div id="course-info"></div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
templ root(s stats) {
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
@head()
|
||||||
|
<body>
|
||||||
|
@navigation()
|
||||||
|
<nav class="level">
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Courses</p>
|
||||||
|
<p class="title">{ s.CoursesCount }</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Clients</p>
|
||||||
|
<p class="title">{ s.ClientsCount }</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Categories</p>
|
||||||
|
<p class="title">{ s.CategoriesCount }</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="section">
|
||||||
|
{ children... }
|
||||||
|
</div>
|
||||||
|
@footer()
|
||||||
|
@breadcrumbsLoad()
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ courseInfoElement(params CourseInfo) {
|
||||||
|
<article class="column is-one-quarter" hx-target="this" hx-swap="outerHTML">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-image">
|
||||||
|
<figure class="image">
|
||||||
|
<img src={ params.ImageLink }/>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-5">{ params.Name }</p>
|
||||||
|
<p class="subtitle is-8">oh well</p>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
if params.FullPrice > 0 {
|
||||||
|
<p>{ strconv.Itoa(params.FullPrice) } руб.</p>
|
||||||
|
} else {
|
||||||
|
<p>Бесплатно</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@buttonRedirect(params.ID, "Show course", params.OriginLink)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
}
|
||||||
714
internal/kurious/ports/http/templ/list_templ.go
Normal file
714
internal/kurious/ports/http/templ/list_templ.go
Normal file
@ -0,0 +1,714 @@
|
|||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.513
|
||||||
|
package templ
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func breadcrumbsLoad() templ.ComponentScript {
|
||||||
|
return templ.ComponentScript{
|
||||||
|
Name: `__templ_breadcrumbsLoad_9a1d`,
|
||||||
|
Function: `function __templ_breadcrumbsLoad_9a1d(){const formFilterOnSubmit = event => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const lt = document.getElementById('learning-type-filter');
|
||||||
|
const ct = document.getElementById('course-thematic-filter');
|
||||||
|
|
||||||
|
const prefix = (lt !== null && lt.value !== '') ? ` + "`" + `/courses/${lt.value}` + "`" + ` : ` + "`" + `/courses` + "`" + `;
|
||||||
|
const out = (ct !== null && ct.value !== '') ? ` + "`" + `${prefix}/${ct.value}` + "`" + ` : prefix;
|
||||||
|
|
||||||
|
document.location.assign(out);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const ff = document.getElementById('filter-form');
|
||||||
|
if (ff === null) return;
|
||||||
|
ff.addEventListener('submit', formFilterOnSubmit);
|
||||||
|
});}`,
|
||||||
|
Call: templ.SafeScript(`__templ_breadcrumbsLoad_9a1d`),
|
||||||
|
CallInline: templ.SafeScriptInline(`__templ_breadcrumbsLoad_9a1d`),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func breadcrumbItem(enabled bool, link string, isLink bool, title string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
if enabled {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><a")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !isEmpty(link) {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL("/courses" + link)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" itemprop=\"url\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("><span itemprop=\"title\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if isEmpty(link) {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" itemprop=\"url\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 string
|
||||||
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 41, Col: 12}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func listCourseHeader(params FilterFormParams) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var4 == nil {
|
||||||
|
templ_7745c5c3_Var4 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container block\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = breadcrumb(params.BreadcrumbsParams).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = filterForm(params).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func breadcrumb(params BreadcrumbsParams) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var5 == nil {
|
||||||
|
templ_7745c5c3_Var5 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"breadcrumb\" aria-label=\"breadcrumbs\" itemprop=\"breadcrumb\" itemtype=\"https://schema.org/BreadcrumbList\" itemscope><ul>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = breadcrumbItem(true, "/courses", !isEmpty(params.ActiveLearningType.ID), "Курсы").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = breadcrumbItem(!params.ActiveLearningType.Empty(), "/"+params.ActiveLearningType.ID, !params.ActiveCourseThematic.Empty(), params.ActiveLearningType.Name).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = breadcrumbItem(!params.ActiveCourseThematic.Empty(), "", false, params.ActiveCourseThematic.Name).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></nav>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterForm(params FilterFormParams) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var6 == nil {
|
||||||
|
templ_7745c5c3_Var6 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form id=\"filter-form\" class=\"columns\"><div class=\"select\"><select id=\"learning-type-filter\" name=\"learning_type\"><option value=\"\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var7 := `All learnings`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</option> ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, item := range params.AvailableLearningTypes {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<option value=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(item.ID))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if item.ID == params.ActiveLearningType.ID {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" selected")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var8 string
|
||||||
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 83, Col: 23}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</option>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</select></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !params.ActiveLearningType.Empty() {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"select\"><select id=\"course-thematic-filter\" name=\"course_thematic\"><option value=\"\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var9 := `All course thematics`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</option> ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, item := range params.AvailableCourseThematics {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<option value=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(item.ID))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if item.ID == params.ActiveCourseThematic.ID {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" selected")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var10 string
|
||||||
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 99, Col: 25}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</option>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</select></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = button("goto", templ.Attributes{"id": "go-to-filter"}).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</form>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func listCoursesContainer(categories []CategoryContainer) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var11 == nil {
|
||||||
|
templ_7745c5c3_Var11 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"category-course-list\" class=\"container\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, category := range categories {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"box\"><div class=\"title is-3\"><a href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var12 templ.SafeURL = templ.URL("/courses/" + category.ID)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var13 string
|
||||||
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(category.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 114, Col: 69}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"subtitle is-6\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var14 := `This category contains a lot of interesing courses. Check them out!`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, subcategory := range category.Subcategories {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"box\"><div class=\"title is-4\"><a href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var15 templ.SafeURL = templ.URL(fmt.Sprintf("/courses/%s/%s", category.ID, subcategory.ID))
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var15)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var16 string
|
||||||
|
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(subcategory.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 123, Col: 26}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a><div class=\"columns is-multiline\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, course := range subcategory.Courses {
|
||||||
|
templ_7745c5c3_Err = courseInfoElement(course).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListCourses(s stats, params ListCoursesParams) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var17 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var17 == nil {
|
||||||
|
templ_7745c5c3_Var17 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Var18 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = listCourseHeader(params.FilterForm).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = listCoursesContainer(params.Categories).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div id=\"course-info\"></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
templ_7745c5c3_Err = root(s).Render(templ.WithChildren(ctx, templ_7745c5c3_Var18), templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func root(s stats) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var19 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var19 == nil {
|
||||||
|
templ_7745c5c3_Var19 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = head().Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = navigation().Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"level\"><div class=\"level-item has-text-centered\"><div><p class=\"heading\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var20 := `Courses`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><p class=\"title\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var21 string
|
||||||
|
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(s.CoursesCount)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 158, Col: 39}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div></div><div class=\"level-item has-text-centered\"><div><p class=\"heading\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var22 := `Clients`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><p class=\"title\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var23 string
|
||||||
|
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(s.ClientsCount)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 164, Col: 39}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div></div><div class=\"level-item has-text-centered\"><div><p class=\"heading\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var24 := `Categories`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><p class=\"title\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var25 string
|
||||||
|
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(s.CategoriesCount)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 170, Col: 42}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div></div></nav><div class=\"section\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_Var19.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = footer().Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = breadcrumbsLoad().Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body></html>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func courseInfoElement(params CourseInfo) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var26 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var26 == nil {
|
||||||
|
templ_7745c5c3_Var26 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"column is-one-quarter\" hx-target=\"this\" hx-swap=\"outerHTML\"><div class=\"card\"><div class=\"card-image\"><figure class=\"image\"><img src=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(params.ImageLink))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></figure></div><div class=\"card-content\"><div class=\"media-content\"><p class=\"title is-5\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var27 string
|
||||||
|
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(params.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 193, Col: 40}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><p class=\"subtitle is-8\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var28 := `oh well`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div><div class=\"content\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if params.FullPrice > 0 {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var29 string
|
||||||
|
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(params.FullPrice))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/templ/list.templ`, Line: 198, Col: 41}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var30 := `руб.`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var30)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var31 := `Бесплатно`
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var31)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = buttonRedirect(params.ID, "Show course", params.OriginLink).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></article>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
95
internal/kurious/ports/http/templ/vars.go
Normal file
95
internal/kurious/ports/http/templ/vars.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package templ
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getCompactedValue(value int) string {
|
||||||
|
var (
|
||||||
|
myValue float64
|
||||||
|
dim string
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case value/1e6 > 0:
|
||||||
|
cutted := value / 1e3
|
||||||
|
myValue, dim = float64(cutted)/1e3, "m"
|
||||||
|
case value/1e3 > 0:
|
||||||
|
myValue, dim = float64(value/1e3), "k"
|
||||||
|
default:
|
||||||
|
myValue, dim = float64(value), ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSuffix(strconv.FormatFloat(myValue, 'f', 3, 32), ".000") + dim
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeNewStats(courses, clients, categories int) stats {
|
||||||
|
return stats{
|
||||||
|
CoursesCount: getCompactedValue(courses),
|
||||||
|
ClientsCount: getCompactedValue(clients),
|
||||||
|
CategoriesCount: getCompactedValue(categories),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type stats struct {
|
||||||
|
CoursesCount string
|
||||||
|
ClientsCount string
|
||||||
|
CategoriesCount string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Category struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Category) Empty() bool {
|
||||||
|
return c == (Category{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type BreadcrumbsParams struct {
|
||||||
|
ActiveLearningType Category
|
||||||
|
ActiveCourseThematic Category
|
||||||
|
}
|
||||||
|
|
||||||
|
type FilterFormParams struct {
|
||||||
|
BreadcrumbsParams
|
||||||
|
|
||||||
|
AvailableLearningTypes []Category
|
||||||
|
AvailableCourseThematics []Category
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEmpty(s string) bool {
|
||||||
|
return s == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type CourseInfo struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
FullPrice int
|
||||||
|
ImageLink string
|
||||||
|
OriginLink string
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryBaseInfo struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryContainer struct {
|
||||||
|
CategoryBaseInfo
|
||||||
|
|
||||||
|
Subcategories []SubcategoryContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubcategoryContainer struct {
|
||||||
|
CategoryBaseInfo
|
||||||
|
|
||||||
|
Courses []CourseInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListCoursesParams struct {
|
||||||
|
FilterForm FilterFormParams
|
||||||
|
|
||||||
|
Categories []CategoryContainer
|
||||||
|
}
|
||||||
57
internal/kurious/ports/http/templ/vars_test.go
Normal file
57
internal/kurious/ports/http/templ/vars_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package templ
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestGetCompactedValue(t *testing.T) {
|
||||||
|
var tt = []struct {
|
||||||
|
name string
|
||||||
|
in int
|
||||||
|
exp string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "less than 1k",
|
||||||
|
in: 666,
|
||||||
|
exp: "666",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exactly 1k",
|
||||||
|
in: 1000,
|
||||||
|
exp: "1k",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "some thousands",
|
||||||
|
in: 12345,
|
||||||
|
exp: "12k",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "more thousands",
|
||||||
|
in: 123456,
|
||||||
|
exp: "123k",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "million",
|
||||||
|
in: 1e6,
|
||||||
|
exp: "1m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "some millions",
|
||||||
|
in: 2e6,
|
||||||
|
exp: "2m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "more complex value",
|
||||||
|
in: 1.2346e6,
|
||||||
|
exp: "1.234m",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tt {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got := getCompactedValue(tc.in)
|
||||||
|
if tc.exp != got {
|
||||||
|
t.Errorf("exp=%s got=%s", tc.exp, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<a>
|
<a>
|
||||||
<span itemprop="title">
|
<span itemprop="title" itemprop="url">
|
||||||
Курсы
|
Курсы
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@ -64,7 +64,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<a>
|
<a>
|
||||||
<span itemprop="title">
|
<span itemprop="title" itemprop="url">
|
||||||
{{ .LearningTypeName }}
|
{{ .LearningTypeName }}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user