chore: update properties UI flow
This commit is contained in:
@@ -161,7 +161,6 @@
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
v-if="folderType === 'collection'"
|
||||
ref="propertiesAction"
|
||||
:icon="IconSettings2"
|
||||
:label="t('action.properties')"
|
||||
|
||||
@@ -146,6 +146,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)
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
<HttpAuthorization
|
||||
v-model="editableCollection.auth"
|
||||
:is-collection-property="true"
|
||||
:is-root-collection="editingProperties.isRootCollection"
|
||||
:inherited-properties="editingProperties.inheritedProperties"
|
||||
/>
|
||||
<AppBanner
|
||||
:banner="{
|
||||
@@ -80,37 +82,46 @@
|
||||
import { watch, ref } from "vue"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
|
||||
import { TeamCollection } from "~/helpers/backend/graphql"
|
||||
import { RESTOptionTabs } from "../http/RequestOptions.vue"
|
||||
import { TeamCollection } from "~/helpers/teams/TeamCollection"
|
||||
import { clone } from "lodash-es"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
type EditingProperties = {
|
||||
collection: HoppCollection<HoppRESTRequest> | TeamCollection | null
|
||||
isRootCollection: boolean
|
||||
path: string
|
||||
inheritedProperties: HoppInheritedProperty | null
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
show: boolean
|
||||
loadingState: boolean
|
||||
collection: HoppCollection<HoppRESTRequest> | 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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -155,7 +155,9 @@
|
||||
/>
|
||||
<CollectionsProperties
|
||||
:show="showModalEditProperties"
|
||||
:editing-properties="editingProperties"
|
||||
@hide-modal="displayModalEditProperties(false)"
|
||||
@set-collection-properties="setCollectionProperties"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -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<number | null>(null)
|
||||
const editingRequestID = ref<string | null>(null)
|
||||
|
||||
const editingProperties = ref<{
|
||||
collection: HoppCollection<HoppRESTRequest> | TeamCollection | null
|
||||
isRootCollection: boolean
|
||||
path: string
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}>({
|
||||
collection: null,
|
||||
isRootCollection: false,
|
||||
path: "",
|
||||
})
|
||||
|
||||
const confirmModalTitle = ref<string | null>(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<HoppRESTRequest>
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user