8398cd6f91
- Added TagSelector component to streamline tag selection in various components. - Refactored existing tag handling in DashboardConversationsPage, ConversationTagPicker, EditDialog, and TicketsPage to utilize the new TagSelector. - Removed redundant tag handling functions and optimized state management for tags. - Updated tests to ensure proper functionality of the new tag handling logic.
90 lines
2.1 KiB
TypeScript
90 lines
2.1 KiB
TypeScript
import type { TagTree } from "@/lib/api/admin"
|
|
|
|
export type FlatTagNode = TagTree & {
|
|
depth: number
|
|
path: string
|
|
searchableText: string
|
|
}
|
|
|
|
type FlattenTagTreeOptions = {
|
|
excludeIds?: number[]
|
|
}
|
|
|
|
type FlattenVisibleTagTreeOptions = FlattenTagTreeOptions & {
|
|
collapsedIds?: number[]
|
|
}
|
|
|
|
export function flattenTagTree(
|
|
nodes: TagTree[] | null | undefined,
|
|
options: FlattenTagTreeOptions = {}
|
|
): FlatTagNode[] {
|
|
const excluded = new Set(options.excludeIds ?? [])
|
|
const result: FlatTagNode[] = []
|
|
|
|
function walk(items: TagTree[] | null | undefined, depth: number, parentPath: string) {
|
|
const safeItems = Array.isArray(items) ? items : []
|
|
|
|
safeItems.forEach((item) => {
|
|
if (excluded.has(item.id)) {
|
|
return
|
|
}
|
|
|
|
const path = parentPath ? `${parentPath} / ${item.name}` : item.name
|
|
result.push({
|
|
...item,
|
|
depth,
|
|
path,
|
|
searchableText: `${path} ${item.id} ${item.remark ?? ""}`,
|
|
})
|
|
walk(item.children, depth + 1, path)
|
|
})
|
|
}
|
|
|
|
walk(nodes, 0, "")
|
|
return result
|
|
}
|
|
|
|
export function buildTagPathMap(
|
|
nodes: TagTree[] | null | undefined
|
|
): Map<number, string> {
|
|
const result = new Map<number, string>()
|
|
flattenTagTree(nodes).forEach((item) => {
|
|
result.set(item.id, item.path)
|
|
})
|
|
return result
|
|
}
|
|
|
|
export function flattenVisibleTagTree(
|
|
nodes: TagTree[] | null | undefined,
|
|
options: FlattenVisibleTagTreeOptions = {}
|
|
): FlatTagNode[] {
|
|
const excluded = new Set(options.excludeIds ?? [])
|
|
const collapsed = new Set(options.collapsedIds ?? [])
|
|
const result: FlatTagNode[] = []
|
|
|
|
function walk(items: TagTree[] | null | undefined, depth: number, parentPath: string) {
|
|
const safeItems = Array.isArray(items) ? items : []
|
|
|
|
safeItems.forEach((item) => {
|
|
if (excluded.has(item.id)) {
|
|
return
|
|
}
|
|
|
|
const path = parentPath ? `${parentPath} / ${item.name}` : item.name
|
|
result.push({
|
|
...item,
|
|
depth,
|
|
path,
|
|
searchableText: `${path} ${item.id} ${item.remark ?? ""}`,
|
|
})
|
|
|
|
if (!collapsed.has(item.id)) {
|
|
walk(item.children, depth + 1, path)
|
|
}
|
|
})
|
|
}
|
|
|
|
walk(nodes, 0, "")
|
|
return result
|
|
}
|