From a28a576c41a0a85a0963dedfd6bc1c18d5c95597 Mon Sep 17 00:00:00 2001 From: Anwarul Islam Date: Tue, 30 Jan 2024 19:49:04 +0530 Subject: [PATCH] feat: team environment search and switch (#3700) Co-authored-by: jamesgeorge007 --- .../helpers/teams/TeamEnvironmentAdapter.ts | 2 +- .../src/newstore/environments.ts | 2 +- .../searchers/environment.searcher.ts | 132 ++++++++++++++++-- 3 files changed, 120 insertions(+), 16 deletions(-) diff --git a/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts b/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts index 90a0966b4..e8aa29fe7 100644 --- a/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts +++ b/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts @@ -110,7 +110,7 @@ export default class TeamEnvironmentAdapter { throw new Error(`Failed fetching team environments: ${result.left}`) } - if (result.right.team !== undefined && result.right.team !== null) { + if (result.right.team) { results.push( ...result.right.team.teamEnvironments.map( (x) => diff --git a/packages/hoppscotch-common/src/newstore/environments.ts b/packages/hoppscotch-common/src/newstore/environments.ts index 71b1bbb65..e92c3eadf 100644 --- a/packages/hoppscotch-common/src/newstore/environments.ts +++ b/packages/hoppscotch-common/src/newstore/environments.ts @@ -6,7 +6,7 @@ import DispatchingStore, { defineDispatchers, } from "~/newstore/DispatchingStore" -type SelectedEnvironmentIndex = +export type SelectedEnvironmentIndex = | { type: "NO_ENV_SELECTED" } | { type: "MY_ENV"; index: number } | { diff --git a/packages/hoppscotch-common/src/services/spotlight/searchers/environment.searcher.ts b/packages/hoppscotch-common/src/services/spotlight/searchers/environment.searcher.ts index 291baabbd..1a2781e14 100644 --- a/packages/hoppscotch-common/src/services/spotlight/searchers/environment.searcher.ts +++ b/packages/hoppscotch-common/src/services/spotlight/searchers/environment.searcher.ts @@ -33,9 +33,10 @@ import { cloneDeep } from "lodash-es" import MiniSearch from "minisearch" import { map } from "rxjs" import { useStreamStatic } from "~/composables/stream" -import { GQLError } from "~/helpers/backend/GQLClient" +import { GQLError, runGQLQuery } from "~/helpers/backend/GQLClient" import { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment" import { + SelectedEnvironmentIndex, createEnvironment, currentEnvironment$, duplicateEnvironment, @@ -45,7 +46,12 @@ import { setSelectedEnvironmentIndex, } from "~/newstore/environments" +import * as E from "fp-ts/Either" import IconCheckCircle from "~/components/app/spotlight/entry/IconSelected.vue" +import { useToast } from "~/composables/toast" +import { GetTeamEnvironmentsDocument } from "~/helpers/backend/graphql" +import { TeamEnvironment } from "~/helpers/teams/TeamEnvironment" +import { WorkspaceService } from "~/services/workspace.service" import IconCircle from "~icons/lucide/circle" type Doc = { @@ -55,6 +61,13 @@ type Doc = { excludeFromSearch?: boolean } +type SelectedEnv = { + selected?: boolean +} & ( + | Omit + | (SelectedEnvironmentIndex & { type: "MY_ENV" }) +) + /** * * This searcher is responsible for providing environments related actions on the spotlight results. @@ -257,11 +270,14 @@ export class SwitchEnvSpotlightSearcherService public static readonly ID = "SWITCH_ENV_SPOTLIGHT_SEARCHER_SERVICE" private t = getI18n() + private toast = useToast() public searcherID = "switch_env" public searcherSectionTitle = this.t("tab.environments") private readonly spotlight = this.bind(SpotlightService) + private readonly workspaceService = this.bind(WorkspaceService) + private teamEnvironmentList: TeamEnvironment[] = [] constructor() { super() @@ -289,6 +305,37 @@ export class SwitchEnvSpotlightSearcherService } )[0] + async fetchTeamEnvironmentList(teamID: string): Promise { + const results: TeamEnvironment[] = [] + + const result = await runGQLQuery({ + query: GetTeamEnvironmentsDocument, + variables: { + teamID: teamID, + }, + }) + + if (E.isRight(result)) { + if (result.right.team) { + results.push( + ...result.right.team.teamEnvironments.map( + ({ id, teamID, name, variables }) => + { + id: id, + teamID: teamID, + environment: { + name: name, + variables: JSON.parse(variables), + }, + } + ) + ) + } + } + + return results + } + createSearchSession( query: Readonly> ): [Ref, () => void] { @@ -303,21 +350,55 @@ export class SwitchEnvSpotlightSearcherService if (this.environmentSearchable.value) { minisearch.addAll( environmentsStore.value.environments.map((entry, index) => { - let id = `environment-${index}` + const id: SelectedEnv = { + type: "MY_ENV", + index, + } if ( this.selectedEnvIndex.value?.type === "MY_ENV" && this.selectedEnvIndex.value.index === index ) { - id += "-selected" + id.selected = true } return { - id, + id: JSON.stringify(id), name: entry.name, alternates: ["environment", "change", entry.name], } }) ) + + const workspace = this.workspaceService.currentWorkspace + + if (workspace.value?.type === "team") { + this.fetchTeamEnvironmentList(workspace.value.teamID).then( + (results) => { + this.teamEnvironmentList = results + minisearch.addAll( + results.map(({ teamID, id: teamEnvID, environment }) => { + const id: SelectedEnv = { + type: "TEAM_ENV", + teamID, + teamEnvID, + } + + if ( + this.selectedEnvIndex.value?.type === "TEAM_ENV" && + this.selectedEnvIndex.value.teamEnvID === teamEnvID + ) { + id.selected = true + } + return { + id: JSON.stringify(id), + name: environment.name, + alternates: ["environment", "change", environment.name], + } + }) + ) + } + ) + } } const scopeHandle = effectScope() @@ -338,16 +419,16 @@ export class SwitchEnvSpotlightSearcherService prefix: 0.8, }, }) - .map((x) => { + .map(({ id, score, name }) => { return { - id: x.id, + id: id, icon: markRaw( - x.id.endsWith("-selected") ? IconCheckCircle : IconCircle + JSON.parse(id).selected ? IconCheckCircle : IconCircle ), - score: x.score, + score: score, text: { type: "text", - text: [this.t("environment.set"), x.name], + text: [this.t("environment.set"), name], }, } }) @@ -370,10 +451,33 @@ export class SwitchEnvSpotlightSearcherService } onResultSelect(result: SpotlightSearcherResult): void { - const selectedEnvIndex = Number(result.id.split("-")[1]) - setSelectedEnvironmentIndex({ - type: "MY_ENV", - index: selectedEnvIndex, - }) + try { + const selectedEnv = JSON.parse(result.id) as SelectedEnv + + if (selectedEnv.type === "MY_ENV") { + setSelectedEnvironmentIndex({ + type: "MY_ENV", + index: selectedEnv.index, + }) + } + + if (selectedEnv.type === "TEAM_ENV") { + const teamEnv = this.teamEnvironmentList.find( + ({ id }) => id === selectedEnv.teamEnvID + ) + if (!teamEnv) return + + const { teamID, teamEnvID } = selectedEnv + setSelectedEnvironmentIndex({ + type: "TEAM_ENV", + teamEnvID, + teamID, + environment: teamEnv.environment, + }) + } + } catch (e) { + console.error((e as Error).message) + this.toast.error(this.t("error.something_went_wrong")) + } } }