mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-24 16:09:19 +02:00
Compare commits
1 Commits
agent/lamb
...
agent/j/d3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0b5391737 |
@@ -1,4 +1,4 @@
|
||||
import type { ProjectStatus } from "../types";
|
||||
import type { ProjectStatus, ProjectPriority } from "../types";
|
||||
|
||||
export const PROJECT_STATUS_ORDER: ProjectStatus[] = [
|
||||
"planned",
|
||||
@@ -18,3 +18,22 @@ export const PROJECT_STATUS_CONFIG: Record<
|
||||
completed: { label: "Completed", color: "text-info", badgeBg: "bg-info", badgeText: "text-white" },
|
||||
cancelled: { label: "Cancelled", color: "text-muted-foreground", badgeBg: "bg-muted", badgeText: "text-muted-foreground" },
|
||||
};
|
||||
|
||||
export const PROJECT_PRIORITY_ORDER: ProjectPriority[] = [
|
||||
"urgent",
|
||||
"high",
|
||||
"medium",
|
||||
"low",
|
||||
"none",
|
||||
];
|
||||
|
||||
export const PROJECT_PRIORITY_CONFIG: Record<
|
||||
ProjectPriority,
|
||||
{ label: string; bars: number; color: string; badgeBg: string; badgeText: string }
|
||||
> = {
|
||||
urgent: { label: "Urgent", bars: 4, color: "text-destructive", badgeBg: "bg-priority", badgeText: "text-white" },
|
||||
high: { label: "High", bars: 3, color: "text-warning", badgeBg: "bg-priority/80", badgeText: "text-white" },
|
||||
medium: { label: "Medium", bars: 2, color: "text-warning", badgeBg: "bg-priority/15", badgeText: "text-priority" },
|
||||
low: { label: "Low", bars: 1, color: "text-info", badgeBg: "bg-priority/10", badgeText: "text-priority" },
|
||||
none: { label: "No priority", bars: 0, color: "text-muted-foreground", badgeBg: "bg-muted", badgeText: "text-muted-foreground" },
|
||||
};
|
||||
|
||||
@@ -30,4 +30,4 @@ export type * from "./events";
|
||||
export type * from "./api";
|
||||
export type { Attachment } from "./attachment";
|
||||
export type { StorageAdapter } from "./storage";
|
||||
export type { Project, ProjectStatus, CreateProjectRequest, UpdateProjectRequest, ListProjectsResponse } from "./project";
|
||||
export type { Project, ProjectStatus, ProjectPriority, CreateProjectRequest, UpdateProjectRequest, ListProjectsResponse } from "./project";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export type ProjectStatus = "planned" | "in_progress" | "paused" | "completed" | "cancelled";
|
||||
|
||||
export type ProjectPriority = "urgent" | "high" | "medium" | "low" | "none";
|
||||
|
||||
export interface Project {
|
||||
id: string;
|
||||
workspace_id: string;
|
||||
@@ -7,6 +9,7 @@ export interface Project {
|
||||
description: string | null;
|
||||
icon: string | null;
|
||||
status: ProjectStatus;
|
||||
priority: ProjectPriority;
|
||||
lead_type: "member" | "agent" | null;
|
||||
lead_id: string | null;
|
||||
created_at: string;
|
||||
@@ -18,6 +21,7 @@ export interface CreateProjectRequest {
|
||||
description?: string;
|
||||
icon?: string;
|
||||
status?: ProjectStatus;
|
||||
priority?: ProjectPriority;
|
||||
lead_type?: "member" | "agent";
|
||||
lead_id?: string;
|
||||
}
|
||||
@@ -27,6 +31,7 @@ export interface UpdateProjectRequest {
|
||||
description?: string | null;
|
||||
icon?: string | null;
|
||||
status?: ProjectStatus;
|
||||
priority?: ProjectPriority;
|
||||
lead_type?: "member" | "agent" | null;
|
||||
lead_id?: string | null;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Check, ChevronRight, Link2, ListTodo, MoreHorizontal, Trash2, UserMinus
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { cn } from "@multica/ui/lib/utils";
|
||||
import { toast } from "sonner";
|
||||
import type { Issue, IssueStatus, ProjectStatus } from "@multica/core/types";
|
||||
import type { Issue, IssueStatus, ProjectStatus, ProjectPriority } from "@multica/core/types";
|
||||
import { projectDetailOptions } from "@multica/core/projects/queries";
|
||||
import { useUpdateProject, useDeleteProject } from "@multica/core/projects/mutations";
|
||||
import { issueListOptions } from "@multica/core/issues/queries";
|
||||
@@ -14,7 +14,7 @@ import { memberListOptions, agentListOptions } from "@multica/core/workspace/que
|
||||
import { useWorkspaceId } from "@multica/core/hooks";
|
||||
import { useWorkspaceStore } from "@multica/core/workspace";
|
||||
import { useActorName } from "@multica/core/workspace/hooks";
|
||||
import { PROJECT_STATUS_ORDER, PROJECT_STATUS_CONFIG } from "@multica/core/projects/config";
|
||||
import { PROJECT_STATUS_ORDER, PROJECT_STATUS_CONFIG, PROJECT_PRIORITY_ORDER, PROJECT_PRIORITY_CONFIG } from "@multica/core/projects/config";
|
||||
import { BOARD_STATUSES } from "@multica/core/issues/config";
|
||||
import { createIssueViewStore, useIssueViewStore as useGlobalIssueViewStore } from "@multica/core/issues/stores/view-store";
|
||||
import { ViewStoreProvider, useViewStore } from "@multica/core/issues/stores/view-store-context";
|
||||
@@ -23,6 +23,7 @@ import { filterIssues } from "../../issues/utils/filter";
|
||||
import { ActorAvatar } from "../../common/actor-avatar";
|
||||
import { AppLink, useNavigation } from "../../navigation";
|
||||
import { TitleEditor, ContentEditor, type ContentEditorRef } from "../../editor";
|
||||
import { PriorityIcon } from "../../issues/components/priority-icon";
|
||||
import { IssuesHeader } from "../../issues/components/issues-header";
|
||||
import { BoardView } from "../../issues/components/board-view";
|
||||
import { ListView } from "../../issues/components/list-view";
|
||||
@@ -218,6 +219,7 @@ export function ProjectDetail({ projectId }: { projectId: string }) {
|
||||
}
|
||||
|
||||
const statusCfg = PROJECT_STATUS_CONFIG[project.status];
|
||||
const priorityCfg = PROJECT_PRIORITY_CONFIG[project.priority];
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
@@ -363,6 +365,27 @@ export function ProjectDetail({ projectId }: { projectId: string }) {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{/* Priority */}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
render={
|
||||
<PropertyPill>
|
||||
<PriorityIcon priority={project.priority} />
|
||||
<span>{priorityCfg.label}</span>
|
||||
</PropertyPill>
|
||||
}
|
||||
/>
|
||||
<DropdownMenuContent align="start" className="w-44">
|
||||
{PROJECT_PRIORITY_ORDER.map((p) => (
|
||||
<DropdownMenuItem key={p} onClick={() => handleUpdateField({ priority: p as ProjectPriority })}>
|
||||
<PriorityIcon priority={p} />
|
||||
<span>{PROJECT_PRIORITY_CONFIG[p].label}</span>
|
||||
{p === project.priority && <Check className="ml-auto h-3.5 w-3.5" />}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{/* Lead */}
|
||||
<Popover open={leadOpen} onOpenChange={(v) => { setLeadOpen(v); if (!v) setLeadFilter(""); }}>
|
||||
<PopoverTrigger
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Plus, FolderKanban, ChevronRight, Maximize2, Minimize2, X as XIcon, Use
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { projectListOptions } from "@multica/core/projects/queries";
|
||||
import { useCreateProject } from "@multica/core/projects/mutations";
|
||||
import { PROJECT_STATUS_CONFIG, PROJECT_STATUS_ORDER } from "@multica/core/projects/config";
|
||||
import { PROJECT_STATUS_CONFIG, PROJECT_STATUS_ORDER, PROJECT_PRIORITY_CONFIG, PROJECT_PRIORITY_ORDER } from "@multica/core/projects/config";
|
||||
import { useWorkspaceId } from "@multica/core/hooks";
|
||||
import { useWorkspaceStore } from "@multica/core/workspace";
|
||||
import { memberListOptions, agentListOptions } from "@multica/core/workspace/queries";
|
||||
@@ -36,7 +36,8 @@ import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/
|
||||
import { ContentEditor, type ContentEditorRef } from "../../editor";
|
||||
import { TitleEditor } from "../../editor";
|
||||
import { EmojiPicker } from "@multica/ui/components/common/emoji-picker";
|
||||
import type { Project, ProjectStatus } from "@multica/core/types";
|
||||
import type { Project, ProjectStatus, ProjectPriority } from "@multica/core/types";
|
||||
import { PriorityIcon } from "../../issues/components/priority-icon";
|
||||
|
||||
function formatRelativeDate(date: string): string {
|
||||
const diff = Date.now() - new Date(date).getTime();
|
||||
@@ -50,6 +51,7 @@ function formatRelativeDate(date: string): string {
|
||||
|
||||
function ProjectRow({ project }: { project: Project }) {
|
||||
const statusCfg = PROJECT_STATUS_CONFIG[project.status];
|
||||
const priorityCfg = PROJECT_PRIORITY_CONFIG[project.priority];
|
||||
return (
|
||||
<AppLink
|
||||
href={`/projects/${project.id}`}
|
||||
@@ -59,6 +61,12 @@ function ProjectRow({ project }: { project: Project }) {
|
||||
<span className="shrink-0 w-[24px] text-center text-base">{project.icon || "📁"}</span>
|
||||
<span className="min-w-0 flex-1 truncate font-medium">{project.title}</span>
|
||||
|
||||
{/* Priority */}
|
||||
<span className="flex w-24 items-center justify-center gap-1 shrink-0">
|
||||
<PriorityIcon priority={project.priority} />
|
||||
<span className={cn("text-xs", priorityCfg.color)}>{priorityCfg.label}</span>
|
||||
</span>
|
||||
|
||||
{/* Status */}
|
||||
<span className={cn(
|
||||
"inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium shrink-0 w-28 justify-center",
|
||||
@@ -115,6 +123,7 @@ function CreateProjectDialog({ open, onOpenChange }: { open: boolean; onOpenChan
|
||||
const [title, setTitle] = useState("");
|
||||
const descEditorRef = useRef<ContentEditorRef>(null);
|
||||
const [status, setStatus] = useState<ProjectStatus>("planned");
|
||||
const [priority, setPriority] = useState<ProjectPriority>("none");
|
||||
const [leadType, setLeadType] = useState<"member" | "agent" | undefined>();
|
||||
const [leadId, setLeadId] = useState<string | undefined>();
|
||||
const [icon, setIcon] = useState<string | undefined>();
|
||||
@@ -144,6 +153,7 @@ function CreateProjectDialog({ open, onOpenChange }: { open: boolean; onOpenChan
|
||||
description: descEditorRef.current?.getMarkdown()?.trim() || undefined,
|
||||
icon,
|
||||
status,
|
||||
priority,
|
||||
lead_type: leadType,
|
||||
lead_id: leadId,
|
||||
});
|
||||
@@ -151,6 +161,7 @@ function CreateProjectDialog({ open, onOpenChange }: { open: boolean; onOpenChan
|
||||
setTitle("");
|
||||
setIcon(undefined);
|
||||
setStatus("planned");
|
||||
setPriority("none");
|
||||
setLeadType(undefined);
|
||||
setLeadId(undefined);
|
||||
toast.success("Project created");
|
||||
@@ -279,6 +290,26 @@ function CreateProjectDialog({ open, onOpenChange }: { open: boolean; onOpenChan
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{/* Priority */}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
render={
|
||||
<PillButton>
|
||||
<PriorityIcon priority={priority} />
|
||||
<span>{PROJECT_PRIORITY_CONFIG[priority].label}</span>
|
||||
</PillButton>
|
||||
}
|
||||
/>
|
||||
<DropdownMenuContent align="start" className="w-44">
|
||||
{PROJECT_PRIORITY_ORDER.map((p) => (
|
||||
<DropdownMenuItem key={p} onClick={() => setPriority(p)}>
|
||||
<PriorityIcon priority={p} />
|
||||
<span>{PROJECT_PRIORITY_CONFIG[p].label}</span>
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{/* Lead */}
|
||||
<Popover open={leadOpen} onOpenChange={(v) => { setLeadOpen(v); if (!v) setLeadFilter(""); }}>
|
||||
<PopoverTrigger
|
||||
@@ -410,6 +441,7 @@ export function ProjectsPage() {
|
||||
{/* Icon spacer + Name */}
|
||||
<span className="shrink-0 w-[24px]" />
|
||||
<span className="min-w-0 flex-1">Name</span>
|
||||
<span className="w-24 text-center shrink-0">Priority</span>
|
||||
<span className="w-28 text-center shrink-0">Status</span>
|
||||
<span className="w-10 text-center shrink-0">Lead</span>
|
||||
<span className="w-20 text-right shrink-0">Created</span>
|
||||
|
||||
@@ -18,6 +18,7 @@ type ProjectResponse struct {
|
||||
Description *string `json:"description"`
|
||||
Icon *string `json:"icon"`
|
||||
Status string `json:"status"`
|
||||
Priority string `json:"priority"`
|
||||
LeadType *string `json:"lead_type"`
|
||||
LeadID *string `json:"lead_id"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
@@ -32,6 +33,7 @@ func projectToResponse(p db.Project) ProjectResponse {
|
||||
Description: textToPtr(p.Description),
|
||||
Icon: textToPtr(p.Icon),
|
||||
Status: p.Status,
|
||||
Priority: p.Priority,
|
||||
LeadType: textToPtr(p.LeadType),
|
||||
LeadID: uuidToPtr(p.LeadID),
|
||||
CreatedAt: timestampToString(p.CreatedAt),
|
||||
@@ -44,6 +46,7 @@ type CreateProjectRequest struct {
|
||||
Description *string `json:"description"`
|
||||
Icon *string `json:"icon"`
|
||||
Status string `json:"status"`
|
||||
Priority string `json:"priority"`
|
||||
LeadType *string `json:"lead_type"`
|
||||
LeadID *string `json:"lead_id"`
|
||||
}
|
||||
@@ -53,6 +56,7 @@ type UpdateProjectRequest struct {
|
||||
Description *string `json:"description"`
|
||||
Icon *string `json:"icon"`
|
||||
Status *string `json:"status"`
|
||||
Priority *string `json:"priority"`
|
||||
LeadType *string `json:"lead_type"`
|
||||
LeadID *string `json:"lead_id"`
|
||||
}
|
||||
@@ -63,9 +67,14 @@ func (h *Handler) ListProjects(w http.ResponseWriter, r *http.Request) {
|
||||
if s := r.URL.Query().Get("status"); s != "" {
|
||||
statusFilter = pgtype.Text{String: s, Valid: true}
|
||||
}
|
||||
var priorityFilter pgtype.Text
|
||||
if p := r.URL.Query().Get("priority"); p != "" {
|
||||
priorityFilter = pgtype.Text{String: p, Valid: true}
|
||||
}
|
||||
projects, err := h.Queries.ListProjects(r.Context(), db.ListProjectsParams{
|
||||
WorkspaceID: parseUUID(workspaceID),
|
||||
Status: statusFilter,
|
||||
Priority: priorityFilter,
|
||||
})
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "failed to list projects")
|
||||
@@ -110,6 +119,10 @@ func (h *Handler) CreateProject(w http.ResponseWriter, r *http.Request) {
|
||||
if status == "" {
|
||||
status = "planned"
|
||||
}
|
||||
priority := req.Priority
|
||||
if priority == "" {
|
||||
priority = "none"
|
||||
}
|
||||
var leadType pgtype.Text
|
||||
var leadID pgtype.UUID
|
||||
if req.LeadType != nil {
|
||||
@@ -126,6 +139,7 @@ func (h *Handler) CreateProject(w http.ResponseWriter, r *http.Request) {
|
||||
Status: status,
|
||||
LeadType: leadType,
|
||||
LeadID: leadID,
|
||||
Priority: priority,
|
||||
})
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "failed to create project")
|
||||
@@ -176,6 +190,9 @@ func (h *Handler) UpdateProject(w http.ResponseWriter, r *http.Request) {
|
||||
if req.Status != nil {
|
||||
params.Status = pgtype.Text{String: *req.Status, Valid: true}
|
||||
}
|
||||
if req.Priority != nil {
|
||||
params.Priority = pgtype.Text{String: *req.Priority, Valid: true}
|
||||
}
|
||||
if _, ok := rawFields["description"]; ok {
|
||||
if req.Description != nil {
|
||||
params.Description = pgtype.Text{String: *req.Description, Valid: true}
|
||||
|
||||
1
server/migrations/035_project_priority.down.sql
Normal file
1
server/migrations/035_project_priority.down.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE project DROP COLUMN priority;
|
||||
2
server/migrations/035_project_priority.up.sql
Normal file
2
server/migrations/035_project_priority.up.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE project ADD COLUMN priority TEXT NOT NULL DEFAULT 'none'
|
||||
CHECK (priority IN ('urgent', 'high', 'medium', 'low', 'none'));
|
||||
@@ -245,6 +245,7 @@ type Project struct {
|
||||
LeadID pgtype.UUID `json:"lead_id"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Priority string `json:"priority"`
|
||||
}
|
||||
|
||||
type RuntimeUsage struct {
|
||||
|
||||
@@ -26,10 +26,10 @@ func (q *Queries) CountIssuesByProject(ctx context.Context, projectID pgtype.UUI
|
||||
const createProject = `-- name: CreateProject :one
|
||||
INSERT INTO project (
|
||||
workspace_id, title, description, icon, status,
|
||||
lead_type, lead_id
|
||||
lead_type, lead_id, priority
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
) RETURNING id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at
|
||||
$1, $2, $3, $4, $5, $6, $7, $8
|
||||
) RETURNING id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at, priority
|
||||
`
|
||||
|
||||
type CreateProjectParams struct {
|
||||
@@ -40,6 +40,7 @@ type CreateProjectParams struct {
|
||||
Status string `json:"status"`
|
||||
LeadType pgtype.Text `json:"lead_type"`
|
||||
LeadID pgtype.UUID `json:"lead_id"`
|
||||
Priority string `json:"priority"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) {
|
||||
@@ -51,6 +52,7 @@ func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (P
|
||||
arg.Status,
|
||||
arg.LeadType,
|
||||
arg.LeadID,
|
||||
arg.Priority,
|
||||
)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
@@ -64,6 +66,7 @@ func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (P
|
||||
&i.LeadID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -78,7 +81,7 @@ func (q *Queries) DeleteProject(ctx context.Context, id pgtype.UUID) error {
|
||||
}
|
||||
|
||||
const getProject = `-- name: GetProject :one
|
||||
SELECT id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at FROM project
|
||||
SELECT id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at, priority FROM project
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
@@ -96,12 +99,13 @@ func (q *Queries) GetProject(ctx context.Context, id pgtype.UUID) (Project, erro
|
||||
&i.LeadID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getProjectInWorkspace = `-- name: GetProjectInWorkspace :one
|
||||
SELECT id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at FROM project
|
||||
SELECT id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at, priority FROM project
|
||||
WHERE id = $1 AND workspace_id = $2
|
||||
`
|
||||
|
||||
@@ -124,24 +128,27 @@ func (q *Queries) GetProjectInWorkspace(ctx context.Context, arg GetProjectInWor
|
||||
&i.LeadID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listProjects = `-- name: ListProjects :many
|
||||
SELECT id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at FROM project
|
||||
SELECT id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at, priority FROM project
|
||||
WHERE workspace_id = $1
|
||||
AND ($2::text IS NULL OR status = $2)
|
||||
AND ($3::text IS NULL OR priority = $3)
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
type ListProjectsParams struct {
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
Status pgtype.Text `json:"status"`
|
||||
Priority pgtype.Text `json:"priority"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListProjects(ctx context.Context, arg ListProjectsParams) ([]Project, error) {
|
||||
rows, err := q.db.Query(ctx, listProjects, arg.WorkspaceID, arg.Status)
|
||||
rows, err := q.db.Query(ctx, listProjects, arg.WorkspaceID, arg.Status, arg.Priority)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -160,6 +167,7 @@ func (q *Queries) ListProjects(ctx context.Context, arg ListProjectsParams) ([]P
|
||||
&i.LeadID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -177,11 +185,12 @@ UPDATE project SET
|
||||
description = $3,
|
||||
icon = $4,
|
||||
status = COALESCE($5, status),
|
||||
lead_type = $6,
|
||||
lead_id = $7,
|
||||
priority = COALESCE($6, priority),
|
||||
lead_type = $7,
|
||||
lead_id = $8,
|
||||
updated_at = now()
|
||||
WHERE id = $1
|
||||
RETURNING id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at
|
||||
RETURNING id, workspace_id, title, description, icon, status, lead_type, lead_id, created_at, updated_at, priority
|
||||
`
|
||||
|
||||
type UpdateProjectParams struct {
|
||||
@@ -190,6 +199,7 @@ type UpdateProjectParams struct {
|
||||
Description pgtype.Text `json:"description"`
|
||||
Icon pgtype.Text `json:"icon"`
|
||||
Status pgtype.Text `json:"status"`
|
||||
Priority pgtype.Text `json:"priority"`
|
||||
LeadType pgtype.Text `json:"lead_type"`
|
||||
LeadID pgtype.UUID `json:"lead_id"`
|
||||
}
|
||||
@@ -201,6 +211,7 @@ func (q *Queries) UpdateProject(ctx context.Context, arg UpdateProjectParams) (P
|
||||
arg.Description,
|
||||
arg.Icon,
|
||||
arg.Status,
|
||||
arg.Priority,
|
||||
arg.LeadType,
|
||||
arg.LeadID,
|
||||
)
|
||||
@@ -216,6 +227,7 @@ func (q *Queries) UpdateProject(ctx context.Context, arg UpdateProjectParams) (P
|
||||
&i.LeadID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
SELECT * FROM project
|
||||
WHERE workspace_id = $1
|
||||
AND (sqlc.narg('status')::text IS NULL OR status = sqlc.narg('status'))
|
||||
AND (sqlc.narg('priority')::text IS NULL OR priority = sqlc.narg('priority'))
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: GetProject :one
|
||||
@@ -15,9 +16,9 @@ WHERE id = $1 AND workspace_id = $2;
|
||||
-- name: CreateProject :one
|
||||
INSERT INTO project (
|
||||
workspace_id, title, description, icon, status,
|
||||
lead_type, lead_id
|
||||
lead_type, lead_id, priority
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
$1, $2, $3, $4, $5, $6, $7, $8
|
||||
) RETURNING *;
|
||||
|
||||
-- name: UpdateProject :one
|
||||
@@ -26,6 +27,7 @@ UPDATE project SET
|
||||
description = sqlc.narg('description'),
|
||||
icon = sqlc.narg('icon'),
|
||||
status = COALESCE(sqlc.narg('status'), status),
|
||||
priority = COALESCE(sqlc.narg('priority'), priority),
|
||||
lead_type = sqlc.narg('lead_type'),
|
||||
lead_id = sqlc.narg('lead_id'),
|
||||
updated_at = now()
|
||||
|
||||
Reference in New Issue
Block a user