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:
Joel Jacob Stephen
2024-06-26 12:30:40 +05:30
committed by GitHub
parent 25fd35770a
commit b3e42bf7c3
6 changed files with 23 additions and 19 deletions

View File

@@ -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",

View File

@@ -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']

View File

@@ -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

View File

@@ -7,6 +7,7 @@ query UserInfo($uid: ID!) {
isAdmin
photoURL
createdOn
lastActiveOn
}
}
}

View File

@@ -7,6 +7,7 @@ query UsersListV2($searchString: String, $skip: Int, $take: Int) {
isAdmin
photoURL
createdOn
lastActiveOn
}
}
}

View File

@@ -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: '' },
];