fix: corrections for spotlight searchers (#3275)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Service } from "dioc"
|
||||
import {
|
||||
SpotlightResultTextType,
|
||||
SpotlightSearcher,
|
||||
SpotlightSearcherResult,
|
||||
SpotlightSearcherSessionState,
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
} from "@hoppscotch/data"
|
||||
import { hoppWorkspaceStore } from "~/newstore/workspace"
|
||||
import { changeWorkspace } from "~/newstore/workspace"
|
||||
import { invokeAction } from "~/helpers/actions"
|
||||
|
||||
/**
|
||||
* A spotlight searcher that searches through the user's collections
|
||||
@@ -143,6 +145,13 @@ export class CollectionsSpotlightSearcherService
|
||||
},
|
||||
})
|
||||
|
||||
if (pageCategory === "rest" || pageCategory === "graphql") {
|
||||
minisearch.add({
|
||||
id: `create-collection`,
|
||||
name: this.t("collection.new"),
|
||||
})
|
||||
}
|
||||
|
||||
if (pageCategory === "rest") {
|
||||
this.loadRESTDocsIntoMinisearch(minisearch)
|
||||
} else if (pageCategory === "graphql") {
|
||||
@@ -153,6 +162,11 @@ export class CollectionsSpotlightSearcherService
|
||||
|
||||
const scopeHandle = effectScope()
|
||||
|
||||
const newCollectionText: SpotlightResultTextType<any> = {
|
||||
type: "text",
|
||||
text: this.t("collection.new"),
|
||||
}
|
||||
|
||||
scopeHandle.run(() => {
|
||||
watch(query, (query) => {
|
||||
if (pageCategory === "other") {
|
||||
@@ -165,28 +179,34 @@ export class CollectionsSpotlightSearcherService
|
||||
|
||||
results.value = searchResults.map((result) => ({
|
||||
id: result.id,
|
||||
text: {
|
||||
type: "custom",
|
||||
component: markRaw(RESTRequestSpotlightEntry),
|
||||
componentProps: {
|
||||
folderPath: result.id.split("rest-")[1],
|
||||
},
|
||||
},
|
||||
text:
|
||||
result.id === "create-collection"
|
||||
? newCollectionText
|
||||
: {
|
||||
type: "custom",
|
||||
component: markRaw(RESTRequestSpotlightEntry),
|
||||
componentProps: {
|
||||
folderPath: result.id.split("rest-")[1],
|
||||
},
|
||||
},
|
||||
icon: markRaw(IconFolder),
|
||||
score: result.score,
|
||||
}))
|
||||
} else {
|
||||
} else if (pageCategory === "graphql") {
|
||||
const searchResults = minisearch.search(query).slice(0, 10)
|
||||
|
||||
results.value = searchResults.map((result) => ({
|
||||
id: result.id,
|
||||
text: {
|
||||
type: "custom",
|
||||
component: markRaw(GQLRequestSpotlightEntry),
|
||||
componentProps: {
|
||||
folderPath: result.id.split("gql-")[1],
|
||||
},
|
||||
},
|
||||
text:
|
||||
result.id === "create-collection"
|
||||
? newCollectionText
|
||||
: {
|
||||
type: "custom",
|
||||
component: markRaw(GQLRequestSpotlightEntry),
|
||||
componentProps: {
|
||||
folderPath: result.id.split("gql-")[1],
|
||||
},
|
||||
},
|
||||
icon: markRaw(IconFolder),
|
||||
score: result.score,
|
||||
}))
|
||||
@@ -256,6 +276,8 @@ export class CollectionsSpotlightSearcherService
|
||||
}
|
||||
|
||||
public onResultSelect(result: SpotlightSearcherResult): void {
|
||||
if (result.id === "create-collection") return invokeAction("collection.new")
|
||||
|
||||
const [type, path] = result.id.split("-")
|
||||
|
||||
if (type === "rest") {
|
||||
|
||||
@@ -21,30 +21,29 @@ import {
|
||||
StaticSpotlightSearcherService,
|
||||
} from "./base/static.searcher"
|
||||
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconLayers from "~icons/lucide/layers"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
|
||||
import { Service } from "dioc"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { pipe } from "fp-ts/function"
|
||||
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 { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment"
|
||||
import {
|
||||
createEnvironment,
|
||||
currentEnvironment$,
|
||||
deleteEnvironment,
|
||||
duplicateEnvironment,
|
||||
environmentsStore,
|
||||
getGlobalVariables,
|
||||
selectedEnvironmentIndex$,
|
||||
setSelectedEnvironmentIndex,
|
||||
} from "~/newstore/environments"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment"
|
||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { Service } from "dioc"
|
||||
import MiniSearch from "minisearch"
|
||||
import { map } from "rxjs"
|
||||
|
||||
type Doc = {
|
||||
text: string
|
||||
@@ -188,29 +187,6 @@ export class EnvironmentsSpotlightSearcherService extends StaticSpotlightSearche
|
||||
}
|
||||
}
|
||||
|
||||
removeSelectedEnvironment = () => {
|
||||
if (this.selectedEnvIndex.value?.type === "NO_ENV_SELECTED") return
|
||||
|
||||
if (this.selectedEnvIndex.value?.type === "MY_ENV") {
|
||||
deleteEnvironment(this.selectedEnvIndex.value.index)
|
||||
// this.toast.success(`${t("state.deleted")}`)
|
||||
}
|
||||
|
||||
if (this.selectedEnvIndex.value?.type === "TEAM_ENV") {
|
||||
pipe(
|
||||
deleteTeamEnvironment(this.selectedEnvIndex.value.teamEnvID),
|
||||
TE.match(
|
||||
(err: GQLError<string>) => {
|
||||
console.error(err)
|
||||
},
|
||||
() => {
|
||||
// this.toast.success(`${this.t("team_environment.deleted")}`)
|
||||
}
|
||||
)
|
||||
)()
|
||||
}
|
||||
}
|
||||
|
||||
public onDocSelected(id: string): void {
|
||||
switch (id) {
|
||||
case "new_environment":
|
||||
@@ -229,7 +205,7 @@ export class EnvironmentsSpotlightSearcherService extends StaticSpotlightSearche
|
||||
})
|
||||
break
|
||||
case "delete_selected_env":
|
||||
this.removeSelectedEnvironment()
|
||||
invokeAction(`modals.environment.delete-selected`)
|
||||
break
|
||||
case "duplicate_selected_env":
|
||||
this.duplicateSelectedEnv()
|
||||
|
||||
@@ -7,14 +7,17 @@ import {
|
||||
StaticSpotlightSearcherService,
|
||||
} from "./base/static.searcher"
|
||||
|
||||
import IconLinkedIn from "~icons/brands/linkedin"
|
||||
import IconTwitter from "~icons/brands/twitter"
|
||||
import IconBook from "~icons/lucide/book"
|
||||
import IconGithub from "~icons/lucide/github"
|
||||
import IconDiscord from "~icons/lucide/link"
|
||||
import IconGitHub from "~icons/lucide/github"
|
||||
import IconLifeBuoy from "~icons/lucide/life-buoy"
|
||||
import IconMessageCircle from "~icons/lucide/message-circle"
|
||||
import IconZap from "~icons/lucide/zap"
|
||||
|
||||
type Doc = {
|
||||
text: string
|
||||
text: string | string[]
|
||||
alternates: string[]
|
||||
icon: object | Component
|
||||
}
|
||||
@@ -56,10 +59,25 @@ export class GeneralSpotlightSearcherService extends StaticSpotlightSearcherServ
|
||||
alternates: ["key", "shortcuts", "binding"],
|
||||
icon: markRaw(IconZap),
|
||||
},
|
||||
social_links: {
|
||||
text: this.t("spotlight.general.social"),
|
||||
alternates: ["social", "github", "binding"],
|
||||
icon: markRaw(IconGithub),
|
||||
link_github: {
|
||||
text: [this.t("spotlight.general.social"), "GitHub"],
|
||||
alternates: ["social", "github", "link"],
|
||||
icon: markRaw(IconGitHub),
|
||||
},
|
||||
link_twitter: {
|
||||
text: [this.t("spotlight.general.social"), "Twitter"],
|
||||
alternates: ["social", "twitter", "link"],
|
||||
icon: markRaw(IconTwitter),
|
||||
},
|
||||
link_discord: {
|
||||
text: [this.t("spotlight.general.social"), "Discord"],
|
||||
alternates: ["social", "discord", "link"],
|
||||
icon: markRaw(IconDiscord),
|
||||
},
|
||||
link_linkedin: {
|
||||
text: [this.t("spotlight.general.social"), "LinkedIn"],
|
||||
alternates: ["social", "linkedin", "link"],
|
||||
icon: markRaw(IconLinkedIn),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -87,8 +105,7 @@ export class GeneralSpotlightSearcherService extends StaticSpotlightSearcherServ
|
||||
}
|
||||
}
|
||||
|
||||
private openDocs() {
|
||||
const url = "https://docs.hoppscotch.io"
|
||||
private openURL(url: string) {
|
||||
window.open(url, "_blank")
|
||||
}
|
||||
|
||||
@@ -101,13 +118,22 @@ export class GeneralSpotlightSearcherService extends StaticSpotlightSearcherServ
|
||||
invokeAction("flyouts.chat.open")
|
||||
break
|
||||
case "open_docs":
|
||||
this.openDocs()
|
||||
this.openURL("https://docs.hoppscotch.io")
|
||||
break
|
||||
case "open_keybindings":
|
||||
invokeAction("flyouts.keybinds.toggle")
|
||||
break
|
||||
case "social_links":
|
||||
invokeAction("modals.social.toggle")
|
||||
case "link_github":
|
||||
this.openURL("https://hoppscotch.io/github")
|
||||
break
|
||||
case "link_twitter":
|
||||
this.openURL("https://twitter.com/hoppscotch_io")
|
||||
break
|
||||
case "link_discord":
|
||||
this.openURL("https://hoppscotch.io/discord")
|
||||
break
|
||||
case "link_linkedin":
|
||||
this.openURL("https://www.linkedin.com/company/hoppscotch/")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
import { Ref, computed, effectScope, markRaw, ref, unref, watch } from "vue"
|
||||
import { getI18n } from "~/modules/i18n"
|
||||
import {
|
||||
SpotlightSearcher,
|
||||
SpotlightSearcherResult,
|
||||
SpotlightSearcherSessionState,
|
||||
SpotlightService,
|
||||
} from ".."
|
||||
|
||||
import { Service } from "dioc"
|
||||
import { useService } from "dioc/vue"
|
||||
import MiniSearch from "minisearch"
|
||||
import IconCheckCircle from "~/components/app/spotlight/entry/IconSelected.vue"
|
||||
import { InterceptorService } from "~/services/interceptor.service"
|
||||
import IconCircle from "~icons/lucide/circle"
|
||||
|
||||
/**
|
||||
* This searcher is responsible for searching through the interceptor.
|
||||
* And switching between them.
|
||||
*/
|
||||
export class InterceptorSpotlightSearcherService
|
||||
extends Service
|
||||
implements SpotlightSearcher
|
||||
{
|
||||
public static readonly ID = "INTERCEPTOR_SPOTLIGHT_SEARCHER_SERVICE"
|
||||
|
||||
private t = getI18n()
|
||||
|
||||
public searcherID = "interceptor"
|
||||
public searcherSectionTitle = this.t("settings.interceptor")
|
||||
|
||||
private readonly spotlight = this.bind(SpotlightService)
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.spotlight.registerSearcher(this)
|
||||
}
|
||||
|
||||
private interceptorService = useService(InterceptorService)
|
||||
|
||||
createSearchSession(
|
||||
query: Readonly<Ref<string>>
|
||||
): [Ref<SpotlightSearcherSessionState>, () => void] {
|
||||
const loading = ref(false)
|
||||
const results = ref<SpotlightSearcherResult[]>([])
|
||||
|
||||
const minisearch = new MiniSearch({
|
||||
fields: ["name", "alternates"],
|
||||
storeFields: ["name"],
|
||||
})
|
||||
|
||||
const interceptorSelection = this.interceptorService
|
||||
.currentInterceptorID as Ref<string>
|
||||
|
||||
const interceptors = this.interceptorService.availableInterceptors
|
||||
|
||||
minisearch.addAll(
|
||||
interceptors.value.map((entry) => {
|
||||
let id = `interceptor-${entry.interceptorID}`
|
||||
if (entry.interceptorID === interceptorSelection.value) {
|
||||
id += "-selected"
|
||||
}
|
||||
const name = unref(entry.name(this.t))
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
alternates: ["interceptor", "change", name],
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const scopeHandle = effectScope()
|
||||
|
||||
scopeHandle.run(() => {
|
||||
watch(
|
||||
[query],
|
||||
([query]) => {
|
||||
results.value = minisearch
|
||||
.search(query, {
|
||||
prefix: true,
|
||||
fuzzy: true,
|
||||
boost: {
|
||||
reltime: 2,
|
||||
},
|
||||
weights: {
|
||||
fuzzy: 0.2,
|
||||
prefix: 0.8,
|
||||
},
|
||||
})
|
||||
.map((x) => {
|
||||
return {
|
||||
id: x.id,
|
||||
icon: markRaw(
|
||||
x.id.endsWith("-selected") ? IconCheckCircle : IconCircle
|
||||
),
|
||||
score: x.score,
|
||||
text: {
|
||||
type: "text",
|
||||
text: [this.t("spotlight.section.interceptor"), x.name],
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
})
|
||||
|
||||
const onSessionEnd = () => {
|
||||
scopeHandle.stop()
|
||||
minisearch.removeAll()
|
||||
}
|
||||
|
||||
const resultObj = computed<SpotlightSearcherSessionState>(() => ({
|
||||
loading: loading.value,
|
||||
results: results.value,
|
||||
}))
|
||||
|
||||
return [resultObj, onSessionEnd]
|
||||
}
|
||||
|
||||
onResultSelect(result: SpotlightSearcherResult): void {
|
||||
const selectedInterceptor = result.id.split("-")[1]
|
||||
this.interceptorService.currentInterceptorID.value = selectedInterceptor
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, markRaw, reactive } from "vue"
|
||||
import { Component, computed, markRaw, reactive } from "vue"
|
||||
import { invokeAction } from "~/helpers/actions"
|
||||
import { getI18n } from "~/modules/i18n"
|
||||
import { SpotlightSearcherResult, SpotlightService } from ".."
|
||||
@@ -7,12 +7,11 @@ import {
|
||||
StaticSpotlightSearcherService,
|
||||
} from "./base/static.searcher"
|
||||
|
||||
import { useRoute } from "vue-router"
|
||||
import { RequestOptionTabs } from "~/components/http/RequestOptions.vue"
|
||||
import { currentActiveTab } from "~/helpers/rest/tab"
|
||||
import IconWindow from "~icons/lucide/app-window"
|
||||
import IconCheck from "~icons/lucide/check"
|
||||
import IconChevronLeft from "~icons/lucide/chevron-left"
|
||||
import IconChevronRight from "~icons/lucide/chevron-right"
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconCode2 from "~icons/lucide/code-2"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconFileCode from "~icons/lucide/file-code"
|
||||
@@ -25,6 +24,7 @@ type Doc = {
|
||||
text: string | string[]
|
||||
alternates: string[]
|
||||
icon: object | Component
|
||||
excludeFromSearch?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,116 +43,160 @@ export class RequestSpotlightSearcherService extends StaticSpotlightSearcherServ
|
||||
|
||||
private readonly spotlight = this.bind(SpotlightService)
|
||||
|
||||
private route = useRoute()
|
||||
private isRESTPage = computed(() => this.route.name === "index")
|
||||
private isGQLPage = computed(() => this.route.name === "graphql")
|
||||
|
||||
private documents: Record<string, Doc> = reactive({
|
||||
send_request: {
|
||||
text: this.t("shortcut.request.send_request"),
|
||||
alternates: ["request", "send"],
|
||||
icon: markRaw(IconPlay),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
save_to_collections: {
|
||||
text: [
|
||||
this.t("request.save_as"),
|
||||
this.t("shortcut.request.save_to_collections"),
|
||||
],
|
||||
text: this.t("spotlight.request.save_as_new"),
|
||||
alternates: ["save", "collections"],
|
||||
icon: markRaw(IconSave),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
save_request: {
|
||||
text: this.t("shortcut.request.save_request"),
|
||||
alternates: ["save", "request"],
|
||||
icon: markRaw(IconSave),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
rename_request: {
|
||||
text: this.t("shortcut.request.rename"),
|
||||
alternates: ["rename", "request"],
|
||||
icon: markRaw(IconRename),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
copy_request_link: {
|
||||
text: this.t("shortcut.request.copy_request_link"),
|
||||
alternates: ["copy", "link"],
|
||||
icon: markRaw(IconCopy),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
reset_request: {
|
||||
text: this.t("shortcut.request.reset_request"),
|
||||
alternates: ["reset", "request"],
|
||||
icon: markRaw(IconRotateCCW),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
import_curl: {
|
||||
text: this.t("shortcut.request.import_curl"),
|
||||
alternates: ["import", "curl"],
|
||||
icon: markRaw(IconFileCode),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
show_code: {
|
||||
text: this.t("shortcut.request.show_code"),
|
||||
alternates: ["show", "code"],
|
||||
icon: markRaw(IconCode2),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
// Change request method
|
||||
next_method: {
|
||||
text: this.t("shortcut.request.next_method"),
|
||||
alternates: ["next", "method"],
|
||||
icon: markRaw(IconChevronRight),
|
||||
},
|
||||
previous_method: {
|
||||
text: this.t("shortcut.request.previous_method"),
|
||||
alternates: ["previous", "method"],
|
||||
icon: markRaw(IconChevronLeft),
|
||||
},
|
||||
get_method: {
|
||||
text: this.t("shortcut.request.get_method"),
|
||||
text: [this.t("spotlight.request.select_method"), "GET"],
|
||||
alternates: ["get", "method"],
|
||||
icon: markRaw(IconCheck),
|
||||
icon: markRaw(IconCheckCircle),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
head_method: {
|
||||
text: this.t("shortcut.request.head_method"),
|
||||
text: [this.t("spotlight.request.select_method"), "HEAD"],
|
||||
alternates: ["head", "method"],
|
||||
icon: markRaw(IconCheck),
|
||||
icon: markRaw(IconCheckCircle),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
post_method: {
|
||||
text: this.t("shortcut.request.post_method"),
|
||||
text: [this.t("spotlight.request.select_method"), "POST"],
|
||||
alternates: ["post", "method"],
|
||||
icon: markRaw(IconCheck),
|
||||
icon: markRaw(IconCheckCircle),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
put_method: {
|
||||
text: this.t("shortcut.request.put_method"),
|
||||
text: [this.t("spotlight.request.select_method"), "PUT"],
|
||||
alternates: ["put", "method"],
|
||||
icon: markRaw(IconCheck),
|
||||
icon: markRaw(IconCheckCircle),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
delete_method: {
|
||||
text: this.t("shortcut.request.delete_method"),
|
||||
text: [this.t("spotlight.request.select_method"), "DELETE"],
|
||||
alternates: ["delete", "method"],
|
||||
icon: markRaw(IconCheck),
|
||||
icon: markRaw(IconCheckCircle),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
// Change sub tabs
|
||||
tab_parameters: {
|
||||
text: this.t("spotlight.request.tab_parameters"),
|
||||
text: [
|
||||
this.t("spotlight.request.switch_to"),
|
||||
this.t("spotlight.request.tab_parameters"),
|
||||
],
|
||||
alternates: ["parameters", "tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
tab_body: {
|
||||
text: this.t("spotlight.request.tab_body"),
|
||||
text: [
|
||||
this.t("spotlight.request.switch_to"),
|
||||
this.t("spotlight.request.tab_body"),
|
||||
],
|
||||
alternates: ["body", "tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
tab_headers: {
|
||||
text: this.t("spotlight.request.tab_headers"),
|
||||
text: [
|
||||
this.t("spotlight.request.switch_to"),
|
||||
this.t("spotlight.request.tab_headers"),
|
||||
],
|
||||
alternates: ["headers", "tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
tab_authorization: {
|
||||
text: this.t("spotlight.request.tab_authorization"),
|
||||
text: [
|
||||
this.t("spotlight.request.switch_to"),
|
||||
this.t("spotlight.request.tab_authorization"),
|
||||
],
|
||||
alternates: ["authorization", "tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.isRESTPage.value ?? !this.isGQLPage.value
|
||||
),
|
||||
},
|
||||
tab_pre_request_script: {
|
||||
text: this.t("spotlight.request.tab_pre_request_script"),
|
||||
text: [
|
||||
this.t("spotlight.request.switch_to"),
|
||||
this.t("spotlight.request.tab_pre_request_script"),
|
||||
],
|
||||
alternates: ["pre-request", "script", "tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
tab_tests: {
|
||||
text: this.t("spotlight.request.tab_tests"),
|
||||
text: [
|
||||
this.t("spotlight.request.switch_to"),
|
||||
this.t("spotlight.request.tab_tests"),
|
||||
],
|
||||
alternates: ["tests", "tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(() => !this.isRESTPage.value),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -209,12 +253,6 @@ export class RequestSpotlightSearcherService extends StaticSpotlightSearcherServ
|
||||
case "reset_request":
|
||||
invokeAction("request.reset")
|
||||
break
|
||||
case "next_method":
|
||||
invokeAction("request.method.next")
|
||||
break
|
||||
case "previous_method":
|
||||
invokeAction("request.method.prev")
|
||||
break
|
||||
case "get_method":
|
||||
invokeAction("request.method.get")
|
||||
break
|
||||
|
||||
@@ -10,11 +10,10 @@ import {
|
||||
} from "./base/static.searcher"
|
||||
|
||||
import IconCloud from "~icons/lucide/cloud"
|
||||
import IconGlobe from "~icons/lucide/globe"
|
||||
import IconMonitor from "~icons/lucide/monitor"
|
||||
import IconMoon from "~icons/lucide/moon"
|
||||
import IconSun from "~icons/lucide/sun"
|
||||
import IconGlobe from "~icons/lucide/globe"
|
||||
import IconShieldCheck from "~icons/lucide/shield-check"
|
||||
import IconType from "~icons/lucide/type"
|
||||
|
||||
type Doc = {
|
||||
@@ -128,22 +127,6 @@ export class SettingsSpotlightSearcherService extends StaticSpotlightSearcherSer
|
||||
alternates: ["language", "change language"],
|
||||
icon: markRaw(IconGlobe),
|
||||
},
|
||||
change_interceptor: {
|
||||
text: [
|
||||
this.t("spotlight.section.interceptor"),
|
||||
this.t("spotlight.settings.change_interceptor"),
|
||||
],
|
||||
alternates: ["interceptor", "change interceptor"],
|
||||
icon: markRaw(IconShieldCheck),
|
||||
},
|
||||
install_ext: {
|
||||
text: [
|
||||
this.t("spotlight.section.interceptor"),
|
||||
this.t("spotlight.settings.install_extension"),
|
||||
],
|
||||
alternates: ["install extension", "extension", "interceptor"],
|
||||
icon: markRaw(IconShieldCheck),
|
||||
},
|
||||
})
|
||||
|
||||
constructor() {
|
||||
@@ -174,27 +157,12 @@ export class SettingsSpotlightSearcherService extends StaticSpotlightSearcherSer
|
||||
applySetting("BG_COLOR", theme)
|
||||
}
|
||||
|
||||
installExtension() {
|
||||
const url = navigator.userAgent.includes("Firefox")
|
||||
? "https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
|
||||
: "https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
|
||||
window.open(url, "_blank")
|
||||
}
|
||||
|
||||
public onDocSelected(id: string): void {
|
||||
switch (id) {
|
||||
case "change_interceptor":
|
||||
invokeAction("navigation.jump.settings")
|
||||
break
|
||||
|
||||
case "change_lang":
|
||||
invokeAction("navigation.jump.settings")
|
||||
break
|
||||
|
||||
case "install_ext":
|
||||
this.installExtension()
|
||||
break
|
||||
|
||||
// theme actions
|
||||
case "theme_system":
|
||||
invokeAction("settings.theme.system")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, markRaw, reactive } from "vue"
|
||||
import { Component, computed, markRaw, reactive } from "vue"
|
||||
import { getI18n } from "~/modules/i18n"
|
||||
import { SpotlightSearcherResult, SpotlightService } from ".."
|
||||
import {
|
||||
@@ -6,19 +6,23 @@ import {
|
||||
StaticSpotlightSearcherService,
|
||||
} from "./base/static.searcher"
|
||||
|
||||
import { useRoute } from "vue-router"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import {
|
||||
closeOtherTabs,
|
||||
closeTab,
|
||||
createNewTab,
|
||||
currentTabID,
|
||||
getActiveTabs,
|
||||
} from "~/helpers/rest/tab"
|
||||
import IconWindow from "~icons/lucide/app-window"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import { invokeAction } from "~/helpers/actions"
|
||||
|
||||
type Doc = {
|
||||
text: string
|
||||
alternates: string[]
|
||||
icon: object | Component
|
||||
excludeFromSearch?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,21 +41,39 @@ export class TabSpotlightSearcherService extends StaticSpotlightSearcherService<
|
||||
|
||||
private readonly spotlight = this.bind(SpotlightService)
|
||||
|
||||
private route = useRoute()
|
||||
private showAction = computed(
|
||||
() => this.route.name === "index" ?? this.route.name === "graphql"
|
||||
)
|
||||
|
||||
private documents: Record<string, Doc> = reactive({
|
||||
duplicate_tab: {
|
||||
text: this.t("spotlight.tab.duplicate"),
|
||||
alternates: ["tab", "duplicate", "duplicate tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(() => !this.showAction.value),
|
||||
},
|
||||
close_current_tab: {
|
||||
text: this.t("spotlight.tab.close_current"),
|
||||
alternates: ["tab", "close", "close tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.showAction.value ?? getActiveTabs().value.length === 1
|
||||
),
|
||||
},
|
||||
close_other_tabs: {
|
||||
text: this.t("spotlight.tab.close_others"),
|
||||
alternates: ["tab", "close", "close all"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(
|
||||
() => !this.showAction.value ?? getActiveTabs().value.length < 2
|
||||
),
|
||||
},
|
||||
open_new_tab: {
|
||||
text: this.t("spotlight.tab.new_tab"),
|
||||
alternates: ["tab", "new", "open tab"],
|
||||
icon: markRaw(IconWindow),
|
||||
excludeFromSearch: computed(() => !this.showAction.value),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -80,6 +102,10 @@ export class TabSpotlightSearcherService extends StaticSpotlightSearcherService<
|
||||
}
|
||||
|
||||
public onDocSelected(id: string): void {
|
||||
if (id === "duplicate_tab")
|
||||
invokeAction("request.duplicate-tab", {
|
||||
tabID: currentTabID.value,
|
||||
})
|
||||
if (id === "close_current_tab") closeTab(currentTabID.value)
|
||||
if (id === "close_other_tabs") closeOtherTabs(currentTabID.value)
|
||||
if (id === "open_new_tab")
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
ref,
|
||||
watch,
|
||||
} from "vue"
|
||||
import { activeActions$, invokeAction } from "~/helpers/actions"
|
||||
import { invokeAction } from "~/helpers/actions"
|
||||
import { getI18n } from "~/modules/i18n"
|
||||
import {
|
||||
SpotlightSearcher,
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
import { Service } from "dioc"
|
||||
import * as E from "fp-ts/Either"
|
||||
import MiniSearch from "minisearch"
|
||||
import IconCheckCircle from "~/components/app/spotlight/entry/IconSelected.vue"
|
||||
import { useStreamStatic } from "~/composables/stream"
|
||||
import { runGQLQuery } from "~/helpers/backend/GQLClient"
|
||||
import { GetMyTeamsDocument, GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
@@ -36,7 +37,7 @@ import IconUserPlus from "~icons/lucide/user-plus"
|
||||
import IconUsers from "~icons/lucide/users"
|
||||
|
||||
type Doc = {
|
||||
text: string
|
||||
text: string | string[]
|
||||
alternates: string[]
|
||||
icon: object | Component
|
||||
excludeFromSearch?: boolean
|
||||
@@ -66,14 +67,6 @@ export class WorkspaceSpotlightSearcherService extends StaticSpotlightSearcherSe
|
||||
}
|
||||
)[0]
|
||||
|
||||
private activeActions = useStreamStatic(activeActions$, [], () => {
|
||||
/* noop */
|
||||
})[0]
|
||||
|
||||
private isLoggedInUser = computed(() =>
|
||||
this.activeActions.value.includes("user.logout")
|
||||
)
|
||||
|
||||
private isTeamSelected = computed(
|
||||
() =>
|
||||
this.workspace.value.type === "team" &&
|
||||
@@ -82,31 +75,33 @@ export class WorkspaceSpotlightSearcherService extends StaticSpotlightSearcherSe
|
||||
|
||||
private documents: Record<string, Doc> = reactive({
|
||||
new_team: {
|
||||
text: this.t("spotlight.workspace.new"),
|
||||
text: [this.t("team.title"), this.t("spotlight.workspace.new")],
|
||||
alternates: ["new", "team", "workspace"],
|
||||
icon: markRaw(IconUsers),
|
||||
excludeFromSearch: computed(() => !this.isLoggedInUser.value),
|
||||
},
|
||||
edit_team: {
|
||||
text: this.t("spotlight.workspace.edit"),
|
||||
text: [this.t("team.title"), this.t("spotlight.workspace.edit")],
|
||||
alternates: ["edit", "team", "workspace"],
|
||||
icon: markRaw(IconEdit),
|
||||
excludeFromSearch: computed(() => !this.isTeamSelected.value),
|
||||
},
|
||||
invite_members: {
|
||||
text: this.t("spotlight.workspace.invite"),
|
||||
text: [this.t("team.title"), this.t("spotlight.workspace.invite")],
|
||||
alternates: ["invite", "members", "workspace"],
|
||||
icon: markRaw(IconUserPlus),
|
||||
excludeFromSearch: computed(() => !this.isTeamSelected.value),
|
||||
},
|
||||
delete_team: {
|
||||
text: this.t("spotlight.workspace.delete"),
|
||||
text: [this.t("team.title"), this.t("spotlight.workspace.delete")],
|
||||
alternates: ["delete", "team", "workspace"],
|
||||
icon: markRaw(IconTrash2),
|
||||
excludeFromSearch: computed(() => !this.isTeamSelected.value),
|
||||
},
|
||||
switch_to_personal: {
|
||||
text: this.t("spotlight.workspace.switch_to_personal"),
|
||||
text: [
|
||||
this.t("team.title"),
|
||||
this.t("spotlight.workspace.switch_to_personal"),
|
||||
],
|
||||
alternates: ["switch", "team", "workspace", "personal"],
|
||||
icon: markRaw(IconUser),
|
||||
excludeFromSearch: computed(() => !this.isTeamSelected.value),
|
||||
@@ -145,8 +140,13 @@ export class WorkspaceSpotlightSearcherService extends StaticSpotlightSearcherSe
|
||||
}
|
||||
|
||||
public onDocSelected(id: string): void {
|
||||
if (id === "new_team") invokeAction(`modals.team.new`)
|
||||
else if (id === "edit_team") invokeAction(`modals.team.edit`)
|
||||
if (id === "new_team") {
|
||||
if (platform.auth.getCurrentUser()) {
|
||||
invokeAction(`modals.team.new`)
|
||||
} else {
|
||||
invokeAction(`modals.login.toggle`)
|
||||
}
|
||||
} else if (id === "edit_team") invokeAction(`modals.team.edit`)
|
||||
else if (id === "invite_members") invokeAction(`modals.team.invite`)
|
||||
else if (id === "delete_team") this.deleteTeam()
|
||||
else if (id === "switch_to_personal")
|
||||
@@ -197,6 +197,14 @@ export class SwitchWorkspaceSpotlightSearcherService
|
||||
})
|
||||
}
|
||||
|
||||
private workspace = useStreamStatic(
|
||||
workspaceStatus$,
|
||||
{ type: "personal" },
|
||||
() => {
|
||||
/* noop */
|
||||
}
|
||||
)[0]
|
||||
|
||||
createSearchSession(
|
||||
query: Readonly<Ref<string>>
|
||||
): [Ref<SpotlightSearcherSessionState>, () => void] {
|
||||
@@ -211,8 +219,16 @@ export class SwitchWorkspaceSpotlightSearcherService
|
||||
this.fetchMyTeams().then((teams) => {
|
||||
minisearch.addAll(
|
||||
teams.map((entry) => {
|
||||
let id = `workspace-${entry.id}`
|
||||
// if id matches add -selected to it
|
||||
if (
|
||||
this.workspace.value.type === "team" &&
|
||||
this.workspace.value.teamID === entry.id
|
||||
) {
|
||||
id += "-selected"
|
||||
}
|
||||
return {
|
||||
id: `workspace-${entry.id}`,
|
||||
id,
|
||||
name: entry.name,
|
||||
alternates: ["team", "workspace", "change", "switch"],
|
||||
}
|
||||
@@ -241,7 +257,9 @@ export class SwitchWorkspaceSpotlightSearcherService
|
||||
.map((x) => {
|
||||
return {
|
||||
id: x.id,
|
||||
icon: markRaw(IconUsers),
|
||||
icon: markRaw(
|
||||
x.id.endsWith("-selected") ? IconCheckCircle : IconUsers
|
||||
),
|
||||
score: x.score,
|
||||
text: {
|
||||
type: "text",
|
||||
|
||||
Reference in New Issue
Block a user