openvsx-webui-test 0.19.0-dev.2 → 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 (350) 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/error-dialog.d.ts.map +1 -1
  8. package/lib/components/error-dialog.js +5 -3
  9. package/lib/components/error-dialog.js.map +1 -1
  10. package/lib/components/rate-limiting/customer/general-details.d.ts +20 -0
  11. package/lib/components/rate-limiting/customer/general-details.d.ts.map +1 -0
  12. package/lib/components/rate-limiting/customer/general-details.js +8 -0
  13. package/lib/components/rate-limiting/customer/general-details.js.map +1 -0
  14. package/lib/components/rate-limiting/customer/index.d.ts +17 -0
  15. package/lib/components/rate-limiting/customer/index.d.ts.map +1 -0
  16. package/lib/components/rate-limiting/customer/index.js +15 -0
  17. package/lib/components/rate-limiting/customer/index.js.map +1 -0
  18. package/lib/components/rate-limiting/customer/usage-stats.d.ts +24 -0
  19. package/lib/components/rate-limiting/customer/usage-stats.d.ts.map +1 -0
  20. package/lib/components/rate-limiting/customer/usage-stats.js +6 -0
  21. package/lib/components/rate-limiting/customer/usage-stats.js.map +1 -0
  22. package/lib/{pages/admin-dashboard → components/rate-limiting}/usage-stats/usage-stats-chart.d.ts +5 -2
  23. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.d.ts.map +1 -0
  24. package/lib/{pages/admin-dashboard → components/rate-limiting}/usage-stats/usage-stats-chart.js +25 -18
  25. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.js.map +1 -0
  26. package/lib/components/rate-limiting/usage-stats/usage-stats-utils.d.ts +15 -0
  27. package/lib/components/rate-limiting/usage-stats/usage-stats-utils.d.ts.map +1 -0
  28. package/{src/pages/admin-dashboard/usage-stats/usage-stats-utils.ts → lib/components/rate-limiting/usage-stats/usage-stats-utils.js} +4 -3
  29. package/lib/components/rate-limiting/usage-stats/usage-stats-utils.js.map +1 -0
  30. package/lib/components/rate-limiting/usage-stats/use-usage-stats.d.ts +22 -0
  31. package/lib/components/rate-limiting/usage-stats/use-usage-stats.d.ts.map +1 -0
  32. package/lib/components/rate-limiting/usage-stats/use-usage-stats.js +58 -0
  33. package/lib/components/rate-limiting/usage-stats/use-usage-stats.js.map +1 -0
  34. package/lib/components/scan-admin/common/conditional-tooltip.js +4 -16
  35. package/lib/components/scan-admin/common/conditional-tooltip.js.map +1 -1
  36. package/lib/components/scan-admin/common/file-table.js +24 -13
  37. package/lib/components/scan-admin/common/file-table.js.map +1 -1
  38. package/lib/components/scan-admin/dialogs/quarantine-dialog.js +4 -8
  39. package/lib/components/scan-admin/dialogs/quarantine-dialog.js.map +1 -1
  40. package/lib/components/scan-admin/scan-card/scan-card-content.js +2 -2
  41. package/lib/components/scan-admin/scan-card/scan-card-content.js.map +1 -1
  42. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.js +21 -16
  43. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.js.map +1 -1
  44. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js +1 -2
  45. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js.map +1 -1
  46. package/lib/components/scan-admin/scan-card/scan-card-header.js +10 -5
  47. package/lib/components/scan-admin/scan-card/scan-card-header.js.map +1 -1
  48. package/lib/components/scan-admin/scan-card/utils.js +1 -2
  49. package/lib/components/scan-admin/scan-card/utils.js.map +1 -1
  50. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.js +4 -6
  51. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.js.map +1 -1
  52. package/lib/components/sidepanel/drawer-header.d.ts +14 -0
  53. package/lib/components/sidepanel/drawer-header.d.ts.map +1 -0
  54. package/lib/components/sidepanel/drawer-header.js +22 -0
  55. package/lib/components/sidepanel/drawer-header.js.map +1 -0
  56. package/lib/components/sidepanel/navigation-item.d.ts.map +1 -1
  57. package/lib/components/sidepanel/navigation-item.js +3 -3
  58. package/lib/components/sidepanel/navigation-item.js.map +1 -1
  59. package/lib/components/sidepanel/sidepanel.d.ts +7 -1
  60. package/lib/components/sidepanel/sidepanel.d.ts.map +1 -1
  61. package/lib/components/sidepanel/sidepanel.js +12 -13
  62. package/lib/components/sidepanel/sidepanel.js.map +1 -1
  63. package/lib/components/text-divider.js +1 -2
  64. package/lib/components/text-divider.js.map +1 -1
  65. package/lib/components/timestamp.d.ts +0 -1
  66. package/lib/components/timestamp.d.ts.map +1 -1
  67. package/lib/components/timestamp.js +2 -4
  68. package/lib/components/timestamp.js.map +1 -1
  69. package/lib/context/scan-admin/scan-api-actions.js +7 -16
  70. package/lib/context/scan-admin/scan-api-actions.js.map +1 -1
  71. package/lib/context/scan-admin/scan-api-effects.js +77 -93
  72. package/lib/context/scan-admin/scan-api-effects.js.map +1 -1
  73. package/lib/context/scan-admin/scan-context.d.ts.map +1 -1
  74. package/lib/context/scan-admin/scan-context.js +1 -0
  75. package/lib/context/scan-admin/scan-context.js.map +1 -1
  76. package/lib/context/scan-admin/scan-reducer.js +134 -53
  77. package/lib/context/scan-admin/scan-reducer.js.map +1 -1
  78. package/lib/default/default-app.d.ts +1 -1
  79. package/lib/default/default-app.d.ts.map +1 -1
  80. package/lib/default/default-app.js +11 -22
  81. package/lib/default/default-app.js.map +1 -1
  82. package/lib/default/menu-content.d.ts.map +1 -1
  83. package/lib/default/menu-content.js +7 -3
  84. package/lib/default/menu-content.js.map +1 -1
  85. package/lib/default/page-settings.js +13 -18
  86. package/lib/default/page-settings.js.map +1 -1
  87. package/lib/extension-registry-service.d.ts +11 -1
  88. package/lib/extension-registry-service.d.ts.map +1 -1
  89. package/lib/extension-registry-service.js +618 -629
  90. package/lib/extension-registry-service.js.map +1 -1
  91. package/lib/extension-registry-types.d.ts +7 -0
  92. package/lib/extension-registry-types.d.ts.map +1 -1
  93. package/lib/hooks/scan-admin/use-auto-rejected-tab.js +5 -7
  94. package/lib/hooks/scan-admin/use-auto-rejected-tab.js.map +1 -1
  95. package/lib/hooks/scan-admin/use-quarantined-tab.js +5 -7
  96. package/lib/hooks/scan-admin/use-quarantined-tab.js.map +1 -1
  97. package/lib/main.d.ts.map +1 -1
  98. package/lib/main.js +8 -16
  99. package/lib/main.js.map +1 -1
  100. package/lib/other-pages.d.ts +12 -0
  101. package/lib/other-pages.d.ts.map +1 -1
  102. package/lib/other-pages.js +25 -12
  103. package/lib/other-pages.js.map +1 -1
  104. package/lib/pages/admin-dashboard/admin-dashboard.d.ts +0 -12
  105. package/lib/pages/admin-dashboard/admin-dashboard.d.ts.map +1 -1
  106. package/lib/pages/admin-dashboard/admin-dashboard.js +136 -49
  107. package/lib/pages/admin-dashboard/admin-dashboard.js.map +1 -1
  108. package/lib/pages/admin-dashboard/admin-routes.d.ts +25 -0
  109. package/lib/pages/admin-dashboard/admin-routes.d.ts.map +1 -0
  110. package/lib/pages/admin-dashboard/admin-routes.js +27 -0
  111. package/lib/pages/admin-dashboard/admin-routes.js.map +1 -0
  112. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.d.ts +1 -9
  113. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.d.ts.map +1 -1
  114. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.js +17 -15
  115. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.js.map +1 -1
  116. package/lib/pages/admin-dashboard/components/data-grid-filter.d.ts +22 -0
  117. package/lib/pages/admin-dashboard/components/data-grid-filter.d.ts.map +1 -0
  118. package/lib/pages/admin-dashboard/components/data-grid-filter.js +13 -0
  119. package/lib/pages/admin-dashboard/components/data-grid-filter.js.map +1 -0
  120. package/lib/pages/admin-dashboard/components/index.d.ts +2 -1
  121. package/lib/pages/admin-dashboard/components/index.d.ts.map +1 -1
  122. package/lib/pages/admin-dashboard/components/index.js +2 -1
  123. package/lib/pages/admin-dashboard/components/index.js.map +1 -1
  124. package/lib/pages/admin-dashboard/{usage-stats/usage-stats-utils.d.ts → customers/customer-details.d.ts} +3 -2
  125. package/lib/pages/admin-dashboard/customers/customer-details.d.ts.map +1 -0
  126. package/lib/pages/admin-dashboard/customers/customer-details.js +77 -0
  127. package/lib/pages/admin-dashboard/customers/customer-details.js.map +1 -0
  128. package/lib/pages/admin-dashboard/customers/customer-form-dialog.d.ts +1 -1
  129. package/lib/pages/admin-dashboard/customers/customer-form-dialog.d.ts.map +1 -1
  130. package/lib/pages/admin-dashboard/customers/customer-form-dialog.js +33 -34
  131. package/lib/pages/admin-dashboard/customers/customer-form-dialog.js.map +1 -1
  132. package/lib/pages/admin-dashboard/customers/customer-member-list.d.ts +19 -0
  133. package/lib/pages/admin-dashboard/customers/customer-member-list.d.ts.map +1 -0
  134. package/lib/pages/admin-dashboard/customers/customer-member-list.js +88 -0
  135. package/lib/pages/admin-dashboard/customers/customer-member-list.js.map +1 -0
  136. package/lib/pages/admin-dashboard/customers/customers.d.ts +1 -1
  137. package/lib/pages/admin-dashboard/customers/customers.js +20 -29
  138. package/lib/pages/admin-dashboard/customers/customers.js.map +1 -1
  139. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.js +4 -14
  140. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.js.map +1 -1
  141. package/lib/pages/admin-dashboard/extension-admin.js +7 -16
  142. package/lib/pages/admin-dashboard/extension-admin.js.map +1 -1
  143. package/lib/pages/admin-dashboard/extension-remove-dialog.js +3 -12
  144. package/lib/pages/admin-dashboard/extension-remove-dialog.js.map +1 -1
  145. package/lib/pages/admin-dashboard/extension-version-container.js +3 -5
  146. package/lib/pages/admin-dashboard/extension-version-container.js.map +1 -1
  147. package/lib/pages/admin-dashboard/logs/logs.d.ts.map +1 -1
  148. package/lib/pages/admin-dashboard/logs/logs.js +6 -24
  149. package/lib/pages/admin-dashboard/logs/logs.js.map +1 -1
  150. package/lib/pages/admin-dashboard/namespace-admin.js +7 -16
  151. package/lib/pages/admin-dashboard/namespace-admin.js.map +1 -1
  152. package/lib/pages/admin-dashboard/namespace-change-dialog.js +3 -12
  153. package/lib/pages/admin-dashboard/namespace-change-dialog.js.map +1 -1
  154. package/lib/pages/admin-dashboard/namespace-input.js +1 -1
  155. package/lib/pages/admin-dashboard/namespace-input.js.map +1 -1
  156. package/lib/pages/admin-dashboard/publisher-admin.d.ts.map +1 -1
  157. package/lib/pages/admin-dashboard/publisher-admin.js +28 -22
  158. package/lib/pages/admin-dashboard/publisher-admin.js.map +1 -1
  159. package/lib/pages/admin-dashboard/publisher-revoke-dialog.js +5 -15
  160. package/lib/pages/admin-dashboard/publisher-revoke-dialog.js.map +1 -1
  161. package/lib/pages/admin-dashboard/publisher-revoke-tokens-button.js +3 -12
  162. package/lib/pages/admin-dashboard/publisher-revoke-tokens-button.js.map +1 -1
  163. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.js +4 -13
  164. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.js.map +1 -1
  165. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.js +34 -23
  166. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.js.map +1 -1
  167. package/lib/pages/admin-dashboard/tiers/tiers.js +12 -21
  168. package/lib/pages/admin-dashboard/tiers/tiers.js.map +1 -1
  169. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.js +3 -14
  170. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.js.map +1 -1
  171. package/lib/pages/admin-dashboard/usage-stats/usage-stats.d.ts.map +1 -1
  172. package/lib/pages/admin-dashboard/usage-stats/usage-stats.js +11 -45
  173. package/lib/pages/admin-dashboard/usage-stats/usage-stats.js.map +1 -1
  174. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.d.ts +22 -0
  175. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.d.ts.map +1 -0
  176. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.js +58 -0
  177. package/lib/pages/admin-dashboard/usage-stats/use-usage-stats.js.map +1 -0
  178. package/lib/pages/admin-dashboard/welcome.js +1 -1
  179. package/lib/pages/admin-dashboard/welcome.js.map +1 -1
  180. package/lib/pages/extension-detail/extension-detail-changes.js +3 -12
  181. package/lib/pages/extension-detail/extension-detail-changes.js.map +1 -1
  182. package/lib/pages/extension-detail/extension-detail-overview.js +6 -16
  183. package/lib/pages/extension-detail/extension-detail-overview.js.map +1 -1
  184. package/lib/pages/extension-detail/extension-detail-reviews.js +12 -24
  185. package/lib/pages/extension-detail/extension-detail-reviews.js.map +1 -1
  186. package/lib/pages/extension-detail/extension-detail-routes.d.ts +32 -0
  187. package/lib/pages/extension-detail/extension-detail-routes.d.ts.map +1 -0
  188. package/lib/pages/extension-detail/extension-detail-routes.js +35 -0
  189. package/lib/pages/extension-detail/extension-detail-routes.js.map +1 -0
  190. package/lib/pages/extension-detail/extension-detail.d.ts +0 -19
  191. package/lib/pages/extension-detail/extension-detail.d.ts.map +1 -1
  192. package/lib/pages/extension-detail/extension-detail.js +28 -50
  193. package/lib/pages/extension-detail/extension-detail.js.map +1 -1
  194. package/lib/pages/extension-detail/extension-rating-stars.js +1 -2
  195. package/lib/pages/extension-detail/extension-rating-stars.js.map +1 -1
  196. package/lib/pages/extension-detail/extension-review-dialog.js +4 -14
  197. package/lib/pages/extension-detail/extension-review-dialog.js.map +1 -1
  198. package/lib/pages/extension-list/extension-list-container.d.ts +0 -3
  199. package/lib/pages/extension-list/extension-list-container.d.ts.map +1 -1
  200. package/lib/pages/extension-list/extension-list-container.js +5 -10
  201. package/lib/pages/extension-list/extension-list-container.js.map +1 -1
  202. package/lib/pages/extension-list/extension-list-header.js +3 -6
  203. package/lib/pages/extension-list/extension-list-header.js.map +1 -1
  204. package/lib/pages/extension-list/extension-list-item.js +7 -17
  205. package/lib/pages/extension-list/extension-list-item.js.map +1 -1
  206. package/lib/pages/extension-list/extension-list-routes.d.ts +16 -0
  207. package/lib/pages/extension-list/extension-list-routes.d.ts.map +1 -0
  208. package/lib/pages/extension-list/extension-list-routes.js +18 -0
  209. package/lib/pages/extension-list/extension-list-routes.js.map +1 -0
  210. package/lib/pages/extension-list/extension-list-searchfield.js +4 -7
  211. package/lib/pages/extension-list/extension-list-searchfield.js.map +1 -1
  212. package/lib/pages/extension-list/extension-list.js +8 -19
  213. package/lib/pages/extension-list/extension-list.js.map +1 -1
  214. package/lib/pages/namespace-detail/namespace-detail-routes.d.ts +20 -0
  215. package/lib/pages/namespace-detail/namespace-detail-routes.d.ts.map +1 -0
  216. package/lib/pages/namespace-detail/namespace-detail-routes.js +23 -0
  217. package/lib/pages/namespace-detail/namespace-detail-routes.js.map +1 -0
  218. package/lib/pages/namespace-detail/namespace-detail.d.ts +0 -7
  219. package/lib/pages/namespace-detail/namespace-detail.d.ts.map +1 -1
  220. package/lib/pages/namespace-detail/namespace-detail.js +4 -24
  221. package/lib/pages/namespace-detail/namespace-detail.js.map +1 -1
  222. package/lib/pages/user/add-namespace-member-dialog.d.ts.map +1 -1
  223. package/lib/pages/user/add-namespace-member-dialog.js +8 -67
  224. package/lib/pages/user/add-namespace-member-dialog.js.map +1 -1
  225. package/lib/pages/user/add-user-dialog.d.ts +25 -0
  226. package/lib/pages/user/add-user-dialog.d.ts.map +1 -0
  227. package/lib/pages/user/add-user-dialog.js +66 -0
  228. package/lib/pages/user/add-user-dialog.js.map +1 -0
  229. package/lib/pages/user/avatar.js +3 -3
  230. package/lib/pages/user/avatar.js.map +1 -1
  231. package/lib/pages/user/create-namespace-dialog.js +3 -12
  232. package/lib/pages/user/create-namespace-dialog.js.map +1 -1
  233. package/lib/pages/user/generate-token-dialog.js +3 -12
  234. package/lib/pages/user/generate-token-dialog.js.map +1 -1
  235. package/lib/pages/user/logout.js +3 -12
  236. package/lib/pages/user/logout.js.map +1 -1
  237. package/lib/pages/user/publish-extension-dialog.js +12 -21
  238. package/lib/pages/user/publish-extension-dialog.js.map +1 -1
  239. package/lib/pages/user/user-namespace-details.js +29 -42
  240. package/lib/pages/user/user-namespace-details.js.map +1 -1
  241. package/lib/pages/user/user-namespace-extension-list-item.js +6 -8
  242. package/lib/pages/user/user-namespace-extension-list-item.js.map +1 -1
  243. package/lib/pages/user/user-namespace-extension-list.js +6 -15
  244. package/lib/pages/user/user-namespace-extension-list.js.map +1 -1
  245. package/lib/pages/user/user-namespace-member-component.js +1 -1
  246. package/lib/pages/user/user-namespace-member-component.js.map +1 -1
  247. package/lib/pages/user/user-namespace-member-list.js +9 -18
  248. package/lib/pages/user/user-namespace-member-list.js.map +1 -1
  249. package/lib/pages/user/user-publisher-agreement.js +8 -18
  250. package/lib/pages/user/user-publisher-agreement.js.map +1 -1
  251. package/lib/pages/user/user-setting-tabs.d.ts.map +1 -1
  252. package/lib/pages/user/user-setting-tabs.js +2 -2
  253. package/lib/pages/user/user-setting-tabs.js.map +1 -1
  254. package/lib/pages/user/user-settings-customer-detail.d.ts +19 -0
  255. package/lib/pages/user/user-settings-customer-detail.d.ts.map +1 -0
  256. package/lib/pages/user/user-settings-customer-detail.js +9 -0
  257. package/lib/pages/user/user-settings-customer-detail.js.map +1 -0
  258. package/lib/pages/user/user-settings-customers.d.ts +15 -0
  259. package/lib/pages/user/user-settings-customers.d.ts.map +1 -0
  260. package/lib/pages/user/user-settings-customers.js +66 -0
  261. package/lib/pages/user/user-settings-customers.js.map +1 -0
  262. package/lib/pages/user/user-settings-delete-extension.js +8 -17
  263. package/lib/pages/user/user-settings-delete-extension.js.map +1 -1
  264. package/lib/pages/user/user-settings-extensions.js +3 -12
  265. package/lib/pages/user/user-settings-extensions.js.map +1 -1
  266. package/lib/pages/user/user-settings-namespace-detail.d.ts.map +1 -1
  267. package/lib/pages/user/user-settings-namespace-detail.js +4 -12
  268. package/lib/pages/user/user-settings-namespace-detail.js.map +1 -1
  269. package/lib/pages/user/user-settings-namespaces.js +6 -15
  270. package/lib/pages/user/user-settings-namespaces.js.map +1 -1
  271. package/lib/pages/user/user-settings-profile.js +1 -2
  272. package/lib/pages/user/user-settings-profile.js.map +1 -1
  273. package/lib/pages/user/user-settings-routes.d.ts +23 -0
  274. package/lib/pages/user/user-settings-routes.d.ts.map +1 -0
  275. package/lib/pages/user/user-settings-routes.js +25 -0
  276. package/lib/pages/user/user-settings-routes.js.map +1 -0
  277. package/lib/pages/user/user-settings-tokens.d.ts +0 -7
  278. package/lib/pages/user/user-settings-tokens.d.ts.map +1 -1
  279. package/lib/pages/user/user-settings-tokens.js +14 -24
  280. package/lib/pages/user/user-settings-tokens.js.map +1 -1
  281. package/lib/pages/user/user-settings.d.ts +0 -9
  282. package/lib/pages/user/user-settings.d.ts.map +1 -1
  283. package/lib/pages/user/user-settings.js +4 -12
  284. package/lib/pages/user/user-settings.js.map +1 -1
  285. package/lib/server-request.js +64 -76
  286. package/lib/server-request.js.map +1 -1
  287. package/lib/utils.d.ts +1 -1
  288. package/lib/utils.d.ts.map +1 -1
  289. package/lib/utils.js +7 -14
  290. package/lib/utils.js.map +1 -1
  291. package/package.json +4 -2
  292. package/src/components/error-dialog.tsx +5 -3
  293. package/src/components/rate-limiting/customer/general-details.tsx +106 -0
  294. package/src/components/rate-limiting/customer/index.ts +18 -0
  295. package/src/components/rate-limiting/customer/usage-stats.tsx +50 -0
  296. package/src/{pages/admin-dashboard → components/rate-limiting}/usage-stats/usage-stats-chart.tsx +46 -26
  297. package/{lib/pages/admin-dashboard/usage-stats/usage-stats-utils.js → src/components/rate-limiting/usage-stats/usage-stats-utils.ts} +4 -2
  298. package/src/components/rate-limiting/usage-stats/use-usage-stats.ts +70 -0
  299. package/src/components/scan-admin/scan-card/scan-card-header.tsx +2 -2
  300. package/src/components/sidepanel/drawer-header.tsx +23 -0
  301. package/src/components/sidepanel/navigation-item.tsx +3 -2
  302. package/src/components/sidepanel/sidepanel.tsx +29 -17
  303. package/src/components/timestamp.tsx +1 -3
  304. package/src/context/scan-admin/scan-context.tsx +1 -0
  305. package/src/default/default-app.tsx +1 -1
  306. package/src/default/menu-content.tsx +6 -2
  307. package/src/default/page-settings.tsx +1 -1
  308. package/src/extension-registry-service.ts +105 -26
  309. package/src/extension-registry-types.ts +9 -0
  310. package/src/main.tsx +2 -1
  311. package/src/other-pages.tsx +21 -4
  312. package/src/pages/admin-dashboard/admin-dashboard.tsx +260 -83
  313. package/src/pages/admin-dashboard/admin-routes.ts +27 -0
  314. package/src/pages/admin-dashboard/components/data-grid-filter-operators.tsx +1 -31
  315. package/src/pages/admin-dashboard/components/data-grid-filter.tsx +45 -0
  316. package/src/pages/admin-dashboard/components/index.ts +1 -1
  317. package/src/pages/admin-dashboard/customers/customer-details.tsx +129 -0
  318. package/src/pages/admin-dashboard/customers/customer-form-dialog.tsx +3 -4
  319. package/src/pages/admin-dashboard/customers/customer-member-list.tsx +174 -0
  320. package/src/pages/admin-dashboard/customers/customers.tsx +8 -8
  321. package/src/pages/admin-dashboard/logs/logs.tsx +1 -10
  322. package/src/pages/admin-dashboard/publisher-admin.tsx +29 -11
  323. package/src/pages/admin-dashboard/usage-stats/usage-stats.tsx +10 -39
  324. package/src/pages/admin-dashboard/usage-stats/use-usage-stats.ts +70 -0
  325. package/src/pages/admin-dashboard/welcome.tsx +1 -1
  326. package/src/pages/extension-detail/extension-detail-overview.tsx +2 -2
  327. package/src/pages/extension-detail/extension-detail-routes.ts +35 -0
  328. package/src/pages/extension-detail/extension-detail.tsx +3 -23
  329. package/src/pages/extension-list/extension-list-container.tsx +1 -5
  330. package/src/pages/extension-list/extension-list-item.tsx +1 -1
  331. package/src/pages/extension-list/extension-list-routes.ts +18 -0
  332. package/src/pages/namespace-detail/namespace-detail-routes.ts +23 -0
  333. package/src/pages/namespace-detail/namespace-detail.tsx +0 -10
  334. package/src/pages/user/add-namespace-member-dialog.tsx +17 -116
  335. package/src/pages/user/add-user-dialog.tsx +141 -0
  336. package/src/pages/user/avatar.tsx +2 -2
  337. package/src/pages/user/user-namespace-extension-list-item.tsx +2 -2
  338. package/src/pages/user/user-setting-tabs.tsx +2 -1
  339. package/src/pages/user/user-settings-customer-detail.tsx +39 -0
  340. package/src/pages/user/user-settings-customers.tsx +120 -0
  341. package/src/pages/user/user-settings-delete-extension.tsx +1 -1
  342. package/src/pages/user/user-settings-namespace-detail.tsx +3 -1
  343. package/src/pages/user/user-settings-routes.ts +25 -0
  344. package/src/pages/user/user-settings-tokens.tsx +2 -9
  345. package/src/pages/user/user-settings.tsx +4 -12
  346. package/src/utils.ts +5 -9
  347. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.d.ts.map +0 -1
  348. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.js.map +0 -1
  349. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.d.ts.map +0 -1
  350. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.js.map +0 -1
@@ -9,45 +9,48 @@
9
9
  ********************************************************************************/
10
10
 
11
11
  import { FunctionComponent, ReactNode, useContext, useState } from 'react';
12
- import { Box, Container, CssBaseline, Typography, IconButton } from '@mui/material';
13
- import { createRoute } from '../../utils';
14
- import { Sidepanel } from '../../components/sidepanel/sidepanel';
15
- import { NavigationItem } from '../../components/sidepanel/navigation-item';
12
+ import {
13
+ Box,
14
+ Container,
15
+ CssBaseline,
16
+ Typography,
17
+ IconButton,
18
+ Breadcrumbs,
19
+ LinkProps,
20
+ Link,
21
+ Toolbar
22
+ } from '@mui/material';
23
+ import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar';
24
+ import { styled } from "@mui/material/styles";
25
+ import { Link as RouterLink, Route, Routes, useNavigate, useLocation } from 'react-router-dom';
26
+ import AccountBoxIcon from '@mui/icons-material/AccountBox';
16
27
  import AssignmentIndIcon from '@mui/icons-material/AssignmentInd';
28
+ import BarChartIcon from '@mui/icons-material/BarChart';
17
29
  import ExtensionSharpIcon from '@mui/icons-material/ExtensionSharp';
18
- import { Route, Routes, useNavigate, useLocation } from 'react-router-dom';
19
- import { NamespaceAdmin } from './namespace-admin';
20
- import { ExtensionAdmin } from './extension-admin';
21
- import { MainContext } from '../../context';
22
30
  import HighlightOffIcon from '@mui/icons-material/HighlightOff';
23
- import { Welcome } from './welcome';
24
- import { PublisherAdmin } from './publisher-admin';
25
- import PersonIcon from '@mui/icons-material/Person';
31
+ import HistoryIcon from '@mui/icons-material/History';
32
+ import MenuIcon from '@mui/icons-material/Menu';
26
33
  import PeopleIcon from '@mui/icons-material/People';
27
- import { ScanAdmin } from './scan-admin';
34
+ import PersonIcon from '@mui/icons-material/Person';
28
35
  import SecurityIcon from '@mui/icons-material/Security';
36
+ import SpeedIcon from '@mui/icons-material/Speed';
29
37
  import StarIcon from '@mui/icons-material/Star';
30
- import BarChartIcon from '@mui/icons-material/BarChart';
31
- import HistoryIcon from '@mui/icons-material/History';
32
- import { Tiers } from './tiers/tiers';
38
+ import { CustomerDetails } from './customers/customer-details';
33
39
  import { Customers } from './customers/customers';
34
- import { UsageStatsView } from './usage-stats/usage-stats';
35
- import { Logs } from './logs/logs';
40
+ import { DrawerHeader } from '../../components/sidepanel/drawer-header';
41
+ import { Sidepanel } from "../../components/sidepanel/sidepanel";
42
+ import { ExtensionAdmin } from './extension-admin';
36
43
  import { LoginComponent } from "../../default/login";
37
- import AccountBoxIcon from '@mui/icons-material/AccountBox';
38
-
39
- export namespace AdminDashboardRoutes {
40
- export const ROOT = 'admin-dashboard';
41
- export const MAIN = createRoute([ROOT]);
42
- export const NAMESPACE_ADMIN = createRoute([ROOT, 'namespaces']);
43
- export const EXTENSION_ADMIN = createRoute([ROOT, 'extensions']);
44
- export const PUBLISHER_ADMIN = createRoute([ROOT, 'publisher']);
45
- export const SCANS_ADMIN = createRoute([ROOT, 'scans']);
46
- export const TIERS = createRoute([ROOT, 'tiers']);
47
- export const CUSTOMERS = createRoute([ROOT, 'customers']);
48
- export const USAGE_STATS = createRoute([ROOT, 'usage']);
49
- export const LOGS = createRoute([ROOT, 'logs']);
50
- }
44
+ import { Logs } from './logs/logs';
45
+ import { MainContext } from '../../context';
46
+ import { NamespaceAdmin } from './namespace-admin';
47
+ import { NavigationItem } from '../../components/sidepanel/navigation-item';
48
+ import { PublisherAdmin } from './publisher-admin';
49
+ import { ScanAdmin } from './scan-admin';
50
+ import { Tiers } from './tiers/tiers';
51
+ import { UsageStatsView } from './usage-stats/usage-stats';
52
+ import { Welcome } from './welcome';
53
+ import { AdminDashboardRoutes } from "./admin-routes";
51
54
 
52
55
  const Message: FunctionComponent<{message: string}> = ({ message }) => {
53
56
  return (<Box sx={{
@@ -60,68 +63,242 @@ const Message: FunctionComponent<{message: string}> = ({ message }) => {
60
63
  </Box>);
61
64
  };
62
65
 
66
+ interface RouteEntry {
67
+ path: string;
68
+ name: string;
69
+ icon: ReactNode;
70
+ }
71
+
72
+ interface NavGroup {
73
+ name: string;
74
+ icon: ReactNode;
75
+ children: RouteEntry[];
76
+ }
77
+
78
+ type NavEntry = RouteEntry | NavGroup;
79
+
80
+ const isNavGroup = (entry: NavEntry): entry is NavGroup => 'children' in entry;
81
+
82
+ const navConfig: NavEntry[] = [
83
+ { path: AdminDashboardRoutes.NAMESPACE_ADMIN, name: 'Namespaces', icon: <AssignmentIndIcon /> },
84
+ { path: AdminDashboardRoutes.EXTENSION_ADMIN, name: 'Extensions', icon: <ExtensionSharpIcon /> },
85
+ { path: AdminDashboardRoutes.PUBLISHER_ADMIN, name: 'Publisher', icon: <PersonIcon /> },
86
+ { path: AdminDashboardRoutes.SCANS_ADMIN, name: 'Scans', icon: <SecurityIcon /> },
87
+ {
88
+ name: 'Rate Limiting',
89
+ icon: <SpeedIcon />,
90
+ children: [
91
+ { path: AdminDashboardRoutes.TIERS, name: 'Tiers', icon: <StarIcon /> },
92
+ { path: AdminDashboardRoutes.CUSTOMERS, name: 'Customers', icon: <PeopleIcon /> },
93
+ { path: AdminDashboardRoutes.USAGE_STATS, name: 'Usage Stats', icon: <BarChartIcon /> },
94
+ ],
95
+ },
96
+ { path: AdminDashboardRoutes.LOGS, name: 'Logs', icon: <HistoryIcon /> },
97
+ ];
98
+
99
+ // Flat name lookup for breadcrumbs
100
+ const routeNames: { [key: string]: string } = {
101
+ [AdminDashboardRoutes.MAIN]: 'Admin Dashboard',
102
+ ...navConfig.reduce<{ [key: string]: string }>((acc, entry) => {
103
+ if (isNavGroup(entry)) {
104
+ entry.children.forEach(child => {
105
+ acc[child.path] = child.name;
106
+ });
107
+ } else {
108
+ acc[entry.path] = entry.name;
109
+ }
110
+ return acc;
111
+ }, {}),
112
+ };
113
+
114
+ const drawerWidth = 240;
115
+
116
+ interface AppBarProps extends MuiAppBarProps {
117
+ open?: boolean;
118
+ }
119
+
120
+ const AppBar = styled(MuiAppBar, {
121
+ shouldForwardProp: (prop) => prop !== 'open',
122
+ })<AppBarProps>(({ theme }) => ({
123
+ transition: theme.transitions.create(['margin', 'width'], {
124
+ easing: theme.transitions.easing.sharp,
125
+ duration: theme.transitions.duration.leavingScreen,
126
+ }),
127
+ variants: [
128
+ {
129
+ props: ({ open }) => open,
130
+ style: {
131
+ width: `calc(100% - ${drawerWidth}px)`,
132
+ marginLeft: `${drawerWidth}px`,
133
+ transition: theme.transitions.create(['margin', 'width'], {
134
+ easing: theme.transitions.easing.easeOut,
135
+ duration: theme.transitions.duration.enteringScreen,
136
+ }),
137
+ },
138
+ },
139
+ ],
140
+ }));
141
+
142
+ interface LinkRouterProps extends LinkProps {
143
+ to: string;
144
+ replace?: boolean;
145
+ }
146
+
147
+ const LinkRouter = (props: LinkRouterProps) => (
148
+ <Link {...props} component={RouterLink as any} />
149
+ );
150
+
151
+ const BreadcrumbsComponent = () => {
152
+ const { pathname } = useLocation();
153
+
154
+ const pathnames = pathname.split("/").filter((segment) => segment);
155
+
156
+ return (
157
+ <Breadcrumbs aria-label='breadcrumb' sx={{ pt: 2, pb: 2, px: 4 }} >
158
+ <LinkRouter underline='hover' color='inherit' to='/'>
159
+ Home
160
+ </LinkRouter>
161
+ {pathnames.map((value, index) => {
162
+ const last = index === pathnames.length - 1;
163
+ const to = `/${pathnames.slice(0, index + 1).join("/")}`;
164
+
165
+ return last ? (
166
+ <Typography color='text.primary' key={to}>
167
+ {routeNames[to] ?? value}
168
+ </Typography>
169
+ ) : (
170
+ <LinkRouter underline='hover' color='inherit' to={to} key={to}>
171
+ {routeNames[to]}
172
+ </LinkRouter>
173
+ );
174
+ })}
175
+ </Breadcrumbs>
176
+ );
177
+ };
178
+
179
+ const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
180
+ open?: boolean;
181
+ }>(({ theme }) => ({
182
+ flexGrow: 1,
183
+ padding: theme.spacing(3),
184
+ transition: theme.transitions.create('margin', {
185
+ easing: theme.transitions.easing.sharp,
186
+ duration: theme.transitions.duration.leavingScreen,
187
+ }),
188
+ marginLeft: `-${drawerWidth}px`,
189
+ variants: [
190
+ {
191
+ props: ({ open }) => open,
192
+ style: {
193
+ transition: theme.transitions.create('margin', {
194
+ easing: theme.transitions.easing.easeOut,
195
+ duration: theme.transitions.duration.enteringScreen,
196
+ }),
197
+ marginLeft: 0,
198
+ },
199
+ },
200
+ ],
201
+ }));
202
+
63
203
  export const AdminDashboard: FunctionComponent<AdminDashboardProps> = props => {
64
204
  const { user, loginProviders } = useContext(MainContext);
205
+ const [drawerOpen, setDrawerOpen] = useState(true);
65
206
 
66
207
  const navigate = useNavigate();
67
208
  const toMainPage = () => navigate('/');
68
209
 
69
210
  const [currentPage, setCurrentPage] = useState<string | undefined>(useLocation().pathname);
70
- const handleOpenRoute = (route: string) => setCurrentPage(route);
211
+ const handleOpenRoute = (route: string) => {
212
+ setCurrentPage(route);
213
+ };
71
214
 
72
215
  let content: ReactNode = null;
73
216
  if (user?.role === 'admin') {
74
- content = <>
75
- <Sidepanel>
76
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.NAMESPACE_ADMIN} label='Namespaces' icon={<AssignmentIndIcon />} route={AdminDashboardRoutes.NAMESPACE_ADMIN} />
77
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.EXTENSION_ADMIN} label='Extensions' icon={<ExtensionSharpIcon />} route={AdminDashboardRoutes.EXTENSION_ADMIN} />
78
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.PUBLISHER_ADMIN} label='Publishers' icon={<PersonIcon />} route={AdminDashboardRoutes.PUBLISHER_ADMIN} />
79
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.SCANS_ADMIN} label='Scans' icon={<SecurityIcon />} route={AdminDashboardRoutes.SCANS_ADMIN} />
80
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.TIERS} label='Tiers' icon={<StarIcon />} route={AdminDashboardRoutes.TIERS} />
81
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.CUSTOMERS} label='Customers' icon={<PeopleIcon />} route={AdminDashboardRoutes.CUSTOMERS} />
82
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage?.startsWith(AdminDashboardRoutes.USAGE_STATS)} label='Usage Stats' icon={<BarChartIcon />} route={AdminDashboardRoutes.USAGE_STATS} />
83
- <NavigationItem onOpenRoute={handleOpenRoute} active={currentPage === AdminDashboardRoutes.LOGS} label='Logs' icon={<HistoryIcon />} route={AdminDashboardRoutes.LOGS} />
84
- </Sidepanel>
85
- <Box
86
- overflow='auto'
87
- flex={1}
88
- sx={{
89
- overflowY: 'scroll',
90
- '&::-webkit-scrollbar': {
91
- width: '12px',
92
- },
93
- '&::-webkit-scrollbar-track': {
94
- backgroundColor: 'rgba(0, 0, 0, 0.2)',
95
- },
96
- '&::-webkit-scrollbar-thumb': {
97
- backgroundColor: 'rgba(255, 255, 255, 0.2)',
98
- borderRadius: '6px',
99
- '&:hover': {
100
- backgroundColor: 'rgba(255, 255, 255, 0.3)',
101
- },
102
- },
103
- }}
104
- >
105
- <IconButton onClick={toMainPage} sx={{ float: 'right', mt: 1, mr: 1 }}>
106
- <HighlightOffIcon/>
107
- </IconButton>
108
- <Container sx={{ pt: 4, pb: 4, px: 3, height: '100%' }} maxWidth='xl'>
109
- <Routes>
110
- <Route path='/namespaces' element={<NamespaceAdmin/>} />
111
- <Route path='/extensions' element={<ExtensionAdmin/>} />
112
- <Route path='/extensions/:namespace/:extension' element={<ExtensionAdmin/>} />
113
- <Route path='/publisher' element={<PublisherAdmin/>} />
114
- <Route path='/scans' element={<ScanAdmin/>} />
115
- <Route path='/tiers' element={<Tiers/>} />
116
- <Route path='/customers' element={<Customers/>} />
117
- <Route path='/usage' element={<UsageStatsView/>} />
118
- <Route path='/usage/:customer' element={<UsageStatsView/>} />
119
- <Route path='/logs' element={<Logs/>} />
120
- <Route path='*' element={<Welcome/>} />
121
- </Routes>
122
- </Container>
123
- </Box>
124
- </>;
217
+ content =
218
+ <Box sx={{ display: 'flex', width: '100%' }}>
219
+ <CssBaseline />
220
+ <AppBar position='fixed' open={drawerOpen} color='default' enableColorOnDark elevation={0}>
221
+ <Toolbar>
222
+ <IconButton
223
+ aria-label='open drawer'
224
+ onClick={() => setDrawerOpen(true)}
225
+ edge='start'
226
+ sx={[{ mr: 2 }, drawerOpen && { display: 'none' }]}
227
+ >
228
+ <MenuIcon />
229
+ </IconButton>
230
+ <Box sx={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
231
+ <BreadcrumbsComponent />
232
+ <IconButton onClick={toMainPage} sx={{ mt: 1, mr: 1 }}>
233
+ <HighlightOffIcon/>
234
+ </IconButton>
235
+ </Box>
236
+ </Toolbar>
237
+ </AppBar>
238
+ <Sidepanel width={drawerWidth} open={drawerOpen} handleDrawerClose={() => setDrawerOpen(false)} >
239
+ {navConfig.map((entry) => {
240
+ if (isNavGroup(entry)) {
241
+ return (
242
+ <NavigationItem
243
+ key={entry.name}
244
+ label={entry.name}
245
+ icon={entry.icon}
246
+ >
247
+ {entry.children.map((child) => (
248
+ <NavigationItem key={child.path} onOpenRoute={handleOpenRoute} active={currentPage?.startsWith(child.path)}
249
+ label={child.name} icon={child.icon} route={child.path}/>
250
+ ))}
251
+ </NavigationItem>
252
+ );
253
+ }
254
+ return (
255
+ <NavigationItem key={entry.path} onOpenRoute={handleOpenRoute} active={currentPage?.startsWith(entry.path)}
256
+ label={entry.name} icon={entry.icon} route={entry.path}/>
257
+ );
258
+ })}
259
+ </Sidepanel>
260
+ <Main open={drawerOpen} >
261
+ <DrawerHeader />
262
+ <Box
263
+ overflow='auto'
264
+ flex={1}
265
+ sx={{
266
+ overflowY: 'scroll',
267
+ '&::-webkit-scrollbar': {
268
+ width: '12px',
269
+ },
270
+ '&::-webkit-scrollbar-track': {
271
+ backgroundColor: 'rgba(0, 0, 0, 0.2)',
272
+ },
273
+ '&::-webkit-scrollbar-thumb': {
274
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
275
+ borderRadius: '6px',
276
+ '&:hover': {
277
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
278
+ },
279
+ },
280
+ }}
281
+ >
282
+ <Container sx={{ pt: 2, pb: 4, px: 3 }} maxWidth='xl'>
283
+ <Routes>
284
+ <Route path='/namespaces' element={<NamespaceAdmin/>} />
285
+ <Route path='/extensions' element={<ExtensionAdmin/>} />
286
+ <Route path='/extensions/:namespace/:extension' element={<ExtensionAdmin/>} />
287
+ <Route path='/publisher' element={<PublisherAdmin/>} />
288
+ <Route path='/publisher/:publisher' element={<PublisherAdmin/>} />
289
+ <Route path='/scans' element={<ScanAdmin/>} />
290
+ <Route path='/tiers' element={<Tiers/>} />
291
+ <Route path='/customers' element={<Customers/>} />
292
+ <Route path='/customers/:customer' element={<CustomerDetails/>} />
293
+ <Route path='/usage' element={<UsageStatsView/>} />
294
+ <Route path='/usage/:customer' element={<UsageStatsView/>} />
295
+ <Route path='/logs' element={<Logs/>} />
296
+ <Route path='*' element={<Welcome/>} />
297
+ </Routes>
298
+ </Container>
299
+ </Box>
300
+ </Main>
301
+ </Box>;
125
302
  } else if (user) {
126
303
  content = <Message message='You are not authorized as administrator.'/>;
127
304
  } else if (!props.userLoading && loginProviders) {
@@ -0,0 +1,27 @@
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 { createRoute } from '../../utils';
15
+
16
+ export namespace AdminDashboardRoutes {
17
+ export const ROOT = 'admin-dashboard';
18
+ export const MAIN = createRoute([ROOT]);
19
+ export const NAMESPACE_ADMIN = createRoute([ROOT, 'namespaces']);
20
+ export const EXTENSION_ADMIN = createRoute([ROOT, 'extensions']);
21
+ export const PUBLISHER_ADMIN = createRoute([ROOT, 'publisher']);
22
+ export const SCANS_ADMIN = createRoute([ROOT, 'scans']);
23
+ export const TIERS = createRoute([ROOT, 'tiers']);
24
+ export const CUSTOMERS = createRoute([ROOT, 'customers']);
25
+ export const USAGE_STATS = createRoute([ROOT, 'usage']);
26
+ export const LOGS = createRoute([ROOT, 'logs']);
27
+ }
@@ -11,39 +11,9 @@
11
11
  * SPDX-License-Identifier: EPL-2.0
12
12
  *****************************************************************************/
13
13
 
14
- import type { SyntheticEvent } from "react";
15
- import { FC } from 'react';
16
- import { Autocomplete, TextField } from '@mui/material';
14
+ import { MultiSelectFilterInput } from "./data-grid-filter";
17
15
  import { GridFilterOperator, GridFilterInputValueProps } from '@mui/x-data-grid';
18
16
 
19
- /**
20
- * Custom multi-select filter input component for DataGrid columns.
21
- * Renders an Autocomplete with multiple selection support.
22
- */
23
- export const MultiSelectFilterInput: FC<GridFilterInputValueProps & { options: string[] }> = ({
24
- item,
25
- applyValue,
26
- options
27
- }) => {
28
- const handleChange = (_event: SyntheticEvent, newValue: string[]) => {
29
- applyValue({ ...item, value: newValue });
30
- };
31
-
32
- return (
33
- <Autocomplete
34
- multiple
35
- size='small'
36
- options={options}
37
- value={(item.value as string[]) || []}
38
- onChange={handleChange}
39
- renderInput={(params) => (
40
- <TextField {...params} variant='standard' placeholder='Filter...' />
41
- )}
42
- sx={{ minWidth: 150, mt: 'auto' }}
43
- />
44
- );
45
- };
46
-
47
17
  /**
48
18
  * Creates filter operators for single-value columns with multi-select capability.
49
19
  * Includes "is any of" and "is none of" operators.
@@ -0,0 +1,45 @@
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 type { SyntheticEvent } from "react";
15
+ import { FC } from 'react';
16
+ import { Autocomplete, TextField } from '@mui/material';
17
+ import { GridFilterInputValueProps } from '@mui/x-data-grid';
18
+
19
+ /**
20
+ * Custom multi-select filter input component for DataGrid columns.
21
+ * Renders an Autocomplete with multiple selection support.
22
+ */
23
+ export const MultiSelectFilterInput: FC<GridFilterInputValueProps & { options: string[] }> = ({
24
+ item,
25
+ applyValue,
26
+ options
27
+ }) => {
28
+ const handleChange = (_event: SyntheticEvent, newValue: string[]) => {
29
+ applyValue({ ...item, value: newValue });
30
+ };
31
+
32
+ return (
33
+ <Autocomplete
34
+ multiple
35
+ size='small'
36
+ options={options}
37
+ value={(item.value as string[]) || []}
38
+ onChange={handleChange}
39
+ renderInput={(params) => (
40
+ <TextField {...params} variant='standard' placeholder='Filter...' />
41
+ )}
42
+ sx={{ minWidth: 150, mt: 'auto' }}
43
+ />
44
+ );
45
+ };
@@ -11,8 +11,8 @@
11
11
  * SPDX-License-Identifier: EPL-2.0
12
12
  *****************************************************************************/
13
13
 
14
+ export { MultiSelectFilterInput } from './data-grid-filter';
14
15
  export {
15
- MultiSelectFilterInput,
16
16
  createMultiSelectFilterOperators,
17
17
  createArrayContainsFilterOperators
18
18
  } from './data-grid-filter-operators';
@@ -0,0 +1,129 @@
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 { FC, useContext, useState, useEffect, useRef, useCallback } from "react";
15
+ import {
16
+ Box,
17
+ Typography,
18
+ Button,
19
+ Alert,
20
+ LinearProgress
21
+ } from "@mui/material";
22
+ import EditIcon from '@mui/icons-material/Edit';
23
+ import { useParams } from 'react-router-dom';
24
+ import { MainContext } from '../../../context';
25
+ import type { Customer } from '../../../extension-registry-types';
26
+ import { handleError } from '../../../utils';
27
+ import { useAdminUsageStats } from '../usage-stats/use-usage-stats';
28
+ import { GeneralDetails, UsageStats } from '../../../components/rate-limiting/customer';
29
+ import { CustomerFormDialog } from './customer-form-dialog';
30
+ import { CustomerMemberList } from './customer-member-list';
31
+
32
+ const CustomerDetailsLoading: FC = () => (
33
+ <Box sx={{ p: 3 }}>
34
+ <LinearProgress color='secondary' sx={{ width: "100%" }} />
35
+ </Box>
36
+ );
37
+
38
+ const CustomerDetailsError: FC<{ message: string }> = ({ message }) => (
39
+ <Box sx={{ p: 3 }}>
40
+ <Alert severity='error'>{message}</Alert>
41
+ </Box>
42
+ );
43
+
44
+ export const CustomerDetails: FC = () => {
45
+ const { customer: customerName } = useParams<{ customer: string }>();
46
+ const abortController = useRef(new AbortController());
47
+ const { service } = useContext(MainContext);
48
+
49
+ const [customer, setCustomer] = useState<Customer | null>(null);
50
+ const [loading, setLoading] = useState(true);
51
+ const [error, setError] = useState<string | null>(null);
52
+ const [formDialogOpen, setFormDialogOpen] = useState(false);
53
+
54
+ const { usageStats, error: statsError, startDate, setStartDate } = useAdminUsageStats(customerName);
55
+
56
+ const loadCustomer = useCallback(async () => {
57
+ if (!customerName) return;
58
+ try {
59
+ setLoading(true);
60
+ setError(null);
61
+ const data = await service.admin.getCustomer(abortController.current, customerName);
62
+ setCustomer(data);
63
+ } catch (err) {
64
+ if ((err as { status?: number })?.status === 404) {
65
+ setError(`Customer "${customerName}" not found.`);
66
+ } else {
67
+ setError(handleError(err as Error));
68
+ }
69
+ } finally {
70
+ setLoading(false);
71
+ }
72
+ }, [service, customerName]);
73
+
74
+ useEffect(() => {
75
+ loadCustomer();
76
+ return () => abortController.current.abort();
77
+ }, [loadCustomer]);
78
+
79
+ const handleFormSubmit = async (updatedCustomer: Customer) => {
80
+ if (customer) {
81
+ await service.admin.updateCustomer(abortController.current, customer.name, updatedCustomer);
82
+ await loadCustomer();
83
+ }
84
+ };
85
+
86
+ if (loading) {
87
+ return <CustomerDetailsLoading />;
88
+ }
89
+
90
+ if (error || statsError) {
91
+ return <CustomerDetailsError message={error ?? statsError ?? ''} />;
92
+ }
93
+
94
+ if (!customer) {
95
+ return null;
96
+ }
97
+
98
+ return (
99
+ <>
100
+ <Box sx={{ p: 2 }}>
101
+ <Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}>
102
+ <Typography variant='h4' component='h1'>
103
+ {customer.name}
104
+ </Typography>
105
+ </Box>
106
+
107
+ <GeneralDetails
108
+ customer={customer}
109
+ headerAction={
110
+ <Button size='small' startIcon={<EditIcon />} onClick={() => setFormDialogOpen(true)}>
111
+ Edit
112
+ </Button>
113
+ }
114
+ />
115
+ <CustomerMemberList
116
+ customer={customer}
117
+ />
118
+ <UsageStats usageStats={usageStats} customer={customer} startDate={startDate} onStartDateChange={setStartDate} />
119
+ </Box>
120
+
121
+ <CustomerFormDialog
122
+ open={formDialogOpen}
123
+ customer={customer}
124
+ onClose={() => setFormDialogOpen(false)}
125
+ onSubmit={handleFormSubmit}
126
+ />
127
+ </>
128
+ );
129
+ };
@@ -31,9 +31,9 @@ import {
31
31
  styled
32
32
  } from '@mui/material';
33
33
  import type { SelectChangeEvent } from '@mui/material';
34
- import { type Customer, EnforcementState, type Tier } from "../../../extension-registry-types";
35
- import { MainContext } from "../../../context";
36
- import { handleError } from "../../../utils";
34
+ import { type Customer, EnforcementState, type Tier } from '../../../extension-registry-types';
35
+ import { MainContext } from '../../../context';
36
+ import { handleError } from '../../../utils';
37
37
 
38
38
  interface CustomerFormDialogProps {
39
39
  open: boolean;
@@ -42,7 +42,6 @@ interface CustomerFormDialogProps {
42
42
  onSubmit: (formData: Customer) => Promise<void>;
43
43
  }
44
44
 
45
-
46
45
  const Code = styled('code')(({ theme }) => ({
47
46
  fontFamily: 'source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace',
48
47
  backgroundColor: theme.palette.action.hover, // Subtle gray background