feat: tab service added (#3367)

This commit is contained in:
Anwarul Islam
2023-10-11 18:51:07 +06:00
committed by GitHub
parent 51510566bc
commit ba31cdabea
60 changed files with 1112 additions and 841 deletions

View File

@@ -59,7 +59,9 @@
:key="`contentTypeItem-${contentTypeIndex}`"
:label="contentTypeItem"
:info-icon="
contentTypeItem === body.contentType ? IconDone : null
contentTypeItem === body.contentType
? IconDone
: undefined
"
:active-info-icon="contentTypeItem === body.contentType"
@click="
@@ -136,7 +138,7 @@ import IconDone from "~icons/lucide/check"
import IconExternalLink from "~icons/lucide/external-link"
import IconInfo from "~icons/lucide/info"
import IconRefreshCW from "~icons/lucide/refresh-cw"
import { RequestOptionTabs } from "./RequestOptions.vue"
import { RESTOptionTabs } from "./RequestOptions.vue"
const colorMode = useColorMode()
const t = useI18n()
@@ -147,7 +149,7 @@ const props = defineProps<{
}>()
const emit = defineEmits<{
(e: "change-tab", value: RequestOptionTabs): void
(e: "change-tab", value: RESTOptionTabs): void
(e: "update:headers", value: HoppRESTHeader[]): void
(e: "update:body", value: HoppRESTReqBody): void
}>()
@@ -164,7 +166,7 @@ const overridenContentType = computed(() =>
)
)
const contentTypeOverride = (tab: RequestOptionTabs) => {
const contentTypeOverride = (tab: RESTOptionTabs) => {
emit("change-tab", tab)
if (!isContentTypeAlreadyExist()) {
// TODO: Fix this

View File

@@ -157,9 +157,10 @@ import {
import IconCopy from "~icons/lucide/copy"
import IconCheck from "~icons/lucide/check"
import IconWrapText from "~icons/lucide/wrap-text"
import { currentActiveTab } from "~/helpers/rest/tab"
import cloneDeep from "lodash-es/cloneDeep"
import { platform } from "~/platform"
import { RESTTabService } from "~/services/tab/rest"
import { useService } from "dioc/vue"
const t = useI18n()
@@ -173,7 +174,8 @@ const emit = defineEmits<{
const toast = useToast()
const request = ref(cloneDeep(currentActiveTab.value.document.request))
const tabs = useService(RESTTabService)
const request = ref(cloneDeep(tabs.currentActiveTab.value.document.request))
const codegenType = ref<CodegenName>("shell-curl")
const errorState = ref(false)
@@ -242,7 +244,7 @@ watch(
() => props.show,
(goingToShow) => {
if (goingToShow) {
request.value = cloneDeep(currentActiveTab.value.document.request)
request.value = cloneDeep(tabs.currentActiveTab.value.document.request)
platform.analytics?.logEvent({
type: "HOPP_REST_CODEGEN_OPENED",

View File

@@ -273,10 +273,13 @@ import { aggregateEnvs$, getAggregateEnvs } from "~/newstore/environments"
import { useVModel } from "@vueuse/core"
import { useService } from "dioc/vue"
import { InspectionService, InspectorResult } from "~/services/inspection"
import { currentTabID } from "~/helpers/rest/tab"
import { RESTTabService } from "~/services/tab/rest"
const t = useI18n()
const toast = useToast()
const tabs = useService(RESTTabService)
const colorMode = useColorMode()
const idTicker = ref(0)
@@ -515,13 +518,13 @@ const changeTab = (tab: ComputedHeader["source"]) => {
const inspectionService = useService(InspectionService)
const headerKeyResults = inspectionService.getResultViewFor(
currentTabID.value,
tabs.currentTabID.value,
(result) =>
result.locations.type === "header" && result.locations.position === "key"
)
const headerValueResults = inspectionService.getResultViewFor(
currentTabID.value,
tabs.currentTabID.value,
(result) =>
result.locations.type === "header" && result.locations.position === "value"
)

View File

@@ -93,13 +93,16 @@ import IconWrapText from "~icons/lucide/wrap-text"
import IconClipboard from "~icons/lucide/clipboard"
import IconCheck from "~icons/lucide/check"
import IconTrash2 from "~icons/lucide/trash-2"
import { currentActiveTab } from "~/helpers/rest/tab"
import { platform } from "~/platform"
import { RESTTabService } from "~/services/tab/rest"
import { useService } from "dioc/vue"
const t = useI18n()
const toast = useToast()
const tabs = useService(RESTTabService)
const curl = ref("")
const curlEditor = ref<any | null>(null)
@@ -149,7 +152,7 @@ const handleImport = () => {
type: "HOPP_REST_IMPORT_CURL",
})
currentActiveTab.value.document.request = req
tabs.currentActiveTab.value.document.request = req
} catch (e) {
console.error(e)
toast.error(`${t("error.curl_invalid_format")}`)

View File

@@ -202,12 +202,13 @@ import { objRemoveKey } from "@functional/object"
import { useVModel } from "@vueuse/core"
import { useService } from "dioc/vue"
import { InspectionService, InspectorResult } from "~/services/inspection"
import { currentTabID } from "~/helpers/rest/tab"
import { RESTTabService } from "~/services/tab/rest"
const colorMode = useColorMode()
const t = useI18n()
const toast = useToast()
const tabs = useService(RESTTabService)
const idTicker = ref(0)
@@ -410,13 +411,13 @@ const clearContent = () => {
const inspectionService = useService(InspectionService)
const parameterKeyResults = inspectionService.getResultViewFor(
currentTabID.value,
tabs.currentTabID.value,
(result) =>
result.locations.type === "parameter" && result.locations.position === "key"
)
const parameterValueResults = inspectionService.getResultViewFor(
currentTabID.value,
tabs.currentTabID.value,
(result) =>
result.locations.type === "parameter" &&
result.locations.position === "value"

View File

@@ -217,6 +217,7 @@
@hide-modal="showCurlImportModal = false"
/>
<HttpCodegenModal
v-if="showCodegenModal"
:show="showCodegenModal"
@hide-modal="showCodegenModal = false"
/>
@@ -257,7 +258,6 @@ import IconLink2 from "~icons/lucide/link-2"
import IconRotateCCW from "~icons/lucide/rotate-ccw"
import IconSave from "~icons/lucide/save"
import IconShare2 from "~icons/lucide/share-2"
import { HoppRESTTab, currentTabID } from "~/helpers/rest/tab"
import { getDefaultRESTRequest } from "~/helpers/rest/default"
import { RESTHistoryEntry, restHistory$ } from "~/newstore/history"
import { platform } from "~/platform"
@@ -265,6 +265,9 @@ import { HoppGQLRequest, HoppRESTRequest } from "@hoppscotch/data"
import { useService } from "dioc/vue"
import { InspectionService } from "~/services/inspection"
import { InterceptorService } from "~/services/interceptor.service"
import { HoppTab } from "~/services/tab"
import { HoppRESTDocument } from "~/helpers/rest/document"
import { RESTTabService } from "~/services/tab/rest"
const t = useI18n()
const interceptorService = useService(InterceptorService)
@@ -286,7 +289,7 @@ const toast = useToast()
const { subscribeToStream } = useStreamSubscriber()
const props = defineProps<{ modelValue: HoppRESTTab }>()
const props = defineProps<{ modelValue: HoppTab<HoppRESTDocument> }>()
const emit = defineEmits(["update:modelValue"])
const tab = useVModel(props, "modelValue", emit)
@@ -434,7 +437,7 @@ const clearContent = () => {
}
const updateRESTResponse = (response: HoppRESTResponse | null) => {
tab.value.response = response
tab.value.document.response = response
}
const copyLinkIcon = refAutoReset<
@@ -642,5 +645,6 @@ const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT")
const inspectionService = useService(InspectionService)
const tabResults = inspectionService.getResultViewFor(currentTabID.value)
const tabs = useService(RESTTabService)
const tabResults = inspectionService.getResultViewFor(tabs.currentTabID.value)
</script>

View File

@@ -1,6 +1,6 @@
<template>
<HoppSmartTabs
v-model="selectedOptionsTab"
v-model="selectedOptionTab"
styles="sticky overflow-x-auto flex-shrink-0 bg-primary top-upperMobilePrimaryStickyFold sm:top-upperPrimaryStickyFold z-10"
render-inactive-tabs
>
@@ -15,7 +15,7 @@
<HttpBody
v-model:headers="request.headers"
v-model:body="request.body"
@change-tab="changeTab"
@change-tab="changeOptionTab"
/>
</HoppSmartTab>
<HoppSmartTab
@@ -23,7 +23,7 @@
:label="`${t('tab.headers')}`"
:info="`${newActiveHeadersCount$}`"
>
<HttpHeaders v-model="request" @change-tab="changeTab" />
<HttpHeaders v-model="request" @change-tab="changeOptionTab" />
</HoppSmartTab>
<HoppSmartTab :id="'authorization'" :label="`${t('tab.authorization')}`">
<HttpAuthorization v-model="request.auth" />
@@ -55,31 +55,43 @@
import { useI18n } from "@composables/i18n"
import { HoppRESTRequest } from "@hoppscotch/data"
import { useVModel } from "@vueuse/core"
import { computed, ref } from "vue"
import { computed } from "vue"
import { defineActionHandler } from "~/helpers/actions"
export type RequestOptionTabs =
| "params"
| "bodyParams"
| "headers"
| "authorization"
| "preRequestScript"
| "tests"
const VALID_OPTION_TABS = [
"params",
"bodyParams",
"headers",
"authorization",
"preRequestScript",
"tests",
] as const
export type RESTOptionTabs = (typeof VALID_OPTION_TABS)[number]
const t = useI18n()
// v-model integration with props and emit
const props = defineProps<{ modelValue: HoppRESTRequest }>()
const props = withDefaults(
defineProps<{
modelValue: HoppRESTRequest
optionTab: RESTOptionTabs
}>(),
{
optionTab: "params",
}
)
const emit = defineEmits<{
(e: "update:modelValue", value: HoppRESTRequest): void
(e: "update:optionTab", value: RESTOptionTabs): void
}>()
const request = useVModel(props, "modelValue", emit)
const selectedOptionTab = useVModel(props, "optionTab", emit)
const selectedOptionsTab = ref<RequestOptionTabs>("params")
const changeTab = (e: RequestOptionTabs) => {
selectedOptionsTab.value = e
const changeOptionTab = (e: RESTOptionTabs) => {
selectedOptionTab.value = e
}
const newActiveParamsCount$ = computed(() => {
@@ -101,6 +113,6 @@ const newActiveHeadersCount$ = computed(() => {
})
defineActionHandler("request.open-tab", ({ tab }) => {
selectedOptionsTab.value = tab as RequestOptionTabs
selectedOptionTab.value = tab as RESTOptionTabs
})
</script>

View File

@@ -2,10 +2,13 @@
<AppPaneLayout layout-id="rest-primary">
<template #primary>
<HttpRequest v-model="tab" />
<HttpRequestOptions v-model="tab.document.request" />
<HttpRequestOptions
v-model="tab.document.request"
v-model:option-tab="tab.document.optionTabPreference"
/>
</template>
<template #secondary>
<HttpResponse v-model:tab="tab" />
<HttpResponse v-model:document="tab.document" />
</template>
</AppPaneLayout>
</template>
@@ -13,16 +16,17 @@
<script setup lang="ts">
import { watch } from "vue"
import { useVModel } from "@vueuse/core"
import { HoppRESTTab } from "~/helpers/rest/tab"
import { cloneDeep } from "lodash-es"
import { isEqualHoppRESTRequest } from "@hoppscotch/data"
import { HoppTab } from "~/services/tab"
import { HoppRESTDocument } from "~/helpers/rest/document"
// TODO: Move Response and Request execution code to over here
const props = defineProps<{ modelValue: HoppRESTTab }>()
const props = defineProps<{ modelValue: HoppTab<HoppRESTDocument> }>()
const emit = defineEmits<{
(e: "update:modelValue", val: HoppRESTTab): void
(e: "update:modelValue", val: HoppTab<HoppRESTDocument>): void
}>()
const tab = useVModel(props, "modelValue", emit)

View File

@@ -1,36 +1,33 @@
<template>
<div class="flex flex-col flex-1 relative">
<HttpResponseMeta :response="tab.response" />
<HttpResponseMeta :response="doc.response" />
<LensesResponseBodyRenderer
v-if="!loading && hasResponse"
v-model:selected-tab-preference="selectedTabPreference"
v-model:tab="tab"
v-model:document="doc"
/>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from "vue"
import { HoppRESTTab } from "~/helpers/rest/tab"
import { useVModel } from "@vueuse/core"
import { computed } from "vue"
import { HoppRESTDocument } from "~/helpers/rest/document"
const props = defineProps<{
tab: HoppRESTTab
document: HoppRESTDocument
}>()
const emit = defineEmits<{
(e: "update:tab", val: HoppRESTTab): void
(e: "update:tab", val: HoppRESTDocument): void
}>()
const tab = useVModel(props, "tab", emit)
const selectedTabPreference = ref<string | null>(null)
const doc = useVModel(props, "document", emit)
const hasResponse = computed(
() =>
tab.value.response?.type === "success" ||
tab.value.response?.type === "fail"
doc.value.response?.type === "success" ||
doc.value.response?.type === "fail"
)
const loading = computed(() => tab.value.response?.type === "loading")
const loading = computed(() => doc.value.response?.type === "loading")
</script>

View File

@@ -93,10 +93,11 @@ import { useColorMode } from "@composables/theming"
import { getStatusCodeReasonPhrase } from "~/helpers/utils/statusCodes"
import { useService } from "dioc/vue"
import { InspectionService } from "~/services/inspection"
import { currentTabID } from "~/helpers/rest/tab"
import { RESTTabService } from "~/services/tab/rest"
const t = useI18n()
const colorMode = useColorMode()
const tabs = useService(RESTTabService)
const props = defineProps<{
response: HoppRESTResponse | null | undefined
@@ -146,7 +147,7 @@ const statusCategory = computed(() => {
const inspectionService = useService(InspectionService)
const tabResults = inspectionService.getResultViewFor(
currentTabID.value,
tabs.currentTabID.value,
(result) => result.locations.type === "response"
)
</script>

View File

@@ -96,16 +96,17 @@ import { ref } from "vue"
import { TippyComponent } from "vue-tippy"
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
import { useI18n } from "~/composables/i18n"
import { HoppRESTTab } from "~/helpers/rest/tab"
import IconXCircle from "~icons/lucide/x-circle"
import IconXSquare from "~icons/lucide/x-square"
import IconFileEdit from "~icons/lucide/file-edit"
import IconCopy from "~icons/lucide/copy"
import { HoppTab } from "~/services/tab"
import { HoppRESTDocument } from "~/helpers/rest/document"
const t = useI18n()
defineProps<{
tab: HoppRESTTab
tab: HoppTab<HoppRESTDocument>
isRemovable: boolean
}>()