feat: added reordering and moving for collection (#2916)

This commit is contained in:
Nivedin
2023-02-24 19:09:07 +05:30
committed by GitHub
parent dcd441f15e
commit 4ca6e9ec3a
24 changed files with 1721 additions and 359 deletions

View File

@@ -0,0 +1,8 @@
mutation MoveRESTTeamCollection($collectionID: ID!, $parentCollectionID: ID) {
moveCollection(
collectionID: $collectionID
parentCollectionID: $parentCollectionID
) {
id
}
}

View File

@@ -0,0 +1,5 @@
mutation MoveRESTTeamRequest($collectionID: ID!, $requestID: ID!) {
moveRequest(destCollID: $collectionID, requestID: $requestID) {
id
}
}

View File

@@ -1,5 +0,0 @@
mutation MoveRESTTeamRequest($requestID: ID!, $collectionID: ID!) {
moveRequest(requestID: $requestID, destCollID: $collectionID) {
id
}
}

View File

@@ -0,0 +1,3 @@
mutation UpdateCollectionOrder($collectionID: ID!, $destCollID: ID!) {
updateCollectionOrder(collectionID: $collectionID, destCollID: $destCollID)
}

View File

@@ -0,0 +1,11 @@
mutation UpdateLookUpRequestOrder(
$requestID: ID!
$nextRequestID: ID
$collectionID: ID!
) {
updateLookUpRequestOrder(
requestID: $requestID
nextRequestID: $nextRequestID
collectionID: $collectionID
)
}

View File

@@ -0,0 +1,9 @@
query GetSingleCollection($collectionID: ID!) {
collection(collectionID: $collectionID) {
id
title
parent {
id
}
}
}

View File

@@ -0,0 +1,8 @@
query GetSingleRequest($requestID: ID!) {
request(requestID: $requestID) {
id
collectionID
title
request
}
}

View File

@@ -0,0 +1,9 @@
subscription TeamCollectionMoved($teamID: ID!) {
teamCollectionMoved(teamID: $teamID) {
id
title
parent {
id
}
}
}

View File

@@ -0,0 +1,18 @@
subscription TeamCollectionOrderUpdated($teamID: ID!) {
collectionOrderUpdated(teamID: $teamID) {
collection {
id
title
parent {
id
}
}
nextCollection {
id
title
parent {
id
}
}
}
}

View File

@@ -0,0 +1,8 @@
subscription TeamRequestMoved($teamID: ID!) {
requestMoved(teamID: $teamID) {
id
collectionID
request
title
}
}

View File

@@ -0,0 +1,16 @@
subscription TeamRequestOrderUpdated($teamID: ID!) {
requestOrderUpdated(teamID: $teamID) {
request {
id
collectionID
request
title
}
nextRequest {
id
collectionID
request
title
}
}
}

View File

@@ -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<ImportFromJsonMutation, ImportFromJsonMutationVariables, "">(
ImportFromJsonDocument,

View File

@@ -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,
})

View File

@@ -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<TeamCollection[]>([])
@@ -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)
}
)
}
/**