Merge pull request #367 from chrishollandaise/fix/limit-inputs-accept-values

fix: file inputs limit to their respective file formats
This commit is contained in:
Badr B. 2024-10-27 20:29:08 +01:00 committed by GitHub
commit 94c2ed50ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 55 additions and 6 deletions

View file

@ -13,6 +13,9 @@ import { Cloud, File, Info, Loader, UploadCloud } from 'lucide-react'
import Link from 'next/link';
import React, { useEffect } from 'react'
import toast from 'react-hot-toast';
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['pdf', 'docx', 'mp4', 'jpg', 'png', 'pptx', 'zip'])
export function AssignmentTaskGeneralEdit() {
const session = useLHSession() as any;
@ -242,6 +245,7 @@ function UpdateTaskRef() {
<div className="flex justify-center items-center">
<input
type="file"
accept={SUPPORTED_FILES}
id="fileInput"
style={{ display: 'none' }}
onChange={handleFileChange}
@ -255,6 +259,7 @@ function UpdateTaskRef() {
<div className="flex justify-center items-center">
<input
type="file"
accept={SUPPORTED_FILES}
id="fileInput"
style={{ display: 'none' }}
onChange={handleFileChange}

View file

@ -6,7 +6,7 @@ import {
uploadOrganizationLogo,
uploadOrganizationThumbnail,
} from '@services/settings/org'
import { UploadCloud, Info, Check, FileWarning } from 'lucide-react'
import { UploadCloud, Info } from 'lucide-react'
import { revalidateTags } from '@services/utils/ts/requests'
import { useRouter } from 'next/navigation'
import { useOrg } from '@components/Contexts/OrgContext'
@ -14,6 +14,9 @@ import { useLHSession } from '@components/Contexts/LHSessionContext'
import { getOrgLogoMediaDirectory, getOrgThumbnailMediaDirectory } from '@services/media/media'
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Toaster, toast } from 'react-hot-toast';
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['png', 'jpg'])
interface OrganizationValues {
name: string
@ -174,6 +177,7 @@ function OrgEditGeneral() {
<input
type="file"
id="fileInput"
accept={SUPPORTED_FILES}
style={{ display: 'none' }}
onChange={handleFileChange}
/>
@ -205,6 +209,7 @@ function OrgEditGeneral() {
<div className="flex justify-center items-center">
<input
type="file"
accept={SUPPORTED_FILES}
id="thumbnailInput"
style={{ display: 'none' }}
onChange={handleThumbnailChange}

View file

@ -12,6 +12,9 @@ import {
} from 'lucide-react'
import UserAvatar from '@components/Objects/UserAvatar'
import { updateUserAvatar } from '@services/users/users'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['image'])
function UserEditGeneral() {
const session = useLHSession() as any;
@ -125,6 +128,7 @@ function UserEditGeneral() {
<input
type="file"
id="fileInput"
accept={SUPPORTED_FILES}
className="hidden"
onChange={handleFileChange}
/>

View file

@ -9,6 +9,9 @@ import { useCourse } from '@components/Contexts/CourseContext'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import { FileUploadBlock, FileUploadBlockButton, FileUploadBlockInput } from '../../FileUploadBlock'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['image'])
function ImageBlockComponent(props: any) {
const org = useOrg() as any
@ -53,7 +56,7 @@ function ImageBlockComponent(props: any) {
return (
<NodeViewWrapper className="block-image">
<FileUploadBlock isEditable={isEditable} isLoading={isLoading} isEmpty={!blockObject} Icon={Image}>
<FileUploadBlockInput onChange={handleImageChange} accept="image/*" />
<FileUploadBlockInput onChange={handleImageChange} accept={SUPPORTED_FILES} />
<FileUploadBlockButton onClick={handleSubmit} disabled={!image}/>
</FileUploadBlock>

View file

@ -9,6 +9,9 @@ import { useCourse } from '@components/Contexts/CourseContext'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import { FileUploadBlock, FileUploadBlockButton, FileUploadBlockInput } from '../../FileUploadBlock'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['pdf'])
function PDFBlockComponent(props: any) {
const org = useOrg() as any
@ -49,7 +52,7 @@ function PDFBlockComponent(props: any) {
return (
<NodeViewWrapper className="block-pdf">
<FileUploadBlock isEditable={isEditable} isLoading={isLoading} isEmpty={!blockObject} Icon={FileText}>
<FileUploadBlockInput onChange={handlePDFChange} accept="application/pdf" />
<FileUploadBlockInput onChange={handlePDFChange} accept={SUPPORTED_FILES} />
<FileUploadBlockButton onClick={handleSubmit} disabled={!pdf}/>
</FileUploadBlock>

View file

@ -9,6 +9,9 @@ import { useCourse } from '@components/Contexts/CourseContext'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import { FileUploadBlock, FileUploadBlockButton, FileUploadBlockInput } from '../../FileUploadBlock'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['webm', 'mp4'])
function VideoBlockComponents(props: any) {
const org = useOrg() as any
@ -51,7 +54,7 @@ function VideoBlockComponents(props: any) {
return (
<NodeViewWrapper className="block-video">
<FileUploadBlock isEditable={isEditable} isLoading={isLoading} isEmpty={!blockObject} Icon={Video}>
<FileUploadBlockInput onChange={handleVideoChange} accept="video/*" />
<FileUploadBlockInput onChange={handleVideoChange} accept={SUPPORTED_FILES} />
<FileUploadBlockButton onClick={handleSubmit} disabled={!video}/>
</FileUploadBlock>

View file

@ -9,6 +9,9 @@ import FormLayout, {
import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['pdf'])
function DocumentPdfModal({ submitFileActivity, chapterId, course }: any) {
const [documentpdf, setDocumentPdf] = React.useState(null) as any
@ -64,7 +67,7 @@ function DocumentPdfModal({ submitFileActivity, chapterId, course }: any) {
</FormMessage>
</Flex>
<Form.Control asChild>
<input type="file" onChange={handleDocumentPdfChange} required />
<input accept={SUPPORTED_FILES} type="file" onChange={handleDocumentPdfChange} required />
</Form.Control>
</FormField>

View file

@ -10,6 +10,9 @@ import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
import { Youtube } from 'lucide-react'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['mp4', 'webm'])
interface ExternalVideoObject {
name: string
@ -134,7 +137,7 @@ function VideoModal({
</FormMessage>
</Flex>
<Form.Control asChild>
<input type="file" onChange={handleVideoChange} required />
<input accept={SUPPORTED_FILES} type="file" onChange={handleVideoChange} required />
</Form.Control>
</FormField>
</div>

20
apps/web/lib/constants.ts Normal file
View file

@ -0,0 +1,20 @@
export const ACCEPTED_FILE_FORMATS = {
video: 'video/*',
mp4: 'video/mp4',
webm: 'video/webm',
image: 'image/*',
jpg: 'image/jpeg',
png: 'image/png',
webp: 'image/webp',
pdf: 'application/pdf',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
zip: 'application/zip,application/x-zip-compressed'
} as const;
/**
* Constructs the 'accept' attribute value for an input element
*/
export function constructAcceptValue(types : (keyof typeof ACCEPTED_FILE_FORMATS)[]): string {
return types.map(type => ACCEPTED_FILE_FORMATS[type]).filter(Boolean).join(",")
}