Skip to content

Commit 9adae1a

Browse files
committed
Refactor dashboard org queries and counts
1 parent 8e81ccf commit 9adae1a

1 file changed

Lines changed: 118 additions & 144 deletions

File tree

apps/web/app/(org)/dashboard/dashboard-data.ts

Lines changed: 118 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -48,41 +48,25 @@ export type UserPreferences = (typeof users.$inferSelect)["preferences"];
4848

4949
export async function getDashboardData(user: typeof userSelectProps) {
5050
try {
51-
const organizationsWithMembers = await db()
52-
.select({
53-
organization: organizations,
54-
settings: organizations.settings,
55-
member: organizationMembers,
56-
iconUrl: organizations.iconUrl,
57-
user: {
58-
id: users.id,
59-
name: users.name,
60-
lastName: users.lastName,
61-
email: users.email,
62-
inviteQuota: users.inviteQuota,
63-
image: users.image,
64-
defaultOrgId: users.defaultOrgId,
65-
},
66-
})
51+
const memberOrgIds = db()
52+
.select({ id: organizationMembers.organizationId })
53+
.from(organizationMembers)
54+
.where(eq(organizationMembers.userId, user.id));
55+
56+
const userOrganizations = await db()
57+
.select()
6758
.from(organizations)
68-
.leftJoin(
69-
organizationMembers,
70-
eq(organizations.id, organizationMembers.organizationId),
71-
)
72-
.leftJoin(users, eq(organizationMembers.userId, users.id))
7359
.where(
7460
and(
61+
isNull(organizations.tombstoneAt),
7562
or(
7663
eq(organizations.ownerId, user.id),
77-
eq(organizationMembers.userId, user.id),
64+
inArray(organizations.id, memberOrgIds),
7865
),
79-
isNull(organizations.tombstoneAt),
8066
),
8167
);
8268

83-
const organizationIds = organizationsWithMembers.map(
84-
(row) => row.organization.id,
85-
);
69+
const organizationIds = userOrganizations.map((org) => org.id);
8670

8771
let organizationInvitesData: (typeof organizationInvites.$inferSelect)[] =
8872
[];
@@ -190,31 +174,22 @@ export async function getDashboardData(user: typeof userSelectProps) {
190174
}).pipe(runPromise);
191175

192176
// Add a single 'All spaces' entry for the active organization
193-
const activeOrgInfo = organizationsWithMembers.find(
194-
(row) => row.organization.id === activeOrganizationId,
177+
const activeOrgInfo = userOrganizations.find(
178+
(org) => org.id === activeOrganizationId,
195179
);
196180
if (activeOrgInfo) {
197-
// Count all members in the organization
198181
const orgMemberCountResult = await db()
199182
.select({ value: sql<number>`COUNT(*)` })
200183
.from(organizationMembers)
201-
.where(
202-
eq(
203-
organizationMembers.organizationId,
204-
activeOrgInfo.organization.id,
205-
),
206-
);
184+
.where(eq(organizationMembers.organizationId, activeOrgInfo.id));
207185
const orgMemberCount = orgMemberCountResult[0]?.value || 0;
208186

209-
// Count all videos shared with the organization (via sharedVideos table)
210187
const orgVideoCountResult = await db()
211188
.select({
212189
value: sql<number>`COUNT(DISTINCT ${sharedVideos.videoId})`,
213190
})
214191
.from(sharedVideos)
215-
.where(
216-
eq(sharedVideos.organizationId, activeOrgInfo.organization.id),
217-
);
192+
.where(eq(sharedVideos.organizationId, activeOrgInfo.id));
218193
const orgVideoCount = orgVideoCountResult[0]?.value || 0;
219194

220195
const userCapsCountResult = await db()
@@ -224,7 +199,7 @@ export async function getDashboardData(user: typeof userSelectProps) {
224199
.from(videos)
225200
.where(
226201
and(
227-
eq(videos.orgId, activeOrgInfo.organization.id),
202+
eq(videos.orgId, activeOrgInfo.id),
228203
eq(videos.ownerId, user.id),
229204
),
230205
);
@@ -234,20 +209,20 @@ export async function getDashboardData(user: typeof userSelectProps) {
234209
const allSpacesEntry = await Effect.gen(function* () {
235210
const imageUploads = yield* ImageUploads;
236211

237-
const iconUrl = activeOrgInfo.organization.iconUrl;
212+
const iconUrl = activeOrgInfo.iconUrl;
238213

239214
return {
240-
id: activeOrgInfo.organization.id,
215+
id: activeOrgInfo.id,
241216
primary: true,
242217
privacy: "Public",
243-
name: `All ${activeOrgInfo.organization.name}`,
244-
description: `View all content in ${activeOrgInfo.organization.name}`,
245-
organizationId: activeOrgInfo.organization.id,
218+
name: `All ${activeOrgInfo.name}`,
219+
description: `View all content in ${activeOrgInfo.name}`,
220+
organizationId: activeOrgInfo.id,
246221
iconUrl: iconUrl
247222
? yield* imageUploads.resolveImageUrl(iconUrl)
248223
: null,
249224
memberCount: orgMemberCount,
250-
createdById: activeOrgInfo.organization.ownerId,
225+
createdById: activeOrgInfo.ownerId,
251226
videoCount: orgVideoCount,
252227
} as const;
253228
}).pipe(runPromise);
@@ -265,107 +240,106 @@ export async function getDashboardData(user: typeof userSelectProps) {
265240
.limit(1);
266241

267242
const organizationSelect: Organization[] = await Effect.all(
268-
organizationsWithMembers
269-
.reduce((acc: (typeof organizations.$inferSelect)[], row) => {
270-
const existingOrganization = acc.find(
271-
(o) => o.id === row.organization.id,
243+
userOrganizations.map(
244+
Effect.fn(function* (organization) {
245+
const db = yield* Database;
246+
const iconImages = yield* ImageUploads;
247+
248+
const allMembers = yield* db.use((db) =>
249+
db
250+
.select({
251+
member: organizationMembers,
252+
user: {
253+
id: users.id,
254+
name: users.name,
255+
lastName: users.lastName,
256+
email: users.email,
257+
image: users.image,
258+
},
259+
})
260+
.from(organizationMembers)
261+
.leftJoin(users, eq(organizationMembers.userId, users.id))
262+
.where(eq(organizationMembers.organizationId, organization.id)),
272263
);
273-
if (!existingOrganization) {
274-
acc.push(row.organization);
275-
}
276-
return acc;
277-
}, [])
278-
.map(
279-
Effect.fn(function* (organization) {
280-
const db = yield* Database;
281-
const iconImages = yield* ImageUploads;
282-
283-
const allMembers = yield* db.use((db) =>
284-
db
285-
.select({
286-
member: organizationMembers,
287-
user: {
288-
id: users.id,
289-
name: users.name,
290-
lastName: users.lastName,
291-
email: users.email,
292-
image: users.image,
293-
},
294-
})
295-
.from(organizationMembers)
296-
.leftJoin(users, eq(organizationMembers.userId, users.id))
297-
.where(eq(organizationMembers.organizationId, organization.id)),
298-
);
299-
300-
const owner = yield* db.use((db) =>
301-
db
302-
.select({
303-
inviteQuota: users.inviteQuota,
304-
})
305-
.from(users)
306-
.where(eq(users.id, organization.ownerId))
307-
.then((result) => result[0]),
308-
);
309-
310-
const totalInvitesResult = yield* db.use((db) =>
311-
db
312-
.select({
313-
value: sql<number>`
314-
${count(organizationMembers.id)} + ${count(
315-
organizationInvites.id,
316-
)}
317-
`,
318-
})
319-
.from(organizations)
320-
.leftJoin(
321-
organizationMembers,
322-
eq(organizations.id, organizationMembers.organizationId),
323-
)
324-
.leftJoin(
325-
organizationInvites,
326-
eq(organizations.id, organizationInvites.organizationId),
327-
)
328-
.where(
329-
and(
330-
eq(organizations.ownerId, organization.ownerId),
331-
isNull(organizations.tombstoneAt),
332-
),
333-
),
334-
);
335-
336-
const totalInvites = totalInvitesResult[0]?.value || 0;
337-
338-
return {
339-
organization: {
340-
...organization,
341-
iconUrl: organization.iconUrl
342-
? yield* iconImages.resolveImageUrl(organization.iconUrl)
343-
: null,
344-
},
345-
members: yield* Effect.all(
346-
allMembers.map(
347-
Effect.fn(function* (m) {
348-
const imageUploads = yield* ImageUploads;
349-
return {
350-
...m.member,
351-
user: {
352-
...m.user!,
353-
image: m.user?.image
354-
? yield* imageUploads.resolveImageUrl(m.user?.image)
355-
: null,
356-
},
357-
};
358-
}),
264+
265+
const owner = yield* db.use((db) =>
266+
db
267+
.select({
268+
inviteQuota: users.inviteQuota,
269+
})
270+
.from(users)
271+
.where(eq(users.id, organization.ownerId))
272+
.then((result) => result[0]),
273+
);
274+
275+
const ownedOrgIds = db.use((db) =>
276+
db
277+
.select({ id: organizations.id })
278+
.from(organizations)
279+
.where(
280+
and(
281+
eq(organizations.ownerId, organization.ownerId),
282+
isNull(organizations.tombstoneAt),
359283
),
284+
)
285+
.then((rows) => rows.map((r) => r.id)),
286+
);
287+
288+
const ownedIds = yield* ownedOrgIds;
289+
290+
const memberCountResult = yield* db.use((db) =>
291+
ownedIds.length > 0
292+
? db
293+
.select({ value: count() })
294+
.from(organizationMembers)
295+
.where(inArray(organizationMembers.organizationId, ownedIds))
296+
: Promise.resolve([{ value: 0 }]),
297+
);
298+
299+
const inviteCountResult = yield* db.use((db) =>
300+
ownedIds.length > 0
301+
? db
302+
.select({ value: count() })
303+
.from(organizationInvites)
304+
.where(inArray(organizationInvites.organizationId, ownedIds))
305+
: Promise.resolve([{ value: 0 }]),
306+
);
307+
308+
const totalInvites =
309+
(memberCountResult[0]?.value || 0) +
310+
(inviteCountResult[0]?.value || 0);
311+
312+
return {
313+
organization: {
314+
...organization,
315+
iconUrl: organization.iconUrl
316+
? yield* iconImages.resolveImageUrl(organization.iconUrl)
317+
: null,
318+
},
319+
members: yield* Effect.all(
320+
allMembers.map(
321+
Effect.fn(function* (m) {
322+
const imageUploads = yield* ImageUploads;
323+
return {
324+
...m.member,
325+
user: {
326+
...m.user!,
327+
image: m.user?.image
328+
? yield* imageUploads.resolveImageUrl(m.user?.image)
329+
: null,
330+
},
331+
};
332+
}),
360333
),
361-
invites: organizationInvitesData.filter(
362-
(invite) => invite.organizationId === organization.id,
363-
),
364-
inviteQuota: owner?.inviteQuota || 1,
365-
totalInvites,
366-
};
367-
}),
368-
),
334+
),
335+
invites: organizationInvitesData.filter(
336+
(invite) => invite.organizationId === organization.id,
337+
),
338+
inviteQuota: owner?.inviteQuota || 1,
339+
totalInvites,
340+
};
341+
}),
342+
),
369343
{ concurrency: 3 },
370344
).pipe(runPromise);
371345

0 commit comments

Comments
 (0)