지움
- flushDesignStore(design_store · 부름 0) — 시험 344-4 의 flush 대조 한 줄도
- b_page_state 옛 세션 열쇠 옮김(legacy · migrate) · b_project_switch 옛 키 머리
— 옛 열쇠는 세션 저장소(탭 닫으면 사라짐) · 지금 코드가 안 씀 · storage · DB 에 없음
· 시험 290-1 · 401 · 384-1 의 옛 키 줄 뺌
- 시험만 부르던 TS — planFootprint(346-2 거울은 footprintRecord + slopePieces 로 그대로)
· shiftSegment · shiftMovingPoints(쉬프트 단추는 09-02 지움 · min_cover_guard 쉬프트 시험 뺌)
· dropStationsNear(test_b05_station_merge.mjs 지움) · createIrregularStationsSection(부름 0)
· generalStations(234-1 은 기본 맞춤 값으로 같은 것 잼) · sameSummaryItem
- test_b05_b06_save_roundtrip + helper_b05_save_payload 둘 — 프로젝트 936be972 storage 없어 늘 skip
· 같은 저장 왕복은 test_472_6_design_save(창구 원자성) · test_449_save_pipes(관 PUT)
· test_238_1_save_keeps_structure_stations(구조물 측점)가 잼
남김
- migrateLegacyStations — 부르는 곳 있음(design_view_profile_sections) · storage 에 비정규 측점 남음
- common_util_excavation 셋 — 지금은 운영이 부름(design_calc_node)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
88 lines
3.7 KiB
TypeScript
88 lines
3.7 KiB
TypeScript
/* =============================================================================
|
|
* common_util_summary_item.ts
|
|
* 구조물 집계표 항목 참조(PLAN 21-1) — 구조물 · 관 지점이 「어느 집계표 항목」인지 가리키는 값.
|
|
*
|
|
* summary_item: { layer: "system"|"company"|"personal", owner: null|"{회사}"|"{회사}/{사용자}",
|
|
* key: "SS000004", name: "돌기슭막이 메쌓기 1.2m" }
|
|
*
|
|
* 없으면 null(= 미지정 · 집계표에 안 들어감). 옵션(options) 밖의 칸이다.
|
|
* import 없음 — 시험이 이 파일만 옮겨 돌림.
|
|
* ========================================================================== */
|
|
|
|
export type SummaryLayer = "system" | "company" | "personal";
|
|
|
|
export interface SummaryItem {
|
|
layer: SummaryLayer;
|
|
owner: string | null;
|
|
key: string;
|
|
name: string;
|
|
}
|
|
|
|
const LAYERS: readonly string[] = ["system", "company", "personal"];
|
|
|
|
/** 참조 모양이 맞는가 — 서버 응답 · 세션 초안을 읽을 때 걸러 쓴다. */
|
|
export function isSummaryItem(value: unknown): value is SummaryItem {
|
|
if (!value || typeof value !== "object") return false;
|
|
const item = value as Record<string, unknown>;
|
|
return (
|
|
typeof item.layer === "string" &&
|
|
LAYERS.includes(item.layer) &&
|
|
(item.owner === null || typeof item.owner === "string") &&
|
|
typeof item.key === "string" &&
|
|
item.key !== "" &&
|
|
typeof item.name === "string"
|
|
);
|
|
}
|
|
|
|
/** 서버 · 세션에서 온 값을 참조 또는 null 로 — 모양이 틀리면 null(미지정). */
|
|
export function readSummaryItem(value: unknown): SummaryItem | null {
|
|
return isSummaryItem(value) ? value : null;
|
|
}
|
|
|
|
/** 옵션 그룹(M02 PLAN 46)마다 고른 항목 `{그룹 id: 참조}` — 본체는 `summary_item`. */
|
|
export type GroupItems = Record<string, SummaryItem>;
|
|
|
|
/** 그룹 복사본 id 잇개 — `{구조물 id}__{그룹 id}`(서버 `GROUP_JOIN` 과 짝). */
|
|
export const GROUP_JOIN = "__";
|
|
|
|
/** 서버 · 세션 값을 그룹 참조 묶음으로 — 모양이 틀린 항목은 뺌 · 없으면 빈 묶음. */
|
|
export function readGroupItems(value: unknown): GroupItems {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
return Object.fromEntries(
|
|
Object.entries(value as Record<string, unknown>).filter(
|
|
(entry): entry is [string, SummaryItem] =>
|
|
/^g[0-9a-z]{1,16}$/.test(entry[0]) && isSummaryItem(entry[1]),
|
|
),
|
|
);
|
|
}
|
|
|
|
/** 저장 · 이음에 실을 연결 칸 — 지정한 것만(본체 `summary_item` · 그룹 `group_items`). */
|
|
export function linkFields(source: { summary_item?: unknown; group_items?: unknown }): {
|
|
summary_item?: SummaryItem;
|
|
group_items?: GroupItems;
|
|
} {
|
|
const summary = readSummaryItem(source.summary_item);
|
|
const groups = readGroupItems(source.group_items);
|
|
return {
|
|
...(summary ? { summary_item: summary } : {}),
|
|
...(Object.keys(groups).length ? { group_items: groups } : {}),
|
|
};
|
|
}
|
|
|
|
/** 연결이 하나라도 있나 — 본체 또는 그룹. */
|
|
export function hasLinks(source: { summary_item?: unknown; group_items?: unknown }): boolean {
|
|
return Object.keys(linkFields(source)).length > 0;
|
|
}
|
|
|
|
/** 표시 글 — 이름(없으면 「미지정」). 키는 앞에 내세우지 않는다(PLAN 21-0). */
|
|
export function summaryLabel(item: SummaryItem | null): string {
|
|
return item ? item.name || item.key : "미지정";
|
|
}
|
|
|
|
/** 툴팁 — 이름 + 어느 그룹 것인지 · 키는 작은 글로만. */
|
|
export function summaryTooltip(item: SummaryItem | null): string {
|
|
if (!item) return "집계 항목 미지정 — 집계표에 안 들어감";
|
|
const group = { system: "마스터", company: "회사용", personal: "개인용" }[item.layer];
|
|
return `${item.name} · ${group} · ${item.key}`;
|
|
}
|