feat(sh-admin): introducing last active status to users table and individual user's page in dashboard (#4077)
Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
25fd35770a
commit
b3e42bf7c3
@@ -279,6 +279,7 @@
|
||||
"invited_on": "Invited On",
|
||||
"invited_users": "Invited Users",
|
||||
"invitee_email": "Invitee Email",
|
||||
"last_active_on": "Last Active",
|
||||
"load_info_error": "Unable to load user info",
|
||||
"load_list_error": "Unable to Load Users List",
|
||||
"make_admin": "Make Admin",
|
||||
@@ -286,6 +287,7 @@
|
||||
"no_invite": "No pending invites found",
|
||||
"no_shared_requests": "No shared requests created by the user",
|
||||
"no_users": "No users found",
|
||||
"not_available": "Not Available",
|
||||
"not_found": "User not found",
|
||||
"pending_invites": "Pending Invites",
|
||||
"remove_admin_privilege": "Remove Admin Privilege",
|
||||
|
||||
10
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
10
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
@@ -17,23 +17,13 @@ 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']
|
||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||
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']
|
||||
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['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']
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMutation } from '@urql/vue';
|
||||
import { useTimeAgo } from '@vueuse/core';
|
||||
import { format } from 'date-fns';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
@@ -133,7 +134,7 @@ const getCreatedDateAndTime = (date: string) =>
|
||||
format(new Date(date), 'd-MM-yyyy hh:mm a');
|
||||
|
||||
// User Info
|
||||
const { uid, displayName, email, createdOn } = props.user;
|
||||
const { uid, displayName, email, createdOn, lastActiveOn } = props.user;
|
||||
|
||||
const userInfo = {
|
||||
uid: {
|
||||
@@ -156,6 +157,13 @@ const userInfo = {
|
||||
label: t('users.created_on'),
|
||||
value: getCreatedDateAndTime(createdOn),
|
||||
},
|
||||
lastActiveOn: {
|
||||
condition: lastActiveOn,
|
||||
label: t('users.last_active_on'),
|
||||
value: lastActiveOn
|
||||
? useTimeAgo(lastActiveOn).value
|
||||
: t('users.not_available'),
|
||||
},
|
||||
};
|
||||
|
||||
// Contains the actual user name
|
||||
|
||||
@@ -7,6 +7,7 @@ query UserInfo($uid: ID!) {
|
||||
isAdmin
|
||||
photoURL
|
||||
createdOn
|
||||
lastActiveOn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ query UsersListV2($searchString: String, $skip: Int, $take: Int) {
|
||||
isAdmin
|
||||
photoURL
|
||||
createdOn
|
||||
lastActiveOn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@
|
||||
</div>
|
||||
</template>
|
||||
<template #head>
|
||||
<th class="px-6 py-2">{{ t('users.id') }}</th>
|
||||
<th class="px-6 py-2">{{ t('users.name') }}</th>
|
||||
<th class="px-6 py-2">{{ t('users.email') }}</th>
|
||||
<th class="px-6 py-2">{{ t('users.date') }}</th>
|
||||
<th class="px-6 py-2">{{ t('users.created_on') }}</th>
|
||||
<th class="px-6 py-2">{{ t('users.last_active_on') }}</th>
|
||||
<!-- Empty header for Action Button -->
|
||||
<th class="w-20 px-6 py-2"></th>
|
||||
</template>
|
||||
@@ -79,10 +79,6 @@
|
||||
</template>
|
||||
|
||||
<template #body="{ row: user }">
|
||||
<td class="py-2 px-7 max-w-[8rem] truncate">
|
||||
{{ user.uid }}
|
||||
</td>
|
||||
|
||||
<td class="py-2 px-7">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>
|
||||
@@ -109,6 +105,8 @@
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="py-2 px-7">{{ getLastActiveOn(user.lastActiveOn) }}</td>
|
||||
|
||||
<td @click.stop class="flex justify-end w-20">
|
||||
<div class="mt-2 mr-5">
|
||||
<tippy interactive trigger="click" theme="popover">
|
||||
@@ -245,6 +243,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMutation, useQuery } from '@urql/vue';
|
||||
import { useTimeAgo } from '@vueuse/core';
|
||||
import { format } from 'date-fns';
|
||||
import { computed, onUnmounted, ref, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -277,15 +276,18 @@ import IconX from '~icons/lucide/x';
|
||||
const t = useI18n();
|
||||
const toast = useToast();
|
||||
|
||||
// Time and Date Helpers
|
||||
const getCreatedDate = (date: string) => format(new Date(date), 'dd-MM-yyyy');
|
||||
const getCreatedTime = (date: string) => format(new Date(date), 'hh:mm a');
|
||||
const getLastActiveOn = (date: string | null) =>
|
||||
date ? useTimeAgo(date).value : t('users.not_available');
|
||||
|
||||
// Table Headings
|
||||
const headings = [
|
||||
{ key: 'uid', label: t('users.id') },
|
||||
{ key: 'displayName', label: t('users.name') },
|
||||
{ key: 'email', label: t('users.email') },
|
||||
{ key: 'createdOn', label: t('users.date') },
|
||||
{ key: 'createdOn', label: t('users.created_on') },
|
||||
{ key: 'lastActiveOn', label: t('users.last_active_on') },
|
||||
{ key: '', label: '' },
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user