All checks were successful
Build and Push App Image / build-and-push (push) Successful in 1m20s
487 lines
13 KiB
Go
487 lines
13 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"gitea.hostxtra.co.uk/mrhid6/notely/backend/internal/application/dto"
|
|
"gitea.hostxtra.co.uk/mrhid6/notely/backend/internal/application/services"
|
|
"github.com/gorilla/mux"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
// TaskHandler handles task and task status endpoints.
|
|
type TaskHandler struct {
|
|
taskService *services.TaskService
|
|
}
|
|
|
|
// NewTaskHandler creates a task handler.
|
|
func NewTaskHandler(taskService *services.TaskService) *TaskHandler {
|
|
return &TaskHandler{taskService: taskService}
|
|
}
|
|
|
|
func parseIDsFromRequest(r *http.Request) (bson.ObjectID, bson.ObjectID, error) {
|
|
userID, err := getUserObjectID(r)
|
|
if err != nil {
|
|
return bson.NilObjectID, bson.NilObjectID, err
|
|
}
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
return bson.NilObjectID, bson.NilObjectID, err
|
|
}
|
|
return userID, spaceID, nil
|
|
}
|
|
|
|
func (h *TaskHandler) CreateTask(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.CreateTaskRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
task, err := h.taskService.CreateTask(r.Context(), spaceID, userID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(task)
|
|
}
|
|
|
|
func (h *TaskHandler) ListTasks(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
taskListID := strings.TrimSpace(r.URL.Query().Get("taskListId"))
|
|
statusID := strings.TrimSpace(r.URL.Query().Get("statusId"))
|
|
parentTaskID := strings.TrimSpace(r.URL.Query().Get("parentTaskId"))
|
|
|
|
taskListFilter := &taskListID
|
|
statusFilter := &statusID
|
|
parentFilter := &parentTaskID
|
|
if taskListID == "" {
|
|
taskListFilter = nil
|
|
}
|
|
if statusID == "" {
|
|
statusFilter = nil
|
|
}
|
|
if parentTaskID == "" {
|
|
parentFilter = nil
|
|
}
|
|
|
|
tasks, err := h.taskService.ListTasks(r.Context(), spaceID, userID, taskListFilter, statusFilter, parentFilter)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(tasks)
|
|
}
|
|
|
|
func (h *TaskHandler) ListTaskLists(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
lists, err := h.taskService.ListTaskLists(r.Context(), spaceID, userID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(lists)
|
|
}
|
|
|
|
func (h *TaskHandler) CreateTaskList(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.CreateTaskListRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
list, err := h.taskService.CreateTaskList(r.Context(), spaceID, userID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(list)
|
|
}
|
|
|
|
func (h *TaskHandler) UpdateTaskList(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskListID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskListId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task list id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.UpdateTaskListRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
list, err := h.taskService.UpdateTaskList(r.Context(), spaceID, taskListID, userID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(list)
|
|
}
|
|
|
|
func (h *TaskHandler) DeleteTaskList(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskListID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskListId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task list id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.taskService.DeleteTaskList(r.Context(), spaceID, taskListID, userID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func (h *TaskHandler) SearchTasks(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
query := r.URL.Query().Get("q")
|
|
tasks, err := h.taskService.SearchTasks(r.Context(), spaceID, userID, query)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(tasks)
|
|
}
|
|
|
|
func (h *TaskHandler) GetTask(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
task, err := h.taskService.GetTaskByID(r.Context(), spaceID, taskID, userID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(task)
|
|
}
|
|
|
|
func (h *TaskHandler) UpdateTask(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.UpdateTaskRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
task, err := h.taskService.UpdateTask(r.Context(), spaceID, taskID, userID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(task)
|
|
}
|
|
|
|
func (h *TaskHandler) DeleteTask(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.taskService.DeleteTask(r.Context(), spaceID, taskID, userID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func (h *TaskHandler) TransitionTaskStatus(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.TaskTransitionRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
task, err := h.taskService.TransitionTaskStatus(r.Context(), spaceID, taskID, userID, req.Direction)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(task)
|
|
}
|
|
|
|
func (h *TaskHandler) LinkTaskNote(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.LinkTaskNoteRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
noteID, err := bson.ObjectIDFromHex(req.NoteID)
|
|
if err != nil {
|
|
http.Error(w, "invalid note id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
task, err := h.taskService.LinkNoteToTask(r.Context(), spaceID, taskID, noteID, userID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(task)
|
|
}
|
|
|
|
func (h *TaskHandler) UnlinkTaskNote(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
taskID, err := bson.ObjectIDFromHex(mux.Vars(r)["taskId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid task id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
noteID, err := bson.ObjectIDFromHex(mux.Vars(r)["noteId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid note id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
task, err := h.taskService.UnlinkNoteFromTask(r.Context(), spaceID, taskID, noteID, userID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(task)
|
|
}
|
|
|
|
func (h *TaskHandler) ListTasksByNote(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
noteID, err := bson.ObjectIDFromHex(mux.Vars(r)["noteId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid note id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
tasks, err := h.taskService.ListTasksLinkedToNote(r.Context(), spaceID, noteID, userID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(tasks)
|
|
}
|
|
|
|
func (h *TaskHandler) ListStatuses(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
statuses, err := h.taskService.ListStatuses(r.Context(), spaceID, userID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(statuses)
|
|
}
|
|
|
|
func (h *TaskHandler) CreateStatus(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.CreateTaskStatusRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
status, err := h.taskService.CreateStatus(r.Context(), spaceID, userID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(status)
|
|
}
|
|
|
|
func (h *TaskHandler) UpdateStatus(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
statusID, err := bson.ObjectIDFromHex(mux.Vars(r)["statusId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid status id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.UpdateTaskStatusRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
status, err := h.taskService.UpdateStatus(r.Context(), spaceID, statusID, userID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(status)
|
|
}
|
|
|
|
func (h *TaskHandler) DeleteStatus(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
statusID, err := bson.ObjectIDFromHex(mux.Vars(r)["statusId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid status id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.taskService.DeleteStatus(r.Context(), spaceID, statusID, userID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func (h *TaskHandler) ReorderStatuses(w http.ResponseWriter, r *http.Request) {
|
|
userID, spaceID, err := parseIDsFromRequest(r)
|
|
if err != nil {
|
|
http.Error(w, "invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.ReorderTaskStatusesRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
statuses, err := h.taskService.ReorderStatuses(r.Context(), spaceID, userID, req.OrderedStatusIDs)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(statuses)
|
|
}
|