123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- package admin
- import (
- "context"
- "database/sql"
- "errors"
- "strconv"
- "git.dmitriygnatenko.ru/dima/go-common/logger"
- validation "github.com/go-ozzo/ozzo-validation/v4"
- "github.com/gofiber/fiber/v2"
- "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/dto"
- "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/mapper"
- "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/i18n"
- )
- type articleAddPage struct {
- tm TransactionManager
- articleRepository ArticleRepository
- tagRepository TagRepository
- articleTagRepository ArticleTagRepository
- languageRepository LanguageRepository
- cacheService CacheService
- }
- func NewArticleAddPageHandler(
- tm TransactionManager,
- articleRepository ArticleRepository,
- tagRepository TagRepository,
- articleTagRepository ArticleTagRepository,
- languageRepository LanguageRepository,
- cacheService CacheService,
- ) fiber.Handler {
- h := articleAddPage{
- tm: tm,
- articleRepository: articleRepository,
- tagRepository: tagRepository,
- articleTagRepository: articleTagRepository,
- languageRepository: languageRepository,
- cacheService: cacheService,
- }
- return h.handler()
- }
- func (h articleAddPage) handler() fiber.Handler {
- return func(fctx *fiber.Ctx) error {
- ctx := fctx.Context()
- lang := i18n.LanguageFromContext(fctx)
- validationErrors := make(map[string]string)
- form := dto.ArticleForm{
- ActiveTags: make(map[uint64]bool),
- }
- tags, err := h.getTags(ctx)
- if err != nil {
- logger.Error(ctx, err.Error())
- return err
- }
- languages, err := h.getLanguages(ctx)
- if err != nil {
- logger.Error(ctx, err.Error())
- return err
- }
- if fctx.Method() == fiber.MethodPost {
- if err = fctx.BodyParser(&form); err != nil {
- logger.Info(ctx, err.Error())
- return err
- }
- if err = h.validateAddArticleForm(ctx, form); err != nil {
- logger.Info(ctx, err.Error())
- validationErrors = mapper.ToErrorsMap(err)
- }
- tagIDs, err := h.formatTags(form.Tags)
- if err != nil {
- logger.Error(ctx, err.Error())
- return err
- }
- for i := range tagIDs {
- form.ActiveTags[tagIDs[i]] = true
- }
- if len(validationErrors) == 0 {
- articleModel, err := mapper.ToArticleModel(form)
- if err != nil {
- logger.Error(ctx, err.Error())
- return err
- }
- err = h.tm.ReadCommitted(ctx, func(ctx context.Context) error {
- articleID, txErr := h.articleRepository.Add(ctx, *articleModel)
- if txErr != nil {
- return txErr
- }
- if len(tagIDs) > 0 {
- if txErr = h.articleTagRepository.Add(ctx, articleID, tagIDs); txErr != nil {
- return txErr
- }
- }
- return nil
- })
- if err != nil {
- logger.Error(ctx, err.Error())
- return err
- }
- return fctx.Redirect("/admin")
- }
- }
- return fctx.Render("admin/article_edit", fiber.Map{
- "lang": lang,
- "title": i18n.T(lang, "admin_article_add_title"),
- "section": "article",
- "show_apply": false,
- "form": form,
- "errors": validationErrors,
- "tags": tags,
- "languages": languages,
- }, "admin/_layout")
- }
- }
- func (h articleAddPage) getTags(ctx context.Context) ([]dto.Tag, error) {
- tagModels, err := h.tagRepository.GetAll(ctx)
- if err != nil {
- return nil, err
- }
- return mapper.ToTagsList(tagModels), nil
- }
- func (h articleAddPage) getLanguages(ctx context.Context) ([]string, error) {
- langModels, err := h.languageRepository.GetAll(ctx)
- if err != nil {
- return nil, err
- }
- res := make([]string, 0, len(langModels))
- for i := range langModels {
- res = append(res, langModels[i].URL)
- }
- return res, nil
- }
- func (h articleAddPage) formatTags(tags []string) ([]uint64, error) {
- ids := make([]uint64, 0, len(tags))
- for i := range tags {
- id, err := strconv.ParseUint(tags[i], 10, 64)
- if err != nil {
- return nil, err
- }
- ids = append(ids, id)
- }
- return ids, nil
- }
- func (h articleAddPage) validateAddArticleForm(ctx context.Context, req dto.ArticleForm) error {
- lang := i18n.DefaultLanguage()
- requiredMsg := i18n.T(lang, "admin_err_required")
- lengthMsg := i18n.T(lang, "admin_err_length_255")
- return validation.ValidateStructWithContext(
- ctx,
- &req,
- validation.Field(
- &req.Title,
- validation.Required.Error(requiredMsg),
- validation.Length(1, 255).Error(lengthMsg),
- ),
- validation.Field(
- &req.Image,
- validation.Required.Error(requiredMsg),
- validation.Length(1, 255).Error(lengthMsg),
- ),
- validation.Field(
- &req.URL,
- validation.Required.Error(requiredMsg),
- validation.Length(1, 255).Error(lengthMsg),
- validation.By(h.validateDuplicateURL),
- ),
- validation.Field(
- &req.Text,
- validation.Required.Error(requiredMsg),
- ),
- validation.Field(
- &req.PreviewText,
- validation.Length(1, 255).Error(lengthMsg),
- ),
- validation.Field(
- &req.MetaKeywords,
- validation.Length(1, 255).Error(lengthMsg),
- ),
- validation.Field(
- &req.MetaDescription,
- validation.Length(1, 255).Error(lengthMsg),
- ),
- validation.Field(
- &req.PublishTime,
- validation.Required.Error(requiredMsg),
- ),
- validation.Field(
- &req.Language,
- validation.Required.Error(requiredMsg),
- ),
- )
- }
- func (h articleAddPage) validateDuplicateURL(value interface{}) error {
- url, _ := value.(string)
- ctx := context.Background()
- lang := i18n.DefaultLanguage()
- _, err := h.articleRepository.GetByURL(ctx, url)
- if err != nil {
- if !errors.Is(err, sql.ErrNoRows) {
- logger.Error(ctx, err.Error())
- }
- return nil
- }
- return errors.New(i18n.T(lang, "admin_err_article_duplicate", url))
- }
|