refactor: init newstore for request body

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
liyasthomas
2021-08-14 14:31:16 +05:30
parent e9eee0703d
commit a129d7eb13
4 changed files with 188 additions and 128 deletions

View File

@@ -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() {

View File

@@ -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">

View File

@@ -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,
} }
} }

View File

@@ -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()