chore: hoppscotch-ui improvements (#3497)
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com> Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
@@ -1,25 +1,21 @@
|
||||
<template>
|
||||
<div
|
||||
:role="bannerRole"
|
||||
class="flex items-center justify-between px-4 py-2 text-tiny"
|
||||
class="flex items-center justify-between px-4 py-2 text-tiny text-secondaryDark"
|
||||
:class="bannerColor"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<component :is="bannerIcon" class="mr-2 text-secondaryDark" />
|
||||
|
||||
<span class="text-secondaryDark">
|
||||
<span v-if="banner.alternateText" class="md:hidden">
|
||||
{{ banner.alternateText(t) }}
|
||||
</span>
|
||||
<span :class="{ '<md:hidden': banner.alternateText }">
|
||||
{{ banner.text(t) }}
|
||||
</span>
|
||||
<component :is="bannerIcon" class="mr-2" />
|
||||
<span :class="{ 'hidden sm:inline-flex': banner.alternateText }">
|
||||
{{ banner.text(t) }}
|
||||
</span>
|
||||
<span v-if="banner.alternateText" class="inline-flex sm:hidden">
|
||||
{{ banner.alternateText(t) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<icon-lucide-x
|
||||
v-if="dismissible"
|
||||
class="text-white hover:cursor-pointer hover:text-gray-300"
|
||||
class="opacity-50 hover:cursor-pointer hover:opacity-100"
|
||||
@click="emit('dismiss')"
|
||||
/>
|
||||
</div>
|
||||
@@ -57,9 +53,9 @@ const ariaRoles: Record<BannerType, string> = {
|
||||
}
|
||||
|
||||
const bgColors: Record<BannerType, string> = {
|
||||
info: "bg-info",
|
||||
warning: "bg-warning",
|
||||
error: "bg-error",
|
||||
info: "bg-bannerInfo",
|
||||
warning: "bg-bannerWarning",
|
||||
error: "bg-bannerError",
|
||||
}
|
||||
|
||||
const icons = {
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
<div>
|
||||
<header
|
||||
ref="headerRef"
|
||||
class="flex flex-1 flex-shrink-0 items-center justify-between space-x-2 overflow-x-auto overflow-y-hidden px-2 py-2"
|
||||
class="grid grid-cols-5 grid-rows-1 gap-2 overflow-x-auto overflow-y-hidden p-2"
|
||||
@mousedown.prevent="platform.ui?.appHeader?.onHeaderAreaClick?.()"
|
||||
>
|
||||
<div
|
||||
class="inline-flex flex-1 items-center justify-start space-x-2"
|
||||
class="col-span-2 flex items-center justify-between space-x-2"
|
||||
:style="{
|
||||
paddingTop: platform.ui?.appHeader?.paddingTop?.value,
|
||||
paddingLeft: platform.ui?.appHeader?.paddingLeft?.value,
|
||||
}"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
:label="t('app.name')"
|
||||
to="/"
|
||||
/>
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
:label="t('app.name')"
|
||||
to="/"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-flex flex-1 items-center justify-center space-x-2">
|
||||
<div class="col-span-1 flex items-center justify-between space-x-2">
|
||||
<button
|
||||
class="flex max-w-[15rem] flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 py-1 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
|
||||
class="flex h-full flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
|
||||
@click="invokeAction('modals.search.toggle')"
|
||||
>
|
||||
<span class="inline-flex flex-1 items-center">
|
||||
@@ -32,169 +34,180 @@
|
||||
<kbd class="shortcut-key">K</kbd>
|
||||
</span>
|
||||
</button>
|
||||
<HoppButtonSecondary
|
||||
v-if="showInstallButton"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('header.install_pwa')"
|
||||
:icon="IconDownload"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="installPWA()"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||
:title="`${
|
||||
mdAndLarger ? t('support.title') : t('app.options')
|
||||
} <kbd>?</kbd>`"
|
||||
:icon="IconLifeBuoy"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="invokeAction('modals.support.toggle')"
|
||||
/>
|
||||
</div>
|
||||
<div class="inline-flex flex-1 items-center justify-end space-x-2">
|
||||
<div
|
||||
v-if="currentUser === null"
|
||||
class="inline-flex items-center space-x-2"
|
||||
>
|
||||
<div class="col-span-2 flex items-center justify-between space-x-2">
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
:icon="IconUploadCloud"
|
||||
:label="t('header.save_workspace')"
|
||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 hidden border border-green-600/25 bg-green-500/[.15] !text-green-500 hover:border-green-800/50 hover:bg-green-400/10 focus-visible:border-green-800/50 focus-visible:bg-green-400/10 md:flex"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
v-if="showInstallButton"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('header.install_pwa')"
|
||||
:icon="IconDownload"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="installPWA()"
|
||||
/>
|
||||
<HoppButtonPrimary
|
||||
:label="t('header.login')"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||
:title="`${
|
||||
mdAndLarger ? t('support.title') : t('app.options')
|
||||
} <kbd>?</kbd>`"
|
||||
:icon="IconLifeBuoy"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="invokeAction('modals.support.toggle')"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="inline-flex items-center space-x-2">
|
||||
<TeamsMemberStack
|
||||
v-if="
|
||||
workspace.type === 'team' &&
|
||||
selectedTeam &&
|
||||
selectedTeam.teamMembers.length > 1
|
||||
"
|
||||
:team-members="selectedTeam.teamMembers"
|
||||
show-count
|
||||
class="mx-2"
|
||||
@handle-click="handleTeamEdit()"
|
||||
/>
|
||||
<div class="flex">
|
||||
<div
|
||||
class="flex divide-x divide-green-600/25 rounded border border-green-600/25 bg-green-500/[.15] focus-within:divide-green-800/50 focus-within:border-green-800/50 focus-within:bg-green-400/10 hover:divide-green-800/50 hover:border-green-800/50 hover:bg-green-400/10"
|
||||
v-if="currentUser === null"
|
||||
class="inline-flex items-center space-x-2"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.invite_tooltip')"
|
||||
:icon="IconUserPlus"
|
||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
|
||||
@click="handleInvite()"
|
||||
:icon="IconUploadCloud"
|
||||
:label="t('header.save_workspace')"
|
||||
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 hidden h-8 border border-emerald-600/25 bg-emerald-500/10 !text-emerald-500 hover:border-emerald-600/20 hover:bg-emerald-600/20 focus-visible:border-emerald-600/20 focus-visible:bg-emerald-600/20 md:flex"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
<HoppButtonPrimary
|
||||
:label="t('header.login')"
|
||||
class="h-8"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="inline-flex items-center space-x-2">
|
||||
<TeamsMemberStack
|
||||
v-if="
|
||||
workspace.type === 'team' &&
|
||||
selectedTeam &&
|
||||
selectedTeam?.myRole === 'OWNER'
|
||||
selectedTeam.teamMembers.length > 1
|
||||
"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.edit')"
|
||||
:icon="IconSettings"
|
||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
|
||||
@click="handleTeamEdit()"
|
||||
:team-members="selectedTeam.teamMembers"
|
||||
show-count
|
||||
class="mx-2"
|
||||
@handle-click="handleTeamEdit()"
|
||||
/>
|
||||
</div>
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => accountActions.focus()"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('workspace.change')"
|
||||
:label="mdAndLarger ? workspaceName : ``"
|
||||
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
|
||||
class="select-wrapper !focus-visible:text-blue-600 !hover:text-blue-600 rounded border border-blue-600/25 bg-blue-500/[.15] py-[0.4375rem] pr-8 !text-blue-500 hover:border-blue-800/50 hover:bg-blue-400/10 focus-visible:border-blue-800/50 focus-visible:bg-blue-400/10"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="accountActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.escape="hide()"
|
||||
@click="hide()"
|
||||
>
|
||||
<WorkspaceSelector />
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
<span class="px-2">
|
||||
<div
|
||||
class="flex h-8 divide-x divide-emerald-600/25 rounded border border-emerald-600/25 bg-emerald-500/10 focus-within:divide-emerald-600/20 focus-within:border-emerald-600/20 focus-within:bg-emerald-600/20 hover:divide-emerald-600/20 hover:border-emerald-600/20 hover:bg-emerald-600/20"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.invite_tooltip')"
|
||||
:icon="IconUserPlus"
|
||||
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
|
||||
@click="handleInvite()"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="
|
||||
workspace.type === 'team' &&
|
||||
selectedTeam &&
|
||||
selectedTeam?.myRole === 'OWNER'
|
||||
"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.edit')"
|
||||
:icon="IconSettings"
|
||||
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
|
||||
@click="handleTeamEdit()"
|
||||
/>
|
||||
</div>
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
:on-shown="() => accountActions.focus()"
|
||||
>
|
||||
<HoppSmartPicture
|
||||
v-tippy="{
|
||||
theme: 'tooltip',
|
||||
}"
|
||||
:name="currentUser.uid"
|
||||
:title="
|
||||
currentUser.displayName ||
|
||||
currentUser.email ||
|
||||
t('profile.default_hopp_displayname')
|
||||
"
|
||||
indicator
|
||||
:indicator-styles="
|
||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
||||
"
|
||||
/>
|
||||
<HoppSmartSelectWrapper
|
||||
class="!text-blue-500 !focus-visible:text-blue-600 !hover:text-blue-600"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('workspace.change')"
|
||||
:label="mdAndLarger ? workspaceName : ``"
|
||||
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
|
||||
class="!focus-visible:text-blue-600 !hover:text-blue-600 h-8 rounded border border-blue-600/25 bg-blue-500/10 pr-8 !text-blue-500 hover:border-blue-600/20 hover:bg-blue-600/20 focus-visible:border-blue-600/20 focus-visible:bg-blue-600/20"
|
||||
/>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
ref="accountActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.p="profile.$el.click()"
|
||||
@keyup.s="settings.$el.click()"
|
||||
@keyup.l="logout.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
@click="hide()"
|
||||
>
|
||||
<div class="flex flex-col px-2 text-tiny">
|
||||
<span class="inline-flex truncate font-semibold">
|
||||
{{
|
||||
currentUser.displayName ||
|
||||
t("profile.default_hopp_displayname")
|
||||
}}
|
||||
</span>
|
||||
<span class="inline-flex truncate text-secondaryLight">
|
||||
{{ currentUser.email }}
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
<HoppSmartItem
|
||||
ref="profile"
|
||||
to="/profile"
|
||||
:icon="IconUser"
|
||||
:label="t('navigation.profile')"
|
||||
:shortcut="['P']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="settings"
|
||||
to="/settings"
|
||||
:icon="IconSettings"
|
||||
:label="t('navigation.settings')"
|
||||
:shortcut="['S']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<FirebaseLogout
|
||||
ref="logout"
|
||||
:shortcut="['L']"
|
||||
@confirm-logout="hide()"
|
||||
/>
|
||||
<WorkspaceSelector />
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
</span>
|
||||
<span class="px-2">
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<HoppSmartPicture
|
||||
v-tippy="{
|
||||
theme: 'tooltip',
|
||||
}"
|
||||
:name="currentUser.uid"
|
||||
:title="
|
||||
currentUser.displayName ||
|
||||
currentUser.email ||
|
||||
t('profile.default_hopp_displayname')
|
||||
"
|
||||
indicator
|
||||
:indicator-styles="
|
||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
||||
"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.p="profile.$el.click()"
|
||||
@keyup.s="settings.$el.click()"
|
||||
@keyup.l="logout.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<div class="flex flex-col px-2">
|
||||
<span class="inline-flex truncate font-semibold">
|
||||
{{
|
||||
currentUser.displayName ||
|
||||
t("profile.default_hopp_displayname")
|
||||
}}
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex truncate text-secondaryLight text-tiny"
|
||||
>
|
||||
{{ currentUser.email }}
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
<HoppSmartItem
|
||||
ref="profile"
|
||||
to="/profile"
|
||||
:icon="IconUser"
|
||||
:label="t('navigation.profile')"
|
||||
:shortcut="['P']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="settings"
|
||||
to="/settings"
|
||||
:icon="IconSettings"
|
||||
:label="t('navigation.settings')"
|
||||
:shortcut="['S']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<FirebaseLogout
|
||||
ref="logout"
|
||||
:shortcut="['L']"
|
||||
@confirm-logout="hide()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -219,7 +232,6 @@
|
||||
@invite-team="inviteTeam(editingTeamName, editingTeamID)"
|
||||
@refetch-teams="refetchTeams"
|
||||
/>
|
||||
|
||||
<HoppSmartConfirmModal
|
||||
:show="confirmRemove"
|
||||
:title="t('confirm.remove_team')"
|
||||
@@ -279,7 +291,7 @@ const bannerContent = computed(() => banner.content.value?.content)
|
||||
let bannerID: number | null = null
|
||||
|
||||
const offlineBanner: BannerContent = {
|
||||
type: "info",
|
||||
type: "warning",
|
||||
text: (t) => t("helpers.offline"),
|
||||
alternateText: (t) => t("helpers.offline_short"),
|
||||
score: BANNER_PRIORITY_HIGH,
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
>
|
||||
<component
|
||||
:is="entry.icon"
|
||||
class="svg-icons opacity-50"
|
||||
:class="{ 'opacity-100': active }"
|
||||
class="svg-icons opacity-80"
|
||||
:class="{ 'opacity-25': active }"
|
||||
/>
|
||||
<template
|
||||
v-if="entry.text.type === 'text' && typeof entry.text.text === 'string'"
|
||||
@@ -82,9 +82,9 @@ const props = defineProps<{
|
||||
|
||||
const formattedShortcutKeys = computed(
|
||||
() =>
|
||||
props.entry.meta?.keyboardShortcut?.map((key) => {
|
||||
return SPECIAL_KEY_CHARS[key] ?? capitalize(key)
|
||||
})
|
||||
props.entry.meta?.keyboardShortcut?.map(
|
||||
(key) => SPECIAL_KEY_CHARS[key] ?? capitalize(key)
|
||||
)
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
autocomplete="off"
|
||||
name="command"
|
||||
:placeholder="`${t('app.type_a_command_search')}`"
|
||||
class="flex flex-1 bg-transparent px-6 py-5 text-base text-secondaryDark"
|
||||
class="flex flex-1 bg-transparent px-6 pt-5 pb-3 text-base text-secondaryDark"
|
||||
/>
|
||||
<HoppSmartSpinner v-if="searchSession?.loading" class="mr-6" />
|
||||
</div>
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
></div>
|
||||
<div class="relative flex flex-col">
|
||||
<div
|
||||
class="z-1 pointer-events-none absolute inset-0 bg-accent opacity-0 transition"
|
||||
class="z-[1] pointer-events-none absolute inset-0 bg-accent opacity-0 transition"
|
||||
:class="{
|
||||
'opacity-25':
|
||||
dragging && notSameDestination && notSameParentDestination,
|
||||
}"
|
||||
></div>
|
||||
<div
|
||||
class="z-3 group pointer-events-auto relative flex cursor-pointer items-stretch"
|
||||
class="z-[3] group pointer-events-auto relative flex cursor-pointer items-stretch"
|
||||
:draggable="!hasNoTeamAccess"
|
||||
@dragstart="dragStart"
|
||||
@drop="handelDrop($event)"
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
v-else-if="step.name === 'TARGET_MY_COLLECTION'"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<div class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<select
|
||||
v-model="mySelectedCollectionID"
|
||||
autocomplete="off"
|
||||
@@ -97,7 +97,7 @@
|
||||
{{ collection.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</HoppSmartSelectWrapper>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
>
|
||||
<span
|
||||
class="pointer-events-none flex w-16 items-center justify-center truncate px-2"
|
||||
:class="requestLabelColor"
|
||||
:style="{ color: requestLabelColor }"
|
||||
:style="{ color: getMethodLabelColorClassOf(request) }"
|
||||
>
|
||||
<component
|
||||
:is="IconCheckCircle"
|
||||
@@ -277,10 +276,6 @@ const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
||||
parentID: "",
|
||||
})
|
||||
|
||||
const requestLabelColor = computed(() =>
|
||||
getMethodLabelColorClassOf(props.request)
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.duplicateLoading,
|
||||
(val) => {
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
class="!rounded-none"
|
||||
:icon="IconPlus"
|
||||
:title="t('team.no_access')"
|
||||
:label="t('add.new')"
|
||||
:label="t('action.new')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-else
|
||||
:icon="IconPlus"
|
||||
:label="t('add.new')"
|
||||
:label="t('action.new')"
|
||||
class="!rounded-none"
|
||||
@click="emit('display-modal-add')"
|
||||
/>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
@dragend="draggingToRoot = false"
|
||||
>
|
||||
<div
|
||||
class="sticky z-10 flex flex-shrink-0 flex-col overflow-x-auto border-b border-dividerLight bg-primary"
|
||||
class="sticky z-10 flex flex-shrink-0 flex-col overflow-x-auto bg-primary border-b border-dividerLight"
|
||||
:class="{ 'rounded-t': saveRequest }"
|
||||
:style="
|
||||
saveRequest ? 'top: calc(-1 * var(--line-height-body))' : 'top: 0'
|
||||
@@ -22,7 +22,7 @@
|
||||
v-model="filterTexts"
|
||||
type="search"
|
||||
autocomplete="off"
|
||||
class="flex h-8 w-full bg-transparent p-4 py-2"
|
||||
class="flex w-full bg-transparent px-4 py-2"
|
||||
:placeholder="t('action.search')"
|
||||
:disabled="collectionsType.type === 'team-collections'"
|
||||
/>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<template #body>
|
||||
<div class="flex flex-1 flex-col space-y-4">
|
||||
<div class="ml-2 flex items-center space-x-8">
|
||||
<label for="name" class="min-w-10 font-semibold">{{
|
||||
<label for="name" class="min-w-[2.5rem] font-semibold">{{
|
||||
t("environment.name")
|
||||
}}</label>
|
||||
<input
|
||||
@@ -18,7 +18,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-2 flex items-center space-x-8">
|
||||
<label for="value" class="min-w-10 font-semibold">{{
|
||||
<label for="value" class="min-w-[2.5rem] font-semibold">{{
|
||||
t("environment.value")
|
||||
}}</label>
|
||||
<input
|
||||
@@ -29,7 +29,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-2 flex items-center space-x-8">
|
||||
<label for="scope" class="min-w-10 font-semibold">
|
||||
<label for="scope" class="min-w-[2.5rem] font-semibold">
|
||||
{{ t("environment.scope") }}
|
||||
</label>
|
||||
<div
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="replaceWithVariable" class="mt-3 flex space-x-2">
|
||||
<div class="min-w-18" />
|
||||
<div class="min-w-[4rem]" />
|
||||
<HoppSmartCheckbox
|
||||
:on="replaceWithVariable"
|
||||
:title="t('environment.replace_with_variable')"
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
theme="popover"
|
||||
:on-shown="() => envSelectorActions!.focus()"
|
||||
>
|
||||
<span
|
||||
<HoppSmartSelectWrapper
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="`${t('environment.select')}`"
|
||||
class="select-wrapper"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconLayers"
|
||||
@@ -22,7 +21,7 @@
|
||||
"
|
||||
class="flex-1 !justify-start rounded-none pr-8"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="envSelectorActions"
|
||||
@@ -207,10 +206,14 @@
|
||||
</div>
|
||||
<div class="my-2 flex flex-1 flex-col space-y-2 pl-4 pr-2">
|
||||
<div class="flex flex-1 space-x-4">
|
||||
<span class="min-w-32 w-1/4 truncate text-tiny font-semibold">
|
||||
<span
|
||||
class="min-w-[9rem] w-1/4 truncate text-tiny font-semibold"
|
||||
>
|
||||
{{ t("environment.name") }}
|
||||
</span>
|
||||
<span class="min-w-32 w-full truncate text-tiny font-semibold">
|
||||
<span
|
||||
class="min-w-[9rem] w-full truncate text-tiny font-semibold"
|
||||
>
|
||||
{{ t("environment.value") }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -219,10 +222,10 @@
|
||||
:key="index"
|
||||
class="flex flex-1 space-x-4"
|
||||
>
|
||||
<span class="min-w-32 w-1/4 truncate text-secondaryLight">
|
||||
<span class="min-w-[9rem] w-1/4 truncate text-secondaryLight">
|
||||
{{ variable.key }}
|
||||
</span>
|
||||
<span class="min-w-32 w-full truncate text-secondaryLight">
|
||||
<span class="min-w-[9rem] w-full truncate text-secondaryLight">
|
||||
{{ variable.value }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -258,10 +261,14 @@
|
||||
</div>
|
||||
<div v-else class="my-2 flex flex-1 flex-col space-y-2 pl-4 pr-2">
|
||||
<div class="flex flex-1 space-x-4">
|
||||
<span class="min-w-32 w-1/4 truncate text-tiny font-semibold">
|
||||
<span
|
||||
class="min-w-[9rem] w-1/4 truncate text-tiny font-semibold"
|
||||
>
|
||||
{{ t("environment.name") }}
|
||||
</span>
|
||||
<span class="min-w-32 w-full truncate text-tiny font-semibold">
|
||||
<span
|
||||
class="min-w-[9rem] w-full truncate text-tiny font-semibold"
|
||||
>
|
||||
{{ t("environment.value") }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -270,10 +277,10 @@
|
||||
:key="index"
|
||||
class="flex flex-1 space-x-4"
|
||||
>
|
||||
<span class="min-w-32 w-1/4 truncate text-secondaryLight">
|
||||
<span class="min-w-[9rem] w-1/4 truncate text-secondaryLight">
|
||||
{{ variable.key }}
|
||||
</span>
|
||||
<span class="min-w-32 w-full truncate text-secondaryLight">
|
||||
<span class="min-w-[9rem] w-full truncate text-secondaryLight">
|
||||
{{ variable.value }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
class="ml-2 rounded-none pr-8"
|
||||
:label="authName"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
@@ -171,7 +171,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
>
|
||||
<div class="pb-2 text-secondaryLight">
|
||||
{{ t("helpers.authorization") }}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
v-model="graphqlFieldsFilterText"
|
||||
type="search"
|
||||
autocomplete="off"
|
||||
class="flex h-8 w-full bg-transparent p-4 py-2"
|
||||
class="flex w-full bg-transparent px-4 py-2"
|
||||
:placeholder="`${t('action.search')}`"
|
||||
/>
|
||||
<div class="flex">
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions!.focus()"
|
||||
>
|
||||
<span class="truncate px-2 leading-8">
|
||||
<span class="truncate">
|
||||
{{ tab.document.request.name }}
|
||||
</span>
|
||||
<template #content="{ hide }">
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
v-model="filterText"
|
||||
type="search"
|
||||
autocomplete="off"
|
||||
class="flex h-8 w-full bg-transparent p-4 py-2"
|
||||
class="flex w-full bg-transparent px-4 py-2"
|
||||
:placeholder="`${t('action.search')}`"
|
||||
/>
|
||||
<div class="flex">
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
class="ml-2 rounded-none pr-8"
|
||||
:label="authName"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
@@ -149,7 +149,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
>
|
||||
<div class="pb-2 text-secondaryLight">
|
||||
{{ t("helpers.authorization") }}
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
:label="body.contentType || t('state.none')"
|
||||
class="ml-2 rounded-none pr-8"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
placement="bottom"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
:label="
|
||||
CodegenDefinitions.find((x) => x.name === codegenType)!.caption
|
||||
@@ -25,7 +25,7 @@
|
||||
outline
|
||||
class="flex-1 pr-8"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<div class="sticky top-0 z-10 flex-shrink-0 overflow-x-auto">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<div ref="preRequestEditor" class="h-full"></div>
|
||||
</div>
|
||||
<div
|
||||
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
>
|
||||
<div class="pb-2 text-secondaryLight">
|
||||
{{ t("helpers.pre_request_script") }}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class="sticky top-0 z-20 flex-none flex-shrink-0 bg-primary p-4 sm:flex sm:flex-shrink-0 sm:space-x-2"
|
||||
>
|
||||
<div
|
||||
class="min-w-52 flex flex-1 whitespace-nowrap rounded border border-divider"
|
||||
class="min-w-[12rem] flex flex-1 whitespace-nowrap rounded border border-divider"
|
||||
>
|
||||
<div class="relative flex">
|
||||
<label for="method">
|
||||
@@ -13,7 +13,7 @@
|
||||
theme="popover"
|
||||
:on-shown="() => methodTippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<input
|
||||
id="method"
|
||||
class="flex w-26 cursor-pointer rounded-l bg-primaryLight px-4 py-2 font-semibold text-secondaryDark transition"
|
||||
@@ -22,7 +22,7 @@
|
||||
:placeholder="`${t('request.method')}`"
|
||||
@input="onSelectMethod($event)"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="methodTippyActions"
|
||||
@@ -34,6 +34,9 @@
|
||||
v-for="(method, index) in methods"
|
||||
:key="`method-${index}`"
|
||||
:label="method"
|
||||
:style="{
|
||||
color: getMethodLabelColor(method),
|
||||
}"
|
||||
@click="
|
||||
() => {
|
||||
updateMethod(method)
|
||||
@@ -67,7 +70,7 @@
|
||||
'action.send'
|
||||
)} <kbd>${getSpecialKey()}</kbd><kbd>↩</kbd>`"
|
||||
:label="`${!loading ? t('action.send') : t('action.cancel')}`"
|
||||
class="min-w-20 flex-1 rounded-r-none"
|
||||
class="min-w-[5rem] flex-1 rounded-r-none"
|
||||
@click="!loading ? newSendRequest() : cancelRequest()"
|
||||
/>
|
||||
<span class="flex">
|
||||
@@ -259,6 +262,7 @@ import { InterceptorService } from "~/services/interceptor.service"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { getMethodLabelColor } from "~/helpers/rest/labelColoring"
|
||||
|
||||
const t = useI18n()
|
||||
const interceptorService = useService(InterceptorService)
|
||||
@@ -270,8 +274,8 @@ const methods = [
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"HEAD",
|
||||
"CONNECT",
|
||||
"OPTIONS",
|
||||
"CONNECT",
|
||||
"TRACE",
|
||||
"CUSTOM",
|
||||
]
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
@click.middle="emit('close-tab')"
|
||||
>
|
||||
<span
|
||||
class="text-tiny font-semibold"
|
||||
class="text-tiny font-semibold mr-2"
|
||||
:style="{ color: getMethodLabelColorClassOf(tab.document.request) }"
|
||||
>
|
||||
{{ tab.document.request.method }}
|
||||
</span>
|
||||
|
||||
<tippy
|
||||
ref="options"
|
||||
trigger="manual"
|
||||
@@ -21,7 +20,7 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions!.focus()"
|
||||
>
|
||||
<span class="truncate px-2 leading-8">
|
||||
<span class="truncate">
|
||||
{{ tab.document.request.name }}
|
||||
</span>
|
||||
<template #content="{ hide }">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<div ref="testScriptEditor" class="h-full"></div>
|
||||
</div>
|
||||
<div
|
||||
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
|
||||
>
|
||||
<div class="pb-2 text-secondaryLight">
|
||||
{{ t("helpers.post_request_tests") }}
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
theme="popover"
|
||||
:on-shown="() => authTippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
:label="auth.addTo || t('state.none')"
|
||||
class="ml-2 rounded-none pr-8"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="authTippyActions"
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
:label="contentType || t('state.none').toLowerCase()"
|
||||
class="ml-2 rounded-none pr-8"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
@@ -279,6 +279,7 @@ defineActionHandler("request.send-cancel", sendMessage)
|
||||
:deep(.cm-panels) {
|
||||
@apply top-upperSecondaryStickyFold #{!important};
|
||||
}
|
||||
|
||||
.eventFeildShown :deep(.cm-panels),
|
||||
.cmResponsePrimaryStickyFold :deep(.cm-panels) {
|
||||
@apply top-upperTertiaryStickyFold #{!important};
|
||||
|
||||
@@ -62,12 +62,12 @@
|
||||
{{ t("mqtt.lw_qos") }}
|
||||
</label>
|
||||
<tippy interactive trigger="click" theme="popover">
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
class="ml-2 rounded-none pr-8"
|
||||
:label="`${config.lwQos}`"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div class="flex flex-col" role="menu">
|
||||
<HoppSmartItem
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
autoScrollEnabled ? t('action.turn_off') : t('action.turn_on')
|
||||
}`"
|
||||
:icon="IconChevronsDown"
|
||||
:class="toggleAutoscrollColor"
|
||||
@click="toggleAutoscroll()"
|
||||
:color="autoScrollEnabled ? 'green' : 'red'"
|
||||
@click="autoScrollEnabled = !autoScrollEnabled"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,7 +60,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, PropType, computed, watch, Ref } from "vue"
|
||||
import { ref, PropType, watch, Ref } from "vue"
|
||||
import IconTrash from "~icons/lucide/trash"
|
||||
import IconArrowUp from "~icons/lucide/arrow-up"
|
||||
import IconArrowDown from "~icons/lucide/arrow-down"
|
||||
@@ -123,12 +123,4 @@ watch(
|
||||
}, 200),
|
||||
{ flush: "post" }
|
||||
)
|
||||
|
||||
const toggleAutoscroll = () => {
|
||||
autoScrollEnabled.value = !autoScrollEnabled.value
|
||||
}
|
||||
|
||||
const toggleAutoscrollColor = computed(() =>
|
||||
autoScrollEnabled.value ? "text-green-500" : "text-red-500"
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="entry.ts !== undefined"
|
||||
class="w-34 hidden items-center px-1 sm:inline-flex"
|
||||
class="w-36 hidden items-center px-1 sm:inline-flex"
|
||||
>
|
||||
<span
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
{{ t("mqtt.qos") }}
|
||||
</label>
|
||||
<tippy interactive trigger="click" theme="popover">
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary class="pr-8" :label="`${QoS}`" />
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div class="flex flex-col" role="menu">
|
||||
<HoppSmartItem
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('settings.choose_language')"
|
||||
@@ -15,7 +15,7 @@
|
||||
outline
|
||||
:label="currentLocale.name"
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<HoppSmartInput
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
class="svg-icons opacity-75"
|
||||
:class="label ? (reverse ? 'ml-4' : 'mr-4') : ''"
|
||||
/>
|
||||
<div class="max-w-54 truncate">
|
||||
<div class="max-w-[16rem] truncate">
|
||||
{{ label }}
|
||||
</div>
|
||||
</HoppSmartLink>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
class="svg-icons"
|
||||
:class="label ? 'mr-4 opacity-75' : ''"
|
||||
/>
|
||||
<div class="max-w-54 truncate">
|
||||
<div class="max-w-[16rem] truncate">
|
||||
{{ label }}
|
||||
</div>
|
||||
</HoppSmartLink>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions![index].focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<input
|
||||
class="flex flex-1 cursor-pointer bg-transparent px-4 py-2"
|
||||
:placeholder="`${t('team.permissions')}`"
|
||||
@@ -83,7 +83,7 @@
|
||||
:value="member.role"
|
||||
readonly
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions![index].focus()"
|
||||
>
|
||||
<span class="select-wrapper">
|
||||
<HoppSmartSelectWrapper>
|
||||
<input
|
||||
class="flex flex-1 cursor-pointer bg-transparent px-4 py-2"
|
||||
:placeholder="`${t('team.permissions')}`"
|
||||
@@ -177,7 +177,7 @@
|
||||
:value="invitee.value"
|
||||
readonly
|
||||
/>
|
||||
</span>
|
||||
</HoppSmartSelectWrapper>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
@@ -272,7 +272,7 @@
|
||||
<ul class="mt-4 space-y-4">
|
||||
<li class="flex">
|
||||
<span
|
||||
class="max-w-16 w-1/4 truncate font-semibold uppercase text-secondaryDark"
|
||||
class="max-w-[4rem] w-1/4 truncate font-semibold uppercase text-secondaryDark"
|
||||
>
|
||||
{{ t("profile.owner") }}
|
||||
</span>
|
||||
@@ -282,7 +282,7 @@
|
||||
</li>
|
||||
<li class="flex">
|
||||
<span
|
||||
class="max-w-16 w-1/4 truncate font-semibold uppercase text-secondaryDark"
|
||||
class="max-w-[4rem] w-1/4 truncate font-semibold uppercase text-secondaryDark"
|
||||
>
|
||||
{{ t("profile.editor") }}
|
||||
</span>
|
||||
@@ -292,7 +292,7 @@
|
||||
</li>
|
||||
<li class="flex">
|
||||
<span
|
||||
class="max-w-16 w-1/4 truncate font-semibold uppercase text-secondaryDark"
|
||||
class="max-w-[4rem] w-1/4 truncate font-semibold uppercase text-secondaryDark"
|
||||
>
|
||||
{{ t("profile.viewer") }}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user