test(M02): 48-2 정의 화면 시나리오 · 종류 줄 · 배치 줄 안 접힘 · 48-1 시나리오 새 화면 고름
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
@@ -156,8 +156,19 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.m02-sod__kindrow {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.m02-sod__kindrow > .m02-opts__kind {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.m02-sod__kindrow > button:not(.m02-opts__kind),
|
||||
.m02-sod__family > button {
|
||||
flex: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.m02-sod__block {
|
||||
@@ -219,9 +230,21 @@
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.m02-sod__place {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.m02-sod__placename {
|
||||
flex: 1 1 8rem;
|
||||
flex: 1 1 6rem;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.m02-sod__place > .m02-sod__num {
|
||||
flex: none;
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.m02-sod__grid {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* - def = { 판 ≥ 1, types: 37, options: 235 }(GET /api/m02/structure-definition)
|
||||
* - types = { types: 37, options: 235, visibleAll: true, pipeGroups: ["관", "관 보호공(유입)", "관 보호공(유출)"] }
|
||||
* (GET /api/projects/structure-types — 옛 꼴 그대로)
|
||||
* - 좌측 「구조물 옵션 보이기」 → 종류 단추 kinds = 37(옵션 없는 종류도 · 옛 화면 그대로)
|
||||
* - 좌측 「구조물 옵션 정의」 → 종류 단추 kinds = 37(옵션 없는 종류도 · 48-2 정의 화면)
|
||||
* · pipe 단추에 그룹 표지 「3」
|
||||
*/
|
||||
(async () => {
|
||||
@@ -41,14 +41,14 @@
|
||||
pipeGroups: pipe.groups.map((g) => g.name),
|
||||
};
|
||||
const row = await until(() => $("[data-options-row]"));
|
||||
if (!row) return JSON.stringify({ ...out, error: "옵션 보이기 줄 없음" });
|
||||
if (!row) return JSON.stringify({ ...out, error: "정의 줄 없음" });
|
||||
row.click();
|
||||
await until(() => $$("[data-options-kind]").length);
|
||||
const kinds = $$("[data-options-kind]");
|
||||
await until(() => $$("[data-sod-kind]").length);
|
||||
const kinds = $$("[data-sod-kind]");
|
||||
out.screen = {
|
||||
kinds: kinds.length,
|
||||
withOptions: def.types.filter((t) => t.options.length).length,
|
||||
pipeTag: $('[data-options-kind="pipe"]')?.innerText.replace(/\s+/g, " ").trim() ?? null,
|
||||
pipeTag: $('[data-sod-kind="pipe"]')?.innerText.replace(/\s+/g, " ").trim() ?? null,
|
||||
};
|
||||
out.ok =
|
||||
out.def.types === 37 &&
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/* 48-2 — M02 구조물 옵션 정의 편집 화면(군 · 종류 · 옵션 · 선택지 · 배치 격자 · 그룹 형상 · 규칙 · 지난 판)
|
||||
* 시작 화면: M02 마스터 템플릿 · 마스터 층(#/m02-master-template?root=master) · 시스템 관리자
|
||||
* 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌 · 20초 안)
|
||||
* 쓰는 것: 없음 — 화면 사본만 고치고 [저장] 안 누름(저장 길은 test_m02_structure_def_screen.py 가 사본으로) ·
|
||||
* 끝에 판이 그대로인지 GET 으로 봄 · 화면을 다시 띄우면 고침은 사라짐
|
||||
* 기대 수치:
|
||||
* - families = 구조물군 수 · kinds = 37 · pipe 줄 options = pipe 옵션 수 · cells = 쓰는 옵션 수 · base = true
|
||||
* - 이름 바꿈 → 왼쪽 단추 글 따라감 · [저장] 켜짐
|
||||
* - 선택지 펼침 = 3(흄관 · VR관 · 파형강관) · 「흄관」 → 「흄관X」 = 기본값 고르기에도 「흄관X」
|
||||
* - 너비 2 → 미리보기 span 2 · 겹치게 두면 issues 에 「배치 겹침」 · [저장] 꺼짐 · 되돌리면 사라짐
|
||||
* - 기준 측점 끔 → 미리보기 기준 측점 칸 0
|
||||
* - 그룹 형상 「길이」 켬 → 뜻 칸 열림
|
||||
* - [규칙 더함] → 규칙 줄 1 · 빨강 아님 · 지우기 → 0
|
||||
* - [지난 판] → 목록 칸(판 단추 또는 「지난 판 없음」)
|
||||
* - 끝 판 = 처음 판(저장 안 함)
|
||||
*/
|
||||
(async () => {
|
||||
const W = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const $ = (s, root = document) => root.querySelector(s);
|
||||
const $$ = (s, root = document) => [...root.querySelectorAll(s)];
|
||||
const until = async (fn, ms = 8000) => {
|
||||
for (let t = 0; t < ms; t += 120) {
|
||||
const v = fn();
|
||||
if (v) return v;
|
||||
await W(120);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
/** 칸 값 바꿈 — 글자 넣음(input) + 떠남(change) */
|
||||
const put = (box, value) => {
|
||||
box.value = value;
|
||||
box.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
box.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
};
|
||||
const tick = (box, on) => {
|
||||
if (box.checked !== on) box.click();
|
||||
};
|
||||
const def = await (
|
||||
await fetch("/api/m02/structure-definition", { credentials: "include" })
|
||||
).json();
|
||||
if (!def.types) return JSON.stringify({ error: "정의 못 읽음" });
|
||||
const pipe = def.types.find((t) => t.type_id === "pipe");
|
||||
const out = { 판: def.판 };
|
||||
|
||||
const row = await until(() => $("[data-options-row]"));
|
||||
if (!row) return JSON.stringify({ error: "정의 줄 없음" });
|
||||
row.click();
|
||||
if (!(await until(() => $$("[data-sod-kind]").length)))
|
||||
return JSON.stringify({ error: "종류 목록 없음" });
|
||||
out.families = [$$("[data-sod-family]").length, Object.keys(def.구조물군).length];
|
||||
out.kinds = $$("[data-sod-kind]").length;
|
||||
$('[data-sod-kind="pipe"]').click();
|
||||
await until(() => $('[data-sod-option="pipe_kind"]'));
|
||||
const liveOpts = pipe.options.filter((o) => o.enabled !== false).length;
|
||||
out.pipe = {
|
||||
options: [$$("[data-sod-option]").length, pipe.options.length],
|
||||
cells: [$$("[data-sod-cell]").length, liveOpts],
|
||||
base: !!$(".m02-sod__cell.is-base"),
|
||||
};
|
||||
|
||||
// 이름 바꿈 → 왼쪽 단추 · [저장] 켜짐
|
||||
put($("[data-sod-kind-name]"), "배수관(시험)");
|
||||
out.rename = {
|
||||
left: $('[data-sod-kind="pipe"]').innerText.includes("배수관(시험)"),
|
||||
save: !$("[data-sod-save]").disabled,
|
||||
};
|
||||
|
||||
// 선택지 펼침 · 이름 바꿈 → 기본값 고르기에도
|
||||
$('[data-sod-choices="pipe_kind"]').click();
|
||||
await until(() => $$("[data-sod-choice]").length);
|
||||
out.choices = $$("[data-sod-choice]").map((r) => $("input", r).value);
|
||||
put($('[data-sod-choice="흄관"] [data-sod-choice-name]'), "흄관X");
|
||||
const defaultPick = $('[data-sod-option="pipe_kind"] [data-sod-default]');
|
||||
out.choiceRename = [...defaultPick.options].some((o) => o.value === "흄관X");
|
||||
|
||||
// 배치 — 너비 2 · 겹침 · 되돌림
|
||||
put($('[data-sod-place-row="pipe_kind"] [data-sod-width]'), "2");
|
||||
const cell = $('[data-sod-cell="pipe_kind"]');
|
||||
out.width2 = cell.style.gridColumn.replace(/\s+/g, " ");
|
||||
const other = pipe.options.filter((o) => o.enabled !== false)[1].key;
|
||||
put($(`[data-sod-place-row="${other}"] [data-sod-row]`), "1");
|
||||
put($(`[data-sod-place-row="${other}"] [data-sod-col]`), "2");
|
||||
out.overlap = {
|
||||
issue: $("[data-sod-issues]").innerText.includes("배치 겹침"),
|
||||
red: $$(".m02-sod__cell.is-bad").length,
|
||||
saveOff: $("[data-sod-save]").disabled,
|
||||
};
|
||||
put($('[data-sod-place-row="pipe_kind"] [data-sod-width]'), "1");
|
||||
out.overlapGone = !$("[data-sod-issues]").innerText.includes("배치 겹침");
|
||||
|
||||
// 기준 측점 끔
|
||||
tick($("[data-sod-base]"), false);
|
||||
out.baseOff = $$(".m02-sod__cell.is-base").length;
|
||||
|
||||
// 그룹 형상 「길이」 켬 → 뜻 칸 열림
|
||||
const shape = $("[data-sog-shape]");
|
||||
const meanBefore = $(".m02-sog__mean", shape).disabled;
|
||||
tick($("[data-sog-shape-0]", shape), true);
|
||||
out.shape = { before: meanBefore, after: $(".m02-sog__mean", $("[data-sog-shape]")).disabled };
|
||||
|
||||
// 규칙 더함 · 지우기
|
||||
$("[data-sod-rule-add]").click();
|
||||
const rule = await until(() => $("[data-sod-rule]"));
|
||||
out.rule = {
|
||||
rows: $$("[data-sod-rule]").length,
|
||||
bad: rule.classList.contains("is-bad"),
|
||||
top: $("[data-sod-rule-top]", rule).value,
|
||||
target: $("[data-sod-rule-target]", rule).value,
|
||||
};
|
||||
[...$$("button", rule)].find((b) => b.innerText.trim() === "지우기").click();
|
||||
out.ruleGone = $$("[data-sod-rule]").length;
|
||||
|
||||
// 지난 판 목록
|
||||
$("[data-sod-history-toggle]").click();
|
||||
await until(() => $("[data-sod-history]").children.length);
|
||||
out.history = $("[data-sod-history]").innerText.replace(/\s+/g, " ").trim().slice(0, 80);
|
||||
|
||||
const after = await (
|
||||
await fetch("/api/m02/structure-definition", { credentials: "include" })
|
||||
).json();
|
||||
out.판그대로 = after.판 === def.판;
|
||||
out.ok =
|
||||
out.families[0] === out.families[1] &&
|
||||
out.kinds === 37 &&
|
||||
out.pipe.options[0] === out.pipe.options[1] &&
|
||||
out.pipe.cells[0] === out.pipe.cells[1] &&
|
||||
out.pipe.base &&
|
||||
out.rename.left &&
|
||||
out.rename.save &&
|
||||
out.choices.length === 3 &&
|
||||
out.choiceRename &&
|
||||
out.width2.includes("span 2") &&
|
||||
out.overlap.issue &&
|
||||
out.overlap.saveOff &&
|
||||
out.overlapGone &&
|
||||
out.baseOff === 0 &&
|
||||
out.shape.before === true &&
|
||||
out.shape.after === false &&
|
||||
out.rule.rows === 1 &&
|
||||
!out.rule.bad &&
|
||||
out.ruleGone === 0 &&
|
||||
out.history.length > 0 &&
|
||||
out.판그대로;
|
||||
return JSON.stringify(out);
|
||||
})();
|
||||
Reference in New Issue
Block a user