From 45e9a9c6a78682851d50dfbd4eed17896966e31c Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Mar 2025 15:54:00 +0100 Subject: [PATCH] update snapthots + admin panel users --- dashboard/components/admin/Users.vue | 101 +++++++++++++----- dashboard/components/dialog/InviteManager.vue | 8 +- .../components/dialog/PermissionManager.vue | 16 ++- .../composables/snapshots/BaseSnapshots.ts | 15 +-- dashboard/composables/useSnapshot.ts | 2 +- dashboard/pages/members.vue | 13 ++- dashboard/server/api/admin/users.ts | 17 ++- 7 files changed, 122 insertions(+), 50 deletions(-) diff --git a/dashboard/components/admin/Users.vue b/dashboard/components/admin/Users.vue index ce77622..b3b2c8d 100644 --- a/dashboard/components/admin/Users.vue +++ b/dashboard/components/admin/Users.vue @@ -2,14 +2,34 @@ import { useSelectMenuStyle } from '~/composables/ui/useSelectMenuStyle'; import type { TAdminUser } from '~/server/api/admin/users'; +import { sub, format, isSameDay, type Duration, startOfDay, endOfDay } from 'date-fns' + const filterText = ref(''); -watch(filterText,()=>{ +watch(filterText, () => { page.value = 1; }) +function isRangeSelected(duration: Duration) { + return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date()) +} + +function selectRange(duration: Duration) { + selected.value = { start: sub(new Date(), duration), end: new Date() } +} + +const ranges = [ + { label: 'Last 7 days', duration: { days: 7 } }, + { label: 'Last 14 days', duration: { days: 14 } }, + { label: 'Last 30 days', duration: { days: 30 } }, + { label: 'Last 3 months', duration: { months: 3 } }, + { label: 'Last 6 months', duration: { months: 6 } }, + { label: 'Last year', duration: { years: 1 } } +] +const selected = ref<{ start: Date, end: Date }>({ start: sub(new Date(), { days: 14 }), end: new Date() }) + const filter = computed(() => { return JSON.stringify({ $or: [ @@ -39,7 +59,7 @@ const limitList = [ const limit = ref(20); const { data: usersInfo, pending: pendingUsers } = await useFetch<{ count: number, users: TAdminUser[] }>( - () => `/api/admin/users?page=${page.value - 1}&limit=${limit.value}&sortQuery=${order.value}&filterQuery=${filter.value}`, + () => `/api/admin/users?page=${page.value - 1}&limit=${limit.value}&sortQuery=${order.value}&filterQuery=${filter.value}&filterFrom=${selected.value.start.toISOString()}&filterTo=${selected.value.end.toISOString()}`, signHeaders() ); @@ -51,44 +71,71 @@ const { uiMenu } = useSelectMenuStyle();
-
+
-
-
Order:
- - -
+
+
+
Order:
+ + +
-
-
Limit:
- - -
+
+
Limit:
+ + +
-
- -
- -
-
Page {{ page }}
-
- {{ Math.min(limit, usersInfo?.count || 0) }} - of - {{ usersInfo?.count || 0 }} +
+
-
- +
+
+
Page {{ page }}
+
+ {{ Math.min(limit, usersInfo?.count || 0) }} + of + {{ usersInfo?.count || 0 }} +
+
+ +
+ +
+ + + +
+ + {{ selected.start.toLocaleDateString() }} - {{ selected.end.toLocaleDateString() }} +
+
+ +
+
+
diff --git a/dashboard/components/dialog/InviteManager.vue b/dashboard/components/dialog/InviteManager.vue index bd78fd2..4bc15d5 100644 --- a/dashboard/components/dialog/InviteManager.vue +++ b/dashboard/components/dialog/InviteManager.vue @@ -64,17 +64,17 @@ async function declineInvite(project_id: string) { }">
-
+
You are invited to join {{ invite.project_name }}. - Do you accept this invitation? + Do you accept?
-
+
+ Decline Accept - Decline
diff --git a/dashboard/components/dialog/PermissionManager.vue b/dashboard/components/dialog/PermissionManager.vue index 9bf4ac4..aaaef94 100644 --- a/dashboard/components/dialog/PermissionManager.vue +++ b/dashboard/components/dialog/PermissionManager.vue @@ -46,9 +46,17 @@ async function save(member_id: string) { }">
+ +
+
Manage permissions
+
Choose what this member can do on this project.
+
+ + +
-
Allowed domains
+
Select what domain is allowed to see:
@@ -89,7 +97,7 @@ async function save(member_id: string) {
-
Allow AI page
+
Allow to use AI data analyst
@@ -98,10 +106,10 @@ async function save(member_id: string) {
- + Cancel + Save - Cancel
diff --git a/dashboard/composables/snapshots/BaseSnapshots.ts b/dashboard/composables/snapshots/BaseSnapshots.ts index cce63df..3bfb992 100644 --- a/dashboard/composables/snapshots/BaseSnapshots.ts +++ b/dashboard/composables/snapshots/BaseSnapshots.ts @@ -88,7 +88,7 @@ export function getDefaultSnapshots(project_id: TProjectSnapshot['project_id'], name: 'Last 30 days', from: fns.startOfDay(fns.subDays(Date.now(), 30)), to: fns.endOfDay(fns.subDays(Date.now(), 0)), - color: '#BC5090', + color: '#606c38', default: true } @@ -98,7 +98,7 @@ export function getDefaultSnapshots(project_id: TProjectSnapshot['project_id'], name: 'Last 60 days', from: fns.startOfDay(fns.subDays(Date.now(), 60)), to: fns.endOfDay(fns.subDays(Date.now(), 0)), - color: '#BC5090', + color: '#bc6c25', default: true } @@ -108,15 +108,18 @@ export function getDefaultSnapshots(project_id: TProjectSnapshot['project_id'], name: 'Last 90 days', from: fns.startOfDay(fns.subDays(Date.now(), 90)), to: fns.endOfDay(fns.subDays(Date.now(), 0)), - color: '#BC5090', + color: '#fefae0', default: true } const snapshotList = [ - lastDay, today, lastMonth, currentMonth, - lastWeek, currentWeek, allTime, - last30Days, last60Days, last90Days + allTime, + lastDay, today, + lastWeek, currentWeek, + lastMonth, currentMonth, + last30Days, + last60Days, last90Days, ] return snapshotList; diff --git a/dashboard/composables/useSnapshot.ts b/dashboard/composables/useSnapshot.ts index e9c7966..f769139 100644 --- a/dashboard/composables/useSnapshot.ts +++ b/dashboard/composables/useSnapshot.ts @@ -15,7 +15,7 @@ const remoteSnapshots = useFetch('/api/project/snapshots', { watch(project, async () => { await remoteSnapshots.refresh(); - snapshot.value = isLiveDemo.value ? snapshots.value[3] : snapshots.value[3]; + snapshot.value = isLiveDemo.value ? snapshots.value[7] : snapshots.value[7]; }); const snapshots = computed(() => { diff --git a/dashboard/pages/members.vue b/dashboard/pages/members.vue index 03653e9..c130af1 100644 --- a/dashboard/pages/members.vue +++ b/dashboard/pages/members.vue @@ -114,7 +114,6 @@ async function leaveProject() { alert(ex.message); } - } @@ -129,8 +128,8 @@ async function leaveProject() { Add
-
- User should have been registered to Litlyx +
+ We will send an invitation email to the user you wish to add to this project.
@@ -150,7 +149,7 @@ async function leaveProject() { @@ -166,6 +165,10 @@ async function leaveProject() {
+ + No permission given + @@ -188,7 +191,7 @@ async function leaveProject() { diff --git a/dashboard/server/api/admin/users.ts b/dashboard/server/api/admin/users.ts index e6d6b60..2a296cb 100644 --- a/dashboard/server/api/admin/users.ts +++ b/dashboard/server/api/admin/users.ts @@ -8,16 +8,27 @@ export default defineEventHandler(async event => { if (!userData?.logged) return; if (!userData.user.roles.includes('ADMIN')) return; - const { page, limit, sortQuery, filterQuery } = getQuery(event); + const { page, limit, sortQuery, filterQuery, filterFrom, filterTo } = getQuery(event); const pageNumber = parseInt(page as string); const limitNumber = parseInt(limit as string); - const count = await UserModel.countDocuments(JSON.parse(filterQuery as string)); + const matchQuery = { + ...JSON.parse(filterQuery as string), + created_at: { + $gte: new Date(filterFrom as string), + $lte: new Date(filterTo as string) + } + } + + + const count = await UserModel.countDocuments(matchQuery); + + const users = await UserModel.aggregate([ { - $match: JSON.parse(filterQuery as string) + $match: matchQuery }, { $lookup: {