@burdenoff/microfe-planmagnet 2026.925.7 → 2026.925.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/planmagnet/board/ProjectBoard.d.ts.map +1 -1
- package/dist/planmagnet/board/ProjectBoard.js +159 -158
- package/dist/planmagnet/board/ProjectBoard.js.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.js +118 -117
- package/dist/planmagnet/create/CreateDialogs.js.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +322 -280
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +147 -126
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.js +202 -201
- package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
- package/dist/planmagnet/utils/mutationResult.d.ts +16 -0
- package/dist/planmagnet/utils/mutationResult.d.ts.map +1 -0
- package/dist/planmagnet/utils/mutationResult.js +10 -0
- package/dist/planmagnet/utils/mutationResult.js.map +1 -0
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectBoard.js","names":[],"sources":["../../../src/planmagnet/board/ProjectBoard.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n Card,\n CardContent,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { ChevronLeft, ChevronRight, LayoutGrid, Pencil, Plus } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { PersonName } from '../people/People';\n\n/**\n * A project's board (P1.2). The server owns placement: each column's `cards`\n * follow the rule in wspace-planmagnet-svc board.service.ts `columnCardsWhere`\n * (placed column, else the first column mapped to the item's status), and\n * `unplacedCount` says how many items are on no column. Moving a card into a\n * column mapped to a status changes that status on the server, and a column's\n * WIP limit is enforced there too. This component only draws and asks.\n */\n\nconst STATUSES = [\n 'BACKLOG',\n 'TODO',\n 'IN_PROGRESS',\n 'IN_REVIEW',\n 'TESTING',\n 'DONE',\n 'CANCELLED',\n] as const;\nconst statusLabel = (status: string) =>\n status.charAt(0) + status.slice(1).toLowerCase().replace(/_/g, ' ');\n\nconst CARDS_PER_COLUMN = 100;\n\nconst BOARDS = gql`\n query ProjectBoards($workspaceId: ID!, $projectId: String) {\n planmagnetBoards(\n workspaceId: $workspaceId\n filter: { projectId: $projectId }\n pagination: { first: 20 }\n ) {\n items {\n id\n name\n isDefault\n }\n }\n }\n`;\n\nconst BOARD = gql`\n query ProjectBoard($id: ID!) {\n planmagnetBoard(id: $id) {\n id\n name\n unplacedCount\n columns {\n id\n name\n mappedStatus\n wipLimit\n sortOrder\n cards(pagination: { first: 100 }) {\n totalCount\n items {\n id\n key\n title\n status\n priority\n storyPoints\n assigneeId\n }\n }\n }\n }\n }\n`;\n\nconst MOVE_CARD = gql`\n mutation ProjectBoardMoveCard($boardId: ID!, $input: PlanmagnetMoveCardInput!) {\n planmagnetMoveCard(boardId: $boardId, input: $input) {\n id\n }\n }\n`;\nconst CREATE_BOARD = gql`\n mutation ProjectBoardCreate($input: PlanmagnetCreateBoardInput!) {\n planmagnetCreateBoard(input: $input) {\n id\n }\n }\n`;\nconst CREATE_COLUMN = gql`\n mutation ProjectBoardCreateColumn($input: PlanmagnetCreateBoardColumnInput!) {\n planmagnetCreateBoardColumn(input: $input) {\n id\n }\n }\n`;\nconst UPDATE_COLUMN = gql`\n mutation ProjectBoardUpdateColumn($id: ID!, $input: PlanmagnetUpdateBoardColumnInput!) {\n planmagnetUpdateBoardColumn(id: $id, input: $input) {\n id\n }\n }\n`;\nconst DELETE_COLUMN = gql`\n mutation ProjectBoardDeleteColumn($id: ID!) {\n planmagnetDeleteBoardColumn(id: $id)\n }\n`;\nconst REORDER_COLUMNS = gql`\n mutation ProjectBoardReorder($boardId: ID!, $input: PlanmagnetReorderColumnsInput!) {\n planmagnetReorderColumns(boardId: $boardId, input: $input) {\n id\n }\n }\n`;\n\n/** Every query whose numbers a board change can move. */\nconst REFETCH = [\n 'ProjectBoard',\n 'ProjectBoards',\n 'GetWorkItems',\n 'GetWorkItemCounts',\n 'GetDashboardData',\n];\n\ninterface BoardCard {\n id: string;\n key: string;\n title: string;\n status: string;\n priority: string;\n storyPoints: number | null;\n assigneeId: string | null;\n}\n\ninterface BoardColumn {\n id: string;\n name: string;\n mappedStatus: string | null;\n wipLimit: number | null;\n sortOrder: number;\n cards: { totalCount: number; items: BoardCard[] };\n}\n\ninterface BoardData {\n id: string;\n name: string;\n unplacedCount: number;\n columns: BoardColumn[];\n}\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback);\n\nfunction ErrorLine({ message }: { message: string }) {\n return (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n );\n}\n\nexport function ProjectBoard({\n projectId,\n projectName,\n}: {\n projectId: string;\n projectName: string;\n}) {\n const { workspaceId } = usePlanMagnet();\n const [chosenBoardId, setChosenBoardId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const { data: boardsData, loading: boardsLoading } = useQuery<{\n planmagnetBoards: { items: Array<{ id: string; name: string; isDefault: boolean }> };\n }>(BOARDS, { variables: { workspaceId, projectId }, skip: !workspaceId });\n const boards = boardsData?.planmagnetBoards.items ?? [];\n const boardId =\n (chosenBoardId && boards.some((b) => b.id === chosenBoardId) ? chosenBoardId : null) ??\n boards.find((b) => b.isDefault)?.id ??\n boards[0]?.id ??\n null;\n\n const { data, loading } = useQuery<{ planmagnetBoard: BoardData | null }>(BOARD, {\n variables: { id: boardId },\n skip: !boardId,\n });\n const board = data?.planmagnetBoard ?? null;\n\n const [createBoard, createBoardState] = useMutation<{ planmagnetCreateBoard: { id: string } }>(\n CREATE_BOARD,\n { refetchQueries: REFETCH, awaitRefetchQueries: true }\n );\n const [moveCard, moveState] = useMutation(MOVE_CARD, {\n refetchQueries: REFETCH,\n awaitRefetchQueries: true,\n });\n const [reorder] = useMutation(REORDER_COLUMNS, {\n refetchQueries: REFETCH,\n awaitRefetchQueries: true,\n });\n\n const run = async (action: () => Promise<unknown>, fallback: string) => {\n setError(null);\n try {\n await action();\n } catch (e) {\n setError(messageOf(e, fallback));\n }\n };\n\n const move = (workItemId: string, targetColumnId: string) =>\n run(\n () => moveCard({ variables: { boardId, input: { workItemId, targetColumnId } } }),\n 'The card could not be moved.'\n );\n\n const shiftColumn = (index: number, delta: -1 | 1) => {\n if (!board) return;\n const order = board.columns.map((c) => c.id);\n const target = index + delta;\n if (target < 0 || target >= order.length) return;\n [order[index], order[target]] = [order[target], order[index]];\n return run(\n () => reorder({ variables: { boardId, input: { columnIds: order } } }),\n 'The columns could not be reordered.'\n );\n };\n\n if (boardsLoading && !boardsData) {\n return <p className=\"text-sm text-muted-foreground p-4\">Loading board…</p>;\n }\n\n if (!boardId) {\n return (\n <Card>\n <CardContent className=\"p-8 text-center space-y-3\" data-testid=\"board-empty\">\n <LayoutGrid className=\"h-8 w-8 mx-auto text-muted-foreground\" />\n <p className=\"text-sm text-muted-foreground\">{projectName} has no board yet.</p>\n <Button\n size=\"sm\"\n disabled={createBoardState.loading}\n onClick={() =>\n run(\n () =>\n createBoard({\n variables: {\n input: {\n projectId,\n name: `${projectName} board`,\n type: 'KANBAN',\n isDefault: true,\n withDefaultColumns: true,\n },\n },\n }),\n 'The board could not be created.'\n )\n }\n >\n <Plus className=\"mr-1 h-4 w-4\" />\n {createBoardState.loading ? 'Creating…' : 'Create board'}\n </Button>\n <p className=\"text-xs text-muted-foreground\">\n Starts with one column per status: Backlog, To Do, In Progress, In Review, Testing,\n Done.\n </p>\n {error && <ErrorLine message={error} />}\n </CardContent>\n </Card>\n );\n }\n\n return (\n <div className=\"space-y-3\" data-testid=\"project-board\">\n <div className=\"flex flex-wrap items-center gap-3\">\n {boards.length > 1 && (\n <select\n aria-label=\"Board\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm\"\n value={boardId}\n onChange={(e) => setChosenBoardId(e.target.value)}\n >\n {boards.map((b) => (\n <option key={b.id} value={b.id}>\n {b.name}\n </option>\n ))}\n </select>\n )}\n {board && board.unplacedCount > 0 && (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"board-unplaced\">\n {board.unplacedCount} work item{board.unplacedCount === 1 ? ' is' : 's are'} not on this\n board: {board.unplacedCount === 1 ? 'its status has' : 'their status has'} no column.\n </p>\n )}\n {board && (\n <div className=\"ml-auto\">\n <ColumnDialog boardId={board.id} />\n </div>\n )}\n </div>\n {error && <ErrorLine message={error} />}\n {loading && !board ? (\n <p className=\"text-sm text-muted-foreground p-4\">Loading board…</p>\n ) : (\n <div className=\"flex gap-3 overflow-x-auto pb-2\">\n {board?.columns.map((column, index) => (\n <BoardColumnView\n key={column.id}\n boardId={board.id}\n column={column}\n columns={board.columns}\n isFirst={index === 0}\n isLast={index === board.columns.length - 1}\n busy={moveState.loading}\n onMove={move}\n onShift={(delta) => shiftColumn(index, delta)}\n />\n ))}\n {board && board.columns.length === 0 && (\n <p className=\"text-sm text-muted-foreground p-4\">\n This board has no columns. Add one to start placing work.\n </p>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction BoardColumnView({\n boardId,\n column,\n columns,\n isFirst,\n isLast,\n busy,\n onMove,\n onShift,\n}: {\n boardId: string;\n column: BoardColumn;\n columns: BoardColumn[];\n isFirst: boolean;\n isLast: boolean;\n busy: boolean;\n onMove: (workItemId: string, targetColumnId: string) => void;\n onShift: (delta: -1 | 1) => void;\n}) {\n const navigate = usePlanMagnetNavigate();\n const [dragOver, setDragOver] = useState(false);\n const count = column.cards.totalCount;\n const atLimit = column.wipLimit != null && column.wipLimit > 0 && count >= column.wipLimit;\n const hidden = count - column.cards.items.length;\n\n return (\n <section\n aria-label={`${column.name} column`}\n data-testid={`board-column-${column.name}`}\n className={`min-w-[240px] w-[240px] shrink-0 rounded-md border bg-muted/30 ${dragOver ? 'ring-2 ring-primary' : ''}`}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={(e) => {\n e.preventDefault();\n setDragOver(false);\n const workItemId = e.dataTransfer.getData('text/plain');\n if (workItemId) onMove(workItemId, column.id);\n }}\n >\n <header className=\"p-2 border-b space-y-1\">\n <div className=\"flex items-center justify-between gap-1\">\n <h3 className=\"text-sm font-medium truncate\">{column.name}</h3>\n <span\n data-testid={`board-column-count-${column.name}`}\n className={`text-xs rounded-full px-1.5 ${atLimit ? 'bg-status-warning-subtle text-status-warning' : 'bg-muted'}`}\n title={column.wipLimit ? `WIP limit ${column.wipLimit}` : undefined}\n >\n {column.wipLimit ? `${count} / ${column.wipLimit}` : count}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-1\">\n <span className=\"text-[11px] text-muted-foreground\">\n {column.mappedStatus ? `Sets status: ${statusLabel(column.mappedStatus)}` : 'No status'}\n </span>\n <span className=\"flex\">\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-6 w-6\"\n aria-label={`Move ${column.name} column left`}\n disabled={isFirst}\n onClick={() => onShift(-1)}\n >\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-6 w-6\"\n aria-label={`Move ${column.name} column right`}\n disabled={isLast}\n onClick={() => onShift(1)}\n >\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </Button>\n <ColumnDialog boardId={boardId} column={column} />\n </span>\n </div>\n </header>\n <ul className=\"p-2 space-y-2 min-h-[80px]\">\n {column.cards.items.map((card) => (\n <li\n key={card.id}\n draggable\n onDragStart={(e) => {\n e.dataTransfer.setData('text/plain', card.id);\n e.dataTransfer.effectAllowed = 'move';\n }}\n className=\"rounded-md border bg-background p-2 space-y-1 cursor-grab\"\n data-testid=\"board-card\"\n >\n <button\n type=\"button\"\n className=\"text-left text-sm font-medium leading-tight hover:underline\"\n onClick={() =>\n navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(card.id)}`)\n }\n >\n {card.title}\n </button>\n <div className=\"flex items-center justify-between text-[11px] text-muted-foreground\">\n <span>{card.key}</span>\n <span>{card.storyPoints ?? 0} pts</span>\n </div>\n <div className=\"flex items-center justify-between gap-1 text-[11px] text-muted-foreground\">\n <span className=\"truncate\">\n {card.assigneeId ? <PersonName id={card.assigneeId} /> : 'Unassigned'}\n </span>\n {/* The same move as drag-and-drop, for keyboard and assistive tech. */}\n <select\n aria-label={`Move ${card.key} to column`}\n className=\"rounded border border-input bg-background px-1 py-0.5 text-[11px]\"\n value=\"\"\n disabled={busy}\n onChange={(e) => e.target.value && onMove(card.id, e.target.value)}\n >\n <option value=\"\">Move…</option>\n {columns\n .filter((c) => c.id !== column.id)\n .map((c) => (\n <option key={c.id} value={c.id}>\n {c.name}\n </option>\n ))}\n </select>\n </div>\n </li>\n ))}\n {count === 0 && <li className=\"text-xs text-muted-foreground text-center py-4\">Empty</li>}\n </ul>\n {hidden > 0 && (\n <p className=\"px-2 pb-2 text-xs text-muted-foreground\">\n +{hidden} more (showing the first {CARDS_PER_COLUMN})\n </p>\n )}\n </section>\n );\n}\n\n/** Add a column (no `column`) or edit one: name, the status it sets, WIP limit; delete. */\nfunction ColumnDialog({ boardId, column }: { boardId: string; column?: BoardColumn }) {\n const editing = column !== undefined;\n const [open, setOpen] = useState(false);\n const [name, setName] = useState(column?.name ?? '');\n const [mappedStatus, setMappedStatus] = useState(column?.mappedStatus ?? '');\n const [wip, setWip] = useState(column?.wipLimit ? String(column.wipLimit) : '');\n const [error, setError] = useState<string | null>(null);\n const options = { refetchQueries: REFETCH, awaitRefetchQueries: true };\n const [create, createState] = useMutation(CREATE_COLUMN, options);\n const [update, updateState] = useMutation(UPDATE_COLUMN, options);\n const [remove, removeState] = useMutation(DELETE_COLUMN, options);\n const busy = createState.loading || updateState.loading || removeState.loading;\n\n const wipValue = wip.trim() === '' ? null : Number(wip);\n const invalidWip = wipValue !== null && (!Number.isInteger(wipValue) || wipValue < 1);\n const canSave = name.trim() !== '' && !invalidWip && !busy;\n\n const reset = () => {\n setName(column?.name ?? '');\n setMappedStatus(column?.mappedStatus ?? '');\n setWip(column?.wipLimit ? String(column.wipLimit) : '');\n setError(null);\n };\n\n const save = async () => {\n setError(null);\n const fields = {\n name: name.trim(),\n mappedStatus: mappedStatus || null,\n wipLimit: wipValue,\n };\n try {\n if (editing) {\n await update({ variables: { id: column.id, input: fields } });\n } else {\n await create({ variables: { input: { boardId, type: 'CUSTOM', ...fields } } });\n }\n setOpen(false);\n } catch (e) {\n setError(messageOf(e, 'The column could not be saved.'));\n }\n };\n\n const idPrefix = editing ? `column-${column.id}` : 'new-column';\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (next) reset();\n }}\n >\n <ResponsiveDialogTrigger asChild>\n {editing ? (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-6 w-6\"\n aria-label={`Edit ${column.name} column`}\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n ) : (\n <Button size=\"sm\" variant=\"outline\">\n <Plus className=\"mr-1 h-4 w-4\" />\n Add column\n </Button>\n )}\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-md\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {editing ? `Edit ${column.name}` : 'Add column'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Moving a card into a column that sets a status changes the work item's status.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <div>\n <label htmlFor={`${idPrefix}-name`} className=\"text-sm font-medium\">\n Name\n </label>\n <Input\n id={`${idPrefix}-name`}\n className=\"mt-1\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div>\n <label htmlFor={`${idPrefix}-status`} className=\"text-sm font-medium\">\n Sets status\n </label>\n <select\n id={`${idPrefix}-status`}\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={mappedStatus}\n onChange={(e) => setMappedStatus(e.target.value)}\n >\n <option value=\"\">No status (cards keep theirs)</option>\n {STATUSES.map((s) => (\n <option key={s} value={s}>\n {statusLabel(s)}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor={`${idPrefix}-wip`} className=\"text-sm font-medium\">\n WIP limit (blank for none)\n </label>\n <Input\n id={`${idPrefix}-wip`}\n type=\"number\"\n min={1}\n className=\"mt-1\"\n value={wip}\n onChange={(e) => setWip(e.target.value)}\n />\n {invalidWip && <ErrorLine message=\"The WIP limit must be a whole number, 1 or more.\" />}\n </div>\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter className=\"gap-2\">\n {editing && (\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"outline\" disabled={busy}>\n Delete column\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete {column.name}?</AlertDialogTitle>\n <AlertDialogDescription>\n Its cards are not deleted: each goes back to the column for its status, or off\n the board if no column sets that status.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Keep it</AlertDialogCancel>\n <AlertDialogAction\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n onClick={async () => {\n try {\n await remove({ variables: { id: column.id } });\n setOpen(false);\n } catch (e) {\n setError(messageOf(e, 'The column could not be deleted.'));\n }\n }}\n >\n Delete column\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n )}\n <Button onClick={save} disabled={!canSave} data-testid={`${idPrefix}-save`}>\n {busy ? 'Saving…' : editing ? 'Save' : 'Add column'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProjectBoard.js","names":[],"sources":["../../../src/planmagnet/board/ProjectBoard.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n Card,\n CardContent,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { ChevronLeft, ChevronRight, LayoutGrid, Pencil, Plus } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { PersonName } from '../people/People';\nimport { throwOnError } from '../utils/mutationResult';\n\n/**\n * A project's board (P1.2). The server owns placement: each column's `cards`\n * follow the rule in wspace-planmagnet-svc board.service.ts `columnCardsWhere`\n * (placed column, else the first column mapped to the item's status), and\n * `unplacedCount` says how many items are on no column. Moving a card into a\n * column mapped to a status changes that status on the server, and a column's\n * WIP limit is enforced there too. This component only draws and asks.\n */\n\nconst STATUSES = [\n 'BACKLOG',\n 'TODO',\n 'IN_PROGRESS',\n 'IN_REVIEW',\n 'TESTING',\n 'DONE',\n 'CANCELLED',\n] as const;\nconst statusLabel = (status: string) =>\n status.charAt(0) + status.slice(1).toLowerCase().replace(/_/g, ' ');\n\nconst CARDS_PER_COLUMN = 100;\n\nconst BOARDS = gql`\n query ProjectBoards($workspaceId: ID!, $projectId: String) {\n planmagnetBoards(\n workspaceId: $workspaceId\n filter: { projectId: $projectId }\n pagination: { first: 20 }\n ) {\n items {\n id\n name\n isDefault\n }\n }\n }\n`;\n\nconst BOARD = gql`\n query ProjectBoard($id: ID!) {\n planmagnetBoard(id: $id) {\n id\n name\n unplacedCount\n columns {\n id\n name\n mappedStatus\n wipLimit\n sortOrder\n cards(pagination: { first: 100 }) {\n totalCount\n items {\n id\n key\n title\n status\n priority\n storyPoints\n assigneeId\n }\n }\n }\n }\n }\n`;\n\nconst MOVE_CARD = gql`\n mutation ProjectBoardMoveCard($boardId: ID!, $input: PlanmagnetMoveCardInput!) {\n planmagnetMoveCard(boardId: $boardId, input: $input) {\n id\n }\n }\n`;\nconst CREATE_BOARD = gql`\n mutation ProjectBoardCreate($input: PlanmagnetCreateBoardInput!) {\n planmagnetCreateBoard(input: $input) {\n id\n }\n }\n`;\nconst CREATE_COLUMN = gql`\n mutation ProjectBoardCreateColumn($input: PlanmagnetCreateBoardColumnInput!) {\n planmagnetCreateBoardColumn(input: $input) {\n id\n }\n }\n`;\nconst UPDATE_COLUMN = gql`\n mutation ProjectBoardUpdateColumn($id: ID!, $input: PlanmagnetUpdateBoardColumnInput!) {\n planmagnetUpdateBoardColumn(id: $id, input: $input) {\n id\n }\n }\n`;\nconst DELETE_COLUMN = gql`\n mutation ProjectBoardDeleteColumn($id: ID!) {\n planmagnetDeleteBoardColumn(id: $id)\n }\n`;\nconst REORDER_COLUMNS = gql`\n mutation ProjectBoardReorder($boardId: ID!, $input: PlanmagnetReorderColumnsInput!) {\n planmagnetReorderColumns(boardId: $boardId, input: $input) {\n id\n }\n }\n`;\n\n/** Every query whose numbers a board change can move. */\nconst REFETCH = [\n 'ProjectBoard',\n 'ProjectBoards',\n 'GetWorkItems',\n 'GetWorkItemCounts',\n 'GetDashboardData',\n];\n\ninterface BoardCard {\n id: string;\n key: string;\n title: string;\n status: string;\n priority: string;\n storyPoints: number | null;\n assigneeId: string | null;\n}\n\ninterface BoardColumn {\n id: string;\n name: string;\n mappedStatus: string | null;\n wipLimit: number | null;\n sortOrder: number;\n cards: { totalCount: number; items: BoardCard[] };\n}\n\ninterface BoardData {\n id: string;\n name: string;\n unplacedCount: number;\n columns: BoardColumn[];\n}\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback);\n\nfunction ErrorLine({ message }: { message: string }) {\n return (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n );\n}\n\nexport function ProjectBoard({\n projectId,\n projectName,\n}: {\n projectId: string;\n projectName: string;\n}) {\n const { workspaceId } = usePlanMagnet();\n const [chosenBoardId, setChosenBoardId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const { data: boardsData, loading: boardsLoading } = useQuery<{\n planmagnetBoards: { items: Array<{ id: string; name: string; isDefault: boolean }> };\n }>(BOARDS, { variables: { workspaceId, projectId }, skip: !workspaceId });\n const boards = boardsData?.planmagnetBoards.items ?? [];\n const boardId =\n (chosenBoardId && boards.some((b) => b.id === chosenBoardId) ? chosenBoardId : null) ??\n boards.find((b) => b.isDefault)?.id ??\n boards[0]?.id ??\n null;\n\n const { data, loading } = useQuery<{ planmagnetBoard: BoardData | null }>(BOARD, {\n variables: { id: boardId },\n skip: !boardId,\n });\n const board = data?.planmagnetBoard ?? null;\n\n const [createBoard, createBoardState] = useMutation<{ planmagnetCreateBoard: { id: string } }>(\n CREATE_BOARD,\n { refetchQueries: REFETCH, awaitRefetchQueries: true }\n );\n const [moveCard, moveState] = useMutation(MOVE_CARD, {\n refetchQueries: REFETCH,\n awaitRefetchQueries: true,\n });\n const [reorder] = useMutation(REORDER_COLUMNS, {\n refetchQueries: REFETCH,\n awaitRefetchQueries: true,\n });\n\n const run = async (action: () => Promise<{ error?: unknown }>, fallback: string) => {\n setError(null);\n try {\n await throwOnError(action());\n } catch (e) {\n setError(messageOf(e, fallback));\n }\n };\n\n const move = (workItemId: string, targetColumnId: string) =>\n run(\n () => moveCard({ variables: { boardId, input: { workItemId, targetColumnId } } }),\n 'The card could not be moved.'\n );\n\n const shiftColumn = (index: number, delta: -1 | 1) => {\n if (!board) return;\n const order = board.columns.map((c) => c.id);\n const target = index + delta;\n if (target < 0 || target >= order.length) return;\n [order[index], order[target]] = [order[target], order[index]];\n return run(\n () => reorder({ variables: { boardId, input: { columnIds: order } } }),\n 'The columns could not be reordered.'\n );\n };\n\n if (boardsLoading && !boardsData) {\n return <p className=\"text-sm text-muted-foreground p-4\">Loading board…</p>;\n }\n\n if (!boardId) {\n return (\n <Card>\n <CardContent className=\"p-8 text-center space-y-3\" data-testid=\"board-empty\">\n <LayoutGrid className=\"h-8 w-8 mx-auto text-muted-foreground\" />\n <p className=\"text-sm text-muted-foreground\">{projectName} has no board yet.</p>\n <Button\n size=\"sm\"\n disabled={createBoardState.loading}\n onClick={() =>\n run(\n () =>\n createBoard({\n variables: {\n input: {\n projectId,\n name: `${projectName} board`,\n type: 'KANBAN',\n isDefault: true,\n withDefaultColumns: true,\n },\n },\n }),\n 'The board could not be created.'\n )\n }\n >\n <Plus className=\"mr-1 h-4 w-4\" />\n {createBoardState.loading ? 'Creating…' : 'Create board'}\n </Button>\n <p className=\"text-xs text-muted-foreground\">\n Starts with one column per status: Backlog, To Do, In Progress, In Review, Testing,\n Done.\n </p>\n {error && <ErrorLine message={error} />}\n </CardContent>\n </Card>\n );\n }\n\n return (\n <div className=\"space-y-3\" data-testid=\"project-board\">\n <div className=\"flex flex-wrap items-center gap-3\">\n {boards.length > 1 && (\n <select\n aria-label=\"Board\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm\"\n value={boardId}\n onChange={(e) => setChosenBoardId(e.target.value)}\n >\n {boards.map((b) => (\n <option key={b.id} value={b.id}>\n {b.name}\n </option>\n ))}\n </select>\n )}\n {board && board.unplacedCount > 0 && (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"board-unplaced\">\n {board.unplacedCount} work item{board.unplacedCount === 1 ? ' is' : 's are'} not on this\n board: {board.unplacedCount === 1 ? 'its status has' : 'their status has'} no column.\n </p>\n )}\n {board && (\n <div className=\"ml-auto\">\n <ColumnDialog boardId={board.id} />\n </div>\n )}\n </div>\n {error && <ErrorLine message={error} />}\n {loading && !board ? (\n <p className=\"text-sm text-muted-foreground p-4\">Loading board…</p>\n ) : (\n <div className=\"flex gap-3 overflow-x-auto pb-2\">\n {board?.columns.map((column, index) => (\n <BoardColumnView\n key={column.id}\n boardId={board.id}\n column={column}\n columns={board.columns}\n isFirst={index === 0}\n isLast={index === board.columns.length - 1}\n busy={moveState.loading}\n onMove={move}\n onShift={(delta) => shiftColumn(index, delta)}\n />\n ))}\n {board && board.columns.length === 0 && (\n <p className=\"text-sm text-muted-foreground p-4\">\n This board has no columns. Add one to start placing work.\n </p>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction BoardColumnView({\n boardId,\n column,\n columns,\n isFirst,\n isLast,\n busy,\n onMove,\n onShift,\n}: {\n boardId: string;\n column: BoardColumn;\n columns: BoardColumn[];\n isFirst: boolean;\n isLast: boolean;\n busy: boolean;\n onMove: (workItemId: string, targetColumnId: string) => void;\n onShift: (delta: -1 | 1) => void;\n}) {\n const navigate = usePlanMagnetNavigate();\n const [dragOver, setDragOver] = useState(false);\n const count = column.cards.totalCount;\n const atLimit = column.wipLimit != null && column.wipLimit > 0 && count >= column.wipLimit;\n const hidden = count - column.cards.items.length;\n\n return (\n <section\n aria-label={`${column.name} column`}\n data-testid={`board-column-${column.name}`}\n className={`min-w-[240px] w-[240px] shrink-0 rounded-md border bg-muted/30 ${dragOver ? 'ring-2 ring-primary' : ''}`}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={(e) => {\n e.preventDefault();\n setDragOver(false);\n const workItemId = e.dataTransfer.getData('text/plain');\n if (workItemId) onMove(workItemId, column.id);\n }}\n >\n <header className=\"p-2 border-b space-y-1\">\n <div className=\"flex items-center justify-between gap-1\">\n <h3 className=\"text-sm font-medium truncate\">{column.name}</h3>\n <span\n data-testid={`board-column-count-${column.name}`}\n className={`text-xs rounded-full px-1.5 ${atLimit ? 'bg-status-warning-subtle text-status-warning' : 'bg-muted'}`}\n title={column.wipLimit ? `WIP limit ${column.wipLimit}` : undefined}\n >\n {column.wipLimit ? `${count} / ${column.wipLimit}` : count}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-1\">\n <span className=\"text-[11px] text-muted-foreground\">\n {column.mappedStatus ? `Sets status: ${statusLabel(column.mappedStatus)}` : 'No status'}\n </span>\n <span className=\"flex\">\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-6 w-6\"\n aria-label={`Move ${column.name} column left`}\n disabled={isFirst}\n onClick={() => onShift(-1)}\n >\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-6 w-6\"\n aria-label={`Move ${column.name} column right`}\n disabled={isLast}\n onClick={() => onShift(1)}\n >\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </Button>\n <ColumnDialog boardId={boardId} column={column} />\n </span>\n </div>\n </header>\n <ul className=\"p-2 space-y-2 min-h-[80px]\">\n {column.cards.items.map((card) => (\n <li\n key={card.id}\n draggable\n onDragStart={(e) => {\n e.dataTransfer.setData('text/plain', card.id);\n e.dataTransfer.effectAllowed = 'move';\n }}\n className=\"rounded-md border bg-background p-2 space-y-1 cursor-grab\"\n data-testid=\"board-card\"\n >\n <button\n type=\"button\"\n className=\"text-left text-sm font-medium leading-tight hover:underline\"\n onClick={() =>\n navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(card.id)}`)\n }\n >\n {card.title}\n </button>\n <div className=\"flex items-center justify-between text-[11px] text-muted-foreground\">\n <span>{card.key}</span>\n <span>{card.storyPoints ?? 0} pts</span>\n </div>\n <div className=\"flex items-center justify-between gap-1 text-[11px] text-muted-foreground\">\n <span className=\"truncate\">\n {card.assigneeId ? <PersonName id={card.assigneeId} /> : 'Unassigned'}\n </span>\n {/* The same move as drag-and-drop, for keyboard and assistive tech. */}\n <select\n aria-label={`Move ${card.key} to column`}\n className=\"rounded border border-input bg-background px-1 py-0.5 text-[11px]\"\n value=\"\"\n disabled={busy}\n onChange={(e) => e.target.value && onMove(card.id, e.target.value)}\n >\n <option value=\"\">Move…</option>\n {columns\n .filter((c) => c.id !== column.id)\n .map((c) => (\n <option key={c.id} value={c.id}>\n {c.name}\n </option>\n ))}\n </select>\n </div>\n </li>\n ))}\n {count === 0 && <li className=\"text-xs text-muted-foreground text-center py-4\">Empty</li>}\n </ul>\n {hidden > 0 && (\n <p className=\"px-2 pb-2 text-xs text-muted-foreground\">\n +{hidden} more (showing the first {CARDS_PER_COLUMN})\n </p>\n )}\n </section>\n );\n}\n\n/** Add a column (no `column`) or edit one: name, the status it sets, WIP limit; delete. */\nfunction ColumnDialog({ boardId, column }: { boardId: string; column?: BoardColumn }) {\n const editing = column !== undefined;\n const [open, setOpen] = useState(false);\n const [name, setName] = useState(column?.name ?? '');\n const [mappedStatus, setMappedStatus] = useState(column?.mappedStatus ?? '');\n const [wip, setWip] = useState(column?.wipLimit ? String(column.wipLimit) : '');\n const [error, setError] = useState<string | null>(null);\n const options = { refetchQueries: REFETCH, awaitRefetchQueries: true };\n const [create, createState] = useMutation(CREATE_COLUMN, options);\n const [update, updateState] = useMutation(UPDATE_COLUMN, options);\n const [remove, removeState] = useMutation(DELETE_COLUMN, options);\n const busy = createState.loading || updateState.loading || removeState.loading;\n\n const wipValue = wip.trim() === '' ? null : Number(wip);\n const invalidWip = wipValue !== null && (!Number.isInteger(wipValue) || wipValue < 1);\n const canSave = name.trim() !== '' && !invalidWip && !busy;\n\n const reset = () => {\n setName(column?.name ?? '');\n setMappedStatus(column?.mappedStatus ?? '');\n setWip(column?.wipLimit ? String(column.wipLimit) : '');\n setError(null);\n };\n\n const save = async () => {\n setError(null);\n const fields = {\n name: name.trim(),\n mappedStatus: mappedStatus || null,\n wipLimit: wipValue,\n };\n try {\n if (editing) {\n await throwOnError(update({ variables: { id: column.id, input: fields } }));\n } else {\n await throwOnError(\n create({ variables: { input: { boardId, type: 'CUSTOM', ...fields } } })\n );\n }\n setOpen(false);\n } catch (e) {\n setError(messageOf(e, 'The column could not be saved.'));\n }\n };\n\n const idPrefix = editing ? `column-${column.id}` : 'new-column';\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (next) reset();\n }}\n >\n <ResponsiveDialogTrigger asChild>\n {editing ? (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-6 w-6\"\n aria-label={`Edit ${column.name} column`}\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n ) : (\n <Button size=\"sm\" variant=\"outline\">\n <Plus className=\"mr-1 h-4 w-4\" />\n Add column\n </Button>\n )}\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-md\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {editing ? `Edit ${column.name}` : 'Add column'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Moving a card into a column that sets a status changes the work item's status.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <div>\n <label htmlFor={`${idPrefix}-name`} className=\"text-sm font-medium\">\n Name\n </label>\n <Input\n id={`${idPrefix}-name`}\n className=\"mt-1\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div>\n <label htmlFor={`${idPrefix}-status`} className=\"text-sm font-medium\">\n Sets status\n </label>\n <select\n id={`${idPrefix}-status`}\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={mappedStatus}\n onChange={(e) => setMappedStatus(e.target.value)}\n >\n <option value=\"\">No status (cards keep theirs)</option>\n {STATUSES.map((s) => (\n <option key={s} value={s}>\n {statusLabel(s)}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor={`${idPrefix}-wip`} className=\"text-sm font-medium\">\n WIP limit (blank for none)\n </label>\n <Input\n id={`${idPrefix}-wip`}\n type=\"number\"\n min={1}\n className=\"mt-1\"\n value={wip}\n onChange={(e) => setWip(e.target.value)}\n />\n {invalidWip && <ErrorLine message=\"The WIP limit must be a whole number, 1 or more.\" />}\n </div>\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter className=\"gap-2\">\n {editing && (\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"outline\" disabled={busy}>\n Delete column\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete {column.name}?</AlertDialogTitle>\n <AlertDialogDescription>\n Its cards are not deleted: each goes back to the column for its status, or off\n the board if no column sets that status.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Keep it</AlertDialogCancel>\n <AlertDialogAction\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n onClick={async () => {\n try {\n await throwOnError(remove({ variables: { id: column.id } }));\n setOpen(false);\n } catch (e) {\n setError(messageOf(e, 'The column could not be deleted.'));\n }\n }}\n >\n Delete column\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n )}\n <Button onClick={save} disabled={!canSave} data-testid={`${idPrefix}-save`}>\n {busy ? 'Saving…' : editing ? 'Save' : 'Add column'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateDialogs.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/create/CreateDialogs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CreateDialogs.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/create/CreateDialogs.tsx"],"names":[],"mappings":"AAqIA,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,2CAsGzF;AAcD,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,2CA+F7F"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
+
import { useState as n } from "react";
|
|
4
|
+
import { Plus as r } from "lucide-react";
|
|
5
|
+
import { gql as i } from "@apollo/client";
|
|
6
|
+
import { useMutation as a, useQuery as o } from "@apollo/client/react";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import { Button as l, Input as u, ResponsiveDialog as d, ResponsiveDialogContent as f, ResponsiveDialogDescription as p, ResponsiveDialogFooter as m, ResponsiveDialogHeader as h, ResponsiveDialogTitle as g, ResponsiveDialogTrigger as _ } from "@burdenoff/fe-libs/ui";
|
|
8
9
|
//#region src/planmagnet/create/CreateDialogs.tsx
|
|
9
|
-
var
|
|
10
|
+
var v = i`
|
|
10
11
|
query CreateDialogProjects($workspaceId: ID!) {
|
|
11
12
|
planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {
|
|
12
13
|
items {
|
|
@@ -15,16 +16,16 @@ var _ = r`
|
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
|
-
`,
|
|
19
|
-
function
|
|
20
|
-
return /* @__PURE__ */
|
|
19
|
+
`, y = "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm";
|
|
20
|
+
function b({ message: e }) {
|
|
21
|
+
return /* @__PURE__ */ s("p", {
|
|
21
22
|
role: "alert",
|
|
22
23
|
className: "text-sm text-destructive",
|
|
23
24
|
children: e
|
|
24
25
|
});
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
-
let { workspaceId: n } = e(), { data: r, loading: i } =
|
|
27
|
+
function x(t) {
|
|
28
|
+
let { workspaceId: n } = e(), { data: r, loading: i } = o(v, {
|
|
28
29
|
variables: { workspaceId: n ?? "" },
|
|
29
30
|
skip: !t || !n
|
|
30
31
|
});
|
|
@@ -33,31 +34,31 @@ function b(t) {
|
|
|
33
34
|
loading: i
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
|
-
function
|
|
37
|
-
return /* @__PURE__ */
|
|
37
|
+
function S({ id: e, value: t, onChange: n, projects: r, loading: i }) {
|
|
38
|
+
return /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
|
|
38
39
|
htmlFor: e,
|
|
39
40
|
className: "text-sm font-medium",
|
|
40
41
|
children: "Project"
|
|
41
|
-
}), /* @__PURE__ */
|
|
42
|
+
}), /* @__PURE__ */ c("select", {
|
|
42
43
|
id: e,
|
|
43
|
-
className:
|
|
44
|
+
className: y,
|
|
44
45
|
value: t,
|
|
45
46
|
onChange: (e) => n(e.target.value),
|
|
46
|
-
children: [r.length === 0 && /* @__PURE__ */
|
|
47
|
+
children: [r.length === 0 && /* @__PURE__ */ s("option", {
|
|
47
48
|
value: "",
|
|
48
49
|
children: i ? "Loading…" : "No projects"
|
|
49
|
-
}), r.map((e) => /* @__PURE__ */
|
|
50
|
+
}), r.map((e) => /* @__PURE__ */ s("option", {
|
|
50
51
|
value: e.id,
|
|
51
52
|
children: e.name
|
|
52
53
|
}, e.id))]
|
|
53
54
|
})] });
|
|
54
55
|
}
|
|
55
|
-
function
|
|
56
|
-
return /* @__PURE__ */
|
|
56
|
+
function C({ id: e, label: t, value: n, onChange: r, type: i = "text", placeholder: a }) {
|
|
57
|
+
return /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
|
|
57
58
|
htmlFor: e,
|
|
58
59
|
className: "text-sm font-medium",
|
|
59
60
|
children: t
|
|
60
|
-
}), /* @__PURE__ */
|
|
61
|
+
}), /* @__PURE__ */ s(u, {
|
|
61
62
|
id: e,
|
|
62
63
|
type: i,
|
|
63
64
|
className: "mt-1",
|
|
@@ -66,217 +67,217 @@ function S({ id: e, label: t, value: n, onChange: r, type: i = "text", placehold
|
|
|
66
67
|
onChange: (e) => r(e.target.value)
|
|
67
68
|
})] });
|
|
68
69
|
}
|
|
69
|
-
var
|
|
70
|
+
var w = (e, t) => e instanceof Error ? e.message : t, T = i`
|
|
70
71
|
mutation CreateDialogRelease($input: PlanmagnetCreateReleaseInput!) {
|
|
71
72
|
planmagnetCreateRelease(input: $input) {
|
|
72
73
|
id
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
`,
|
|
76
|
+
`, E = {
|
|
76
77
|
name: "",
|
|
77
78
|
version: "",
|
|
78
79
|
projectId: "",
|
|
79
80
|
plannedDate: "",
|
|
80
81
|
description: ""
|
|
81
82
|
};
|
|
82
|
-
function
|
|
83
|
-
let [
|
|
83
|
+
function D({ onCreated: e }) {
|
|
84
|
+
let [i, o] = n(!1), [u, v] = n(E), [y, D] = n(null), { projects: O, loading: k } = x(i), A = u.projectId || O[0]?.id || "", [j, { loading: M }] = a(T, {
|
|
84
85
|
refetchQueries: ["ListReleases"],
|
|
85
86
|
awaitRefetchQueries: !0
|
|
86
|
-
}),
|
|
87
|
-
return /* @__PURE__ */
|
|
88
|
-
open:
|
|
87
|
+
}), N = u.name.trim() !== "" && u.version.trim() !== "" && A !== "" && !M;
|
|
88
|
+
return /* @__PURE__ */ c(d, {
|
|
89
|
+
open: i,
|
|
89
90
|
onOpenChange: (e) => {
|
|
90
|
-
|
|
91
|
+
o(e), e || D(null);
|
|
91
92
|
},
|
|
92
|
-
children: [/* @__PURE__ */
|
|
93
|
+
children: [/* @__PURE__ */ s(_, {
|
|
93
94
|
asChild: !0,
|
|
94
|
-
children: /* @__PURE__ */
|
|
95
|
+
children: /* @__PURE__ */ c(l, {
|
|
95
96
|
size: "sm",
|
|
96
|
-
children: [/* @__PURE__ */
|
|
97
|
+
children: [/* @__PURE__ */ s(r, { className: "mr-1 h-4 w-4" }), "New Release"]
|
|
97
98
|
})
|
|
98
|
-
}), /* @__PURE__ */
|
|
99
|
+
}), /* @__PURE__ */ c(f, {
|
|
99
100
|
className: "max-w-lg",
|
|
100
101
|
children: [
|
|
101
|
-
/* @__PURE__ */
|
|
102
|
-
/* @__PURE__ */
|
|
102
|
+
/* @__PURE__ */ c(h, { children: [/* @__PURE__ */ s(g, { children: "New release" }), /* @__PURE__ */ s(p, { children: "The release starts in Planning." })] }),
|
|
103
|
+
/* @__PURE__ */ c("div", {
|
|
103
104
|
className: "space-y-3",
|
|
104
105
|
children: [
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ s(C, {
|
|
106
107
|
id: "new-release-name",
|
|
107
108
|
label: "Name",
|
|
108
|
-
value:
|
|
109
|
-
onChange: (e) =>
|
|
110
|
-
...
|
|
109
|
+
value: u.name,
|
|
110
|
+
onChange: (e) => v({
|
|
111
|
+
...u,
|
|
111
112
|
name: e
|
|
112
113
|
})
|
|
113
114
|
}),
|
|
114
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ s(C, {
|
|
115
116
|
id: "new-release-version",
|
|
116
117
|
label: "Version",
|
|
117
118
|
placeholder: "e.g. 1.4.0",
|
|
118
|
-
value:
|
|
119
|
-
onChange: (e) =>
|
|
120
|
-
...
|
|
119
|
+
value: u.version,
|
|
120
|
+
onChange: (e) => v({
|
|
121
|
+
...u,
|
|
121
122
|
version: e
|
|
122
123
|
})
|
|
123
124
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ s(S, {
|
|
125
126
|
id: "new-release-project",
|
|
126
|
-
value:
|
|
127
|
-
onChange: (e) =>
|
|
128
|
-
...
|
|
127
|
+
value: A,
|
|
128
|
+
onChange: (e) => v({
|
|
129
|
+
...u,
|
|
129
130
|
projectId: e
|
|
130
131
|
}),
|
|
131
|
-
projects:
|
|
132
|
-
loading:
|
|
132
|
+
projects: O,
|
|
133
|
+
loading: k
|
|
133
134
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ s(C, {
|
|
135
136
|
id: "new-release-date",
|
|
136
137
|
label: "Planned date",
|
|
137
138
|
type: "date",
|
|
138
|
-
value:
|
|
139
|
-
onChange: (e) =>
|
|
140
|
-
...
|
|
139
|
+
value: u.plannedDate,
|
|
140
|
+
onChange: (e) => v({
|
|
141
|
+
...u,
|
|
141
142
|
plannedDate: e
|
|
142
143
|
})
|
|
143
144
|
}),
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ s(C, {
|
|
145
146
|
id: "new-release-description",
|
|
146
147
|
label: "Description",
|
|
147
|
-
value:
|
|
148
|
-
onChange: (e) =>
|
|
149
|
-
...
|
|
148
|
+
value: u.description,
|
|
149
|
+
onChange: (e) => v({
|
|
150
|
+
...u,
|
|
150
151
|
description: e
|
|
151
152
|
})
|
|
152
153
|
})
|
|
153
154
|
]
|
|
154
155
|
}),
|
|
155
|
-
|
|
156
|
-
/* @__PURE__ */
|
|
156
|
+
y && /* @__PURE__ */ s(b, { message: y }),
|
|
157
|
+
/* @__PURE__ */ s(m, { children: /* @__PURE__ */ s(l, {
|
|
157
158
|
onClick: async () => {
|
|
158
|
-
|
|
159
|
+
D(null);
|
|
159
160
|
try {
|
|
160
|
-
let
|
|
161
|
-
name:
|
|
162
|
-
version:
|
|
163
|
-
projectId:
|
|
164
|
-
plannedDate:
|
|
165
|
-
description:
|
|
166
|
-
} } })).data?.planmagnetCreateRelease.id;
|
|
167
|
-
|
|
161
|
+
let n = (await t(j({ variables: { input: {
|
|
162
|
+
name: u.name.trim(),
|
|
163
|
+
version: u.version.trim(),
|
|
164
|
+
projectId: A,
|
|
165
|
+
plannedDate: u.plannedDate || void 0,
|
|
166
|
+
description: u.description.trim() || void 0
|
|
167
|
+
} } }))).data?.planmagnetCreateRelease.id;
|
|
168
|
+
v(E), o(!1), n && e(n);
|
|
168
169
|
} catch (e) {
|
|
169
|
-
|
|
170
|
+
D(w(e, "The release could not be created."));
|
|
170
171
|
}
|
|
171
172
|
},
|
|
172
|
-
disabled: !
|
|
173
|
+
disabled: !N,
|
|
173
174
|
"data-testid": "new-release-submit",
|
|
174
|
-
children:
|
|
175
|
+
children: M ? "Creating…" : "Create release"
|
|
175
176
|
}) })
|
|
176
177
|
]
|
|
177
178
|
})]
|
|
178
179
|
});
|
|
179
180
|
}
|
|
180
|
-
var
|
|
181
|
+
var O = i`
|
|
181
182
|
mutation CreateDialogMilestone($input: PlanmagnetCreateMilestoneInput!) {
|
|
182
183
|
planmagnetCreateMilestone(input: $input) {
|
|
183
184
|
id
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
|
-
`,
|
|
187
|
+
`, k = {
|
|
187
188
|
name: "",
|
|
188
189
|
projectId: "",
|
|
189
190
|
dueDate: "",
|
|
190
191
|
description: ""
|
|
191
192
|
};
|
|
192
|
-
function
|
|
193
|
-
let [
|
|
193
|
+
function A({ onCreated: e }) {
|
|
194
|
+
let [i, o] = n(!1), [u, v] = n(k), [y, T] = n(null), { projects: E, loading: D } = x(i), A = u.projectId || E[0]?.id || "", [j, { loading: M }] = a(O, {
|
|
194
195
|
refetchQueries: ["GetMilestones"],
|
|
195
196
|
awaitRefetchQueries: !0
|
|
196
|
-
}),
|
|
197
|
-
return /* @__PURE__ */
|
|
198
|
-
open:
|
|
197
|
+
}), N = u.name.trim() !== "" && A !== "" && !M;
|
|
198
|
+
return /* @__PURE__ */ c(d, {
|
|
199
|
+
open: i,
|
|
199
200
|
onOpenChange: (e) => {
|
|
200
|
-
|
|
201
|
+
o(e), e || T(null);
|
|
201
202
|
},
|
|
202
|
-
children: [/* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ s(_, {
|
|
203
204
|
asChild: !0,
|
|
204
|
-
children: /* @__PURE__ */
|
|
205
|
+
children: /* @__PURE__ */ c(l, {
|
|
205
206
|
size: "sm",
|
|
206
|
-
children: [/* @__PURE__ */
|
|
207
|
+
children: [/* @__PURE__ */ s(r, { className: "mr-1 h-4 w-4" }), "New Milestone"]
|
|
207
208
|
})
|
|
208
|
-
}), /* @__PURE__ */
|
|
209
|
+
}), /* @__PURE__ */ c(f, {
|
|
209
210
|
className: "max-w-lg",
|
|
210
211
|
children: [
|
|
211
|
-
/* @__PURE__ */
|
|
212
|
-
/* @__PURE__ */
|
|
212
|
+
/* @__PURE__ */ c(h, { children: [/* @__PURE__ */ s(g, { children: "New milestone" }), /* @__PURE__ */ s(p, { children: "The milestone starts as Pending." })] }),
|
|
213
|
+
/* @__PURE__ */ c("div", {
|
|
213
214
|
className: "space-y-3",
|
|
214
215
|
children: [
|
|
215
|
-
/* @__PURE__ */
|
|
216
|
+
/* @__PURE__ */ s(C, {
|
|
216
217
|
id: "new-milestone-name",
|
|
217
218
|
label: "Name",
|
|
218
|
-
value:
|
|
219
|
-
onChange: (e) =>
|
|
220
|
-
...
|
|
219
|
+
value: u.name,
|
|
220
|
+
onChange: (e) => v({
|
|
221
|
+
...u,
|
|
221
222
|
name: e
|
|
222
223
|
})
|
|
223
224
|
}),
|
|
224
|
-
/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ s(S, {
|
|
225
226
|
id: "new-milestone-project",
|
|
226
|
-
value:
|
|
227
|
-
onChange: (e) =>
|
|
228
|
-
...
|
|
227
|
+
value: A,
|
|
228
|
+
onChange: (e) => v({
|
|
229
|
+
...u,
|
|
229
230
|
projectId: e
|
|
230
231
|
}),
|
|
231
|
-
projects:
|
|
232
|
-
loading:
|
|
232
|
+
projects: E,
|
|
233
|
+
loading: D
|
|
233
234
|
}),
|
|
234
|
-
/* @__PURE__ */
|
|
235
|
+
/* @__PURE__ */ s(C, {
|
|
235
236
|
id: "new-milestone-due",
|
|
236
237
|
label: "Due date",
|
|
237
238
|
type: "date",
|
|
238
|
-
value:
|
|
239
|
-
onChange: (e) =>
|
|
240
|
-
...
|
|
239
|
+
value: u.dueDate,
|
|
240
|
+
onChange: (e) => v({
|
|
241
|
+
...u,
|
|
241
242
|
dueDate: e
|
|
242
243
|
})
|
|
243
244
|
}),
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ s(C, {
|
|
245
246
|
id: "new-milestone-description",
|
|
246
247
|
label: "Description",
|
|
247
|
-
value:
|
|
248
|
-
onChange: (e) =>
|
|
249
|
-
...
|
|
248
|
+
value: u.description,
|
|
249
|
+
onChange: (e) => v({
|
|
250
|
+
...u,
|
|
250
251
|
description: e
|
|
251
252
|
})
|
|
252
253
|
})
|
|
253
254
|
]
|
|
254
255
|
}),
|
|
255
|
-
|
|
256
|
-
/* @__PURE__ */
|
|
256
|
+
y && /* @__PURE__ */ s(b, { message: y }),
|
|
257
|
+
/* @__PURE__ */ s(m, { children: /* @__PURE__ */ s(l, {
|
|
257
258
|
onClick: async () => {
|
|
258
|
-
|
|
259
|
+
T(null);
|
|
259
260
|
try {
|
|
260
|
-
let
|
|
261
|
-
name:
|
|
262
|
-
projectId:
|
|
263
|
-
dueDate:
|
|
264
|
-
description:
|
|
265
|
-
} } })).data?.planmagnetCreateMilestone.id;
|
|
266
|
-
|
|
261
|
+
let n = (await t(j({ variables: { input: {
|
|
262
|
+
name: u.name.trim(),
|
|
263
|
+
projectId: A,
|
|
264
|
+
dueDate: u.dueDate || void 0,
|
|
265
|
+
description: u.description.trim() || void 0
|
|
266
|
+
} } }))).data?.planmagnetCreateMilestone.id;
|
|
267
|
+
v(k), o(!1), n && e(n);
|
|
267
268
|
} catch (e) {
|
|
268
|
-
w(
|
|
269
|
+
T(w(e, "The milestone could not be created."));
|
|
269
270
|
}
|
|
270
271
|
},
|
|
271
|
-
disabled: !
|
|
272
|
+
disabled: !N,
|
|
272
273
|
"data-testid": "new-milestone-submit",
|
|
273
|
-
children:
|
|
274
|
+
children: M ? "Creating…" : "Create milestone"
|
|
274
275
|
}) })
|
|
275
276
|
]
|
|
276
277
|
})]
|
|
277
278
|
});
|
|
278
279
|
}
|
|
279
280
|
//#endregion
|
|
280
|
-
export {
|
|
281
|
+
export { A as NewMilestoneDialog, D as NewReleaseDialog };
|
|
281
282
|
|
|
282
283
|
//# sourceMappingURL=CreateDialogs.js.map
|