feat: update articles & articles_categories

This commit is contained in:
hanif salafi 2025-01-20 11:43:40 +07:00
parent ea0637aac2
commit 58c3bfc283
14 changed files with 141 additions and 42 deletions

View File

@ -8,6 +8,7 @@ type ArticleCategories struct {
Description string `json:"description" gorm:"type:varchar"` Description string `json:"description" gorm:"type:varchar"`
ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"` ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"`
ParentId *int `json:"parent_id" gorm:"type:int4"` ParentId *int `json:"parent_id" gorm:"type:int4"`
Tags *string `json:"tags" gorm:"type:varchar"`
Position *int `json:"position" gorm:"type:int4"` Position *int `json:"position" gorm:"type:int4"`
CreatedById *uint `json:"created_by_id" gorm:"type:int4"` CreatedById *uint `json:"created_by_id" gorm:"type:int4"`
StatusId int `json:"status_id" gorm:"type:int4;default:1"` StatusId int `json:"status_id" gorm:"type:int4;default:1"`

View File

@ -4,7 +4,7 @@ import "time"
type ArticleCategoryDetails struct { type ArticleCategoryDetails struct {
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"` ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
ArticleId int `json:"article_id" gorm:"type:int4"` ArticleId uint `json:"article_id" gorm:"type:int4"`
CategoryId int `json:"category_id" gorm:"type:int4"` CategoryId int `json:"category_id" gorm:"type:int4"`
IsActive bool `json:"is_active" gorm:"type:bool"` IsActive bool `json:"is_active" gorm:"type:bool"`
CreatedAt time.Time `json:"created_at" gorm:"default:now()"` CreatedAt time.Time `json:"created_at" gorm:"default:now()"`

View File

@ -4,16 +4,16 @@ import (
"go-humas-be/app/database/entity" "go-humas-be/app/database/entity"
res "go-humas-be/app/module/article_categories/response" res "go-humas-be/app/module/article_categories/response"
"strconv" "strconv"
"strings"
) )
func ArticleCategoriesResponseMapper(articleCategoriesReq *entity.ArticleCategories) (articleCategoriesRes *res.ArticleCategoriesResponse) { func ArticleCategoriesResponseMapper(articleCategoriesReq *entity.ArticleCategories, host string) (articleCategoriesRes *res.ArticleCategoriesResponse) {
if articleCategoriesReq != nil { if articleCategoriesReq != nil {
articleCategoriesRes = &res.ArticleCategoriesResponse{ articleCategoriesRes = &res.ArticleCategoriesResponse{
ID: articleCategoriesReq.ID, ID: articleCategoriesReq.ID,
Title: articleCategoriesReq.Title, Title: articleCategoriesReq.Title,
Description: articleCategoriesReq.Description, Description: articleCategoriesReq.Description,
ThumbnailPath: articleCategoriesReq.ThumbnailPath, ThumbnailPath: articleCategoriesReq.ThumbnailPath,
ThumbnailUrl: "/article-categories/thumbnail/viewer/" + strconv.Itoa(int(articleCategoriesReq.ID)),
ParentId: articleCategoriesReq.ParentId, ParentId: articleCategoriesReq.ParentId,
CreatedById: articleCategoriesReq.CreatedById, CreatedById: articleCategoriesReq.CreatedById,
StatusId: articleCategoriesReq.StatusId, StatusId: articleCategoriesReq.StatusId,
@ -23,6 +23,15 @@ func ArticleCategoriesResponseMapper(articleCategoriesReq *entity.ArticleCategor
CreatedAt: articleCategoriesReq.CreatedAt, CreatedAt: articleCategoriesReq.CreatedAt,
UpdatedAt: articleCategoriesReq.UpdatedAt, UpdatedAt: articleCategoriesReq.UpdatedAt,
} }
if articleCategoriesReq.Tags != nil {
tagsValue := *articleCategoriesReq.Tags
articleCategoriesRes.Tags = strings.Split(tagsValue, ",")
}
if articleCategoriesRes.ThumbnailPath != nil {
articleCategoriesRes.ThumbnailUrl = host + "/article-categories/thumbnail/viewer/" + strconv.Itoa(int(articleCategoriesReq.ID))
}
} }
return articleCategoriesRes return articleCategoriesRes
} }

View File

@ -24,6 +24,7 @@ type ArticleCategoriesCreateRequest struct {
Title string `json:"title" validate:"required"` Title string `json:"title" validate:"required"`
Description string `json:"description" validate:"required"` Description string `json:"description" validate:"required"`
StatusId int `json:"statusId" validate:"required"` StatusId int `json:"statusId" validate:"required"`
Tags *string `json:"tags"`
ParentId *int `json:"parentId"` ParentId *int `json:"parentId"`
} }
@ -31,6 +32,7 @@ func (req ArticleCategoriesCreateRequest) ToEntity() *entity.ArticleCategories {
return &entity.ArticleCategories{ return &entity.ArticleCategories{
Title: req.Title, Title: req.Title,
Description: req.Description, Description: req.Description,
Tags: req.Tags,
ParentId: req.ParentId, ParentId: req.ParentId,
StatusId: req.StatusId, StatusId: req.StatusId,
} }
@ -41,6 +43,7 @@ type ArticleCategoriesUpdateRequest struct {
Title string `json:"title" validate:"required"` Title string `json:"title" validate:"required"`
Description string `json:"description" validate:"required"` Description string `json:"description" validate:"required"`
StatusId int `json:"statusId" validate:"required"` StatusId int `json:"statusId" validate:"required"`
Tags *string `json:"tags"`
ParentId *int `json:"parentId"` ParentId *int `json:"parentId"`
IsPublish *bool `json:"isPublish"` IsPublish *bool `json:"isPublish"`
PublishedAt *time.Time `json:"publishedAt"` PublishedAt *time.Time `json:"publishedAt"`
@ -52,6 +55,7 @@ func (req ArticleCategoriesUpdateRequest) ToEntity() *entity.ArticleCategories {
Title: req.Title, Title: req.Title,
Description: req.Description, Description: req.Description,
ParentId: req.ParentId, ParentId: req.ParentId,
Tags: req.Tags,
StatusId: req.StatusId, StatusId: req.StatusId,
IsPublish: req.IsPublish, IsPublish: req.IsPublish,
PublishedAt: req.PublishedAt, PublishedAt: req.PublishedAt,

View File

@ -6,8 +6,9 @@ type ArticleCategoriesResponse struct {
ID uint `json:"id"` ID uint `json:"id"`
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
ThumbnailPath *string `json:"thumbnailPath"`
ThumbnailUrl string `json:"thumbnailUrl"` ThumbnailUrl string `json:"thumbnailUrl"`
Tags []string `json:"tags"`
ThumbnailPath *string `json:"thumbnailPath"`
ParentId *int `json:"parentId"` ParentId *int `json:"parentId"`
CreatedById *uint `json:"createdById"` CreatedById *uint `json:"createdById"`
StatusId int `json:"statusId"` StatusId int `json:"statusId"`

View File

@ -11,6 +11,7 @@ import (
"go-humas-be/app/module/article_categories/request" "go-humas-be/app/module/article_categories/request"
"go-humas-be/app/module/article_categories/response" "go-humas-be/app/module/article_categories/response"
usersRepository "go-humas-be/app/module/users/repository" usersRepository "go-humas-be/app/module/users/repository"
config "go-humas-be/config/config"
minioStorage "go-humas-be/config/config" minioStorage "go-humas-be/config/config"
"go-humas-be/utils/paginator" "go-humas-be/utils/paginator"
utilSvc "go-humas-be/utils/service" utilSvc "go-humas-be/utils/service"
@ -30,6 +31,7 @@ type articleCategoriesService struct {
UsersRepo usersRepository.UsersRepository UsersRepo usersRepository.UsersRepository
MinioStorage *minioStorage.MinioStorage MinioStorage *minioStorage.MinioStorage
Log zerolog.Logger Log zerolog.Logger
Cfg *config.Config
} }
// ArticleCategoriesService define interface of IArticleCategoriesService // ArticleCategoriesService define interface of IArticleCategoriesService
@ -44,13 +46,14 @@ type ArticleCategoriesService interface {
} }
// NewArticleCategoriesService init ArticleCategoriesService // NewArticleCategoriesService init ArticleCategoriesService
func NewArticleCategoriesService(repo repository.ArticleCategoriesRepository, usersRepo usersRepository.UsersRepository, minioStorage *minioStorage.MinioStorage, log zerolog.Logger) ArticleCategoriesService { func NewArticleCategoriesService(repo repository.ArticleCategoriesRepository, usersRepo usersRepository.UsersRepository, minioStorage *minioStorage.MinioStorage, log zerolog.Logger, cfg *config.Config) ArticleCategoriesService {
return &articleCategoriesService{ return &articleCategoriesService{
Repo: repo, Repo: repo,
UsersRepo: usersRepo, UsersRepo: usersRepo,
MinioStorage: minioStorage, MinioStorage: minioStorage,
Log: log, Log: log,
Cfg: cfg,
} }
} }
@ -61,8 +64,10 @@ func (_i *articleCategoriesService) All(req request.ArticleCategoriesQueryReques
return return
} }
host := _i.Cfg.App.Domain
port := _i.Cfg.App.ExternalPort
for _, result := range results { for _, result := range results {
articleCategoriess = append(articleCategoriess, mapper.ArticleCategoriesResponseMapper(result)) articleCategoriess = append(articleCategoriess, mapper.ArticleCategoriesResponseMapper(result, host+port))
} }
return return
@ -73,8 +78,9 @@ func (_i *articleCategoriesService) Show(id uint) (articleCategories *response.A
if err != nil { if err != nil {
return nil, err return nil, err
} }
host := _i.Cfg.App.Domain
return mapper.ArticleCategoriesResponseMapper(result), nil port := _i.Cfg.App.ExternalPort
return mapper.ArticleCategoriesResponseMapper(result, host+port), nil
} }
func (_i *articleCategoriesService) Save(req request.ArticleCategoriesCreateRequest, authToken string) (articleCategories *entity.ArticleCategories, err error) { func (_i *articleCategoriesService) Save(req request.ArticleCategoriesCreateRequest, authToken string) (articleCategories *entity.ArticleCategories, err error) {

View File

@ -18,7 +18,7 @@ type ArticleCategoryDetailsQueryRequest struct {
} }
type ArticleCategoryDetailsCreateRequest struct { type ArticleCategoryDetailsCreateRequest struct {
ArticleId int `json:"article_id" validate:"required"` ArticleId uint `json:"article_id" validate:"required"`
CategoryId int `json:"category_id" validate:"required"` CategoryId int `json:"category_id" validate:"required"`
IsActive bool `json:"is_active" validate:"required"` IsActive bool `json:"is_active" validate:"required"`
} }
@ -33,7 +33,7 @@ func (req ArticleCategoryDetailsCreateRequest) ToEntity() *entity.ArticleCategor
type ArticleCategoryDetailsUpdateRequest struct { type ArticleCategoryDetailsUpdateRequest struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
ArticleId int `json:"article_id" validate:"required"` ArticleId uint `json:"article_id" validate:"required"`
CategoryId int `json:"category_id" validate:"required"` CategoryId int `json:"category_id" validate:"required"`
IsActive bool `json:"is_active" validate:"required"` IsActive bool `json:"is_active" validate:"required"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`

View File

@ -13,15 +13,12 @@ import (
func ArticlesResponseMapper( func ArticlesResponseMapper(
log zerolog.Logger, log zerolog.Logger,
host string,
articlesReq *entity.Articles, articlesReq *entity.Articles,
articleCategoriesRepo articleCategoriesRepository.ArticleCategoriesRepository, articleCategoriesRepo articleCategoriesRepository.ArticleCategoriesRepository,
articleFilesRepo articleFilesRepository.ArticleFilesRepository, articleFilesRepo articleFilesRepository.ArticleFilesRepository,
usersRepo usersRepository.UsersRepository, usersRepo usersRepository.UsersRepository,
) (articlesRes *res.ArticlesResponse) { ) (articlesRes *res.ArticlesResponse) {
thumbnailUrl := "/articles/thumbnail/viewer/"
if articlesReq.ThumbnailName != nil {
thumbnailUrl += *articlesReq.ThumbnailName
}
createdByName := "" createdByName := ""
if articlesReq.CreatedById != nil { if articlesReq.CreatedById != nil {
@ -56,7 +53,6 @@ func ArticlesResponseMapper(
HtmlDescription: articlesReq.HtmlDescription, HtmlDescription: articlesReq.HtmlDescription,
TypeId: articlesReq.TypeId, TypeId: articlesReq.TypeId,
Tags: articlesReq.Tags, Tags: articlesReq.Tags,
ThumbnailUrl: thumbnailUrl,
CategoryId: articlesReq.CategoryId, CategoryId: articlesReq.CategoryId,
CategoryName: categoryName, CategoryName: categoryName,
PageUrl: articlesReq.PageUrl, PageUrl: articlesReq.PageUrl,
@ -73,6 +69,10 @@ func ArticlesResponseMapper(
UpdatedAt: articlesReq.UpdatedAt, UpdatedAt: articlesReq.UpdatedAt,
ArticleFiles: articleFilesArr, ArticleFiles: articleFilesArr,
} }
if articlesReq.ThumbnailName != nil {
articlesRes.ThumbnailUrl = host + "/articles/thumbnail/viewer/" + *articlesReq.ThumbnailName
}
} }
return articlesRes return articlesRes

View File

@ -29,6 +29,7 @@ type ArticlesCreateRequest struct {
Description string `json:"description" validate:"required"` Description string `json:"description" validate:"required"`
HtmlDescription string `json:"htmlDescription" validate:"required"` HtmlDescription string `json:"htmlDescription" validate:"required"`
CategoryId int `json:"categoryId" validate:"required"` CategoryId int `json:"categoryId" validate:"required"`
CategoryIds string `json:"categoryIds" validate:"required"`
TypeId int `json:"typeId" validate:"required"` TypeId int `json:"typeId" validate:"required"`
Tags string `json:"tags" validate:"required"` Tags string `json:"tags" validate:"required"`
OldId *uint `json:"oldId"` OldId *uint `json:"oldId"`

View File

@ -2,17 +2,21 @@ package service
import ( import (
"context" "context"
"errors"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"go-humas-be/app/database/entity" "go-humas-be/app/database/entity"
articleCategoriesRepository "go-humas-be/app/module/article_categories/repository" articleCategoriesRepository "go-humas-be/app/module/article_categories/repository"
articleCategoryDetailsRepository "go-humas-be/app/module/article_category_details/repository"
articleCategoryDetailsReq "go-humas-be/app/module/article_category_details/request"
articleFilesRepository "go-humas-be/app/module/article_files/repository" articleFilesRepository "go-humas-be/app/module/article_files/repository"
"go-humas-be/app/module/articles/mapper" "go-humas-be/app/module/articles/mapper"
"go-humas-be/app/module/articles/repository" "go-humas-be/app/module/articles/repository"
"go-humas-be/app/module/articles/request" "go-humas-be/app/module/articles/request"
"go-humas-be/app/module/articles/response" "go-humas-be/app/module/articles/response"
usersRepository "go-humas-be/app/module/users/repository" usersRepository "go-humas-be/app/module/users/repository"
config "go-humas-be/config/config"
minioStorage "go-humas-be/config/config" minioStorage "go-humas-be/config/config"
"go-humas-be/utils/paginator" "go-humas-be/utils/paginator"
utilSvc "go-humas-be/utils/service" utilSvc "go-humas-be/utils/service"
@ -31,7 +35,9 @@ type articlesService struct {
Repo repository.ArticlesRepository Repo repository.ArticlesRepository
ArticleCategoriesRepo articleCategoriesRepository.ArticleCategoriesRepository ArticleCategoriesRepo articleCategoriesRepository.ArticleCategoriesRepository
ArticleFilesRepo articleFilesRepository.ArticleFilesRepository ArticleFilesRepo articleFilesRepository.ArticleFilesRepository
ArticleCategoryDetailsRepo articleCategoryDetailsRepository.ArticleCategoryDetailsRepository
Log zerolog.Logger Log zerolog.Logger
Cfg *config.Config
UsersRepo usersRepository.UsersRepository UsersRepo usersRepository.UsersRepository
MinioStorage *minioStorage.MinioStorage MinioStorage *minioStorage.MinioStorage
} }
@ -51,8 +57,10 @@ type ArticlesService interface {
func NewArticlesService( func NewArticlesService(
repo repository.ArticlesRepository, repo repository.ArticlesRepository,
articleCategoriesRepo articleCategoriesRepository.ArticleCategoriesRepository, articleCategoriesRepo articleCategoriesRepository.ArticleCategoriesRepository,
articleCategoryDetailsRepo articleCategoryDetailsRepository.ArticleCategoryDetailsRepository,
articleFilesRepo articleFilesRepository.ArticleFilesRepository, articleFilesRepo articleFilesRepository.ArticleFilesRepository,
log zerolog.Logger, log zerolog.Logger,
cfg *config.Config,
usersRepo usersRepository.UsersRepository, usersRepo usersRepository.UsersRepository,
minioStorage *minioStorage.MinioStorage, minioStorage *minioStorage.MinioStorage,
) ArticlesService { ) ArticlesService {
@ -60,10 +68,12 @@ func NewArticlesService(
return &articlesService{ return &articlesService{
Repo: repo, Repo: repo,
ArticleCategoriesRepo: articleCategoriesRepo, ArticleCategoriesRepo: articleCategoriesRepo,
ArticleCategoryDetailsRepo: articleCategoryDetailsRepo,
ArticleFilesRepo: articleFilesRepo, ArticleFilesRepo: articleFilesRepo,
Log: log, Log: log,
UsersRepo: usersRepo, UsersRepo: usersRepo,
MinioStorage: minioStorage, MinioStorage: minioStorage,
Cfg: cfg,
} }
} }
@ -78,8 +88,11 @@ func (_i *articlesService) All(req request.ArticlesQueryRequest) (articless []*r
Format(time.RFC3339)).Str("Service:articlesService", "Methods:All"). Format(time.RFC3339)).Str("Service:articlesService", "Methods:All").
Interface("results", results).Msg("") Interface("results", results).Msg("")
host := _i.Cfg.App.Domain
port := _i.Cfg.App.ExternalPort
for _, result := range results { for _, result := range results {
articleRes := mapper.ArticlesResponseMapper(_i.Log, result, _i.ArticleCategoriesRepo, _i.ArticleFilesRepo, _i.UsersRepo) articleRes := mapper.ArticlesResponseMapper(_i.Log, host+port, result, _i.ArticleCategoriesRepo, _i.ArticleFilesRepo, _i.UsersRepo)
articless = append(articless, articleRes) articless = append(articless, articleRes)
} }
@ -92,7 +105,10 @@ func (_i *articlesService) Show(id uint) (articles *response.ArticlesResponse, e
return nil, err return nil, err
} }
return mapper.ArticlesResponseMapper(_i.Log, result, _i.ArticleCategoriesRepo, _i.ArticleFilesRepo, _i.UsersRepo), nil host := _i.Cfg.App.Domain
port := _i.Cfg.App.ExternalPort
return mapper.ArticlesResponseMapper(_i.Log, host+port, result, _i.ArticleCategoriesRepo, _i.ArticleFilesRepo, _i.UsersRepo), nil
} }
func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken string) (articles *entity.Articles, err error) { func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken string) (articles *entity.Articles, err error) {
@ -102,7 +118,41 @@ func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken str
createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
newReq.CreatedById = &createdBy.ID newReq.CreatedById = &createdBy.ID
return _i.Repo.Create(newReq) saveArticleRepo, err := _i.Repo.Create(newReq)
if err != nil {
return nil, err
}
var categoryIds []string
if req.CategoryIds != "" {
categoryIds = strings.Split(req.CategoryIds, ",")
}
for categoryId := range categoryIds {
findCategory, err := _i.ArticleCategoriesRepo.FindOne(uint(categoryId))
if err != nil {
return nil, err
}
if findCategory != nil {
return nil, errors.New("category not found")
}
categoryReq := articleCategoryDetailsReq.ArticleCategoryDetailsCreateRequest{
ArticleId: saveArticleRepo.ID,
CategoryId: categoryId,
IsActive: true,
}
newCategoryReq := categoryReq.ToEntity()
err = _i.ArticleCategoryDetailsRepo.Create(newCategoryReq)
if err != nil {
return nil, err
}
}
return saveArticleRepo, nil
} }
func (_i *articlesService) SaveThumbnail(c *fiber.Ctx) (err error) { func (_i *articlesService) SaveThumbnail(c *fiber.Ctx) (err error) {

View File

@ -3,7 +3,7 @@
name = "Fiber starter" name = "Fiber starter"
host = "http://38.47.180.165" host = "http://38.47.180.165"
port = ":8800" port = ":8800"
domain = "https://38.47.180.165" domain = "http://38.47.180.165"
external-port = ":8802" external-port = ":8802"
idle-timeout = 5 # As seconds idle-timeout = 5 # As seconds
print-routes = false print-routes = false
@ -13,7 +13,7 @@ body-limit = 1048576000 # "100 * 1024 * 1024"
[db.postgres] [db.postgres]
dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database> dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database>
migrate = false migrate = true
seed = false seed = false
[logger] [logger]

View File

@ -6125,6 +6125,9 @@ const docTemplate = `{
"statusId": { "statusId": {
"type": "integer" "type": "integer"
}, },
"tags": {
"type": "string"
},
"title": { "title": {
"type": "string" "type": "string"
} }
@ -6157,6 +6160,9 @@ const docTemplate = `{
"statusId": { "statusId": {
"type": "integer" "type": "integer"
}, },
"tags": {
"type": "string"
},
"title": { "title": {
"type": "string" "type": "string"
} }
@ -6302,6 +6308,7 @@ const docTemplate = `{
"type": "object", "type": "object",
"required": [ "required": [
"categoryId", "categoryId",
"categoryIds",
"description", "description",
"htmlDescription", "htmlDescription",
"slug", "slug",
@ -6313,6 +6320,9 @@ const docTemplate = `{
"categoryId": { "categoryId": {
"type": "integer" "type": "integer"
}, },
"categoryIds": {
"type": "string"
},
"description": { "description": {
"type": "string" "type": "string"
}, },

View File

@ -6114,6 +6114,9 @@
"statusId": { "statusId": {
"type": "integer" "type": "integer"
}, },
"tags": {
"type": "string"
},
"title": { "title": {
"type": "string" "type": "string"
} }
@ -6146,6 +6149,9 @@
"statusId": { "statusId": {
"type": "integer" "type": "integer"
}, },
"tags": {
"type": "string"
},
"title": { "title": {
"type": "string" "type": "string"
} }
@ -6291,6 +6297,7 @@
"type": "object", "type": "object",
"required": [ "required": [
"categoryId", "categoryId",
"categoryIds",
"description", "description",
"htmlDescription", "htmlDescription",
"slug", "slug",
@ -6302,6 +6309,9 @@
"categoryId": { "categoryId": {
"type": "integer" "type": "integer"
}, },
"categoryIds": {
"type": "string"
},
"description": { "description": {
"type": "string" "type": "string"
}, },

View File

@ -26,6 +26,8 @@ definitions:
type: integer type: integer
statusId: statusId:
type: integer type: integer
tags:
type: string
title: title:
type: string type: string
required: required:
@ -47,6 +49,8 @@ definitions:
type: string type: string
statusId: statusId:
type: integer type: integer
tags:
type: string
title: title:
type: string type: string
required: required:
@ -155,6 +159,8 @@ definitions:
properties: properties:
categoryId: categoryId:
type: integer type: integer
categoryIds:
type: string
description: description:
type: string type: string
htmlDescription: htmlDescription:
@ -171,6 +177,7 @@ definitions:
type: integer type: integer
required: required:
- categoryId - categoryId
- categoryIds
- description - description
- htmlDescription - htmlDescription
- slug - slug