refactor: session based search results view implementation

This commit is contained in:
jamesgeorge007
2024-02-24 17:14:42 +05:30
parent 5a64cdb7bc
commit c30ee5becc
5 changed files with 125 additions and 103 deletions

View File

@@ -351,22 +351,21 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import * as E from "fp-ts/lib/Either"
import { useService } from "dioc/vue"
import { markRaw, nextTick, ref, watch } from "vue"
import { HoppCollection, HoppRESTAuth, HoppRESTRequest } from "@hoppscotch/data" import { HoppCollection, HoppRESTAuth, HoppRESTRequest } from "@hoppscotch/data"
import { useService } from "dioc/vue"
import * as E from "fp-ts/lib/Either"
import { cloneDeep, isEqual } from "lodash-es" import { cloneDeep, isEqual } from "lodash-es"
import { computed, markRaw, nextTick, ref, watch } from "vue"
import { useI18n } from "~/composables/i18n" import { useI18n } from "~/composables/i18n"
import { useReadonlyStream } from "~/composables/stream" import { useReadonlyStream } from "~/composables/stream"
import { useToast } from "~/composables/toast" import { useToast } from "~/composables/toast"
import { invokeAction } from "~/helpers/actions" import { invokeAction } from "~/helpers/actions"
import { WorkspaceRESTSearchCollectionTreeAdapter } from "~/helpers/adapters/WorkspaceRESTCollectionSearchTreeAdapter"
import { WorkspaceRESTCollectionTreeAdapter } from "~/helpers/adapters/WorkspaceRESTCollectionTreeAdapter" import { WorkspaceRESTCollectionTreeAdapter } from "~/helpers/adapters/WorkspaceRESTCollectionTreeAdapter"
import { TeamCollection } from "~/helpers/backend/graphql" import { TeamCollection } from "~/helpers/backend/graphql"
import { import {
getFoldersByPath, getFoldersByPath,
resolveSaveContextOnCollectionReorder,
updateInheritedPropertiesForAffectedRequests, updateInheritedPropertiesForAffectedRequests,
} from "~/helpers/collection/collection" } from "~/helpers/collection/collection"
import { getRequestsByPath } from "~/helpers/collection/request" import { getRequestsByPath } from "~/helpers/collection/request"
@@ -387,7 +386,6 @@ import { RESTTabService } from "~/services/tab/rest"
import IconImport from "~icons/lucide/folder-down" import IconImport from "~icons/lucide/folder-down"
import IconHelpCircle from "~icons/lucide/help-circle" import IconHelpCircle from "~icons/lucide/help-circle"
import IconPlus from "~icons/lucide/plus" import IconPlus from "~icons/lucide/plus"
import { WorkspaceRESTSearchCollectionTreeAdapter } from "~/helpers/adapters/WorkspaceRESTCollectionSearchTreeAdapter"
const t = useI18n() const t = useI18n()
const toast = useToast() const toast = useToast()
@@ -414,11 +412,9 @@ const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
parentID: "", parentID: "",
}) })
const treeAdapter = markRaw( const currentUser = useReadonlyStream(
new WorkspaceRESTCollectionTreeAdapter( platform.auth.getCurrentUserStream(),
props.workspaceHandle, platform.auth.getCurrentUser()
workspaceService
)
) )
const draggingToRoot = ref(false) const draggingToRoot = ref(false)
@@ -442,11 +438,9 @@ const editingChildCollectionName = ref<string>("")
const editingRequestName = ref<string>("") const editingRequestName = ref<string>("")
const editingRequestIndexPath = ref<string>("") const editingRequestIndexPath = ref<string>("")
const filteredCollections = ref<HoppCollection[]>([]) const onSessionEnd = ref<() => void>()
const searchTreeAdapter = new WorkspaceRESTSearchCollectionTreeAdapter( const filteredCollections = ref<HoppCollection[]>([])
filteredCollections
)
const editingProperties = ref<{ const editingProperties = ref<{
collection: Omit<HoppCollection, "v"> | TeamCollection | null collection: Omit<HoppCollection, "v"> | TeamCollection | null
@@ -462,18 +456,19 @@ const editingProperties = ref<{
const confirmModalTitle = ref<string | null>(null) const confirmModalTitle = ref<string | null>(null)
const currentUser = useReadonlyStream( const isActiveSearchSession = computed(() => !!searchText.value)
platform.auth.getCurrentUserStream(),
platform.auth.getCurrentUser() watch(isActiveSearchSession, async (newState) => {
) if (!newState) {
filteredCollections.value = []
onSessionEnd.value?.()
return
}
watch(
() => searchText.value,
async (newSearchText: string) => {
const searchResultsHandleResult = const searchResultsHandleResult =
await workspaceService.getRESTSearchResultsView( await workspaceService.getRESTSearchResultsView(
props.workspaceHandle, props.workspaceHandle,
newSearchText ref(searchText)
) )
if (E.isLeft(searchResultsHandleResult)) { if (E.isLeft(searchResultsHandleResult)) {
@@ -489,8 +484,18 @@ watch(
} }
filteredCollections.value = searchResultsHandle.value.data.results.value filteredCollections.value = searchResultsHandle.value.data.results.value
}, onSessionEnd.value = searchResultsHandle.value.data.onSessionEnd
{ immediate: true } })
const treeAdapter = markRaw(
new WorkspaceRESTCollectionTreeAdapter(
props.workspaceHandle,
workspaceService
)
)
const searchTreeAdapter = new WorkspaceRESTSearchCollectionTreeAdapter(
filteredCollections
) )
const isSelected = ({ const isSelected = ({

View File

@@ -690,7 +690,7 @@ export class NewWorkspaceService extends Service {
public async getRESTSearchResultsView( public async getRESTSearchResultsView(
workspaceHandle: HandleRef<Workspace>, workspaceHandle: HandleRef<Workspace>,
searchQuery: string searchQuery: Ref<string>
): Promise< ): Promise<
E.Either< E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,

View File

@@ -44,7 +44,7 @@ export interface WorkspaceProvider {
): Promise<E.Either<unknown, HandleRef<RESTCollectionLevelAuthHeadersView>>> ): Promise<E.Either<unknown, HandleRef<RESTCollectionLevelAuthHeadersView>>>
getRESTSearchResultsView( getRESTSearchResultsView(
workspaceHandle: HandleRef<Workspace>, workspaceHandle: HandleRef<Workspace>,
searchQuery: string searchQuery: Ref<string>
): Promise<E.Either<unknown, HandleRef<RESTSearchResultsView>>> ): Promise<E.Either<unknown, HandleRef<RESTSearchResultsView>>>
createRESTRootCollection( createRESTRootCollection(

View File

@@ -7,7 +7,16 @@ import {
} from "@hoppscotch/data" } from "@hoppscotch/data"
import { Service } from "dioc" import { Service } from "dioc"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import { Ref, computed, markRaw, ref, shallowRef } from "vue" import {
Ref,
computed,
effect,
effectScope,
markRaw,
ref,
shallowRef,
watch,
} from "vue"
import PersonalWorkspaceSelector from "~/components/workspace/PersonalWorkspaceSelector.vue" import PersonalWorkspaceSelector from "~/components/workspace/PersonalWorkspaceSelector.vue"
import { useStreamStatic } from "~/composables/stream" import { useStreamStatic } from "~/composables/stream"
@@ -951,46 +960,22 @@ export class PersonalWorkspaceProviderService
public getRESTSearchResultsView( public getRESTSearchResultsView(
workspaceHandle: HandleRef<Workspace>, workspaceHandle: HandleRef<Workspace>,
searchQuery: string searchQuery: Ref<string>
): Promise<E.Either<never, HandleRef<RESTSearchResultsView>>> { ): Promise<E.Either<never, HandleRef<RESTSearchResultsView>>> {
return Promise.resolve( const results = ref<HoppCollection[]>([])
E.right(
computed(() => { const scopeHandle = effectScope()
if (
workspaceHandle.value.type === "invalid" || scopeHandle.run(() => {
workspaceHandle.value.data.providerID !== this.providerID || watch(
workspaceHandle.value.data.workspaceID !== "personal" searchQuery,
) { (newSearchQuery) => {
return { if (!newSearchQuery) {
type: "invalid" as const, results.value = this.restCollectionState.value.state
reason: "INVALID_WORKSPACE_HANDLE" as const, return
}
} }
if (!searchQuery) { const filterText = newSearchQuery.toLowerCase()
return {
type: "ok" as const,
data: {
providerID: this.providerID,
workspaceID: workspaceHandle.value.data.workspaceID,
loading: ref(false),
results: ref(this.restCollectionState.value.state),
},
}
}
return markRaw({
type: "ok" as const,
data: {
providerID: this.providerID,
workspaceID: workspaceHandle.value.data.workspaceID,
loading: ref(false),
results: computed(() => {
const filterText = searchQuery.toLowerCase()
const filteredCollections = [] const filteredCollections = []
const isMatch = (text: string) => const isMatch = (text: string) =>
@@ -1006,8 +991,7 @@ export class PersonalWorkspaceProviderService
if (isMatch(folder.name)) filteredFolders.push(folder) if (isMatch(folder.name)) filteredFolders.push(folder)
const filteredFolderRequests = [] const filteredFolderRequests = []
for (const request of folder.requests) { for (const request of folder.requests) {
if (isMatch(request.name)) if (isMatch(request.name)) filteredFolderRequests.push(request)
filteredFolderRequests.push(request)
} }
if (filteredFolderRequests.length > 0) { if (filteredFolderRequests.length > 0) {
const filteredFolder = Object.assign({}, folder) const filteredFolder = Object.assign({}, folder)
@@ -1025,12 +1009,44 @@ export class PersonalWorkspaceProviderService
filteredCollection.folders = filteredFolders filteredCollection.folders = filteredFolders
filteredCollections.push(filteredCollection) filteredCollections.push(filteredCollection)
} }
results.value = filteredCollections
}
},
{ immediate: true }
)
})
const onSessionEnd = () => {
scopeHandle.stop()
} }
return filteredCollections 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,
}
}
return {
type: "ok" as const,
data: {
providerID: this.providerID,
workspaceID: workspaceHandle.value.data.workspaceID,
loading: ref(false),
results,
onSessionEnd,
}, },
}) }
}) })
) )
) )

View File

@@ -54,4 +54,5 @@ export interface RESTSearchResultsView {
loading: Ref<boolean> loading: Ref<boolean>
results: Ref<HoppCollection[]> results: Ref<HoppCollection[]>
onSessionEnd: () => void
} }