chore: merge hoppscotch/staging into self-hosted/main
This commit is contained in:
@@ -17,27 +17,13 @@
|
|||||||
/>
|
/>
|
||||||
<!-- <AppGitHubStarButton class="mt-1.5 transition" /> -->
|
<!-- <AppGitHubStarButton class="mt-1.5 transition" /> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex items-center justify-center flex-1 space-x-2">
|
<div class="inline-flex items-center space-x-2">
|
||||||
<AppNavigation v-if="mdAndLarger" />
|
|
||||||
<div
|
|
||||||
class="bg-primaryDark max-w-128 text-secondaryLight justify-between cursor-pointer rounded border border-dividerDark hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary focus:outline-none transition flex flex-1 items-center px-2 py-1.25"
|
|
||||||
tabindex="0"
|
|
||||||
@click="invokeAction('modals.search.toggle')"
|
|
||||||
>
|
|
||||||
<span class="inline-flex">
|
|
||||||
<icon-lucide-search class="mr-2 svg-icons" />
|
|
||||||
{{ t("app.search") }}
|
|
||||||
</span>
|
|
||||||
<kbd class="shortcut-key">/</kbd>
|
|
||||||
</div>
|
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||||
:title="`${
|
:title="`${t('app.search')} <kbd>/</kbd>`"
|
||||||
mdAndLarger ? t('support.title') : t('app.options')
|
:icon="IconSearch"
|
||||||
} <kbd>?</kbd>`"
|
|
||||||
:icon="IconHelpCircle"
|
|
||||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
@click="invokeAction('modals.support.toggle')"
|
@click="invokeAction('modals.search.toggle')"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-if="showInstallButton"
|
v-if="showInstallButton"
|
||||||
@@ -47,8 +33,15 @@
|
|||||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
@click="installPWA()"
|
@click="installPWA()"
|
||||||
/>
|
/>
|
||||||
</div>
|
<HoppButtonSecondary
|
||||||
<div class="inline-flex items-center justify-end flex-1 space-x-2">
|
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||||
|
:title="`${
|
||||||
|
mdAndLarger ? t('support.title') : t('app.options')
|
||||||
|
} <kbd>?</kbd>`"
|
||||||
|
:icon="IconLifeBuoy"
|
||||||
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
|
@click="invokeAction('modals.support.toggle')"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="currentUser === null"
|
v-if="currentUser === null"
|
||||||
class="inline-flex items-center space-x-2"
|
class="inline-flex items-center space-x-2"
|
||||||
@@ -242,7 +235,8 @@ import IconSettings from "~icons/lucide/settings"
|
|||||||
import IconDownload from "~icons/lucide/download"
|
import IconDownload from "~icons/lucide/download"
|
||||||
import IconUploadCloud from "~icons/lucide/upload-cloud"
|
import IconUploadCloud from "~icons/lucide/upload-cloud"
|
||||||
import IconUserPlus from "~icons/lucide/user-plus"
|
import IconUserPlus from "~icons/lucide/user-plus"
|
||||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
import IconLifeBuoy from "~icons/lucide/life-buoy"
|
||||||
|
import IconSearch from "~icons/lucide/search"
|
||||||
import { breakpointsTailwind, useBreakpoints, useNetwork } from "@vueuse/core"
|
import { breakpointsTailwind, useBreakpoints, useNetwork } from "@vueuse/core"
|
||||||
import { pwaDefferedPrompt, installPWA } from "@modules/pwa"
|
import { pwaDefferedPrompt, installPWA } from "@modules/pwa"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip', delay: [500, 20], allowHTML: true }"
|
|
||||||
:title="`${t(
|
|
||||||
'action.go_back'
|
|
||||||
)} <kbd>${getSpecialKey()}</kbd><kbd>←</kbd>`"
|
|
||||||
:icon="IconArrowLeft"
|
|
||||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
|
||||||
@click="router.go(-1)"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip', delay: [500, 20], allowHTML: true }"
|
|
||||||
:title="`${t(
|
|
||||||
'action.go_forward'
|
|
||||||
)} <kbd>${getSpecialKey()}</kbd><kbd>→</kbd>`"
|
|
||||||
:icon="IconArrowRight"
|
|
||||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
|
||||||
@click="router.go(1)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useI18n } from "@composables/i18n"
|
|
||||||
import { useRouter } from "vue-router"
|
|
||||||
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
|
|
||||||
import IconArrowLeft from "~icons/lucide/arrow-left"
|
|
||||||
import IconArrowRight from "~icons/lucide/arrow-right"
|
|
||||||
|
|
||||||
const t = useI18n()
|
|
||||||
const router = useRouter()
|
|
||||||
</script>
|
|
||||||
@@ -165,6 +165,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLastItem"
|
||||||
|
class="w-full transition"
|
||||||
|
:class="[
|
||||||
|
{
|
||||||
|
'bg-accentDark': isLastItemReorderable,
|
||||||
|
'h-1 ': isLastItem,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
@drop="updateLastItemOrder"
|
||||||
|
@dragover.prevent="orderingLastItem = true"
|
||||||
|
@dragleave="orderingLastItem = false"
|
||||||
|
@dragend="resetDragState"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -249,6 +263,11 @@ const props = defineProps({
|
|||||||
default: () => [],
|
default: () => [],
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
isLastItem: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -262,6 +281,7 @@ const emit = defineEmits<{
|
|||||||
(event: "drag-event", payload: DataTransfer): void
|
(event: "drag-event", payload: DataTransfer): void
|
||||||
(event: "dragging", payload: boolean): void
|
(event: "dragging", payload: boolean): void
|
||||||
(event: "update-collection-order", payload: DataTransfer): void
|
(event: "update-collection-order", payload: DataTransfer): void
|
||||||
|
(event: "update-last-collection-order", payload: DataTransfer): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
@@ -274,6 +294,7 @@ const options = ref<TippyComponent | null>(null)
|
|||||||
|
|
||||||
const dragging = ref(false)
|
const dragging = ref(false)
|
||||||
const ordering = ref(false)
|
const ordering = ref(false)
|
||||||
|
const orderingLastItem = ref(false)
|
||||||
const dropItemID = ref("")
|
const dropItemID = ref("")
|
||||||
|
|
||||||
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
||||||
@@ -333,6 +354,14 @@ const isReorderable = computed(() => {
|
|||||||
isSameParent.value
|
isSameParent.value
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
const isLastItemReorderable = computed(() => {
|
||||||
|
return (
|
||||||
|
orderingLastItem.value &&
|
||||||
|
notSameDestination.value &&
|
||||||
|
!isRequestDragging.value &&
|
||||||
|
isSameParent.value
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
const dragStart = ({ dataTransfer }: DragEvent) => {
|
const dragStart = ({ dataTransfer }: DragEvent) => {
|
||||||
if (dataTransfer) {
|
if (dataTransfer) {
|
||||||
@@ -350,17 +379,35 @@ const dragStart = ({ dataTransfer }: DragEvent) => {
|
|||||||
// Trigger the re-ordering event when a collection is dragged over another collection's top section
|
// Trigger the re-ordering event when a collection is dragged over another collection's top section
|
||||||
const handleDragOver = (e: DragEvent) => {
|
const handleDragOver = (e: DragEvent) => {
|
||||||
dragging.value = true
|
dragging.value = true
|
||||||
if (e.offsetY < 10 && notSameDestination.value) {
|
if (
|
||||||
|
e.offsetY < 10 &&
|
||||||
|
notSameDestination.value &&
|
||||||
|
!isRequestDragging.value &&
|
||||||
|
isSameParent.value
|
||||||
|
) {
|
||||||
ordering.value = true
|
ordering.value = true
|
||||||
dragging.value = false
|
dragging.value = false
|
||||||
|
orderingLastItem.value = false
|
||||||
|
} else if (
|
||||||
|
e.offsetY > 18 &&
|
||||||
|
notSameDestination.value &&
|
||||||
|
!isRequestDragging.value &&
|
||||||
|
isSameParent.value
|
||||||
|
) {
|
||||||
|
orderingLastItem.value = true
|
||||||
|
dragging.value = false
|
||||||
|
ordering.value = false
|
||||||
} else {
|
} else {
|
||||||
ordering.value = false
|
ordering.value = false
|
||||||
|
orderingLastItem.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handelDrop = (e: DragEvent) => {
|
const handelDrop = (e: DragEvent) => {
|
||||||
if (ordering.value) {
|
if (ordering.value) {
|
||||||
orderUpdateCollectionEvent(e)
|
orderUpdateCollectionEvent(e)
|
||||||
|
} else if (orderingLastItem.value) {
|
||||||
|
updateLastItemOrder(e)
|
||||||
} else {
|
} else {
|
||||||
dropEvent(e)
|
dropEvent(e)
|
||||||
}
|
}
|
||||||
@@ -382,6 +429,14 @@ const orderUpdateCollectionEvent = (e: DragEvent) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateLastItemOrder = (e: DragEvent) => {
|
||||||
|
if (e.dataTransfer) {
|
||||||
|
e.stopPropagation()
|
||||||
|
emit("update-last-collection-order", e.dataTransfer)
|
||||||
|
resetDragState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const notSameDestination = computed(() => {
|
const notSameDestination = computed(() => {
|
||||||
return dropItemID.value !== props.id
|
return dropItemID.value !== props.id
|
||||||
})
|
})
|
||||||
@@ -397,5 +452,6 @@ const isCollLoading = computed(() => {
|
|||||||
const resetDragState = () => {
|
const resetDragState = () => {
|
||||||
dragging.value = false
|
dragging.value = false
|
||||||
ordering.value = false
|
ordering.value = false
|
||||||
|
orderingLastItem.value = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
:data="node.data.data.data"
|
:data="node.data.data.data"
|
||||||
:collections-type="collectionsType.type"
|
:collections-type="collectionsType.type"
|
||||||
:is-open="isOpen"
|
:is-open="isOpen"
|
||||||
|
:is-last-item="node.data.isLastItem"
|
||||||
:is-selected="
|
:is-selected="
|
||||||
isSelected({
|
isSelected({
|
||||||
collectionIndex: parseInt(node.id),
|
collectionIndex: parseInt(node.id),
|
||||||
@@ -77,7 +78,18 @@
|
|||||||
@remove-collection="emit('remove-collection', node.id)"
|
@remove-collection="emit('remove-collection', node.id)"
|
||||||
@drop-event="dropEvent($event, node.id)"
|
@drop-event="dropEvent($event, node.id)"
|
||||||
@drag-event="dragEvent($event, node.id)"
|
@drag-event="dragEvent($event, node.id)"
|
||||||
@update-collection-order="updateCollectionOrder($event, node.id)"
|
@update-collection-order="
|
||||||
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: node.id,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
@update-last-collection-order="
|
||||||
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: null,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
|
"
|
||||||
@dragging="
|
@dragging="
|
||||||
(isDraging) => highlightChildren(isDraging ? node.id : null)
|
(isDraging) => highlightChildren(isDraging ? node.id : null)
|
||||||
"
|
"
|
||||||
@@ -99,6 +111,7 @@
|
|||||||
:data="node.data.data.data"
|
:data="node.data.data.data"
|
||||||
:collections-type="collectionsType.type"
|
:collections-type="collectionsType.type"
|
||||||
:is-open="isOpen"
|
:is-open="isOpen"
|
||||||
|
:is-last-item="node.data.isLastItem"
|
||||||
:is-selected="
|
:is-selected="
|
||||||
isSelected({
|
isSelected({
|
||||||
folderPath: node.id,
|
folderPath: node.id,
|
||||||
@@ -133,7 +146,18 @@
|
|||||||
@remove-collection="emit('remove-folder', node.id)"
|
@remove-collection="emit('remove-folder', node.id)"
|
||||||
@drop-event="dropEvent($event, node.id)"
|
@drop-event="dropEvent($event, node.id)"
|
||||||
@drag-event="dragEvent($event, node.id)"
|
@drag-event="dragEvent($event, node.id)"
|
||||||
@update-collection-order="updateCollectionOrder($event, node.id)"
|
@update-collection-order="
|
||||||
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: node.id,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
@update-last-collection-order="
|
||||||
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: null,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
|
"
|
||||||
@dragging="
|
@dragging="
|
||||||
(isDraging) => highlightChildren(isDraging ? node.id : null)
|
(isDraging) => highlightChildren(isDraging ? node.id : null)
|
||||||
"
|
"
|
||||||
@@ -155,6 +179,7 @@
|
|||||||
:parent-i-d="node.data.data.parentIndex"
|
:parent-i-d="node.data.data.parentIndex"
|
||||||
:collections-type="collectionsType.type"
|
:collections-type="collectionsType.type"
|
||||||
:save-request="saveRequest"
|
:save-request="saveRequest"
|
||||||
|
:is-last-item="node.data.isLastItem"
|
||||||
:is-active="
|
:is-active="
|
||||||
isActiveRequest(
|
isActiveRequest(
|
||||||
node.data.data.parentIndex,
|
node.data.data.parentIndex,
|
||||||
@@ -209,6 +234,12 @@
|
|||||||
requestIndex: node.id,
|
requestIndex: node.id,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
|
@update-last-request-order="
|
||||||
|
updateRequestOrder($event, {
|
||||||
|
folderPath: node.data.data.parentIndex,
|
||||||
|
requestIndex: null,
|
||||||
|
})
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #emptyNode="{ node }">
|
<template #emptyNode="{ node }">
|
||||||
@@ -305,6 +336,7 @@ import { currentActiveTab } from "~/helpers/rest/tab"
|
|||||||
|
|
||||||
export type Collection = {
|
export type Collection = {
|
||||||
type: "collections"
|
type: "collections"
|
||||||
|
isLastItem: boolean
|
||||||
data: {
|
data: {
|
||||||
parentIndex: null
|
parentIndex: null
|
||||||
data: HoppCollection<HoppRESTRequest>
|
data: HoppCollection<HoppRESTRequest>
|
||||||
@@ -313,6 +345,7 @@ export type Collection = {
|
|||||||
|
|
||||||
type Folder = {
|
type Folder = {
|
||||||
type: "folders"
|
type: "folders"
|
||||||
|
isLastItem: boolean
|
||||||
data: {
|
data: {
|
||||||
parentIndex: string
|
parentIndex: string
|
||||||
data: HoppCollection<HoppRESTRequest>
|
data: HoppCollection<HoppRESTRequest>
|
||||||
@@ -321,6 +354,7 @@ type Folder = {
|
|||||||
|
|
||||||
type Requests = {
|
type Requests = {
|
||||||
type: "requests"
|
type: "requests"
|
||||||
|
isLastItem: boolean
|
||||||
data: {
|
data: {
|
||||||
parentIndex: string
|
parentIndex: string
|
||||||
data: HoppRESTRequest
|
data: HoppRESTRequest
|
||||||
@@ -450,7 +484,7 @@ const emit = defineEmits<{
|
|||||||
event: "update-request-order",
|
event: "update-request-order",
|
||||||
payload: {
|
payload: {
|
||||||
dragedRequestIndex: string
|
dragedRequestIndex: string
|
||||||
destinationRequestIndex: string
|
destinationRequestIndex: string | null
|
||||||
destinationCollectionIndex: string
|
destinationCollectionIndex: string
|
||||||
}
|
}
|
||||||
): void
|
): void
|
||||||
@@ -458,7 +492,10 @@ const emit = defineEmits<{
|
|||||||
event: "update-collection-order",
|
event: "update-collection-order",
|
||||||
payload: {
|
payload: {
|
||||||
dragedCollectionIndex: string
|
dragedCollectionIndex: string
|
||||||
destinationCollectionIndex: string
|
destinationCollection: {
|
||||||
|
destinationCollectionIndex: string | null
|
||||||
|
destinationCollectionParentIndex: string | null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
): void
|
): void
|
||||||
(event: "select", payload: Picked | null): void
|
(event: "select", payload: Picked | null): void
|
||||||
@@ -589,7 +626,7 @@ const updateRequestOrder = (
|
|||||||
{
|
{
|
||||||
folderPath,
|
folderPath,
|
||||||
requestIndex,
|
requestIndex,
|
||||||
}: { folderPath: string | null; requestIndex: string }
|
}: { folderPath: string | null; requestIndex: string | null }
|
||||||
) => {
|
) => {
|
||||||
if (!folderPath) return
|
if (!folderPath) return
|
||||||
const dragedRequestIndex = dataTransfer.getData("requestIndex")
|
const dragedRequestIndex = dataTransfer.getData("requestIndex")
|
||||||
@@ -605,13 +642,16 @@ const updateRequestOrder = (
|
|||||||
|
|
||||||
const updateCollectionOrder = (
|
const updateCollectionOrder = (
|
||||||
dataTransfer: DataTransfer,
|
dataTransfer: DataTransfer,
|
||||||
destinationCollectionIndex: string
|
destinationCollection: {
|
||||||
|
destinationCollectionIndex: string | null
|
||||||
|
destinationCollectionParentIndex: string | null
|
||||||
|
}
|
||||||
) => {
|
) => {
|
||||||
const dragedCollectionIndex = dataTransfer.getData("collectionIndex")
|
const dragedCollectionIndex = dataTransfer.getData("collectionIndex")
|
||||||
|
|
||||||
emit("update-collection-order", {
|
emit("update-collection-order", {
|
||||||
dragedCollectionIndex,
|
dragedCollectionIndex,
|
||||||
destinationCollectionIndex,
|
destinationCollection,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,6 +681,7 @@ class MyCollectionsAdapter implements SmartTreeAdapter<MyCollectionNode> {
|
|||||||
id: index.toString(),
|
id: index.toString(),
|
||||||
data: {
|
data: {
|
||||||
type: "collections",
|
type: "collections",
|
||||||
|
isLastItem: index === this.data.value.length - 1,
|
||||||
data: {
|
data: {
|
||||||
parentIndex: null,
|
parentIndex: null,
|
||||||
data: item,
|
data: item,
|
||||||
@@ -662,23 +703,25 @@ class MyCollectionsAdapter implements SmartTreeAdapter<MyCollectionNode> {
|
|||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
const data = [
|
const data = [
|
||||||
...item.folders.map((item, index) => ({
|
...item.folders.map((folder, index) => ({
|
||||||
id: `${id}/${index}`,
|
id: `${id}/${index}`,
|
||||||
data: {
|
data: {
|
||||||
|
isLastItem: index === item.folders.length - 1,
|
||||||
type: "folders",
|
type: "folders",
|
||||||
data: {
|
data: {
|
||||||
parentIndex: id,
|
parentIndex: id,
|
||||||
data: item,
|
data: folder,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
...item.requests.map((item, index) => ({
|
...item.requests.map((requests, index) => ({
|
||||||
id: `${id}/${index}`,
|
id: `${id}/${index}`,
|
||||||
data: {
|
data: {
|
||||||
|
isLastItem: index === item.requests.length - 1,
|
||||||
type: "requests",
|
type: "requests",
|
||||||
data: {
|
data: {
|
||||||
parentIndex: id,
|
parentIndex: id,
|
||||||
data: item,
|
data: requests,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div
|
<div
|
||||||
class="h-1"
|
class="h-1 w-full transition"
|
||||||
:class="[
|
:class="[
|
||||||
{
|
{
|
||||||
'bg-accentDark': isReorderable,
|
'bg-accentDark': isReorderable,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
@drop="dropEvent"
|
@drop="updateRequestOrder"
|
||||||
@dragover.prevent="ordering = true"
|
@dragover.prevent="ordering = true"
|
||||||
@dragleave="resetDragState"
|
@dragleave="resetDragState"
|
||||||
@dragend="resetDragState"
|
@dragend="resetDragState"
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<div
|
<div
|
||||||
class="flex items-stretch group"
|
class="flex items-stretch group"
|
||||||
:draggable="!hasNoTeamAccess"
|
:draggable="!hasNoTeamAccess"
|
||||||
@drop="dropEvent"
|
@drop="handelDrop"
|
||||||
@dragstart="dragStart"
|
@dragstart="dragStart"
|
||||||
@dragover="handleDragOver($event)"
|
@dragover="handleDragOver($event)"
|
||||||
@dragleave="resetDragState"
|
@dragleave="resetDragState"
|
||||||
@@ -138,6 +138,19 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="w-full transition"
|
||||||
|
:class="[
|
||||||
|
{
|
||||||
|
'bg-accentDark': isLastItemReorderable,
|
||||||
|
'h-1 ': isLastItem,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
@drop="handelDrop"
|
||||||
|
@dragover.prevent="orderingLastItem = true"
|
||||||
|
@dragleave="resetDragState"
|
||||||
|
@dragend="resetDragState"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -214,6 +227,11 @@ const props = defineProps({
|
|||||||
default: () => [],
|
default: () => [],
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
isLastItem: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -223,6 +241,7 @@ const emit = defineEmits<{
|
|||||||
(event: "select-request"): void
|
(event: "select-request"): void
|
||||||
(event: "drag-request", payload: DataTransfer): void
|
(event: "drag-request", payload: DataTransfer): void
|
||||||
(event: "update-request-order", payload: DataTransfer): void
|
(event: "update-request-order", payload: DataTransfer): void
|
||||||
|
(event: "update-last-request-order", payload: DataTransfer): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
@@ -233,6 +252,7 @@ const duplicate = ref<HTMLButtonElement | null>(null)
|
|||||||
|
|
||||||
const dragging = ref(false)
|
const dragging = ref(false)
|
||||||
const ordering = ref(false)
|
const ordering = ref(false)
|
||||||
|
const orderingLastItem = ref(false)
|
||||||
|
|
||||||
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
||||||
type: "collection",
|
type: "collection",
|
||||||
@@ -269,6 +289,10 @@ const dragStart = ({ dataTransfer }: DragEvent) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSameRequest = computed(() => {
|
||||||
|
return currentReorderingStatus.value.id === props.requestID
|
||||||
|
})
|
||||||
|
|
||||||
const isCollectionDragging = computed(() => {
|
const isCollectionDragging = computed(() => {
|
||||||
return currentReorderingStatus.value.type === "collection"
|
return currentReorderingStatus.value.type === "collection"
|
||||||
})
|
})
|
||||||
@@ -278,7 +302,18 @@ const isSameParent = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const isReorderable = computed(() => {
|
const isReorderable = computed(() => {
|
||||||
return ordering.value && !isCollectionDragging.value && isSameParent.value
|
return (
|
||||||
|
ordering.value &&
|
||||||
|
!isCollectionDragging.value &&
|
||||||
|
isSameParent.value &&
|
||||||
|
!isSameRequest.value
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const isLastItemReorderable = computed(() => {
|
||||||
|
return (
|
||||||
|
orderingLastItem.value && isSameParent.value && !isCollectionDragging.value
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Trigger the re-ordering event when a request is dragged over another request's top section
|
// Trigger the re-ordering event when a request is dragged over another request's top section
|
||||||
@@ -287,12 +322,28 @@ const handleDragOver = (e: DragEvent) => {
|
|||||||
if (e.offsetY < 10) {
|
if (e.offsetY < 10) {
|
||||||
ordering.value = true
|
ordering.value = true
|
||||||
dragging.value = false
|
dragging.value = false
|
||||||
|
orderingLastItem.value = false
|
||||||
|
} else if (e.offsetY > 18) {
|
||||||
|
orderingLastItem.value = true
|
||||||
|
dragging.value = false
|
||||||
|
ordering.value = false
|
||||||
} else {
|
} else {
|
||||||
ordering.value = false
|
ordering.value = false
|
||||||
|
orderingLastItem.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dropEvent = (e: DragEvent) => {
|
const handelDrop = (e: DragEvent) => {
|
||||||
|
if (ordering.value) {
|
||||||
|
updateRequestOrder(e)
|
||||||
|
} else if (orderingLastItem.value) {
|
||||||
|
updateLastItemOrder(e)
|
||||||
|
} else {
|
||||||
|
updateRequestOrder(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateRequestOrder = (e: DragEvent) => {
|
||||||
if (e.dataTransfer) {
|
if (e.dataTransfer) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
resetDragState()
|
resetDragState()
|
||||||
@@ -300,6 +351,14 @@ const dropEvent = (e: DragEvent) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateLastItemOrder = (e: DragEvent) => {
|
||||||
|
if (e.dataTransfer) {
|
||||||
|
e.stopPropagation()
|
||||||
|
resetDragState()
|
||||||
|
emit("update-last-request-order", e.dataTransfer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isRequestLoading = computed(() => {
|
const isRequestLoading = computed(() => {
|
||||||
if (props.requestMoveLoading.length > 0 && props.requestID) {
|
if (props.requestMoveLoading.length > 0 && props.requestID) {
|
||||||
return props.requestMoveLoading.includes(props.requestID)
|
return props.requestMoveLoading.includes(props.requestID)
|
||||||
@@ -311,5 +370,6 @@ const isRequestLoading = computed(() => {
|
|||||||
const resetDragState = () => {
|
const resetDragState = () => {
|
||||||
dragging.value = false
|
dragging.value = false
|
||||||
ordering.value = false
|
ordering.value = false
|
||||||
|
orderingLastItem.value = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
:export-loading="exportLoading"
|
:export-loading="exportLoading"
|
||||||
:has-no-team-access="hasNoTeamAccess"
|
:has-no-team-access="hasNoTeamAccess"
|
||||||
:collection-move-loading="collectionMoveLoading"
|
:collection-move-loading="collectionMoveLoading"
|
||||||
|
:is-last-item="node.data.isLastItem"
|
||||||
:is-selected="
|
:is-selected="
|
||||||
isSelected({
|
isSelected({
|
||||||
collectionID: node.id,
|
collectionID: node.id,
|
||||||
@@ -95,7 +96,16 @@
|
|||||||
@drop-event="dropEvent($event, node.id)"
|
@drop-event="dropEvent($event, node.id)"
|
||||||
@drag-event="dragEvent($event, node.id)"
|
@drag-event="dragEvent($event, node.id)"
|
||||||
@update-collection-order="
|
@update-collection-order="
|
||||||
updateCollectionOrder($event, node.data.data.data.id)
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: node.data.data.data.id,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
@update-last-collection-order="
|
||||||
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: null,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
"
|
"
|
||||||
@dragging="
|
@dragging="
|
||||||
(isDraging) =>
|
(isDraging) =>
|
||||||
@@ -122,6 +132,7 @@
|
|||||||
:export-loading="exportLoading"
|
:export-loading="exportLoading"
|
||||||
:has-no-team-access="hasNoTeamAccess"
|
:has-no-team-access="hasNoTeamAccess"
|
||||||
:collection-move-loading="collectionMoveLoading"
|
:collection-move-loading="collectionMoveLoading"
|
||||||
|
:is-last-item="node.data.isLastItem"
|
||||||
:is-selected="
|
:is-selected="
|
||||||
isSelected({
|
isSelected({
|
||||||
folderID: node.data.data.data.id,
|
folderID: node.data.data.data.id,
|
||||||
@@ -159,7 +170,16 @@
|
|||||||
@drop-event="dropEvent($event, node.data.data.data.id)"
|
@drop-event="dropEvent($event, node.data.data.data.id)"
|
||||||
@drag-event="dragEvent($event, node.data.data.data.id)"
|
@drag-event="dragEvent($event, node.data.data.data.id)"
|
||||||
@update-collection-order="
|
@update-collection-order="
|
||||||
updateCollectionOrder($event, node.data.data.data.id)
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: node.data.data.data.id,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
@update-last-collection-order="
|
||||||
|
updateCollectionOrder($event, {
|
||||||
|
destinationCollectionIndex: null,
|
||||||
|
destinationCollectionParentIndex: node.data.data.parentIndex,
|
||||||
|
})
|
||||||
"
|
"
|
||||||
@dragging="
|
@dragging="
|
||||||
(isDraging) =>
|
(isDraging) =>
|
||||||
@@ -186,6 +206,7 @@
|
|||||||
:is-active="isActiveRequest(node.data.data.data.id)"
|
:is-active="isActiveRequest(node.data.data.data.id)"
|
||||||
:has-no-team-access="hasNoTeamAccess"
|
:has-no-team-access="hasNoTeamAccess"
|
||||||
:request-move-loading="requestMoveLoading"
|
:request-move-loading="requestMoveLoading"
|
||||||
|
:is-last-item="node.data.isLastItem"
|
||||||
:is-selected="
|
:is-selected="
|
||||||
isSelected({
|
isSelected({
|
||||||
requestID: node.data.data.data.id,
|
requestID: node.data.data.data.id,
|
||||||
@@ -231,6 +252,12 @@
|
|||||||
requestIndex: node.data.data.data.id,
|
requestIndex: node.data.data.data.id,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
|
@update-last-request-order="
|
||||||
|
updateRequestOrder($event, {
|
||||||
|
folderPath: node.data.data.parentIndex,
|
||||||
|
requestIndex: null,
|
||||||
|
})
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #emptyNode="{ node }">
|
<template #emptyNode="{ node }">
|
||||||
@@ -461,7 +488,7 @@ const emit = defineEmits<{
|
|||||||
event: "update-request-order",
|
event: "update-request-order",
|
||||||
payload: {
|
payload: {
|
||||||
dragedRequestIndex: string
|
dragedRequestIndex: string
|
||||||
destinationRequestIndex: string
|
destinationRequestIndex: string | null
|
||||||
destinationCollectionIndex: string
|
destinationCollectionIndex: string
|
||||||
}
|
}
|
||||||
): void
|
): void
|
||||||
@@ -469,7 +496,10 @@ const emit = defineEmits<{
|
|||||||
event: "update-collection-order",
|
event: "update-collection-order",
|
||||||
payload: {
|
payload: {
|
||||||
dragedCollectionIndex: string
|
dragedCollectionIndex: string
|
||||||
destinationCollectionIndex: string
|
destinationCollection: {
|
||||||
|
destinationCollectionIndex: string | null
|
||||||
|
destinationCollectionParentIndex: string | null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
): void
|
): void
|
||||||
(event: "select", payload: Picked | null): void
|
(event: "select", payload: Picked | null): void
|
||||||
@@ -597,7 +627,7 @@ const updateRequestOrder = (
|
|||||||
{
|
{
|
||||||
folderPath,
|
folderPath,
|
||||||
requestIndex,
|
requestIndex,
|
||||||
}: { folderPath: string | null; requestIndex: string }
|
}: { folderPath: string | null; requestIndex: string | null }
|
||||||
) => {
|
) => {
|
||||||
if (!folderPath) return
|
if (!folderPath) return
|
||||||
const dragedRequestIndex = dataTransfer.getData("requestIndex")
|
const dragedRequestIndex = dataTransfer.getData("requestIndex")
|
||||||
@@ -613,17 +643,21 @@ const updateRequestOrder = (
|
|||||||
|
|
||||||
const updateCollectionOrder = (
|
const updateCollectionOrder = (
|
||||||
dataTransfer: DataTransfer,
|
dataTransfer: DataTransfer,
|
||||||
destinationCollectionIndex: string
|
destinationCollection: {
|
||||||
|
destinationCollectionIndex: string | null
|
||||||
|
destinationCollectionParentIndex: string | null
|
||||||
|
}
|
||||||
) => {
|
) => {
|
||||||
const dragedCollectionIndex = dataTransfer.getData("collectionIndex")
|
const dragedCollectionIndex = dataTransfer.getData("collectionIndex")
|
||||||
|
|
||||||
emit("update-collection-order", {
|
emit("update-collection-order", {
|
||||||
dragedCollectionIndex,
|
dragedCollectionIndex,
|
||||||
destinationCollectionIndex,
|
destinationCollection,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type TeamCollections = {
|
type TeamCollections = {
|
||||||
|
isLastItem: boolean
|
||||||
type: "collections"
|
type: "collections"
|
||||||
data: {
|
data: {
|
||||||
parentIndex: null
|
parentIndex: null
|
||||||
@@ -632,6 +666,7 @@ type TeamCollections = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TeamFolder = {
|
type TeamFolder = {
|
||||||
|
isLastItem: boolean
|
||||||
type: "folders"
|
type: "folders"
|
||||||
data: {
|
data: {
|
||||||
parentIndex: string
|
parentIndex: string
|
||||||
@@ -640,6 +675,7 @@ type TeamFolder = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TeamRequests = {
|
type TeamRequests = {
|
||||||
|
isLastItem: boolean
|
||||||
type: "requests"
|
type: "requests"
|
||||||
data: {
|
data: {
|
||||||
parentIndex: string
|
parentIndex: string
|
||||||
@@ -679,9 +715,10 @@ class TeamCollectionsAdapter implements SmartTreeAdapter<TeamCollectionNode> {
|
|||||||
status: "loading",
|
status: "loading",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const data = this.data.value.map((item) => ({
|
const data = this.data.value.map((item, index) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
data: {
|
data: {
|
||||||
|
isLastItem: index === this.data.value.length - 1,
|
||||||
type: "collections",
|
type: "collections",
|
||||||
data: {
|
data: {
|
||||||
parentIndex: null,
|
parentIndex: null,
|
||||||
@@ -709,9 +746,10 @@ class TeamCollectionsAdapter implements SmartTreeAdapter<TeamCollectionNode> {
|
|||||||
if (items) {
|
if (items) {
|
||||||
const data = [
|
const data = [
|
||||||
...(items.children
|
...(items.children
|
||||||
? items.children.map((item) => ({
|
? items.children.map((item, index) => ({
|
||||||
id: `${id}/${item.id}`,
|
id: `${id}/${item.id}`,
|
||||||
data: {
|
data: {
|
||||||
|
isLastItem: index === items.children.length - 1,
|
||||||
type: "folders",
|
type: "folders",
|
||||||
data: {
|
data: {
|
||||||
parentIndex: parsedID,
|
parentIndex: parsedID,
|
||||||
@@ -721,9 +759,10 @@ class TeamCollectionsAdapter implements SmartTreeAdapter<TeamCollectionNode> {
|
|||||||
}))
|
}))
|
||||||
: []),
|
: []),
|
||||||
...(items.requests
|
...(items.requests
|
||||||
? items.requests.map((item) => ({
|
? items.requests.map((item, index) => ({
|
||||||
id: `${id}/${item.id}`,
|
id: `${id}/${item.id}`,
|
||||||
data: {
|
data: {
|
||||||
|
isLastItem: index === items.requests.length - 1,
|
||||||
type: "requests",
|
type: "requests",
|
||||||
data: {
|
data: {
|
||||||
parentIndex: parsedID,
|
parentIndex: parsedID,
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<div
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
'rounded border border-divider': saveRequest,
|
'rounded border border-divider': saveRequest,
|
||||||
'bg-primaryDark': draggingToRoot,
|
'bg-primaryDark':
|
||||||
|
draggingToRoot && currentReorderingStatus.type !== 'request',
|
||||||
}"
|
}"
|
||||||
class="flex-1"
|
class="flex-1"
|
||||||
@drop.prevent="dropToRoot"
|
@drop.prevent="dropToRoot"
|
||||||
@@ -85,7 +86,9 @@
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="hidden bg-primaryDark flex-col flex-1 items-center py-15 justify-center px-4 text-secondaryLight"
|
class="hidden bg-primaryDark flex-col flex-1 items-center py-15 justify-center px-4 text-secondaryLight"
|
||||||
:class="{ '!flex': draggingToRoot }"
|
:class="{
|
||||||
|
'!flex': draggingToRoot && currentReorderingStatus.type !== 'request',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<component :is="IconListEnd" class="svg-icons !w-8 !h-8" />
|
<component :is="IconListEnd" class="svg-icons !w-8 !h-8" />
|
||||||
</div>
|
</div>
|
||||||
@@ -232,6 +235,7 @@ import {
|
|||||||
resolveSaveContextOnCollectionReorder,
|
resolveSaveContextOnCollectionReorder,
|
||||||
updateSaveContextForAffectedRequests,
|
updateSaveContextForAffectedRequests,
|
||||||
} from "~/helpers/collection/collection"
|
} from "~/helpers/collection/collection"
|
||||||
|
import { currentReorderingStatus$ } from "~/newstore/reordering"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -396,6 +400,12 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
||||||
|
type: "collection",
|
||||||
|
id: "",
|
||||||
|
parentID: "",
|
||||||
|
})
|
||||||
|
|
||||||
const hasTeamWriteAccess = computed(() => {
|
const hasTeamWriteAccess = computed(() => {
|
||||||
if (!collectionsType.value.selectedTeam) return false
|
if (!collectionsType.value.selectedTeam) return false
|
||||||
|
|
||||||
@@ -1525,13 +1535,34 @@ const dropToRoot = ({ dataTransfer }: DragEvent) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to check if the request/collection is being moved to the same parent since reorder is only allowed within the same parent
|
* Used to check if the request/collection is being moved to the same parent since reorder is only allowed within the same parent
|
||||||
* @param draggedReq - path index of the dragged request
|
* @param draggedItem - path index of the dragged request
|
||||||
* @param destinationReq - path index of the destination request
|
* @param destinationItem - path index of the destination request
|
||||||
|
* @param destinationCollectionIndex - index of the destination collection
|
||||||
* @returns boolean - true if the request is being moved to the same parent
|
* @returns boolean - true if the request is being moved to the same parent
|
||||||
*/
|
*/
|
||||||
const isSameSameParent = (draggedItem: string, destinationItem: string) => {
|
const isSameSameParent = (
|
||||||
const draggedItemIndex = pathToIndex(draggedItem)
|
draggedItemPath: string,
|
||||||
const destinationItemIndex = pathToIndex(destinationItem)
|
destinationItemPath: string | null,
|
||||||
|
destinationCollectionIndex: string | null
|
||||||
|
) => {
|
||||||
|
const draggedItemIndex = pathToIndex(draggedItemPath)
|
||||||
|
|
||||||
|
// if the destinationItemPath and destinationCollectionIndex is null, it means the request is being moved to the root
|
||||||
|
if (destinationItemPath === null && destinationCollectionIndex === null) {
|
||||||
|
return draggedItemIndex.length === 1
|
||||||
|
} else if (
|
||||||
|
destinationItemPath === null &&
|
||||||
|
destinationCollectionIndex !== null &&
|
||||||
|
draggedItemIndex.length === 1
|
||||||
|
) {
|
||||||
|
return draggedItemIndex[0] === destinationCollectionIndex
|
||||||
|
} else if (destinationItemPath === null && draggedItemIndex.length !== 1) {
|
||||||
|
const dragedItemParent = draggedItemIndex.slice(0, -1)
|
||||||
|
|
||||||
|
return dragedItemParent[0] === destinationCollectionIndex
|
||||||
|
} else {
|
||||||
|
if (destinationItemPath === null) return false
|
||||||
|
const destinationItemIndex = pathToIndex(destinationItemPath)
|
||||||
|
|
||||||
// length of 1 means the request is in the root
|
// length of 1 means the request is in the root
|
||||||
if (draggedItemIndex.length === 1 && destinationItemIndex.length === 1) {
|
if (draggedItemIndex.length === 1 && destinationItemIndex.length === 1) {
|
||||||
@@ -1547,6 +1578,7 @@ const isSameSameParent = (draggedItem: string, destinationItem: string) => {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1556,7 +1588,7 @@ const isSameSameParent = (draggedItem: string, destinationItem: string) => {
|
|||||||
*/
|
*/
|
||||||
const updateRequestOrder = (payload: {
|
const updateRequestOrder = (payload: {
|
||||||
dragedRequestIndex: string
|
dragedRequestIndex: string
|
||||||
destinationRequestIndex: string
|
destinationRequestIndex: string | null
|
||||||
destinationCollectionIndex: string
|
destinationCollectionIndex: string
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
@@ -1565,29 +1597,28 @@ const updateRequestOrder = (payload: {
|
|||||||
destinationCollectionIndex,
|
destinationCollectionIndex,
|
||||||
} = payload
|
} = payload
|
||||||
|
|
||||||
if (
|
if (!dragedRequestIndex || !destinationCollectionIndex) return
|
||||||
!dragedRequestIndex ||
|
|
||||||
!destinationRequestIndex ||
|
|
||||||
!destinationCollectionIndex
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
if (dragedRequestIndex === destinationRequestIndex) return
|
if (dragedRequestIndex === destinationRequestIndex) return
|
||||||
|
|
||||||
if (collectionsType.value.type === "my-collections") {
|
if (collectionsType.value.type === "my-collections") {
|
||||||
if (!isSameSameParent(dragedRequestIndex, destinationRequestIndex)) {
|
if (
|
||||||
|
!isSameSameParent(
|
||||||
|
dragedRequestIndex,
|
||||||
|
destinationRequestIndex,
|
||||||
|
destinationCollectionIndex
|
||||||
|
)
|
||||||
|
) {
|
||||||
toast.error(`${t("collection.different_parent")}`)
|
toast.error(`${t("collection.different_parent")}`)
|
||||||
} else {
|
} else {
|
||||||
updateRESTRequestOrder(
|
updateRESTRequestOrder(
|
||||||
pathToLastIndex(dragedRequestIndex),
|
pathToLastIndex(dragedRequestIndex),
|
||||||
pathToLastIndex(destinationRequestIndex),
|
destinationRequestIndex
|
||||||
|
? pathToLastIndex(destinationRequestIndex)
|
||||||
|
: null,
|
||||||
destinationCollectionIndex
|
destinationCollectionIndex
|
||||||
)
|
)
|
||||||
resolveSaveContextOnRequestReorder({
|
|
||||||
lastIndex: pathToLastIndex(dragedRequestIndex),
|
|
||||||
newIndex: pathToLastIndex(destinationRequestIndex),
|
|
||||||
folderPath: destinationCollectionIndex,
|
|
||||||
})
|
|
||||||
toast.success(`${t("request.order_changed")}`)
|
toast.success(`${t("request.order_changed")}`)
|
||||||
}
|
}
|
||||||
} else if (hasTeamWriteAccess.value) {
|
} else if (hasTeamWriteAccess.value) {
|
||||||
@@ -1628,14 +1659,25 @@ const updateRequestOrder = (payload: {
|
|||||||
*/
|
*/
|
||||||
const updateCollectionOrder = (payload: {
|
const updateCollectionOrder = (payload: {
|
||||||
dragedCollectionIndex: string
|
dragedCollectionIndex: string
|
||||||
destinationCollectionIndex: string
|
destinationCollection: {
|
||||||
|
destinationCollectionIndex: string | null
|
||||||
|
destinationCollectionParentIndex: string | null
|
||||||
|
}
|
||||||
}) => {
|
}) => {
|
||||||
const { dragedCollectionIndex, destinationCollectionIndex } = payload
|
const { dragedCollectionIndex, destinationCollection } = payload
|
||||||
if (!dragedCollectionIndex || !destinationCollectionIndex) return
|
const { destinationCollectionIndex, destinationCollectionParentIndex } =
|
||||||
|
destinationCollection
|
||||||
|
if (!dragedCollectionIndex) return
|
||||||
if (dragedCollectionIndex === destinationCollectionIndex) return
|
if (dragedCollectionIndex === destinationCollectionIndex) return
|
||||||
|
|
||||||
if (collectionsType.value.type === "my-collections") {
|
if (collectionsType.value.type === "my-collections") {
|
||||||
if (!isSameSameParent(dragedCollectionIndex, destinationCollectionIndex)) {
|
if (
|
||||||
|
!isSameSameParent(
|
||||||
|
dragedCollectionIndex,
|
||||||
|
destinationCollectionIndex,
|
||||||
|
destinationCollectionParentIndex
|
||||||
|
)
|
||||||
|
) {
|
||||||
toast.error(`${t("collection.different_parent")}`)
|
toast.error(`${t("collection.different_parent")}`)
|
||||||
} else {
|
} else {
|
||||||
updateRESTCollectionOrder(
|
updateRESTCollectionOrder(
|
||||||
@@ -1644,7 +1686,9 @@ const updateCollectionOrder = (payload: {
|
|||||||
)
|
)
|
||||||
resolveSaveContextOnCollectionReorder({
|
resolveSaveContextOnCollectionReorder({
|
||||||
lastIndex: pathToLastIndex(dragedCollectionIndex),
|
lastIndex: pathToLastIndex(dragedCollectionIndex),
|
||||||
newIndex: pathToLastIndex(destinationCollectionIndex),
|
newIndex: pathToLastIndex(
|
||||||
|
destinationCollectionIndex ? destinationCollectionIndex : ""
|
||||||
|
),
|
||||||
folderPath: dragedCollectionIndex.split("/").slice(0, -1).join("/"),
|
folderPath: dragedCollectionIndex.split("/").slice(0, -1).join("/"),
|
||||||
})
|
})
|
||||||
toast.success(`${t("collection.order_changed")}`)
|
toast.success(`${t("collection.order_changed")}`)
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
mutation UpdateCollectionOrder($collectionID: ID!, $destCollID: ID!) {
|
mutation UpdateCollectionOrder($collectionID: ID!, $destCollID: ID) {
|
||||||
updateCollectionOrder(collectionID: $collectionID, destCollID: $destCollID)
|
updateCollectionOrder(collectionID: $collectionID, destCollID: $destCollID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const moveRESTTeamCollection = (
|
|||||||
|
|
||||||
export const updateOrderRESTTeamCollection = (
|
export const updateOrderRESTTeamCollection = (
|
||||||
collectionID: string,
|
collectionID: string,
|
||||||
destCollID: string
|
destCollID: string | null
|
||||||
) =>
|
) =>
|
||||||
runMutation<
|
runMutation<
|
||||||
UpdateCollectionOrderMutation,
|
UpdateCollectionOrderMutation,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export const moveRESTTeamRequest = (collectionID: string, requestID: string) =>
|
|||||||
|
|
||||||
export const updateOrderRESTTeamRequest = (
|
export const updateOrderRESTTeamRequest = (
|
||||||
requestID: string,
|
requestID: string,
|
||||||
nextRequestID: string,
|
nextRequestID: string | null,
|
||||||
collectionID: string
|
collectionID: string
|
||||||
) =>
|
) =>
|
||||||
runMutation<
|
runMutation<
|
||||||
|
|||||||
@@ -558,11 +558,30 @@ export default class NewTeamCollectionAdapter {
|
|||||||
|
|
||||||
public updateRequestOrder(
|
public updateRequestOrder(
|
||||||
dragedRequestID: string,
|
dragedRequestID: string,
|
||||||
destinationRequestID: string,
|
destinationRequestID: string | null,
|
||||||
destinationCollectionID: string
|
destinationCollectionID: string
|
||||||
) {
|
) {
|
||||||
const tree = this.collections$.value
|
const tree = this.collections$.value
|
||||||
|
|
||||||
|
// If the destination request is null, then it is the last request in the collection
|
||||||
|
if (destinationRequestID === null) {
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
// If the collection index is not found, don't update
|
||||||
|
if (requestIndex === -1) return
|
||||||
|
|
||||||
|
// Move the request to the end of the requests
|
||||||
|
collection.requests.push(collection.requests.splice(requestIndex, 1)[0])
|
||||||
|
} else {
|
||||||
// Find collection in tree, don't attempt if no collection is found
|
// Find collection in tree, don't attempt if no collection is found
|
||||||
const collection = findCollInTree(tree, destinationCollectionID)
|
const collection = findCollInTree(tree, destinationCollectionID)
|
||||||
if (!collection) return // Ignore order update
|
if (!collection) return // Ignore order update
|
||||||
@@ -580,16 +599,39 @@ export default class NewTeamCollectionAdapter {
|
|||||||
if (requestIndex === -1) return
|
if (requestIndex === -1) return
|
||||||
|
|
||||||
this.reorderItems(collection.requests, requestIndex, destinationIndex)
|
this.reorderItems(collection.requests, requestIndex, destinationIndex)
|
||||||
|
}
|
||||||
|
|
||||||
this.collections$.next(tree)
|
this.collections$.next(tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateCollectionOrder = (
|
public updateCollectionOrder = (
|
||||||
collectionID: string,
|
collectionID: string,
|
||||||
destinationCollectionID: string
|
destinationCollectionID: string | null
|
||||||
) => {
|
) => {
|
||||||
const tree = this.collections$.value
|
const tree = this.collections$.value
|
||||||
|
|
||||||
|
// If the destination collection is null, then it is the last collection in the tree
|
||||||
|
if (destinationCollectionID === null) {
|
||||||
|
const collLast = findParentOfColl(tree, collectionID)
|
||||||
|
if (collLast && collLast.children) {
|
||||||
|
const collectionIndex = collLast.children.findIndex(
|
||||||
|
(coll) => coll.id === collectionID
|
||||||
|
)
|
||||||
|
|
||||||
|
// reorder the collection to the end of the collections
|
||||||
|
collLast.children.push(collLast.children.splice(collectionIndex, 1)[0])
|
||||||
|
} else {
|
||||||
|
const collectionIndex = tree.findIndex(
|
||||||
|
(coll) => coll.id === collectionID
|
||||||
|
)
|
||||||
|
|
||||||
|
// If the collection index is not found, don't update
|
||||||
|
if (collectionIndex === -1) return
|
||||||
|
|
||||||
|
// reorder the collection to the end of the collections in the root
|
||||||
|
tree.push(tree.splice(collectionIndex, 1)[0])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Find collection in tree
|
// Find collection in tree
|
||||||
const coll = findParentOfColl(tree, destinationCollectionID)
|
const coll = findParentOfColl(tree, destinationCollectionID)
|
||||||
|
|
||||||
@@ -609,7 +651,9 @@ export default class NewTeamCollectionAdapter {
|
|||||||
this.reorderItems(coll.children, collectionIndex, destinationIndex)
|
this.reorderItems(coll.children, collectionIndex, destinationIndex)
|
||||||
} else {
|
} else {
|
||||||
// If the collection has no parent collection, it is a root collection
|
// If the collection has no parent collection, it is a root collection
|
||||||
const collectionIndex = tree.findIndex((coll) => coll.id === collectionID)
|
const collectionIndex = tree.findIndex(
|
||||||
|
(coll) => coll.id === collectionID
|
||||||
|
)
|
||||||
|
|
||||||
const destinationIndex = tree.findIndex(
|
const destinationIndex = tree.findIndex(
|
||||||
(coll) => coll.id === destinationCollectionID
|
(coll) => coll.id === destinationCollectionID
|
||||||
@@ -620,6 +664,7 @@ export default class NewTeamCollectionAdapter {
|
|||||||
|
|
||||||
this.reorderItems(tree, collectionIndex, destinationIndex)
|
this.reorderItems(tree, collectionIndex, destinationIndex)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.collections$.next(tree)
|
this.collections$.next(tree)
|
||||||
}
|
}
|
||||||
@@ -821,12 +866,10 @@ export default class NewTeamCollectionAdapter {
|
|||||||
const { request } = requestOrderUpdated
|
const { request } = requestOrderUpdated
|
||||||
const { nextRequest } = requestOrderUpdated
|
const { nextRequest } = requestOrderUpdated
|
||||||
|
|
||||||
if (!nextRequest) return
|
|
||||||
|
|
||||||
this.updateRequestOrder(
|
this.updateRequestOrder(
|
||||||
request.id,
|
request.id,
|
||||||
nextRequest.id,
|
nextRequest ? nextRequest.id : null,
|
||||||
nextRequest.collectionID
|
nextRequest ? nextRequest.collectionID : request.collectionID
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -851,9 +894,10 @@ export default class NewTeamCollectionAdapter {
|
|||||||
const { collection } = collectionOrderUpdated
|
const { collection } = collectionOrderUpdated
|
||||||
const { nextCollection } = collectionOrderUpdated
|
const { nextCollection } = collectionOrderUpdated
|
||||||
|
|
||||||
if (!nextCollection) return
|
this.updateCollectionOrder(
|
||||||
|
collection.id,
|
||||||
this.updateCollectionOrder(collection.id, nextCollection.id)
|
nextCollection ? nextCollection.id : null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||||
import { cloneDeep } from "lodash-es"
|
import { cloneDeep } from "lodash-es"
|
||||||
import { getTabRefWithSaveContext } from "~/helpers/rest/tab"
|
import { getTabRefWithSaveContext } from "~/helpers/rest/tab"
|
||||||
|
import { resolveSaveContextOnRequestReorder } from "~/helpers/collection/request"
|
||||||
|
|
||||||
const defaultRESTCollectionState = {
|
const defaultRESTCollectionState = {
|
||||||
state: [
|
state: [
|
||||||
@@ -288,18 +289,49 @@ const restCollectionDispatchers = defineDispatchers({
|
|||||||
destinationCollectionIndex,
|
destinationCollectionIndex,
|
||||||
}: {
|
}: {
|
||||||
collectionIndex: string
|
collectionIndex: string
|
||||||
destinationCollectionIndex: string
|
destinationCollectionIndex: string | null
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const newState = state
|
const newState = state
|
||||||
|
|
||||||
const indexPaths = collectionIndex.split("/").map((x) => parseInt(x))
|
const indexPaths = collectionIndex.split("/").map((x) => parseInt(x))
|
||||||
|
|
||||||
|
if (indexPaths.length === 0) {
|
||||||
|
console.log("Given path too short. Skipping request.")
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reordering the collection to the last position
|
||||||
|
if (destinationCollectionIndex === null) {
|
||||||
|
const folderIndex = indexPaths.pop() as number
|
||||||
|
|
||||||
|
const containingFolder = navigateToFolderWithIndexPath(
|
||||||
|
newState,
|
||||||
|
indexPaths
|
||||||
|
)
|
||||||
|
|
||||||
|
if (containingFolder === null) {
|
||||||
|
newState.push(newState.splice(folderIndex, 1)[0])
|
||||||
|
return {
|
||||||
|
state: newState,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushing the folder to the end of the array (last position)
|
||||||
|
containingFolder.folders.push(
|
||||||
|
containingFolder.folders.splice(folderIndex, 1)[0]
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
state: newState,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const destinationIndexPaths = destinationCollectionIndex
|
const destinationIndexPaths = destinationCollectionIndex
|
||||||
.split("/")
|
.split("/")
|
||||||
.map((x) => parseInt(x))
|
.map((x) => parseInt(x))
|
||||||
|
|
||||||
if (indexPaths.length === 0 || destinationIndexPaths.length === 0) {
|
if (destinationIndexPaths.length === 0) {
|
||||||
console.log("Given path too short. Skipping request.")
|
console.log("Given path too short. Skipping request.")
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
@@ -487,7 +519,7 @@ const restCollectionDispatchers = defineDispatchers({
|
|||||||
destinationCollectionPath,
|
destinationCollectionPath,
|
||||||
}: {
|
}: {
|
||||||
requestIndex: number
|
requestIndex: number
|
||||||
destinationRequestIndex: number
|
destinationRequestIndex: number | null
|
||||||
destinationCollectionPath: string
|
destinationCollectionPath: string
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
@@ -511,8 +543,32 @@ const restCollectionDispatchers = defineDispatchers({
|
|||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the destination is null, we are moving to the end of the list
|
||||||
|
if (destinationRequestIndex === null) {
|
||||||
|
// move to the end of the list
|
||||||
|
targetLocation.requests.push(
|
||||||
|
targetLocation.requests.splice(requestIndex, 1)[0]
|
||||||
|
)
|
||||||
|
|
||||||
|
resolveSaveContextOnRequestReorder({
|
||||||
|
lastIndex: requestIndex,
|
||||||
|
newIndex: targetLocation.requests.length,
|
||||||
|
folderPath: destinationCollectionPath,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
state: newState,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reorderItems(targetLocation.requests, requestIndex, destinationRequestIndex)
|
reorderItems(targetLocation.requests, requestIndex, destinationRequestIndex)
|
||||||
|
|
||||||
|
resolveSaveContextOnRequestReorder({
|
||||||
|
lastIndex: requestIndex,
|
||||||
|
newIndex: destinationRequestIndex,
|
||||||
|
folderPath: destinationCollectionPath,
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state: newState,
|
state: newState,
|
||||||
}
|
}
|
||||||
@@ -967,7 +1023,7 @@ export function moveRESTRequest(
|
|||||||
|
|
||||||
export function updateRESTRequestOrder(
|
export function updateRESTRequestOrder(
|
||||||
requestIndex: number,
|
requestIndex: number,
|
||||||
destinationRequestIndex: number,
|
destinationRequestIndex: number | null,
|
||||||
destinationCollectionPath: string
|
destinationCollectionPath: string
|
||||||
) {
|
) {
|
||||||
restCollectionStore.dispatch({
|
restCollectionStore.dispatch({
|
||||||
@@ -982,7 +1038,7 @@ export function updateRESTRequestOrder(
|
|||||||
|
|
||||||
export function updateRESTCollectionOrder(
|
export function updateRESTCollectionOrder(
|
||||||
collectionIndex: string,
|
collectionIndex: string,
|
||||||
destinationCollectionIndex: string
|
destinationCollectionIndex: string | null
|
||||||
) {
|
) {
|
||||||
restCollectionStore.dispatch({
|
restCollectionStore.dispatch({
|
||||||
dispatcher: "updateCollectionOrder",
|
dispatcher: "updateCollectionOrder",
|
||||||
|
|||||||
Reference in New Issue
Block a user