openvsx-webui-test 0.20.1-rc.0 → 0.20.2-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.
- package/lib/components/scan-admin/scan-card/scan-card-expanded-content.d.ts.map +1 -1
- package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js +28 -4
- package/lib/components/scan-admin/scan-card/scan-card-expanded-content.js.map +1 -1
- package/lib/components/sidepanel/navigation-item.d.ts +0 -1
- package/lib/components/sidepanel/navigation-item.d.ts.map +1 -1
- package/lib/components/sidepanel/navigation-item.js +22 -8
- package/lib/components/sidepanel/navigation-item.js.map +1 -1
- package/lib/components/sidepanel/sidebar-context.d.ts +16 -0
- package/lib/components/sidepanel/sidebar-context.d.ts.map +1 -0
- package/lib/components/sidepanel/sidebar-context.js +15 -0
- package/lib/components/sidepanel/sidebar-context.js.map +1 -0
- package/lib/components/sidepanel/sidepanel.d.ts +4 -4
- package/lib/components/sidepanel/sidepanel.d.ts.map +1 -1
- package/lib/components/sidepanel/sidepanel.js +47 -10
- package/lib/components/sidepanel/sidepanel.js.map +1 -1
- package/lib/context/scan-admin/scan-api-effects.d.ts.map +1 -1
- package/lib/context/scan-admin/scan-api-effects.js +1 -0
- package/lib/context/scan-admin/scan-api-effects.js.map +1 -1
- package/lib/context/scan-admin/scan-types.d.ts +2 -0
- package/lib/context/scan-admin/scan-types.d.ts.map +1 -1
- package/lib/context/scan-admin/scan-types.js.map +1 -1
- package/lib/extension-registry-service.d.ts +6 -0
- package/lib/extension-registry-service.d.ts.map +1 -1
- package/lib/extension-registry-service.js +17 -0
- package/lib/extension-registry-service.js.map +1 -1
- package/lib/hooks/use-local-storage.d.ts +23 -0
- package/lib/hooks/use-local-storage.d.ts.map +1 -0
- package/lib/hooks/use-local-storage.js +62 -0
- package/lib/hooks/use-local-storage.js.map +1 -0
- package/lib/pages/admin-dashboard/admin-dashboard.d.ts.map +1 -1
- package/lib/pages/admin-dashboard/admin-dashboard.js +39 -95
- package/lib/pages/admin-dashboard/admin-dashboard.js.map +1 -1
- package/lib/pages/admin-dashboard/admin-header.d.ts +19 -0
- package/lib/pages/admin-dashboard/admin-header.d.ts.map +1 -0
- package/lib/pages/admin-dashboard/admin-header.js +16 -0
- package/lib/pages/admin-dashboard/admin-header.js.map +1 -0
- package/lib/pages/admin-dashboard/admin-sidepanel.d.ts +19 -0
- package/lib/pages/admin-dashboard/admin-sidepanel.d.ts.map +1 -0
- package/lib/pages/admin-dashboard/admin-sidepanel.js +17 -0
- package/lib/pages/admin-dashboard/admin-sidepanel.js.map +1 -0
- package/lib/pages/admin-dashboard/namespace-admin.d.ts.map +1 -1
- package/lib/pages/admin-dashboard/namespace-admin.js +4 -1
- package/lib/pages/admin-dashboard/namespace-admin.js.map +1 -1
- package/lib/pages/admin-dashboard/namespace-change-dialog.d.ts.map +1 -1
- package/lib/pages/admin-dashboard/namespace-change-dialog.js +6 -1
- package/lib/pages/admin-dashboard/namespace-change-dialog.js.map +1 -1
- package/lib/pages/admin-dashboard/namespace-delete-dialog.d.ts +23 -0
- package/lib/pages/admin-dashboard/namespace-delete-dialog.d.ts.map +1 -0
- package/lib/pages/admin-dashboard/namespace-delete-dialog.js +53 -0
- package/lib/pages/admin-dashboard/namespace-delete-dialog.js.map +1 -0
- package/lib/pages/admin-dashboard/nav-types.d.ts +27 -0
- package/lib/pages/admin-dashboard/nav-types.d.ts.map +1 -0
- package/lib/pages/admin-dashboard/nav-types.js +14 -0
- package/lib/pages/admin-dashboard/nav-types.js.map +1 -0
- package/lib/pages/admin-dashboard/scan-admin.d.ts.map +1 -1
- package/lib/pages/admin-dashboard/scan-admin.js +1 -4
- package/lib/pages/admin-dashboard/scan-admin.js.map +1 -1
- package/lib/pages/admin-dashboard/welcome.d.ts +5 -1
- package/lib/pages/admin-dashboard/welcome.d.ts.map +1 -1
- package/lib/pages/admin-dashboard/welcome.js +18 -16
- package/lib/pages/admin-dashboard/welcome.js.map +1 -1
- package/lib/pages/user/user-namespace-details.d.ts.map +1 -1
- package/lib/pages/user/user-namespace-details.js +2 -3
- package/lib/pages/user/user-namespace-details.js.map +1 -1
- package/lib/pages/user/user-setting-tabs.d.ts.map +1 -1
- package/lib/pages/user/user-setting-tabs.js +1 -1
- package/lib/pages/user/user-setting-tabs.js.map +1 -1
- package/lib/pages/user/user-settings-namespace-detail.d.ts +1 -0
- package/lib/pages/user/user-settings-namespace-detail.d.ts.map +1 -1
- package/lib/pages/user/user-settings-namespace-detail.js +18 -2
- package/lib/pages/user/user-settings-namespace-detail.js.map +1 -1
- package/lib/pages/user/user-settings-namespaces.js.map +1 -1
- package/package.json +2 -4
- package/src/components/scan-admin/scan-card/scan-card-expanded-content.tsx +50 -5
- package/src/components/sidepanel/navigation-item.tsx +79 -23
- package/src/components/sidepanel/sidebar-context.tsx +17 -0
- package/src/components/sidepanel/sidepanel.tsx +57 -29
- package/src/context/scan-admin/scan-api-effects.ts +1 -0
- package/src/context/scan-admin/scan-types.ts +2 -0
- package/src/extension-registry-service.ts +18 -0
- package/src/hooks/use-local-storage.ts +67 -0
- package/src/pages/admin-dashboard/admin-dashboard.tsx +48 -197
- package/src/pages/admin-dashboard/admin-header.tsx +59 -0
- package/src/pages/admin-dashboard/admin-sidepanel.tsx +59 -0
- package/src/pages/admin-dashboard/namespace-admin.tsx +5 -0
- package/src/pages/admin-dashboard/namespace-change-dialog.tsx +55 -46
- package/src/pages/admin-dashboard/namespace-delete-dialog.tsx +89 -0
- package/src/pages/admin-dashboard/nav-types.ts +31 -0
- package/src/pages/admin-dashboard/scan-admin.tsx +1 -4
- package/src/pages/admin-dashboard/welcome.tsx +80 -48
- package/src/pages/user/user-namespace-details.tsx +4 -5
- package/src/pages/user/user-setting-tabs.tsx +3 -2
- package/src/pages/user/user-settings-namespace-detail.tsx +37 -4
- package/src/pages/user/user-settings-namespaces.tsx +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-settings-namespaces.js","sourceRoot":"","sources":["../../../src/pages/user/user-settings-namespaces.tsx"],"names":[],"mappings":";AAAA;;;;;;;;kFAQkF;AAElF,OAAO,EAAqB,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAa,MAAM,OAAO,CAAC;AAC9F,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAQlE,MAAM,cAAc,GAAG,CAAC,KAAwB,EAAE,EAAE;IAChD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,OAAO,KAAC,IAAI,IACR,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EAClD,KAAK,EAAE,KAAK,CAAC,eAAe,EAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EACjD,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EAC9C,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EACzC,cAAc,EAAC,WAAW,EAC1B,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,YAGxE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;YAC7B,OAAO,KAAC,GAAG,IACP,EAAE,EAAE;oBACA,IAAI,EAAE;wBACF,SAAS,EAAE,MAAM;qBACpB;oBACD,OAAO,EAAE;wBACL,aAAa,EAAE,MAAM;qBACxB;iBACJ,EAED,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,CAAC,IAAI,IAFhB,QAAQ,GAAG,SAAS,CAAC,IAAI,CAGhC,CAAC;QACP,CAAC,CAAC,GAEH,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAsB,GAAG,EAAE;IAE1D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAmB,EAAE,CAAC,CAAC;IACnE,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,EAAa,CAAC;IACpE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAC7E,MAAM,eAAe,GAAG,MAAM,CAAkB,IAAI,eAAe,EAAE,CAAC,CAAC;IAEvE,SAAS,CAAC,GAAG,EAAE;QACX,cAAc,EAAE,CAAC;QACjB,OAAO,GAAG,EAAE;YACR,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACpC,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,qBAAqB,GAAG,CAAC,KAAgB,EAAQ,EAAE;QACrD,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC;IAEF,MAAM,uBAAuB,GAAG,KAAK,EAAC,eAA0B,EAAiB,EAAE;QAC/E,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,KAAK,IAAkB,EAAE;QAC5C,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACxE,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACtE,aAAa,CAAC,UAAU,CAAC,CAAC;YAC1B,kBAAkB,CAAC,eAAe,CAAC,CAAC;YACpC,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,WAAW,CAAC,GAAG,CAAC,CAAC;YACjB,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,GAAG,EAAE;QAChC,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,cAAc,EAAE,CAAC;IACrB,CAAC,CAAC;IAEF,IAAI,kBAAkB,GAAc,IAAI,CAAC;IACzC,MAAM,kBAAkB,GAAG,YAAY,CAAC,IAAI,CAAC,mBAAmB,CAAC;IACjE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,EAAE,CAAC;QAC3C,kBAAkB,GAAG,MAAC,GAAG,IACrB,EAAE,EAAE;gBACA,OAAO,EAAE,MAAM;gBACf,KAAK,EAAE,MAAM;gBACb,aAAa,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE;gBACjF,UAAU,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE;aACvF,aAED,KAAC,cAAc,IACX,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,qBAAqB,GACjC,EACF,KAAC,eAAe,IACZ,SAAS,EAAE,eAAe,EAC1B,eAAe,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAC1D,WAAW,EAAE,CAAC,SAAmB,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,EAAE,QAAQ,IAAI,SAAS,CAAC,SAAS,KAAK,IAAI,EAAE,SAAS,EACtH,OAAO,EAAE,IAAI,EACb,kBAAkB,EAAE,kBAAkB,EACtC,KAAK,EAAE,YAAY,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"user-settings-namespaces.js","sourceRoot":"","sources":["../../../src/pages/user/user-settings-namespaces.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openvsx-webui-test",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.2-dev.1",
|
|
4
4
|
"description": "User interface for Eclipse Open VSX",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"node": ">=22.0.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@babel/core": "^7.29.0",
|
|
43
42
|
"@emotion/react": "^11.11.1",
|
|
44
43
|
"@emotion/styled": "^11.11.0",
|
|
45
44
|
"@mdit/plugin-alert": "^0.22.3",
|
|
@@ -61,7 +60,7 @@
|
|
|
61
60
|
"prop-types": "^15.8.1",
|
|
62
61
|
"punycode": "^2.3.0",
|
|
63
62
|
"react": "^18.2.0",
|
|
64
|
-
"react-avatar-editor": "^
|
|
63
|
+
"react-avatar-editor": "^15.0.0",
|
|
65
64
|
"react-dom": "^18.2.0",
|
|
66
65
|
"react-dropzone": "^14.2.3",
|
|
67
66
|
"react-helmet-async": "^2.0.5",
|
|
@@ -91,7 +90,6 @@
|
|
|
91
90
|
"@types/prop-types": "^15.7.0",
|
|
92
91
|
"@types/punycode": "^2.1.0",
|
|
93
92
|
"@types/react": "^18.2.0",
|
|
94
|
-
"@types/react-avatar-editor": "^13.0.0",
|
|
95
93
|
"@types/react-dom": "^18.2.0",
|
|
96
94
|
"@types/react-infinite-scroller": "^1.2.0",
|
|
97
95
|
"@types/react-router-dom": "^5.3.0",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
********************************************************************************/
|
|
13
13
|
|
|
14
14
|
import { FC } from 'react';
|
|
15
|
-
import { Box, Typography, Collapse, Chip } from '@mui/material';
|
|
15
|
+
import { Box, Typography, Collapse, Chip, Link } from '@mui/material';
|
|
16
|
+
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
16
17
|
import { useTheme, Theme } from '@mui/material/styles';
|
|
17
18
|
import { ScanResult, Threat, ValidationFailure, CheckResult } from '../../../context/scan-admin';
|
|
18
19
|
import { ScanDetailCard } from './scan-detail-card';
|
|
@@ -127,17 +128,22 @@ const CheckResultItem: FC<CheckResultItemProps> = ({ checkResult }) => {
|
|
|
127
128
|
// Non-required errors get striped styling to indicate they didn't block publishing
|
|
128
129
|
const isOptionalError = isError && checkResult.required === false;
|
|
129
130
|
|
|
131
|
+
// Scanner rows often carry long verdict text while publish checks just show
|
|
132
|
+
// short statuses like "No issues found"
|
|
133
|
+
const isScannerJob = checkResult.category === 'SCANNER_JOB';
|
|
134
|
+
const showSummaryInMiddle = isScannerJob && !!checkResult.summary;
|
|
135
|
+
|
|
130
136
|
return (
|
|
131
137
|
<Box sx={{
|
|
132
138
|
display: 'flex',
|
|
133
139
|
alignItems: 'center',
|
|
134
|
-
|
|
140
|
+
gap: 2,
|
|
135
141
|
p: 1.5,
|
|
136
142
|
borderRadius: 1,
|
|
137
143
|
bgcolor: isPassed ? 'action.hover' : 'transparent',
|
|
138
144
|
border: isPassed ? 'none' : `1px solid ${theme.palette.divider}`,
|
|
139
145
|
}}>
|
|
140
|
-
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
|
146
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, flexShrink: 0 }}>
|
|
141
147
|
<Chip
|
|
142
148
|
label={checkResult.result}
|
|
143
149
|
size='small'
|
|
@@ -162,12 +168,51 @@ const CheckResultItem: FC<CheckResultItemProps> = ({ checkResult }) => {
|
|
|
162
168
|
sx={{ fontSize: '0.65rem', height: 18 }}
|
|
163
169
|
/>
|
|
164
170
|
</Box>
|
|
165
|
-
|
|
166
|
-
|
|
171
|
+
{showSummaryInMiddle && (
|
|
172
|
+
<Typography
|
|
173
|
+
variant='caption'
|
|
174
|
+
sx={{
|
|
175
|
+
flex: 1,
|
|
176
|
+
minWidth: 0,
|
|
177
|
+
lineHeight: 1.5,
|
|
178
|
+
color: 'text.secondary',
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
{checkResult.summary}
|
|
182
|
+
</Typography>
|
|
183
|
+
)}
|
|
184
|
+
<Box sx={{
|
|
185
|
+
display: 'flex',
|
|
186
|
+
alignItems: 'center',
|
|
187
|
+
gap: 2,
|
|
188
|
+
ml: 'auto',
|
|
189
|
+
color: 'text.secondary',
|
|
190
|
+
flexShrink: 0,
|
|
191
|
+
}}>
|
|
192
|
+
{!showSummaryInMiddle && checkResult.summary && (
|
|
167
193
|
<Typography variant='caption'>
|
|
168
194
|
{checkResult.summary}
|
|
169
195
|
</Typography>
|
|
170
196
|
)}
|
|
197
|
+
{checkResult.externalUrl && (
|
|
198
|
+
<Link
|
|
199
|
+
href={checkResult.externalUrl}
|
|
200
|
+
target='_blank'
|
|
201
|
+
rel='noopener noreferrer'
|
|
202
|
+
onClick={(e) => e.stopPropagation()}
|
|
203
|
+
sx={{
|
|
204
|
+
display: 'inline-flex',
|
|
205
|
+
alignItems: 'center',
|
|
206
|
+
gap: 0.25,
|
|
207
|
+
fontSize: '0.7rem',
|
|
208
|
+
fontWeight: 500,
|
|
209
|
+
whiteSpace: 'nowrap',
|
|
210
|
+
}}
|
|
211
|
+
>
|
|
212
|
+
View in scanner
|
|
213
|
+
<OpenInNewIcon sx={{ fontSize: '0.85rem' }} />
|
|
214
|
+
</Link>
|
|
215
|
+
)}
|
|
171
216
|
{checkResult.durationMs !== null && (
|
|
172
217
|
<Typography variant='caption' sx={{ minWidth: 50, textAlign: 'right' }}>
|
|
173
218
|
{formatDuration(checkResult.durationMs)}
|
|
@@ -8,42 +8,99 @@
|
|
|
8
8
|
* SPDX-License-Identifier: EPL-2.0
|
|
9
9
|
********************************************************************************/
|
|
10
10
|
|
|
11
|
-
import { FunctionComponent, PropsWithChildren, ReactNode, useState } from 'react';
|
|
12
|
-
import {
|
|
11
|
+
import { FunctionComponent, PropsWithChildren, ReactNode, useContext, useRef, useState } from 'react';
|
|
12
|
+
import {
|
|
13
|
+
Collapse, List, ListItemButton, ListItemIcon, ListItemText,
|
|
14
|
+
Popover, Tooltip,
|
|
15
|
+
} from '@mui/material';
|
|
13
16
|
import ExpandLess from '@mui/icons-material/ExpandLess';
|
|
14
17
|
import ExpandMore from '@mui/icons-material/ExpandMore';
|
|
15
18
|
import { useNavigate } from 'react-router';
|
|
19
|
+
import { SidebarContext } from './sidebar-context';
|
|
20
|
+
|
|
21
|
+
const EXPANDED_CONTEXT = { collapsed: false };
|
|
16
22
|
|
|
17
23
|
export const NavigationItem: FunctionComponent<PropsWithChildren<NavigationProps>> = props => {
|
|
18
|
-
const [
|
|
24
|
+
const [groupExpanded, setGroupExpanded] = useState(false);
|
|
25
|
+
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
26
|
+
const anchorRef = useRef<HTMLDivElement>(null);
|
|
27
|
+
const { collapsed } = useContext(SidebarContext);
|
|
19
28
|
const navigate = useNavigate();
|
|
20
29
|
|
|
30
|
+
const isGroup = !!props.children;
|
|
31
|
+
|
|
21
32
|
const handleClick = () => {
|
|
22
|
-
if (
|
|
23
|
-
|
|
33
|
+
if (isGroup) {
|
|
34
|
+
if (collapsed) {
|
|
35
|
+
setPopoverOpen(true);
|
|
36
|
+
} else {
|
|
37
|
+
setGroupExpanded(prev => !prev);
|
|
38
|
+
}
|
|
24
39
|
} else if (props.route) {
|
|
25
|
-
props.onOpenRoute?.call(this, props.route);
|
|
26
40
|
navigate(props.route);
|
|
27
41
|
}
|
|
28
42
|
};
|
|
29
43
|
|
|
30
|
-
|
|
31
|
-
<ListItemButton
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
const button = (
|
|
45
|
+
<ListItemButton
|
|
46
|
+
ref={anchorRef}
|
|
47
|
+
selected={props.active}
|
|
48
|
+
onClick={handleClick}
|
|
49
|
+
sx={{
|
|
50
|
+
minHeight: 48,
|
|
51
|
+
px: 2.5,
|
|
52
|
+
justifyContent: collapsed ? 'center' : 'initial',
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
{props.icon && (
|
|
56
|
+
<ListItemIcon sx={{ minWidth: 0, mr: collapsed ? 'auto' : 3, justifyContent: 'center' }}>
|
|
57
|
+
{props.icon}
|
|
58
|
+
</ListItemIcon>
|
|
59
|
+
)}
|
|
60
|
+
{!collapsed && <ListItemText primary={props.label} />}
|
|
61
|
+
{!collapsed && isGroup && (groupExpanded ? <ExpandLess /> : <ExpandMore />)}
|
|
37
62
|
</ListItemButton>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
{collapsed ? (
|
|
68
|
+
<Tooltip title={props.label} placement='right'>
|
|
69
|
+
{button}
|
|
70
|
+
</Tooltip>
|
|
71
|
+
) : (
|
|
72
|
+
button
|
|
73
|
+
)}
|
|
74
|
+
|
|
75
|
+
{/* Inline expand for groups when sidebar is open */}
|
|
76
|
+
{!collapsed && isGroup && (
|
|
77
|
+
<Collapse in={groupExpanded} timeout='auto' unmountOnExit>
|
|
78
|
+
<List sx={{ pl: 2 }} disablePadding>
|
|
79
|
+
{props.children}
|
|
80
|
+
</List>
|
|
81
|
+
</Collapse>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
{/* Floating popover for groups when sidebar is collapsed */}
|
|
85
|
+
{isGroup && (
|
|
86
|
+
<Popover
|
|
87
|
+
open={popoverOpen}
|
|
88
|
+
anchorEl={anchorRef.current}
|
|
89
|
+
onClose={() => setPopoverOpen(false)}
|
|
90
|
+
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
|
91
|
+
transformOrigin={{ vertical: 'top', horizontal: 'left' }}
|
|
92
|
+
disableRestoreFocus
|
|
93
|
+
elevation={2}
|
|
94
|
+
>
|
|
95
|
+
<SidebarContext.Provider value={EXPANDED_CONTEXT}>
|
|
96
|
+
<List disablePadding onClick={() => setPopoverOpen(false)}>
|
|
97
|
+
{props.children}
|
|
98
|
+
</List>
|
|
99
|
+
</SidebarContext.Provider>
|
|
100
|
+
</Popover>
|
|
101
|
+
)}
|
|
102
|
+
</>
|
|
103
|
+
);
|
|
47
104
|
};
|
|
48
105
|
|
|
49
106
|
export interface NavigationProps {
|
|
@@ -51,5 +108,4 @@ export interface NavigationProps {
|
|
|
51
108
|
icon?: ReactNode;
|
|
52
109
|
label: string;
|
|
53
110
|
active?: boolean;
|
|
54
|
-
onOpenRoute?: (route: string) => void;
|
|
55
111
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
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 { createContext } from 'react';
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
export const SidebarContext = createContext<{ collapsed: boolean; }>({ collapsed: false });
|
|
@@ -8,43 +8,71 @@
|
|
|
8
8
|
* SPDX-License-Identifier: EPL-2.0
|
|
9
9
|
********************************************************************************/
|
|
10
10
|
|
|
11
|
-
import { FunctionComponent, PropsWithChildren } from 'react';
|
|
11
|
+
import { FunctionComponent, PropsWithChildren, useMemo } from 'react';
|
|
12
12
|
import { Divider, Drawer, IconButton, List } from '@mui/material';
|
|
13
|
+
import { styled, Theme, CSSObject } from '@mui/material/styles';
|
|
13
14
|
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
|
15
|
+
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
14
16
|
import { DrawerHeader } from './drawer-header';
|
|
17
|
+
import { SidebarContext } from './sidebar-context';
|
|
15
18
|
|
|
16
|
-
export const
|
|
17
|
-
|
|
19
|
+
export const DRAWER_WIDTH = 240;
|
|
20
|
+
export const COLLAPSED_WIDTH = 57;
|
|
18
21
|
|
|
22
|
+
const openedMixin = (theme: Theme): CSSObject => ({
|
|
23
|
+
width: DRAWER_WIDTH,
|
|
24
|
+
transition: theme.transitions.create('width', {
|
|
25
|
+
easing: theme.transitions.easing.sharp,
|
|
26
|
+
duration: theme.transitions.duration.enteringScreen,
|
|
27
|
+
}),
|
|
28
|
+
overflowX: 'hidden',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const closedMixin = (theme: Theme): CSSObject => ({
|
|
32
|
+
width: COLLAPSED_WIDTH,
|
|
33
|
+
transition: theme.transitions.create('width', {
|
|
34
|
+
easing: theme.transitions.easing.sharp,
|
|
35
|
+
duration: theme.transitions.duration.leavingScreen,
|
|
36
|
+
}),
|
|
37
|
+
overflowX: 'hidden',
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const StyledDrawer = styled(Drawer, { shouldForwardProp: (prop) => prop !== 'open' })(
|
|
41
|
+
({ theme, open }) => ({
|
|
42
|
+
width: DRAWER_WIDTH,
|
|
43
|
+
flexShrink: 0,
|
|
44
|
+
whiteSpace: 'nowrap',
|
|
45
|
+
boxSizing: 'border-box',
|
|
46
|
+
...(open ? {
|
|
47
|
+
...openedMixin(theme),
|
|
48
|
+
'& .MuiDrawer-paper': openedMixin(theme),
|
|
49
|
+
} : {
|
|
50
|
+
...closedMixin(theme),
|
|
51
|
+
'& .MuiDrawer-paper': closedMixin(theme),
|
|
52
|
+
}),
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const Sidepanel: FunctionComponent<PropsWithChildren<SidepanelProps>> = ({ open, onToggle, children }) => {
|
|
57
|
+
const contextValue = useMemo(() => ({ collapsed: !open }), [open]);
|
|
19
58
|
return (
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
>
|
|
33
|
-
<DrawerHeader>
|
|
34
|
-
<IconButton onClick={props.handleDrawerClose}>
|
|
35
|
-
<ChevronLeftIcon />
|
|
36
|
-
</IconButton>
|
|
37
|
-
</DrawerHeader>
|
|
38
|
-
<Divider />
|
|
39
|
-
<List>
|
|
40
|
-
{props.children}
|
|
41
|
-
</List>
|
|
42
|
-
</Drawer>
|
|
59
|
+
<SidebarContext.Provider value={contextValue}>
|
|
60
|
+
<StyledDrawer variant='permanent' anchor='left' open={open}>
|
|
61
|
+
<DrawerHeader>
|
|
62
|
+
<IconButton onClick={onToggle} aria-label={open ? 'collapse sidebar' : 'expand sidebar'}>
|
|
63
|
+
{open ? <ChevronLeftIcon /> : <ChevronRightIcon />}
|
|
64
|
+
</IconButton>
|
|
65
|
+
</DrawerHeader>
|
|
66
|
+
<Divider />
|
|
67
|
+
<List disablePadding>
|
|
68
|
+
{children}
|
|
69
|
+
</List>
|
|
70
|
+
</StyledDrawer>
|
|
71
|
+
</SidebarContext.Provider>
|
|
43
72
|
);
|
|
44
73
|
};
|
|
45
74
|
|
|
46
|
-
interface SidepanelProps {
|
|
47
|
-
width: number;
|
|
75
|
+
export interface SidepanelProps {
|
|
48
76
|
open: boolean;
|
|
49
|
-
|
|
77
|
+
onToggle: () => void;
|
|
50
78
|
}
|
|
@@ -211,6 +211,7 @@ export const useScansEffect = (
|
|
|
211
211
|
summary: result.summary || null,
|
|
212
212
|
errorMessage: result.errorMessage || null,
|
|
213
213
|
required: result.required ?? null,
|
|
214
|
+
externalUrl: result.externalUrl || null,
|
|
214
215
|
})),
|
|
215
216
|
extensionIcon: scan.extensionIcon,
|
|
216
217
|
downloadUrl: scan.downloadUrl || null,
|
|
@@ -58,6 +58,8 @@ export interface CheckResult {
|
|
|
58
58
|
errorMessage: string | null;
|
|
59
59
|
/** Whether this check was required (errors block publishing). Null for scanner jobs. */
|
|
60
60
|
required: boolean | null;
|
|
61
|
+
/** Deep link to the external scanner's dashboard for this job. Null if not applicable. */
|
|
62
|
+
externalUrl: string | null;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
export interface ScanResult {
|
|
@@ -504,6 +504,7 @@ export interface AdminService {
|
|
|
504
504
|
deleteExtensions(abortController: AbortController, req: { namespace: string, extension: string, targetPlatformVersions?: object[] }): Promise<Readonly<SuccessResult | ErrorResult>>
|
|
505
505
|
getNamespace(abortController: AbortController, name: string): Promise<Readonly<Namespace>>
|
|
506
506
|
createNamespace(abortController: AbortController, namespace: { name: string }): Promise<Readonly<SuccessResult | ErrorResult>>
|
|
507
|
+
deleteNamespace(abortController: AbortController, namespace: { name: string }): Promise<Readonly<SuccessResult | ErrorResult>>
|
|
507
508
|
changeNamespace(abortController: AbortController, req: {oldNamespace: string, newNamespace: string, removeOldNamespace: boolean, mergeIfNewNamespaceAlreadyExists: boolean}): Promise<Readonly<SuccessResult | ErrorResult>>
|
|
508
509
|
getPublisherInfo(abortController: AbortController, provider: string, login: string): Promise<Readonly<PublisherInfo>>
|
|
509
510
|
revokePublisherContributions(abortController: AbortController, provider: string, login: string): Promise<Readonly<SuccessResult | ErrorResult>>
|
|
@@ -601,6 +602,23 @@ export class AdminServiceImpl implements AdminService {
|
|
|
601
602
|
});
|
|
602
603
|
}
|
|
603
604
|
|
|
605
|
+
async deleteNamespace(abortController: AbortController, namespace: { name: string }): Promise<Readonly<SuccessResult | ErrorResult>> {
|
|
606
|
+
const csrfResponse = await this.registry.getCsrfToken(abortController);
|
|
607
|
+
const headers: Record<string, string> = {
|
|
608
|
+
'Content-Type': 'application/json;charset=UTF-8'
|
|
609
|
+
};
|
|
610
|
+
if (!isError(csrfResponse)) {
|
|
611
|
+
const csrfToken = csrfResponse as CsrfTokenJson;
|
|
612
|
+
headers[csrfToken.header] = csrfToken.value;
|
|
613
|
+
}
|
|
614
|
+
return sendRequest({
|
|
615
|
+
abortController,
|
|
616
|
+
credentials: true,
|
|
617
|
+
endpoint: createAbsoluteURL([this.registry.serverUrl, 'admin', 'namespace', namespace.name]),
|
|
618
|
+
method: 'DELETE',
|
|
619
|
+
headers
|
|
620
|
+
});
|
|
621
|
+
}
|
|
604
622
|
async changeNamespace(abortController: AbortController, req: {oldNamespace: string, newNamespace: string, removeOldNamespace: boolean, mergeIfNewNamespaceAlreadyExists: boolean}): Promise<Readonly<SuccessResult | ErrorResult>> {
|
|
605
623
|
const csrfResponse = await this.registry.getCsrfToken(abortController);
|
|
606
624
|
const headers: Record<string, string> = {
|
|
@@ -0,0 +1,67 @@
|
|
|
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 { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Reads a value from localStorage and deserializes it.
|
|
18
|
+
* Returns `fallback` when the key is missing or the stored value cannot be parsed.
|
|
19
|
+
*/
|
|
20
|
+
function readStorage<T>(key: string, fallback: T): T {
|
|
21
|
+
try {
|
|
22
|
+
const raw = localStorage.getItem(key);
|
|
23
|
+
return raw === null ? fallback : (JSON.parse(raw) as T);
|
|
24
|
+
} catch {
|
|
25
|
+
return fallback;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A useState-compatible hook that persists its value in localStorage.
|
|
31
|
+
*
|
|
32
|
+
* - Initialises from localStorage (falling back to `initialValue`).
|
|
33
|
+
* - Keeps multiple tabs in sync by listening to the `storage` event.
|
|
34
|
+
* - The setter accepts both a direct value and an updater function, matching
|
|
35
|
+
* the full useState API.
|
|
36
|
+
*/
|
|
37
|
+
export function useLocalStorage<T>(key: string, initialValue: T): [T, Dispatch<SetStateAction<T>>] {
|
|
38
|
+
const [state, setState] = useState<T>(() => readStorage(key, initialValue));
|
|
39
|
+
|
|
40
|
+
// Persist every state change to localStorage.
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
try {
|
|
43
|
+
localStorage.setItem(key, JSON.stringify(state));
|
|
44
|
+
} catch {
|
|
45
|
+
// Quota exceeded or private-browsing restrictions — silently ignore.
|
|
46
|
+
}
|
|
47
|
+
}, [key, state]);
|
|
48
|
+
|
|
49
|
+
// Keep tabs in sync: when another tab writes to the same key, update state.
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const onStorage = (event: StorageEvent) => {
|
|
52
|
+
if (event.key !== key || event.storageArea !== localStorage) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
setState(event.newValue === null ? initialValue : (JSON.parse(event.newValue) as T));
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
globalThis.addEventListener('storage', onStorage);
|
|
59
|
+
return () => globalThis.removeEventListener('storage', onStorage);
|
|
60
|
+
}, [key, initialValue]);
|
|
61
|
+
|
|
62
|
+
const setValue: Dispatch<SetStateAction<T>> = useCallback((action) => {
|
|
63
|
+
setState(prev => (typeof action === 'function' ? (action as (prev: T) => T)(prev) : action));
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
return [state, setValue];
|
|
67
|
+
}
|