feat: add publish/unpublish article, show by slug article, update response article

This commit is contained in:
hanif salafi 2025-10-24 08:47:07 +07:00
parent 0d7b29dd7c
commit 08820dbee5
9 changed files with 816 additions and 1 deletions

View File

@ -58,8 +58,13 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() {
router.Get("/pending-approval", articlesController.GetPendingApprovals)
router.Get("/waiting-for-approval", articlesController.GetArticlesWaitingForApproval)
// Publish/Unpublish routes
router.Put("/:id/publish", articlesController.Publish)
router.Put("/:id/unpublish", articlesController.Unpublish)
router.Get("/", articlesController.All)
router.Get("/old-id/:id", articlesController.ShowByOldId)
router.Get("/slug/:slug", articlesController.ShowBySlug)
router.Get("/:id", articlesController.Show)
router.Post("/", articlesController.Save)
router.Put("/:id", articlesController.Update)

View File

@ -23,6 +23,7 @@ type ArticlesController interface {
All(c *fiber.Ctx) error
Show(c *fiber.Ctx) error
ShowByOldId(c *fiber.Ctx) error
ShowBySlug(c *fiber.Ctx) error
Save(c *fiber.Ctx) error
SaveThumbnail(c *fiber.Ctx) error
Update(c *fiber.Ctx) error
@ -39,6 +40,10 @@ type ArticlesController interface {
GetApprovalStatus(c *fiber.Ctx) error
GetPendingApprovals(c *fiber.Ctx) error
GetArticlesWaitingForApproval(c *fiber.Ctx) error
// Publish/Unpublish methods
Publish(c *fiber.Ctx) error
Unpublish(c *fiber.Ctx) error
}
func NewArticlesController(articlesService service.ArticlesService, log zerolog.Logger) ArticlesController {
@ -174,6 +179,42 @@ func (_i *articlesController) ShowByOldId(c *fiber.Ctx) error {
})
}
// ShowBySlug Articles
// @Summary Get one Articles by Slug
// @Description API for getting one Articles by slug
// @Tags Articles
// @Security Bearer
// @Param X-Client-Key header string true "Insert the X-Client-Key"
// @Param slug path string true "Articles Slug"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.BadRequestError
// @Failure 401 {object} response.UnauthorizedError
// @Failure 500 {object} response.InternalServerError
// @Router /articles/slug/{slug} [get]
func (_i *articlesController) ShowBySlug(c *fiber.Ctx) error {
slug := c.Params("slug")
if slug == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": true,
"msg": "Slug parameter is required",
})
}
// Get ClientId from context
clientId := middleware.GetClientID(c)
articlesData, err := _i.articlesService.ShowBySlug(clientId, slug)
if err != nil {
return err
}
return utilRes.Resp(c, utilRes.Response{
Success: true,
Messages: utilRes.Messages{"Articles successfully retrieved"},
Data: articlesData,
})
}
// Save Articles
// @Summary Create Articles
// @Description API for create Articles
@ -680,3 +721,77 @@ func (_i *articlesController) GetArticlesWaitingForApproval(c *fiber.Ctx) error
Meta: paging,
})
}
// Publish Articles
// @Summary Publish Article
// @Description API for publishing an article
// @Tags Articles
// @Security Bearer
// @Param X-Client-Key header string true "Insert the X-Client-Key"
// @Param X-Csrf-Token header string false "Insert the X-Csrf-Token"
// @Param Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param id path int true "article id"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.BadRequestError
// @Failure 401 {object} response.UnauthorizedError
// @Failure 500 {object} response.InternalServerError
// @Router /articles/{id}/publish [put]
func (_i *articlesController) Publish(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
if err != nil {
return err
}
// Get ClientId from context
clientId := middleware.GetClientID(c)
// Get Authorization token from header
authToken := c.Get("Authorization")
err = _i.articlesService.Publish(clientId, uint(id), authToken)
if err != nil {
return err
}
return utilRes.Resp(c, utilRes.Response{
Success: true,
Messages: utilRes.Messages{"Article successfully published"},
})
}
// Unpublish Articles
// @Summary Unpublish Article
// @Description API for unpublishing an article
// @Tags Articles
// @Security Bearer
// @Param X-Client-Key header string true "Insert the X-Client-Key"
// @Param X-Csrf-Token header string false "Insert the X-Csrf-Token"
// @Param Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param id path int true "article id"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.BadRequestError
// @Failure 401 {object} response.UnauthorizedError
// @Failure 500 {object} response.InternalServerError
// @Router /articles/{id}/unpublish [put]
func (_i *articlesController) Unpublish(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
if err != nil {
return err
}
// Get ClientId from context
clientId := middleware.GetClientID(c)
// Get Authorization token from header
authToken := c.Get("Authorization")
err = _i.articlesService.Unpublish(clientId, uint(id), authToken)
if err != nil {
return err
}
return utilRes.Resp(c, utilRes.Response{
Success: true,
Messages: utilRes.Messages{"Article successfully unpublished"},
})
}

View File

@ -53,6 +53,23 @@ func ArticlesResponseMapper(
}
}
// Calculate PublishStatus based on conditions
publishStatus := "Cancel" // Default status
if articlesReq.IsPublish != nil && *articlesReq.IsPublish {
// Published: isPublish = true
publishStatus = "Published"
} else if articlesReq.PublishSchedule != nil && *articlesReq.PublishSchedule != "" {
// On Schedule: has publishSchedule and isPublish = false
if articlesReq.IsPublish == nil || !*articlesReq.IsPublish {
publishStatus = "On Schedule"
}
} else if articlesReq.IsPublish != nil && !*articlesReq.IsPublish &&
articlesReq.IsDraft != nil && !*articlesReq.IsDraft {
// Cancel: isPublish = false and isDraft = false
publishStatus = "Cancel"
}
if articlesReq != nil {
articlesRes = &res.ArticlesResponse{
ID: articlesReq.ID,
@ -73,9 +90,13 @@ func ArticlesResponseMapper(
CommentCount: articlesReq.CommentCount,
OldId: articlesReq.OldId,
StatusId: articlesReq.StatusId,
IsDraft: articlesReq.IsDraft,
DraftedAt: articlesReq.DraftedAt,
IsBanner: articlesReq.IsBanner,
IsPublish: articlesReq.IsPublish,
PublishSchedule: articlesReq.PublishSchedule,
PublishedAt: articlesReq.PublishedAt,
PublishStatus: publishStatus,
IsActive: articlesReq.IsActive,
Source: articlesReq.Source,
CustomCreatorName: articlesReq.CustomCreatorName,

View File

@ -27,6 +27,7 @@ type ArticlesRepository interface {
FindOne(clientId *uuid.UUID, id uint) (articles *entity.Articles, err error)
FindByFilename(clientId *uuid.UUID, thumbnailName string) (articleReturn *entity.Articles, err error)
FindByOldId(clientId *uuid.UUID, oldId uint) (articles *entity.Articles, err error)
FindBySlug(clientId *uuid.UUID, slug string) (articles *entity.Articles, err error)
Create(clientId *uuid.UUID, articles *entity.Articles) (articleReturn *entity.Articles, err error)
Update(clientId *uuid.UUID, id uint, articles *entity.Articles) (err error)
UpdateSkipNull(clientId *uuid.UUID, id uint, articles *entity.Articles) (err error)
@ -246,6 +247,18 @@ func (_i *articlesRepository) FindByOldId(clientId *uuid.UUID, oldId uint) (arti
return articles, nil
}
func (_i *articlesRepository) FindBySlug(clientId *uuid.UUID, slug string) (articles *entity.Articles, err error) {
query := _i.DB.DB.Where("slug = ?", slug)
if clientId != nil {
query = query.Where("client_id = ?", clientId)
}
if err := query.First(&articles).Error; err != nil {
return nil, err
}
return articles, nil
}
func (_i *articlesRepository) Create(clientId *uuid.UUID, articles *entity.Articles) (articleReturn *entity.Articles, err error) {
// Set client ID
if clientId != nil {

View File

@ -26,9 +26,13 @@ type ArticlesResponse struct {
AiArticleId *int `json:"aiArticleId"`
OldId *uint `json:"oldId"`
StatusId *int `json:"statusId"`
IsDraft *bool `json:"isDraft"`
DraftedAt *time.Time `json:"draftedAt"`
IsBanner *bool `json:"isBanner"`
IsPublish *bool `json:"isPublish"`
PublishedAt *time.Time `json:"publishedAt"`
PublishSchedule *string `json:"publishSchedule"`
PublishStatus string `json:"publishStatus"` // "On Schedule", "Published", "Cancel"
IsActive *bool `json:"isActive"`
Source *string `json:"source"`
CustomCreatorName *string `json:"customCreatorName"`

View File

@ -58,6 +58,7 @@ type ArticlesService interface {
All(clientId *uuid.UUID, authToken string, req request.ArticlesQueryRequest) (articles []*response.ArticlesResponse, paging paginator.Pagination, err error)
Show(clientId *uuid.UUID, id uint) (articles *response.ArticlesResponse, err error)
ShowByOldId(clientId *uuid.UUID, oldId uint) (articles *response.ArticlesResponse, err error)
ShowBySlug(clientId *uuid.UUID, slug string) (articles *response.ArticlesResponse, err error)
Save(clientId *uuid.UUID, req request.ArticlesCreateRequest, authToken string) (articles *entity.Articles, err error)
SaveThumbnail(clientId *uuid.UUID, c *fiber.Ctx) (err error)
Update(clientId *uuid.UUID, id uint, req request.ArticlesUpdateRequest) (err error)
@ -83,6 +84,10 @@ type ArticlesService interface {
AutoApproveArticle(clientId *uuid.UUID, articleId uint, reason string) error
GetClientApprovalSettings(clientId *uuid.UUID) (*response.ClientApprovalSettingsResponse, error)
SetArticleApprovalExempt(clientId *uuid.UUID, articleId uint, exempt bool, reason string) error
// Publish/Unpublish methods
Publish(clientId *uuid.UUID, articleId uint, authToken string) error
Unpublish(clientId *uuid.UUID, articleId uint, authToken string) error
}
// NewArticlesService init ArticlesService
@ -176,6 +181,17 @@ func (_i *articlesService) ShowByOldId(clientId *uuid.UUID, oldId uint) (article
return mapper.ArticlesResponseMapper(_i.Log, host, clientId, result, _i.ArticleCategoriesRepo, _i.ArticleCategoryDetailsRepo, _i.ArticleFilesRepo, _i.UsersRepo), nil
}
func (_i *articlesService) ShowBySlug(clientId *uuid.UUID, slug string) (articles *response.ArticlesResponse, err error) {
result, err := _i.Repo.FindBySlug(clientId, slug)
if err != nil {
return nil, err
}
host := _i.Cfg.App.Domain
return mapper.ArticlesResponseMapper(_i.Log, host, clientId, result, _i.ArticleCategoriesRepo, _i.ArticleCategoryDetailsRepo, _i.ArticleFilesRepo, _i.UsersRepo), nil
}
func (_i *articlesService) Save(clientId *uuid.UUID, req request.ArticlesCreateRequest, authToken string) (articles *entity.Articles, err error) {
_i.Log.Info().Interface("data", req).Msg("")
newReq := req.ToEntity()
@ -1205,6 +1221,133 @@ func (_i *articlesService) SetArticleApprovalExempt(clientId *uuid.UUID, article
return nil
}
// Publish publishes an article
func (_i *articlesService) Publish(clientId *uuid.UUID, articleId uint, authToken string) error {
// Extract user info from auth token
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if user == nil {
return errors.New("user not found from auth token")
}
// Check if article exists
article, err := _i.Repo.FindOne(clientId, articleId)
if err != nil {
return err
}
// Check if article is already published
if article.IsPublish != nil && *article.IsPublish {
return errors.New("article is already published")
}
// Check if user has permission to publish
// For now, we'll allow any authenticated user to publish
// You can add more sophisticated permission checks here
// Update article to published status
isPublish := true
publishedAt := time.Now()
isDraftFalse := false
statusIdTwo := 2 // Published status
article.IsPublish = &isPublish
article.PublishedAt = &publishedAt
article.IsDraft = &isDraftFalse
article.DraftedAt = nil
article.StatusId = &statusIdTwo
article.PublishSchedule = nil // Clear any scheduled publish time
err = _i.Repo.Update(clientId, articleId, article)
if err != nil {
return err
}
// Create approval record for audit trail
articleApproval := &entity.ArticleApprovals{
ArticleId: articleId,
ApprovalBy: user.ID,
StatusId: statusIdTwo,
Message: "Article published",
ApprovalAtLevel: nil,
}
_, err = _i.ArticleApprovalsRepo.Create(articleApproval)
if err != nil {
_i.Log.Error().Err(err).Msg("Failed to create approval record for published article")
// Don't return error as article was already updated
}
_i.Log.Info().
Str("article_id", fmt.Sprintf("%d", articleId)).
Str("client_id", clientId.String()).
Str("user_id", fmt.Sprintf("%d", user.ID)).
Msg("Article published successfully")
return nil
}
// Unpublish unpublishes an article
func (_i *articlesService) Unpublish(clientId *uuid.UUID, articleId uint, authToken string) error {
// Extract user info from auth token
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if user == nil {
return errors.New("user not found from auth token")
}
// Check if article exists
article, err := _i.Repo.FindOne(clientId, articleId)
if err != nil {
return err
}
// Check if article is already unpublished
if article.IsPublish == nil || !*article.IsPublish {
return errors.New("article is already unpublished")
}
// Check if user has permission to unpublish
// For now, we'll allow any authenticated user to unpublish
// You can add more sophisticated permission checks here
// Update article to unpublished status
isPublishFalse := false
isDraftTrue := true
draftedAt := time.Now()
statusIdOne := 1 // Draft status
article.IsPublish = &isPublishFalse
article.PublishedAt = nil
article.IsDraft = &isDraftTrue
article.DraftedAt = &draftedAt
article.StatusId = &statusIdOne
err = _i.Repo.Update(clientId, articleId, article)
if err != nil {
return err
}
// Create approval record for audit trail
articleApproval := &entity.ArticleApprovals{
ArticleId: articleId,
ApprovalBy: user.ID,
StatusId: statusIdOne,
Message: "Article unpublished",
ApprovalAtLevel: nil,
}
_, err = _i.ArticleApprovalsRepo.Create(articleApproval)
if err != nil {
_i.Log.Error().Err(err).Msg("Failed to create approval record for unpublished article")
// Don't return error as article was already updated
}
_i.Log.Info().
Str("article_id", fmt.Sprintf("%d", articleId)).
Str("client_id", clientId.String()).
Str("user_id", fmt.Sprintf("%d", user.ID)).
Msg("Article unpublished successfully")
return nil
}
// findNextApprovalLevel finds the next higher level for approval
func (_i *articlesService) findNextApprovalLevel(clientId *uuid.UUID, currentLevelNumber int) int {
// For now, we'll use a simple logic based on level numbers

View File

@ -7307,6 +7307,62 @@ const docTemplate = `{
}
}
},
"/articles/slug/{slug}": {
"get": {
"security": [
{
"Bearer": []
}
],
"description": "API for getting one Articles by slug",
"tags": [
"Articles"
],
"summary": "Get one Articles by Slug",
"parameters": [
{
"type": "string",
"description": "Insert the X-Client-Key",
"name": "X-Client-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Articles Slug",
"name": "slug",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.BadRequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.InternalServerError"
}
}
}
}
},
"/articles/statistic/monthly": {
"get": {
"security": [
@ -7913,6 +7969,75 @@ const docTemplate = `{
}
}
},
"/articles/{id}/publish": {
"put": {
"security": [
{
"Bearer": []
}
],
"description": "API for publishing an article",
"tags": [
"Articles"
],
"summary": "Publish Article",
"parameters": [
{
"type": "string",
"description": "Insert the X-Client-Key",
"name": "X-Client-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Insert the X-Csrf-Token",
"name": "X-Csrf-Token",
"in": "header"
},
{
"type": "string",
"default": "Bearer \u003cAdd access token here\u003e",
"description": "Insert your access token",
"name": "Authorization",
"in": "header"
},
{
"type": "integer",
"description": "article id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.BadRequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.InternalServerError"
}
}
}
}
},
"/articles/{id}/submit-approval": {
"post": {
"security": [
@ -7990,6 +8115,75 @@ const docTemplate = `{
}
}
},
"/articles/{id}/unpublish": {
"put": {
"security": [
{
"Bearer": []
}
],
"description": "API for unpublishing an article",
"tags": [
"Articles"
],
"summary": "Unpublish Article",
"parameters": [
{
"type": "string",
"description": "Insert the X-Client-Key",
"name": "X-Client-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Insert the X-Csrf-Token",
"name": "X-Csrf-Token",
"in": "header"
},
{
"type": "string",
"default": "Bearer \u003cAdd access token here\u003e",
"description": "Insert your access token",
"name": "Authorization",
"in": "header"
},
{
"type": "integer",
"description": "article id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.BadRequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.InternalServerError"
}
}
}
}
},
"/bookmarks": {
"get": {
"security": [

View File

@ -7296,6 +7296,62 @@
}
}
},
"/articles/slug/{slug}": {
"get": {
"security": [
{
"Bearer": []
}
],
"description": "API for getting one Articles by slug",
"tags": [
"Articles"
],
"summary": "Get one Articles by Slug",
"parameters": [
{
"type": "string",
"description": "Insert the X-Client-Key",
"name": "X-Client-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Articles Slug",
"name": "slug",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.BadRequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.InternalServerError"
}
}
}
}
},
"/articles/statistic/monthly": {
"get": {
"security": [
@ -7902,6 +7958,75 @@
}
}
},
"/articles/{id}/publish": {
"put": {
"security": [
{
"Bearer": []
}
],
"description": "API for publishing an article",
"tags": [
"Articles"
],
"summary": "Publish Article",
"parameters": [
{
"type": "string",
"description": "Insert the X-Client-Key",
"name": "X-Client-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Insert the X-Csrf-Token",
"name": "X-Csrf-Token",
"in": "header"
},
{
"type": "string",
"default": "Bearer \u003cAdd access token here\u003e",
"description": "Insert your access token",
"name": "Authorization",
"in": "header"
},
{
"type": "integer",
"description": "article id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.BadRequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.InternalServerError"
}
}
}
}
},
"/articles/{id}/submit-approval": {
"post": {
"security": [
@ -7979,6 +8104,75 @@
}
}
},
"/articles/{id}/unpublish": {
"put": {
"security": [
{
"Bearer": []
}
],
"description": "API for unpublishing an article",
"tags": [
"Articles"
],
"summary": "Unpublish Article",
"parameters": [
{
"type": "string",
"description": "Insert the X-Client-Key",
"name": "X-Client-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Insert the X-Csrf-Token",
"name": "X-Csrf-Token",
"in": "header"
},
{
"type": "string",
"default": "Bearer \u003cAdd access token here\u003e",
"description": "Insert your access token",
"name": "Authorization",
"in": "header"
},
{
"type": "integer",
"description": "article id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.BadRequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.UnauthorizedError"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.InternalServerError"
}
}
}
}
},
"/bookmarks": {
"get": {
"security": [

View File

@ -6106,6 +6106,51 @@ paths:
summary: Get Article Approval Status
tags:
- Articles
/articles/{id}/publish:
put:
description: API for publishing an article
parameters:
- description: Insert the X-Client-Key
in: header
name: X-Client-Key
required: true
type: string
- description: Insert the X-Csrf-Token
in: header
name: X-Csrf-Token
type: string
- default: Bearer <Add access token here>
description: Insert your access token
in: header
name: Authorization
type: string
- description: article id
in: path
name: id
required: true
type: integer
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.BadRequestError'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.UnauthorizedError'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.InternalServerError'
security:
- Bearer: []
summary: Publish Article
tags:
- Articles
/articles/{id}/submit-approval:
post:
description: API for submitting article for approval workflow
@ -6156,6 +6201,51 @@ paths:
summary: Submit Article for Approval
tags:
- Articles
/articles/{id}/unpublish:
put:
description: API for unpublishing an article
parameters:
- description: Insert the X-Client-Key
in: header
name: X-Client-Key
required: true
type: string
- description: Insert the X-Csrf-Token
in: header
name: X-Csrf-Token
type: string
- default: Bearer <Add access token here>
description: Insert your access token
in: header
name: Authorization
type: string
- description: article id
in: path
name: id
required: true
type: integer
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.BadRequestError'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.UnauthorizedError'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.InternalServerError'
security:
- Bearer: []
summary: Unpublish Article
tags:
- Articles
/articles/banner/{id}:
put:
description: API for Update Banner Articles
@ -6332,6 +6422,42 @@ paths:
summary: PublishScheduling Articles
tags:
- Articles
/articles/slug/{slug}:
get:
description: API for getting one Articles by slug
parameters:
- description: Insert the X-Client-Key
in: header
name: X-Client-Key
required: true
type: string
- description: Articles Slug
in: path
name: slug
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.BadRequestError'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.UnauthorizedError'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.InternalServerError'
security:
- Bearer: []
summary: Get one Articles by Slug
tags:
- Articles
/articles/statistic/monthly:
get:
description: API for ArticleMonthlyStats of Article