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 Link from 'next/link';
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import toast from 'react-hot-toast'; 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() { export function AssignmentTaskGeneralEdit() {
const session = useLHSession() as any; const session = useLHSession() as any;
@ -242,6 +245,7 @@ function UpdateTaskRef() {
<div className="flex justify-center items-center"> <div className="flex justify-center items-center">
<input <input
type="file" type="file"
accept={SUPPORTED_FILES}
id="fileInput" id="fileInput"
style={{ display: 'none' }} style={{ display: 'none' }}
onChange={handleFileChange} onChange={handleFileChange}
@ -255,6 +259,7 @@ function UpdateTaskRef() {
<div className="flex justify-center items-center"> <div className="flex justify-center items-center">
<input <input
type="file" type="file"
accept={SUPPORTED_FILES}
id="fileInput" id="fileInput"
style={{ display: 'none' }} style={{ display: 'none' }}
onChange={handleFileChange} onChange={handleFileChange}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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