feat: complete project workspace tags and notes UI
This commit is contained in:
@@ -29,9 +29,12 @@ func (h *Handler) Register(router gin.IRouter) {
|
||||
router.GET("/projects", h.listProjects)
|
||||
router.GET("/projects/:id/dashboard", h.dashboard)
|
||||
router.GET("/projects/:id/workspace", h.workspace)
|
||||
router.GET("/projects/:id/tags", h.listTags)
|
||||
router.POST("/projects/:id/tasks", h.createTask)
|
||||
router.PATCH("/projects/:id/tasks/:taskID", h.updateTask)
|
||||
router.POST("/projects/:id/sources", h.uploadSource)
|
||||
router.POST("/projects/:id/cron-plans", h.createCronPlan)
|
||||
router.POST("/projects/:id/tags", h.createTag)
|
||||
}
|
||||
|
||||
func (h *Handler) createProject(c *gin.Context) {
|
||||
@@ -42,13 +45,22 @@ func (h *Handler) createProject(c *gin.Context) {
|
||||
}
|
||||
var input struct {
|
||||
Name string `json:"name"`
|
||||
Identifier string `json:"identifier"`
|
||||
Icon string `json:"icon"`
|
||||
Background string `json:"background"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
||||
return
|
||||
}
|
||||
project, err := h.service.CreateProject(userID, input.Name, input.Description)
|
||||
project, err := h.service.CreateProjectWithInput(userID, CreateProjectInput{
|
||||
Name: input.Name,
|
||||
Identifier: input.Identifier,
|
||||
Icon: input.Icon,
|
||||
Background: input.Background,
|
||||
Description: input.Description,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
@@ -108,6 +120,24 @@ func (h *Handler) workspace(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, workspace)
|
||||
}
|
||||
|
||||
func (h *Handler) listTags(c *gin.Context) {
|
||||
userID, ok := auth.CurrentUserID(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing current user"})
|
||||
return
|
||||
}
|
||||
projectID, ok := parseProjectID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
tags, err := h.service.ListProjectTags(userID, projectID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, tags)
|
||||
}
|
||||
|
||||
func (h *Handler) createTask(c *gin.Context) {
|
||||
userID, ok := auth.CurrentUserID(c)
|
||||
if !ok {
|
||||
@@ -123,6 +153,7 @@ func (h *Handler) createTask(c *gin.Context) {
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
DueAt string `json:"dueAt"`
|
||||
Tag string `json:"tag"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
||||
@@ -138,6 +169,7 @@ func (h *Handler) createTask(c *gin.Context) {
|
||||
Description: input.Description,
|
||||
Status: input.Status,
|
||||
DueAt: dueAt,
|
||||
Tag: input.Tag,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
@@ -146,6 +178,47 @@ func (h *Handler) createTask(c *gin.Context) {
|
||||
c.JSON(http.StatusCreated, task)
|
||||
}
|
||||
|
||||
func (h *Handler) updateTask(c *gin.Context) {
|
||||
userID, ok := auth.CurrentUserID(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing current user"})
|
||||
return
|
||||
}
|
||||
projectID, ok := parseProjectID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
taskID, ok := parseTaskID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var input struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
Completed bool `json:"completed"`
|
||||
NextProjectID uint `json:"nextProjectId"`
|
||||
Tag string `json:"tag"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
||||
return
|
||||
}
|
||||
task, err := h.service.UpdateTask(userID, projectID, taskID, UpdateTaskInput{
|
||||
Title: input.Title,
|
||||
Description: input.Description,
|
||||
Status: input.Status,
|
||||
Completed: input.Completed,
|
||||
NextProjectID: input.NextProjectID,
|
||||
Tag: input.Tag,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, task)
|
||||
}
|
||||
|
||||
func (h *Handler) uploadSource(c *gin.Context) {
|
||||
userID, ok := auth.CurrentUserID(c)
|
||||
if !ok {
|
||||
@@ -233,6 +306,31 @@ func (h *Handler) createCronPlan(c *gin.Context) {
|
||||
c.JSON(http.StatusCreated, plan)
|
||||
}
|
||||
|
||||
func (h *Handler) createTag(c *gin.Context) {
|
||||
userID, ok := auth.CurrentUserID(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing current user"})
|
||||
return
|
||||
}
|
||||
projectID, ok := parseProjectID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var input struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
||||
return
|
||||
}
|
||||
tag, err := h.service.CreateProjectTag(userID, projectID, input.Name)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, tag)
|
||||
}
|
||||
|
||||
func parseProjectID(c *gin.Context) (uint, bool) {
|
||||
projectID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
@@ -242,6 +340,15 @@ func parseProjectID(c *gin.Context) (uint, bool) {
|
||||
return uint(projectID), true
|
||||
}
|
||||
|
||||
func parseTaskID(c *gin.Context) (uint, bool) {
|
||||
taskID, err := strconv.ParseUint(c.Param("taskID"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid task id"})
|
||||
return 0, false
|
||||
}
|
||||
return uint(taskID), true
|
||||
}
|
||||
|
||||
func parseOptionalTime(value string) (*time.Time, error) {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if trimmed == "" {
|
||||
|
||||
Reference in New Issue
Block a user