refactor: init newstore for request body
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
bg-primary
|
bg-primary
|
||||||
border-b border-dividerLight
|
border-b border-dividerLight
|
||||||
flex flex-1
|
flex flex-1
|
||||||
pl-4 pl-4
|
pl-4
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
"
|
"
|
||||||
@@ -44,11 +44,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</span>
|
</span>
|
||||||
<SmartToggle :on="rawInput" class="px-2" @change="rawInput = !rawInput">
|
|
||||||
{{ $t("raw_input") }}
|
|
||||||
</SmartToggle>
|
|
||||||
</div>
|
</div>
|
||||||
<HttpBodyParameters v-if="!rawInput" :content-type="contentType" />
|
<HttpBodyParameters
|
||||||
|
v-if="contentType == 'multipart/form-data'"
|
||||||
|
:content-type="contentType"
|
||||||
|
/>
|
||||||
<HttpRawBody v-else :content-type="contentType" />
|
<HttpRawBody v-else :content-type="contentType" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -63,7 +63,6 @@ export default defineComponent({
|
|||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
contentType: pluckRef(useRESTRequestBody(), "contentType"),
|
contentType: pluckRef(useRESTRequestBody(), "contentType"),
|
||||||
rawInput: pluckRef(useRESTRequestBody(), "isRaw"),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
justify-between
|
justify-between
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label>
|
<label class="font-semibold text-secondaryLight">
|
||||||
{{ $t("request_body") }}
|
{{ $t("request_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
@@ -38,11 +38,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <div v-if="typeof bodyParams !== 'string'"> -->
|
||||||
<div
|
<div
|
||||||
v-for="(param, index) in bodyParams"
|
v-for="(param, index) in bodyParams"
|
||||||
:key="`param-${index}`"
|
:key="`param-${index}`"
|
||||||
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
||||||
:class="{ 'border-t': index == 0 }"
|
|
||||||
>
|
>
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
|
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
@@ -88,13 +88,12 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-if="EXPERIMENTAL_URL_BAR_ENABLED && !requestBodyParamIsFile(index)"
|
v-if="EXPERIMENTAL_URL_BAR_ENABLED && !param.isFile"
|
||||||
v-model="param.value"
|
v-model="param.value"
|
||||||
:placeholder="$t('count.value', { count: index + 1 })"
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
styles="
|
styles="
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
flex
|
flex
|
||||||
|
|
||||||
flex-1
|
flex-1
|
||||||
py-1
|
py-1
|
||||||
px-4
|
px-4
|
||||||
@@ -109,7 +108,7 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="!EXPERIMENTAL_URL_BAR_ENABLED && !requestBodyParamIsFile(index)"
|
v-if="!EXPERIMENTAL_URL_BAR_ENABLED && !param.isFile"
|
||||||
class="
|
class="
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
flex flex-1
|
flex flex-1
|
||||||
@@ -208,124 +207,35 @@
|
|||||||
@click.native="addBodyParam"
|
@click.native="addBodyParam"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- </div> -->
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
export default {
|
import { defineComponent, onMounted } from "@nuxtjs/composition-api"
|
||||||
props: {
|
import { pluckRef } from "~/helpers/utils/composables"
|
||||||
bodyParams: { type: Array, default: () => [] },
|
import { addFormDataEntry, useRESTRequestBody } from "~/newstore/RESTSession"
|
||||||
},
|
import { useSetting } from "~/newstore/settings"
|
||||||
computed: {
|
|
||||||
contentType() {
|
export default defineComponent({
|
||||||
return this.$store.state.request.contentType
|
setup() {
|
||||||
},
|
const bodyParams = pluckRef(useRESTRequestBody(), "body")
|
||||||
},
|
|
||||||
watch: {
|
onMounted(() => {
|
||||||
bodyParams: {
|
console.log(bodyParams.value)
|
||||||
handler(newValue) {
|
})
|
||||||
if (
|
return {
|
||||||
(newValue[newValue.length - 1]?.key !== "" ||
|
bodyParams,
|
||||||
newValue[newValue.length - 1]?.value !== "") &&
|
EXPERIMENTAL_URL_BAR_ENABLED: useSetting("EXPERIMENTAL_URL_BAR_ENABLED"),
|
||||||
newValue.length
|
|
||||||
)
|
|
||||||
this.addBodyParam()
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (!this.bodyParams?.length) {
|
|
||||||
this.addRequestBodyParam()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clearContent() {
|
addBodyParam() {
|
||||||
this.$emit("clear-content")
|
addFormDataEntry({ key: "", value: "", active: true, isFile: false })
|
||||||
},
|
|
||||||
removeRequestBodyParam(index) {
|
|
||||||
const paramArr = this.$store.state.request.bodyParams.filter(
|
|
||||||
(item, itemIndex) =>
|
|
||||||
itemIndex !== index &&
|
|
||||||
(Object.prototype.hasOwnProperty.call(item, "active")
|
|
||||||
? item.active === true
|
|
||||||
: true)
|
|
||||||
)
|
|
||||||
this.setRawParams(paramArr)
|
|
||||||
this.$emit("remove-request-body-param", index)
|
|
||||||
},
|
|
||||||
addRequestBodyParam() {
|
|
||||||
this.$emit("add-request-body-param")
|
|
||||||
},
|
|
||||||
setRequestAttachment(event, index) {
|
|
||||||
const { files } = event.target
|
|
||||||
this.$store.commit("setFilesBodyParams", {
|
|
||||||
index,
|
|
||||||
value: Array.from(files),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
requestBodyParamIsFile(index) {
|
|
||||||
const bodyParamValue = this.bodyParams?.[index]?.value
|
|
||||||
const isFile = bodyParamValue?.[0] instanceof File
|
|
||||||
return isFile
|
|
||||||
},
|
|
||||||
chipDelete(paramIndex, fileIndex) {
|
|
||||||
this.$store.commit("removeFile", {
|
|
||||||
index: paramIndex,
|
|
||||||
fileIndex,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateBodyParams(event, index, type) {
|
|
||||||
this.$store.commit(type, {
|
|
||||||
index,
|
|
||||||
value: event.target.value,
|
|
||||||
})
|
|
||||||
const paramArr = this.$store.state.request.bodyParams.filter((item) =>
|
|
||||||
Object.prototype.hasOwnProperty.call(item, "active")
|
|
||||||
? item.active === true
|
|
||||||
: true
|
|
||||||
)
|
|
||||||
|
|
||||||
this.setRawParams(paramArr)
|
|
||||||
},
|
|
||||||
toggleActive(index, param) {
|
|
||||||
const paramArr = this.$store.state.request.bodyParams.filter(
|
|
||||||
(item, itemIndex) => {
|
|
||||||
if (index === itemIndex) {
|
|
||||||
return !param.active
|
|
||||||
} else {
|
|
||||||
return Object.prototype.hasOwnProperty.call(item, "active")
|
|
||||||
? item.active === true
|
|
||||||
: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
this.setRawParams(paramArr)
|
|
||||||
|
|
||||||
this.$store.commit("setActiveBodyParams", {
|
|
||||||
index,
|
|
||||||
value: Object.prototype.hasOwnProperty.call(param, "active")
|
|
||||||
? !param.active
|
|
||||||
: false,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
setRawParams(filteredParamArr) {
|
|
||||||
let rawParams = {}
|
|
||||||
filteredParamArr.forEach((_param) => {
|
|
||||||
rawParams = {
|
|
||||||
...rawParams,
|
|
||||||
[_param.key]: _param.value,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const rawParamsStr = JSON.stringify(rawParams, null, 2)
|
|
||||||
this.$store.commit("setState", {
|
|
||||||
value: rawParamsStr,
|
|
||||||
attribute: "rawParams",
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
updateBodyParam() {},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -15,12 +15,23 @@ export type HoppRESTHeader = {
|
|||||||
active: boolean
|
active: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HoppRESTReqBody = {
|
export type FormDataKeyValue = {
|
||||||
contentType: ValidContentTypes
|
key: string
|
||||||
body: string
|
active: boolean
|
||||||
isRaw: boolean
|
} & ({ isFile: true; value: Blob } | { isFile: false; value: string })
|
||||||
|
|
||||||
|
export type HoppRESTReqBodyFormData = {
|
||||||
|
contentType: "multipart/form-data"
|
||||||
|
body: FormDataKeyValue[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type HoppRESTReqBody =
|
||||||
|
| {
|
||||||
|
contentType: Exclude<ValidContentTypes, "multipart/form-data">
|
||||||
|
body: string
|
||||||
|
}
|
||||||
|
| HoppRESTReqBodyFormData
|
||||||
|
|
||||||
export interface HoppRESTRequest {
|
export interface HoppRESTRequest {
|
||||||
v: string
|
v: string
|
||||||
|
|
||||||
@@ -55,14 +66,12 @@ function parseRequestBody(x: any): HoppRESTReqBody {
|
|||||||
return {
|
return {
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
body: x.rawParams,
|
body: x.rawParams,
|
||||||
isRaw: x.rawInput,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
body: "",
|
body: "",
|
||||||
isRaw: x.rawInput,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { pluck, distinctUntilChanged, map, filter } from "rxjs/operators"
|
|||||||
import { Ref } from "@nuxtjs/composition-api"
|
import { Ref } from "@nuxtjs/composition-api"
|
||||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||||
import {
|
import {
|
||||||
|
FormDataKeyValue,
|
||||||
HoppRESTHeader,
|
HoppRESTHeader,
|
||||||
HoppRESTParam,
|
HoppRESTParam,
|
||||||
HoppRESTReqBody,
|
HoppRESTReqBody,
|
||||||
@@ -12,6 +13,7 @@ import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
|
|||||||
import { useStream } from "~/helpers/utils/composables"
|
import { useStream } from "~/helpers/utils/composables"
|
||||||
import { HoppTestResult } from "~/helpers/types/HoppTestResult"
|
import { HoppTestResult } from "~/helpers/types/HoppTestResult"
|
||||||
import { HoppRESTAuth } from "~/helpers/types/HoppRESTAuth"
|
import { HoppRESTAuth } from "~/helpers/types/HoppRESTAuth"
|
||||||
|
import { ValidContentTypes } from "~/helpers/utils/contenttypes"
|
||||||
|
|
||||||
type RESTSession = {
|
type RESTSession = {
|
||||||
request: HoppRESTRequest
|
request: HoppRESTRequest
|
||||||
@@ -36,7 +38,6 @@ const defaultRESTRequest: HoppRESTRequest = {
|
|||||||
body: {
|
body: {
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
body: "",
|
body: "",
|
||||||
isRaw: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +197,112 @@ const dispatchers = defineDispatchers({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setContentType(
|
||||||
|
curr: RESTSession,
|
||||||
|
{ newContentType }: { newContentType: ValidContentTypes }
|
||||||
|
) {
|
||||||
|
// TODO: persist body evenafter switching content typees
|
||||||
|
if (curr.request.body.contentType !== "multipart/form-data") {
|
||||||
|
if (newContentType === "multipart/form-data") {
|
||||||
|
// Going from non-formdata to form-data, discard contents and set empty array as body
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// non-formdata to non-formdata, keep body and set content type
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: newContentType,
|
||||||
|
body: curr.request.body.body,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (newContentType !== "multipart/form-data") {
|
||||||
|
// Going from formdata to non-formdata, discard contents and set empty string
|
||||||
|
return {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: newContentType,
|
||||||
|
body: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// form-data to form-data ? just set the content type ¯\_(ツ)_/¯
|
||||||
|
return {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: newContentType,
|
||||||
|
body: curr.request.body.body,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addFormDataEntry(curr: RESTSession, { entry }: { entry: FormDataKeyValue }) {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (curr.request.body.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [...curr.request.body.body, entry],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeFormDataEntry(curr: RESTSession, { index }: { index: number }) {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (curr.request.body.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: curr.request.body.body.filter((_, i) => i !== index),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateFormDataEntry(
|
||||||
|
curr: RESTSession,
|
||||||
|
{ index, entry }: { index: number; entry: FormDataKeyValue }
|
||||||
|
) {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (curr.request.body.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: curr.request.body.body.map((x, i) => (i !== index ? x : entry)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearAllFormDataEntries(curr: RESTSession) {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (curr.request.body.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...curr.request,
|
||||||
|
body: <HoppRESTReqBody>{
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
setRequestBody(curr: RESTSession, { newBody }: { newBody: HoppRESTReqBody }) {
|
setRequestBody(curr: RESTSession, { newBody }: { newBody: HoppRESTReqBody }) {
|
||||||
return {
|
return {
|
||||||
request: {
|
request: {
|
||||||
@@ -422,6 +529,41 @@ export function setRESTTestResults(newResults: HoppTestResult | null) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addFormDataEntry(entry: FormDataKeyValue) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "addFormDataEntry",
|
||||||
|
payload: {
|
||||||
|
entry,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeFormDataEntry(index: number) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "removeFormDataEntry",
|
||||||
|
payload: {
|
||||||
|
index,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateFormDataEntry(index: number, entry: FormDataKeyValue) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "updateFormDataEntry",
|
||||||
|
payload: {
|
||||||
|
index,
|
||||||
|
entry,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearAllFormDataEntries() {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "clearAllFormDataEntries",
|
||||||
|
payload: {},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const restRequest$ = restSessionStore.subject$.pipe(
|
export const restRequest$ = restSessionStore.subject$.pipe(
|
||||||
pluck("request"),
|
pluck("request"),
|
||||||
distinctUntilChanged()
|
distinctUntilChanged()
|
||||||
|
|||||||
Reference in New Issue
Block a user