Parcourir la source

update password log

CR003
Alex Cheung il y a 1 an
Parent
révision
bd40598a1d
12 fichiers modifiés avec 800 ajouts et 167 suppressions
  1. +122
    -0
      src/pages/User/ChangePasswordPage/ResetPasswordSuccess.js
  2. +459
    -0
      src/pages/User/ChangePasswordPage/index.js
  3. +1
    -0
      src/pages/authentication/auth-forms/AuthLogin.js
  4. +1
    -0
      src/pages/authentication/auth-forms/AuthLoginCustom.js
  5. +1
    -0
      src/pages/iAmSmart/AuthCallback/index.js
  6. +1
    -0
      src/pages/iAmSmart/DirectLoginCallback/index.js
  7. +159
    -151
      src/routes/GLDUserRoutes.js
  8. +19
    -5
      src/routes/PublicUserRoutes.js
  9. +11
    -9
      src/routes/index.js
  10. +1
    -1
      src/translations/zh-CN.json
  11. +1
    -1
      src/translations/zh-HK.json
  12. +24
    -0
      src/utils/Utils.js

+ 122
- 0
src/pages/User/ChangePasswordPage/ResetPasswordSuccess.js Voir le fichier

@@ -0,0 +1,122 @@
// import { useFormik } from 'formik';
// import * as yup from 'yup';
import * as React from "react";
// import * as HttpUtils from "utils/HttpUtils";
// import * as UrlUtils from "utils/ApiPathConst";
// import { useNavigate } from "react-router-dom";
// import { useDispatch } from "react-redux";
// import { handleLogoutFunction, handleLogin} from 'auth/index';
// import useJwt from "auth/jwt/useJwt";

import {
Grid,
Typography,
Button,
// RadioGroup,
// Dialog, DialogTitle, DialogContent, DialogActions,
Stack,
// InputLabel,
// OutlinedInput,
// FormHelperText,
// TextField,
// IconButton, InputAdornment,
// Box,
// FormControl
} from '@mui/material';
import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
// import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';
// import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
// import {ThemeProvider} from "@emotion/react";
import {FormattedMessage,
// useIntl
} from "react-intl";
// import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
// import axios from 'axios';
import {
// useParams,
Link
} from 'react-router-dom';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';

// import LocaleContext from "components/I18nProvider";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ResetPasswordSuccess = () => {

const [isLoading, setLoding] = React.useState(true);

React.useEffect(() => {
setLoding(false)
}, []);

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

return (
isLoading ?
<Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
:
<Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
<Grid item xs={12} md={12} width={{sx:"90%", sm:"90%",md: "60%", xs: "90%"}}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
margin: { sm: 0, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, }}>
{/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
<CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
<Typography display="inline" variant="h4">
<FormattedMessage id="resetPasswordSuccess"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
<Button color="success" variant="outlined" component={Link} to="/login">
<Typography variant="h5">
<FormattedMessage id="backToLogin"/>
</Typography>
</Button>
</Grid>
</Grid>
</MainCard>
</Grid>
</Grid>
);
};

export default ResetPasswordSuccess;

+ 459
- 0
src/pages/User/ChangePasswordPage/index.js Voir le fichier

@@ -0,0 +1,459 @@
import { useFormik } from 'formik';
import * as yup from 'yup';
import * as React from "react";
import * as HttpUtils from "utils/HttpUtils";
import * as UrlUtils from "utils/ApiPathConst";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { handleLogoutFunction,
// handleLogin
} from 'auth/index';
import useJwt from "auth/jwt/useJwt";

import {
Grid,
Typography,
Button,
// RadioGroup,
// Dialog, DialogTitle, DialogContent, DialogActions,
Stack,
InputLabel,
// OutlinedInput,
FormHelperText,
TextField,
IconButton, InputAdornment,
// Box,
// FormControl
} from '@mui/material';
import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
// import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';
import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";
import {FormattedMessage, useIntl} from "react-intl";
import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
import axios from 'axios';
import { useParams,Link } from 'react-router-dom';
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
// import LocaleContext from "components/I18nProvider";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const Index = () => {
const dispatch = useDispatch()
const navigate = useNavigate()
const [showPassword, setShowPassword] = React.useState(false);
const [showConfirmPassword, setshowConfirmPassword] = React.useState(false);
const [isLoading, setLoding] = React.useState(true);
const [verifyState, setVerifyState] = React.useState(null)
const [enterUseEffect, setEnterUseEffect] = React.useState(false)
const [username, setUsername] = React.useState("")
// const { setLocale } = React.useContext(LocaleContext);
const params = useParams()
const intl = useIntl();
React.useEffect(() => {
console.log(params);
setEnterUseEffect(true)
}, []);

React.useEffect(() => {
// console.log("if (enterUseEffect) handleVerify()");
if (enterUseEffect){
handleVerify()
}
}, [enterUseEffect])

const handleVerify = async () => {
console.log(params);
await axios.get(UrlUtils.GET_FORGOT_PASSWORD_VERIFY_USER_ACCOUNT, {
params: {
email: decodeURIComponent(params.email),
emailVerifyHash: decodeURIComponent(params.verifyCode)
}
}).then(
(response)=>{
if (response.status === 200 && response.data) {
console.log(response)
setUsername(response.data.username)
setVerifyState(true)
} else {
setVerifyState(false)
}
setLoding(false)
}
).catch(error => {
console.log(error)
setVerifyState(false)
setLoding(false)
});

}

const goLogin = async (values) =>{
dispatch(handleLogoutFunction());
HttpUtils.post({
url: UrlUtils.POST_FORGOT_PASSWORD_NEW_PASSWORD,
params:{
username: username,
newPassword: values.password
},
onSuccess: () => {
useJwt
.login({ username: username, password: values.password })
.then((
// response
) => {
// console.log(response)
navigate('/forgot/password/success');
location.reload()
// setSumitting(false)
})
.catch((error) => {
console.error(error)
});
},
onFail: (response)=>{
console.log("Fail");
console.log(response);
// window.location.assign("/iamsmart/loginFail");
},
onError:(error)=>{
console.log(error);
// window.location.assign("/iamsmart/loginFail");
}
});
}

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

const handleClickShowPassword = () => {
setShowPassword(!showPassword);
};

const handleClickShowConfirmPassword = () => {
setshowConfirmPassword(!showConfirmPassword);
};

const handleMouseDownPassword = (event) => {
event.preventDefault();
};

const changePassword = (
// value
) => {
// const temp = strengthIndicator(value);
// setLevel(strengthColorChi(temp));
};

const formik = useFormik({
enableReinitialize: true,
initialValues: {
// username: '',
password: '',
confirmPassword: '',
// emailVerifyHash: '',
},
validationSchema: yup.object().shape({
// emailVerifyHash: yup.string().required(intl.formatMessage({id: 'requireSecurityCode'})),
// username: yup.string().required(intl.formatMessage({id: 'requireUsername'})),
password: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
.required(intl.formatMessage({id: 'requirePassword'}))
.matches(/^\S*$/, { message: (intl.formatMessage({id: 'noSpacePassword'}))})
.matches(/^(?=.*[a-z])/, { message: intl.formatMessage({id: 'atLeastOneSmallLetter'})})
.matches(/^(?=.*[A-Z])/, { message: intl.formatMessage({id: 'atLeastOneCapLetter'})})
.matches(/^(?=.*[0-9])/, { message: intl.formatMessage({id: 'atLeast1Number'})})
.matches(/^(?=.*[!@#%&])/, { message: intl.formatMessage({id: 'atLeast1SpecialChar'})}),
confirmPassword: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
.required(intl.formatMessage({id: 'pleaseConfirmPassword'}))
.oneOf([yup.ref('password'), null], intl.formatMessage({id: 'samePassword'})),
}),
onSubmit: values => {
// console.log(values)
goLogin(values)
}
});

return (
isLoading || verifyState == null ?
<Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
:
<Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
{/* <Grid item xs={12} width={{xs:"90%", sm:"90%", md:"60%", lg:"60%"}}>
<Button
aria-label={intl.formatMessage({id: 'back'})}
title={intl.formatMessage({id: 'back'})}
sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}
>
<ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
</Button>
</Grid> */}
{/* <Grid item xs={12}>
<Typography variant="pnspsFormParagraphBold">申請公共啟事</Typography>
</Grid> */}
<Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
margin: { sm: 0, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<form onSubmit={formik.handleSubmit}>
{verifyState ?
// SUCCESS page
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"50vh", md: "50vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid container direction="column" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, }}>
<Typography display="inline" variant="h4">
<FormattedMessage id="verifySuccess"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1,}}>
<InputLabel htmlFor="email-login-title3">
<Typography variant="h5" >
<FormattedMessage id="setNewPassword"/>
</Typography>
</InputLabel>
</Grid>
</Grid>
{/* <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
onChange={formik.handleChange}
id="emailVerifyHash"
name="emailVerifyHash"
label={intl.formatMessage({id: 'securityCode'}) + ":"}
placeholder={intl.formatMessage({id: 'securityCode'})}
defaultValue={formik.values.emailVerifyHash}
value={formik.values.emailVerifyHash}
error={Boolean(formik.touched.emailVerifyHash && formik.errors.emailVerifyHash)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 50,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
/>
</Grid>
{formik.touched.emailVerifyHash && formik.errors.emailVerifyHash && (
<FormHelperText error id="standard-weight-helper-text-username-login">
{formik.errors.emailVerifyHash}
</FormHelperText>
)}
</Grid>
</Grid> */}
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
id="username"
name="username"
label={intl.formatMessage({id: 'userLoginName'}) + ":"}
placeholder={intl.formatMessage({id: 'userLoginName'})}
// defaultValue={username}
value={username}
disabled={true} />
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
autoFocus
onChange={(e) => {
formik.handleChange(e);
changePassword(e.target.value);
}}
id="password"
type={showPassword ? 'text' : 'password'}
name="password"
label={intl.formatMessage({id: 'newPassword'}) + ":"}
placeholder={intl.formatMessage({id: 'newPassword'})}
// defaultValue={formik.values.password.trim()}
value={formik.values.password.trim()}
error={Boolean(formik.touched.password && formik.errors.password)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
InputProps={{
endAdornment:(
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
size="large"
>
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Grid>
{/* <FormControl fullWidth sx={{ mt: 2 }}>
<Grid container spacing={2} alignItems="center">
<Grid item>
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
</Grid>
<Grid item>
<Typography variant="subtitle1">
<FormattedMessage id={level ? level?.label : "pwWeak" }/>
</Typography>
</Grid>
</Grid>
</FormControl> */}
{formik.touched.password && formik.errors.password && (
<FormHelperText error id="helper-text-password-signup">
{formik.errors.password}
</FormHelperText>
)}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
onChange={(e) => {
formik.handleChange(e);
// changePassword(e.target.value);
}}
id="confirmPassword"
type={showConfirmPassword ? 'text' : 'password'}
name="confirmPassword"
label={intl.formatMessage({id: 'confirmPassword'}) + ":"}
placeholder={intl.formatMessage({id: 'confirmPassword'})}
// defaultValue={formik.values.confirmPassword.trim()}
value={formik.values.confirmPassword.trim()}
error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 50,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
InputProps={{
endAdornment:(
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowConfirmPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
size="large"
>
{showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Grid>
{formik.touched.confirmPassword && formik.errors.confirmPassword && (
<FormHelperText error id="helper-text-confirmPassword-signup">
{formik.errors.confirmPassword}
</FormHelperText>
)}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} mt={1} sx={{mb:3}}>
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<Button
aria-label={intl.formatMessage({id: 'confirm'})}
variant="contained"
type="submit"
// onClick={()=>goLogin()}
>
<FormattedMessage id="confirm"/>
</Button>
</ThemeProvider>
</Grid>
</Grid>
:
// ERROR page
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
{/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
<CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
<Typography display="inline" variant="h4">
<FormattedMessage id="verifyFail"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
<Button color="error" variant="outlined" component={Link} to="/login">
<Typography variant="h5">
<FormattedMessage id="backToLogin"/>
</Typography>
</Button>
</Grid>
</Grid>
}
</form>
</MainCard>
</Grid>
</Grid>
);
};

export default Index;

+ 1
- 0
src/pages/authentication/auth-forms/AuthLogin.js Voir le fichier

@@ -83,6 +83,7 @@ const AuthLogin = () => {
type: response.data.type,
role: response.data.role,
abilities: response.data.abilities,
passwordExpiryDate: response.data.passwordExpiryDate,
//avatar: require('src/assets/images/users/avatar-3.png').default,
}
// const abilities = response.data.abilities


+ 1
- 0
src/pages/authentication/auth-forms/AuthLoginCustom.js Voir le fichier

@@ -93,6 +93,7 @@ const AuthLoginCustom = () => {
abilities: response.data.abilities,
creditor: response.data.creditor,
locale: response.data.preferLocale,
passwordExpiryDate: response.data.passwordExpiryDate,
//avatar: require('src/assets/images/users/avatar-3.png').default,
}
const data = { ...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken }


+ 1
- 0
src/pages/iAmSmart/AuthCallback/index.js Voir le fichier

@@ -45,6 +45,7 @@ const Index = () => {
role: responseData.role,
abilities: responseData.abilities,
creditor: responseData.creditor,
passwordExpiryDate: response.data.passwordExpiryDate,
//locale: responseData.preferLocale,
//avatar: require('src/assets/images/users/avatar-3.png').default,
}


+ 1
- 0
src/pages/iAmSmart/DirectLoginCallback/index.js Voir le fichier

@@ -45,6 +45,7 @@ const Index = () => {
role: responseData.role,
abilities: responseData.abilities,
creditor: responseData.creditor,
passwordExpiryDate: response.data.passwordExpiryDate,
//avatar: require('src/assets/images/users/avatar-3.png').default,
}
const data = { ...userData, accessToken: responseData.accessToken, refreshToken: responseData.refreshToken }


+ 159
- 151
src/routes/GLDUserRoutes.js Voir le fichier

@@ -5,7 +5,7 @@ import Loadable from 'components/Loadable';
// import MainLayout from 'layout/MainLayout';
const MainLayout = Loadable(lazy(() => import('layout/MainLayout')));
import {isGranted, isGrantedAny} from "auth/utils";
import { isPasswordExpiry } from "utils/Utils";
// render - dashboard
const DashboardDefault = Loadable(lazy(() => import('pages/Dashboard/GLD')));
const ApplicationDetail = Loadable(lazy(() => import('pages/PublicNotice/Details_GLD')));
@@ -32,163 +32,171 @@ const GazetteIssuePage = Loadable(lazy(() => import('pages/GazetteIssue/index'))
const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport')));
const AuditLogPage = Loadable(lazy(() => import('pages/AuditLog/index')));
const ReconReportPage = Loadable(lazy(() => import('pages/Recon')));
const ChangePasswordPage = Loadable(lazy(() => import('pages/User/ChangePasswordPage')));

// ==============================|| MAIN ROUTING ||============================== //

const GLDUserRoutes = {
path: '/',
element: <MainLayout />,
children: [
(
isPasswordExpiry()?
{
path: '/',
element: <ChangePasswordPage />
}:
{
path: '/',
element: <DashboardDefault />
}
),
{
path: '/',
element: <DashboardDefault />
},
{
path: '/',
children: [
{
path: '/dashboard',
element: <DashboardDefault />
},
{
path: '/application/:id',
element: <ApplicationDetail/>
},
{
path: '/application/search',
element: <ApplicationSearch/>
},
isGranted(["MAINTAIN_PAYMENT"])?
{
path: '/application/markAsPaid/search',
element: <ApplicationMarkAsPaidSearch/>
}:{},

isGrantedAny(["VIEW_PROOF","MAINTAIN_PROOF"])?{
path: '/proof/search',
element: <ProofSearch/>
}:{},

isGranted("MAINTAIN_PROOF")?
{
path: '/proof/create/:id',
element: <ProofCreate_FromApp/>
}:{},

isGrantedAny(["VIEW_PROOF","MAINTAIN_PROOF"])?{
path: '/proof/reply/:id',
element: <ProofReply_GLD/>
}:{},

isGranted(["MAINTAIN_PAYMENT"])?
{
path: '/paymentPage/search',
element: <PaymentSearch_GLD/>
}:{},
isGranted(["MAINTAIN_PAYMENT"])?
{
path: '/paymentPage/details/:id',
element: <PaymentDetails_GLD/>
}:{},

isGranted(["MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/createDemandNote',
element: <DemandNote_Create/>
}:{},

isGranted(["MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/exportGDN',
element: <DemandNote_Export/>
}:{},

isGrantedAny(["VIEW_DEMANDNOTE","MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/demandNote',
element: <DemandNote_Search/>
}:{},

isGrantedAny(["VIEW_DEMANDNOTE","MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/demandNote/details/:id',
element: <DemandNote_Details/>
}:{},

isGranted("MAINTAIN_RECON") ?
{
path: '/paymentPage/reconReport',
element: <ReconReportPage/>
}:{},

isGranted("MAINTAIN_RECON") ?
{
path: '/gfmis/search',
element: <GFMIS_Search/>
}:{},


{
path: '/user/profile',
element: <UserMaintainPage />
},

isGranted("MAINTAIN_SETTING") ?
{
path: '/setting/sys',
element: <SystemSetting />
}:{},

isGranted("MAINTAIN_ANNOUNCEMENT") ?
{
path: '/setting/announcement',
element: <AnnouncementSearch />
}:{},

isGranted("MAINTAIN_ANNOUNCEMENT")?
{
path: '/setting/announcement/details/:id',
element: <AnnouncementDetails />
}:{},

isGranted("MAINTAIN_EMAIL")?
{
path: '/setting/emailTemplate',
element: <EmailTemplatePage/>
}:{},

isGranted("MAINTAIN_EMAIL")?
{
path: '/setting/emailTemplate/:id',
element: <EmailTemplateDetailPage/>
}:{},

isGranted("MAINTAIN_GAZETTE_ISSUE")?
{
path: '/setting/holiday',
element: <HolidayPage/>
}:{},

isGranted("MAINTAIN_GAZETTE_ISSUE")?
{
path: '/setting/gazetteissuepage',
element: <GazetteIssuePage/>
}:{},

isGranted("MAINTAIN_DR")?
{
path: '/setting/drImport',
element: <DrImport />
}:{},

{
path: '/setting/auditLog',
element: <AuditLogPage />
},
]
},
path: '/',
children: [
{
path: '/dashboard',
element: <DashboardDefault />
},
{
path: '/application/:id',
element: <ApplicationDetail/>
},
{
path: '/application/search',
element: <ApplicationSearch/>
},
isGranted(["MAINTAIN_PAYMENT"])?
{
path: '/application/markAsPaid/search',
element: <ApplicationMarkAsPaidSearch/>
}:{},
isGrantedAny(["VIEW_PROOF","MAINTAIN_PROOF"])?{
path: '/proof/search',
element: <ProofSearch/>
}:{},
isGranted("MAINTAIN_PROOF")?
{
path: '/proof/create/:id',
element: <ProofCreate_FromApp/>
}:{},
isGrantedAny(["VIEW_PROOF","MAINTAIN_PROOF"])?{
path: '/proof/reply/:id',
element: <ProofReply_GLD/>
}:{},
isGranted(["MAINTAIN_PAYMENT"])?
{
path: '/paymentPage/search',
element: <PaymentSearch_GLD/>
}:{},
isGranted(["MAINTAIN_PAYMENT"])?
{
path: '/paymentPage/details/:id',
element: <PaymentDetails_GLD/>
}:{},
isGranted(["MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/createDemandNote',
element: <DemandNote_Create/>
}:{},
isGranted(["MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/exportGDN',
element: <DemandNote_Export/>
}:{},
isGrantedAny(["VIEW_DEMANDNOTE","MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/demandNote',
element: <DemandNote_Search/>
}:{},
isGrantedAny(["VIEW_DEMANDNOTE","MAINTAIN_DEMANDNOTE"])?
{
path: '/paymentPage/demandNote/details/:id',
element: <DemandNote_Details/>
}:{},
isGranted("MAINTAIN_RECON") ?
{
path: '/paymentPage/reconReport',
element: <ReconReportPage/>
}:{},
isGranted("MAINTAIN_RECON") ?
{
path: '/gfmis/search',
element: <GFMIS_Search/>
}:{},
{
path: '/user/profile',
element: <UserMaintainPage />
},
isGranted("MAINTAIN_SETTING") ?
{
path: '/setting/sys',
element: <SystemSetting />
}:{},
isGranted("MAINTAIN_ANNOUNCEMENT") ?
{
path: '/setting/announcement',
element: <AnnouncementSearch />
}:{},
isGranted("MAINTAIN_ANNOUNCEMENT")?
{
path: '/setting/announcement/details/:id',
element: <AnnouncementDetails />
}:{},
isGranted("MAINTAIN_EMAIL")?
{
path: '/setting/emailTemplate',
element: <EmailTemplatePage/>
}:{},
isGranted("MAINTAIN_EMAIL")?
{
path: '/setting/emailTemplate/:id',
element: <EmailTemplateDetailPage/>
}:{},
isGranted("MAINTAIN_GAZETTE_ISSUE")?
{
path: '/setting/holiday',
element: <HolidayPage/>
}:{},
isGranted("MAINTAIN_GAZETTE_ISSUE")?
{
path: '/setting/gazetteissuepage',
element: <GazetteIssuePage/>
}:{},
isGranted("MAINTAIN_DR")?
{
path: '/setting/drImport',
element: <DrImport />
}:{},
{
path: '/setting/auditLog',
element: <AuditLogPage />
},
]
},
]
};



+ 19
- 5
src/routes/PublicUserRoutes.js Voir le fichier

@@ -4,6 +4,7 @@ import { lazy } from 'react';
import Loadable from 'components/Loadable';
// import MainLayout from 'layout/MainLayout';
const MainLayout = Loadable(lazy(() => import('layout/MainLayout')));
import { isPasswordExpiry } from "utils/Utils";

// render - dashboard
const DashboardDefault = Loadable(lazy(() => import('pages/Dashboard/Public')));
@@ -30,6 +31,7 @@ const Msg_Details = Loadable(lazy(() => import('pages/Message/Details')));
const Msg_Search = Loadable(lazy(() => import('pages/Message/Search')));
const AnnouncementSearch = Loadable(lazy(() => import('pages/Announcement/Search_Public')));
const IAmSmart_SuccessCallback = Loadable(lazy(() => import('pages/iAmSmart/SuccessCallback')));
const ChangePasswordPage = Loadable(lazy(() => import('pages/User/ChangePasswordPage')));


// ==============================|| MAIN ROUTING ||============================== //
@@ -38,10 +40,17 @@ const PublicDashboard = {
path: '/',
element: <MainLayout />,
children: [
{
path: '/',
element: <DashboardDefault />
},
(
isPasswordExpiry()?
{
path: '/',
element: <ChangePasswordPage />
}:
{
path: '/',
element: <DashboardDefault />
}
),
{
path: '/',
children: [
@@ -141,8 +150,13 @@ const PublicDashboard = {
path: '/announcement/search',
element: <AnnouncementSearch />
},
{
path: '/user/changePassword',
element: <ChangePasswordPage />
}
]
},
}
]
};



+ 11
- 9
src/routes/index.js Voir le fichier

@@ -31,16 +31,18 @@ export default function ThemeRoutes() {
return useRoutes([{
path: '',
children: [
(isUserLoggedIn() ?
{
path: '',
element: <Navigate to="/dashboard" />
}
(
isUserLoggedIn() ?
{
path: '',
element: <Navigate to="/dashboard" />
}
:
{
path: '',
element: <Navigate to="/login" />
})
{
path: '',
element: <Navigate to="/login" />
}
)
]
},
// isUserLoggedIn() ? MainRoutes : LoginRoutes,


+ 1
- 1
src/translations/zh-CN.json Voir le fichier

@@ -334,7 +334,7 @@
"pwRemark2": "字母和数字的混合",
"pwRemark3": "英文字母大写与小写的混合",
"pwRemark4": "至少包含一个特殊符号,例如,@ # ?",
"pwRemark5": "請注意,嚴禁使用字典單字、使用者名稱或明顯短語作為密碼內容。",
"pwRemark5": "请注意,严禁使用字典单词、用户名或明显的短语作为密码内容。",
"pwWeak": "弱",
"pwNormal": "普通",
"pwGood": "良好",


+ 1
- 1
src/translations/zh-HK.json Voir le fichier

@@ -337,7 +337,7 @@
"pwRemark2": "字母和數字的混合",
"pwRemark3": "英文字母大寫與小寫的混合",
"pwRemark4": "至少包含一個特殊符號,例如,@ # ?",
"pwRemark5": "请注意,严禁使用字典单词、用户名或明显的短语作为密码内容。",
"pwRemark5": "請注意,嚴禁使用字典單字、使用者名稱或明顯短語作為密碼內容。",
"pwWeak": "弱",
"pwNormal": "普通",
"pwGood": "良好",


+ 24
- 0
src/utils/Utils.js Voir le fichier

@@ -1,3 +1,5 @@
import * as DateUtils from "utils/DateUtils"

export const defaultHomePage = '/dashboard'

// ** Checks if an object is empty (returns boolean)
@@ -147,3 +149,25 @@ export const getUserId = () =>{
return JSON.parse(localStorage.getItem('userData')).id
}
}

export const isPasswordExpiry = () =>{
var date;
if (localStorage.getItem('userData') != null){
date = JSON.parse(localStorage.getItem('userData')).passwordExpiryDate
}
if (date != null){
var currentDate = new Date();
var expirationDate = DateUtils.convertToDate(date);
if (expirationDate < currentDate) {
console.log(true)
return true; // The date has expired
} else {
console.log(false)
return false; // The date is still valid
}
}else{
return false;
}
}

Chargement…
Annuler
Enregistrer