feat: update filter article and register middleware

This commit is contained in:
hanif salafi 2025-09-23 07:22:08 +07:00
parent e39a8d442a
commit 1c9b288e10
6 changed files with 80 additions and 60 deletions

View File

@ -58,7 +58,7 @@ func (m *Middleware) Register(db *database.Database) {
m.App.Use(cors.New(cors.Config{
Next: utilsSvc.IsEnabled(m.Cfg.Middleware.Cors.Enable),
AllowOrigins: "http://localhost:3000, http://localhost:4000, https://dev.mikulnews.com, https://n8n.qudoco.com, https://narasiahli.com",
AllowOrigins: "http://localhost:3000, http://localhost:4000, https://dev.mikulnews.com, https://n8n.qudoco.com, https://narasiahli.com, https://dev.asuransiaman.com, https://dev.beritabumn.com, https://dev.kabarharapan.com, https://dev.kebaikanindonesia.com, https://dev.isukini.com",
AllowMethods: "HEAD, GET, POST, PUT, DELETE, OPTION, PATCH",
AllowHeaders: "Origin, Content-Type, Accept, Accept-Language, Authorization, X-Requested-With, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Origin, Access-Control-Allow-Credentials, X-Csrf-Token, Cookie, Set-Cookie, X-Client-Key",
ExposeHeaders: "Content-Length, Content-Type",

View File

@ -199,6 +199,11 @@ func (_i *articleApprovalFlowsRepository) GetPendingApprovals(clientId *uuid.UUI
query = query.Where("articles.category_id = ?", categoryId)
}
if typeId, ok := filters["type_id"]; ok {
query = query.Joins("JOIN articles ON article_approval_flows.article_id = articles.id")
query = query.Where("articles.type_id = ?", typeId)
}
if search, ok := filters["search"]; ok {
query = query.Joins("JOIN articles ON article_approval_flows.article_id = articles.id")
query = query.Where("articles.title ILIKE ? OR articles.description ILIKE ?", fmt.Sprintf("%%%s%%", search), fmt.Sprintf("%%%s%%", search))

View File

@ -4,21 +4,21 @@ import "time"
type ArticleFilesResponse struct {
ID uint `json:"id"`
ArticleId uint `json:"article_id"`
FilePath *string `json:"file_path"`
FileUrl *string `json:"file_url"`
FileName *string `json:"file_name"`
FileThumbnail *string `json:"file_thumbnail"`
FileAlt *string `json:"file_alt"`
WidthPixel *string `json:"width_pixel"`
HeightPixel *string `json:"height_pixel"`
ArticleId uint `json:"articleId"`
FilePath *string `json:"filePath"`
FileUrl *string `json:"fileUrl"`
FileName *string `json:"fileName"`
FileThumbnail *string `json:"fileThumbnail"`
FileAlt *string `json:"fileAlt"`
WidthPixel *string `json:"widthPixel"`
HeightPixel *string `json:"heightPixel"`
Size *string `json:"size"`
DownloadCount *int `json:"download_count"`
CreatedById int `json:"created_by_id"`
StatusId int `json:"status_id"`
IsPublish *bool `json:"is_publish"`
PublishedAt *time.Time `json:"published_at"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DownloadCount *int `json:"downloadCount"`
CreatedById int `json:"createdById"`
StatusId int `json:"statusId"`
IsPublish *bool `json:"isPublish"`
PublishedAt *time.Time `json:"publishedAt"`
IsActive bool `json:"isActive"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}

View File

@ -589,6 +589,7 @@ func (_i *articlesController) GetApprovalStatus(c *fiber.Ctx) error {
// @Param Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param page query int false "page number"
// @Param limit query int false "items per page"
// @Param typeId query int false "article type id"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.BadRequestError
// @Failure 401 {object} response.UnauthorizedError
@ -605,13 +606,21 @@ func (_i *articlesController) GetPendingApprovals(c *fiber.Ctx) error {
limit = 10
}
// Parse typeId filter
var typeId *int
if typeIdStr := c.Query("typeId"); typeIdStr != "" {
if parsedTypeId, err := strconv.Atoi(typeIdStr); err == nil {
typeId = &parsedTypeId
}
}
// Get ClientId from context
clientId := middleware.GetClientID(c)
// Get Authorization token from header
authToken := c.Get("Authorization")
response, paging, err := _i.articlesService.GetPendingApprovals(clientId, authToken, page, limit)
response, paging, err := _i.articlesService.GetPendingApprovals(clientId, authToken, page, limit, typeId) // Updated with typeId filter
if err != nil {
return err
}

View File

@ -62,18 +62,18 @@ type ArticleMonthlyStats struct {
// ArticleApprovalStatusResponse represents the approval status of an article
type ArticleApprovalStatusResponse struct {
ArticleId uint `json:"article_id"`
WorkflowId *uint `json:"workflow_id"`
WorkflowName *string `json:"workflow_name"`
CurrentStep int `json:"current_step"`
TotalSteps int `json:"total_steps"`
ArticleId uint `json:"articleId"`
WorkflowId *uint `json:"workflowId"`
WorkflowName *string `json:"workflowName"`
CurrentStep int `json:"currentStep"`
TotalSteps int `json:"totalSteps"`
Status string `json:"status"` // "pending", "in_progress", "approved", "rejected", "revision_requested"
CurrentApprover *string `json:"current_approver"`
SubmittedAt *time.Time `json:"submitted_at"`
LastActionAt *time.Time `json:"last_action_at"`
CurrentApprover *string `json:"currentApprover"`
SubmittedAt *time.Time `json:"submittedAt"`
LastActionAt *time.Time `json:"lastActionAt"`
Progress float64 `json:"progress"` // percentage complete
CanApprove bool `json:"can_approve"` // whether current user can approve
NextStep *string `json:"next_step"`
CanApprove bool `json:"canApprove"` // whether current user can approve
NextStep *string `json:"nextStep"`
}
// ArticleApprovalQueueResponse represents an article in the approval queue
@ -82,31 +82,31 @@ type ArticleApprovalQueueResponse struct {
Title string `json:"title"`
Slug string `json:"slug"`
Description string `json:"description"`
CategoryName string `json:"category_name"`
AuthorName string `json:"author_name"`
SubmittedAt time.Time `json:"submitted_at"`
CurrentStep int `json:"current_step"`
TotalSteps int `json:"total_steps"`
CategoryName string `json:"categoryName"`
AuthorName string `json:"authorName"`
SubmittedAt time.Time `json:"submittedAt"`
CurrentStep int `json:"currentStep"`
TotalSteps int `json:"totalSteps"`
Priority string `json:"priority"` // "low", "medium", "high", "urgent"
DaysInQueue int `json:"days_in_queue"`
WorkflowName string `json:"workflow_name"`
CanApprove bool `json:"can_approve"`
EstimatedTime string `json:"estimated_time"` // estimated time to complete approval
DaysInQueue int `json:"daysInQueue"`
WorkflowName string `json:"workflowName"`
CanApprove bool `json:"canApprove"`
EstimatedTime string `json:"estimatedTime"` // estimated time to complete approval
}
// ClientApprovalSettingsResponse represents client-level approval settings
type ClientApprovalSettingsResponse struct {
ClientId string `json:"client_id"`
RequiresApproval bool `json:"requires_approval"`
DefaultWorkflowId *uint `json:"default_workflow_id"`
DefaultWorkflowName *string `json:"default_workflow_name"`
AutoPublishArticles bool `json:"auto_publish_articles"`
ApprovalExemptUsers []uint `json:"approval_exempt_users"`
ApprovalExemptRoles []uint `json:"approval_exempt_roles"`
ApprovalExemptCategories []uint `json:"approval_exempt_categories"`
RequireApprovalFor []string `json:"require_approval_for"`
SkipApprovalFor []string `json:"skip_approval_for"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ClientId string `json:"clientId"`
RequiresApproval bool `json:"requiresApproval"`
DefaultWorkflowId *uint `json:"defaultWorkflowId"`
DefaultWorkflowName *string `json:"defaultWorkflowName"`
AutoPublishArticles bool `json:"autoPublishArticles"`
ApprovalExemptUsers []uint `json:"approvalExemptUsers"`
ApprovalExemptRoles []uint `json:"approvalExemptRoles"`
ApprovalExemptCategories []uint `json:"approvalExemptCategories"`
RequireApprovalFor []string `json:"requireApprovalFor"`
SkipApprovalFor []string `json:"skipApprovalFor"`
IsActive bool `json:"isActive"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}

View File

@ -76,7 +76,7 @@ type ArticlesService interface {
SubmitForApproval(clientId *uuid.UUID, articleId uint, authToken string, workflowId *uint) error
GetApprovalStatus(clientId *uuid.UUID, articleId uint) (*response.ArticleApprovalStatusResponse, error)
GetArticlesWaitingForApproval(clientId *uuid.UUID, authToken string, page, limit int) ([]*response.ArticleApprovalQueueResponse, paginator.Pagination, error)
GetPendingApprovals(clientId *uuid.UUID, authToken string, page, limit int) ([]*response.ArticleApprovalQueueResponse, paginator.Pagination, error)
GetPendingApprovals(clientId *uuid.UUID, authToken string, page, limit int, typeId *int) ([]*response.ArticleApprovalQueueResponse, paginator.Pagination, error) // Updated with typeId filter
// No-approval system methods
CheckApprovalRequired(clientId *uuid.UUID, articleId uint, userId uint, userLevelId uint) (bool, error)
@ -872,15 +872,21 @@ func (_i *articlesService) GetApprovalStatus(clientId *uuid.UUID, articleId uint
}
// GetPendingApprovals gets articles pending approval for a specific user level
func (_i *articlesService) GetPendingApprovals(clientId *uuid.UUID, authToken string, page, limit int) ([]*response.ArticleApprovalQueueResponse, paginator.Pagination, error) {
func (_i *articlesService) GetPendingApprovals(clientId *uuid.UUID, authToken string, page, limit int, typeId *int) ([]*response.ArticleApprovalQueueResponse, paginator.Pagination, error) {
// Extract user info from auth token
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if user == nil {
return nil, paginator.Pagination{}, errors.New("user not found from auth token")
}
// Prepare filters
filters := make(map[string]interface{})
if typeId != nil {
filters["type_id"] = *typeId
}
// Get pending approvals for the user level
approvalFlows, paging, err := _i.ArticleApprovalFlowsRepo.GetPendingApprovalsByUserLevel(clientId, user.UserLevelId, page, limit)
approvalFlows, paging, err := _i.ArticleApprovalFlowsRepo.GetPendingApprovals(clientId, user.UserLevelId, page, limit, filters)
if err != nil {
return nil, paging, err
}