diff --git a/packages/hoppscotch-common/src/services/new-workspace/index.ts b/packages/hoppscotch-common/src/services/new-workspace/index.ts index 448b640c3..b07e35dfd 100644 --- a/packages/hoppscotch-common/src/services/new-workspace/index.ts +++ b/packages/hoppscotch-common/src/services/new-workspace/index.ts @@ -15,6 +15,7 @@ import { Workspace, WorkspaceCollection, WorkspaceRequest } from "./workspace" import { RESTCollectionChildrenView, RESTCollectionLevelAuthHeadersView, + RESTSearchResultsView, RootRESTCollectionView, } from "./view" import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data" @@ -687,6 +688,39 @@ export class NewWorkspaceService extends Service { return E.right(result.right) } + public async getRESTSearchResultsView( + workspaceHandle: HandleRef, + searchQuery: Ref + ): Promise< + E.Either< + WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, + HandleRef + > + > { + if (workspaceHandle.value.type === "invalid") { + return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" }) + } + + const provider = this.registeredProviders.get( + workspaceHandle.value.data.providerID + ) + + if (!provider) { + return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" }) + } + + const result = await provider.getRESTSearchResultsView( + workspaceHandle, + searchQuery + ) + + if (E.isLeft(result)) { + return E.left({ type: "PROVIDER_ERROR", error: result.left }) + } + + return E.right(result.right) + } + public registerWorkspaceProvider(provider: WorkspaceProvider) { if (this.registeredProviders.has(provider.providerID)) { console.warn( diff --git a/packages/hoppscotch-common/src/services/new-workspace/provider.ts b/packages/hoppscotch-common/src/services/new-workspace/provider.ts index 34de31035..f311c8bc4 100644 --- a/packages/hoppscotch-common/src/services/new-workspace/provider.ts +++ b/packages/hoppscotch-common/src/services/new-workspace/provider.ts @@ -11,6 +11,7 @@ import { RESTCollectionLevelAuthHeadersView, RESTCollectionChildrenView, RootRESTCollectionView, + RESTSearchResultsView, } from "./view" import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data" @@ -40,6 +41,10 @@ export interface WorkspaceProvider { getRESTCollectionLevelAuthHeadersView( collectionHandle: HandleRef ): Promise>> + getRESTSearchResultsView( + workspaceHandle: HandleRef, + searchQuery: Ref + ): Promise>> createRESTRootCollection( workspaceHandle: HandleRef, diff --git a/packages/hoppscotch-common/src/services/new-workspace/providers/personal.workspace.ts b/packages/hoppscotch-common/src/services/new-workspace/providers/personal.workspace.ts index 53545b314..6f8d4e52f 100644 --- a/packages/hoppscotch-common/src/services/new-workspace/providers/personal.workspace.ts +++ b/packages/hoppscotch-common/src/services/new-workspace/providers/personal.workspace.ts @@ -37,7 +37,10 @@ import { WorkspaceProvider } from "~/services/new-workspace/provider" import { RESTCollectionChildrenView, RESTCollectionLevelAuthHeadersView, + RESTCollectionViewCollection, RESTCollectionViewItem, + RESTCollectionViewRequest, + RESTSearchResultsView, RootRESTCollectionView, } from "~/services/new-workspace/view" import { @@ -766,6 +769,7 @@ export class PersonalWorkspaceProviderService }) const requests = item.requests.map((req, id) => { + // TODO: Replace `parentCollectionID` with `collectionID` return { type: "request", value: { @@ -945,6 +949,174 @@ export class PersonalWorkspaceProviderService ) } + public getRESTSearchResultsView( + workspaceHandle: HandleRef, + searchQuery: Ref + ): Promise>> { + return Promise.resolve( + E.right( + computed(() => { + if ( + workspaceHandle.value.type === "invalid" || + workspaceHandle.value.data.providerID !== this.providerID || + workspaceHandle.value.data.workspaceID !== "personal" + ) { + return { + type: "invalid" as const, + reason: "INVALID_WORKSPACE_HANDLE" as const, + } + } + + if (!searchQuery.value) { + return markRaw({ + type: "ok" as const, + data: { + providerID: this.providerID, + workspaceID: workspaceHandle.value.data.workspaceID, + + loading: ref(false), + + results: computed(() => { + return this.restCollectionState.value.state.map( + (coll, id) => { + return { + type: "collection", + value: { + collectionID: id.toString(), + isLastItem: + id === + this.restCollectionState.value.state.length - 1, + name: coll.name, + parentCollectionID: null, + }, + } + } + ) + }), + }, + }) + } + + return markRaw({ + type: "ok" as const, + data: { + providerID: this.providerID, + workspaceID: workspaceHandle.value.data.workspaceID, + + loading: ref(false), + + results: computed(() => { + const filterText = searchQuery.value.toLowerCase() + const filteredCollections: RESTCollectionViewItem[] = [] + + const isMatch = (text: string) => + text.toLowerCase().includes(filterText) + + for (const collection of this.restCollectionState.value.state) { + const filteredRequests: Extract< + RESTCollectionViewItem, + { type: "request" } + >[] = [] + + const filteredFolders: Extract< + RESTCollectionViewItem, + { type: "collection" } + >[] = [] + + collection.requests.forEach((request, requestID) => { + if (isMatch(request.name)) { + filteredRequests.push({ + type: "request", + value: { + collectionID: collection.id!, + isLastItem: + collection.requests?.length > 1 + ? requestID === collection.requests.length - 1 + : false, + // TODO: Replace `parentCollectionID` with `collectionID` + parentCollectionID: collection.id!, + requestID: requestID.toString(), + request: request as HoppRESTRequest, + }, + }) + } + }) + + collection.folders.forEach( + (childCollection, childCollectionID) => { + if (isMatch(childCollection.name)) { + filteredFolders.push({ + type: "collection", + value: { + collectionID: `${collection.id}/${childCollectionID}`, + isLastItem: + collection.folders?.length > 1 + ? childCollectionID === + collection.folders.length - 1 + : false, + name: childCollection.name, + parentCollectionID: collection.id!, + }, + }) + } + + const filteredFolderRequests: Extract< + RESTCollectionViewItem, + { type: "request" } + >[] = ([] = []) + + childCollection.requests.forEach( + (request: HoppRESTRequest, requestID: number) => { + if (isMatch(request.name)) + filteredFolderRequests.push({ + type: "request", + value: { + collectionID: childCollection.id!, + isLastItem: + childCollection.requests?.length > 1 + ? requestID === + childCollection.requests.length - 1 + : false, + // TODO: Replace `parentCollectionID` with `collectionID` + parentCollectionID: childCollection.id!, + requestID: requestID.toString(), + request, + }, + }) + } + ) + + if (filteredFolderRequests.length > 0) { + const filteredFolder = Object.assign( + {}, + childCollection + ) + filteredFolder.requests = filteredFolderRequests + filteredFolders.push(filteredFolder) + } + } + ) + + if ( + filteredRequests.length + filteredFolders.length > 0 || + isMatch(collection.name) + ) { + filteredCollections.push( + ...filteredFolders, + ...filteredRequests + ) + } + } + + return filteredCollections + }), + }, + }) + }) + ) + ) + } + public getWorkspaceHandle( workspaceID: string ): Promise>> { diff --git a/packages/hoppscotch-common/src/services/new-workspace/view.ts b/packages/hoppscotch-common/src/services/new-workspace/view.ts index 7372dc040..2088fc7df 100644 --- a/packages/hoppscotch-common/src/services/new-workspace/view.ts +++ b/packages/hoppscotch-common/src/services/new-workspace/view.ts @@ -46,3 +46,12 @@ export interface RESTCollectionChildrenView { content: Ref } + +export interface RESTSearchResultsView { + providerID: string + workspaceID: string + + loading: Ref + + results: Ref +}