feat: implement TagSelector component for improved tag management across dashboard features
- 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.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user