From 2c0564f68cb2da3694141e7e27ae0c7556a0ab8b Mon Sep 17 00:00:00 2001 From: Aleksandr Trushkin Date: Mon, 8 Jan 2024 18:31:35 +0300 Subject: [PATCH] add show course and map names --- cmd/background/main.go | 37 +++++++++++--- cmd/dev/sravnicli/products.go | 4 +- cmd/kuriweb/main.go | 29 ++++++++++- internal/common/client/sravni/client.go | 6 +-- internal/common/client/sravni/entities.go | 4 +- internal/common/config/ydb.go | 1 + internal/common/{xslice => xslices}/filter.go | 2 +- .../common/{xslice => xslices}/filter_test.go | 6 +-- .../common/{xslice => xslices}/foreach.go | 2 +- internal/common/{xslice => xslices}/map.go | 2 +- internal/kurious/adapters/memory_mapper.go | 21 ++++++++ .../kurious/adapters/ydb_course_repository.go | 51 ++++++++++--------- internal/kurious/app/command/createcourse.go | 4 +- internal/kurious/app/query/listcourses.go | 16 ++++-- internal/kurious/domain/course.go | 10 ++-- internal/kurious/domain/mapper.go | 6 +++ .../kurious/ports/background/synchandler.go | 12 ++--- internal/kurious/ports/http/course.go | 6 +-- internal/kurious/ports/http/listtemplate.go | 4 +- .../kurious/ports/http/templates/get.tmpl | 11 ++-- internal/kurious/service/service.go | 5 +- pkg/slices/map.go | 17 ------- 22 files changed, 166 insertions(+), 90 deletions(-) rename internal/common/{xslice => xslices}/filter.go (97%) rename internal/common/{xslice => xslices}/filter_test.go (85%) rename internal/common/{xslice => xslices}/foreach.go (84%) rename internal/common/{xslice => xslices}/map.go (89%) create mode 100644 internal/kurious/adapters/memory_mapper.go create mode 100644 internal/kurious/domain/mapper.go delete mode 100644 pkg/slices/map.go diff --git a/cmd/background/main.go b/cmd/background/main.go index 81fe258..009da69 100644 --- a/cmd/background/main.go +++ b/cmd/background/main.go @@ -13,6 +13,7 @@ import ( "git.loyso.art/frx/kurious/internal/common/config" "git.loyso.art/frx/kurious/internal/common/xcontext" "git.loyso.art/frx/kurious/internal/common/xlog" + "git.loyso.art/frx/kurious/internal/kurious/adapters" "git.loyso.art/frx/kurious/internal/kurious/ports" "git.loyso.art/frx/kurious/internal/kurious/service" ) @@ -43,19 +44,39 @@ func app(ctx context.Context) error { log := config.NewSLogger(cfg.Log) - app, err := service.NewApplication(ctx, service.ApplicationConfig{ - LogConfig: cfg.Log, - YDB: cfg.YDB, - }) - if err != nil { - return fmt.Errorf("making new application: %w", err) - } - sravniClient, err := sravni.NewClient(ctx, log, cfg.DebugHTTP) if err != nil { return fmt.Errorf("making sravni client: %w", err) } + mainPageState, err := sravniClient.GetMainPageState() + if err != nil { + return fmt.Errorf("getting main page state: %w", err) + } + + dictionaries := mainPageState.Props.InitialReduxState.Dictionaries.Data + + dictFieldsAsMap := func(fields ...sravni.Field) map[string]string { + out := make(map[string]string, len(fields)) + for _, field := range fields { + out[field.Value] = field.Name + } + return out + } + + courseThematcisMapped := dictFieldsAsMap(dictionaries.CourseThematics.Fields...) + learningTypeMapped := dictFieldsAsMap(dictionaries.LearningType.Fields...) + + mapper := adapters.NewMemoryMapper(courseThematcisMapped, learningTypeMapped) + + app, err := service.NewApplication(ctx, service.ApplicationConfig{ + LogConfig: cfg.Log, + YDB: cfg.YDB, + }, mapper) + if err != nil { + return fmt.Errorf("making new application: %w", err) + } + bgProcess := ports.NewBackgroundProcess(ctx, log) err = bgProcess.RegisterSyncSravniHandler(ctx, app, sravniClient, cfg.SyncSravniCron) if err != nil { diff --git a/cmd/dev/sravnicli/products.go b/cmd/dev/sravnicli/products.go index 38453bd..8d2d4e0 100644 --- a/cmd/dev/sravnicli/products.go +++ b/cmd/dev/sravnicli/products.go @@ -9,7 +9,7 @@ import ( "git.loyso.art/frx/kurious/internal/common/client/sravni" "git.loyso.art/frx/kurious/internal/common/errors" - "git.loyso.art/frx/kurious/internal/common/xslice" + "git.loyso.art/frx/kurious/internal/common/xslices" "github.com/teris-io/cli" ) @@ -188,7 +188,7 @@ func (a *productsFilterCountAction) parse(args []string, options map[string]stri filterNotEmpty := func(value string) bool { return value != "" } - a.params.courseThematic = xslice.Filter( + a.params.courseThematic = xslices.Filter( strings.Split(options[courseThematicOptName], ","), filterNotEmpty, ) diff --git a/cmd/kuriweb/main.go b/cmd/kuriweb/main.go index 0b3191b..2a1ee51 100644 --- a/cmd/kuriweb/main.go +++ b/cmd/kuriweb/main.go @@ -10,9 +10,11 @@ import ( "os/signal" "time" + "git.loyso.art/frx/kurious/internal/common/client/sravni" "git.loyso.art/frx/kurious/internal/common/config" "git.loyso.art/frx/kurious/internal/common/generator" "git.loyso.art/frx/kurious/internal/common/xcontext" + "git.loyso.art/frx/kurious/internal/kurious/adapters" xhttp "git.loyso.art/frx/kurious/internal/kurious/ports/http" "git.loyso.art/frx/kurious/internal/kurious/service" "golang.org/x/sync/errgroup" @@ -46,10 +48,35 @@ func app(ctx context.Context) error { log := config.NewSLogger(cfg.Log) + sravniClient, err := sravni.NewClient(ctx, log, false) + if err != nil { + return fmt.Errorf("unable to make new sravni client: %w", err) + } + + mainPageState, err := sravniClient.GetMainPageState() + if err != nil { + return fmt.Errorf("getting main page state: %w", err) + } + + dictionaries := mainPageState.Props.InitialReduxState.Dictionaries.Data + + dictFieldsAsMap := func(fields ...sravni.Field) map[string]string { + out := make(map[string]string, len(fields)) + for _, field := range fields { + out[field.Value] = field.Name + } + return out + } + + courseThematcisMapped := dictFieldsAsMap(dictionaries.CourseThematics.Fields...) + learningTypeMapped := dictFieldsAsMap(dictionaries.LearningType.Fields...) + + mapper := adapters.NewMemoryMapper(courseThematcisMapped, learningTypeMapped) + app, err := service.NewApplication(ctx, service.ApplicationConfig{ LogConfig: cfg.Log, YDB: cfg.YDB, - }) + }, mapper) if err != nil { return fmt.Errorf("making new application: %w", err) } diff --git a/internal/common/client/sravni/client.go b/internal/common/client/sravni/client.go index 15314fa..3dbb508 100644 --- a/internal/common/client/sravni/client.go +++ b/internal/common/client/sravni/client.go @@ -11,7 +11,7 @@ import ( "time" "git.loyso.art/frx/kurious/internal/common/errors" - "git.loyso.art/frx/kurious/pkg/slices" + "git.loyso.art/frx/kurious/internal/common/xslices" "git.loyso.art/frx/kurious/pkg/xdefault" "github.com/go-resty/resty/v2" @@ -52,8 +52,8 @@ func NewClient(ctx context.Context, log *slog.Logger, debug bool) (c *client, er return nil, err } - getQuerySet := func(fields []field) querySet { - items := slices.Map(fields, func(f field) string { + getQuerySet := func(fields []Field) querySet { + items := xslices.Map(fields, func(f Field) string { return f.Value }) diff --git a/internal/common/client/sravni/entities.go b/internal/common/client/sravni/entities.go index 7e6690d..160c7c0 100644 --- a/internal/common/client/sravni/entities.go +++ b/internal/common/client/sravni/entities.go @@ -39,7 +39,7 @@ type ReduxMetadata struct { } `json:"data"` } -type field struct { +type Field struct { Name string `json:"name"` Value string `json:"value"` } @@ -51,7 +51,7 @@ type ReduxDictionaryContainer struct { UserID string `json:"userId"` Created time.Time `json:"created"` Updated time.Time `json:"updated"` - Fields []field `json:"fields"` + Fields []Field `json:"fields"` } type ReduxDictionaries struct { diff --git a/internal/common/config/ydb.go b/internal/common/config/ydb.go index 854b6f2..55f6beb 100644 --- a/internal/common/config/ydb.go +++ b/internal/common/config/ydb.go @@ -27,6 +27,7 @@ type YDB struct { DSN string Auth YCAuth ShutdownDuration time.Duration + DebugYDB bool } func (ydb *YDB) UnmarshalJSON(data []byte) error { diff --git a/internal/common/xslice/filter.go b/internal/common/xslices/filter.go similarity index 97% rename from internal/common/xslice/filter.go rename to internal/common/xslices/filter.go index 7d266c5..57bb097 100644 --- a/internal/common/xslice/filter.go +++ b/internal/common/xslices/filter.go @@ -1,4 +1,4 @@ -package xslice +package xslices func Filter[T any](values []T, f func(T) bool) []T { out := make([]T, 0, len(values)) diff --git a/internal/common/xslice/filter_test.go b/internal/common/xslices/filter_test.go similarity index 85% rename from internal/common/xslice/filter_test.go rename to internal/common/xslices/filter_test.go index 08945cb..090fb1c 100644 --- a/internal/common/xslice/filter_test.go +++ b/internal/common/xslices/filter_test.go @@ -1,9 +1,9 @@ -package xslice_test +package xslices_test import ( "testing" - "git.loyso.art/frx/kurious/internal/common/xslice" + "git.loyso.art/frx/kurious/internal/common/xslices" ) func TestFilterInplace(t *testing.T) { @@ -43,7 +43,7 @@ func TestFilterInplace(t *testing.T) { for _, tc := range tt { tc := tc t.Run(tc.name, func(t *testing.T) { - gotLen := xslice.FilterInplace(tc.in, tc.check) + gotLen := xslices.FilterInplace(tc.in, tc.check) if gotLen != tc.expLen { t.Errorf("exp %d got %d", tc.expLen, gotLen) } diff --git a/internal/common/xslice/foreach.go b/internal/common/xslices/foreach.go similarity index 84% rename from internal/common/xslice/foreach.go rename to internal/common/xslices/foreach.go index 01380e4..05568e9 100644 --- a/internal/common/xslice/foreach.go +++ b/internal/common/xslices/foreach.go @@ -1,4 +1,4 @@ -package xslice +package xslices func ForEach[T any](items []T, f func(T)) { for _, item := range items { diff --git a/internal/common/xslice/map.go b/internal/common/xslices/map.go similarity index 89% rename from internal/common/xslice/map.go rename to internal/common/xslices/map.go index 4189501..91e0da4 100644 --- a/internal/common/xslice/map.go +++ b/internal/common/xslices/map.go @@ -1,4 +1,4 @@ -package xslice +package xslices func Map[T, U any](in []T, f func(T) U) []U { out := make([]U, len(in)) diff --git a/internal/kurious/adapters/memory_mapper.go b/internal/kurious/adapters/memory_mapper.go new file mode 100644 index 0000000..32dfb40 --- /dev/null +++ b/internal/kurious/adapters/memory_mapper.go @@ -0,0 +1,21 @@ +package adapters + +type inMemoryMapper struct { + courseThematicsByID map[string]string + learningTypeByID map[string]string +} + +func NewMemoryMapper(courseThematics, learningType map[string]string) inMemoryMapper { + return inMemoryMapper{ + courseThematicsByID: courseThematics, + learningTypeByID: learningType, + } +} + +func (m inMemoryMapper) CourseThematicNameByID(id string) string { + return m.courseThematicsByID[id] +} + +func (m inMemoryMapper) LearningTypeNameByID(id string) string { + return m.learningTypeByID[id] +} diff --git a/internal/kurious/adapters/ydb_course_repository.go b/internal/kurious/adapters/ydb_course_repository.go index 516fa00..3d0254e 100644 --- a/internal/kurious/adapters/ydb_course_repository.go +++ b/internal/kurious/adapters/ydb_course_repository.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log/slog" + "os" "path" "strings" "text/template" @@ -17,10 +18,12 @@ import ( "git.loyso.art/frx/kurious/pkg/xdefault" "github.com/ydb-platform/ydb-go-sdk/v3" + ydblog "github.com/ydb-platform/ydb-go-sdk/v3/log" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/table/result/named" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" + "github.com/ydb-platform/ydb-go-sdk/v3/trace" yc "github.com/ydb-platform/ydb-go-yc" ) @@ -69,9 +72,11 @@ func NewYDBConnection(ctx context.Context, cfg config.YDB, log *slog.Logger) (*Y yc.WithServiceAccountKeyFileCredentials(auth.Path), ) } - opts = append(opts, - ydb.WithDialTimeout(time.Second*3), - ) + if cfg.DebugYDB { + opts = append(opts, + ydb.WithLogger(ydblog.Default(os.Stdout, ydblog.WithMinLevel(ydblog.DEBUG)), trace.DetailsAll), + ) + } db, err := ydb.Open( ctx, @@ -81,6 +86,14 @@ func NewYDBConnection(ctx context.Context, cfg config.YDB, log *slog.Logger) (*Y if err != nil { return nil, fmt.Errorf("opening connection: %w", err) } + endpoints, err := db.Discovery().Discover(ctx) + if err != nil { + return nil, fmt.Errorf("discovering endpoints: %w", err) + } + + for _, endpoint := range endpoints { + xcontext.LogInfo(ctx, log, "discovered endpoint", slog.String("value", endpoint.Address())) + } return &YDBConnection{ Driver: db, @@ -163,11 +176,9 @@ func (r *ydbCourseRepository) List( query, err := qtParams.render() if err != nil { - return result, fmt.Errorf("rendering: %w", err) + return result, fmt.Errorf("rendering query params: %w", err) } - xcontext.LogInfo(ctx, r.log, "planning to run query", slog.String("query", query), slog.String("opts", tableParamOptsToString(opts...))) - courses := make([]domain.Course, 0, 1_000) readTx := table.TxControl( table.BeginTx( @@ -176,11 +187,9 @@ func (r *ydbCourseRepository) List( table.CommitTx(), ) - xcontext.LogInfo(ctx, r.log, "executing do") err = r.db.Table().Do( ctx, func(ctx context.Context, s table.Session) error { - xcontext.LogInfo(ctx, r.log, "inside do") start := time.Now() defer func() { since := time.Since(start) @@ -194,8 +203,6 @@ func (r *ydbCourseRepository) List( queryParams := table.NewQueryParameters(opts...) - xcontext.LogDebug(ctx, r.log, "executing") - _, res, err := s.Execute( ctx, readTx, query, queryParams, options.WithCollectStatsModeBasic(), @@ -204,14 +211,10 @@ func (r *ydbCourseRepository) List( return fmt.Errorf("executing: %w", err) } - xcontext.LogDebug(ctx, r.log, "checking") - if !res.NextResultSet(ctx) || !res.HasNextRow() { return nil } - xcontext.LogDebug(ctx, r.log, "scanning") - for res.NextRow() { var cdb courseDB err = res.ScanNamed(cdb.getNamedValues()...) @@ -393,7 +396,6 @@ func createCourseParamsAsStruct(params domain.CreateCourseParams) types.Value { } func (r *ydbCourseRepository) CreateBatch(ctx context.Context, params ...domain.CreateCourseParams) error { - // -- PRAGMA TablePathPrefix("courses"); const upsertQuery = `DECLARE $courseData AS List, @@ -680,8 +682,8 @@ func mapCourseDB(cdb courseDB) domain.Course { Name: cdb.Name, SourceType: st, SourceName: nullable.NewValuePtr(cdb.SourceName), - Thematic: cdb.CourseThematic, - LearningType: cdb.LearningType, + ThematicID: cdb.CourseThematic, + LearningTypeID: cdb.LearningType, OrganizationID: cdb.OrganizationID, OriginLink: cdb.OriginLink, ImageLink: cdb.ImageLink, @@ -738,11 +740,10 @@ WHERE {{ range .Conditions }}{{.}}{{end}} var querySelect = template.Must(template.New("").Parse(queryTemplateSelect)) -func tableParamOptsToString(in ...table.ParameterOption) string { - var sb strings.Builder - for _, opt := range in { - sb.WriteString(opt.Name() + "(" + opt.Value().Type().String() + ");") - } - - return sb.String() -} +// func tableParamOptsToString(in ...table.ParameterOption) string { +// var sb strings.Builder +// for _, opt := range in { +// sb.WriteString(opt.Name() + "(" + opt.Value().Type().String() + ");") +// } +// return sb.String() +// } diff --git a/internal/kurious/app/command/createcourse.go b/internal/kurious/app/command/createcourse.go index 91554f1..60f6e02 100644 --- a/internal/kurious/app/command/createcourse.go +++ b/internal/kurious/app/command/createcourse.go @@ -8,7 +8,7 @@ import ( "git.loyso.art/frx/kurious/internal/common/decorator" "git.loyso.art/frx/kurious/internal/common/nullable" - "git.loyso.art/frx/kurious/internal/common/xslice" + "git.loyso.art/frx/kurious/internal/common/xslices" "git.loyso.art/frx/kurious/internal/kurious/domain" ) @@ -78,7 +78,7 @@ func NewCreateCoursesHandler( } func (h createCoursesHandler) Handle(ctx context.Context, cmd CreateCourses) error { - params := xslice.Map(cmd.Courses, func(in CreateCourse) (out domain.CreateCourseParams) { + params := xslices.Map(cmd.Courses, func(in CreateCourse) (out domain.CreateCourseParams) { return domain.CreateCourseParams(in) }) err := h.repo.CreateBatch(ctx, params...) diff --git a/internal/kurious/app/query/listcourses.go b/internal/kurious/app/query/listcourses.go index 0e0388b..05303ae 100644 --- a/internal/kurious/app/query/listcourses.go +++ b/internal/kurious/app/query/listcourses.go @@ -6,6 +6,7 @@ import ( "log/slog" "git.loyso.art/frx/kurious/internal/common/decorator" + "git.loyso.art/frx/kurious/internal/common/xslices" "git.loyso.art/frx/kurious/internal/kurious/domain" ) @@ -23,15 +24,18 @@ type ListCourse struct { type ListCourseHandler decorator.QueryHandler[ListCourse, domain.ListCoursesResult] type listCourseHandler struct { - repo domain.CourseRepository + repo domain.CourseRepository + mapper domain.CourseMapper } func NewListCourseHandler( repo domain.CourseRepository, + mapper domain.CourseMapper, log *slog.Logger, ) ListCourseHandler { h := listCourseHandler{ - repo: repo, + repo: repo, + mapper: mapper, } return decorator.AddQueryDecorators(h, log) } @@ -43,7 +47,6 @@ func (h listCourseHandler) Handle(ctx context.Context, query ListCourse) (out do out.Courses = make([]domain.Course, 0, query.Limit) } for { - print("listing") result, err := h.repo.List(ctx, domain.ListCoursesParams{ CourseThematic: query.CourseThematic, LearningType: query.LearningType, @@ -56,6 +59,13 @@ func (h listCourseHandler) Handle(ctx context.Context, query ListCourse) (out do return out, fmt.Errorf("listing courses: %w", err) } + result.Courses = xslices.Map(result.Courses, func(in domain.Course) domain.Course { + in.LearningType = h.mapper.LearningTypeNameByID(in.LearningTypeID) + in.Thematic = h.mapper.CourseThematicNameByID(in.ThematicID) + + return in + }) + out.Courses = append(out.Courses, result.Courses...) out.NextPageToken = result.NextPageToken diff --git a/internal/kurious/domain/course.go b/internal/kurious/domain/course.go index 648c88d..7f6ff38 100644 --- a/internal/kurious/domain/course.go +++ b/internal/kurious/domain/course.go @@ -27,9 +27,13 @@ type Course struct { // FullPrice is a course full price without discount. FullPrice float64 // Discount for the course. - Discount float64 - Thematic string - LearningType string + Discount float64 + + Thematic string + ThematicID string + + LearningType string + LearningTypeID string // Duration for the course. It will be splitted in values like: // full month / full day / full hour. diff --git a/internal/kurious/domain/mapper.go b/internal/kurious/domain/mapper.go new file mode 100644 index 0000000..b0e96d3 --- /dev/null +++ b/internal/kurious/domain/mapper.go @@ -0,0 +1,6 @@ +package domain + +type CourseMapper interface { + CourseThematicNameByID(string) string + LearningTypeNameByID(string) string +} diff --git a/internal/kurious/ports/background/synchandler.go b/internal/kurious/ports/background/synchandler.go index fd13807..eb603f3 100644 --- a/internal/kurious/ports/background/synchandler.go +++ b/internal/kurious/ports/background/synchandler.go @@ -14,7 +14,7 @@ import ( "git.loyso.art/frx/kurious/internal/common/generator" "git.loyso.art/frx/kurious/internal/common/nullable" "git.loyso.art/frx/kurious/internal/common/xcontext" - "git.loyso.art/frx/kurious/internal/common/xslice" + "git.loyso.art/frx/kurious/internal/common/xslices" "git.loyso.art/frx/kurious/internal/kurious/app/command" "git.loyso.art/frx/kurious/internal/kurious/app/query" "git.loyso.art/frx/kurious/internal/kurious/domain" @@ -126,7 +126,7 @@ func (h *syncSravniHandler) Handle(ctx context.Context) (err error) { return fmt.Errorf("loading educational products: %w", err) } - xslice.ForEach(buffer, func(c sravni.Course) { + xslices.ForEach(buffer, func(c sravni.Course) { c.Learningtype = []string{learningType.Value} c.CourseThematics = []string{courseThematic} courses = append(courses, c) @@ -155,7 +155,7 @@ func (h *syncSravniHandler) Handle(ctx context.Context) (err error) { continue } - xslice.ForEach(courses, func(c sravni.Course) { + xslices.ForEach(courses, func(c sravni.Course) { h.knownExternalIDs[c.ID] = struct{}{} }) @@ -212,7 +212,7 @@ func (h *syncSravniHandler) loadEducationalProducts(ctx context.Context, learnin } func (h *syncSravniHandler) filterByCache(courses []sravni.Course) (toInsert []sravni.Course) { - toCut := xslice.FilterInplace(courses, xslice.Not(h.isCached)) + toCut := xslices.FilterInplace(courses, xslices.Not(h.isCached)) return courses[:toCut] } @@ -222,7 +222,7 @@ func (h *syncSravniHandler) isCached(course sravni.Course) bool { } func (h *syncSravniHandler) insertValues(ctx context.Context, courses []sravni.Course) error { - courseParams := xslice.Map(courses, courseAsCreateCourseParams) + courseParams := xslices.Map(courses, courseAsCreateCourseParams) err := h.svc.Commands.InsertCourses.Handle(ctx, command.CreateCourses{ Courses: courseParams, }) @@ -249,7 +249,7 @@ func (h *syncSravniHandler) fillCaches(ctx context.Context) error { h.knownExternalIDs = make(map[string]struct{}, len(courses)) - xslice.ForEach(courses, func(c domain.Course) { + xslices.ForEach(courses, func(c domain.Course) { if !c.ExternalID.Valid() { return } diff --git a/internal/kurious/ports/http/course.go b/internal/kurious/ports/http/course.go index 5e773d9..f013a1e 100644 --- a/internal/kurious/ports/http/course.go +++ b/internal/kurious/ports/http/course.go @@ -9,7 +9,7 @@ import ( "git.loyso.art/frx/kurious/internal/common/errors" "git.loyso.art/frx/kurious/internal/common/xcontext" - "git.loyso.art/frx/kurious/internal/common/xslice" + "git.loyso.art/frx/kurious/internal/common/xslices" "git.loyso.art/frx/kurious/internal/kurious/app/command" "git.loyso.art/frx/kurious/internal/kurious/app/query" "git.loyso.art/frx/kurious/internal/kurious/domain" @@ -90,7 +90,7 @@ type listCoursesTemplateParams struct { func mapDomainCourseToTemplate(in ...domain.Course) listCoursesTemplateParams { coursesBySubcategory := make(map[string][]domain.Course, len(in)) subcategoriesByCategories := make(map[string]map[string]struct{}, len(in)) - xslice.ForEach(in, func(c domain.Course) { + xslices.ForEach(in, func(c domain.Course) { coursesBySubcategory[c.Thematic] = append(coursesBySubcategory[c.Thematic], c) if _, ok := subcategoriesByCategories[c.LearningType]; !ok { subcategoriesByCategories[c.LearningType] = map[string]struct{}{} @@ -216,7 +216,7 @@ func (c courseServer) RenderEditDescription(w http.ResponseWriter, r *http.Reque func (c courseServer) UpdateCourseDescription(w http.ResponseWriter, r *http.Request) { type requestModel struct { ID string `json:"-"` - Text string `json:"text"` + Text string `json:"description"` } ctx := r.Context() diff --git a/internal/kurious/ports/http/listtemplate.go b/internal/kurious/ports/http/listtemplate.go index 4ab5556..bc43d77 100644 --- a/internal/kurious/ports/http/listtemplate.go +++ b/internal/kurious/ports/http/listtemplate.go @@ -9,7 +9,7 @@ import ( "path" "git.loyso.art/frx/kurious/internal/common/xcontext" - "git.loyso.art/frx/kurious/internal/common/xslice" + "git.loyso.art/frx/kurious/internal/common/xslices" ) const baseTemplatePath = "./internal/kurious/ports/http/templates/" @@ -22,7 +22,7 @@ func must[T any](t T, err error) T { } func scanFiles() []string { - entries := xslice.Map( + entries := xslices.Map( must(os.ReadDir(baseTemplatePath)), func(v fs.DirEntry) string { return path.Join(baseTemplatePath, v.Name()) diff --git a/internal/kurious/ports/http/templates/get.tmpl b/internal/kurious/ports/http/templates/get.tmpl index 70204e5..9831c5b 100644 --- a/internal/kurious/ports/http/templates/get.tmpl +++ b/internal/kurious/ports/http/templates/get.tmpl @@ -9,13 +9,16 @@
-

{{ .Name }}

+

{{ .Name }}

{{ .Description }}

{{ .FullPrice }} rub.

+ @@ -49,7 +52,7 @@
- +
@@ -59,7 +62,7 @@

-

@@ -69,8 +72,6 @@

- {{ end }} diff --git a/internal/kurious/service/service.go b/internal/kurious/service/service.go index 0b181c0..e987313 100644 --- a/internal/kurious/service/service.go +++ b/internal/kurious/service/service.go @@ -11,6 +11,7 @@ import ( "git.loyso.art/frx/kurious/internal/kurious/app" "git.loyso.art/frx/kurious/internal/kurious/app/command" "git.loyso.art/frx/kurious/internal/kurious/app/query" + "git.loyso.art/frx/kurious/internal/kurious/domain" ) type ApplicationConfig struct { @@ -25,7 +26,7 @@ type Application struct { closers []io.Closer } -func NewApplication(ctx context.Context, cfg ApplicationConfig) (Application, error) { +func NewApplication(ctx context.Context, cfg ApplicationConfig, mapper domain.CourseMapper) (Application, error) { log := config.NewSLogger(cfg.LogConfig) ydbConnection, err := adapters.NewYDBConnection(ctx, cfg.YDB, log.With(slog.String("db", "ydb"))) if err != nil { @@ -43,7 +44,7 @@ func NewApplication(ctx context.Context, cfg ApplicationConfig) (Application, er }, Queries: app.Queries{ GetCourse: query.NewGetCourseHandler(courseadapter, log), - ListCourses: query.NewListCourseHandler(courseadapter, log), + ListCourses: query.NewListCourseHandler(courseadapter, mapper, log), }, } diff --git a/pkg/slices/map.go b/pkg/slices/map.go deleted file mode 100644 index 9eb12db..0000000 --- a/pkg/slices/map.go +++ /dev/null @@ -1,17 +0,0 @@ -package slices - -// Map slice from one type to another one. -func Map[S any, E any](s []S, f func(S) E) []E { - out := make([]E, len(s)) - for i := range s { - out[i] = f(s[i]) - } - - return out -} - -func ForEach[S any](s []S, f func(S)) { - for i := range s { - f(s[i]) - } -}