feat: initial cookie ui implementation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"action": {
|
||||
"add": "Add",
|
||||
"autoscroll": "Autoscroll",
|
||||
"cancel": "Cancel",
|
||||
"choose_file": "Choose a file",
|
||||
@@ -54,9 +55,23 @@
|
||||
"new": "Add new",
|
||||
"star": "Add star"
|
||||
},
|
||||
"cookies": {
|
||||
"modal": {
|
||||
"new_domain_name": "New domain name",
|
||||
"set": "Set a cookie",
|
||||
"cookie_string": "Cookie string",
|
||||
"cookie_name": "Name",
|
||||
"cookie_value": "Value",
|
||||
"cookie_path": "Path",
|
||||
"cookie_expires": "Expires",
|
||||
"managed_tab": "Managed",
|
||||
"raw_tab": "Raw"
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"chat_with_us": "Chat with us",
|
||||
"contact_us": "Contact us",
|
||||
"cookies": "Cookies",
|
||||
"copy": "Copy",
|
||||
"copy_user_id": "Copy User Auth Token",
|
||||
"developer_option": "Developer options",
|
||||
@@ -764,7 +779,7 @@
|
||||
"published_error": "Something went wrong while publishing msg: {topic} to topic: {message}",
|
||||
"published_message": "Published message: {message} to topic: {topic}",
|
||||
"reconnection_error": "Failed to reconnect",
|
||||
"show":"Show",
|
||||
"show": "Show",
|
||||
"subscribed_failed": "Failed to subscribe to topic: {topic}",
|
||||
"subscribed_success": "Successfully subscribed to topic: {topic}",
|
||||
"unsubscribed_failed": "Failed to unsubscribe from topic: {topic}",
|
||||
|
||||
@@ -58,6 +58,9 @@ declare module 'vue' {
|
||||
CollectionsRequest: typeof import('./components/collections/Request.vue')['default']
|
||||
CollectionsSaveRequest: typeof import('./components/collections/SaveRequest.vue')['default']
|
||||
CollectionsTeamCollections: typeof import('./components/collections/TeamCollections.vue')['default']
|
||||
CookiesAllModal: typeof import('./components/cookies/AllModal.vue')['default']
|
||||
CookiesCookieJarModal: typeof import('./components/cookies/CookieJarModal.vue')['default']
|
||||
CookiesEditCookie: typeof import('./components/cookies/EditCookie.vue')['default']
|
||||
Environments: typeof import('./components/environments/index.vue')['default']
|
||||
EnvironmentsAdd: typeof import('./components/environments/Add.vue')['default']
|
||||
EnvironmentsImportExport: typeof import('./components/environments/ImportExport.vue')['default']
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
<AppInterceptor />
|
||||
</template>
|
||||
</tippy>
|
||||
<HoppButtonSecondary
|
||||
:label="t('app.cookies')"
|
||||
:icon="IconCookie"
|
||||
@click="showCookiesModal = true"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<tippy
|
||||
@@ -195,12 +200,17 @@
|
||||
:show="showDeveloperOptions"
|
||||
@hide-modal="showDeveloperOptions = false"
|
||||
/>
|
||||
<CookiesAllModal
|
||||
:show="showCookiesModal"
|
||||
@hide-modal="showCookiesModal = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { version } from "~/../package.json"
|
||||
import IconCookie from "~icons/lucide/cookie"
|
||||
import IconSidebar from "~icons/lucide/sidebar"
|
||||
import IconZap from "~icons/lucide/zap"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
@@ -223,7 +233,9 @@ import { invokeAction } from "@helpers/actions"
|
||||
import { HoppSmartItem } from "@hoppscotch/ui"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const showDeveloperOptions = ref(false)
|
||||
const showCookiesModal = ref(false)
|
||||
|
||||
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
|
||||
const SIDEBAR = useSetting("SIDEBAR")
|
||||
|
||||
195
packages/hoppscotch-common/src/components/cookies/AllModal.vue
Normal file
195
packages/hoppscotch-common/src/components/cookies/AllModal.vue
Normal file
@@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<HoppSmartModal
|
||||
v-if="show"
|
||||
dialog
|
||||
:title="t('app.cookies')"
|
||||
aria-modal="true"
|
||||
@close="hideModal"
|
||||
>
|
||||
<template #body>
|
||||
<div class="flex gap-x-2 border-b border-dividerLight pb-3">
|
||||
<HoppSmartInput
|
||||
v-model="newDomainText"
|
||||
class="flex-grow"
|
||||
:placeholder="t('cookies.modal.new_domain_name')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
outline
|
||||
filled
|
||||
:label="t('action.add')"
|
||||
@click="addNewDomain"
|
||||
/>
|
||||
</div>
|
||||
<div class="pt-3 flex flex-col gap-y-6">
|
||||
<div
|
||||
v-for="[domain, entries] in workingCookieJar.entries()"
|
||||
:key="domain"
|
||||
class="flex flex-col gap-y-2"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3>{{ domain }}</h3>
|
||||
<div>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconTrash2"
|
||||
@click="deleteDomain(domain)"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconPlus"
|
||||
@click="addCookieToDomain(domain)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border rounded border-divider">
|
||||
<div class="divide-y divide-dividerLight">
|
||||
<div
|
||||
v-for="(entry, entryIndex) in entries"
|
||||
:key="`${entry}-${entryIndex}`"
|
||||
class="flex divide-x divide-dividerLight"
|
||||
>
|
||||
<input
|
||||
class="flex flex-1 px-4 py-2 bg-transparent"
|
||||
:value="entry"
|
||||
readonly
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconEdit"
|
||||
@click="editCookie(domain, entryIndex, entry)"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
color="red"
|
||||
:icon="IconTrash"
|
||||
@click="deleteCookie(domain, entryIndex)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="flex space-x-2">
|
||||
<HoppButtonPrimary
|
||||
v-focus
|
||||
:label="t('action.save')"
|
||||
outline
|
||||
@click="saveCookieChanges"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.cancel')"
|
||||
outline
|
||||
filled
|
||||
@click="cancelCookieChanges"
|
||||
/>
|
||||
</span>
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.clear_all')"
|
||||
outline
|
||||
filled
|
||||
@click="hideModal"
|
||||
/>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
<CookiesEditCookie
|
||||
:show="!!showEditModalFor"
|
||||
:entry="showEditModalFor"
|
||||
@save-cookie="saveCookieUpdate"
|
||||
@hide-modal="showEditModalFor = null"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useService } from "dioc/vue"
|
||||
import { CookieJarService } from "~/services/cookie-jar.service"
|
||||
import IconTrash from "~icons/lucide/trash"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { ref, watch } from "vue"
|
||||
|
||||
const props = defineProps<{
|
||||
show: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "hide-modal"): void
|
||||
}>()
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const newDomainText = ref("")
|
||||
|
||||
const cookieJarService = useService(CookieJarService)
|
||||
|
||||
const workingCookieJar = ref(cloneDeep(cookieJarService.cookieJar.value))
|
||||
|
||||
function addNewDomain() {
|
||||
workingCookieJar.value.set(newDomainText.value, [])
|
||||
newDomainText.value = ""
|
||||
}
|
||||
|
||||
function deleteDomain(domain: string) {
|
||||
workingCookieJar.value.delete(domain)
|
||||
}
|
||||
|
||||
function addCookieToDomain(domain: string) {
|
||||
const entry = workingCookieJar.value.get(domain)
|
||||
|
||||
if (entry) {
|
||||
entry.push("")
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
(show) => {
|
||||
if (show) {
|
||||
workingCookieJar.value = cloneDeep(cookieJarService.cookieJar.value)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Tuple of [domain, entryIndex]
|
||||
const showEditModalFor = ref<[string, number, string] | null>(null)
|
||||
|
||||
function saveCookieChanges() {
|
||||
cookieJarService.cookieJar.value = workingCookieJar.value
|
||||
hideModal()
|
||||
}
|
||||
|
||||
function cancelCookieChanges() {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
function editCookie(domain: string, entryIndex: number, cookieEntry: string) {
|
||||
showEditModalFor.value = [domain, entryIndex, cookieEntry]
|
||||
}
|
||||
|
||||
function deleteCookie(domain: string, entryIndex: number) {
|
||||
const entry = workingCookieJar.value.get(domain)
|
||||
|
||||
if (entry) {
|
||||
entry.splice(entryIndex, 1)
|
||||
}
|
||||
}
|
||||
|
||||
function saveCookieUpdate(cookie: string) {
|
||||
if (!showEditModalFor.value) return
|
||||
|
||||
const [domain, entryIndex] = showEditModalFor.value!
|
||||
|
||||
const entry = workingCookieJar.value.get(domain)
|
||||
|
||||
if (entry) {
|
||||
entry[entryIndex] = cookie
|
||||
}
|
||||
|
||||
showEditModalFor.value = null
|
||||
}
|
||||
|
||||
const hideModal = () => {
|
||||
emit("hide-modal")
|
||||
}
|
||||
</script>
|
||||
145
packages/hoppscotch-common/src/components/cookies/EditCookie.vue
Normal file
145
packages/hoppscotch-common/src/components/cookies/EditCookie.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<HoppSmartModal
|
||||
v-if="show"
|
||||
dialog
|
||||
:title="t('cookies.modal.set')"
|
||||
aria-modal="true"
|
||||
@close="hideModal"
|
||||
>
|
||||
<template #body>
|
||||
<HoppSmartTabs v-model="currentActiveTab">
|
||||
<HoppSmartTab :id="'managed'" :label="t('cookies.modal.managed_tab')">
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<div class="flex items-center">
|
||||
<label class="w-20">{{ t("cookies.modal.cookie_name") }}</label>
|
||||
<HoppSmartInput
|
||||
v-model="cookieName"
|
||||
:placeholder="t('cookies.modal.cookie_name')"
|
||||
class="flex-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<label class="w-20">{{ t("cookies.modal.cookie_value") }}</label>
|
||||
<HoppSmartInput
|
||||
v-model="cookieValue"
|
||||
:placeholder="t('cookies.modal.cookie_value')"
|
||||
class="flex-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<label class="w-20">{{ t("cookies.modal.cookie_path") }}</label>
|
||||
<HoppSmartInput
|
||||
v-model="cookiePath"
|
||||
:placeholder="t('cookies.modal.cookie_path')"
|
||||
class="flex-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<label class="w-20">{{
|
||||
t("cookies.modal.cookie_expires")
|
||||
}}</label>
|
||||
<HoppSmartInput
|
||||
v-model="cookieExpires"
|
||||
:placeholder="t('cookies.modal.cookie_expires')"
|
||||
:type="'datetime-local'"
|
||||
class="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</HoppSmartTab>
|
||||
|
||||
<HoppSmartTab :id="'raw'" :label="t('cookies.modal.raw_tab')">
|
||||
<HoppSmartInput
|
||||
v-model="rawCookieString"
|
||||
:placeholder="t('cookies.modal.cookie_string')"
|
||||
/>
|
||||
</HoppSmartTab>
|
||||
</HoppSmartTabs>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex space-x-2">
|
||||
<HoppButtonPrimary
|
||||
v-focus
|
||||
:label="t('action.save')"
|
||||
outline
|
||||
@click="saveCookieChange"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.cancel')"
|
||||
outline
|
||||
filled
|
||||
@click="cancelCookieChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { HoppSmartInput, HoppSmartTab } from "@hoppscotch/ui"
|
||||
import { useService } from "dioc/vue"
|
||||
import { watch, ref } from "vue"
|
||||
import { CookieJarService } from "~/services/cookie-jar.service"
|
||||
|
||||
const cookieService = useService(CookieJarService)
|
||||
|
||||
// TODO: Build Managed Mode!
|
||||
|
||||
const props = defineProps<{
|
||||
show: boolean
|
||||
|
||||
// Tuple of [domain, entryIndex, cookieEntry]
|
||||
entry: [string, number, string] | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "save-cookie", cookie: string): void
|
||||
(e: "hide-modal"): void
|
||||
}>()
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const currentActiveTab = ref<"managed" | "raw">("managed")
|
||||
|
||||
const cookieName = ref("")
|
||||
const cookieValue = ref("")
|
||||
const cookiePath = ref("")
|
||||
const cookieExpires = ref("")
|
||||
|
||||
const rawCookieString = ref("")
|
||||
|
||||
watch(
|
||||
() => props.entry,
|
||||
() => {
|
||||
if (!props.entry) return
|
||||
|
||||
const cookieEntry = props.entry[2]
|
||||
|
||||
const parsedEntry = cookieService.parseSetCookieString(cookieEntry)
|
||||
|
||||
rawCookieString.value = cookieEntry
|
||||
|
||||
cookieName.value = parsedEntry.name ?? ""
|
||||
cookieValue.value = parsedEntry.value ?? ""
|
||||
cookiePath.value = parsedEntry.path ?? ""
|
||||
cookieExpires.value = (parsedEntry.expires ?? new Date()).toISOString()
|
||||
}
|
||||
)
|
||||
|
||||
function hideModal() {
|
||||
emit("hide-modal")
|
||||
}
|
||||
|
||||
function cancelCookieChange() {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
function saveCookieChange() {
|
||||
emit("save-cookie", rawCookieString.value)
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user