-
Notifications
You must be signed in to change notification settings - Fork 5
CSV Uploads #2134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CSV Uploads #2134
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { getContentType } from "@/services/uploads/multipartUploadCore"; | ||
|
|
||
| describe("getContentType", () => { | ||
| it("normalizes csv files to text/csv", () => { | ||
| const file = new File(["a,b"], "data.csv", { | ||
| type: "application/vnd.ms-excel", | ||
| }); | ||
|
|
||
| expect(getContentType(file)).toBe("text/csv"); | ||
| }); | ||
|
|
||
| it("keeps non-csv mime types unchanged", () => { | ||
| const file = new File(["x"], "image.png", { | ||
| type: "image/png", | ||
| }); | ||
|
|
||
| expect(getContentType(file)).toBe("image/png"); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| "use client"; | ||
|
|
||
| import Download from "@/components/download/Download"; | ||
| import { getFileInfoFromUrl } from "@/helpers/file.helpers"; | ||
|
|
||
| export default function DropMediaAttachmentCard({ | ||
| src, | ||
| mimeType, | ||
| }: { | ||
| readonly src: string; | ||
| readonly mimeType: string; | ||
| }) { | ||
| const fileInfo = getFileInfoFromUrl(src); | ||
| const extension = | ||
| fileInfo?.extension ?? (mimeType === "text/csv" ? "csv" : ""); | ||
| const name = fileInfo?.name ?? "attachment"; | ||
| const displayName = extension ? `${name}.${extension}` : name; | ||
| const label = mimeType === "text/csv" ? "CSV attachment" : "Attachment"; | ||
|
|
||
| return ( | ||
| <div className="tw-flex tw-h-full tw-w-full tw-items-center tw-justify-between tw-gap-4 tw-rounded-2xl tw-border tw-border-iron-700 tw-bg-iron-900/70 tw-p-5"> | ||
| <div className="tw-flex tw-min-w-0 tw-items-center tw-gap-4"> | ||
| <div className="tw-flex tw-h-12 tw-w-12 tw-flex-shrink-0 tw-items-center tw-justify-center tw-rounded-2xl tw-bg-iron-800 tw-text-iron-200"> | ||
| <svg | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| fill="none" | ||
| viewBox="0 0 24 24" | ||
| strokeWidth="1.5" | ||
| stroke="currentColor" | ||
| className="tw-h-6 tw-w-6" | ||
| aria-hidden="true" | ||
| > | ||
| <path | ||
| strokeLinecap="round" | ||
| strokeLinejoin="round" | ||
| d="M19.5 14.25v-8.25a2.25 2.25 0 0 0-2.25-2.25H8.25L4.5 7.5v10.5a2.25 2.25 0 0 0 2.25 2.25h6.75m0-9h6m-6 3h6m-6 3h3" | ||
| /> | ||
| </svg> | ||
| </div> | ||
| <div className="tw-min-w-0"> | ||
| <div className="tw-text-xs tw-font-medium tw-uppercase tw-tracking-[0.16em] tw-text-iron-400"> | ||
| {label} | ||
| </div> | ||
| <div className="tw-mt-1 tw-truncate tw-text-sm tw-font-semibold tw-text-iron-100"> | ||
| {displayName} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| <Download | ||
| href={src} | ||
| name={name} | ||
| extension={extension} | ||
| variant="text" | ||
| alwaysShowText={true} | ||
| /> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ import dynamic from "next/dynamic"; | |||||||||||||||||
| import SandboxedExternalIframe from "@/components/common/SandboxedExternalIframe"; | ||||||||||||||||||
| import { ImageScale } from "@/helpers/image.helpers"; | ||||||||||||||||||
| import MediaDisplayAudio from "./MediaDisplayAudio"; | ||||||||||||||||||
| import DropMediaAttachmentCard from "./DropMediaAttachmentCard"; | ||||||||||||||||||
| import MediaDisplayImage from "./MediaDisplayImage"; | ||||||||||||||||||
| import MediaDisplayVideo from "./MediaDisplayVideo"; | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -13,6 +14,7 @@ enum MediaType { | |||||||||||||||||
| AUDIO = "AUDIO", | ||||||||||||||||||
| GLB = "GLB", | ||||||||||||||||||
| HTML = "HTML", | ||||||||||||||||||
| CSV = "CSV", | ||||||||||||||||||
| UNKNOWN = "UNKNOWN", | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -63,6 +65,9 @@ export default function MediaDisplay({ | |||||||||||||||||
| if (media_mime_type === "text/html") { | ||||||||||||||||||
| return MediaType.HTML; | ||||||||||||||||||
| } | ||||||||||||||||||
| if (media_mime_type === "text/csv") { | ||||||||||||||||||
| return MediaType.CSV; | ||||||||||||||||||
|
Comment on lines
+69
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle parameterized CSV MIME types in classifier.
Proposed fix- if (media_mime_type === "text/csv" || hasCsvFileExtension(media_url)) {
+ if (
+ media_mime_type.toLowerCase().startsWith("text/csv") ||
+ hasCsvFileExtension(media_url)
+ ) {
return MediaType.CSV;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| } | ||||||||||||||||||
| return MediaType.UNKNOWN; | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -105,6 +110,13 @@ export default function MediaDisplay({ | |||||||||||||||||
| className="tw-h-full tw-w-full" | ||||||||||||||||||
| /> | ||||||||||||||||||
| ); | ||||||||||||||||||
| case MediaType.CSV: | ||||||||||||||||||
| return ( | ||||||||||||||||||
| <DropMediaAttachmentCard | ||||||||||||||||||
| src={media_url} | ||||||||||||||||||
| mimeType={media_mime_type} | ||||||||||||||||||
| /> | ||||||||||||||||||
| ); | ||||||||||||||||||
| case MediaType.UNKNOWN: | ||||||||||||||||||
| return <></>; | ||||||||||||||||||
| default: | ||||||||||||||||||
|
|
||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.