From 63fa3995c533815e61dbfaa1fbc3f3fdd0a8a0d9 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 3 Mar 2025 19:31:35 +0100 Subject: [PATCH] refactoring --- consumer/src/index.ts | 11 +- dashboard/components/FirstInteraction.vue | 26 +- dashboard/components/admin/Overview.vue | 26 +- .../components/dashboard/ActionableChart.vue | 5 + dashboard/components/dashboard/TopCards.vue | 2 +- dashboard/components/dialog/InviteManager.vue | 56 + .../components/dialog/PermissionManager.vue | 110 ++ dashboard/components/layout/TopNavigation.vue | 66 +- .../components/layout/VerticalNavigation.vue | 43 +- .../components/selector/DomainSelector.vue | 6 +- .../components/selector/ProjectSelector.vue | 1 - dashboard/components/settings/members.vue | 123 -- dashboard/composables/useDomain.ts | 18 +- dashboard/composables/usePermission.ts | 14 + dashboard/layouts/dashboard.vue | 1 + dashboard/pages/accept_invite.vue | 34 + dashboard/pages/admin/index.vue | 157 -- dashboard/pages/analyst.vue | 9 +- dashboard/pages/events.vue | 8 +- dashboard/pages/index.vue | 38 +- dashboard/pages/members.vue | 186 ++ dashboard/pages/settings.vue | 4 - dashboard/pages/test_links.vue | 15 + dashboard/public/tech-icons/wpel.png | Bin 0 -> 4378 bytes dashboard/public/yt.png | Bin 0 -> 2102 bytes dashboard/server/api/admin/metrics.ts | 36 + dashboard/server/api/ai/[chat_id]/delete.ts | 2 +- .../server/api/ai/[chat_id]/get_messages.ts | 2 +- dashboard/server/api/ai/[chat_id]/status.ts | 2 +- dashboard/server/api/ai/chats_remaining.ts | 2 +- dashboard/server/api/ai/delete_all_chats.ts | 2 +- dashboard/server/api/ai/send_message.post.ts | 2 +- dashboard/server/api/data/browsers.ts | 2 +- dashboard/server/api/data/count.ts | 2 +- dashboard/server/api/data/countries.ts | 2 +- dashboard/server/api/data/devices.ts | 2 +- dashboard/server/api/data/events.ts | 2 +- dashboard/server/api/data/oss.ts | 2 +- dashboard/server/api/data/pages.ts | 2 +- dashboard/server/api/data/referrers.ts | 2 +- dashboard/server/api/domains/list.ts | 35 +- dashboard/server/api/project/links/list.ts | 18 + .../server/api/project/members/accept.post.ts | 21 + .../server/api/project/members/add.post.ts | 66 +- .../api/project/members/decline.post.ts | 18 + .../server/api/project/members/edit.post.ts | 25 + dashboard/server/api/project/members/get.ts | 23 + .../server/api/project/members/kick.post.ts | 2 +- dashboard/server/api/project/members/leave.ts | 2 +- dashboard/server/api/project/members/list.ts | 36 +- dashboard/server/api/project/members/me.ts | 39 + .../server/api/project/members/pending.ts | 44 + .../server/api/timeline/bouncing_rate.ts | 9 +- dashboard/server/api/timeline/events.ts | 2 +- .../server/api/timeline/events_stacked.ts | 2 +- dashboard/server/api/timeline/sessions.ts | 2 +- .../server/api/timeline/sessions_duration.ts | 4 +- dashboard/server/api/timeline/visits.ts | 2 +- dashboard/server/utils/getRequestData.ts | 59 +- email/package.json | 3 +- email/pnpm-lock.yaml | 1737 +++++++++++++++++ email/src/services/email.ts | 54 +- email/src/services/server.ts | 30 + email/src/services/templates.ts | 7 +- email/templates/ProjectInviteEmail.ts | 21 + .../templates/ProjectInviteEmailNoAccount.ts | 21 + scripts/email/deploy.ts | 2 +- shared_global/schema/TeamMemberSchema.ts | 14 +- .../schema/project/ProjectLinkSchema.ts | 19 + shared_global/services/EmailService.ts | 6 +- 70 files changed, 2928 insertions(+), 418 deletions(-) create mode 100644 dashboard/components/dialog/InviteManager.vue create mode 100644 dashboard/components/dialog/PermissionManager.vue delete mode 100644 dashboard/components/settings/members.vue create mode 100644 dashboard/composables/usePermission.ts create mode 100644 dashboard/pages/accept_invite.vue create mode 100644 dashboard/pages/members.vue create mode 100644 dashboard/pages/test_links.vue create mode 100644 dashboard/public/tech-icons/wpel.png create mode 100644 dashboard/public/yt.png create mode 100644 dashboard/server/api/admin/metrics.ts create mode 100644 dashboard/server/api/project/links/list.ts create mode 100644 dashboard/server/api/project/members/accept.post.ts create mode 100644 dashboard/server/api/project/members/decline.post.ts create mode 100644 dashboard/server/api/project/members/edit.post.ts create mode 100644 dashboard/server/api/project/members/get.ts create mode 100644 dashboard/server/api/project/members/me.ts create mode 100644 dashboard/server/api/project/members/pending.ts create mode 100644 email/templates/ProjectInviteEmail.ts create mode 100644 email/templates/ProjectInviteEmailNoAccount.ts create mode 100644 shared_global/schema/project/ProjectLinkSchema.ts diff --git a/consumer/src/index.ts b/consumer/src/index.ts index 6c1e33a..6e16ad1 100644 --- a/consumer/src/index.ts +++ b/consumer/src/index.ts @@ -112,7 +112,7 @@ async function process_visit(data: Record, sessionHash: string) async function process_keep_alive(data: Record, sessionHash: string) { - const { pid, instant, flowHash, timestamp } = data; + const { pid, instant, flowHash, timestamp, website } = data; const existingSession = await SessionModel.findOne({ project_id: pid, session: sessionHash }, { _id: 1 }); if (!existingSession) { @@ -123,13 +123,15 @@ async function process_keep_alive(data: Record, sessionHash: str await SessionModel.updateOne({ project_id: pid, session: sessionHash, }, { $inc: { duration: 0 }, flowHash, - updated_at: Date.now() + website, + updated_at: new Date(parseInt(timestamp)) }, { upsert: true }); } else { await SessionModel.updateOne({ project_id: pid, session: sessionHash, }, { $inc: { duration: 1 }, flowHash, - updated_at: Date.now() + website, + updated_at: new Date(parseInt(timestamp)) }, { upsert: true }); } @@ -137,7 +139,7 @@ async function process_keep_alive(data: Record, sessionHash: str async function process_event(data: Record, sessionHash: string) { - const { name, metadata, pid, flowHash, timestamp } = data; + const { name, metadata, pid, flowHash, timestamp, website } = data; let metadataObject; try { @@ -149,6 +151,7 @@ async function process_event(data: Record, sessionHash: string) await Promise.all([ EventModel.create({ project_id: pid, name, flowHash, metadata: metadataObject, session: sessionHash, + website, created_at: new Date(parseInt(timestamp)) }), ProjectCountModel.updateOne({ project_id: pid }, { $inc: { 'events': 1 } }, { upsert: true }), diff --git a/dashboard/components/FirstInteraction.vue b/dashboard/components/FirstInteraction.vue index 5debe10..a2a5f85 100644 --- a/dashboard/components/FirstInteraction.vue +++ b/dashboard/components/FirstInteraction.vue @@ -79,13 +79,13 @@ function reloadPage() { -
+
-
@@ -133,6 +133,28 @@ function reloadPage() {
+
+
+ + + +
+ + +
+
+
+
{ const filter = ref('{}'); -const { data: projectsInfo, pending: pendingProjects } = await useFetch<{ count: number, projects: TAdminProject[] }>( +const { data: projectsInfo, pending: pendingProjects } = useFetch<{ count: number, projects: TAdminProject[] }>( () => `/api/admin/projects?page=${page.value - 1}&limit=${limit.value}&sortQuery=${order.value}&filterQuery=${filter.value}&filterFrom=${selected.value.start.toISOString()}&filterTo=${selected.value.end.toISOString()}`, signHeaders() ); - +const { data: metrics, pending: pendingMetrics } = useFetch( + () => `/api/admin/metrics?filterFrom=${selected.value.start.toISOString()}&filterTo=${selected.value.end.toISOString()}`, + signHeaders() +); const { uiMenu } = useSelectMenuStyle(); @@ -136,7 +139,7 @@ const { uiMenu } = useSelectMenuStyle();
Page {{ page }}
{{ Math.min(limit, projectsInfo?.count || 0) }} of {{ projectsInfo?.count || 0 - }}
+ }}
@@ -165,6 +168,23 @@ const { uiMenu } = useSelectMenuStyle();
+ +
+
Loading...
+
+
Projects: {{ metrics.totalProjects }} ({{ metrics.premiumProjects }} premium)
+
+ Total visits: {{ formatNumberK(metrics.totalVisits) }} +
+
+ Active: {{ metrics.totalProjects - metrics.deadProjects }} | + Dead: {{ metrics.deadProjects }} +
+
+ Total events: {{ formatNumberK(metrics.totalEvents) }} +
+
+
diff --git a/dashboard/components/dashboard/ActionableChart.vue b/dashboard/components/dashboard/ActionableChart.vue index 111285c..91ccc78 100644 --- a/dashboard/components/dashboard/ActionableChart.vue +++ b/dashboard/components/dashboard/ActionableChart.vue @@ -198,11 +198,16 @@ const selectLabelsAvailable = computed<{ label: string, value: Slice, disabled: }) const selectedSlice = computed(() => { + console.log({ available: selectLabelsAvailable.value }) const targetValue = selectLabelsAvailable.value[selectedLabelIndex.value]; if (!targetValue) return 'day'; if (targetValue.disabled) { selectedLabelIndex.value = selectLabelsAvailable.value.findIndex(e => !e.disabled); } + if (selectedLabelIndex.value === -1) { + console.error('ERROR CANNOT FIND CORRECT SLICE') + return 'day'; + } return selectLabelsAvailable.value[selectedLabelIndex.value].value }); diff --git a/dashboard/components/dashboard/TopCards.vue b/dashboard/components/dashboard/TopCards.vue index 1c40339..be4f089 100644 --- a/dashboard/components/dashboard/TopCards.vue +++ b/dashboard/components/dashboard/TopCards.vue @@ -8,7 +8,7 @@ const { snapshot, safeSnapshotDates, snapshotDuration } = useSnapshot() const chartSlice = computed(() => { if (snapshotDuration.value <= 3) return 'hour' as Slice; - if (snapshotDuration.value <= 32) return 'day' as Slice; + if (snapshotDuration.value <= 31 * 3) return 'day' as Slice; return 'month' as Slice; }); diff --git a/dashboard/components/dialog/InviteManager.vue b/dashboard/components/dialog/InviteManager.vue new file mode 100644 index 0000000..3617946 --- /dev/null +++ b/dashboard/components/dialog/InviteManager.vue @@ -0,0 +1,56 @@ + + + \ No newline at end of file diff --git a/dashboard/components/dialog/PermissionManager.vue b/dashboard/components/dialog/PermissionManager.vue new file mode 100644 index 0000000..9bf4ac4 --- /dev/null +++ b/dashboard/components/dialog/PermissionManager.vue @@ -0,0 +1,110 @@ + + + + + \ No newline at end of file diff --git a/dashboard/components/layout/TopNavigation.vue b/dashboard/components/layout/TopNavigation.vue index 0e0cf32..0b8988f 100644 --- a/dashboard/components/layout/TopNavigation.vue +++ b/dashboard/components/layout/TopNavigation.vue @@ -5,6 +5,7 @@ import { DialogFeedback, DialogHelp } from '#components'; const modal = useModal(); const selfhosted = useSelfhosted(); +const { domain } = useDomain(); const colorMode = useColorMode() const isDark = computed({ @@ -16,47 +17,50 @@ const isDark = computed({ } }) -const {safeSnapshotDates} = useSnapshot(); +const { safeSnapshotDates } = useSnapshot();