chore: update properties UI flow
This commit is contained in:
@@ -161,7 +161,6 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
v-if="folderType === 'collection'"
|
|
||||||
ref="propertiesAction"
|
ref="propertiesAction"
|
||||||
:icon="IconSettings2"
|
:icon="IconSettings2"
|
||||||
:label="t('action.properties')"
|
:label="t('action.properties')"
|
||||||
|
|||||||
@@ -146,6 +146,13 @@
|
|||||||
folder: node.data.data.data,
|
folder: node.data.data.data,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
|
@edit-properties="
|
||||||
|
node.data.type === 'folders' &&
|
||||||
|
emit('edit-properties', {
|
||||||
|
collectionIndex: node.id,
|
||||||
|
collection: node.data.data.data,
|
||||||
|
})
|
||||||
|
"
|
||||||
@export-data="
|
@export-data="
|
||||||
node.data.type === 'folders' &&
|
node.data.type === 'folders' &&
|
||||||
emit('export-data', node.data.data.data)
|
emit('export-data', node.data.data.data)
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
<HttpAuthorization
|
<HttpAuthorization
|
||||||
v-model="editableCollection.auth"
|
v-model="editableCollection.auth"
|
||||||
:is-collection-property="true"
|
:is-collection-property="true"
|
||||||
|
:is-root-collection="editingProperties.isRootCollection"
|
||||||
|
:inherited-properties="editingProperties.inheritedProperties"
|
||||||
/>
|
/>
|
||||||
<AppBanner
|
<AppBanner
|
||||||
:banner="{
|
:banner="{
|
||||||
@@ -80,37 +82,46 @@
|
|||||||
import { watch, ref } from "vue"
|
import { watch, ref } from "vue"
|
||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
|
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
|
||||||
import { TeamCollection } from "~/helpers/backend/graphql"
|
|
||||||
import { RESTOptionTabs } from "../http/RequestOptions.vue"
|
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()
|
const t = useI18n()
|
||||||
|
|
||||||
|
type EditingProperties = {
|
||||||
|
collection: HoppCollection<HoppRESTRequest> | TeamCollection | null
|
||||||
|
isRootCollection: boolean
|
||||||
|
path: string
|
||||||
|
inheritedProperties: HoppInheritedProperty | null
|
||||||
|
}
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
show: boolean
|
show: boolean
|
||||||
loadingState: boolean
|
loadingState: boolean
|
||||||
collection: HoppCollection<HoppRESTRequest> | TeamCollection
|
editingProperties: EditingProperties | null
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
show: false,
|
show: false,
|
||||||
loadingState: false,
|
loadingState: false,
|
||||||
|
editingProperties: null,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "submit", name: string): void
|
(e: "set-collection-properties", newCollection: any): void
|
||||||
(e: "hide-modal"): void
|
(e: "hide-modal"): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const editableCollection = ref({
|
const editableCollection = ref({
|
||||||
...props.collection,
|
|
||||||
body: {
|
body: {
|
||||||
contentType: null,
|
contentType: null,
|
||||||
body: null,
|
body: null,
|
||||||
},
|
},
|
||||||
headers: [],
|
headers: [],
|
||||||
auth: {
|
auth: {
|
||||||
authType: "none",
|
authType: "inherit",
|
||||||
authActive: false,
|
authActive: false,
|
||||||
},
|
},
|
||||||
}) as any
|
}) as any
|
||||||
@@ -124,23 +135,44 @@ const changeOptionTab = (tab: RESTOptionTabs) => {
|
|||||||
watch(
|
watch(
|
||||||
() => props.show,
|
() => props.show,
|
||||||
(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 = () => {
|
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 = () => {
|
const hideModal = () => {
|
||||||
emit("hide-modal")
|
emit("hide-modal")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,13 @@
|
|||||||
folder: node.data.data.data,
|
folder: node.data.data.data,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
|
@edit-properties="
|
||||||
|
node.data.type === 'folders' &&
|
||||||
|
emit('edit-properties', {
|
||||||
|
collectionIndex: node.id,
|
||||||
|
collection: node.data.data.data,
|
||||||
|
})
|
||||||
|
"
|
||||||
@export-data="
|
@export-data="
|
||||||
node.data.type === 'folders' &&
|
node.data.type === 'folders' &&
|
||||||
emit('export-data', node.data.data.data)
|
emit('export-data', node.data.data.data)
|
||||||
|
|||||||
@@ -155,7 +155,9 @@
|
|||||||
/>
|
/>
|
||||||
<CollectionsProperties
|
<CollectionsProperties
|
||||||
:show="showModalEditProperties"
|
:show="showModalEditProperties"
|
||||||
|
:editing-properties="editingProperties"
|
||||||
@hide-modal="displayModalEditProperties(false)"
|
@hide-modal="displayModalEditProperties(false)"
|
||||||
|
@set-collection-properties="setCollectionProperties"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -226,6 +228,7 @@ import {
|
|||||||
getFoldersByPath,
|
getFoldersByPath,
|
||||||
resolveSaveContextOnCollectionReorder,
|
resolveSaveContextOnCollectionReorder,
|
||||||
updateSaveContextForAffectedRequests,
|
updateSaveContextForAffectedRequests,
|
||||||
|
updateInheritedPropertiesForAffectedRequests,
|
||||||
resetTeamRequestsContext,
|
resetTeamRequestsContext,
|
||||||
} from "~/helpers/collection/collection"
|
} from "~/helpers/collection/collection"
|
||||||
import { currentReorderingStatus$ } from "~/newstore/reordering"
|
import { currentReorderingStatus$ } from "~/newstore/reordering"
|
||||||
@@ -233,6 +236,7 @@ import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
|||||||
import { WorkspaceService } from "~/services/workspace.service"
|
import { WorkspaceService } from "~/services/workspace.service"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -288,6 +292,17 @@ const editingRequestName = ref("")
|
|||||||
const editingRequestIndex = ref<number | null>(null)
|
const editingRequestIndex = ref<number | null>(null)
|
||||||
const editingRequestID = ref<string | 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 confirmModalTitle = ref<string | null>(null)
|
||||||
|
|
||||||
const filterTexts = ref("")
|
const filterTexts = ref("")
|
||||||
@@ -597,6 +612,11 @@ const addNewRootCollection = (name: string) => {
|
|||||||
name,
|
name,
|
||||||
folders: [],
|
folders: [],
|
||||||
requests: [],
|
requests: [],
|
||||||
|
headers: [],
|
||||||
|
auth: {
|
||||||
|
authType: "inherit",
|
||||||
|
authActive: false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -657,6 +677,8 @@ const onAddRequest = (requestName: string) => {
|
|||||||
if (!path) return
|
if (!path) return
|
||||||
const insertionIndex = saveRESTRequestAs(path, newRequest)
|
const insertionIndex = saveRESTRequestAs(path, newRequest)
|
||||||
|
|
||||||
|
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path)
|
||||||
|
|
||||||
tabs.createNewTab({
|
tabs.createNewTab({
|
||||||
request: newRequest,
|
request: newRequest,
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
@@ -665,6 +687,12 @@ const onAddRequest = (requestName: string) => {
|
|||||||
folderPath: path,
|
folderPath: path,
|
||||||
requestIndex: insertionIndex,
|
requestIndex: insertionIndex,
|
||||||
},
|
},
|
||||||
|
inheritedProperties: {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
parentName: name,
|
||||||
|
parentId: path,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
@@ -1286,6 +1314,63 @@ const selectPicked = (payload: Picked | null) => {
|
|||||||
emit("select", payload)
|
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
|
* 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
|
* @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
|
// If there is a request with this save context, switch into it
|
||||||
let possibleTab = null
|
let possibleTab = null
|
||||||
|
|
||||||
|
const { auth, headers, name } =
|
||||||
|
cascaseParentCollectionForHeaderAuth(folderPath)
|
||||||
|
|
||||||
if (collectionsType.value.type === "team-collections") {
|
if (collectionsType.value.type === "team-collections") {
|
||||||
possibleTab = tabs.getTabRefWithSaveContext({
|
possibleTab = tabs.getTabRefWithSaveContext({
|
||||||
originLocation: "team-collection",
|
originLocation: "team-collection",
|
||||||
@@ -1336,6 +1424,12 @@ const selectRequest = (selectedRequest: {
|
|||||||
folderPath: folderPath!,
|
folderPath: folderPath!,
|
||||||
requestIndex: parseInt(requestIndex),
|
requestIndex: parseInt(requestIndex),
|
||||||
},
|
},
|
||||||
|
inheritedProperties: {
|
||||||
|
parentId: folderPath || "",
|
||||||
|
parentName: name,
|
||||||
|
auth: auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1364,14 +1458,14 @@ const dropRequest = (payload: {
|
|||||||
|
|
||||||
if (!requestIndex || !destinationCollectionIndex) return
|
if (!requestIndex || !destinationCollectionIndex) return
|
||||||
|
|
||||||
|
let possibleTab = null
|
||||||
|
|
||||||
if (collectionsType.value.type === "my-collections" && folderPath) {
|
if (collectionsType.value.type === "my-collections" && folderPath) {
|
||||||
moveRESTRequest(
|
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
||||||
folderPath,
|
|
||||||
pathToLastIndex(requestIndex),
|
|
||||||
destinationCollectionIndex
|
destinationCollectionIndex
|
||||||
)
|
)
|
||||||
|
|
||||||
const possibleTab = tabs.getTabRefWithSaveContext({
|
possibleTab = tabs.getTabRefWithSaveContext({
|
||||||
originLocation: "user-collection",
|
originLocation: "user-collection",
|
||||||
folderPath,
|
folderPath,
|
||||||
requestIndex: pathToLastIndex(requestIndex),
|
requestIndex: pathToLastIndex(requestIndex),
|
||||||
@@ -1387,6 +1481,13 @@ const dropRequest = (payload: {
|
|||||||
destinationCollectionIndex
|
destinationCollectionIndex
|
||||||
).length,
|
).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
|
// When it's drop it's basically getting deleted from last folder. reordering last folder accordingly
|
||||||
@@ -1396,6 +1497,11 @@ const dropRequest = (payload: {
|
|||||||
folderPath,
|
folderPath,
|
||||||
length: getRequestsByPath(myCollections.value, folderPath).length,
|
length: getRequestsByPath(myCollections.value, folderPath).length,
|
||||||
})
|
})
|
||||||
|
moveRESTRequest(
|
||||||
|
folderPath,
|
||||||
|
pathToLastIndex(requestIndex),
|
||||||
|
destinationCollectionIndex
|
||||||
|
)
|
||||||
|
|
||||||
toast.success(`${t("request.moved")}`)
|
toast.success(`${t("request.moved")}`)
|
||||||
draggingToRoot.value = false
|
draggingToRoot.value = false
|
||||||
@@ -1420,7 +1526,7 @@ const dropRequest = (payload: {
|
|||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
|
||||||
const possibleTab = tabs.getTabRefWithSaveContext({
|
possibleTab = tabs.getTabRefWithSaveContext({
|
||||||
originLocation: "team-collection",
|
originLocation: "team-collection",
|
||||||
requestID: requestIndex,
|
requestID: requestIndex,
|
||||||
})
|
})
|
||||||
@@ -1550,6 +1656,22 @@ const dropCollection = (payload: {
|
|||||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
|
`${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
|
draggingToRoot.value = false
|
||||||
toast.success(`${t("collection.moved")}`)
|
toast.success(`${t("collection.moved")}`)
|
||||||
} else if (hasTeamWriteAccess.value) {
|
} else if (hasTeamWriteAccess.value) {
|
||||||
@@ -1912,13 +2034,58 @@ const editProperties = (payload: {
|
|||||||
}) => {
|
}) => {
|
||||||
const { collection, collectionIndex } = 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)
|
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) => {
|
const resolveConfirmModal = (title: string | null) => {
|
||||||
if (title === `${t("confirm.remove_collection")}`) onRemoveCollection()
|
if (title === `${t("confirm.remove_collection")}`) onRemoveCollection()
|
||||||
else if (title === `${t("confirm.remove_request")}`) onRemoveRequest()
|
else if (title === `${t("confirm.remove_request")}`) onRemoveRequest()
|
||||||
|
|||||||
Reference in New Issue
Block a user