feat(workbench): align v2 GIS and SCADA API
This commit is contained in:
@@ -8,8 +8,8 @@ import {
|
||||
|
||||
describe("feature panel properties", () => {
|
||||
it.each([
|
||||
["pipes", ["id", "diameter", "length", "material"]],
|
||||
["junctions", ["id", "elevation", "demand", "pressure"]]
|
||||
["pipes", ["id", "start_node_id", "end_node_id", "diameter", "length", "roughness", "status"]],
|
||||
["junctions", ["id", "elevation", "base_demand"]]
|
||||
] as const)("shows the configured %s fields", (layer, expectedKeys) => {
|
||||
const entries = getFeaturePanelProperties(layer, {}, "feature-id");
|
||||
|
||||
@@ -20,16 +20,22 @@ describe("feature panel properties", () => {
|
||||
it("formats pipe diameter from GeoServer DN millimeter values", () => {
|
||||
const entries = getFeaturePanelProperties("pipes", {
|
||||
id: "P-1",
|
||||
start_node_id: "J-1",
|
||||
end_node_id: "J-2",
|
||||
diameter: 600,
|
||||
length: 42.5,
|
||||
material: "DI"
|
||||
roughness: 120,
|
||||
status: "OPEN"
|
||||
});
|
||||
|
||||
expect(entries.map(({ label, value }) => [label, value])).toEqual([
|
||||
["编号", "P-1"],
|
||||
["起点节点", "J-1"],
|
||||
["终点节点", "J-2"],
|
||||
["管径", "600 mm"],
|
||||
["长度", "42.50 m"],
|
||||
["材质", "球墨铸铁"]
|
||||
["粗糙系数", "120"],
|
||||
["状态", "开启"]
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -37,14 +43,14 @@ describe("feature panel properties", () => {
|
||||
const metrics = getFeatureInsightMetrics("pipes", {
|
||||
diameter: 600,
|
||||
length: 42.5,
|
||||
material: "DI",
|
||||
roughness: 120,
|
||||
status: "OPEN"
|
||||
});
|
||||
|
||||
expect(metrics).toEqual([
|
||||
{ label: "管径", value: "600 mm" },
|
||||
{ label: "长度", value: "42.50 m" },
|
||||
{ label: "材质", value: "球墨铸铁" },
|
||||
{ label: "粗糙系数", value: "120" },
|
||||
{ label: "状态", value: "开启" }
|
||||
]);
|
||||
});
|
||||
@@ -52,56 +58,62 @@ describe("feature panel properties", () => {
|
||||
it("localizes common enumerated property values in the panel", () => {
|
||||
expect(getFeaturePanelProperties("valves", {
|
||||
id: "V-1",
|
||||
node1: "J-1",
|
||||
node2: "J-2",
|
||||
start_node_id: "J-1",
|
||||
end_node_id: "J-2",
|
||||
diameter: 300,
|
||||
v_type: "PRV",
|
||||
setting: "OPEN"
|
||||
valve_type: "PRV",
|
||||
setting: "OPEN",
|
||||
minor_loss: 0.2
|
||||
}).map(({ label, value }) => [label, value])).toEqual([
|
||||
["编号", "V-1"],
|
||||
["起点节点", "J-1"],
|
||||
["终点节点", "J-2"],
|
||||
["管径", "300 mm"],
|
||||
["阀门类型", "减压阀"],
|
||||
["阀门设定", "开启"]
|
||||
["阀门设定", "开启"],
|
||||
["局部损失系数", "0.20"]
|
||||
]);
|
||||
|
||||
expect(getFeaturePanelProperties("scada", {
|
||||
id: "S-1",
|
||||
type: "pressure",
|
||||
associated_element_id: "J-1",
|
||||
device_id: "S-1",
|
||||
device_type: "pressure",
|
||||
node_id: "J-1",
|
||||
link_id: null,
|
||||
api_query_id: "query-1",
|
||||
transmission_mode: "non_realtime",
|
||||
transmission_frequency: "15min",
|
||||
reliability: "high"
|
||||
}).map(({ label, value }) => [label, value])).toEqual([
|
||||
["编号", "S-1"],
|
||||
["类型", "压力监测"],
|
||||
["关联资产", "J-1"],
|
||||
["设备 ID", "S-1"],
|
||||
["设备类型", "压力监测"],
|
||||
["关联节点", "J-1"],
|
||||
["关联连线", "暂无"],
|
||||
["采集接口", "query-1"],
|
||||
["传输方式", "非实时"],
|
||||
["传输频率", "15min"],
|
||||
["可靠性", "高"]
|
||||
]);
|
||||
|
||||
expect(getFeaturePanelProperties("scada", {
|
||||
id: "S-2",
|
||||
type: "pipe_flow"
|
||||
}).find((entry) => entry.key === "type")?.value).toBe("流量监测");
|
||||
device_id: "S-2",
|
||||
device_type: "pipe_flow"
|
||||
}).find((entry) => entry.key === "device_type")?.value).toBe("流量监测");
|
||||
});
|
||||
|
||||
it("uses the map feature id when the properties omit it", () => {
|
||||
const model = getFeaturePanelModel("junctions", { demand: 3.4 }, "map-feature-id");
|
||||
const model = getFeaturePanelModel("junctions", { base_demand: 3.4 }, "map-feature-id");
|
||||
|
||||
expect(model.id).toBe("map-feature-id");
|
||||
expect(model.badge).toBeUndefined();
|
||||
expect(model.attributes.map((entry) => entry.key)).toEqual(["elevation", "demand", "pressure"]);
|
||||
expect(model.attributes.map((entry) => entry.key)).toEqual(["elevation", "base_demand"]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["valves", ["id", "node1", "node2", "diameter", "v_type", "setting"]],
|
||||
["reservoirs", ["id", "head", "pattern"]],
|
||||
["scada", ["id", "type", "associated_element_id", "transmission_mode", "transmission_frequency", "reliability"]],
|
||||
["pumps", ["id", "node1", "node2", "status"]],
|
||||
["tanks", ["id", "elevation", "init_level", "min_level", "max_level"]]
|
||||
["valves", ["id", "start_node_id", "end_node_id", "diameter", "valve_type", "setting", "minor_loss"]],
|
||||
["reservoirs", ["id", "head", "pattern_id"]],
|
||||
["scada", ["device_id", "device_type", "node_id", "link_id", "api_query_id", "transmission_mode", "transmission_frequency", "reliability"]],
|
||||
["pumps", ["id", "start_node_id", "end_node_id", "power", "head_curve_id", "speed", "pattern_id"]],
|
||||
["tanks", ["id", "elevation", "initial_level", "minimum_level", "maximum_level", "diameter", "minimum_volume", "volume_curve_id", "overflow"]]
|
||||
] as const)("localizes configured %s panel field labels", (layer, keys) => {
|
||||
const entries = getFeaturePanelProperties(layer, {}, "feature-id");
|
||||
|
||||
@@ -112,7 +124,7 @@ describe("feature panel properties", () => {
|
||||
label: getFeaturePropertyLabel(entry.key)
|
||||
}))
|
||||
);
|
||||
expect(entries.filter((entry) => entry.key !== "id").map((entry) => entry.label))
|
||||
expect(entries.filter((entry) => entry.key !== "id" && entry.key !== "device_id").map((entry) => entry.label))
|
||||
.not.toContainEqual(expect.stringMatching(/^[a-z][a-z0-9_]*$/));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,8 +29,6 @@ const PROPERTY_LABELS: Record<string, string> = {
|
||||
fid: "GeoServer 要素 ID",
|
||||
id: "编号",
|
||||
scada_id: "编号 UUID",
|
||||
sensor_id: "传感器 ID",
|
||||
sensor_name: "传感器名称",
|
||||
swmm_node: "SWMM 节点",
|
||||
topology_order: "拓扑序",
|
||||
distance_to_wwtp_m: "距处理厂距离",
|
||||
@@ -48,8 +46,11 @@ const PROPERTY_LABELS: Record<string, string> = {
|
||||
name: "名称",
|
||||
code: "编码",
|
||||
type: "类型",
|
||||
device_type: "设备类型",
|
||||
node1: "起点节点",
|
||||
node2: "终点节点",
|
||||
start_node_id: "起点节点",
|
||||
end_node_id: "终点节点",
|
||||
from_node: "起点节点",
|
||||
to_node: "终点节点",
|
||||
diameter: "管径",
|
||||
@@ -60,6 +61,7 @@ const PROPERTY_LABELS: Record<string, string> = {
|
||||
max_depth: "最大深度",
|
||||
invert_elevation: "井底高程",
|
||||
v_type: "阀门类型",
|
||||
valve_type: "阀门类型",
|
||||
setting: "阀门设定",
|
||||
minor_loss: "局部损失系数",
|
||||
orifice_type: "孔口类型",
|
||||
@@ -76,12 +78,24 @@ const PROPERTY_LABELS: Record<string, string> = {
|
||||
status: "状态",
|
||||
head: "水头",
|
||||
pattern: "模式",
|
||||
pattern_id: "模式",
|
||||
head_curve_id: "扬程曲线",
|
||||
volume_curve_id: "容积曲线",
|
||||
init_level: "初始水位",
|
||||
min_level: "最低水位",
|
||||
max_level: "最高水位",
|
||||
initial_level: "初始水位",
|
||||
minimum_level: "最低水位",
|
||||
maximum_level: "最高水位",
|
||||
minimum_volume: "最小容积",
|
||||
overflow: "允许溢流",
|
||||
power: "功率",
|
||||
speed: "转速倍率",
|
||||
material: "材质",
|
||||
elevation: "高程",
|
||||
demand: "需水量",
|
||||
base_demand: "基础需水量",
|
||||
demands: "需水配置",
|
||||
pressure: "压力",
|
||||
flow: "流量",
|
||||
velocity: "流速",
|
||||
@@ -93,6 +107,9 @@ const PROPERTY_LABELS: Record<string, string> = {
|
||||
point_external_id: "测点编号",
|
||||
point_name: "测点名称",
|
||||
associated_element_id: "关联资产",
|
||||
node_id: "关联节点",
|
||||
link_id: "关联连线",
|
||||
api_query_id: "采集接口",
|
||||
transmission_mode: "传输方式",
|
||||
transmission_frequency: "传输频率",
|
||||
reliability: "可靠性",
|
||||
@@ -114,8 +131,6 @@ const PROPERTY_ORDER: Record<string, number> = {
|
||||
fid: 9,
|
||||
id: 10,
|
||||
scada_id: 10,
|
||||
sensor_id: 10,
|
||||
sensor_name: 12,
|
||||
swmm_node: 13,
|
||||
topology_order: 14,
|
||||
distance_to_wwtp_m: 15,
|
||||
@@ -143,10 +158,13 @@ const PROPERTY_ORDER: Record<string, number> = {
|
||||
material: 23,
|
||||
node1: 24,
|
||||
from_node: 24,
|
||||
start_node_id: 24,
|
||||
node2: 25,
|
||||
to_node: 25,
|
||||
end_node_id: 25,
|
||||
elevation: 30,
|
||||
demand: 31,
|
||||
base_demand: 31,
|
||||
pressure: 32,
|
||||
flow: 33,
|
||||
velocity: 34,
|
||||
@@ -275,13 +293,13 @@ const PROPERTY_UNITS: Record<string, string> = {
|
||||
};
|
||||
|
||||
const FEATURE_PANEL_PROPERTY_KEYS: Record<WaterNetworkSourceId, readonly string[]> = {
|
||||
pipes: ["id", "diameter", "length", "material"],
|
||||
junctions: ["id", "elevation", "demand", "pressure"],
|
||||
valves: ["id", "node1", "node2", "diameter", "v_type", "setting"],
|
||||
reservoirs: ["id", "head", "pattern"],
|
||||
scada: ["id", "type", "associated_element_id", "transmission_mode", "transmission_frequency", "reliability"],
|
||||
pumps: ["id", "node1", "node2", "status"],
|
||||
tanks: ["id", "elevation", "init_level", "min_level", "max_level"]
|
||||
pipes: ["id", "start_node_id", "end_node_id", "diameter", "length", "roughness", "status"],
|
||||
junctions: ["id", "elevation", "base_demand"],
|
||||
valves: ["id", "start_node_id", "end_node_id", "diameter", "valve_type", "setting", "minor_loss"],
|
||||
reservoirs: ["id", "head", "pattern_id"],
|
||||
scada: ["device_id", "device_type", "node_id", "link_id", "api_query_id", "transmission_mode", "transmission_frequency", "reliability"],
|
||||
pumps: ["id", "start_node_id", "end_node_id", "power", "head_curve_id", "speed", "pattern_id"],
|
||||
tanks: ["id", "elevation", "initial_level", "minimum_level", "maximum_level", "diameter", "minimum_volume", "volume_curve_id", "overflow"]
|
||||
};
|
||||
|
||||
const FEATURE_PANEL_BADGE_KEYS: Partial<Record<WaterNetworkSourceId, string>> = {
|
||||
@@ -299,42 +317,44 @@ const FEATURE_INSIGHT_METRICS: Record<WaterNetworkSourceId, readonly FeatureInsi
|
||||
pipes: [
|
||||
{ label: "管径", key: "diameter" },
|
||||
{ label: "长度", key: "length" },
|
||||
{ label: "材质", key: "material" },
|
||||
{ label: "粗糙系数", key: "roughness" },
|
||||
{ label: "状态", key: "status" }
|
||||
],
|
||||
junctions: [
|
||||
{ label: "需水量", key: "demand" },
|
||||
{ label: "基础需水量", key: "base_demand" },
|
||||
{ label: "高程", key: "elevation" },
|
||||
{ label: "压力", key: "pressure" },
|
||||
{ label: "状态", value: "在线" }
|
||||
{ label: "X 坐标", key: "x" },
|
||||
{ label: "Y 坐标", key: "y" }
|
||||
],
|
||||
valves: [
|
||||
{ label: "管径", key: "diameter" },
|
||||
{ label: "类型", key: "v_type" },
|
||||
{ label: "类型", key: "valve_type" },
|
||||
{ label: "设定", key: "setting" },
|
||||
{ label: "局部损失", key: "minor_loss" }
|
||||
],
|
||||
reservoirs: [
|
||||
{ label: "水头", key: "head" },
|
||||
{ label: "模式", key: "pattern" },
|
||||
{ label: "状态", value: "在线" }
|
||||
{ label: "模式", key: "pattern_id" },
|
||||
{ label: "X 坐标", key: "x" },
|
||||
{ label: "Y 坐标", key: "y" }
|
||||
],
|
||||
scada: [
|
||||
{ label: "类型", key: "type" },
|
||||
{ label: "关联资产", key: "associated_element_id" },
|
||||
{ label: "传输方式", key: "transmission_mode" },
|
||||
{ label: "可靠性", key: "reliability" }
|
||||
{ label: "类型", key: "device_type" },
|
||||
{ label: "关联节点", key: "node_id" },
|
||||
{ label: "关联连线", key: "link_id" },
|
||||
{ label: "传输方式", key: "transmission_mode" }
|
||||
],
|
||||
pumps: [
|
||||
{ label: "起点", key: "node1" },
|
||||
{ label: "终点", key: "node2" },
|
||||
{ label: "状态", key: "status" }
|
||||
{ label: "功率", key: "power" },
|
||||
{ label: "扬程曲线", key: "head_curve_id" },
|
||||
{ label: "转速倍率", key: "speed" },
|
||||
{ label: "模式", key: "pattern_id" }
|
||||
],
|
||||
tanks: [
|
||||
{ label: "高程", key: "elevation" },
|
||||
{ label: "初始水位", key: "init_level" },
|
||||
{ label: "最高水位", key: "max_level" },
|
||||
{ label: "状态", value: "在线" }
|
||||
{ label: "初始水位", key: "initial_level" },
|
||||
{ label: "最低水位", key: "minimum_level" },
|
||||
{ label: "最高水位", key: "maximum_level" }
|
||||
]
|
||||
};
|
||||
|
||||
@@ -353,7 +373,7 @@ export function getFeaturePanelProperties(
|
||||
): LocalizedFeatureProperty[] {
|
||||
return FEATURE_PANEL_PROPERTY_KEYS[layer].map((key) => {
|
||||
const propertyValue = getPropertyValue(properties, key);
|
||||
const value = key === "id" || key === "scada_id" || key === "sensor_id" ? propertyValue ?? featureId : propertyValue;
|
||||
const value = key === "id" || key === "scada_id" || key === "device_id" ? propertyValue ?? featureId : propertyValue;
|
||||
|
||||
return {
|
||||
key,
|
||||
@@ -391,7 +411,7 @@ export function getFeaturePanelModel(
|
||||
featureId?: string
|
||||
): FeaturePanelModel {
|
||||
const entries = getFeaturePanelProperties(layer, properties, featureId);
|
||||
const idKey = "id";
|
||||
const idKey = layer === "scada" ? "device_id" : "id";
|
||||
const id = entries.find((entry) => entry.key === idKey)?.value ?? "暂无";
|
||||
const badgeKey = FEATURE_PANEL_BADGE_KEYS[layer];
|
||||
const badgeEntry = badgeKey ? entries.find((entry) => entry.key === badgeKey) : undefined;
|
||||
@@ -420,7 +440,7 @@ export function formatFeaturePropertyValue(key: string, value: unknown) {
|
||||
return OUTFALL_TYPE_LABELS[value.toLowerCase()] ?? value;
|
||||
}
|
||||
|
||||
if (normalizedKey === "gated" && value !== null && value !== undefined && value !== "") {
|
||||
if (["gated", "overflow"].includes(normalizedKey) && value !== null && value !== undefined && value !== "") {
|
||||
return GATED_LABELS[String(value).toLowerCase()] ?? formatValue(value);
|
||||
}
|
||||
|
||||
@@ -452,7 +472,7 @@ export function formatFeaturePropertyValue(key: string, value: unknown) {
|
||||
: formatValue(value);
|
||||
}
|
||||
|
||||
if (["length", "elevation", "invert_elevation", "max_depth", "startup_depth", "shutoff_depth", "distance_to_wwtp_m"].includes(normalizedKey)
|
||||
if (["length", "elevation", "invert_elevation", "max_depth", "startup_depth", "shutoff_depth", "distance_to_wwtp_m", "initial_level", "minimum_level", "maximum_level"].includes(normalizedKey)
|
||||
&& value !== null && value !== undefined && value !== "") {
|
||||
return `${formatValue(value)} m`;
|
||||
}
|
||||
@@ -485,7 +505,7 @@ function getMappedPropertyValue(normalizedKey: string, value: string) {
|
||||
return STATUS_LABELS[normalizedValue];
|
||||
}
|
||||
|
||||
if (normalizedKey === "v_type") {
|
||||
if (normalizedKey === "v_type" || normalizedKey === "valve_type") {
|
||||
return VALVE_TYPE_LABELS[normalizedValue];
|
||||
}
|
||||
|
||||
@@ -493,7 +513,7 @@ function getMappedPropertyValue(normalizedKey: string, value: string) {
|
||||
return MATERIAL_LABELS[normalizedValue];
|
||||
}
|
||||
|
||||
if (normalizedKey === "type") {
|
||||
if (normalizedKey === "type" || normalizedKey === "device_type") {
|
||||
return ASSET_TYPE_LABELS[normalizedValue];
|
||||
}
|
||||
|
||||
@@ -505,7 +525,7 @@ function getMappedPropertyValue(normalizedKey: string, value: string) {
|
||||
return RELIABILITY_LABELS[normalizedValue];
|
||||
}
|
||||
|
||||
if (normalizedKey === "pattern") {
|
||||
if (normalizedKey === "pattern" || normalizedKey === "pattern_id") {
|
||||
return PATTERN_LABELS[normalizedValue];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user