Преглед на файлове

Update admin article page

Dima преди 2 години
родител
ревизия
68f17c662e

+ 1 - 0
internal/interfaces/repository.go

@@ -13,6 +13,7 @@ type IArticleRepository interface {
 	GetByURL(ctx context.Context, url string) (*models.Article, error)
 	GetByID(ctx context.Context, ID int) (*models.Article, error)
 	Add(ctx context.Context, m models.Article) (int, error)
+	Update(ctx context.Context, m models.Article) error
 }
 
 type ITagRepository interface {

+ 1 - 1
internal/mapper/article.go

@@ -129,7 +129,7 @@ func ConvertArticleFormToModel(f models.ArticleForm) models.Article {
 	}
 
 	return models.Article{
-		ID:              0,
+		ID:              f.ID,
 		URL:             f.URL,
 		Title:           f.Title,
 		PublishTime:     f.PublishTime,

+ 1 - 1
internal/models/article.go

@@ -33,7 +33,7 @@ type ArticleForm struct {
 	PreviewText     string   `form:"preview_text" validate:"max=255"`
 	MetaKeywords    string   `form:"meta_keywords" validate:"max=255"`
 	MetaDescription string   `form:"meta_description" validate:"max=255"`
-	IsActive        bool     `form:"is_active" validate:"boolean"`
+	IsActive        bool     `form:"is_active"`
 	PublishTime     string   `form:"publish_time" validate:"required"`
 	Tags            []string `form:"tag"`
 	ActiveTags      map[int]bool

+ 11 - 0
internal/repositories/article.go

@@ -176,3 +176,14 @@ func (a articleRepository) Add(ctx context.Context, m models.Article) (int, erro
 
 	return int(id), err
 }
+
+func (a articleRepository) Update(ctx context.Context, m models.Article) error {
+	query := "UPDATE " + articleTableName + " " +
+		"SET url = ?, publish_time = ?, title = ?, image = ?, text = ?, preview_text = ?, meta_keywords = ?, " +
+		" meta_desc = ?, is_active = ? WHERE id = ?"
+
+	_, err := a.db.ExecContext(ctx, query, m.URL, m.PublishTime, m.Title, m.Image, m.Text, m.PreviewText,
+		m.MetaKeywords, m.MetaDescription, m.IsActive, m.ID)
+
+	return err
+}

+ 18 - 2
internal/repositories/article_tag.go

@@ -20,7 +20,7 @@ func (a articleTagRepository) Add(ctx context.Context, articleID int, tagIDs []i
 		return nil
 	}
 
-	query := "INSERT INTO article_tag (article_id, tag_id) VALUES "
+	query := "INSERT INTO " + articleTagTableName + " (article_id, tag_id) VALUES "
 
 	var vals []interface{}
 	for _, tagID := range tagIDs {
@@ -35,5 +35,21 @@ func (a articleTagRepository) Add(ctx context.Context, articleID int, tagIDs []i
 }
 
 func (a articleTagRepository) Delete(ctx context.Context, articleID int, tagIDs []int) error {
-	return nil
+	if len(tagIDs) == 0 {
+		return nil
+	}
+
+	query := "DELETE FROM " + articleTagTableName + " WHERE article_id = ? AND tag_id IN ("
+
+	var vals []interface{}
+	vals = append(vals, articleID)
+	for _, tagID := range tagIDs {
+		query += "?,"
+		vals = append(vals, tagID)
+	}
+	query = query[0:len(query)-1] + ")"
+
+	_, err := a.db.ExecContext(ctx, query, vals...)
+
+	return err
 }

+ 86 - 19
internal/services/handler/admin/article.go

@@ -79,6 +79,10 @@ func AddArticleHandler(app interfaces.IApp) fiber.Handler {
 				tagIDs = append(tagIDs, tagID)
 			}
 
+			for i := range tagIDs {
+				form.ActiveTags[tagIDs[i]] = true
+			}
+
 			if len(validateErrors) == 0 {
 				articleID, articleErr := app.GetArticleRepository().Add(ctx.Context(), mapper.ConvertArticleFormToModel(form))
 				if articleErr != nil {
@@ -86,7 +90,6 @@ func AddArticleHandler(app interfaces.IApp) fiber.Handler {
 				}
 
 				if len(form.Tags) > 0 {
-
 					if err = app.GetArticleTagRepository().Add(ctx.Context(), articleID, tagIDs); err != nil {
 						return err
 					}
@@ -98,10 +101,6 @@ func AddArticleHandler(app interfaces.IApp) fiber.Handler {
 					return err
 				}
 			}
-
-			for i := range tagIDs {
-				form.ActiveTags[tagIDs[i]] = true
-			}
 		}
 
 		return ctx.Render("admin/article_edit", fiber.Map{
@@ -143,11 +142,6 @@ func EditArticleHandler(app interfaces.IApp) fiber.Handler {
 			return err
 		}
 
-		form, err := mapper.ConvertArticleModelToForm(*article, articleTags)
-		if err != nil {
-			return err
-		}
-
 		tags, err := app.GetTagRepository().GetAll(ctx.Context())
 		if err != nil {
 			return err
@@ -158,24 +152,97 @@ func EditArticleHandler(app interfaces.IApp) fiber.Handler {
 			return err
 		}
 
-		if ctx.Method() == fiber.MethodPost {
-			if err = ctx.BodyParser(&form); err != nil {
+		var form *models.ArticleForm
+		if ctx.Method() == fiber.MethodGet {
+			form, err = mapper.ConvertArticleModelToForm(*article, articleTags)
+			if err != nil {
 				return err
 			}
+		} else if ctx.Method() == fiber.MethodPost {
+			form = &models.ArticleForm{
+				ID:         ID,
+				ActiveTags: make(map[int]bool),
+			}
 
-			if err = validate.Struct(form); err != nil {
+			if err = ctx.BodyParser(form); err != nil {
+				return err
+			}
+
+			if err = validate.Struct(*form); err != nil {
 				validateErrors = helpers.FormatValidateErrors(err, trans)
 			}
 
-			// TODO
+			if res, _ := app.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 = app.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 = app.GetArticleTagRepository().Add(ctx.Context(), ID, tagsToAdd); err != nil {
+						return err
+					}
+				}
+
+				if len(tagsToDelete) > 0 {
+					if err = app.GetArticleTagRepository().Delete(ctx.Context(), ID, tagsToDelete); err != nil {
+						return err
+					}
+				}
+
+				app.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,
-			"section": "article",
-			"title":   "Редактирование статьи",
+			"form":       form,
+			"errors":     validateErrors,
+			"tags":       tagsDTO,
+			"show_apply": true,
+			"section":    "article",
+			"title":      "Редактирование статьи",
 		}, "admin/_layout")
 	}
 }

+ 2 - 2
internal/templates/admin/article_edit.html

@@ -146,8 +146,8 @@
         </div>
         <a href="/admin" class="btn btn-sm btn-secondary">Назад</a>
         {{ if .show_apply }}
-        <button type="submit" class="btn btn-sm btn-primary" name="apply">Применить</button>
+        <button type="submit" class="btn btn-sm btn-primary" name="action" value="apply">Применить</button>
         {{ end }}
-        <button type="submit" class="btn btn-sm btn-primary" name="save">Сохранить</button>
+        <button type="submit" class="btn btn-sm btn-primary" name="action" value="save">Сохранить</button>
     </form>
 </main>