@burdenoff/planmagnet-fe-sdk 2026.703.3 → 2026.704.1
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/index.d.ts +176 -7
- package/dist/index.js +517 -138
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { onError } from '@apollo/client/link/error';
|
|
|
6
6
|
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
|
7
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
8
8
|
import { gql } from '@apollo/client';
|
|
9
|
-
import { CircleX, CircleCheckBig, CircleDotDashed, CircleDot, Circle, CircleDashed, User, Link2, CalendarDays, ChevronUp, ChevronDown, ChevronLeft, ChevronRight, CalendarRange, List, LayoutGrid, Search, Plus } from 'lucide-react';
|
|
9
|
+
import { CircleX, CircleCheckBig, CircleDotDashed, CircleDot, Circle, CircleDashed, User, Link2, CalendarDays, ChevronUp, ChevronDown, ChevronLeft, ChevronRight, Flag, CalendarRange, List, LayoutGrid, Search, Plus, Trash2 } from 'lucide-react';
|
|
10
10
|
import { clsx } from 'clsx';
|
|
11
11
|
import { twMerge } from 'tailwind-merge';
|
|
12
12
|
import { addWeeks, startOfWeek, endOfWeek, eachDayOfInterval, addMonths, startOfMonth, endOfMonth, format, isToday, isSameMonth, startOfDay, parseISO, isValid } from 'date-fns';
|
|
@@ -467,6 +467,51 @@ var DELETE_WORK_ITEM_LINK = gql`
|
|
|
467
467
|
planmagnetUnlinkWorkItem(id: $id)
|
|
468
468
|
}
|
|
469
469
|
`;
|
|
470
|
+
var MILESTONE_FIELDS = gql`
|
|
471
|
+
fragment MilestoneFields on Milestone {
|
|
472
|
+
id
|
|
473
|
+
projectId
|
|
474
|
+
name
|
|
475
|
+
description
|
|
476
|
+
status
|
|
477
|
+
dueDate
|
|
478
|
+
completedAt
|
|
479
|
+
ownerId
|
|
480
|
+
createdAt
|
|
481
|
+
updatedAt
|
|
482
|
+
}
|
|
483
|
+
`;
|
|
484
|
+
var LIST_MILESTONES = gql`
|
|
485
|
+
query ListMilestones(
|
|
486
|
+
$workspaceId: ID!
|
|
487
|
+
$filter: PlanmagnetMilestoneFilter
|
|
488
|
+
$pagination: PlanmagnetPaginationInput
|
|
489
|
+
) {
|
|
490
|
+
planmagnetMilestones(
|
|
491
|
+
workspaceId: $workspaceId
|
|
492
|
+
filter: $filter
|
|
493
|
+
pagination: $pagination
|
|
494
|
+
) {
|
|
495
|
+
items {
|
|
496
|
+
...MilestoneFields
|
|
497
|
+
}
|
|
498
|
+
pageInfo {
|
|
499
|
+
hasNextPage
|
|
500
|
+
hasPreviousPage
|
|
501
|
+
startCursor
|
|
502
|
+
endCursor
|
|
503
|
+
totalCount
|
|
504
|
+
}
|
|
505
|
+
totalCount
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
${MILESTONE_FIELDS}
|
|
509
|
+
`;
|
|
510
|
+
var DELETE_WORK_ITEM = gql`
|
|
511
|
+
mutation DeleteWorkItem($id: ID!) {
|
|
512
|
+
planmagnetDeleteWorkItem(id: $id)
|
|
513
|
+
}
|
|
514
|
+
`;
|
|
470
515
|
function cn(...inputs) {
|
|
471
516
|
return twMerge(clsx(inputs));
|
|
472
517
|
}
|
|
@@ -639,6 +684,111 @@ function LinkChip({ link, renderIcon, className }) {
|
|
|
639
684
|
}
|
|
640
685
|
return body;
|
|
641
686
|
}
|
|
687
|
+
var DEFAULT_TASK_LABELS = {
|
|
688
|
+
board: "Board",
|
|
689
|
+
list: "List",
|
|
690
|
+
timeline: "Timeline",
|
|
691
|
+
searchPlaceholder: "Search tasks\u2026",
|
|
692
|
+
allPriorities: "All priorities",
|
|
693
|
+
allTypes: "All types",
|
|
694
|
+
newTask: "New task",
|
|
695
|
+
myTasks: "My tasks",
|
|
696
|
+
noTasks: "No tasks",
|
|
697
|
+
noTasksFound: "No tasks found.",
|
|
698
|
+
dropHere: "Drop here",
|
|
699
|
+
unassigned: "Unassigned",
|
|
700
|
+
assigned: "Assigned",
|
|
701
|
+
overdue: "{n} overdue",
|
|
702
|
+
noDueDate: "No due date ({n})",
|
|
703
|
+
milestones: "Milestones",
|
|
704
|
+
today: "Today",
|
|
705
|
+
week: "Week",
|
|
706
|
+
month: "Month",
|
|
707
|
+
tasksSingular: "task",
|
|
708
|
+
tasksPlural: "tasks",
|
|
709
|
+
colTask: "Task",
|
|
710
|
+
colStatus: "Status",
|
|
711
|
+
colPriority: "Priority",
|
|
712
|
+
colAssignee: "Assignee",
|
|
713
|
+
colDueDate: "Due Date",
|
|
714
|
+
colPoints: "Points",
|
|
715
|
+
colLinkedRecord: "Linked Record",
|
|
716
|
+
colType: "Type",
|
|
717
|
+
colKey: "Key",
|
|
718
|
+
colLabels: "Labels",
|
|
719
|
+
newTaskHeading: "New task",
|
|
720
|
+
newTaskSubtitle: "Create a work item in this workspace.",
|
|
721
|
+
title: "Title",
|
|
722
|
+
titlePlaceholder: "What needs doing?",
|
|
723
|
+
description: "Description",
|
|
724
|
+
descriptionPlaceholder: "Add more detail (optional)",
|
|
725
|
+
typeLabel: "Type",
|
|
726
|
+
statusLabel: "Status",
|
|
727
|
+
priorityLabel: "Priority",
|
|
728
|
+
assigneeLabel: "Assignee",
|
|
729
|
+
assigneePlaceholder: "Actor ID (optional)",
|
|
730
|
+
dueDateLabel: "Due date",
|
|
731
|
+
storyPointsLabel: "Story points",
|
|
732
|
+
labelsLabel: "Labels",
|
|
733
|
+
labelsPlaceholder: "comma, separated, labels",
|
|
734
|
+
create: "Create task",
|
|
735
|
+
creating: "Creating\u2026",
|
|
736
|
+
cancel: "Cancel",
|
|
737
|
+
edit: "Edit",
|
|
738
|
+
del: "Delete",
|
|
739
|
+
deletePrompt: "Delete?",
|
|
740
|
+
yes: "Yes",
|
|
741
|
+
no: "No",
|
|
742
|
+
save: "Save changes",
|
|
743
|
+
saving: "Saving\u2026",
|
|
744
|
+
taskNotFound: "Task not found.",
|
|
745
|
+
projectRequired: "A projectId is required to create a task.",
|
|
746
|
+
errorLoading: "Error loading tasks",
|
|
747
|
+
moveFailed: "Couldn't move the task. Please try again.",
|
|
748
|
+
failedToCreate: "Failed to create task",
|
|
749
|
+
failedToSave: "Failed to save",
|
|
750
|
+
failedToDelete: "Failed to delete",
|
|
751
|
+
overdueLabel: "Overdue",
|
|
752
|
+
more: "more",
|
|
753
|
+
status: {
|
|
754
|
+
BACKLOG: "Backlog",
|
|
755
|
+
TODO: "To Do",
|
|
756
|
+
IN_PROGRESS: "In Progress",
|
|
757
|
+
IN_REVIEW: "In Review",
|
|
758
|
+
TESTING: "Testing",
|
|
759
|
+
DONE: "Done",
|
|
760
|
+
CANCELLED: "Cancelled"
|
|
761
|
+
},
|
|
762
|
+
priority: {
|
|
763
|
+
NONE: "None",
|
|
764
|
+
LOW: "Low",
|
|
765
|
+
MEDIUM: "Medium",
|
|
766
|
+
HIGH: "High",
|
|
767
|
+
CRITICAL: "Critical"
|
|
768
|
+
},
|
|
769
|
+
type: {
|
|
770
|
+
TASK: "Task",
|
|
771
|
+
STORY: "Story",
|
|
772
|
+
BUG: "Bug",
|
|
773
|
+
EPIC: "Epic",
|
|
774
|
+
SUB_TASK: "Sub Task"
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
var TaskLabelsContext = createContext(DEFAULT_TASK_LABELS);
|
|
778
|
+
var TaskLabelsProvider = TaskLabelsContext.Provider;
|
|
779
|
+
function useTaskLabels() {
|
|
780
|
+
return useContext(TaskLabelsContext);
|
|
781
|
+
}
|
|
782
|
+
function mergeTaskLabels(overrides) {
|
|
783
|
+
if (!overrides) return DEFAULT_TASK_LABELS;
|
|
784
|
+
return {
|
|
785
|
+
...DEFAULT_TASK_LABELS,
|
|
786
|
+
...overrides,
|
|
787
|
+
status: { ...DEFAULT_TASK_LABELS.status, ...overrides.status },
|
|
788
|
+
priority: { ...DEFAULT_TASK_LABELS.priority, ...overrides.priority },
|
|
789
|
+
type: { ...DEFAULT_TASK_LABELS.type, ...overrides.type }
|
|
790
|
+
};
|
|
791
|
+
}
|
|
642
792
|
var STATUS_META = {
|
|
643
793
|
BACKLOG: { icon: CircleDashed, tone: "text-muted-foreground/60" },
|
|
644
794
|
TODO: { icon: Circle, tone: "text-muted-foreground" },
|
|
@@ -660,6 +810,7 @@ function StatusIcon({ status, className }) {
|
|
|
660
810
|
);
|
|
661
811
|
}
|
|
662
812
|
function StatusPill({ status, className }) {
|
|
813
|
+
const L = useTaskLabels();
|
|
663
814
|
return /* @__PURE__ */ jsxs(
|
|
664
815
|
"span",
|
|
665
816
|
{
|
|
@@ -669,7 +820,7 @@ function StatusPill({ status, className }) {
|
|
|
669
820
|
),
|
|
670
821
|
children: [
|
|
671
822
|
/* @__PURE__ */ jsx(StatusIcon, { status }),
|
|
672
|
-
|
|
823
|
+
L.status[status]
|
|
673
824
|
]
|
|
674
825
|
}
|
|
675
826
|
);
|
|
@@ -687,12 +838,13 @@ function PriorityIndicator({
|
|
|
687
838
|
showLabel = false,
|
|
688
839
|
className
|
|
689
840
|
}) {
|
|
841
|
+
const L = useTaskLabels();
|
|
690
842
|
const meta = PRIORITY_META[priority] ?? PRIORITY_META.NONE;
|
|
691
843
|
return /* @__PURE__ */ jsxs(
|
|
692
844
|
"span",
|
|
693
845
|
{
|
|
694
846
|
className: cn("inline-flex items-center gap-1.5", meta.tone, className),
|
|
695
|
-
title:
|
|
847
|
+
title: `${L.priorityLabel}: ${L.priority[priority]}`,
|
|
696
848
|
children: [
|
|
697
849
|
/* @__PURE__ */ jsx("span", { className: "flex items-end gap-0.5", "aria-hidden": "true", children: BAR_HEIGHTS.map((h, i) => /* @__PURE__ */ jsx(
|
|
698
850
|
"span",
|
|
@@ -705,7 +857,7 @@ function PriorityIndicator({
|
|
|
705
857
|
},
|
|
706
858
|
h
|
|
707
859
|
)) }),
|
|
708
|
-
showLabel && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium capitalize", children:
|
|
860
|
+
showLabel && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium capitalize", children: L.priority[priority] })
|
|
709
861
|
]
|
|
710
862
|
}
|
|
711
863
|
);
|
|
@@ -718,7 +870,8 @@ var TYPE_VARIANT = {
|
|
|
718
870
|
SUB_TASK: "muted"
|
|
719
871
|
};
|
|
720
872
|
function TypeBadge({ type, className }) {
|
|
721
|
-
|
|
873
|
+
const L = useTaskLabels();
|
|
874
|
+
return /* @__PURE__ */ jsx(Badge, { variant: TYPE_VARIANT[type], className, children: L.type[type] });
|
|
722
875
|
}
|
|
723
876
|
function OverlayShell({
|
|
724
877
|
open,
|
|
@@ -796,6 +949,7 @@ function TaskCard({
|
|
|
796
949
|
renderLinkIcon,
|
|
797
950
|
className
|
|
798
951
|
}) {
|
|
952
|
+
const L = useTaskLabels();
|
|
799
953
|
const overdue = isOverdue(task.dueDate, task.status);
|
|
800
954
|
const due = formatDueDate(task.dueDate);
|
|
801
955
|
const resolved = task.assigneeId ? resolveAssignee?.(task.assigneeId) : null;
|
|
@@ -866,7 +1020,7 @@ function TaskCard({
|
|
|
866
1020
|
"span",
|
|
867
1021
|
{
|
|
868
1022
|
className: "flex h-5 min-w-5 items-center justify-center rounded-full bg-primary/10 px-1 text-[10px] font-semibold text-primary",
|
|
869
|
-
title: `${task.storyPoints}
|
|
1023
|
+
title: `${task.storyPoints} ${L.storyPointsLabel}`,
|
|
870
1024
|
children: task.storyPoints
|
|
871
1025
|
}
|
|
872
1026
|
)
|
|
@@ -883,7 +1037,7 @@ function TaskCard({
|
|
|
883
1037
|
"flex shrink-0 items-center gap-1 text-[11px]",
|
|
884
1038
|
overdue ? "font-medium text-destructive" : "text-muted-foreground"
|
|
885
1039
|
),
|
|
886
|
-
title: overdue ?
|
|
1040
|
+
title: overdue ? L.overdueLabel : L.dueDateLabel,
|
|
887
1041
|
children: [
|
|
888
1042
|
/* @__PURE__ */ jsx(CalendarDays, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
889
1043
|
due
|
|
@@ -938,6 +1092,7 @@ function TaskBoardCore({
|
|
|
938
1092
|
const ctx = usePlanMagnetContextSafe();
|
|
939
1093
|
const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
|
|
940
1094
|
const client = useApolloClient();
|
|
1095
|
+
const L = useTaskLabels();
|
|
941
1096
|
const hidden = useMemo(() => new Set(hiddenFields ?? []), [hiddenFields]);
|
|
942
1097
|
const { linksByItem } = useWorkItemLinks(workspaceId, linkSourceProduct);
|
|
943
1098
|
const [draggingId, setDraggingId] = useState(null);
|
|
@@ -967,10 +1122,10 @@ function TaskBoardCore({
|
|
|
967
1122
|
variables: { id: task.id, input: { status: toStatus } }
|
|
968
1123
|
}).catch(() => {
|
|
969
1124
|
client.cache.modify({ id, fields: { status: () => from2 } });
|
|
970
|
-
setMoveError(
|
|
1125
|
+
setMoveError(L.moveFailed);
|
|
971
1126
|
});
|
|
972
1127
|
},
|
|
973
|
-
[client, updateItem]
|
|
1128
|
+
[client, updateItem, L]
|
|
974
1129
|
);
|
|
975
1130
|
if (!workspaceId) {
|
|
976
1131
|
return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TaskBoard: no workspaceId provided (prop or PlanMagnetProvider)." });
|
|
@@ -980,7 +1135,8 @@ function TaskBoardCore({
|
|
|
980
1135
|
}
|
|
981
1136
|
if (error && !data) {
|
|
982
1137
|
return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
|
|
983
|
-
|
|
1138
|
+
L.errorLoading,
|
|
1139
|
+
": ",
|
|
984
1140
|
error.message
|
|
985
1141
|
] });
|
|
986
1142
|
}
|
|
@@ -1012,11 +1168,11 @@ function TaskBoardCore({
|
|
|
1012
1168
|
};
|
|
1013
1169
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
|
|
1014
1170
|
!hideHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
|
|
1015
|
-
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children:
|
|
1171
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: L.board }),
|
|
1016
1172
|
/* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
|
|
1017
1173
|
filtered.length,
|
|
1018
1174
|
" ",
|
|
1019
|
-
filtered.length === 1 ?
|
|
1175
|
+
filtered.length === 1 ? L.tasksSingular : L.tasksPlural
|
|
1020
1176
|
] })
|
|
1021
1177
|
] }),
|
|
1022
1178
|
moveError && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-1.5 text-xs text-destructive", children: moveError }),
|
|
@@ -1037,11 +1193,11 @@ function TaskBoardCore({
|
|
|
1037
1193
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2", children: [
|
|
1038
1194
|
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1039
1195
|
/* @__PURE__ */ jsx(StatusIcon, { status: col.status }),
|
|
1040
|
-
col.
|
|
1196
|
+
L.status[col.status]
|
|
1041
1197
|
] }),
|
|
1042
1198
|
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 text-xs font-medium text-muted-foreground", children: colTasks.length })
|
|
1043
1199
|
] }),
|
|
1044
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 px-2 pb-2", children: colTasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border/70 px-3 py-6 text-center text-xs text-muted-foreground", children: isOver ?
|
|
1200
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 px-2 pb-2", children: colTasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border/70 px-3 py-6 text-center text-xs text-muted-foreground", children: isOver ? L.dropHere : L.noTasks }) : colTasks.map((task) => /* @__PURE__ */ jsx(
|
|
1045
1201
|
TaskCard,
|
|
1046
1202
|
{
|
|
1047
1203
|
task,
|
|
@@ -1106,10 +1262,11 @@ var fieldClass = "w-full rounded-md border border-input bg-background px-3 py-2
|
|
|
1106
1262
|
var labelClass = "text-sm font-medium text-foreground";
|
|
1107
1263
|
function CreateTaskCore({
|
|
1108
1264
|
projectId: projectIdProp,
|
|
1265
|
+
assigneeOptions,
|
|
1109
1266
|
hiddenFields,
|
|
1110
1267
|
defaultValues,
|
|
1111
1268
|
hideHeader,
|
|
1112
|
-
submitLabel
|
|
1269
|
+
submitLabel,
|
|
1113
1270
|
onCreated,
|
|
1114
1271
|
onError: onError2,
|
|
1115
1272
|
onCancel,
|
|
@@ -1119,6 +1276,7 @@ function CreateTaskCore({
|
|
|
1119
1276
|
const ctx = usePlanMagnetContextSafe();
|
|
1120
1277
|
const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
|
|
1121
1278
|
const projectId = projectIdProp ?? defaultValues?.projectId;
|
|
1279
|
+
const L = useTaskLabels();
|
|
1122
1280
|
const hidden = useMemo(
|
|
1123
1281
|
() => new Set(hiddenFields ?? []),
|
|
1124
1282
|
[hiddenFields]
|
|
@@ -1201,12 +1359,12 @@ function CreateTaskCore({
|
|
|
1201
1359
|
}
|
|
1202
1360
|
return /* @__PURE__ */ jsx(Card, { className: cn("shadow-sm", className), children: /* @__PURE__ */ jsx(CardContent, { className: "p-6", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
1203
1361
|
!hideHeader && /* @__PURE__ */ jsxs("div", { children: [
|
|
1204
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground", children:
|
|
1205
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children:
|
|
1362
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground", children: L.newTaskHeading }),
|
|
1363
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: L.newTaskSubtitle })
|
|
1206
1364
|
] }),
|
|
1207
|
-
!projectId && /* @__PURE__ */ jsx("p", { className: "rounded-md bg-destructive/10 p-2 text-xs text-destructive", children:
|
|
1365
|
+
!projectId && /* @__PURE__ */ jsx("p", { className: "rounded-md bg-destructive/10 p-2 text-xs text-destructive", children: L.projectRequired }),
|
|
1208
1366
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1209
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-title", className: labelClass, children:
|
|
1367
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-title", className: labelClass, children: L.title }),
|
|
1210
1368
|
/* @__PURE__ */ jsx(
|
|
1211
1369
|
"input",
|
|
1212
1370
|
{
|
|
@@ -1214,13 +1372,13 @@ function CreateTaskCore({
|
|
|
1214
1372
|
className: fieldClass,
|
|
1215
1373
|
value: title,
|
|
1216
1374
|
onChange: (e) => setTitle(e.target.value),
|
|
1217
|
-
placeholder:
|
|
1375
|
+
placeholder: L.titlePlaceholder,
|
|
1218
1376
|
required: true
|
|
1219
1377
|
}
|
|
1220
1378
|
)
|
|
1221
1379
|
] }),
|
|
1222
1380
|
!hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1223
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-description", className: labelClass, children:
|
|
1381
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-description", className: labelClass, children: L.description }),
|
|
1224
1382
|
/* @__PURE__ */ jsx(
|
|
1225
1383
|
"textarea",
|
|
1226
1384
|
{
|
|
@@ -1228,13 +1386,13 @@ function CreateTaskCore({
|
|
|
1228
1386
|
className: cn(fieldClass, "min-h-[80px]"),
|
|
1229
1387
|
value: description,
|
|
1230
1388
|
onChange: (e) => setDescription(e.target.value),
|
|
1231
|
-
placeholder:
|
|
1389
|
+
placeholder: L.descriptionPlaceholder
|
|
1232
1390
|
}
|
|
1233
1391
|
)
|
|
1234
1392
|
] }),
|
|
1235
1393
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
|
|
1236
1394
|
!hidden.has("type") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1237
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-type", className: labelClass, children:
|
|
1395
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-type", className: labelClass, children: L.typeLabel }),
|
|
1238
1396
|
/* @__PURE__ */ jsx(
|
|
1239
1397
|
"select",
|
|
1240
1398
|
{
|
|
@@ -1242,12 +1400,12 @@ function CreateTaskCore({
|
|
|
1242
1400
|
className: cn(fieldClass, "capitalize"),
|
|
1243
1401
|
value: type,
|
|
1244
1402
|
onChange: (e) => setType(e.target.value),
|
|
1245
|
-
children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children:
|
|
1403
|
+
children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: L.type[t] }, t))
|
|
1246
1404
|
}
|
|
1247
1405
|
)
|
|
1248
1406
|
] }),
|
|
1249
1407
|
!hidden.has("status") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1250
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-status", className: labelClass, children:
|
|
1408
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-status", className: labelClass, children: L.statusLabel }),
|
|
1251
1409
|
/* @__PURE__ */ jsx(
|
|
1252
1410
|
"select",
|
|
1253
1411
|
{
|
|
@@ -1255,12 +1413,12 @@ function CreateTaskCore({
|
|
|
1255
1413
|
className: cn(fieldClass, "capitalize"),
|
|
1256
1414
|
value: status,
|
|
1257
1415
|
onChange: (e) => setStatus(e.target.value),
|
|
1258
|
-
children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children:
|
|
1416
|
+
children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
|
|
1259
1417
|
}
|
|
1260
1418
|
)
|
|
1261
1419
|
] }),
|
|
1262
1420
|
!hidden.has("priority") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1263
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-priority", className: labelClass, children:
|
|
1421
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-priority", className: labelClass, children: L.priorityLabel }),
|
|
1264
1422
|
/* @__PURE__ */ jsx(
|
|
1265
1423
|
"select",
|
|
1266
1424
|
{
|
|
@@ -1268,25 +1426,37 @@ function CreateTaskCore({
|
|
|
1268
1426
|
className: cn(fieldClass, "capitalize"),
|
|
1269
1427
|
value: priority,
|
|
1270
1428
|
onChange: (e) => setPriority(e.target.value),
|
|
1271
|
-
children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children:
|
|
1429
|
+
children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: L.priority[p] }, p))
|
|
1272
1430
|
}
|
|
1273
1431
|
)
|
|
1274
1432
|
] }),
|
|
1275
1433
|
!hidden.has("assignee") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1276
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-assignee", className: labelClass, children:
|
|
1277
|
-
/* @__PURE__ */
|
|
1434
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-assignee", className: labelClass, children: L.assigneeLabel }),
|
|
1435
|
+
assigneeOptions && assigneeOptions.length > 0 ? /* @__PURE__ */ jsxs(
|
|
1436
|
+
"select",
|
|
1437
|
+
{
|
|
1438
|
+
id: "pm-assignee",
|
|
1439
|
+
className: fieldClass,
|
|
1440
|
+
value: assigneeId,
|
|
1441
|
+
onChange: (e) => setAssigneeId(e.target.value),
|
|
1442
|
+
children: [
|
|
1443
|
+
/* @__PURE__ */ jsx("option", { value: "", children: L.unassigned }),
|
|
1444
|
+
assigneeOptions.map((o) => /* @__PURE__ */ jsx("option", { value: o.id, children: o.name }, o.id))
|
|
1445
|
+
]
|
|
1446
|
+
}
|
|
1447
|
+
) : /* @__PURE__ */ jsx(
|
|
1278
1448
|
"input",
|
|
1279
1449
|
{
|
|
1280
1450
|
id: "pm-assignee",
|
|
1281
1451
|
className: fieldClass,
|
|
1282
1452
|
value: assigneeId,
|
|
1283
1453
|
onChange: (e) => setAssigneeId(e.target.value),
|
|
1284
|
-
placeholder:
|
|
1454
|
+
placeholder: L.assigneePlaceholder
|
|
1285
1455
|
}
|
|
1286
1456
|
)
|
|
1287
1457
|
] }),
|
|
1288
1458
|
!hidden.has("dueDate") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1289
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-due", className: labelClass, children:
|
|
1459
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-due", className: labelClass, children: L.dueDateLabel }),
|
|
1290
1460
|
/* @__PURE__ */ jsx(
|
|
1291
1461
|
"input",
|
|
1292
1462
|
{
|
|
@@ -1299,7 +1469,7 @@ function CreateTaskCore({
|
|
|
1299
1469
|
)
|
|
1300
1470
|
] }),
|
|
1301
1471
|
!hidden.has("storyPoints") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1302
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-points", className: labelClass, children:
|
|
1472
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-points", className: labelClass, children: L.storyPointsLabel }),
|
|
1303
1473
|
/* @__PURE__ */ jsx(
|
|
1304
1474
|
"input",
|
|
1305
1475
|
{
|
|
@@ -1315,7 +1485,7 @@ function CreateTaskCore({
|
|
|
1315
1485
|
] })
|
|
1316
1486
|
] }),
|
|
1317
1487
|
!hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1318
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-labels", className: labelClass, children:
|
|
1488
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-labels", className: labelClass, children: L.labelsLabel }),
|
|
1319
1489
|
/* @__PURE__ */ jsx(
|
|
1320
1490
|
"input",
|
|
1321
1491
|
{
|
|
@@ -1323,12 +1493,13 @@ function CreateTaskCore({
|
|
|
1323
1493
|
className: fieldClass,
|
|
1324
1494
|
value: labels,
|
|
1325
1495
|
onChange: (e) => setLabels(e.target.value),
|
|
1326
|
-
placeholder:
|
|
1496
|
+
placeholder: L.labelsPlaceholder
|
|
1327
1497
|
}
|
|
1328
1498
|
)
|
|
1329
1499
|
] }),
|
|
1330
1500
|
error && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
|
|
1331
|
-
|
|
1501
|
+
L.failedToCreate,
|
|
1502
|
+
": ",
|
|
1332
1503
|
error.message
|
|
1333
1504
|
] }),
|
|
1334
1505
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
@@ -1338,7 +1509,7 @@ function CreateTaskCore({
|
|
|
1338
1509
|
type: "button",
|
|
1339
1510
|
onClick: onCancel,
|
|
1340
1511
|
className: "rounded-md bg-muted px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted/70",
|
|
1341
|
-
children:
|
|
1512
|
+
children: L.cancel
|
|
1342
1513
|
}
|
|
1343
1514
|
),
|
|
1344
1515
|
/* @__PURE__ */ jsx(
|
|
@@ -1350,7 +1521,7 @@ function CreateTaskCore({
|
|
|
1350
1521
|
"rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
|
|
1351
1522
|
(!canSubmit || loading) && "cursor-not-allowed opacity-50"
|
|
1352
1523
|
),
|
|
1353
|
-
children: loading ?
|
|
1524
|
+
children: loading ? L.creating : submitLabel ?? L.create
|
|
1354
1525
|
}
|
|
1355
1526
|
)
|
|
1356
1527
|
] })
|
|
@@ -1408,18 +1579,32 @@ var statusRank = {
|
|
|
1408
1579
|
DONE: 5,
|
|
1409
1580
|
CANCELLED: 6
|
|
1410
1581
|
};
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1582
|
+
function columnLabel(col, L) {
|
|
1583
|
+
switch (col) {
|
|
1584
|
+
case "key":
|
|
1585
|
+
return L.colKey;
|
|
1586
|
+
case "title":
|
|
1587
|
+
return L.colTask;
|
|
1588
|
+
case "type":
|
|
1589
|
+
return L.colType;
|
|
1590
|
+
case "status":
|
|
1591
|
+
return L.colStatus;
|
|
1592
|
+
case "priority":
|
|
1593
|
+
return L.colPriority;
|
|
1594
|
+
case "assignee":
|
|
1595
|
+
return L.colAssignee;
|
|
1596
|
+
case "dueDate":
|
|
1597
|
+
return L.colDueDate;
|
|
1598
|
+
case "storyPoints":
|
|
1599
|
+
return L.colPoints;
|
|
1600
|
+
case "linkedRecord":
|
|
1601
|
+
return L.colLinkedRecord;
|
|
1602
|
+
case "labels":
|
|
1603
|
+
return L.colLabels;
|
|
1604
|
+
default:
|
|
1605
|
+
return col;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1423
1608
|
var COLUMN_SORT = {
|
|
1424
1609
|
title: "title",
|
|
1425
1610
|
type: "type",
|
|
@@ -1450,6 +1635,7 @@ function TaskListCore({
|
|
|
1450
1635
|
const ctx = usePlanMagnetContextSafe();
|
|
1451
1636
|
const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
|
|
1452
1637
|
const { linksByItem } = useWorkItemLinks(workspaceId, linkSourceProduct);
|
|
1638
|
+
const L = useTaskLabels();
|
|
1453
1639
|
const [sort, setSort] = useState({
|
|
1454
1640
|
by: sortBy ?? null,
|
|
1455
1641
|
dir: sortDir
|
|
@@ -1497,17 +1683,18 @@ function TaskListCore({
|
|
|
1497
1683
|
}
|
|
1498
1684
|
if (error && !data) {
|
|
1499
1685
|
return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
|
|
1500
|
-
|
|
1686
|
+
L.errorLoading,
|
|
1687
|
+
": ",
|
|
1501
1688
|
error.message
|
|
1502
1689
|
] });
|
|
1503
1690
|
}
|
|
1504
1691
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
|
|
1505
1692
|
!hideHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
|
|
1506
|
-
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children:
|
|
1693
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: L.list }),
|
|
1507
1694
|
/* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
|
|
1508
1695
|
rows.length,
|
|
1509
1696
|
" ",
|
|
1510
|
-
rows.length === 1 ?
|
|
1697
|
+
rows.length === 1 ? L.tasksSingular : L.tasksPlural
|
|
1511
1698
|
] })
|
|
1512
1699
|
] }),
|
|
1513
1700
|
/* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border border-border", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-sm", children: [
|
|
@@ -1523,7 +1710,7 @@ function TaskListCore({
|
|
|
1523
1710
|
sortable && "cursor-pointer select-none hover:text-foreground"
|
|
1524
1711
|
),
|
|
1525
1712
|
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1526
|
-
|
|
1713
|
+
columnLabel(col, L),
|
|
1527
1714
|
active && (sort.dir === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3 w-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3", "aria-hidden": "true" }))
|
|
1528
1715
|
] })
|
|
1529
1716
|
},
|
|
@@ -1536,7 +1723,7 @@ function TaskListCore({
|
|
|
1536
1723
|
{
|
|
1537
1724
|
colSpan: columns.length,
|
|
1538
1725
|
className: "px-3 py-8 text-center text-muted-foreground",
|
|
1539
|
-
children:
|
|
1726
|
+
children: L.noTasksFound
|
|
1540
1727
|
}
|
|
1541
1728
|
) }),
|
|
1542
1729
|
rows.map((task) => /* @__PURE__ */ jsx(
|
|
@@ -1554,7 +1741,8 @@ function TaskListCore({
|
|
|
1554
1741
|
children: renderCell(col, task, {
|
|
1555
1742
|
resolveAssignee,
|
|
1556
1743
|
links: linksByItem.get(task.id),
|
|
1557
|
-
renderLinkIcon
|
|
1744
|
+
renderLinkIcon,
|
|
1745
|
+
unassigned: L.unassigned
|
|
1558
1746
|
})
|
|
1559
1747
|
},
|
|
1560
1748
|
col
|
|
@@ -1567,7 +1755,7 @@ function TaskListCore({
|
|
|
1567
1755
|
] });
|
|
1568
1756
|
}
|
|
1569
1757
|
function renderCell(col, task, opts) {
|
|
1570
|
-
const { resolveAssignee, links, renderLinkIcon } = opts;
|
|
1758
|
+
const { resolveAssignee, links, renderLinkIcon, unassigned } = opts;
|
|
1571
1759
|
switch (col) {
|
|
1572
1760
|
case "key":
|
|
1573
1761
|
return /* @__PURE__ */ jsx("span", { className: "font-mono text-xs text-muted-foreground", children: task.key });
|
|
@@ -1586,7 +1774,7 @@ function renderCell(col, task, opts) {
|
|
|
1586
1774
|
const resolved = task.assigneeId ? resolveAssignee?.(task.assigneeId) : null;
|
|
1587
1775
|
return /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
1588
1776
|
/* @__PURE__ */ jsx(Avatar, { id: task.assigneeId, name: resolved?.name, size: "sm" }),
|
|
1589
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: resolved?.name ?? (task.assigneeId ? "" :
|
|
1777
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: resolved?.name ?? (task.assigneeId ? "" : unassigned) })
|
|
1590
1778
|
] });
|
|
1591
1779
|
}
|
|
1592
1780
|
case "dueDate": {
|
|
@@ -1675,6 +1863,35 @@ function TaskList({
|
|
|
1675
1863
|
}
|
|
1676
1864
|
);
|
|
1677
1865
|
}
|
|
1866
|
+
function useMilestones(workspaceId, opts = {}) {
|
|
1867
|
+
const { projectId, enabled = true, limit = 100 } = opts;
|
|
1868
|
+
const { data, loading } = useQuery(LIST_MILESTONES, {
|
|
1869
|
+
variables: {
|
|
1870
|
+
workspaceId,
|
|
1871
|
+
...projectId ? { filter: { projectId } } : {},
|
|
1872
|
+
pagination: { first: limit }
|
|
1873
|
+
},
|
|
1874
|
+
skip: !workspaceId || !enabled,
|
|
1875
|
+
errorPolicy: "all"
|
|
1876
|
+
});
|
|
1877
|
+
const milestones = useMemo(
|
|
1878
|
+
() => data?.planmagnetMilestones?.items ?? [],
|
|
1879
|
+
[data]
|
|
1880
|
+
);
|
|
1881
|
+
const byDay = useMemo(() => {
|
|
1882
|
+
const map = /* @__PURE__ */ new Map();
|
|
1883
|
+
for (const m of milestones) {
|
|
1884
|
+
const d = parseDate(m.dueDate);
|
|
1885
|
+
if (!d) continue;
|
|
1886
|
+
const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
1887
|
+
const arr = map.get(key);
|
|
1888
|
+
if (arr) arr.push(m);
|
|
1889
|
+
else map.set(key, [m]);
|
|
1890
|
+
}
|
|
1891
|
+
return map;
|
|
1892
|
+
}, [milestones]);
|
|
1893
|
+
return { milestones, byDay, loading };
|
|
1894
|
+
}
|
|
1678
1895
|
var WEEK_OPTS = { weekStartsOn: 1 };
|
|
1679
1896
|
function dayKey(d) {
|
|
1680
1897
|
return format(d, "yyyy-MM-dd");
|
|
@@ -1688,11 +1905,17 @@ function TaskTimelineCore({
|
|
|
1688
1905
|
defaultMode = "week",
|
|
1689
1906
|
onSelect,
|
|
1690
1907
|
resolveAssignee,
|
|
1908
|
+
showMilestones = true,
|
|
1691
1909
|
className,
|
|
1692
1910
|
workspaceId: workspaceIdProp
|
|
1693
1911
|
}) {
|
|
1694
1912
|
const ctx = usePlanMagnetContextSafe();
|
|
1695
1913
|
const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
|
|
1914
|
+
const L = useTaskLabels();
|
|
1915
|
+
const { milestones, byDay: milestonesByDay } = useMilestones(workspaceId, {
|
|
1916
|
+
projectId,
|
|
1917
|
+
enabled: showMilestones
|
|
1918
|
+
});
|
|
1696
1919
|
const [mode, setMode] = useState(defaultMode);
|
|
1697
1920
|
const [offset, setOffset] = useState(0);
|
|
1698
1921
|
const { data, loading, error } = useQuery(
|
|
@@ -1772,7 +1995,8 @@ function TaskTimelineCore({
|
|
|
1772
1995
|
}
|
|
1773
1996
|
if (error && !data) {
|
|
1774
1997
|
return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
|
|
1775
|
-
|
|
1998
|
+
L.errorLoading,
|
|
1999
|
+
": ",
|
|
1776
2000
|
error.message
|
|
1777
2001
|
] });
|
|
1778
2002
|
}
|
|
@@ -1796,7 +2020,7 @@ function TaskTimelineCore({
|
|
|
1796
2020
|
type: "button",
|
|
1797
2021
|
onClick: () => setOffset(0),
|
|
1798
2022
|
className: "h-8 rounded-md border border-border px-3 text-xs font-medium text-foreground hover:bg-muted/50",
|
|
1799
|
-
children:
|
|
2023
|
+
children: L.today
|
|
1800
2024
|
}
|
|
1801
2025
|
),
|
|
1802
2026
|
/* @__PURE__ */ jsx(
|
|
@@ -1823,16 +2047,13 @@ function TaskTimelineCore({
|
|
|
1823
2047
|
"rounded px-3 py-1 text-xs font-medium capitalize transition-colors",
|
|
1824
2048
|
mode === m ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"
|
|
1825
2049
|
),
|
|
1826
|
-
children: m
|
|
2050
|
+
children: m === "week" ? L.week : L.month
|
|
1827
2051
|
},
|
|
1828
2052
|
m
|
|
1829
2053
|
)) })
|
|
1830
2054
|
] }),
|
|
1831
2055
|
overdue.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2", children: [
|
|
1832
|
-
/* @__PURE__ */
|
|
1833
|
-
overdue.length,
|
|
1834
|
-
" overdue"
|
|
1835
|
-
] }),
|
|
2056
|
+
/* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-semibold text-destructive", children: L.overdue.replace("{n}", String(overdue.length)) }),
|
|
1836
2057
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: overdue.map((t) => /* @__PURE__ */ jsx(
|
|
1837
2058
|
TaskChip,
|
|
1838
2059
|
{
|
|
@@ -1844,8 +2065,16 @@ function TaskTimelineCore({
|
|
|
1844
2065
|
t.id
|
|
1845
2066
|
)) })
|
|
1846
2067
|
] }),
|
|
2068
|
+
milestones.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-primary/30 bg-primary/5 px-3 py-2", children: [
|
|
2069
|
+
/* @__PURE__ */ jsxs("p", { className: "mb-1 flex items-center gap-1 text-xs font-semibold text-primary", children: [
|
|
2070
|
+
/* @__PURE__ */ jsx(Flag, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2071
|
+
L.milestones
|
|
2072
|
+
] }),
|
|
2073
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: milestones.map((m) => /* @__PURE__ */ jsx(MilestoneFlag, { milestone: m }, m.id)) })
|
|
2074
|
+
] }),
|
|
1847
2075
|
mode === "week" ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-2", children: days.map((day) => {
|
|
1848
2076
|
const items = byDay.get(dayKey(day)) ?? [];
|
|
2077
|
+
const dayMilestones = milestonesByDay.get(dayKey(day)) ?? [];
|
|
1849
2078
|
const today = isToday(day);
|
|
1850
2079
|
return /* @__PURE__ */ jsxs(
|
|
1851
2080
|
"div",
|
|
@@ -1877,15 +2106,18 @@ function TaskTimelineCore({
|
|
|
1877
2106
|
}
|
|
1878
2107
|
)
|
|
1879
2108
|
] }),
|
|
1880
|
-
/* @__PURE__ */
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2109
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
2110
|
+
dayMilestones.map((m) => /* @__PURE__ */ jsx(MilestoneFlag, { milestone: m, compact: true }, m.id)),
|
|
2111
|
+
items.map((t) => /* @__PURE__ */ jsx(
|
|
2112
|
+
TaskChip,
|
|
2113
|
+
{
|
|
2114
|
+
task: t,
|
|
2115
|
+
onSelect,
|
|
2116
|
+
resolveAssignee
|
|
2117
|
+
},
|
|
2118
|
+
t.id
|
|
2119
|
+
))
|
|
2120
|
+
] })
|
|
1889
2121
|
]
|
|
1890
2122
|
},
|
|
1891
2123
|
dayKey(day)
|
|
@@ -1935,7 +2167,8 @@ function TaskTimelineCore({
|
|
|
1935
2167
|
items.length > 3 && /* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
1936
2168
|
"+",
|
|
1937
2169
|
items.length - 3,
|
|
1938
|
-
"
|
|
2170
|
+
" ",
|
|
2171
|
+
L.more
|
|
1939
2172
|
] })
|
|
1940
2173
|
]
|
|
1941
2174
|
},
|
|
@@ -1944,11 +2177,7 @@ function TaskTimelineCore({
|
|
|
1944
2177
|
})
|
|
1945
2178
|
] }),
|
|
1946
2179
|
undated.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-muted/20 px-3 py-2", children: [
|
|
1947
|
-
/* @__PURE__ */
|
|
1948
|
-
"No due date (",
|
|
1949
|
-
undated.length,
|
|
1950
|
-
")"
|
|
1951
|
-
] }),
|
|
2180
|
+
/* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-semibold text-muted-foreground", children: L.noDueDate.replace("{n}", String(undated.length)) }),
|
|
1952
2181
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: undated.map((t) => /* @__PURE__ */ jsx(
|
|
1953
2182
|
TaskChip,
|
|
1954
2183
|
{
|
|
@@ -1961,6 +2190,30 @@ function TaskTimelineCore({
|
|
|
1961
2190
|
] })
|
|
1962
2191
|
] });
|
|
1963
2192
|
}
|
|
2193
|
+
function MilestoneFlag({
|
|
2194
|
+
milestone,
|
|
2195
|
+
compact
|
|
2196
|
+
}) {
|
|
2197
|
+
const due = formatDueDate(milestone.dueDate);
|
|
2198
|
+
return /* @__PURE__ */ jsxs(
|
|
2199
|
+
"span",
|
|
2200
|
+
{
|
|
2201
|
+
className: cn(
|
|
2202
|
+
"inline-flex max-w-full items-center gap-1 rounded-md border border-primary/40 bg-primary/10 px-1.5 py-1 text-[11px] font-medium text-primary",
|
|
2203
|
+
compact && "w-full"
|
|
2204
|
+
),
|
|
2205
|
+
title: milestone.name + (due ? ` \xB7 ${due}` : ""),
|
|
2206
|
+
children: [
|
|
2207
|
+
/* @__PURE__ */ jsx(Flag, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }),
|
|
2208
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: milestone.name }),
|
|
2209
|
+
!compact && due && /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-primary/70", children: [
|
|
2210
|
+
"\xB7 ",
|
|
2211
|
+
due
|
|
2212
|
+
] })
|
|
2213
|
+
]
|
|
2214
|
+
}
|
|
2215
|
+
);
|
|
2216
|
+
}
|
|
1964
2217
|
function TaskChip({
|
|
1965
2218
|
task,
|
|
1966
2219
|
onSelect,
|
|
@@ -1990,10 +2243,10 @@ function TaskChip({
|
|
|
1990
2243
|
}
|
|
1991
2244
|
);
|
|
1992
2245
|
}
|
|
1993
|
-
var
|
|
1994
|
-
board:
|
|
1995
|
-
list:
|
|
1996
|
-
timeline:
|
|
2246
|
+
var VIEW_ICONS = {
|
|
2247
|
+
board: LayoutGrid,
|
|
2248
|
+
list: List,
|
|
2249
|
+
timeline: CalendarRange
|
|
1997
2250
|
};
|
|
1998
2251
|
var SELECT_CLASS = "h-8 rounded-md border border-border bg-background px-2 text-xs font-medium text-foreground capitalize transition-colors hover:bg-muted/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
1999
2252
|
function TaskToolbar({
|
|
@@ -2008,8 +2261,16 @@ function TaskToolbar({
|
|
|
2008
2261
|
onTypeChange,
|
|
2009
2262
|
onNewTask,
|
|
2010
2263
|
canCreate,
|
|
2264
|
+
mine,
|
|
2265
|
+
onMineChange,
|
|
2011
2266
|
className
|
|
2012
2267
|
}) {
|
|
2268
|
+
const L = useTaskLabels();
|
|
2269
|
+
const viewLabel = {
|
|
2270
|
+
board: L.board,
|
|
2271
|
+
list: L.list,
|
|
2272
|
+
timeline: L.timeline
|
|
2273
|
+
};
|
|
2013
2274
|
return /* @__PURE__ */ jsxs(
|
|
2014
2275
|
"div",
|
|
2015
2276
|
{
|
|
@@ -2025,8 +2286,7 @@ function TaskToolbar({
|
|
|
2025
2286
|
role: "tablist",
|
|
2026
2287
|
"aria-label": "Task views",
|
|
2027
2288
|
children: views.map((v) => {
|
|
2028
|
-
const
|
|
2029
|
-
const Icon = meta.icon;
|
|
2289
|
+
const Icon = VIEW_ICONS[v];
|
|
2030
2290
|
const active = v === view;
|
|
2031
2291
|
return /* @__PURE__ */ jsxs(
|
|
2032
2292
|
"button",
|
|
@@ -2041,7 +2301,7 @@ function TaskToolbar({
|
|
|
2041
2301
|
),
|
|
2042
2302
|
children: [
|
|
2043
2303
|
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2044
|
-
|
|
2304
|
+
viewLabel[v],
|
|
2045
2305
|
active && /* @__PURE__ */ jsx("span", { className: "absolute inset-x-1 -bottom-[9px] h-0.5 rounded-full bg-primary" })
|
|
2046
2306
|
]
|
|
2047
2307
|
},
|
|
@@ -2065,22 +2325,38 @@ function TaskToolbar({
|
|
|
2065
2325
|
type: "search",
|
|
2066
2326
|
value: search,
|
|
2067
2327
|
onChange: (e) => onSearchChange(e.target.value),
|
|
2068
|
-
placeholder:
|
|
2069
|
-
"aria-label":
|
|
2328
|
+
placeholder: L.searchPlaceholder,
|
|
2329
|
+
"aria-label": L.searchPlaceholder,
|
|
2070
2330
|
className: "h-8 w-40 rounded-md border border-border bg-background pl-7 pr-2 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
2071
2331
|
}
|
|
2072
2332
|
)
|
|
2073
2333
|
] }),
|
|
2334
|
+
onMineChange && /* @__PURE__ */ jsxs(
|
|
2335
|
+
"button",
|
|
2336
|
+
{
|
|
2337
|
+
type: "button",
|
|
2338
|
+
onClick: () => onMineChange(!mine),
|
|
2339
|
+
"aria-pressed": mine,
|
|
2340
|
+
className: cn(
|
|
2341
|
+
"flex h-8 items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium transition-colors",
|
|
2342
|
+
mine ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-muted-foreground hover:bg-muted/50 hover:text-foreground"
|
|
2343
|
+
),
|
|
2344
|
+
children: [
|
|
2345
|
+
/* @__PURE__ */ jsx(User, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2346
|
+
L.myTasks
|
|
2347
|
+
]
|
|
2348
|
+
}
|
|
2349
|
+
),
|
|
2074
2350
|
/* @__PURE__ */ jsxs(
|
|
2075
2351
|
"select",
|
|
2076
2352
|
{
|
|
2077
2353
|
value: priority,
|
|
2078
2354
|
onChange: (e) => onPriorityChange(e.target.value),
|
|
2079
|
-
"aria-label":
|
|
2355
|
+
"aria-label": L.priorityLabel,
|
|
2080
2356
|
className: SELECT_CLASS,
|
|
2081
2357
|
children: [
|
|
2082
|
-
/* @__PURE__ */ jsx("option", { value: "ALL", children:
|
|
2083
|
-
TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children:
|
|
2358
|
+
/* @__PURE__ */ jsx("option", { value: "ALL", children: L.allPriorities }),
|
|
2359
|
+
TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: L.priority[p] }, p))
|
|
2084
2360
|
]
|
|
2085
2361
|
}
|
|
2086
2362
|
),
|
|
@@ -2089,11 +2365,11 @@ function TaskToolbar({
|
|
|
2089
2365
|
{
|
|
2090
2366
|
value: type,
|
|
2091
2367
|
onChange: (e) => onTypeChange(e.target.value),
|
|
2092
|
-
"aria-label":
|
|
2368
|
+
"aria-label": L.typeLabel,
|
|
2093
2369
|
className: SELECT_CLASS,
|
|
2094
2370
|
children: [
|
|
2095
|
-
/* @__PURE__ */ jsx("option", { value: "ALL", children:
|
|
2096
|
-
TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children:
|
|
2371
|
+
/* @__PURE__ */ jsx("option", { value: "ALL", children: L.allTypes }),
|
|
2372
|
+
TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: L.type[t] }, t))
|
|
2097
2373
|
]
|
|
2098
2374
|
}
|
|
2099
2375
|
),
|
|
@@ -2105,7 +2381,7 @@ function TaskToolbar({
|
|
|
2105
2381
|
className: "flex h-8 items-center gap-1.5 rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90",
|
|
2106
2382
|
children: [
|
|
2107
2383
|
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2108
|
-
|
|
2384
|
+
L.newTask
|
|
2109
2385
|
]
|
|
2110
2386
|
}
|
|
2111
2387
|
)
|
|
@@ -2129,9 +2405,14 @@ function TaskDetailCore({
|
|
|
2129
2405
|
hiddenFields,
|
|
2130
2406
|
hideHeader,
|
|
2131
2407
|
onUpdated,
|
|
2408
|
+
onDeleted,
|
|
2132
2409
|
onError: onError2,
|
|
2410
|
+
resolveAssignee,
|
|
2411
|
+
assigneeOptions,
|
|
2133
2412
|
className
|
|
2134
2413
|
}) {
|
|
2414
|
+
const client = useApolloClient();
|
|
2415
|
+
const L = useTaskLabels();
|
|
2135
2416
|
const hidden = useMemo(
|
|
2136
2417
|
() => new Set(hiddenFields ?? []),
|
|
2137
2418
|
[hiddenFields]
|
|
@@ -2142,6 +2423,7 @@ function TaskDetailCore({
|
|
|
2142
2423
|
});
|
|
2143
2424
|
const item = data?.planmagnetWorkItem ?? null;
|
|
2144
2425
|
const [editing, setEditing] = useState(false);
|
|
2426
|
+
const [confirmingDelete, setConfirmingDelete] = useState(false);
|
|
2145
2427
|
const [title, setTitle] = useState("");
|
|
2146
2428
|
const [description, setDescription] = useState("");
|
|
2147
2429
|
const [type, setType] = useState("TASK");
|
|
@@ -2164,6 +2446,22 @@ function TaskDetailCore({
|
|
|
2164
2446
|
setStoryPoints(item.storyPoints != null ? String(item.storyPoints) : "");
|
|
2165
2447
|
}, [item]);
|
|
2166
2448
|
const [updateWorkItem, { loading: saving, error: saveError }] = useMutation(UPDATE_WORK_ITEM);
|
|
2449
|
+
const [deleteWorkItem, { loading: deleting, error: deleteError }] = useMutation(DELETE_WORK_ITEM);
|
|
2450
|
+
const handleDelete = async () => {
|
|
2451
|
+
if (!item) return;
|
|
2452
|
+
try {
|
|
2453
|
+
await deleteWorkItem({ variables: { id: item.id } });
|
|
2454
|
+
client.cache.evict({
|
|
2455
|
+
id: client.cache.identify({ __typename: "WorkItem", id: item.id })
|
|
2456
|
+
});
|
|
2457
|
+
client.cache.gc();
|
|
2458
|
+
void client.refetchQueries({ include: [LIST_WORK_ITEMS] }).catch(() => {
|
|
2459
|
+
});
|
|
2460
|
+
onDeleted?.(item.id);
|
|
2461
|
+
} catch (err) {
|
|
2462
|
+
onError2?.(err instanceof Error ? err : new Error(String(err)));
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2167
2465
|
const handleSave = async (e) => {
|
|
2168
2466
|
e.preventDefault();
|
|
2169
2467
|
if (!item) return;
|
|
@@ -2212,12 +2510,13 @@ function TaskDetailCore({
|
|
|
2212
2510
|
}
|
|
2213
2511
|
if (error && !data) {
|
|
2214
2512
|
return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
|
|
2215
|
-
|
|
2513
|
+
L.errorLoading,
|
|
2514
|
+
": ",
|
|
2216
2515
|
error.message
|
|
2217
2516
|
] });
|
|
2218
2517
|
}
|
|
2219
2518
|
if (!item) {
|
|
2220
|
-
return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-muted-foreground", className), children:
|
|
2519
|
+
return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-muted-foreground", className), children: L.taskNotFound });
|
|
2221
2520
|
}
|
|
2222
2521
|
const canEdit = !readonly;
|
|
2223
2522
|
return /* @__PURE__ */ jsx(Card, { className: cn("shadow-sm", className), children: /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4 p-6", children: [
|
|
@@ -2226,29 +2525,78 @@ function TaskDetailCore({
|
|
|
2226
2525
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: item.key }),
|
|
2227
2526
|
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground", children: item.title })
|
|
2228
2527
|
] }),
|
|
2229
|
-
canEdit && !editing && /* @__PURE__ */
|
|
2230
|
-
"
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2528
|
+
canEdit && !editing && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
2529
|
+
onDeleted && (confirmingDelete ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs", children: [
|
|
2530
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: L.deletePrompt }),
|
|
2531
|
+
/* @__PURE__ */ jsx(
|
|
2532
|
+
"button",
|
|
2533
|
+
{
|
|
2534
|
+
type: "button",
|
|
2535
|
+
disabled: deleting,
|
|
2536
|
+
onClick: handleDelete,
|
|
2537
|
+
className: "rounded bg-destructive px-2 py-1 font-medium text-destructive-foreground disabled:opacity-50",
|
|
2538
|
+
children: deleting ? "\u2026" : L.yes
|
|
2539
|
+
}
|
|
2540
|
+
),
|
|
2541
|
+
/* @__PURE__ */ jsx(
|
|
2542
|
+
"button",
|
|
2543
|
+
{
|
|
2544
|
+
type: "button",
|
|
2545
|
+
onClick: () => setConfirmingDelete(false),
|
|
2546
|
+
className: "rounded bg-muted px-2 py-1 text-muted-foreground",
|
|
2547
|
+
children: L.no
|
|
2548
|
+
}
|
|
2549
|
+
)
|
|
2550
|
+
] }) : /* @__PURE__ */ jsx(
|
|
2551
|
+
"button",
|
|
2552
|
+
{
|
|
2553
|
+
type: "button",
|
|
2554
|
+
onClick: () => setConfirmingDelete(true),
|
|
2555
|
+
title: L.del,
|
|
2556
|
+
"aria-label": L.del,
|
|
2557
|
+
className: "rounded-md p-1.5 text-destructive hover:bg-destructive/10",
|
|
2558
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
|
|
2559
|
+
}
|
|
2560
|
+
)),
|
|
2561
|
+
/* @__PURE__ */ jsx(
|
|
2562
|
+
"button",
|
|
2563
|
+
{
|
|
2564
|
+
type: "button",
|
|
2565
|
+
onClick: () => setEditing(true),
|
|
2566
|
+
className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground",
|
|
2567
|
+
children: L.edit
|
|
2568
|
+
}
|
|
2569
|
+
)
|
|
2570
|
+
] })
|
|
2571
|
+
] }),
|
|
2572
|
+
deleteError && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
|
|
2573
|
+
L.failedToDelete,
|
|
2574
|
+
": ",
|
|
2575
|
+
deleteError.message
|
|
2238
2576
|
] }),
|
|
2239
2577
|
!editing ? /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
|
|
2240
|
-
!hidden.has("type") && /* @__PURE__ */ jsx(Field, { label:
|
|
2241
|
-
!hidden.has("status") && /* @__PURE__ */ jsx(Field, { label:
|
|
2242
|
-
!hidden.has("priority") && /* @__PURE__ */ jsx(Field, { label:
|
|
2243
|
-
!hidden.has("assignee") && /* @__PURE__ */ jsx(Field, { label:
|
|
2244
|
-
|
|
2245
|
-
|
|
2578
|
+
!hidden.has("type") && /* @__PURE__ */ jsx(Field, { label: L.typeLabel, children: /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: L.type[item.type] }) }),
|
|
2579
|
+
!hidden.has("status") && /* @__PURE__ */ jsx(Field, { label: L.statusLabel, children: /* @__PURE__ */ jsx("span", { className: "capitalize text-foreground", children: L.status[item.status] }) }),
|
|
2580
|
+
!hidden.has("priority") && /* @__PURE__ */ jsx(Field, { label: L.priorityLabel, children: /* @__PURE__ */ jsx(Badge, { variant: priorityVariant[item.priority], children: L.priority[item.priority] }) }),
|
|
2581
|
+
!hidden.has("assignee") && /* @__PURE__ */ jsx(Field, { label: L.assigneeLabel, children: item.assigneeId ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
2582
|
+
/* @__PURE__ */ jsx(
|
|
2583
|
+
Avatar,
|
|
2584
|
+
{
|
|
2585
|
+
id: item.assigneeId,
|
|
2586
|
+
name: resolveAssignee?.(item.assigneeId)?.name,
|
|
2587
|
+
size: "sm"
|
|
2588
|
+
}
|
|
2589
|
+
),
|
|
2590
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground", children: resolveAssignee?.(item.assigneeId)?.name ?? L.assigned })
|
|
2591
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: L.unassigned }) }),
|
|
2592
|
+
!hidden.has("dueDate") && /* @__PURE__ */ jsx(Field, { label: L.dueDateLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.dueDate ?? "\u2014" }) }),
|
|
2593
|
+
!hidden.has("storyPoints") && /* @__PURE__ */ jsx(Field, { label: L.storyPointsLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.storyPoints ?? 0 }) }),
|
|
2246
2594
|
!hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
|
|
2247
|
-
/* @__PURE__ */ jsx("dt", { className: labelClass2, children:
|
|
2595
|
+
/* @__PURE__ */ jsx("dt", { className: labelClass2, children: L.description }),
|
|
2248
2596
|
/* @__PURE__ */ jsx("dd", { className: "mt-1 whitespace-pre-wrap text-sm text-foreground", children: item.description || "\u2014" })
|
|
2249
2597
|
] }),
|
|
2250
2598
|
!hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
|
|
2251
|
-
/* @__PURE__ */ jsx("dt", { className: labelClass2, children:
|
|
2599
|
+
/* @__PURE__ */ jsx("dt", { className: labelClass2, children: L.labelsLabel }),
|
|
2252
2600
|
/* @__PURE__ */ jsx("dd", { className: "mt-1 flex flex-wrap gap-1", children: (item.labels ?? []).length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "\u2014" }) : item.labels.map((l) => /* @__PURE__ */ jsx(
|
|
2253
2601
|
"span",
|
|
2254
2602
|
{
|
|
@@ -2260,7 +2608,7 @@ function TaskDetailCore({
|
|
|
2260
2608
|
] })
|
|
2261
2609
|
] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSave, className: "space-y-4", children: [
|
|
2262
2610
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2263
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-title", className: labelClass2, children:
|
|
2611
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-title", className: labelClass2, children: L.title }),
|
|
2264
2612
|
/* @__PURE__ */ jsx(
|
|
2265
2613
|
"input",
|
|
2266
2614
|
{
|
|
@@ -2273,7 +2621,7 @@ function TaskDetailCore({
|
|
|
2273
2621
|
)
|
|
2274
2622
|
] }),
|
|
2275
2623
|
!hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2276
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-desc", className: labelClass2, children:
|
|
2624
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-desc", className: labelClass2, children: L.description }),
|
|
2277
2625
|
/* @__PURE__ */ jsx(
|
|
2278
2626
|
"textarea",
|
|
2279
2627
|
{
|
|
@@ -2286,7 +2634,7 @@ function TaskDetailCore({
|
|
|
2286
2634
|
] }),
|
|
2287
2635
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
|
|
2288
2636
|
!hidden.has("type") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2289
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-type", className: labelClass2, children:
|
|
2637
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-type", className: labelClass2, children: L.typeLabel }),
|
|
2290
2638
|
/* @__PURE__ */ jsx(
|
|
2291
2639
|
"select",
|
|
2292
2640
|
{
|
|
@@ -2294,12 +2642,12 @@ function TaskDetailCore({
|
|
|
2294
2642
|
className: cn(fieldClass2, "capitalize"),
|
|
2295
2643
|
value: type,
|
|
2296
2644
|
onChange: (e) => setType(e.target.value),
|
|
2297
|
-
children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children:
|
|
2645
|
+
children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: L.type[t] }, t))
|
|
2298
2646
|
}
|
|
2299
2647
|
)
|
|
2300
2648
|
] }),
|
|
2301
2649
|
!hidden.has("status") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2302
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-status", className: labelClass2, children:
|
|
2650
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-status", className: labelClass2, children: L.statusLabel }),
|
|
2303
2651
|
/* @__PURE__ */ jsx(
|
|
2304
2652
|
"select",
|
|
2305
2653
|
{
|
|
@@ -2307,12 +2655,12 @@ function TaskDetailCore({
|
|
|
2307
2655
|
className: cn(fieldClass2, "capitalize"),
|
|
2308
2656
|
value: status,
|
|
2309
2657
|
onChange: (e) => setStatus(e.target.value),
|
|
2310
|
-
children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children:
|
|
2658
|
+
children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
|
|
2311
2659
|
}
|
|
2312
2660
|
)
|
|
2313
2661
|
] }),
|
|
2314
2662
|
!hidden.has("priority") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2315
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-priority", className: labelClass2, children:
|
|
2663
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-priority", className: labelClass2, children: L.priorityLabel }),
|
|
2316
2664
|
/* @__PURE__ */ jsx(
|
|
2317
2665
|
"select",
|
|
2318
2666
|
{
|
|
@@ -2320,25 +2668,37 @@ function TaskDetailCore({
|
|
|
2320
2668
|
className: cn(fieldClass2, "capitalize"),
|
|
2321
2669
|
value: priority,
|
|
2322
2670
|
onChange: (e) => setPriority(e.target.value),
|
|
2323
|
-
children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children:
|
|
2671
|
+
children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: L.priority[p] }, p))
|
|
2324
2672
|
}
|
|
2325
2673
|
)
|
|
2326
2674
|
] }),
|
|
2327
2675
|
!hidden.has("assignee") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2328
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-assignee", className: labelClass2, children:
|
|
2329
|
-
/* @__PURE__ */
|
|
2676
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-assignee", className: labelClass2, children: L.assigneeLabel }),
|
|
2677
|
+
assigneeOptions && assigneeOptions.length > 0 ? /* @__PURE__ */ jsxs(
|
|
2678
|
+
"select",
|
|
2679
|
+
{
|
|
2680
|
+
id: "pm-detail-assignee",
|
|
2681
|
+
className: fieldClass2,
|
|
2682
|
+
value: assigneeId,
|
|
2683
|
+
onChange: (e) => setAssigneeId(e.target.value),
|
|
2684
|
+
children: [
|
|
2685
|
+
/* @__PURE__ */ jsx("option", { value: "", children: L.unassigned }),
|
|
2686
|
+
assigneeOptions.map((o) => /* @__PURE__ */ jsx("option", { value: o.id, children: o.name }, o.id))
|
|
2687
|
+
]
|
|
2688
|
+
}
|
|
2689
|
+
) : /* @__PURE__ */ jsx(
|
|
2330
2690
|
"input",
|
|
2331
2691
|
{
|
|
2332
2692
|
id: "pm-detail-assignee",
|
|
2333
2693
|
className: fieldClass2,
|
|
2334
2694
|
value: assigneeId,
|
|
2335
2695
|
onChange: (e) => setAssigneeId(e.target.value),
|
|
2336
|
-
placeholder:
|
|
2696
|
+
placeholder: L.assigneePlaceholder
|
|
2337
2697
|
}
|
|
2338
2698
|
)
|
|
2339
2699
|
] }),
|
|
2340
2700
|
!hidden.has("dueDate") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2341
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-due", className: labelClass2, children:
|
|
2701
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-due", className: labelClass2, children: L.dueDateLabel }),
|
|
2342
2702
|
/* @__PURE__ */ jsx(
|
|
2343
2703
|
"input",
|
|
2344
2704
|
{
|
|
@@ -2351,7 +2711,7 @@ function TaskDetailCore({
|
|
|
2351
2711
|
)
|
|
2352
2712
|
] }),
|
|
2353
2713
|
!hidden.has("storyPoints") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2354
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-points", className: labelClass2, children:
|
|
2714
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-points", className: labelClass2, children: L.storyPointsLabel }),
|
|
2355
2715
|
/* @__PURE__ */ jsx(
|
|
2356
2716
|
"input",
|
|
2357
2717
|
{
|
|
@@ -2366,7 +2726,7 @@ function TaskDetailCore({
|
|
|
2366
2726
|
] })
|
|
2367
2727
|
] }),
|
|
2368
2728
|
!hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2369
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-labels", className: labelClass2, children:
|
|
2729
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-labels", className: labelClass2, children: L.labelsLabel }),
|
|
2370
2730
|
/* @__PURE__ */ jsx(
|
|
2371
2731
|
"input",
|
|
2372
2732
|
{
|
|
@@ -2374,12 +2734,13 @@ function TaskDetailCore({
|
|
|
2374
2734
|
className: fieldClass2,
|
|
2375
2735
|
value: labels,
|
|
2376
2736
|
onChange: (e) => setLabels(e.target.value),
|
|
2377
|
-
placeholder:
|
|
2737
|
+
placeholder: L.labelsPlaceholder
|
|
2378
2738
|
}
|
|
2379
2739
|
)
|
|
2380
2740
|
] }),
|
|
2381
2741
|
saveError && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
|
|
2382
|
-
|
|
2742
|
+
L.failedToSave,
|
|
2743
|
+
": ",
|
|
2383
2744
|
saveError.message
|
|
2384
2745
|
] }),
|
|
2385
2746
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
@@ -2389,7 +2750,7 @@ function TaskDetailCore({
|
|
|
2389
2750
|
type: "button",
|
|
2390
2751
|
onClick: () => setEditing(false),
|
|
2391
2752
|
className: "rounded-md bg-muted px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted/70",
|
|
2392
|
-
children:
|
|
2753
|
+
children: L.cancel
|
|
2393
2754
|
}
|
|
2394
2755
|
),
|
|
2395
2756
|
/* @__PURE__ */ jsx(
|
|
@@ -2401,7 +2762,7 @@ function TaskDetailCore({
|
|
|
2401
2762
|
"rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
|
|
2402
2763
|
(saving || !title.trim()) && "cursor-not-allowed opacity-50"
|
|
2403
2764
|
),
|
|
2404
|
-
children: saving ?
|
|
2765
|
+
children: saving ? L.saving : L.save
|
|
2405
2766
|
}
|
|
2406
2767
|
)
|
|
2407
2768
|
] })
|
|
@@ -2454,6 +2815,9 @@ function TasksPageCore({
|
|
|
2454
2815
|
resolveAssignee,
|
|
2455
2816
|
linkSourceProduct,
|
|
2456
2817
|
renderLinkIcon,
|
|
2818
|
+
assigneeOptions,
|
|
2819
|
+
currentActorId,
|
|
2820
|
+
labels,
|
|
2457
2821
|
header,
|
|
2458
2822
|
onTaskSaved,
|
|
2459
2823
|
createSurface = "modal",
|
|
@@ -2463,10 +2827,12 @@ function TasksPageCore({
|
|
|
2463
2827
|
const ctx = usePlanMagnetContextSafe();
|
|
2464
2828
|
const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
|
|
2465
2829
|
const client = useApolloClient();
|
|
2830
|
+
const mergedLabels = mergeTaskLabels(labels);
|
|
2466
2831
|
const [view, setView] = useState(defaultView);
|
|
2467
2832
|
const [search, setSearch] = useState("");
|
|
2468
2833
|
const [priority, setPriority] = useState("ALL");
|
|
2469
2834
|
const [type, setType] = useState("ALL");
|
|
2835
|
+
const [mine, setMine] = useState(false);
|
|
2470
2836
|
const [creating, setCreating] = useState(false);
|
|
2471
2837
|
const [selectedId, setSelectedId] = useState(null);
|
|
2472
2838
|
const refetchBoard = useCallback(() => {
|
|
@@ -2488,6 +2854,9 @@ function TasksPageCore({
|
|
|
2488
2854
|
},
|
|
2489
2855
|
[refetchBoard, onTaskSaved]
|
|
2490
2856
|
);
|
|
2857
|
+
const handleDeleted = useCallback(() => {
|
|
2858
|
+
setSelectedId(null);
|
|
2859
|
+
}, []);
|
|
2491
2860
|
const handleTaskClick = useCallback((task) => {
|
|
2492
2861
|
setSelectedId(task.id);
|
|
2493
2862
|
}, []);
|
|
@@ -2503,6 +2872,7 @@ function TasksPageCore({
|
|
|
2503
2872
|
{
|
|
2504
2873
|
workspaceId,
|
|
2505
2874
|
projectId,
|
|
2875
|
+
assigneeOptions,
|
|
2506
2876
|
hiddenFields,
|
|
2507
2877
|
onCreated: handleCreated,
|
|
2508
2878
|
onCancel: () => setCreating(false)
|
|
@@ -2514,11 +2884,15 @@ function TasksPageCore({
|
|
|
2514
2884
|
id: selectedId,
|
|
2515
2885
|
readonly,
|
|
2516
2886
|
hiddenFields,
|
|
2517
|
-
|
|
2887
|
+
resolveAssignee,
|
|
2888
|
+
assigneeOptions,
|
|
2889
|
+
onUpdated: handleUpdated,
|
|
2890
|
+
onDeleted: handleDeleted
|
|
2518
2891
|
}
|
|
2519
2892
|
) : null;
|
|
2520
2893
|
const listPriority = priority === "ALL" ? void 0 : priority;
|
|
2521
2894
|
const listType = type === "ALL" ? void 0 : type;
|
|
2895
|
+
const mineAssignee = mine && currentActorId ? currentActorId : void 0;
|
|
2522
2896
|
const listColumns = linkSourceProduct ? [
|
|
2523
2897
|
"title",
|
|
2524
2898
|
"status",
|
|
@@ -2527,7 +2901,7 @@ function TasksPageCore({
|
|
|
2527
2901
|
"dueDate",
|
|
2528
2902
|
"linkedRecord"
|
|
2529
2903
|
] : void 0;
|
|
2530
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 p-6", className), children: [
|
|
2904
|
+
return /* @__PURE__ */ jsx(TaskLabelsProvider, { value: mergedLabels, children: /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 p-6", className), children: [
|
|
2531
2905
|
header && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: typeof header === "string" ? /* @__PURE__ */ jsx("h1", { className: "truncate text-2xl font-semibold text-foreground", children: header }) : header }),
|
|
2532
2906
|
/* @__PURE__ */ jsx(
|
|
2533
2907
|
TaskToolbar,
|
|
@@ -2542,7 +2916,9 @@ function TasksPageCore({
|
|
|
2542
2916
|
type,
|
|
2543
2917
|
onTypeChange: setType,
|
|
2544
2918
|
onNewTask: () => setCreating(true),
|
|
2545
|
-
canCreate
|
|
2919
|
+
canCreate,
|
|
2920
|
+
mine,
|
|
2921
|
+
onMineChange: currentActorId ? setMine : void 0
|
|
2546
2922
|
}
|
|
2547
2923
|
),
|
|
2548
2924
|
showInlineCreate && /* @__PURE__ */ jsx("div", { children: createForm }),
|
|
@@ -2557,6 +2933,7 @@ function TasksPageCore({
|
|
|
2557
2933
|
priority,
|
|
2558
2934
|
type,
|
|
2559
2935
|
search,
|
|
2936
|
+
assigneeId: mineAssignee,
|
|
2560
2937
|
hiddenFields,
|
|
2561
2938
|
resolveAssignee,
|
|
2562
2939
|
linkSourceProduct,
|
|
@@ -2572,6 +2949,7 @@ function TasksPageCore({
|
|
|
2572
2949
|
priority: listPriority,
|
|
2573
2950
|
type: listType,
|
|
2574
2951
|
search: search || void 0,
|
|
2952
|
+
assigneeId: mineAssignee,
|
|
2575
2953
|
hideHeader: true,
|
|
2576
2954
|
resolveAssignee,
|
|
2577
2955
|
linkSourceProduct,
|
|
@@ -2588,6 +2966,7 @@ function TasksPageCore({
|
|
|
2588
2966
|
priority,
|
|
2589
2967
|
type,
|
|
2590
2968
|
search,
|
|
2969
|
+
assigneeId: mineAssignee,
|
|
2591
2970
|
resolveAssignee,
|
|
2592
2971
|
onSelect: handleSelect
|
|
2593
2972
|
}
|
|
@@ -2612,7 +2991,7 @@ function TasksPageCore({
|
|
|
2612
2991
|
children: /* @__PURE__ */ jsx("div", { className: "p-2 pt-8", children: detailView })
|
|
2613
2992
|
}
|
|
2614
2993
|
)
|
|
2615
|
-
] });
|
|
2994
|
+
] }) });
|
|
2616
2995
|
}
|
|
2617
2996
|
function TasksPage({
|
|
2618
2997
|
apiGatewayUrl,
|
|
@@ -2643,6 +3022,6 @@ function TasksPage({
|
|
|
2643
3022
|
);
|
|
2644
3023
|
}
|
|
2645
3024
|
|
|
2646
|
-
export { Avatar, Badge, CREATE_WORK_ITEM, CREATE_WORK_ITEM_LINK, CreateTask, CreateTaskCore, DEFAULT_BOARD_COLUMNS, DELETE_WORK_ITEM_LINK, Drawer, GET_PROJECTS, GET_WORK_ITEM, LIST_WORK_ITEMS, LIST_WORK_ITEM_LINKS, LinkChip, MOVE_WORK_ITEM, Modal, PRIORITY_META, PROJECT_SUMMARY_FIELDS, PlanMagnetProvider, PriorityIndicator, STATUS_META, StatusIcon, StatusPill, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, TaskBoard, TaskBoardCore, TaskCard, TaskDetail, TaskDetailCore, TaskList, TaskListCore, TaskTimelineCore, TaskToolbar, TasksPage, TasksPageCore, TypeBadge, UPDATE_WORK_ITEM, WORK_ITEM_FIELDS, WORK_ITEM_LINK_FIELDS, WORK_ITEM_SUMMARY_FIELDS, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, usePlanMagnetContext, usePlanMagnetContextSafe, useWorkItemLinks, validateTrustedOrigin, waitForPlanMagnetClient };
|
|
3025
|
+
export { Avatar, Badge, CREATE_WORK_ITEM, CREATE_WORK_ITEM_LINK, CreateTask, CreateTaskCore, DEFAULT_BOARD_COLUMNS, DEFAULT_TASK_LABELS, DELETE_WORK_ITEM, DELETE_WORK_ITEM_LINK, Drawer, GET_PROJECTS, GET_WORK_ITEM, LIST_MILESTONES, LIST_WORK_ITEMS, LIST_WORK_ITEM_LINKS, LinkChip, MILESTONE_FIELDS, MOVE_WORK_ITEM, Modal, PRIORITY_META, PROJECT_SUMMARY_FIELDS, PlanMagnetProvider, PriorityIndicator, STATUS_META, StatusIcon, StatusPill, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, TaskBoard, TaskBoardCore, TaskCard, TaskDetail, TaskDetailCore, TaskLabelsProvider, TaskList, TaskListCore, TaskTimelineCore, TaskToolbar, TasksPage, TasksPageCore, TypeBadge, UPDATE_WORK_ITEM, WORK_ITEM_FIELDS, WORK_ITEM_LINK_FIELDS, WORK_ITEM_SUMMARY_FIELDS, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, mergeTaskLabels, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, useMilestones, usePlanMagnetContext, usePlanMagnetContextSafe, useTaskLabels, useWorkItemLinks, validateTrustedOrigin, waitForPlanMagnetClient };
|
|
2647
3026
|
//# sourceMappingURL=index.js.map
|
|
2648
3027
|
//# sourceMappingURL=index.js.map
|