diff --git a/packages/hoppscotch-common/src/components.d.ts b/packages/hoppscotch-common/src/components.d.ts
index 714945c49..593041153 100644
--- a/packages/hoppscotch-common/src/components.d.ts
+++ b/packages/hoppscotch-common/src/components.d.ts
@@ -16,7 +16,6 @@ declare module '@vue/runtime-core' {
AppHeader: typeof import('./components/app/Header.vue')['default']
AppInterceptor: typeof import('./components/app/Interceptor.vue')['default']
AppLogo: typeof import('./components/app/Logo.vue')['default']
- AppNavigation: typeof import('./components/app/Navigation.vue')['default']
AppOptions: typeof import('./components/app/Options.vue')['default']
AppPaneLayout: typeof import('./components/app/PaneLayout.vue')['default']
AppPowerSearch: typeof import('./components/app/PowerSearch.vue')['default']
@@ -99,6 +98,20 @@ declare module '@vue/runtime-core' {
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
HttpTests: typeof import('./components/http/Tests.vue')['default']
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
+ IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
+ IconLucideBrush: typeof import('~icons/lucide/brush')['default']
+ IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
+ IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
+ IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
+ IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
+ IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
+ IconLucideInfo: typeof import('~icons/lucide/info')['default']
+ IconLucideLayers: typeof import('~icons/lucide/layers')['default']
+ IconLucideMinus: typeof import('~icons/lucide/minus')['default']
+ IconLucideRss: typeof import('~icons/lucide/rss')['default']
+ IconLucideSearch: typeof import('~icons/lucide/search')['default']
+ IconLucideUser: typeof import('~icons/lucide/user')['default']
+ IconLucideUsers: typeof import('~icons/lucide/users')['default']
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
LensesRenderersHTMLLensRenderer: typeof import('./components/lenses/renderers/HTMLLensRenderer.vue')['default']
diff --git a/packages/hoppscotch-common/src/components/collections/Collection.vue b/packages/hoppscotch-common/src/components/collections/Collection.vue
index 7babb29f1..0c069a545 100644
--- a/packages/hoppscotch-common/src/components/collections/Collection.vue
+++ b/packages/hoppscotch-common/src/components/collections/Collection.vue
@@ -16,7 +16,8 @@
dragging.value,
(val) => {
- if (val && notSameDestination.value) {
+ if (val && notSameDestination.value && notSameParentDestination.value) {
emit("dragging", true)
} else {
emit("dragging", false)
@@ -338,6 +339,10 @@ watch(
}
)
+const notSameParentDestination = computed(() => {
+ return currentReorderingStatus.value.parentID !== props.id
+})
+
const isRequestDragging = computed(() => {
return currentReorderingStatus.value.type === "request"
})
@@ -392,7 +397,8 @@ const handleDragOver = (e: DragEvent) => {
e.offsetY > 18 &&
notSameDestination.value &&
!isRequestDragging.value &&
- isSameParent.value
+ isSameParent.value &&
+ props.isLastItem
) {
orderingLastItem.value = true
dragging.value = false
@@ -409,7 +415,7 @@ const handelDrop = (e: DragEvent) => {
} else if (orderingLastItem.value) {
updateLastItemOrder(e)
} else {
- dropEvent(e)
+ notSameParentDestination.value ? dropEvent(e) : e.stopPropagation()
}
}
diff --git a/packages/hoppscotch-common/src/components/collections/MyCollections.vue b/packages/hoppscotch-common/src/components/collections/MyCollections.vue
index ca13025a4..5b9f2be0d 100644
--- a/packages/hoppscotch-common/src/components/collections/MyCollections.vue
+++ b/packages/hoppscotch-common/src/components/collections/MyCollections.vue
@@ -504,45 +504,41 @@ const emit = defineEmits<{
const refFilterCollection = toRef(props, "filteredCollections")
-const pathToIndex = computed(() => {
- return (path: string) => {
- const pathArr = path.split("/")
- return pathArr[pathArr.length - 1]
- }
-})
+const pathToIndex = (path: string) => {
+ const pathArr = path.split("/")
+ return pathArr[pathArr.length - 1]
+}
-const isSelected = computed(() => {
- return ({
- collectionIndex,
- folderPath,
- requestIndex,
- }: {
- collectionIndex?: number | undefined
- folderPath?: string | undefined
- requestIndex?: number | undefined
- }) => {
- if (collectionIndex !== undefined) {
- return (
- props.picked &&
- props.picked.pickedType === "my-collection" &&
- props.picked.collectionIndex === collectionIndex
- )
- } else if (requestIndex !== undefined && folderPath !== undefined) {
- return (
- props.picked &&
- props.picked.pickedType === "my-request" &&
- props.picked.folderPath === folderPath &&
- props.picked.requestIndex === requestIndex
- )
- } else {
- return (
- props.picked &&
- props.picked.pickedType === "my-folder" &&
- props.picked.folderPath === folderPath
- )
- }
+const isSelected = ({
+ collectionIndex,
+ folderPath,
+ requestIndex,
+}: {
+ collectionIndex?: number | undefined
+ folderPath?: string | undefined
+ requestIndex?: number | undefined
+}) => {
+ if (collectionIndex !== undefined) {
+ return (
+ props.picked &&
+ props.picked.pickedType === "my-collection" &&
+ props.picked.collectionIndex === collectionIndex
+ )
+ } else if (requestIndex !== undefined && folderPath !== undefined) {
+ return (
+ props.picked &&
+ props.picked.pickedType === "my-request" &&
+ props.picked.folderPath === folderPath &&
+ props.picked.requestIndex === requestIndex
+ )
+ } else {
+ return (
+ props.picked &&
+ props.picked.pickedType === "my-folder" &&
+ props.picked.folderPath === folderPath
+ )
}
-})
+}
const active = computed(() => currentActiveTab.value.document.saveContext)
@@ -706,7 +702,10 @@ class MyCollectionsAdapter implements SmartTreeAdapter {
...item.folders.map((folder, index) => ({
id: `${id}/${index}`,
data: {
- isLastItem: index === item.folders.length - 1,
+ isLastItem:
+ item.folders && item.folders.length > 1
+ ? index === item.folders.length - 1
+ : false,
type: "folders",
data: {
parentIndex: id,
@@ -717,7 +716,10 @@ class MyCollectionsAdapter implements SmartTreeAdapter {
...item.requests.map((requests, index) => ({
id: `${id}/${index}`,
data: {
- isLastItem: index === item.requests.length - 1,
+ isLastItem:
+ item.requests && item.requests.length > 1
+ ? index === item.requests.length - 1
+ : false,
type: "requests",
data: {
parentIndex: id,
diff --git a/packages/hoppscotch-common/src/components/collections/TeamCollections.vue b/packages/hoppscotch-common/src/components/collections/TeamCollections.vue
index 2c7a8c379..9a05330e3 100644
--- a/packages/hoppscotch-common/src/components/collections/TeamCollections.vue
+++ b/packages/hoppscotch-common/src/components/collections/TeamCollections.vue
@@ -517,54 +517,50 @@ const hasNoTeamAccess = computed(
props.collectionsType.selectedTeam.myRole === "VIEWER")
)
-const isSelected = computed(() => {
- return ({
- collectionID,
- folderID,
- requestID,
- }: {
- collectionID?: string | undefined
- folderID?: string | undefined
- requestID?: string | undefined
- }) => {
- if (collectionID !== undefined) {
- return (
- props.picked &&
- props.picked.pickedType === "teams-collection" &&
- props.picked.collectionID === collectionID
- )
- } else if (requestID !== undefined) {
- return (
- props.picked &&
- props.picked.pickedType === "teams-request" &&
- props.picked.requestID === requestID
- )
- } else {
- return (
- props.picked &&
- props.picked.pickedType === "teams-folder" &&
- props.picked.folderID === folderID
- )
- }
+const isSelected = ({
+ collectionID,
+ folderID,
+ requestID,
+}: {
+ collectionID?: string | undefined
+ folderID?: string | undefined
+ requestID?: string | undefined
+}) => {
+ if (collectionID !== undefined) {
+ return (
+ props.picked &&
+ props.picked.pickedType === "teams-collection" &&
+ props.picked.collectionID === collectionID
+ )
+ } else if (requestID !== undefined) {
+ return (
+ props.picked &&
+ props.picked.pickedType === "teams-request" &&
+ props.picked.requestID === requestID
+ )
+ } else {
+ return (
+ props.picked &&
+ props.picked.pickedType === "teams-folder" &&
+ props.picked.folderID === folderID
+ )
}
-})
+}
const active = computed(() => currentActiveTab.value.document.saveContext)
-const isActiveRequest = computed(() => {
- return (requestID: string) => {
- return pipe(
- active.value,
- O.fromNullable,
- O.filter(
- (active) =>
- active.originLocation === "team-collection" &&
- active.requestID === requestID
- ),
- O.isSome
- )
- }
-})
+const isActiveRequest = (requestID: string) => {
+ return pipe(
+ active.value,
+ O.fromNullable,
+ O.filter(
+ (active) =>
+ active.originLocation === "team-collection" &&
+ active.requestID === requestID
+ ),
+ O.isSome
+ )
+}
const selectRequest = (data: {
request: HoppRESTRequest
@@ -580,7 +576,7 @@ const selectRequest = (data: {
emit("select-request", {
request: request,
requestIndex: requestIndex,
- isActive: isActiveRequest.value(requestIndex),
+ isActive: isActiveRequest(requestIndex),
})
}
}
@@ -749,7 +745,10 @@ class TeamCollectionsAdapter implements SmartTreeAdapter {
? items.children.map((item, index) => ({
id: `${id}/${item.id}`,
data: {
- isLastItem: index === items.children.length - 1,
+ isLastItem:
+ items.children && items.children.length > 1
+ ? index === items.children.length - 1
+ : false,
type: "folders",
data: {
parentIndex: parsedID,
@@ -762,7 +761,10 @@ class TeamCollectionsAdapter implements SmartTreeAdapter {
? items.requests.map((item, index) => ({
id: `${id}/${item.id}`,
data: {
- isLastItem: index === items.requests.length - 1,
+ isLastItem:
+ items.requests && items.requests.length > 1
+ ? index === items.requests.length - 1
+ : false,
type: "requests",
data: {
parentIndex: parsedID,
diff --git a/packages/hoppscotch-common/src/components/collections/index.vue b/packages/hoppscotch-common/src/components/collections/index.vue
index 61d53a996..979630df7 100644
--- a/packages/hoppscotch-common/src/components/collections/index.vue
+++ b/packages/hoppscotch-common/src/components/collections/index.vue
@@ -1395,6 +1395,27 @@ const checkIfCollectionIsAParentOfTheChildren = (
return false
}
+const isMoveToSameLocation = (
+ draggedItemPath: string,
+ destinationPath: string
+) => {
+ const draggedItemPathArr = pathToIndex(draggedItemPath)
+ const destinationPathArr = pathToIndex(destinationPath)
+
+ if (draggedItemPathArr.length > 0) {
+ const draggedItemParentPathArr = draggedItemPathArr.slice(
+ 0,
+ draggedItemPathArr.length - 1
+ )
+
+ if (isEqual(draggedItemParentPathArr, destinationPathArr)) {
+ return true
+ } else {
+ return false
+ }
+ }
+}
+
/**
* This function is called when the user moves the collection
* to a different collection or folder
@@ -1419,6 +1440,13 @@ const dropCollection = (payload: {
return
}
+ //check if the collection is being moved to its own parent
+ if (
+ isMoveToSameLocation(collectionIndexDragged, destinationCollectionIndex)
+ ) {
+ return
+ }
+
const parentFolder = collectionIndexDragged
.split("/")
.slice(0, -1)
@@ -1556,10 +1584,14 @@ const isSameSameParent = (
draggedItemIndex.length === 1
) {
return draggedItemIndex[0] === destinationCollectionIndex
- } else if (destinationItemPath === null && draggedItemIndex.length !== 1) {
+ } else if (
+ destinationItemPath === null &&
+ draggedItemIndex.length !== 1 &&
+ destinationCollectionIndex !== null
+ ) {
const dragedItemParent = draggedItemIndex.slice(0, -1)
- return dragedItemParent[0] === destinationCollectionIndex
+ return dragedItemParent.join("/") === destinationCollectionIndex
} else {
if (destinationItemPath === null) return false
const destinationItemIndex = pathToIndex(destinationItemPath)
diff --git a/packages/hoppscotch-common/src/pages/index.vue b/packages/hoppscotch-common/src/pages/index.vue
index b095878bc..954737ccd 100644
--- a/packages/hoppscotch-common/src/pages/index.vue
+++ b/packages/hoppscotch-common/src/pages/index.vue
@@ -16,19 +16,33 @@
:key="tab.id"
:label="tab.document.request.name"
:is-removable="tabs.length > 1"
+ :close-visibility="'hover'"
>
-
- {{ tab.document.request.method }}
-
-
- •
-
-
- {{ tab.document.request.name }}
+
+ {{ tab.document.request.method }}
+
+
+ {{ tab.document.request.name }}
+
+
+
+
+
+
(),
+ {
+ label: null,
+ info: null,
+ isRemovable: true,
+ closeVisibility: "always",
+ selected: false,
+ }
+)
const tabMeta = computed(() => ({
info: props.info,
label: props.label,
isRemovable: props.isRemovable,
icon: slots.icon,
- tabhead: slots.tabhead
+ suffix: slots.suffix,
+ tabhead: slots.tabhead,
+ closeVisibility: props.closeVisibility,
}))
const {
diff --git a/packages/hoppscotch-ui/src/components/smart/Windows.vue b/packages/hoppscotch-ui/src/components/smart/Windows.vue
index d15c4bbef..c22b5cedc 100644
--- a/packages/hoppscotch-ui/src/components/smart/Windows.vue
+++ b/packages/hoppscotch-ui/src/components/smart/Windows.vue
@@ -1,43 +1,95 @@
-
-
-
+
+
+
-
+
-