From 9276affe5844061f3f499fce6ccb60ec7a0dfdff Mon Sep 17 00:00:00 2001 From: Alex Cheung Date: Wed, 6 Sep 2023 18:06:54 +0800 Subject: [PATCH 1/2] upload file with bug --- .../auth-forms/BusCustomFormWizard.js | 55 ++++++++- .../auth-forms/CustomFormWizard.js | 104 ++++++++++-------- .../auth-forms/UploadFileTable.js | 5 +- src/utils/ApiPathConst.js | 2 +- src/utils/HttpUtils.js | 9 +- 5 files changed, 114 insertions(+), 61 deletions(-) diff --git a/src/pages/authentication/auth-forms/BusCustomFormWizard.js b/src/pages/authentication/auth-forms/BusCustomFormWizard.js index 2fd0cc8..cb62c32 100644 --- a/src/pages/authentication/auth-forms/BusCustomFormWizard.js +++ b/src/pages/authentication/auth-forms/BusCustomFormWizard.js @@ -92,6 +92,7 @@ const BusCustomFormWizard = (props) => { + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" + // const refType = "identification"; useEffect(() => { changePassword(''); @@ -137,23 +138,65 @@ const BusCustomFormWizard = (props) => { } }; + useEffect(() => { + let updateRowList = new DataTransfer(); + var updateRowsIndex = updateRows.length; + const saveFileList = []; + + if (updateRowsIndex!=null){ + for (let i = 0; i < updateRowsIndex; i++){ + const file = updateRows[i] + file.id = i; + updateRowList.items.add(file); + saveFileList.push(file); + } + let updatedFileList = updateRowList.files; + setFileList(updatedFileList); + setFileListData(saveFileList) + + } + + }, [updateRows]); + const handleFileUpload = (event)=>{ + let updateList = new DataTransfer(); + let currentFileList = fileListData; const uploadFileList = event.target.files; const saveFileList = []; var currentIndex = 0; - if (!fileList.length==null){ - currentIndex = fileList.length; + if (currentFileList.length!=null){ + currentIndex = currentFileList.length; + for (let i = 0; i < currentIndex; i++){ + const file = currentFileList[i] + // file.id = currentIndex; + updateList.items.add(file); + saveFileList.push(file); + } } - for (let i = 0; i < uploadFileList.length; i++){ + for (let i = 0; i < uploadFileList.length && currentIndex<5; i++){ const file = event.target.files[i] - file.id = currentIndex+i+1 - saveFileList.push(file) + let isDuplicate = false; + + // Check if the file name already exists in saveFileList + for (let j = 0; j < saveFileList.length; j++) { + if (saveFileList[j].name === file.name) { + isDuplicate = true; + break; + } + } + if (!isDuplicate) { + file.id = currentIndex+i + saveFileList.push(file) + updateList.items.add(file); + } + } + let updatedFileList = updateList.files; setFileListData(saveFileList) - setFileList(uploadFileList); + setFileList(updatedFileList); }; useEffect(() => { diff --git a/src/pages/authentication/auth-forms/CustomFormWizard.js b/src/pages/authentication/auth-forms/CustomFormWizard.js index 3ad47d7..776e272 100644 --- a/src/pages/authentication/auth-forms/CustomFormWizard.js +++ b/src/pages/authentication/auth-forms/CustomFormWizard.js @@ -27,10 +27,10 @@ import * as yup from 'yup'; // project import // import AnimateButton from 'components/@extended/AnimateButton'; import { strengthColorChi, strengthIndicator } from 'utils/password-strength'; -import {apiPath} from "auth/utils"; +// import {apiPath} from "auth/utils"; import axios from "axios"; import {POST_PUBLIC_USER_REGISTER} from "utils/ApiPathConst"; -import * as HttpUtils from 'utils/HttpUtils'; +// import * as HttpUtils from 'utils/HttpUtils'; import * as ComboData from "../../../utils/ComboData"; import Loadable from 'components/Loadable'; @@ -96,6 +96,7 @@ const CustomFormWizard = (props) => { + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" + const refType = "identification"; useEffect(() => { changePassword(''); @@ -143,17 +144,21 @@ const CustomFormWizard = (props) => { }; useEffect(() => { - console.log(updateRows); let updateRowList = new DataTransfer(); var updateRowsIndex = updateRows.length; + const saveFileList = []; if (updateRowsIndex!=null){ for (let i = 0; i < updateRowsIndex; i++){ const file = updateRows[i] + file.id = i; updateRowList.items.add(file); + saveFileList.push(file); } let updatedFileList = updateRowList.files; setFileList(updatedFileList); + setFileListData(saveFileList) + } }, [updateRows]); @@ -164,25 +169,21 @@ const CustomFormWizard = (props) => { const uploadFileList = event.target.files; const saveFileList = []; var currentIndex = 0; - // console.log("uploadFileList") - // console.log(uploadFileList) - + if (currentFileList.length!=null){ currentIndex = currentFileList.length; for (let i = 0; i < currentIndex; i++){ const file = currentFileList[i] + // file.id = currentIndex; updateList.items.add(file); saveFileList.push(file); } } - // console.log("saveFileList") - // console.log(saveFileList) - + for (let i = 0; i < uploadFileList.length && currentIndex<5; i++){ const file = event.target.files[i] let isDuplicate = false; - // console.log("file 1") - // console.log(file) + // Check if the file name already exists in saveFileList for (let j = 0; j < saveFileList.length; j++) { if (saveFileList[j].name === file.name) { @@ -191,8 +192,6 @@ const CustomFormWizard = (props) => { } } if (!isDuplicate) { - // console.log("file2") - // console.log(file) file.id = currentIndex+i saveFileList.push(file) updateList.items.add(file); @@ -203,8 +202,6 @@ const CustomFormWizard = (props) => { setFileListData(saveFileList) setFileList(updatedFileList); - // console.log("saveFileList2") - // console.log(saveFileList) }; useEffect(() => { @@ -256,38 +253,53 @@ const CustomFormWizard = (props) => { if (termsAndConNotAccept){ tncFlag = false } + + const user = { + username: values.username, + password: values.password, + name: values.username, + enName: values.enName, + chName: values.chName, + emailAddress: values.email, + idDocType:values.idDocType, + identification:values.idNo, + checkDigit:values.checkDigit, + tncFlag:tncFlag, + type:"IND", + }; + + var formData = new FormData(); + for (let i = 0; i < fileListData.length; i++){ + const file = fileListData[i] + formData.append("multipartFileList", file); + } + formData.append("refType", refType); + + for (const [key, value] of Object.entries(user)) { + formData.append(key, value); + } + formData.append("userFaxNo", JSON.stringify(userFaxNo)); + formData.append("userMobileNumber", JSON.stringify(userMobileNumber)); + formData.append("userAddress", JSON.stringify(userAddress)); + + // if(refCode){ + // formData.append("refCode", refCode); + // } + + console.log("formData:") + console.log(formData) + if (isValid){ - axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, { - username: values.username, - password: values.password, - name: values.username, - enName: values.enName, - chName: values.chName, - emailAddress: values.email, - idDocType:values.idDocType, - identification:values.idNo, - checkDigit:values.checkDigit, - userFaxNo:userFaxNo, - userMobileNumber:userMobileNumber, - userAddress:userAddress, - tncFlag:tncFlag, - type:"IND" + axios.post(POST_PUBLIC_USER_REGISTER, formData,{ + headers: { + "Content-Type":"multipart/form-data" + } }) .then((response) => { + console.log(response) setCheckUpload(true) - HttpUtils.fileUpload( - { - refType:"identification", - refId: response.data.id, - file: fileList, - onSuccess: (response)=>{ - console.log(response); - // setOpen(true); - setLoding(false); - } - } - ); + setLoding(false); }) .catch(error => { console.error(error); @@ -341,7 +353,6 @@ const CustomFormWizard = (props) => { var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; // var result = reg.test(email); var result = email.match(validRegex); - console.log("test1: "+result) if (result == false) { return false; } @@ -599,11 +610,8 @@ const CustomFormWizard = (props) => { // getOptionLabel={(idDocTypeComboList) => idDocTypeComboList.label} onBlur={formik.handleBlur} onChange={(event, newValue) => { - // console.log(newValue) if (newValue!=null){ - console.log(newValue) setSelectedIdDocType(newValue); - // setSelectedIdDocLabel(newValue.label); if (newValue.type!="HKID"){ formik.setFieldValue("checkDigit","") } @@ -1067,7 +1075,7 @@ const CustomFormWizard = (props) => { 如: 香港身份證; 護照; 中國內地身份證等 {fileList !=null? - :null} + :null} {/* @@ -1288,7 +1296,7 @@ const CustomFormWizard = (props) => { 身份證明文件 {fileList !=null? - :null} + :null} diff --git a/src/pages/authentication/auth-forms/UploadFileTable.js b/src/pages/authentication/auth-forms/UploadFileTable.js index 1944d08..e73ff3e 100644 --- a/src/pages/authentication/auth-forms/UploadFileTable.js +++ b/src/pages/authentication/auth-forms/UploadFileTable.js @@ -15,7 +15,7 @@ import { } from '@mui/material'; // ==============================|| EVENT TABLE ||============================== // -export default function UploadFileTable({recordList, setUpdateRows}) { +export default function UploadFileTable({recordList, setUpdateRows, disableDelete}) { const [rows, setRows] = React.useState(recordList); const [rowModesModel,setRowModesModel] = React.useState({}); @@ -45,7 +45,7 @@ export default function UploadFileTable({recordList, setUpdateRows}) { ...rowModesModel, [id]: { mode: GridRowModes.View, ignoreModifications: true }, }); - console.log("test123") + console.log("Starting Delete") const editedRow = rows.find((row) => row.id === id); console.log(editedRow) console.log(editedRow.isNew) @@ -60,6 +60,7 @@ export default function UploadFileTable({recordList, setUpdateRows}) { headerName: '', width: 30, cellClassName: 'actions', + hide:{disableDelete}, getActions: ({id}) => { return [ { }); }; -export const fileUpload = ({ refType, refId, file,refCode, onSuccess, onFail, onError}) =>{ +export const fileUpload = ({ refType, refId, files,refCode, onSuccess, onFail, onError}) =>{ + console.log(files); var formData = new FormData(); - for (let i = 0; i < file.length; i++){ - const file = file[i] - formData.append("multipartFile", file); + for (let i = 0; i < files.length; i++){ + const file = files[i] + formData.append("multipartFileList", file); } // formData.append("multipartFile", file); formData.append("refType", refType); From ebf4b375c8a2e0f0e6d36c5fbfcd7e191a2cf719 Mon Sep 17 00:00:00 2001 From: Alex Cheung Date: Thu, 7 Sep 2023 05:03:26 +0800 Subject: [PATCH 2/2] fix file upload and add alert window for password error --- src/pages/authentication/BusRegister.js | 2 +- src/pages/authentication/Register.js | 2 +- .../auth-forms/AuthLoginCustom.js | 34 +++--- .../auth-forms/BusCustomFormWizard.js | 110 +++++++++++++----- .../auth-forms/CustomFormWizard.js | 54 ++++++--- .../auth-forms/PasswordAlertDialog.js | 48 ++++++++ .../auth-forms/PreviewUploadFileTable.js | 107 +++++++++++++++++ .../auth-forms/UploadFileTable.js | 9 +- 8 files changed, 298 insertions(+), 68 deletions(-) create mode 100644 src/pages/authentication/auth-forms/PasswordAlertDialog.js create mode 100644 src/pages/authentication/auth-forms/PreviewUploadFileTable.js diff --git a/src/pages/authentication/BusRegister.js b/src/pages/authentication/BusRegister.js index 3c003b2..96ff6d1 100644 --- a/src/pages/authentication/BusRegister.js +++ b/src/pages/authentication/BusRegister.js @@ -125,7 +125,7 @@ All steps completed - you're finished - + diff --git a/src/pages/authentication/Register.js b/src/pages/authentication/Register.js index 2f59a6d..c0ef694 100644 --- a/src/pages/authentication/Register.js +++ b/src/pages/authentication/Register.js @@ -141,7 +141,7 @@ const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); {/* */} - + { activeStep === 2|| activeStep === 0? ( @@ -1221,7 +1259,17 @@ const BusCustomFormWizard = (props) => { - + + + + + 身份證明文件 + {fileList !=null? + :null} + + + + diff --git a/src/pages/authentication/auth-forms/CustomFormWizard.js b/src/pages/authentication/auth-forms/CustomFormWizard.js index 776e272..e44c7f4 100644 --- a/src/pages/authentication/auth-forms/CustomFormWizard.js +++ b/src/pages/authentication/auth-forms/CustomFormWizard.js @@ -36,6 +36,7 @@ import * as ComboData from "../../../utils/ComboData"; import Loadable from 'components/Loadable'; import { lazy } from 'react'; const UploadFileTable = Loadable(lazy(() => import('./UploadFileTable'))); +const PreviewUploadFileTable = Loadable(lazy(() => import('./PreviewUploadFileTable'))); const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent'))); // import UploadFileTable from './UploadFileTable'; // import LoadingComponent from "../../extra-pages/LoadingComponent"; @@ -58,6 +59,7 @@ const CustomFormWizard = (props) => { const [fileList, setFileList] = useState([]); const [fileListData, setFileListData] = useState([]); const [checkUpload, setCheckUpload] = useState(false); + const [isLoading, setLoding] = useState(true); const [updateRows, setUpdateRows] = useState([]); const handleClickShowPassword = () => { @@ -83,7 +85,6 @@ const CustomFormWizard = (props) => { const [termsAndConAccept, setTermsAndConAccept] = useState(false); const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); const [isValid, setisValid] = useState(false); - const [isLoading, setLoding] = useState(true); const idDocTypeComboList = ComboData.idDocType; const address4ComboList = ComboData.district; @@ -191,7 +192,7 @@ const CustomFormWizard = (props) => { break; } } - if (!isDuplicate) { + if (!isDuplicate && i+currentIndex<5) { file.id = currentIndex+i saveFileList.push(file) updateList.items.add(file); @@ -287,9 +288,6 @@ const CustomFormWizard = (props) => { // formData.append("refCode", refCode); // } - console.log("formData:") - console.log(formData) - if (isValid){ axios.post(POST_PUBLIC_USER_REGISTER, formData,{ headers: { @@ -399,9 +397,9 @@ const CustomFormWizard = (props) => { checkDigit:yup.string().max(1).required('請輸入括號內的數字或字母'), idDocType: yup.string().max(255).required('請輸入證件類別'), phoneCountryCode: yup.string().min(3,'請輸入3位數字').required('請輸入國際區號'), - faxCountryCode: yup.string().min(3,'請輸入3位數字'), + // faxCountryCode: yup.string().min(3,'請輸入3位數字'), phone: yup.string().min(8,'請輸入8位數字').required('請輸入聯絡電話'), - fax: yup.string().min(8,'請輸入8位數字'), + // fax: yup.string().min(8,'請輸入8位數字'), }), }); @@ -959,7 +957,14 @@ const CustomFormWizard = (props) => { value={formik.values.phoneCountryCode} name="phoneCountryCode" // onBlur={formik.handleBlur} - onChange={formik.handleChange} + // onChange={formik.handleChange} + onChange={(event) => { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("phoneCountryCode",value); + }} placeholder="國際區號" error={Boolean(formik.touched.phone && formik.errors.phone)} onBlur={formik.handleBlur} @@ -979,7 +984,14 @@ const CustomFormWizard = (props) => { value={formik.values.phone} name="phone" // onBlur={formik.handleBlur} - onChange={formik.handleChange} + // onChange={formik.handleChange} + onChange={(event) => { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("phone",value); + }} placeholder="聯絡電話" error={Boolean(formik.touched.phone && formik.errors.phone)} onBlur={formik.handleBlur} @@ -1015,7 +1027,14 @@ const CustomFormWizard = (props) => { type="faxCountryCode" value={formik.values.faxCountryCode} name="faxCountryCode" - onChange={formik.handleChange} + // onChange={formik.handleChange} + onChange={(event) => { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("faxCountryCode",value); + }} placeholder="國際區號" onBlur={formik.handleBlur} inputProps={{ @@ -1034,7 +1053,14 @@ const CustomFormWizard = (props) => { value={formik.values.fax} name="fax" onBlur={formik.handleBlur} - onChange={formik.handleChange} + // onChange={formik.handleChange} + onChange={(event) => { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("fax",value); + }} placeholder="傳真號碼" inputProps={{ maxLength: 8, @@ -1075,7 +1101,7 @@ const CustomFormWizard = (props) => { 如: 香港身份證; 護照; 中國內地身份證等 {fileList !=null? - :null} + :null} {/* @@ -1296,13 +1322,11 @@ const CustomFormWizard = (props) => { 身份證明文件 {fileList !=null? - :null} + :null} - - diff --git a/src/pages/authentication/auth-forms/PasswordAlertDialog.js b/src/pages/authentication/auth-forms/PasswordAlertDialog.js new file mode 100644 index 0000000..e5d68c7 --- /dev/null +++ b/src/pages/authentication/auth-forms/PasswordAlertDialog.js @@ -0,0 +1,48 @@ +import React, { + // useEffect, + // useState +} from 'react'; + +// material-ui +import { + Button, + // Link, + Stack, + Typography, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle +} from '@mui/material'; +import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; + +const PasswordAlertDialog = (props) => { + return ( + + + + + 用戶名或密碼錯誤 + + + + + {""} + + + + + + + ); +}; + +export default PasswordAlertDialog; diff --git a/src/pages/authentication/auth-forms/PreviewUploadFileTable.js b/src/pages/authentication/auth-forms/PreviewUploadFileTable.js new file mode 100644 index 0000000..7c70087 --- /dev/null +++ b/src/pages/authentication/auth-forms/PreviewUploadFileTable.js @@ -0,0 +1,107 @@ +// material-ui +import * as React from 'react'; +import { + DataGrid, + // GridActionsCellItem, + // GridRowModes +} from "@mui/x-data-grid"; +// import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; +import {useEffect} from "react"; +// import {useNavigate} from "react-router-dom"; +// import { useTheme } from '@mui/material/styles'; +import { + Box, + Stack +} from '@mui/material'; +// ==============================|| EVENT TABLE ||============================== // + +export default function PreviewUploadFileTable({recordList,}) { + + const [rows, setRows] = React.useState(recordList); + const [rowModesModel] = React.useState({}); + // const theme = useTheme(); + + // const navigate = useNavigate() + + useEffect(() => { + setRows(recordList); + }, [recordList]); + + function NoRowsOverlay() { + return ( + + 沒有上傳檔案 + {/*
(rows={[]})
*/} +
+ ); + } + + // const handleCancelClick = (id) => () => { + // setRowModesModel({ + // ...rowModesModel, + // [id]: { mode: GridRowModes.View, ignoreModifications: true }, + // }); + // console.log("Starting Delete") + // const editedRow = rows.find((row) => row.id === id); + // console.log(editedRow) + // console.log(editedRow.isNew) + // setUpdateRows(rows.filter((row) => row.id !== id)); + // setRows(rows.filter((row) => row.id !== id)); + // } + + const columns = [ + // { + // field: 'actions', + // type: 'actions', + // headerName: '', + // width: 30, + // cellClassName: 'actions', + // getActions: ({id}) => { + // return [ + // } + // label="delete" + // className="textPrimary" + // onClick={handleCancelClick(id)} + // color="error" + // />] + // }, + // }, + { + id: 'name', + field: 'name', + headerName: '檔案名稱', + flex: 1, + }, + { + id: 'size', + field: 'size', + headerName: '檔案大小', + valueGetter: (params) => { + // console.log(params) + return Math.ceil(params.value/1024)+" KB"; + }, + flex: 1, + }, + ]; + + return ( + + + + ); +} diff --git a/src/pages/authentication/auth-forms/UploadFileTable.js b/src/pages/authentication/auth-forms/UploadFileTable.js index e73ff3e..3755f2e 100644 --- a/src/pages/authentication/auth-forms/UploadFileTable.js +++ b/src/pages/authentication/auth-forms/UploadFileTable.js @@ -15,7 +15,7 @@ import { } from '@mui/material'; // ==============================|| EVENT TABLE ||============================== // -export default function UploadFileTable({recordList, setUpdateRows, disableDelete}) { +export default function UploadFileTable({recordList, setUpdateRows,}) { const [rows, setRows] = React.useState(recordList); const [rowModesModel,setRowModesModel] = React.useState({}); @@ -25,12 +25,9 @@ export default function UploadFileTable({recordList, setUpdateRows, disableDelet useEffect(() => { setRows(recordList); + // console.log(disableDelete); }, [recordList]); - // useEffect(() => { - // console.log(updateRows); - // }, [updateRows]); - function NoRowsOverlay() { return ( @@ -60,7 +57,7 @@ export default function UploadFileTable({recordList, setUpdateRows, disableDelet headerName: '', width: 30, cellClassName: 'actions', - hide:{disableDelete}, + // hide:true, getActions: ({id}) => { return [