@burdenoff/microfe-planmagnet 2026.930.25 → 2026.1001.2
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/_virtual/__vite-browser-external.js +9 -0
- package/dist/_virtual/__vite-browser-external.js.map +1 -0
- package/dist/_virtual/_rolldown/runtime.js +5 -2
- package/dist/index.js +3 -1
- package/dist/node_modules/fflate/esm/browser.js +554 -0
- package/dist/node_modules/fflate/esm/browser.js.map +1 -0
- package/dist/node_modules/jszip/dist/jszip.min.js +3038 -0
- package/dist/node_modules/jszip/dist/jszip.min.js.map +1 -0
- package/dist/node_modules/pptxgenjs/dist/pptxgen.es.js +2151 -0
- package/dist/node_modules/pptxgenjs/dist/pptxgen.es.js.map +1 -0
- package/dist/node_modules/write-excel-file/browser/index.js +3 -0
- package/dist/node_modules/write-excel-file/modules/export/convertFileContentToUint8ArrayBrowser.js +13 -0
- package/dist/node_modules/write-excel-file/modules/export/convertFileContentToUint8ArrayBrowser.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/export/convertFilesContentToUint8Arrays.js +21 -0
- package/dist/node_modules/write-excel-file/modules/export/convertFilesContentToUint8Arrays.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/export/downloadBlob.js +11 -0
- package/dist/node_modules/write-excel-file/modules/export/downloadBlob.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileBrowser.js +23 -0
- package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileBrowser.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileUniversal.js +22 -0
- package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileUniversal.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/getSheetData/getSheetData.js +18 -0
- package/dist/node_modules/write-excel-file/modules/getSheetData/getSheetData.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/features/conditionalFormatting.js +131 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/features/conditionalFormatting.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/features/images.js +188 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/features/images.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/features/stickyRowsOrColumns.js +52 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/features/stickyRowsOrColumns.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/_Content_Types_.xml.js +18 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/_Content_Types_.xml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.js +18 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.rels.js +17 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.rels.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/rels.js +11 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/rels.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sharedStrings.xml.js +42 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sharedStrings.xml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/cell.js +102 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/cell.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/column.js +17 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/column.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/columns.js +15 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/columns.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/drawingReference.js +8 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/drawingReference.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/helpers/getCellStyleProperties.js +71 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/helpers/getCellStyleProperties.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/mergedCellsDescription.js +56 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/mergedCellsDescription.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageMargins.js +15 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageMargins.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageSetup.js +13 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageSetup.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/processMergedCells.js +44 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/processMergedCells.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/row.js +123 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/row.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheet.xml.js +41 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheet.xml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetData.js +11 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetData.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetViews.js +17 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetViews.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml.rels.js +20 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml.rels.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/styles.xml.js +77 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/styles.xml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.js +22 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.rels.js +13 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.rels.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/generateXlsxFileContents.js +242 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/generateXlsxFileContents.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/getFeatures.js +29 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/getFeatures.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/convertDateToSerialNumber.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/convertDateToSerialNumber.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js +42 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getElementXml.js +43 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getElementXml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getWrittenFiles.js +93 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getWrittenFiles.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/transformContent.js +39 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/transformContent.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getAlignmentXml.js +17 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getAlignmentXml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getBorderXml.js +29 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getBorderXml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getCellAddress.js +14 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getCellAddress.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFileExtensionForContentType.js +11 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFileExtensionForContentType.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFillXml.js +14 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFillXml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFontXml.js +12 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFontXml.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getOrderOfSiblings.js +24 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getOrderOfSiblings.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getXlsxColorForHexColor.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getXlsxColorForHexColor.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasAlignment.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasAlignment.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasBorder.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasBorder.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFill.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFill.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFont.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFont.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isCellObject.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isCellObject.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isObject.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isObject.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/orderOfSiblings.js +27 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/helpers/orderOfSiblings.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/initializeSharedStrings.js +17 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/initializeSharedStrings.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/initializeSheets.js +74 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/initializeSheets.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/initializeStyles.js +138 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/initializeStyles.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetData.js +40 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetData.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetName.js +11 -0
- package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetName.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/appendMarkupInsideElement.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xml/appendMarkupInsideElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/applyEnclosingElementOffset.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xml/applyEnclosingElementOffset.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/escapeXmlSpecialCharacters.js +12 -0
- package/dist/node_modules/write-excel-file/modules/xml/escapeXmlSpecialCharacters.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/findElement.js +12 -0
- package/dist/node_modules/write-excel-file/modules/xml/findElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/findElementInsideElement.js +12 -0
- package/dist/node_modules/write-excel-file/modules/xml/findElementInsideElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/findElementsNonRecursive_.js +41 -0
- package/dist/node_modules/write-excel-file/modules/xml/findElementsNonRecursive_.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/getAttributesString.js +14 -0
- package/dist/node_modules/write-excel-file/modules/xml/getAttributesString.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/getChildElements.js +42 -0
- package/dist/node_modules/write-excel-file/modules/xml/getChildElements.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/getClosingTagMarkup.js +8 -0
- package/dist/node_modules/write-excel-file/modules/xml/getClosingTagMarkup.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/getMarkupInsideElement.js +8 -0
- package/dist/node_modules/write-excel-file/modules/xml/getMarkupInsideElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/getOpeningTagMarkup.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xml/getOpeningTagMarkup.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/getSelfClosingTagMarkup.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xml/getSelfClosingTagMarkup.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/insertElementMarkupAccordingToOrderOfSiblings.js +64 -0
- package/dist/node_modules/write-excel-file/modules/xml/insertElementMarkupAccordingToOrderOfSiblings.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/prependMarkupInsideElement.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xml/prependMarkupInsideElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/removeInvalidXmlCharacters.js +9 -0
- package/dist/node_modules/write-excel-file/modules/xml/removeInvalidXmlCharacters.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/replaceElement.js +8 -0
- package/dist/node_modules/write-excel-file/modules/xml/replaceElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeName.js +10 -0
- package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeName.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeValue.js +11 -0
- package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeValue.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/sanitizeTextContent.js +11 -0
- package/dist/node_modules/write-excel-file/modules/xml/sanitizeTextContent.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/xml/setMarkupInsideElement.js +8 -0
- package/dist/node_modules/write-excel-file/modules/xml/setMarkupInsideElement.js.map +1 -0
- package/dist/node_modules/write-excel-file/modules/zip/zipToArrayBuffer.js +18 -0
- package/dist/node_modules/write-excel-file/modules/zip/zipToArrayBuffer.js.map +1 -0
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +160 -147
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +126 -106
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/comments/CommentThread.js +36 -36
- package/dist/planmagnet/comments/RoadmapComments.js +21 -21
- package/dist/planmagnet/controls/AutomationRuleControls.js +24 -24
- package/dist/planmagnet/controls/FeatureControls.js +60 -60
- package/dist/planmagnet/controls/Pickers.d.ts +10 -0
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +75 -27
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/controls/SyncControls.js +59 -59
- package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js +15 -15
- package/dist/planmagnet/docs/DocSuggestionsPanel.js +12 -12
- package/dist/planmagnet/docs/DocVersionCompare.js +3 -3
- package/dist/planmagnet/forecast/DeliveryForecastCard.d.ts +12 -0
- package/dist/planmagnet/forecast/DeliveryForecastCard.d.ts.map +1 -0
- package/dist/planmagnet/forecast/DeliveryForecastCard.js +208 -0
- package/dist/planmagnet/forecast/DeliveryForecastCard.js.map +1 -0
- package/dist/planmagnet/forecast/ProjectOutlookCard.d.ts +5 -0
- package/dist/planmagnet/forecast/ProjectOutlookCard.d.ts.map +1 -0
- package/dist/planmagnet/forecast/ProjectOutlookCard.js +190 -0
- package/dist/planmagnet/forecast/ProjectOutlookCard.js.map +1 -0
- package/dist/planmagnet/forecast/ProjectRiskSummaryCard.d.ts +5 -0
- package/dist/planmagnet/forecast/ProjectRiskSummaryCard.d.ts.map +1 -0
- package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js +99 -0
- package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js.map +1 -0
- package/dist/planmagnet/forecast/ResourceForecastCard.d.ts +8 -0
- package/dist/planmagnet/forecast/ResourceForecastCard.d.ts.map +1 -0
- package/dist/planmagnet/forecast/ResourceForecastCard.js +185 -0
- package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -0
- package/dist/planmagnet/forecast/riskFlags.d.ts +35 -0
- package/dist/planmagnet/forecast/riskFlags.d.ts.map +1 -0
- package/dist/planmagnet/forecast/riskFlags.js +37 -0
- package/dist/planmagnet/forecast/riskFlags.js.map +1 -0
- package/dist/planmagnet/index.d.ts +2 -0
- package/dist/planmagnet/index.d.ts.map +1 -1
- package/dist/planmagnet/index.js +2 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +216 -182
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js +11 -11
- package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js +4 -4
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js +163 -163
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/IntegrationsNewSyncPagePage.js +165 -165
- package/dist/planmagnet/pages/IntegrationsNewSyncPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsAtRiskPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsAtRiskPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js +234 -0
- package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +206 -182
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts +6 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js +5 -177
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ReportsEditReportPagePage.d.ts +3 -0
- package/dist/planmagnet/pages/ReportsEditReportPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsEditReportPagePage.js +15 -0
- package/dist/planmagnet/pages/ReportsEditReportPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ReportsReportPagePage.d.ts +7 -0
- package/dist/planmagnet/pages/ReportsReportPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsReportPagePage.js +226 -0
- package/dist/planmagnet/pages/ReportsReportPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ReportsReportsPagePage.js +224 -496
- package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.js +88 -83
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/analytics/SprintDeliveryCards.d.ts.map +1 -1
- package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js +139 -112
- package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js.map +1 -1
- package/dist/planmagnet/pages/analytics/StatusFlowCard.js +21 -21
- package/dist/planmagnet/product/ProductControls.js +91 -91
- package/dist/planmagnet/reports/ExportMenu.d.ts +9 -0
- package/dist/planmagnet/reports/ExportMenu.d.ts.map +1 -0
- package/dist/planmagnet/reports/ExportMenu.js +116 -0
- package/dist/planmagnet/reports/ExportMenu.js.map +1 -0
- package/dist/planmagnet/reports/PrintReportView.d.ts +24 -0
- package/dist/planmagnet/reports/PrintReportView.d.ts.map +1 -0
- package/dist/planmagnet/reports/PrintReportView.js +75 -0
- package/dist/planmagnet/reports/PrintReportView.js.map +1 -0
- package/dist/planmagnet/reports/ReportBuilderCanvas.d.ts +8 -0
- package/dist/planmagnet/reports/ReportBuilderCanvas.d.ts.map +1 -0
- package/dist/planmagnet/reports/ReportBuilderCanvas.js +261 -0
- package/dist/planmagnet/reports/ReportBuilderCanvas.js.map +1 -0
- package/dist/planmagnet/reports/ReportBuilderPage.d.ts +5 -0
- package/dist/planmagnet/reports/ReportBuilderPage.d.ts.map +1 -0
- package/dist/planmagnet/reports/ReportBuilderPage.js +198 -0
- package/dist/planmagnet/reports/ReportBuilderPage.js.map +1 -0
- package/dist/planmagnet/reports/ReportRunHistory.d.ts +8 -0
- package/dist/planmagnet/reports/ReportRunHistory.d.ts.map +1 -0
- package/dist/planmagnet/reports/ReportRunHistory.js +63 -0
- package/dist/planmagnet/reports/ReportRunHistory.js.map +1 -0
- package/dist/planmagnet/reports/ReportWidgetRenderer.d.ts +7 -0
- package/dist/planmagnet/reports/ReportWidgetRenderer.d.ts.map +1 -0
- package/dist/planmagnet/reports/ReportWidgetRenderer.js +251 -0
- package/dist/planmagnet/reports/ReportWidgetRenderer.js.map +1 -0
- package/dist/planmagnet/reports/SchedulesPanel.d.ts +4 -0
- package/dist/planmagnet/reports/SchedulesPanel.d.ts.map +1 -0
- package/dist/planmagnet/reports/SchedulesPanel.js +457 -0
- package/dist/planmagnet/reports/SchedulesPanel.js.map +1 -0
- package/dist/planmagnet/reports/ShareDialog.d.ts +5 -0
- package/dist/planmagnet/reports/ShareDialog.d.ts.map +1 -0
- package/dist/planmagnet/reports/ShareDialog.js +234 -0
- package/dist/planmagnet/reports/ShareDialog.js.map +1 -0
- package/dist/planmagnet/reports/SharedReportPage.d.ts +4 -0
- package/dist/planmagnet/reports/SharedReportPage.d.ts.map +1 -0
- package/dist/planmagnet/reports/SharedReportPage.js +180 -0
- package/dist/planmagnet/reports/SharedReportPage.js.map +1 -0
- package/dist/planmagnet/reports/WidgetEditorDialog.d.ts +10 -0
- package/dist/planmagnet/reports/WidgetEditorDialog.d.ts.map +1 -0
- package/dist/planmagnet/reports/WidgetEditorDialog.js +220 -0
- package/dist/planmagnet/reports/WidgetEditorDialog.js.map +1 -0
- package/dist/planmagnet/reports/reportExportPptx.d.ts +4 -0
- package/dist/planmagnet/reports/reportExportPptx.d.ts.map +1 -0
- package/dist/planmagnet/reports/reportExportPptx.js +118 -0
- package/dist/planmagnet/reports/reportExportPptx.js.map +1 -0
- package/dist/planmagnet/reports/reportExportXlsx.d.ts +4 -0
- package/dist/planmagnet/reports/reportExportXlsx.d.ts.map +1 -0
- package/dist/planmagnet/reports/reportExportXlsx.js +42 -0
- package/dist/planmagnet/reports/reportExportXlsx.js.map +1 -0
- package/dist/planmagnet/reports/reportGraphql.d.ts +28 -0
- package/dist/planmagnet/reports/reportGraphql.d.ts.map +1 -0
- package/dist/planmagnet/reports/reportGraphql.js +360 -0
- package/dist/planmagnet/reports/reportGraphql.js.map +1 -0
- package/dist/planmagnet/reports/reportModel.d.ts +198 -0
- package/dist/planmagnet/reports/reportModel.d.ts.map +1 -0
- package/dist/planmagnet/reports/reportModel.js +328 -0
- package/dist/planmagnet/reports/reportModel.js.map +1 -0
- package/dist/planmagnet/reports/sharedReportRoute.d.ts +15 -0
- package/dist/planmagnet/reports/sharedReportRoute.d.ts.map +1 -0
- package/dist/planmagnet/reports/sharedReportRoute.js +9 -0
- package/dist/planmagnet/reports/sharedReportRoute.js.map +1 -0
- package/dist/planmagnet/roadmaps/RoadmapControls.js +60 -60
- package/dist/planmagnet/roadmaps/RoadmapNowNextLater.js +30 -30
- package/dist/planmagnet/roadmaps/RoadmapReviewPanel.js +21 -21
- package/dist/planmagnet/roadmaps/RoadmapVersionsPanel.js +22 -22
- package/package.json +6 -4
|
@@ -3,20 +3,21 @@ import { Tooltip as t } from "../../../node_modules/recharts/es6/component/Toolt
|
|
|
3
3
|
import { ResponsiveContainer as n } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
|
|
4
4
|
import { Bar as r } from "../../../node_modules/recharts/es6/cartesian/Bar.js";
|
|
5
5
|
import { ReferenceLine as i } from "../../../node_modules/recharts/es6/cartesian/ReferenceLine.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
6
|
+
import { ReferenceArea as a } from "../../../node_modules/recharts/es6/cartesian/ReferenceArea.js";
|
|
7
|
+
import { CartesianGrid as o } from "../../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
|
|
8
|
+
import { Line as s } from "../../../node_modules/recharts/es6/cartesian/Line.js";
|
|
9
|
+
import { XAxis as c } from "../../../node_modules/recharts/es6/cartesian/XAxis.js";
|
|
10
|
+
import { YAxis as l } from "../../../node_modules/recharts/es6/cartesian/YAxis.js";
|
|
11
|
+
import { LineChart as u } from "../../../node_modules/recharts/es6/chart/LineChart.js";
|
|
12
|
+
import { BarChart as d } from "../../../node_modules/recharts/es6/chart/BarChart.js";
|
|
13
|
+
import { BarChart3 as f, TrendingUp as p } from "lucide-react";
|
|
14
|
+
import { gql as m } from "@apollo/client";
|
|
15
|
+
import { useQuery as h } from "@apollo/client/react";
|
|
16
|
+
import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
17
|
+
import { useI18n as y } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
18
|
+
import { Card as b, CardContent as x, CardHeader as S, CardTitle as C } from "@burdenoff/fe-libs/ui";
|
|
18
19
|
//#region src/planmagnet/pages/analytics/SprintDeliveryCards.tsx
|
|
19
|
-
var
|
|
20
|
+
var w = m`
|
|
20
21
|
query DashboardSprintBurndown($workspaceId: ID!, $sprintId: ID!) {
|
|
21
22
|
planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {
|
|
22
23
|
sprintId
|
|
@@ -29,7 +30,7 @@ var C = p`
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
`,
|
|
33
|
+
`, T = m`
|
|
33
34
|
query DashboardVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {
|
|
34
35
|
planmagnetVelocity(
|
|
35
36
|
workspaceId: $workspaceId
|
|
@@ -39,6 +40,11 @@ var C = p`
|
|
|
39
40
|
projectId
|
|
40
41
|
averageVelocity
|
|
41
42
|
forecastNextSprintPoints
|
|
43
|
+
forecastRange {
|
|
44
|
+
p15
|
|
45
|
+
p85
|
|
46
|
+
}
|
|
47
|
+
insufficientHistory
|
|
42
48
|
sprints {
|
|
43
49
|
sprintId
|
|
44
50
|
sprintName
|
|
@@ -49,171 +55,192 @@ var C = p`
|
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
`;
|
|
52
|
-
function
|
|
58
|
+
function E(e) {
|
|
53
59
|
let t = new Date(e);
|
|
54
60
|
return `${t.getUTCMonth() + 1}/${t.getUTCDate()}`;
|
|
55
61
|
}
|
|
56
|
-
function
|
|
57
|
-
let { t:
|
|
62
|
+
function D({ workspaceId: r, sprintId: i }) {
|
|
63
|
+
let { t: a } = y(), { data: d, loading: p, error: m } = h(w, {
|
|
58
64
|
variables: {
|
|
59
65
|
workspaceId: r,
|
|
60
66
|
sprintId: i
|
|
61
67
|
},
|
|
62
68
|
skip: !r || !i
|
|
63
|
-
}),
|
|
64
|
-
day:
|
|
69
|
+
}), g = (d?.planmagnetSprintBurndown?.points ?? []).map((e) => ({
|
|
70
|
+
day: E(e.date),
|
|
65
71
|
remaining: e.remainingPoints,
|
|
66
72
|
completed: e.completedPoints
|
|
67
73
|
}));
|
|
68
|
-
return /* @__PURE__ */
|
|
74
|
+
return /* @__PURE__ */ v(b, { children: [/* @__PURE__ */ v(S, { children: [/* @__PURE__ */ v(C, {
|
|
69
75
|
className: "flex items-center gap-2",
|
|
70
|
-
children: [/* @__PURE__ */
|
|
71
|
-
}), /* @__PURE__ */
|
|
76
|
+
children: [/* @__PURE__ */ _(f, { className: "h-4 w-4" }), a("planmagnet.dashboards.burndown.title", "Sprint burndown")]
|
|
77
|
+
}), /* @__PURE__ */ _("p", {
|
|
72
78
|
className: "text-xs text-muted-foreground",
|
|
73
|
-
children:
|
|
74
|
-
})] }), /* @__PURE__ */
|
|
79
|
+
children: a("planmagnet.dashboards.burndown.subtitle", "Remaining vs. completed story points, by day of the sprint.")
|
|
80
|
+
})] }), /* @__PURE__ */ _(x, { children: i ? p && !d ? /* @__PURE__ */ _("p", {
|
|
75
81
|
className: "text-sm text-muted-foreground",
|
|
76
|
-
children:
|
|
77
|
-
}) :
|
|
82
|
+
children: a("planmagnet.dashboards.loading", "Loading…")
|
|
83
|
+
}) : m ? /* @__PURE__ */ v("p", {
|
|
78
84
|
className: "text-sm text-status-error-text",
|
|
79
85
|
children: [
|
|
80
|
-
|
|
86
|
+
a("planmagnet.dashboards.burndown.error", "Burndown could not be loaded"),
|
|
81
87
|
":",
|
|
82
88
|
" ",
|
|
83
|
-
|
|
89
|
+
m.message
|
|
84
90
|
]
|
|
85
|
-
}) :
|
|
91
|
+
}) : g.length === 0 ? /* @__PURE__ */ _("p", {
|
|
86
92
|
className: "text-sm text-muted-foreground",
|
|
87
|
-
children:
|
|
88
|
-
}) : /* @__PURE__ */
|
|
93
|
+
children: a("planmagnet.dashboards.burndown.empty", "The active sprint has no work items yet.")
|
|
94
|
+
}) : /* @__PURE__ */ _(n, {
|
|
89
95
|
width: "100%",
|
|
90
96
|
height: 220,
|
|
91
|
-
children: /* @__PURE__ */
|
|
92
|
-
data:
|
|
97
|
+
children: /* @__PURE__ */ v(u, {
|
|
98
|
+
data: g,
|
|
93
99
|
children: [
|
|
94
|
-
/* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ _(o, {
|
|
95
101
|
strokeDasharray: "3 3",
|
|
96
102
|
opacity: .2
|
|
97
103
|
}),
|
|
98
|
-
/* @__PURE__ */
|
|
104
|
+
/* @__PURE__ */ _(c, {
|
|
99
105
|
dataKey: "day",
|
|
100
106
|
tick: { fontSize: 11 }
|
|
101
107
|
}),
|
|
102
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ _(l, {
|
|
103
109
|
tick: { fontSize: 11 },
|
|
104
110
|
allowDecimals: !1
|
|
105
111
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
/* @__PURE__ */
|
|
108
|
-
/* @__PURE__ */
|
|
112
|
+
/* @__PURE__ */ _(t, {}),
|
|
113
|
+
/* @__PURE__ */ _(e, { wrapperStyle: { fontSize: 12 } }),
|
|
114
|
+
/* @__PURE__ */ _(s, {
|
|
109
115
|
type: "monotone",
|
|
110
116
|
dataKey: "remaining",
|
|
111
|
-
name:
|
|
117
|
+
name: a("planmagnet.dashboards.burndown.remaining", "Remaining points"),
|
|
112
118
|
stroke: "#f59e0b",
|
|
113
119
|
strokeWidth: 2,
|
|
114
120
|
dot: { r: 2 }
|
|
115
121
|
}),
|
|
116
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ _(s, {
|
|
117
123
|
type: "monotone",
|
|
118
124
|
dataKey: "completed",
|
|
119
|
-
name:
|
|
125
|
+
name: a("planmagnet.dashboards.burndown.completed", "Completed points"),
|
|
120
126
|
stroke: "#22c55e",
|
|
121
127
|
strokeWidth: 2,
|
|
122
128
|
dot: { r: 2 }
|
|
123
129
|
})
|
|
124
130
|
]
|
|
125
131
|
})
|
|
126
|
-
}) : /* @__PURE__ */
|
|
132
|
+
}) : /* @__PURE__ */ _("p", {
|
|
127
133
|
className: "text-sm text-muted-foreground",
|
|
128
|
-
children:
|
|
134
|
+
children: a("planmagnet.dashboards.burndown.noSprint", "No active sprint for this project.")
|
|
129
135
|
}) })] });
|
|
130
136
|
}
|
|
131
|
-
function
|
|
132
|
-
let { t:
|
|
137
|
+
function O({ workspaceId: s, projectId: u, trailingSprintCount: f = 6 }) {
|
|
138
|
+
let { t: m } = y(), { data: w, loading: E, error: D } = h(T, {
|
|
133
139
|
variables: {
|
|
134
|
-
workspaceId:
|
|
135
|
-
projectId:
|
|
136
|
-
trailingSprintCount:
|
|
140
|
+
workspaceId: s,
|
|
141
|
+
projectId: u,
|
|
142
|
+
trailingSprintCount: f
|
|
137
143
|
},
|
|
138
|
-
skip: !
|
|
139
|
-
}),
|
|
144
|
+
skip: !s || !u
|
|
145
|
+
}), O = w?.planmagnetVelocity, k = O?.sprints.map((e) => ({
|
|
140
146
|
name: e.sprintName,
|
|
141
147
|
completed: e.completedPoints,
|
|
142
148
|
planned: e.plannedPoints ?? void 0
|
|
143
|
-
})) ?? [],
|
|
144
|
-
return /* @__PURE__ */
|
|
149
|
+
})) ?? [], A = O ? Math.round(O.averageVelocity) : 0, j = O ? Math.round(O.forecastNextSprintPoints) : 0, M = O?.forecastRange ?? null, N = O?.insufficientHistory ?? !1;
|
|
150
|
+
return /* @__PURE__ */ v(b, { children: [/* @__PURE__ */ v(S, { children: [/* @__PURE__ */ v(C, {
|
|
145
151
|
className: "flex items-center gap-2",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
147
|
-
}), /* @__PURE__ */
|
|
152
|
+
children: [/* @__PURE__ */ _(p, { className: "h-4 w-4" }), m("planmagnet.dashboards.velocity.title", "Sprint velocity")]
|
|
153
|
+
}), /* @__PURE__ */ _("p", {
|
|
148
154
|
className: "text-xs text-muted-foreground",
|
|
149
|
-
children:
|
|
150
|
-
})] }), /* @__PURE__ */
|
|
155
|
+
children: m("planmagnet.dashboards.velocity.subtitle", "Completed story points per sprint, across the trailing {{count}} completed sprints.", { count: f })
|
|
156
|
+
})] }), /* @__PURE__ */ _(x, { children: u ? E && !w ? /* @__PURE__ */ _("p", {
|
|
151
157
|
className: "text-sm text-muted-foreground",
|
|
152
|
-
children:
|
|
153
|
-
}) :
|
|
158
|
+
children: m("planmagnet.dashboards.loading", "Loading…")
|
|
159
|
+
}) : D ? /* @__PURE__ */ v("p", {
|
|
154
160
|
className: "text-sm text-status-error-text",
|
|
155
161
|
children: [
|
|
156
|
-
|
|
162
|
+
m("planmagnet.dashboards.velocity.error", "Velocity could not be loaded"),
|
|
157
163
|
":",
|
|
158
164
|
" ",
|
|
159
|
-
|
|
165
|
+
D.message
|
|
160
166
|
]
|
|
161
|
-
}) :
|
|
167
|
+
}) : k.length === 0 ? /* @__PURE__ */ _("p", {
|
|
162
168
|
className: "text-sm text-muted-foreground",
|
|
163
|
-
children:
|
|
164
|
-
}) : /* @__PURE__ */
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
169
|
+
children: m("planmagnet.dashboards.velocity.empty", "No completed sprints yet for this project.")
|
|
170
|
+
}) : /* @__PURE__ */ v(g, { children: [
|
|
171
|
+
/* @__PURE__ */ _(n, {
|
|
172
|
+
width: "100%",
|
|
173
|
+
height: 190,
|
|
174
|
+
children: /* @__PURE__ */ v(d, {
|
|
175
|
+
data: k,
|
|
176
|
+
children: [
|
|
177
|
+
/* @__PURE__ */ _(o, {
|
|
178
|
+
strokeDasharray: "3 3",
|
|
179
|
+
opacity: .2
|
|
180
|
+
}),
|
|
181
|
+
/* @__PURE__ */ _(c, {
|
|
182
|
+
dataKey: "name",
|
|
183
|
+
tick: { fontSize: 11 }
|
|
184
|
+
}),
|
|
185
|
+
/* @__PURE__ */ _(l, {
|
|
186
|
+
tick: { fontSize: 11 },
|
|
187
|
+
allowDecimals: !1
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ _(t, {}),
|
|
190
|
+
/* @__PURE__ */ _(e, { wrapperStyle: { fontSize: 12 } }),
|
|
191
|
+
M && /* @__PURE__ */ _(a, {
|
|
192
|
+
y1: M.p15,
|
|
193
|
+
y2: M.p85,
|
|
194
|
+
fill: "var(--color-chart-2)",
|
|
195
|
+
fillOpacity: .12,
|
|
196
|
+
stroke: "none"
|
|
197
|
+
}),
|
|
198
|
+
/* @__PURE__ */ _(r, {
|
|
199
|
+
dataKey: "planned",
|
|
200
|
+
name: m("planmagnet.dashboards.velocity.planned", "Planned"),
|
|
201
|
+
fill: "#cbd5e1"
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ _(r, {
|
|
204
|
+
dataKey: "completed",
|
|
205
|
+
name: m("planmagnet.dashboards.velocity.completed", "Completed"),
|
|
206
|
+
fill: "#6366f1"
|
|
207
|
+
}),
|
|
208
|
+
/* @__PURE__ */ _(i, {
|
|
209
|
+
y: A,
|
|
210
|
+
stroke: "#22c55e",
|
|
211
|
+
strokeDasharray: "4 4",
|
|
212
|
+
label: {
|
|
213
|
+
value: m("planmagnet.dashboards.velocity.avgLabel", "avg"),
|
|
214
|
+
fontSize: 10
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
]
|
|
218
|
+
})
|
|
219
|
+
}),
|
|
220
|
+
/* @__PURE__ */ v("p", {
|
|
221
|
+
className: "mt-2 text-center text-xs text-muted-foreground",
|
|
222
|
+
children: [m("planmagnet.dashboards.velocity.trailingAverage", "Median of the last {{count}} completed sprints: {{points}} pts per sprint", {
|
|
223
|
+
count: k.length,
|
|
224
|
+
points: j
|
|
225
|
+
}), M && ` · ${m("planmagnet.dashboards.velocity.range", "likely range (p15–p85): {{low}}–{{high}} pts", {
|
|
226
|
+
low: Math.round(M.p15),
|
|
227
|
+
high: Math.round(M.p85)
|
|
228
|
+
})}`]
|
|
229
|
+
}),
|
|
230
|
+
N && /* @__PURE__ */ _("p", {
|
|
231
|
+
className: "mt-1 text-center text-xs text-status-warning-text",
|
|
232
|
+
children: m("planmagnet.dashboards.velocity.insufficientHistory", "Fewer than 3 sprints with completed points — this forecast is low-confidence.")
|
|
233
|
+
}),
|
|
234
|
+
/* @__PURE__ */ _("p", {
|
|
235
|
+
className: "mt-1 text-center text-xs text-muted-foreground",
|
|
236
|
+
children: m("planmagnet.dashboards.velocity.methodLabel", "Statistical forecast (not AI-generated).")
|
|
210
237
|
})
|
|
211
|
-
|
|
238
|
+
] }) : /* @__PURE__ */ _("p", {
|
|
212
239
|
className: "text-sm text-muted-foreground",
|
|
213
|
-
children:
|
|
240
|
+
children: m("planmagnet.dashboards.velocity.noProject", "Select a project to see its velocity.")
|
|
214
241
|
}) })] });
|
|
215
242
|
}
|
|
216
243
|
//#endregion
|
|
217
|
-
export {
|
|
244
|
+
export { D as SprintBurndownCard, O as SprintVelocityCard };
|
|
218
245
|
|
|
219
246
|
//# sourceMappingURL=SprintDeliveryCards.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SprintDeliveryCards.js","names":[],"sources":["../../../../src/planmagnet/pages/analytics/SprintDeliveryCards.tsx"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, TrendingUp } from 'lucide-react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\n\n/**\n * Sprint burndown and velocity, as their own cards (BOFF-4447's server-computed\n * `planmagnetSprintBurndown` / `planmagnetVelocity`). Extracted out of\n * `pages/AnalyticsAnalyticsPagePage.tsx`, where this same chart code lived inline, so the\n * role dashboards (`dashboards/project-manager-page`) can import the chart rather than\n * duplicating it — same reasoning as `CycleTimeCard`/`BudgetPerformanceCard` alongside\n * them in `DeliveryHealthCards.tsx`. Each card owns its query, so neither can land a hook\n * after an early return in the host page.\n *\n * recharts' `stroke`/`fill` render as literal SVG paint attributes, not Tailwind\n * classNames — they cannot consume semantic `bg-*`/`text-*` tokens, the same documented\n * exception `AnalyticsAnalyticsPagePage.tsx`'s cumulative-flow chart carries.\n */\n\nconst GET_SPRINT_BURNDOWN = gql`\n query DashboardSprintBurndown($workspaceId: ID!, $sprintId: ID!) {\n planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {\n sprintId\n totalPoints\n totalCount\n points {\n date\n remainingPoints\n completedPoints\n }\n }\n }\n`;\n\nconst GET_VELOCITY = gql`\n query DashboardVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {\n planmagnetVelocity(\n workspaceId: $workspaceId\n projectId: $projectId\n trailingSprintCount: $trailingSprintCount\n ) {\n projectId\n averageVelocity\n forecastNextSprintPoints\n sprints {\n sprintId\n sprintName\n sequenceNumber\n completedPoints\n plannedPoints\n }\n }\n }\n`;\n\ninterface BurndownData {\n planmagnetSprintBurndown: {\n sprintId: string;\n totalPoints: number;\n totalCount: number;\n points: { date: string; remainingPoints: number; completedPoints: number }[];\n } | null;\n}\n\ninterface VelocityData {\n planmagnetVelocity: {\n projectId: string;\n averageVelocity: number;\n forecastNextSprintPoints: number;\n sprints: {\n sprintId: string;\n sprintName: string;\n sequenceNumber: number;\n completedPoints: number;\n plannedPoints: number | null;\n }[];\n };\n}\n\nfunction formatDay(iso: string): string {\n const d = new Date(iso);\n return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;\n}\n\nexport function SprintBurndownCard({\n workspaceId,\n sprintId,\n}: {\n workspaceId?: string | null;\n sprintId: string;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<BurndownData>(GET_SPRINT_BURNDOWN, {\n variables: { workspaceId, sprintId },\n skip: !workspaceId || !sprintId,\n });\n const points = data?.planmagnetSprintBurndown?.points ?? [];\n const chartData = points.map((p) => ({\n day: formatDay(p.date),\n remaining: p.remainingPoints,\n completed: p.completedPoints,\n }));\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.burndown.title', 'Sprint burndown')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.burndown.subtitle',\n 'Remaining vs. completed story points, by day of the sprint.'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!sprintId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.noSprint', 'No active sprint for this project.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.burndown.error', 'Burndown could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.empty', 'The active sprint has no work items yet.')}\n </p>\n ) : (\n <ResponsiveContainer width=\"100%\" height={220}>\n <LineChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"day\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Line\n type=\"monotone\"\n dataKey=\"remaining\"\n name={t('planmagnet.dashboards.burndown.remaining', 'Remaining points')}\n stroke=\"#f59e0b\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.burndown.completed', 'Completed points')}\n stroke=\"#22c55e\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n </LineChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\nexport function SprintVelocityCard({\n workspaceId,\n projectId,\n trailingSprintCount = 6,\n}: {\n workspaceId?: string | null;\n projectId: string;\n trailingSprintCount?: number;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<VelocityData>(GET_VELOCITY, {\n variables: { workspaceId, projectId, trailingSprintCount },\n skip: !workspaceId || !projectId,\n });\n const velocity = data?.planmagnetVelocity;\n const chartData =\n velocity?.sprints.map((s) => ({\n name: s.sprintName,\n completed: s.completedPoints,\n planned: s.plannedPoints ?? undefined,\n })) ?? [];\n const avgVelocity = velocity ? Math.round(velocity.averageVelocity) : 0;\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <TrendingUp className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.velocity.title', 'Sprint velocity')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.subtitle',\n 'Completed story points per sprint, across the trailing {{count}} completed sprints.',\n { count: trailingSprintCount }\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!projectId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.velocity.noProject', 'Select a project to see its velocity.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.velocity.error', 'Velocity could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.empty',\n 'No completed sprints yet for this project.'\n )}\n </p>\n ) : (\n <>\n <ResponsiveContainer width=\"100%\" height={190}>\n <BarChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"name\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Bar\n dataKey=\"planned\"\n name={t('planmagnet.dashboards.velocity.planned', 'Planned')}\n fill=\"#cbd5e1\"\n />\n <Bar\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.velocity.completed', 'Completed')}\n fill=\"#6366f1\"\n />\n <ReferenceLine\n y={avgVelocity}\n stroke=\"#22c55e\"\n strokeDasharray=\"4 4\"\n label={{\n value: t('planmagnet.dashboards.velocity.avgLabel', 'avg'),\n fontSize: 10,\n }}\n />\n </BarChart>\n </ResponsiveContainer>\n <p className=\"mt-2 text-center text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.trailingAverage',\n 'Average of the last {{count}} completed sprints: {{points}} pts per sprint',\n { count: chartData.length, points: avgVelocity }\n )}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiCA,IAAM,IAAsB,CAAG;;;;;;;;;;;;;GAezB,IAAe,CAAG;;;;;;;;;;;;;;;;;;;;AA6CxB,SAAS,EAAU,GAAqB;CACtC,IAAM,IAAI,IAAI,KAAK,EAAI;AACvB,QAAO,GAAG,EAAE,aAAa,GAAG,EAAE,GAAG,EAAE,YAAY;;AAGjD,SAAgB,EAAmB,EACjC,gBACA,eAIC;CACD,IAAM,EAAE,SAAM,GAAS,EACjB,EAAE,SAAM,YAAS,aAAU,EAAuB,GAAqB;EAC3E,WAAW;GAAE;GAAa;GAAU;EACpC,MAAM,CAAC,KAAe,CAAC;EACxB,CAAC,EAEI,KADS,GAAM,0BAA0B,UAAU,EAAE,EAClC,KAAK,OAAO;EACnC,KAAK,EAAU,EAAE,KAAK;EACtB,WAAW,EAAE;EACb,WAAW,EAAE;EACd,EAAE;AAEH,QACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EAAW,WAAU;YAArB,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAChC,EAAE,wCAAwC,kBAAkB,CACnD;KACZ,kBAAC,KAAD;EAAG,WAAU;YACV,EACC,2CACA,8DACD;EACC,CAAA,CACO,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACI,IAIE,KAAW,CAAC,IACd,kBAAC,KAAD;EAAG,WAAU;YACV,EAAE,iCAAiC,WAAW;EAC7C,CAAA,GACF,IACF,kBAAC,KAAD;EAAG,WAAU;YAAb;GACG,EAAE,wCAAwC,+BAA+B;GAAC;GAAE;GAC5E,EAAM;GACL;MACF,EAAU,WAAW,IACvB,kBAAC,KAAD;EAAG,WAAU;YACV,EAAE,wCAAwC,2CAA2C;EACpF,CAAA,GAEJ,kBAAC,GAAD;EAAqB,OAAM;EAAO,QAAQ;YACxC,kBAAC,GAAD;GAAW,MAAM;aAAjB;IACE,kBAAC,GAAD;KAAe,iBAAgB;KAAM,SAAS;KAAO,CAAA;IACrD,kBAAC,GAAD;KAAO,SAAQ;KAAM,MAAM,EAAE,UAAU,IAAI;KAAI,CAAA;IAC/C,kBAAC,GAAD;KAAO,MAAM,EAAE,UAAU,IAAI;KAAE,eAAe;KAAS,CAAA;IACvD,kBAAC,GAAD,EAAW,CAAA;IACX,kBAAC,GAAD,EAAQ,cAAc,EAAE,UAAU,IAAI,EAAI,CAAA;IAC1C,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,MAAM,EAAE,4CAA4C,mBAAmB;KACvE,QAAO;KACP,aAAa;KACb,KAAK,EAAE,GAAG,GAAG;KACb,CAAA;IACF,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,MAAM,EAAE,4CAA4C,mBAAmB;KACvE,QAAO;KACP,aAAa;KACb,KAAK,EAAE,GAAG,GAAG;KACb,CAAA;IACQ;;EACQ,CAAA,GAzCtB,kBAAC,KAAD;EAAG,WAAU;YACV,EAAE,2CAA2C,qCAAqC;EACjF,CAAA,EAyCM,CAAA,CACT,EAAA,CAAA;;AAIX,SAAgB,EAAmB,EACjC,gBACA,cACA,yBAAsB,KAKrB;CACD,IAAM,EAAE,SAAM,GAAS,EACjB,EAAE,SAAM,YAAS,aAAU,EAAuB,GAAc;EACpE,WAAW;GAAE;GAAa;GAAW;GAAqB;EAC1D,MAAM,CAAC,KAAe,CAAC;EACxB,CAAC,EACI,IAAW,GAAM,oBACjB,IACJ,GAAU,QAAQ,KAAK,OAAO;EAC5B,MAAM,EAAE;EACR,WAAW,EAAE;EACb,SAAS,EAAE,iBAAiB,KAAA;EAC7B,EAAE,IAAI,EAAE,EACL,IAAc,IAAW,KAAK,MAAM,EAAS,gBAAgB,GAAG;AAEtE,QACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EAAW,WAAU;YAArB,CACE,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA,EACjC,EAAE,wCAAwC,kBAAkB,CACnD;KACZ,kBAAC,KAAD;EAAG,WAAU;YACV,EACC,2CACA,uFACA,EAAE,OAAO,GAAqB,CAC/B;EACC,CAAA,CACO,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACI,IAIE,KAAW,CAAC,IACd,kBAAC,KAAD;EAAG,WAAU;YACV,EAAE,iCAAiC,WAAW;EAC7C,CAAA,GACF,IACF,kBAAC,KAAD;EAAG,WAAU;YAAb;GACG,EAAE,wCAAwC,+BAA+B;GAAC;GAAE;GAC5E,EAAM;GACL;MACF,EAAU,WAAW,IACvB,kBAAC,KAAD;EAAG,WAAU;YACV,EACC,wCACA,6CACD;EACC,CAAA,GAEJ,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EAAqB,OAAM;EAAO,QAAQ;YACxC,kBAAC,GAAD;GAAU,MAAM;aAAhB;IACE,kBAAC,GAAD;KAAe,iBAAgB;KAAM,SAAS;KAAO,CAAA;IACrD,kBAAC,GAAD;KAAO,SAAQ;KAAO,MAAM,EAAE,UAAU,IAAI;KAAI,CAAA;IAChD,kBAAC,GAAD;KAAO,MAAM,EAAE,UAAU,IAAI;KAAE,eAAe;KAAS,CAAA;IACvD,kBAAC,GAAD,EAAW,CAAA;IACX,kBAAC,GAAD,EAAQ,cAAc,EAAE,UAAU,IAAI,EAAI,CAAA;IAC1C,kBAAC,GAAD;KACE,SAAQ;KACR,MAAM,EAAE,0CAA0C,UAAU;KAC5D,MAAK;KACL,CAAA;IACF,kBAAC,GAAD;KACE,SAAQ;KACR,MAAM,EAAE,4CAA4C,YAAY;KAChE,MAAK;KACL,CAAA;IACF,kBAAC,GAAD;KACE,GAAG;KACH,QAAO;KACP,iBAAgB;KAChB,OAAO;MACL,OAAO,EAAE,2CAA2C,MAAM;MAC1D,UAAU;MACX;KACD,CAAA;IACO;;EACS,CAAA,EACtB,kBAAC,KAAD;EAAG,WAAU;YACV,EACC,kDACA,8EACA;GAAE,OAAO,EAAU;GAAQ,QAAQ;GAAa,CACjD;EACC,CAAA,CACH,EAAA,CAAA,GAxDH,kBAAC,KAAD;EAAG,WAAU;YACV,EAAE,4CAA4C,wCAAwC;EACrF,CAAA,EAwDM,CAAA,CACT,EAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"SprintDeliveryCards.js","names":[],"sources":["../../../../src/planmagnet/pages/analytics/SprintDeliveryCards.tsx"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, TrendingUp } from 'lucide-react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceArea,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\n\n/**\n * Sprint burndown and velocity, as their own cards (BOFF-4447's server-computed\n * `planmagnetSprintBurndown` / `planmagnetVelocity`). Extracted out of\n * `pages/AnalyticsAnalyticsPagePage.tsx`, where this same chart code lived inline, so the\n * role dashboards (`dashboards/project-manager-page`) can import the chart rather than\n * duplicating it — same reasoning as `CycleTimeCard`/`BudgetPerformanceCard` alongside\n * them in `DeliveryHealthCards.tsx`. Each card owns its query, so neither can land a hook\n * after an early return in the host page.\n *\n * recharts' `stroke`/`fill` render as literal SVG paint attributes, not Tailwind\n * classNames — they cannot consume semantic `bg-*`/`text-*` tokens, the same documented\n * exception `AnalyticsAnalyticsPagePage.tsx`'s cumulative-flow chart carries.\n */\n\nconst GET_SPRINT_BURNDOWN = gql`\n query DashboardSprintBurndown($workspaceId: ID!, $sprintId: ID!) {\n planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {\n sprintId\n totalPoints\n totalCount\n points {\n date\n remainingPoints\n completedPoints\n }\n }\n }\n`;\n\nconst GET_VELOCITY = gql`\n query DashboardVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {\n planmagnetVelocity(\n workspaceId: $workspaceId\n projectId: $projectId\n trailingSprintCount: $trailingSprintCount\n ) {\n projectId\n averageVelocity\n forecastNextSprintPoints\n forecastRange {\n p15\n p85\n }\n insufficientHistory\n sprints {\n sprintId\n sprintName\n sequenceNumber\n completedPoints\n plannedPoints\n }\n }\n }\n`;\n\ninterface BurndownData {\n planmagnetSprintBurndown: {\n sprintId: string;\n totalPoints: number;\n totalCount: number;\n points: { date: string; remainingPoints: number; completedPoints: number }[];\n } | null;\n}\n\ninterface VelocityData {\n planmagnetVelocity: {\n projectId: string;\n averageVelocity: number;\n forecastNextSprintPoints: number;\n forecastRange: { p15: number; p85: number } | null;\n insufficientHistory: boolean;\n sprints: {\n sprintId: string;\n sprintName: string;\n sequenceNumber: number;\n completedPoints: number;\n plannedPoints: number | null;\n }[];\n };\n}\n\nfunction formatDay(iso: string): string {\n const d = new Date(iso);\n return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;\n}\n\nexport function SprintBurndownCard({\n workspaceId,\n sprintId,\n}: {\n workspaceId?: string | null;\n sprintId: string;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<BurndownData>(GET_SPRINT_BURNDOWN, {\n variables: { workspaceId, sprintId },\n skip: !workspaceId || !sprintId,\n });\n const points = data?.planmagnetSprintBurndown?.points ?? [];\n const chartData = points.map((p) => ({\n day: formatDay(p.date),\n remaining: p.remainingPoints,\n completed: p.completedPoints,\n }));\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.burndown.title', 'Sprint burndown')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.burndown.subtitle',\n 'Remaining vs. completed story points, by day of the sprint.'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!sprintId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.noSprint', 'No active sprint for this project.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.burndown.error', 'Burndown could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.empty', 'The active sprint has no work items yet.')}\n </p>\n ) : (\n <ResponsiveContainer width=\"100%\" height={220}>\n <LineChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"day\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Line\n type=\"monotone\"\n dataKey=\"remaining\"\n name={t('planmagnet.dashboards.burndown.remaining', 'Remaining points')}\n stroke=\"#f59e0b\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.burndown.completed', 'Completed points')}\n stroke=\"#22c55e\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n </LineChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\nexport function SprintVelocityCard({\n workspaceId,\n projectId,\n trailingSprintCount = 6,\n}: {\n workspaceId?: string | null;\n projectId: string;\n trailingSprintCount?: number;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<VelocityData>(GET_VELOCITY, {\n variables: { workspaceId, projectId, trailingSprintCount },\n skip: !workspaceId || !projectId,\n });\n const velocity = data?.planmagnetVelocity;\n const chartData =\n velocity?.sprints.map((s) => ({\n name: s.sprintName,\n completed: s.completedPoints,\n planned: s.plannedPoints ?? undefined,\n })) ?? [];\n const avgVelocity = velocity ? Math.round(velocity.averageVelocity) : 0;\n const forecastNextSprint = velocity ? Math.round(velocity.forecastNextSprintPoints) : 0;\n const forecastRange = velocity?.forecastRange ?? null;\n const insufficientHistory = velocity?.insufficientHistory ?? false;\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <TrendingUp className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.velocity.title', 'Sprint velocity')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.subtitle',\n 'Completed story points per sprint, across the trailing {{count}} completed sprints.',\n { count: trailingSprintCount }\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!projectId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.velocity.noProject', 'Select a project to see its velocity.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.velocity.error', 'Velocity could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.empty',\n 'No completed sprints yet for this project.'\n )}\n </p>\n ) : (\n <>\n <ResponsiveContainer width=\"100%\" height={190}>\n <BarChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"name\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n {/* ANR-02: the empirical p15-p85 band around next sprint's forecast — full-width (no\n x1/x2) since it isn't tied to any historical sprint's x position. */}\n {forecastRange && (\n <ReferenceArea\n y1={forecastRange.p15}\n y2={forecastRange.p85}\n fill=\"var(--color-chart-2)\"\n fillOpacity={0.12}\n stroke=\"none\"\n />\n )}\n <Bar\n dataKey=\"planned\"\n name={t('planmagnet.dashboards.velocity.planned', 'Planned')}\n fill=\"#cbd5e1\"\n />\n <Bar\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.velocity.completed', 'Completed')}\n fill=\"#6366f1\"\n />\n <ReferenceLine\n y={avgVelocity}\n stroke=\"#22c55e\"\n strokeDasharray=\"4 4\"\n label={{\n value: t('planmagnet.dashboards.velocity.avgLabel', 'avg'),\n fontSize: 10,\n }}\n />\n </BarChart>\n </ResponsiveContainer>\n {/* Accessible text restatement of the shaded band, for screen readers. */}\n <p className=\"mt-2 text-center text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.trailingAverage',\n 'Median of the last {{count}} completed sprints: {{points}} pts per sprint',\n { count: chartData.length, points: forecastNextSprint }\n )}\n {forecastRange &&\n ` · ${t(\n 'planmagnet.dashboards.velocity.range',\n 'likely range (p15–p85): {{low}}–{{high}} pts',\n { low: Math.round(forecastRange.p15), high: Math.round(forecastRange.p85) }\n )}`}\n </p>\n {insufficientHistory && (\n <p className=\"mt-1 text-center text-xs text-status-warning-text\">\n {t(\n 'planmagnet.dashboards.velocity.insufficientHistory',\n 'Fewer than 3 sprints with completed points — this forecast is low-confidence.'\n )}\n </p>\n )}\n <p className=\"mt-1 text-center text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.methodLabel',\n 'Statistical forecast (not AI-generated).'\n )}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Tooltip as e } from "../../../node_modules/recharts/es6/component/Tooltip.js";
|
|
2
2
|
import { ResponsiveContainer as t } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
|
|
3
3
|
import { Sankey as n } from "../../../node_modules/recharts/es6/chart/Sankey.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { isForbidden as r } from "../../utils/graphqlErrors.js";
|
|
5
|
+
import { WORK_ITEM_STATUSES as i, enumLabel as a } from "../../controls/WorkItemControls.js";
|
|
6
|
+
import { statusVisual as o } from "../../utils/statusColor.js";
|
|
7
7
|
import { useMemo as s } from "react";
|
|
8
8
|
import { Workflow as c } from "lucide-react";
|
|
9
9
|
import { gql as l } from "@apollo/client";
|
|
@@ -39,19 +39,19 @@ function x(e, t) {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
function S(e) {
|
|
42
|
-
let t =
|
|
42
|
+
let t = i.filter((t) => e.some((e) => e.fromStatus === t)), n = i.filter((t) => e.some((e) => e.toStatus === t)), r = new Map(t.map((e, t) => [e, t])), o = new Map(n.map((e, n) => [e, t.length + n]));
|
|
43
43
|
return {
|
|
44
44
|
nodes: [...t.map((e) => ({
|
|
45
|
-
name:
|
|
45
|
+
name: a(e),
|
|
46
46
|
status: e,
|
|
47
47
|
side: "from"
|
|
48
48
|
})), ...n.map((e) => ({
|
|
49
|
-
name:
|
|
49
|
+
name: a(e),
|
|
50
50
|
status: e,
|
|
51
51
|
side: "to"
|
|
52
52
|
}))],
|
|
53
53
|
links: e.flatMap((e) => {
|
|
54
|
-
let t =
|
|
54
|
+
let t = r.get(e.fromStatus), n = o.get(e.toStatus);
|
|
55
55
|
return t === void 0 || n === void 0 ? [] : [{
|
|
56
56
|
source: t,
|
|
57
57
|
target: n,
|
|
@@ -61,7 +61,7 @@ function S(e) {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
function C({ x: e, y: t, width: n, height: r, payload: i }) {
|
|
64
|
-
let
|
|
64
|
+
let a = o(i.status), s = i.side === "from";
|
|
65
65
|
return /* @__PURE__ */ f("g", { children: [/* @__PURE__ */ d("rect", {
|
|
66
66
|
x: e,
|
|
67
67
|
y: t,
|
|
@@ -69,8 +69,8 @@ function C({ x: e, y: t, width: n, height: r, payload: i }) {
|
|
|
69
69
|
height: r,
|
|
70
70
|
rx: 2,
|
|
71
71
|
style: {
|
|
72
|
-
fill:
|
|
73
|
-
stroke:
|
|
72
|
+
fill: a.color,
|
|
73
|
+
stroke: a.color
|
|
74
74
|
},
|
|
75
75
|
strokeWidth: 1
|
|
76
76
|
}), /* @__PURE__ */ d("text", {
|
|
@@ -82,25 +82,25 @@ function C({ x: e, y: t, width: n, height: r, payload: i }) {
|
|
|
82
82
|
children: i.name
|
|
83
83
|
})] });
|
|
84
84
|
}
|
|
85
|
-
function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourceControlX: i, targetControlX:
|
|
86
|
-
let l =
|
|
85
|
+
function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourceControlX: i, targetControlX: a, linkWidth: s, payload: c }) {
|
|
86
|
+
let l = o(c.source.status);
|
|
87
87
|
return /* @__PURE__ */ d("path", {
|
|
88
|
-
d: `M${e},${t} C${i},${t} ${
|
|
88
|
+
d: `M${e},${t} C${i},${t} ${a},${r} ${n},${r}`,
|
|
89
89
|
style: { stroke: l.color },
|
|
90
90
|
strokeWidth: Math.max(s, 1),
|
|
91
91
|
strokeOpacity: .45,
|
|
92
92
|
fill: "none"
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
-
function T({ workspaceId:
|
|
95
|
+
function T({ workspaceId: i, projectId: o, startDate: l, endDate: b }) {
|
|
96
96
|
let { t: T } = p(), E = s(() => x(l, b), [l, b]), { data: D, loading: O, error: k } = u(v, {
|
|
97
97
|
variables: {
|
|
98
|
-
workspaceId:
|
|
99
|
-
projectId:
|
|
98
|
+
workspaceId: i,
|
|
99
|
+
projectId: o,
|
|
100
100
|
from: E.from,
|
|
101
101
|
to: E.to
|
|
102
102
|
},
|
|
103
|
-
skip: !
|
|
103
|
+
skip: !i || !o
|
|
104
104
|
}), A = D?.planmagnetStatusFlow ?? [], { nodes: j, links: M } = S(A), N = [...A].sort((e, t) => t.count - e.count);
|
|
105
105
|
return /* @__PURE__ */ f(m, {
|
|
106
106
|
"data-testid": "status-flow-card",
|
|
@@ -120,12 +120,12 @@ function T({ workspaceId: r, projectId: a, startDate: l, endDate: b }) {
|
|
|
120
120
|
from: E.from.slice(0, 10)
|
|
121
121
|
})
|
|
122
122
|
})
|
|
123
|
-
] }), /* @__PURE__ */ d(h, { children:
|
|
123
|
+
] }), /* @__PURE__ */ d(h, { children: o ? O && !D ? /* @__PURE__ */ d("div", {
|
|
124
124
|
className: "flex justify-center py-12",
|
|
125
125
|
children: /* @__PURE__ */ d("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
126
126
|
}) : k ? /* @__PURE__ */ d("p", {
|
|
127
127
|
className: "text-sm text-status-error-text",
|
|
128
|
-
children:
|
|
128
|
+
children: r(k) ? T("planmagnet.analytics.statusFlow.forbidden", "You do not have access to status flow for this project.") : `${T("planmagnet.analytics.statusFlow.error", "Status flow could not be loaded")}: ${k.message}`
|
|
129
129
|
}) : A.length === 0 ? /* @__PURE__ */ d("p", {
|
|
130
130
|
className: "text-sm text-muted-foreground py-8 text-center",
|
|
131
131
|
children: T("planmagnet.analytics.statusFlow.empty", "No status changes recorded for this project in the selected range.")
|
|
@@ -208,11 +208,11 @@ function T({ workspaceId: r, projectId: a, startDate: l, endDate: b }) {
|
|
|
208
208
|
children: [
|
|
209
209
|
/* @__PURE__ */ d("td", {
|
|
210
210
|
className: "py-1.5 pr-2",
|
|
211
|
-
children:
|
|
211
|
+
children: a(e.fromStatus)
|
|
212
212
|
}),
|
|
213
213
|
/* @__PURE__ */ d("td", {
|
|
214
214
|
className: "py-1.5 pr-2",
|
|
215
|
-
children:
|
|
215
|
+
children: a(e.toStatus)
|
|
216
216
|
}),
|
|
217
217
|
/* @__PURE__ */ d("td", {
|
|
218
218
|
className: "py-1.5 text-right tabular-nums",
|