Compare commits

...

12 Commits

Author SHA1 Message Date
nivedin
4aaf5c279c fix: show response section only if response is present 2024-01-23 22:24:01 +05:30
nivedin
dcb8b2c511 refactor: update loading state UI in embed 2024-01-23 22:24:01 +05:30
nivedin
58d3ef900f refactor: minor code update 2024-01-23 22:24:01 +05:30
nivedin
0a94c169bd fix: no selected option tab during the initial load 2024-01-23 22:24:01 +05:30
nivedin
80eb4c7701 fix: shortcode subscription failing to initialize 2024-01-23 22:24:01 +05:30
nivedin
6ed4b73a34 chore: code refactor 2024-01-23 22:24:01 +05:30
nivedin
52ef2d8d32 fix: remove redundant array creation 2024-01-23 22:24:01 +05:30
nivedin
53e013e2a4 chore: minor padding update 2024-01-23 22:24:01 +05:30
nivedin
4a14de76c9 chore: minor code update 2024-01-23 22:24:01 +05:30
nivedin
a4aa808103 chore: minor update for team header-auth properties 2024-01-23 22:24:01 +05:30
nivedin
6d7b0e11a3 fix: add loading and error state 2024-01-23 22:24:01 +05:30
nivedin
ffff54b5af fix: update i18n text 2024-01-23 22:24:01 +05:30
11 changed files with 67 additions and 35 deletions

View File

@@ -70,7 +70,11 @@
v-model:option-tab="selectedOptionTab" v-model:option-tab="selectedOptionTab"
:properties="properties" :properties="properties"
/> />
<HttpResponse :document="tab.document" :is-embed="true" /> <HttpResponse
v-if="tab.document.response"
:document="tab.document"
:is-embed="true"
/>
</div> </div>
</template> </template>
@@ -88,18 +92,19 @@ import { runRESTRequest$ } from "~/helpers/RequestRunner"
import { HoppTab } from "~/services/tab" import { HoppTab } from "~/services/tab"
import { HoppRESTDocument } from "~/helpers/rest/document" import { HoppRESTDocument } from "~/helpers/rest/document"
import IconSave from "~icons/lucide/save" import IconSave from "~icons/lucide/save"
import { RESTOptionTabs } from "../http/RequestOptions.vue"
const t = useI18n() const t = useI18n()
const toast = useToast() const toast = useToast()
const props = defineProps<{ const props = defineProps<{
modelTab: HoppTab<HoppRESTDocument> modelTab: HoppTab<HoppRESTDocument>
properties: string[] properties: RESTOptionTabs[]
sharedRequestID: string sharedRequestID: string
}>() }>()
const tab = useModel(props, "modelTab") const tab = useModel(props, "modelTab")
const selectedOptionTab = ref(props.properties[0]) const selectedOptionTab = ref<RESTOptionTabs>(props.properties[0])
const requestCancelFunc: Ref<(() => void) | null> = ref(null) const requestCancelFunc: Ref<(() => void) | null> = ref(null)

View File

@@ -5,7 +5,7 @@
render-inactive-tabs render-inactive-tabs
> >
<HoppSmartTab <HoppSmartTab
v-if="properties ? properties.includes('parameters') : true" v-if="properties ? properties.includes('params') : true"
:id="'params'" :id="'params'"
:label="`${t('tab.parameters')}`" :label="`${t('tab.parameters')}`"
:info="`${newActiveParamsCount$}`" :info="`${newActiveParamsCount$}`"
@@ -13,7 +13,7 @@
<HttpParameters v-model="request.params" /> <HttpParameters v-model="request.params" />
</HoppSmartTab> </HoppSmartTab>
<HoppSmartTab <HoppSmartTab
v-if="properties ? properties.includes('body') : true" v-if="properties ? properties.includes('bodyParams') : true"
:id="'bodyParams'" :id="'bodyParams'"
:label="`${t('tab.body')}`" :label="`${t('tab.body')}`"
> >

View File

@@ -103,7 +103,7 @@ const widgets: Widget[] = [
}, },
] ]
type Tabs = "parameters" | "body" | "headers" | "authorization" type Tabs = "params" | "bodyParams" | "headers" | "authorization"
type EmbedOption = { type EmbedOption = {
selectedTab: Tabs selectedTab: Tabs
@@ -116,15 +116,15 @@ type EmbedOption = {
} }
const embedOption = ref<EmbedOption>({ const embedOption = ref<EmbedOption>({
selectedTab: "parameters", selectedTab: "params",
tabs: [ tabs: [
{ {
value: "parameters", value: "params",
label: t("tab.parameters"), label: t("tab.parameters"),
enabled: true, enabled: true,
}, },
{ {
value: "body", value: "bodyParams",
label: t("tab.body"), label: t("tab.body"),
enabled: true, enabled: true,
}, },

View File

@@ -225,10 +225,10 @@ const props = defineProps({
embedOptions: { embedOptions: {
type: Object as PropType<EmbedOption>, type: Object as PropType<EmbedOption>,
default: () => ({ default: () => ({
selectedTab: "parameters", selectedTab: "params",
tabs: [ tabs: [
{ {
value: "parameters", value: "params",
label: "shared_requests.parameters", label: "shared_requests.parameters",
enabled: true, enabled: true,
}, },
@@ -290,7 +290,7 @@ const widgets: Widget[] = [
}, },
] ]
type EmbedTabs = "parameters" | "body" | "headers" | "authorization" type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
type EmbedOption = { type EmbedOption = {
selectedTab: EmbedTabs selectedTab: EmbedTabs

View File

@@ -56,7 +56,7 @@ import { useI18n } from "~/composables/i18n"
const t = useI18n() const t = useI18n()
type EmbedTabs = "parameters" | "body" | "headers" | "authorization" type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
type EmbedOption = { type EmbedOption = {
selectedTab: EmbedTabs selectedTab: EmbedTabs
@@ -93,15 +93,15 @@ const props = defineProps({
embedOptions: { embedOptions: {
type: Object as PropType<EmbedOption>, type: Object as PropType<EmbedOption>,
default: () => ({ default: () => ({
selectedTab: "parameters", selectedTab: "params",
tabs: [ tabs: [
{ {
value: "parameters", value: "params",
label: "shared_requests.parameters", label: "shared_requests.parameters",
enabled: true, enabled: true,
}, },
{ {
value: "body", value: "bodyParams",
label: "shared_requests.body", label: "shared_requests.body",
enabled: true, enabled: true,
}, },

View File

@@ -21,7 +21,7 @@
/> />
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<div v-if="loading" class="flex flex-col items-center justify-center"> <div v-if="loading" class="flex flex-col items-center justify-center p-4">
<HoppSmartSpinner class="mb-4" /> <HoppSmartSpinner class="mb-4" />
<span class="text-secondaryLight">{{ t("state.loading") }}</span> <span class="text-secondaryLight">{{ t("state.loading") }}</span>
</div> </div>
@@ -136,15 +136,15 @@ const shareRequestCreatingLoading = ref(false)
const requestToShare = ref<HoppRESTRequest | null>(null) const requestToShare = ref<HoppRESTRequest | null>(null)
const embedOptions = ref<EmbedOption>({ const embedOptions = ref<EmbedOption>({
selectedTab: "parameters", selectedTab: "params",
tabs: [ tabs: [
{ {
value: "parameters", value: "params",
label: t("tab.parameters"), label: t("tab.parameters"),
enabled: false, enabled: false,
}, },
{ {
value: "body", value: "bodyParams",
label: t("tab.body"), label: t("tab.body"),
enabled: false, enabled: false,
}, },
@@ -208,7 +208,7 @@ const currentUser = useReadonlyStream(
const step = ref(1) const step = ref(1)
type EmbedTabs = "parameters" | "body" | "headers" | "authorization" type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
type EmbedOption = { type EmbedOption = {
selectedTab: EmbedTabs selectedTab: EmbedTabs
@@ -249,7 +249,15 @@ const loading = computed(
onLoggedIn(() => { onLoggedIn(() => {
try { try {
adapter.initialize() // wait for a bit to let the auth token to be set
// because in some race conditions, the token is not set this fixes that
const initLoadTimeout = setTimeout(() => {
adapter.initialize()
}, 10)
return () => {
clearTimeout(initLoadTimeout)
}
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }
@@ -313,15 +321,15 @@ const displayCustomizeRequestModal = (
info: t("shared_requests.button_info"), info: t("shared_requests.button_info"),
} }
embedOptions.value = { embedOptions.value = {
selectedTab: "parameters", selectedTab: "params",
tabs: [ tabs: [
{ {
value: "parameters", value: "params",
label: t("tab.parameters"), label: t("tab.parameters"),
enabled: false, enabled: false,
}, },
{ {
value: "body", value: "bodyParams",
label: t("tab.body"), label: t("tab.body"),
enabled: false, enabled: false,
}, },
@@ -451,7 +459,7 @@ const getErrorMessage = (err: GQLError<string>) => {
} }
switch (err.error) { switch (err.error) {
case "shortcode/not_found": case "shortcode/not_found":
return t("shared_request.not_found") return t("shared_requests.not_found")
default: default:
return t("error.something_went_wrong") return t("error.something_went_wrong")
} }

View File

@@ -57,7 +57,7 @@ import { computed } from "vue"
import { useI18n } from "~/composables/i18n" import { useI18n } from "~/composables/i18n"
type Tabs = "parameters" | "body" | "headers" | "authorization" type Tabs = "params" | "bodyParams" | "headers" | "authorization"
type EmbedOption = { type EmbedOption = {
selectedTab: Tabs selectedTab: Tabs

View File

@@ -156,6 +156,7 @@ export default class ShortcodeListAdapter {
const [shortcodeCreated$, shortcodeCreatedSub] = runAuthOnlyGQLSubscription( const [shortcodeCreated$, shortcodeCreatedSub] = runAuthOnlyGQLSubscription(
{ {
query: ShortcodeCreatedDocument, query: ShortcodeCreatedDocument,
variables: {},
} }
) )
@@ -172,6 +173,7 @@ export default class ShortcodeListAdapter {
const [shortcodeRevoked$, shortcodeRevokedSub] = runAuthOnlyGQLSubscription( const [shortcodeRevoked$, shortcodeRevokedSub] = runAuthOnlyGQLSubscription(
{ {
query: ShortcodeDeletedDocument, query: ShortcodeDeletedDocument,
variables: {},
} }
) )
@@ -188,6 +190,7 @@ export default class ShortcodeListAdapter {
const [shortcodeUpdated$, shortcodeUpdatedSub] = runAuthOnlyGQLSubscription( const [shortcodeUpdated$, shortcodeUpdatedSub] = runAuthOnlyGQLSubscription(
{ {
query: ShortcodeUpdatedDocument, query: ShortcodeUpdatedDocument,
variables: {},
} }
) )

View File

@@ -1034,6 +1034,11 @@ export default class NewTeamCollectionAdapter {
} }
} }
/**
* Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL team collections
* @param folderPath the path of the folder to cascade the auth from
* @returns the inherited auth and headers for the given folder path
*/
public cascadeParentCollectionForHeaderAuth(folderPath: string) { public cascadeParentCollectionForHeaderAuth(folderPath: string) {
let auth: HoppInheritedProperty["auth"] = { let auth: HoppInheritedProperty["auth"] = {
parentID: folderPath ?? "", parentID: folderPath ?? "",
@@ -1080,7 +1085,7 @@ export default class NewTeamCollectionAdapter {
authType: "inherit", authType: "inherit",
authActive: true, authActive: true,
} }
auth.parentID = [...path.slice(0, i + 1)].join("/") auth.parentID = path.slice(0, i + 1).join("/")
auth.parentName = parentFolder.title auth.parentName = parentFolder.title
} }
@@ -1089,9 +1094,12 @@ export default class NewTeamCollectionAdapter {
const parentFolderAuth = data.auth const parentFolderAuth = data.auth
const parentFolderHeaders = data.headers const parentFolderHeaders = data.headers
if (parentFolderAuth?.authType === "inherit" && path.length === 1) { if (
parentFolderAuth?.authType === "inherit" &&
path.slice(0, i + 1).length === 1
) {
auth = { auth = {
parentID: [...path.slice(0, i + 1)].join("/"), parentID: path.slice(0, i + 1).join("/"),
parentName: parentFolder.title, parentName: parentFolder.title,
inheritedAuth: auth.inheritedAuth, inheritedAuth: auth.inheritedAuth,
} }
@@ -1099,7 +1107,7 @@ export default class NewTeamCollectionAdapter {
if (parentFolderAuth?.authType !== "inherit") { if (parentFolderAuth?.authType !== "inherit") {
auth = { auth = {
parentID: [...path.slice(0, i + 1)].join("/"), parentID: path.slice(0, i + 1).join("/"),
parentName: parentFolder.title, parentName: parentFolder.title,
inheritedAuth: parentFolderAuth, inheritedAuth: parentFolderAuth,
} }
@@ -1112,7 +1120,7 @@ export default class NewTeamCollectionAdapter {
const index = headers.findIndex( const index = headers.findIndex(
(h) => h.inheritedHeader?.key === header.key (h) => h.inheritedHeader?.key === header.key
) )
const currentPath = [...path.slice(0, i + 1)].join("/") const currentPath = path.slice(0, i + 1).join("/")
if (index !== -1) { if (index !== -1) {
// Replace the existing header with the same key // Replace the existing header with the same key
headers[index] = { headers[index] = {

View File

@@ -68,7 +68,7 @@ export function navigateToFolderWithIndexPath(
} }
/** /**
* Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL * Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL personal collections
* @param folderPath the path of the folder to cascade the auth from * @param folderPath the path of the folder to cascade the auth from
* @param type the type of collection * @param type the type of collection
* @returns the inherited auth and headers for the given folder path * @returns the inherited auth and headers for the given folder path

View File

@@ -1,7 +1,14 @@
<template> <template>
<div class="flex flex-col justify-center"> <div class="flex flex-col justify-center">
<div <div
v-if="invalidLink" v-if="sharedRequestDetails.loading"
class="flex justify-center items-center py-5"
>
<HoppSmartSpinner />
</div>
<div
v-else-if="E.isLeft(sharedRequestDetails.data) || invalidLink"
class="flex flex-1 flex-col items-center justify-center p-8" class="flex flex-1 flex-col items-center justify-center p-8"
> >
<icon-lucide-alert-triangle class="svg-icons mb-2 opacity-75" /> <icon-lucide-alert-triangle class="svg-icons mb-2 opacity-75" />
@@ -12,8 +19,9 @@
{{ t("error.invalid_embed_link") }} {{ t("error.invalid_embed_link") }}
</p> </p>
</div> </div>
<Embeds <Embeds
v-else-if="!invalidLink && tab" v-else-if="tab"
v-model:modelTab="tab" v-model:modelTab="tab"
:properties="properties" :properties="properties"
:shared-request-i-d="sharedRequestID" :shared-request-i-d="sharedRequestID"