link_pair bug
This commit is contained in:
43
src/App.tsx
43
src/App.tsx
@@ -29,6 +29,9 @@ const POPUP_ASPECT_VAL: Record<PopupAspect, number> = {
|
||||
type Filters = {
|
||||
videos: Set<string>; // empty = all
|
||||
sides: Set<string>; // empty = all
|
||||
// Carriageway/lane the asset's site_id belongs to (LHS / RHS). Stays
|
||||
// distinct from `sides`, which is left/right-of-vehicle.
|
||||
lanes: Set<string>;
|
||||
types: Set<"fixed" | "range">; // empty = all
|
||||
names: Set<string>; // empty = all (asset_name)
|
||||
};
|
||||
@@ -402,6 +405,7 @@ function AppShell({
|
||||
const [filters, setFilters] = useState<Filters>({
|
||||
videos: new Set(),
|
||||
sides: new Set(),
|
||||
lanes: new Set(),
|
||||
types: new Set(),
|
||||
names: new Set(),
|
||||
});
|
||||
@@ -731,15 +735,18 @@ function AppShell({
|
||||
const counts = useMemo(() => {
|
||||
const byVideo = new Map<string, number>();
|
||||
const bySide = new Map<string, number>();
|
||||
const byLane = new Map<string, number>();
|
||||
const byType = new Map<string, number>();
|
||||
for (const a of assets) {
|
||||
const vn = displayVideo(a.video_name);
|
||||
byVideo.set(vn, (byVideo.get(vn) ?? 0) + 1);
|
||||
const s = a.side ?? "(none)";
|
||||
bySide.set(s, (bySide.get(s) ?? 0) + 1);
|
||||
const l = a.lane_side ?? "(none)";
|
||||
byLane.set(l, (byLane.get(l) ?? 0) + 1);
|
||||
byType.set(a.asset_type, (byType.get(a.asset_type) ?? 0) + 1);
|
||||
}
|
||||
return { byVideo, bySide, byType };
|
||||
return { byVideo, bySide, byLane, byType };
|
||||
}, [assets]);
|
||||
|
||||
const filteredAssets = useMemo(() => {
|
||||
@@ -750,6 +757,10 @@ function AppShell({
|
||||
const s = a.side ?? "(none)";
|
||||
if (!filters.sides.has(s)) return false;
|
||||
}
|
||||
if (filters.lanes.size) {
|
||||
const l = a.lane_side ?? "(none)";
|
||||
if (!filters.lanes.has(l)) return false;
|
||||
}
|
||||
if (filters.types.size && !filters.types.has(a.asset_type)) return false;
|
||||
if (filters.names.size && !filters.names.has(a.asset_name)) return false;
|
||||
// Video filter: explicit list. If allVideoNames is loaded and the asset's
|
||||
@@ -781,11 +792,15 @@ function AppShell({
|
||||
const s = a.side ?? "(none)";
|
||||
if (!filters.sides.has(s)) continue;
|
||||
}
|
||||
if (filters.lanes.size) {
|
||||
const l = a.lane_side ?? "(none)";
|
||||
if (!filters.lanes.has(l)) continue;
|
||||
}
|
||||
if (filters.types.size && !filters.types.has(a.asset_type)) continue;
|
||||
m.set(a.asset_name, (m.get(a.asset_name) ?? 0) + 1);
|
||||
}
|
||||
return m;
|
||||
}, [assets, filters.videos, filters.sides, filters.types]);
|
||||
}, [assets, filters.videos, filters.sides, filters.lanes, filters.types]);
|
||||
|
||||
function toggleSet<T>(set: Set<T>, value: T): Set<T> {
|
||||
const next = new Set(set);
|
||||
@@ -798,6 +813,7 @@ function AppShell({
|
||||
setFilters({
|
||||
videos: new Set(),
|
||||
sides: new Set(),
|
||||
lanes: new Set(),
|
||||
types: new Set(),
|
||||
names: new Set(),
|
||||
});
|
||||
@@ -4250,6 +4266,7 @@ function AppShell({
|
||||
disabled={
|
||||
filters.videos.size +
|
||||
filters.sides.size +
|
||||
filters.lanes.size +
|
||||
filters.types.size +
|
||||
filters.names.size ===
|
||||
0
|
||||
@@ -4358,6 +4375,28 @@ function AppShell({
|
||||
</label>
|
||||
))}
|
||||
|
||||
<h4 title="Carriageway derived from the import-time site_id pair (lower site_id → LHS, higher → RHS)">
|
||||
Lane
|
||||
</h4>
|
||||
{Array.from(counts.byLane.entries())
|
||||
.sort()
|
||||
.map(([lane, n]) => (
|
||||
<label key={lane} className="filter-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={filters.lanes.has(lane)}
|
||||
onChange={() =>
|
||||
setFilters((f) => ({
|
||||
...f,
|
||||
lanes: toggleSet(f.lanes, lane),
|
||||
}))
|
||||
}
|
||||
/>
|
||||
<span className="label">{lane}</span>
|
||||
<span className="count">{n}</span>
|
||||
</label>
|
||||
))}
|
||||
|
||||
<h4
|
||||
style={{ cursor: "pointer", userSelect: "none" }}
|
||||
onClick={() => setVideosExpanded((v) => !v)}
|
||||
|
||||
@@ -38,6 +38,7 @@ export type Asset = {
|
||||
merged_into: number | null;
|
||||
in_scope: number | null;
|
||||
side: string | null;
|
||||
lane_side: string | null;
|
||||
link_pair_id: number | null;
|
||||
link_locked: number | null;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user