fix: keep V2X intersection code out of login UI
This commit is contained in:
@@ -24,6 +24,8 @@ Add a non-sensitive `v2xPreview` object to the area configuration:
|
|||||||
`apiBaseUrl` and `wsBaseUrl` should normally be relative, same-origin paths.
|
`apiBaseUrl` and `wsBaseUrl` should normally be relative, same-origin paths.
|
||||||
The deployment server proxies them to the V2X REST and WebSocket services. Do
|
The deployment server proxies them to the V2X REST and WebSocket services. Do
|
||||||
not commit a private upstream address, an account, a token, or an AMap key.
|
not commit a private upstream address, an account, a token, or an AMap key.
|
||||||
|
`crossCode` is deployment configuration for the selected intersection. It is
|
||||||
|
never shown or editable in the browser login panel.
|
||||||
|
|
||||||
The browser sends `POST {apiBaseUrl}/facilities/api/sys/login` with `userName`
|
The browser sends `POST {apiBaseUrl}/facilities/api/sys/login` with `userName`
|
||||||
and an MD5-hashed password, matching the source V2X dashboard. It holds the
|
and an MD5-hashed password, matching the source V2X dashboard. It holds the
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
metrics: null,
|
metrics: null,
|
||||||
vehicleSource: "waiting",
|
vehicleSource: "waiting",
|
||||||
};
|
};
|
||||||
const ui = buildUi(state, settings);
|
const ui = buildUi(state);
|
||||||
|
|
||||||
function setStatus(message) {
|
function setStatus(message) {
|
||||||
state.status = message;
|
state.status = message;
|
||||||
@@ -99,12 +99,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadLiveData() {
|
async function loadLiveData() {
|
||||||
const crossCode = ui.crossCode.value.trim();
|
const crossCode = state.crossCode;
|
||||||
if (!crossCode) {
|
if (!crossCode) {
|
||||||
setStatus("Enter a V2X intersection code.");
|
setStatus("V2X intersection code is not configured.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.crossCode = crossCode;
|
|
||||||
clearEntities();
|
clearEntities();
|
||||||
state.vehicleSource = "waiting";
|
state.vehicleSource = "waiting";
|
||||||
setStatus("Loading live V2X intersection data...");
|
setStatus("Loading live V2X intersection data...");
|
||||||
@@ -195,12 +194,12 @@
|
|||||||
return { state, load: loadLiveData, signOut, dispose: () => { disconnect(); clearEntities(); state.vehicleSource = "waiting"; ui.root.remove(); } };
|
return { state, load: loadLiveData, signOut, dispose: () => { disconnect(); clearEntities(); state.vehicleSource = "waiting"; ui.root.remove(); } };
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUi(state, settings) {
|
function buildUi(state) {
|
||||||
const root = document.createElement("aside");
|
const root = document.createElement("aside");
|
||||||
root.id = "v2xPanel";
|
root.id = "v2xPanel";
|
||||||
root.innerHTML = `<div class="v2x-heading"><strong>Live V2X Data</strong><span>Native: WGS84/ENU | V2X: GCJ-02</span></div>
|
root.innerHTML = `<div class="v2x-heading"><strong>Live V2X Data</strong><span>Native: WGS84/ENU | V2X: GCJ-02</span></div>
|
||||||
<form id="v2xLoginForm"><label>Username<input name="userName" autocomplete="username" required></label><label>Password<input name="password" type="password" autocomplete="current-password" required></label><button type="submit">Sign in</button></form>
|
<form id="v2xLoginForm"><label>Username<input name="userName" autocomplete="username" required></label><label>Password<input name="password" type="password" autocomplete="current-password" required></label><button type="submit">Sign in</button></form>
|
||||||
<div id="v2xLiveControls" hidden><label>Intersection code<input name="crossCode" value="${escapeAttribute(settings.crossCode || "")}" required></label><div><button type="button" data-action="reload">Refresh</button><button type="button" data-action="signout">Sign out</button></div></div>
|
<div id="v2xLiveControls" hidden><div><button type="button" data-action="reload">Refresh</button><button type="button" data-action="signout">Sign out</button></div></div>
|
||||||
<output id="v2xStatus"></output>`;
|
<output id="v2xStatus"></output>`;
|
||||||
document.body.appendChild(root);
|
document.body.appendChild(root);
|
||||||
return {
|
return {
|
||||||
@@ -209,7 +208,6 @@
|
|||||||
live: root.querySelector("#v2xLiveControls"),
|
live: root.querySelector("#v2xLiveControls"),
|
||||||
userName: root.querySelector("[name=userName]"),
|
userName: root.querySelector("[name=userName]"),
|
||||||
password: root.querySelector("[name=password]"),
|
password: root.querySelector("[name=password]"),
|
||||||
crossCode: root.querySelector("[name=crossCode]"),
|
|
||||||
reload: root.querySelector("[data-action=reload]"),
|
reload: root.querySelector("[data-action=reload]"),
|
||||||
signOut: root.querySelector("[data-action=signout]"),
|
signOut: root.querySelector("[data-action=signout]"),
|
||||||
status: root.querySelector("#v2xStatus"),
|
status: root.querySelector("#v2xStatus"),
|
||||||
@@ -329,7 +327,6 @@
|
|||||||
resolved.searchParams.set("authorization", token);
|
resolved.searchParams.set("authorization", token);
|
||||||
return resolved.href;
|
return resolved.href;
|
||||||
}
|
}
|
||||||
function escapeAttribute(value) { return String(value).replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<"); }
|
|
||||||
|
|
||||||
function transformLat(x, y) { let value = -100 + 2 * x + 3 * y + .2 * y * y + .1 * x * y + .2 * Math.sqrt(Math.abs(x)); value += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3; value += (20 * Math.sin(y * PI) + 40 * Math.sin(y / 3 * PI)) * 2 / 3; value += (160 * Math.sin(y / 12 * PI) + 320 * Math.sin(y * PI / 30)) * 2 / 3; return value; }
|
function transformLat(x, y) { let value = -100 + 2 * x + 3 * y + .2 * y * y + .1 * x * y + .2 * Math.sqrt(Math.abs(x)); value += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3; value += (20 * Math.sin(y * PI) + 40 * Math.sin(y / 3 * PI)) * 2 / 3; value += (160 * Math.sin(y / 12 * PI) + 320 * Math.sin(y * PI / 30)) * 2 / 3; return value; }
|
||||||
function transformLon(x, y) { let value = 300 + x + 2 * y + .1 * x * x + .1 * x * y + .1 * Math.sqrt(Math.abs(x)); value += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3; value += (20 * Math.sin(x * PI) + 40 * Math.sin(x / 3 * PI)) * 2 / 3; value += (150 * Math.sin(x / 12 * PI) + 300 * Math.sin(x / 30 * PI)) * 2 / 3; return value; }
|
function transformLon(x, y) { let value = 300 + x + 2 * y + .1 * x * x + .1 * x * y + .1 * Math.sqrt(Math.abs(x)); value += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3; value += (20 * Math.sin(x * PI) + 40 * Math.sin(x / 3 * PI)) * 2 / 3; value += (150 * Math.sin(x / 12 * PI) + 300 * Math.sin(x / 30 * PI)) * 2 / 3; return value; }
|
||||||
|
|||||||
@@ -281,6 +281,8 @@ assert.match(v2xRuntime, /GCJ-02 -> WGS84 once/);
|
|||||||
assert.match(v2xRuntime, /\/network\/ws\/network\/signal/);
|
assert.match(v2xRuntime, /\/network\/ws\/network\/signal/);
|
||||||
assert.match(v2xRuntime, /\/network\/ws\/network\/obuPosition/);
|
assert.match(v2xRuntime, /\/network\/ws\/network\/obuPosition/);
|
||||||
assert.match(v2xRuntime, /\/network\/ws\/network\/targetPosition/);
|
assert.match(v2xRuntime, /\/network\/ws\/network\/targetPosition/);
|
||||||
|
assert.doesNotMatch(v2xRuntime, /Intersection code<input/);
|
||||||
|
assert.match(v2xRuntime, /V2X intersection code is not configured/);
|
||||||
assert.match(v2xRuntime, /gcj02ToWgs84/);
|
assert.match(v2xRuntime, /gcj02ToWgs84/);
|
||||||
assert.match(previewRuntime, /createLiveVehicleState\(\)/);
|
assert.match(previewRuntime, /createLiveVehicleState\(\)/);
|
||||||
assert.doesNotMatch(previewRuntime, /const cruise = addVehicleCruises\(/);
|
assert.doesNotMatch(previewRuntime, /const cruise = addVehicleCruises\(/);
|
||||||
|
|||||||
Reference in New Issue
Block a user