공개 primary 네비 트리 중복 방지 (v0.0.101)

- 동일 id 중복 제거, 자식으로 붙은 항목은 루트에서 제외
- spec·history·update 반영

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-12 15:45:17 +09:00
parent 003fb86fad
commit 5031b9de22
5 changed files with 53 additions and 8 deletions

View File

@@ -162,11 +162,38 @@ export const renumberSortOrderByTree = (items, location) => {
/**
* 공개 API용 primary 트리(순환 참조 없음).
* 동일 id가 평면 목록에 중복되거나(시드·이전 마이그레이션 등), 한 행은 루트·다른 행은 자식으로만 잡히면
* 기존 한 루프 방식으로는 같은 노드가 roots와 children에 동시에 들어갈 수 있어, 자식으로 연결된 id는 루트에서 제외한다.
* @param {Array<Object>} flatPrimary - location primary인 항목만
* @returns {Array<Object>}
*/
export const buildPublicPrimaryTree = (flatPrimary) => {
const list = flatPrimary.map((row) => ({
const sorted = [...(flatPrimary || [])].sort((a, b) => {
const sa = a.sortOrder || 0
const sb = b.sortOrder || 0
if (sa !== sb) {
return sa - sb
}
const la = String(a.label || '')
const lb = String(b.label || '')
if (la !== lb) {
return la.localeCompare(lb)
}
return String(a.id).localeCompare(String(b.id))
})
const idSeen = new Set()
const deduped = []
for (const row of sorted) {
const id = String(row.id)
if (idSeen.has(id)) {
continue
}
idSeen.add(id)
deduped.push(row)
}
const list = deduped.map((row) => ({
id: row.id,
label: row.label,
url: row.url,
@@ -177,16 +204,24 @@ export const buildPublicPrimaryTree = (flatPrimary) => {
}))
const byId = new Map(list.map((i) => [String(i.id), { ...i, children: [] }]))
const roots = []
const attachedAsChild = new Set()
for (const row of list) {
const id = String(row.id)
const node = byId.get(id)
const p = row.parentId
if (p && byId.has(String(p))) {
byId.get(String(p)).children.push(node)
} else {
roots.push(node)
const pid = p != null && String(p).trim() !== '' ? String(p).trim() : ''
if (pid && pid !== id && byId.has(pid)) {
byId.get(pid).children.push(node)
attachedAsChild.add(id)
}
}
const roots = []
for (const row of list) {
const id = String(row.id)
if (!attachedAsChild.has(id)) {
roots.push(byId.get(id))
}
}