feat: added inherit auth-header for personal gql
This commit is contained in:
@@ -240,15 +240,14 @@ const saveRequestAs = async () => {
|
||||
},
|
||||
}
|
||||
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
||||
`${picked.value.collectionIndex}`
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
`${picked.value.collectionIndex}`,
|
||||
"rest"
|
||||
)
|
||||
|
||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
parentId: `${picked.value.collectionIndex}`,
|
||||
parentName: name,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
@@ -278,15 +277,14 @@ const saveRequestAs = async () => {
|
||||
},
|
||||
}
|
||||
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"rest"
|
||||
)
|
||||
|
||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
parentId: picked.value.folderPath,
|
||||
parentName: name,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
@@ -317,15 +315,14 @@ const saveRequestAs = async () => {
|
||||
},
|
||||
}
|
||||
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"rest"
|
||||
)
|
||||
|
||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
parentId: picked.value.folderPath,
|
||||
parentName: name,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
@@ -412,6 +409,16 @@ const saveRequestAs = async () => {
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "gql-my-folder") {
|
||||
// TODO: Check for GQL request ?
|
||||
@@ -427,6 +434,16 @@ const saveRequestAs = async () => {
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "gql-my-collection") {
|
||||
// TODO: Check for GQL request ?
|
||||
@@ -442,6 +459,16 @@ const saveRequestAs = async () => {
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
`${picked.value.collectionIndex}`,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
requestSaved()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,11 @@ const addNewCollection = () => {
|
||||
name: name.value,
|
||||
folders: [],
|
||||
requests: [],
|
||||
auth: {
|
||||
authType: "inherit",
|
||||
authActive: true,
|
||||
},
|
||||
headers: [],
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
@@ -128,6 +128,21 @@
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="propertiesAction"
|
||||
:icon="IconSettings2"
|
||||
:label="t('action.properties')"
|
||||
:shortcut="['P']"
|
||||
@click="
|
||||
() => {
|
||||
emit('edit-properties', {
|
||||
collectionIndex: String(collectionIndex),
|
||||
collection: collection,
|
||||
})
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
@@ -155,7 +170,14 @@
|
||||
@edit-folder="$emit('edit-folder', $event)"
|
||||
@edit-request="$emit('edit-request', $event)"
|
||||
@duplicate-request="$emit('duplicate-request', $event)"
|
||||
@edit-properties="
|
||||
$emit('edit-properties', {
|
||||
collectionIndex: `${collectionIndex}/${String(index)}`,
|
||||
collection: folder,
|
||||
})
|
||||
"
|
||||
@select="$emit('select', $event)"
|
||||
@select-request="$emit('select-request', $event)"
|
||||
/>
|
||||
<CollectionsGraphqlRequest
|
||||
v-for="(request, index) in collection.requests"
|
||||
@@ -171,6 +193,7 @@
|
||||
@edit-request="$emit('edit-request', $event)"
|
||||
@duplicate-request="$emit('duplicate-request', $event)"
|
||||
@select="$emit('select', $event)"
|
||||
@select-request="$emit('select-request', $event)"
|
||||
/>
|
||||
<HoppSmartPlaceholder
|
||||
v-if="
|
||||
@@ -214,6 +237,7 @@ import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
@@ -224,15 +248,16 @@ import {
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { useService } from "dioc/vue"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
|
||||
|
||||
const props = defineProps({
|
||||
picked: { type: Object, default: null },
|
||||
const props = defineProps<{
|
||||
picked: Picked | null
|
||||
// Whether the viewing context is related to picking (activates 'select' events)
|
||||
saveRequest: { type: Boolean, default: false },
|
||||
collectionIndex: { type: Number, default: null },
|
||||
collection: { type: Object, default: () => ({}) },
|
||||
isFiltered: Boolean,
|
||||
})
|
||||
saveRequest: boolean
|
||||
collectionIndex: number | null
|
||||
collection: HoppCollection<HoppGQLRequest>
|
||||
isFiltered: boolean
|
||||
}>()
|
||||
|
||||
const colorMode = useColorMode()
|
||||
const toast = useToast()
|
||||
@@ -248,7 +273,15 @@ const emit = defineEmits<{
|
||||
(e: "add-request", i: any): void
|
||||
(e: "add-folder", i: any): void
|
||||
(e: "edit-folder", i: any): void
|
||||
(
|
||||
e: "edit-properties",
|
||||
payload: {
|
||||
collectionIndex: string | null
|
||||
collection: HoppCollection<HoppGQLRequest>
|
||||
}
|
||||
): void
|
||||
(e: "edit-collection"): void
|
||||
(e: "select-request", i: any): void
|
||||
}>()
|
||||
|
||||
// Template refs
|
||||
|
||||
@@ -121,6 +121,21 @@
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="propertiesAction"
|
||||
:icon="IconSettings2"
|
||||
:label="t('action.properties')"
|
||||
:shortcut="['P']"
|
||||
@click="
|
||||
() => {
|
||||
emit('edit-properties', {
|
||||
collectionIndex: collectionIndex,
|
||||
collection: collection,
|
||||
})
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
@@ -149,7 +164,14 @@
|
||||
@edit-folder="emit('edit-folder', $event)"
|
||||
@edit-request="emit('edit-request', $event)"
|
||||
@duplicate-request="emit('duplicate-request', $event)"
|
||||
@edit-properties="
|
||||
emit('edit-properties', {
|
||||
collectionIndex: `${folderPath}/${String(subFolderIndex)}`,
|
||||
collection: subFolder,
|
||||
})
|
||||
"
|
||||
@select="emit('select', $event)"
|
||||
@select-request="$emit('select-request', $event)"
|
||||
/>
|
||||
<CollectionsGraphqlRequest
|
||||
v-for="(request, index) in folder.requests"
|
||||
@@ -165,6 +187,7 @@
|
||||
@edit-request="emit('edit-request', $event)"
|
||||
@duplicate-request="emit('duplicate-request', $event)"
|
||||
@select="emit('select', $event)"
|
||||
@select-request="$emit('select-request', $event)"
|
||||
/>
|
||||
|
||||
<HoppSmartPlaceholder
|
||||
@@ -198,6 +221,7 @@ import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
@@ -205,6 +229,8 @@ import { removeGraphqlFolder, moveGraphqlRequest } from "~/newstore/collections"
|
||||
import { computed, ref } from "vue"
|
||||
import { useService } from "dioc/vue"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
|
||||
|
||||
const toast = useToast()
|
||||
const t = useI18n()
|
||||
@@ -212,16 +238,16 @@ const colorMode = useColorMode()
|
||||
|
||||
const tabs = useService(GQLTabService)
|
||||
|
||||
const props = defineProps({
|
||||
picked: { type: Object, default: null },
|
||||
const props = defineProps<{
|
||||
picked: Picked
|
||||
// Whether the request is in a selectable mode (activates 'select' event)
|
||||
saveRequest: { type: Boolean, default: false },
|
||||
folder: { type: Object, default: () => ({}) },
|
||||
folderIndex: { type: Number, default: null },
|
||||
collectionIndex: { type: Number, default: null },
|
||||
folderPath: { type: String, default: null },
|
||||
isFiltered: Boolean,
|
||||
})
|
||||
saveRequest: boolean
|
||||
folder: HoppCollection<HoppGQLRequest>
|
||||
folderIndex: number
|
||||
collectionIndex: number
|
||||
folderPath: string
|
||||
isFiltered: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits([
|
||||
"select",
|
||||
@@ -230,6 +256,8 @@ const emit = defineEmits([
|
||||
"add-folder",
|
||||
"edit-folder",
|
||||
"duplicate-request",
|
||||
"edit-properties",
|
||||
"select-request",
|
||||
])
|
||||
|
||||
// Template refs
|
||||
|
||||
@@ -178,7 +178,12 @@ const isActive = computed(() => {
|
||||
})
|
||||
|
||||
// TODO: Better types please
|
||||
const emit = defineEmits(["select", "edit-request", "duplicate-request"])
|
||||
const emit = defineEmits([
|
||||
"select",
|
||||
"edit-request",
|
||||
"duplicate-request",
|
||||
"select-request",
|
||||
])
|
||||
|
||||
const dragging = ref(false)
|
||||
const confirmRemove = ref(false)
|
||||
@@ -202,36 +207,11 @@ const selectRequest = () => {
|
||||
if (props.saveRequest) {
|
||||
pick()
|
||||
} else {
|
||||
const possibleTab = tabs.getTabRefWithSaveContext({
|
||||
originLocation: "user-collection",
|
||||
emit("select-request", {
|
||||
request: props.request,
|
||||
folderPath: props.folderPath,
|
||||
requestIndex: props.requestIndex,
|
||||
})
|
||||
|
||||
// Switch to that request if that request is open
|
||||
if (possibleTab) {
|
||||
tabs.setActiveTab(possibleTab.value.id)
|
||||
return
|
||||
}
|
||||
|
||||
tabs.createNewTab({
|
||||
saveContext: {
|
||||
originLocation: "user-collection",
|
||||
folderPath: props.folderPath,
|
||||
requestIndex: props.requestIndex,
|
||||
},
|
||||
request: cloneDeep(
|
||||
makeGQLRequest({
|
||||
name: props.request.name,
|
||||
url: props.request.url,
|
||||
query: props.request.query,
|
||||
headers: props.request.headers,
|
||||
variables: props.request.variables,
|
||||
auth: props.request.auth,
|
||||
})
|
||||
),
|
||||
isDirty: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@
|
||||
@edit-request="editRequest($event)"
|
||||
@duplicate-request="duplicateRequest($event)"
|
||||
@select-collection="$emit('use-collection', collection)"
|
||||
@edit-properties="editProperties($event)"
|
||||
@select="$emit('select', $event)"
|
||||
@select-request="selectRequest($event)"
|
||||
/>
|
||||
</div>
|
||||
<HoppSmartPlaceholder
|
||||
@@ -142,16 +144,25 @@
|
||||
v-if="showModalImportExport"
|
||||
@hide-modal="displayModalImportExport(false)"
|
||||
/>
|
||||
<CollectionsProperties
|
||||
:show="showModalEditProperties"
|
||||
:editing-properties="editingProperties"
|
||||
@hide-modal="displayModalEditProperties(false)"
|
||||
@set-collection-properties="setCollectionProperties"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { nextTick, ref } from "vue"
|
||||
import { clone, cloneDeep } from "lodash-es"
|
||||
import {
|
||||
graphqlCollections$,
|
||||
addGraphqlFolder,
|
||||
saveGraphqlRequestAs,
|
||||
cascaseParentCollectionForHeaderAuth,
|
||||
editGraphqlCollection,
|
||||
editGraphqlFolder,
|
||||
} from "~/newstore/collections"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||
@@ -163,8 +174,14 @@ import { platform } from "~/platform"
|
||||
import { useService } from "dioc/vue"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { computed } from "vue"
|
||||
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
|
||||
import {
|
||||
HoppCollection,
|
||||
HoppGQLRequest,
|
||||
makeGQLRequest,
|
||||
} from "@hoppscotch/data"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
import { updateInheritedPropertiesForAffectedRequests } from "~/helpers/collection/collection"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -185,6 +202,7 @@ const showModalAddRequest = ref(false)
|
||||
const showModalAddFolder = ref(false)
|
||||
const showModalEditFolder = ref(false)
|
||||
const showModalEditRequest = ref(false)
|
||||
const showModalEditProperties = ref(false)
|
||||
|
||||
const editingCollection = ref<HoppCollection<HoppGQLRequest> | null>(null)
|
||||
const editingCollectionIndex = ref<number | null>(null)
|
||||
@@ -195,6 +213,18 @@ const editingFolderPath = ref("")
|
||||
const editingRequest = ref<HoppGQLRequest | null>(null)
|
||||
const editingRequestIndex = ref<number | null>(null)
|
||||
|
||||
const editingProperties = ref<{
|
||||
collection: HoppCollection<HoppGQLRequest> | null
|
||||
isRootCollection: boolean
|
||||
path: string
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}>({
|
||||
collection: null,
|
||||
isRootCollection: false,
|
||||
path: "",
|
||||
inheritedProperties: undefined,
|
||||
})
|
||||
|
||||
const filterText = ref("")
|
||||
|
||||
const filteredCollections = computed(() => {
|
||||
@@ -276,6 +306,12 @@ const displayModalEditRequest = (shouldDisplay: boolean) => {
|
||||
if (!shouldDisplay) resetSelectedData()
|
||||
}
|
||||
|
||||
const displayModalEditProperties = (show: boolean) => {
|
||||
showModalEditProperties.value = show
|
||||
|
||||
if (!show) resetSelectedData()
|
||||
}
|
||||
|
||||
const editCollection = (
|
||||
collection: HoppCollection<HoppGQLRequest>,
|
||||
collectionIndex: number
|
||||
@@ -302,6 +338,11 @@ const onAddRequest = ({
|
||||
|
||||
saveGraphqlRequestAs(path, newRequest)
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
path,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
tabs.createNewTab({
|
||||
saveContext: {
|
||||
originLocation: "user-collection",
|
||||
@@ -310,6 +351,10 @@ const onAddRequest = ({
|
||||
},
|
||||
request: newRequest,
|
||||
isDirty: false,
|
||||
inheritedProperties: {
|
||||
auth,
|
||||
headers,
|
||||
},
|
||||
})
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
@@ -401,6 +446,128 @@ const duplicateRequest = ({
|
||||
})
|
||||
}
|
||||
|
||||
const selectRequest = ({
|
||||
request,
|
||||
folderPath,
|
||||
requestIndex,
|
||||
}: {
|
||||
request: HoppGQLRequest
|
||||
folderPath: string
|
||||
requestIndex: number
|
||||
}) => {
|
||||
const possibleTab = tabs.getTabRefWithSaveContext({
|
||||
originLocation: "user-collection",
|
||||
folderPath: folderPath,
|
||||
requestIndex: requestIndex,
|
||||
})
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
folderPath,
|
||||
"graphql"
|
||||
)
|
||||
// Switch to that request if that request is open
|
||||
if (possibleTab) {
|
||||
tabs.setActiveTab(possibleTab.value.id)
|
||||
return
|
||||
}
|
||||
|
||||
tabs.createNewTab({
|
||||
saveContext: {
|
||||
originLocation: "user-collection",
|
||||
folderPath: folderPath,
|
||||
requestIndex: requestIndex,
|
||||
},
|
||||
request: cloneDeep(
|
||||
makeGQLRequest({
|
||||
name: request.name,
|
||||
url: request.url,
|
||||
query: request.query,
|
||||
headers: request.headers,
|
||||
variables: request.variables,
|
||||
auth: request.auth,
|
||||
})
|
||||
),
|
||||
isDirty: false,
|
||||
inheritedProperties: {
|
||||
auth,
|
||||
headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the collection is already in the root
|
||||
* @param id - path of the collection
|
||||
* @returns boolean - true if the collection is already in the root
|
||||
*/
|
||||
const isAlreadyInRoot = (id: string) => {
|
||||
const indexPath = id.split("/")
|
||||
return indexPath.length === 1
|
||||
}
|
||||
|
||||
const editProperties = ({
|
||||
collectionIndex,
|
||||
collection,
|
||||
}: {
|
||||
collectionIndex: string | null
|
||||
collection: HoppCollection<HoppGQLRequest> | null
|
||||
}) => {
|
||||
if (collectionIndex === null || collection === null) return
|
||||
|
||||
const parentIndex = collectionIndex.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
|
||||
let inheritedProperties = {}
|
||||
|
||||
if (parentIndex) {
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
parentIndex,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
} as HoppInheritedProperty
|
||||
}
|
||||
|
||||
editingProperties.value = {
|
||||
collection,
|
||||
isRootCollection: isAlreadyInRoot(collectionIndex),
|
||||
path: collectionIndex,
|
||||
inheritedProperties,
|
||||
}
|
||||
|
||||
displayModalEditProperties(true)
|
||||
}
|
||||
|
||||
const setCollectionProperties = (newCollection: {
|
||||
collection: HoppCollection<HoppGQLRequest>
|
||||
path: string
|
||||
isRootCollection: boolean
|
||||
}) => {
|
||||
const { collection, path, isRootCollection } = newCollection
|
||||
if (isRootCollection) {
|
||||
editGraphqlCollection(parseInt(path), collection)
|
||||
} else {
|
||||
editGraphqlFolder(path, collection)
|
||||
}
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
path,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
nextTick(() => {
|
||||
updateInheritedPropertiesForAffectedRequests(
|
||||
path,
|
||||
{
|
||||
auth,
|
||||
headers,
|
||||
},
|
||||
"graphql"
|
||||
)
|
||||
})
|
||||
|
||||
displayModalEditProperties(false)
|
||||
}
|
||||
const resetSelectedData = () => {
|
||||
editingCollection.value = null
|
||||
editingCollectionIndex.value = null
|
||||
|
||||
@@ -679,7 +679,7 @@ const onAddRequest = (requestName: string) => {
|
||||
if (!path) return
|
||||
const insertionIndex = saveRESTRequestAs(path, newRequest)
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path, "rest")
|
||||
|
||||
tabs.createNewTab({
|
||||
request: newRequest,
|
||||
@@ -1329,7 +1329,10 @@ const selectRequest = (selectedRequest: {
|
||||
// If there is a request with this save context, switch into it
|
||||
let possibleTab = null
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(folderPath)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
folderPath,
|
||||
"rest"
|
||||
)
|
||||
|
||||
if (collectionsType.value.type === "team-collections") {
|
||||
possibleTab = tabs.getTabRefWithSaveContext({
|
||||
@@ -1402,7 +1405,8 @@ const dropRequest = (payload: {
|
||||
|
||||
if (collectionsType.value.type === "my-collections" && folderPath) {
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
destinationCollectionIndex
|
||||
destinationCollectionIndex,
|
||||
"rest"
|
||||
)
|
||||
|
||||
possibleTab = tabs.getTabRefWithSaveContext({
|
||||
@@ -1595,7 +1599,8 @@ const dropCollection = (payload: {
|
||||
)
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
|
||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
|
||||
"rest"
|
||||
)
|
||||
|
||||
const inheritedProperty = {
|
||||
@@ -1605,7 +1610,8 @@ const dropCollection = (payload: {
|
||||
|
||||
updateInheritedPropertiesForAffectedRequests(
|
||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
|
||||
inheritedProperty
|
||||
inheritedProperty,
|
||||
"rest"
|
||||
)
|
||||
|
||||
draggingToRoot.value = false
|
||||
@@ -1975,7 +1981,10 @@ const editProperties = (payload: {
|
||||
let inheritedProperties = {}
|
||||
|
||||
if (parentIndex) {
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(parentIndex)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
parentIndex,
|
||||
"rest"
|
||||
)
|
||||
|
||||
inheritedProperties = {
|
||||
auth,
|
||||
@@ -2005,13 +2014,17 @@ const setCollectionProperties = (newCollection: {
|
||||
editRESTFolder(path, collection)
|
||||
}
|
||||
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path, "rest")
|
||||
|
||||
nextTick(() => {
|
||||
updateInheritedPropertiesForAffectedRequests(path, {
|
||||
auth,
|
||||
headers,
|
||||
})
|
||||
updateInheritedPropertiesForAffectedRequests(
|
||||
path,
|
||||
{
|
||||
auth,
|
||||
headers,
|
||||
},
|
||||
"rest"
|
||||
)
|
||||
})
|
||||
|
||||
displayModalEditProperties(false)
|
||||
|
||||
@@ -37,6 +37,18 @@
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
v-if="!isRootCollection"
|
||||
label="Inherit"
|
||||
:icon="authName === 'Inherit' ? IconCircleDot : IconCircle"
|
||||
:active="authName === 'Inherit'"
|
||||
@click="
|
||||
() => {
|
||||
auth.authType = 'inherit'
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
label="Basic Auth"
|
||||
:icon="authName === 'Basic Auth' ? IconCircleDot : IconCircle"
|
||||
@@ -149,6 +161,17 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="auth.authType === 'inherit'" class="p-4">
|
||||
<span v-if="inheritedProperties?.auth">
|
||||
Inherited
|
||||
{{ getAuthName(inheritedProperties.auth.inheritedAuth.authType) }}
|
||||
from Parent Collection {{ inheritedProperties?.auth.parentName }}
|
||||
</span>
|
||||
<span v-else>
|
||||
Please save this request in any collection to inherit the
|
||||
authorization
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="auth.authType === 'bearer'">
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput
|
||||
@@ -203,6 +226,8 @@ import { pluckRef } from "@composables/ref"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
import { onMounted } from "vue"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -210,12 +235,24 @@ const colorMode = useColorMode()
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: HoppGQLAuth
|
||||
isCollectionProperty?: boolean
|
||||
isRootCollection?: boolean
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:modelValue", value: HoppGQLAuth): void
|
||||
}>()
|
||||
|
||||
onMounted(() => {
|
||||
if (props.isRootCollection && auth.value.authType === "inherit") {
|
||||
auth.value = {
|
||||
authType: "none",
|
||||
authActive: true,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const auth = useVModel(props, "modelValue", emit)
|
||||
|
||||
const AUTH_KEY_NAME = {
|
||||
@@ -224,12 +261,20 @@ const AUTH_KEY_NAME = {
|
||||
"oauth-2": "OAuth 2.0",
|
||||
"api-key": "API key",
|
||||
none: "None",
|
||||
inherit: "Inherit",
|
||||
} as const
|
||||
|
||||
const authType = pluckRef(auth, "authType")
|
||||
|
||||
const authName = computed(() =>
|
||||
AUTH_KEY_NAME[authType.value] ? AUTH_KEY_NAME[authType.value] : "None"
|
||||
)
|
||||
|
||||
const getAuthName = (type: HoppGQLAuth["authType"] | undefined) => {
|
||||
if (!type) return "None"
|
||||
return AUTH_KEY_NAME[type] ? AUTH_KEY_NAME[type] : "None"
|
||||
}
|
||||
|
||||
const authActive = pluckRef(auth, "authActive")
|
||||
|
||||
const clearContent = () => {
|
||||
|
||||
@@ -215,6 +215,60 @@
|
||||
</template>
|
||||
</draggable>
|
||||
|
||||
<draggable
|
||||
v-model="inheritedProperties"
|
||||
item-key="id"
|
||||
animation="250"
|
||||
handle=".draggable-handle"
|
||||
draggable=".draggable-content"
|
||||
ghost-class="cursor-move"
|
||||
chosen-class="bg-primaryLight"
|
||||
drag-class="cursor-grabbing"
|
||||
>
|
||||
<template #item="{ element: header, index }">
|
||||
<div
|
||||
class="draggable-content group flex divide-x divide-dividerLight border-b border-dividerLight"
|
||||
>
|
||||
<span>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconLock"
|
||||
class="cursor-auto bg-divider text-secondaryLight opacity-25"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</span>
|
||||
<SmartEnvInput
|
||||
v-model="header.header.key"
|
||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||
readonly
|
||||
/>
|
||||
<SmartEnvInput
|
||||
:model-value="
|
||||
header.source === 'auth' ? mask(header) : header.header.value
|
||||
"
|
||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||
readonly
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="header.source === 'auth'"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t(masking ? 'state.show' : 'state.hide')"
|
||||
:icon="masking && header.source === 'auth' ? IconEye : IconEyeOff"
|
||||
@click="toggleMask()"
|
||||
/>
|
||||
<span v-else class="aspect-square w-[2.05rem]"></span>
|
||||
<span>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:icon="IconInfo"
|
||||
:title="`This header is inherited from Parent Collection ${
|
||||
header.inheritedFrom ?? ''
|
||||
}`"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
|
||||
<HoppSmartPlaceholder
|
||||
v-if="workingHeaders.length === 0"
|
||||
:src="`/images/states/${colorMode.value}/add_category.svg`"
|
||||
@@ -247,7 +301,7 @@ import IconArrowUpRight from "~icons/lucide/arrow-up-right"
|
||||
import IconLock from "~icons/lucide/lock"
|
||||
import IconEye from "~icons/lucide/eye"
|
||||
import IconEyeOff from "~icons/lucide/eye-off"
|
||||
|
||||
import IconInfo from "~icons/lucide/info"
|
||||
import { computed, reactive, ref, watch } from "vue"
|
||||
import * as E from "fp-ts/Either"
|
||||
import * as O from "fp-ts/Option"
|
||||
@@ -272,13 +326,18 @@ import { objRemoveKey } from "~/helpers/functional/object"
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { HoppGQLHeader } from "~/helpers/graphql"
|
||||
import { throwError } from "~/helpers/functional/error"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
|
||||
const colorMode = useColorMode()
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
|
||||
// v-model integration with props and emit
|
||||
const props = defineProps<{ modelValue: HoppGQLRequest }>()
|
||||
const props = defineProps<{
|
||||
modelValue: HoppGQLRequest
|
||||
isCollectionProperty?: boolean
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:modelValue", value: HoppGQLRequest): void
|
||||
@@ -565,6 +624,64 @@ const computedHeaders = computed(() =>
|
||||
}))
|
||||
)
|
||||
|
||||
const inheritedProperties = computed(() => {
|
||||
if (!props.inheritedProperties?.auth || !props.inheritedProperties.headers)
|
||||
return []
|
||||
|
||||
//filter out headers that are already in the request headers
|
||||
|
||||
const inheritedHeaders = props.inheritedProperties.headers.filter(
|
||||
(header) =>
|
||||
!request.value.headers.some(
|
||||
(requestHeader) => requestHeader.key === header.key
|
||||
)
|
||||
)
|
||||
|
||||
const headers = inheritedHeaders.map((header, index) => ({
|
||||
inheritedFrom: props.inheritedProperties?.headers[index].parentName,
|
||||
source: "headers",
|
||||
id: `header-${index}`,
|
||||
header: {
|
||||
key: header.inheritedHeader?.key,
|
||||
value: header.inheritedHeader?.value,
|
||||
active: header.inheritedHeader?.active,
|
||||
},
|
||||
}))
|
||||
|
||||
let auth = [] as {
|
||||
inheritedFrom: string
|
||||
source: "auth"
|
||||
id: string
|
||||
header: {
|
||||
key: string
|
||||
value: string
|
||||
active: boolean
|
||||
}
|
||||
}[]
|
||||
|
||||
const computedAuthHeader = getComputedAuthHeaders(
|
||||
request.value,
|
||||
props.inheritedProperties.auth.inheritedAuth
|
||||
)[0]
|
||||
|
||||
if (
|
||||
computedAuthHeader &&
|
||||
request.value.auth.authType === "inherit" &&
|
||||
request.value.auth.authActive
|
||||
) {
|
||||
auth = [
|
||||
{
|
||||
inheritedFrom: props.inheritedProperties?.auth.parentName,
|
||||
source: "auth",
|
||||
id: `header-auth`,
|
||||
header: computedAuthHeader,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
return [...headers, ...auth]
|
||||
})
|
||||
|
||||
const masking = ref(true)
|
||||
|
||||
const toggleMask = () => {
|
||||
|
||||
@@ -34,10 +34,16 @@
|
||||
:label="`${t('tab.headers')}`"
|
||||
:info="activeGQLHeadersCount === 0 ? null : `${activeGQLHeadersCount}`"
|
||||
>
|
||||
<GraphqlHeaders v-model="request" />
|
||||
<GraphqlHeaders
|
||||
v-model="request"
|
||||
:inherited-properties="inheritedProperties"
|
||||
/>
|
||||
</HoppSmartTab>
|
||||
<HoppSmartTab :id="'authorization'" :label="`${t('tab.authorization')}`">
|
||||
<GraphqlAuthorization v-model="request.auth" />
|
||||
<GraphqlAuthorization
|
||||
v-model="request.auth"
|
||||
:inherited-properties="inheritedProperties"
|
||||
/>
|
||||
</HoppSmartTab>
|
||||
</HoppSmartTabs>
|
||||
<CollectionsSaveRequest
|
||||
@@ -69,6 +75,7 @@ import { useService } from "dioc/vue"
|
||||
import { InterceptorService } from "~/services/interceptor.service"
|
||||
import { editGraphqlRequest } from "~/newstore/collections"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
|
||||
const VALID_GQL_OPERATIONS = [
|
||||
"query",
|
||||
@@ -93,6 +100,7 @@ const props = withDefaults(
|
||||
response?: GQLResponseEvent[] | null
|
||||
optionTab?: GQLOptionTabs
|
||||
tabId: string
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}>(),
|
||||
{
|
||||
response: null,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
v-model="tab.document.request"
|
||||
v-model:response="tab.document.response"
|
||||
v-model:option-tab="tab.document.optionTabPreference"
|
||||
v-model:inherited-properties="tab.document.inheritedProperties"
|
||||
:tab-id="tab.id"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -231,7 +231,6 @@ const auth = useVModel(props, "modelValue", emit)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.isRootCollection && auth.value.authType === "inherit") {
|
||||
console.log("isRootCollection", auth.value.authType)
|
||||
auth.value = {
|
||||
authType: "none",
|
||||
authActive: true,
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as E from "fp-ts/Either"
|
||||
import { getService } from "~/modules/dioc"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
|
||||
/**
|
||||
* Resolve save context on reorder
|
||||
@@ -111,9 +112,11 @@ export function updateSaveContextForAffectedRequests(
|
||||
|
||||
export function updateInheritedPropertiesForAffectedRequests(
|
||||
path: string,
|
||||
inheritedProperties: HoppInheritedProperty
|
||||
inheritedProperties: HoppInheritedProperty,
|
||||
type: "rest" | "graphql"
|
||||
) {
|
||||
const tabService = getService(RESTTabService)
|
||||
const tabService =
|
||||
type === "rest" ? getService(RESTTabService) : getService(GQLTabService)
|
||||
const tabs = tabService.getTabsRefTo((tab) => {
|
||||
return (
|
||||
tab.document.saveContext?.originLocation === "user-collection" &&
|
||||
|
||||
@@ -27,7 +27,7 @@ export const getDefaultGQLRequest = (): HoppGQLRequest => ({
|
||||
}`,
|
||||
query: DEFAULT_QUERY,
|
||||
auth: {
|
||||
authType: "none",
|
||||
authType: "inherit",
|
||||
authActive: true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { HoppGQLRequest } from "@hoppscotch/data"
|
||||
import { GQLResponseEvent } from "./connection"
|
||||
import { GQLOptionTabs } from "~/components/graphql/RequestOptions.vue"
|
||||
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||
|
||||
export type HoppGQLSaveContext =
|
||||
| {
|
||||
@@ -73,4 +74,10 @@ export type HoppGQLDocument = {
|
||||
* Options tab preference for the current tab's document
|
||||
*/
|
||||
optionTabPreference?: GQLOptionTabs
|
||||
|
||||
/**
|
||||
* The inherited properties from the parent collection
|
||||
* (if any)
|
||||
*/
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}
|
||||
|
||||
@@ -64,8 +64,12 @@ export function navigateToFolderWithIndexPath(
|
||||
}
|
||||
|
||||
export function cascaseParentCollectionForHeaderAuth(
|
||||
folderPath: string | undefined
|
||||
folderPath: string | undefined,
|
||||
type: "rest" | "graphql"
|
||||
) {
|
||||
const collectionStore =
|
||||
type === "rest" ? restCollectionStore : graphqlCollectionStore
|
||||
|
||||
let auth: HoppInheritedProperty["auth"] = {
|
||||
parentID: folderPath ?? "",
|
||||
parentName: "",
|
||||
@@ -87,7 +91,7 @@ export function cascaseParentCollectionForHeaderAuth(
|
||||
// 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,
|
||||
collectionStore.value.state,
|
||||
[...path.slice(0, i + 1)] // Create a copy of the path array
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user