diff --git a/M01_MasterData/M01_MasterData_UI_Side.ts b/M01_MasterData/M01_MasterData_UI_Side.ts index 4fe29ef8..3b132e30 100644 --- a/M01_MasterData/M01_MasterData_UI_Side.ts +++ b/M01_MasterData/M01_MasterData_UI_Side.ts @@ -186,7 +186,7 @@ export function buildSide( ? [] : [ el("span", { - className: "m01-side__muted", + className: "ui-tree__count", text: node.count.toLocaleString("ko-KR"), }), ]), diff --git a/resources/tester/ui/item-picker-data.test.ts b/resources/tester/ui/item-picker-data.test.ts index 8e0c62bc..be8ffa93 100644 --- a/resources/tester/ui/item-picker-data.test.ts +++ b/resources/tester/ui/item-picker-data.test.ts @@ -11,6 +11,8 @@ import { itemName, pathIds, rowId, + rowTip, + shown, toSummary, type PickerRow, type TreeLabels, @@ -72,6 +74,33 @@ assert.equal(itemName(rows[6]), "옹벽 H=2m"); assert.equal(itemName({ key: "SS000009", 열: "zz" }), "zz"); assert.equal(itemName({ key: "SS000009", 열: "" }), "SS000009"); +// 「새 분류N」 자리표는 이름 · 나무 이름에서 뺌 +assert.equal(shown("새 분류1"), ""); +assert.equal(shown("새 분류 12"), ""); +assert.equal(shown("새 분류"), ""); +assert.equal(shown("새 분류표"), "새 분류표"); // 자리표가 아닌 진짜 이름은 그대로 +assert.equal(shown(undefined), ""); +const fresh = row("SS000300", "n1", "새 분류1", ["새 분류2", "", ""], "personal", { + 분류3: "새 분류3", +}); +assert.equal(itemName(fresh), "n1"); // 이름이 모두 자리표면 열 id +assert.equal( + itemName(row("SS000301", "n2", "옹벽", ["새 분류1", "H=2m", ""], "personal")), + "옹벽 H=2m", +); +const placeholderTree = buildTree([fresh], labels); +assert.equal(placeholderTree[2].children?.[0].label, "분류 없음"); // 종류 +assert.equal(placeholderTree[2].children?.[0].children?.[0].label, "분류 없음"); // 분류1 +assert.deepEqual(pathIds(fresh, labels), [ + "personal", + "personal|분류 없음", + "personal|분류 없음|분류 없음", +]); + +// 툴팁 = 층 이름 + 키 +assert.equal(rowTip(rows[7], labels), "개인 · SS000201"); +assert.equal(rowTip(rows[5], labels), "회사 · SS000101"); + // 나무 — 그룹은 늘 마스터 · 회사 · 개인 차례 · 그룹 → 종류 → 분류1 → 잎 const tree = buildTree(rows, labels); assert.deepEqual( @@ -96,7 +125,7 @@ assert.equal(cat?.label, "메쌓기"); assert.equal(cat?.count, 2); const leaf = cat?.children?.[0]; assert.equal(leaf?.label, "돌기슭막이 메쌓기 1.2m 기초유"); -assert.equal(leaf?.tip, "SS000001"); // 키는 툴팁 +assert.equal(leaf?.tip, "마스터 · SS000001"); // 툴팁 = 층 이름 + 키 assert.equal(leaf?.count, null); assert.ok(leaf?.row); diff --git a/ui_template/ui_template_item_picker.css b/ui_template/ui_template_item_picker.css index 26356c04..fa14a514 100644 --- a/ui_template/ui_template_item_picker.css +++ b/ui_template/ui_template_item_picker.css @@ -57,7 +57,7 @@ .ui-item-picker__where, .ui-item-picker__hint { margin: 0; - color: var(--color-text-muted); + color: var(--color-text-secondary); font-size: var(--text-caption); } @@ -87,16 +87,16 @@ .ui-item-picker__folder-label { flex: 0 0 5.5em; - color: var(--color-text-muted); + color: var(--color-text-secondary); } .ui-item-picker__key { - color: var(--color-text-muted); + color: var(--color-text-secondary); font-size: 11px; } .ui-item-picker__none { - color: var(--color-text-muted); + color: var(--color-text-secondary); } .ui-item-picker__actions { diff --git a/ui_template/ui_template_item_picker.ts b/ui_template/ui_template_item_picker.ts index f441d22e..aef2bf73 100644 --- a/ui_template/ui_template_item_picker.ts +++ b/ui_template/ui_template_item_picker.ts @@ -20,6 +20,8 @@ import { ownerOf, pathIds, rowId, + rowTip, + shown, toSummary, type FolderKind, type PickNode, @@ -127,7 +129,7 @@ export function openItemPicker(opts: ItemPickerOptions): Promise @@ -136,7 +138,7 @@ export function openItemPicker(opts: ItemPickerOptions): Promise + part && !PLACEHOLDER.test(part.trim()) ? part : ""; + +/** 보이는 항목 이름 — 종류 · 분류1~3 을 이음(자리표는 뺌 · 비면 열 id · 키) */ export const itemName = (row: PickerRow): string => - [row.종류, row.분류1, row.분류2, row.분류3].filter(Boolean).join(" ") || row.열 || row.key; + [row.종류, row.분류1, row.분류2, row.분류3].map(shown).filter(Boolean).join(" ") || + row.열 || + row.key; + +/** 마우스를 올렸을 때 — 층 이름 + 키 */ +export const rowTip = (row: PickerRow, labels: TreeLabels): string => + `${labels.layers[layerOf(row)]} · ${row.key}`; export const layerOf = (row: PickerRow): PickerLayer => row.layer ?? "system"; export const ownerOf = (row: PickerRow): string | null => @@ -108,8 +119,8 @@ export function buildTree(rows: PickerRow[], labels: TreeLabels): PickNode[] { const mine = rows.filter((row) => layerOf(row) === layer); const kinds = new Map>(); for (const row of mine) { - const kind = row.종류 || labels.unclassified; - const cat = row.분류1 || labels.unclassified; + const kind = shown(row.종류) || labels.unclassified; + const cat = shown(row.분류1) || labels.unclassified; const cats = kinds.get(kind) ?? new Map(); cats.set(cat, [...(cats.get(cat) ?? []), row]); kinds.set(kind, cats); @@ -122,7 +133,7 @@ export function buildTree(rows: PickerRow[], labels: TreeLabels): PickNode[] { children: leaves.map((row) => ({ id: rowId(row), label: itemName(row), - tip: row.key, + tip: rowTip(row, labels), count: null, row, })), @@ -141,8 +152,8 @@ export function buildTree(rows: PickerRow[], labels: TreeLabels): PickNode[] { /** 잎까지 가는 길의 나무 줄 id — 처음부터 펼칠 자리 */ export function pathIds(row: PickerRow, labels: TreeLabels): string[] { const layer = layerOf(row); - const kind = row.종류 || labels.unclassified; - const cat = row.분류1 || labels.unclassified; + const kind = shown(row.종류) || labels.unclassified; + const cat = shown(row.분류1) || labels.unclassified; return [layer, `${layer}|${kind}`, `${layer}|${kind}|${cat}`]; } diff --git a/ui_template/ui_template_tree.css b/ui_template/ui_template_tree.css index 228ae44f..a8a47253 100644 --- a/ui_template/ui_template_tree.css +++ b/ui_template/ui_template_tree.css @@ -14,10 +14,10 @@ .ui-tree__caret { display: inline-block; width: var(--spacing-12); - color: var(--color-text-muted); + color: var(--color-text-secondary); } .ui-tree__count { - color: var(--color-text-muted); + color: var(--color-text-secondary); font-size: var(--text-caption); }