поправлен маппинг с отсортированными элементами в инпутах
This commit is contained in:
@@ -1457,7 +1457,7 @@
|
|||||||
.hockey-map-target-hint{flex:0 0 auto;display:grid;gap:2px;margin:10px 10px 0;padding:9px 10px;border:1px dashed #3a4b61;border-radius:10px;background:#101923}.hockey-map-target-hint.is-active{border-style:solid;border-color:#39bfa2;background:rgba(72,223,189,.07)}.hockey-map-target-hint span{font-size:9px;font-weight:900;letter-spacing:.08em;color:#7f93aa}.hockey-map-target-hint strong{font-size:12px;color:#e6f0fb}.hockey-map-target-hint small{font-size:10px;color:#7f93aa}
|
.hockey-map-target-hint{flex:0 0 auto;display:grid;gap:2px;margin:10px 10px 0;padding:9px 10px;border:1px dashed #3a4b61;border-radius:10px;background:#101923}.hockey-map-target-hint.is-active{border-style:solid;border-color:#39bfa2;background:rgba(72,223,189,.07)}.hockey-map-target-hint span{font-size:9px;font-weight:900;letter-spacing:.08em;color:#7f93aa}.hockey-map-target-hint strong{font-size:12px;color:#e6f0fb}.hockey-map-target-hint small{font-size:10px;color:#7f93aa}
|
||||||
.hockey-map-data-search{flex:0 0 auto;display:flex;align-items:center;gap:7px;margin:10px;padding:0 10px;height:38px;border:1px solid #33475f;border-radius:9px;background:#0b141f;color:#48dfbd}.hockey-map-data-search input{width:100%;min-width:0;border:0;outline:0;background:transparent;color:#eaf4ff;font-size:12px}.hockey-map-data-search input::placeholder{color:#667d96}
|
.hockey-map-data-search{flex:0 0 auto;display:flex;align-items:center;gap:7px;margin:10px;padding:0 10px;height:38px;border:1px solid #33475f;border-radius:9px;background:#0b141f;color:#48dfbd}.hockey-map-data-search input{width:100%;min-width:0;border:0;outline:0;background:transparent;color:#eaf4ff;font-size:12px}.hockey-map-data-search input::placeholder{color:#667d96}
|
||||||
.hockey-map-data-scroll,.hockey-map-vmix-scroll{min-height:0;flex:1;overflow:auto;padding:0 9px 10px}
|
.hockey-map-data-scroll,.hockey-map-vmix-scroll{min-height:0;flex:1;overflow:auto;padding:0 9px 10px}
|
||||||
.hockey-map-data-group{border-bottom:1px solid #24354a}.hockey-map-data-group summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 4px;color:#b9c8d9;font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:.04em}.hockey-map-data-group summary::-webkit-details-marker{display:none}.hockey-map-data-group summary b{min-width:23px;padding:3px 6px;border-radius:999px;background:#1d3047;color:#8ea6c0;font-size:9px;text-align:center}.hockey-map-data-group>div{display:grid;gap:6px;padding:0 0 9px}
|
.hockey-map-data-group{border-bottom:1px solid #24354a}.hockey-map-data-group summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:10px 4px;color:#b9c8d9;font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:.04em}.hockey-map-data-group summary::-webkit-details-marker{display:none}.hockey-map-data-group summary>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hockey-map-data-group summary b{margin-left:auto;min-width:23px;padding:3px 6px;border-radius:999px;background:#1d3047;color:#8ea6c0;font-size:9px;text-align:center;flex:0 0 auto}.hockey-map-data-group summary::after{width:14px;flex:0 0 14px;text-align:center}.hockey-map-data-group>div{display:grid;gap:6px;padding:0 0 9px}
|
||||||
.hockey-map-data-item{width:100%;display:grid;gap:3px;text-align:left;padding:8px 9px;border:1px solid #293c52;border-radius:9px;background:#121d2a;color:#dce8f5;cursor:pointer}.hockey-map-data-item:hover,.hockey-map-data-item.is-selected{border-color:#48dfbd;background:#142a2b}.hockey-map-data-main{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px}.hockey-map-data-main strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hockey-map-data-main em{max-width:150px;font-style:normal;font-size:11px;font-weight:900;color:#48dfbd;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hockey-map-data-item small{font:9px/1.2 Consolas,monospace;color:#667b93;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
.hockey-map-data-item{width:100%;display:grid;gap:3px;text-align:left;padding:8px 9px;border:1px solid #293c52;border-radius:9px;background:#121d2a;color:#dce8f5;cursor:pointer}.hockey-map-data-item:hover,.hockey-map-data-item.is-selected{border-color:#48dfbd;background:#142a2b}.hockey-map-data-main{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px}.hockey-map-data-main strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hockey-map-data-main em{max-width:150px;font-style:normal;font-size:11px;font-weight:900;color:#48dfbd;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hockey-map-data-item small{font:9px/1.2 Consolas,monospace;color:#667b93;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||||
.hockey-map-vmix-browser>header>div:first-child{display:grid;gap:4px;min-width:0;flex:1}.hockey-map-vmix-browser>header select{width:min(540px,100%);min-height:34px;border:1px solid #39495f;border-radius:8px;background:#0d1520;color:#edf5ff;padding:5px 8px;font-weight:750}.hockey-map-input-progress{display:flex;align-items:baseline;gap:4px;white-space:nowrap}.hockey-map-input-progress b{font-size:20px;color:#48dfbd}.hockey-map-input-progress span{font-size:10px;color:#8094aa}
|
.hockey-map-vmix-browser>header>div:first-child{display:grid;gap:4px;min-width:0;flex:1}.hockey-map-vmix-browser>header select{width:min(540px,100%);min-height:34px;border:1px solid #39495f;border-radius:8px;background:#0d1520;color:#edf5ff;padding:5px 8px;font-weight:750}.hockey-map-input-progress{display:flex;align-items:baseline;gap:4px;white-space:nowrap}.hockey-map-input-progress b{font-size:20px;color:#48dfbd}.hockey-map-input-progress span{font-size:10px;color:#8094aa}
|
||||||
.hockey-map-vmix-scroll{display:grid;align-content:start;gap:8px;padding:10px}
|
.hockey-map-vmix-scroll{display:grid;align-content:start;gap:8px;padding:10px}
|
||||||
|
|||||||
@@ -1338,16 +1338,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mappingInventoryInputs(profile) {
|
function mappingInventoryInputs(profile) {
|
||||||
const inputs = Array.isArray(profile?.inventory?.inputs) ? [...profile.inventory.inputs] : [];
|
// Preserve the exact Input sequence received from the vMix API via Agent.
|
||||||
const numberValue = (item) => {
|
// The array order is presentation-only: stable Mapping identity still uses
|
||||||
const match = String(item?.number ?? "").match(/\d+/);
|
// key -> unique title -> number, so changing Input positions does not break links.
|
||||||
return match ? Number(match[0]) : Number.MAX_SAFE_INTEGER;
|
return Array.isArray(profile?.inventory?.inputs) ? [...profile.inventory.inputs] : [];
|
||||||
};
|
|
||||||
return inputs.sort((a, b) => {
|
|
||||||
const diff = numberValue(a) - numberValue(b);
|
|
||||||
if (diff) return diff;
|
|
||||||
return String(a?.title || a?.key || "").localeCompare(String(b?.title || b?.key || ""), "ru", { numeric: true, sensitivity: "base" });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mappingInputByKey(profile, key, title = "") {
|
function mappingInputByKey(profile, key, title = "") {
|
||||||
|
|||||||
28
tests/test_build79_mapping_alignment_input_order.py
Normal file
28
tests/test_build79_mapping_alignment_input_order.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
JS = (ROOT / "hockey_data/static/admin-directories.js").read_text(encoding="utf-8")
|
||||||
|
CSS = (ROOT / "hockey_data/static/admin-directories.css").read_text(encoding="utf-8")
|
||||||
|
AGENT = (ROOT / "hockey_data/agent_bridge.py").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def test_mapping_data_group_count_is_right_aligned_before_fixed_arrow():
|
||||||
|
assert ".hockey-map-data-group summary b{margin-left:auto" in CSS
|
||||||
|
assert ".hockey-map-data-group summary::after{width:14px;flex:0 0 14px;text-align:center}" in CSS
|
||||||
|
assert ".hockey-map-data-group summary>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}" in CSS
|
||||||
|
|
||||||
|
|
||||||
|
def test_mapping_vmix_input_selector_preserves_inventory_api_order():
|
||||||
|
start = JS.index("function mappingInventoryInputs(profile)")
|
||||||
|
end = JS.index("function mappingInputByKey", start)
|
||||||
|
block = JS[start:end]
|
||||||
|
assert "return Array.isArray(profile?.inventory?.inputs) ? [...profile.inventory.inputs] : [];" in block
|
||||||
|
assert ".sort(" not in block
|
||||||
|
assert "numberValue" not in block
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_preserves_agent_inventory_array_order():
|
||||||
|
# receive_inventory iterates the Agent-provided inputs and appends in that order.
|
||||||
|
assert "for raw_input in inputs:" in AGENT
|
||||||
|
assert "clean_inputs.append({" in AGENT
|
||||||
|
assert '"inputs": clean_inputs' in AGENT
|
||||||
@@ -17,13 +17,13 @@ def test_mapping_load_is_resilient_per_endpoint():
|
|||||||
assert 'Часть Mapping API недоступна' in JS
|
assert 'Часть Mapping API недоступна' in JS
|
||||||
|
|
||||||
|
|
||||||
def test_visual_mapping_has_sql_table_cell_picker_and_searchable_ordered_inputs():
|
def test_visual_mapping_has_sql_table_cell_picker_and_searchable_api_order_inputs():
|
||||||
assert 'data-map-table-source' in JS
|
assert 'data-map-table-source' in JS
|
||||||
assert 'data-map-table-row-search' in JS
|
assert 'data-map-table-row-search' in JS
|
||||||
assert '.row.${row.index}.' in JS
|
assert '.row.${row.index}.' in JS
|
||||||
assert 'data-map-input-search' in JS
|
assert 'data-map-input-search' in JS
|
||||||
assert 'mappingFilteredInputs' in JS
|
assert 'mappingFilteredInputs' in JS
|
||||||
assert 'return inputs.sort' in JS
|
assert 'return Array.isArray(profile?.inventory?.inputs) ? [...profile.inventory.inputs] : [];' in JS
|
||||||
|
|
||||||
|
|
||||||
def test_visual_mapping_has_explicit_sql_cell_dropdowns_and_apply_input():
|
def test_visual_mapping_has_explicit_sql_cell_dropdowns_and_apply_input():
|
||||||
|
|||||||
Reference in New Issue
Block a user