fix: form data request as body

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
liyasthomas
2021-08-14 19:11:05 +05:30
parent 2051b8788a
commit 691629890f
7 changed files with 180 additions and 99 deletions

View File

@@ -38,7 +38,6 @@
/> />
</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}`"
@@ -51,7 +50,6 @@
styles=" styles="
bg-primaryLight bg-primaryLight
flex flex
flex-1 flex-1
py-1 py-1
px-4 px-4
@@ -59,9 +57,10 @@
" "
@change=" @change="
updateBodyParam(index, { updateBodyParam(index, {
key: $event.target.value, key: $event,
value: param.value, value: param.value,
active: param.active, active: param.active,
isFile: param.isFile,
}) })
" "
/> />
@@ -84,54 +83,14 @@
key: $event.target.value, key: $event.target.value,
value: param.value, value: param.value,
active: param.active, active: param.active,
isFile: param.isFile,
}) })
" "
/> />
<SmartEnvInput <div v-if="param.isFile" class="file-chips-container hide-scrollbar">
v-if="EXPERIMENTAL_URL_BAR_ENABLED && !param.isFile" <div class="space-x-2 file-chips-wrapper">
v-model="param.value"
:placeholder="$t('count.value', { count: index + 1 })"
styles="
bg-primaryLight
flex
flex-1
py-1
px-4
focus:outline-none
"
@change="
updateBodyParam(index, {
key: param.key,
value: $event.target.value,
active: param.active,
})
"
/>
<input
v-if="!EXPERIMENTAL_URL_BAR_ENABLED && !param.isFile"
class="
bg-primaryLight
flex flex-1
py-2
px-4
truncate
focus:outline-none
"
:placeholder="$t('count.value', { count: index + 1 })"
:name="'value' + index"
:value="param.value"
@change="
updateBodyParam(index, {
key: param.key,
value: $event.target.value,
active: param.active,
})
"
/>
<div v-else class="file-chips-container">
<div class="file-chips-wrapper">
<SmartDeletableChip <SmartDeletableChip
v-for="(file, fileIndex) in Array.from(bodyParams[index].value)" v-for="(file, fileIndex) in param.value"
:key="`param-${index}-file-${fileIndex}`" :key="`param-${index}-file-${fileIndex}`"
@chip-delete="chipDelete(index, fileIndex)" @chip-delete="chipDelete(index, fileIndex)"
> >
@@ -139,6 +98,68 @@
</SmartDeletableChip> </SmartDeletableChip>
</div> </div>
</div> </div>
<span v-else class="flex flex-1">
<SmartEnvInput
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
v-model="param.value"
:placeholder="$t('count.value', { count: index + 1 })"
styles="
bg-primaryLight
flex
flex-1
py-1
px-4
focus:outline-none
"
@change="
updateBodyParam(index, {
key: param.key,
value: $event,
active: param.active,
isFile: param.isFile,
})
"
/>
<input
v-else
class="
bg-primaryLight
flex flex-1
py-2
px-4
truncate
focus:outline-none
"
:placeholder="$t('count.value', { count: index + 1 })"
:name="'value' + index"
:value="param.value"
@change="
updateBodyParam(index, {
key: param.key,
value: $event.target.value,
active: param.active,
isFile: param.isFile,
})
"
/>
</span>
<span>
<label for="attachment" class="p-0">
<ButtonSecondary
class="w-full"
icon="attach_file"
@click.native="$refs.attachment[index].click()"
/>
</label>
<input
ref="attachment"
class="input"
name="attachment"
type="file"
multiple
@change="setRequestAttachment(index, param, $event)"
/>
</span>
<span> <span>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
@@ -162,27 +183,11 @@
key: param.key, key: param.key,
value: param.value, value: param.value,
active: param.hasOwnProperty('active') ? !param.active : false, active: param.hasOwnProperty('active') ? !param.active : false,
isFile: param.isFile,
}) })
" "
/> />
</span> </span>
<span>
<label for="attachment" class="p-0">
<ButtonSecondary
class="w-full"
icon="attach_file"
@click.native="$refs.attachment[index].click()"
/>
</label>
<input
ref="attachment"
class="input"
name="attachment"
type="file"
multiple
@change="setRequestAttachment($event, index)"
/>
</span>
<span> <span>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
@@ -207,34 +212,106 @@
@click.native="addBodyParam" @click.native="addBodyParam"
/> />
</div> </div>
<!-- </div> -->
</AppSection> </AppSection>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted } from "@nuxtjs/composition-api" import { defineComponent, onMounted, Ref, watch } from "@nuxtjs/composition-api"
import { FormDataKeyValue } from "~/helpers/types/HoppRESTRequest"
import { pluckRef } from "~/helpers/utils/composables" import { pluckRef } from "~/helpers/utils/composables"
import { addFormDataEntry, useRESTRequestBody } from "~/newstore/RESTSession" import {
addFormDataEntry,
deleteAllFormDataEntries,
deleteFormDataEntry,
updateFormDataEntry,
useRESTRequestBody,
} from "~/newstore/RESTSession"
import { useSetting } from "~/newstore/settings" import { useSetting } from "~/newstore/settings"
export default defineComponent({ export default defineComponent({
setup() { setup() {
const bodyParams = pluckRef(useRESTRequestBody(), "body") const bodyParams = pluckRef<any, any>(useRESTRequestBody(), "body") as Ref<
FormDataKeyValue[]
>
const addBodyParam = () => {
addFormDataEntry({ key: "", value: "", active: true, isFile: false })
}
const updateBodyParam = (index: number, entry: FormDataKeyValue) => {
updateFormDataEntry(index, entry)
}
const deleteBodyParam = (index: number) => {
deleteFormDataEntry(index)
}
const clearContent = () => {
deleteAllFormDataEntries()
}
const chipDelete = (paramIndex: number, fileIndex: number) => {
const entry = bodyParams.value[paramIndex]
if (entry.isFile) {
entry.value.splice(fileIndex, 1)
if (entry.value.length === 0) {
updateFormDataEntry(paramIndex, {
...entry,
isFile: false,
value: "",
})
return
}
}
updateFormDataEntry(paramIndex, entry)
}
const setRequestAttachment = (
index: number,
entry: FormDataKeyValue,
event: InputEvent
) => {
console.log(index, event)
const fileEntry: FormDataKeyValue = {
...entry,
isFile: true,
value: Array.from((event.target as HTMLInputElement).files!),
}
updateFormDataEntry(index, fileEntry)
}
watch(
bodyParams,
() => {
if (
bodyParams.value.length > 0 &&
(bodyParams.value[bodyParams.value.length - 1].key !== "" ||
bodyParams.value[bodyParams.value.length - 1].value !== "")
)
addBodyParam()
},
{ deep: true }
)
onMounted(() => { onMounted(() => {
console.log(bodyParams.value) if (!bodyParams.value?.length) {
addBodyParam()
}
}) })
return { return {
bodyParams, bodyParams,
addBodyParam,
updateBodyParam,
deleteBodyParam,
clearContent,
setRequestAttachment,
chipDelete,
EXPERIMENTAL_URL_BAR_ENABLED: useSetting("EXPERIMENTAL_URL_BAR_ENABLED"), EXPERIMENTAL_URL_BAR_ENABLED: useSetting("EXPERIMENTAL_URL_BAR_ENABLED"),
} }
}, },
methods: {
addBodyParam() {
addFormDataEntry({ key: "", value: "", active: true, isFile: false })
},
updateBodyParam() {},
},
}) })
</script> </script>
@@ -243,10 +320,12 @@ export default defineComponent({
@apply flex flex-1; @apply flex flex-1;
@apply whitespace-nowrap; @apply whitespace-nowrap;
@apply overflow-auto; @apply overflow-auto;
@apply bg-primaryDark; @apply bg-primaryLight;
.file-chips-wrapper { .file-chips-wrapper {
@apply flex; @apply flex;
@apply px-4;
@apply py-1;
@apply w-0; @apply w-0;
} }
} }

View File

@@ -82,7 +82,7 @@
@change=" @change="
updateHeader(index, { updateHeader(index, {
key: header.key, key: header.key,
value: $event.target.value, value: $event,
active: header.active, active: header.active,
}) })
" "

View File

@@ -57,7 +57,7 @@
" "
@change=" @change="
updateParam(index, { updateParam(index, {
key: $event.target.value, key: $event,
value: param.value, value: param.value,
active: param.active, active: param.active,
}) })
@@ -100,7 +100,7 @@
@change=" @change="
updateParam(index, { updateParam(index, {
key: param.key, key: param.key,
value: $event.target.value, value: $event,
active: param.active, active: param.active,
}) })
" "

View File

@@ -1,8 +1,9 @@
<template> <template>
<span class="chip"> <span class="chip">
<span><slot></slot></span> <i class="opacity-75 material-icons">attachment</i>
<span class="px-2"><slot></slot></span>
<ButtonSecondary <ButtonSecondary
class="rounded p-2 close-button icon" class="rounded close-button"
icon="close" icon="close"
@click.native="$emit('chip-delete')" @click.native="$emit('chip-delete')"
/> />
@@ -15,15 +16,13 @@
@apply items-center; @apply items-center;
@apply justify-center; @apply justify-center;
@apply rounded; @apply rounded;
@apply m-1; @apply pl-2;
@apply pl-4; @apply pr-0.5;
@apply bg-primaryDark; @apply bg-primary;
@apply text-secondary;
@apply border border-divider; @apply border border-divider;
} }
.close-button { .close-button {
@apply text-base; @apply p-0.5;
} }
</style> </style>

View File

@@ -12,7 +12,6 @@
:class="styles" :class="styles"
contenteditable="true" contenteditable="true"
@keydown.enter.prevent="$emit('enter', $event)" @keydown.enter.prevent="$emit('enter', $event)"
@change="$emit('change', $event)"
@keyup="$emit('keyup', $event)" @keyup="$emit('keyup', $event)"
@click="$emit('click', $event)" @click="$emit('click', $event)"
@keydown="$emit('keydown', $event)" @keydown="$emit('keydown', $event)"
@@ -133,6 +132,7 @@ export default defineComponent({
if (!this.highlightEnabled) { if (!this.highlightEnabled) {
this.htmlOutput = this.internalValue this.htmlOutput = this.internalValue
this.$emit("input", this.internalValue) this.$emit("input", this.internalValue)
this.$emit("change", this.internalValue)
return return
} }
@@ -232,6 +232,7 @@ export default defineComponent({
}) })
this.$emit("input", this.internalValue) this.$emit("input", this.internalValue)
this.$emit("change", this.internalValue)
}, },
renderTippy() { renderTippy() {
const tippable = document.querySelectorAll("[v-tippy]") const tippable = document.querySelectorAll("[v-tippy]")

View File

@@ -18,7 +18,7 @@ export type HoppRESTHeader = {
export type FormDataKeyValue = { export type FormDataKeyValue = {
key: string key: string
active: boolean active: boolean
} & ({ isFile: true; value: Blob } | { isFile: false; value: string }) } & ({ isFile: true; value: Blob[] } | { isFile: false; value: string })
export type HoppRESTReqBodyFormData = { export type HoppRESTReqBodyFormData = {
contentType: "multipart/form-data" contentType: "multipart/form-data"

View File

@@ -260,7 +260,7 @@ const dispatchers = defineDispatchers({
}, },
} }
}, },
removeFormDataEntry(curr: RESTSession, { index }: { index: number }) { deleteFormDataEntry(curr: RESTSession, { index }: { index: number }) {
// Only perform update if the current content-type is formdata // Only perform update if the current content-type is formdata
if (curr.request.body.contentType !== "multipart/form-data") return {} if (curr.request.body.contentType !== "multipart/form-data") return {}
@@ -291,15 +291,17 @@ const dispatchers = defineDispatchers({
}, },
} }
}, },
clearAllFormDataEntries(curr: RESTSession) { deleteAllFormDataEntries(curr: RESTSession) {
// Only perform update if the current content-type is formdata // Only perform update if the current content-type is formdata
if (curr.request.body.contentType !== "multipart/form-data") return {} if (curr.request.body.contentType !== "multipart/form-data") return {}
return { return {
...curr.request, request: {
body: <HoppRESTReqBody>{ ...curr.request,
contentType: "multipart/form-data", body: <HoppRESTReqBody>{
body: [], contentType: "multipart/form-data",
body: [],
},
}, },
} }
}, },
@@ -538,9 +540,9 @@ export function addFormDataEntry(entry: FormDataKeyValue) {
}) })
} }
export function removeFormDataEntry(index: number) { export function deleteFormDataEntry(index: number) {
restSessionStore.dispatch({ restSessionStore.dispatch({
dispatcher: "removeFormDataEntry", dispatcher: "deleteFormDataEntry",
payload: { payload: {
index, index,
}, },
@@ -557,9 +559,9 @@ export function updateFormDataEntry(index: number, entry: FormDataKeyValue) {
}) })
} }
export function clearAllFormDataEntries() { export function deleteAllFormDataEntries() {
restSessionStore.dispatch({ restSessionStore.dispatch({
dispatcher: "clearAllFormDataEntries", dispatcher: "deleteAllFormDataEntries",
payload: {}, payload: {},
}) })
} }