{"version":3,"file":"FileUpload-BB0TI98g.js","sources":["../../Client/legacy/Components/FormGroups/FileUpload.tsx"],"sourcesContent":["import { FormGroup } from '@legacy/Components/FormGroups/Base';\r\nimport { Svg } from '@legacy/Components/Svg';\r\nimport { InlineError } from '@legacy/FormFields';\r\nimport { MimeType } from '@shared/Constants';\r\nimport { Value } from '@webkit/index';\r\nimport { clsx } from 'clsx';\r\nimport * as React from 'react';\r\nimport { ReactElement } from 'react';\r\n\r\nexport interface IFileUploadFormGroupProps {\r\n /** The identifier for the form group. */\r\n id: string;\r\n\r\n /** The name for the file input. */\r\n name?: string;\r\n\r\n /** The change handler for when files have been added or removed. */\r\n onFilesChanged: (files: File[]) => void;\r\n\r\n /** The list of files. */\r\n files: Value<File[]>;\r\n\r\n /** The optional CSS class for the form group. */\r\n className?: string;\r\n\r\n /** The optional tab index to support keyboard navigation. */\r\n tabIndex?: number;\r\n\r\n /** Optional, pass in the accepted file types as a string to preselect the file type in the file browser (see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file for examples).\r\n * Note that this does *not* prevent the user from uploading a file of a different type; it just sets the default filter after the file selection dialog opens. Additional validation\r\n * needs to be present to ensure the correct file type is uploaded. */\r\n accept?: MimeType[];\r\n\r\n /** Optional, pass in a boolean controller for displaying an error (if not used, the Value will generate an error based on the rule pattern in FormFields.tsx */\r\n error?: boolean;\r\n\r\n /** Optional, pass in a boolean value to hide the tooltip. */\r\n hideToolTip?: boolean;\r\n\r\n /** Flag to allow multiple file uploads simultaneously. Defaults to false. */\r\n multiple?: boolean;\r\n\r\n /** Optional label for the control. */\r\n label?: string;\r\n\r\n /** Optional disabled flag */\r\n disabled?: boolean;\r\n\r\n /** Optional message to display when disabled */\r\n disabledMessage?: string | ReactElement;\r\n\r\n /** Optional control to disable deleting a previously added file. */\r\n disableDeleteFile?: boolean;\r\n}\r\n\r\ninterface IFileUploadFormGroupState {\r\n dragging: boolean;\r\n}\r\n\r\n// TODO: Convert to function component and clean up code - Darius 9/13/23\r\nexport class FileUploadFormGroup extends React.Component<IFileUploadFormGroupProps, IFileUploadFormGroupState> {\r\n upload: HTMLInputElement;\r\n dragCounter: number = 0;\r\n\r\n state = {\r\n dragging: false,\r\n };\r\n\r\n render() {\r\n const p = this.props;\r\n return (\r\n <div className={clsx('form-group-file-upload-cp', p.className, p.disabled ? 'disabled' : '')}>\r\n {p.label && <FormGroup label={p.label} />}\r\n\r\n <input\r\n id={p.id}\r\n type='file'\r\n name={p.name}\r\n ref={c => {\r\n this.upload = c as HTMLInputElement;\r\n }}\r\n onChange={e => e.target.files && this.onAddFiles(e.target.files)}\r\n accept={p.accept?.join(', ')}\r\n multiple={p.multiple}\r\n />\r\n\r\n <div\r\n className={clsx(\r\n 'form-group-file-upload-drop-cp',\r\n this.state.dragging && !p.disabled && 'form-group-file-upload-drop-dragging-cp',\r\n p.disabled && 'disabled',\r\n p.files.error && 'error'\r\n )}\r\n onClick={() => {\r\n if (this.props.disabled) {\r\n return;\r\n }\r\n\r\n this.upload.click();\r\n }}\r\n onDragEnter={(e: React.DragEvent<HTMLDivElement>) => this.onDragEnter(e)}\r\n onDragLeave={(e: React.DragEvent<HTMLDivElement>) => this.onDragLeave(e)}\r\n onDragOver={(e: React.DragEvent<HTMLDivElement>) => this.onDragOver(e)}\r\n onDrop={(e: React.DragEvent<HTMLDivElement>) => this.onDrop(e)}\r\n >\r\n {p.disabled && p.disabledMessage ? (\r\n p.disabledMessage\r\n ) : (\r\n <span>\r\n <a tabIndex={p.tabIndex}>Drag files here or click to browse</a>.\r\n </span>\r\n )}\r\n\r\n {(p.error === undefined || p.error) && (\r\n <InlineError error={p.files.error} noToolTip={p.hideToolTip ? p.hideToolTip : false} />\r\n )}\r\n </div>\r\n\r\n <div className='form-group-file-upload-list-cp'>\r\n {p.files.content.map((f: File) => (\r\n <FileWrapper\r\n file={f}\r\n onDelete={(file: File) => this.onDeleteFile(file)}\r\n key={getFileIdentifier(f)}\r\n disableDeleteFile={p.disableDeleteFile}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n private onAddFiles(files: FileList) {\r\n // If disabled, do nothing\r\n if (this.props.disabled) {\r\n return;\r\n }\r\n\r\n const addedFiles = this.getAddedFiles();\r\n for (let i = 0; i < files.length; i++) addedFiles[getFileIdentifier(files[i])] = files[i];\r\n this.props.onFilesChanged(Object.keys(addedFiles).map(key => addedFiles[key]));\r\n }\r\n\r\n private onDeleteFile(fileToDelete: File) {\r\n // If deleting a file is disabled, do nothing\r\n if (this.props.disableDeleteFile) {\r\n return;\r\n }\r\n\r\n // Delete files from the list and update the parent state\r\n const files = this.getAddedFiles();\r\n delete files[getFileIdentifier(fileToDelete)];\r\n this.props.onFilesChanged(Object.keys(files).map(key => files[key]));\r\n\r\n // The file list should not be null\r\n const inputFiles = this.upload.files;\r\n if (!inputFiles) {\r\n return;\r\n }\r\n\r\n // Remove the file from the input file list\r\n const inputFileArray = Array.from(inputFiles),\r\n filteredFileArray = inputFileArray.filter(f => f.name !== fileToDelete.name);\r\n\r\n // Generate a DataTransfer object to set the new file list (FileList is an illegal constructor)\r\n // https://stackoverflow.com/questions/52078853/is-it-possible-to-update-filelist\r\n // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer\r\n const dataTransfer = new DataTransfer();\r\n\r\n // Add the undeleted files to the new dataTransfer file list\r\n filteredFileArray.forEach(f => dataTransfer.items.add(f));\r\n\r\n // Set the file input files to the new dataTransfer file list\r\n this.upload.files = dataTransfer.files;\r\n }\r\n\r\n private onDragEnter(e: React.DragEvent<HTMLDivElement>) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.dragCounter++;\r\n this.setState({ dragging: true });\r\n }\r\n\r\n private onDragLeave(e: React.DragEvent<HTMLDivElement>) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.dragCounter--;\r\n if (this.dragCounter === 0) this.setState({ dragging: false });\r\n }\r\n\r\n private onDragOver(e: React.DragEvent<HTMLDivElement>) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n\r\n private onDrop(e: React.DragEvent<HTMLDivElement>) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.dragCounter = 0;\r\n this.setState({ dragging: false });\r\n this.onAddFiles(e.dataTransfer.files);\r\n this.upload.files = e.dataTransfer.files;\r\n }\r\n\r\n private getAddedFiles() {\r\n const files = {};\r\n this.props.files.content.forEach(f => {\r\n files[getFileIdentifier(f)] = f;\r\n });\r\n return files;\r\n }\r\n}\r\n\r\nconst FileWrapper = ({ file, onDelete, disableDeleteFile }) => (\r\n <div className='form-group-file-upload-file-cp'>\r\n <div>\r\n <i onClick={() => onDelete(file)} style={{ cursor: disableDeleteFile ? 'not-allowed' : 'pointer' }}>\r\n ✕\r\n </i>\r\n <Svg className='dropped-file-svg-ly' path='/images/icon-link.svg' alt={`${file.name} uploaded`} />\r\n </div>\r\n <span>{file.name}</span>\r\n </div>\r\n);\r\n\r\nfunction getFileIdentifier(file: File) {\r\n return file.name + file.size;\r\n}\r\n"],"names":["FileUploadFormGroup","React.Component","__publicField","p","jsxs","clsx","jsx","FormGroup","c","e","_a","InlineError","f","FileWrapper","file","getFileIdentifier","files","addedFiles","i","key","fileToDelete","inputFiles","inputFileArray","filteredFileArray","dataTransfer","onDelete","disableDeleteFile","Svg"],"mappings":"oXA4Da,MAAAA,UAA4BC,EAAAA,SAAsE,CAAlG,kCACTC,EAAA,eACAA,EAAA,mBAAsB,GAEtBA,EAAA,aAAQ,CACJ,SAAU,EACd,GAEA,QAAS,OACL,MAAMC,EAAI,KAAK,MAEX,OAAAC,EAAA,KAAC,MAAI,CAAA,UAAWC,EAAK,4BAA6BF,EAAE,UAAWA,EAAE,SAAW,WAAa,EAAE,EACtF,SAAA,CAAAA,EAAE,OAASG,MAACC,EAAU,CAAA,MAAOJ,EAAE,MAAO,EAEvCG,EAAA,IAAC,QAAA,CACG,GAAIH,EAAE,GACN,KAAK,OACL,KAAMA,EAAE,KACR,IAAUK,GAAA,CACN,KAAK,OAASA,CAClB,EACA,YAAeC,EAAE,OAAO,OAAS,KAAK,WAAWA,EAAE,OAAO,KAAK,EAC/D,QAAQC,EAAAP,EAAE,SAAF,YAAAO,EAAU,KAAK,MACvB,SAAUP,EAAE,QAAA,CAChB,EAEAC,EAAA,KAAC,MAAA,CACG,UAAWC,EACP,iCACA,KAAK,MAAM,UAAY,CAACF,EAAE,UAAY,0CACtCA,EAAE,UAAY,WACdA,EAAE,MAAM,OAAS,OACrB,EACA,QAAS,IAAM,CACP,KAAK,MAAM,UAIf,KAAK,OAAO,MAAM,CACtB,EACA,YAAcM,GAAuC,KAAK,YAAYA,CAAC,EACvE,YAAcA,GAAuC,KAAK,YAAYA,CAAC,EACvE,WAAaA,GAAuC,KAAK,WAAWA,CAAC,EACrE,OAASA,GAAuC,KAAK,OAAOA,CAAC,EAE5D,SAAA,CAAAN,EAAE,UAAYA,EAAE,gBACbA,EAAE,uBAED,OACG,CAAA,SAAA,CAAAG,EAAA,IAAC,IAAE,CAAA,SAAUH,EAAE,SAAU,SAAkC,qCAAA,EAAI,GAAA,EACnE,GAGFA,EAAE,QAAU,QAAaA,EAAE,cACxBQ,EAAY,CAAA,MAAOR,EAAE,MAAM,MAAO,UAAWA,EAAE,YAAcA,EAAE,YAAc,EAAO,CAAA,CAAA,CAAA,CAE7F,EAEAG,EAAAA,IAAC,OAAI,UAAU,iCACV,WAAE,MAAM,QAAQ,IAAKM,GAClBN,EAAA,IAACO,EAAA,CACG,KAAMD,EACN,SAAWE,GAAe,KAAK,aAAaA,CAAI,EAEhD,kBAAmBX,EAAE,iBAAA,EADhBY,EAAkBH,CAAC,CAAA,CAG/B,CACL,CAAA,CAAA,EACJ,CAAA,CAIA,WAAWI,EAAiB,CAE5B,GAAA,KAAK,MAAM,SACX,OAGE,MAAAC,EAAa,KAAK,cAAc,EACtC,QAASC,EAAI,EAAGA,EAAIF,EAAM,OAAQE,IAAKD,EAAWF,EAAkBC,EAAME,CAAC,CAAC,CAAC,EAAIF,EAAME,CAAC,EACnF,KAAA,MAAM,eAAe,OAAO,KAAKD,CAAU,EAAE,IAAWE,GAAAF,EAAWE,CAAG,CAAC,CAAC,CAAA,CAGzE,aAAaC,EAAoB,CAEjC,GAAA,KAAK,MAAM,kBACX,OAIE,MAAAJ,EAAQ,KAAK,cAAc,EAC1B,OAAAA,EAAMD,EAAkBK,CAAY,CAAC,EACvC,KAAA,MAAM,eAAe,OAAO,KAAKJ,CAAK,EAAE,IAAWG,GAAAH,EAAMG,CAAG,CAAC,CAAC,EAG7D,MAAAE,EAAa,KAAK,OAAO,MAC/B,GAAI,CAACA,EACD,OAIJ,MAAMC,EAAiB,MAAM,KAAKD,CAAU,EACxCE,EAAoBD,EAAe,OAAYV,GAAAA,EAAE,OAASQ,EAAa,IAAI,EAKzEI,EAAe,IAAI,aAGzBD,EAAkB,QAAaX,GAAAY,EAAa,MAAM,IAAIZ,CAAC,CAAC,EAGnD,KAAA,OAAO,MAAQY,EAAa,KAAA,CAG7B,YAAY,EAAoC,CACpD,EAAE,eAAe,EACjB,EAAE,gBAAgB,EACb,KAAA,cACL,KAAK,SAAS,CAAE,SAAU,EAAA,CAAM,CAAA,CAG5B,YAAY,EAAoC,CACpD,EAAE,eAAe,EACjB,EAAE,gBAAgB,EACb,KAAA,cACD,KAAK,cAAgB,GAAG,KAAK,SAAS,CAAE,SAAU,GAAO,CAAA,CAGzD,WAAW,EAAoC,CACnD,EAAE,eAAe,EACjB,EAAE,gBAAgB,CAAA,CAGd,OAAO,EAAoC,CAC/C,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,KAAK,YAAc,EACnB,KAAK,SAAS,CAAE,SAAU,EAAA,CAAO,EAC5B,KAAA,WAAW,EAAE,aAAa,KAAK,EAC/B,KAAA,OAAO,MAAQ,EAAE,aAAa,KAAA,CAG/B,eAAgB,CACpB,MAAMR,EAAQ,CAAC,EACf,YAAK,MAAM,MAAM,QAAQ,QAAaJ,GAAA,CAC5BI,EAAAD,EAAkBH,CAAC,CAAC,EAAIA,CAAA,CACjC,EACMI,CAAA,CAEf,CAEA,MAAMH,EAAc,CAAC,CAAE,KAAAC,EAAM,SAAAW,EAAU,kBAAAC,KACnCtB,EAAA,KAAC,MAAI,CAAA,UAAU,iCACX,SAAA,CAAAA,OAAC,MACG,CAAA,SAAA,CAAAE,EAAA,IAAC,IAAE,CAAA,QAAS,IAAMmB,EAASX,CAAI,EAAG,MAAO,CAAE,OAAQY,EAAoB,cAAgB,SAAA,EAAa,SAEpG,IAAA,EACApB,EAAAA,IAACqB,EAAI,CAAA,UAAU,sBAAsB,KAAK,wBAAwB,IAAK,GAAGb,EAAK,IAAI,WAAa,CAAA,CAAA,EACpG,EACAR,EAAAA,IAAC,OAAM,CAAA,SAAAQ,EAAK,IAAK,CAAA,CAAA,EACrB,EAGJ,SAASC,EAAkBD,EAAY,CAC5B,OAAAA,EAAK,KAAOA,EAAK,IAC5B"}