Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions apps/web/components/dashboard/preview/AttachmentBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,23 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
prefetch={false}
>
{ASSET_TYPE_TO_ICON[asset.assetType]}
<p>{humanFriendlyNameForAssertType(asset.assetType)}</p>
<p>
{asset.assetType === "userUploaded" && asset.fileName
? asset.fileName
: humanFriendlyNameForAssertType(asset.assetType)}
</p>
</Link>
<div className="flex gap-2">
<Link
title="Download"
target="_blank"
href={getAssetUrl(asset.id)}
className="flex items-center gap-1"
download={humanFriendlyNameForAssertType(asset.assetType)}
download={
asset.assetType === "userUploaded" && asset.fileName
? asset.fileName
: humanFriendlyNameForAssertType(asset.assetType)
}
prefetch={false}
>
<Download className="size-4" />
Expand All @@ -118,7 +126,11 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
<FilePickerButton
title="Replace"
loading={isReplacing}
accept=".jgp,.JPG,.jpeg,.png,.webp"
accept={
asset.assetType === "userUploaded"
? undefined
: ".jgp,.JPG,.jpeg,.png,.webp"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo in file extensions filter.

The accept filter has a typo: ".jgp" should be ".jpg". Note this typo also exists on line 186 in the "Attach a Banner" button.

Apply this diff to fix the typo in both locations:

                  accept={
                    asset.assetType === "userUploaded"
                      ? undefined
-                     : ".jgp,.JPG,.jpeg,.png,.webp"
+                     : ".jpg,.JPG,.jpeg,.png,.webp"
                  }

Also fix line 186:

              loading={isAttaching}
-             accept=".jgp,.JPG,.jpeg,.png,.webp"
+             accept=".jpg,.JPG,.jpeg,.png,.webp"
              multiple={false}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
accept={
asset.assetType === "userUploaded"
? undefined
: ".jgp,.JPG,.jpeg,.png,.webp"
}
accept={
asset.assetType === "userUploaded"
? undefined
: ".jpg,.JPG,.jpeg,.png,.webp"
}
🤖 Prompt for AI Agents
In apps/web/components/dashboard/preview/AttachmentBox.tsx around lines 129-133
and also at line 186, there is a typo in the accept file extensions string
(".jgp" instead of ".jpg"); update both occurrences to use the correct extension
list ".jpg,.JPG,.jpeg,.png,.webp" (preserve casing and the rest of the
conditional logic) so the accept filter correctly allows JPG files.

multiple={false}
variant="none"
size="none"
Expand Down Expand Up @@ -194,6 +206,30 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
Attach a Banner
</FilePickerButton>
)}
<FilePickerButton
title="Upload File"
loading={isAttaching}
multiple={false}
variant="ghost"
size="none"
className="flex w-full items-center justify-center gap-2"
onFileSelect={(file) =>
uploadAsset(file, {
onSuccess: (resp) => {
attachAsset({
Comment on lines +212 to +216

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Backend still rejects non whitelisted file types

The new "Upload File" button allows selecting any file, but the upload endpoint (packages/api/utils/upload.tsuploadAsset) still checks SUPPORTED_UPLOAD_ASSET_TYPES and returns "Unsupported asset type" for MIME types outside the existing image/video/pdf list. As a result, attempting to attach a ZIP or DOCX fails even though the UI now advertises arbitrary uploads. Consider widening the whitelist or skipping that check for userUploaded assets so the feature works as described.

Useful? React with 👍 / 👎.

bookmarkId: bookmark.id,
asset: {
id: resp.assetId,
assetType: "userUploaded",
},
});
},
})
}
>
<Plus className="size-4" />
Upload File
</FilePickerButton>
</CollapsibleContent>
</Collapsible>
);
Expand Down
2 changes: 2 additions & 0 deletions apps/web/lib/attachments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
FileCode,
Image,
Paperclip,
Upload,
Video,
} from "lucide-react";

Expand All @@ -18,5 +19,6 @@ export const ASSET_TYPE_TO_ICON: Record<ZAssetType, React.ReactNode> = {
video: <Video className="size-4" />,
bookmarkAsset: <Paperclip className="size-4" />,
linkHtmlContent: <FileCode className="size-4" />,
userUploaded: <Upload className="size-4" />,
unknown: <Paperclip className="size-4" />,
};
2 changes: 2 additions & 0 deletions packages/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ export const enum AssetTypes {
LINK_VIDEO = "linkVideo",
LINK_HTML_CONTENT = "linkHtmlContent",
BOOKMARK_ASSET = "bookmarkAsset",
USER_UPLOADED = "userUploaded",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

LGTM: USER_UPLOADED asset type properly added to schema.

The new asset type is correctly declared in both the enum definition and the table constraint list, following the existing pattern for other asset types.

Please ensure a database migration has been created to support the new USER_UPLOADED asset type in the schema. Run the following script to check for recent migrations:

Also applies to: 250-250


🏁 Script executed:

#!/bin/bash
# Check for recent migration files that might include the USER_UPLOADED asset type
fd -e sql -e ts migration packages/db | head -20

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Explore packages/db directory structure
echo "=== Directory structure of packages/db ==="
find packages/db -type f -name "*migration*" -o -name "*migrate*" 2>/dev/null | head -20

echo -e "\n=== All files in packages/db ==="
find packages/db -type f | head -30

echo -e "\n=== Search for USER_UPLOADED in packages/db ==="
rg -n "USER_UPLOADED" packages/db/

Length of output: 1600


🏁 Script executed:

#!/bin/bash
# Check the schema.ts file around the lines mentioned
echo "=== Content of schema.ts around lines 231 and 250 ==="
sed -n '225,260p' packages/db/schema.ts

Length of output: 1226


🏁 Script executed:

#!/bin/bash
# Search entire codebase for migration-related patterns
echo "=== Search for migration files/folders ==="
find . -type d -name "*migrat*" 2>/dev/null | grep -v node_modules

echo -e "\n=== Search for USER_UPLOADED in entire codebase ==="
rg -n "USER_UPLOADED" --type ts --type sql 2>/dev/null | head -30

Length of output: 434



---

🏁 Script executed:

```shell
#!/bin/bash
# Check the latest migration file
echo "=== Latest migration file (0026) ==="
cat packages/db/drizzle/0026_silky_imperial_guard.sql

echo -e "\n=== Check for any 0027+ migration files ==="
ls -la packages/db/drizzle/00* 2>/dev/null | tail -5

echo -e "\n=== Check if there are uncommitted migrations ==="
ls -la packages/db/drizzle/ | wc -l

Length of output: 715


🏁 Script executed:

#!/bin/bash
# Search for references to USER_UPLOADED to understand scope
echo "=== All references to USER_UPLOADED in codebase ==="
rg -n "USER_UPLOADED" --type ts --type sql

echo -e "\n=== Check packages/trpc/lib/attachments.ts context ==="
sed -n '15,45p' packages/trpc/lib/attachments.ts

Length of output: 1497


🏁 Script executed:

#!/bin/bash
# Verify schema.ts has the complete AssetTypes enum
echo "=== Complete AssetTypes enum ==="
rg -A 15 "enum AssetTypes" packages/db/schema.ts

Length of output: 501


Missing database migration for USER_UPLOADED asset type.

The schema.ts changes are correct, but there is no corresponding migration file in packages/db/drizzle/. Since USER_UPLOADED is already referenced in packages/trpc/lib/attachments.ts (lines 19, 37), the database schema must be updated to support this new enum value. A migration file needs to be generated to add the USER_UPLOADED enum variant to the assets table's assetType constraint.

🤖 Prompt for AI Agents
In packages/db/schema.ts around line 231, you added USER_UPLOADED to the asset
type enum but did not add a DB migration; create a new migration file under
packages/db/drizzle (timestamped like
<timestamp>_add_user_uploaded_asset_type.sql) that alters the existing Postgres
enum used by the assets table (or updates the CHECK/constraint if you used one)
to include the new value 'userUploaded'—for a Postgres enum use ALTER TYPE
<enum_name> ADD VALUE 'userUploaded'; ensure the migration is
numbered/registered with your migration runner and include a corresponding down
migration or reversible steps if required by your tooling, then run the
migration locally to verify packages/trpc/lib/attachments.ts references work
with the updated schema.

UNKNOWN = "unknown",
}

Expand All @@ -246,6 +247,7 @@ export const assets = sqliteTable(
AssetTypes.LINK_VIDEO,
AssetTypes.LINK_HTML_CONTENT,
AssetTypes.BOOKMARK_ASSET,
AssetTypes.USER_UPLOADED,
AssetTypes.UNKNOWN,
],
}).notNull(),
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/types/bookmarks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ export const zAssetTypesSchema = z.enum([
"video",
"bookmarkAsset",
"precrawledArchive",
"userUploaded",
"unknown",
]);
export type ZAssetType = z.infer<typeof zAssetTypesSchema>;

export const zAssetSchema = z.object({
id: z.string(),
assetType: zAssetTypesSchema,
fileName: z.string().nullish(),
});

export const zBookmarkedLinkSchema = z.object({
Expand Down
5 changes: 5 additions & 0 deletions packages/trpc/lib/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function mapDBAssetTypeToUserType(assetType: AssetTypes): ZAssetType {
[AssetTypes.LINK_VIDEO]: "video",
[AssetTypes.LINK_HTML_CONTENT]: "linkHtmlContent",
[AssetTypes.BOOKMARK_ASSET]: "bookmarkAsset",
[AssetTypes.USER_UPLOADED]: "userUploaded",
[AssetTypes.UNKNOWN]: "bannerImage",
};
return map[assetType];
Expand All @@ -33,6 +34,7 @@ export function mapSchemaAssetTypeToDB(
video: AssetTypes.LINK_VIDEO,
bookmarkAsset: AssetTypes.BOOKMARK_ASSET,
linkHtmlContent: AssetTypes.LINK_HTML_CONTENT,
userUploaded: AssetTypes.USER_UPLOADED,
unknown: AssetTypes.UNKNOWN,
};
return map[assetType];
Expand All @@ -48,6 +50,7 @@ export function humanFriendlyNameForAssertType(type: ZAssetType) {
video: "Video",
bookmarkAsset: "Bookmark Asset",
linkHtmlContent: "HTML Content",
userUploaded: "User Uploaded File",
unknown: "Unknown",
};
return map[type];
Expand All @@ -63,6 +66,7 @@ export function isAllowedToAttachAsset(type: ZAssetType) {
video: true,
bookmarkAsset: false,
linkHtmlContent: false,
userUploaded: true,
unknown: false,
};
return map[type];
Expand All @@ -78,6 +82,7 @@ export function isAllowedToDetachAsset(type: ZAssetType) {
video: true,
bookmarkAsset: false,
linkHtmlContent: false,
userUploaded: true,
unknown: false,
};
return map[type];
Expand Down
1 change: 1 addition & 0 deletions packages/trpc/models/bookmarks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ export class Bookmark implements PrivacyAware {
acc[bookmarkId].assets.push({
id: row.assets.id,
assetType: mapDBAssetTypeToUserType(row.assets.assetType),
fileName: row.assets.fileName,
});
}

Expand Down
Loading