aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-11-08 15:22:14 +0000
committerGitHub <noreply@github.com>2025-11-08 15:22:14 +0000
commit31960fcd11daa2dfaf8ae409c80b572c9b22940f (patch)
tree17bd227dac336ccabd2b6ffc6558920c68e053d0 /apps/web/components
parent99413db0e79a156a1b87eacd3c6a7b83e9df946e (diff)
downloadkarakeep-31960fcd11daa2dfaf8ae409c80b572c9b22940f.tar.zst
feat: Add support for user uploaded files (#2100)
* feat: add user file upload support for bookmarks Add a new "user-uploaded" asset type that allows users to upload and attach their own files to bookmarks from the attachment box in the bookmark preview page. Changes: - Add USER_UPLOADED asset type to database schema - Add userUploaded to zAssetTypesSchema for type safety - Update attachment permissions to allow attaching/detaching user files - Add fileName field to asset schema for displaying custom filenames - Add "Upload File" button in AttachmentBox component - Display actual filename for user-uploaded files - Allow any file type for user uploads (respects existing upload limits) - Add Upload icon for user-uploaded files Fixes #1863 related asset attachment improvements * fix: ensure fileName is returned and remove edit button for user uploads - Fix attachAsset mutation to fetch and return complete asset with fileName instead of just returning the input (which lacks fileName) - Remove replace/edit button for user-uploaded files - users can only delete and re-upload instead - This ensures the filename displays correctly in the UI immediately after upload Fixes fileName propagation issue for user-uploaded assets * fix asset file name * remove filename from attach asset api --------- Co-authored-by: Claude <noreply@anthropic.com>
Diffstat (limited to 'apps/web/components')
-rw-r--r--apps/web/components/dashboard/preview/AttachmentBox.tsx85
1 files changed, 59 insertions, 26 deletions
diff --git a/apps/web/components/dashboard/preview/AttachmentBox.tsx b/apps/web/components/dashboard/preview/AttachmentBox.tsx
index 87c56eb8..e24cc646 100644
--- a/apps/web/components/dashboard/preview/AttachmentBox.tsx
+++ b/apps/web/components/dashboard/preview/AttachmentBox.tsx
@@ -101,7 +101,11 @@ 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
@@ -109,35 +113,40 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
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" />
</Link>
- {isAllowedToAttachAsset(asset.assetType) && (
- <FilePickerButton
- title="Replace"
- loading={isReplacing}
- accept=".jgp,.JPG,.jpeg,.png,.webp"
- multiple={false}
- variant="none"
- size="none"
- className="flex items-center gap-2"
- onFileSelect={(file) =>
- uploadAsset(file, {
- onSuccess: (resp) => {
- replaceAsset({
- bookmarkId: bookmark.id,
- oldAssetId: asset.id,
- newAssetId: resp.assetId,
- });
- },
- })
- }
- >
- <Pencil className="size-4" />
- </FilePickerButton>
- )}
+ {isAllowedToAttachAsset(asset.assetType) &&
+ asset.assetType !== "userUploaded" && (
+ <FilePickerButton
+ title="Replace"
+ loading={isReplacing}
+ accept=".jgp,.JPG,.jpeg,.png,.webp"
+ multiple={false}
+ variant="none"
+ size="none"
+ className="flex items-center gap-2"
+ onFileSelect={(file) =>
+ uploadAsset(file, {
+ onSuccess: (resp) => {
+ replaceAsset({
+ bookmarkId: bookmark.id,
+ oldAssetId: asset.id,
+ newAssetId: resp.assetId,
+ });
+ },
+ })
+ }
+ >
+ <Pencil className="size-4" />
+ </FilePickerButton>
+ )}
{isAllowedToDetachAsset(asset.assetType) && (
<ActionConfirmingDialog
title="Delete Attachment?"
@@ -194,6 +203,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({
+ bookmarkId: bookmark.id,
+ asset: {
+ id: resp.assetId,
+ assetType: "userUploaded",
+ },
+ });
+ },
+ })
+ }
+ >
+ <Plus className="size-4" />
+ Upload File
+ </FilePickerButton>
</CollapsibleContent>
</Collapsible>
);