openvsx-webui-test 0.19.0-dev.1 → 0.20.0-dev.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 (344) hide show
  1. package/lib/components/banner.js +1 -2
  2. package/lib/components/banner.js.map +1 -1
  3. package/lib/components/copy-to-clipboard.js +1 -2
  4. package/lib/components/copy-to-clipboard.js.map +1 -1
  5. package/lib/components/delayed-load-indicator.js +2 -4
  6. package/lib/components/delayed-load-indicator.js.map +1 -1
  7. package/lib/components/rate-limiting/customer/general-details.d.ts +20 -0
  8. package/lib/components/rate-limiting/customer/general-details.d.ts.map +1 -0
  9. package/lib/components/rate-limiting/customer/general-details.js +8 -0
  10. package/lib/components/rate-limiting/customer/general-details.js.map +1 -0
  11. package/lib/components/rate-limiting/customer/index.d.ts +17 -0
  12. package/lib/components/rate-limiting/customer/index.d.ts.map +1 -0
  13. package/lib/components/rate-limiting/customer/index.js +15 -0
  14. package/lib/components/rate-limiting/customer/index.js.map +1 -0
  15. package/lib/components/rate-limiting/customer/usage-stats.d.ts +24 -0
  16. package/lib/components/rate-limiting/customer/usage-stats.d.ts.map +1 -0
  17. package/lib/components/rate-limiting/customer/usage-stats.js +6 -0
  18. package/lib/components/rate-limiting/customer/usage-stats.js.map +1 -0
  19. package/lib/{pages/admin-dashboard → components/rate-limiting}/usage-stats/usage-stats-chart.d.ts +5 -2
  20. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.d.ts.map +1 -0
  21. package/lib/{pages/admin-dashboard → components/rate-limiting}/usage-stats/usage-stats-chart.js +25 -18
  22. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.js.map +1 -0
  23. package/lib/components/rate-limiting/usage-stats/usage-stats-utils.d.ts +15 -0
  24. package/lib/components/rate-limiting/usage-stats/usage-stats-utils.d.ts.map +1 -0
  25. package/{src/pages/admin-dashboard/usage-stats/usage-stats-utils.ts → lib/components/rate-limiting/usage-stats/usage-stats-utils.js} +4 -3
  26. package/lib/components/rate-limiting/usage-stats/usage-stats-utils.js.map +1 -0
  27. package/lib/components/rate-limiting/usage-stats/use-usage-stats.d.ts +22 -0
  28. package/lib/components/rate-limiting/usage-stats/use-usage-stats.d.ts.map +1 -0
  29. package/lib/components/rate-limiting/usage-stats/use-usage-stats.js +58 -0
  30. package/lib/components/rate-limiting/usage-stats/use-usage-stats.js.map +1 -0
  31. package/lib/components/scan-admin/common/conditional-tooltip.js +4 -16
  32. package/lib/components/scan-admin/common/conditional-tooltip.js.map +1 -1
  33. package/lib/components/scan-admin/common/file-table.js +24 -13
  34. package/lib/components/scan-admin/common/file-table.js.map +1 -1
  35. package/lib/components/scan-admin/dialogs/quarantine-dialog.js +4 -8
  36. package/lib/components/scan-admin/dialogs/quarantine-dialog.js.map +1 -1
  37. package/lib/components/scan-admin/scan-card/scan-card-content.js +2 -2
  38. package/lib/components/scan-admin/scan-card/scan-card-content.js.map +1 -1
  39. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.js +21 -16
  40. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.js.map +1 -1
  41. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js +1 -2
  42. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js.map +1 -1
  43. package/lib/components/scan-admin/scan-card/scan-card-header.js +10 -5
  44. package/lib/components/scan-admin/scan-card/scan-card-header.js.map +1 -1
  45. package/lib/components/scan-admin/scan-card/utils.js +1 -2
  46. package/lib/components/scan-admin/scan-card/utils.js.map +1 -1
  47. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.js +4 -6
  48. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.js.map +1 -1
  49. package/lib/components/sidepanel/drawer-header.d.ts +14 -0
  50. package/lib/components/sidepanel/drawer-header.d.ts.map +1 -0
  51. package/lib/components/sidepanel/drawer-header.js +22 -0
  52. package/lib/components/sidepanel/drawer-header.js.map +1 -0
  53. package/lib/components/sidepanel/navigation-item.d.ts.map +1 -1
  54. package/lib/components/sidepanel/navigation-item.js +3 -3
  55. package/lib/components/sidepanel/navigation-item.js.map +1 -1
  56. package/lib/components/sidepanel/sidepanel.d.ts +7 -1
  57. package/lib/components/sidepanel/sidepanel.d.ts.map +1 -1
  58. package/lib/components/sidepanel/sidepanel.js +12 -13
  59. package/lib/components/sidepanel/sidepanel.js.map +1 -1
  60. package/lib/components/text-divider.js +1 -2
  61. package/lib/components/text-divider.js.map +1 -1
  62. package/lib/components/timestamp.js +1 -2
  63. package/lib/components/timestamp.js.map +1 -1
  64. package/lib/context/scan-admin/scan-api-actions.js +7 -16
  65. package/lib/context/scan-admin/scan-api-actions.js.map +1 -1
  66. package/lib/context/scan-admin/scan-api-effects.js +77 -93
  67. package/lib/context/scan-admin/scan-api-effects.js.map +1 -1
  68. package/lib/context/scan-admin/scan-context.d.ts.map +1 -1
  69. package/lib/context/scan-admin/scan-context.js +1 -0
  70. package/lib/context/scan-admin/scan-context.js.map +1 -1
  71. package/lib/context/scan-admin/scan-reducer.js +134 -53
  72. package/lib/context/scan-admin/scan-reducer.js.map +1 -1
  73. package/lib/default/default-app.d.ts +1 -1
  74. package/lib/default/default-app.d.ts.map +1 -1
  75. package/lib/default/default-app.js +11 -22
  76. package/lib/default/default-app.js.map +1 -1
  77. package/lib/default/menu-content.d.ts.map +1 -1
  78. package/lib/default/menu-content.js +7 -3
  79. package/lib/default/menu-content.js.map +1 -1
  80. package/lib/default/page-settings.js +13 -18
  81. package/lib/default/page-settings.js.map +1 -1
  82. package/lib/extension-registry-service.d.ts +11 -1
  83. package/lib/extension-registry-service.d.ts.map +1 -1
  84. package/lib/extension-registry-service.js +618 -629
  85. package/lib/extension-registry-service.js.map +1 -1
  86. package/lib/extension-registry-types.d.ts +7 -0
  87. package/lib/extension-registry-types.d.ts.map +1 -1
  88. package/lib/hooks/scan-admin/use-auto-rejected-tab.js +5 -7
  89. package/lib/hooks/scan-admin/use-auto-rejected-tab.js.map +1 -1
  90. package/lib/hooks/scan-admin/use-quarantined-tab.js +5 -7
  91. package/lib/hooks/scan-admin/use-quarantined-tab.js.map +1 -1
  92. package/lib/main.d.ts.map +1 -1
  93. package/lib/main.js +8 -16
  94. package/lib/main.js.map +1 -1
  95. package/lib/other-pages.d.ts +12 -0
  96. package/lib/other-pages.d.ts.map +1 -1
  97. package/lib/other-pages.js +25 -12
  98. package/lib/other-pages.js.map +1 -1
  99. package/lib/pages/admin-dashboard/admin-dashboard.d.ts +0 -12
  100. package/lib/pages/admin-dashboard/admin-dashboard.d.ts.map +1 -1
  101. package/lib/pages/admin-dashboard/admin-dashboard.js +136 -49
  102. package/lib/pages/admin-dashboard/admin-dashboard.js.map +1 -1
  103. package/lib/pages/admin-dashboard/admin-routes.d.ts +25 -0
  104. package/lib/pages/admin-dashboard/admin-routes.d.ts.map +1 -0
  105. package/lib/pages/admin-dashboard/admin-routes.js +27 -0
  106. package/lib/pages/admin-dashboard/admin-routes.js.map +1 -0
  107. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.d.ts +1 -9
  108. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.d.ts.map +1 -1
  109. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.js +17 -15
  110. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.js.map +1 -1
  111. package/lib/pages/admin-dashboard/components/data-grid-filter.d.ts +22 -0
  112. package/lib/pages/admin-dashboard/components/data-grid-filter.d.ts.map +1 -0
  113. package/lib/pages/admin-dashboard/components/data-grid-filter.js +13 -0
  114. package/lib/pages/admin-dashboard/components/data-grid-filter.js.map +1 -0
  115. package/lib/pages/admin-dashboard/components/index.d.ts +2 -1
  116. package/lib/pages/admin-dashboard/components/index.d.ts.map +1 -1
  117. package/lib/pages/admin-dashboard/components/index.js +2 -1
  118. package/lib/pages/admin-dashboard/components/index.js.map +1 -1
  119. package/lib/pages/admin-dashboard/{usage-stats/usage-stats-utils.d.ts → customers/customer-details.d.ts} +3 -2
  120. package/lib/pages/admin-dashboard/customers/customer-details.d.ts.map +1 -0
  121. package/lib/pages/admin-dashboard/customers/customer-details.js +77 -0
  122. package/lib/pages/admin-dashboard/customers/customer-details.js.map +1 -0
  123. package/lib/pages/admin-dashboard/customers/customer-form-dialog.d.ts +1 -1
  124. package/lib/pages/admin-dashboard/customers/customer-form-dialog.d.ts.map +1 -1
  125. package/lib/pages/admin-dashboard/customers/customer-form-dialog.js +33 -34
  126. package/lib/pages/admin-dashboard/customers/customer-form-dialog.js.map +1 -1
  127. package/lib/pages/admin-dashboard/customers/customer-member-list.d.ts +19 -0
  128. package/lib/pages/admin-dashboard/customers/customer-member-list.d.ts.map +1 -0
  129. package/lib/pages/admin-dashboard/customers/customer-member-list.js +88 -0
  130. package/lib/pages/admin-dashboard/customers/customer-member-list.js.map +1 -0
  131. package/lib/pages/admin-dashboard/customers/customers.d.ts +1 -1
  132. package/lib/pages/admin-dashboard/customers/customers.js +20 -29
  133. package/lib/pages/admin-dashboard/customers/customers.js.map +1 -1
  134. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.js +4 -14
  135. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.js.map +1 -1
  136. package/lib/pages/admin-dashboard/extension-admin.js +7 -16
  137. package/lib/pages/admin-dashboard/extension-admin.js.map +1 -1
  138. package/lib/pages/admin-dashboard/extension-remove-dialog.js +3 -12
  139. package/lib/pages/admin-dashboard/extension-remove-dialog.js.map +1 -1
  140. package/lib/pages/admin-dashboard/extension-version-container.js +3 -5
  141. package/lib/pages/admin-dashboard/extension-version-container.js.map +1 -1
  142. package/lib/pages/admin-dashboard/logs/logs.d.ts.map +1 -1
  143. package/lib/pages/admin-dashboard/logs/logs.js +6 -24
  144. package/lib/pages/admin-dashboard/logs/logs.js.map +1 -1
  145. package/lib/pages/admin-dashboard/namespace-admin.js +7 -16
  146. package/lib/pages/admin-dashboard/namespace-admin.js.map +1 -1
  147. package/lib/pages/admin-dashboard/namespace-change-dialog.js +3 -12
  148. package/lib/pages/admin-dashboard/namespace-change-dialog.js.map +1 -1
  149. package/lib/pages/admin-dashboard/namespace-input.js +1 -1
  150. package/lib/pages/admin-dashboard/namespace-input.js.map +1 -1
  151. package/lib/pages/admin-dashboard/publisher-admin.d.ts.map +1 -1
  152. package/lib/pages/admin-dashboard/publisher-admin.js +28 -22
  153. package/lib/pages/admin-dashboard/publisher-admin.js.map +1 -1
  154. package/lib/pages/admin-dashboard/publisher-revoke-dialog.js +5 -15
  155. package/lib/pages/admin-dashboard/publisher-revoke-dialog.js.map +1 -1
  156. package/lib/pages/admin-dashboard/publisher-revoke-tokens-button.js +3 -12
  157. package/lib/pages/admin-dashboard/publisher-revoke-tokens-button.js.map +1 -1
  158. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.js +4 -13
  159. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.js.map +1 -1
  160. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.js +34 -23
  161. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.js.map +1 -1
  162. package/lib/pages/admin-dashboard/tiers/tiers.js +12 -21
  163. package/lib/pages/admin-dashboard/tiers/tiers.js.map +1 -1
  164. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.js +3 -14
  165. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.js.map +1 -1
  166. package/lib/pages/admin-dashboard/usage-stats/usage-stats.d.ts.map +1 -1
  167. package/lib/pages/admin-dashboard/usage-stats/usage-stats.js +11 -45
  168. package/lib/pages/admin-dashboard/usage-stats/usage-stats.js.map +1 -1
  169. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.d.ts +22 -0
  170. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.d.ts.map +1 -0
  171. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.js +58 -0
  172. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.js.map +1 -0
  173. package/lib/pages/admin-dashboard/welcome.js +1 -1
  174. package/lib/pages/admin-dashboard/welcome.js.map +1 -1
  175. package/lib/pages/extension-detail/extension-detail-changes.js +3 -12
  176. package/lib/pages/extension-detail/extension-detail-changes.js.map +1 -1
  177. package/lib/pages/extension-detail/extension-detail-overview.js +7 -17
  178. package/lib/pages/extension-detail/extension-detail-overview.js.map +1 -1
  179. package/lib/pages/extension-detail/extension-detail-reviews.js +12 -24
  180. package/lib/pages/extension-detail/extension-detail-reviews.js.map +1 -1
  181. package/lib/pages/extension-detail/extension-detail-routes.d.ts +32 -0
  182. package/lib/pages/extension-detail/extension-detail-routes.d.ts.map +1 -0
  183. package/lib/pages/extension-detail/extension-detail-routes.js +35 -0
  184. package/lib/pages/extension-detail/extension-detail-routes.js.map +1 -0
  185. package/lib/pages/extension-detail/extension-detail.d.ts +0 -19
  186. package/lib/pages/extension-detail/extension-detail.d.ts.map +1 -1
  187. package/lib/pages/extension-detail/extension-detail.js +28 -50
  188. package/lib/pages/extension-detail/extension-detail.js.map +1 -1
  189. package/lib/pages/extension-detail/extension-rating-stars.js +1 -2
  190. package/lib/pages/extension-detail/extension-rating-stars.js.map +1 -1
  191. package/lib/pages/extension-detail/extension-review-dialog.d.ts.map +1 -1
  192. package/lib/pages/extension-detail/extension-review-dialog.js +6 -25
  193. package/lib/pages/extension-detail/extension-review-dialog.js.map +1 -1
  194. package/lib/pages/extension-list/extension-list-container.d.ts +0 -3
  195. package/lib/pages/extension-list/extension-list-container.d.ts.map +1 -1
  196. package/lib/pages/extension-list/extension-list-container.js +5 -10
  197. package/lib/pages/extension-list/extension-list-container.js.map +1 -1
  198. package/lib/pages/extension-list/extension-list-header.js +3 -6
  199. package/lib/pages/extension-list/extension-list-header.js.map +1 -1
  200. package/lib/pages/extension-list/extension-list-item.js +7 -17
  201. package/lib/pages/extension-list/extension-list-item.js.map +1 -1
  202. package/lib/pages/extension-list/extension-list-routes.d.ts +16 -0
  203. package/lib/pages/extension-list/extension-list-routes.d.ts.map +1 -0
  204. package/lib/pages/extension-list/extension-list-routes.js +18 -0
  205. package/lib/pages/extension-list/extension-list-routes.js.map +1 -0
  206. package/lib/pages/extension-list/extension-list-searchfield.js +4 -7
  207. package/lib/pages/extension-list/extension-list-searchfield.js.map +1 -1
  208. package/lib/pages/extension-list/extension-list.js +8 -19
  209. package/lib/pages/extension-list/extension-list.js.map +1 -1
  210. package/lib/pages/namespace-detail/namespace-detail-routes.d.ts +20 -0
  211. package/lib/pages/namespace-detail/namespace-detail-routes.d.ts.map +1 -0
  212. package/lib/pages/namespace-detail/namespace-detail-routes.js +23 -0
  213. package/lib/pages/namespace-detail/namespace-detail-routes.js.map +1 -0
  214. package/lib/pages/namespace-detail/namespace-detail.d.ts +0 -7
  215. package/lib/pages/namespace-detail/namespace-detail.d.ts.map +1 -1
  216. package/lib/pages/namespace-detail/namespace-detail.js +4 -24
  217. package/lib/pages/namespace-detail/namespace-detail.js.map +1 -1
  218. package/lib/pages/user/add-namespace-member-dialog.d.ts.map +1 -1
  219. package/lib/pages/user/add-namespace-member-dialog.js +8 -67
  220. package/lib/pages/user/add-namespace-member-dialog.js.map +1 -1
  221. package/lib/pages/user/add-user-dialog.d.ts +25 -0
  222. package/lib/pages/user/add-user-dialog.d.ts.map +1 -0
  223. package/lib/pages/user/add-user-dialog.js +66 -0
  224. package/lib/pages/user/add-user-dialog.js.map +1 -0
  225. package/lib/pages/user/avatar.js +3 -3
  226. package/lib/pages/user/avatar.js.map +1 -1
  227. package/lib/pages/user/create-namespace-dialog.js +3 -12
  228. package/lib/pages/user/create-namespace-dialog.js.map +1 -1
  229. package/lib/pages/user/generate-token-dialog.js +3 -12
  230. package/lib/pages/user/generate-token-dialog.js.map +1 -1
  231. package/lib/pages/user/logout.js +3 -12
  232. package/lib/pages/user/logout.js.map +1 -1
  233. package/lib/pages/user/publish-extension-dialog.js +12 -21
  234. package/lib/pages/user/publish-extension-dialog.js.map +1 -1
  235. package/lib/pages/user/user-namespace-details.js +29 -42
  236. package/lib/pages/user/user-namespace-details.js.map +1 -1
  237. package/lib/pages/user/user-namespace-extension-list-item.js +6 -8
  238. package/lib/pages/user/user-namespace-extension-list-item.js.map +1 -1
  239. package/lib/pages/user/user-namespace-extension-list.js +6 -15
  240. package/lib/pages/user/user-namespace-extension-list.js.map +1 -1
  241. package/lib/pages/user/user-namespace-member-component.js +1 -1
  242. package/lib/pages/user/user-namespace-member-component.js.map +1 -1
  243. package/lib/pages/user/user-namespace-member-list.js +9 -18
  244. package/lib/pages/user/user-namespace-member-list.js.map +1 -1
  245. package/lib/pages/user/user-publisher-agreement.js +8 -18
  246. package/lib/pages/user/user-publisher-agreement.js.map +1 -1
  247. package/lib/pages/user/user-setting-tabs.d.ts.map +1 -1
  248. package/lib/pages/user/user-setting-tabs.js +2 -2
  249. package/lib/pages/user/user-setting-tabs.js.map +1 -1
  250. package/lib/pages/user/user-settings-customer-detail.d.ts +19 -0
  251. package/lib/pages/user/user-settings-customer-detail.d.ts.map +1 -0
  252. package/lib/pages/user/user-settings-customer-detail.js +9 -0
  253. package/lib/pages/user/user-settings-customer-detail.js.map +1 -0
  254. package/lib/pages/user/user-settings-customers.d.ts +15 -0
  255. package/lib/pages/user/user-settings-customers.d.ts.map +1 -0
  256. package/lib/pages/user/user-settings-customers.js +66 -0
  257. package/lib/pages/user/user-settings-customers.js.map +1 -0
  258. package/lib/pages/user/user-settings-delete-extension.js +8 -17
  259. package/lib/pages/user/user-settings-delete-extension.js.map +1 -1
  260. package/lib/pages/user/user-settings-extensions.js +3 -12
  261. package/lib/pages/user/user-settings-extensions.js.map +1 -1
  262. package/lib/pages/user/user-settings-namespace-detail.d.ts.map +1 -1
  263. package/lib/pages/user/user-settings-namespace-detail.js +4 -12
  264. package/lib/pages/user/user-settings-namespace-detail.js.map +1 -1
  265. package/lib/pages/user/user-settings-namespaces.js +6 -15
  266. package/lib/pages/user/user-settings-namespaces.js.map +1 -1
  267. package/lib/pages/user/user-settings-profile.js +1 -2
  268. package/lib/pages/user/user-settings-profile.js.map +1 -1
  269. package/lib/pages/user/user-settings-routes.d.ts +23 -0
  270. package/lib/pages/user/user-settings-routes.d.ts.map +1 -0
  271. package/lib/pages/user/user-settings-routes.js +25 -0
  272. package/lib/pages/user/user-settings-routes.js.map +1 -0
  273. package/lib/pages/user/user-settings-tokens.d.ts +0 -7
  274. package/lib/pages/user/user-settings-tokens.d.ts.map +1 -1
  275. package/lib/pages/user/user-settings-tokens.js +13 -23
  276. package/lib/pages/user/user-settings-tokens.js.map +1 -1
  277. package/lib/pages/user/user-settings.d.ts +0 -9
  278. package/lib/pages/user/user-settings.d.ts.map +1 -1
  279. package/lib/pages/user/user-settings.js +4 -12
  280. package/lib/pages/user/user-settings.js.map +1 -1
  281. package/lib/server-request.js +64 -76
  282. package/lib/server-request.js.map +1 -1
  283. package/lib/utils.d.ts.map +1 -1
  284. package/lib/utils.js +3 -4
  285. package/lib/utils.js.map +1 -1
  286. package/package.json +4 -2
  287. package/src/components/rate-limiting/customer/general-details.tsx +106 -0
  288. package/src/components/rate-limiting/customer/index.ts +18 -0
  289. package/src/components/rate-limiting/customer/usage-stats.tsx +50 -0
  290. package/src/{pages/admin-dashboard → components/rate-limiting}/usage-stats/usage-stats-chart.tsx +46 -26
  291. package/{lib/pages/admin-dashboard/usage-stats/usage-stats-utils.js → src/components/rate-limiting/usage-stats/usage-stats-utils.ts} +4 -2
  292. package/src/components/rate-limiting/usage-stats/use-usage-stats.ts +70 -0
  293. package/src/components/scan-admin/scan-card/scan-card-header.tsx +2 -2
  294. package/src/components/sidepanel/drawer-header.tsx +23 -0
  295. package/src/components/sidepanel/navigation-item.tsx +3 -2
  296. package/src/components/sidepanel/sidepanel.tsx +29 -17
  297. package/src/context/scan-admin/scan-context.tsx +1 -0
  298. package/src/default/default-app.tsx +1 -1
  299. package/src/default/menu-content.tsx +6 -2
  300. package/src/default/page-settings.tsx +1 -1
  301. package/src/extension-registry-service.ts +105 -26
  302. package/src/extension-registry-types.ts +9 -0
  303. package/src/main.tsx +2 -1
  304. package/src/other-pages.tsx +21 -4
  305. package/src/pages/admin-dashboard/admin-dashboard.tsx +260 -83
  306. package/src/pages/admin-dashboard/admin-routes.ts +27 -0
  307. package/src/pages/admin-dashboard/components/data-grid-filter-operators.tsx +1 -31
  308. package/src/pages/admin-dashboard/components/data-grid-filter.tsx +45 -0
  309. package/src/pages/admin-dashboard/components/index.ts +1 -1
  310. package/src/pages/admin-dashboard/customers/customer-details.tsx +129 -0
  311. package/src/pages/admin-dashboard/customers/customer-form-dialog.tsx +3 -4
  312. package/src/pages/admin-dashboard/customers/customer-member-list.tsx +174 -0
  313. package/src/pages/admin-dashboard/customers/customers.tsx +8 -8
  314. package/src/pages/admin-dashboard/logs/logs.tsx +1 -10
  315. package/src/pages/admin-dashboard/publisher-admin.tsx +29 -11
  316. package/src/pages/admin-dashboard/usage-stats/usage-stats.tsx +10 -39
  317. package/src/pages/admin-dashboard/usage-stats/use-usage-stats.ts +70 -0
  318. package/src/pages/admin-dashboard/welcome.tsx +1 -1
  319. package/src/pages/extension-detail/extension-detail-overview.tsx +3 -3
  320. package/src/pages/extension-detail/extension-detail-routes.ts +35 -0
  321. package/src/pages/extension-detail/extension-detail.tsx +3 -23
  322. package/src/pages/extension-detail/extension-review-dialog.tsx +2 -12
  323. package/src/pages/extension-list/extension-list-container.tsx +1 -5
  324. package/src/pages/extension-list/extension-list-item.tsx +1 -1
  325. package/src/pages/extension-list/extension-list-routes.ts +18 -0
  326. package/src/pages/namespace-detail/namespace-detail-routes.ts +23 -0
  327. package/src/pages/namespace-detail/namespace-detail.tsx +0 -10
  328. package/src/pages/user/add-namespace-member-dialog.tsx +17 -116
  329. package/src/pages/user/add-user-dialog.tsx +141 -0
  330. package/src/pages/user/avatar.tsx +2 -2
  331. package/src/pages/user/user-namespace-extension-list-item.tsx +2 -2
  332. package/src/pages/user/user-setting-tabs.tsx +2 -1
  333. package/src/pages/user/user-settings-customer-detail.tsx +39 -0
  334. package/src/pages/user/user-settings-customers.tsx +120 -0
  335. package/src/pages/user/user-settings-delete-extension.tsx +1 -1
  336. package/src/pages/user/user-settings-namespace-detail.tsx +3 -1
  337. package/src/pages/user/user-settings-routes.ts +25 -0
  338. package/src/pages/user/user-settings-tokens.tsx +1 -8
  339. package/src/pages/user/user-settings.tsx +4 -12
  340. package/src/utils.ts +2 -1
  341. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.d.ts.map +0 -1
  342. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.js.map +0 -1
  343. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.d.ts.map +0 -1
  344. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.js.map +0 -1
@@ -0,0 +1,70 @@
1
+ /******************************************************************************
2
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
3
+ *
4
+ * See the NOTICE file(s) distributed with this work for additional
5
+ * information regarding copyright ownership.
6
+ *
7
+ * This program and the accompanying materials are made available under the
8
+ * terms of the Eclipse Public License 2.0 which is available at
9
+ * https://www.eclipse.org/legal/epl-2.0.
10
+ *
11
+ * SPDX-License-Identifier: EPL-2.0
12
+ *****************************************************************************/
13
+
14
+ import { useContext, useState, useEffect, useRef, useCallback } from "react";
15
+ import { MainContext } from "../../../context";
16
+ import type { UsageStats } from "../../../extension-registry-types";
17
+ import { handleError } from "../../../utils";
18
+ import { getDefaultStartDate } from "./usage-stats-utils";
19
+ import { DateTime } from "luxon";
20
+
21
+ export const useUsageStats = (customerName: string | undefined) => {
22
+ const abortController = useRef(new AbortController());
23
+ const { service } = useContext(MainContext);
24
+
25
+ const [usageStats, setUsageStats] = useState<readonly UsageStats[]>([]);
26
+ const [loading, setLoading] = useState(false);
27
+ const [error, setError] = useState<string | null>(null);
28
+ const [internalStartDate, setInternalStartDate] = useState<DateTime>(getDefaultStartDate);
29
+
30
+ const startDateRef = useRef(internalStartDate);
31
+ startDateRef.current = internalStartDate;
32
+
33
+ const fetchUsageStats = useCallback(async (date: DateTime) => {
34
+ if (!customerName) {
35
+ setUsageStats([]);
36
+ setLoading(false);
37
+ return;
38
+ }
39
+
40
+ try {
41
+ setLoading(true);
42
+ setError(null);
43
+ const data = await service.getUsageStats(
44
+ abortController.current,
45
+ customerName,
46
+ date.toJSDate()
47
+ );
48
+ setUsageStats(data.stats);
49
+ } catch (err) {
50
+ setError(handleError(err as Error));
51
+ } finally {
52
+ setLoading(false);
53
+ }
54
+ }, [service, customerName]);
55
+
56
+ const setStartDate = useCallback((date: DateTime) => {
57
+ setInternalStartDate(date);
58
+ fetchUsageStats(date);
59
+ }, [fetchUsageStats]);
60
+
61
+ useEffect(() => {
62
+ fetchUsageStats(startDateRef.current);
63
+ return () => {
64
+ abortController.current.abort();
65
+ abortController.current = new AbortController();
66
+ };
67
+ }, [fetchUsageStats]);
68
+
69
+ return { usageStats, loading, error, startDate: internalStartDate, setStartDate };
70
+ };
@@ -32,8 +32,8 @@ import {
32
32
  getStatusColorSx,
33
33
  } from './utils';
34
34
  import { createRoute } from '../../../utils';
35
- import { AdminDashboardRoutes } from '../../../pages/admin-dashboard/admin-dashboard';
36
- import { ExtensionDetailRoutes } from '../../../pages/extension-detail/extension-detail';
35
+ import { AdminDashboardRoutes } from '../../../pages/admin-dashboard/admin-routes';
36
+ import { ExtensionDetailRoutes } from '../../../pages/extension-detail/extension-detail-routes';
37
37
 
38
38
  interface ScanCardHeaderProps {
39
39
  scan: ScanResult;
@@ -0,0 +1,23 @@
1
+ /******************************************************************************
2
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
3
+ *
4
+ * See the NOTICE file(s) distributed with this work for additional
5
+ * information regarding copyright ownership.
6
+ *
7
+ * This program and the accompanying materials are made available under the
8
+ * terms of the Eclipse Public License 2.0 which is available at
9
+ * https://www.eclipse.org/legal/epl-2.0.
10
+ *
11
+ * SPDX-License-Identifier: EPL-2.0
12
+ *****************************************************************************/
13
+
14
+ import { styled } from '@mui/material/styles';
15
+
16
+ export const DrawerHeader = styled('div')(({ theme }) => ({
17
+ display: 'flex',
18
+ alignItems: 'center',
19
+ padding: theme.spacing(0, 1),
20
+ // necessary for content to be below app bar
21
+ ...theme.mixins.toolbar,
22
+ justifyContent: 'flex-end',
23
+ }));
@@ -11,6 +11,7 @@
11
11
  import { FunctionComponent, PropsWithChildren, ReactNode, useState } from 'react';
12
12
  import { ListItemButton, ListItemText, Collapse, List, ListItemIcon } from '@mui/material';
13
13
  import ExpandLess from '@mui/icons-material/ExpandLess';
14
+ import ExpandMore from '@mui/icons-material/ExpandMore';
14
15
  import { useNavigate } from 'react-router';
15
16
 
16
17
  export const NavigationItem: FunctionComponent<PropsWithChildren<NavigationProps>> = props => {
@@ -21,7 +22,7 @@ export const NavigationItem: FunctionComponent<PropsWithChildren<NavigationProps
21
22
  if (props.children) {
22
23
  setOpen(!open);
23
24
  } else if (props.route) {
24
- props.onOpenRoute?.call(props.route);
25
+ props.onOpenRoute?.call(this, props.route);
25
26
  navigate(props.route);
26
27
  }
27
28
  };
@@ -32,7 +33,7 @@ export const NavigationItem: FunctionComponent<PropsWithChildren<NavigationProps
32
33
  props.icon && <ListItemIcon>{props.icon}</ListItemIcon>
33
34
  }
34
35
  <ListItemText primary={props.label} />
35
- {props.children && open && <ExpandLess />}
36
+ {props.children && (open ? <ExpandLess /> : <ExpandMore />)}
36
37
  </ListItemButton>
37
38
  {
38
39
  props.children &&
@@ -9,30 +9,42 @@
9
9
  ********************************************************************************/
10
10
 
11
11
  import { FunctionComponent, PropsWithChildren } from 'react';
12
- import { Drawer, List } from '@mui/material';
13
- import { Theme } from '@mui/material/styles';
12
+ import { Divider, Drawer, IconButton, List } from '@mui/material';
13
+ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
14
+ import { DrawerHeader } from './drawer-header';
15
+
16
+ export const Sidepanel: FunctionComponent<PropsWithChildren<SidepanelProps>> = props => {
17
+ const width = props.width;
14
18
 
15
- export const Sidepanel: FunctionComponent<PropsWithChildren> = props => {
16
19
  return (
17
20
  <Drawer
18
- variant='permanent'
19
- PaperProps={{ elevation: 3 }}
20
- sx={(theme: Theme) => ({
21
+ sx={{
22
+ width: width,
23
+ flexShrink: 0,
21
24
  '& .MuiDrawer-paper': {
22
- position: 'relative',
23
- justifyContent: 'space-between',
24
- transition: theme.transitions.create('width', {
25
- easing: theme.transitions.easing.sharp,
26
- duration: theme.transitions.duration.enteringScreen
27
- }),
28
- overflowX: { xs: 'hidden', sm: 'hidden', md: 'none', lg: 'none', xl: 'none' },
29
- width: { xs: theme.spacing(7) + 1, sm: theme.spacing(9) + 1, md: 240 },
30
- }
31
- })}
25
+ width: width,
26
+ boxSizing: 'border-box',
27
+ },
28
+ }}
29
+ variant='persistent'
30
+ anchor='left'
31
+ open={props.open}
32
32
  >
33
+ <DrawerHeader>
34
+ <IconButton onClick={props.handleDrawerClose}>
35
+ <ChevronLeftIcon />
36
+ </IconButton>
37
+ </DrawerHeader>
38
+ <Divider />
33
39
  <List>
34
40
  {props.children}
35
41
  </List>
36
42
  </Drawer>
37
43
  );
38
- };
44
+ };
45
+
46
+ interface SidepanelProps {
47
+ width: number;
48
+ open: boolean;
49
+ handleDrawerClose: () => void;
50
+ }
@@ -114,6 +114,7 @@ export const ScanProvider: FC<ScanProviderProps> = ({ children, service, handleE
114
114
  // Custom Hook
115
115
  // ============================================================================
116
116
 
117
+ // eslint-disable-next-line react-refresh/only-export-components
117
118
  export const useScanContext = (): ScanContextValue => {
118
119
  const context = useContext(ScanContext);
119
120
  if (!context) {
@@ -48,7 +48,7 @@ async function getServerVersion(): Promise<string> {
48
48
  }
49
49
  }
50
50
 
51
- const App = () => {
51
+ export const App = () => {
52
52
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
53
53
  const theme = useMemo(
54
54
  () => createDefaultTheme(prefersDarkMode ? 'dark' : 'light'),
@@ -19,17 +19,18 @@ import InfoIcon from '@mui/icons-material/Info';
19
19
  import PublishIcon from '@mui/icons-material/Publish';
20
20
  import AccountBoxIcon from '@mui/icons-material/AccountBox';
21
21
  import { UserAvatar } from '../pages/user/avatar';
22
- import { UserSettingsRoutes } from '../pages/user/user-settings';
22
+ import { UserSettingsRoutes } from '../pages/user/user-settings-routes';
23
23
  import { styled, Theme } from '@mui/material/styles';
24
24
  import { MainContext } from '../context';
25
25
  import SettingsIcon from '@mui/icons-material/Settings';
26
26
  import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
27
27
  import LogoutIcon from '@mui/icons-material/Logout';
28
- import { AdminDashboardRoutes } from '../pages/admin-dashboard/admin-dashboard';
28
+ import { AdminDashboardRoutes } from '../pages/admin-dashboard/admin-routes';
29
29
  import { LogoutForm } from '../pages/user/logout';
30
30
  import { LoginComponent } from './login';
31
31
 
32
32
  //-------------------- Mobile View --------------------//
33
+ // eslint-disable-next-line react-refresh/only-export-components
33
34
  export const itemIcon = {
34
35
  mr: 1,
35
36
  width: '16px',
@@ -161,6 +162,7 @@ export const MobileMenuContent: FunctionComponent = () => {
161
162
 
162
163
  //-------------------- Default View --------------------//
163
164
 
165
+ // eslint-disable-next-line react-refresh/only-export-components
164
166
  export const headerItem = ({ theme }: { theme: Theme }) => ({
165
167
  margin: theme.spacing(2.5),
166
168
  color: theme.palette.text.primary,
@@ -175,7 +177,9 @@ export const headerItem = ({ theme }: { theme: Theme }) => ({
175
177
  }
176
178
  });
177
179
 
180
+ // eslint-disable-next-line react-refresh/only-export-components
178
181
  export const MenuLink = styled(Link)(headerItem);
182
+ // eslint-disable-next-line react-refresh/only-export-components
179
183
  export const MenuRouteLink = styled(RouteLink)(headerItem);
180
184
 
181
185
  export const DefaultMenuContent: FunctionComponent = () => {
@@ -16,7 +16,7 @@ import { Link as RouteLink, Route, useParams } from 'react-router-dom';
16
16
  import GitHubIcon from '@mui/icons-material/GitHub';
17
17
  import { Extension, NamespaceDetails } from '../extension-registry-types';
18
18
  import { PageSettings } from '../page-settings';
19
- import { ExtensionListRoutes } from '../pages/extension-list/extension-list-container';
19
+ import { ExtensionListRoutes } from '../pages/extension-list/extension-list-routes';
20
20
  import { DefaultMenuContent, MobileMenuContent } from './menu-content';
21
21
  import OpenVSXLogo from './openvsx-registry-logo';
22
22
  import About from './about';
@@ -15,7 +15,7 @@ import {
15
15
  LoginProviders, ScanResultJson, ScanCounts, ScanResultsResponse, ScanFilterOptions,
16
16
  FilesResponse, FileDecisionCountsJson, ScanDecisionRequest, ScanDecisionResponse,
17
17
  FileDecisionRequest, FileDecisionResponse, FileDecisionDeleteRequest, FileDecisionDeleteResponse,
18
- Tier, TierList, Customer, CustomerList, UsageStatsList, LogPageableList,
18
+ Tier, TierList, Customer, CustomerList, UsageStatsList, LogPageableList, CustomerMembershipList,
19
19
  } from './extension-registry-types';
20
20
  import { createAbsoluteURL, addQuery } from './utils';
21
21
  import { sendRequest, ErrorResponse } from './server-request';
@@ -28,7 +28,7 @@ export class ExtensionRegistryService {
28
28
  this.admin = new AdminConstructor(this);
29
29
  }
30
30
 
31
- getLoginProviders(abortController: AbortController): Promise<Readonly<LoginProviders|SuccessResult>> {
31
+ async getLoginProviders(abortController: AbortController): Promise<Readonly<LoginProviders|SuccessResult>> {
32
32
  const endpoint = createAbsoluteURL([this.serverUrl, 'login-providers']);
33
33
  return sendRequest({ abortController, endpoint });
34
34
  }
@@ -49,7 +49,7 @@ export class ExtensionRegistryService {
49
49
  return createAbsoluteURL(arr);
50
50
  }
51
51
 
52
- getNamespaceDetails(abortController: AbortController, name: string): Promise<Readonly<NamespaceDetails>> {
52
+ async getNamespaceDetails(abortController: AbortController, name: string): Promise<Readonly<NamespaceDetails>> {
53
53
  const endpoint = createAbsoluteURL([this.serverUrl, 'api', name, 'details']);
54
54
  return sendRequest({ abortController, endpoint });
55
55
  }
@@ -95,7 +95,7 @@ export class ExtensionRegistryService {
95
95
  });
96
96
  }
97
97
 
98
- search(abortController: AbortController, filter?: ExtensionFilter): Promise<Readonly<SearchResult | ErrorResult>> {
98
+ async search(abortController: AbortController, filter?: ExtensionFilter): Promise<Readonly<SearchResult | ErrorResult>> {
99
99
  const query: { key: string, value: string | number }[] = [];
100
100
  if (filter) {
101
101
  if (filter.query)
@@ -115,11 +115,11 @@ export class ExtensionRegistryService {
115
115
  return sendRequest({ abortController, endpoint });
116
116
  }
117
117
 
118
- getExtensionDetail(abortController: AbortController, extensionUrl: UrlString): Promise<Readonly<Extension | ErrorResult>> {
118
+ async getExtensionDetail(abortController: AbortController, extensionUrl: UrlString): Promise<Readonly<Extension | ErrorResult>> {
119
119
  return sendRequest({ abortController, endpoint: extensionUrl });
120
120
  }
121
121
 
122
- getExtensionReadme(abortController: AbortController, extension: Extension): Promise<string> {
122
+ async getExtensionReadme(abortController: AbortController, extension: Extension): Promise<string> {
123
123
  return sendRequest({
124
124
  abortController,
125
125
  endpoint: extension.files.readme,
@@ -128,7 +128,7 @@ export class ExtensionRegistryService {
128
128
  });
129
129
  }
130
130
 
131
- getExtensionChangelog(abortController: AbortController, extension: Extension): Promise<string> {
131
+ async getExtensionChangelog(abortController: AbortController, extension: Extension): Promise<string> {
132
132
  return sendRequest({
133
133
  abortController,
134
134
  endpoint: extension.files.changelog,
@@ -137,7 +137,7 @@ export class ExtensionRegistryService {
137
137
  });
138
138
  }
139
139
 
140
- getExtensionIcon(abortController: AbortController, extension: Extension | SearchEntry): Promise<string | undefined> {
140
+ async getExtensionIcon(abortController: AbortController, extension: Extension | SearchEntry): Promise<string | undefined> {
141
141
  if (!extension.files.icon) {
142
142
  return Promise.resolve(undefined);
143
143
  }
@@ -173,7 +173,7 @@ export class ExtensionRegistryService {
173
173
  ];
174
174
  }
175
175
 
176
- getExtensionReviews(abortController: AbortController, extension: Extension): Promise<Readonly<ExtensionReviewList>> {
176
+ async getExtensionReviews(abortController: AbortController, extension: Extension): Promise<Readonly<ExtensionReviewList>> {
177
177
  return sendRequest({ abortController, endpoint: extension.reviewsUrl });
178
178
  }
179
179
 
@@ -228,7 +228,7 @@ export class ExtensionRegistryService {
228
228
  });
229
229
  }
230
230
 
231
- getUser(abortController: AbortController): Promise<Readonly<UserData | ErrorResult>> {
231
+ async getUser(abortController: AbortController): Promise<Readonly<UserData | ErrorResult>> {
232
232
  return sendRequest({
233
233
  abortController,
234
234
  endpoint: createAbsoluteURL([this.serverUrl, 'user']),
@@ -236,7 +236,7 @@ export class ExtensionRegistryService {
236
236
  });
237
237
  }
238
238
 
239
- getUserAuthError(abortController: AbortController): Promise<Readonly<ErrorResponse>> {
239
+ async getUserAuthError(abortController: AbortController): Promise<Readonly<ErrorResponse>> {
240
240
  return sendRequest({
241
241
  abortController,
242
242
  endpoint: createAbsoluteURL([this.serverUrl, 'user', 'auth-error']),
@@ -244,7 +244,7 @@ export class ExtensionRegistryService {
244
244
  });
245
245
  }
246
246
 
247
- getUserByName(abortController: AbortController, name: string): Promise<Readonly<UserData>[]> {
247
+ async getUserByName(abortController: AbortController, name: string): Promise<Readonly<UserData>[]> {
248
248
  return sendRequest({
249
249
  abortController,
250
250
  endpoint: createAbsoluteURL([this.serverUrl, 'user', 'search', name]),
@@ -252,7 +252,7 @@ export class ExtensionRegistryService {
252
252
  });
253
253
  }
254
254
 
255
- getAccessTokens(abortController: AbortController, user: UserData): Promise<Readonly<PersonalAccessToken>[]> {
255
+ async getAccessTokens(abortController: AbortController, user: UserData): Promise<Readonly<PersonalAccessToken>[]> {
256
256
  return sendRequest({
257
257
  abortController,
258
258
  credentials: true,
@@ -310,7 +310,7 @@ export class ExtensionRegistryService {
310
310
  })));
311
311
  }
312
312
 
313
- getCsrfToken(abortController: AbortController): Promise<Readonly<CsrfTokenJson | ErrorResult>> {
313
+ async getCsrfToken(abortController: AbortController): Promise<Readonly<CsrfTokenJson | ErrorResult>> {
314
314
  return sendRequest({
315
315
  abortController,
316
316
  credentials: true,
@@ -318,7 +318,7 @@ export class ExtensionRegistryService {
318
318
  });
319
319
  }
320
320
 
321
- getNamespaces(abortController: AbortController): Promise<Readonly<Namespace>[]> {
321
+ async getNamespaces(abortController: AbortController): Promise<Readonly<Namespace>[]> {
322
322
  return sendRequest({
323
323
  abortController,
324
324
  credentials: true,
@@ -326,7 +326,26 @@ export class ExtensionRegistryService {
326
326
  });
327
327
  }
328
328
 
329
- getNamespaceMembers(abortController: AbortController, namespace: Namespace): Promise<Readonly<NamespaceMembershipList>> {
329
+ async getCustomers(abortController: AbortController): Promise<Readonly<Customer>[]> {
330
+ return sendRequest({
331
+ abortController,
332
+ credentials: true,
333
+ endpoint: createAbsoluteURL([this.serverUrl, 'user', 'customers'])
334
+ });
335
+ }
336
+
337
+ async getUsageStats(abortController: AbortController, customerName: string, date: Date): Promise<Readonly<UsageStatsList>> {
338
+ const query: { key: string, value: string | number }[] = [];
339
+ query.push({ key: 'date', value: date.toISOString() });
340
+
341
+ return sendRequest({
342
+ abortController,
343
+ endpoint: createAbsoluteURL([this.serverUrl, 'user', 'customers', customerName, 'usage'], query),
344
+ credentials: true
345
+ }, false);
346
+ }
347
+
348
+ async getNamespaceMembers(abortController: AbortController, namespace: Namespace): Promise<Readonly<NamespaceMembershipList>> {
330
349
  return sendRequest({
331
350
  abortController,
332
351
  credentials: true,
@@ -371,7 +390,7 @@ export class ExtensionRegistryService {
371
390
  });
372
391
  }
373
392
 
374
- getStaticContent(abortController: AbortController, url: string): Promise<string> {
393
+ async getStaticContent(abortController: AbortController, url: string): Promise<string> {
375
394
  return sendRequest({
376
395
  abortController,
377
396
  endpoint: url,
@@ -505,9 +524,13 @@ export interface AdminService {
505
524
  updateTier(abortController: AbortController, name: string, tier: Tier): Promise<Readonly<Tier>>;
506
525
  deleteTier(abortController: AbortController, name: string): Promise<Readonly<SuccessResult | ErrorResult>>;
507
526
  getCustomers(abortController: AbortController): Promise<Readonly<CustomerList>>;
527
+ getCustomer(abortController: AbortController, name: string): Promise<Readonly<Customer>>;
508
528
  createCustomer(abortController: AbortController, customer: Customer): Promise<Readonly<Customer>>;
509
529
  updateCustomer(abortController: AbortController, name: string, customer: Customer): Promise<Readonly<Customer>>;
510
530
  deleteCustomer(abortController: AbortController, name: string): Promise<Readonly<SuccessResult | ErrorResult>>;
531
+ getCustomerMembers(abortController: AbortController, name: string): Promise<Readonly<CustomerMembershipList>>;
532
+ addCustomerMember(abortController: AbortController, name: string, user: UserData): Promise<Readonly<SuccessResult | ErrorResult>>;
533
+ removeCustomerMember(abortController: AbortController, name: string, user: UserData): Promise<Readonly<SuccessResult | ErrorResult>>;
511
534
  getUsageStats(abortController: AbortController, customerName: string, date: Date): Promise<Readonly<UsageStatsList>>;
512
535
  getLogs(abortController: AbortController, page?: number, size?: number, period?: string): Promise<Readonly<LogPageableList>>;
513
536
  }
@@ -520,7 +543,7 @@ export class AdminServiceImpl implements AdminService {
520
543
 
521
544
  constructor(readonly registry: ExtensionRegistryService) {}
522
545
 
523
- getExtension(abortController: AbortController, namespace: string, extension: string): Promise<Readonly<Extension>> {
546
+ async getExtension(abortController: AbortController, namespace: string, extension: string): Promise<Readonly<Extension>> {
524
547
  return sendRequest({
525
548
  abortController,
526
549
  credentials: true,
@@ -548,7 +571,7 @@ export class AdminServiceImpl implements AdminService {
548
571
  });
549
572
  }
550
573
 
551
- getNamespace(abortController: AbortController, name: string): Promise<Readonly<Namespace>> {
574
+ async getNamespace(abortController: AbortController, name: string): Promise<Readonly<Namespace>> {
552
575
  return sendRequest({
553
576
  abortController,
554
577
  credentials: true,
@@ -634,7 +657,7 @@ export class AdminServiceImpl implements AdminService {
634
657
  });
635
658
  }
636
659
 
637
- getAllScans(abortController: AbortController, params?: { size?: number; offset?: number; status?: string | string[]; publisher?: string; namespace?: string; name?: string; validationType?: string[]; threatScannerName?: string[]; dateStartedFrom?: string; dateStartedTo?: string; enforcement?: 'enforced' | 'notEnforced' | 'all'; adminDecision?: string[] }): Promise<Readonly<ScanResultsResponse>> {
660
+ async getAllScans(abortController: AbortController, params?: { size?: number; offset?: number; status?: string | string[]; publisher?: string; namespace?: string; name?: string; validationType?: string[]; threatScannerName?: string[]; dateStartedFrom?: string; dateStartedTo?: string; enforcement?: 'enforced' | 'notEnforced' | 'all'; adminDecision?: string[] }): Promise<Readonly<ScanResultsResponse>> {
638
661
  const query: { key: string, value: string | number }[] = [];
639
662
  if (params) {
640
663
  if (params.size !== undefined)
@@ -672,7 +695,7 @@ export class AdminServiceImpl implements AdminService {
672
695
  });
673
696
  }
674
697
 
675
- getScan(abortController: AbortController, scanId: string): Promise<Readonly<ScanResultJson>> {
698
+ async getScan(abortController: AbortController, scanId: string): Promise<Readonly<ScanResultJson>> {
676
699
  return sendRequest({
677
700
  abortController,
678
701
  credentials: true,
@@ -680,7 +703,7 @@ export class AdminServiceImpl implements AdminService {
680
703
  });
681
704
  }
682
705
 
683
- getScanCounts(abortController: AbortController, params?: { dateStartedFrom?: string; dateStartedTo?: string; enforcement?: 'enforced' | 'notEnforced' | 'all'; threatScannerName?: string[]; validationType?: string[] }): Promise<Readonly<ScanCounts>> {
706
+ async getScanCounts(abortController: AbortController, params?: { dateStartedFrom?: string; dateStartedTo?: string; enforcement?: 'enforced' | 'notEnforced' | 'all'; threatScannerName?: string[]; validationType?: string[] }): Promise<Readonly<ScanCounts>> {
684
707
  const query: { key: string, value: string | number }[] = [];
685
708
  if (params) {
686
709
  if (params.dateStartedFrom)
@@ -704,7 +727,7 @@ export class AdminServiceImpl implements AdminService {
704
727
  });
705
728
  }
706
729
 
707
- getScanFilterOptions(abortController: AbortController): Promise<Readonly<ScanFilterOptions>> {
730
+ async getScanFilterOptions(abortController: AbortController): Promise<Readonly<ScanFilterOptions>> {
708
731
  return sendRequest({
709
732
  abortController,
710
733
  credentials: true,
@@ -712,7 +735,7 @@ export class AdminServiceImpl implements AdminService {
712
735
  });
713
736
  }
714
737
 
715
- getFiles(abortController: AbortController, params?: { size?: number; offset?: number; decision?: string; publisher?: string; namespace?: string; name?: string; dateDecidedFrom?: string; dateDecidedTo?: string; sortBy?: string; sortOrder?: 'asc' | 'desc' }): Promise<Readonly<FilesResponse>> {
738
+ async getFiles(abortController: AbortController, params?: { size?: number; offset?: number; decision?: string; publisher?: string; namespace?: string; name?: string; dateDecidedFrom?: string; dateDecidedTo?: string; sortBy?: string; sortOrder?: 'asc' | 'desc' }): Promise<Readonly<FilesResponse>> {
716
739
  const query: { key: string, value: string | number }[] = [];
717
740
  if (params) {
718
741
  if (params.size !== undefined)
@@ -744,7 +767,7 @@ export class AdminServiceImpl implements AdminService {
744
767
  });
745
768
  }
746
769
 
747
- getFileCounts(abortController: AbortController, params?: { dateDecidedFrom?: string; dateDecidedTo?: string }): Promise<Readonly<FileDecisionCountsJson>> {
770
+ async getFileCounts(abortController: AbortController, params?: { dateDecidedFrom?: string; dateDecidedTo?: string }): Promise<Readonly<FileDecisionCountsJson>> {
748
771
  const query: { key: string, value: string | number }[] = [];
749
772
  if (params) {
750
773
  if (params.dateDecidedFrom)
@@ -885,13 +908,21 @@ export class AdminServiceImpl implements AdminService {
885
908
  }
886
909
 
887
910
  async getCustomers(abortController: AbortController): Promise<Readonly<CustomerList>> {
888
- return sendRequest({
911
+ return await sendRequest({
889
912
  abortController,
890
913
  endpoint: createAbsoluteURL([this.registry.serverUrl, 'admin', 'ratelimit', 'customers']),
891
914
  credentials: true
892
915
  }, false);
893
916
  }
894
917
 
918
+ async getCustomer(abortController: AbortController, name: string): Promise<Readonly<Customer>> {
919
+ return await sendRequest({
920
+ abortController,
921
+ endpoint: createAbsoluteURL([this.registry.serverUrl, 'admin', 'ratelimit', 'customers', name]),
922
+ credentials: true
923
+ }, false);
924
+ }
925
+
895
926
  async createCustomer(abortController: AbortController, customer: Customer): Promise<Readonly<Customer>> {
896
927
  const csrfResponse = await this.registry.getCsrfToken(abortController);
897
928
  const headers: Record<string, string> = {
@@ -948,6 +979,54 @@ export class AdminServiceImpl implements AdminService {
948
979
  }, false);
949
980
  }
950
981
 
982
+ async getCustomerMembers(abortController: AbortController, name: string): Promise<Readonly<CustomerMembershipList>> {
983
+ return sendRequest({
984
+ abortController,
985
+ credentials: true,
986
+ endpoint: createAbsoluteURL([this.registry.serverUrl, 'admin', 'ratelimit', 'customers', name, "members"]),
987
+ }, false);
988
+ }
989
+
990
+ async addCustomerMember(abortController: AbortController, name: string, user: UserData): Promise<Readonly<SuccessResult | ErrorResult>> {
991
+ const csrfResponse = await this.registry.getCsrfToken(abortController);
992
+ const headers: Record<string, string> = {};
993
+ if (!isError(csrfResponse)) {
994
+ const csrfToken = csrfResponse as CsrfTokenJson;
995
+ headers[csrfToken.header] = csrfToken.value;
996
+ }
997
+ const query = [
998
+ { key: 'user', value: user.loginName },
999
+ { key: 'provider', value: user.provider },
1000
+ ];
1001
+ return sendRequest({
1002
+ abortController,
1003
+ headers,
1004
+ method: 'POST',
1005
+ credentials: true,
1006
+ endpoint: addQuery(createAbsoluteURL([this.registry.serverUrl, 'admin', 'ratelimit', 'customers', name, "add-member"]), query),
1007
+ }, false);
1008
+ }
1009
+
1010
+ async removeCustomerMember(abortController: AbortController, name: string, user: UserData): Promise<Readonly<SuccessResult | ErrorResult>> {
1011
+ const csrfResponse = await this.registry.getCsrfToken(abortController);
1012
+ const headers: Record<string, string> = {};
1013
+ if (!isError(csrfResponse)) {
1014
+ const csrfToken = csrfResponse as CsrfTokenJson;
1015
+ headers[csrfToken.header] = csrfToken.value;
1016
+ }
1017
+ const query = [
1018
+ { key: 'user', value: user.loginName },
1019
+ { key: 'provider', value: user.provider },
1020
+ ];
1021
+ return sendRequest({
1022
+ abortController,
1023
+ headers,
1024
+ method: 'POST',
1025
+ credentials: true,
1026
+ endpoint: addQuery(createAbsoluteURL([this.registry.serverUrl, 'admin', 'ratelimit', 'customers', name, "remove-member"]), query),
1027
+ }, false);
1028
+ }
1029
+
951
1030
  /**
952
1031
  * Get usage stats for a customer within an optional date range.
953
1032
  */
@@ -458,6 +458,15 @@ export interface CustomerList {
458
458
  customers: Customer[];
459
459
  }
460
460
 
461
+ export interface CustomerMembership {
462
+ customer: string;
463
+ user: UserData;
464
+ }
465
+
466
+ export interface CustomerMembershipList {
467
+ customerMemberships: CustomerMembership[];
468
+ }
469
+
461
470
  export interface UsageStats {
462
471
  windowStart: number; // epoch seconds in UTC
463
472
  duration: number; // in seconds
package/src/main.tsx CHANGED
@@ -11,7 +11,8 @@
11
11
  import { FunctionComponent, ReactNode, useEffect, useState, useRef } from 'react';
12
12
  import { CssBaseline } from '@mui/material';
13
13
  import { Route, Routes } from 'react-router-dom';
14
- import { AdminDashboard, AdminDashboardRoutes } from './pages/admin-dashboard/admin-dashboard';
14
+ import { AdminDashboard } from './pages/admin-dashboard/admin-dashboard';
15
+ import { AdminDashboardRoutes } from './pages/admin-dashboard/admin-routes';
15
16
  import { ErrorDialog } from './components/error-dialog';
16
17
  import { handleError } from './utils';
17
18
  import { ExtensionRegistryService } from './extension-registry-service';
@@ -1,3 +1,16 @@
1
+ /******************************************************************************
2
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
3
+ *
4
+ * See the NOTICE file(s) distributed with this work for additional
5
+ * information regarding copyright ownership.
6
+ *
7
+ * This program and the accompanying materials are made available under the
8
+ * terms of the Eclipse Public License 2.0 which is available at
9
+ * https://www.eclipse.org/legal/epl-2.0.
10
+ *
11
+ * SPDX-License-Identifier: EPL-2.0
12
+ *****************************************************************************/
13
+
1
14
  import { FunctionComponent, useContext, useEffect, useState } from 'react';
2
15
  import { Routes, Route } from 'react-router-dom';
3
16
  import { AppBar, Box, Toolbar } from '@mui/material';
@@ -5,10 +18,14 @@ import { styled, Theme } from '@mui/material/styles';
5
18
  import { Banner } from './components/banner';
6
19
  import { MainContext } from './context';
7
20
  import { HeaderMenu } from './header-menu';
8
- import { ExtensionListContainer, ExtensionListRoutes } from './pages/extension-list/extension-list-container';
9
- import { UserSettings, UserSettingsRoutes } from './pages/user/user-settings';
10
- import { NamespaceDetail, NamespaceDetailRoutes } from './pages/namespace-detail/namespace-detail';
11
- import { ExtensionDetail, ExtensionDetailRoutes } from './pages/extension-detail/extension-detail';
21
+ import { ExtensionListContainer } from './pages/extension-list/extension-list-container';
22
+ import { ExtensionListRoutes } from "./pages/extension-list/extension-list-routes";
23
+ import { UserSettings } from './pages/user/user-settings';
24
+ import { UserSettingsRoutes } from './pages/user/user-settings-routes';
25
+ import { NamespaceDetail } from './pages/namespace-detail/namespace-detail';
26
+ import { NamespaceDetailRoutes } from './pages/namespace-detail/namespace-detail-routes';
27
+ import { ExtensionDetail } from './pages/extension-detail/extension-detail';
28
+ import { ExtensionDetailRoutes } from './pages/extension-detail/extension-detail-routes';
12
29
  import { getCookieValueByKey, setCookie } from './utils';
13
30
  import { UserData } from './extension-registry-types';
14
31
  import { NotFound } from './not-found';