Skip to content

Commit 91d3098

Browse files
committed
feat: add upload_files support and minimatch for file validation in SubmissionUploadForm
1 parent 9175584 commit 91d3098

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

components/submissions/submission-upload-form.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import { Attempts } from '@/lib/types';
1111
import { Skeleton } from '../ui/skeleton';
1212
import Editor from "@monaco-editor/react";
1313
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
14+
import { minimatch } from "minimatch";
1415

1516
interface SubmissionUploadFormProps {
1617
problemId: string;
1718
uploadLimits: {
1819
max_num: number;
1920
max_size: number;
2021
upload_form?: boolean;
22+
upload_files?: string[];
2123
editor?: boolean;
2224
editor_files?: string[];
2325
};
@@ -98,7 +100,20 @@ export default function SubmissionUploadForm({ problemId, uploadLimits }: Submis
98100
const fileInputRef = useRef<HTMLInputElement>(null);
99101
const folderInputRef = useRef<HTMLInputElement>(null);
100102

103+
const uploadFiles = uploadLimits.upload_files || [];
104+
101105
const addFiles = useCallback((newFiles: File[]) => {
106+
107+
if (uploadFiles.length > 0) {
108+
newFiles = newFiles.filter(file =>
109+
uploadFiles.some(pattern => minimatch(((file as FileWithPath).path || (file as any).webkitRelativePath || file.name).replace(/^\/+/, "").replace(/^(\.\/)+/, ""), pattern))
110+
);
111+
if (newFiles.length === 0) {
112+
toast({ variant: 'destructive', title: 'No valid files', description: `No selected files match the allowed patterns: ${uploadFiles.join(', ')}` });
113+
return;
114+
}
115+
}
116+
102117
const allFiles = [...files, ...newFiles];
103118
if (uploadLimits.max_num > 0 && allFiles.length > uploadLimits.max_num) {
104119
toast({ variant: 'destructive', title: 'Too many files', description: `You can upload a maximum of ${uploadLimits.max_num} files.` });
@@ -183,7 +198,7 @@ export default function SubmissionUploadForm({ problemId, uploadLimits }: Submis
183198
setIsSubmitting(true);
184199
const formData = new FormData();
185200
filesToSubmit.forEach(file => {
186-
const filePath = (file as FileWithPath).path || (file as any).webkitRelativePath || file.name;
201+
const filePath = ((file as FileWithPath).path || (file as any).webkitRelativePath || file.name).replace(/^\/+/, "").replace(/^(\.\/)+/, "");
187202
formData.append('files', file, btoaUTF8(filePath));
188203
});
189204

lib/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export interface Problem {
4343
max_num: number;
4444
max_size: number;
4545
upload_form?: boolean;
46+
upload_files?: string[];
4647
editor?: boolean;
4748
editor_files?: string[];
4849
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"framer-motion": "^12.23.24",
3333
"jwt-decode": "^4.0.0",
3434
"lucide-react": "^0.378.0",
35+
"minimatch": "^10.0.3",
3536
"next": "14.2.3",
3637
"next-intl": "^4.3.12",
3738
"next-themes": "^0.3.0",

pnpm-lock.yaml

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)