From 5d7df5ffbdd1636dcd40a8d0e45663478c0ec012 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Feb 2024 17:07:51 +0800 Subject: [PATCH 1/5] DR import --- src/layout/MainLayout/Header/index.js | 3 + src/pages/Setting/DrImport/index.js | 176 ++++++++++++++++++++++++++ src/routes/GLDUserRoutes.js | 5 + src/utils/ApiPathConst.js | 5 + src/utils/HttpUtils.js | 141 +++++++++++---------- 5 files changed, 260 insertions(+), 70 deletions(-) create mode 100644 src/pages/Setting/DrImport/index.js diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index ea6c01e..25e0d66 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -149,6 +149,9 @@ function Header(props) {
  • Holiday Setting
  • +
  • + DR Import +
  • Announcement
  • diff --git a/src/pages/Setting/DrImport/index.js b/src/pages/Setting/DrImport/index.js new file mode 100644 index 0000000..4918323 --- /dev/null +++ b/src/pages/Setting/DrImport/index.js @@ -0,0 +1,176 @@ + +import * as React from "react"; +import * as HttpUtils from "utils/HttpUtils"; +import * as UrlUtils from "utils/ApiPathConst"; + +import { + Grid, Typography, Button, + Stack, Box, + Dialog, DialogTitle, DialogContent, DialogActions, +} from '@mui/material'; +import { notifyDownloadSuccess } from 'utils/CommonFunction'; + +import { FormattedMessage, useIntl } from "react-intl"; + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' + +// ==============================|| DASHBOARD - DEFAULT ||============================== // + +const Index = () => { + const [isWarningPopUp, setIsWarningPopUp] = React.useState(false); + const [warningText, setWarningText] = React.useState(""); + const [resultStr, setResultStr] = React.useState(""); + + const intl = useIntl(); + + + const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: 'auto', + height: 'auto', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' + } + + + const readFile = (event) => { + let file = event.target.files[0]; + if (file) { + if (file.name.toLowerCase().substr(file.name.length - 5).includes(".xlsx") + ) { + HttpUtils.postWithFiles({ + url: UrlUtils.DR_IMPORT, + params:null, + files: [event.target.files[0]], + onSuccess: function (responData) { + if(responData?.msg){ + setResultStr(<>Error:
    {responData?.msg}) + }else if(responData?.success){ + setResultStr(<>Success
    Record Count: {responData.recordCount}) + } + } + }); + } else { + setWarningText(intl.formatMessage({ id: 'requireValidFileWithFormat' })); + setIsWarningPopUp(true); + setAttachment({}); + document.getElementById("uploadFileBtn").value = ""; + return; + } + } + document.getElementById("uploadFileBtn").value = ""; + } + + return ( + + +
    + + + DR Import + + +
    +
    + + + + + + + + + + { + readFile(event) + }} + /> + + + + + + + + + + + + + + + + + + + + Result: + + {resultStr} + + + + + + +
    + setIsWarningPopUp(false)} + PaperProps={{ + sx: { + minWidth: '40vw', + maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, + maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } + } + }} + > + + Action Fail + + + {warningText} + + + + + +
    +
    + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/routes/GLDUserRoutes.js b/src/routes/GLDUserRoutes.js index a2f78c8..bfc21f6 100644 --- a/src/routes/GLDUserRoutes.js +++ b/src/routes/GLDUserRoutes.js @@ -22,6 +22,7 @@ const UserMaintainPage = Loadable(lazy(() => import('pages/User/GLDUserProfile') const SystemSetting = Loadable(lazy(() => import('pages/Setting/SystemSetting'))); const AnnouncementDetails = Loadable(lazy(() => import('pages/Announcement/Details'))); const AnnouncementSearch = Loadable(lazy(() => import('pages/Announcement/Search'))); +const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport'))); // ==============================|| MAIN ROUTING ||============================== // @@ -100,6 +101,10 @@ const GLDUserRoutes = { path: '/setting/announcement/details/:id', element: }, + { + path: '/setting/drImport', + element: + }, ] }, ] diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index bcd1daf..c44004b 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -67,6 +67,11 @@ export const POST_FILE_LIST = apiPath+'/file/list'; export const GET_FILE_DELETE = apiPath+'/file/delete'; //export const FILE_DOWN_GET = ({id,skey,filename})=>{ return apiPath+'/file/dl/'+id+'/'+skey+'/'+filename}; +export const DR_EXPORT = apiPath+'/settings/dr/export'; +export const DR_IMPORT = apiPath+'/settings/dr/import'; + + + // POST request //Login export const POST_LOGIN = '/login'; diff --git a/src/utils/HttpUtils.js b/src/utils/HttpUtils.js index 8209476..1c208ac 100644 --- a/src/utils/HttpUtils.js +++ b/src/utils/HttpUtils.js @@ -1,109 +1,110 @@ import axios from "axios"; -import {FILE_UP_POST, FILE_DOWN_GET} from "../utils/ApiPathConst"; +import { FILE_UP_POST, FILE_DOWN_GET } from "../utils/ApiPathConst"; -export const get = ({url, params, onSuccess, onFail, onError}) =>{ - axios.get(url,{ +export const get = ({ url, params, onSuccess, onFail, onError }) => { + axios.get(url, { params: params }).then( - (response)=>{onResponse(response, onSuccess, onFail);} + (response) => { onResponse(response, onSuccess, onFail); } ).catch(error => { - return handleError(error,onError); + return handleError(error, onError); }); }; //TODO -export const put = ({url,params, onSuccess, onFail, onError}) =>{ - axios.put(url,params).then( - (response)=>{onResponse(response, onSuccess, onFail);} +export const put = ({ url, params, onSuccess, onFail, onError }) => { + axios.put(url, params).then( + (response) => { onResponse(response, onSuccess, onFail); } ).catch(error => { - return handleError(error,onError); + return handleError(error, onError); }); }; -export const patch = ({url,params, onSuccess, onFail, onError}) =>{ - axios.patch(url,params).then( - (response)=>{onResponse(response, onSuccess, onFail);} +export const patch = ({ url, params, onSuccess, onFail, onError }) => { + axios.patch(url, params).then( + (response) => { onResponse(response, onSuccess, onFail); } ).catch(error => { - return handleError(error,onError); + return handleError(error, onError); }); }; -export const post = ({url, params, onSuccess, onFail, onError, headers}) =>{ - headers = headers?headers:{ - "Content-Type":"application/json" +export const post = ({ url, params, onSuccess, onFail, onError, headers }) => { + headers = headers ? headers : { + "Content-Type": "application/json" }; - - axios.post(url,params, + + axios.post(url, params, { - headers:headers + headers: headers }).then( - (response)=>{onResponse(response, onSuccess, onFail);} - ).catch(error => { - return handleError(error,onError); - }); + (response) => { onResponse(response, onSuccess, onFail); } + ).catch(error => { + return handleError(error, onError); + }); }; -export const postWithFiles = ({url, params, files, onSuccess, onFail, onError}) =>{ +export const postWithFiles = ({ url, params, files, onSuccess, onFail, onError }) => { var formData = new FormData(); - for (let i = 0; i < files.length; i++){ + for (let i = 0; i < files.length; i++) { const file = files[i] formData.append("multipartFileList", file); } - for (var key in params) { - if(typeof(params[key]) ==='object'){ - formData.append(key, JSON.stringify(params[key])); - }else{ - formData.append(key, params[key]); - } - } - - axios.post(url,formData, - {headers: {"Content-Type":"multipart/form-data"}}) - .then( - (response)=>{onResponse(response, onSuccess, onFail);} - ).catch(error => { - return handleError(error,onError); - }); + if (params) + for (var key in params) { + if (typeof (params[key]) === 'object') { + formData.append(key, JSON.stringify(params[key])); + } else { + formData.append(key, params[key]); + } + } + + axios.post(url, formData, + { headers: { "Content-Type": "multipart/form-data" } }) + .then( + (response) => { onResponse(response, onSuccess, onFail); } + ).catch(error => { + return handleError(error, onError); + }); }; -export const fileDownload = ({url, fileId, skey, filename, params, method, onResponse, onError}) =>{ - if(!url){ - url = FILE_DOWN_GET+"/"+fileId+"/"+skey+"/"+filename +export const fileDownload = ({ url, fileId, skey, filename, params, method, onResponse, onError }) => { + if (!url) { + url = FILE_DOWN_GET + "/" + fileId + "/" + skey + "/" + filename } - if(method == 'post'){ - axios.post( url, params, + if (method == 'post') { + axios.post(url, params, { responseType: 'blob', - headers:{ - "Content-Type":"application/json" + headers: { + "Content-Type": "application/json" } } ).then( - (response)=>{ + (response) => { fileDownloadResponse(response, onResponse) } ).catch(error => { - return handleError(error,onError); + return handleError(error, onError); }); - }else{ - axios.get( url, + } else { + axios.get(url, { responseType: 'blob', - params:params + params: params } ).then( - (response)=>{ + (response) => { fileDownloadResponse(response, onResponse) } ).catch(error => { - return handleError(error,onError); + return handleError(error, onError); }); } }; -const fileDownloadResponse=(response, onResponse)=>{ - const fn = response.headers.get("content-disposition")?.split("filename=")[1]?.split('"')[1]?.trim()??filename; +const fileDownloadResponse = (response, onResponse) => { + const fn = response.headers.get("content-disposition")?.split("filename=")[1]?.split('"')[1]?.trim() ?? filename; const url = URL.createObjectURL(response.data); const a = document.createElement('a'); a.href = url; @@ -112,47 +113,47 @@ const fileDownloadResponse=(response, onResponse)=>{ a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); - if(onResponse){ + if (onResponse) { onResponse(); } } -export const fileUpload = ({refType, refId, files, refCode, onSuccess, onFail, onError}) =>{ +export const fileUpload = ({ refType, refId, files, refCode, onSuccess, onFail, onError }) => { postWithFiles({ url: FILE_UP_POST, - params:{ + params: { refType: refType, refId: refId, refCode: refCode }, files: files, onSuccess: onSuccess, - onFail:onFail, - onError:onError + onFail: onFail, + onError: onError }); }; -const onResponse= (response, onSuccess, onFail) =>{ - if (response.status >= 300 ||response.status < 200) { +const onResponse = (response, onSuccess, onFail) => { + if (response.status >= 300 || response.status < 200) { console.log("onFail"); - if(onFail){ + if (onFail) { onFail(response); - }else{ + } else { console.log(response); } return; } - - if(onSuccess){ + + if (onSuccess) { onSuccess(response?.data); } } -const handleError= (error, onError) =>{ - if(onError){ +const handleError = (error, onError) => { + if (onError) { return onError(error); - }else{ + } else { console.log(error); return false; } From 48d5594aa418901f01c70c3bde15cd8b1fec4ea4 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Feb 2024 17:11:09 +0800 Subject: [PATCH 2/5] update ui --- src/pages/Setting/DrImport/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Setting/DrImport/index.js b/src/pages/Setting/DrImport/index.js index 4918323..033649c 100644 --- a/src/pages/Setting/DrImport/index.js +++ b/src/pages/Setting/DrImport/index.js @@ -46,9 +46,9 @@ const Index = () => { files: [event.target.files[0]], onSuccess: function (responData) { if(responData?.msg){ - setResultStr(<>Error:
    {responData?.msg}) + setResultStr(<>Error
    {responData?.msg}) }else if(responData?.success){ - setResultStr(<>Success
    Record Count: {responData.recordCount}) + setResultStr(<>Success
    Record Count: {responData.recordCount}) } } }); From 3cb6b5d94a3fb97987046364f7c21295a6cf0115 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Feb 2024 17:29:11 +0800 Subject: [PATCH 3/5] add please wait --- src/pages/Setting/DrImport/index.js | 36 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/pages/Setting/DrImport/index.js b/src/pages/Setting/DrImport/index.js index 033649c..cbbc3bf 100644 --- a/src/pages/Setting/DrImport/index.js +++ b/src/pages/Setting/DrImport/index.js @@ -1,6 +1,7 @@ import * as React from "react"; import * as HttpUtils from "utils/HttpUtils"; +import * as DateUtils from "utils/DateUtils"; import * as UrlUtils from "utils/ApiPathConst"; import { @@ -20,6 +21,7 @@ const Index = () => { const [isWarningPopUp, setIsWarningPopUp] = React.useState(false); const [warningText, setWarningText] = React.useState(""); const [resultStr, setResultStr] = React.useState(""); + const [wait, setWait] = React.useState(false); const intl = useIntl(); @@ -37,7 +39,9 @@ const Index = () => { const readFile = (event) => { let file = event.target.files[0]; + setWait(true); if (file) { + if (file.name.toLowerCase().substr(file.name.length - 5).includes(".xlsx") ) { HttpUtils.postWithFiles({ @@ -45,20 +49,27 @@ const Index = () => { params:null, files: [event.target.files[0]], onSuccess: function (responData) { + setWait(false); if(responData?.msg){ - setResultStr(<>Error
    {responData?.msg}) + setResultStr(<>{DateUtils.datetimeStr(new Date())}
    Error
    {responData?.msg}) }else if(responData?.success){ - setResultStr(<>Success
    Record Count: {responData.recordCount}) + setResultStr(<>{DateUtils.datetimeStr(new Date())}
    Success
    Record Count: {responData.recordCount}) } + }, + onError: function(){ + setWait(false); + setResultStr(<>{DateUtils.datetimeStr(new Date())}
    Error
    Action Fail: Please import valid file.) } }); } else { - setWarningText(intl.formatMessage({ id: 'requireValidFileWithFormat' })); + setWait(false); + setWarningText("Please upload a valid file (file format: .xlsx)"); setIsWarningPopUp(true); - setAttachment({}); document.getElementById("uploadFileBtn").value = ""; return; } + }else{ + setWait(false); } document.getElementById("uploadFileBtn").value = ""; } @@ -169,6 +180,23 @@ const Index = () => { +
    + setWait(false)} + PaperProps={{ + sx: { + minWidth: '40vw', + maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, + maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } + } + }} + > + + Please wait ... + + +
    ); }; From 65c773c7da2e9e0f4b413a97fd7f55caf2e8fa0a Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Feb 2024 17:38:29 +0800 Subject: [PATCH 4/5] correct message title --- src/pages/Message/Search/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Message/Search/index.js b/src/pages/Message/Search/index.js index b96ae87..9ee6c86 100644 --- a/src/pages/Message/Search/index.js +++ b/src/pages/Message/Search/index.js @@ -70,7 +70,7 @@ const Index = () => {
    - +
    From 014ca5600545e85112a7d1aa88ba88f3e849db64 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Feb 2024 17:44:29 +0800 Subject: [PATCH 5/5] public Announcement datetime -> date --- src/pages/Announcement/Search_Public/DataGrid.js | 2 +- src/pages/dashboard/Public/Notice.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Announcement/Search_Public/DataGrid.js b/src/pages/Announcement/Search_Public/DataGrid.js index 0482e52..e89ba81 100644 --- a/src/pages/Announcement/Search_Public/DataGrid.js +++ b/src/pages/Announcement/Search_Public/DataGrid.js @@ -21,7 +21,7 @@ export default function SearchPublicNoticeTable({ recordList }) { width: 250, cellClassName: 'announceDate', renderCell: (params) => { - return DateUtils.datetimeStr(params?.value); + return DateUtils.dateStr(params?.value); }, }, { diff --git a/src/pages/dashboard/Public/Notice.js b/src/pages/dashboard/Public/Notice.js index e1ce7b8..b518f11 100644 --- a/src/pages/dashboard/Public/Notice.js +++ b/src/pages/dashboard/Public/Notice.js @@ -33,7 +33,7 @@ const SearchDemandNoteForm = () => { list.push( {locale === 'en' ?item.subjectEng:locale === 'zh-HK' ?item.subjectCht:item.subjectChs} - {DateUtils.datetimeStr(item.announceDate)} + {DateUtils.dateStr(item.announceDate)} {locale === 'en' ?item.contentEng:locale === 'zh-HK' ?item.contentCht:item.contentChs}