refactor: handle based updates post collection move
This commit is contained in:
@@ -1569,10 +1569,10 @@ const dropToRoot = async ({ dataTransfer }: DragEvent) => {
|
|||||||
restCollectionState.value.length - 1
|
restCollectionState.value.length - 1
|
||||||
).toString()
|
).toString()
|
||||||
|
|
||||||
updateSaveContextForAffectedRequests(
|
// updateSaveContextForAffectedRequests(
|
||||||
draggedCollectionIndex,
|
// draggedCollectionIndex,
|
||||||
destinationRootCollectionIndex
|
// destinationRootCollectionIndex
|
||||||
)
|
// )
|
||||||
|
|
||||||
const destinationRootCollectionHandleResult =
|
const destinationRootCollectionHandleResult =
|
||||||
await workspaceService.getCollectionHandle(
|
await workspaceService.getCollectionHandle(
|
||||||
@@ -1808,43 +1808,43 @@ const dropCollection = async (payload: {
|
|||||||
// Hence, we need to reduce the destination root collection index by 1
|
// Hence, we need to reduce the destination root collection index by 1
|
||||||
// This only applies to the case when the destination collection lies below the dragged collection
|
// This only applies to the case when the destination collection lies below the dragged collection
|
||||||
|
|
||||||
let resolvedDestinationCollectionIndex = destinationCollectionIndex
|
// let resolvedDestinationCollectionIndex = destinationCollectionIndex
|
||||||
|
|
||||||
const draggedRootCollectionIndex = parseInt(
|
// const draggedRootCollectionIndex = parseInt(
|
||||||
pathToIndex(draggedCollectionIndex)[0]
|
// pathToIndex(draggedCollectionIndex)[0]
|
||||||
)
|
// )
|
||||||
const destinationRootCollectionIndex = parseInt(
|
// const destinationRootCollectionIndex = parseInt(
|
||||||
pathToIndex(destinationCollectionIndex)[0]
|
// pathToIndex(destinationCollectionIndex)[0]
|
||||||
)
|
// )
|
||||||
|
|
||||||
if (
|
// if (
|
||||||
isAlreadyInRoot(draggedCollectionIndex) &&
|
// isAlreadyInRoot(draggedCollectionIndex) &&
|
||||||
destinationRootCollectionIndex > draggedRootCollectionIndex
|
// destinationRootCollectionIndex > draggedRootCollectionIndex
|
||||||
) {
|
// ) {
|
||||||
resolvedDestinationCollectionIndex = `${
|
// resolvedDestinationCollectionIndex = `${
|
||||||
destinationRootCollectionIndex - 1
|
// destinationRootCollectionIndex - 1
|
||||||
}/${pathToIndex(destinationCollectionIndex).slice(1).join("/")}`
|
// }/${pathToIndex(destinationCollectionIndex).slice(1).join("/")}`
|
||||||
|
|
||||||
resolvedDestinationCollectionIndex =
|
// resolvedDestinationCollectionIndex =
|
||||||
resolvedDestinationCollectionIndex.endsWith("/")
|
// resolvedDestinationCollectionIndex.endsWith("/")
|
||||||
? resolvedDestinationCollectionIndex.slice(0, -1)
|
// ? resolvedDestinationCollectionIndex.slice(0, -1)
|
||||||
: resolvedDestinationCollectionIndex
|
// : resolvedDestinationCollectionIndex
|
||||||
}
|
// }
|
||||||
|
|
||||||
resolveSaveContextOnCollectionReorder({
|
// resolveSaveContextOnCollectionReorder({
|
||||||
lastIndex: pathToLastIndex(draggedCollectionIndex),
|
// lastIndex: pathToLastIndex(draggedCollectionIndex),
|
||||||
newIndex: -1,
|
// newIndex: -1,
|
||||||
folderPath: draggedParentCollectionIndex,
|
// folderPath: draggedParentCollectionIndex,
|
||||||
length: getFoldersByPath(
|
// length: getFoldersByPath(
|
||||||
restCollectionState.value,
|
// restCollectionState.value,
|
||||||
draggedParentCollectionIndex
|
// draggedParentCollectionIndex
|
||||||
).length,
|
// ).length,
|
||||||
})
|
// })
|
||||||
|
|
||||||
updateSaveContextForAffectedRequests(
|
// updateSaveContextForAffectedRequests(
|
||||||
draggedCollectionIndex,
|
// draggedCollectionIndex,
|
||||||
`${resolvedDestinationCollectionIndex}/${totalChildCollectionsInDestinationCollection}`
|
// `${resolvedDestinationCollectionIndex}/${totalChildCollectionsInDestinationCollection}`
|
||||||
)
|
// )
|
||||||
|
|
||||||
const destinationCollectionHandleResult =
|
const destinationCollectionHandleResult =
|
||||||
await workspaceService.getCollectionHandle(
|
await workspaceService.getCollectionHandle(
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type HoppRESTSaveContext =
|
|||||||
* The origin source of the request
|
* The origin source of the request
|
||||||
*/
|
*/
|
||||||
// TODO: Make this `user-collection` after porting all usages
|
// TODO: Make this `user-collection` after porting all usages
|
||||||
|
// Future TODO: Keep separate types for the IDs (specific to persistence) & `requestHandle` (only existing at runtime)
|
||||||
originLocation: "workspace-user-collection"
|
originLocation: "workspace-user-collection"
|
||||||
/**
|
/**
|
||||||
* ID of the workspace
|
* ID of the workspace
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ const onResolveConfirmSaveTab = () => {
|
|||||||
if (
|
if (
|
||||||
!saveContext ||
|
!saveContext ||
|
||||||
(saveContext.originLocation === "workspace-user-collection" &&
|
(saveContext.originLocation === "workspace-user-collection" &&
|
||||||
saveContext.requestHandle?.value.type === "invalid")
|
saveContext.requestHandle?.get().value.type === "invalid")
|
||||||
) {
|
) {
|
||||||
return (savingRequest.value = true)
|
return (savingRequest.value = true)
|
||||||
}
|
}
|
||||||
@@ -331,7 +331,7 @@ const getTabDirtyStatus = (tab: HoppTab<HoppRESTDocument>) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
tab.document.saveContext?.originLocation === "workspace-user-collection" &&
|
tab.document.saveContext?.originLocation === "workspace-user-collection" &&
|
||||||
tab.document.saveContext.requestHandle?.value.type === "invalid"
|
tab.document.saveContext.requestHandle?.get().value.type === "invalid"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ export class PersonalWorkspaceProviderService
|
|||||||
this.workspaceService.registerWorkspaceProvider(this)
|
this.workspaceService.registerWorkspaceProvider(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Move the below out of provider definitions as generic helper functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to get the index of the request from the path
|
* Used to get the index of the request from the path
|
||||||
* @param path The path of the request
|
* @param path The path of the request
|
||||||
@@ -130,6 +132,25 @@ export class PersonalWorkspaceProviderService
|
|||||||
return parseInt(pathArr[pathArr.length - 1])
|
return parseInt(pathArr[pathArr.length - 1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path The path of the collection or request
|
||||||
|
* @returns The index of the collection or request
|
||||||
|
*/
|
||||||
|
private pathToIndex(path: string) {
|
||||||
|
const pathArr = path.split("/")
|
||||||
|
return pathArr
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the collection is already in the root
|
||||||
|
* @param id - path of the collection
|
||||||
|
* @returns boolean - true if the collection is already in the root
|
||||||
|
*/
|
||||||
|
private isAlreadyInRoot(id: string) {
|
||||||
|
const indexPath = this.pathToIndex(id)
|
||||||
|
return indexPath.length === 1
|
||||||
|
}
|
||||||
|
|
||||||
public createRESTRootCollection(
|
public createRESTRootCollection(
|
||||||
workspaceHandle: Handle<Workspace>,
|
workspaceHandle: Handle<Workspace>,
|
||||||
newCollection: Partial<Exclude<HoppCollection, "id">> & { name: string }
|
newCollection: Partial<Exclude<HoppCollection, "id">> & { name: string }
|
||||||
@@ -665,12 +686,165 @@ export class PersonalWorkspaceProviderService
|
|||||||
) {
|
) {
|
||||||
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
|
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
|
||||||
}
|
}
|
||||||
|
const { collectionID: draggedCollectionID } = collectionHandleRef.value.data
|
||||||
|
|
||||||
|
const draggedParentCollectionID = this.isAlreadyInRoot(draggedCollectionID)
|
||||||
|
? draggedCollectionID
|
||||||
|
: draggedCollectionID.split("/").slice(0, -1).join("/")
|
||||||
|
|
||||||
|
const isMoveToSiblingCollection = this.isAlreadyInRoot(draggedCollectionID)
|
||||||
|
? this.isAlreadyInRoot(
|
||||||
|
destinationCollectionID === null
|
||||||
|
? // Move to root
|
||||||
|
this.restCollectionState.value.state.length.toString()
|
||||||
|
: destinationCollectionID
|
||||||
|
)
|
||||||
|
: !!destinationCollectionID?.startsWith(draggedParentCollectionID)
|
||||||
|
|
||||||
|
const draggedCollectionIndexPos = this.pathToLastIndex(draggedCollectionID)
|
||||||
|
|
||||||
|
let resolvedDestinationCollectionID = ""
|
||||||
|
|
||||||
|
if (destinationCollectionID === null) {
|
||||||
|
// destinationCollectionID` being `null` indicates moving to root
|
||||||
|
// New ID will be the length of the root nodes at this point (before the store update)
|
||||||
|
resolvedDestinationCollectionID =
|
||||||
|
this.restCollectionState.value.state.length.toString()
|
||||||
|
} else {
|
||||||
|
// Move to an inner-level collection
|
||||||
|
const destinationCollectionIndexPos = this.pathToLastIndex(
|
||||||
|
destinationCollectionID
|
||||||
|
)
|
||||||
|
|
||||||
|
// The count of child collections within the destination collection will be the new index position
|
||||||
|
// Appended to the `resolvedDestinationCollectionID`
|
||||||
|
const resolvedDestinationCollectionIndexPos = getFoldersByPath(
|
||||||
|
this.restCollectionState.value.state,
|
||||||
|
destinationCollectionID
|
||||||
|
).length
|
||||||
|
|
||||||
|
// Indicates a move from a collection at the top to a sibling collection below it
|
||||||
|
if (
|
||||||
|
isMoveToSiblingCollection &&
|
||||||
|
destinationCollectionIndexPos > draggedCollectionIndexPos
|
||||||
|
) {
|
||||||
|
const draggedCollectionIDStrLength =
|
||||||
|
draggedCollectionID.split("/").length
|
||||||
|
|
||||||
|
// Obtain a subset of the destination collection ID till the dragged collection ID string length
|
||||||
|
// Only update the index position at the level of the dragged collection
|
||||||
|
// This ensures moves to deeply any nested collections are accounted
|
||||||
|
const destinationCollectionIDSubset = destinationCollectionID
|
||||||
|
.split("/")
|
||||||
|
.slice(0, draggedCollectionIDStrLength)
|
||||||
|
.join("/")
|
||||||
|
|
||||||
|
// Reduce `1` from the index position to account for the dragged collection
|
||||||
|
// Dragged collection doesn't exist anymore at the previous level
|
||||||
|
const collectionIDSubsetIndexPos = Number(
|
||||||
|
this.pathToLastIndex(destinationCollectionIDSubset) - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Replace the destination collection ID with `1` reduced from the index position
|
||||||
|
const replacedDestinationCollectionID = destinationCollectionID.replace(
|
||||||
|
destinationCollectionIDSubset,
|
||||||
|
`${destinationCollectionIDSubset
|
||||||
|
.split("/")
|
||||||
|
.slice(0, -1)
|
||||||
|
.join("/")}/${collectionIDSubsetIndexPos}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const resolvedDestinationCollectionIDPrefix = this.isAlreadyInRoot(
|
||||||
|
draggedCollectionID
|
||||||
|
)
|
||||||
|
? collectionIDSubsetIndexPos
|
||||||
|
: replacedDestinationCollectionID
|
||||||
|
|
||||||
|
resolvedDestinationCollectionID = `${resolvedDestinationCollectionIDPrefix}/${resolvedDestinationCollectionIndexPos}`
|
||||||
|
} else {
|
||||||
|
resolvedDestinationCollectionID = `${destinationCollectionID}/${resolvedDestinationCollectionIndexPos}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const draggedParentCollectionSize = this.isAlreadyInRoot(
|
||||||
|
draggedCollectionID
|
||||||
|
)
|
||||||
|
? this.restCollectionState.value.state.length
|
||||||
|
: getFoldersByPath(
|
||||||
|
this.restCollectionState.value.state,
|
||||||
|
draggedParentCollectionID
|
||||||
|
).length
|
||||||
|
|
||||||
|
const affectedParentCollectionIDRange =
|
||||||
|
draggedParentCollectionSize - 1 - draggedCollectionIndexPos
|
||||||
|
|
||||||
moveRESTFolder(
|
moveRESTFolder(
|
||||||
collectionHandleRef.value.data.collectionID,
|
collectionHandleRef.value.data.collectionID,
|
||||||
destinationCollectionID
|
destinationCollectionID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.issuedHandles.forEach((handle) => {
|
||||||
|
if (handle.value.type === "invalid") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!("requestID" in handle.value.data)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { collectionID, requestID } = handle.value.data
|
||||||
|
|
||||||
|
const reqIndexPos = requestID.slice(-1)[0]
|
||||||
|
|
||||||
|
if (requestID.startsWith(draggedCollectionID)) {
|
||||||
|
const newCollectionID = collectionID.replace(
|
||||||
|
draggedCollectionID,
|
||||||
|
resolvedDestinationCollectionID
|
||||||
|
)
|
||||||
|
|
||||||
|
handle.value.data.collectionID = newCollectionID
|
||||||
|
handle.value.data.requestID = `${newCollectionID}/${reqIndexPos}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Array.from({ length: affectedParentCollectionIDRange }).forEach(
|
||||||
|
(_, idx) => {
|
||||||
|
// Adding `1` to dragged collection index position to get the affected collection index position
|
||||||
|
const affectedCollectionIndexPos = draggedCollectionIndexPos + idx + 1
|
||||||
|
|
||||||
|
const affectedCollectionID = `${draggedParentCollectionID}/${affectedCollectionIndexPos}`
|
||||||
|
|
||||||
|
// The index position will be reduced by `1` for the affected collections
|
||||||
|
const newAffectedCollectionID = `${draggedParentCollectionID}/${
|
||||||
|
affectedCollectionIndexPos - 1
|
||||||
|
}`
|
||||||
|
|
||||||
|
// For each affected collection, we'll have to iterate over the `issuedHandles` to account for nested collections
|
||||||
|
this.issuedHandles.forEach((handle) => {
|
||||||
|
if (
|
||||||
|
handle.value.type === "invalid" ||
|
||||||
|
!("requestID" in handle.value.data)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.value.data.requestID.startsWith(affectedCollectionID)) {
|
||||||
|
const { collectionID, requestID } = handle.value.data
|
||||||
|
|
||||||
|
handle.value.data.collectionID = collectionID.replace(
|
||||||
|
affectedCollectionID,
|
||||||
|
newAffectedCollectionID
|
||||||
|
)
|
||||||
|
|
||||||
|
handle.value.data.requestID = requestID.replace(
|
||||||
|
affectedCollectionID,
|
||||||
|
newAffectedCollectionID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return Promise.resolve(E.right(undefined))
|
return Promise.resolve(E.right(undefined))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user