diff --git a/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionSearchTreeAdapter.ts b/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionSearchTreeAdapter.ts index 0e2f01bf9..65314a418 100644 --- a/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionSearchTreeAdapter.ts +++ b/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionSearchTreeAdapter.ts @@ -1,9 +1,39 @@ import { HoppCollection } from "@hoppscotch/data" import { ChildrenResult, SmartTreeAdapter } from "@hoppscotch/ui" import { Ref, computed } from "vue" -import { navigateToFolderWithIndexPath } from "~/newstore/collections" import { RESTCollectionViewItem } from "~/services/new-workspace/view" +// Shape covers both `HoppCollection` (personal — uses `folders`) and +// `TeamCollection` (teams — uses `children`). Normalized at access time +// so a single adapter handles both workspaces. +type SearchTreeNode = { + name?: string + title?: string + folders?: SearchTreeNode[] | null + children?: SearchTreeNode[] | null + requests?: Array<{ name?: string; title?: string; [key: string]: unknown }> | null +} + +const getChildCollections = (node: SearchTreeNode): SearchTreeNode[] => + node.folders ?? node.children ?? [] + +const getNodeName = (node: SearchTreeNode): string => + node.name ?? node.title ?? "" + +// Local tree walk — does not depend on `folders` shape unlike the +// personal-workspace `navigateToFolderWithIndexPath` helper. +const navigateToNode = ( + roots: SearchTreeNode[], + indexPath: number[] +): SearchTreeNode | null => { + if (indexPath.length === 0) return null + let current: SearchTreeNode | undefined = roots[indexPath[0]] + for (let i = 1; i < indexPath.length && current; i++) { + current = getChildCollections(current)[indexPath[i]] + } + return current ?? null +} + export class WorkspaceRESTSearchCollectionTreeAdapter implements SmartTreeAdapter { @@ -13,18 +43,20 @@ export class WorkspaceRESTSearchCollectionTreeAdapter nodeID: string | null ): Ref> { return computed(() => { + const roots = this.data.value as unknown as SearchTreeNode[] + if (nodeID === null) { return { status: "loaded" as const, - data: this.data.value.map((item, index) => ({ + data: roots.map((item, index) => ({ id: index.toString(), data: { type: "collection", value: { collectionID: index.toString(), - isLastItem: index === this.data.value.length - 1, - name: item.name, + isLastItem: index === roots.length - 1, + name: getNodeName(item), parentCollectionID: null, }, }, @@ -33,11 +65,11 @@ export class WorkspaceRESTSearchCollectionTreeAdapter } const indexPath = nodeID.split("/").map((x) => parseInt(x, 10)) - - const item = navigateToFolderWithIndexPath(this.data.value, indexPath) + const item = navigateToNode(roots, indexPath) if (item) { - const collections = item.folders.map( + const childCollections = getChildCollections(item) + const collections = childCollections.map( (childCollection, childCollectionID) => { return { id: `${nodeID}/${childCollectionID}`, @@ -45,9 +77,9 @@ export class WorkspaceRESTSearchCollectionTreeAdapter type: "collection", value: { isLastItem: - childCollectionID === item.folders.length - 1, + childCollectionID === childCollections.length - 1, collectionID: `${nodeID}/${childCollectionID}`, - name: childCollection.name, + name: getNodeName(childCollection), parentCollectionID: nodeID, }, }, @@ -55,14 +87,14 @@ export class WorkspaceRESTSearchCollectionTreeAdapter } ) - const requests = item.requests.map((request, requestID) => { + const requestsList = item.requests ?? [] + const requests = requestsList.map((request, requestID) => { return { id: `${nodeID}/${requestID}`, data: { type: "request", value: { - isLastItem: - requestID === item.requests.length - 1, + isLastItem: requestID === requestsList.length - 1, parentCollectionID: nodeID, collectionID: nodeID, requestID: `${nodeID}/${requestID}`,