123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- package admin
- import (
- "strconv"
- "github.com/dmitriygnatenko/internal/helpers"
- "github.com/dmitriygnatenko/internal/interfaces"
- "github.com/dmitriygnatenko/internal/mapper"
- "github.com/dmitriygnatenko/internal/models"
- "github.com/go-playground/validator/v10"
- "github.com/gofiber/fiber/v2"
- )
- const errArticleExists = "Статья с данным URL уже существует"
- func ArticleHandler(sp interfaces.ServiceProvider) fiber.Handler {
- return func(ctx *fiber.Ctx) error {
- articles, err := sp.GetArticleRepository().GetAll(ctx.Context())
- if err != nil {
- return err
- }
- return ctx.Render("admin/article", fiber.Map{
- "articles": mapper.ConvertArticleModelsToDTO(articles),
- "section": "article",
- }, "admin/_layout")
- }
- }
- func AddArticleHandler(sp interfaces.ServiceProvider) fiber.Handler {
- return func(ctx *fiber.Ctx) error {
- var validate = validator.New()
- validateErrors := make(map[string]string)
- trans, err := helpers.GetDefaultTranslator(validate)
- if err != nil {
- return err
- }
- form := models.ArticleForm{
- ActiveTags: make(map[int]bool),
- }
- tags, err := sp.GetTagRepository().GetAll(ctx.Context())
- if err != nil {
- return err
- }
- tagsDTO := mapper.ConvertTagModelsToDTO(tags)
- if ctx.Method() == fiber.MethodPost {
- if err = ctx.BodyParser(&form); err != nil {
- return err
- }
- if err = validate.Struct(form); err != nil {
- validateErrors = helpers.FormatValidateErrors(err, trans)
- }
- if res, _ := sp.GetArticleRepository().GetByURL(ctx.Context(), form.URL); res != nil {
- validateErrors["ArticleForm.URL"] = errArticleExists
- }
- tagIDs := make([]int, 0, len(form.Tags))
- for i := range form.Tags {
- tagID, tagErr := strconv.Atoi(form.Tags[i])
- if tagErr != nil {
- return tagErr
- }
- tagIDs = append(tagIDs, tagID)
- }
- for i := range tagIDs {
- form.ActiveTags[tagIDs[i]] = true
- }
- if len(validateErrors) == 0 {
- articleID, articleErr := sp.GetArticleRepository().Add(ctx.Context(), mapper.ConvertArticleFormToModel(form))
- if articleErr != nil {
- return articleErr
- }
- if len(form.Tags) > 0 {
- if err = sp.GetArticleTagRepository().Add(ctx.Context(), articleID, tagIDs); err != nil {
- return err
- }
- }
- sp.GetCacheService().FlushAll()
- if err = ctx.Redirect("/admin"); err != nil {
- return err
- }
- }
- }
- return ctx.Render("admin/article_edit", fiber.Map{
- "form": form,
- "errors": validateErrors,
- "tags": tagsDTO,
- "section": "article",
- "title": "Добавление статьи",
- "show_apply": false,
- }, "admin/_layout")
- }
- }
- func EditArticleHandler(sp interfaces.ServiceProvider) fiber.Handler {
- return func(ctx *fiber.Ctx) error {
- var validate = validator.New()
- validateErrors := make(map[string]string)
- trans, err := helpers.GetDefaultTranslator(validate)
- if err != nil {
- return err
- }
- ID, err := strconv.Atoi(ctx.Params("id"))
- if err != nil {
- return err
- }
- article, err := sp.GetArticleRepository().GetByID(ctx.Context(), ID)
- if err != nil {
- return err
- }
- if article == nil {
- return fiber.ErrNotFound
- }
- articleTags, err := sp.GetTagRepository().GetByArticleID(ctx.Context(), ID)
- if err != nil {
- return err
- }
- tags, err := sp.GetTagRepository().GetAll(ctx.Context())
- if err != nil {
- return err
- }
- tagsDTO := mapper.ConvertTagModelsToDTO(tags)
- var form *models.ArticleForm
- if ctx.Method() == fiber.MethodGet {
- form = mapper.ConvertArticleModelToForm(*article, articleTags)
- } else if ctx.Method() == fiber.MethodPost {
- form = &models.ArticleForm{
- ID: ID,
- ActiveTags: make(map[int]bool),
- }
- if err = ctx.BodyParser(form); err != nil {
- return err
- }
- if err = validate.Struct(*form); err != nil {
- validateErrors = helpers.FormatValidateErrors(err, trans)
- }
- if res, _ := sp.GetArticleRepository().GetByURL(ctx.Context(), form.URL); res != nil {
- if res.ID != ID {
- validateErrors["ArticleForm.URL"] = errArticleExists
- }
- }
- tagIDs := make([]int, 0, len(form.Tags))
- for i := range form.Tags {
- tagID, tagErr := strconv.Atoi(form.Tags[i])
- if tagErr != nil {
- return tagErr
- }
- tagIDs = append(tagIDs, tagID)
- }
- for i := range tagIDs {
- form.ActiveTags[tagIDs[i]] = true
- }
- if len(validateErrors) == 0 {
- err = sp.GetArticleRepository().Update(ctx.Context(), mapper.ConvertArticleFormToModel(*form))
- if err != nil {
- return err
- }
- var tagsToAdd, tagsToDelete []int
- oldTagsMap := make(map[int]struct{}, len(articleTags))
- for i := range articleTags {
- oldTagsMap[articleTags[i].ID] = struct{}{}
- if _, ok := form.ActiveTags[articleTags[i].ID]; !ok {
- tagsToDelete = append(tagsToDelete, articleTags[i].ID)
- }
- }
- for i := range tagIDs {
- if _, ok := oldTagsMap[tagIDs[i]]; !ok {
- tagsToAdd = append(tagsToAdd, tagIDs[i])
- }
- }
- if len(tagsToAdd) > 0 {
- if err = sp.GetArticleTagRepository().Add(ctx.Context(), ID, tagsToAdd); err != nil {
- return err
- }
- }
- if len(tagsToDelete) > 0 {
- if err = sp.GetArticleTagRepository().Delete(ctx.Context(), ID, tagsToDelete); err != nil {
- return err
- }
- }
- sp.GetCacheService().FlushAll()
- if ctx.FormValue("action", "save") == "save" {
- if err = ctx.Redirect("/admin"); err != nil {
- return err
- }
- }
- }
- }
- return ctx.Render("admin/article_edit", fiber.Map{
- "form": form,
- "errors": validateErrors,
- "tags": tagsDTO,
- "show_apply": true,
- "section": "article",
- "title": "Редактирование статьи",
- }, "admin/_layout")
- }
- }
- func DeleteArticleHandler(sp interfaces.ServiceProvider) fiber.Handler {
- return func(ctx *fiber.Ctx) error {
- ID, err := strconv.Atoi(ctx.Params("id"))
- if err != nil {
- return err
- }
- article, err := sp.GetArticleRepository().GetByID(ctx.Context(), ID)
- if err != nil {
- return err
- }
- if ctx.Method() == fiber.MethodPost {
- err = sp.GetArticleTagRepository().DeleteByArticleID(ctx.Context(), ID)
- if err != nil {
- return err
- }
- err = sp.GetArticleRepository().Delete(ctx.Context(), ID)
- if err != nil {
- return err
- }
- sp.GetCacheService().FlushAll()
- if err = ctx.Redirect("/admin"); err != nil {
- return err
- }
- }
- return ctx.Render("admin/article_delete", fiber.Map{
- "article": article.Title,
- "section": "article",
- }, "admin/_layout")
- }
- }
|