Skip to content

Commit 2f2f3d1

Browse files
committed
update ui site
1 parent a04ce22 commit 2f2f3d1

1 file changed

Lines changed: 125 additions & 28 deletions

File tree

index.html

Lines changed: 125 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,17 +1013,26 @@
10131013
}
10141014
}, "Ref"))), /*#__PURE__*/React.createElement("tbody", null, paged.map((row, i) => {
10151015
const sv = SV[row.severity] || 'MEDIUM';
1016+
const isExpanded = expandedId === row.id;
1017+
const toggleExpand = () => setExpandedId(prev => prev === row.id ? null : row.id);
10161018
return /*#__PURE__*/React.createElement("tr", {
10171019
key: row.id + '-' + i,
1018-
onMouseEnter: e => e.currentTarget.style.background = '#0d1117',
1019-
onMouseLeave: e => e.currentTarget.style.background = 'transparent'
1020+
onClick: toggleExpand,
1021+
onMouseEnter: e => { if (!isExpanded) e.currentTarget.style.background = '#0d1117'; },
1022+
onMouseLeave: e => { if (!isExpanded) e.currentTarget.style.background = 'transparent'; },
1023+
style: {
1024+
cursor: 'pointer',
1025+
background: isExpanded ? '#10151d' : 'transparent',
1026+
transition: 'background 0.15s ease'
1027+
}
10201028
}, /*#__PURE__*/React.createElement("td", {
10211029
style: {
10221030
padding: '7px 12px',
1023-
maxWidth: 200,
1024-
overflow: 'hidden',
1025-
textOverflow: 'ellipsis',
1026-
whiteSpace: 'nowrap',
1031+
maxWidth: isExpanded ? 'none' : 200,
1032+
overflow: isExpanded ? 'visible' : 'hidden',
1033+
textOverflow: isExpanded ? 'clip' : 'ellipsis',
1034+
whiteSpace: isExpanded ? 'normal' : 'nowrap',
1035+
wordBreak: isExpanded ? 'break-word' : 'normal',
10271036
color: '#c8ccd4'
10281037
}
10291038
}, row.name || '-'), /*#__PURE__*/React.createElement("td", {
@@ -1034,7 +1043,8 @@
10341043
}
10351044
}, /*#__PURE__*/React.createElement("span", {
10361045
title: 'Click to copy: ' + row.id + (row.sha256 ? '\nSHA256: ' + row.sha256 : ''),
1037-
onClick: () => {
1046+
onClick: e => {
1047+
e.stopPropagation();
10381048
navigator.clipboard && navigator.clipboard.writeText(row.id);
10391049
setExpandedId(prev => prev === row.id ? null : row.id);
10401050
setCopiedId(row.id);
@@ -1043,24 +1053,36 @@
10431053
style: {
10441054
cursor: 'pointer',
10451055
fontFamily: 'monospace',
1046-
background: expandedId === row.id ? '#1c2333' : 'transparent',
1047-
padding: expandedId === row.id ? '2px 6px' : '0',
1056+
background: isExpanded ? '#1c2333' : 'transparent',
1057+
padding: isExpanded ? '2px 6px' : '0',
10481058
borderRadius: 4,
1049-
border: expandedId === row.id ? '1px solid #30363d' : '1px solid transparent',
1059+
border: isExpanded ? '1px solid #30363d' : '1px solid transparent',
10501060
display: 'inline-block',
1051-
wordBreak: expandedId === row.id ? 'break-all' : 'normal',
1052-
whiteSpace: expandedId === row.id ? 'normal' : 'nowrap',
1061+
wordBreak: isExpanded ? 'break-all' : 'normal',
1062+
whiteSpace: isExpanded ? 'normal' : 'nowrap',
10531063
transition: 'all 0.15s ease'
10541064
}
1055-
}, expandedId === row.id ? row.id : (row.id.length > 24 ? row.id.slice(0, 24) + '\u2026' : row.id),
1065+
}, isExpanded ? row.id : (row.id.length > 24 ? row.id.slice(0, 24) + '\u2026' : row.id),
10561066
copiedId === row.id && /*#__PURE__*/React.createElement("span", {
10571067
style: {
10581068
marginLeft: 6,
10591069
color: '#3fb950',
10601070
fontSize: 10,
10611071
fontFamily: 'sans-serif'
10621072
}
1063-
}, '\u2713 copied'))), /*#__PURE__*/React.createElement("td", {
1073+
}, '\u2713 copied')),
1074+
isExpanded && row.sha256 && /*#__PURE__*/React.createElement("div", {
1075+
style: {
1076+
marginTop: 6,
1077+
fontSize: 10,
1078+
color: '#484f58',
1079+
fontFamily: 'monospace',
1080+
wordBreak: 'break-all',
1081+
lineHeight: 1.4
1082+
}
1083+
}, /*#__PURE__*/React.createElement("span", {
1084+
style: { color: '#6e7681', marginRight: 6 }
1085+
}, "SHA256:"), row.sha256)), /*#__PURE__*/React.createElement("td", {
10641086
style: {
10651087
padding: '7px 12px'
10661088
}
@@ -1080,12 +1102,15 @@
10801102
}, sv)), /*#__PURE__*/React.createElement("td", {
10811103
style: {
10821104
padding: '7px 12px',
1083-
maxWidth: 240,
1084-
overflow: 'hidden',
1085-
textOverflow: 'ellipsis',
1086-
whiteSpace: 'nowrap',
1105+
maxWidth: isExpanded ? 'none' : 240,
1106+
minWidth: isExpanded ? 240 : 0,
1107+
overflow: isExpanded ? 'visible' : 'hidden',
1108+
textOverflow: isExpanded ? 'clip' : 'ellipsis',
1109+
whiteSpace: isExpanded ? 'normal' : 'nowrap',
1110+
wordBreak: isExpanded ? 'break-word' : 'normal',
10871111
color: '#6e7681',
1088-
fontSize: 11
1112+
fontSize: 11,
1113+
lineHeight: isExpanded ? 1.55 : 'normal'
10891114
}
10901115
}, row.comment), /*#__PURE__*/React.createElement("td", {
10911116
style: {
@@ -1095,6 +1120,7 @@
10951120
href: row.link,
10961121
target: "_blank",
10971122
rel: "noopener noreferrer",
1123+
onClick: e => e.stopPropagation(),
10981124
style: {
10991125
color: '#58a6ff',
11001126
textDecoration: 'none',
@@ -1509,8 +1535,7 @@
15091535
}
15101536
}, "+ Contribute extension");
15111537
}
1512-
function ExtensionChecker() {
1513-
const [subTab, setSubTab] = useState('check');
1538+
function ExtensionChecker({ subTab, setSubTab }) {
15141539
const [extId, setExtId] = useState('');
15151540
const [manifest, setManifest] = useState('');
15161541
const [result, setResult] = useState(null);
@@ -2450,10 +2475,82 @@
24502475
type: "info"
24512476
}, "Permission-based blocking stops any extension requesting dangerous capabilities, regardless of whether it is in the malicious feed. Combine with a blocklist for defense in depth.")));
24522477
}
2478+
const TAB_SUBS = {
2479+
dashboard: [],
2480+
feeds: ['malicious', 'sensitive', 'download'],
2481+
checker: ['check', 'analyze', 'inventory'],
2482+
policy: [],
2483+
guide: ['traces', 'remediation']
2484+
};
2485+
const TAB_IDS = Object.keys(TAB_SUBS);
2486+
function parseHash() {
2487+
const raw = (window.location.hash || '').replace(/^#\/?/, '');
2488+
if (!raw) return { tab: 'dashboard', sub: null };
2489+
const parts = raw.split('/').filter(Boolean);
2490+
const tab = TAB_IDS.includes(parts[0]) ? parts[0] : 'dashboard';
2491+
const subs = TAB_SUBS[tab];
2492+
const sub = parts[1] && subs.includes(parts[1]) ? parts[1] : null;
2493+
return { tab, sub };
2494+
}
2495+
function buildHash(tab, sub) {
2496+
return sub ? '#' + tab + '/' + sub : '#' + tab;
2497+
}
2498+
function pushHash(tab, sub) {
2499+
const h = buildHash(tab, sub);
2500+
if (window.location.hash !== h) {
2501+
window.history.pushState(null, '', h);
2502+
}
2503+
}
24532504
function App() {
2454-
const [tab, setTab] = useState('dashboard');
2455-
const [feedSub, setFeedSub] = useState('malicious');
2456-
const [guidePanel, setGuidePanel] = useState('traces');
2505+
const initial = parseHash();
2506+
const [tab, setTab] = useState(initial.tab);
2507+
const [feedSub, setFeedSub] = useState(initial.tab === 'feeds' && initial.sub ? initial.sub : 'malicious');
2508+
const [checkerSub, setCheckerSub] = useState(initial.tab === 'checker' && initial.sub ? initial.sub : 'check');
2509+
const [guidePanel, setGuidePanel] = useState(initial.tab === 'guide' && initial.sub ? initial.sub : 'traces');
2510+
2511+
// Ensure URL reflects initial state (e.g. empty hash -> #dashboard, or #feeds -> #feeds/malicious)
2512+
React.useEffect(() => {
2513+
const currentSub =
2514+
tab === 'feeds' ? feedSub :
2515+
tab === 'checker' ? checkerSub :
2516+
tab === 'guide' ? guidePanel : null;
2517+
const target = buildHash(tab, currentSub);
2518+
if (window.location.hash !== target) {
2519+
window.history.replaceState(null, '', target);
2520+
}
2521+
// run once on mount
2522+
// eslint-disable-next-line react-hooks/exhaustive-deps
2523+
}, []);
2524+
2525+
// Sync state when user navigates with Back/Forward or edits the URL
2526+
React.useEffect(() => {
2527+
const sync = () => {
2528+
const p = parseHash();
2529+
setTab(p.tab);
2530+
if (p.tab === 'feeds' && p.sub) setFeedSub(p.sub);
2531+
if (p.tab === 'checker' && p.sub) setCheckerSub(p.sub);
2532+
if (p.tab === 'guide' && p.sub) setGuidePanel(p.sub);
2533+
};
2534+
window.addEventListener('hashchange', sync);
2535+
window.addEventListener('popstate', sync);
2536+
return () => {
2537+
window.removeEventListener('hashchange', sync);
2538+
window.removeEventListener('popstate', sync);
2539+
};
2540+
}, []);
2541+
2542+
const selectTab = (id) => {
2543+
setTab(id);
2544+
const sub =
2545+
id === 'feeds' ? feedSub :
2546+
id === 'checker' ? checkerSub :
2547+
id === 'guide' ? guidePanel : null;
2548+
pushHash(id, sub);
2549+
};
2550+
const selectFeedSub = (id) => { setFeedSub(id); pushHash('feeds', id); };
2551+
const selectCheckerSub = (id) => { setCheckerSub(id); pushHash('checker', id); };
2552+
const selectGuidePanel = (id) => { setGuidePanel(id); pushHash('guide', id); };
2553+
24572554
const tabs = [{
24582555
id: 'dashboard',
24592556
l: 'Dashboard'
@@ -2566,7 +2663,7 @@
25662663
}
25672664
}, tabs.map(t => /*#__PURE__*/React.createElement("button", {
25682665
key: t.id,
2569-
onClick: () => setTab(t.id),
2666+
onClick: () => selectTab(t.id),
25702667
style: {
25712668
background: tab === t.id ? '#161b22' : 'transparent',
25722669
border: tab === t.id ? '1px solid #30363d' : '1px solid transparent',
@@ -2873,7 +2970,7 @@
28732970
}
28742971
}, feedSubs.map(s => /*#__PURE__*/React.createElement("button", {
28752972
key: s.id,
2876-
onClick: () => setFeedSub(s.id),
2973+
onClick: () => selectFeedSub(s.id),
28772974
style: {
28782975
display: 'flex',
28792976
alignItems: 'center',
@@ -3058,7 +3155,7 @@
30583155
cursor: 'pointer',
30593156
textDecoration: 'none'
30603157
}
3061-
}, "Sensitive"))))))), tab === 'checker' && /*#__PURE__*/React.createElement(ExtensionChecker, null), tab === 'policy' && /*#__PURE__*/React.createElement(PolicyGenerator, null), tab === 'guide' && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
3158+
}, "Sensitive"))))))), tab === 'checker' && /*#__PURE__*/React.createElement(ExtensionChecker, { subTab: checkerSub, setSubTab: selectCheckerSub }), tab === 'policy' && /*#__PURE__*/React.createElement(PolicyGenerator, null), tab === 'guide' && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
30623159
style: {
30633160
marginBottom: 20
30643161
}
@@ -3082,7 +3179,7 @@
30823179
}
30833180
}, gps.map(p => /*#__PURE__*/React.createElement("button", {
30843181
key: p.id,
3085-
onClick: () => !p.soon && setGuidePanel(p.id),
3182+
onClick: () => !p.soon && selectGuidePanel(p.id),
30863183
style: {
30873184
background: guidePanel === p.id ? '#161b22' : 'transparent',
30883185
border: guidePanel === p.id ? '1px solid #58a6ff33' : '1px solid #1b1f27',

0 commit comments

Comments
 (0)