feat: response shortcuts (#2705)

This commit is contained in:
Liyas Thomas
2022-09-30 19:32:09 +05:30
committed by GitHub
parent 06a8d62dfe
commit 938f940f90
40 changed files with 307 additions and 107 deletions

View File

@@ -3,7 +3,6 @@
v-if="response"
v-model="selectedLensTab"
styles="sticky z-10 bg-primary top-lowerPrimaryStickyFold"
render-inactive-tabs
>
<SmartTab
v-for="(lens, index) in validLenses"

View File

@@ -17,24 +17,28 @@
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${
previewEnabled ? t('hide.preview') : t('response.preview_html')
"
} <xmp>${getSpecialKey()}</xmp><xmp>Shift</xmp><xmp>P</xmp>`"
:icon="!previewEnabled ? IconEye : IconEyeOff"
@click.prevent="togglePreview"
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.download_file')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.download_file'
)} <xmp>${getSpecialKey()}</xmp><xmp>J</xmp>`"
:icon="downloadIcon"
@click="downloadResponse"
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.copy')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.copy'
)} <xmp>${getSpecialKey()}</xmp><xmp>.</xmp>`"
:icon="copyIcon"
@click="copyResponse"
/>
@@ -70,6 +74,8 @@ import {
import { useCodemirror } from "@composables/codemirror"
import { useI18n } from "@composables/i18n"
import type { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { defineActionHandler } from "~/helpers/actions"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
const t = useI18n()
@@ -105,6 +111,10 @@ useCodemirror(
environmentHighlights: true,
})
)
defineActionHandler("response.preview.toggle", () => togglePreview())
defineActionHandler("response.file.download", () => downloadResponse())
defineActionHandler("response.copy", () => copyResponse())
</script>
<style lang="scss" scoped>

View File

@@ -9,9 +9,11 @@
<div class="flex">
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.download_file')"
:icon="downloadIcon === 'download' ? IconDownload : IconCheck"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.download_file'
)} <xmp>${getSpecialKey()}</xmp><xmp>J</xmp>`"
:icon="downloadIcon"
@click="downloadResponse"
/>
</div>
@@ -25,92 +27,76 @@
</div>
</template>
<script lang="ts">
import IconDownload from "~icons/lucide/download"
import IconCheck from "~icons/lucide/check"
<script setup lang="ts">
import { useI18n } from "@composables/i18n"
import { useToast } from "@composables/toast"
import { defineComponent } from "vue"
import { defineActionHandler } from "~/helpers/actions"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
import { computed, onMounted, ref, watch } from "vue"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { useDownloadResponse } from "~/composables/lens-actions"
import { flow, pipe } from "fp-ts/function"
import * as S from "fp-ts/string"
import * as RNEA from "fp-ts/ReadonlyNonEmptyArray"
import * as A from "fp-ts/Array"
import * as O from "fp-ts/Option"
import { objFieldMatches } from "~/helpers/functional/object"
export default defineComponent({
props: {
response: { type: Object, default: () => ({}) },
},
setup() {
return {
t: useI18n(),
toast: useToast(),
IconDownload,
IconCheck,
}
},
data() {
return {
imageSource: "",
downloadIcon: "download",
}
},
computed: {
responseType() {
return (
this.response.headers.find(
(h) => h.key.toLowerCase() === "content-type"
).value || ""
const t = useI18n()
const props = defineProps<{
response: HoppRESTResponse & { type: "success" | "fail" }
}>()
const imageSource = ref("")
const responseType = computed(() =>
pipe(
props.response,
O.fromPredicate(objFieldMatches("type", ["fail", "success"] as const)),
O.chain(
// Try getting content-type
flow(
(res) => res.headers,
A.findFirst((h) => h.key.toLowerCase() === "content-type"),
O.map(flow((h) => h.value, S.split(";"), RNEA.head, S.toLowerCase))
)
.split(";")[0]
.toLowerCase()
},
},
watch: {
response: {
immediate: true,
handler() {
this.imageSource = ""
),
O.getOrElse(() => "text/plain")
)
)
const buf = this.response.body
const bytes = new Uint8Array(buf)
const blob = new Blob([bytes.buffer])
const { downloadIcon, downloadResponse } = useDownloadResponse(
responseType.value,
computed(() => props.response.body)
)
const reader = new FileReader()
reader.onload = ({ target }) => {
this.imageSource = target.result
}
reader.readAsDataURL(blob)
},
},
},
mounted() {
this.imageSource = ""
watch(props.response, () => {
imageSource.value = ""
const buf = props.response.body
const bytes = new Uint8Array(buf)
const blob = new Blob([bytes.buffer])
const buf = this.response.body
const bytes = new Uint8Array(buf)
const blob = new Blob([bytes.buffer])
const reader = new FileReader()
reader.onload = ({ target }) => {
this.imageSource = target.result
}
reader.readAsDataURL(blob)
},
methods: {
downloadResponse() {
const dataToWrite = this.response.body
const file = new Blob([dataToWrite], { type: this.responseType })
const a = document.createElement("a")
const url = URL.createObjectURL(file)
a.href = url
// TODO get uri from meta
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
document.body.appendChild(a)
a.click()
this.downloadIcon = "check"
this.toast.success(this.t("state.download_started"))
setTimeout(() => {
document.body.removeChild(a)
URL.revokeObjectURL(url)
this.downloadIcon = "download"
}, 1000)
},
},
const reader = new FileReader()
reader.onload = ({ target }) => {
// target.result will always be string because we're using FileReader.readAsDataURL
imageSource.value = target!.result as string
}
reader.readAsDataURL(blob)
})
onMounted(() => {
imageSource.value = ""
const buf = props.response.body
const bytes = new Uint8Array(buf)
const blob = new Blob([bytes.buffer])
const reader = new FileReader()
reader.onload = ({ target }) => {
// target.result will always be string because we're using FileReader.readAsDataURL
imageSource.value = target!.result as string
}
reader.readAsDataURL(blob)
})
defineActionHandler("response.file.download", () => downloadResponse())
</script>

View File

@@ -28,15 +28,19 @@
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.download_file')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.download_file'
)} <xmp>${getSpecialKey()}</xmp><xmp>J</xmp>`"
:icon="downloadIcon"
@click="downloadResponse"
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.copy')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.copy'
)} <xmp>${getSpecialKey()}</xmp><xmp>.</xmp>`"
:icon="copyIcon"
@click="copyResponse"
/>
@@ -215,6 +219,8 @@ import {
useResponseBody,
useDownloadResponse,
} from "@composables/lens-actions"
import { defineActionHandler } from "~/helpers/actions"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
const t = useI18n()
@@ -358,6 +364,9 @@ const toggleFilterState = () => {
filterQueryText.value = ""
toggleFilter.value = !toggleFilter.value
}
defineActionHandler("response.file.download", () => downloadResponse())
defineActionHandler("response.copy", () => copyResponse())
</script>
<style lang="scss" scoped>

View File

@@ -9,8 +9,10 @@
<div class="flex">
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.download_file')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.download_file'
)} <xmp>${getSpecialKey()}</xmp><xmp>J</xmp>`"
:icon="downloadIcon"
@click="downloadResponse"
/>
@@ -30,6 +32,8 @@ import VuePdfEmbed from "vue-pdf-embed"
import { useI18n } from "@composables/i18n"
import { useDownloadResponse } from "@composables/lens-actions"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { defineActionHandler } from "~/helpers/actions"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
const t = useI18n()
@@ -51,4 +55,6 @@ const { downloadIcon, downloadResponse } = useDownloadResponse(
"application/pdf",
computed(() => props.response.body)
)
defineActionHandler("response.file.download", () => downloadResponse())
</script>

View File

@@ -17,15 +17,19 @@
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.download_file')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.download_file'
)} <xmp>${getSpecialKey()}</xmp><xmp>J</xmp>`"
:icon="downloadIcon"
@click="downloadResponse"
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.copy')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.copy'
)} <xmp>${getSpecialKey()}</xmp><xmp>.</xmp>`"
:icon="copyIcon"
@click="copyResponse"
/>
@@ -52,6 +56,8 @@ import {
useCopyResponse,
} from "@composables/lens-actions"
import { objFieldMatches } from "~/helpers/functional/object"
import { defineActionHandler } from "~/helpers/actions"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
const t = useI18n()
@@ -107,4 +113,7 @@ useCodemirror(
environmentHighlights: true,
})
)
defineActionHandler("response.file.download", () => downloadResponse())
defineActionHandler("response.copy", () => copyResponse())
</script>

View File

@@ -17,15 +17,19 @@
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.download_file')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.download_file'
)} <xmp>${getSpecialKey()}</xmp><xmp>J</xmp>`"
:icon="downloadIcon"
@click="downloadResponse"
/>
<ButtonSecondary
v-if="response.body"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.copy')"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${t(
'action.copy'
)} <xmp>${getSpecialKey()}</xmp><xmp>.</xmp>`"
:icon="copyIcon"
@click="copyResponse"
/>
@@ -46,6 +50,8 @@ import {
useDownloadResponse,
useCopyResponse,
} from "@composables/lens-actions"
import { defineActionHandler } from "~/helpers/actions"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
const t = useI18n()
@@ -88,4 +94,7 @@ useCodemirror(
environmentHighlights: true,
})
)
defineActionHandler("response.file.download", () => downloadResponse())
defineActionHandler("response.copy", () => copyResponse())
</script>