From 5a2eed60c908f0b64510cc118d60a0ac0d8db305 Mon Sep 17 00:00:00 2001 From: Nivedin <53208152+nivedin@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:15:19 +0530 Subject: [PATCH] fix: resolve multiple UI issues and account for `description` field in syncing context (#4309) * fix: collection properties header bulk update editor bug * chore: add migration step while resolving `headers` in the syncing context Resolve type errors. * fix: prevent inifinite loading state in add environments modal Toggle back the loading state if attempting to create an environment from a team workspace without specifying a name. * fix: tab change when clicking computed auth * fix: ensure tab change action works in GQL headers view `Go to Authorization tab` action. * chore: account for REST params while adding description fields Writing to store after pulling from the syncing context. --------- Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com> --- .../src/components/collections/Properties.vue | 6 ++ .../components/environments/teams/Details.vue | 2 + .../src/components/graphql/Headers.vue | 20 +++---- .../src/components/graphql/RequestOptions.vue | 6 ++ .../src/components/http/Headers.vue | 8 ++- .../collections/collections.platform.ts | 60 ++++++++++++++----- 6 files changed, 73 insertions(+), 29 deletions(-) diff --git a/packages/hoppscotch-common/src/components/collections/Properties.vue b/packages/hoppscotch-common/src/components/collections/Properties.vue index d9c80f16d..c79a4140a 100644 --- a/packages/hoppscotch-common/src/components/collections/Properties.vue +++ b/packages/hoppscotch-common/src/components/collections/Properties.vue @@ -17,6 +17,7 @@
{ emit("hide-modal") } +const changeOptionTab = (e: RESTOptionTabs) => { + activeTab.value = e +} + const copyCollectionID = () => { copyToClipboard(props.editingProperties.path) copyIcon.value = IconCheck diff --git a/packages/hoppscotch-common/src/components/environments/teams/Details.vue b/packages/hoppscotch-common/src/components/environments/teams/Details.vue index 64a0b403f..676408beb 100644 --- a/packages/hoppscotch-common/src/components/environments/teams/Details.vue +++ b/packages/hoppscotch-common/src/components/environments/teams/Details.vue @@ -354,7 +354,9 @@ const saveEnvironment = async () => { isLoading.value = true if (!editingName.value) { + isLoading.value = false toast.error(`${t("environment.invalid_name")}`) + return } diff --git a/packages/hoppscotch-common/src/components/graphql/Headers.vue b/packages/hoppscotch-common/src/components/graphql/Headers.vue index f86d96a39..1a6904fcf 100644 --- a/packages/hoppscotch-common/src/components/graphql/Headers.vue +++ b/packages/hoppscotch-common/src/components/graphql/Headers.vue @@ -127,19 +127,15 @@ :icon="masking ? IconEye : IconEyeOff" @click="toggleMask()" /> - +
+
@@ -235,6 +231,7 @@ import { useColorMode } from "@composables/theming" import { useToast } from "@composables/toast" import { GQLHeader, + HoppGQLAuth, HoppGQLRequest, parseRawKeyValueEntriesE, rawKeyValueEntriesToString, @@ -267,6 +264,7 @@ import IconLock from "~icons/lucide/lock" import IconPlus from "~icons/lucide/plus" import IconTrash2 from "~icons/lucide/trash-2" import IconWrapText from "~icons/lucide/wrap-text" +import { GQLOptionTabs } from "./RequestOptions.vue" const colorMode = useColorMode() const t = useI18n() @@ -281,6 +279,7 @@ const props = defineProps<{ const emit = defineEmits<{ (e: "update:modelValue", value: HoppGQLRequest): void + (e: "change-tab", value: GQLOptionTabs): void }>() const request = useVModel(props, "modelValue", emit) @@ -645,7 +644,7 @@ const inheritedProperties = computed(() => { const computedAuthHeader = getComputedAuthHeaders( request.value, - props.inheritedProperties.auth.inheritedAuth + props.inheritedProperties.auth.inheritedAuth as HoppGQLAuth )[0] if ( @@ -678,8 +677,5 @@ const mask = (header: any) => { return header.header.value } -// const changeTab = (tab: ComputedHeader["source"]) => { -// if (tab === "auth") emit("change-tab", "authorization") -// else emit("change-tab", "bodyParams") -// } +const changeTab = () => emit("change-tab", "authorization") diff --git a/packages/hoppscotch-common/src/components/graphql/RequestOptions.vue b/packages/hoppscotch-common/src/components/graphql/RequestOptions.vue index 8392fec8e..17f68aa50 100644 --- a/packages/hoppscotch-common/src/components/graphql/RequestOptions.vue +++ b/packages/hoppscotch-common/src/components/graphql/RequestOptions.vue @@ -37,6 +37,7 @@ @@ -261,6 +262,11 @@ const saveRequest = () => { const clearGQLQuery = () => { request.value.query = "" } + +const changeOptionTab = (e: GQLOptionTabs) => { + selectedOptionTab.value = e +} + defineActionHandler("request.send-cancel", runQuery) defineActionHandler("request.save", saveRequest) defineActionHandler("request.save-as", () => { diff --git a/packages/hoppscotch-common/src/components/http/Headers.vue b/packages/hoppscotch-common/src/components/http/Headers.vue index a8e559357..a19517359 100644 --- a/packages/hoppscotch-common/src/components/http/Headers.vue +++ b/packages/hoppscotch-common/src/components/http/Headers.vue @@ -49,8 +49,14 @@ /> +
-
+
({ + ...item, + description: "description" in item ? item.description : "", + })) +} + function exportedCollectionToHoppCollection( collection: ExportedUserCollectionREST | ExportedUserCollectionGQL, collectionType: "REST" | "GQL" ): HoppCollection { if (collectionType == "REST") { const restCollection = collection as ExportedUserCollectionREST + const data = restCollection.data && restCollection.data !== "null" ? JSON.parse(restCollection.data) @@ -113,9 +126,10 @@ function exportedCollectionToHoppCollection( auth: { authType: "inherit", authActive: false }, headers: [], } + return { id: restCollection.id, - v: 2, + v: 3, name: restCollection.name, folders: restCollection.folders.map((folder) => exportedCollectionToHoppCollection(folder, collectionType) @@ -140,26 +154,31 @@ function exportedCollectionToHoppCollection( testScript, requestVariables, } = request + + const resolvedParams = addDescriptionField(params) + const resolvedHeaders = addDescriptionField(headers) + return { v, id, name, endpoint, method, - params, - requestVariables: requestVariables, + params: resolvedParams, + requestVariables, auth, - headers, + headers: resolvedHeaders, body, preRequestScript, testScript, } }), auth: data.auth, - headers: data.headers, + headers: addDescriptionField(data.headers), } } else { const gqlCollection = collection as ExportedUserCollectionGQL + const data = gqlCollection.data && gqlCollection.data !== "null" ? JSON.parse(gqlCollection.data) @@ -170,25 +189,34 @@ function exportedCollectionToHoppCollection( return { id: gqlCollection.id, - v: 2, + v: 3, name: gqlCollection.name, folders: gqlCollection.folders.map((folder) => exportedCollectionToHoppCollection(folder, collectionType) ), - requests: gqlCollection.requests.map( - ({ v, auth, headers, name, id, query, url, variables }) => ({ + requests: gqlCollection.requests.map((request) => { + const requestParsedResult = HoppGQLRequest.safeParse(request) + if (requestParsedResult.type === "ok") { + return requestParsedResult.value + } + + const { v, auth, headers, name, id, query, url, variables } = request + + const resolvedHeaders = addDescriptionField(headers) + + return { id, v, auth, - headers, + headers: resolvedHeaders, name, query, url, variables, - }) - ) as HoppGQLRequest[], + } + }), auth: data.auth, - headers: data.headers, + headers: addDescriptionField(data.headers), } } } @@ -349,17 +377,17 @@ function setupUserCollectionCreatedSubscription() { name: res.right.userCollectionCreated.title, folders: [], requests: [], - v: 2, + v: 3, auth: data.auth, - headers: data.headers, + headers: addDescriptionField(data.headers), }) : addRESTCollection({ name: res.right.userCollectionCreated.title, folders: [], requests: [], - v: 2, + v: 3, auth: data.auth, - headers: data?.headers, + headers: addDescriptionField(data.headers), }) const localIndex = collectionStore.value.state.length - 1