diff --git a/packages/hoppscotch-common/src/components/smart/TreeBranch.vue b/packages/hoppscotch-common/src/components/smart/TreeBranch.vue
index 32bdbe2dc..45366755a 100644
--- a/packages/hoppscotch-common/src/components/smart/TreeBranch.vue
+++ b/packages/hoppscotch-common/src/components/smart/TreeBranch.vue
@@ -3,6 +3,7 @@
:node="nodeItem"
:toggle-children="toggleNodeChildren"
:is-open="isNodeOpen"
+ :highlight-children="(id:string|null) => highlightNodeChildren(id)"
>
@@ -20,6 +21,9 @@
-
+
@@ -87,6 +99,8 @@ const childrenRendered = ref(false)
const showChildren = ref(false)
const isNodeOpen = ref(false)
+const highlightNode = ref(false)
+
/**
* Fetch the child nodes from the adapter by passing the node id of the current node
*/
@@ -100,4 +114,12 @@ const toggleNodeChildren = () => {
showChildren.value = !showChildren.value
isNodeOpen.value = !isNodeOpen.value
}
+
+const highlightNodeChildren = (id: string | null) => {
+ if (id) {
+ highlightNode.value = true
+ } else {
+ highlightNode.value = false
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamCollection.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamCollection.graphql
new file mode 100644
index 000000000..88794ca7a
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamCollection.graphql
@@ -0,0 +1,8 @@
+mutation MoveRESTTeamCollection($collectionID: ID!, $parentCollectionID: ID) {
+ moveCollection(
+ collectionID: $collectionID
+ parentCollectionID: $parentCollectionID
+ ) {
+ id
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamRequest.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamRequest.graphql
new file mode 100644
index 000000000..c1538d31e
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamRequest.graphql
@@ -0,0 +1,5 @@
+mutation MoveRESTTeamRequest($collectionID: ID!, $requestID: ID!) {
+ moveRequest(destCollID: $collectionID, requestID: $requestID) {
+ id
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamRquest.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamRquest.graphql
deleted file mode 100644
index 3c0bc3b46..000000000
--- a/packages/hoppscotch-common/src/helpers/backend/gql/mutations/MoveRESTTeamRquest.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-mutation MoveRESTTeamRequest($requestID: ID!, $collectionID: ID!) {
- moveRequest(requestID: $requestID, destCollID: $collectionID) {
- id
- }
-}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/mutations/UpdateCollectionOrder.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/UpdateCollectionOrder.graphql
new file mode 100644
index 000000000..fdc422fa2
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/UpdateCollectionOrder.graphql
@@ -0,0 +1,3 @@
+mutation UpdateCollectionOrder($collectionID: ID!, $destCollID: ID!) {
+ updateCollectionOrder(collectionID: $collectionID, destCollID: $destCollID)
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/mutations/UpdateLookUpRequestOrder.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/UpdateLookUpRequestOrder.graphql
new file mode 100644
index 000000000..972f7a619
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/mutations/UpdateLookUpRequestOrder.graphql
@@ -0,0 +1,11 @@
+mutation UpdateLookUpRequestOrder(
+ $requestID: ID!
+ $nextRequestID: ID
+ $collectionID: ID!
+) {
+ updateLookUpRequestOrder(
+ requestID: $requestID
+ nextRequestID: $nextRequestID
+ collectionID: $collectionID
+ )
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/queries/GetSingleCollection.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/queries/GetSingleCollection.graphql
new file mode 100644
index 000000000..50505d6f5
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/queries/GetSingleCollection.graphql
@@ -0,0 +1,9 @@
+query GetSingleCollection($collectionID: ID!) {
+ collection(collectionID: $collectionID) {
+ id
+ title
+ parent {
+ id
+ }
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/queries/GetSingleRequest.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/queries/GetSingleRequest.graphql
new file mode 100644
index 000000000..ba7cb4c11
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/queries/GetSingleRequest.graphql
@@ -0,0 +1,8 @@
+query GetSingleRequest($requestID: ID!) {
+ request(requestID: $requestID) {
+ id
+ collectionID
+ title
+ request
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamCollectionMoved.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamCollectionMoved.graphql
new file mode 100644
index 000000000..6fff331af
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamCollectionMoved.graphql
@@ -0,0 +1,9 @@
+subscription TeamCollectionMoved($teamID: ID!) {
+ teamCollectionMoved(teamID: $teamID) {
+ id
+ title
+ parent {
+ id
+ }
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamCollectionOrderUpdated.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamCollectionOrderUpdated.graphql
new file mode 100644
index 000000000..0509082ab
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamCollectionOrderUpdated.graphql
@@ -0,0 +1,18 @@
+subscription TeamCollectionOrderUpdated($teamID: ID!) {
+ collectionOrderUpdated(teamID: $teamID) {
+ collection {
+ id
+ title
+ parent {
+ id
+ }
+ }
+ nextCollection {
+ id
+ title
+ parent {
+ id
+ }
+ }
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamRequestMoved.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamRequestMoved.graphql
new file mode 100644
index 000000000..bda0cb05f
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamRequestMoved.graphql
@@ -0,0 +1,8 @@
+subscription TeamRequestMoved($teamID: ID!) {
+ requestMoved(teamID: $teamID) {
+ id
+ collectionID
+ request
+ title
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamRequestOrderUpdated.graphql b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamRequestOrderUpdated.graphql
new file mode 100644
index 000000000..1b09ce52e
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/backend/gql/subscriptions/TeamRequestOrderUpdated.graphql
@@ -0,0 +1,16 @@
+subscription TeamRequestOrderUpdated($teamID: ID!) {
+ requestOrderUpdated(teamID: $teamID) {
+ request {
+ id
+ collectionID
+ request
+ title
+ }
+ nextRequest {
+ id
+ collectionID
+ request
+ title
+ }
+ }
+}
diff --git a/packages/hoppscotch-common/src/helpers/backend/mutations/TeamCollection.ts b/packages/hoppscotch-common/src/helpers/backend/mutations/TeamCollection.ts
index 87b818236..23a450897 100644
--- a/packages/hoppscotch-common/src/helpers/backend/mutations/TeamCollection.ts
+++ b/packages/hoppscotch-common/src/helpers/backend/mutations/TeamCollection.ts
@@ -12,16 +12,37 @@ import {
ImportFromJsonDocument,
ImportFromJsonMutation,
ImportFromJsonMutationVariables,
+ MoveRestTeamCollectionDocument,
+ MoveRestTeamCollectionMutation,
+ MoveRestTeamCollectionMutationVariables,
RenameCollectionDocument,
RenameCollectionMutation,
RenameCollectionMutationVariables,
+ UpdateCollectionOrderDocument,
+ UpdateCollectionOrderMutation,
+ UpdateCollectionOrderMutationVariables,
} from "../graphql"
type CreateNewRootCollectionError = "team_coll/short_title"
+
type CreateChildCollectionError = "team_coll/short_title"
+
type RenameCollectionError = "team_coll/short_title"
+
type DeleteCollectionError = "team/invalid_coll_id"
+type MoveRestTeamCollectionError =
+ | "team/invalid_coll_id"
+ | "team_coll/invalid_target_id"
+ | "team/collection_is_parent_coll"
+ | "team/target_and_destination_collection_are_same"
+ | "team/target_collection_is_already_root_collection"
+
+type UpdateCollectionOrderError =
+ | "team/invalid_coll_id"
+ | "team/collection_and_next_collection_are_same"
+ | "team/team_collections_have_different_parents"
+
export const createNewRootCollection = (title: string, teamID: string) =>
runMutation<
CreateNewRootCollectionMutation,
@@ -66,6 +87,33 @@ export const deleteCollection = (collectionID: string) =>
collectionID,
})
+/** Can be used to move both collection and folder (considered same in BE) */
+export const moveRESTTeamCollection = (
+ collectionID: string,
+ destinationCollectionID: string | null
+) =>
+ runMutation<
+ MoveRestTeamCollectionMutation,
+ MoveRestTeamCollectionMutationVariables,
+ MoveRestTeamCollectionError
+ >(MoveRestTeamCollectionDocument, {
+ collectionID,
+ parentCollectionID: destinationCollectionID,
+ })
+
+export const updateOrderRESTTeamCollection = (
+ collectionID: string,
+ destCollID: string
+) =>
+ runMutation<
+ UpdateCollectionOrderMutation,
+ UpdateCollectionOrderMutationVariables,
+ UpdateCollectionOrderError
+ >(UpdateCollectionOrderDocument, {
+ collectionID,
+ destCollID,
+ })
+
export const importJSONToTeam = (collectionJSON: string, teamID: string) =>
runMutation(
ImportFromJsonDocument,
diff --git a/packages/hoppscotch-common/src/helpers/backend/mutations/TeamRequest.ts b/packages/hoppscotch-common/src/helpers/backend/mutations/TeamRequest.ts
index 7346a66c5..daff454a5 100644
--- a/packages/hoppscotch-common/src/helpers/backend/mutations/TeamRequest.ts
+++ b/packages/hoppscotch-common/src/helpers/backend/mutations/TeamRequest.ts
@@ -9,16 +9,27 @@ import {
MoveRestTeamRequestDocument,
MoveRestTeamRequestMutation,
MoveRestTeamRequestMutationVariables,
+ UpdateLookUpRequestOrderDocument,
+ UpdateLookUpRequestOrderMutation,
+ UpdateLookUpRequestOrderMutationVariables,
UpdateRequestDocument,
UpdateRequestMutation,
UpdateRequestMutationVariables,
} from "../graphql"
+type DeleteRequestErrors = "team_req/not_found"
+
type MoveRestTeamRequestErrors =
| "team_req/not_found"
| "team_req/invalid_target_id"
+ | "team/invalid_coll_id"
+ | "team_req/not_required_role"
+ | "bug/team_req/no_req_id"
-type DeleteRequestErrors = "team_req/not_found"
+type UpdateLookUpRequestOrderErrors =
+ | "team_req/not_found"
+ | "team/request_and_next_request_are_same"
+ | "team_req/requests_not_from_same_collection"
export const createRequestInCollection = (
collectionID: string,
@@ -61,12 +72,27 @@ export const deleteTeamRequest = (requestID: string) =>
requestID,
})
-export const moveRESTTeamRequest = (requestID: string, collectionID: string) =>
+export const moveRESTTeamRequest = (collectionID: string, requestID: string) =>
runMutation<
MoveRestTeamRequestMutation,
MoveRestTeamRequestMutationVariables,
MoveRestTeamRequestErrors
>(MoveRestTeamRequestDocument, {
+ collectionID,
requestID,
+ })
+
+export const updateOrderRESTTeamRequest = (
+ requestID: string,
+ nextRequestID: string,
+ collectionID: string
+) =>
+ runMutation<
+ UpdateLookUpRequestOrderMutation,
+ UpdateLookUpRequestOrderMutationVariables,
+ UpdateLookUpRequestOrderErrors
+ >(UpdateLookUpRequestOrderDocument, {
+ requestID,
+ nextRequestID,
collectionID,
})
diff --git a/packages/hoppscotch-common/src/helpers/teams/TeamCollectionAdapter.ts b/packages/hoppscotch-common/src/helpers/teams/TeamCollectionAdapter.ts
index 49a891bde..8fa716f4b 100644
--- a/packages/hoppscotch-common/src/helpers/teams/TeamCollectionAdapter.ts
+++ b/packages/hoppscotch-common/src/helpers/teams/TeamCollectionAdapter.ts
@@ -16,6 +16,10 @@ import {
TeamRequestDeletedDocument,
GetCollectionChildrenDocument,
GetCollectionRequestsDocument,
+ TeamRequestMovedDocument,
+ TeamCollectionMovedDocument,
+ TeamRequestOrderUpdatedDocument,
+ TeamCollectionOrderUpdatedDocument,
} from "~/helpers/backend/graphql"
const TEAMS_BACKEND_PAGE_SIZE = 10
@@ -201,6 +205,10 @@ export default class NewTeamCollectionAdapter {
private teamRequestAdded$: Subscription | null
private teamRequestUpdated$: Subscription | null
private teamRequestDeleted$: Subscription | null
+ private teamRequestMoved$: Subscription | null
+ private teamCollectionMoved$: Subscription | null
+ private teamRequestOrderUpdated$: Subscription | null
+ private teamCollectionOrderUpdated$: Subscription | null
private teamCollectionAddedSub: WSubscription | null
private teamCollectionUpdatedSub: WSubscription | null
@@ -208,6 +216,10 @@ export default class NewTeamCollectionAdapter {
private teamRequestAddedSub: WSubscription | null
private teamRequestUpdatedSub: WSubscription | null
private teamRequestDeletedSub: WSubscription | null
+ private teamRequestMovedSub: WSubscription | null
+ private teamCollectionMovedSub: WSubscription | null
+ private teamRequestOrderUpdatedSub: WSubscription | null
+ private teamCollectionOrderUpdatedSub: WSubscription | null
constructor(private teamID: string | null) {
this.collections$ = new BehaviorSubject([])
@@ -221,6 +233,10 @@ export default class NewTeamCollectionAdapter {
this.teamRequestAdded$ = null
this.teamRequestDeleted$ = null
this.teamRequestUpdated$ = null
+ this.teamRequestMoved$ = null
+ this.teamCollectionMoved$ = null
+ this.teamRequestOrderUpdated$ = null
+ this.teamCollectionOrderUpdated$ = null
this.teamCollectionAddedSub = null
this.teamCollectionUpdatedSub = null
@@ -228,6 +244,10 @@ export default class NewTeamCollectionAdapter {
this.teamRequestAddedSub = null
this.teamRequestDeletedSub = null
this.teamRequestUpdatedSub = null
+ this.teamRequestMovedSub = null
+ this.teamCollectionMovedSub = null
+ this.teamRequestOrderUpdatedSub = null
+ this.teamCollectionOrderUpdatedSub = null
if (this.teamID) this.initialize()
}
@@ -255,6 +275,10 @@ export default class NewTeamCollectionAdapter {
this.teamRequestAdded$?.unsubscribe()
this.teamRequestDeleted$?.unsubscribe()
this.teamRequestUpdated$?.unsubscribe()
+ this.teamRequestMoved$?.unsubscribe()
+ this.teamCollectionMoved$?.unsubscribe()
+ this.teamRequestOrderUpdated$?.unsubscribe()
+ this.teamCollectionOrderUpdated$?.unsubscribe()
this.teamCollectionAddedSub?.unsubscribe()
this.teamCollectionUpdatedSub?.unsubscribe()
@@ -262,6 +286,10 @@ export default class NewTeamCollectionAdapter {
this.teamRequestAddedSub?.unsubscribe()
this.teamRequestDeletedSub?.unsubscribe()
this.teamRequestUpdatedSub?.unsubscribe()
+ this.teamRequestMovedSub?.unsubscribe()
+ this.teamCollectionMovedSub?.unsubscribe()
+ this.teamRequestOrderUpdatedSub?.unsubscribe()
+ this.teamCollectionOrderUpdatedSub?.unsubscribe()
}
private async initialize() {
@@ -328,7 +356,7 @@ export default class NewTeamCollectionAdapter {
this.loadingCollections$.getValue().filter((x) => x !== "root")
)
- throw new Error(`Error fetching root collections: ${result}`)
+ throw new Error(`Error fetching root collections: ${result.left.error}`)
}
totalCollections.push(
@@ -456,6 +484,143 @@ export default class NewTeamCollectionAdapter {
this.collections$.next(tree)
}
+ /**
+ * Moves a request from one collection to another
+ *
+ * @param {string} request - The request to move
+ */
+ private async moveRequest(request: TeamRequest) {
+ const tree = this.collections$.value
+
+ // Remove the request from the current collection
+ this.removeRequest(request.id)
+
+ const currentRequest = request.request
+
+ if (currentRequest === null || currentRequest === undefined) return
+
+ // Find request in tree, don't attempt if no collection or no requests is found
+ const collection = findCollInTree(tree, request.collectionID)
+ if (!collection) return // Ignore add request
+
+ // Collection is not expanded
+ if (!collection.requests) return
+
+ this.addRequest({
+ id: request.id,
+ collectionID: request.collectionID,
+ request: translateToNewRequest(request.request),
+ title: request.title,
+ })
+ }
+
+ /**
+ * Moves a collection from one collection to another or to root
+ *
+ * @param {string} collectionID - The ID of the collection to move
+ */
+ private async moveCollection(
+ collectionID: string,
+ parentID: string | null,
+ title: string
+ ) {
+ // Remove the collection from the current position
+ this.removeCollection(collectionID)
+
+ if (collectionID === null || parentID === undefined) return
+
+ // Expand the parent collection if it is not expanded
+ // so that the old children is also visible when expanding
+ if (parentID) this.expandCollection(parentID)
+
+ this.addCollection(
+ {
+ id: collectionID,
+ children: null,
+ requests: null,
+ title: title,
+ },
+ parentID ?? null
+ )
+ }
+
+ public updateRequestOrder(
+ dragedRequestID: string,
+ destinationRequestID: string,
+ destinationCollectionID: string
+ ) {
+ const tree = this.collections$.value
+
+ // Find collection in tree, don't attempt if no collection is found
+ const collection = findCollInTree(tree, destinationCollectionID)
+ if (!collection) return // Ignore order update
+
+ // Collection is not expanded
+ if (!collection.requests) return
+
+ const requestIndex = collection.requests.findIndex(
+ (req) => req.id === dragedRequestID
+ )
+ const destinationIndex = collection.requests.findIndex(
+ (req) => req.id === destinationRequestID
+ )
+
+ if (requestIndex === -1) return
+
+ const request = collection.requests[requestIndex]
+
+ collection.requests.splice(requestIndex, 1)
+ collection.requests.splice(destinationIndex, 0, request)
+
+ this.collections$.next(tree)
+ }
+
+ public updateCollectionOrder = (
+ collectionID: string,
+ destinationCollectionID: string
+ ) => {
+ const tree = this.collections$.value
+
+ // Find collection in tree
+ const coll = findParentOfColl(tree, destinationCollectionID)
+
+ // If the collection has a parent collection and check if it has children
+ if (coll && coll.children) {
+ const collectionIndex = coll.children.findIndex(
+ (coll) => coll.id === collectionID
+ )
+
+ const destinationIndex = coll.children.findIndex(
+ (coll) => coll.id === destinationCollectionID
+ )
+
+ // If the collection index is not found, don't update
+ if (collectionIndex === -1) return
+
+ const collection = coll.children[collectionIndex]
+
+ coll.children.splice(collectionIndex, 1)
+ coll.children.splice(destinationIndex, 0, collection)
+ } else {
+ // If the collection has no parent collection, it is a root collection
+ const collectionIndex = tree.findIndex((coll) => coll.id === collectionID)
+
+ const destinationIndex = tree.findIndex(
+ (coll) => coll.id === destinationCollectionID
+ )
+
+ // If the collection index is not found, don't update
+ if (collectionIndex === -1) return
+
+ const collection = tree[collectionIndex]
+
+ tree.splice(collectionIndex, 1)
+ tree.splice(destinationIndex, 0, collection)
+ }
+
+ this.collections$.next(tree)
+ }
+
private registerSubscriptions() {
if (!this.teamID) return
@@ -575,7 +740,7 @@ export default class NewTeamCollectionAdapter {
},
})
- this.teamRequestUpdatedSub = teamReqDeleted
+ this.teamRequestDeletedSub = teamReqDeleted
this.teamRequestDeleted$ = teamReqDeleted$.subscribe((result) => {
if (E.isLeft(result))
throw new Error(
@@ -584,6 +749,110 @@ export default class NewTeamCollectionAdapter {
this.removeRequest(result.right.teamRequestDeleted)
})
+
+ const [teamRequestMoved$, teamRequestMoved] = runGQLSubscription({
+ query: TeamRequestMovedDocument,
+ variables: {
+ teamID: this.teamID,
+ },
+ })
+
+ this.teamRequestMovedSub = teamRequestMoved
+ this.teamRequestMoved$ = teamRequestMoved$.subscribe((result) => {
+ if (E.isLeft(result))
+ throw new Error(
+ `Team Request Move Error ${JSON.stringify(result.left)}`
+ )
+
+ const { requestMoved } = result.right
+
+ const request = {
+ id: requestMoved.id,
+ collectionID: requestMoved.collectionID,
+ title: requestMoved.title,
+ request: JSON.parse(requestMoved.request),
+ }
+
+ this.moveRequest(request)
+ })
+
+ const [teamCollectionMoved$, teamCollectionMoved] = runGQLSubscription({
+ query: TeamCollectionMovedDocument,
+ variables: {
+ teamID: this.teamID,
+ },
+ })
+
+ this.teamCollectionMovedSub = teamCollectionMoved
+ this.teamCollectionMoved$ = teamCollectionMoved$.subscribe((result) => {
+ if (E.isLeft(result))
+ throw new Error(
+ `Team Collection Move Error ${JSON.stringify(result.left)}`
+ )
+
+ const { teamCollectionMoved } = result.right
+ const { id, parent, title } = teamCollectionMoved
+
+ const parentID = parent?.id ?? null
+
+ this.moveCollection(id, parentID, title)
+ })
+
+ const [teamRequestOrderUpdated$, teamRequestOrderUpdated] =
+ runGQLSubscription({
+ query: TeamRequestOrderUpdatedDocument,
+ variables: {
+ teamID: this.teamID,
+ },
+ })
+
+ this.teamRequestOrderUpdatedSub = teamRequestOrderUpdated
+ this.teamRequestOrderUpdated$ = teamRequestOrderUpdated$.subscribe(
+ (result) => {
+ if (E.isLeft(result))
+ throw new Error(
+ `Team Request Order Update Error ${JSON.stringify(result.left)}`
+ )
+
+ const { requestOrderUpdated } = result.right
+ const { request } = requestOrderUpdated
+ const { nextRequest } = requestOrderUpdated
+
+ if (!nextRequest) return
+
+ this.updateRequestOrder(
+ request.id,
+ nextRequest.id,
+ nextRequest.collectionID
+ )
+ }
+ )
+
+ const [teamCollectionOrderUpdated$, teamCollectionOrderUpdated] =
+ runGQLSubscription({
+ query: TeamCollectionOrderUpdatedDocument,
+ variables: {
+ teamID: this.teamID,
+ },
+ })
+
+ this.teamCollectionOrderUpdatedSub = teamCollectionOrderUpdated
+ this.teamCollectionOrderUpdated$ = teamCollectionOrderUpdated$.subscribe(
+ (result) => {
+ if (E.isLeft(result))
+ throw new Error(
+ `Team Collection Order Update Error ${JSON.stringify(result.left)}`
+ )
+
+ const { collectionOrderUpdated } = result.right
+ const { collection } = collectionOrderUpdated
+ const { nextCollection } = collectionOrderUpdated
+
+ if (!nextCollection) return
+
+ this.updateCollectionOrder(collection.id, nextCollection.id)
+ }
+ )
}
/**
diff --git a/packages/hoppscotch-common/src/newstore/collections.ts b/packages/hoppscotch-common/src/newstore/collections.ts
index 6ccec0e66..bcfe05571 100644
--- a/packages/hoppscotch-common/src/newstore/collections.ts
+++ b/packages/hoppscotch-common/src/newstore/collections.ts
@@ -186,6 +186,133 @@ const restCollectionDispatchers = defineDispatchers({
}
},
+ moveFolder(
+ { state }: RESTCollectionStoreType,
+ { path, destinationPath }: { path: string; destinationPath: string | null }
+ ) {
+ const newState = state
+
+ // Move the folder to the root
+ if (destinationPath === null) {
+ const indexPaths = path.split("/").map((x) => parseInt(x))
+
+ if (indexPaths.length === 0) {
+ console.log("Given path too short. Skipping request.")
+ return {}
+ }
+
+ const folderIndex = indexPaths.pop() as number
+
+ const containingFolder = navigateToFolderWithIndexPath(
+ newState,
+ indexPaths
+ )
+ if (containingFolder === null) {
+ console.error(
+ `The folder to move is already in the root. Skipping request to move folder.`
+ )
+ return {}
+ }
+
+ const theFolder = containingFolder.folders.splice(folderIndex, 1)
+ newState.push(theFolder[0] as HoppCollection)
+
+ return {
+ state: newState,
+ }
+ }
+
+ const indexPaths = path.split("/").map((x) => parseInt(x))
+
+ const destinationIndexPaths = destinationPath
+ .split("/")
+ .map((x) => parseInt(x))
+
+ if (indexPaths.length === 0 || destinationIndexPaths.length === 0) {
+ console.error(
+ `Given path is too short. Skipping request to move folder '${path}' to destination '${destinationPath}'.`
+ )
+ return {}
+ }
+
+ const target = navigateToFolderWithIndexPath(
+ newState,
+ destinationIndexPaths
+ )
+ if (target === null) {
+ console.error(
+ `Could not resolve destination path '${destinationPath}'. Skipping moveFolder dispatch.`
+ )
+ return {}
+ }
+
+ const folderIndex = indexPaths.pop() as number
+
+ const containingFolder = navigateToFolderWithIndexPath(newState, indexPaths)
+ // We are moving a folder from the root
+ if (containingFolder === null) {
+ const theFolder = newState.splice(folderIndex, 1)
+
+ target.folders.push(theFolder[0])
+ } else {
+ const theFolder = containingFolder.folders.splice(folderIndex, 1)
+
+ target.folders.push(theFolder[0])
+ }
+
+ return { state: newState }
+ },
+
+ updateCollectionOrder(
+ { state }: RESTCollectionStoreType,
+ {
+ collectionIndex,
+ destinationCollectionIndex,
+ }: {
+ collectionIndex: string
+ destinationCollectionIndex: string
+ }
+ ) {
+ const newState = state
+
+ const indexPaths = collectionIndex.split("/").map((x) => parseInt(x))
+
+ const destinationIndexPaths = destinationCollectionIndex
+ .split("/")
+ .map((x) => parseInt(x))
+
+ if (indexPaths.length === 0 || destinationIndexPaths.length === 0) {
+ console.log("Given path too short. Skipping request.")
+ return {}
+ }
+
+ const folderIndex = indexPaths.pop() as number
+ const destinationFolderIndex = destinationIndexPaths.pop() as number
+
+ const containingFolder = navigateToFolderWithIndexPath(
+ newState,
+ destinationIndexPaths
+ )
+
+ if (containingFolder === null) {
+ const [removed] = newState.splice(folderIndex, 1)
+
+ newState.splice(destinationFolderIndex, 0, removed)
+
+ return {
+ state: newState,
+ }
+ }
+
+ const [removed] = containingFolder.folders.splice(folderIndex, 1)
+
+ containingFolder.folders.splice(destinationFolderIndex, 0, removed)
+
+ return {
+ state: newState,
+ }
+ },
+
editRequest(
{ state }: RESTCollectionStoreType,
{
@@ -286,6 +413,11 @@ const restCollectionDispatchers = defineDispatchers({
const indexPaths = path.split("/").map((x) => parseInt(x))
+ if (indexPaths.length === 0) {
+ console.log("Given path too short. Skipping request.")
+ return {}
+ }
+
const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
if (targetLocation === null) {
@@ -315,6 +447,47 @@ const restCollectionDispatchers = defineDispatchers({
state: newState,
}
},
+
+ updateRequestOrder(
+ { state }: RESTCollectionStoreType,
+ {
+ requestIndex,
+ destinationRequestIndex,
+ destinationCollectionPath,
+ }: {
+ requestIndex: number
+ destinationRequestIndex: number
+ destinationCollectionPath: string
+ }
+ ) {
+ const newState = state
+
+ const indexPaths = destinationCollectionPath
+ .split("/")
+ .map((x) => parseInt(x))
+
+ if (indexPaths.length === 0) {
+ console.log("Given path too short. Skipping request.")
+ return {}
+ }
+
+ const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
+
+ if (targetLocation === null) {
+ console.log(
+ `Could not resolve path '${destinationCollectionPath}'. Ignoring reorderRequest dispatch.`
+ )
+ return {}
+ }
+
+ const [removed] = targetLocation.requests.splice(requestIndex, 1)
+
+ targetLocation.requests.splice(destinationRequestIndex, 0, removed)
+
+ return {
+ state: newState,
+ }
+ },
})
const gqlCollectionDispatchers = defineDispatchers({
@@ -691,6 +864,16 @@ export function removeRESTFolder(path: string) {
})
}
+export function moveRESTFolder(path: string, destinationPath: string | null) {
+ restCollectionStore.dispatch({
+ dispatcher: "moveFolder",
+ payload: {
+ path,
+ destinationPath,
+ },
+ })
+}
+
export function editRESTRequest(
path: string,
requestIndex: number,
@@ -757,6 +940,34 @@ export function moveRESTRequest(
})
}
+export function updateRESTRequestOrder(
+ requestIndex: number,
+ destinationRequestIndex: number,
+ destinationCollectionPath: string
+) {
+ restCollectionStore.dispatch({
+ dispatcher: "updateRequestOrder",
+ payload: {
+ requestIndex,
+ destinationRequestIndex,
+ destinationCollectionPath,
+ },
+ })
+}
+
+export function updateRESTCollectionOrder(
+ collectionIndex: string,
+ destinationCollectionIndex: string
+) {
+ restCollectionStore.dispatch({
+ dispatcher: "updateCollectionOrder",
+ payload: {
+ collectionIndex,
+ destinationCollectionIndex,
+ },
+ })
+}
+
export function setGraphqlCollections(
entries: HoppCollection[]
) {