Skip to content

Commit 509743d

Browse files
committed
apply ImageUrl to more places
1 parent 99fbf9b commit 509743d

File tree

4 files changed

+118
-100
lines changed

4 files changed

+118
-100
lines changed

apps/web/app/(org)/dashboard/caps/Caps.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import type { VideoMetadata } from "@cap/database/types";
44
import { Button } from "@cap/ui";
5-
import type { Video } from "@cap/web-domain";
5+
import type { ImageUpload, Video } from "@cap/web-domain";
66
import { faFolderPlus, faInfoCircle } from "@fortawesome/free-solid-svg-icons";
77
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
88
import { Effect, Exit } from "effect";
@@ -34,11 +34,14 @@ export type VideoData = {
3434
totalComments: number;
3535
totalReactions: number;
3636
foldersData: FolderDataType[];
37-
sharedOrganizations: { id: string; name: string; iconUrl?: string }[];
37+
sharedOrganizations: {
38+
id: string;
39+
name: string;
40+
iconUrl?: ImageUpload.ImageUrl | null;
41+
}[];
3842
sharedSpaces?: {
3943
id: string;
4044
name: string;
41-
iconUrl: string;
4245
isOrg: boolean;
4346
organizationId: string;
4447
}[];

apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
DropdownMenuItem,
99
DropdownMenuTrigger,
1010
} from "@cap/ui";
11-
import type { Video } from "@cap/web-domain";
11+
import type { ImageUpload, Video } from "@cap/web-domain";
1212
import { HttpClient } from "@effect/platform";
1313
import {
1414
faCheck,
@@ -63,12 +63,12 @@ export interface CapCardProps extends PropsWithChildren {
6363
sharedOrganizations?: {
6464
id: string;
6565
name: string;
66-
iconUrl?: string | null;
66+
iconUrl?: ImageUpload.ImageUrl | null;
6767
}[];
6868
sharedSpaces?: {
6969
id: string;
7070
name: string;
71-
iconUrl?: string | null;
71+
iconUrl?: ImageUpload.ImageUrl | null;
7272
organizationId: string;
7373
}[];
7474
ownerName: string | null;

apps/web/app/(org)/dashboard/caps/page.tsx

Lines changed: 58 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { serverEnv } from "@cap/env";
1515
import { Database, ImageUploads } from "@cap/web-backend";
1616
import { type ImageUpload, Video } from "@cap/web-domain";
1717
import { and, count, desc, eq, inArray, isNull, sql } from "drizzle-orm";
18-
import { Array, Effect } from "effect";
18+
import { type Array, Effect } from "effect";
1919
import type { Metadata } from "next";
2020
import { redirect } from "next/navigation";
2121
import { runPromise } from "@/lib/server";
@@ -32,41 +32,21 @@ const getSharedSpacesForVideos = Effect.fn(function* (
3232
if (videoIds.length === 0) return {};
3333

3434
const db = yield* Database;
35-
const imageUploads = yield* ImageUploads;
3635

3736
// Fetch space-level sharing
38-
const spaceSharing = yield* db
39-
.use((db) =>
40-
db
41-
.select({
42-
videoId: spaceVideos.videoId,
43-
id: spaces.id,
44-
name: spaces.name,
45-
organizationId: spaces.organizationId,
46-
iconUrl: organizations.iconUrl,
47-
})
48-
.from(spaceVideos)
49-
.innerJoin(spaces, eq(spaceVideos.spaceId, spaces.id))
50-
.innerJoin(organizations, eq(spaces.organizationId, organizations.id))
51-
.where(inArray(spaceVideos.videoId, videoIds)),
52-
)
53-
.pipe(
54-
Effect.map((v) =>
55-
v.map(
56-
Effect.fn(function* (v) {
57-
return {
58-
...v,
59-
iconUrl: v.iconUrl
60-
? yield* imageUploads.resolveImageUrl(
61-
v.iconUrl as ImageUpload.ImageUrlOrKey,
62-
)
63-
: null,
64-
};
65-
}),
66-
),
67-
),
68-
Effect.flatMap(Effect.all),
69-
);
37+
const spaceSharing = yield* db.use((db) =>
38+
db
39+
.select({
40+
videoId: spaceVideos.videoId,
41+
id: spaces.id,
42+
name: spaces.name,
43+
organizationId: spaces.organizationId,
44+
})
45+
.from(spaceVideos)
46+
.innerJoin(spaces, eq(spaceVideos.spaceId, spaces.id))
47+
.innerJoin(organizations, eq(spaces.organizationId, organizations.id))
48+
.where(inArray(spaceVideos.videoId, videoIds)),
49+
);
7050

7151
// Fetch organization-level sharing
7252
const orgSharing = yield* db.use((db) =>
@@ -93,7 +73,6 @@ const getSharedSpacesForVideos = Effect.fn(function* (
9373
id: string;
9474
name: string;
9575
organizationId: string;
96-
iconUrl: string;
9776
isOrg: boolean;
9877
}>
9978
> = {};
@@ -107,7 +86,6 @@ const getSharedSpacesForVideos = Effect.fn(function* (
10786
id: space.id,
10887
name: space.name,
10988
organizationId: space.organizationId,
110-
iconUrl: space.iconUrl || "",
11189
isOrg: false,
11290
});
11391
});
@@ -121,7 +99,6 @@ const getSharedSpacesForVideos = Effect.fn(function* (
12199
id: org.id,
122100
name: org.name,
123101
organizationId: org.organizationId,
124-
iconUrl: org.iconUrl || "",
125102
isOrg: true,
126103
});
127104
});
@@ -167,7 +144,13 @@ export default async function CapsPage(props: PageProps<"/dashboard/caps">) {
167144
public: videos.public,
168145
totalComments: sql<number>`COUNT(DISTINCT CASE WHEN ${comments.type} = 'text' THEN ${comments.id} END)`,
169146
totalReactions: sql<number>`COUNT(DISTINCT CASE WHEN ${comments.type} = 'emoji' THEN ${comments.id} END)`,
170-
sharedOrganizations: sql<{ id: string; name: string; iconUrl: string }[]>`
147+
sharedOrganizations: sql<
148+
{
149+
id: string;
150+
name: string;
151+
iconUrl: ImageUpload.ImageUrlOrKey | null;
152+
}[]
153+
>`
171154
COALESCE(
172155
JSON_ARRAYAGG(
173156
JSON_OBJECT(
@@ -247,31 +230,44 @@ export default async function CapsPage(props: PageProps<"/dashboard/caps">) {
247230
const sharedSpacesMap =
248231
await getSharedSpacesForVideos(videoIds).pipe(runPromise);
249232

250-
const processedVideoData = videoData.map((video) => {
251-
const { effectiveDate, ...videoWithoutEffectiveDate } = video;
233+
const processedVideoData = await Effect.all(
234+
videoData.map(
235+
Effect.fn(function* (video) {
236+
const imageUploads = yield* ImageUploads;
252237

253-
return {
254-
...videoWithoutEffectiveDate,
255-
id: Video.VideoId.make(video.id),
256-
foldersData,
257-
settings: video.settings,
258-
sharedOrganizations: Array.isArray(video.sharedOrganizations)
259-
? video.sharedOrganizations.filter(
260-
(organization) => organization.id !== null,
261-
)
262-
: [],
263-
sharedSpaces: Array.isArray(sharedSpacesMap[video.id])
264-
? sharedSpacesMap[video.id]
265-
: [],
266-
ownerName: video.ownerName ?? "",
267-
metadata: video.metadata as
268-
| {
269-
customCreatedAt?: string;
270-
[key: string]: any;
271-
}
272-
| undefined,
273-
};
274-
});
238+
const { effectiveDate, ...videoWithoutEffectiveDate } = video;
239+
240+
return {
241+
...videoWithoutEffectiveDate,
242+
id: Video.VideoId.make(video.id),
243+
foldersData,
244+
settings: video.settings,
245+
sharedOrganizations: yield* Effect.all(
246+
(video.sharedOrganizations ?? [])
247+
.filter((organization) => organization.id !== null)
248+
.map(
249+
Effect.fn(function* (org) {
250+
return {
251+
...org,
252+
iconUrl: org.iconUrl
253+
? yield* imageUploads.resolveImageUrl(org.iconUrl)
254+
: null,
255+
};
256+
}),
257+
),
258+
),
259+
sharedSpaces: sharedSpacesMap[video.id] ?? [],
260+
ownerName: video.ownerName ?? "",
261+
metadata: video.metadata as
262+
| {
263+
customCreatedAt?: string;
264+
[key: string]: any;
265+
}
266+
| undefined,
267+
};
268+
}),
269+
),
270+
).pipe(runPromise);
275271

276272
return (
277273
<Caps

apps/web/lib/folder.ts

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import {
1111
videos,
1212
videoUploads,
1313
} from "@cap/database/schema";
14-
import { Database } from "@cap/web-backend";
15-
import type { Organisation, Space, Video } from "@cap/web-domain";
14+
import { Database, ImageUploads } from "@cap/web-backend";
15+
import type { ImageUpload, Organisation, Space, Video } from "@cap/web-domain";
1616
import { CurrentUser, Folder } from "@cap/web-domain";
1717
import { and, desc, eq } from "drizzle-orm";
1818
import { sql } from "drizzle-orm/sql";
1919
import { Effect } from "effect";
20+
import { runPromise } from "./server";
2021

2122
export const getFolderById = Effect.fn(function* (folderId: string) {
2223
if (!folderId) throw new Error("Folder ID is required");
@@ -163,6 +164,7 @@ export const getVideosByFolderId = Effect.fn(function* (
163164
) {
164165
if (!folderId) throw new Error("Folder ID is required");
165166
const db = yield* Database;
167+
const imageUploads = yield* ImageUploads;
166168

167169
const videoData = yield* db.use((db) =>
168170
db
@@ -177,7 +179,11 @@ export const getVideosByFolderId = Effect.fn(function* (
177179
totalComments: sql<number>`COUNT(DISTINCT CASE WHEN ${comments.type} = 'text' THEN ${comments.id} END)`,
178180
totalReactions: sql<number>`COUNT(DISTINCT CASE WHEN ${comments.type} = 'emoji' THEN ${comments.id} END)`,
179181
sharedOrganizations: sql<
180-
{ id: string; name: string; iconUrl: string }[]
182+
{
183+
id: string;
184+
name: string;
185+
iconUrl: ImageUpload.ImageUrlOrKey | null;
186+
}[]
181187
>`
182188
COALESCE(
183189
JSON_ARRAYAGG(
@@ -242,35 +248,48 @@ export const getVideosByFolderId = Effect.fn(function* (
242248
const sharedSpacesMap = yield* getSharedSpacesForVideos(videoIds);
243249

244250
// Process the video data to match the expected format
245-
const processedVideoData = videoData.map((video) => {
246-
return {
247-
id: video.id as Video.VideoId, // Cast to Video.VideoId branded type
248-
ownerId: video.ownerId,
249-
name: video.name,
250-
createdAt: video.createdAt,
251-
public: video.public,
252-
totalComments: video.totalComments,
253-
totalReactions: video.totalReactions,
254-
sharedOrganizations: Array.isArray(video.sharedOrganizations)
255-
? video.sharedOrganizations.filter(
256-
(organization) => organization.id !== null,
257-
)
258-
: [],
259-
sharedSpaces: Array.isArray(sharedSpacesMap[video.id])
260-
? sharedSpacesMap[video.id]
261-
: [],
262-
ownerName: video.ownerName ?? "",
263-
metadata: video.metadata as
264-
| {
265-
customCreatedAt?: string;
266-
[key: string]: unknown;
267-
}
268-
| undefined,
269-
hasPassword: video.hasPassword,
270-
hasActiveUpload: video.hasActiveUpload,
271-
foldersData: [], // Empty array since videos in a folder don't need folder data
272-
};
273-
});
251+
const processedVideoData = yield* Effect.all(
252+
videoData.map(
253+
Effect.fn(function* (video) {
254+
return {
255+
id: video.id as Video.VideoId, // Cast to Video.VideoId branded type
256+
ownerId: video.ownerId,
257+
name: video.name,
258+
createdAt: video.createdAt,
259+
public: video.public,
260+
totalComments: video.totalComments,
261+
totalReactions: video.totalReactions,
262+
sharedOrganizations: yield* Effect.all(
263+
(video.sharedOrganizations ?? [])
264+
.filter((organization) => organization.id !== null)
265+
.map(
266+
Effect.fn(function* (org) {
267+
return {
268+
...org,
269+
iconUrl: org.iconUrl
270+
? yield* imageUploads.resolveImageUrl(org.iconUrl)
271+
: null,
272+
};
273+
}),
274+
),
275+
),
276+
sharedSpaces: Array.isArray(sharedSpacesMap[video.id])
277+
? sharedSpacesMap[video.id]
278+
: [],
279+
ownerName: video.ownerName ?? "",
280+
metadata: video.metadata as
281+
| {
282+
customCreatedAt?: string;
283+
[key: string]: unknown;
284+
}
285+
| undefined,
286+
hasPassword: video.hasPassword,
287+
hasActiveUpload: video.hasActiveUpload,
288+
foldersData: [], // Empty array since videos in a folder don't need folder data
289+
};
290+
}),
291+
),
292+
);
274293

275294
return processedVideoData;
276295
});

0 commit comments

Comments
 (0)