Send user trajectories from the user list into a focused live map
- Open 「用户轨迹」 straight on the live map instead of a drawer, carrying the server, the focused user and a start/end window through the plugin page hash. - Default that window to one hour before the user's last seen time and keep the plugin page query available to bundles through the host context. - Replace the time range preset gate with always visible start/end datetime fields plus a quick-range select, so the user list rebuilds from the window. - Drop the bulky trajectory list and draw one compact colour legend under the map, keeping a stable colour per identity and restricting vehicle tracks to the vehicles the selected users actually rode.
This commit is contained in:
@@ -51,6 +51,14 @@ describe("console shell routes", () => {
|
||||
expect(resolved.params).toEqual({ pluginId: "game.scum", routeKey: "operations", serverId: "server/scum-1" });
|
||||
});
|
||||
|
||||
it("carries hosted plugin page focus queries through the hash", () => {
|
||||
const pageQuery = { focus: "76561198000000001", from: "2026-09-16T09:30:00Z", to: "2026-09-16T11:00:00Z" };
|
||||
const hash = hashForPage("pluginPage", { pluginId: "game.scum", routeKey: "live-map", serverId: "server-1", pageQuery });
|
||||
const resolved = resolveRouteHash(hash, platformAdmin);
|
||||
expect(resolved.route.id).toBe("pluginPage");
|
||||
expect(resolved.params).toEqual({ pluginId: "game.scum", routeKey: "live-map", serverId: "server-1", pageQuery });
|
||||
});
|
||||
|
||||
it("keeps route metadata available for shell navigation", () => {
|
||||
expect(firstPartyRoutes.map((route) => route.id)).toContain("maintenance");
|
||||
expect(firstPartyRoutes.map((route) => route.id)).toContain("profileSettings");
|
||||
|
||||
@@ -110,6 +110,11 @@ export function hashForPage(pageId: PageId, params: PageParams = {}): string {
|
||||
if (params.serverId) {
|
||||
query.set("serverInstanceId", params.serverId);
|
||||
}
|
||||
for (const [key, value] of Object.entries(params.pageQuery ?? {})) {
|
||||
if (value) {
|
||||
query.set(key, value);
|
||||
}
|
||||
}
|
||||
const suffix = query.toString();
|
||||
return `#/plugin-pages/${encodeURIComponent(params.pluginId)}/${encodeURIComponent(params.routeKey)}${suffix ? `?${suffix}` : ""}`;
|
||||
}
|
||||
@@ -151,13 +156,22 @@ export function resolveRouteHash(hash: string, user?: CurrentUserView): Resolved
|
||||
return { route: routeForPage("serverDetail"), params: { serverId: decodeURIComponent(segments[1]), routeKey } };
|
||||
}
|
||||
if (segments[0] === "plugin-pages" && segments.length > 2) {
|
||||
const serverId = new URLSearchParams(rawQuery).get("serverInstanceId") ?? undefined;
|
||||
const query = new URLSearchParams(rawQuery);
|
||||
const serverId = query.get("serverInstanceId") ?? undefined;
|
||||
query.delete("serverInstanceId");
|
||||
const pageQuery: Record<string, string> = {};
|
||||
for (const [key, value] of query.entries()) {
|
||||
if (value) {
|
||||
pageQuery[key] = value;
|
||||
}
|
||||
}
|
||||
return {
|
||||
route: routeForPage("pluginPage"),
|
||||
params: {
|
||||
pluginId: decodeURIComponent(segments[1]),
|
||||
routeKey: decodeURIComponent(segments[2]),
|
||||
serverId
|
||||
serverId,
|
||||
...(Object.keys(pageQuery).length ? { pageQuery } : {})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user