+
-
+
-
+
+
{{ node.data.value }}
-
+
Empty Node!
+
+
+
+
+
+
diff --git a/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionTreeAdapter.ts b/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionTreeAdapter.ts
index fbb8cf8aa..66e36284b 100644
--- a/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionTreeAdapter.ts
+++ b/packages/hoppscotch-common/src/helpers/adapters/WorkspaceRESTCollectionTreeAdapter.ts
@@ -2,7 +2,7 @@ import {
ChildrenResult,
SmartTreeAdapter,
} from "@hoppscotch/ui/dist/src/helpers/treeAdapter"
-import { Ref, computed, ref, watchEffect } from "vue"
+import { Ref, ref, watchEffect } from "vue"
import { NewWorkspaceService } from "~/services/new-workspace"
import { HandleRef } from "~/services/new-workspace/handle"
import {
diff --git a/packages/hoppscotch-common/src/helpers/rest/labelColoring.ts b/packages/hoppscotch-common/src/helpers/rest/labelColoring.ts
index 092b76dc6..a2bbf45a3 100644
--- a/packages/hoppscotch-common/src/helpers/rest/labelColoring.ts
+++ b/packages/hoppscotch-common/src/helpers/rest/labelColoring.ts
@@ -1,13 +1,17 @@
import { pipe } from "fp-ts/function"
import * as O from "fp-ts/Option"
import * as RR from "fp-ts/ReadonlyRecord"
+import { HoppRESTRequest } from "@hoppscotch/data"
export const REQUEST_METHOD_LABEL_COLORS = {
- get: "var(--success-color)",
- post: "var(--warning-color)",
- put: "var(--blue-color)",
- delete: "var(--cl-error-color)",
- default: "#6b7280",
+ get: "var(--method-get-color)",
+ post: "var(--method-post-color)",
+ put: "var(--method-put-color)",
+ patch: "var(--method-patch-color)",
+ delete: "var(--method-delete-color)",
+ head: "var(--method-head-color)",
+ options: "var(--method-options-color)",
+ default: "var(--method-default-color)",
} as const
/**
@@ -15,10 +19,18 @@ export const REQUEST_METHOD_LABEL_COLORS = {
* @param request The HoppRESTRequest object to get the value for
* @returns The class value for the given HTTP VERB, if not, a generic verb class
*/
-export function getMethodLabelColorClassOf(request: { method: string }) {
+export function getMethodLabelColorClassOf(request: HoppRESTRequest) {
return pipe(
REQUEST_METHOD_LABEL_COLORS,
RR.lookup(request.method.toLowerCase()),
O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
)
}
+
+export function getMethodLabelColor(method: string) {
+ return pipe(
+ REQUEST_METHOD_LABEL_COLORS,
+ RR.lookup(method.toLowerCase()),
+ O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
+ )
+}
diff --git a/packages/hoppscotch-common/src/index.ts b/packages/hoppscotch-common/src/index.ts
index a4db8641d..3a084c7ea 100644
--- a/packages/hoppscotch-common/src/index.ts
+++ b/packages/hoppscotch-common/src/index.ts
@@ -25,6 +25,9 @@ export function createHoppApp(el: string | Element, platformDef: PlatformDef) {
const app = createApp(App)
+ HOPP_MODULES.forEach((mod) => mod.onVueAppInit?.(app))
+ platformDef.addedHoppModules?.forEach((mod) => mod.onVueAppInit?.(app))
+
// Some basic work that needs to be done before module inits even
initBackendGQLClient()
initializeApp()
@@ -37,9 +40,6 @@ export function createHoppApp(el: string | Element, platformDef: PlatformDef) {
getService(TestWorkspaceProviderService)
getService(PersonalWorkspaceProviderService)
- HOPP_MODULES.forEach((mod) => mod.onVueAppInit?.(app))
- platformDef.addedHoppModules?.forEach((mod) => mod.onVueAppInit?.(app))
-
app.mount(el)
console.info(
diff --git a/packages/hoppscotch-common/src/newstore/collections.ts b/packages/hoppscotch-common/src/newstore/collections.ts
index 3c021809a..72afdc029 100644
--- a/packages/hoppscotch-common/src/newstore/collections.ts
+++ b/packages/hoppscotch-common/src/newstore/collections.ts
@@ -319,6 +319,7 @@ const restCollectionDispatchers = defineDispatchers({
)
return {}
}
+
// We get the index path to the folder itself,
// we have to find the folder containing the target folder,
// so we pop the last path index
diff --git a/packages/hoppscotch-common/src/services/new-workspace/index.ts b/packages/hoppscotch-common/src/services/new-workspace/index.ts
index 60331f88a..29e6f006e 100644
--- a/packages/hoppscotch-common/src/services/new-workspace/index.ts
+++ b/packages/hoppscotch-common/src/services/new-workspace/index.ts
@@ -13,6 +13,7 @@ import { HandleRef } from "./handle"
import * as E from "fp-ts/Either"
import { Workspace, WorkspaceCollection } from "./workspace"
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
+import { HoppRESTRequest } from "@hoppscotch/data"
export type WorkspaceError
=
| { type: "SERVICE_ERROR"; error: ServiceErr }
@@ -172,7 +173,8 @@ export class NewWorkspaceService extends Service {
public async createRESTChildCollection(
parentCollHandle: HandleRef,
- collectionName: string
+ collectionName: string,
+ path: string
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
@@ -193,7 +195,8 @@ export class NewWorkspaceService extends Service {
const result = await provider.createRESTChildCollection(
parentCollHandle,
- collectionName
+ collectionName,
+ path
)
if (E.isLeft(result)) {
@@ -203,6 +206,186 @@ export class NewWorkspaceService extends Service {
return E.right(result.right)
}
+ public async createRESTRequest(
+ parentCollHandle: HandleRef,
+ requestName: string,
+ path: string
+ ): Promise<
+ E.Either<
+ WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
+ HandleRef
+ >
+ > {
+ if (parentCollHandle.value.type === "invalid") {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
+ }
+
+ const provider = this.registeredProviders.get(
+ parentCollHandle.value.data.providerID
+ )
+
+ if (!provider) {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
+ }
+
+ const result = await provider.createRESTRequest(
+ parentCollHandle,
+ requestName,
+ path
+ )
+
+ if (E.isLeft(result)) {
+ return E.left({ type: "PROVIDER_ERROR", error: result.left })
+ }
+
+ return E.right(result.right)
+ }
+
+ public async removeRESTRequest(
+ parentCollHandle: HandleRef,
+ path: string,
+ requestIndex: number
+ ): Promise<
+ E.Either<
+ WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
+ HandleRef
+ >
+ > {
+ if (parentCollHandle.value.type === "invalid") {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
+ }
+
+ const provider = this.registeredProviders.get(
+ parentCollHandle.value.data.providerID
+ )
+
+ if (!provider) {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
+ }
+
+ const result = await provider.removeRESTRequest(
+ parentCollHandle,
+ path,
+ requestIndex
+ )
+
+ if (E.isLeft(result)) {
+ return E.left({ type: "PROVIDER_ERROR", error: result.left })
+ }
+
+ return E.right(result.right)
+ }
+
+ public async selectRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ requestIndex: string,
+ request: HoppRESTRequest
+ ): Promise<
+ E.Either<
+ WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
+ HandleRef
+ >
+ > {
+ if (parentCollHandle.value.type === "invalid") {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
+ }
+
+ const provider = this.registeredProviders.get(
+ parentCollHandle.value.data.providerID
+ )
+
+ if (!provider) {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
+ }
+
+ const result = await provider.selectRESTRequest(
+ parentCollHandle,
+ collPath,
+ requestIndex,
+ request
+ )
+
+ if (E.isLeft(result)) {
+ return E.left({ type: "PROVIDER_ERROR", error: result.left })
+ }
+
+ return E.right(result.right)
+ }
+
+ public async duplicateRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ request: HoppRESTRequest
+ ): Promise<
+ E.Either<
+ WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
+ HandleRef
+ >
+ > {
+ if (parentCollHandle.value.type === "invalid") {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
+ }
+
+ const provider = this.registeredProviders.get(
+ parentCollHandle.value.data.providerID
+ )
+
+ if (!provider) {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
+ }
+
+ const result = await provider.duplicateRESTRequest(
+ parentCollHandle,
+ collPath,
+ request
+ )
+
+ if (E.isLeft(result)) {
+ return E.left({ type: "PROVIDER_ERROR", error: result.left })
+ }
+
+ return E.right(result.right)
+ }
+
+ public async editRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ requestIndex: number,
+ request: HoppRESTRequest
+ ): Promise<
+ E.Either<
+ WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
+ HandleRef
+ >
+ > {
+ if (parentCollHandle.value.type === "invalid") {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
+ }
+
+ const provider = this.registeredProviders.get(
+ parentCollHandle.value.data.providerID
+ )
+
+ if (!provider) {
+ return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
+ }
+
+ const result = await provider.editRESTRequest(
+ parentCollHandle,
+ collPath,
+ requestIndex,
+ request
+ )
+
+ if (E.isLeft(result)) {
+ return E.left({ type: "PROVIDER_ERROR", error: result.left })
+ }
+
+ return E.right(result.right)
+ }
+
+
public async getRESTCollectionChildrenView(
collectionHandle: HandleRef
): Promise<
diff --git a/packages/hoppscotch-common/src/services/new-workspace/provider.ts b/packages/hoppscotch-common/src/services/new-workspace/provider.ts
index 5ad1ad1fc..653626377 100644
--- a/packages/hoppscotch-common/src/services/new-workspace/provider.ts
+++ b/packages/hoppscotch-common/src/services/new-workspace/provider.ts
@@ -3,6 +3,7 @@ import * as E from "fp-ts/Either"
import { HandleRef } from "./handle"
import { Workspace, WorkspaceCollection, WorkspaceDecor } from "./workspace"
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
+import { HoppRESTRequest } from "@hoppscotch/data"
export interface WorkspaceProvider {
providerID: string
@@ -30,6 +31,34 @@ export interface WorkspaceProvider {
): Promise>>
createRESTChildCollection(
parentCollHandle: HandleRef,
- collectionName: string
+ collectionName: string,
+ path: string
+ ): Promise>>
+ createRESTRequest(
+ parentCollHandle: HandleRef,
+ requestName: string,
+ path: string
+ ): Promise>>
+ removeRESTRequest(
+ parentCollHandle: HandleRef,
+ path: string,
+ requestIndex: number
+ ): Promise>>
+ selectRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ requestIndex: string,
+ request: HoppRESTRequest
+ ): Promise>>
+ duplicateRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ request: HoppRESTRequest
+ ): Promise>>
+ editRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ requestIndex: number,
+ request: HoppRESTRequest
): Promise>>
}
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 81353d5b1..37850cd9a 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
@@ -1,18 +1,21 @@
-import {
- HoppCollection,
- HoppRESTRequest,
- makeCollection,
-} from "@hoppscotch/data"
+import { HoppCollection, makeCollection } from "@hoppscotch/data"
import { Service } from "dioc"
import * as E from "fp-ts/Either"
-import { get } from "lodash-es"
-import { v4 as uuid } from "uuid"
-import { Ref, computed, markRaw, ref, shallowReactive, shallowRef } from "vue"
+import { Ref, computed, markRaw, nextTick, ref, shallowRef } from "vue"
import PersonalWorkspaceSelector from "~/components/workspace/PersonalWorkspaceSelector.vue"
import { useStreamStatic } from "~/composables/stream"
-import { addRESTCollection, restCollectionStore } from "~/newstore/collections"
+import {
+ addRESTCollection,
+ addRESTFolder,
+ cascadeParentCollectionForHeaderAuth,
+ editRESTRequest,
+ navigateToFolderWithIndexPath,
+ removeRESTRequest,
+ restCollectionStore,
+ saveRESTRequestAs,
+} from "~/newstore/collections"
import { platform } from "~/platform"
import { HandleRef } from "~/services/new-workspace/handle"
@@ -28,8 +31,15 @@ import {
WorkspaceDecor,
} from "~/services/new-workspace/workspace"
+import { cloneDeep } from "lodash-es"
+import {
+ getRequestsByPath,
+ resolveSaveContextOnRequestReorder,
+} from "~/helpers/collection/request"
+import { RESTTabService } from "~/services/tab/rest"
import IconUser from "~icons/lucide/user"
import { NewWorkspaceService } from ".."
+import { HoppRESTRequest } from "@hoppscotch/data"
export class PersonalWorkspaceProviderService
extends Service
@@ -40,6 +50,7 @@ export class PersonalWorkspaceProviderService
public readonly providerID = "PERSONAL_WORKSPACE_PROVIDER"
private workspaceService = this.bind(NewWorkspaceService)
+ private tabs = this.bind(RESTTabService)
public workspaceDecor: Ref = ref({
headerCurrentIcon: IconUser,
@@ -63,77 +74,68 @@ export class PersonalWorkspaceProviderService
this.workspaceService.registerWorkspaceProvider(this)
}
- private collectionIDMap = shallowReactive(
- new WeakMap()
- )
-
- private reqIDMap = shallowReactive(new WeakMap())
-
- private collectionIDPathMap = shallowReactive(new Map())
-
- private generatedUUIDs = new Set()
-
- private generateUniqueUUID() {
- let id = uuid()
-
- while (this.generatedUUIDs.has(id)) {
- id = uuid()
- }
-
- this.generatedUUIDs.add(id)
-
- return id
- }
-
- private resolvePathFromCollectionID(id: string): number[] | undefined {
- return this.collectionIDPathMap.get(id)
- }
-
- private resolveCollectionFromCollectionID(
- id: string
- ): HoppCollection | undefined {
- const path = this.resolvePathFromCollectionID(id)
-
- if (path === undefined) return
-
- const collPath = path.flatMap((x, i) =>
- i === 0 ? [x.toString()] : ["folders", x.toString()]
- )
-
- const coll = get(this.restCollectionState.value.state, collPath) as
- | HoppCollection
- | undefined
-
- return coll
- }
-
- private getIssuedInstanceIDForCollection(
- coll: HoppCollection,
- location: number[]
+ private navigateToFolderWithIndexPath(
+ collections: HoppCollection[],
+ indexPaths: number[]
) {
- const id = this.collectionIDMap.has(coll)
- ? this.collectionIDMap.get(coll)!
- : this.generateUniqueUUID()
+ if (indexPaths.length === 0) return null
- this.collectionIDPathMap.set(id, location)
- this.collectionIDMap.set(coll, id)
+ let target = collections[indexPaths.shift() as number]
- return id
- }
+ while (indexPaths.length > 0)
+ target = target?.folders[indexPaths.shift() as number]
- private getIssuedInstanceIDForRequest(req: HoppRESTRequest) {
- const id = this.reqIDMap.get(req) ?? this.generateUniqueUUID()
-
- this.reqIDMap.set(req, id)
-
- return id
+ return target !== undefined ? target : null
}
public createRESTChildCollection(
parentCollHandle: HandleRef,
- collectionName: string
+ collectionName: string,
+ path: string
): Promise>> {
- throw new Error("TODO: Method not implemented.")
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
+ }
+
+ return Promise.resolve(
+ E.right(
+ computed(() => {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return {
+ type: "invalid" as const,
+ reason: "WORKSPACE_INVALIDATED" as const,
+ }
+ }
+
+ addRESTFolder(collectionName, path)
+
+ platform.analytics?.logEvent({
+ type: "HOPP_CREATE_COLLECTION",
+ workspaceType: "personal",
+ isRootCollection: false,
+ platform: "rest",
+ })
+
+ return {
+ type: "ok",
+ data: {
+ providerID: this.providerID,
+ workspaceID: parentCollHandle.value.data.workspaceID,
+ collectionID: parentCollHandle.value.data.collectionID,
+ name: collectionName,
+ },
+ }
+ })
+ )
+ )
}
public createRESTRootCollection(
@@ -157,7 +159,7 @@ export class PersonalWorkspaceProviderService
workspaceHandle.value.data.workspaceID !== "personal"
) {
return {
- type: "invalid",
+ type: "invalid" as const,
reason: "WORKSPACE_INVALIDATED" as const,
}
}
@@ -196,6 +198,329 @@ export class PersonalWorkspaceProviderService
)
}
+ public createRESTRequest(
+ parentCollHandle: HandleRef,
+ requestName: string,
+ path: string
+ ): Promise>> {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
+ }
+
+ return Promise.resolve(
+ E.right(
+ computed(() => {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return {
+ type: "invalid" as const,
+ reason: "WORKSPACE_INVALIDATED" as const,
+ }
+ }
+
+ const newRequest = {
+ ...cloneDeep(this.tabs.currentActiveTab.value.document.request),
+ name: requestName,
+ }
+
+ const insertionIndex = saveRESTRequestAs(path, newRequest)
+
+ const { auth, headers } = cascadeParentCollectionForHeaderAuth(
+ path,
+ "rest"
+ )
+
+ this.tabs.createNewTab({
+ request: newRequest,
+ isDirty: false,
+ saveContext: {
+ originLocation: "user-collection",
+ folderPath: path,
+ requestIndex: insertionIndex,
+ },
+ inheritedProperties: {
+ auth,
+ headers,
+ },
+ })
+
+ platform.analytics?.logEvent({
+ type: "HOPP_SAVE_REQUEST",
+ workspaceType: "personal",
+ createdNow: true,
+ platform: "rest",
+ })
+
+ return {
+ type: "ok",
+ data: {
+ providerID: this.providerID,
+ workspaceID: parentCollHandle.value.data.workspaceID,
+ collectionID: parentCollHandle.value.data.collectionID,
+ name: requestName,
+ },
+ }
+ })
+ )
+ )
+ }
+
+ public removeRESTRequest(
+ parentCollHandle: HandleRef,
+ path: string,
+ requestIndex: number
+ ): Promise>> {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
+ }
+
+ return Promise.resolve(
+ E.right(
+ computed(() => {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return {
+ type: "invalid" as const,
+ reason: "WORKSPACE_INVALIDATED" as const,
+ }
+ }
+
+ const possibleTab = this.tabs.getTabRefWithSaveContext({
+ originLocation: "user-collection",
+ folderPath: path,
+ requestIndex,
+ })
+
+ // If there is a tab attached to this request, dissociate its state and mark it dirty
+ if (possibleTab) {
+ possibleTab.value.document.saveContext = null
+ possibleTab.value.document.isDirty = true
+ }
+
+ console.log(
+ `REST collection store state is `,
+ restCollectionStore.value.state
+ )
+
+ const requestToRemove = navigateToFolderWithIndexPath(
+ restCollectionStore.value.state,
+ path.split("/").map((i) => parseInt(i))
+ )?.requests[requestIndex]
+
+ removeRESTRequest(path, requestIndex, requestToRemove?.id)
+
+ // the same function is used to reorder requests since after removing, it's basically doing reorder
+ resolveSaveContextOnRequestReorder({
+ lastIndex: requestIndex,
+ newIndex: -1,
+ folderPath: path,
+ length: getRequestsByPath(
+ this.restCollectionState.value.state,
+ path
+ ).length,
+ })
+
+ return {
+ type: "ok",
+ data: {
+ providerID: this.providerID,
+ workspaceID: parentCollHandle.value.data.workspaceID,
+ collectionID: parentCollHandle.value.data.workspaceID,
+ name: "" as const,
+ },
+ }
+ })
+ )
+ )
+ }
+
+ public selectRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ requestIndex: string,
+ request: HoppRESTRequest
+ ): Promise>> {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
+ }
+
+ return Promise.resolve(
+ E.right(
+ computed(() => {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return {
+ type: "invalid" as const,
+ reason: "WORKSPACE_INVALIDATED" as const,
+ }
+ }
+
+ // If there is a request with this save context, switch into it
+ let possibleTab = null
+
+ const { auth, headers } = cascadeParentCollectionForHeaderAuth(
+ collPath,
+ "rest"
+ )
+ possibleTab = this.tabs.getTabRefWithSaveContext({
+ originLocation: "user-collection",
+ requestIndex: parseInt(requestIndex),
+ folderPath: collPath!,
+ })
+ if (possibleTab) {
+ this.tabs.setActiveTab(possibleTab.value.id)
+ } else {
+ // If not, open the request in a new tab
+ this.tabs.createNewTab({
+ request: cloneDeep(request),
+ isDirty: false,
+ saveContext: {
+ originLocation: "user-collection",
+ folderPath: collPath!,
+ requestIndex: parseInt(requestIndex),
+ },
+ inheritedProperties: {
+ auth,
+ headers,
+ },
+ })
+ }
+
+ return {
+ type: "ok",
+ data: {
+ providerID: this.providerID,
+ workspaceID: parentCollHandle.value.data.workspaceID,
+ collectionID: parentCollHandle.value.data.workspaceID,
+ name: "",
+ },
+ }
+ })
+ )
+ )
+ }
+
+ public duplicateRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ request: HoppRESTRequest
+ ): Promise>> {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
+ }
+
+ return Promise.resolve(
+ E.right(
+ computed(() => {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return {
+ type: "invalid" as const,
+ reason: "WORKSPACE_INVALIDATED" as const,
+ }
+ }
+
+ saveRESTRequestAs(collPath, request)
+
+ return {
+ type: "ok",
+ data: {
+ providerID: this.providerID,
+ workspaceID: parentCollHandle.value.data.workspaceID,
+ collectionID: parentCollHandle.value.data.workspaceID,
+ name: "",
+ },
+ }
+ })
+ )
+ )
+ }
+
+ public editRESTRequest(
+ parentCollHandle: HandleRef,
+ collPath: string,
+ requestIndex: number,
+ request: HoppRESTRequest
+ ): Promise>> {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
+ }
+
+ return Promise.resolve(
+ E.right(
+ computed(() => {
+ if (
+ parentCollHandle.value.type !== "ok" ||
+ parentCollHandle.value.data.providerID !== this.providerID ||
+ parentCollHandle.value.data.workspaceID !== "personal"
+ ) {
+ return {
+ type: "invalid" as const,
+ reason: "WORKSPACE_INVALIDATED" as const,
+ }
+ }
+
+ const possibleActiveTab = this.tabs.getTabRefWithSaveContext({
+ originLocation: "user-collection",
+ requestIndex,
+ collPath,
+ })
+
+ editRESTRequest(collPath, requestIndex, request)
+
+ if (possibleActiveTab) {
+ possibleActiveTab.value.document.request.name = request.name
+ nextTick(() => {
+ possibleActiveTab.value.document.isDirty = false
+ })
+ }
+
+ return {
+ type: "ok",
+ data: {
+ providerID: this.providerID,
+ workspaceID: parentCollHandle.value.data.workspaceID,
+ collectionID: parentCollHandle.value.data.workspaceID,
+ name: "",
+ },
+ }
+ })
+ )
+ )
+ }
+
public getCollectionHandle(
workspaceHandle: HandleRef,
collectionID: string
@@ -224,24 +549,13 @@ export class PersonalWorkspaceProviderService
}
}
- // TODO: The way the IDs are issued, this will make it so we need a view
- // before the ID is issued correctly
- const coll = this.resolveCollectionFromCollectionID(collectionID)
-
- if (coll === undefined) {
- return {
- type: "invalid",
- reason: "INVALID_COLL_ID" as const,
- }
- }
-
return {
type: "ok",
data: {
providerID: this.providerID,
workspaceID: workspaceHandle.value.data.workspaceID,
collectionID,
- name: coll.name,
+ name: "" as const,
},
}
})
@@ -279,45 +593,41 @@ export class PersonalWorkspaceProviderService
mayHaveMoreContent: ref(false),
content: computed(() => {
- const path = this.resolvePathFromCollectionID(collectionID)
- const coll =
- this.resolveCollectionFromCollectionID(collectionID)
+ const indexPath = collectionID
+ .split("/")
+ .map((x) => parseInt(x))
- if (coll === undefined || path === undefined) {
- console.warn("Collection against ID was not resolvable")
+ const item = this.navigateToFolderWithIndexPath(
+ this.restCollectionState.value.state,
+ indexPath
+ )
- return []
+ if (item) {
+ const collections = item.folders.map((childColl, id) => {
+ return {
+ type: "collection",
+ value: {
+ collectionID: `${collectionID}/${id}`,
+ name: childColl.name,
+ },
+ }
+ })
+
+ const requests = item.requests.map((req, id) => {
+ return {
+ type: "request",
+ value: {
+ requestID: `${collectionID}/${id}`,
+ name: req.name,
+ method: req.method,
+ request: req,
+ },
+ }
+ })
+
+ return [...collections, ...requests]
}
-
- const collections = coll.folders.map((childColl, i) => {
- const id = this.getIssuedInstanceIDForCollection(childColl, [
- ...path,
- i,
- ])
-
- return {
- type: "collection",
- value: {
- collectionID: id,
- name: coll.name,
- },
- }
- })
-
- const requests = coll.requests.map((req, i) => {
- const id = this.getIssuedInstanceIDForRequest(req)
-
- return {
- type: "request",
- value: {
- requestID: id,
- name: req.name,
- method: req.method,
- },
- }
- })
-
- return [...collections, ...requests]
+ return []
}),
loadMore() {
return Promise.resolve()
@@ -356,11 +666,9 @@ export class PersonalWorkspaceProviderService
mayHaveMoreContent: ref(false),
collections: computed(() => {
- return this.restCollectionState.value.state.map((coll, i) => {
- const id = this.getIssuedInstanceIDForCollection(coll, [i])
-
+ return this.restCollectionState.value.state.map((coll, id) => {
return {
- collectionID: id,
+ collectionID: id.toString(),
name: coll.name,
}
})
diff --git a/packages/hoppscotch-common/src/services/new-workspace/view.ts b/packages/hoppscotch-common/src/services/new-workspace/view.ts
index e735c0532..fc9c27260 100644
--- a/packages/hoppscotch-common/src/services/new-workspace/view.ts
+++ b/packages/hoppscotch-common/src/services/new-workspace/view.ts
@@ -1,3 +1,4 @@
+import { HoppRESTRequest } from "@hoppscotch/data"
import { Ref } from "vue"
export type RESTCollectionViewCollection = {
@@ -10,6 +11,7 @@ export type RESTCollectionViewRequest = {
name: string
method: string
+ request: HoppRESTRequest
}
export type RESTCollectionViewItem =