refactor: integrate provider API methods for collection move/reorder

This commit is contained in:
jamesgeorge007
2024-02-20 22:16:03 +05:30
parent 0a0f441da1
commit fe01322bf7
9 changed files with 609 additions and 304 deletions

View File

@@ -534,6 +534,7 @@ const saveRequest = async () => {
if (E.isLeft(requestHandleResult)) {
// INVALID_COLLECTION_HANDLE | INVALID_REQUEST_ID | REQUEST_NOT_FOUND
showSaveRequestModal.value = true
return
}

View File

@@ -22,8 +22,8 @@
></div>
<div
class="z-[3] group pointer-events-auto relative flex cursor-pointer items-stretch"
:draggable="true"
@dragstart="dragStart"
@drop="handleDrop($event)"
@dragover="handleDragOver($event)"
@dragleave="resetDragState"
@dragend="
@@ -32,7 +32,8 @@
dropItemID = ''
}
"
@contextmenu.prevent="options?.tippy.show()"
@drop="handleDrop($event)"
@contextmenu.prevent="options?.tippy?.show()"
>
<div
class="flex min-w-0 flex-1 items-center justify-center"
@@ -179,12 +180,12 @@
</div>
</div>
<div
v-if="isLastItem"
v-if="collectionView.isLastItem"
class="w-full transition"
:class="[
{
'bg-accentDark': isLastItemReorderable,
'h-1 ': isLastItem,
'h-1 ': collectionView.isLastItem,
},
]"
@drop="updateLastItemOrder"
@@ -224,7 +225,6 @@ const props = defineProps<{
collectionView: RESTCollectionViewCollection
isOpen: boolean
isSelected?: boolean | null
isLastItem?: boolean
}>()
const emit = defineEmits<{
@@ -349,8 +349,10 @@ const editCollection = () => {
const dragStart = ({ dataTransfer }: DragEvent) => {
if (dataTransfer) {
emit("drag-event", dataTransfer)
dropItemID.value = dataTransfer.getData("collectionIndex")
dragging.value = !dragging.value
changeCurrentReorderStatus({
type: "collection",
id: props.collectionView.collectionID,
@@ -376,7 +378,7 @@ const handleDragOver = (e: DragEvent) => {
notSameDestination.value &&
!isRequestDragging.value &&
isSameParent.value &&
props.isLastItem
props.collectionView.isLastItem
) {
orderingLastItem.value = true
dragging.value = false

View File

@@ -1,8 +1,27 @@
<template>
<div class="flex flex-col">
<div
class="h-1 w-full transition"
:class="[
{
'bg-accentDark': isReorderable,
},
]"
@drop="updateRequestOrder"
@dragover.prevent="ordering = true"
@dragleave="resetDragState"
@dragend="resetDragState"
></div>
<div
class="group flex items-stretch"
@contextmenu.prevent="options?.tippy.show()"
:draggable="true"
@dragstart="dragStart"
@dragover="handleDragOver($event)"
@dragleave="resetDragState"
@dragend="resetDragState"
@drop="handleDrop"
@contextmenu.prevent="options?.tippy?.show()"
>
<div
class="pointer-events-auto flex min-w-0 flex-1 cursor-pointer items-center justify-center"
@@ -45,6 +64,7 @@
</span>
</span>
</div>
<div class="flex">
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
@@ -59,7 +79,7 @@
interactive
trigger="click"
theme="popover"
:on-shown="() => tippyActions!.focus()"
:on-shown="() => tippyActions.focus()"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
@@ -134,6 +154,20 @@
</span>
</div>
</div>
<div
class="w-full transition"
:class="[
{
'bg-accentDark': isLastItemReorderable,
'h-1 ': props.requestView.isLastItem,
},
]"
@drop="handleDrop"
@dragover.prevent="orderingLastItem = true"
@dragleave="resetDragState"
@dragend="resetDragState"
></div>
</div>
</template>
@@ -142,8 +176,13 @@ import { useI18n } from "@composables/i18n"
import { HoppRESTRequest } from "@hoppscotch/data"
import { computed, ref } from "vue"
import { TippyComponent } from "vue-tippy"
import { useReadonlyStream } from "~/composables/stream"
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
import {
currentReorderingStatus$,
changeCurrentReorderStatus,
} from "~/newstore/reordering"
import { RESTCollectionViewRequest } from "~/services/new-workspace/view"
import IconCheckCircle from "~icons/lucide/check-circle"
@@ -156,6 +195,12 @@ import IconTrash2 from "~icons/lucide/trash-2"
const t = useI18n()
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
type: "collection",
id: "",
parentID: "",
})
const props = defineProps<{
isActive: boolean
requestView: RESTCollectionViewRequest
@@ -174,6 +219,9 @@ const emit = defineEmits<{
(event: "remove-request", requestIndexPath: string): void
(event: "select-request", requestIndexPath: string): void
(event: "share-request", request: HoppRESTRequest): void
(event: "drag-request", payload: DataTransfer): void
(event: "update-request-order", payload: DataTransfer): void
(event: "update-last-request-order", payload: DataTransfer): void
}>()
const tippyActions = ref<TippyComponent | null>(null)
@@ -183,9 +231,105 @@ const options = ref<TippyComponent | null>(null)
const duplicate = ref<HTMLButtonElement | null>(null)
const shareAction = ref<HTMLButtonElement | null>(null)
const dragging = ref(false)
const ordering = ref(false)
const orderingLastItem = ref(false)
const isCollectionDragging = computed(() => {
return currentReorderingStatus.value.type === "collection"
})
const isLastItemReorderable = computed(() => {
return (
orderingLastItem.value && isSameParent.value && !isCollectionDragging.value
)
})
const isReorderable = computed(() => {
return (
ordering.value &&
!isCollectionDragging.value &&
isSameParent.value &&
!isSameRequest.value
)
})
const isSameParent = computed(() => {
return (
currentReorderingStatus.value.parentID ===
props.requestView.parentCollectionID
)
})
const isSameRequest = computed(() => {
return currentReorderingStatus.value.id === props.requestView.requestID
})
const requestLabelColor = computed(() =>
getMethodLabelColorClassOf(props.requestView.request)
)
const dragStart = ({ dataTransfer }: DragEvent) => {
if (dataTransfer) {
emit("drag-request", dataTransfer)
dragging.value = !dragging.value
changeCurrentReorderStatus({
type: "request",
id: props.requestView.requestID,
parentID: props.requestView.parentCollectionID,
})
}
}
const handleDrop = (e: DragEvent) => {
if (ordering.value) {
updateRequestOrder(e)
} else if (orderingLastItem.value) {
updateLastItemOrder(e)
} else {
updateRequestOrder(e)
}
}
// Trigger the re-ordering event when a request is dragged over another request's top section
const handleDragOver = (e: DragEvent) => {
dragging.value = true
if (e.offsetY < 10) {
ordering.value = true
dragging.value = false
orderingLastItem.value = false
} else if (e.offsetY > 18) {
orderingLastItem.value = true
dragging.value = false
ordering.value = false
} else {
ordering.value = false
orderingLastItem.value = false
}
}
const resetDragState = () => {
dragging.value = false
ordering.value = false
orderingLastItem.value = false
}
const selectRequest = () => emit("select-request", props.requestView.requestID)
const updateRequestOrder = (e: DragEvent) => {
if (e.dataTransfer) {
e.stopPropagation()
resetDragState()
emit("update-request-order", e.dataTransfer)
}
}
const updateLastItemOrder = (e: DragEvent) => {
if (e.dataTransfer) {
e.stopPropagation()
resetDragState()
emit("update-last-request-order", e.dataTransfer)
}
}
</script>

View File

@@ -12,9 +12,10 @@
>
<div
class="sticky z-10 flex flex-shrink-0 flex-col overflow-x-auto border-b border-dividerLight bg-primary"
:style="{
top: 0,
}"
:class="{ 'rounded-t': saveRequest }"
:style="
saveRequest ? 'top: calc(-1 * var(--line-height-body))' : 'top: 0'
"
>
<WorkspaceCurrent :section="t('tab.collections')" />
<input
@@ -25,6 +26,7 @@
:placeholder="t('action.search')"
/>
</div>
<div class="flex flex-1 flex-col">
<div
class="sticky z-10 flex flex-1 justify-between border-b border-dividerLight bg-primary"
@@ -66,7 +68,6 @@
<NewCollectionsRestCollection
v-if="node.data.type === 'collection'"
:collection-view="node.data.value"
:is-last-item="node.data.value.isLastItem"
:is-open="isOpen"
:is-selected="
isSelected(
@@ -126,7 +127,6 @@
<NewCollectionsRestRequest
v-else-if="node.data.type === 'request'"
:is-active="isActiveRequest(node.data.value)"
:is-last-item="node.data.value.isLastItem"
:is-selected="
isSelected(getRequestIndexPathArgs(node.data.value.requestID))
"
@@ -168,12 +168,14 @@
</HoppSmartTree>
</div>
<!-- <div
class="py-15 hidden flex-1 flex-col items-center justify-center bg-primaryDark px-4 text-secondaryLight"
:class="{
'!flex': draggingToRoot && currentReorderingStatus.type !== 'request',
}"
> -->
<div
class="py-15 hidden flex-1 flex-col items-center justify-center bg-primaryDark px-4 text-secondaryLight"
:class="{
'!flex': draggingToRoot && currentReorderingStatus.type !== 'request',
}"
>
<icon-lucide-list-end class="svg-icons !h-8 !w-8" />
</div>
<CollectionsAdd
:show="showModalAdd"
@@ -258,20 +260,22 @@ import { WorkspaceRESTCollectionTreeAdapter } from "~/helpers/adapters/Workspace
import { TeamCollection } from "~/helpers/backend/graphql"
import {
getFoldersByPath,
resolveSaveContextOnCollectionReorder,
updateInheritedPropertiesForAffectedRequests,
updateSaveContextForAffectedRequests,
} from "~/helpers/collection/collection"
import {
getRequestsByPath,
resolveSaveContextOnRequestReorder,
} from "~/helpers/collection/request"
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
import { Picked } from "~/helpers/types/HoppPicked"
import {
cascadeParentCollectionForHeaderAuth,
moveRESTFolder,
moveRESTRequest,
navigateToFolderWithIndexPath,
restCollections$,
saveRESTRequestAs,
updateRESTCollectionOrder,
updateRESTRequestOrder,
} from "~/newstore/collections"
import { currentReorderingStatus$ } from "~/newstore/reordering"
import { platform } from "~/platform"
import { NewWorkspaceService } from "~/services/new-workspace"
import { HandleRef } from "~/services/new-workspace/handle"
@@ -281,7 +285,6 @@ import { RESTTabService } from "~/services/tab/rest"
import IconImport from "~icons/lucide/folder-down"
import IconHelpCircle from "~icons/lucide/help-circle"
import IconPlus from "~icons/lucide/plus"
import { currentReorderingStatus$ } from "~/newstore/reordering"
const t = useI18n()
const toast = useToast()
@@ -296,40 +299,7 @@ const props = defineProps<{
const emit = defineEmits<{
(e: "display-modal-add"): void
(e: "display-modal-import-export"): void
(
event: "drop-collection",
payload: {
collectionIndexDragged: string
destinationCollectionIndex: string
}
): void
(
event: "drop-request",
payload: {
parentCollectionIndexPath: string
requestIndex: string
destinationCollectionIndex: string
}
): void
(event: "select", payload: Picked | null): void
(
event: "update-collection-order",
payload: {
dragedCollectionIndex: string
destinationCollection: {
destinationCollectionIndex: string | null
destinationCollectionParentIndex: string | null
}
}
): void
(
event: "update-request-order",
payload: {
dragedRequestIndex: string
destinationRequestIndex: string | null
destinationCollectionIndex: string
}
): void
}>()
const workspaceService = useService(NewWorkspaceService)
@@ -1301,7 +1271,7 @@ const dragRequest = (
dataTransfer.setData("requestIndex", requestIndex)
}
const dropEvent = (
const dropEvent = async (
dataTransfer: DataTransfer,
destinationCollectionIndex: string
) => {
@@ -1309,22 +1279,17 @@ const dropEvent = (
"parentCollectionIndexPath"
)
const requestIndex = dataTransfer.getData("requestIndex")
const collectionIndexDragged = dataTransfer.getData("collectionIndex")
const draggedCollectionIndex = dataTransfer.getData("collectionIndex")
if (parentCollectionIndexPath && requestIndex) {
// emit("drop-request", {
// parentCollectionIndexPath,
// requestIndex,
// destinationCollectionIndex,
// })
dropRequest({
await dropRequest({
parentCollectionIndexPath,
requestIndex,
destinationCollectionIndex,
})
} else {
dropCollection({
collectionIndexDragged,
await dropCollection({
draggedCollectionIndex,
destinationCollectionIndex,
})
}
@@ -1335,23 +1300,115 @@ const dropEvent = (
* to the root
* @param payload - object containing the collection index dragged
*/
const dropToRoot = ({ dataTransfer }: DragEvent) => {
if (dataTransfer) {
const collectionIndexDragged = dataTransfer.getData("collectionIndex")
if (!collectionIndexDragged) return
// check if the collection is already in the root
if (isAlreadyInRoot(collectionIndexDragged)) {
toast.error(`${t("collection.invalid_root_move")}`)
} else {
moveRESTFolder(collectionIndexDragged, null)
toast.success(`${t("collection.moved")}`)
}
draggingToRoot.value = false
const dropToRoot = async ({ dataTransfer }: DragEvent) => {
if (!dataTransfer) {
return
}
const draggedCollectionIndex = dataTransfer.getData("collectionIndex")
if (!draggedCollectionIndex) {
return
}
// check if the collection is already in the root
if (isAlreadyInRoot(draggedCollectionIndex)) {
toast.error(`${t("collection.invalid_root_move")}`)
draggingToRoot.value = false
return
}
const draggedCollectionHandleResult =
await workspaceService.getCollectionHandle(
props.workspaceHandle,
draggedCollectionIndex
)
if (E.isLeft(draggedCollectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
return
}
const draggedCollectionHandle = draggedCollectionHandleResult.right
if (draggedCollectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const result = await workspaceService.moveRESTCollection(
draggedCollectionHandle,
null
)
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
const destinationRootCollectionIndex = (
restCollectionState.value.length - 1
).toString()
updateSaveContextForAffectedRequests(
draggedCollectionIndex,
destinationRootCollectionIndex
)
const destinationRootCollectionHandleResult =
await workspaceService.getCollectionHandle(
props.workspaceHandle,
destinationRootCollectionIndex
)
if (E.isLeft(destinationRootCollectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
return
}
const destinationRootCollectionHandle =
destinationRootCollectionHandleResult.right
if (destinationRootCollectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
destinationRootCollectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth, headers } = cascadingAuthHeadersHandle.value.data
const inheritedProperty = {
auth,
headers,
}
updateInheritedPropertiesForAffectedRequests(
destinationRootCollectionIndex,
inheritedProperty,
"rest"
)
toast.success(`${t("collection.moved")}`)
draggingToRoot.value = false
}
const dropRequest = (payload: {
const dropRequest = async (payload: {
parentCollectionIndexPath?: string | undefined
requestIndex: string
destinationCollectionIndex: string
@@ -1366,65 +1423,137 @@ const dropRequest = (payload: {
!requestIndex ||
!destinationCollectionIndex ||
!parentCollectionIndexPath
)
) {
return
}
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
// destinationCollectionIndex,
// "rest"
// )
const requestHandleResult = await workspaceService.getRequestHandle(
props.workspaceHandle,
requestIndex
)
// const possibleTab = tabs.getTabRefWithSaveContext({
// originLocation: "user-collection",
// folderPath,
// requestIndex: pathToLastIndex(requestIndex),
// })
if (E.isLeft(requestHandleResult)) {
// INVALID_COLLECTION_HANDLE | INVALID_REQUEST_ID | REQUEST_NOT_FOUND
return
}
// If there is a tab attached to this request, change save its save context
// if (possibleTab) {
// possibleTab.value.document.saveContext = {
// originLocation: "user-collection",
// folderPath: destinationCollectionIndex,
// requestIndex: getRequestsByPath(
// restCollectionState.value,
// destinationCollectionIndex
// ).length,
// }
const requestHandle = requestHandleResult.right
// possibleTab.value.document.inheritedProperties = {
// auth,
// headers,
// }
// }
if (requestHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
// When it's drop it's basically getting deleted from last folder. reordering last folder accordingly
// resolveSaveContextOnRequestReorder({
// lastIndex: pathToLastIndex(requestIndex),
// newIndex: -1, // being deleted from last folder
// folderPath,
// length: getRequestsByPath(myCollections.value, folderPath).length,
// })
moveRESTRequest(
parentCollectionIndexPath,
pathToLastIndex(requestIndex),
const result = await workspaceService.moveRESTRequest(
requestHandle,
destinationCollectionIndex
)
if (E.isLeft(result)) {
// INVALID_REQUEST_HANDLE
return
}
const collectionHandleResult = await workspaceService.getCollectionHandle(
props.workspaceHandle,
destinationCollectionIndex
)
if (E.isLeft(collectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
return
}
const collectionHandle = collectionHandleResult.right
if (collectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
collectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth, headers } = cascadingAuthHeadersHandle.value.data
const { collectionID, providerID, requestID, workspaceID } =
requestHandle.value.data
const possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "workspace-user-collection",
workspaceID,
providerID,
collectionID,
requestID,
})
// If there is a tab attached to this request, update its save context
if (possibleTab) {
const newCollectionID = destinationCollectionIndex
const newRequestID = `${destinationCollectionIndex}/${(
getRequestsByPath(restCollectionState.value, destinationCollectionIndex)
.length - 1
).toString()}`
possibleTab.value.document.saveContext = {
originLocation: "workspace-user-collection",
workspaceID,
providerID,
collectionID: newCollectionID,
requestID: newRequestID,
}
possibleTab.value.document.inheritedProperties = {
auth,
headers,
}
}
// When it's drop it's basically getting deleted from last folder. reordering last folder accordingly
resolveSaveContextOnRequestReorder({
lastIndex: pathToLastIndex(requestIndex),
newIndex: -1, // being deleted from last folder
folderPath: parentCollectionIndexPath,
length:
getRequestsByPath(restCollectionState.value, parentCollectionIndexPath)
.length - 1,
})
toast.success(`${t("request.moved")}`)
// draggingToRoot.value = false
draggingToRoot.value = false
}
const dropCollection = (payload: {
collectionIndexDragged: string
const dropCollection = async (payload: {
draggedCollectionIndex: string
destinationCollectionIndex: string
}) => {
const { collectionIndexDragged, destinationCollectionIndex } = payload
if (!collectionIndexDragged || !destinationCollectionIndex) return
if (collectionIndexDragged === destinationCollectionIndex) return
const { draggedCollectionIndex, destinationCollectionIndex } = payload
if (
!draggedCollectionIndex ||
!destinationCollectionIndex ||
draggedCollectionIndex === destinationCollectionIndex
) {
return
}
if (
checkIfCollectionIsAParentOfTheChildren(
collectionIndexDragged,
draggedCollectionIndex,
destinationCollectionIndex
)
) {
@@ -1434,38 +1563,96 @@ const dropCollection = (payload: {
//check if the collection is being moved to its own parent
if (
isMoveToSameLocation(collectionIndexDragged, destinationCollectionIndex)
isMoveToSameLocation(draggedCollectionIndex, destinationCollectionIndex)
) {
return
}
const parentFolder = collectionIndexDragged.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
const parentFolder = draggedCollectionIndex.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
const totalFoldersOfDestinationCollection =
getFoldersByPath(restCollectionState.value, destinationCollectionIndex)
.length - (parentFolder === destinationCollectionIndex ? 1 : 0)
moveRESTFolder(collectionIndexDragged, destinationCollectionIndex)
const draggedCollectionHandleResult =
await workspaceService.getCollectionHandle(
props.workspaceHandle,
draggedCollectionIndex
)
// resolveSaveContextOnCollectionReorder(
// {
// lastIndex: pathToLastIndex(collectionIndexDragged),
// newIndex: -1,
// folderPath: parentFolder,
// length: getFoldersByPath(restCollectionState.value, parentFolder).length,
// },
// "drop"
// )
if (E.isLeft(draggedCollectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
return
}
// updateSaveContextForAffectedRequests(
// collectionIndexDragged,
// `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
// )
const draggedCollectionHandle = draggedCollectionHandleResult.right
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
"rest"
if (draggedCollectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const result = await workspaceService.moveRESTCollection(
draggedCollectionHandle,
destinationCollectionIndex
)
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
resolveSaveContextOnCollectionReorder(
{
lastIndex: pathToLastIndex(draggedCollectionIndex),
newIndex: -1,
folderPath: parentFolder,
length: getFoldersByPath(restCollectionState.value, parentFolder).length,
},
"drop"
)
updateSaveContextForAffectedRequests(
draggedCollectionIndex,
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
)
const destinationCollectionHandleResult =
await workspaceService.getCollectionHandle(
props.workspaceHandle,
destinationCollectionIndex
)
if (E.isLeft(destinationCollectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
return
}
const destinationCollectionHandle = destinationCollectionHandleResult.right
if (destinationCollectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
destinationCollectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth, headers } = cascadingAuthHeadersHandle.value.data
const inheritedProperty = {
auth,
headers,
@@ -1477,50 +1664,75 @@ const dropCollection = (payload: {
"rest"
)
// draggingToRoot.value = false
draggingToRoot.value = false
toast.success(`${t("collection.moved")}`)
}
const updateRequestOrder = (
const updateRequestOrder = async (
dataTransfer: DataTransfer,
{
parentCollectionIndexPath,
requestIndex,
}: { parentCollectionIndexPath: string | null; requestIndex: string | null }
) => {
if (!parentCollectionIndexPath) return
const dragedRequestIndex = dataTransfer.getData("requestIndex")
if (!parentCollectionIndexPath) {
return
}
const draggedRequestIndex = dataTransfer.getData("requestIndex")
const destinationRequestIndex = requestIndex
const destinationCollectionIndex = parentCollectionIndexPath
if (
!dragedRequestIndex ||
!draggedRequestIndex ||
!destinationCollectionIndex ||
dragedRequestIndex === destinationRequestIndex
draggedRequestIndex === destinationRequestIndex
) {
return
}
if (
!isSameSameParent(
dragedRequestIndex,
draggedRequestIndex,
destinationRequestIndex,
destinationCollectionIndex
)
) {
toast.error(`${t("collection.different_parent")}`)
} else {
updateRESTRequestOrder(
pathToLastIndex(dragedRequestIndex),
destinationRequestIndex ? pathToLastIndex(destinationRequestIndex) : null,
destinationCollectionIndex
)
toast.success(`${t("request.order_changed")}`)
return toast.error(`${t("collection.different_parent")}`)
}
const requestHandleResult = await workspaceService.getRequestHandle(
props.workspaceHandle,
draggedRequestIndex
)
if (E.isLeft(requestHandleResult)) {
// INVALID_COLLECTION_HANDLE | INVALID_REQUEST_ID | REQUEST_NOT_FOUND
return
}
const requestHandle = requestHandleResult.right
if (requestHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const result = await workspaceService.reorderRESTRequest(
requestHandle,
destinationCollectionIndex,
destinationRequestIndex
)
if (E.isLeft(result)) {
// INVALID_REQUEST_HANDLE
return
}
toast.success(`${t("request.order_changed")}`)
}
const updateCollectionOrder = (
const updateCollectionOrder = async (
dataTransfer: DataTransfer,
destinationCollection: {
destinationCollectionIndex: string | null
@@ -1546,21 +1758,43 @@ const updateCollectionOrder = (
destinationCollectionParentIndex
)
) {
toast.error(`${t("collection.different_parent")}`)
} else {
updateRESTCollectionOrder(
draggedCollectionIndex,
destinationCollectionIndex
)
// resolveSaveContextOnCollectionReorder({
// lastIndex: pathToLastIndex(draggedCollectionIndex),
// newIndex: pathToLastIndex(
// destinationCollectionIndex ? destinationCollectionIndex : ""
// ),
// folderPath: draggedCollectionIndex.split("/").slice(0, -1).join("/"),
// })
toast.success(`${t("collection.order_changed")}`)
return toast.error(`${t("collection.different_parent")}`)
}
const collectionHandleResult = await workspaceService.getCollectionHandle(
props.workspaceHandle,
draggedCollectionIndex
)
if (E.isLeft(collectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
return
}
const collectionHandle = collectionHandleResult.right
if (collectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const result = await workspaceService.reorderRESTCollection(
collectionHandle,
destinationCollectionIndex
)
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
resolveSaveContextOnCollectionReorder({
lastIndex: pathToLastIndex(draggedCollectionIndex),
newIndex: pathToLastIndex(destinationCollectionIndex ?? ""),
folderPath: draggedCollectionIndex.split("/").slice(0, -1).join("/"),
})
toast.success(`${t("collection.order_changed")}`)
}
const shareRequest = (request: HoppRESTRequest) => {
@@ -1579,15 +1813,15 @@ const shareRequest = (request: HoppRESTRequest) => {
/**
* Used to check if the collection exist as the parent of the childrens
* @param collectionIndexDragged The index of the collection dragged
* @param draggedCollectionIndex The index of the collection dragged
* @param destinationCollectionIndex The index of the destination collection
* @returns True if the collection exist as the parent of the childrens
*/
const checkIfCollectionIsAParentOfTheChildren = (
collectionIndexDragged: string,
draggedCollectionIndex: string,
destinationCollectionIndex: string
) => {
const collectionDraggedPath = pathToIndex(collectionIndexDragged)
const collectionDraggedPath = pathToIndex(draggedCollectionIndex)
const destinationCollectionPath = pathToIndex(destinationCollectionIndex)
if (collectionDraggedPath.length < destinationCollectionPath.length) {
@@ -1701,9 +1935,9 @@ const isSameSameParent = (
draggedItemIndex.length !== 1 &&
destinationCollectionIndex !== null
) {
const dragedItemParent = draggedItemIndex.slice(0, -1)
const draggedItemParent = draggedItemIndex.slice(0, -1)
return dragedItemParent.join("/") === destinationCollectionIndex
return draggedItemParent.join("/") === destinationCollectionIndex
}
if (destinationItemPath === null) return false
const destinationItemIndex = pathToIndex(destinationItemPath)
@@ -1712,9 +1946,9 @@ const isSameSameParent = (
if (draggedItemIndex.length === 1 && destinationItemIndex.length === 1) {
return true
} else if (draggedItemIndex.length === destinationItemIndex.length) {
const dragedItemParent = draggedItemIndex.slice(0, -1)
const draggedItemParent = draggedItemIndex.slice(0, -1)
const destinationItemParent = destinationItemIndex.slice(0, -1)
if (isEqual(dragedItemParent, destinationItemParent)) {
if (isEqual(draggedItemParent, destinationItemParent)) {
return true
}
return false

View File

@@ -87,10 +87,15 @@ export function resolveSaveContextOnCollectionReorder(
tab.value.document.saveContext?.originLocation ===
"workspace-user-collection"
) {
const newPath = affectedPaths.get(
const newCollectionID = affectedPaths.get(
tab.value.document.saveContext?.collectionID
)!
tab.value.document.saveContext.collectionID = newPath
const newRequestID = `${newCollectionID}/${
tab.value.document.saveContext.requestID.split("/").slice(-1)[0]
}`
tab.value.document.saveContext.collectionID = newCollectionID
tab.value.document.saveContext.requestID = newRequestID
}
}
}
@@ -134,12 +139,19 @@ export function updateSaveContextForAffectedRequests(
tab.value.document.saveContext?.originLocation ===
"workspace-user-collection"
) {
tab.value.document.saveContext = {
...tab.value.document.saveContext,
collectionID: tab.value.document.saveContext.collectionID.replace(
const newCollectionID =
tab.value.document.saveContext.collectionID.replace(
oldFolderPath,
newFolderPath
),
)
const newRequestID = `${newCollectionID}/${
tab.value.document.saveContext.requestID.split("/").slice(-1)[0]
}`
tab.value.document.saveContext = {
...tab.value.document.saveContext,
collectionID: newCollectionID,
requestID: newRequestID,
}
}
}

View File

@@ -63,6 +63,19 @@ export function resolveSaveContextOnRequestReorder(payload: {
)!
tab.value.document.saveContext.requestIndex = newIndex
}
if (
tab.value.document.saveContext?.originLocation ===
"workspace-user-collection"
) {
const requestID = tab.value.document.saveContext.requestID
const requestIDArray = requestID.split("/")
const requestIndex = affectedIndexes.get(
parseInt(requestIDArray[requestIDArray.length - 1])
)!
requestIDArray[requestIDArray.length - 1] = requestIndex.toString()
tab.value.document.saveContext.requestID = requestIDArray.join("/")
}
}
}

View File

@@ -478,7 +478,7 @@ export class NewWorkspaceService extends Service {
public async reorderRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
destinationCollectionIndex: string
destinationCollectionIndex: string | null
): Promise<
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
> {
@@ -508,7 +508,7 @@ export class NewWorkspaceService extends Service {
public async moveRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
destinationCollectionIndex: string
destinationCollectionIndex: string | null
): Promise<
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
> {
@@ -538,8 +538,8 @@ export class NewWorkspaceService extends Service {
public async reorderRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,
destinationRequestIndex: string,
destinationCollectionIndex: string
destinationCollectionIndex: string,
destinationRequestIndex: string | null
): Promise<
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
> {
@@ -557,8 +557,8 @@ export class NewWorkspaceService extends Service {
const result = await provider.reorderRESTRequest(
requestHandle,
destinationRequestIndex,
destinationCollectionIndex
destinationCollectionIndex,
destinationRequestIndex
)
if (E.isLeft(result)) {

View File

@@ -83,7 +83,7 @@ export interface WorkspaceProvider {
reorderRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
destinationCollectionIndex: string
destinationCollectionIndex: string | null
): Promise<E.Either<unknown, void>>
moveRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
@@ -91,8 +91,8 @@ export interface WorkspaceProvider {
): Promise<E.Either<unknown, void>>
reorderRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,
destinationRequestIndex: string,
destinationCollectionIndex: string
destinationCollectionIndex: string,
destinationRequestIndex: string | null
): Promise<E.Either<unknown, void>>
moveRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,

View File

@@ -16,7 +16,6 @@ import {
addRESTCollection,
addRESTFolder,
appendRESTCollections,
cascadeParentCollectionForHeaderAuth,
editRESTCollection,
editRESTFolder,
editRESTRequest,
@@ -52,20 +51,10 @@ import { HoppRESTRequest } from "@hoppscotch/data"
import { merge } from "lodash-es"
import path from "path"
import { HoppGQLHeader } from "~/helpers/graphql"
import { initializeDownloadFile } from "~/helpers/import-export/export"
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
import IconUser from "~icons/lucide/user"
import { NewWorkspaceService } from ".."
import { initializeDownloadFile } from "~/helpers/import-export/export"
import {
getFoldersByPath,
resolveSaveContextOnCollectionReorder,
updateInheritedPropertiesForAffectedRequests,
updateSaveContextForAffectedRequests,
} from "~/helpers/collection/collection"
import {
getRequestsByPath,
resolveSaveContextOnRequestReorder,
} from "~/helpers/collection/request"
export class PersonalWorkspaceProviderService
extends Service
@@ -492,7 +481,7 @@ export class PersonalWorkspaceProviderService
public reorderRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
destinationCollectionIndex: string
destinationCollectionIndex: string | null
): Promise<E.Either<unknown, void>> {
if (
collectionHandle.value.type !== "ok" ||
@@ -508,11 +497,6 @@ export class PersonalWorkspaceProviderService
draggedCollectionIndex,
destinationCollectionIndex
)
resolveSaveContextOnCollectionReorder({
lastIndex: this.pathToLastIndex(draggedCollectionIndex),
newIndex: this.pathToLastIndex(destinationCollectionIndex ?? ""),
folderPath: draggedCollectionIndex.split("/").slice(0, -1).join("/"),
})
return Promise.resolve(E.right(undefined))
}
@@ -529,64 +513,18 @@ export class PersonalWorkspaceProviderService
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
}
const draggedCollectionIndex = collectionHandle.value.data.collectionID
moveRESTFolder(draggedCollectionIndex, destinationCollectionIndex)
if (destinationCollectionIndex === null) {
return Promise.resolve(E.right(undefined))
}
const parentFolder = draggedCollectionIndex
.split("/")
.slice(0, -1)
.join("/") // remove last folder to get parent folder
const totalFoldersOfDestinationCollection =
getFoldersByPath(
restCollectionStore.value.state,
destinationCollectionIndex
).length - (parentFolder === destinationCollectionIndex ? 1 : 0)
resolveSaveContextOnCollectionReorder(
{
lastIndex: this.pathToLastIndex(draggedCollectionIndex),
newIndex: -1,
folderPath: parentFolder,
length: getFoldersByPath(restCollectionStore.value.state, parentFolder)
.length,
},
"drop"
moveRESTFolder(
collectionHandle.value.data.collectionID,
destinationCollectionIndex
)
updateSaveContextForAffectedRequests(
draggedCollectionIndex,
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
)
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
// `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
// "rest"
// )
// const inheritedProperty = {
// auth,
// headers,
// }
// updateInheritedPropertiesForAffectedRequests(
// `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
// inheritedProperty,
// "rest"
// )
return Promise.resolve(E.right(undefined))
}
public reorderRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,
destinationCollectionIndex: string,
destinationRequestIndex: string
destinationRequestIndex: string | null
): Promise<E.Either<unknown, void>> {
if (
requestHandle.value.type !== "ok" ||
@@ -627,45 +565,6 @@ export class PersonalWorkspaceProviderService
.slice(0, -1)
.join("/")
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
// destinationCollectionIndex,
// "rest"
// )
// const possibleTab = tabs.getTabRefWithSaveContext({
// originLocation: "user-collection",
// folderPath: parentCollectionIndexPath,
// requestIndex: this.pathToLastIndex(requestIndex),
// })
// // If there is a tab attached to this request, change save its save context
// if (possibleTab) {
// possibleTab.value.document.saveContext = {
// originLocation: "user-collection",
// folderPath: destinationCollectionIndex,
// requestIndex: getRequestsByPath(
// restCollectionStore.value.state,
// destinationCollectionIndex
// ).length,
// }
// possibleTab.value.document.inheritedProperties = {
// auth,
// headers,
// }
// }
// // When it's drop it's basically getting deleted from last folder. reordering last folder accordingly
// resolveSaveContextOnRequestReorder({
// lastIndex: this.pathToLastIndex(requestIndex),
// newIndex: -1, // being deleted from last folder
// folderPath: parentCollectionIndexPath,
// length: getRequestsByPath(
// restCollectionStore.value.state,
// parentCollectionIndexPath
// ).length,
// })
moveRESTRequest(
parentCollectionIndexPath,
this.pathToLastIndex(requestIndex),
@@ -924,7 +823,7 @@ export class PersonalWorkspaceProviderService
isLastItem:
id === this.restCollectionState.value.state.length - 1,
name: coll.name,
parentIndex: null,
parentCollectionID: null,
}
})
}),