- 정의 덧칸 얹기 — GET /m02/structure-definition 의 구조물군 이름 · 기준측점 · 동작 · 배치 · 규칙 · 그룹 형상을 종류에 얹음(못 받으면 옛 화면 그대로)
- 레지스트리 칸 — 배치(줄 · 칸 · 너비) 격자 · 차례 · 안 씀(enabled:false) · 규칙(선택지 · 보이기 · 기본값) 즉시 적용 · 규칙이 가린 칸은 저장 안 건드림
- 손코딩 시설 폼(동작 계곡통과시설) — 안 씀 · 선택지 · 규칙을 칸 표식으로 붙임 · 배치 · 이름은 손코딩 그대로
- 지난 정의 값 — 지금 정의에 없는 키 값을 읽기만 상자로
- 그룹 형상 칸 — 길이 · 높이 · 전 · 후 받기 켬끔 · 값은 옵션 {그룹 id}__{칸}
- 정의에서 뺀 선택지를 고른 옛 값은 그 값만 남겨 보임
- 시험 test_b05_structures_define 8 · 헬퍼 문맥 groupBoxes 로
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
86 lines
4.2 KiB
TypeScript
86 lines
4.2 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Structures_Define_Form.ts
|
|
* 손코딩 시설 폼(동작 「계곡통과시설」)에 정의를 붙임(PLAN 48-3 · 48-4) — 숨긴 선택지 · 규칙.
|
|
*
|
|
* · 칸은 `labeled(..., 옵션키)` 가 붙인 `data-option-keys` 표식으로 찾음(키 하나인 칸만) · 찾는 자리 =
|
|
* 폼 본문 전체(그룹 상자로 옮겨 간 칸까지).
|
|
* · 칸 배치 · 이름은 손코딩 그대로(동작이 그림) — 안 씀은 끈 옵션과 같은 길(`_Drainage_Facility_Hidden`).
|
|
* · 선택지 = 정의 · 규칙 선택지 — 새 선택지는 보기를 더하고 밖 보기는 `hidden` 으로만 가림(옛 값은 그대로).
|
|
* 여러 키를 함께 적는 칸(유입구 구조 · 본체 규격)은 키 하나 표식이 아니라 안 건드림.
|
|
* · 규칙이 가린 칸 = `is-rule-hidden`(끈 옵션 표식 `is-option-hidden` 과 따로).
|
|
* ========================================================================== */
|
|
|
|
import type { StructureType } from "./B05_Profile_Api_Structures";
|
|
import { ruleDefaults, ruleStates } from "./B05_Profile_UI_Structures_Define";
|
|
import { isOptionVisible } from "./B05_Profile_UI_Structures_Summary";
|
|
|
|
/** 시설 폼이 가릴 옵션 키 — 「구조물 옵션 보이기」에서 끈 것 + 정의 「안 씀」. */
|
|
export function hiddenOptionKeys(type: StructureType | null): string[] {
|
|
return (type?.options ?? []).filter((o) => !isOptionVisible(o)).map((o) => o.key);
|
|
}
|
|
|
|
export interface FacilityDefinition {
|
|
/** 지금 종류 정의로 칸 모양을 맞춤 — 시설 폼을 채운 뒤마다 부름. */
|
|
apply: (type: StructureType | null) => void;
|
|
}
|
|
|
|
export function createFacilityDefinition(root: HTMLElement): FacilityDefinition {
|
|
let type: StructureType | null = null;
|
|
const wrapOf = (key: string): HTMLElement | null =>
|
|
[...root.querySelectorAll<HTMLElement>("[data-option-keys]")].find(
|
|
(node) => node.dataset.optionKeys === key,
|
|
) ?? null;
|
|
const controlOf = (key: string): HTMLInputElement | HTMLSelectElement | null =>
|
|
wrapOf(key)?.querySelector<HTMLInputElement | HTMLSelectElement>("select, input") ?? null;
|
|
const values = (): Record<string, string> =>
|
|
Object.fromEntries((type?.options ?? []).map((o) => [o.key, controlOf(o.key)?.value ?? ""]));
|
|
|
|
const paint = (): void => {
|
|
if (!type) return;
|
|
const states = ruleStates(type, values());
|
|
for (const option of type.options) {
|
|
const wrap = wrapOf(option.key);
|
|
const state = states.get(option.key);
|
|
if (!wrap || !state) continue;
|
|
wrap.classList.toggle("is-rule-hidden", !state.visible);
|
|
const control = controlOf(option.key);
|
|
if (!(control instanceof HTMLSelectElement)) continue;
|
|
// 정의에 새로 든 선택지는 보기를 더하고, 정의 · 규칙 밖 보기는 가림(빈 보기 · 지금 값은 그대로)
|
|
const have = new Set([...control.options].map((item) => item.value));
|
|
for (const choice of state.choices)
|
|
if (!have.has(choice)) control.add(new Option(choice, choice));
|
|
for (const item of control.options) {
|
|
item.hidden =
|
|
!!item.value && !state.choices.includes(item.value) && item.value !== control.value;
|
|
}
|
|
}
|
|
};
|
|
|
|
// 상위 칸이 바뀌면 걸린 규칙의 기본값을 하위 칸에 넣고, 그 칸의 change 로 폼 반영(시설 폼 emit)을 잇는다.
|
|
root.addEventListener("change", (event) => {
|
|
if (!type) return;
|
|
const key = (event.target as HTMLElement).closest<HTMLElement>("[data-option-keys]")?.dataset
|
|
.optionKeys;
|
|
if (key) {
|
|
for (const [child, value] of Object.entries(ruleDefaults(type, key, values()))) {
|
|
const control = controlOf(child);
|
|
if (!control || control.value === String(value)) continue;
|
|
control.value = String(value);
|
|
control.dispatchEvent(new Event("change", { bubbles: true }));
|
|
}
|
|
}
|
|
paint();
|
|
});
|
|
|
|
return {
|
|
apply(next) {
|
|
type = next;
|
|
root
|
|
.querySelectorAll(".is-rule-hidden")
|
|
.forEach((node) => node.classList.remove("is-rule-hidden"));
|
|
root.querySelectorAll<HTMLOptionElement>("option[hidden]").forEach((o) => (o.hidden = false));
|
|
paint();
|
|
},
|
|
};
|
|
}
|