您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

285 行
9.0 KiB

  1. import DialogTitle from '@mui/material/DialogTitle';
  2. import DialogContent from '@mui/material/DialogContent';
  3. import DialogContentText from '@mui/material/DialogContentText';
  4. import DialogActions from '@mui/material/DialogActions';
  5. import { Button, Grid, TextField, Typography, InputLabel, FormControl } from '@mui/material';
  6. import Dialog from '@mui/material/Dialog';
  7. import * as React from 'react';
  8. import {useEffect, useRef, useState} from 'react';
  9. import axios from 'axios';
  10. import {apiPath, getUserData} from '../../../auth/utils';
  11. import {GENERAL_RED_COLOR, GENERAL_TEXT_COLOR} from '../../../themes/colorConst';
  12. import { MuiFileInput } from 'mui-file-input';
  13. import { POST_TEMPLATE_PATH } from '../../../utils/ApiPathConst';
  14. import { useForm } from 'react-hook-form';
  15. import AttachFileIcon from '@mui/icons-material/AttachFile'
  16. import CloudUploadIcon from '@mui/icons-material/CloudUpload';
  17. import { notifySaveSuccess, base64ToBlob } from "../../../utils/CommonFunction";
  18. import { GET_TEMPLATE_PATH } from "../../../utils/ApiPathConst";
  19. export function UploadTemplateWindow({ isWindowOpen, onNormalClose, onConfirmClose, recordId }) {
  20. const [errors, setErrors] = useState({});
  21. const [file, setFile] = React.useState(null)
  22. const [templateId, setTemplateId] = React.useState(0)
  23. const [isFilePreloaded, setIsFilePreloaded] = React.useState(false)
  24. const fileInputRef = useRef(null);
  25. const { register, getValues, setValue } = useForm();
  26. const handleOnClose = () => {
  27. resetForm();
  28. onNormalClose();
  29. };
  30. const handleFieldChange = (newFile) => {
  31. setIsFilePreloaded(false);
  32. setFile(newFile);
  33. };
  34. const handleChange = (event) => {
  35. if(event !== null){
  36. const newFile = event.target.files[0];
  37. handleFieldChange(newFile);
  38. }
  39. else{
  40. setFile(null)
  41. }
  42. };
  43. const handleOpenFileSelect = () => {
  44. fileInputRef.current.click();
  45. };
  46. const resetForm = () => {
  47. setFile(null);
  48. setTemplateId(0);
  49. // setValue('file', record.name);
  50. setValue('file', null);
  51. setValue('name', null);
  52. setValue('remarks', null);
  53. setIsFilePreloaded(false);
  54. setErrors({});
  55. }
  56. useEffect(() => { // Load/Clear Data
  57. if (recordId == 0 || recordId == null) { // New Template
  58. resetForm();
  59. } else { // Edit Template
  60. axios.get(`${apiPath}${GET_TEMPLATE_PATH}/${recordId}`)
  61. .then((response) => {
  62. if (response.status === 200) {
  63. const record = response.data;
  64. const fileBlob = base64ToBlob(record.blobValue, 'application/pdf');
  65. const newFile = new File([fileBlob], record.filename, { type:'application/pdf' });
  66. setFile(newFile);
  67. setTemplateId(record.id);
  68. // setValue('file', record.name);
  69. setValue('name', record.name);
  70. setValue('remarks', record.remarks);
  71. setIsFilePreloaded(true);
  72. }
  73. })
  74. .catch(error => {
  75. console.log(error);
  76. return false;
  77. });
  78. }
  79. }, [recordId]);
  80. function validate() {
  81. const formErrors = {};
  82. if (!isFilePreloaded) {
  83. if (file == null) {
  84. formErrors.file = 'File must not be null';
  85. } else if (file.type !== 'application/pdf') {
  86. formErrors.file = 'File must be a PDF file';
  87. }
  88. }
  89. if (getValues().name == null) {
  90. formErrors.name = 'Name must not be empty';
  91. }
  92. setErrors(formErrors);
  93. if (Object.keys(formErrors).length === 0) {
  94. uploadData();
  95. }
  96. }
  97. function uploadData() {
  98. const values = getValues();
  99. const records = {
  100. 'id': templateId,
  101. 'name': values.name,
  102. 'remarks': values.remarks,
  103. }
  104. let formData = new FormData();
  105. if (file !== null) {
  106. formData.append('file', file);
  107. }
  108. if (values.name) {
  109. formData.append('record', JSON.stringify(records));
  110. }
  111. formData.append('newUpload', !isFilePreloaded);
  112. axios.post(`${apiPath}${POST_TEMPLATE_PATH}`, formData, {
  113. headers: {
  114. 'Content-Type': 'multipart/form-data'
  115. }
  116. })
  117. .then((response) => {
  118. if (response.status === 200) {
  119. notifySaveSuccess();
  120. resetForm();
  121. onConfirmClose();
  122. }
  123. })
  124. .catch((error) => {
  125. console.log(error);
  126. return false;
  127. });
  128. }
  129. const handleDragOver = (e) => {
  130. e.preventDefault();
  131. e.stopPropagation();
  132. };
  133. const handleDrop = (e) => {
  134. e.preventDefault();
  135. e.stopPropagation();
  136. const droppedFiles = Array.from(e.dataTransfer.files);
  137. console.log(droppedFiles);
  138. // setFiles((prevFiles) => [...prevFiles, ...droppedFiles]);
  139. };
  140. return (
  141. <Dialog
  142. PaperProps={{
  143. sx: {
  144. minWidth: '50vw',
  145. width: { xs: '90vw', s: '90vw', m: '70vw', lg: '50vw' },
  146. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '70vh' }
  147. }
  148. }}
  149. open={isWindowOpen}
  150. onClose={handleOnClose}
  151. aria-labelledby="alert-dialog-title"
  152. aria-describedby="alert-dialog-description"
  153. >
  154. <DialogTitle id="alert-dialog-title">
  155. <Typography variant="lionerBold" component="span">
  156. Upload new PDF Template
  157. </Typography>
  158. </DialogTitle>
  159. <DialogContent>
  160. <Grid container alignItems="flex-start" spacing={2} sx={{ mt: 3 }}>
  161. <Grid item>
  162. <Typography variant="lionerLabel" component="span">
  163. File Name:
  164. </Typography>
  165. </Grid>
  166. <Grid item xs={6}>
  167. <MuiFileInput
  168. inputProps={{
  169. accept: '.pdf',
  170. }}
  171. InputProps={{
  172. padding: '7.5px 8px 7.5px 12px',
  173. startAdornment: null,
  174. }}
  175. value={file}
  176. onChange={handleFieldChange}
  177. error={!!errors.file}
  178. helperText={errors.file}
  179. />
  180. </Grid>
  181. <Grid item>
  182. <Button
  183. component="label"
  184. variant="contained"
  185. startIcon={<CloudUploadIcon />}
  186. inputprops={{
  187. accept: '.pdf',
  188. startAdornment: <AttachFileIcon />
  189. }}
  190. onClick={handleOpenFileSelect}
  191. >
  192. Upload file
  193. </Button>
  194. <input
  195. type="file"
  196. accept=".pdf"
  197. style={{ display: 'none' }}
  198. ref={fileInputRef}
  199. onChange={handleChange}
  200. />
  201. </Grid>
  202. </Grid>
  203. <Grid container alignItems={'flex-start'} spacing={2} sx={{ mt: 3 }}>
  204. <Grid item sx={{ mr: 4 }}>
  205. <Typography variant="lionerLabel" component="span">
  206. Name:
  207. </Typography>
  208. </Grid>
  209. <Grid item xs={6}>
  210. <TextField
  211. fullWidth
  212. {...register("name")}
  213. id='name'
  214. inputProps={{maxLength: 255, style: {fontSize: '1.1rem'}}}
  215. // InputProps={{
  216. // style: { minHeight:'42.5px', maxHeight: '50vh', },
  217. // }}
  218. error={!!errors.name}
  219. helperText={errors.name}
  220. />
  221. </Grid>
  222. </Grid>
  223. <Grid container alignItems={'flex-start'} spacing={2} sx={{ mt: 3 }}>
  224. <Grid item sx={{ mr: -0.5 }}>{/*3 }}>*/}
  225. <Typography variant="lionerLabel" component="span">
  226. Form Code:
  227. </Typography>
  228. </Grid>
  229. <Grid item xs={9}>
  230. <TextField
  231. fullWidth
  232. inputProps={{maxLength: 255, style: {fontSize: '1.1rem'}}}
  233. {...register('remarks')}
  234. id="remarks"
  235. InputProps={{
  236. style: { minHeight:'42.5px', maxHeight: '50vh' },
  237. }}
  238. multiline
  239. rows={3}
  240. />
  241. </Grid>
  242. </Grid>
  243. </DialogContent>
  244. <DialogActions>
  245. <Button onClick={handleOnClose}>
  246. <Typography variant="lionerLabel" component="span">
  247. Cancel
  248. </Typography>
  249. </Button>
  250. <Button onClick={validate} autoFocus>
  251. <Typography variant="lionerLabel" component="span">
  252. Confirm
  253. </Typography>
  254. </Button>
  255. </DialogActions>
  256. </Dialog>
  257. );
  258. }