refactor(sh-admin): updated invite flow for the admin dashboard (#4176)
* feat: new success invite link modal introduced * refactor: replaced button with lucide icon * style: vertical padding to lucide icon * feat: new success invite modal component * refactor: hide copy link button when there are no pending invites * refactor: changed copy link button to copy invite link * chore: minor UI update --------- Co-authored-by: nivedin <nivedinp@gmail.com>
This commit is contained in:
committed by
GitHub
parent
9cde6c597b
commit
9e445cda84
@@ -166,6 +166,8 @@
|
||||
"link_copied_to_clipboard": "Link copied to clipboard",
|
||||
"logged_out": "Logged out",
|
||||
"login_as_admin": "and login with an admin account.",
|
||||
"login_using_email": "Please ask the user to check their email or share the link below",
|
||||
"login_using_link": "Please ask the user to login using the link below",
|
||||
"logout": "Logout",
|
||||
"magic_link_sign_in": "Click on the link to sign in.",
|
||||
"magic_link_success": "We sent a magic link to",
|
||||
@@ -269,10 +271,12 @@
|
||||
"valid_owner_email": "Please enter a valid owner email"
|
||||
},
|
||||
"users": {
|
||||
"add_user": "Add User",
|
||||
"admin": "Admin",
|
||||
"admin_id": "Admin ID",
|
||||
"cancel": "Cancel",
|
||||
"created_on": "Created On",
|
||||
"copy_invite_link": "Copy Invite Link",
|
||||
"copy_link": "Copy Link",
|
||||
"date": "Date",
|
||||
"delete": "Delete",
|
||||
@@ -296,6 +300,7 @@
|
||||
"load_list_error": "Unable to Load Users List",
|
||||
"make_admin": "Make Admin",
|
||||
"name": "Name",
|
||||
"new_user_added": "New User Added",
|
||||
"no_invite": "No pending invites found",
|
||||
"no_shared_requests": "No shared requests created by the user",
|
||||
"no_users": "No users found",
|
||||
|
||||
@@ -17,21 +17,29 @@ declare module '@vue/runtime-core' {
|
||||
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
||||
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
|
||||
HoppSmartAutoComplete: typeof import('@hoppscotch/ui')['HoppSmartAutoComplete']
|
||||
HoppSmartCheckbox: typeof import('@hoppscotch/ui')['HoppSmartCheckbox']
|
||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||
HoppSmartIntersection: typeof import('@hoppscotch/ui')['HoppSmartIntersection']
|
||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||
HoppSmartPlaceholder: typeof import('@hoppscotch/ui')['HoppSmartPlaceholder']
|
||||
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
|
||||
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
||||
HoppSmartTab: typeof import('@hoppscotch/ui')['HoppSmartTab']
|
||||
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
|
||||
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
||||
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||
IconLucideCheck: typeof import('~icons/lucide/check')['default']
|
||||
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
|
||||
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
|
||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||
IconLucideSearch: typeof import('~icons/lucide/search')['default']
|
||||
IconLucideUser: typeof import('~icons/lucide/user')['default']
|
||||
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
|
||||
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
|
||||
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default']
|
||||
@@ -49,6 +57,7 @@ declare module '@vue/runtime-core' {
|
||||
UsersDetails: typeof import('./components/users/Details.vue')['default']
|
||||
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']
|
||||
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default']
|
||||
UsersSuccessInviteModal: typeof import('./components/users/SuccessInviteModal.vue')['default']
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
<template #footer>
|
||||
<span class="flex space-x-2">
|
||||
<HoppButtonPrimary
|
||||
:disabled="!smtpEnabled"
|
||||
:label="t('users.send_invite')"
|
||||
:label="t('users.add_user')"
|
||||
@click="emit('send-invite', email)"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
@@ -26,12 +25,6 @@
|
||||
@click="hideModal"
|
||||
/>
|
||||
</span>
|
||||
<HoppButtonSecondary
|
||||
:label="t('users.copy_link')"
|
||||
outline
|
||||
filled
|
||||
@click="emit('copy-invite-link', email)"
|
||||
/>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<HoppSmartModal
|
||||
dialog
|
||||
:title="t('users.new_user_added')"
|
||||
@close="inviteSuccessModal = false"
|
||||
>
|
||||
<template #body>
|
||||
<icon-lucide-check
|
||||
class="text-4xl text-emerald-500 w-min mx-auto my-3 p-3 bg-primaryDark rounded-full"
|
||||
/>
|
||||
<p class="text-center my-2">
|
||||
{{
|
||||
smtpEnabled
|
||||
? t('state.login_using_email')
|
||||
: t('state.login_using_link')
|
||||
}}
|
||||
</p>
|
||||
<div class="flex p-3 mx-10">
|
||||
<input
|
||||
:value="baseURL"
|
||||
class="input rounded-r-none"
|
||||
placeholder=""
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
disabled
|
||||
/>
|
||||
<div class="bg-primaryDark rounded-r-sm">
|
||||
<UiAutoResetIcon
|
||||
:title="t('users.copy_link')"
|
||||
:icon="{ default: IconCopy, temporary: IconCheck }"
|
||||
@click="emit('copy-invite-link')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
|
||||
import IconCheck from '~icons/lucide/check';
|
||||
import IconCopy from '~icons/lucide/copy';
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
const props = defineProps<{
|
||||
baseURL: string;
|
||||
inviteSuccess: boolean;
|
||||
smtpEnabled: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'copy-invite-link'): void;
|
||||
(event: 'update:inviteSuccess', v: boolean): void;
|
||||
}>();
|
||||
|
||||
const inviteSuccessModal = useVModel(props, 'inviteSuccess', emit);
|
||||
</script>
|
||||
@@ -203,6 +203,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
<UsersInviteModal
|
||||
v-if="showInviteUserModal"
|
||||
:smtp-enabled="smtpEnabled"
|
||||
@@ -210,6 +211,14 @@
|
||||
@send-invite="sendInvite"
|
||||
@copy-invite-link="copyInviteLink"
|
||||
/>
|
||||
<UsersSuccessInviteModal
|
||||
v-if="inviteSuccessModal"
|
||||
v-model:invite-success="inviteSuccessModal"
|
||||
:baseURL="baseURL"
|
||||
:smtp-enabled="smtpEnabled"
|
||||
@hide-modal="inviteSuccessModal = false"
|
||||
@copy-invite-link="copyInviteLink"
|
||||
/>
|
||||
<HoppSmartConfirmModal
|
||||
:show="confirmUsersToAdmin"
|
||||
:title="
|
||||
@@ -453,6 +462,13 @@ const goToUserDetails = (user: UserInfoQuery['infra']['userInfo']) =>
|
||||
// Check if SMTP is enabled
|
||||
const { data: status } = useQuery({ query: IsSmtpEnabledDocument });
|
||||
const smtpEnabled = computed(() => status?.value?.isSMTPEnabled);
|
||||
const inviteSuccessModal = ref(false);
|
||||
|
||||
const baseURL = import.meta.env.VITE_BASE_URL ?? '';
|
||||
const copyInviteLink = () => {
|
||||
copyToClipboard(baseURL);
|
||||
toast.success(t('state.link_copied_to_clipboard'));
|
||||
};
|
||||
|
||||
// Send Invitation through Email
|
||||
const showInviteUserModal = ref(false);
|
||||
@@ -482,18 +498,11 @@ const sendInvite = async (email: string) => {
|
||||
} else {
|
||||
if (smtpEnabled.value) toast.success(t('state.email_success'));
|
||||
showInviteUserModal.value = false;
|
||||
inviteSuccessModal.value = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const copyInviteLink = async (email: string) => {
|
||||
const result = await sendInvite(email);
|
||||
if (!result) return;
|
||||
const baseURL = import.meta.env.VITE_BASE_URL ?? '';
|
||||
copyToClipboard(baseURL);
|
||||
toast.success(t('state.link_copied_to_clipboard'));
|
||||
};
|
||||
|
||||
// Make Multiple Users Admin
|
||||
const confirmUsersToAdmin = ref(false);
|
||||
const usersToAdminUID = ref<string | null>(null);
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="text-lg font-bold text-accentContrast pt-6 pb-4">
|
||||
<div class="flex justify-between items-center py-6">
|
||||
<h3 class="text-lg font-bold text-accentContrast">
|
||||
{{ t('users.pending_invites') }}
|
||||
</h3>
|
||||
|
||||
<HoppButtonSecondary
|
||||
:label="t('users.copy_link')"
|
||||
v-if="pendingInvites?.length"
|
||||
:label="t('users.copy_invite_link')"
|
||||
outline
|
||||
filled
|
||||
@click="copyInviteLink"
|
||||
|
||||
Reference in New Issue
Block a user