@massdriver/backstage-plugin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +196 -0
  3. package/dist/MassdriverRouter.esm.js +78 -0
  4. package/dist/MassdriverRouter.esm.js.map +1 -0
  5. package/dist/api.esm.js +119 -0
  6. package/dist/api.esm.js.map +1 -0
  7. package/dist/assets/massdriver-logo-dark.svg +55 -0
  8. package/dist/assets/massdriver-logo-light.svg +50 -0
  9. package/dist/components/AttributesColumn.esm.js +95 -0
  10. package/dist/components/AttributesColumn.esm.js.map +1 -0
  11. package/dist/components/AttributesSummaryCell.esm.js +103 -0
  12. package/dist/components/AttributesSummaryCell.esm.js.map +1 -0
  13. package/dist/components/AuthedIcon.esm.js +26 -0
  14. package/dist/components/AuthedIcon.esm.js.map +1 -0
  15. package/dist/components/ConditionsCell.esm.js +48 -0
  16. package/dist/components/ConditionsCell.esm.js.map +1 -0
  17. package/dist/components/DisabledAction.esm.js +30 -0
  18. package/dist/components/DisabledAction.esm.js.map +1 -0
  19. package/dist/components/EntityMassdriverContent/EntityMassdriverContent.esm.js +80 -0
  20. package/dist/components/EntityMassdriverContent/EntityMassdriverContent.esm.js.map +1 -0
  21. package/dist/components/EntityMassdriverContent/index.esm.js +6 -0
  22. package/dist/components/EntityMassdriverContent/index.esm.js.map +1 -0
  23. package/dist/components/EntityMassdriverOverviewCard/EntityMassdriverOverviewCard.esm.js +75 -0
  24. package/dist/components/EntityMassdriverOverviewCard/EntityMassdriverOverviewCard.esm.js.map +1 -0
  25. package/dist/components/EntityMassdriverOverviewCard/index.esm.js +6 -0
  26. package/dist/components/EntityMassdriverOverviewCard/index.esm.js.map +1 -0
  27. package/dist/components/ForkPill.esm.js +84 -0
  28. package/dist/components/ForkPill.esm.js.map +1 -0
  29. package/dist/components/InstanceStatusIndicator.esm.js +21 -0
  30. package/dist/components/InstanceStatusIndicator.esm.js.map +1 -0
  31. package/dist/components/InstanceStatusPill.esm.js +67 -0
  32. package/dist/components/InstanceStatusPill.esm.js.map +1 -0
  33. package/dist/components/MassdriverIcon.esm.js +13 -0
  34. package/dist/components/MassdriverIcon.esm.js.map +1 -0
  35. package/dist/components/MassdriverSidebarItem.esm.js +45 -0
  36. package/dist/components/MassdriverSidebarItem.esm.js.map +1 -0
  37. package/dist/components/NotFound.esm.js +44 -0
  38. package/dist/components/NotFound.esm.js.map +1 -0
  39. package/dist/components/OpenInMassdriverButton.esm.js +24 -0
  40. package/dist/components/OpenInMassdriverButton.esm.js.map +1 -0
  41. package/dist/components/PageLayout.esm.js +88 -0
  42. package/dist/components/PageLayout.esm.js.map +1 -0
  43. package/dist/components/RouterLinkAdapter.esm.js +12 -0
  44. package/dist/components/RouterLinkAdapter.esm.js.map +1 -0
  45. package/dist/components/VersionBadge.esm.js +57 -0
  46. package/dist/components/VersionBadge.esm.js.map +1 -0
  47. package/dist/components/grantColumns.esm.js +56 -0
  48. package/dist/components/grantColumns.esm.js.map +1 -0
  49. package/dist/components/icons/BundleIcon.esm.js +7 -0
  50. package/dist/components/icons/BundleIcon.esm.js.map +1 -0
  51. package/dist/components/icons/FolderOutlinedIcon.esm.js +7 -0
  52. package/dist/components/icons/FolderOutlinedIcon.esm.js.map +1 -0
  53. package/dist/components/icons/TokenIcon.esm.js +7 -0
  54. package/dist/components/icons/TokenIcon.esm.js.map +1 -0
  55. package/dist/entity.esm.js +23 -0
  56. package/dist/entity.esm.js.map +1 -0
  57. package/dist/features/environment/CompareDeploymentsDialog/CompareDeploymentsDialog.esm.js +115 -0
  58. package/dist/features/environment/CompareDeploymentsDialog/CompareDeploymentsDialog.esm.js.map +1 -0
  59. package/dist/features/environment/CompareDeploymentsDialog/ResultsStep.esm.js +165 -0
  60. package/dist/features/environment/CompareDeploymentsDialog/ResultsStep.esm.js.map +1 -0
  61. package/dist/features/environment/CompareDeploymentsDialog/SelectStep.esm.js +216 -0
  62. package/dist/features/environment/CompareDeploymentsDialog/SelectStep.esm.js.map +1 -0
  63. package/dist/features/environment/CompareDeploymentsDialog/compareColumns.esm.js +86 -0
  64. package/dist/features/environment/CompareDeploymentsDialog/compareColumns.esm.js.map +1 -0
  65. package/dist/features/environment/CompareDeploymentsDialog/flattenDeploymentComparison.esm.js +57 -0
  66. package/dist/features/environment/CompareDeploymentsDialog/flattenDeploymentComparison.esm.js.map +1 -0
  67. package/dist/features/environment/CompareDeploymentsDialog/queries.esm.js +53 -0
  68. package/dist/features/environment/CompareDeploymentsDialog/queries.esm.js.map +1 -0
  69. package/dist/features/environment/CompareEnvironmentsDialog/CompareEnvironmentsDialog.esm.js +94 -0
  70. package/dist/features/environment/CompareEnvironmentsDialog/CompareEnvironmentsDialog.esm.js.map +1 -0
  71. package/dist/features/environment/CompareEnvironmentsDialog/ComparisonValueCell.esm.js +67 -0
  72. package/dist/features/environment/CompareEnvironmentsDialog/ComparisonValueCell.esm.js.map +1 -0
  73. package/dist/features/environment/CompareEnvironmentsDialog/ResultsStep.esm.js +202 -0
  74. package/dist/features/environment/CompareEnvironmentsDialog/ResultsStep.esm.js.map +1 -0
  75. package/dist/features/environment/CompareEnvironmentsDialog/SelectStep.esm.js +183 -0
  76. package/dist/features/environment/CompareEnvironmentsDialog/SelectStep.esm.js.map +1 -0
  77. package/dist/features/environment/CompareEnvironmentsDialog/compareColumns.esm.js +73 -0
  78. package/dist/features/environment/CompareEnvironmentsDialog/compareColumns.esm.js.map +1 -0
  79. package/dist/features/environment/CompareEnvironmentsDialog/flattenComparison.esm.js +70 -0
  80. package/dist/features/environment/CompareEnvironmentsDialog/flattenComparison.esm.js.map +1 -0
  81. package/dist/features/environment/CompareEnvironmentsDialog/queries.esm.js +32 -0
  82. package/dist/features/environment/CompareEnvironmentsDialog/queries.esm.js.map +1 -0
  83. package/dist/features/environment/EnvironmentGraphPage.esm.js +131 -0
  84. package/dist/features/environment/EnvironmentGraphPage.esm.js.map +1 -0
  85. package/dist/features/environment/GraphHeader/EnvironmentDefaults.esm.js +252 -0
  86. package/dist/features/environment/GraphHeader/EnvironmentDefaults.esm.js.map +1 -0
  87. package/dist/features/environment/GraphHeader/GraphHeader.esm.js +247 -0
  88. package/dist/features/environment/GraphHeader/GraphHeader.esm.js.map +1 -0
  89. package/dist/features/environment/GraphHeader/HeaderActions.esm.js +127 -0
  90. package/dist/features/environment/GraphHeader/HeaderActions.esm.js.map +1 -0
  91. package/dist/features/environment/GraphHeader/Switcher.esm.js +75 -0
  92. package/dist/features/environment/GraphHeader/Switcher.esm.js.map +1 -0
  93. package/dist/features/environment/GraphHeader/queries.esm.js +60 -0
  94. package/dist/features/environment/GraphHeader/queries.esm.js.map +1 -0
  95. package/dist/features/environment/InstanceDrawer/AlarmCard.esm.js +151 -0
  96. package/dist/features/environment/InstanceDrawer/AlarmCard.esm.js.map +1 -0
  97. package/dist/features/environment/InstanceDrawer/InstanceDrawer.esm.js +165 -0
  98. package/dist/features/environment/InstanceDrawer/InstanceDrawer.esm.js.map +1 -0
  99. package/dist/features/environment/InstanceDrawer/InstanceDrawerHeader.esm.js +241 -0
  100. package/dist/features/environment/InstanceDrawer/InstanceDrawerHeader.esm.js.map +1 -0
  101. package/dist/features/environment/InstanceDrawer/InstanceTabs.esm.js +119 -0
  102. package/dist/features/environment/InstanceDrawer/InstanceTabs.esm.js.map +1 -0
  103. package/dist/features/environment/InstanceDrawer/TabState.esm.js +30 -0
  104. package/dist/features/environment/InstanceDrawer/TabState.esm.js.map +1 -0
  105. package/dist/features/environment/InstanceDrawer/formsDataSource.esm.js +25 -0
  106. package/dist/features/environment/InstanceDrawer/formsDataSource.esm.js.map +1 -0
  107. package/dist/features/environment/InstanceDrawer/helpers.esm.js +282 -0
  108. package/dist/features/environment/InstanceDrawer/helpers.esm.js.map +1 -0
  109. package/dist/features/environment/InstanceDrawer/queries.esm.js +281 -0
  110. package/dist/features/environment/InstanceDrawer/queries.esm.js.map +1 -0
  111. package/dist/features/environment/InstanceDrawer/tabs/ConfigTab.esm.js +170 -0
  112. package/dist/features/environment/InstanceDrawer/tabs/ConfigTab.esm.js.map +1 -0
  113. package/dist/features/environment/InstanceDrawer/tabs/DependenciesTab.esm.js +413 -0
  114. package/dist/features/environment/InstanceDrawer/tabs/DependenciesTab.esm.js.map +1 -0
  115. package/dist/features/environment/InstanceDrawer/tabs/DeploymentLogsPanel.esm.js +191 -0
  116. package/dist/features/environment/InstanceDrawer/tabs/DeploymentLogsPanel.esm.js.map +1 -0
  117. package/dist/features/environment/InstanceDrawer/tabs/DeploymentReadOnlyActions.esm.js +63 -0
  118. package/dist/features/environment/InstanceDrawer/tabs/DeploymentReadOnlyActions.esm.js.map +1 -0
  119. package/dist/features/environment/InstanceDrawer/tabs/GuideTab.esm.js +48 -0
  120. package/dist/features/environment/InstanceDrawer/tabs/GuideTab.esm.js.map +1 -0
  121. package/dist/features/environment/InstanceDrawer/tabs/HistoryTab.esm.js +446 -0
  122. package/dist/features/environment/InstanceDrawer/tabs/HistoryTab.esm.js.map +1 -0
  123. package/dist/features/environment/InstanceDrawer/tabs/MonitorTab.esm.js +146 -0
  124. package/dist/features/environment/InstanceDrawer/tabs/MonitorTab.esm.js.map +1 -0
  125. package/dist/features/environment/InstanceDrawer/tabs/OverviewTab.esm.js +572 -0
  126. package/dist/features/environment/InstanceDrawer/tabs/OverviewTab.esm.js.map +1 -0
  127. package/dist/features/environment/InstanceDrawer/tabs/ResourcesTab.esm.js +471 -0
  128. package/dist/features/environment/InstanceDrawer/tabs/ResourcesTab.esm.js.map +1 -0
  129. package/dist/features/environment/InstanceDrawer/tabs/SecretsTab.esm.js +109 -0
  130. package/dist/features/environment/InstanceDrawer/tabs/SecretsTab.esm.js.map +1 -0
  131. package/dist/features/environment/InstanceDrawer/tabs/ViewDeploymentDetails.esm.js +384 -0
  132. package/dist/features/environment/InstanceDrawer/tabs/ViewDeploymentDetails.esm.js.map +1 -0
  133. package/dist/features/environment/InstanceDrawer/tabs/flattenParams.esm.js +23 -0
  134. package/dist/features/environment/InstanceDrawer/tabs/flattenParams.esm.js.map +1 -0
  135. package/dist/features/environment/InstanceDrawer/useInstanceApiQuery.esm.js +6 -0
  136. package/dist/features/environment/InstanceDrawer/useInstanceApiQuery.esm.js.map +1 -0
  137. package/dist/features/environment/InstanceDrawer/useOverflowMeasure.esm.js +55 -0
  138. package/dist/features/environment/InstanceDrawer/useOverflowMeasure.esm.js.map +1 -0
  139. package/dist/features/environment/InstanceDrawer/useResizableWidth.esm.js +44 -0
  140. package/dist/features/environment/InstanceDrawer/useResizableWidth.esm.js.map +1 -0
  141. package/dist/features/environment/components/InstanceStatusPill.esm.js +54 -0
  142. package/dist/features/environment/components/InstanceStatusPill.esm.js.map +1 -0
  143. package/dist/features/environment/graph/Diagram.esm.js +143 -0
  144. package/dist/features/environment/graph/Diagram.esm.js.map +1 -0
  145. package/dist/features/environment/graph/DiagramNode.constants.esm.js +5 -0
  146. package/dist/features/environment/graph/DiagramNode.constants.esm.js.map +1 -0
  147. package/dist/features/environment/graph/DiagramNode.esm.js +221 -0
  148. package/dist/features/environment/graph/DiagramNode.esm.js.map +1 -0
  149. package/dist/features/environment/graph/NodeMeta.esm.js +182 -0
  150. package/dist/features/environment/graph/NodeMeta.esm.js.map +1 -0
  151. package/dist/features/environment/graph/NodeVersionBadges.esm.js +150 -0
  152. package/dist/features/environment/graph/NodeVersionBadges.esm.js.map +1 -0
  153. package/dist/features/environment/graph/diagramFactory.esm.js +151 -0
  154. package/dist/features/environment/graph/diagramFactory.esm.js.map +1 -0
  155. package/dist/features/environment/graph/handles/ExpandableHandleWrapper.esm.js +174 -0
  156. package/dist/features/environment/graph/handles/ExpandableHandleWrapper.esm.js.map +1 -0
  157. package/dist/features/environment/graph/handles/NodeHandle.esm.js +45 -0
  158. package/dist/features/environment/graph/handles/NodeHandle.esm.js.map +1 -0
  159. package/dist/features/environment/graph/handles/NodeHandleTooltip.esm.js +134 -0
  160. package/dist/features/environment/graph/handles/NodeHandleTooltip.esm.js.map +1 -0
  161. package/dist/features/environment/graph/handles/handleTypes.esm.js +170 -0
  162. package/dist/features/environment/graph/handles/handleTypes.esm.js.map +1 -0
  163. package/dist/features/environment/graph/handles/useAnimationFrameSync.esm.js +19 -0
  164. package/dist/features/environment/graph/handles/useAnimationFrameSync.esm.js.map +1 -0
  165. package/dist/features/environment/graph/handles/useRadialPositions.esm.js +37 -0
  166. package/dist/features/environment/graph/handles/useRadialPositions.esm.js.map +1 -0
  167. package/dist/features/environment/graph/handles/useTransitionLifecycle.esm.js +19 -0
  168. package/dist/features/environment/graph/handles/useTransitionLifecycle.esm.js.map +1 -0
  169. package/dist/features/environment/graph/hasUndeployedPlan.esm.js +43 -0
  170. package/dist/features/environment/graph/hasUndeployedPlan.esm.js.map +1 -0
  171. package/dist/features/environment/graph/queries.esm.js +103 -0
  172. package/dist/features/environment/graph/queries.esm.js.map +1 -0
  173. package/dist/features/environment/graph/useDiagramSnapshot.esm.js +43 -0
  174. package/dist/features/environment/graph/useDiagramSnapshot.esm.js.map +1 -0
  175. package/dist/features/environment/realtime/RealtimeProvider.esm.js +43 -0
  176. package/dist/features/environment/realtime/RealtimeProvider.esm.js.map +1 -0
  177. package/dist/features/environment/realtime/queries.esm.js +76 -0
  178. package/dist/features/environment/realtime/queries.esm.js.map +1 -0
  179. package/dist/features/environment/realtime/useLiveRelayQuery.esm.js +36 -0
  180. package/dist/features/environment/realtime/useLiveRelayQuery.esm.js.map +1 -0
  181. package/dist/features/project/ProjectDetailsPage.esm.js +101 -0
  182. package/dist/features/project/ProjectDetailsPage.esm.js.map +1 -0
  183. package/dist/features/project/tabs/ComponentsTab.esm.js +149 -0
  184. package/dist/features/project/tabs/ComponentsTab.esm.js.map +1 -0
  185. package/dist/features/project/tabs/EnvStatus.esm.js +149 -0
  186. package/dist/features/project/tabs/EnvStatus.esm.js.map +1 -0
  187. package/dist/features/project/tabs/EnvironmentsTab.esm.js +199 -0
  188. package/dist/features/project/tabs/EnvironmentsTab.esm.js.map +1 -0
  189. package/dist/features/project/tabs/OverviewTab.esm.js +420 -0
  190. package/dist/features/project/tabs/OverviewTab.esm.js.map +1 -0
  191. package/dist/features/projects/ProjectsListPage.esm.js +50 -0
  192. package/dist/features/projects/ProjectsListPage.esm.js.map +1 -0
  193. package/dist/features/projects/ProjectsListPageLazy.esm.js +12 -0
  194. package/dist/features/projects/ProjectsListPageLazy.esm.js.map +1 -0
  195. package/dist/features/projects/projectColumns.esm.js +38 -0
  196. package/dist/features/projects/projectColumns.esm.js.map +1 -0
  197. package/dist/features/projects/useProjects.esm.js +48 -0
  198. package/dist/features/projects/useProjects.esm.js.map +1 -0
  199. package/dist/features/repo/DeploymentLogsDrawer.esm.js +213 -0
  200. package/dist/features/repo/DeploymentLogsDrawer.esm.js.map +1 -0
  201. package/dist/features/repo/DeploymentLogsDrawer.loading.esm.js +43 -0
  202. package/dist/features/repo/DeploymentLogsDrawer.loading.esm.js.map +1 -0
  203. package/dist/features/repo/FileTree.esm.js +179 -0
  204. package/dist/features/repo/FileTree.esm.js.map +1 -0
  205. package/dist/features/repo/FileViewer.esm.js +115 -0
  206. package/dist/features/repo/FileViewer.esm.js.map +1 -0
  207. package/dist/features/repo/FileViewer.helpers.esm.js +54 -0
  208. package/dist/features/repo/FileViewer.helpers.esm.js.map +1 -0
  209. package/dist/features/repo/RepoDetailsPage.esm.js +127 -0
  210. package/dist/features/repo/RepoDetailsPage.esm.js.map +1 -0
  211. package/dist/features/repo/RepoEmptyState.esm.js +58 -0
  212. package/dist/features/repo/RepoEmptyState.esm.js.map +1 -0
  213. package/dist/features/repo/RepoNoVersionsState.esm.js +29 -0
  214. package/dist/features/repo/RepoNoVersionsState.esm.js.map +1 -0
  215. package/dist/features/repo/RepoTabHeader.esm.js +30 -0
  216. package/dist/features/repo/RepoTabHeader.esm.js.map +1 -0
  217. package/dist/features/repo/RepoTabLayout.esm.js +18 -0
  218. package/dist/features/repo/RepoTabLayout.esm.js.map +1 -0
  219. package/dist/features/repo/RepoVersionSelect.esm.js +176 -0
  220. package/dist/features/repo/RepoVersionSelect.esm.js.map +1 -0
  221. package/dist/features/repo/ViewDeploymentDetailsDialog.esm.js +427 -0
  222. package/dist/features/repo/ViewDeploymentDetailsDialog.esm.js.map +1 -0
  223. package/dist/features/repo/deploymentHelpers.esm.js +74 -0
  224. package/dist/features/repo/deploymentHelpers.esm.js.map +1 -0
  225. package/dist/features/repo/fileTreeHelpers.esm.js +45 -0
  226. package/dist/features/repo/fileTreeHelpers.esm.js.map +1 -0
  227. package/dist/features/repo/flattenParams.esm.js +23 -0
  228. package/dist/features/repo/flattenParams.esm.js.map +1 -0
  229. package/dist/features/repo/queries.esm.js +239 -0
  230. package/dist/features/repo/queries.esm.js.map +1 -0
  231. package/dist/features/repo/repoFilter.esm.js +9 -0
  232. package/dist/features/repo/repoFilter.esm.js.map +1 -0
  233. package/dist/features/repo/repoTabs.esm.js +22 -0
  234. package/dist/features/repo/repoTabs.esm.js.map +1 -0
  235. package/dist/features/repo/resolveVersion.esm.js +22 -0
  236. package/dist/features/repo/resolveVersion.esm.js.map +1 -0
  237. package/dist/features/repo/tabs/DeploymentRow.esm.js +201 -0
  238. package/dist/features/repo/tabs/DeploymentRow.esm.js.map +1 -0
  239. package/dist/features/repo/tabs/DeploymentsTab.esm.js +188 -0
  240. package/dist/features/repo/tabs/DeploymentsTab.esm.js.map +1 -0
  241. package/dist/features/repo/tabs/DeploymentsTab.helpers.esm.js +46 -0
  242. package/dist/features/repo/tabs/DeploymentsTab.helpers.esm.js.map +1 -0
  243. package/dist/features/repo/tabs/DeploymentsTab.loading.esm.js +37 -0
  244. package/dist/features/repo/tabs/DeploymentsTab.loading.esm.js.map +1 -0
  245. package/dist/features/repo/tabs/FilesTab.esm.js +142 -0
  246. package/dist/features/repo/tabs/FilesTab.esm.js.map +1 -0
  247. package/dist/features/repo/tabs/InstanceRow.esm.js +121 -0
  248. package/dist/features/repo/tabs/InstanceRow.esm.js.map +1 -0
  249. package/dist/features/repo/tabs/InstancesTab.esm.js +147 -0
  250. package/dist/features/repo/tabs/InstancesTab.esm.js.map +1 -0
  251. package/dist/features/repo/tabs/InstancesTab.helpers.esm.js +44 -0
  252. package/dist/features/repo/tabs/InstancesTab.helpers.esm.js.map +1 -0
  253. package/dist/features/repo/tabs/InstancesTab.loading.esm.js +33 -0
  254. package/dist/features/repo/tabs/InstancesTab.loading.esm.js.map +1 -0
  255. package/dist/features/repo/tabs/OverviewTab.esm.js +77 -0
  256. package/dist/features/repo/tabs/OverviewTab.esm.js.map +1 -0
  257. package/dist/features/repo/tabs/PermissionsTab.esm.js +56 -0
  258. package/dist/features/repo/tabs/PermissionsTab.esm.js.map +1 -0
  259. package/dist/features/repo/tabs/VersionsTab.esm.js +152 -0
  260. package/dist/features/repo/tabs/VersionsTab.esm.js.map +1 -0
  261. package/dist/features/repo/useInfiniteRelayList.esm.js +92 -0
  262. package/dist/features/repo/useInfiniteRelayList.esm.js.map +1 -0
  263. package/dist/features/repo/useInfiniteScroll.esm.js +21 -0
  264. package/dist/features/repo/useInfiniteScroll.esm.js.map +1 -0
  265. package/dist/features/repos/ReposListPage.esm.js +53 -0
  266. package/dist/features/repos/ReposListPage.esm.js.map +1 -0
  267. package/dist/features/repos/queries.esm.js +40 -0
  268. package/dist/features/repos/queries.esm.js.map +1 -0
  269. package/dist/features/repos/repoColumns.esm.js +121 -0
  270. package/dist/features/repos/repoColumns.esm.js.map +1 -0
  271. package/dist/features/repos/useRepos.esm.js +22 -0
  272. package/dist/features/repos/useRepos.esm.js.map +1 -0
  273. package/dist/features/resource/OriginChip.esm.js +42 -0
  274. package/dist/features/resource/OriginChip.esm.js.map +1 -0
  275. package/dist/features/resource/ResourceDetailsPage.esm.js +167 -0
  276. package/dist/features/resource/ResourceDetailsPage.esm.js.map +1 -0
  277. package/dist/features/resource/queries.esm.js +141 -0
  278. package/dist/features/resource/queries.esm.js.map +1 -0
  279. package/dist/features/resource/tabs/GeneralTab.esm.js +247 -0
  280. package/dist/features/resource/tabs/GeneralTab.esm.js.map +1 -0
  281. package/dist/features/resource/tabs/GeneralTab.loading.esm.js +76 -0
  282. package/dist/features/resource/tabs/GeneralTab.loading.esm.js.map +1 -0
  283. package/dist/features/resource/tabs/PermissionsTab.esm.js +57 -0
  284. package/dist/features/resource/tabs/PermissionsTab.esm.js.map +1 -0
  285. package/dist/features/resource/tabs/SettingsTabLayout.esm.js +18 -0
  286. package/dist/features/resource/tabs/SettingsTabLayout.esm.js.map +1 -0
  287. package/dist/features/resource/tabs/TabHeader.esm.js +30 -0
  288. package/dist/features/resource/tabs/TabHeader.esm.js.map +1 -0
  289. package/dist/features/resource/tabs/UsagePanel.esm.js +35 -0
  290. package/dist/features/resource/tabs/UsagePanel.esm.js.map +1 -0
  291. package/dist/features/resource/tabs/UsageTab.esm.js +91 -0
  292. package/dist/features/resource/tabs/UsageTab.esm.js.map +1 -0
  293. package/dist/features/resource/tabs/UsageTab.helpers.esm.js +168 -0
  294. package/dist/features/resource/tabs/UsageTab.helpers.esm.js.map +1 -0
  295. package/dist/features/resources/ResourcesEmptyState.esm.js +148 -0
  296. package/dist/features/resources/ResourcesEmptyState.esm.js.map +1 -0
  297. package/dist/features/resources/ResourcesListPage.esm.js +115 -0
  298. package/dist/features/resources/ResourcesListPage.esm.js.map +1 -0
  299. package/dist/features/resources/queries.esm.js +50 -0
  300. package/dist/features/resources/queries.esm.js.map +1 -0
  301. package/dist/features/resources/resourceColumns.esm.js +158 -0
  302. package/dist/features/resources/resourceColumns.esm.js.map +1 -0
  303. package/dist/features/resources/resourceConstants.esm.js +7 -0
  304. package/dist/features/resources/resourceConstants.esm.js.map +1 -0
  305. package/dist/features/resources/toResourceRow.esm.js +29 -0
  306. package/dist/features/resources/toResourceRow.esm.js.map +1 -0
  307. package/dist/hooks/useAuthedSvg.esm.js +34 -0
  308. package/dist/hooks/useAuthedSvg.esm.js.map +1 -0
  309. package/dist/hooks/useCursorPagination.esm.js +40 -0
  310. package/dist/hooks/useCursorPagination.esm.js.map +1 -0
  311. package/dist/hooks/useMassdriverSubscription.esm.js +61 -0
  312. package/dist/hooks/useMassdriverSubscription.esm.js.map +1 -0
  313. package/dist/hooks/usePaginatedRelayQuery.esm.js +68 -0
  314. package/dist/hooks/usePaginatedRelayQuery.esm.js.map +1 -0
  315. package/dist/index.d.ts +256 -0
  316. package/dist/index.esm.js +8 -0
  317. package/dist/index.esm.js.map +1 -0
  318. package/dist/internalRoutes.esm.js +29 -0
  319. package/dist/internalRoutes.esm.js.map +1 -0
  320. package/dist/plugin.esm.js +57 -0
  321. package/dist/plugin.esm.js.map +1 -0
  322. package/dist/queries.esm.js +54 -0
  323. package/dist/queries.esm.js.map +1 -0
  324. package/dist/routes.esm.js +6 -0
  325. package/dist/routes.esm.js.map +1 -0
  326. package/dist/shell/MassdriverHeader.esm.js +37 -0
  327. package/dist/shell/MassdriverHeader.esm.js.map +1 -0
  328. package/dist/shell/MassdriverShell.esm.js +30 -0
  329. package/dist/shell/MassdriverShell.esm.js.map +1 -0
  330. package/dist/theme/MassdriverThemeScope.esm.js +30 -0
  331. package/dist/theme/MassdriverThemeScope.esm.js.map +1 -0
  332. package/dist/theme/ThemeModeContext.esm.js +35 -0
  333. package/dist/theme/ThemeModeContext.esm.js.map +1 -0
  334. package/dist/theme/muiClassNameAudit.esm.js +11 -0
  335. package/dist/theme/muiClassNameAudit.esm.js.map +1 -0
  336. package/dist/useInstances.esm.js +39 -0
  337. package/dist/useInstances.esm.js.map +1 -0
  338. package/dist/utils/attributes.esm.js +28 -0
  339. package/dist/utils/attributes.esm.js.map +1 -0
  340. package/dist/utils/conditions.esm.js +20 -0
  341. package/dist/utils/conditions.esm.js.map +1 -0
  342. package/dist/utils/formatRelativeTime.esm.js +40 -0
  343. package/dist/utils/formatRelativeTime.esm.js.map +1 -0
  344. package/dist/utils/instanceStatuses.esm.js +74 -0
  345. package/dist/utils/instanceStatuses.esm.js.map +1 -0
  346. package/package.json +92 -0
@@ -0,0 +1,147 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useMemo } from 'react';
3
+ import Alert from '@massdriver/ui/Alert';
4
+ import Box from '@massdriver/ui/Box';
5
+ import LoadingIndicator from '@massdriver/ui/LoadingIndicator';
6
+ import Select, { MenuItem } from '@massdriver/ui/Select';
7
+ import ExtensionIcon from '@massdriver/ui/icons/ExtensionIcon';
8
+ import FilterListIcon from '@massdriver/ui/icons/FilterListIcon';
9
+ import SortIcon from '@massdriver/ui/icons/SortIcon';
10
+ import stylin from '@massdriver/ui/stylin';
11
+ import { RepoEmptyState } from '../RepoEmptyState.esm.js';
12
+ import { RepoNoVersionsState } from '../RepoNoVersionsState.esm.js';
13
+ import { RepoTabHeader } from '../RepoTabHeader.esm.js';
14
+ import { RepoTabLayout } from '../RepoTabLayout.esm.js';
15
+ import { buildRepoVersionFilter } from '../repoFilter.esm.js';
16
+ import { ALL_VERSIONS } from '../resolveVersion.esm.js';
17
+ import { REPO_INSTANCES_QUERY } from '../queries.esm.js';
18
+ import { useInfiniteRelayList } from '../useInfiniteRelayList.esm.js';
19
+ import { useInfiniteScroll } from '../useInfiniteScroll.esm.js';
20
+ import { InstanceRow } from './InstanceRow.esm.js';
21
+ import { InstancesTabLoading } from './InstancesTab.loading.esm.js';
22
+ import { DEFAULT_SORT_VALUE, DEFAULT_STATUS_VALUE, sortValueToInput, statusValueToFilter, STATUS_OPTIONS, SORT_OPTIONS } from './InstancesTab.helpers.esm.js';
23
+ import '@mui/material/Chip';
24
+ import '@mui/material/Drawer';
25
+ import '@mui/material/OutlinedInput';
26
+ import { selectClasses } from '@mui/material/Select';
27
+ import '@mui/material/ToggleButton';
28
+
29
+ const InstancesTab = ({
30
+ repoId,
31
+ version,
32
+ hasNoVersions
33
+ }) => {
34
+ const [sortValue, setSortValue] = useState(DEFAULT_SORT_VALUE);
35
+ const [statusValue, setStatusValue] = useState(DEFAULT_STATUS_VALUE);
36
+ const versionScoped = version !== ALL_VERSIONS;
37
+ const sort = useMemo(() => sortValueToInput(sortValue), [sortValue]);
38
+ const status = useMemo(() => statusValueToFilter(statusValue), [statusValue]);
39
+ const versionFilter = buildRepoVersionFilter(repoId, version);
40
+ const filter = versionFilter && status ? { ...versionFilter, status: { eq: status } } : versionFilter;
41
+ const { items, loading, loadingMore, error, hasMore, onLoadMore } = useInfiniteRelayList(REPO_INSTANCES_QUERY, {
42
+ responseKey: "instances",
43
+ variables: { filter, sort },
44
+ pageSize: 20,
45
+ skip: hasNoVersions
46
+ });
47
+ const sentinelRef = useInfiniteScroll({
48
+ onLoadMore,
49
+ hasMore,
50
+ loading: loading || loadingMore
51
+ });
52
+ if (hasNoVersions) {
53
+ return /* @__PURE__ */ jsx(RepoNoVersionsState, { tabLabel: "instances" });
54
+ }
55
+ const description = versionScoped ? "Instances of this bundle version across your organization." : "Instances using any version of this bundle across your organization.";
56
+ return /* @__PURE__ */ jsxs(RepoTabLayout, { children: [
57
+ /* @__PURE__ */ jsx(RepoTabHeader, { title: "Instances", description }),
58
+ /* @__PURE__ */ jsxs(Controls, { children: [
59
+ /* @__PURE__ */ jsxs(ControlGroup, { children: [
60
+ /* @__PURE__ */ jsx(FilterListIcon, { fontSize: "small" }),
61
+ /* @__PURE__ */ jsx(
62
+ ControlSelect,
63
+ {
64
+ value: statusValue,
65
+ onChange: (event) => setStatusValue(event.target.value),
66
+ size: "small",
67
+ variant: "standard",
68
+ InputProps: { disableUnderline: true },
69
+ "aria-label": "Filter by instance status",
70
+ children: STATUS_OPTIONS.map((option) => /* @__PURE__ */ jsx(MenuItem, { value: option.value, children: option.label }, option.value))
71
+ }
72
+ )
73
+ ] }),
74
+ /* @__PURE__ */ jsxs(ControlGroup, { children: [
75
+ /* @__PURE__ */ jsx(SortIcon, { fontSize: "small" }),
76
+ /* @__PURE__ */ jsx(
77
+ ControlSelect,
78
+ {
79
+ value: sortValue,
80
+ onChange: (event) => setSortValue(event.target.value),
81
+ size: "small",
82
+ variant: "standard",
83
+ InputProps: { disableUnderline: true },
84
+ "aria-label": "Sort instances",
85
+ children: SORT_OPTIONS.map((option) => /* @__PURE__ */ jsx(MenuItem, { value: option.value, children: option.label }, option.value))
86
+ }
87
+ )
88
+ ] })
89
+ ] }),
90
+ error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: String(error.message ?? error) }) : loading && items.length === 0 ? /* @__PURE__ */ jsx(InstancesTabLoading, {}) : items.length === 0 ? /* @__PURE__ */ jsx(
91
+ RepoEmptyState,
92
+ {
93
+ icon: /* @__PURE__ */ jsx(ExtensionIcon, {}),
94
+ title: "No instances",
95
+ description: versionScoped ? "No instances match these filters for this bundle version." : "No instances match these filters for this bundle."
96
+ }
97
+ ) : /* @__PURE__ */ jsxs(List, { children: [
98
+ items.map((instance) => /* @__PURE__ */ jsx(InstanceRow, { instance }, instance.id)),
99
+ /* @__PURE__ */ jsx(Sentinel, { ref: sentinelRef }),
100
+ loadingMore ? /* @__PURE__ */ jsx(LoadingMoreRow, { children: /* @__PURE__ */ jsx(LoadingIndicator, { size: 24, delay: 0 }) }) : null
101
+ ] })
102
+ ] });
103
+ };
104
+ const Controls = stylin(Box)(({ theme }) => ({
105
+ display: "flex",
106
+ alignItems: "center",
107
+ gap: theme.spacing(2),
108
+ flexWrap: "wrap",
109
+ paddingBottom: theme.spacing(0.5),
110
+ borderBottom: `1px solid ${theme.palette.divider}`
111
+ }));
112
+ const ControlGroup = stylin(Box)(({ theme }) => ({
113
+ display: "flex",
114
+ alignItems: "center",
115
+ gap: theme.spacing(0.75),
116
+ color: theme.palette.text.secondary,
117
+ "& > svg": {
118
+ color: theme.palette.text.disabled
119
+ }
120
+ }));
121
+ const ControlSelect = stylin(Select)(({ theme }) => ({
122
+ [`& .${selectClasses.select}`]: {
123
+ fontSize: theme.typography.body2.fontSize,
124
+ padding: theme.spacing(0.25, 0.5),
125
+ paddingRight: `${theme.spacing(3)} !important`,
126
+ color: theme.palette.text.primary,
127
+ borderRadius: 1
128
+ }
129
+ }));
130
+ const List = stylin(Box)(({ theme }) => ({
131
+ display: "flex",
132
+ flexDirection: "column",
133
+ gap: theme.spacing(1.5)
134
+ }));
135
+ const Sentinel = stylin("div")({
136
+ height: 1,
137
+ width: "100%"
138
+ });
139
+ const LoadingMoreRow = stylin(Box)(({ theme }) => ({
140
+ display: "flex",
141
+ alignItems: "center",
142
+ justifyContent: "center",
143
+ padding: theme.spacing(1.5)
144
+ }));
145
+
146
+ export { InstancesTab };
147
+ //# sourceMappingURL=InstancesTab.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstancesTab.esm.js","sources":["../../../../src/features/repo/tabs/InstancesTab.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport Alert from '@massdriver/ui/Alert';\nimport Box from '@massdriver/ui/Box';\nimport LoadingIndicator from '@massdriver/ui/LoadingIndicator';\nimport Select, { MenuItem } from '@massdriver/ui/Select';\nimport ExtensionIcon from '@massdriver/ui/icons/ExtensionIcon';\nimport FilterListIcon from '@massdriver/ui/icons/FilterListIcon';\nimport SortIcon from '@massdriver/ui/icons/SortIcon';\nimport stylin from '@massdriver/ui/stylin';\nimport { RepoEmptyState } from '../RepoEmptyState';\nimport { RepoNoVersionsState } from '../RepoNoVersionsState';\nimport { RepoTabHeader } from '../RepoTabHeader';\nimport { RepoTabLayout } from '../RepoTabLayout';\nimport { buildRepoVersionFilter } from '../repoFilter';\nimport { ALL_VERSIONS } from '../resolveVersion';\nimport { REPO_INSTANCES_QUERY } from '../queries';\nimport type { RepoTabProps } from '../RepoDetailsPage';\nimport type { RepoInstance } from '../types';\nimport { useInfiniteRelayList } from '../useInfiniteRelayList';\nimport { useInfiniteScroll } from '../useInfiniteScroll';\nimport { InstanceRow } from './InstanceRow';\nimport { InstancesTabLoading } from './InstancesTab.loading';\nimport {\n DEFAULT_SORT_VALUE,\n DEFAULT_STATUS_VALUE,\n SORT_OPTIONS,\n STATUS_OPTIONS,\n sortValueToInput,\n statusValueToFilter,\n} from './InstancesTab.helpers';\nimport { selectClasses } from '../../../theme/muiClasses';\n\n// Ported from apps/web/features/repos/sections/InstancesTab/ (container + view\n// merged into one component, matching this plugin's single-file tab style). The\n// web app's infinite-scroll card list is reproduced here over the relay via\n// useInfiniteRelayList + an IntersectionObserver sentinel.\nexport const InstancesTab = ({\n repoId,\n version,\n hasNoVersions,\n}: RepoTabProps) => {\n const [sortValue, setSortValue] = useState(DEFAULT_SORT_VALUE);\n const [statusValue, setStatusValue] = useState(DEFAULT_STATUS_VALUE);\n const versionScoped = version !== ALL_VERSIONS;\n\n const sort = useMemo(() => sortValueToInput(sortValue), [sortValue]);\n const status = useMemo(() => statusValueToFilter(statusValue), [statusValue]);\n\n const versionFilter = buildRepoVersionFilter(repoId, version);\n const filter =\n versionFilter && status\n ? { ...versionFilter, status: { eq: status } }\n : versionFilter;\n\n const { items, loading, loadingMore, error, hasMore, onLoadMore } =\n useInfiniteRelayList<RepoInstance>(REPO_INSTANCES_QUERY, {\n responseKey: 'instances',\n variables: { filter, sort },\n pageSize: 20,\n skip: hasNoVersions,\n });\n\n const sentinelRef = useInfiniteScroll({\n onLoadMore,\n hasMore,\n loading: loading || loadingMore,\n });\n\n if (hasNoVersions) {\n return <RepoNoVersionsState tabLabel=\"instances\" />;\n }\n\n const description = versionScoped\n ? 'Instances of this bundle version across your organization.'\n : 'Instances using any version of this bundle across your organization.';\n\n return (\n <RepoTabLayout>\n <RepoTabHeader title=\"Instances\" description={description} />\n <Controls>\n <ControlGroup>\n <FilterListIcon fontSize=\"small\" />\n <ControlSelect\n value={statusValue}\n onChange={(event: { target: { value: string } }) =>\n setStatusValue(event.target.value)\n }\n size=\"small\"\n variant=\"standard\"\n InputProps={{ disableUnderline: true }}\n aria-label=\"Filter by instance status\"\n >\n {STATUS_OPTIONS.map(option => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </ControlSelect>\n </ControlGroup>\n <ControlGroup>\n <SortIcon fontSize=\"small\" />\n <ControlSelect\n value={sortValue}\n onChange={(event: { target: { value: string } }) =>\n setSortValue(event.target.value)\n }\n size=\"small\"\n variant=\"standard\"\n InputProps={{ disableUnderline: true }}\n aria-label=\"Sort instances\"\n >\n {SORT_OPTIONS.map(option => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </ControlSelect>\n </ControlGroup>\n </Controls>\n {error ? (\n <Alert severity=\"error\">{String(error.message ?? error)}</Alert>\n ) : loading && items.length === 0 ? (\n <InstancesTabLoading />\n ) : items.length === 0 ? (\n <RepoEmptyState\n icon={<ExtensionIcon />}\n title=\"No instances\"\n description={\n versionScoped\n ? 'No instances match these filters for this bundle version.'\n : 'No instances match these filters for this bundle.'\n }\n />\n ) : (\n <List>\n {items.map(instance => (\n <InstanceRow key={instance.id} instance={instance} />\n ))}\n <Sentinel ref={sentinelRef} />\n {loadingMore ? (\n <LoadingMoreRow>\n <LoadingIndicator size={24} delay={0} />\n </LoadingMoreRow>\n ) : null}\n </List>\n )}\n </RepoTabLayout>\n );\n};\n\nconst Controls = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n flexWrap: 'wrap',\n paddingBottom: theme.spacing(0.5),\n borderBottom: `1px solid ${theme.palette.divider}`,\n}));\n\nconst ControlGroup = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.75),\n color: theme.palette.text.secondary,\n '& > svg': {\n color: theme.palette.text.disabled,\n },\n}));\n\nconst ControlSelect = stylin(Select)(({ theme }: { theme: any }) => ({\n [`& .${selectClasses.select}`]: {\n fontSize: theme.typography.body2.fontSize,\n padding: theme.spacing(0.25, 0.5),\n paddingRight: `${theme.spacing(3)} !important`,\n color: theme.palette.text.primary,\n borderRadius: 1,\n },\n}));\n\nconst List = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1.5),\n}));\n\nconst Sentinel = stylin('div')({\n height: 1,\n width: '100%',\n});\n\nconst LoadingMoreRow = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: theme.spacing(1.5),\n}));\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ const STATUS_OPTIONS = [
2
+ { value: "ALL", label: "All statuses" },
3
+ { value: "PROVISIONED", label: "Provisioned" },
4
+ { value: "INITIALIZED", label: "Initialized" },
5
+ { value: "FAILED", label: "Failed" },
6
+ { value: "DECOMMISSIONED", label: "Decommissioned" }
7
+ ];
8
+ const DEFAULT_STATUS_VALUE = "ALL";
9
+ const statusValueToFilter = (value) => value === "ALL" || !value ? null : value;
10
+ const SORT_OPTIONS = [
11
+ { value: "NAME_ASC", label: "Name (A\u2013Z)" },
12
+ { value: "NAME_DESC", label: "Name (Z\u2013A)" },
13
+ { value: "CREATED_AT_DESC", label: "Newest first" },
14
+ { value: "CREATED_AT_ASC", label: "Oldest first" }
15
+ ];
16
+ const DEFAULT_SORT_VALUE = "NAME_ASC";
17
+ const sortValueToInput = (value) => {
18
+ switch (value) {
19
+ case "NAME_DESC":
20
+ return { field: "NAME", order: "DESC" };
21
+ case "CREATED_AT_ASC":
22
+ return { field: "CREATED_AT", order: "ASC" };
23
+ case "CREATED_AT_DESC":
24
+ return { field: "CREATED_AT", order: "DESC" };
25
+ case "NAME_ASC":
26
+ default:
27
+ return { field: "NAME", order: "ASC" };
28
+ }
29
+ };
30
+ const formatCost = (lastMonth, { fallback = "\u2014" } = {}) => {
31
+ if (!lastMonth || lastMonth.amount == null) return fallback;
32
+ try {
33
+ return new Intl.NumberFormat("en-US", {
34
+ style: "currency",
35
+ currency: lastMonth.currency || "USD",
36
+ maximumFractionDigits: 2
37
+ }).format(lastMonth.amount);
38
+ } catch {
39
+ return `${lastMonth.amount}`;
40
+ }
41
+ };
42
+
43
+ export { DEFAULT_SORT_VALUE, DEFAULT_STATUS_VALUE, SORT_OPTIONS, STATUS_OPTIONS, formatCost, sortValueToInput, statusValueToFilter };
44
+ //# sourceMappingURL=InstancesTab.helpers.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstancesTab.helpers.esm.js","sources":["../../../../src/features/repo/tabs/InstancesTab.helpers.ts"],"sourcesContent":["// Ported from apps/web/features/repos/sections/InstancesTab/InstancesTab.helpers.js.\n\nexport const STATUS_OPTIONS = [\n { value: 'ALL', label: 'All statuses' },\n { value: 'PROVISIONED', label: 'Provisioned' },\n { value: 'INITIALIZED', label: 'Initialized' },\n { value: 'FAILED', label: 'Failed' },\n { value: 'DECOMMISSIONED', label: 'Decommissioned' },\n];\n\nexport const DEFAULT_STATUS_VALUE = 'ALL';\n\nexport const statusValueToFilter = (value: string): string | null =>\n value === 'ALL' || !value ? null : value;\n\nexport const SORT_OPTIONS = [\n { value: 'NAME_ASC', label: 'Name (A–Z)' },\n { value: 'NAME_DESC', label: 'Name (Z–A)' },\n { value: 'CREATED_AT_DESC', label: 'Newest first' },\n { value: 'CREATED_AT_ASC', label: 'Oldest first' },\n];\n\nexport const DEFAULT_SORT_VALUE = 'NAME_ASC';\n\nexport interface SortInput {\n field: string;\n order: 'ASC' | 'DESC';\n}\n\nexport const sortValueToInput = (value: string): SortInput => {\n switch (value) {\n case 'NAME_DESC':\n return { field: 'NAME', order: 'DESC' };\n case 'CREATED_AT_ASC':\n return { field: 'CREATED_AT', order: 'ASC' };\n case 'CREATED_AT_DESC':\n return { field: 'CREATED_AT', order: 'DESC' };\n case 'NAME_ASC':\n default:\n return { field: 'NAME', order: 'ASC' };\n }\n};\n\nexport const formatCost = (\n lastMonth: { amount?: number | null; currency?: string } | null | undefined,\n { fallback = '—' }: { fallback?: string | null } = {},\n): string | null => {\n if (!lastMonth || lastMonth.amount == null) return fallback;\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: lastMonth.currency || 'USD',\n maximumFractionDigits: 2,\n }).format(lastMonth.amount);\n } catch {\n return `${lastMonth.amount}`;\n }\n};\n"],"names":[],"mappings":"AAEO,MAAM,cAAA,GAAiB;AAAA,EAC5B,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,cAAA,EAAe;AAAA,EACtC,EAAE,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,aAAA,EAAc;AAAA,EAC7C,EAAE,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,aAAA,EAAc;AAAA,EAC7C,EAAE,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,QAAA,EAAS;AAAA,EACnC,EAAE,KAAA,EAAO,gBAAA,EAAkB,KAAA,EAAO,gBAAA;AACpC;AAEO,MAAM,oBAAA,GAAuB;AAE7B,MAAM,sBAAsB,CAAC,KAAA,KAClC,UAAU,KAAA,IAAS,CAAC,QAAQ,IAAA,GAAO;AAE9B,MAAM,YAAA,GAAe;AAAA,EAC1B,EAAE,KAAA,EAAO,UAAA,EAAY,KAAA,EAAO,iBAAA,EAAa;AAAA,EACzC,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,iBAAA,EAAa;AAAA,EAC1C,EAAE,KAAA,EAAO,iBAAA,EAAmB,KAAA,EAAO,cAAA,EAAe;AAAA,EAClD,EAAE,KAAA,EAAO,gBAAA,EAAkB,KAAA,EAAO,cAAA;AACpC;AAEO,MAAM,kBAAA,GAAqB;AAO3B,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAA6B;AAC5D,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,WAAA;AACH,MAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAO;AAAA,IACxC,KAAK,gBAAA;AACH,MAAA,OAAO,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,KAAA,EAAM;AAAA,IAC7C,KAAK,iBAAA;AACH,MAAA,OAAO,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,MAAA,EAAO;AAAA,IAC9C,KAAK,UAAA;AAAA,IACL;AACE,MAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAM;AAAA;AAE3C;AAEO,MAAM,UAAA,GAAa,CACxB,SAAA,EACA,EAAE,WAAW,QAAA,EAAI,GAAkC,EAAC,KAClC;AAClB,EAAA,IAAI,CAAC,SAAA,IAAa,SAAA,CAAU,MAAA,IAAU,MAAM,OAAO,QAAA;AACnD,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS;AAAA,MACpC,KAAA,EAAO,UAAA;AAAA,MACP,QAAA,EAAU,UAAU,QAAA,IAAY,KAAA;AAAA,MAChC,qBAAA,EAAuB;AAAA,KACxB,CAAA,CAAE,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,CAAA,EAAG,UAAU,MAAM,CAAA,CAAA;AAAA,EAC5B;AACF;;;;"}
@@ -0,0 +1,33 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import Box from '@massdriver/ui/Box';
3
+ import Skeleton from '@massdriver/ui/Skeleton';
4
+ import stylin from '@massdriver/ui/stylin';
5
+
6
+ const ROW_COUNT = 4;
7
+ const InstancesTabLoading = () => /* @__PURE__ */ jsx(List, { children: Array.from({ length: ROW_COUNT }).map((_, index) => /* @__PURE__ */ jsxs(RowSkeleton, { children: [
8
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", width: 72, height: 20 }),
9
+ /* @__PURE__ */ jsx(Skeleton, { variant: "text", width: "30%" }),
10
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", width: 60, height: 20 }),
11
+ /* @__PURE__ */ jsx(Spacer, {}),
12
+ /* @__PURE__ */ jsx(Skeleton, { variant: "text", width: 80 })
13
+ ] }, index)) });
14
+ const List = stylin(Box)(({ theme }) => ({
15
+ display: "flex",
16
+ flexDirection: "column",
17
+ gap: theme.spacing(1.5)
18
+ }));
19
+ const RowSkeleton = stylin(Box)(({ theme }) => ({
20
+ display: "flex",
21
+ alignItems: "center",
22
+ gap: theme.spacing(1),
23
+ padding: theme.spacing(1.5),
24
+ borderRadius: 1,
25
+ border: `1px solid ${theme.palette.divider}`,
26
+ backgroundColor: theme.palette.background.paper
27
+ }));
28
+ const Spacer = stylin(Box)({
29
+ flex: 1
30
+ });
31
+
32
+ export { InstancesTabLoading };
33
+ //# sourceMappingURL=InstancesTab.loading.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstancesTab.loading.esm.js","sources":["../../../../src/features/repo/tabs/InstancesTab.loading.tsx"],"sourcesContent":["import Box from '@massdriver/ui/Box';\nimport Skeleton from '@massdriver/ui/Skeleton';\nimport stylin from '@massdriver/ui/stylin';\n\n// Ported from apps/web/features/repos/sections/InstancesTab/InstancesTab.loading.js.\nconst ROW_COUNT = 4;\n\nexport const InstancesTabLoading = () => (\n <List>\n {Array.from({ length: ROW_COUNT }).map((_, index) => (\n <RowSkeleton key={index}>\n <Skeleton variant=\"rounded\" width={72} height={20} />\n <Skeleton variant=\"text\" width=\"30%\" />\n <Skeleton variant=\"rounded\" width={60} height={20} />\n <Spacer />\n <Skeleton variant=\"text\" width={80} />\n </RowSkeleton>\n ))}\n </List>\n);\n\nexport default InstancesTabLoading;\n\nconst List = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1.5),\n}));\n\nconst RowSkeleton = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n padding: theme.spacing(1.5),\n borderRadius: 1,\n border: `1px solid ${theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n}));\n\nconst Spacer = stylin(Box)({\n flex: 1,\n});\n"],"names":[],"mappings":";;;;;AAKA,MAAM,SAAA,GAAY,CAAA;AAEX,MAAM,sBAAsB,sBACjC,GAAA,CAAC,IAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,KAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,EAAE,GAAA,CAAI,CAAC,CAAA,EAAG,KAAA,0BACxC,WAAA,EAAA,EACC,QAAA,EAAA;AAAA,kBAAA,GAAA,CAAC,YAAS,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA,EAAI,CAAA;AAAA,kBACnD,GAAA,CAAC,QAAA,EAAA,EAAS,OAAA,EAAQ,MAAA,EAAO,OAAM,KAAA,EAAM,CAAA;AAAA,sBACpC,QAAA,EAAA,EAAS,OAAA,EAAQ,WAAU,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA,EAAI,CAAA;AAAA,sBAClD,MAAA,EAAA,EAAO,CAAA;AAAA,kBACR,GAAA,CAAC,QAAA,EAAA,EAAS,OAAA,EAAQ,MAAA,EAAO,OAAO,EAAA,EAAI;AAAA,CAAA,EAAA,EALpB,KAMlB,CACD,CAAA,EACH;AAKF,MAAM,OAAO,MAAA,CAAO,GAAG,EAAE,CAAC,EAAE,OAAM,MAAuB;AAAA,EACvD,OAAA,EAAS,MAAA;AAAA,EACT,aAAA,EAAe,QAAA;AAAA,EACf,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG;AACxB,CAAA,CAAE,CAAA;AAEF,MAAM,cAAc,MAAA,CAAO,GAAG,EAAE,CAAC,EAAE,OAAM,MAAuB;AAAA,EAC9D,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,EAC1B,YAAA,EAAc,CAAA;AAAA,EACd,MAAA,EAAQ,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,EAC1C,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW;AAC5C,CAAA,CAAE,CAAA;AAEF,MAAM,MAAA,GAAS,MAAA,CAAO,GAAG,CAAA,CAAE;AAAA,EACzB,IAAA,EAAM;AACR,CAAC,CAAA;;;;"}
@@ -0,0 +1,77 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useApi } from '@backstage/frontend-plugin-api';
3
+ import Alert from '@massdriver/ui/Alert';
4
+ import Box from '@massdriver/ui/Box';
5
+ import Button from '@massdriver/ui/Button';
6
+ import GuideMarkdown from '@massdriver/ui/GuideMarkdown';
7
+ import LoadingIndicator from '@massdriver/ui/LoadingIndicator';
8
+ import DescriptionOutlinedIcon from '@massdriver/ui/icons/DescriptionOutlinedIcon';
9
+ import stylin from '@massdriver/ui/stylin';
10
+ import useAsync from 'react-use/esm/useAsync';
11
+ import { massdriverApiRef } from '../../../api.esm.js';
12
+ import { BUNDLE_QUERY } from '../queries.esm.js';
13
+ import { bundleQueryId } from '../resolveVersion.esm.js';
14
+ import { RepoEmptyState } from '../RepoEmptyState.esm.js';
15
+ import { RepoNoVersionsState } from '../RepoNoVersionsState.esm.js';
16
+
17
+ const OverviewTab = ({
18
+ repoId,
19
+ version,
20
+ hasNoVersions
21
+ }) => {
22
+ const api = useApi(massdriverApiRef);
23
+ const id = bundleQueryId(repoId, version);
24
+ const { value, loading, error } = useAsync(async () => {
25
+ if (hasNoVersions || !id) return null;
26
+ const data = await api.query(BUNDLE_QUERY, { id });
27
+ return data.bundle;
28
+ }, [api, id, hasNoVersions]);
29
+ if (hasNoVersions) {
30
+ return /* @__PURE__ */ jsx(RepoNoVersionsState, { tabLabel: "an overview" });
31
+ }
32
+ if (loading) {
33
+ return /* @__PURE__ */ jsx(Centered, { children: /* @__PURE__ */ jsx(LoadingIndicator, {}) });
34
+ }
35
+ if (error) {
36
+ return /* @__PURE__ */ jsx(Padded, { children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: String(error.message ?? error) }) });
37
+ }
38
+ const readme = value?.readme;
39
+ const sourceUrl = value?.sourceUrl;
40
+ const versionLabel = !version || version === "all" ? "latest" : version;
41
+ return readme ? /* @__PURE__ */ jsx(ReadmeContainer, { children: /* @__PURE__ */ jsx(GuideMarkdown, { shouldLinkHeadings: true, children: readme }) }) : /* @__PURE__ */ jsx(EmptyContainer, { children: /* @__PURE__ */ jsx(
42
+ RepoEmptyState,
43
+ {
44
+ icon: /* @__PURE__ */ jsx(DescriptionOutlinedIcon, {}),
45
+ title: `Version ${versionLabel} has no README`,
46
+ description: sourceUrl ? "Add a README.md in the source repository to display it here." : "Add a README.md in your code repository to make it available here.",
47
+ action: sourceUrl ? /* @__PURE__ */ jsx(
48
+ Button,
49
+ {
50
+ href: sourceUrl,
51
+ target: "_blank",
52
+ rel: "noopener noreferrer",
53
+ variant: "text",
54
+ children: "Open source repository"
55
+ }
56
+ ) : null
57
+ }
58
+ ) });
59
+ };
60
+ const ReadmeContainer = stylin(Box)(({ theme }) => ({
61
+ padding: theme.spacing(3),
62
+ maxWidth: "100%"
63
+ }));
64
+ const Padded = stylin(Box)(({ theme }) => ({
65
+ padding: theme.spacing(3)
66
+ }));
67
+ const Centered = stylin(Box)(({ theme }) => ({
68
+ display: "flex",
69
+ justifyContent: "center",
70
+ padding: theme.spacing(6)
71
+ }));
72
+ const EmptyContainer = stylin(Box)(({ theme }) => ({
73
+ padding: theme.spacing(3)
74
+ }));
75
+
76
+ export { OverviewTab };
77
+ //# sourceMappingURL=OverviewTab.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OverviewTab.esm.js","sources":["../../../../src/features/repo/tabs/OverviewTab.tsx"],"sourcesContent":["import { useApi } from '@backstage/frontend-plugin-api';\nimport Alert from '@massdriver/ui/Alert';\nimport Box from '@massdriver/ui/Box';\nimport Button from '@massdriver/ui/Button';\nimport GuideMarkdown from '@massdriver/ui/GuideMarkdown';\nimport LoadingIndicator from '@massdriver/ui/LoadingIndicator';\nimport DescriptionOutlinedIcon from '@massdriver/ui/icons/DescriptionOutlinedIcon';\nimport stylin from '@massdriver/ui/stylin';\nimport useAsync from 'react-use/esm/useAsync';\nimport { massdriverApiRef } from '../../../api';\nimport type { RepoTabProps } from '../RepoDetailsPage';\nimport { BUNDLE_QUERY } from '../queries';\nimport { bundleQueryId } from '../resolveVersion';\nimport { RepoEmptyState } from '../RepoEmptyState';\nimport { RepoNoVersionsState } from '../RepoNoVersionsState';\nimport type { RepoBundle } from '../types';\n\n// Ported from apps/web/features/repos/sections/OverviewTab/. Renders the\n// bundle's README; empty state links out to the source repository when known.\nexport const OverviewTab = ({\n repoId,\n version,\n hasNoVersions,\n}: RepoTabProps) => {\n const api = useApi(massdriverApiRef);\n const id = bundleQueryId(repoId, version);\n\n const { value, loading, error } = useAsync(async () => {\n if (hasNoVersions || !id) return null;\n const data = (await api.query(BUNDLE_QUERY, { id })) as {\n bundle: RepoBundle | null;\n };\n return data.bundle;\n }, [api, id, hasNoVersions]);\n\n if (hasNoVersions) {\n return <RepoNoVersionsState tabLabel=\"an overview\" />;\n }\n\n if (loading) {\n return (\n <Centered>\n <LoadingIndicator />\n </Centered>\n );\n }\n\n if (error) {\n return (\n <Padded>\n <Alert severity=\"error\">{String(error.message ?? error)}</Alert>\n </Padded>\n );\n }\n\n const readme = value?.readme;\n const sourceUrl = value?.sourceUrl;\n const versionLabel = !version || version === 'all' ? 'latest' : version;\n\n return readme ? (\n <ReadmeContainer>\n <GuideMarkdown shouldLinkHeadings>{readme}</GuideMarkdown>\n </ReadmeContainer>\n ) : (\n <EmptyContainer>\n <RepoEmptyState\n icon={<DescriptionOutlinedIcon />}\n title={`Version ${versionLabel} has no README`}\n description={\n sourceUrl\n ? 'Add a README.md in the source repository to display it here.'\n : 'Add a README.md in your code repository to make it available here.'\n }\n action={\n sourceUrl ? (\n <Button\n href={sourceUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n variant=\"text\"\n >\n Open source repository\n </Button>\n ) : null\n }\n />\n </EmptyContainer>\n );\n};\n\nconst ReadmeContainer = stylin(Box)(({ theme }: { theme: any }) => ({\n padding: theme.spacing(3),\n maxWidth: '100%',\n}));\n\nconst Padded = stylin(Box)(({ theme }: { theme: any }) => ({\n padding: theme.spacing(3),\n}));\n\nconst Centered = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n justifyContent: 'center',\n padding: theme.spacing(6),\n}));\n\nconst EmptyContainer = stylin(Box)(({ theme }: { theme: any }) => ({\n padding: theme.spacing(3),\n}));\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useApi } from '@backstage/frontend-plugin-api';
3
+ import { repoTabUrl } from '@massdriver/backstage-plugin-common';
4
+ import Alert from '@massdriver/ui/Alert';
5
+ import DataList from '@massdriver/ui/DataList';
6
+ import { massdriverApiRef } from '../../../api.esm.js';
7
+ import { OpenInMassdriverButton } from '../../../components/OpenInMassdriverButton.esm.js';
8
+ import { buildGrantColumns, mapGrantToRow } from '../../../components/grantColumns.esm.js';
9
+ import { usePaginatedRelayQuery } from '../../../hooks/usePaginatedRelayQuery.esm.js';
10
+ import { RepoTabHeader } from '../RepoTabHeader.esm.js';
11
+ import { RepoTabLayout } from '../RepoTabLayout.esm.js';
12
+ import { REPO_GRANTS_QUERY } from '../queries.esm.js';
13
+
14
+ const PermissionsTab = ({ repoId, version }) => {
15
+ const api = useApi(massdriverApiRef);
16
+ const { items, loading, error, hasMore, dataListParams } = usePaginatedRelayQuery(REPO_GRANTS_QUERY, {
17
+ responseKey: ["ociRepo", "grants"],
18
+ variables: { id: repoId },
19
+ pageSize: 20
20
+ });
21
+ const manageUrl = repoTabUrl(
22
+ api.appUrl,
23
+ api.organizationId,
24
+ repoId,
25
+ version || "all",
26
+ "permissions"
27
+ );
28
+ const columns = buildGrantColumns({ manageUrl });
29
+ const rows = items.map(mapGrantToRow);
30
+ return /* @__PURE__ */ jsxs(RepoTabLayout, { children: [
31
+ /* @__PURE__ */ jsx(
32
+ RepoTabHeader,
33
+ {
34
+ title: "Permissions",
35
+ description: "Share this repository with other projects. Each permission grants repo:pull to recipient projects whose attributes match the recipient conditions.",
36
+ actions: /* @__PURE__ */ jsx(OpenInMassdriverButton, { url: manageUrl, children: "Add permission" })
37
+ }
38
+ ),
39
+ error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: String(error.message ?? error) }) : /* @__PURE__ */ jsx(
40
+ DataList,
41
+ {
42
+ rows,
43
+ columns,
44
+ loading,
45
+ serverSide: true,
46
+ hasMore,
47
+ emptyMessage: "No permissions yet. Add one to share this repository with other projects.",
48
+ variant: "outlined",
49
+ ...dataListParams
50
+ }
51
+ )
52
+ ] });
53
+ };
54
+
55
+ export { PermissionsTab };
56
+ //# sourceMappingURL=PermissionsTab.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermissionsTab.esm.js","sources":["../../../../src/features/repo/tabs/PermissionsTab.tsx"],"sourcesContent":["import { useApi } from '@backstage/frontend-plugin-api';\nimport { repoTabUrl } from '@massdriver/backstage-plugin-common';\nimport Alert from '@massdriver/ui/Alert';\nimport DataList from '@massdriver/ui/DataList';\nimport { massdriverApiRef } from '../../../api';\nimport { OpenInMassdriverButton } from '../../../components/OpenInMassdriverButton';\nimport {\n buildGrantColumns,\n mapGrantToRow,\n Grant,\n} from '../../../components/grantColumns';\nimport { usePaginatedRelayQuery } from '../../../hooks/usePaginatedRelayQuery';\nimport { RepoTabHeader } from '../RepoTabHeader';\nimport { RepoTabLayout } from '../RepoTabLayout';\nimport type { RepoTabProps } from '../RepoDetailsPage';\nimport { REPO_GRANTS_QUERY } from '../queries';\n\n// Ported from apps/web/features/repos/sections/PermissionsTab/. Uses the shared\n// tab layout + header, matching the web. The web app's \"Add permission\" and\n// per-row \"Remove\" both mutate — here they deep-link out to this repo's\n// Permissions tab in the Massdriver web app (read-only parity).\nexport const PermissionsTab = ({ repoId, version }: RepoTabProps) => {\n const api = useApi(massdriverApiRef);\n const { items, loading, error, hasMore, dataListParams } =\n usePaginatedRelayQuery<Grant>(REPO_GRANTS_QUERY, {\n responseKey: ['ociRepo', 'grants'],\n variables: { id: repoId },\n pageSize: 20,\n });\n\n const manageUrl = repoTabUrl(\n api.appUrl,\n api.organizationId,\n repoId,\n version || 'all',\n 'permissions',\n );\n const columns = buildGrantColumns({ manageUrl });\n const rows = items.map(mapGrantToRow);\n\n return (\n <RepoTabLayout>\n <RepoTabHeader\n title=\"Permissions\"\n description=\"Share this repository with other projects. Each permission grants repo:pull to recipient projects whose attributes match the recipient conditions.\"\n actions={\n <OpenInMassdriverButton url={manageUrl}>\n Add permission\n </OpenInMassdriverButton>\n }\n />\n {error ? (\n <Alert severity=\"error\">{String(error.message ?? error)}</Alert>\n ) : (\n <DataList\n rows={rows}\n columns={columns}\n loading={loading}\n serverSide\n hasMore={hasMore}\n emptyMessage=\"No permissions yet. Add one to share this repository with other projects.\"\n variant=\"outlined\"\n {...dataListParams}\n />\n )}\n </RepoTabLayout>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AAqBO,MAAM,cAAA,GAAiB,CAAC,EAAE,MAAA,EAAQ,SAAQ,KAAoB;AACnE,EAAA,MAAM,GAAA,GAAM,OAAO,gBAAgB,CAAA;AACnC,EAAA,MAAM,EAAE,OAAO,OAAA,EAAS,KAAA,EAAO,SAAS,cAAA,EAAe,GACrD,uBAA8B,iBAAA,EAAmB;AAAA,IAC/C,WAAA,EAAa,CAAC,SAAA,EAAW,QAAQ,CAAA;AAAA,IACjC,SAAA,EAAW,EAAE,EAAA,EAAI,MAAA,EAAO;AAAA,IACxB,QAAA,EAAU;AAAA,GACX,CAAA;AAEH,EAAA,MAAM,SAAA,GAAY,UAAA;AAAA,IAChB,GAAA,CAAI,MAAA;AAAA,IACJ,GAAA,CAAI,cAAA;AAAA,IACJ,MAAA;AAAA,IACA,OAAA,IAAW,KAAA;AAAA,IACX;AAAA,GACF;AACA,EAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,EAAE,SAAA,EAAW,CAAA;AAC/C,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,GAAA,CAAI,aAAa,CAAA;AAEpC,EAAA,4BACG,aAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAM,aAAA;AAAA,QACN,WAAA,EAAY,oJAAA;AAAA,QACZ,OAAA,kBACE,GAAA,CAAC,sBAAA,EAAA,EAAuB,GAAA,EAAK,WAAW,QAAA,EAAA,gBAAA,EAExC;AAAA;AAAA,KAEJ;AAAA,IACC,KAAA,mBACC,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,iBAAO,KAAA,CAAM,OAAA,IAAW,KAAK,CAAA,EAAE,CAAA,mBAExD,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,OAAA;AAAA,QACA,OAAA;AAAA,QACA,UAAA,EAAU,IAAA;AAAA,QACV,OAAA;AAAA,QACA,YAAA,EAAa,2EAAA;AAAA,QACb,OAAA,EAAQ,UAAA;AAAA,QACP,GAAG;AAAA;AAAA;AACN,GAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -0,0 +1,152 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import Box from '@massdriver/ui/Box';
3
+ import Chip from '@massdriver/ui/Chip';
4
+ import Typography from '@massdriver/ui/Typography';
5
+ import HistoryIcon from '@massdriver/ui/icons/HistoryIcon';
6
+ import stylin from '@massdriver/ui/stylin';
7
+ import { RepoEmptyState } from '../RepoEmptyState.esm.js';
8
+ import { RepoNoVersionsState } from '../RepoNoVersionsState.esm.js';
9
+
10
+ const dateFormatter = new Intl.DateTimeFormat(void 0, {
11
+ year: "numeric",
12
+ month: "long",
13
+ day: "numeric"
14
+ });
15
+ const formatDate = (value) => {
16
+ if (!value) return null;
17
+ const date = new Date(value);
18
+ return Number.isNaN(date.getTime()) ? null : dateFormatter.format(date);
19
+ };
20
+ const VersionsTab = ({ repo, hasNoVersions }) => {
21
+ if (hasNoVersions) {
22
+ return /* @__PURE__ */ jsx(RepoNoVersionsState, { tabLabel: "version history" });
23
+ }
24
+ const tags = (repo?.tags?.items ?? []).filter(Boolean);
25
+ const releaseChannels = (repo?.releaseChannels?.items ?? []).filter(
26
+ Boolean
27
+ );
28
+ if (tags.length === 0) {
29
+ return /* @__PURE__ */ jsx(EmptyContainer, { children: /* @__PURE__ */ jsx(
30
+ RepoEmptyState,
31
+ {
32
+ icon: /* @__PURE__ */ jsx(HistoryIcon, {}),
33
+ title: "No published versions",
34
+ description: "Publish a version to populate this list."
35
+ }
36
+ ) });
37
+ }
38
+ return /* @__PURE__ */ jsxs(Container, { children: [
39
+ releaseChannels.length > 0 ? /* @__PURE__ */ jsxs(Section, { children: [
40
+ /* @__PURE__ */ jsx(SectionTitle, { variant: "subtitle2", children: "Release channels" }),
41
+ /* @__PURE__ */ jsx(List, { children: releaseChannels.map((channel) => /* @__PURE__ */ jsxs(ChannelRow, { children: [
42
+ /* @__PURE__ */ jsx(ChannelName, { children: channel.name }),
43
+ /* @__PURE__ */ jsx(Arrow, { "aria-hidden": "true", children: "\u2192" }),
44
+ /* @__PURE__ */ jsx(VersionTag, { label: `v${channel.tag}`, size: "small" })
45
+ ] }, channel.name)) })
46
+ ] }) : null,
47
+ /* @__PURE__ */ jsxs(Section, { children: [
48
+ /* @__PURE__ */ jsxs(SectionTitle, { variant: "subtitle2", children: [
49
+ "Versions",
50
+ /* @__PURE__ */ jsxs(Count, { variant: "caption", children: [
51
+ "(",
52
+ tags.length,
53
+ ")"
54
+ ] })
55
+ ] }),
56
+ /* @__PURE__ */ jsx(List, { children: tags.map((tag, index) => {
57
+ const releasedOn = formatDate(tag.createdAt);
58
+ return /* @__PURE__ */ jsxs(TagRow, { children: [
59
+ /* @__PURE__ */ jsxs(TagLeft, { children: [
60
+ /* @__PURE__ */ jsx(VersionTag, { label: `v${tag.tag}`, size: "small" }),
61
+ index === 0 ? /* @__PURE__ */ jsx(LatestChip, { label: "latest", size: "small", color: "primary" }) : null
62
+ ] }),
63
+ releasedOn ? /* @__PURE__ */ jsxs(ReleaseDate, { variant: "caption", children: [
64
+ "Released ",
65
+ releasedOn
66
+ ] }) : null
67
+ ] }, tag.tag);
68
+ }) })
69
+ ] })
70
+ ] });
71
+ };
72
+ const Container = stylin(Box)(({ theme }) => ({
73
+ padding: theme.spacing(3),
74
+ display: "flex",
75
+ flexDirection: "column",
76
+ gap: theme.spacing(3)
77
+ }));
78
+ const Section = stylin(Box)(({ theme }) => ({
79
+ display: "flex",
80
+ flexDirection: "column",
81
+ gap: theme.spacing(1)
82
+ }));
83
+ const SectionTitle = stylin(Typography)(({ theme }) => ({
84
+ display: "flex",
85
+ alignItems: "baseline",
86
+ gap: theme.spacing(0.75),
87
+ fontWeight: 600,
88
+ color: theme.palette.text.primary
89
+ }));
90
+ const Count = stylin(Typography)(({ theme }) => ({
91
+ color: theme.palette.text.secondary,
92
+ fontWeight: 400
93
+ }));
94
+ const List = stylin(Box)(({ theme }) => ({
95
+ border: `1px solid ${theme.palette.divider}`,
96
+ borderRadius: 1,
97
+ backgroundColor: theme.palette.background.paper,
98
+ overflow: "hidden"
99
+ }));
100
+ const ChannelRow = stylin(Box)(({ theme }) => ({
101
+ display: "flex",
102
+ alignItems: "center",
103
+ gap: theme.spacing(1.5),
104
+ padding: theme.spacing(1.25, 2),
105
+ "&:not(:last-of-type)": {
106
+ borderBottom: `1px solid ${theme.palette.divider}`
107
+ }
108
+ }));
109
+ const ChannelName = stylin("span")(({ theme }) => ({
110
+ fontFamily: theme.typography.fontFamilyMono,
111
+ fontSize: theme.typography.pxToRem(13),
112
+ fontWeight: 600,
113
+ color: theme.palette.text.primary,
114
+ minWidth: theme.spacing(8)
115
+ }));
116
+ const Arrow = stylin("span")(({ theme }) => ({
117
+ color: theme.palette.text.disabled,
118
+ fontSize: theme.typography.pxToRem(14)
119
+ }));
120
+ const TagRow = stylin(Box)(({ theme }) => ({
121
+ display: "flex",
122
+ alignItems: "center",
123
+ justifyContent: "space-between",
124
+ gap: theme.spacing(1.5),
125
+ padding: theme.spacing(1.25, 2),
126
+ "&:not(:last-of-type)": {
127
+ borderBottom: `1px solid ${theme.palette.divider}`
128
+ }
129
+ }));
130
+ const TagLeft = stylin(Box)(({ theme }) => ({
131
+ display: "flex",
132
+ alignItems: "center",
133
+ gap: theme.spacing(1)
134
+ }));
135
+ const VersionTag = stylin(Chip)(({ theme }) => ({
136
+ fontFamily: theme.typography.fontFamilyMono,
137
+ fontWeight: 600
138
+ }));
139
+ const LatestChip = stylin(Chip)({
140
+ textTransform: "uppercase",
141
+ letterSpacing: "0.04em",
142
+ fontSize: "11px"
143
+ });
144
+ const ReleaseDate = stylin(Typography)(({ theme }) => ({
145
+ color: theme.palette.text.secondary
146
+ }));
147
+ const EmptyContainer = stylin(Box)(({ theme }) => ({
148
+ padding: theme.spacing(3)
149
+ }));
150
+
151
+ export { VersionsTab };
152
+ //# sourceMappingURL=VersionsTab.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VersionsTab.esm.js","sources":["../../../../src/features/repo/tabs/VersionsTab.tsx"],"sourcesContent":["import Box from '@massdriver/ui/Box';\nimport Chip from '@massdriver/ui/Chip';\nimport Typography from '@massdriver/ui/Typography';\nimport HistoryIcon from '@massdriver/ui/icons/HistoryIcon';\nimport stylin from '@massdriver/ui/stylin';\nimport type { RepoTabProps } from '../RepoDetailsPage';\nimport { RepoEmptyState } from '../RepoEmptyState';\nimport { RepoNoVersionsState } from '../RepoNoVersionsState';\n\n// Ported from apps/web/features/repos/sections/VersionsTab/. Pure presentation\n// from the repo header's tags + releaseChannels.\nconst dateFormatter = new Intl.DateTimeFormat(undefined, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n});\n\nconst formatDate = (value?: string | null): string | null => {\n if (!value) return null;\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? null : dateFormatter.format(date);\n};\n\nexport const VersionsTab = ({ repo, hasNoVersions }: RepoTabProps) => {\n if (hasNoVersions) {\n return <RepoNoVersionsState tabLabel=\"version history\" />;\n }\n\n const tags = (repo?.tags?.items ?? []).filter(Boolean) as Array<{\n tag: string;\n createdAt?: string;\n }>;\n const releaseChannels = (repo?.releaseChannels?.items ?? []).filter(\n Boolean,\n ) as Array<{ name: string; tag: string }>;\n\n if (tags.length === 0) {\n return (\n <EmptyContainer>\n <RepoEmptyState\n icon={<HistoryIcon />}\n title=\"No published versions\"\n description=\"Publish a version to populate this list.\"\n />\n </EmptyContainer>\n );\n }\n\n return (\n <Container>\n {releaseChannels.length > 0 ? (\n <Section>\n <SectionTitle variant=\"subtitle2\">Release channels</SectionTitle>\n <List>\n {releaseChannels.map(channel => (\n <ChannelRow key={channel.name}>\n <ChannelName>{channel.name}</ChannelName>\n <Arrow aria-hidden=\"true\">→</Arrow>\n <VersionTag label={`v${channel.tag}`} size=\"small\" />\n </ChannelRow>\n ))}\n </List>\n </Section>\n ) : null}\n <Section>\n <SectionTitle variant=\"subtitle2\">\n Versions\n <Count variant=\"caption\">({tags.length})</Count>\n </SectionTitle>\n <List>\n {tags.map((tag, index) => {\n const releasedOn = formatDate(tag.createdAt);\n return (\n <TagRow key={tag.tag}>\n <TagLeft>\n <VersionTag label={`v${tag.tag}`} size=\"small\" />\n {index === 0 ? (\n <LatestChip label=\"latest\" size=\"small\" color=\"primary\" />\n ) : null}\n </TagLeft>\n {releasedOn ? (\n <ReleaseDate variant=\"caption\">\n Released {releasedOn}\n </ReleaseDate>\n ) : null}\n </TagRow>\n );\n })}\n </List>\n </Section>\n </Container>\n );\n};\n\nconst Container = stylin(Box)(({ theme }: { theme: any }) => ({\n padding: theme.spacing(3),\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(3),\n}));\n\nconst Section = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1),\n}));\n\nconst SectionTitle = stylin(Typography)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'baseline',\n gap: theme.spacing(0.75),\n fontWeight: 600,\n color: theme.palette.text.primary,\n}));\n\nconst Count = stylin(Typography)(({ theme }: { theme: any }) => ({\n color: theme.palette.text.secondary,\n fontWeight: 400,\n}));\n\nconst List = stylin(Box)(({ theme }: { theme: any }) => ({\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 1,\n backgroundColor: theme.palette.background.paper,\n overflow: 'hidden',\n}));\n\nconst ChannelRow = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1.5),\n padding: theme.spacing(1.25, 2),\n '&:not(:last-of-type)': {\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n}));\n\nconst ChannelName = stylin('span')(({ theme }: { theme: any }) => ({\n fontFamily: theme.typography.fontFamilyMono,\n fontSize: theme.typography.pxToRem(13),\n fontWeight: 600,\n color: theme.palette.text.primary,\n minWidth: theme.spacing(8),\n}));\n\nconst Arrow = stylin('span')(({ theme }: { theme: any }) => ({\n color: theme.palette.text.disabled,\n fontSize: theme.typography.pxToRem(14),\n}));\n\nconst TagRow = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: theme.spacing(1.5),\n padding: theme.spacing(1.25, 2),\n '&:not(:last-of-type)': {\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n}));\n\nconst TagLeft = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n}));\n\nconst VersionTag = stylin(Chip)(({ theme }: { theme: any }) => ({\n fontFamily: theme.typography.fontFamilyMono,\n fontWeight: 600,\n}));\n\nconst LatestChip = stylin(Chip)({\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n fontSize: '11px',\n});\n\nconst ReleaseDate = stylin(Typography)(({ theme }: { theme: any }) => ({\n color: theme.palette.text.secondary,\n}));\n\nconst EmptyContainer = stylin(Box)(({ theme }: { theme: any }) => ({\n padding: theme.spacing(3),\n}));\n"],"names":[],"mappings":"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"}