feat: initial cookie ui implementation
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"action": {
|
"action": {
|
||||||
|
"add": "Add",
|
||||||
"autoscroll": "Autoscroll",
|
"autoscroll": "Autoscroll",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"choose_file": "Choose a file",
|
"choose_file": "Choose a file",
|
||||||
@@ -54,9 +55,23 @@
|
|||||||
"new": "Add new",
|
"new": "Add new",
|
||||||
"star": "Add star"
|
"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": {
|
"app": {
|
||||||
"chat_with_us": "Chat with us",
|
"chat_with_us": "Chat with us",
|
||||||
"contact_us": "Contact us",
|
"contact_us": "Contact us",
|
||||||
|
"cookies": "Cookies",
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
"copy_user_id": "Copy User Auth Token",
|
"copy_user_id": "Copy User Auth Token",
|
||||||
"developer_option": "Developer options",
|
"developer_option": "Developer options",
|
||||||
@@ -764,7 +779,7 @@
|
|||||||
"published_error": "Something went wrong while publishing msg: {topic} to topic: {message}",
|
"published_error": "Something went wrong while publishing msg: {topic} to topic: {message}",
|
||||||
"published_message": "Published message: {message} to topic: {topic}",
|
"published_message": "Published message: {message} to topic: {topic}",
|
||||||
"reconnection_error": "Failed to reconnect",
|
"reconnection_error": "Failed to reconnect",
|
||||||
"show":"Show",
|
"show": "Show",
|
||||||
"subscribed_failed": "Failed to subscribe to topic: {topic}",
|
"subscribed_failed": "Failed to subscribe to topic: {topic}",
|
||||||
"subscribed_success": "Successfully subscribed to topic: {topic}",
|
"subscribed_success": "Successfully subscribed to topic: {topic}",
|
||||||
"unsubscribed_failed": "Failed to unsubscribe from 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']
|
CollectionsRequest: typeof import('./components/collections/Request.vue')['default']
|
||||||
CollectionsSaveRequest: typeof import('./components/collections/SaveRequest.vue')['default']
|
CollectionsSaveRequest: typeof import('./components/collections/SaveRequest.vue')['default']
|
||||||
CollectionsTeamCollections: typeof import('./components/collections/TeamCollections.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']
|
Environments: typeof import('./components/environments/index.vue')['default']
|
||||||
EnvironmentsAdd: typeof import('./components/environments/Add.vue')['default']
|
EnvironmentsAdd: typeof import('./components/environments/Add.vue')['default']
|
||||||
EnvironmentsImportExport: typeof import('./components/environments/ImportExport.vue')['default']
|
EnvironmentsImportExport: typeof import('./components/environments/ImportExport.vue')['default']
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
<AppInterceptor />
|
<AppInterceptor />
|
||||||
</template>
|
</template>
|
||||||
</tippy>
|
</tippy>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
:label="t('app.cookies')"
|
||||||
|
:icon="IconCookie"
|
||||||
|
@click="showCookiesModal = true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<tippy
|
<tippy
|
||||||
@@ -195,12 +200,17 @@
|
|||||||
:show="showDeveloperOptions"
|
:show="showDeveloperOptions"
|
||||||
@hide-modal="showDeveloperOptions = false"
|
@hide-modal="showDeveloperOptions = false"
|
||||||
/>
|
/>
|
||||||
|
<CookiesAllModal
|
||||||
|
:show="showCookiesModal"
|
||||||
|
@hide-modal="showCookiesModal = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue"
|
import { ref } from "vue"
|
||||||
import { version } from "~/../package.json"
|
import { version } from "~/../package.json"
|
||||||
|
import IconCookie from "~icons/lucide/cookie"
|
||||||
import IconSidebar from "~icons/lucide/sidebar"
|
import IconSidebar from "~icons/lucide/sidebar"
|
||||||
import IconZap from "~icons/lucide/zap"
|
import IconZap from "~icons/lucide/zap"
|
||||||
import IconShare2 from "~icons/lucide/share-2"
|
import IconShare2 from "~icons/lucide/share-2"
|
||||||
@@ -223,7 +233,9 @@ import { invokeAction } from "@helpers/actions"
|
|||||||
import { HoppSmartItem } from "@hoppscotch/ui"
|
import { HoppSmartItem } from "@hoppscotch/ui"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const showDeveloperOptions = ref(false)
|
const showDeveloperOptions = ref(false)
|
||||||
|
const showCookiesModal = ref(false)
|
||||||
|
|
||||||
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
|
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
|
||||||
const SIDEBAR = useSetting("SIDEBAR")
|
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