Skip to content

Commit aef45fa

Browse files
authored
Merge pull request #499 from trycompai/main
[comp] Production Deploy
2 parents 006d445 + e02703f commit aef45fa

10 files changed

Lines changed: 495 additions & 465 deletions

File tree

apps/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"@ai-sdk/provider": "^1.1.3",
2121
"@ai-sdk/react": "^1.2.9",
2222
"@aws-sdk/client-s3": "^3.796.0",
23-
"@aws-sdk/s3-request-presigner": "^3.796.0",
23+
"@aws-sdk/s3-request-presigner": "^3.800.0",
2424
"@browserbasehq/sdk": "^2.5.0",
2525
"@comp/data": "workspace:*",
2626
"@comp/db": "workspace:*",

apps/app/src/actions/files/upload-file.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { headers } from "next/headers";
99
import { PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
1010
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1111

12-
// Helper to map MIME type to AttachmentType enum
1312
function mapFileTypeToAttachmentType(fileType: string): AttachmentType {
1413
const type = fileType.split("/")[0];
1514
switch (type) {
@@ -19,19 +18,17 @@ function mapFileTypeToAttachmentType(fileType: string): AttachmentType {
1918
return AttachmentType.video;
2019
case "audio":
2120
return AttachmentType.audio;
22-
// Add more specific checks if needed (e.g., application/pdf)
2321
case "application":
2422
return AttachmentType.document;
2523
default:
2624
return AttachmentType.other;
2725
}
2826
}
2927

30-
// Update schema to include base64 file data
3128
const uploadAttachmentSchema = z.object({
3229
fileName: z.string(),
3330
fileType: z.string(),
34-
fileData: z.string(), // Base64 encoded file content
31+
fileData: z.string(),
3532
entityId: z.string(),
3633
entityType: z.nativeEnum(AttachmentEntityType),
3734
});
@@ -52,10 +49,8 @@ export const uploadFile = async (
5249
}
5350

5451
try {
55-
// 1. Decode Base64 Data
5652
const fileBuffer = Buffer.from(fileData, "base64");
5753

58-
// --- Add file size check ---
5954
const MAX_FILE_SIZE_MB = 5;
6055
const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
6156
if (fileBuffer.length > MAX_FILE_SIZE_BYTES) {
@@ -65,51 +60,45 @@ export const uploadFile = async (
6560
data: null,
6661
};
6762
}
68-
// --- End file size check ---
6963

70-
// 2. Prepare S3 Key
7164
const timestamp = Date.now();
7265
const sanitizedFileName = fileName.replace(/[^a-zA-Z0-9.-]/g, "_");
7366
const key = `${organizationId}/attachments/${entityType}/${entityId}/${timestamp}-${sanitizedFileName}`;
7467

75-
// 3. Upload directly to S3 using shared client and bucket name
7668
const putCommand = new PutObjectCommand({
7769
Bucket: BUCKET_NAME,
7870
Key: key,
7971
Body: fileBuffer,
8072
ContentType: fileType,
8173
});
82-
await s3Client.send(putCommand);
8374

84-
// 4. S3 Key is now stored in the DB. No need to construct full public URL here.
75+
await s3Client.send(putCommand);
8576

86-
// 5. Create Attachment Record in DB
8777
const attachment = await db.attachment.create({
8878
data: {
8979
name: fileName,
90-
url: key, // Store the S3 key in the 'url' field
80+
url: key,
9181
type: mapFileTypeToAttachmentType(fileType),
9282
entityId: entityId,
9383
entityType: entityType,
9484
organizationId: organizationId,
9585
},
9686
});
9787

98-
// 6. Generate Pre-signed URL for immediate access
9988
const getCommand = new GetObjectCommand({
10089
Bucket: BUCKET_NAME,
10190
Key: key,
10291
});
92+
10393
const signedUrl = await getSignedUrl(s3Client, getCommand, {
104-
expiresIn: 900, // Expires in 15 minutes
94+
expiresIn: 900,
10595
});
10696

107-
// 7. Return Success with Attachment Info AND Signed URL
10897
return {
10998
success: true,
11099
data: {
111-
...attachment, // Include all DB record fields
112-
signedUrl: signedUrl, // Add the temporary signed URL
100+
...attachment,
101+
signedUrl,
113102
},
114103
error: null,
115104
} as const;

apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/implementation/components/Checklist.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export function Checklist({ items }: { items: ChecklistItemProps[] }) {
77
return (
88
<div className="flex flex-col gap-4">
99
{items.map((item) => (
10-
<ChecklistItem key={item.dbColumn} {...item} />
10+
<ChecklistItem key={`checklist-${item.dbColumn}`} {...item} />
1111
))}
1212
</div>
1313
);

apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/components/create-vendor-form.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import { searchGlobalVendorsAction } from "../actions/search-global-vendors-acti
4646

4747
const createVendorSchema = z.object({
4848
name: z.string().min(1, "Name is required"),
49-
website: z.string().url("Must be a valid URL").optional(),
49+
website: z.string().url("URL must be valid and start with https://").optional(),
5050
description: z.string().optional(),
5151
category: z.nativeEnum(VendorCategory),
5252
status: z.nativeEnum(VendorStatus).default(VendorStatus.not_assessed),
@@ -245,7 +245,6 @@ export function CreateVendorForm({
245245
placeholder={t(
246246
"vendors.form.vendor_website_placeholder",
247247
)}
248-
type="url"
249248
/>
250249
</FormControl>
251250
<FormMessage />

apps/app/src/components/main-menu.tsx

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,6 @@ export function MainMenu({
160160
},
161161
];
162162

163-
if (session?.data?.user?.email?.endsWith("@trycomp.ai")) {
164-
items.push({
165-
id: "admin",
166-
path: "/internal/admin",
167-
name: t("sidebar.admin"),
168-
disabled: false,
169-
icon: Icons.AI,
170-
protected: true,
171-
});
172-
}
173-
174163
// Helper function to check if a path is active
175164
const isPathActive = (itemPath: string) => {
176165
const normalizedItemPath = itemPath.replace(
@@ -213,7 +202,7 @@ export function MainMenu({
213202
const isActive = isPathActive(item.path);
214203
return (
215204
<Item
216-
key={item.id}
205+
key={`${item.id}-${Math.random()}`}
217206
organizationId={organizationId ?? ""}
218207
item={item}
219208
isActive={isActive}
@@ -275,7 +264,7 @@ const Item = ({
275264
"hover:bg-accent hover:border-r-2 hover:border-r-primary/40",
276265
"transition-all duration-300",
277266
isActive &&
278-
"bg-accent dark:bg-secondary border-border border-r-2 border-r-primary hover:border-r-primary",
267+
"bg-accent dark:bg-secondary border-border border-r-2 border-r-primary hover:border-r-primary",
279268
)}
280269
>
281270
<div
@@ -308,8 +297,8 @@ const Item = ({
308297
className={cn(
309298
"ml-1.5 text-[9px] px-1 py-0 h-auto",
310299
badgeVariants[
311-
item.badge
312-
.variant
300+
item.badge
301+
.variant
313302
],
314303
)}
315304
>

apps/app/src/components/onboarding/FloatingOnboardingChecklist.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export function FloatingOnboardingChecklist({
113113
: (item.href ?? "#");
114114
return (
115115
<div
116-
key={item.dbColumn}
116+
key={`checklist-${item.dbColumn}`}
117117
className="group flex items-center gap-3"
118118
>
119119
<Checkbox
@@ -139,9 +139,9 @@ export function FloatingOnboardingChecklist({
139139
className={cn(
140140
"flex-1 cursor-pointer text-sm font-medium hover:text-primary",
141141
item.completed &&
142-
"line-through text-muted-foreground hover:text-muted-foreground",
142+
"line-through text-muted-foreground hover:text-muted-foreground",
143143
isPending &&
144-
"opacity-50 cursor-not-allowed",
144+
"opacity-50 cursor-not-allowed",
145145
)}
146146
tabIndex={isPending ? -1 : 0}
147147
aria-disabled={isPending}

0 commit comments

Comments
 (0)