@@ -47,6 +47,7 @@ interface Field {
const props = defineProps<{
field: Field
+ readonly?: boolean
}>()
const t = useI18n()
diff --git a/packages/hoppscotch-common/src/components/graphql/FieldLink.vue b/packages/hoppscotch-common/src/components/graphql/FieldLink.vue
index 54934355..d4ba445e 100644
--- a/packages/hoppscotch-common/src/components/graphql/FieldLink.vue
+++ b/packages/hoppscotch-common/src/components/graphql/FieldLink.vue
@@ -1,16 +1,16 @@
-
+
-
-
+
+
{{ field.name }}
@@ -20,6 +20,7 @@
diff --git a/packages/hoppscotch-common/src/components/graphql/TypeLink.vue b/packages/hoppscotch-common/src/components/graphql/TypeLink.vue
index f352b579..40c73362 100644
--- a/packages/hoppscotch-common/src/components/graphql/TypeLink.vue
+++ b/packages/hoppscotch-common/src/components/graphql/TypeLink.vue
@@ -12,13 +12,15 @@ import { renderType, useExplorer } from "~/helpers/graphql/explorer"
const props = defineProps<{
type: GraphQLType
clickable?: boolean
+ readonly?: boolean
+ isHeading?: boolean
}>()
const { push } = useExplorer()
const handleTypeClick = (event: MouseEvent, namedType: GraphQLNamedType) => {
event.preventDefault()
- push({ name: namedType.name, def: namedType })
+ push({ name: namedType.name, def: namedType, readonly: props.readonly })
}
/**
@@ -31,7 +33,11 @@ const renderedComponent = computed(() => {
return h(
"span",
{
- class: "hopp-doc-explorer-type-name",
+ class: `hopp-doc-explorer-type-name ${
+ props.isHeading ? "!text-lg !font-bold" : ""
+ }
+ ${props.clickable ? "cursor-pointer hover:underline" : ""}
+ `,
onClick: (event: MouseEvent) =>
props.clickable ? handleTypeClick(event, namedType) : undefined,
},
diff --git a/packages/hoppscotch-common/src/helpers/graphql/explorer.ts b/packages/hoppscotch-common/src/helpers/graphql/explorer.ts
index e453ddd5..e2c78156 100644
--- a/packages/hoppscotch-common/src/helpers/graphql/explorer.ts
+++ b/packages/hoppscotch-common/src/helpers/graphql/explorer.ts
@@ -32,6 +32,7 @@ export type ExplorerFieldDef =
* Represents a single item in the explorer navigation stack
*/
export type ExplorerNavStackItem = {
+ readonly?: boolean
name: string
def?: GraphQLNamedType | ExplorerFieldDef
}
@@ -71,7 +72,7 @@ export function useExplorer(initialSchema?: GraphQLSchema) {
// Avoid pushing duplicate items
if (lastItem.def === item.def) return
- navStack.value.push(item)
+ navStack.value.push(lastItem.readonly ? { ...item, readonly: true } : item)
}
/**
diff --git a/packages/hoppscotch-common/src/helpers/graphql/query.ts b/packages/hoppscotch-common/src/helpers/graphql/query.ts
index 3d7084d3..37f6b1d9 100644
--- a/packages/hoppscotch-common/src/helpers/graphql/query.ts
+++ b/packages/hoppscotch-common/src/helpers/graphql/query.ts
@@ -188,7 +188,11 @@ export function useQuery() {
// Check if paths are different at the top level
const existingTopField = existingOperation.selectionSet
.selections[0] as FieldNode
- if (existingTopField.name.value !== queryPath[0].name) {
+
+ if (
+ existingTopField.name.value !==
+ (queryPath && queryPath[0] && queryPath[0]?.name)
+ ) {
append = true
currentSelectionSet.selections = []
}
@@ -365,10 +369,7 @@ export function useQuery() {
}
}
- const isItemInOperation = (
- item: ExplorerFieldDef,
- isArgument = false
- ): boolean => {
+ const isFieldInOperation = (item: ExplorerFieldDef): boolean => {
const operation = getOperation(
tabs.currentActiveTab.value?.document.cursorPosition || 0
)
@@ -397,22 +398,44 @@ export function useQuery() {
// Check based on type
return currentSelections.some((selection) => {
if (selection.kind !== Kind.FIELD) return false
- return isArgument
- ? selection.arguments?.some(
- (argNode) => argNode.name.value === item.name
- )
- : selection.name.value === item.name
+ return selection.name.value === item.name
})
}
+ const isArgumentInOperation = (item: ExplorerFieldDef): boolean => {
+ const { cursorPosition } = tabs.currentActiveTab.value?.document
+ const operation = getOperation(cursorPosition)
+ if (!operation) return false
+
+ // Start from the operation's selection set
+ let args: ArgumentNode[] = []
+
+ // change the currentSelections based on current Field by the cursor position
+ operation.selectionSet.selections.forEach((selection) => {
+ if (selection.kind === Kind.FIELD) {
+ const fieldNode = selection as FieldNode
+ if (
+ fieldNode.loc &&
+ fieldNode.loc.start <= cursorPosition &&
+ fieldNode.loc.end >= cursorPosition
+ ) {
+ args = fieldNode.arguments || []
+ }
+ }
+ })
+
+ if (args.length === 0) return false
+
+ return args.some((arg) => arg.name.value === item.name)
+ }
+
return {
handleAddField: (field: ExplorerFieldDef) => handleOperation(field),
handleAddArgument: (arg: ExplorerFieldDef) => handleOperation(arg, true),
updatedQuery,
cursorPosition,
operationDefinitions: operations,
- isFieldInOperation: (field: ExplorerFieldDef) => isItemInOperation(field),
- isArgumentInOperation: (arg: ExplorerFieldDef) =>
- isItemInOperation(arg, true),
+ isFieldInOperation,
+ isArgumentInOperation,
}
}