@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.
Files changed (26) hide show
  1. package/dist/planmagnet/board/ProjectBoard.d.ts.map +1 -1
  2. package/dist/planmagnet/board/ProjectBoard.js +159 -158
  3. package/dist/planmagnet/board/ProjectBoard.js.map +1 -1
  4. package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -1
  5. package/dist/planmagnet/create/CreateDialogs.js +118 -117
  6. package/dist/planmagnet/create/CreateDialogs.js.map +1 -1
  7. package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.d.ts.map +1 -1
  8. package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js.map +1 -1
  9. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
  10. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +322 -280
  11. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
  12. package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
  13. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
  14. package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
  15. package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
  16. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  17. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +147 -126
  18. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  19. package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
  20. package/dist/planmagnet/sprints/SprintControls.js +202 -201
  21. package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
  22. package/dist/planmagnet/utils/mutationResult.d.ts +16 -0
  23. package/dist/planmagnet/utils/mutationResult.d.ts.map +1 -0
  24. package/dist/planmagnet/utils/mutationResult.js +10 -0
  25. package/dist/planmagnet/utils/mutationResult.js.map +1 -0
  26. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"CreateDialogs.js","names":[],"sources":["../../../src/planmagnet/create/CreateDialogs.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Button,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { Plus } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\n/**\n * Create dialogs for records whose list pages had a dead \"New …\" button, or\n * none at all (QA report 2026-09-23: C4 New Release had no onClick; H7 there\n * was no way to create a milestone). Both mutations were already served and\n * verified in prod; only the UI trigger was missing.\n */\n\nconst DIALOG_PROJECTS = gql`\n query CreateDialogProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n }\n }\n`;\n\nconst FIELD = 'mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm';\n\nfunction ErrorLine({ message }: { message: string }) {\n return (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n );\n}\n\nfunction useDialogProjects(open: boolean) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading } = useQuery<{\n planmagnetProjects: { items: Array<{ id: string; name: string }> };\n }>(DIALOG_PROJECTS, {\n variables: { workspaceId: workspaceId ?? '' },\n skip: !open || !workspaceId,\n });\n return { projects: data?.planmagnetProjects.items ?? [], loading };\n}\n\nfunction ProjectField({\n id,\n value,\n onChange,\n projects,\n loading,\n}: {\n id: string;\n value: string;\n onChange: (id: string) => void;\n projects: Array<{ id: string; name: string }>;\n loading: boolean;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n Project\n </label>\n <select id={id} className={FIELD} value={value} onChange={(e) => onChange(e.target.value)}>\n {projects.length === 0 && <option value=\"\">{loading ? 'Loading…' : 'No projects'}</option>}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\nfunction TextField({\n id,\n label,\n value,\n onChange,\n type = 'text',\n placeholder,\n}: {\n id: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n type?: string;\n placeholder?: string;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n {label}\n </label>\n <Input\n id={id}\n type={type}\n className=\"mt-1\"\n value={value}\n placeholder={placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n );\n}\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback);\n\n// ─── New release (C4) ────────────────────────────────────────────────────────\n\nconst CREATE_RELEASE = gql`\n mutation CreateDialogRelease($input: PlanmagnetCreateReleaseInput!) {\n planmagnetCreateRelease(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_RELEASE = { name: '', version: '', projectId: '', plannedDate: '', description: '' };\n\nexport function NewReleaseDialog({ onCreated }: { onCreated: (releaseId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_RELEASE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateRelease: { id: string } }>(\n CREATE_RELEASE,\n { refetchQueries: ['ListReleases'], awaitRefetchQueries: true }\n );\n\n const canSubmit =\n form.name.trim() !== '' && form.version.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await create({\n variables: {\n input: {\n name: form.name.trim(),\n version: form.version.trim(),\n projectId,\n plannedDate: form.plannedDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n });\n const id = result.data?.planmagnetCreateRelease.id;\n setForm(EMPTY_RELEASE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The release could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Release\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New release</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>The release starts in Planning.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-release-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <TextField\n id=\"new-release-version\"\n label=\"Version\"\n placeholder=\"e.g. 1.4.0\"\n value={form.version}\n onChange={(version) => setForm({ ...form, version })}\n />\n <ProjectField\n id=\"new-release-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-release-date\"\n label=\"Planned date\"\n type=\"date\"\n value={form.plannedDate}\n onChange={(plannedDate) => setForm({ ...form, plannedDate })}\n />\n <TextField\n id=\"new-release-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-release-submit\">\n {loading ? 'Creating…' : 'Create release'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New milestone (H7) ──────────────────────────────────────────────────────\n\nconst CREATE_MILESTONE = gql`\n mutation CreateDialogMilestone($input: PlanmagnetCreateMilestoneInput!) {\n planmagnetCreateMilestone(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_MILESTONE = { name: '', projectId: '', dueDate: '', description: '' };\n\nexport function NewMilestoneDialog({ onCreated }: { onCreated: (milestoneId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_MILESTONE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateMilestone: { id: string } }>(\n CREATE_MILESTONE,\n { refetchQueries: ['GetMilestones'], awaitRefetchQueries: true }\n );\n\n const canSubmit = form.name.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await create({\n variables: {\n input: {\n name: form.name.trim(),\n projectId,\n dueDate: form.dueDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n });\n const id = result.data?.planmagnetCreateMilestone.id;\n setForm(EMPTY_MILESTONE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The milestone could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Milestone\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New milestone</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n The milestone starts as Pending.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-milestone-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <ProjectField\n id=\"new-milestone-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-milestone-due\"\n label=\"Due date\"\n type=\"date\"\n value={form.dueDate}\n onChange={(dueDate) => setForm({ ...form, dueDate })}\n />\n <TextField\n id=\"new-milestone-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-milestone-submit\">\n {loading ? 'Creating…' : 'Create milestone'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;;;;AAwBA,IAAM,IAAkB,CAAG;;;;;;;;;GAWrB,IAAQ;AAEd,SAAS,EAAU,EAAE,cAAgC;AACnD,QACE,kBAAC,KAAD;EAAG,MAAK;EAAQ,WAAU;YACvB;EACC,CAAA;;AAIR,SAAS,EAAkB,GAAe;CACxC,IAAM,EAAE,mBAAgB,GAAe,EACjC,EAAE,SAAM,eAAY,EAEvB,GAAiB;EAClB,WAAW,EAAE,aAAa,KAAe,IAAI;EAC7C,MAAM,CAAC,KAAQ,CAAC;EACjB,CAAC;AACF,QAAO;EAAE,UAAU,GAAM,mBAAmB,SAAS,EAAE;EAAE;EAAS;;AAGpE,SAAS,EAAa,EACpB,OACA,UACA,aACA,aACA,cAOC;AACD,QACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;EAAO,SAAS;EAAI,WAAU;YAAsB;EAE5C,CAAA,EACR,kBAAC,UAAD;EAAY;EAAI,WAAW;EAAc;EAAO,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;YAAzF,CACG,EAAS,WAAW,KAAK,kBAAC,UAAD;GAAQ,OAAM;aAAI,IAAU,aAAa;GAAuB,CAAA,EACzF,EAAS,KAAK,MACb,kBAAC,UAAD;GAAmB,OAAO,EAAE;aACzB,EAAE;GACI,EAFI,EAAE,GAEN,CACT,CACK;IACL,EAAA,CAAA;;AAIV,SAAS,EAAU,EACjB,OACA,UACA,UACA,aACA,UAAO,QACP,kBAQC;AACD,QACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;EAAO,SAAS;EAAI,WAAU;YAC3B;EACK,CAAA,EACR,kBAAC,GAAD;EACM;EACE;EACN,WAAU;EACH;EACM;EACb,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;EACzC,CAAA,CACE,EAAA,CAAA;;AAIV,IAAM,KAAa,GAAY,MAAsB,aAAa,QAAQ,EAAE,UAAU,GAIhF,IAAiB,CAAG;;;;;;GAQpB,IAAgB;CAAE,MAAM;CAAI,SAAS;CAAI,WAAW;CAAI,aAAa;CAAI,aAAa;CAAI;AAEhG,SAAgB,EAAiB,EAAE,gBAAyD;CAC1F,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,CAAC,GAAM,KAAW,EAAS,EAAc,EACzC,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,EAAE,aAAU,SAAS,MAAoB,EAAkB,EAAK,EAChE,IAAY,EAAK,aAAa,EAAS,IAAI,MAAM,IACjD,CAAC,GAAQ,EAAE,gBAAa,EAC5B,GACA;EAAE,gBAAgB,CAAC,eAAe;EAAE,qBAAqB;EAAM,CAChE,EAEK,IACJ,EAAK,KAAK,MAAM,KAAK,MAAM,EAAK,QAAQ,MAAM,KAAK,MAAM,MAAc,MAAM,CAAC;AAyBhF,QACE,kBAAC,GAAD;EACQ;EACN,eAAe,MAAS;AAEtB,GADA,EAAQ,EAAK,EACR,KAAM,EAAS,KAAK;;YAJ7B,CAOE,kBAAC,GAAD;GAAyB,SAAA;aACvB,kBAAC,GAAD;IAAQ,MAAK;cAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,cAE1B;;GACe,CAAA,EAC1B,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAuB,eAAmC,CAAA,EAC1D,kBAAC,GAAD,EAAA,UAA6B,mCAA6D,CAAA,CACnE,EAAA,CAAA;IACzB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,OAAO,EAAK;OACZ,WAAW,MAAS,EAAQ;QAAE,GAAG;QAAM;QAAM,CAAC;OAC9C,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,aAAY;OACZ,OAAO,EAAK;OACZ,WAAW,MAAY,EAAQ;QAAE,GAAG;QAAM;QAAS,CAAC;OACpD,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAO;OACP,WAAW,MAAO,EAAQ;QAAE,GAAG;QAAM,WAAW;QAAI,CAAC;OAC3C;OACV,SAAS;OACT,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,MAAK;OACL,OAAO,EAAK;OACZ,WAAW,MAAgB,EAAQ;QAAE,GAAG;QAAM;QAAa,CAAC;OAC5D,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,OAAO,EAAK;OACZ,WAAW,MAAgB,EAAQ;QAAE,GAAG;QAAM;QAAa,CAAC;OAC5D,CAAA;MACE;;IACL,KAAS,kBAAC,GAAD,EAAW,SAAS,GAAS,CAAA;IACvC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;KAAQ,SA/EK,YAAY;AAC/B,QAAS,KAAK;AACd,UAAI;OAYF,IAAM,KAXS,MAAM,EAAO,EAC1B,WAAW,EACT,OAAO;QACL,MAAM,EAAK,KAAK,MAAM;QACtB,SAAS,EAAK,QAAQ,MAAM;QAC5B;QACA,aAAa,EAAK,eAAe,KAAA;QACjC,aAAa,EAAK,YAAY,MAAM,IAAI,KAAA;QACzC,EACF,EACF,CAAC,EACgB,MAAM,wBAAwB;AAGhD,OAFA,EAAQ,EAAc,EACtB,EAAQ,GAAM,EACV,KAAI,EAAU,EAAG;eACd,GAAG;AACV,SAAS,EAAU,GAAG,oCAAoC,CAAC;;;KA4DxB,UAAU,CAAC;KAAW,eAAY;eAC9D,IAAU,cAAc;KAClB,CAAA,EACc,CAAA;IACD;KACT;;;AAMvB,IAAM,IAAmB,CAAG;;;;;;GAQtB,IAAkB;CAAE,MAAM;CAAI,WAAW;CAAI,SAAS;CAAI,aAAa;CAAI;AAEjF,SAAgB,EAAmB,EAAE,gBAA2D;CAC9F,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,CAAC,GAAM,KAAW,EAAS,EAAgB,EAC3C,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,EAAE,aAAU,SAAS,MAAoB,EAAkB,EAAK,EAChE,IAAY,EAAK,aAAa,EAAS,IAAI,MAAM,IACjD,CAAC,GAAQ,EAAE,gBAAa,EAC5B,GACA;EAAE,gBAAgB,CAAC,gBAAgB;EAAE,qBAAqB;EAAM,CACjE,EAEK,IAAY,EAAK,KAAK,MAAM,KAAK,MAAM,MAAc,MAAM,CAAC;AAwBlE,QACE,kBAAC,GAAD;EACQ;EACN,eAAe,MAAS;AAEtB,GADA,EAAQ,EAAK,EACR,KAAM,EAAS,KAAK;;YAJ7B,CAOE,kBAAC,GAAD;GAAyB,SAAA;aACvB,kBAAC,GAAD;IAAQ,MAAK;cAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,gBAE1B;;GACe,CAAA,EAC1B,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAuB,iBAAqC,CAAA,EAC5D,kBAAC,GAAD,EAAA,UAA6B,oCAEC,CAAA,CACP,EAAA,CAAA;IACzB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,OAAO,EAAK;OACZ,WAAW,MAAS,EAAQ;QAAE,GAAG;QAAM;QAAM,CAAC;OAC9C,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAO;OACP,WAAW,MAAO,EAAQ;QAAE,GAAG;QAAM,WAAW;QAAI,CAAC;OAC3C;OACV,SAAS;OACT,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,MAAK;OACL,OAAO,EAAK;OACZ,WAAW,MAAY,EAAQ;QAAE,GAAG;QAAM;QAAS,CAAC;OACpD,CAAA;MACF,kBAAC,GAAD;OACE,IAAG;OACH,OAAM;OACN,OAAO,EAAK;OACZ,WAAW,MAAgB,EAAQ;QAAE,GAAG;QAAM;QAAa,CAAC;OAC5D,CAAA;MACE;;IACL,KAAS,kBAAC,GAAD,EAAW,SAAS,GAAS,CAAA;IACvC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;KAAQ,SAzEK,YAAY;AAC/B,QAAS,KAAK;AACd,UAAI;OAWF,IAAM,KAVS,MAAM,EAAO,EAC1B,WAAW,EACT,OAAO;QACL,MAAM,EAAK,KAAK,MAAM;QACtB;QACA,SAAS,EAAK,WAAW,KAAA;QACzB,aAAa,EAAK,YAAY,MAAM,IAAI,KAAA;QACzC,EACF,EACF,CAAC,EACgB,MAAM,0BAA0B;AAGlD,OAFA,EAAQ,EAAgB,EACxB,EAAQ,GAAM,EACV,KAAI,EAAU,EAAG;eACd,GAAG;AACV,SAAS,EAAU,GAAG,sCAAsC,CAAC;;;KAuD1B,UAAU,CAAC;KAAW,eAAY;eAC9D,IAAU,cAAc;KAClB,CAAA,EACc,CAAA;IACD;KACT"}
1
+ {"version":3,"file":"CreateDialogs.js","names":[],"sources":["../../../src/planmagnet/create/CreateDialogs.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Button,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { Plus } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { throwOnError } from '../utils/mutationResult';\n\n/**\n * Create dialogs for records whose list pages had a dead \"New …\" button, or\n * none at all (QA report 2026-09-23: C4 New Release had no onClick; H7 there\n * was no way to create a milestone). Both mutations were already served and\n * verified in prod; only the UI trigger was missing.\n */\n\nconst DIALOG_PROJECTS = gql`\n query CreateDialogProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n }\n }\n`;\n\nconst FIELD = 'mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm';\n\nfunction ErrorLine({ message }: { message: string }) {\n return (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n );\n}\n\nfunction useDialogProjects(open: boolean) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading } = useQuery<{\n planmagnetProjects: { items: Array<{ id: string; name: string }> };\n }>(DIALOG_PROJECTS, {\n variables: { workspaceId: workspaceId ?? '' },\n skip: !open || !workspaceId,\n });\n return { projects: data?.planmagnetProjects.items ?? [], loading };\n}\n\nfunction ProjectField({\n id,\n value,\n onChange,\n projects,\n loading,\n}: {\n id: string;\n value: string;\n onChange: (id: string) => void;\n projects: Array<{ id: string; name: string }>;\n loading: boolean;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n Project\n </label>\n <select id={id} className={FIELD} value={value} onChange={(e) => onChange(e.target.value)}>\n {projects.length === 0 && <option value=\"\">{loading ? 'Loading…' : 'No projects'}</option>}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\nfunction TextField({\n id,\n label,\n value,\n onChange,\n type = 'text',\n placeholder,\n}: {\n id: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n type?: string;\n placeholder?: string;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n {label}\n </label>\n <Input\n id={id}\n type={type}\n className=\"mt-1\"\n value={value}\n placeholder={placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n );\n}\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback);\n\n// ─── New release (C4) ────────────────────────────────────────────────────────\n\nconst CREATE_RELEASE = gql`\n mutation CreateDialogRelease($input: PlanmagnetCreateReleaseInput!) {\n planmagnetCreateRelease(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_RELEASE = { name: '', version: '', projectId: '', plannedDate: '', description: '' };\n\nexport function NewReleaseDialog({ onCreated }: { onCreated: (releaseId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_RELEASE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateRelease: { id: string } }>(\n CREATE_RELEASE,\n { refetchQueries: ['ListReleases'], awaitRefetchQueries: true }\n );\n\n const canSubmit =\n form.name.trim() !== '' && form.version.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await throwOnError(\n create({\n variables: {\n input: {\n name: form.name.trim(),\n version: form.version.trim(),\n projectId,\n plannedDate: form.plannedDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n })\n );\n const id = result.data?.planmagnetCreateRelease.id;\n setForm(EMPTY_RELEASE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The release could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Release\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New release</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>The release starts in Planning.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-release-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <TextField\n id=\"new-release-version\"\n label=\"Version\"\n placeholder=\"e.g. 1.4.0\"\n value={form.version}\n onChange={(version) => setForm({ ...form, version })}\n />\n <ProjectField\n id=\"new-release-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-release-date\"\n label=\"Planned date\"\n type=\"date\"\n value={form.plannedDate}\n onChange={(plannedDate) => setForm({ ...form, plannedDate })}\n />\n <TextField\n id=\"new-release-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-release-submit\">\n {loading ? 'Creating…' : 'Create release'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New milestone (H7) ──────────────────────────────────────────────────────\n\nconst CREATE_MILESTONE = gql`\n mutation CreateDialogMilestone($input: PlanmagnetCreateMilestoneInput!) {\n planmagnetCreateMilestone(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_MILESTONE = { name: '', projectId: '', dueDate: '', description: '' };\n\nexport function NewMilestoneDialog({ onCreated }: { onCreated: (milestoneId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_MILESTONE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateMilestone: { id: string } }>(\n CREATE_MILESTONE,\n { refetchQueries: ['GetMilestones'], awaitRefetchQueries: true }\n );\n\n const canSubmit = form.name.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await throwOnError(\n create({\n variables: {\n input: {\n name: form.name.trim(),\n projectId,\n dueDate: form.dueDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n })\n );\n const id = result.data?.planmagnetCreateMilestone.id;\n setForm(EMPTY_MILESTONE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The milestone could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Milestone\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New milestone</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n The milestone starts as Pending.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-milestone-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <ProjectField\n id=\"new-milestone-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-milestone-due\"\n label=\"Due date\"\n type=\"date\"\n value={form.dueDate}\n onChange={(dueDate) => setForm({ ...form, dueDate })}\n />\n <TextField\n id=\"new-milestone-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-milestone-submit\">\n {loading ? 'Creating…' : 'Create milestone'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"GoalsCreateObjectivePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,4BAA4B,4CA2G3C"}
1
+ {"version":3,"file":"GoalsCreateObjectivePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,4BAA4B,4CA4G3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"GoalsCreateObjectivePagePage.js","names":[],"sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, Flag } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst CREATE_OBJECTIVE = gql`\n mutation CreateObjective($input: PlanmagnetCreateObjectiveInput!) {\n planmagnetCreateObjective(input: $input) {\n id\n }\n }\n`;\n\nexport function GoalsCreateObjectivePagePage() {\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState({\n title: '',\n description: '',\n periodLabel: '',\n endDate: '',\n });\n\n const [createObjective, { loading: saving, error }] = useMutation(CREATE_OBJECTIVE);\n\n const handleCreate = async () => {\n if (!form.title.trim() || !form.periodLabel.trim()) return;\n const result = await createObjective({\n variables: {\n input: {\n title: form.title.trim(),\n description: form.description.trim() || undefined,\n periodLabel: form.periodLabel.trim(),\n endDate: form.endDate || undefined,\n },\n },\n });\n const newId = result.data?.planmagnetCreateObjective?.id;\n if (newId) {\n navigate(`/goals/objective-detail-page?objectiveId=${newId}`);\n } else {\n navigate('/goals/goals-page');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Objective</h1>\n <p className=\"text-sm text-muted-foreground\">\n Define a workspace goal for a time period, then add key results to make progress\n measurable.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/goals/goals-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={handleCreate}\n disabled={saving || !form.title.trim() || !form.periodLabel.trim()}\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Creating...' : 'Create Objective'}\n </Button>\n </div>\n </div>\n {error && <div className=\"p-6 text-red-500\">Error: {error.message}</div>}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Flag className=\"h-4 w-4\" />\n Objective Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Grow enterprise revenue\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Why this objective matters this period...\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Time Period</label>\n <Input\n value={form.periodLabel}\n onChange={(e) => setForm({ ...form, periodLabel: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Q3 2026\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Target End Date</label>\n <Input\n type=\"date\"\n value={form.endDate}\n onChange={(e) => setForm({ ...form, endDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"GoalsCreateObjectivePagePage.js","names":[],"sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, Flag } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst CREATE_OBJECTIVE = gql`\n mutation CreateObjective($input: PlanmagnetCreateObjectiveInput!) {\n planmagnetCreateObjective(input: $input) {\n id\n }\n }\n`;\n\nexport function GoalsCreateObjectivePagePage() {\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState({\n title: '',\n description: '',\n periodLabel: '',\n endDate: '',\n });\n\n const [createObjective, { loading: saving, error }] = useMutation(CREATE_OBJECTIVE);\n\n const handleCreate = async () => {\n if (!form.title.trim() || !form.periodLabel.trim()) return;\n // mutation-error: shown from the hook's `error`; it only navigates when an id came back.\n const result = await createObjective({\n variables: {\n input: {\n title: form.title.trim(),\n description: form.description.trim() || undefined,\n periodLabel: form.periodLabel.trim(),\n endDate: form.endDate || undefined,\n },\n },\n });\n const newId = result.data?.planmagnetCreateObjective?.id;\n if (newId) {\n navigate(`/goals/objective-detail-page?objectiveId=${newId}`);\n } else {\n navigate('/goals/goals-page');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Objective</h1>\n <p className=\"text-sm text-muted-foreground\">\n Define a workspace goal for a time period, then add key results to make progress\n measurable.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/goals/goals-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={handleCreate}\n disabled={saving || !form.title.trim() || !form.periodLabel.trim()}\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Creating...' : 'Create Objective'}\n </Button>\n </div>\n </div>\n {error && <div className=\"p-6 text-red-500\">Error: {error.message}</div>}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Flag className=\"h-4 w-4\" />\n Objective Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Grow enterprise revenue\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Why this objective matters this period...\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Time Period</label>\n <Input\n value={form.periodLabel}\n onChange={(e) => setForm({ ...form, periodLabel: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Q3 2026\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Target End Date</label>\n <Input\n type=\"date\"\n value={form.endDate}\n onChange={(e) => setForm({ ...form, endDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"GoalsObjectiveDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsObjectiveDetailPagePage.tsx"],"names":[],"mappings":"AAgOA,wBAAgB,4BAA4B,4CAiP3C"}
1
+ {"version":3,"file":"GoalsObjectiveDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsObjectiveDetailPagePage.tsx"],"names":[],"mappings":"AAqPA,wBAAgB,4BAA4B,4CAqQ3C"}