openvsx-webui-test 0.17.2 → 0.18.0-dev.1

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 (403) hide show
  1. package/lib/components/button-with-progress.d.ts +1 -0
  2. package/lib/components/button-with-progress.d.ts.map +1 -1
  3. package/lib/components/button-with-progress.js +1 -1
  4. package/lib/components/button-with-progress.js.map +1 -1
  5. package/lib/components/sanitized-markdown.d.ts.map +1 -1
  6. package/lib/components/sanitized-markdown.js +79 -1
  7. package/lib/components/sanitized-markdown.js.map +1 -1
  8. package/lib/components/scan-admin/common/auto-refresh.d.ts +21 -0
  9. package/lib/components/scan-admin/common/auto-refresh.d.ts.map +1 -0
  10. package/lib/components/scan-admin/common/auto-refresh.js +45 -0
  11. package/lib/components/scan-admin/common/auto-refresh.js.map +1 -0
  12. package/lib/components/scan-admin/common/conditional-tooltip.d.ts +24 -0
  13. package/lib/components/scan-admin/common/conditional-tooltip.d.ts.map +1 -0
  14. package/lib/components/scan-admin/common/conditional-tooltip.js +63 -0
  15. package/lib/components/scan-admin/common/conditional-tooltip.js.map +1 -0
  16. package/lib/components/scan-admin/common/file-table.d.ts +23 -0
  17. package/lib/components/scan-admin/common/file-table.d.ts.map +1 -0
  18. package/lib/components/scan-admin/common/file-table.js +350 -0
  19. package/lib/components/scan-admin/common/file-table.js.map +1 -0
  20. package/lib/components/scan-admin/common/index.d.ts +18 -0
  21. package/lib/components/scan-admin/common/index.d.ts.map +1 -0
  22. package/lib/components/scan-admin/common/index.js +18 -0
  23. package/lib/components/scan-admin/common/index.js.map +1 -0
  24. package/lib/components/scan-admin/common/tab-panel.d.ts +25 -0
  25. package/lib/components/scan-admin/common/tab-panel.d.ts.map +1 -0
  26. package/lib/components/scan-admin/common/tab-panel.js +22 -0
  27. package/lib/components/scan-admin/common/tab-panel.js.map +1 -0
  28. package/lib/components/scan-admin/common/utils.d.ts +15 -0
  29. package/lib/components/scan-admin/common/utils.d.ts.map +1 -0
  30. package/lib/components/scan-admin/common/utils.js +46 -0
  31. package/lib/components/scan-admin/common/utils.js.map +1 -0
  32. package/lib/components/scan-admin/dialogs/file-dialog.d.ts +19 -0
  33. package/lib/components/scan-admin/dialogs/file-dialog.d.ts.map +1 -0
  34. package/lib/components/scan-admin/dialogs/file-dialog.js +85 -0
  35. package/lib/components/scan-admin/dialogs/file-dialog.js.map +1 -0
  36. package/lib/components/scan-admin/dialogs/index.d.ts +15 -0
  37. package/lib/components/scan-admin/dialogs/index.d.ts.map +1 -0
  38. package/lib/components/scan-admin/dialogs/index.js +15 -0
  39. package/lib/components/scan-admin/dialogs/index.js.map +1 -0
  40. package/lib/components/scan-admin/dialogs/quarantine-dialog.d.ts +23 -0
  41. package/lib/components/scan-admin/dialogs/quarantine-dialog.d.ts.map +1 -0
  42. package/lib/components/scan-admin/dialogs/quarantine-dialog.js +192 -0
  43. package/lib/components/scan-admin/dialogs/quarantine-dialog.js.map +1 -0
  44. package/lib/components/scan-admin/index.d.ts +20 -0
  45. package/lib/components/scan-admin/index.d.ts.map +1 -0
  46. package/lib/components/scan-admin/index.js +25 -0
  47. package/lib/components/scan-admin/index.js.map +1 -0
  48. package/lib/components/scan-admin/scan-card/index.d.ts +20 -0
  49. package/lib/components/scan-admin/scan-card/index.d.ts.map +1 -0
  50. package/lib/components/scan-admin/scan-card/index.js +20 -0
  51. package/lib/components/scan-admin/scan-card/index.js.map +1 -0
  52. package/lib/components/scan-admin/scan-card/scan-card-content.d.ts +30 -0
  53. package/lib/components/scan-admin/scan-card/scan-card-content.d.ts.map +1 -0
  54. package/lib/components/scan-admin/scan-card/scan-card-content.js +232 -0
  55. package/lib/components/scan-admin/scan-card/scan-card-content.js.map +1 -0
  56. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.d.ts +26 -0
  57. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.d.ts.map +1 -0
  58. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.js +121 -0
  59. package/lib/components/scan-admin/scan-card/scan-card-expand-strip-badges.js.map +1 -0
  60. package/lib/components/scan-admin/scan-card/scan-card-expand-strip.d.ts +27 -0
  61. package/lib/components/scan-admin/scan-card/scan-card-expand-strip.d.ts.map +1 -0
  62. package/lib/components/scan-admin/scan-card/scan-card-expand-strip.js +66 -0
  63. package/lib/components/scan-admin/scan-card/scan-card-expand-strip.js.map +1 -0
  64. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.d.ts +26 -0
  65. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.d.ts.map +1 -0
  66. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js +151 -0
  67. package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js.map +1 -0
  68. package/lib/components/scan-admin/scan-card/scan-card-header.d.ts +26 -0
  69. package/lib/components/scan-admin/scan-card/scan-card-header.d.ts.map +1 -0
  70. package/lib/components/scan-admin/scan-card/scan-card-header.js +101 -0
  71. package/lib/components/scan-admin/scan-card/scan-card-header.js.map +1 -0
  72. package/lib/components/scan-admin/scan-card/scan-card.d.ts +34 -0
  73. package/lib/components/scan-admin/scan-card/scan-card.d.ts.map +1 -0
  74. package/lib/components/scan-admin/scan-card/scan-card.js +90 -0
  75. package/lib/components/scan-admin/scan-card/scan-card.js.map +1 -0
  76. package/lib/components/scan-admin/scan-card/scan-detail-card.d.ts +38 -0
  77. package/lib/components/scan-admin/scan-card/scan-detail-card.d.ts.map +1 -0
  78. package/lib/components/scan-admin/scan-card/scan-detail-card.js +72 -0
  79. package/lib/components/scan-admin/scan-card/scan-detail-card.js.map +1 -0
  80. package/lib/components/scan-admin/scan-card/utils.d.ts +48 -0
  81. package/lib/components/scan-admin/scan-card/utils.d.ts.map +1 -0
  82. package/lib/components/scan-admin/scan-card/utils.js +166 -0
  83. package/lib/components/scan-admin/scan-card/utils.js.map +1 -0
  84. package/lib/components/scan-admin/tab-contents/allow-list-tab-content.d.ts +19 -0
  85. package/lib/components/scan-admin/tab-contents/allow-list-tab-content.d.ts.map +1 -0
  86. package/lib/components/scan-admin/tab-contents/allow-list-tab-content.js +55 -0
  87. package/lib/components/scan-admin/tab-contents/allow-list-tab-content.js.map +1 -0
  88. package/lib/components/scan-admin/tab-contents/auto-rejected-tab-content.d.ts +19 -0
  89. package/lib/components/scan-admin/tab-contents/auto-rejected-tab-content.d.ts.map +1 -0
  90. package/lib/components/scan-admin/tab-contents/auto-rejected-tab-content.js +43 -0
  91. package/lib/components/scan-admin/tab-contents/auto-rejected-tab-content.js.map +1 -0
  92. package/lib/components/scan-admin/tab-contents/block-list-tab-content.d.ts +19 -0
  93. package/lib/components/scan-admin/tab-contents/block-list-tab-content.d.ts.map +1 -0
  94. package/lib/components/scan-admin/tab-contents/block-list-tab-content.js +55 -0
  95. package/lib/components/scan-admin/tab-contents/block-list-tab-content.js.map +1 -0
  96. package/lib/components/scan-admin/tab-contents/index.d.ts +18 -0
  97. package/lib/components/scan-admin/tab-contents/index.d.ts.map +1 -0
  98. package/lib/components/scan-admin/tab-contents/index.js +18 -0
  99. package/lib/components/scan-admin/tab-contents/index.js.map +1 -0
  100. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.d.ts +19 -0
  101. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.d.ts.map +1 -0
  102. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.js +78 -0
  103. package/lib/components/scan-admin/tab-contents/quarantined-tab-content.js.map +1 -0
  104. package/lib/components/scan-admin/tab-contents/scans-tab-content.d.ts +19 -0
  105. package/lib/components/scan-admin/tab-contents/scans-tab-content.d.ts.map +1 -0
  106. package/lib/components/scan-admin/tab-contents/scans-tab-content.js +52 -0
  107. package/lib/components/scan-admin/tab-contents/scans-tab-content.js.map +1 -0
  108. package/lib/components/scan-admin/toolbars/counts-toolbar.d.ts +35 -0
  109. package/lib/components/scan-admin/toolbars/counts-toolbar.d.ts.map +1 -0
  110. package/lib/components/scan-admin/toolbars/counts-toolbar.js +132 -0
  111. package/lib/components/scan-admin/toolbars/counts-toolbar.js.map +1 -0
  112. package/lib/components/scan-admin/toolbars/index.d.ts +16 -0
  113. package/lib/components/scan-admin/toolbars/index.d.ts.map +1 -0
  114. package/lib/components/scan-admin/toolbars/index.js +16 -0
  115. package/lib/components/scan-admin/toolbars/index.js.map +1 -0
  116. package/lib/components/scan-admin/toolbars/search-toolbar.d.ts +43 -0
  117. package/lib/components/scan-admin/toolbars/search-toolbar.d.ts.map +1 -0
  118. package/lib/components/scan-admin/toolbars/search-toolbar.js +106 -0
  119. package/lib/components/scan-admin/toolbars/search-toolbar.js.map +1 -0
  120. package/lib/components/scan-admin/toolbars/tab-toolbar.d.ts +25 -0
  121. package/lib/components/scan-admin/toolbars/tab-toolbar.d.ts.map +1 -0
  122. package/lib/components/scan-admin/toolbars/tab-toolbar.js +33 -0
  123. package/lib/components/scan-admin/toolbars/tab-toolbar.js.map +1 -0
  124. package/lib/context/scan-admin/index.d.ts +21 -0
  125. package/lib/context/scan-admin/index.d.ts.map +1 -0
  126. package/lib/context/scan-admin/index.js +27 -0
  127. package/lib/context/scan-admin/index.js.map +1 -0
  128. package/lib/context/scan-admin/scan-actions.d.ts +19 -0
  129. package/lib/context/scan-admin/scan-actions.d.ts.map +1 -0
  130. package/lib/context/scan-admin/scan-actions.js +64 -0
  131. package/lib/context/scan-admin/scan-actions.js.map +1 -0
  132. package/lib/context/scan-admin/scan-api-actions.d.ts +26 -0
  133. package/lib/context/scan-admin/scan-api-actions.d.ts.map +1 -0
  134. package/lib/context/scan-admin/scan-api-actions.js +118 -0
  135. package/lib/context/scan-admin/scan-api-actions.js.map +1 -0
  136. package/lib/context/scan-admin/scan-api-effects.d.ts +40 -0
  137. package/lib/context/scan-admin/scan-api-effects.d.ts.map +1 -0
  138. package/lib/context/scan-admin/scan-api-effects.js +446 -0
  139. package/lib/context/scan-admin/scan-api-effects.js.map +1 -0
  140. package/lib/context/scan-admin/scan-context-types.d.ts +69 -0
  141. package/lib/context/scan-admin/scan-context-types.d.ts.map +1 -0
  142. package/lib/context/scan-admin/scan-context-types.js +14 -0
  143. package/lib/context/scan-admin/scan-context-types.js.map +1 -0
  144. package/lib/context/scan-admin/scan-context.d.ts +17 -0
  145. package/lib/context/scan-admin/scan-context.d.ts.map +1 -0
  146. package/lib/context/scan-admin/scan-context.js +90 -0
  147. package/lib/context/scan-admin/scan-context.js.map +1 -0
  148. package/lib/context/scan-admin/scan-helpers.d.ts +28 -0
  149. package/lib/context/scan-admin/scan-helpers.d.ts.map +1 -0
  150. package/lib/context/scan-admin/scan-helpers.js +56 -0
  151. package/lib/context/scan-admin/scan-helpers.js.map +1 -0
  152. package/lib/context/scan-admin/scan-reducer.d.ts +18 -0
  153. package/lib/context/scan-admin/scan-reducer.d.ts.map +1 -0
  154. package/lib/context/scan-admin/scan-reducer.js +194 -0
  155. package/lib/context/scan-admin/scan-reducer.js.map +1 -0
  156. package/lib/context/scan-admin/scan-types.d.ts +292 -0
  157. package/lib/context/scan-admin/scan-types.d.ts.map +1 -0
  158. package/lib/context/scan-admin/scan-types.js +67 -0
  159. package/lib/context/scan-admin/scan-types.js.map +1 -0
  160. package/lib/default/page-settings.d.ts.map +1 -1
  161. package/lib/default/page-settings.js +3 -0
  162. package/lib/default/page-settings.js.map +1 -1
  163. package/lib/default/theme.d.ts +50 -12
  164. package/lib/default/theme.d.ts.map +1 -1
  165. package/lib/default/theme.js +42 -0
  166. package/lib/default/theme.js.map +1 -1
  167. package/lib/extension-registry-service.d.ts +106 -1
  168. package/lib/extension-registry-service.d.ts.map +1 -1
  169. package/lib/extension-registry-service.js +348 -1
  170. package/lib/extension-registry-service.js.map +1 -1
  171. package/lib/extension-registry-types.d.ts +181 -0
  172. package/lib/extension-registry-types.d.ts.map +1 -1
  173. package/lib/extension-registry-types.js +16 -0
  174. package/lib/extension-registry-types.js.map +1 -1
  175. package/lib/hooks/scan-admin/index.d.ts +34 -0
  176. package/lib/hooks/scan-admin/index.d.ts.map +1 -0
  177. package/lib/hooks/scan-admin/index.js +28 -0
  178. package/lib/hooks/scan-admin/index.js.map +1 -0
  179. package/lib/hooks/scan-admin/use-auto-rejected-tab.d.ts +76 -0
  180. package/lib/hooks/scan-admin/use-auto-rejected-tab.d.ts.map +1 -0
  181. package/lib/hooks/scan-admin/use-auto-rejected-tab.js +79 -0
  182. package/lib/hooks/scan-admin/use-auto-rejected-tab.js.map +1 -0
  183. package/lib/hooks/scan-admin/use-dialogs.d.ts +43 -0
  184. package/lib/hooks/scan-admin/use-dialogs.d.ts.map +1 -0
  185. package/lib/hooks/scan-admin/use-dialogs.js +55 -0
  186. package/lib/hooks/scan-admin/use-dialogs.js.map +1 -0
  187. package/lib/hooks/scan-admin/use-file-list-tab.d.ts +208 -0
  188. package/lib/hooks/scan-admin/use-file-list-tab.d.ts.map +1 -0
  189. package/lib/hooks/scan-admin/use-file-list-tab.js +125 -0
  190. package/lib/hooks/scan-admin/use-file-list-tab.js.map +1 -0
  191. package/lib/hooks/scan-admin/use-pagination.d.ts +36 -0
  192. package/lib/hooks/scan-admin/use-pagination.d.ts.map +1 -0
  193. package/lib/hooks/scan-admin/use-pagination.js +79 -0
  194. package/lib/hooks/scan-admin/use-pagination.js.map +1 -0
  195. package/lib/hooks/scan-admin/use-quarantined-tab.d.ts +92 -0
  196. package/lib/hooks/scan-admin/use-quarantined-tab.d.ts.map +1 -0
  197. package/lib/hooks/scan-admin/use-quarantined-tab.js +125 -0
  198. package/lib/hooks/scan-admin/use-quarantined-tab.js.map +1 -0
  199. package/lib/hooks/scan-admin/use-scan-card-state.d.ts +29 -0
  200. package/lib/hooks/scan-admin/use-scan-card-state.d.ts.map +1 -0
  201. package/lib/hooks/scan-admin/use-scan-card-state.js +50 -0
  202. package/lib/hooks/scan-admin/use-scan-card-state.js.map +1 -0
  203. package/lib/hooks/scan-admin/use-scan-filters.d.ts +53 -0
  204. package/lib/hooks/scan-admin/use-scan-filters.d.ts.map +1 -0
  205. package/lib/hooks/scan-admin/use-scan-filters.js +75 -0
  206. package/lib/hooks/scan-admin/use-scan-filters.js.map +1 -0
  207. package/lib/hooks/scan-admin/use-scans-tab.d.ts +85 -0
  208. package/lib/hooks/scan-admin/use-scans-tab.d.ts.map +1 -0
  209. package/lib/hooks/scan-admin/use-scans-tab.js +87 -0
  210. package/lib/hooks/scan-admin/use-scans-tab.js.map +1 -0
  211. package/lib/hooks/scan-admin/use-search.d.ts +32 -0
  212. package/lib/hooks/scan-admin/use-search.d.ts.map +1 -0
  213. package/lib/hooks/scan-admin/use-search.js +48 -0
  214. package/lib/hooks/scan-admin/use-search.js.map +1 -0
  215. package/lib/hooks/scan-admin/use-tab-navigation.d.ts +96 -0
  216. package/lib/hooks/scan-admin/use-tab-navigation.d.ts.map +1 -0
  217. package/lib/hooks/scan-admin/use-tab-navigation.js +70 -0
  218. package/lib/hooks/scan-admin/use-tab-navigation.js.map +1 -0
  219. package/lib/hooks/scan-admin/use-url-sync.d.ts +22 -0
  220. package/lib/hooks/scan-admin/use-url-sync.d.ts.map +1 -0
  221. package/lib/hooks/scan-admin/use-url-sync.js +252 -0
  222. package/lib/hooks/scan-admin/use-url-sync.js.map +1 -0
  223. package/lib/page-settings.d.ts +4 -0
  224. package/lib/page-settings.d.ts.map +1 -1
  225. package/lib/pages/admin-dashboard/admin-dashboard.d.ts +4 -0
  226. package/lib/pages/admin-dashboard/admin-dashboard.d.ts.map +1 -1
  227. package/lib/pages/admin-dashboard/admin-dashboard.js +55 -5
  228. package/lib/pages/admin-dashboard/admin-dashboard.js.map +1 -1
  229. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.d.ts +28 -0
  230. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.d.ts.map +1 -0
  231. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.js +93 -0
  232. package/lib/pages/admin-dashboard/components/data-grid-filter-operators.js.map +1 -0
  233. package/lib/pages/admin-dashboard/components/index.d.ts +2 -0
  234. package/lib/pages/admin-dashboard/components/index.d.ts.map +1 -0
  235. package/lib/pages/admin-dashboard/components/index.js +14 -0
  236. package/lib/pages/admin-dashboard/components/index.js.map +1 -0
  237. package/lib/pages/admin-dashboard/customers/customer-form-dialog.d.ts +23 -0
  238. package/lib/pages/admin-dashboard/customers/customer-form-dialog.d.ts.map +1 -0
  239. package/lib/pages/admin-dashboard/customers/customer-form-dialog.js +225 -0
  240. package/lib/pages/admin-dashboard/customers/customer-form-dialog.js.map +1 -0
  241. package/lib/pages/admin-dashboard/customers/customers.d.ts +15 -0
  242. package/lib/pages/admin-dashboard/customers/customers.d.ts.map +1 -0
  243. package/lib/pages/admin-dashboard/customers/customers.js +175 -0
  244. package/lib/pages/admin-dashboard/customers/customers.js.map +1 -0
  245. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.d.ts +23 -0
  246. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.d.ts.map +1 -0
  247. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.js +64 -0
  248. package/lib/pages/admin-dashboard/customers/delete-customer-dialog.js.map +1 -0
  249. package/lib/pages/admin-dashboard/publisher-admin.js +5 -5
  250. package/lib/pages/admin-dashboard/publisher-admin.js.map +1 -1
  251. package/lib/pages/admin-dashboard/publisher-revoke-dialog.d.ts.map +1 -1
  252. package/lib/pages/admin-dashboard/publisher-revoke-dialog.js +1 -1
  253. package/lib/pages/admin-dashboard/publisher-revoke-dialog.js.map +1 -1
  254. package/lib/pages/admin-dashboard/scan-admin.d.ts +20 -0
  255. package/lib/pages/admin-dashboard/scan-admin.d.ts.map +1 -0
  256. package/lib/pages/admin-dashboard/scan-admin.js +66 -0
  257. package/lib/pages/admin-dashboard/scan-admin.js.map +1 -0
  258. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.d.ts +23 -0
  259. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.d.ts.map +1 -0
  260. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.js +55 -0
  261. package/lib/pages/admin-dashboard/tiers/delete-tier-dialog.js.map +1 -0
  262. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.d.ts +23 -0
  263. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.d.ts.map +1 -0
  264. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.js +215 -0
  265. package/lib/pages/admin-dashboard/tiers/tier-form-dialog.js.map +1 -0
  266. package/lib/pages/admin-dashboard/tiers/tiers.d.ts +15 -0
  267. package/lib/pages/admin-dashboard/tiers/tiers.d.ts.map +1 -0
  268. package/lib/pages/admin-dashboard/tiers/tiers.js +174 -0
  269. package/lib/pages/admin-dashboard/tiers/tiers.js.map +1 -0
  270. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.d.ts +23 -0
  271. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.d.ts.map +1 -0
  272. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.js +106 -0
  273. package/lib/pages/admin-dashboard/usage-stats/usage-stats-chart.js.map +1 -0
  274. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.d.ts +26 -0
  275. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.d.ts.map +1 -0
  276. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.js +50 -0
  277. package/lib/pages/admin-dashboard/usage-stats/usage-stats-search.js.map +1 -0
  278. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.d.ts +14 -0
  279. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.d.ts.map +1 -0
  280. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.js +16 -0
  281. package/lib/pages/admin-dashboard/usage-stats/usage-stats-utils.js.map +1 -0
  282. package/lib/pages/admin-dashboard/usage-stats/usage-stats.d.ts +15 -0
  283. package/lib/pages/admin-dashboard/usage-stats/usage-stats.d.ts.map +1 -0
  284. package/lib/pages/admin-dashboard/usage-stats/usage-stats.js +103 -0
  285. package/lib/pages/admin-dashboard/usage-stats/usage-stats.js.map +1 -0
  286. package/lib/pages/admin-dashboard/welcome.d.ts.map +1 -1
  287. package/lib/pages/admin-dashboard/welcome.js +5 -1
  288. package/lib/pages/admin-dashboard/welcome.js.map +1 -1
  289. package/lib/pages/extension-detail/extension-detail-overview.d.ts.map +1 -1
  290. package/lib/pages/extension-detail/extension-detail-overview.js +9 -1
  291. package/lib/pages/extension-detail/extension-detail-overview.js.map +1 -1
  292. package/lib/pages/extension-detail/extension-detail-reviews.d.ts.map +1 -1
  293. package/lib/pages/extension-detail/extension-detail-reviews.js +67 -18
  294. package/lib/pages/extension-detail/extension-detail-reviews.js.map +1 -1
  295. package/lib/pages/extension-detail/extension-detail.js +2 -2
  296. package/lib/pages/extension-detail/extension-detail.js.map +1 -1
  297. package/lib/pages/extension-detail/extension-rating-stars.d.ts +2 -2
  298. package/lib/pages/extension-detail/extension-rating-stars.d.ts.map +1 -1
  299. package/lib/pages/extension-detail/extension-rating-stars.js +1 -1
  300. package/lib/pages/extension-detail/extension-rating-stars.js.map +1 -1
  301. package/lib/pages/extension-list/extension-list-item.js +2 -2
  302. package/lib/pages/extension-list/extension-list-item.js.map +1 -1
  303. package/lib/pages/user/user-namespace-extension-list-item.d.ts.map +1 -1
  304. package/lib/pages/user/user-namespace-extension-list-item.js +23 -9
  305. package/lib/pages/user/user-namespace-extension-list-item.js.map +1 -1
  306. package/lib/pages/user/user-publisher-agreement.d.ts.map +1 -1
  307. package/lib/pages/user/user-publisher-agreement.js +34 -13
  308. package/lib/pages/user/user-publisher-agreement.js.map +1 -1
  309. package/lib/pages/user/user-settings-profile.d.ts.map +1 -1
  310. package/lib/pages/user/user-settings-profile.js +10 -5
  311. package/lib/pages/user/user-settings-profile.js.map +1 -1
  312. package/lib/pages/user/user-settings-tokens.d.ts.map +1 -1
  313. package/lib/pages/user/user-settings-tokens.js +13 -5
  314. package/lib/pages/user/user-settings-tokens.js.map +1 -1
  315. package/lib/server-request.d.ts +1 -1
  316. package/lib/server-request.d.ts.map +1 -1
  317. package/lib/server-request.js +3 -3
  318. package/lib/server-request.js.map +1 -1
  319. package/package.json +17 -9
  320. package/src/components/button-with-progress.tsx +2 -1
  321. package/src/components/sanitized-markdown.tsx +81 -1
  322. package/src/components/scan-admin/common/auto-refresh.tsx +79 -0
  323. package/src/components/scan-admin/common/conditional-tooltip.tsx +74 -0
  324. package/src/components/scan-admin/common/file-table.tsx +508 -0
  325. package/src/components/scan-admin/common/index.ts +18 -0
  326. package/src/components/scan-admin/common/tab-panel.tsx +42 -0
  327. package/src/components/scan-admin/common/utils.ts +48 -0
  328. package/src/components/scan-admin/dialogs/file-dialog.tsx +137 -0
  329. package/src/components/scan-admin/dialogs/index.ts +15 -0
  330. package/src/components/scan-admin/dialogs/quarantine-dialog.tsx +270 -0
  331. package/src/components/scan-admin/index.ts +52 -0
  332. package/src/components/scan-admin/scan-card/index.ts +20 -0
  333. package/src/components/scan-admin/scan-card/scan-card-content.tsx +457 -0
  334. package/src/components/scan-admin/scan-card/scan-card-expand-strip-badges.tsx +186 -0
  335. package/src/components/scan-admin/scan-card/scan-card-expand-strip.tsx +104 -0
  336. package/src/components/scan-admin/scan-card/scan-card-expanded-content.tsx +262 -0
  337. package/src/components/scan-admin/scan-card/scan-card-header.tsx +176 -0
  338. package/src/components/scan-admin/scan-card/scan-card.tsx +152 -0
  339. package/src/components/scan-admin/scan-card/scan-detail-card.tsx +144 -0
  340. package/src/components/scan-admin/scan-card/utils.ts +199 -0
  341. package/src/components/scan-admin/tab-contents/allow-list-tab-content.tsx +119 -0
  342. package/src/components/scan-admin/tab-contents/auto-rejected-tab-content.tsx +106 -0
  343. package/src/components/scan-admin/tab-contents/block-list-tab-content.tsx +119 -0
  344. package/src/components/scan-admin/tab-contents/index.ts +18 -0
  345. package/src/components/scan-admin/tab-contents/quarantined-tab-content.tsx +158 -0
  346. package/src/components/scan-admin/tab-contents/scans-tab-content.tsx +113 -0
  347. package/src/components/scan-admin/toolbars/counts-toolbar.tsx +262 -0
  348. package/src/components/scan-admin/toolbars/index.ts +16 -0
  349. package/src/components/scan-admin/toolbars/search-toolbar.tsx +255 -0
  350. package/src/components/scan-admin/toolbars/tab-toolbar.tsx +56 -0
  351. package/src/context/scan-admin/index.ts +43 -0
  352. package/src/context/scan-admin/scan-actions.ts +87 -0
  353. package/src/context/scan-admin/scan-api-actions.ts +137 -0
  354. package/src/context/scan-admin/scan-api-effects.ts +491 -0
  355. package/src/context/scan-admin/scan-context-types.ts +102 -0
  356. package/src/context/scan-admin/scan-context.tsx +123 -0
  357. package/src/context/scan-admin/scan-helpers.ts +63 -0
  358. package/src/context/scan-admin/scan-reducer.ts +321 -0
  359. package/src/context/scan-admin/scan-types.ts +337 -0
  360. package/src/default/page-settings.tsx +3 -0
  361. package/src/default/theme.tsx +102 -13
  362. package/src/extension-registry-service.ts +372 -1
  363. package/src/extension-registry-types.ts +207 -0
  364. package/src/hooks/scan-admin/index.ts +48 -0
  365. package/src/hooks/scan-admin/use-auto-rejected-tab.ts +85 -0
  366. package/src/hooks/scan-admin/use-dialogs.ts +83 -0
  367. package/src/hooks/scan-admin/use-file-list-tab.ts +149 -0
  368. package/src/hooks/scan-admin/use-pagination.ts +90 -0
  369. package/src/hooks/scan-admin/use-quarantined-tab.ts +138 -0
  370. package/src/hooks/scan-admin/use-scan-card-state.ts +73 -0
  371. package/src/hooks/scan-admin/use-scan-filters.ts +83 -0
  372. package/src/hooks/scan-admin/use-scans-tab.ts +92 -0
  373. package/src/hooks/scan-admin/use-search.ts +54 -0
  374. package/src/hooks/scan-admin/use-tab-navigation.ts +82 -0
  375. package/src/hooks/scan-admin/use-url-sync.ts +293 -0
  376. package/src/page-settings.ts +4 -0
  377. package/src/pages/admin-dashboard/admin-dashboard.tsx +71 -4
  378. package/src/pages/admin-dashboard/components/data-grid-filter-operators.tsx +126 -0
  379. package/src/pages/admin-dashboard/components/index.ts +18 -0
  380. package/src/pages/admin-dashboard/customers/customer-form-dialog.tsx +348 -0
  381. package/src/pages/admin-dashboard/customers/customers.tsx +279 -0
  382. package/src/pages/admin-dashboard/customers/delete-customer-dialog.tsx +94 -0
  383. package/src/pages/admin-dashboard/publisher-admin.tsx +5 -5
  384. package/src/pages/admin-dashboard/publisher-revoke-dialog.tsx +2 -1
  385. package/src/pages/admin-dashboard/scan-admin.tsx +109 -0
  386. package/src/pages/admin-dashboard/tiers/delete-tier-dialog.tsx +83 -0
  387. package/src/pages/admin-dashboard/tiers/tier-form-dialog.tsx +372 -0
  388. package/src/pages/admin-dashboard/tiers/tiers.tsx +254 -0
  389. package/src/pages/admin-dashboard/usage-stats/usage-stats-chart.tsx +189 -0
  390. package/src/pages/admin-dashboard/usage-stats/usage-stats-search.tsx +83 -0
  391. package/src/pages/admin-dashboard/usage-stats/usage-stats-utils.ts +16 -0
  392. package/src/pages/admin-dashboard/usage-stats/usage-stats.tsx +127 -0
  393. package/src/pages/admin-dashboard/welcome.tsx +4 -0
  394. package/src/pages/extension-detail/extension-detail-overview.tsx +16 -2
  395. package/src/pages/extension-detail/extension-detail-reviews.tsx +116 -30
  396. package/src/pages/extension-detail/extension-detail.tsx +2 -2
  397. package/src/pages/extension-detail/extension-rating-stars.tsx +2 -2
  398. package/src/pages/extension-list/extension-list-item.tsx +2 -2
  399. package/src/pages/user/user-namespace-extension-list-item.tsx +38 -13
  400. package/src/pages/user/user-publisher-agreement.tsx +30 -11
  401. package/src/pages/user/user-settings-profile.tsx +10 -6
  402. package/src/pages/user/user-settings-tokens.tsx +15 -6
  403. package/src/server-request.ts +3 -3
@@ -0,0 +1,189 @@
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 React, { FC, useMemo } from "react";
15
+ import {
16
+ Box,
17
+ Paper,
18
+ Typography,
19
+ Alert,
20
+ Stack
21
+ } from "@mui/material";
22
+ import { BarPlot } from "@mui/x-charts/BarChart";
23
+ import { DatePicker } from "@mui/x-date-pickers/DatePicker";
24
+ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
25
+ import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
26
+ import type { Customer, UsageStats } from "../../../extension-registry-types";
27
+ import { addDays, format, startOfDay } from "date-fns";
28
+ import {
29
+ ChartsReferenceLine,
30
+ ChartsTooltip,
31
+ ChartsXAxis,
32
+ ChartsYAxis,
33
+ ResponsiveChartContainer
34
+ } from "@mui/x-charts";
35
+
36
+ interface UsageStatsChartProps {
37
+ usageStats: readonly UsageStats[];
38
+ customer: Customer | null;
39
+ startDate: Date;
40
+ onStartDateChange: (date: Date) => void;
41
+ }
42
+
43
+ export const UsageStatsChart: FC<UsageStatsChartProps> = ({
44
+ usageStats,
45
+ customer,
46
+ startDate,
47
+ onStartDateChange
48
+ }) => {
49
+ const dayStart = startOfDay(startDate).getTime() / 1000;
50
+ const dayEnd = startOfDay(addDays(startDate, 1)).getTime() / 1000;
51
+
52
+ // we have 5min steps
53
+ const step = 5 * 60;
54
+ const tierCapacity =
55
+ customer?.tier !== undefined ? customer.tier.capacity * step / customer.tier.duration : 0;
56
+
57
+ const data: UsageStats[] = useMemo(
58
+ () => {
59
+ const arr: UsageStats[] = [];
60
+
61
+ for (let idx = dayStart; idx < dayEnd; idx += step) {
62
+ arr.push({
63
+ windowStart: idx,
64
+ duration: step,
65
+ count: 0
66
+ });
67
+ }
68
+
69
+ for (const stat of usageStats) {
70
+ const idx = (stat.windowStart - dayStart) / step;
71
+ arr[idx].count = stat.count;
72
+ }
73
+ return arr;
74
+ }, [usageStats]
75
+ );
76
+
77
+ const maxDataValue: number = useMemo(
78
+ () => {
79
+ if (usageStats.length === 0) {
80
+ return 0;
81
+ } else {
82
+ return Math.max(...usageStats.map(v => v.count));
83
+ }
84
+ }, [usageStats]
85
+ );
86
+
87
+ const totalRequests = useMemo(
88
+ () => usageStats.reduce((sum, d) => sum + d.count, 0),
89
+ [usageStats]
90
+ );
91
+
92
+ return (
93
+ <LocalizationProvider dateAdapter={AdapterDateFns}>
94
+ <Paper sx={{ p: 2, mb: 3 }}>
95
+ <Typography variant='subtitle2' gutterBottom color='text.secondary'>
96
+ Filters
97
+ </Typography>
98
+ <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} alignItems='center'>
99
+ <DatePicker
100
+ label='Start Date'
101
+ value={startDate}
102
+ onChange={onStartDateChange}
103
+ slotProps={{ textField: { size: 'small' } }}
104
+ />
105
+ </Stack>
106
+ </Paper>
107
+
108
+ {usageStats.length === 0 ?
109
+ <Alert severity='info'>No usage data available for this customer.</Alert>
110
+ :
111
+ <>
112
+ <Paper sx={{ p: 2 }}>
113
+ <ResponsiveChartContainer
114
+ series={[{
115
+ type: 'bar',
116
+ data: data.map(d => d.count),
117
+ label: 'Request Count',
118
+ color: 'lightgray',
119
+ }]}
120
+
121
+ height={400}
122
+ margin={{ top: 10 }}
123
+ xAxis={[
124
+ {
125
+ id: 'date',
126
+ data: data.map((value) => new Date(value.windowStart * 1000)),
127
+ scaleType: 'band',
128
+ valueFormatter: (value) => format(new Date(value), 'HH:mm'),
129
+ },
130
+ ]}
131
+ yAxis={[
132
+ {
133
+ id: 'requests',
134
+ scaleType: 'linear',
135
+ min: 0,
136
+ max: Math.max(tierCapacity, maxDataValue) + 10
137
+ },
138
+ ]}
139
+ >
140
+ <BarPlot />
141
+
142
+ {tierCapacity > 0 &&
143
+ <ChartsReferenceLine
144
+ y={tierCapacity}
145
+ label='Tier Limit'
146
+ labelAlign='end'
147
+ lineStyle={{
148
+ strokeDasharray: '10 5',
149
+ strokeWidth: 2,
150
+ stroke: '#a83244',
151
+ }}
152
+ />
153
+ }
154
+
155
+ <ChartsXAxis
156
+ label='Time'
157
+ position='bottom'
158
+ axisId='date'
159
+ tickInterval={(value, index) => {
160
+ return new Date(value).getMinutes() === 0;
161
+ }}
162
+ tickLabelInterval={(value, index) => {
163
+ return new Date(value).getMinutes() === 0;
164
+ }}
165
+ tickLabelStyle={{
166
+ fontSize: 10,
167
+ }}
168
+ />
169
+ <ChartsYAxis
170
+ label='Requests'
171
+ position='left'
172
+ axisId='requests'
173
+ tickLabelStyle={{ fontSize: 10 }}
174
+ />
175
+ <ChartsTooltip />
176
+ </ResponsiveChartContainer>
177
+ </Paper>
178
+
179
+ <Box mt={2}>
180
+ <Typography variant='body2' color='text.secondary'>
181
+ Total requests in selected range: {totalRequests.toLocaleString()}
182
+ {usageStats.length > 0 && <> ({usageStats.length} data points)</>}
183
+ </Typography>
184
+ </Box>
185
+ </>
186
+ }
187
+ </LocalizationProvider>
188
+ );
189
+ };
@@ -0,0 +1,83 @@
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 React, { FC } from "react";
15
+ import { Paper, Autocomplete, InputBase, IconButton } from "@mui/material";
16
+ import SearchIcon from '@mui/icons-material/Search';
17
+ import type { Customer } from "../../../extension-registry-types";
18
+
19
+ interface CustomerSearchProps {
20
+ customers: Customer[];
21
+ selectedCustomer: Customer | null;
22
+ loading: boolean;
23
+ onCustomerChange: (_: unknown, value: Customer | null) => void;
24
+ pageSettings?: { themeType?: string };
25
+ }
26
+
27
+ export const CustomerSearch: FC<CustomerSearchProps> = ({
28
+ customers,
29
+ selectedCustomer,
30
+ loading,
31
+ onCustomerChange,
32
+ pageSettings
33
+ }) => {
34
+ const searchIconColor = pageSettings?.themeType === 'dark' ? '#111111' : '#ffffff';
35
+
36
+ return (
37
+ <Autocomplete
38
+ key='customer-search'
39
+ options={customers}
40
+ getOptionLabel={(option) => option.name}
41
+ value={selectedCustomer}
42
+ onChange={onCustomerChange}
43
+ loading={loading}
44
+ renderInput={(params) => {
45
+ const { ref, color, size, ...inputProps } = params.inputProps;
46
+ return (
47
+ <Paper
48
+ ref={params.InputProps.ref}
49
+ elevation={3}
50
+ sx={{
51
+ flex: 2,
52
+ display: 'flex',
53
+ mr: { xs: 0, sm: 0, md: 1, lg: 1, xl: 1 },
54
+ mb: { xs: 2, sm: 2, md: 0, lg: 0, xl: 0 },
55
+ }}
56
+ >
57
+ <InputBase
58
+ inputRef={ref}
59
+ {...inputProps}
60
+ autoFocus
61
+ sx={{ flex: 1, pl: 1 }}
62
+ placeholder='Search Customer'
63
+ />
64
+ <IconButton
65
+ color='primary'
66
+ sx={{
67
+ bgcolor: 'secondary.main',
68
+ borderRadius: '0 4px 4px 0',
69
+ padding: 1,
70
+ transition: 'all 0s',
71
+ '&:hover': {
72
+ filter: 'invert(100%)',
73
+ }
74
+ }}
75
+ >
76
+ <SearchIcon sx={{ color: searchIconColor }} />
77
+ </IconButton>
78
+ </Paper>
79
+ );
80
+ }}
81
+ />
82
+ );
83
+ };
@@ -0,0 +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
+
14
+ export const getDefaultStartDate = () => {
15
+ return new Date();
16
+ };
@@ -0,0 +1,127 @@
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 React, { FC, useState, useEffect, useRef, useMemo, useCallback } from "react";
15
+ import { Box, Alert } from "@mui/material";
16
+ import { useParams, useNavigate } from "react-router-dom";
17
+ import { MainContext } from "../../../context";
18
+ import type { UsageStats, Customer } from "../../../extension-registry-types";
19
+ import { handleError } from "../../../utils";
20
+ import { AdminDashboardRoutes } from "../admin-dashboard";
21
+ import { SearchListContainer } from "../search-list-container";
22
+ import { CustomerSearch } from "./usage-stats-search";
23
+ import { UsageStatsChart } from "./usage-stats-chart";
24
+ import { getDefaultStartDate } from "./usage-stats-utils";
25
+
26
+ export const UsageStatsView: FC = () => {
27
+ const { customer } = useParams<{ customer: string }>();
28
+ const navigate = useNavigate();
29
+ const abortController = useRef(new AbortController());
30
+ const { service, pageSettings } = React.useContext(MainContext);
31
+
32
+ const [customers, setCustomers] = useState<Customer[]>([]);
33
+ const [customersLoading, setCustomersLoading] = useState(true);
34
+ const [usageStats, setUsageStats] = useState<readonly UsageStats[]>([]);
35
+ const [loading, setLoading] = useState(false);
36
+ const [error, setError] = useState<string | null>(null);
37
+ const [startDate, setStartDate] = useState<Date>(getDefaultStartDate);
38
+
39
+ // Load customers for autocomplete
40
+ useEffect(() => {
41
+ const loadCustomers = async () => {
42
+ try {
43
+ setCustomersLoading(true);
44
+ const data = await service.admin.getCustomers(abortController.current);
45
+ setCustomers(data.customers);
46
+ } catch (err) {
47
+ setError(handleError(err as Error));
48
+ } finally {
49
+ setCustomersLoading(false);
50
+ }
51
+ };
52
+ loadCustomers();
53
+ return () => abortController.current.abort();
54
+ }, [service]);
55
+
56
+ const selectedCustomer = useMemo(
57
+ () => customers.find(c => c.name === customer) || null,
58
+ [customers, customer]
59
+ );
60
+
61
+ const handleCustomerChange = (_: unknown, value: Customer | null) => {
62
+ if (value) {
63
+ navigate(`${AdminDashboardRoutes.USAGE_STATS}/${value.name}`);
64
+ } else {
65
+ navigate(AdminDashboardRoutes.USAGE_STATS);
66
+ }
67
+ };
68
+
69
+ const loadUsageStats = useCallback(async () => {
70
+ if (!customer) {
71
+ setUsageStats([]);
72
+ setLoading(false);
73
+ return;
74
+ }
75
+
76
+ try {
77
+ setLoading(true);
78
+ setError(null);
79
+ const data = await service.admin.getUsageStats(
80
+ abortController.current,
81
+ customer,
82
+ startDate
83
+ );
84
+ setUsageStats(data.stats);
85
+ } catch (err) {
86
+ setError(handleError(err as Error));
87
+ } finally {
88
+ setLoading(false);
89
+ }
90
+ }, [service, customer, startDate]);
91
+
92
+ useEffect(() => {
93
+ if (customer) {
94
+ loadUsageStats();
95
+ }
96
+ }, [loadUsageStats, customer]);
97
+
98
+ if (error) {
99
+ return <Alert severity='error'>{error}</Alert>;
100
+ }
101
+
102
+ return (
103
+ <Box>
104
+ <SearchListContainer
105
+ searchContainer={[
106
+ <CustomerSearch
107
+ key='customer-search'
108
+ customers={customers}
109
+ selectedCustomer={selectedCustomer}
110
+ loading={customersLoading}
111
+ onCustomerChange={handleCustomerChange}
112
+ pageSettings={pageSettings}
113
+ />
114
+ ]}
115
+ listContainer={!customer && <Alert severity='info'>Select a customer to view usage statistics.</Alert>}
116
+ loading={loading || customersLoading}
117
+ />
118
+ {customer && (
119
+ <UsageStatsChart
120
+ usageStats={usageStats}
121
+ customer={selectedCustomer}
122
+ startDate={startDate}
123
+ onStartDateChange={setStartDate}
124
+ />)}
125
+ </Box>
126
+ );
127
+ };
@@ -27,6 +27,10 @@ export const Welcome: FunctionComponent = props => {
27
27
  <WelcomeLinkItem route={AdminDashboardRoutes.NAMESPACE_ADMIN} label='Namespaces' description='Manage user roles, create new namespaces' />
28
28
  <WelcomeLinkItem route={AdminDashboardRoutes.EXTENSION_ADMIN} label='Extensions' description='Search for extensions and remove certain versions' />
29
29
  <WelcomeLinkItem route={AdminDashboardRoutes.PUBLISHER_ADMIN} label='Publishers' description='Search for publishers and revoke their contributions' />
30
+ <WelcomeLinkItem route={AdminDashboardRoutes.SCANS_ADMIN} label='Scans' description='View security scan results and manage quarantined extensions' />
31
+ <WelcomeLinkItem route={AdminDashboardRoutes.TIERS} label='Tiers' description='Manage rate-limit tiers' />
32
+ <WelcomeLinkItem route={AdminDashboardRoutes.CUSTOMERS} label='Customers' description='Manage rate-limit customers' />
33
+ <WelcomeLinkItem route={AdminDashboardRoutes.USAGE_STATS} label='Usage Stats' description='Show usage stats for customers' />
30
34
  </Grid>
31
35
  </Paper>
32
36
  </Grid>
@@ -141,6 +141,13 @@ export const ExtensionDetailOverview: FunctionComponent<ExtensionDetailOverviewP
141
141
  </>;
142
142
  };
143
143
 
144
+ const renderIdentifierSection = (): ReactNode => {
145
+ return <>
146
+ <Typography variant='h6'>Unique Identifier</Typography>
147
+ <Typography variant='body2'><code>{`${extension.namespace}.${extension.name}`}</code></Typography>
148
+ </>;
149
+ };
150
+
144
151
  const renderAliasesSection = (otherAliases: string[], sx: SxProps<Theme>): ReactNode => {
145
152
  const { extension } = props;
146
153
  const aliasButtons = otherAliases.length ?
@@ -321,6 +328,13 @@ export const ExtensionDetailOverview: FunctionComponent<ExtensionDetailOverviewP
321
328
  (otherAliases.length || extension.versionAlias.length) ? <Box>{renderAliasesSection(otherAliases, tagButton)}</Box> : ''
322
329
  }
323
330
  </Box>
331
+
332
+ <Box sx={resourcesGroup}>
333
+ <Box>
334
+ {renderIdentifierSection()}
335
+ </Box>
336
+ </Box>
337
+
324
338
  <Box sx={resourcesGroup}>
325
339
  {
326
340
  extension.categories && extension.categories.length > 0 ?
@@ -331,7 +345,7 @@ export const ExtensionDetailOverview: FunctionComponent<ExtensionDetailOverviewP
331
345
  }
332
346
  {
333
347
  tags && tags.length > 0 ?
334
- <Box mt={2}>
348
+ <Box mt={extension.categories && extension.categories.length > 0 ? 2 : 0}>
335
349
  {renderButtonList('search', 'Tags', tags, tagButton)}
336
350
  </Box>
337
351
  : null
@@ -392,4 +406,4 @@ export const ExtensionDetailOverview: FunctionComponent<ExtensionDetailOverviewP
392
406
  export interface ExtensionDetailOverviewProps {
393
407
  extension: Extension;
394
408
  selectVersion: (version: string) => void;
395
- }
409
+ }
@@ -9,7 +9,17 @@
9
9
  ********************************************************************************/
10
10
 
11
11
  import React, { Fragment, FunctionComponent, ReactNode, useContext, useState, useEffect, useRef } from 'react';
12
- import { Box, Typography, Divider, Link } from '@mui/material';
12
+ import {
13
+ Box,
14
+ Typography,
15
+ Divider,
16
+ Link,
17
+ Dialog,
18
+ DialogTitle,
19
+ DialogContent,
20
+ DialogContentText,
21
+ DialogActions, Button
22
+ } from '@mui/material';
13
23
  import { MainContext } from '../../context';
14
24
  import { toLocalTime } from '../../utils';
15
25
  import { ExtensionReview, Extension, ExtensionReviewList, isEqualUser, isError, UserData } from '../../extension-registry-types';
@@ -17,16 +27,30 @@ import { TextDivider } from '../../components/text-divider';
17
27
  import { DelayedLoadIndicator } from '../../components/delayed-load-indicator';
18
28
  import { ButtonWithProgress } from '../../components/button-with-progress';
19
29
  import { Timestamp } from '../../components/timestamp';
20
- import { ExportRatingStars } from './extension-rating-stars';
30
+ import { ExtensionRatingStars } from './extension-rating-stars';
21
31
  import { ExtensionReviewDialog } from './extension-review-dialog';
22
32
 
23
33
  export const ExtensionDetailReviews: FunctionComponent<ExtensionDetailReviewsProps> = props => {
24
34
  const [reviewList, setReviewList] = useState<ExtensionReviewList>();
25
35
  const [loading, setLoading] = useState<boolean>(true);
26
36
  const [revoked, setRevoked] = useState<boolean>(false);
37
+ const [removeDialogOpen, setRemoveDialogOpen] = useState(false);
38
+ const [removeReviewSet, setRemoveReviewSet] = useState(new Set<string>());
27
39
  const context = useContext(MainContext);
28
40
  const abortController = useRef<AbortController>(new AbortController());
29
41
 
42
+ const addRemoveReviewRequest = (loginName: string) => {
43
+ const newSet = new Set<string>(removeReviewSet);
44
+ newSet.add(loginName);
45
+ setRemoveReviewSet(newSet);
46
+ };
47
+
48
+ const deleteRemoveReviewRequest = (loginName: string) => {
49
+ const newSet = new Set<string>(removeReviewSet);
50
+ newSet.delete(loginName);
51
+ setRemoveReviewSet(newSet);
52
+ };
53
+
30
54
  useEffect(() => {
31
55
  updateReviews();
32
56
  return () => abortController.current.abort();
@@ -87,6 +111,58 @@ export const ExtensionDetailReviews: FunctionComponent<ExtensionDetailReviewsPro
87
111
  }
88
112
  };
89
113
 
114
+ const handleAdminRemoveReviewButton = async (r: ExtensionReview) => {
115
+ addRemoveReviewRequest(r.user.loginName);
116
+ try {
117
+ const result = await context.service.deleteUserReview(abortController.current, props.extension, r.user);
118
+ if (isError(result)) {
119
+ throw result;
120
+ }
121
+ saveCompleted();
122
+ } catch (err) {
123
+ context.handleError(err);
124
+ } finally {
125
+ deleteRemoveReviewRequest(r.user.loginName);
126
+ }
127
+ };
128
+
129
+ const renderAdminRemoveButton = (r: ExtensionReview): ReactNode => {
130
+ return <>
131
+ <Button
132
+ variant='contained'
133
+ color='error'
134
+ onClick={() => setRemoveDialogOpen(true)} >
135
+ Remove review
136
+ </Button>
137
+ <Dialog
138
+ open={removeDialogOpen}
139
+ onClose={() => setRemoveDialogOpen(false)}>
140
+ <DialogTitle>Remove Review</DialogTitle>
141
+ <DialogContent>
142
+ <DialogContentText component='div'>
143
+ <Typography>Confirm removal of review comment from <code>{r.user.loginName}</code>?</Typography>
144
+ </DialogContentText>
145
+ </DialogContent>
146
+ <DialogActions>
147
+ <Button
148
+ variant='contained'
149
+ color='primary'
150
+ onClick={() => setRemoveDialogOpen(false)} >
151
+ Cancel
152
+ </Button>
153
+ <ButtonWithProgress
154
+ autoFocus
155
+ color='error'
156
+ sx={{ ml: 1 }}
157
+ working={removeReviewSet.has(r.user.loginName)}
158
+ onClick={() => handleAdminRemoveReviewButton(r)} >
159
+ Remove review
160
+ </ButtonWithProgress>
161
+ </DialogActions>
162
+ </Dialog>
163
+ </>;
164
+ };
165
+
90
166
  const renderReviewList = (list?: ExtensionReviewList): ReactNode => {
91
167
  if (!list) {
92
168
  return '';
@@ -101,37 +177,47 @@ export const ExtensionDetailReviews: FunctionComponent<ExtensionDetailReviewsPro
101
177
 
102
178
  const renderReview = (r: ExtensionReview): ReactNode => {
103
179
  return <Fragment key={r.user.loginName + r.timestamp}>
104
- <Box my={2}>
105
- <Box display='flex'>
106
- {
107
- r.timestamp ?
108
- <>
109
- <Typography variant='body2'><Timestamp value={r.timestamp}/></Typography>
110
- <TextDivider />
111
- </>
112
- : null
113
- }
114
- <Typography variant='body2'>
180
+ <Box display='flex' justifyContent='space-between'>
181
+ <Box my={2}>
182
+ <Box display='flex'>
115
183
  {
116
- r.user.homepage ?
117
- <Link
118
- href={r.user.homepage}
119
- color='text.primary'
120
- underline='hover'
121
- >
122
- {r.user.loginName}
123
- </Link>
124
- :
125
- r.user.loginName
184
+ r.timestamp ?
185
+ <>
186
+ <Typography variant='body2'><Timestamp value={r.timestamp}/></Typography>
187
+ <TextDivider />
188
+ </>
189
+ : null
126
190
  }
127
- </Typography>
128
- </Box>
129
- <Box display='flex' alignItems='center'>
130
- <ExportRatingStars number={r.rating} />
131
- </Box>
132
- <Box overflow='auto'>
133
- <Typography variant='body1' sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.comment}</Typography>
191
+ <Typography variant='body2'>
192
+ {
193
+ r.user.homepage ?
194
+ <Link
195
+ href={r.user.homepage}
196
+ color='text.primary'
197
+ underline='hover'
198
+ >
199
+ {r.user.loginName}
200
+ </Link>
201
+ :
202
+ r.user.loginName
203
+ }
204
+ </Typography>
205
+ </Box>
206
+ <Box display='flex' alignItems='center'>
207
+ <ExtensionRatingStars number={r.rating} />
208
+ </Box>
209
+ <Box overflow='auto'>
210
+ <Typography variant='body1' sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.comment}</Typography>
211
+ </Box>
134
212
  </Box>
213
+ {
214
+ context.user?.role === 'admin' ?
215
+ <Box mb={2} display='flex' alignItems='end'>
216
+ {renderAdminRemoveButton(r)}
217
+ </Box>
218
+ :
219
+ null
220
+ }
135
221
  </Box>
136
222
  <Divider />
137
223
  </Fragment>;
@@ -24,7 +24,7 @@ import { DelayedLoadIndicator } from '../../components/delayed-load-indicator';
24
24
  import { HoverPopover } from '../../components/hover-popover';
25
25
  import { Extension, UserData, isError } from '../../extension-registry-types';
26
26
  import { TextDivider } from '../../components/text-divider';
27
- import { ExportRatingStars } from './extension-rating-stars';
27
+ import { ExtensionRatingStars } from './extension-rating-stars';
28
28
  import { NamespaceDetailRoutes } from '../namespace-detail/namespace-detail';
29
29
  import { ExtensionDetailOverview } from './extension-detail-overview';
30
30
  import { ExtensionDetailChanges } from './extension-detail-changes';
@@ -399,7 +399,7 @@ export const ExtensionDetail: FunctionComponent = () => {
399
399
  `Average rating: ${getRoundedRating(extension.averageRating)} out of 5 (${extension.reviewCount} reviews)`
400
400
  : 'Not rated yet'
401
401
  }>
402
- <ExportRatingStars number={extension.averageRating ?? 0} fontSize='small' />
402
+ <ExtensionRatingStars number={extension.averageRating ?? 0} fontSize='small' />
403
403
  ({reviewCountFormatted})
404
404
  </StyledLink>
405
405
  </Box>