diff --git a/packages/hoppscotch-common/src/components/collections/Collection.vue b/packages/hoppscotch-common/src/components/collections/Collection.vue
index b5bd7f139..f59202186 100644
--- a/packages/hoppscotch-common/src/components/collections/Collection.vue
+++ b/packages/hoppscotch-common/src/components/collections/Collection.vue
@@ -161,7 +161,6 @@
"
/>
| TeamCollection | null
+ isRootCollection: boolean
+ path: string
+ inheritedProperties: HoppInheritedProperty | null
+}
+
const props = withDefaults(
defineProps<{
show: boolean
loadingState: boolean
- collection: HoppCollection | TeamCollection
+ editingProperties: EditingProperties | null
}>(),
{
show: false,
loadingState: false,
+ editingProperties: null,
}
)
const emit = defineEmits<{
- (e: "submit", name: string): void
+ (e: "set-collection-properties", newCollection: any): void
(e: "hide-modal"): void
}>()
const editableCollection = ref({
- ...props.collection,
body: {
contentType: null,
body: null,
},
headers: [],
auth: {
- authType: "none",
+ authType: "inherit",
authActive: false,
},
}) as any
@@ -124,23 +135,44 @@ const changeOptionTab = (tab: RESTOptionTabs) => {
watch(
() => props.show,
(show) => {
- if (!show) {
+ if (show && props.editingProperties?.collection) {
+ editableCollection.value.auth = clone(
+ props.editingProperties.collection.auth
+ )
+ editableCollection.value.headers = clone(
+ props.editingProperties.collection.headers
+ )
+ } else {
+ editableCollection.value = {
+ body: {
+ contentType: null,
+ body: null,
+ },
+ headers: [],
+ auth: {
+ authType: "inherit",
+ authActive: false,
+ },
+ }
}
}
)
const saveEditedCollection = () => {
- console.log("new-coll", editableCollection.value)
+ if (!props.editingProperties) return
+ const finalCollection = clone(editableCollection.value)
+ delete finalCollection.body
+ const collection = {
+ path: props.editingProperties.path,
+ collection: {
+ ...props.editingProperties.collection,
+ ...finalCollection,
+ },
+ isRootCollection: props.editingProperties.isRootCollection,
+ }
+ emit("set-collection-properties", collection)
}
-// const addNewCollection = () => {
-// if (!editingName.value) {
-// toast.error(t("collection.invalid_name"))
-// return
-// }
-
-// }
-
const hideModal = () => {
emit("hide-modal")
}
diff --git a/packages/hoppscotch-common/src/components/collections/TeamCollections.vue b/packages/hoppscotch-common/src/components/collections/TeamCollections.vue
index ad09b7758..2d624545e 100644
--- a/packages/hoppscotch-common/src/components/collections/TeamCollections.vue
+++ b/packages/hoppscotch-common/src/components/collections/TeamCollections.vue
@@ -166,6 +166,13 @@
folder: node.data.data.data,
})
"
+ @edit-properties="
+ node.data.type === 'folders' &&
+ emit('edit-properties', {
+ collectionIndex: node.id,
+ collection: node.data.data.data,
+ })
+ "
@export-data="
node.data.type === 'folders' &&
emit('export-data', node.data.data.data)
diff --git a/packages/hoppscotch-common/src/components/collections/index.vue b/packages/hoppscotch-common/src/components/collections/index.vue
index 356a09744..944d465be 100644
--- a/packages/hoppscotch-common/src/components/collections/index.vue
+++ b/packages/hoppscotch-common/src/components/collections/index.vue
@@ -155,7 +155,9 @@
/>
@@ -226,6 +228,7 @@ import {
getFoldersByPath,
resolveSaveContextOnCollectionReorder,
updateSaveContextForAffectedRequests,
+ updateInheritedPropertiesForAffectedRequests,
resetTeamRequestsContext,
} from "~/helpers/collection/collection"
import { currentReorderingStatus$ } from "~/newstore/reordering"
@@ -233,6 +236,7 @@ import { defineActionHandler, invokeAction } from "~/helpers/actions"
import { WorkspaceService } from "~/services/workspace.service"
import { useService } from "dioc/vue"
import { RESTTabService } from "~/services/tab/rest"
+import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
const t = useI18n()
const toast = useToast()
@@ -288,6 +292,17 @@ const editingRequestName = ref("")
const editingRequestIndex = ref(null)
const editingRequestID = ref(null)
+const editingProperties = ref<{
+ collection: HoppCollection | TeamCollection | null
+ isRootCollection: boolean
+ path: string
+ inheritedProperties?: HoppInheritedProperty
+}>({
+ collection: null,
+ isRootCollection: false,
+ path: "",
+})
+
const confirmModalTitle = ref(null)
const filterTexts = ref("")
@@ -597,6 +612,11 @@ const addNewRootCollection = (name: string) => {
name,
folders: [],
requests: [],
+ headers: [],
+ auth: {
+ authType: "inherit",
+ authActive: false,
+ },
})
)
@@ -657,6 +677,8 @@ const onAddRequest = (requestName: string) => {
if (!path) return
const insertionIndex = saveRESTRequestAs(path, newRequest)
+ const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path)
+
tabs.createNewTab({
request: newRequest,
isDirty: false,
@@ -665,6 +687,12 @@ const onAddRequest = (requestName: string) => {
folderPath: path,
requestIndex: insertionIndex,
},
+ inheritedProperties: {
+ auth,
+ headers,
+ parentName: name,
+ parentId: path,
+ },
})
platform.analytics?.logEvent({
@@ -1286,6 +1314,63 @@ const selectPicked = (payload: Picked | null) => {
emit("select", payload)
}
+const cascaseParentCollectionForHeaderAuth = (
+ folderPath: string | undefined
+) => {
+ let auth: HoppRESTRequest["auth"] = {
+ authType: "none",
+ authActive: false,
+ }
+ const headers: HoppRESTRequest["headers"] = []
+ let name = ""
+ if (!folderPath) return { auth, headers, name: "" }
+ const path = folderPath.split("/").map((i) => parseInt(i))
+
+ // Check if the path is empty or invalid
+ if (!path || path.length === 0) {
+ console.error("Invalid path:", folderPath)
+ return { auth, headers, name: "" }
+ }
+
+ // Loop through the path and get the last parent folder with authType other than 'inherit'
+ for (let i = 0; i < path.length; i++) {
+ const parentFolder = navigateToFolderWithIndexPath(
+ restCollectionStore.value.state,
+ [...path.slice(0, i + 1)] // Create a copy of the path array
+ )
+
+ // Check if parentFolder is undefined or null
+ if (!parentFolder) {
+ console.error("Parent folder not found for path:", path)
+ return { auth, headers, name: "" }
+ }
+
+ const parentFolderAuth = parentFolder.auth
+ const parentFolderHeaders = parentFolder.headers
+
+ // Check if authType is not 'inherit'
+ if (parentFolderAuth?.authType !== "inherit") {
+ auth = parentFolderAuth || auth
+ name = parentFolder.name
+ }
+ // Update headers, overwriting duplicates by key
+ if (parentFolderHeaders) {
+ const activeHeaders = parentFolderHeaders.filter((h) => h.active)
+ activeHeaders.forEach((header) => {
+ const index = headers.findIndex((h) => h.key === header.key)
+ if (index !== -1) {
+ // Replace the existing header with the same key
+ headers[index] = header
+ } else {
+ headers.push(header)
+ }
+ })
+ }
+ }
+
+ return { auth, headers, name }
+}
+
/**
* This function is called when the user clicks on a request
* @param selectedRequest The request that the user clicked on emited from the collection tree
@@ -1301,6 +1386,9 @@ const selectRequest = (selectedRequest: {
// If there is a request with this save context, switch into it
let possibleTab = null
+ const { auth, headers, name } =
+ cascaseParentCollectionForHeaderAuth(folderPath)
+
if (collectionsType.value.type === "team-collections") {
possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "team-collection",
@@ -1336,6 +1424,12 @@ const selectRequest = (selectedRequest: {
folderPath: folderPath!,
requestIndex: parseInt(requestIndex),
},
+ inheritedProperties: {
+ parentId: folderPath || "",
+ parentName: name,
+ auth: auth,
+ headers,
+ },
})
}
}
@@ -1364,14 +1458,14 @@ const dropRequest = (payload: {
if (!requestIndex || !destinationCollectionIndex) return
+ let possibleTab = null
+
if (collectionsType.value.type === "my-collections" && folderPath) {
- moveRESTRequest(
- folderPath,
- pathToLastIndex(requestIndex),
+ const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
destinationCollectionIndex
)
- const possibleTab = tabs.getTabRefWithSaveContext({
+ possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "user-collection",
folderPath,
requestIndex: pathToLastIndex(requestIndex),
@@ -1387,6 +1481,13 @@ const dropRequest = (payload: {
destinationCollectionIndex
).length,
}
+
+ possibleTab.value.document.inheritedProperties = {
+ parentId: destinationCollectionIndex,
+ parentName: name,
+ auth,
+ headers,
+ }
}
// When it's drop it's basically getting deleted from last folder. reordering last folder accordingly
@@ -1396,6 +1497,11 @@ const dropRequest = (payload: {
folderPath,
length: getRequestsByPath(myCollections.value, folderPath).length,
})
+ moveRESTRequest(
+ folderPath,
+ pathToLastIndex(requestIndex),
+ destinationCollectionIndex
+ )
toast.success(`${t("request.moved")}`)
draggingToRoot.value = false
@@ -1420,7 +1526,7 @@ const dropRequest = (payload: {
1
)
- const possibleTab = tabs.getTabRefWithSaveContext({
+ possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "team-collection",
requestID: requestIndex,
})
@@ -1550,6 +1656,22 @@ const dropCollection = (payload: {
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
)
+ const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
+ `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
+ )
+
+ const inheritedProperty = {
+ parentId: `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
+ parentName: name,
+ auth,
+ headers,
+ }
+
+ updateInheritedPropertiesForAffectedRequests(
+ `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
+ inheritedProperty
+ )
+
draggingToRoot.value = false
toast.success(`${t("collection.moved")}`)
} else if (hasTeamWriteAccess.value) {
@@ -1912,13 +2034,58 @@ const editProperties = (payload: {
}) => {
const { collection, collectionIndex } = payload
- console.log(collectionIndex, collection)
+ const parentIndex = collectionIndex.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
- editingCollection.value = collection
+ let inheritedProperties = {}
+
+ if (parentIndex) {
+ const { auth, headers, name } =
+ cascaseParentCollectionForHeaderAuth(parentIndex)
+
+ inheritedProperties = {
+ parentId: parentIndex ?? "",
+ parentName: name,
+ auth,
+ headers,
+ } as HoppInheritedProperty
+ }
+
+ editingProperties.value = {
+ collection,
+ isRootCollection: isAlreadyInRoot(collectionIndex),
+ path: collectionIndex,
+ inheritedProperties,
+ }
displayModalEditProperties(true)
}
+const setCollectionProperties = (newCollection: {
+ collection: HoppCollection
+ path: string
+ isRootCollection: boolean
+}) => {
+ const { collection, path, isRootCollection } = newCollection
+ if (isRootCollection) {
+ editRESTCollection(parseInt(path), collection)
+ } else {
+ editRESTFolder(path, collection)
+ }
+
+ const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path)
+
+ nextTick(() => {
+ updateInheritedPropertiesForAffectedRequests(path, {
+ parentId: path,
+ parentName: name,
+ auth,
+ headers,
+ })
+ })
+
+ displayModalEditProperties(false)
+}
+
const resolveConfirmModal = (title: string | null) => {
if (title === `${t("confirm.remove_collection")}`) onRemoveCollection()
else if (title === `${t("confirm.remove_request")}`) onRemoveRequest()