@burdenoff/microfe-planmagnet 2026.1002.1 → 2026.1002.3
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/generated/wspace-operations.d.ts +2533 -546
- package/dist/generated/wspace-operations.d.ts.map +1 -1
- package/dist/generated/wspace-types.d.ts +5654 -71
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +180 -162
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +100 -84
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/board/BulkActions.d.ts.map +1 -1
- package/dist/planmagnet/board/BulkActions.js +106 -55
- package/dist/planmagnet/board/BulkActions.js.map +1 -1
- package/dist/planmagnet/controls/Pickers.d.ts +10 -5
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +10 -9
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/dashboards/DashboardUI.d.ts +0 -4
- package/dist/planmagnet/dashboards/DashboardUI.d.ts.map +1 -1
- package/dist/planmagnet/dashboards/DashboardUI.js +6 -13
- package/dist/planmagnet/dashboards/DashboardUI.js.map +1 -1
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +70 -59
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
- package/dist/planmagnet/forecast/ResourceForecastCard.js +1 -1
- package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -1
- package/dist/planmagnet/index.d.ts +1 -1
- package/dist/planmagnet/index.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts +3 -3
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js +26 -19
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js.map +1 -1
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts +2 -2
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js +18 -12
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js +251 -0
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js +4 -4
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +133 -131
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +5 -5
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +6 -6
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +107 -82
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.js +174 -0
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.js +350 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.js +168 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +116 -114
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +174 -159
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +159 -145
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js +161 -143
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +160 -156
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.d.ts.map +1 -1
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +97 -99
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js.map +1 -1
- package/dist/planmagnet/product/FeatureLinkPanels.d.ts +29 -0
- package/dist/planmagnet/product/FeatureLinkPanels.d.ts.map +1 -0
- package/dist/planmagnet/product/FeatureLinkPanels.js +373 -0
- package/dist/planmagnet/product/FeatureLinkPanels.js.map +1 -0
- package/dist/planmagnet/product/ProductControls.js +1 -1
- package/dist/planmagnet/product/ProductControls.js.map +1 -1
- package/dist/planmagnet/product/ProductFeatureControls.d.ts +39 -0
- package/dist/planmagnet/product/ProductFeatureControls.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductFeatureControls.js +315 -0
- package/dist/planmagnet/product/ProductFeatureControls.js.map +1 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.d.ts +4 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.js +192 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.js.map +1 -0
- package/dist/planmagnet/product/ProductLineControls.d.ts +52 -0
- package/dist/planmagnet/product/ProductLineControls.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductLineControls.js +417 -0
- package/dist/planmagnet/product/ProductLineControls.js.map +1 -0
- package/dist/planmagnet/product/ProductTeamsPanel.d.ts +4 -0
- package/dist/planmagnet/product/ProductTeamsPanel.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductTeamsPanel.js +129 -0
- package/dist/planmagnet/product/ProductTeamsPanel.js.map +1 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.d.ts +4 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.d.ts.map +1 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.js +41 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.js.map +1 -0
- package/dist/planmagnet/product/hierarchy.d.ts +127 -0
- package/dist/planmagnet/product/hierarchy.d.ts.map +1 -0
- package/dist/planmagnet/product/hierarchy.js +173 -0
- package/dist/planmagnet/product/hierarchy.js.map +1 -0
- package/dist/planmagnet/product/hierarchyOperations.d.ts +35 -0
- package/dist/planmagnet/product/hierarchyOperations.d.ts.map +1 -0
- package/dist/planmagnet/product/hierarchyOperations.js +440 -0
- package/dist/planmagnet/product/hierarchyOperations.js.map +1 -0
- package/dist/planmagnet/product/refusal.d.ts +14 -0
- package/dist/planmagnet/product/refusal.d.ts.map +1 -0
- package/dist/planmagnet/product/refusal.js +10 -0
- package/dist/planmagnet/product/refusal.js.map +1 -0
- package/dist/planmagnet/product/routes.d.ts +10 -0
- package/dist/planmagnet/product/routes.d.ts.map +1 -1
- package/dist/planmagnet/product/routes.js +2 -2
- package/dist/planmagnet/product/routes.js.map +1 -1
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts +20 -0
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js +55 -0
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts +30 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.js +282 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts +9 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js +390 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts +17 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js +77 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts +18 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js +87 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts +13 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js +326 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts +23 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js +258 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts +6 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js +56 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts +16 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js +102 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfaction.d.ts +154 -0
- package/dist/planmagnet/satisfaction/satisfaction.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfaction.js +210 -0
- package/dist/planmagnet/satisfaction/satisfaction.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts +108 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.js +211 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.d.ts +90 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.js +90 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts +116 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.js +86 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.js.map +1 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts +20 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.js +31 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.js.map +1 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts +35 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts.map +1 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.js +124 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.js.map +1 -0
- package/dist/planmagnet/skills/SkillChips.d.ts +30 -0
- package/dist/planmagnet/skills/SkillChips.d.ts.map +1 -0
- package/dist/planmagnet/skills/SkillChips.js +57 -0
- package/dist/planmagnet/skills/SkillChips.js.map +1 -0
- package/dist/planmagnet/skills/SkillCoverageCard.d.ts +24 -0
- package/dist/planmagnet/skills/SkillCoverageCard.d.ts.map +1 -0
- package/dist/planmagnet/skills/SkillCoverageCard.js +256 -0
- package/dist/planmagnet/skills/SkillCoverageCard.js.map +1 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts +10 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts.map +1 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.js +65 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.js.map +1 -0
- package/dist/planmagnet/skills/skillOperations.d.ts +52 -0
- package/dist/planmagnet/skills/skillOperations.d.ts.map +1 -0
- package/dist/planmagnet/skills/skillOperations.js +44 -0
- package/dist/planmagnet/skills/skillOperations.js.map +1 -0
- package/dist/planmagnet/skills/skillTags.d.ts +103 -0
- package/dist/planmagnet/skills/skillTags.d.ts.map +1 -0
- package/dist/planmagnet/skills/skillTags.js +115 -0
- package/dist/planmagnet/skills/skillTags.js.map +1 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts +28 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts.map +1 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.js +30 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.js.map +1 -0
- package/dist/shared/utils/i18n.d.ts +3 -0
- package/dist/shared/utils/i18n.d.ts.map +1 -1
- package/dist/shared/utils/i18n.js +1 -1
- package/dist/shared/utils/i18n.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsProductsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsProductsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Package, Plus, Archive, Loader2, Map, GitBranch, Star } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { enumLabel } from '../controls/WorkItemControls';\n\n/**\n * The real \"Products\" list (BOFF-8045). Before this shipped, this page listed Roadmaps\n * relabelled as products (CAPABILITY_REGISTER: \"not-built\") — it now queries the Product\n * entity directly, which links roadmaps/releases/feature requests/OKR objectives rather\n * than being one.\n */\n\nconst LIST_PRODUCTS = gql`\n query GetProducts(\n $workspaceId: ID!\n $filter: PlanmagnetProductFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetProducts(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n description\n vision\n lifecycleStage\n ownerId\n archivedAt\n northStar {\n name\n unit\n target\n current\n progressRatio\n }\n roadmaps {\n id\n }\n releases {\n id\n }\n featureRequests {\n id\n }\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProductNorthStar {\n name: string;\n unit: string;\n target: number;\n current: number;\n progressRatio: number | null;\n}\n\ninterface ProductListNode {\n id: string;\n name: string;\n description: string | null;\n vision: string;\n lifecycleStage: string;\n ownerId: string;\n archivedAt: string | null;\n northStar: ProductNorthStar | null;\n roadmaps: { id: string }[];\n releases: { id: string }[];\n featureRequests: { id: string }[];\n updatedAt: string;\n}\n\nexport function ProductsProductsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const { t } = useI18n();\n const [showArchived, setShowArchived] = useState(false);\n\n const { data, loading, error } = useQuery<{\n planmagnetProducts: { items: ProductListNode[]; totalCount: number };\n }>(LIST_PRODUCTS, {\n variables: {\n workspaceId,\n filter: showArchived ? undefined : { isActive: true },\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch must not blank the page.\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-6 text-destructive\">\n {t('planmagnet.products.errorLoading', 'Failed to load products')}: {error.message}\n </div>\n );\n }\n\n const products = data?.planmagnetProducts?.items ?? [];\n const totalProducts = data?.planmagnetProducts?.totalCount ?? 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <Package className=\"h-6 w-6\" /> {t('planmagnet.products.title', 'Products')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t(\n 'planmagnet.products.subtitle',\n 'Strategy entities that link roadmaps, releases, feature requests and OKRs'\n )}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant={showArchived ? 'default' : 'outline'}\n onClick={() => setShowArchived((v) => !v)}\n data-testid=\"products-toggle-archived\"\n >\n <Archive className=\"h-4 w-4 mr-1\" />\n {showArchived\n ? t('planmagnet.products.actions.hideArchived', 'Hide archived')\n : t('planmagnet.products.actions.showArchived', 'Show archived')}\n </Button>\n <Button size=\"sm\" onClick={() => navigate('/products/create-product-page')}>\n <Plus className=\"h-4 w-4 mr-1\" />\n {t('planmagnet.products.actions.newProduct', 'New Product')}\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n {\n label: t('planmagnet.products.metrics.totalProducts', 'Total Products'),\n val: totalProducts,\n icon: Package,\n color: 'text-blue-500',\n },\n {\n label: t('planmagnet.products.metrics.roadmaps', 'Linked roadmaps'),\n val: products.reduce((sum, p) => sum + p.roadmaps.length, 0),\n icon: Map,\n color: 'text-green-500',\n },\n {\n label: t('planmagnet.products.metrics.releases', 'Linked releases'),\n val: products.reduce((sum, p) => sum + p.releases.length, 0),\n icon: GitBranch,\n color: 'text-purple-500',\n },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-muted-foreground\">{s.label}</p>\n <p className=\"text-2xl font-bold\">{s.val}</p>\n </div>\n <s.icon className={`h-8 w-8 ${s.color} opacity-60`} />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {products.length === 0 ? (\n <Card>\n <CardContent className=\"py-12 text-center text-sm text-muted-foreground\">\n {t('planmagnet.products.empty', 'No products yet. Create one to get started.')}\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-2\">\n {products.map((product) => (\n <Card\n key={product.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/product-detail-page', product.id)),\n product.name\n )}\n >\n <CardHeader>\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-base\">{product.name}</CardTitle>\n <div className=\"flex items-center gap-1 shrink-0\">\n {product.archivedAt && (\n <Badge variant=\"outline\" className=\"text-xs\">\n {t('planmagnet.products.shared.archived', 'Archived')}\n </Badge>\n )}\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {enumLabel(product.lifecycleStage)}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground line-clamp-2\">\n {product.vision || t('planmagnet.products.shared.noVision', 'No vision set')}\n </p>\n <div className=\"grid grid-cols-3 gap-2 text-center\">\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.roadmaps.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.roadmaps', 'Roadmaps')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.releases.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.releases', 'Releases')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.featureRequests.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n <Star className=\"inline h-3 w-3 mr-0.5\" />\n {t('planmagnet.products.shared.features', 'Features')}\n </p>\n </div>\n </div>\n {product.northStar && (\n <div className=\"rounded border p-2 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-muted-foreground\">{product.northStar.name}</span>\n <span className=\"font-medium\">\n {product.northStar.current} / {product.northStar.target}{' '}\n {product.northStar.unit}\n {product.northStar.progressRatio != null\n ? ` (${Math.round(product.northStar.progressRatio * 100)}%)`\n : ''}\n </span>\n </div>\n </div>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {t('planmagnet.products.shared.owner', 'Owner')}:{' '}\n <PersonName id={product.ownerId} />\n </span>\n <span>\n {t('planmagnet.products.shared.updated', 'Updated')}{' '}\n {new Date(product.updatedAt).toLocaleDateString()}\n </span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductsProductsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsProductsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Package, Plus, Archive, Loader2, Map, GitBranch, Star } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { enumLabel } from '../controls/WorkItemControls';\n\n/**\n * The real \"Products\" list (BOFF-8045). Before this shipped, this page listed Roadmaps\n * relabelled as products (CAPABILITY_REGISTER: \"not-built\") — it now queries the Product\n * entity directly, which links roadmaps/releases/feature requests/OKR objectives rather\n * than being one.\n */\n\nconst LIST_PRODUCTS = gql`\n query GetProducts(\n $workspaceId: ID!\n $filter: PlanmagnetProductFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetProducts(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n description\n vision\n lifecycleStage\n ownerId\n archivedAt\n northStar {\n name\n unit\n target\n current\n progressRatio\n }\n roadmaps {\n id\n }\n releases {\n id\n }\n featureRequests {\n id\n }\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProductNorthStar {\n name: string;\n unit: string;\n target: number;\n current: number;\n progressRatio: number | null;\n}\n\ninterface ProductListNode {\n id: string;\n name: string;\n description: string | null;\n vision: string;\n lifecycleStage: string;\n ownerId: string;\n archivedAt: string | null;\n northStar: ProductNorthStar | null;\n roadmaps: { id: string }[];\n releases: { id: string }[];\n featureRequests: { id: string }[];\n updatedAt: string;\n}\n\nexport function ProductsProductsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const { t } = useI18n();\n const [showArchived, setShowArchived] = useState(false);\n\n const { data, loading, error } = useQuery<{\n planmagnetProducts: { items: ProductListNode[]; totalCount: number };\n }>(LIST_PRODUCTS, {\n variables: {\n workspaceId,\n filter: showArchived ? undefined : { isActive: true },\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch must not blank the page.\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-6 text-destructive\">\n {t('planmagnet.products.errorLoading', 'Failed to load products')}: {error.message}\n </div>\n );\n }\n\n const products = data?.planmagnetProducts?.items ?? [];\n const totalProducts = data?.planmagnetProducts?.totalCount ?? 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <Package className=\"h-6 w-6\" /> {t('planmagnet.products.title', 'Products')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t(\n 'planmagnet.products.subtitle',\n 'Strategy entities that link roadmaps, releases, feature requests and OKRs'\n )}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant={showArchived ? 'default' : 'outline'}\n onClick={() => setShowArchived((v) => !v)}\n data-testid=\"products-toggle-archived\"\n >\n <Archive className=\"h-4 w-4 mr-1\" />\n {showArchived\n ? t('planmagnet.products.actions.hideArchived', 'Hide archived')\n : t('planmagnet.products.actions.showArchived', 'Show archived')}\n </Button>\n <Button size=\"sm\" onClick={() => navigate('/products/create-product-page')}>\n <Plus className=\"h-4 w-4 mr-1\" />\n {t('planmagnet.products.actions.newProduct', 'New Product')}\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n {\n label: t('planmagnet.products.metrics.totalProducts', 'Total Products'),\n val: totalProducts,\n icon: Package,\n color: 'text-blue-500',\n },\n {\n label: t('planmagnet.products.metrics.roadmaps', 'Linked roadmaps'),\n val: products.reduce((sum, p) => sum + p.roadmaps.length, 0),\n icon: Map,\n color: 'text-green-500',\n },\n {\n label: t('planmagnet.products.metrics.releases', 'Linked releases'),\n val: products.reduce((sum, p) => sum + p.releases.length, 0),\n icon: GitBranch,\n color: 'text-purple-500',\n },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-muted-foreground\">{s.label}</p>\n <p className=\"text-2xl font-bold\">{s.val}</p>\n </div>\n <s.icon className={`h-8 w-8 ${s.color} opacity-60`} />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {products.length === 0 ? (\n <Card>\n <CardContent className=\"py-12 text-center text-sm text-muted-foreground\">\n {t('planmagnet.products.empty', 'No products yet. Create one to get started.')}\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-2\">\n {products.map((product) => (\n <Card\n key={product.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/product-detail-page', product.id)),\n product.name\n )}\n >\n <CardHeader>\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-base\">{product.name}</CardTitle>\n <div className=\"flex items-center gap-1 shrink-0\">\n {product.archivedAt && (\n <Badge variant=\"outline\" className=\"text-xs\">\n {t('planmagnet.products.shared.archived', 'Archived')}\n </Badge>\n )}\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {enumLabel(product.lifecycleStage)}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground line-clamp-2\">\n {product.vision || t('planmagnet.products.shared.noVision', 'No vision set')}\n </p>\n <div className=\"grid grid-cols-3 gap-2 text-center\">\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.roadmaps.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.roadmaps', 'Roadmaps')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.releases.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.releases', 'Releases')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.featureRequests.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n <Star className=\"inline h-3 w-3 mr-0.5\" />\n {/* PRM-01: these are feature REQUESTS (customer feedback), not product features.\n A new key, so a locale that translated the old one as \"Features\" cannot keep\n the old wording. */}\n {t('planmagnet.products.shared.featureRequests', 'Feature requests')}\n </p>\n </div>\n </div>\n {product.northStar && (\n <div className=\"rounded border p-2 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-muted-foreground\">{product.northStar.name}</span>\n <span className=\"font-medium\">\n {product.northStar.current} / {product.northStar.target}{' '}\n {product.northStar.unit}\n {product.northStar.progressRatio != null\n ? ` (${Math.round(product.northStar.progressRatio * 100)}%)`\n : ''}\n </span>\n </div>\n </div>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {t('planmagnet.products.shared.owner', 'Owner')}:{' '}\n <PersonName id={product.ownerId} />\n </span>\n <span>\n {t('planmagnet.products.shared.updated', 'Updated')}{' '}\n {new Date(product.updatedAt).toLocaleDateString()}\n </span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsReleaseDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProductsReleaseDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"names":[],"mappings":"AAiEA,wBAAgB,6BAA6B,4CAyM5C"}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as t } from "../people/People.js";
|
|
3
3
|
import { ReleaseHeaderActions as n } from "../controls/ReleaseControls.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
4
|
+
import { SatisfactionSummaryCard as r } from "../satisfaction/SatisfactionSummaryCard.js";
|
|
5
|
+
import { ReleaseNotesCard as i } from "../releases/ReleaseNotesCard.js";
|
|
6
|
+
import { ReleaseGatesCard as a } from "../releases/ReleaseGatesCard.js";
|
|
7
|
+
import { ReleaseReadinessCard as o } from "../releases/ReleaseReadinessCard.js";
|
|
8
|
+
import { ReleaseChecklistCard as s } from "../releases/ReleaseChecklistCard.js";
|
|
9
|
+
import { ReleaseWorkItemsCard as c } from "../releases/ReleaseWorkItemsCard.js";
|
|
10
|
+
import { Calendar as l, Clock as u, GitBranch as d, Loader2 as f } from "lucide-react";
|
|
11
|
+
import { useParams as p } from "react-router";
|
|
12
|
+
import { gql as m } from "@apollo/client";
|
|
13
|
+
import { useQuery as h } from "@apollo/client/react";
|
|
14
|
+
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
15
|
+
import { Badge as v, Card as y, CardContent as b, CardHeader as x, CardTitle as S } from "@burdenoff/fe-libs/ui";
|
|
16
|
+
import { Markdown as C } from "@burdenoff/fe-libs/shared/components";
|
|
16
17
|
//#region src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx
|
|
17
|
-
var
|
|
18
|
+
var w = m`
|
|
18
19
|
query GetRelease($id: ID!) {
|
|
19
20
|
planmagnetRelease(id: $id) {
|
|
20
21
|
id
|
|
@@ -41,7 +42,7 @@ var C = p`
|
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
|
-
`,
|
|
45
|
+
`, T = {
|
|
45
46
|
DRAFT: "bg-gray-100 text-gray-800",
|
|
46
47
|
PLANNING: "bg-yellow-100 text-yellow-800",
|
|
47
48
|
IN_PROGRESS: "bg-blue-100 text-blue-800",
|
|
@@ -50,109 +51,109 @@ var C = p`
|
|
|
50
51
|
CANCELLED: "bg-red-100 text-red-800",
|
|
51
52
|
ROLLED_BACK: "bg-red-100 text-red-800"
|
|
52
53
|
};
|
|
53
|
-
function
|
|
54
|
-
let { workspaceId:
|
|
55
|
-
variables: { id:
|
|
56
|
-
skip: !
|
|
54
|
+
function E() {
|
|
55
|
+
let { workspaceId: m } = e(), E = p().id ?? "", { data: D, loading: O, error: k } = h(w, {
|
|
56
|
+
variables: { id: E },
|
|
57
|
+
skip: !E
|
|
57
58
|
});
|
|
58
|
-
if (
|
|
59
|
+
if (O && !D) return /* @__PURE__ */ g("div", {
|
|
59
60
|
className: "flex items-center justify-center p-12",
|
|
60
|
-
children: /* @__PURE__ */
|
|
61
|
+
children: /* @__PURE__ */ g(f, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
61
62
|
});
|
|
62
|
-
if (
|
|
63
|
+
if (k) return /* @__PURE__ */ _("div", {
|
|
63
64
|
className: "p-6 text-destructive",
|
|
64
|
-
children: ["Failed to load release: ",
|
|
65
|
+
children: ["Failed to load release: ", k.message]
|
|
65
66
|
});
|
|
66
|
-
let
|
|
67
|
-
if (!
|
|
67
|
+
let A = D?.planmagnetRelease;
|
|
68
|
+
if (!A) return /* @__PURE__ */ g("div", {
|
|
68
69
|
className: "p-6 text-muted-foreground",
|
|
69
70
|
children: "Release not found."
|
|
70
71
|
});
|
|
71
|
-
let
|
|
72
|
-
return /* @__PURE__ */
|
|
72
|
+
let j = A.workItems ?? [], M = j.filter((e) => e.type === "EPIC" || e.type === "STORY"), N = j.filter((e) => e.type === "BUG"), P = j.length - M.length - N.length;
|
|
73
|
+
return /* @__PURE__ */ _("div", {
|
|
73
74
|
className: "space-y-6 p-6",
|
|
74
|
-
children: [/* @__PURE__ */
|
|
75
|
+
children: [/* @__PURE__ */ _("div", {
|
|
75
76
|
className: "flex items-center justify-between",
|
|
76
|
-
children: [/* @__PURE__ */
|
|
77
|
+
children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("div", {
|
|
77
78
|
className: "flex items-center gap-2",
|
|
78
79
|
children: [
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
/* @__PURE__ */
|
|
80
|
+
/* @__PURE__ */ g(d, { className: "h-5 w-5 text-primary" }),
|
|
81
|
+
/* @__PURE__ */ g("h1", {
|
|
81
82
|
className: "text-2xl font-semibold",
|
|
82
|
-
children:
|
|
83
|
+
children: A.version
|
|
83
84
|
}),
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
className: `text-xs px-2 py-0.5 rounded-full capitalize ${
|
|
86
|
-
children:
|
|
85
|
+
/* @__PURE__ */ g("span", {
|
|
86
|
+
className: `text-xs px-2 py-0.5 rounded-full capitalize ${T[A.status] ?? "bg-gray-100"}`,
|
|
87
|
+
children: A.status.toLowerCase().replace("_", " ")
|
|
87
88
|
})
|
|
88
89
|
]
|
|
89
|
-
}), /* @__PURE__ */
|
|
90
|
+
}), /* @__PURE__ */ g("p", {
|
|
90
91
|
className: "text-sm text-muted-foreground mt-1",
|
|
91
|
-
children:
|
|
92
|
-
})] }), /* @__PURE__ */
|
|
93
|
-
releaseId:
|
|
94
|
-
version:
|
|
95
|
-
status:
|
|
92
|
+
children: A.name
|
|
93
|
+
})] }), /* @__PURE__ */ g(n, {
|
|
94
|
+
releaseId: A.id,
|
|
95
|
+
version: A.version,
|
|
96
|
+
status: A.status
|
|
96
97
|
})]
|
|
97
|
-
}), /* @__PURE__ */
|
|
98
|
+
}), /* @__PURE__ */ _("div", {
|
|
98
99
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
100
|
+
children: [/* @__PURE__ */ _("div", {
|
|
100
101
|
className: "lg:col-span-2 space-y-6",
|
|
101
102
|
children: [
|
|
102
|
-
/* @__PURE__ */
|
|
103
|
-
releaseId:
|
|
104
|
-
projectId:
|
|
105
|
-
releaseStatus:
|
|
106
|
-
plannedDate:
|
|
103
|
+
/* @__PURE__ */ g(o, {
|
|
104
|
+
releaseId: A.id,
|
|
105
|
+
projectId: A.projectId || null,
|
|
106
|
+
releaseStatus: A.status,
|
|
107
|
+
plannedDate: A.plannedDate ?? null
|
|
107
108
|
}),
|
|
108
|
-
/* @__PURE__ */
|
|
109
|
-
releaseId:
|
|
110
|
-
projectId:
|
|
109
|
+
/* @__PURE__ */ g(s, {
|
|
110
|
+
releaseId: A.id,
|
|
111
|
+
projectId: A.projectId || null
|
|
111
112
|
}),
|
|
112
|
-
/* @__PURE__ */
|
|
113
|
+
/* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Overview" }) }), /* @__PURE__ */ _(b, {
|
|
113
114
|
className: "space-y-4",
|
|
114
|
-
children: [/* @__PURE__ */
|
|
115
|
+
children: [/* @__PURE__ */ g("div", {
|
|
115
116
|
className: "text-sm prose prose-sm dark:prose-invert max-w-none",
|
|
116
|
-
children:
|
|
117
|
-
}), /* @__PURE__ */
|
|
117
|
+
children: A.description ? /* @__PURE__ */ g(C, { children: A.description }) : /* @__PURE__ */ g("p", { children: "No description provided." })
|
|
118
|
+
}), /* @__PURE__ */ _("div", {
|
|
118
119
|
className: "grid grid-cols-4 gap-4",
|
|
119
120
|
children: [
|
|
120
|
-
/* @__PURE__ */
|
|
121
|
+
/* @__PURE__ */ _("div", {
|
|
121
122
|
className: "text-center p-3 bg-muted rounded-md",
|
|
122
|
-
children: [/* @__PURE__ */
|
|
123
|
+
children: [/* @__PURE__ */ g("p", {
|
|
123
124
|
className: "text-lg font-semibold mt-1",
|
|
124
|
-
children:
|
|
125
|
-
}), /* @__PURE__ */
|
|
125
|
+
children: M.length
|
|
126
|
+
}), /* @__PURE__ */ g("p", {
|
|
126
127
|
className: "text-xs text-muted-foreground",
|
|
127
128
|
children: "Features"
|
|
128
129
|
})]
|
|
129
130
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ _("div", {
|
|
131
132
|
className: "text-center p-3 bg-muted rounded-md",
|
|
132
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ g("p", {
|
|
133
134
|
className: "text-lg font-semibold mt-1",
|
|
134
|
-
children:
|
|
135
|
-
}), /* @__PURE__ */
|
|
135
|
+
children: N.length
|
|
136
|
+
}), /* @__PURE__ */ g("p", {
|
|
136
137
|
className: "text-xs text-muted-foreground",
|
|
137
138
|
children: "Bug Fixes"
|
|
138
139
|
})]
|
|
139
140
|
}),
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ _("div", {
|
|
141
142
|
className: "text-center p-3 bg-muted rounded-md",
|
|
142
|
-
children: [/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ g("p", {
|
|
143
144
|
className: "text-lg font-semibold mt-1",
|
|
144
|
-
children:
|
|
145
|
-
}), /* @__PURE__ */
|
|
145
|
+
children: P
|
|
146
|
+
}), /* @__PURE__ */ g("p", {
|
|
146
147
|
className: "text-xs text-muted-foreground",
|
|
147
148
|
children: "Other"
|
|
148
149
|
})]
|
|
149
150
|
}),
|
|
150
|
-
/* @__PURE__ */
|
|
151
|
+
/* @__PURE__ */ _("div", {
|
|
151
152
|
className: "text-center p-3 bg-muted rounded-md",
|
|
152
|
-
children: [/* @__PURE__ */
|
|
153
|
+
children: [/* @__PURE__ */ g("p", {
|
|
153
154
|
className: "text-lg font-semibold mt-1",
|
|
154
|
-
children:
|
|
155
|
-
}), /* @__PURE__ */
|
|
155
|
+
children: j.length
|
|
156
|
+
}), /* @__PURE__ */ g("p", {
|
|
156
157
|
className: "text-xs text-muted-foreground",
|
|
157
158
|
children: "Total Items"
|
|
158
159
|
})]
|
|
@@ -160,104 +161,105 @@ function T() {
|
|
|
160
161
|
]
|
|
161
162
|
})]
|
|
162
163
|
})] }),
|
|
163
|
-
/* @__PURE__ */
|
|
164
|
-
releaseId:
|
|
165
|
-
projectId:
|
|
166
|
-
releaseStatus:
|
|
164
|
+
/* @__PURE__ */ g(a, {
|
|
165
|
+
releaseId: A.id,
|
|
166
|
+
projectId: A.projectId ?? null,
|
|
167
|
+
releaseStatus: A.status
|
|
167
168
|
}),
|
|
168
|
-
/* @__PURE__ */
|
|
169
|
-
releaseId:
|
|
170
|
-
notes:
|
|
169
|
+
/* @__PURE__ */ g(i, {
|
|
170
|
+
releaseId: A.id,
|
|
171
|
+
notes: A.releaseNotes ?? null
|
|
171
172
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
173
|
-
releaseId:
|
|
174
|
-
projectId:
|
|
175
|
-
items:
|
|
173
|
+
/* @__PURE__ */ g(c, {
|
|
174
|
+
releaseId: A.id,
|
|
175
|
+
projectId: A.projectId || null,
|
|
176
|
+
items: j
|
|
176
177
|
})
|
|
177
178
|
]
|
|
178
|
-
}), /* @__PURE__ */
|
|
179
|
+
}), /* @__PURE__ */ _("div", {
|
|
179
180
|
className: "space-y-6",
|
|
180
181
|
children: [
|
|
181
|
-
/* @__PURE__ */ g(
|
|
182
|
+
/* @__PURE__ */ g(r, { scope: { releaseId: A.id } }),
|
|
183
|
+
/* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Timeline" }) }), /* @__PURE__ */ _(b, {
|
|
182
184
|
className: "space-y-3 text-sm",
|
|
183
|
-
children: [/* @__PURE__ */
|
|
185
|
+
children: [/* @__PURE__ */ _("div", {
|
|
184
186
|
className: "flex items-center gap-2",
|
|
185
187
|
children: [
|
|
186
|
-
/* @__PURE__ */
|
|
187
|
-
/* @__PURE__ */
|
|
188
|
+
/* @__PURE__ */ g(l, { className: "h-4 w-4 text-muted-foreground" }),
|
|
189
|
+
/* @__PURE__ */ g("span", {
|
|
188
190
|
className: "text-muted-foreground",
|
|
189
191
|
children: "Planned:"
|
|
190
192
|
}),
|
|
191
|
-
/* @__PURE__ */
|
|
193
|
+
/* @__PURE__ */ g("span", {
|
|
192
194
|
className: "font-medium",
|
|
193
|
-
children:
|
|
195
|
+
children: A.plannedDate ? new Date(A.plannedDate).toLocaleDateString() : "Not set"
|
|
194
196
|
})
|
|
195
197
|
]
|
|
196
|
-
}),
|
|
198
|
+
}), A.releasedAt && /* @__PURE__ */ _("div", {
|
|
197
199
|
className: "flex items-center gap-2",
|
|
198
200
|
children: [
|
|
199
|
-
/* @__PURE__ */
|
|
200
|
-
/* @__PURE__ */
|
|
201
|
+
/* @__PURE__ */ g(u, { className: "h-4 w-4 text-green-500" }),
|
|
202
|
+
/* @__PURE__ */ g("span", {
|
|
201
203
|
className: "text-muted-foreground",
|
|
202
204
|
children: "Released:"
|
|
203
205
|
}),
|
|
204
|
-
/* @__PURE__ */
|
|
206
|
+
/* @__PURE__ */ g("span", {
|
|
205
207
|
className: "font-medium",
|
|
206
|
-
children: new Date(
|
|
208
|
+
children: new Date(A.releasedAt).toLocaleDateString()
|
|
207
209
|
})
|
|
208
210
|
]
|
|
209
211
|
})]
|
|
210
212
|
})] }),
|
|
211
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Details" }) }), /* @__PURE__ */ _(b, {
|
|
212
214
|
className: "space-y-2 text-sm",
|
|
213
215
|
children: [
|
|
214
|
-
/* @__PURE__ */
|
|
216
|
+
/* @__PURE__ */ _("div", {
|
|
215
217
|
className: "flex justify-between",
|
|
216
|
-
children: [/* @__PURE__ */
|
|
218
|
+
children: [/* @__PURE__ */ g("span", {
|
|
217
219
|
className: "text-muted-foreground",
|
|
218
220
|
children: "Version"
|
|
219
|
-
}), /* @__PURE__ */
|
|
221
|
+
}), /* @__PURE__ */ g("span", {
|
|
220
222
|
className: "font-medium",
|
|
221
|
-
children:
|
|
223
|
+
children: A.version
|
|
222
224
|
})]
|
|
223
225
|
}),
|
|
224
|
-
/* @__PURE__ */
|
|
226
|
+
/* @__PURE__ */ _("div", {
|
|
225
227
|
className: "flex justify-between",
|
|
226
|
-
children: [/* @__PURE__ */
|
|
228
|
+
children: [/* @__PURE__ */ g("span", {
|
|
227
229
|
className: "text-muted-foreground",
|
|
228
230
|
children: "Status"
|
|
229
|
-
}), /* @__PURE__ */
|
|
231
|
+
}), /* @__PURE__ */ g(v, {
|
|
230
232
|
variant: "outline",
|
|
231
233
|
className: "text-xs capitalize",
|
|
232
|
-
children:
|
|
234
|
+
children: A.status.toLowerCase().replace("_", " ")
|
|
233
235
|
})]
|
|
234
236
|
}),
|
|
235
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ _("div", {
|
|
236
238
|
className: "flex justify-between",
|
|
237
|
-
children: [/* @__PURE__ */
|
|
239
|
+
children: [/* @__PURE__ */ g("span", {
|
|
238
240
|
className: "text-muted-foreground",
|
|
239
241
|
children: "Owner"
|
|
240
|
-
}), /* @__PURE__ */
|
|
242
|
+
}), /* @__PURE__ */ g("span", { children: /* @__PURE__ */ g(t, { id: A.ownerId }) })]
|
|
241
243
|
}),
|
|
242
|
-
/* @__PURE__ */
|
|
244
|
+
/* @__PURE__ */ _("div", {
|
|
243
245
|
className: "flex justify-between",
|
|
244
|
-
children: [/* @__PURE__ */
|
|
246
|
+
children: [/* @__PURE__ */ g("span", {
|
|
245
247
|
className: "text-muted-foreground",
|
|
246
248
|
children: "Created"
|
|
247
|
-
}), /* @__PURE__ */
|
|
249
|
+
}), /* @__PURE__ */ g("span", { children: new Date(A.createdAt).toLocaleDateString() })]
|
|
248
250
|
}),
|
|
249
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ _("div", {
|
|
250
252
|
className: "flex justify-between",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ g("span", {
|
|
252
254
|
className: "text-muted-foreground",
|
|
253
255
|
children: "Updated"
|
|
254
|
-
}), /* @__PURE__ */
|
|
256
|
+
}), /* @__PURE__ */ g("span", { children: new Date(A.updatedAt).toLocaleDateString() })]
|
|
255
257
|
})
|
|
256
258
|
]
|
|
257
259
|
})] }),
|
|
258
|
-
|
|
260
|
+
A.tags?.length > 0 && /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Tags" }) }), /* @__PURE__ */ g(b, {
|
|
259
261
|
className: "flex flex-wrap gap-1",
|
|
260
|
-
children:
|
|
262
|
+
children: A.tags.map((e) => /* @__PURE__ */ g(v, {
|
|
261
263
|
variant: "outline",
|
|
262
264
|
className: "text-xs",
|
|
263
265
|
children: e
|
|
@@ -269,6 +271,6 @@ function T() {
|
|
|
269
271
|
});
|
|
270
272
|
}
|
|
271
273
|
//#endregion
|
|
272
|
-
export {
|
|
274
|
+
export { E as ProductsReleaseDetailPagePage };
|
|
273
275
|
|
|
274
276
|
//# sourceMappingURL=ProductsReleaseDetailPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsReleaseDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { GitBranch, Calendar, Clock, Server, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { ReleaseNotesCard } from '../releases/ReleaseNotesCard';\nimport { ReleaseHeaderActions } from '../controls/ReleaseControls';\nimport { ReleaseGatesCard } from '../releases/ReleaseGatesCard';\nimport { ReleaseReadinessCard } from '../releases/ReleaseReadinessCard';\nimport { ReleaseChecklistCard } from '../releases/ReleaseChecklistCard';\nimport { ReleaseWorkItemsCard } from '../releases/ReleaseWorkItemsCard';\n\nconst GET_RELEASE = gql`\n query GetRelease($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n metadata\n createdAt\n updatedAt\n workItems {\n id\n title\n status\n type\n priority\n }\n }\n }\n`;\n\ninterface WorkItemSummary {\n id: string;\n title: string;\n status: string;\n type: string;\n priority: string;\n}\n\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleaseDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const releaseId = params.id ?? '';\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_RELEASE, {\n variables: { id: releaseId },\n skip: !releaseId,\n });\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load release: {error.message}</div>;\n }\n\n const release = data?.planmagnetRelease;\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n const workItems: WorkItemSummary[] = release.workItems ?? [];\n // The release notes' classification (svc release-notes.ts): EPIC and STORY are features, BUG a fix, the rest other\n // — so these tiles agree with the notes on the same page and add up to the total (BOFF-7988).\n const featureItems = workItems.filter((w) => w.type === 'EPIC' || w.type === 'STORY');\n const bugItems = workItems.filter((w) => w.type === 'BUG');\n const otherItems = workItems.length - featureItems.length - bugItems.length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <GitBranch className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{release.version}</h1>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{release.name}</p>\n </div>\n {/* Status, Edit and Delete (BOFF-7952): nothing could release, edit or delete a release. */}\n <ReleaseHeaderActions\n releaseId={release.id}\n version={release.version}\n status={release.status}\n />\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <ReleaseReadinessCard\n releaseId={release.id}\n projectId={release.projectId || null}\n releaseStatus={release.status}\n plannedDate={release.plannedDate ?? null}\n />\n {/* PRM-19: the team's readiness criteria; a required one still open blocks releasing. */}\n <ReleaseChecklistCard releaseId={release.id} projectId={release.projectId || null} />\n <Card>\n <CardHeader>\n <CardTitle>Overview</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n {release.description ? (\n <Markdown>{release.description}</Markdown>\n ) : (\n <p>No description provided.</p>\n )}\n </div>\n <div className=\"grid grid-cols-4 gap-4\">\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{featureItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Features</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{bugItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Bug Fixes</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{otherItems}</p>\n <p className=\"text-xs text-muted-foreground\">Other</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{workItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Total Items</p>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ReleaseGatesCard\n releaseId={release.id}\n projectId={release.projectId ?? null}\n releaseStatus={release.status}\n />\n <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n <ReleaseWorkItemsCard\n releaseId={release.id}\n projectId={release.projectId || null}\n items={workItems}\n />\n </div>\n\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Timeline</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Planned:</span>\n <span className=\"font-medium\">\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'Not set'}\n </span>\n </div>\n {release.releasedAt && (\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-green-500\" />\n <span className=\"text-muted-foreground\">Released:</span>\n <span className=\"font-medium\">\n {new Date(release.releasedAt).toLocaleDateString()}\n </span>\n </div>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Version</span>\n <span className=\"font-medium\">{release.version}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={release.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(release.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(release.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {release.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {release.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductsReleaseDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { GitBranch, Calendar, Clock, Server, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { ReleaseNotesCard } from '../releases/ReleaseNotesCard';\nimport { ReleaseHeaderActions } from '../controls/ReleaseControls';\nimport { ReleaseGatesCard } from '../releases/ReleaseGatesCard';\nimport { ReleaseReadinessCard } from '../releases/ReleaseReadinessCard';\nimport { ReleaseChecklistCard } from '../releases/ReleaseChecklistCard';\nimport { ReleaseWorkItemsCard } from '../releases/ReleaseWorkItemsCard';\nimport { SatisfactionSummaryCard } from '../satisfaction/SatisfactionSummaryCard';\n\nconst GET_RELEASE = gql`\n query GetRelease($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n metadata\n createdAt\n updatedAt\n workItems {\n id\n title\n status\n type\n priority\n }\n }\n }\n`;\n\ninterface WorkItemSummary {\n id: string;\n title: string;\n status: string;\n type: string;\n priority: string;\n}\n\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleaseDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const releaseId = params.id ?? '';\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_RELEASE, {\n variables: { id: releaseId },\n skip: !releaseId,\n });\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load release: {error.message}</div>;\n }\n\n const release = data?.planmagnetRelease;\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n const workItems: WorkItemSummary[] = release.workItems ?? [];\n // The release notes' classification (svc release-notes.ts): EPIC and STORY are features, BUG a fix, the rest other\n // — so these tiles agree with the notes on the same page and add up to the total (BOFF-7988).\n const featureItems = workItems.filter((w) => w.type === 'EPIC' || w.type === 'STORY');\n const bugItems = workItems.filter((w) => w.type === 'BUG');\n const otherItems = workItems.length - featureItems.length - bugItems.length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <GitBranch className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{release.version}</h1>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{release.name}</p>\n </div>\n {/* Status, Edit and Delete (BOFF-7952): nothing could release, edit or delete a release. */}\n <ReleaseHeaderActions\n releaseId={release.id}\n version={release.version}\n status={release.status}\n />\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <ReleaseReadinessCard\n releaseId={release.id}\n projectId={release.projectId || null}\n releaseStatus={release.status}\n plannedDate={release.plannedDate ?? null}\n />\n {/* PRM-19: the team's readiness criteria; a required one still open blocks releasing. */}\n <ReleaseChecklistCard releaseId={release.id} projectId={release.projectId || null} />\n <Card>\n <CardHeader>\n <CardTitle>Overview</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n {release.description ? (\n <Markdown>{release.description}</Markdown>\n ) : (\n <p>No description provided.</p>\n )}\n </div>\n <div className=\"grid grid-cols-4 gap-4\">\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{featureItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Features</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{bugItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Bug Fixes</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{otherItems}</p>\n <p className=\"text-xs text-muted-foreground\">Other</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{workItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Total Items</p>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ReleaseGatesCard\n releaseId={release.id}\n projectId={release.projectId ?? null}\n releaseStatus={release.status}\n />\n <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n <ReleaseWorkItemsCard\n releaseId={release.id}\n projectId={release.projectId || null}\n items={workItems}\n />\n </div>\n\n <div className=\"space-y-6\">\n {/* ANR-21: CSAT and NPS from responses about this release (its own query). */}\n <SatisfactionSummaryCard scope={{ releaseId: release.id }} />\n <Card>\n <CardHeader>\n <CardTitle>Timeline</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Planned:</span>\n <span className=\"font-medium\">\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'Not set'}\n </span>\n </div>\n {release.releasedAt && (\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-green-500\" />\n <span className=\"text-muted-foreground\">Released:</span>\n <span className=\"font-medium\">\n {new Date(release.releasedAt).toLocaleDateString()}\n </span>\n </div>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Version</span>\n <span className=\"font-medium\">{release.version}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={release.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(release.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(release.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {release.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {release.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AAuGA,wBAAgB,8BAA8B,4CA4X7C"}
|