Skip to content

Commit

Permalink
feat: team search in workspace search and spotlight (#3896)
Browse files Browse the repository at this point in the history
Co-authored-by: jamesgeorge007 <jamesgeorge998001@gmail.com>
  • Loading branch information
amk-dev and jamesgeorge007 committed Mar 19, 2024
1 parent a3f3e3e commit 457857a
Show file tree
Hide file tree
Showing 7 changed files with 940 additions and 20 deletions.
5 changes: 3 additions & 2 deletions packages/hoppscotch-common/locales/en.json
Expand Up @@ -281,7 +281,7 @@
"updated": "Environment updated",
"value": "Value",
"variable": "Variable",
"variables":"Variables",
"variables": "Variables",
"variable_list": "Variable List"
},
"error": {
Expand Down Expand Up @@ -961,7 +961,8 @@
"success_invites": "Success invites",
"title": "Workspaces",
"we_sent_invite_link": "We sent an invite link to all invitees!",
"we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the workspace."
"we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the workspace.",
"search_title": "Team Requests"
},
"team_environment": {
"deleted": "Environment Deleted",
Expand Down
@@ -0,0 +1,32 @@
<template>
<span class="flex flex-1 items-center space-x-2">
<template v-for="(title, index) in collectionTitles" :key="index">
<span class="block" :class="{ truncate: index !== 0 }">
{{ title }}
</span>
<icon-lucide-chevron-right class="flex flex-shrink-0" />
</template>
<span
v-if="request"
class="flex flex-shrink-0 truncate rounded-md border border-dividerDark px-1 text-tiny font-semibold"
:style="{ color: getMethodLabelColor(request.method) }"
>
{{ request.method.toUpperCase() }}
</span>
<span v-if="request" class="block">
{{ request.name }}
</span>
</span>
</template>

<script setup lang="ts">
import { getMethodLabelColor } from "~/helpers/rest/labelColoring"
defineProps<{
collectionTitles: string[]
request: {
name: string
method: string
}
}>()
</script>
Expand Up @@ -111,6 +111,7 @@ import { RequestSpotlightSearcherService } from "~/services/spotlight/searchers/
import { ResponseSpotlightSearcherService } from "~/services/spotlight/searchers/response.searcher"
import { SettingsSpotlightSearcherService } from "~/services/spotlight/searchers/settings.searcher"
import { TabSpotlightSearcherService } from "~/services/spotlight/searchers/tab.searcher"
import { TeamsSpotlightSearcherService } from "~/services/spotlight/searchers/teamRequest.searcher"
import { UserSpotlightSearcherService } from "~/services/spotlight/searchers/user.searcher"
import {
SwitchWorkspaceSpotlightSearcherService,
Expand Down Expand Up @@ -144,6 +145,7 @@ useService(SwitchEnvSpotlightSearcherService)
useService(WorkspaceSpotlightSearcherService)
useService(SwitchWorkspaceSpotlightSearcherService)
useService(InterceptorSpotlightSearcherService)
useService(TeamsSpotlightSearcherService)
platform.spotlight?.additionalSearchers?.forEach((searcher) =>
useService(searcher)
Expand Down
Expand Up @@ -9,7 +9,7 @@
"
>
<HoppButtonSecondary
v-if="hasNoTeamAccess"
v-if="hasNoTeamAccess || isShowingSearchResults"
v-tippy="{ theme: 'tooltip' }"
disabled
class="!rounded-none"
Expand All @@ -36,8 +36,9 @@
v-if="!saveRequest"
v-tippy="{ theme: 'tooltip' }"
:disabled="
collectionsType.type === 'team-collections' &&
collectionsType.selectedTeam === undefined
(collectionsType.type === 'team-collections' &&
collectionsType.selectedTeam === undefined) ||
isShowingSearchResults
"
:icon="IconImport"
:title="t('modal.import_export')"
Expand All @@ -58,7 +59,7 @@
:collections-type="collectionsType.type"
:is-open="isOpen"
:export-loading="exportLoading"
:has-no-team-access="hasNoTeamAccess"
:has-no-team-access="hasNoTeamAccess || isShowingSearchResults"
:collection-move-loading="collectionMoveLoading"
:is-last-item="node.data.isLastItem"
:is-selected="
Expand Down Expand Up @@ -128,6 +129,14 @@
})
}
"
@click="
() => {
handleCollectionClick({
collectionID: node.id,
isOpen,
})
}
"
/>
<CollectionsCollection
v-if="node.data.type === 'folders'"
Expand All @@ -137,7 +146,7 @@
:collections-type="collectionsType.type"
:is-open="isOpen"
:export-loading="exportLoading"
:has-no-team-access="hasNoTeamAccess"
:has-no-team-access="hasNoTeamAccess || isShowingSearchResults"
:collection-move-loading="collectionMoveLoading"
:is-last-item="node.data.isLastItem"
:is-selected="
Expand Down Expand Up @@ -209,6 +218,15 @@
})
}
"
@click="
() => {
handleCollectionClick({
// for the folders, we get a path, so we need to get the last part of the path which is the folder id
collectionID: node.id.split('/').pop() as string,
isOpen,
})
}
"
/>
<CollectionsRequest
v-if="node.data.type === 'requests'"
Expand All @@ -218,7 +236,7 @@
:collections-type="collectionsType.type"
:duplicate-loading="duplicateLoading"
:is-active="isActiveRequest(node.data.data.data.id)"
:has-no-team-access="hasNoTeamAccess"
:has-no-team-access="hasNoTeamAccess || isShowingSearchResults"
:request-move-loading="requestMoveLoading"
:is-last-item="node.data.isLastItem"
:is-selected="
Expand Down Expand Up @@ -283,7 +301,15 @@
</template>
<template #emptyNode="{ node }">
<HoppSmartPlaceholder
v-if="node === null"
v-if="filterText.length !== 0 && teamCollectionList.length === 0"
:text="`${t('state.nothing_found')}${filterText}`"
>
<template #icon>
<icon-lucide-search class="svg-icons opacity-75" />
</template>
</HoppSmartPlaceholder>
<HoppSmartPlaceholder
v-else-if="node === null"
:src="`/images/states/${colorMode.value}/pack.svg`"
:alt="`${t('empty.collections')}`"
:text="t('empty.collections')"
Expand Down Expand Up @@ -394,6 +420,11 @@ const props = defineProps({
default: () => ({ type: "my-collections", selectedTeam: undefined }),
required: true,
},
filterText: {
type: String as PropType<string>,
default: "",
required: true,
},
teamCollectionList: {
type: Array as PropType<TeamCollection[]>,
default: () => [],
Expand Down Expand Up @@ -436,6 +467,8 @@ const props = defineProps({
},
})
const isShowingSearchResults = computed(() => props.filterText.length > 0)
const emit = defineEmits<{
(
event: "add-request",
Expand Down Expand Up @@ -543,6 +576,14 @@ const emit = defineEmits<{
}
}
): void
(
event: "collection-click",
payload: {
// if the collection is open or not in the tree
isOpen: boolean
collectionID: string
}
): void
(event: "select", payload: Picked | null): void
(event: "expand-team-collection", payload: string): void
(event: "display-modal-add"): void
Expand All @@ -555,6 +596,18 @@ const getPath = (path: string) => {
return pathArray.join("/")
}
const handleCollectionClick = (payload: {
collectionID: string
isOpen: boolean
}) => {
const { collectionID, isOpen } = payload
emit("collection-click", {
collectionID,
isOpen,
})
}
const teamCollectionsList = toRef(props, "teamCollectionList")
const hasNoTeamAccess = computed(
Expand Down
104 changes: 93 additions & 11 deletions packages/hoppscotch-common/src/components/collections/index.vue
Expand Up @@ -24,7 +24,6 @@
autocomplete="off"
class="flex w-full bg-transparent px-4 py-2 h-8"
:placeholder="t('action.search')"
:disabled="collectionsType.type === 'team-collections'"
/>
</div>
<CollectionsMyCollections
Expand Down Expand Up @@ -58,8 +57,15 @@
<CollectionsTeamCollections
v-else
:collections-type="collectionsType"
:team-collection-list="teamCollectionList"
:team-loading-collections="teamLoadingCollections"
:team-collection-list="
filterTexts.length > 0 ? teamsSearchResults : teamCollectionList
"
:team-loading-collections="
filterTexts.length > 0
? collectionsBeingLoadedFromSearch
: teamLoadingCollections
"
:filter-text="filterTexts"
:export-loading="exportLoading"
:duplicate-loading="duplicateLoading"
:save-request="saveRequest"
Expand Down Expand Up @@ -87,6 +93,7 @@
@expand-team-collection="expandTeamCollection"
@display-modal-add="displayModalAdd(true)"
@display-modal-import-export="displayModalImportExport(true)"
@collection-click="handleCollectionClick"
/>
<div
class="py-15 hidden flex-1 flex-col items-center justify-center bg-primaryDark px-4 text-secondaryLight"
Expand Down Expand Up @@ -199,7 +206,7 @@ import {
HoppRESTRequest,
makeCollection,
} from "@hoppscotch/data"
import { cloneDeep, isEqual } from "lodash-es"
import { cloneDeep, debounce, isEqual } from "lodash-es"
import { GQLError } from "~/helpers/backend/GQLClient"
import {
createNewRootCollection,
Expand Down Expand Up @@ -240,6 +247,7 @@ import { WorkspaceService } from "~/services/workspace.service"
import { useService } from "dioc/vue"
import { RESTTabService } from "~/services/tab/rest"
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
import { TeamSearchService } from "~/helpers/teams/TeamsSearch.service"
const t = useI18n()
const toast = useToast()
Expand Down Expand Up @@ -336,6 +344,50 @@ const teamLoadingCollections = useReadonlyStream(
[]
)
const {
cascadeParentCollectionForHeaderAuthForSearchResults,
searchTeams,
teamsSearchResults,
teamsSearchResultsLoading,
expandCollection,
expandingCollections,
} = useService(TeamSearchService)
watch(teamsSearchResults, (newSearchResults) => {
if (newSearchResults.length === 1 && filterTexts.value.length > 0) {
expandCollection(newSearchResults[0].id)
}
})
const debouncedSearch = debounce(searchTeams, 400)
const collectionsBeingLoadedFromSearch = computed(() => {
const collections = []
if (teamsSearchResultsLoading.value) {
collections.push("root")
}
collections.push(...expandingCollections.value)
return collections
})
watch(
filterTexts,
(newFilterText) => {
if (collectionsType.value.type === "team-collections") {
const selectedTeamID = collectionsType.value.selectedTeam?.id
selectedTeamID &&
debouncedSearch(newFilterText, selectedTeamID)?.catch((_) => {})
}
},
{
immediate: true,
}
)
watch(
() => myTeams.value,
(newTeams) => {
Expand Down Expand Up @@ -364,7 +416,28 @@ const switchToMyCollections = () => {
teamCollectionAdapter.changeTeamID(null)
}
/**
* right now, for search results, we rely on collection click + isOpen to expand the collection
*/
const handleCollectionClick = (payload: {
collectionID: string
isOpen: boolean
}) => {
if (
filterTexts.value.length > 0 &&
teamsSearchResults.value.length &&
payload.isOpen
) {
expandCollection(payload.collectionID)
return
}
}
const expandTeamCollection = (collectionID: string) => {
if (filterTexts.value.length > 0 && teamsSearchResults.value) {
return
}
teamCollectionAdapter.expandCollection(collectionID)
}
Expand Down Expand Up @@ -1330,13 +1403,25 @@ const selectRequest = (selectedRequest: {
let possibleTab = null
if (collectionsType.value.type === "team-collections") {
const { auth, headers } =
teamCollectionAdapter.cascadeParentCollectionForHeaderAuth(folderPath)
let inheritedProperties: HoppInheritedProperty | undefined = undefined
possibleTab = tabs.getTabRefWithSaveContext({
if (filterTexts.value.length > 0) {
const collectionID = folderPath.split("/").at(-1)
if (!collectionID) return
inheritedProperties =
cascadeParentCollectionForHeaderAuthForSearchResults(collectionID)
} else {
inheritedProperties =
teamCollectionAdapter.cascadeParentCollectionForHeaderAuth(folderPath)
}
const possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "team-collection",
requestID: requestIndex,
})
if (possibleTab) {
tabs.setActiveTab(possibleTab.value.id)
} else {
Expand All @@ -1348,10 +1433,7 @@ const selectRequest = (selectedRequest: {
requestID: requestIndex,
collectionID: folderPath,
},
inheritedProperties: {
auth,
headers,
},
inheritedProperties: inheritedProperties,
})
}
} else {
Expand Down

0 comments on commit 457857a

Please sign in to comment.