Bladeren bron

add user search page and user group page and user authority page

master
Alex Cheung 2 jaren geleden
bovenliggende
commit
287a9b2856
26 gewijzigde bestanden met toevoegingen van 2588 en 414 verwijderingen
  1. +0
    -359
      src/pages/arsdashboard/index.js
  2. +59
    -49
      src/pages/authentication/auth-forms/CustomFormWizard.js
  3. +17
    -0
      src/pages/extra-pages/LoadingComponent.js
  4. +27
    -0
      src/pages/extra-pages/LogoutPage.js
  5. +292
    -0
      src/pages/pnspsPasswordPolicyPage/index.js
  6. +177
    -0
      src/pages/pnspsSettingPage/index.js
  7. +80
    -0
      src/pages/pnspsUserDetailPage/UserAuthTable.js
  8. +60
    -0
      src/pages/pnspsUserDetailPage/UserAuthorityCard.js
  9. +59
    -0
      src/pages/pnspsUserDetailPage/UserGroupCard.js
  10. +76
    -0
      src/pages/pnspsUserDetailPage/UserGroupTable.js
  11. +321
    -0
      src/pages/pnspsUserDetailPage/UserInformationCard.js
  12. +135
    -0
      src/pages/pnspsUserDetailPage/index.js
  13. +93
    -0
      src/pages/pnspsUserGroupSearchPage/UserGroupSearchForm.js
  14. +75
    -0
      src/pages/pnspsUserGroupSearchPage/UserGroupTable.js
  15. +78
    -0
      src/pages/pnspsUserGroupSearchPage/index.js
  16. +229
    -0
      src/pages/pnspsUserSearchPage/UserSearchForm.js
  17. +137
    -0
      src/pages/pnspsUserSearchPage/UserTable.js
  18. +84
    -0
      src/pages/pnspsUserSearchPage/index.js
  19. +77
    -0
      src/pages/pnspsUserSettingPage/DummyComboRecord.js
  20. +232
    -0
      src/pages/pnspsUserSettingPage/UserSearchForm.js
  21. +137
    -0
      src/pages/pnspsUserSettingPage/UserTable.js
  22. +89
    -0
      src/pages/pnspsUserSettingPage/index.js
  23. +0
    -5
      src/routes/MainRoutes.js
  24. +48
    -0
      src/routes/SettingRoutes.js
  25. +3
    -1
      src/routes/index.js
  26. +3
    -0
      src/utils/ApiPathConst.js

+ 0
- 359
src/pages/arsdashboard/index.js Bestand weergeven

@@ -1,359 +0,0 @@
import {useEffect, useState} from 'react';

// material-ui
import {
Avatar,
AvatarGroup,
Box,
Button,
Grid,
List,
ListItemAvatar,
ListItemButton,
ListItemSecondaryAction,
ListItemText,
MenuItem,
Stack,
TextField,
Typography
} from '@mui/material';

// project import
import OrdersTable from 'pages/dashboard/OrdersTable';
import IncomeAreaChart from 'pages/dashboard/IncomeAreaChart';
import MonthlyBarChart from 'pages/dashboard/MonthlyBarChart';
import ReportAreaChart from 'pages/dashboard/ReportAreaChart';
import SalesColumnChart from 'pages/dashboard/SalesColumnChart';
import MainCard from 'components/MainCard';
import AnalyticEcommerce from 'components/cards/statistics/AnalyticEcommerce';

// assets
import { GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons';
import avatar1 from 'assets/images/users/avatar-1.png';
import avatar2 from 'assets/images/users/avatar-2.png';
import avatar3 from 'assets/images/users/avatar-3.png';
import avatar4 from 'assets/images/users/avatar-4.png';
import axios from "axios";

// avatar style
const avatarSX = {
width: 36,
height: 36,
fontSize: '1rem'
};

// action style
const actionSX = {
mt: 0.75,
ml: 1,
top: 'auto',
right: 'auto',
alignSelf: 'flex-start',
transform: 'none'
};

// sales report status
const status = [
{
value: 'today',
label: 'Today'
},
{
value: 'month',
label: 'This Month'
},
{
value: 'year',
label: 'This Year'
}
];

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

const ARSDashboard = () => {
const [value, setValue] = useState('today');
const [slot, setSlot] = useState('week');

useEffect(() =>{
tryAPI();
},[]);

const tryAPI = () =>{
axios.get('http://localhost:8090/api/test')
.then((response) => {
console.log(response)
})
.catch(error => {
console.error(error);
});
}

return (
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
{/* row 1 */}
<Grid item xs={12} sx={{ mb: -2.25 }}>
<Typography variant="h5">Event Overall Status</Typography>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title="Total Page Views" count="4,42,236" percentage={59.3} extra="35,000" />
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title="Total Users" count="78,250" percentage={70.5} extra="8,900" />
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title="Total Order" count="18,800" percentage={27.4} isLoss color="warning" extra="1,943" />
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title="Total Sales" count="$35,078" percentage={27.4} isLoss color="warning" extra="$20,395" />
</Grid>

<Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} />

{/* row 2 */}
<Grid item xs={12} md={7} lg={8}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Application</Typography>
</Grid>
<Grid item>
<Stack direction="row" alignItems="center" spacing={0}>
<Button
size="small"
onClick={() => setSlot('month')}
color={slot === 'month' ? 'primary' : 'secondary'}
variant={slot === 'month' ? 'outlined' : 'text'}
>
Month
</Button>
<Button
size="small"
onClick={() => setSlot('week')}
color={slot === 'week' ? 'primary' : 'secondary'}
variant={slot === 'week' ? 'outlined' : 'text'}
>
Week
</Button>
</Stack>
</Grid>
</Grid>
<MainCard content={false} sx={{ mt: 1.5 }}>
<Box sx={{ pt: 1, pr: 2 }}>
<IncomeAreaChart slot={slot} />
</Box>
</MainCard>
</Grid>
<Grid item xs={12} md={5} lg={4}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Income Overview</Typography>
</Grid>
<Grid item />
</Grid>
<MainCard sx={{ mt: 2 }} content={false}>
<Box sx={{ p: 3, pb: 0 }}>
<Stack spacing={2}>
<Typography variant="h6" color="textSecondary">
This Week Statistics
</Typography>
<Typography variant="h3">$7,650</Typography>
</Stack>
</Box>
<MonthlyBarChart />
</MainCard>
</Grid>

{/* row 3 */}
<Grid item xs={12} md={7} lg={8}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Recent Orders</Typography>
</Grid>
<Grid item />
</Grid>
<MainCard sx={{ mt: 2 }} content={false}>
<OrdersTable />
</MainCard>
</Grid>
<Grid item xs={12} md={5} lg={4}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Analytics Report</Typography>
</Grid>
<Grid item />
</Grid>
<MainCard sx={{ mt: 2 }} content={false}>
<List sx={{ p: 0, '& .MuiListItemButton-root': { py: 2 } }}>
<ListItemButton divider>
<ListItemText primary="Company Finance Growth" />
<Typography variant="h5">+45.14%</Typography>
</ListItemButton>
<ListItemButton divider>
<ListItemText primary="Company Expenses Ratio" />
<Typography variant="h5">0.58%</Typography>
</ListItemButton>
<ListItemButton>
<ListItemText primary="Business Risk Cases" />
<Typography variant="h5">Low</Typography>
</ListItemButton>
</List>
<ReportAreaChart />
</MainCard>
</Grid>

{/* row 4 */}
<Grid item xs={12} md={7} lg={8}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Sales Report</Typography>
</Grid>
<Grid item>
<TextField
id="standard-select-currency"
size="small"
select
value={value}
onChange={(e) => setValue(e.target.value)}
sx={{ '& .MuiInputBase-input': { py: 0.5, fontSize: '0.875rem' } }}
>
{status.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
</Grid>
<MainCard sx={{ mt: 1.75 }}>
<Stack spacing={1.5} sx={{ mb: -12 }}>
<Typography variant="h6" color="secondary">
Net Profit
</Typography>
<Typography variant="h4">$1560</Typography>
</Stack>
<SalesColumnChart />
</MainCard>
</Grid>
<Grid item xs={12} md={5} lg={4}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Transaction History</Typography>
</Grid>
<Grid item />
</Grid>
<MainCard sx={{ mt: 2 }} content={false}>
<List
component="nav"
sx={{
px: 0,
py: 0,
'& .MuiListItemButton-root': {
py: 1.5,
'& .MuiAvatar-root': avatarSX,
'& .MuiListItemSecondaryAction-root': { ...actionSX, position: 'relative' }
}
}}
>
<ListItemButton divider>
<ListItemAvatar>
<Avatar
sx={{
color: 'success.main',
bgcolor: 'success.lighter'
}}
>
<GiftOutlined />
</Avatar>
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">Order #002434</Typography>} secondary="Today, 2:00 AM" />
<ListItemSecondaryAction>
<Stack alignItems="flex-end">
<Typography variant="subtitle1" noWrap>
+ $1,430
</Typography>
<Typography variant="h6" color="secondary" noWrap>
78%
</Typography>
</Stack>
</ListItemSecondaryAction>
</ListItemButton>
<ListItemButton divider>
<ListItemAvatar>
<Avatar
sx={{
color: 'primary.main',
bgcolor: 'primary.lighter'
}}
>
<MessageOutlined />
</Avatar>
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">Order #984947</Typography>} secondary="5 August, 1:45 PM" />
<ListItemSecondaryAction>
<Stack alignItems="flex-end">
<Typography variant="subtitle1" noWrap>
+ $302
</Typography>
<Typography variant="h6" color="secondary" noWrap>
8%
</Typography>
</Stack>
</ListItemSecondaryAction>
</ListItemButton>
<ListItemButton>
<ListItemAvatar>
<Avatar
sx={{
color: 'error.main',
bgcolor: 'error.lighter'
}}
>
<SettingOutlined />
</Avatar>
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">Order #988784</Typography>} secondary="7 hours ago" />
<ListItemSecondaryAction>
<Stack alignItems="flex-end">
<Typography variant="subtitle1" noWrap>
+ $682
</Typography>
<Typography variant="h6" color="secondary" noWrap>
16%
</Typography>
</Stack>
</ListItemSecondaryAction>
</ListItemButton>
</List>
</MainCard>
<MainCard sx={{ mt: 2 }}>
<Stack spacing={3}>
<Grid container justifyContent="space-between" alignItems="center">
<Grid item>
<Stack>
<Typography variant="h5" noWrap>
Help & Support Chat
</Typography>
<Typography variant="caption" color="secondary" noWrap>
Typical replay within 5 min
</Typography>
</Stack>
</Grid>
<Grid item>
<AvatarGroup sx={{ '& .MuiAvatar-root': { width: 32, height: 32 } }}>
<Avatar alt="Remy Sharp" src={avatar1} />
<Avatar alt="Travis Howard" src={avatar2} />
<Avatar alt="Cindy Baker" src={avatar3} />
<Avatar alt="Agnes Walker" src={avatar4} />
</AvatarGroup>
</Grid>
</Grid>
<Button size="small" variant="contained" sx={{ textTransform: 'capitalize' }}>
Need Help?
</Button>
</Stack>
</MainCard>
</Grid>
</Grid>
);
};

export default ARSDashboard;

+ 59
- 49
src/pages/authentication/auth-forms/CustomFormWizard.js Bestand weergeven

@@ -275,56 +275,66 @@ const CustomFormWizard = (props) => {
</Typography> */}
</Stack>
</Grid>
<Grid item xs={12} md={6}>
<Stack spacing={1}>
<InputLabel htmlFor="idDocType-signup">身份證明文件
<span style={{color: '#f10000'}}>*</span>
</InputLabel>
<Select
name = "idDocType"
multiple
displayEmpty
value={""}
onChange={handleChange}
input={<OutlinedInput />}
{...register("idDocType")}
renderValue={(selected) => {
if (selected.length === 0) {
return "證件類別";
}
return selected.join(', ');
}}
// MenuProps={MenuProps}
inputProps={{ 'aria-label': 'Without label' }}
>
</Select>
{/* {touched.enName && errors.enName && (
<FormHelperText error id="helper-text-enName-signup">
{errors.enName}
</FormHelperText>
)} */}
</Stack>
</Grid>
<Grid item xs={12} md={6}>
<Stack spacing={1} alignItems="flex-end">
<OutlinedInput
id="idNo-login"
type="text"
value={values.idNo}
name="idNo"
{...register("idNo")}
onChange={handleChange}
placeholder="證件號碼"
fullWidth
error={Boolean(touched.idNo && errors.idNo)}
/>
{touched.idNo && errors.idNo && (
<FormHelperText error id="helper-text-enName-signup">
{errors.idNo}
</FormHelperText>
)}
</Stack>
<Grid item xs={12} md={12} >
<Grid container xs={12} md={12} sx={{mb:1}}>
<Stack spacing={1}>
<InputLabel htmlFor="idDocType-signup">身份證明文件
<span style={{color: '#f10000'}}>*</span>
</InputLabel>
{/* {touched.enName && errors.enName && (
<FormHelperText error id="helper-text-enName-signup">
{errors.enName}
</FormHelperText>
)} */}
</Stack>
</Grid>

<Grid container xs={12} md={12}>
<Grid item xs={12} md={6} >
<Stack spacing={1} sx={{mr:{md:1},mb:{xs:1}}}>
<Select
name = "idDocType"
multiple
displayEmpty
value={""}
onChange={handleChange}
input={<OutlinedInput />}
{...register("idDocType")}
renderValue={(selected) => {
if (selected.length === 0) {
return "證件類別";
}
return selected.join(', ');
}}
// MenuProps={MenuProps}
inputProps={{ 'aria-label': 'Without label' }}
>
</Select>
</Stack>
</Grid>
<Grid item xs={12} md={6}>
<Stack spacing={1}>
<OutlinedInput
id="idNo-login"
type="text"
value={values.idNo}
name="idNo"
{...register("idNo")}
onChange={handleChange}
placeholder="證件號碼"
fullWidth
error={Boolean(touched.idNo && errors.idNo)}
/>
{touched.idNo && errors.idNo && (
<FormHelperText error id="helper-text-enName-signup">
{errors.idNo}
</FormHelperText>
)}
</Stack>
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={6}>
<Stack spacing={1}>
<InputLabel htmlFor="enName-signup">英文姓名


+ 17
- 0
src/pages/extra-pages/LoadingComponent.js Bestand weergeven

@@ -0,0 +1,17 @@
import {Box, CircularProgress, Grid} from "@mui/material";

const LoadingComponent = () => {
return (
<Grid item xs={12} md={12} lg={12} justifyContent="space-between" alignItems="center">
<Box
display="flex"
justifyContent="center"
alignItems="center"
autoHeight
>
<CircularProgress />
</Box>
</Grid>
)
}
export default LoadingComponent;

+ 27
- 0
src/pages/extra-pages/LogoutPage.js Bestand weergeven

@@ -0,0 +1,27 @@
// material-ui
import {
Grid
} from '@mui/material';
import {useEffect} from "react";
import {handleLogoutFunction} from "../../auth";
import {useDispatch} from "react-redux";
import {useNavigate} from "react-router-dom";

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

const LogoutPage = () => {
const dispatch = useDispatch()
const navigate = useNavigate()

useEffect(() =>{
dispatch(handleLogoutFunction());
navigate('/login');
},[])

return (
<Grid>
</Grid>
);
};

export default LogoutPage;

+ 292
- 0
src/pages/pnspsPasswordPolicyPage/index.js Bestand weergeven

@@ -0,0 +1,292 @@
// material-ui
import {
Button,
CardContent, Divider, FormControlLabel,
Grid, InputAdornment, Switch, TextField
} from '@mui/material';
import MainCard from "../../components/MainCard";
import {useForm} from "react-hook-form";
import {useState} from "react";

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

const PasswordPolicyPage = () => {

const { reset, register, handleSubmit } = useForm()
const [aNonA, setANonA] = useState(false);
const [needSpecialCharacter, setNeedSpecialCharacter] = useState(false);
const [noUsernameAsPart, setNoUsernameAsPart] = useState(false);
const [noIdenticalChar, setNoIdenticalChar] = useState(false);

const onSubmit = (data) => {
console.log(data);
console.log(aNonA)
};

function resetForm(){
setANonA(false);
reset();
}
return (
<Grid container rowSpacing={4.5} columnSpacing={2.75} justifyContent="center">
<Grid item xs={12} md={11} lg={10} >
<MainCard xs={12} md={12} lg={12}
border={false}
content={false}>

<form onSubmit={handleSubmit(onSubmit)}>
{/*Title*/}
<CardContent sx={{ px: 2.5, pt: 3 }}>
<Grid item justifyContent="space-between" alignItems="center">
Password Policy
</Grid>
</CardContent>

<Grid container alignItems={"center"} justifyContent="center">
{/*row 1*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
Length of Password
</Grid>

<Grid item xs={12} s={12} md={12} lg={5} justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("syncDateCount")}
id='syncDateCount'
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 2*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
Change Password (days)
</Grid>

<Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("idleLogoutTime")}
id="idleLogoutTime"
InputProps={{
endAdornment: <InputAdornment position="end">days</InputAdornment>,
}}
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 3*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
Password History
</Grid>

<Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("passwordHistory")}
id="passwordHistory"
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 4*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
Maximum number of login failure
</Grid>

<Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("maxLoginFailure")}
id="maxLoginFailure"
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 5*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
Penalty time of login failure (minutes)
</Grid>

<Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("loginFailPenaltyTime")}
id="loginFailPenaltyTime"
InputProps={{
endAdornment: <InputAdornment position="end">minutes</InputAdornment>,
}}
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 6*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
Disable After (days)
</Grid>

<Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("disableAfterCount")}
id="disableAfterCount"
InputProps={{
endAdornment: <InputAdornment position="end">days</InputAdornment>,
}}
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} />
{/*row 7*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>
<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
Generate Password:
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 8*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}>
<Grid item xs={1} s={1} md={3} lg={3} />
<Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center">
<FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={
<Switch
onChange={(event, newValue) => {
setANonA(newValue);
}}
checked={aNonA}
/>
} label="Contain at least one alphabetic and non-alphabetic character" />
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 9*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}>
<Grid item xs={1} s={1} md={3} lg={3} />
<Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center">
<FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={
<Switch
onChange={(event, newValue) => {
setNeedSpecialCharacter(newValue);
}}
checked={needSpecialCharacter}
/>
} label="Contain at least one special character (eg. #,$,@ etc)" />
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 10*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}>
<Grid item xs={1} s={1} md={3} lg={3} />
<Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center">
<FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={
<Switch
onChange={(event, newValue) => {
setNoUsernameAsPart(newValue);
}}
checked={noUsernameAsPart}
/>
} label="Not contain the username as part of password" />
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 11*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}>
<Grid item xs={1} s={1} md={3} lg={3} />
<Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center">
<FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={
<Switch
onChange={(event, newValue) => {
setNoIdenticalChar(newValue);
}}
checked={noIdenticalChar}
/>
} label="Contain no more than three identical consecutive characters" />
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*last row*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}} alignItems={"center"} justifyContent="center">
<Grid container maxWidth justifyContent="flex-end">
<Grid item sx={{ml:3, mr:3}}>
<Button
size="large"
variant="contained"
onClick={resetForm}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Clear
</Button>
</Grid>

<Grid item sx={{ml:3, mr:3}}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Save Change
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</form>
</MainCard>
</Grid>

</Grid>

);
};

export default PasswordPolicyPage;

+ 177
- 0
src/pages/pnspsSettingPage/index.js Bestand weergeven

@@ -0,0 +1,177 @@
// material-ui
import {
Button,
CardContent, Divider,
Grid, InputAdornment, TextField
} from '@mui/material';
import MainCard from "../../components/MainCard";
import {useForm} from "react-hook-form";
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormControl from '@mui/material/FormControl';
import {useState} from "react";

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

const SettingPage = () => {

const [notificationType, setNotificationType] = useState(null);

const { reset, register, handleSubmit } = useForm()
const onSubmit = (data) => {
console.log(data);
console.log(notificationType);
};

function resetForm(){
setNotificationType(null);
reset();
}
return (
<Grid container rowSpacing={4.5} columnSpacing={2.75} justifyContent="center">
<Grid item xs={12} md={11} lg={10} >
<MainCard xs={12} md={12} lg={12}
border={false}
content={false}>

<form onSubmit={handleSubmit(onSubmit)}>
{/*Title*/}
<CardContent sx={{ px: 2.5, pt: 3 }}>
<Grid item justifyContent="space-between" alignItems="center">
System Configuration
</Grid>
</CardContent>

<Grid container alignItems={"center"} justifyContent="center">
{/*row 1*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex'}}>
Notification Frequency
</Grid>

<FormControl>
<RadioGroup
aria-labelledby="notification-group-label"
defaultValue="None"
value={notificationType === null ? null : notificationType}
onChange={(event, newValue) => {
setNotificationType(newValue);
}}
name="radio-buttons-group"
>
<FormControlLabel value="Weekly" control={
<Radio
checked={notificationType === null ? false : notificationType === "Weekly"}
/>
} label="Weekly" />
<FormControlLabel value="Monthly" control={
<Radio
checked={notificationType === null ? false : notificationType === "Monthly"}
/>
} label="Monthly" />
<FormControlLabel value="Bi-Monthly" control={
<Radio
checked={notificationType === null ? false : notificationType === "Bi-Monthly"}
/>
} label="Bi-Monthly" />
<FormControlLabel value="None" control={
<Radio
checked={notificationType === null ? false : notificationType === "None"}
/>
} label="None" />
</RadioGroup>
</FormControl>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 2*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', alignItems: 'center'}}>
Number of days to keep the Government Directory Sync Indicator
</Grid>

<Grid item xs={12} s={12} md={12} lg={5} justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("syncDateCount")}
id='syncDateCount'
InputProps={{
endAdornment: <InputAdornment position="end">days</InputAdornment>,
}}
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 3*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}>
<Grid container sx={{mb:3}}>

<Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', alignItems: 'center'}}>
Idle Logout Time
</Grid>

<Grid item xs={12} s={12} md={12} lg={5} justifyContent="space-between" alignItems="right">
<TextField
fullWidth
{...register("idleLogoutTime")}
id="idleLogoutTime"
InputProps={{
endAdornment: <InputAdornment position="start">minutes</InputAdornment>,
}}
/>
</Grid>
</Grid>
<Divider variant="middle" />
</Grid>

{/*row 4*/}
<Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}} alignItems={"center"} justifyContent="center">
<Grid container maxWidth justifyContent="flex-end">
<Grid item sx={{ml:3, mr:3}}>
<Button
size="large"
variant="contained"
onClick={resetForm}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Clear
</Button>
</Grid>

<Grid item sx={{ml:3, mr:3}}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Save Change
</Button>
</Grid>
</Grid>
</Grid>
</Grid>


</form>
</MainCard>
</Grid>

</Grid>

);
};

export default SettingPage;

+ 80
- 0
src/pages/pnspsUserDetailPage/UserAuthTable.js Bestand weergeven

@@ -0,0 +1,80 @@
// material-ui
import {
DataGrid,
} from "@mui/x-data-grid";
import {useEffect, useState} from "react";
import axios from "axios";
import {apiPath} from "../../auth/utils";
import LoadingComponent from "../extra-pages/LoadingComponent";
import * as React from "react";
import {GET_AUTH_LIST} from "../../utils/ApiPathConst";

// ==============================|| EVENT TABLE ||============================== //

export default function UserAuthTable({setSelectedRow, userAuth}) {
const [authData, setAuthData] = useState([]);
const [onReady, setOnReady] = useState(false);
const [currentSelectedRow, setCurrentSelectedRow] = useState(userAuth);

useEffect(() => {
axios.get(`${apiPath}${GET_AUTH_LIST}`)
.then((response) => {
if (response.status === 200) {
setAuthData(response.data.records);
}
})
.catch(error => {
console.log(error);
return false;
});
}, []);

useEffect(() => {
//if state data are ready and assign to different field
if (authData.length > 0) {
setOnReady(true);
}
}, [authData]);

const columns = [
{
id: 'module',
field: 'module',
headerName: 'Module',
flex: 1,
},
{
id: 'authority',
field: 'name',
headerName: 'Authority',
flex: 2,
},
];

return (
!onReady ?
<LoadingComponent/>
:
<div style={{height: '100%', width: '100%'}}>
<DataGrid
rows={authData}
columns={columns}
editMode="row"
initialState={{
pagination: {
paginationModel: {page: 0, pageSize: 20},
},
}}
pageSizeOptions={[10, 20, 30]}
checkboxSelection
rowSelectionModel={currentSelectedRow}
onRowSelectionModelChange={(ids) => {
console.log(ids);
setSelectedRow(ids);
setCurrentSelectedRow(ids);
}}
autoHeight
/>
</div>
);
}

+ 60
- 0
src/pages/pnspsUserDetailPage/UserAuthorityCard.js Bestand weergeven

@@ -0,0 +1,60 @@
// material-ui
import {
Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import * as React from "react";
import {useEffect, useState} from "react";
import LoadingComponent from "../extra-pages/LoadingComponent";
import UserAuthTable from "./UserAuthTable";

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


const UserAuthorityCard = ({isCollectData, updateUserAuthList,userData}) => {
const [currentAuthData, setCurrentAuthData] = React.useState({});
const [onReady, setOnReady] = useState(false);
const [selectedRow, setSelectedRow] = useState([]);

useEffect(() => {
//if user data from parent are not null
if (Object.keys(userData).length > 0 && userData !== undefined) {
setCurrentAuthData(userData.data);
setSelectedRow(userData.authIds);
}
}, [userData]);

useEffect(() => {
//if state data are ready and assign to different field
if (Object.keys(userData).length > 0 && currentAuthData !== undefined) {
setOnReady(true);
}
}, [currentAuthData]);

useEffect(() => {
//upload latest data to parent
updateUserAuthList(selectedRow);
}, [isCollectData]);


return (
!onReady ?
<LoadingComponent/>
:
<MainCard elevation={0}
border={false}
content={false}
>
<Typography variant="h5" sx={{mt: 3, ml: 3}}>
User Authority
</Typography>

<UserAuthTable
userAuth={userData.authIds}
setSelectedRow={setSelectedRow}
/>
</MainCard>
);
};

export default UserAuthorityCard;

+ 59
- 0
src/pages/pnspsUserDetailPage/UserGroupCard.js Bestand weergeven

@@ -0,0 +1,59 @@
// material-ui
import {
Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import * as React from "react";
import {useEffect, useState} from "react";
import LoadingComponent from "../extra-pages/LoadingComponent";
import UserGroupTable from "./UserGroupTable";

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


const UserGroupCard = ({isCollectData, updateUserGroupList,userData}) => {
const [currentUserData, setCurrentUserData] = React.useState({});
const [onReady, setOnReady] = useState(false);
const [selectedRow, setSelectedRow] = useState([]);

useEffect(() => {
//if user data from parent are not null
if (Object.keys(userData).length > 0 && userData !== undefined) {
setCurrentUserData(userData.data);
setSelectedRow(userData.groupIds);
}
}, [userData]);

useEffect(() => {
//if state data are ready and assign to different field
if (Object.keys(userData).length > 0 &&currentUserData !== undefined) {
setOnReady(true);
}
}, [currentUserData]);

useEffect(() => {
//upload latest data to parent
updateUserGroupList(selectedRow);
}, [isCollectData]);


return (
!onReady ?
<LoadingComponent/>
:
<MainCard elevation={0}
border={false}
content={false}
>
<Typography variant="h5" sx={{mt: 3, ml: 3}}>
Group(s)
</Typography>
<UserGroupTable
userGroup={userData.groupIds}
setSelectedRow={setSelectedRow}
/>
</MainCard>
);
};

export default UserGroupCard;

+ 76
- 0
src/pages/pnspsUserDetailPage/UserGroupTable.js Bestand weergeven

@@ -0,0 +1,76 @@
// material-ui
import {
DataGrid,
} from "@mui/x-data-grid";
import {useEffect, useState} from "react";
import axios from "axios";
import {apiPath} from "../../auth/utils";
import LoadingComponent from "../extra-pages/LoadingComponent";
import * as React from "react";
import {GET_GROUP_COMBO_PATH} from "../../utils/ApiPathConst";

// ==============================|| EVENT TABLE ||============================== //

export default function UserGroupTable({setSelectedRow, userGroup}) {
const [groupData, setGroupData] = useState([]);
const [onReady, setOnReady] = useState(false);
const [currentSelectedRow, setCurrentSelectedRow] = useState(userGroup);

useEffect(() => {
axios.get(`${apiPath}${GET_GROUP_COMBO_PATH}`)
.then((response) => {
if (response.status === 200) {
setGroupData(response.data.records);
}
})
.catch(error => {
console.log(error);
return false;
});
}, []);

useEffect(() => {
//if state data are ready and assign to different field
console.log(groupData.length)
if (groupData !== "" && groupData !== undefined) {
setOnReady(true);
}
}, [groupData]);

const columns = [
{
id: 'group',
field: 'name',
headerName: 'Group',
flex: 1,
editable: true,
},
];

return (
!onReady ?
<LoadingComponent/>
:
<div style={{height: '100%', width: '100%'}}>
<DataGrid
rows={groupData}
columns={columns}
editMode="row"
initialState={{
pagination: {
paginationModel: {page: 0, pageSize: 3},
},
}}
pageSizeOptions={[3, 5]}
checkboxSelection
rowSelectionModel={currentSelectedRow}
onRowSelectionModelChange={(ids) => {
console.log(ids);
setSelectedRow(ids);
setCurrentSelectedRow(ids);
}}
autoHeight
/>
</div>
);
}

+ 321
- 0
src/pages/pnspsUserDetailPage/UserInformationCard.js Bestand weergeven

@@ -0,0 +1,321 @@
// material-ui
import {
Grid, TextField, Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import * as React from "react";
import {useForm} from "react-hook-form";
import Autocomplete from "@mui/material/Autocomplete";
import {
subDivision1,
subDivision2,
subDivision3,
subDivision4,
subDivision5,
subDivision6
} from "../pnspsUserSettingPage/DummyComboRecord";
import {useEffect, useState} from "react";
import Checkbox from "@mui/material/Checkbox";
import LoadingComponent from "../extra-pages/LoadingComponent";
//import {useParams} from "react-router-dom";

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


const subDivisionArray = [
...subDivision1,
...subDivision2,
...subDivision3,
...subDivision4,
...subDivision5,
...subDivision6
];


const UserInformationCard = ({isCollectData, updateUserObject,userData}) => {
//const params = useParams();
const [currentUserData, setCurrentUserData] = React.useState({});
const [subDivision, setSubDivision] = useState(null);
const [locked, setLocked] = useState(false);
const [isLotusNoteUser, setIsLotusNoteUser] = useState(false);
const [lotusNoteUserList, setLotusNoteUserList] = useState([])
const [selectedLotusUser, setSelectedLotusUser] = useState(null);

const [onReady, setOnReady] = useState(false);
const {register, getValues} = useForm()

useEffect(() => {
//TODO: Get lotus note user list
setLotusNoteUserList([
{
key: 1,
label: "user01",
account: "user123456"
},
{
key: 2,
label: "user02",
account: "userabcde1"
},
{
key: 3,
label: "user03",
account: "user2001"
},
{
key: 4,
label: "user04",
account: "user2000"
},
{
key: 5,
label: "user05",
account: "user1999"
},
])
}, []);

useEffect(() => {
//if user data from parent are not null
if (Object.keys(userData).length > 0 && userData !== undefined) {
setCurrentUserData(userData.data);
}
}, [userData]);

useEffect(() => {
//if state data are ready and assign to different field
if (Object.keys(userData).length > 0 &&currentUserData !== undefined) {
setLocked(currentUserData.locked);
setOnReady(true);
}
}, [currentUserData]);

useEffect(() => {
//upload latest data to parent
const values = getValues();
const objectData ={
...values,
selectedLotusUser: selectedLotusUser,
subDivision: subDivision,
locked: locked,
}
updateUserObject(objectData);
}, [isCollectData]);


return (
!onReady ?
<LoadingComponent/>
:
<MainCard elevation={0}
border={false}
content={false}
>
<Typography variant="h5" sx={{mt: 3, ml: 3, mb: 1}}>
Information
</Typography>


<form>
<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Lotus Note User:
</Grid>

<Grid item xs={1} s={1} md={1} lg={1}>
<Checkbox
checked={isLotusNoteUser}
onChange={(event) => setIsLotusNoteUser(event.target.checked)}
name="isLotusNoteUser"
color="primary"
size="small"
/>
</Grid>

<Grid item xs={6} s={6} md={6} lg={5}>
<Autocomplete
disablePortal
id="lotus-note-combo"
value={selectedLotusUser === null ? null : selectedLotusUser}
options={lotusNoteUserList}
disabled={!isLotusNoteUser}
onChange={(event, newValue) => {
setSelectedLotusUser(newValue);
}}
renderInput={(params) => <TextField {...params} />}
/>
</Grid>
</Grid>
</Grid>

<Grid container>
<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Username:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<TextField
fullWidth
{...register("userName",
{
value: currentUserData.username,
})}
id='username'
disabled
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Password:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<TextField
fullWidth
{...register("password")}
id='password'
disabled
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Full Name:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<TextField
fullWidth
{...register("fullName",
{
value: currentUserData.fullname,
})}
id='fullName'
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Post:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<TextField
fullWidth
{...register("post",
{
value: currentUserData.post,
})}
id='post'
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Sub-Division:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<Autocomplete
disablePortal
id="sub-division-combo"
value={subDivision === null ? null : subDivision}
options={subDivisionArray}
onChange={(event, newValue) => {
setSubDivision(newValue);
}}
renderInput={(params) => <TextField {...params} />}
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Email:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<TextField
fullWidth
{...register("email",
{
value: currentUserData.email,
})}
id='email'
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container alignItems={"center"}>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Phone:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<TextField
fullWidth
{...register("phone1",
{
value: currentUserData.phone1,
})}
id='phone1'
/>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}>
<Grid container>
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}>
Locked:
</Grid>

<Grid item xs={7} s={7} md={7} lg={6}>
<Checkbox
checked={locked}
onChange={(event) => setLocked(event.target.checked)}
name="checked"
color="primary"
size="small"
/>
</Grid>
</Grid>
</Grid>

</Grid>

</form>
</MainCard>
);
};

export default UserInformationCard;

+ 135
- 0
src/pages/pnspsUserDetailPage/index.js Bestand weergeven

@@ -0,0 +1,135 @@
// material-ui
import {
Button,
Grid, Typography
} from '@mui/material';
import {useEffect, useState} from "react";
import * as React from "react";
import axios from "axios";
import {apiPath} from "../../auth/utils";
import {useParams} from "react-router-dom";
import UserInformationCard from "./UserInformationCard";
import LoadingComponent from "../extra-pages/LoadingComponent";
import UserGroupCard from "./UserGroupCard";
import UserAuthorityCard from "./UserAuthorityCard";
import {GET_USER_PATH} from "../../utils/ApiPathConst";

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


const UserMaintainPage = () => {
const params = useParams();
const [userData, setUserData] = React.useState({});
const [onReady, setOnReady] = useState(false);
const [isCollectData, setIsCollectData] = useState(false);
const [editedCustomerData, setEditedCustomerData] = useState({});
const [userGroupData,setUserGroupData] = useState([]);
const [userAuthData,setUserAuthData] = useState([]);
const [userConfirm, setUserConfirm] = useState(false);

function updateUserObject(userData) {
setEditedCustomerData(userData);
}

function updateUserGroupList(userGroupData){
setUserGroupData(userGroupData);
}

function updateUserAuthList(userAuthData){
setUserAuthData(userAuthData);
}

const submitData = () => {
setUserConfirm(true);
setIsCollectData(!isCollectData);
}

useEffect(() => {

axios.get(`${apiPath}${GET_USER_PATH}/${params.id}`)
.then((response) => {
if (response.status === 200) {
setUserData(response.data);
}
})
.catch(error => {
console.log(error);
return false;
});
}, []);

useEffect(() => {
setOnReady(true);
}, [userData]);

useEffect(() => {
if(userConfirm && onReady){
console.log("update in parents");
console.log(editedCustomerData);
console.log(userGroupData);
console.log(userAuthData);
}
setUserConfirm(false);
}, [editedCustomerData,userGroupData,userAuthData]);

return (
!onReady ?
<LoadingComponent/>
:
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
<Grid item xs={12} sx={{mb: -2.25}}>
<Typography variant="h5">Maintain User</Typography>
</Grid>
{/*col 1*/}
<Grid item xs={12} md={5} lg={5}>
<Grid container>
<Grid item xs={12} md={12} lg={12}>
<UserInformationCard
updateUserObject={updateUserObject}
userData={userData}
isCollectData={isCollectData}
/>
</Grid>

<Grid item xs={12} md={12} lg={12} sx={{mt: 3}}>
<UserGroupCard
updateUserGroupList={updateUserGroupList}
userData={userData}
isCollectData={isCollectData}
/>
</Grid>
</Grid>
</Grid>
{/*col 2*/}
<Grid item xs={12} md={7} lg={7}>
<UserAuthorityCard
updateUserAuthList={updateUserAuthList}
userData={userData}
isCollectData={isCollectData}
/>
</Grid>

{/*bottom button*/}
<Grid item s={12} md={12} lg={12} sx={{mb: 3}} alignItems={"end"} justifyContent="center">
<Grid container maxWidth justifyContent="flex-end">
<Grid item sx={{ml: 3, mr: 3}}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}
onClick={submitData}
>
Save User
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
);
};

export default UserMaintainPage;

+ 93
- 0
src/pages/pnspsUserGroupSearchPage/UserGroupSearchForm.js Bestand weergeven

@@ -0,0 +1,93 @@
// material-ui
import {
Button,
CardContent,
Grid, TextField,
} from '@mui/material';
import MainCard from "../../components/MainCard";
import {useForm} from "react-hook-form";
import * as React from "react";
// ==============================|| DASHBOARD - DEFAULT ||============================== //

const UserGroupSearchForm = ({applySearch}) => {

const { reset, register, handleSubmit } = useForm()
const onSubmit = (data) => {
console.log(data)
applySearch(data);
};

function resetForm(){
reset();
}

return (
<MainCard xs={12} md={12} lg={12}
border={false}
content={false}>

<form onSubmit={handleSubmit(onSubmit)}>
{/*row 1*/}
<CardContent sx={{ px: 2.5, pt: 3 }}>
<Grid item justifyContent="space-between" alignItems="center">
Search Form
</Grid>
</CardContent>

{/*row 2*/}
<Grid container alignItems={"center"}>
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("userGroupName")}
id='userGroupName'
label="User Group Name"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("userGroupDescription")}
id="userGroupDescription"
label="User Group Description"
/>
</Grid>
</Grid>


{/*last row*/}
<Grid container maxWidth justifyContent="flex-end">

<Grid item sx={{ml:3, mr:3, mb:3, mt:3}}>
<Button
size="large"
variant="contained"
onClick={resetForm}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Clear
</Button>
</Grid>

<Grid item sx={{ml:3, mr:3, mb:3, mt:3}}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Submit
</Button>
</Grid>
</Grid>
</form>
</MainCard>
);
};

export default UserGroupSearchForm;

+ 75
- 0
src/pages/pnspsUserGroupSearchPage/UserGroupTable.js Bestand weergeven

@@ -0,0 +1,75 @@
// material-ui
import * as React from 'react';
import {
DataGrid,
GridActionsCellItem,
} from "@mui/x-data-grid";
import EditIcon from '@mui/icons-material/Edit';
import {useEffect} from "react";
import {useNavigate} from "react-router-dom";
// ==============================|| EVENT TABLE ||============================== //

export default function UserGroupTable({recordList}) {
const [rows, setRows] = React.useState(recordList);
const [rowModesModel] = React.useState({});
const navigate = useNavigate()

useEffect(() => {
setRows(recordList);
}, [recordList]);

const handleEditClick = (id) => () => {
navigate('/userGroup/'+ id);
};

const columns = [
{
field: 'actions',
type: 'actions',
headerName: 'Actions',
width: 100,
cellClassName: 'actions',
getActions: ({id}) => {
return [
<GridActionsCellItem
key="OutSave"
icon={<EditIcon/>}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="primary"
/>]
},
},
{
id: 'groupName',
field: 'groupName',
headerName: 'User Group Name',
flex: 1,
},
{
id: 'description',
field: 'description',
headerName: 'User Group Description',
flex: 1,
},
];

return (
<div style={{height: 400, width: '100%'}}>
<DataGrid
rows={rows}
columns={columns}
editMode="row"
rowModesModel={rowModesModel}
initialState={{
pagination: {
paginationModel: {page: 0, pageSize: 10},
},
}}
pageSizeOptions={[10, 15, 20]}
autoHeight
/>
</div>
);
}

+ 78
- 0
src/pages/pnspsUserGroupSearchPage/index.js Bestand weergeven

@@ -0,0 +1,78 @@
// material-ui
import {
Grid, Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import UserGroupSearchForm from "./UserGroupSearchForm";
import UserGroupTable from "./UserGroupTable";
import {useEffect, useState} from "react";

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



const UserGroupSearchPanel = () => {

const [record] = useState([]);
const [searchCriteria, setSearchCriteria] = useState({});
const [sortedRecord, setSortedRecord] = useState([]);

const filterSearchName = (array) => {
return array.filter((item) => item.name.toLowerCase().includes(searchCriteria.eventName));
};

const filterSearchType = (array) => {
return array.filter((item) => item.category.includes(searchCriteria.type));
};

function sortData(record){
let sortedRecord = record;
sortedRecord = filterSearchName(sortedRecord);
sortedRecord = filterSearchType(sortedRecord);
return sortedRecord;
}

function applySearch(input){
setSearchCriteria(input);
//console.log("Apply Search: ");
//console.log(input);
}

useEffect(() => {
//console.log(searchCriteria);
if(Object.keys(searchCriteria).length !== 0){
const tempSortedRecord = sortData(record);
console.log(tempSortedRecord);
setSortedRecord(tempSortedRecord);
}else{
setSortedRecord(record);
}
}, [searchCriteria]);

return (
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
<Grid item xs={12} sx={{mb: -2.25}}>
<Typography variant="h5">View User Group</Typography>
</Grid>
{/*row 1*/}
<Grid item xs={12} md={12} lg={12}>
<UserGroupSearchForm applySearch={applySearch}/>
</Grid>
{/*row 2*/}
<Grid item xs={12} md={12} lg={12}>
<MainCard elevation={0}
border={false}
content={false}
>
<UserGroupTable
recordList={sortedRecord}
/>
</MainCard>
</Grid>

</Grid>

);
};

export default UserGroupSearchPanel;

+ 229
- 0
src/pages/pnspsUserSearchPage/UserSearchForm.js Bestand weergeven

@@ -0,0 +1,229 @@
// material-ui
import {
Button,
CardContent, FormControlLabel,
Grid, TextField,
Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import {useForm} from "react-hook-form";

import {useEffect, useState} from "react";
import Autocomplete from '@mui/material/Autocomplete';
import {
subDivision1,
subDivision2,
subDivision3,
subDivision4,
subDivision5,
subDivision6
} from "pages/pnspsUserSettingPage/DummyComboRecord";
import Checkbox from "@mui/material/Checkbox";
import * as React from "react";
// ==============================|| DASHBOARD - DEFAULT ||============================== //

const subDivisionArray =[
...subDivision1,
...subDivision2,
...subDivision3,
...subDivision4,
...subDivision5,
...subDivision6
];

const UserSearchForm = ({applySearch}) => {

const [type, setType] = useState([]);
const [division, setDivision] = useState(null);
const [subDivision, setSubDivision] = useState(null);
const [isLotusNoteUser, setIsLotusNoteUser] = useState(false);
const [locked, setLocked] = useState(false);


const { reset, register, handleSubmit } = useForm()
const onSubmit = (data) => {

let typeArray = [];

for(let i =0; i < type.length; i++){
typeArray.push(type[i].label);
}

const temp = {
username: data.userName,
fullName: data.fullName,
post: data.post,
subDivision: subDivision,
email: data.email,
phone: data.phone,
isLotusNoteUser: isLotusNoteUser,
locked: locked,
};
applySearch(temp);
};

useEffect(() => {
if(division != null){
setSubDivision(subDivisionArray[division.type-1][0]);
}

}, [division]);

function resetForm(){
setType([]);
setDivision(null);
setSubDivision(null);
setIsLotusNoteUser(false);
setLocked(false);
reset();
}

return (
<MainCard xs={12} md={12} lg={12}
border={false}
content={false}>

<form onSubmit={handleSubmit(onSubmit)}>
{/*row 1*/}
<CardContent sx={{ px: 2.5, pt: 3 }}>
<Grid item justifyContent="space-between" alignItems="center">
Search Form
</Grid>
</CardContent>

{/*row 2*/}
<Grid container alignItems={"center"}>
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("userName")}
id='userName'
label="Username"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("fullName")}
id="fullName"
label="Full Name"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("post")}
id="post"
label="Post"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<Autocomplete
disablePortal
id="sub-division-combo"
value={subDivision === null? null : subDivision}
options={subDivisionArray}
onChange={(event, newValue) => {
setSubDivision(newValue);
}}
renderInput={(params) => <TextField {...params} label="Sub-Division" />}
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("email")}
id="email"
label="Email"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("phone")}
id="phone"
label="Phone"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<FormControlLabel
control={
<Checkbox
checked={isLotusNoteUser}
onChange={(event) => setIsLotusNoteUser(event.target.checked)}
name="checked"
color="primary"
size="small"
/>
}
label={<Typography variant="h6">Lotus Notes User</Typography>}
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<FormControlLabel
control={
<Checkbox
checked={locked}
onChange={(event) => setLocked(event.target.checked)}
name="checked"
color="primary"
size="small"
/>
}
label={<Typography variant="h6">Locked</Typography>}
/>
</Grid>
{/*<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>*/}
{/* <TextField*/}
{/* fullWidth*/}
{/* {...register("subDivisionId")}*/}
{/* id="subDivision"*/}
{/* label="Sub-Division"*/}
{/* />*/}
{/*</Grid>*/}

</Grid>


{/*last row*/}
<Grid container maxWidth justifyContent="flex-end">

<Grid item sx={{ml:3, mr:3, mb:3, mt:3}}>
<Button
size="large"
variant="contained"
onClick={resetForm}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Clear
</Button>
</Grid>

<Grid item sx={{ml:3, mr:3, mb:3, mt:3}}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Submit
</Button>
</Grid>
</Grid>
</form>
</MainCard>
);
};

export default UserSearchForm;

+ 137
- 0
src/pages/pnspsUserSearchPage/UserTable.js Bestand weergeven

@@ -0,0 +1,137 @@
// material-ui
import * as React from 'react';
import {
DataGrid,
GridActionsCellItem,
} from "@mui/x-data-grid";
import EditIcon from '@mui/icons-material/Edit';
import {useEffect} from "react";
import {useNavigate} from "react-router-dom";
import { useTheme } from '@mui/material/styles';
import Checkbox from '@mui/material/Checkbox';
// ==============================|| EVENT TABLE ||============================== //

export default function UserTable({recordList}) {
const [rows, setRows] = React.useState(recordList);
const [rowModesModel] = React.useState({});
const theme = useTheme();

const navigate = useNavigate()

useEffect(() => {
setRows(recordList);
}, [recordList]);

const handleEditClick = (id) => () => {
navigate('/user/'+ id);
};

const columns = [
{
field: 'actions',
type: 'actions',
headerName: 'Actions',
width: 100,
cellClassName: 'actions',
getActions: ({id}) => {
return [
<GridActionsCellItem
key="OutSave"
icon={<EditIcon/>}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="primary"
/>]
},
},
{
id: 'username',
field: 'username',
headerName: 'User Name',
flex: 1,
},
{
id: 'name',
field: 'name',
headerName: 'Full Name',
flex: 1,
},
{
id: 'post',
field: 'post',
headerName: 'Post',
flex: 1,
},
{
id: 'email',
field: 'email',
headerName: 'Email',
flex: 1,
},
{
id: 'subDivisionId',
field: 'subDivisionId',
//type: 'date',
//sortable: false,
headerName: 'Sub-Division',
flex: 1,
},
{
id: 'lotusNotesUser',
field: 'lotusNotesUser',
type: 'bool',
headerName: 'Lotus Notes User',
flex: 1,
renderCell: (params) => {
return (
<Checkbox
theme={theme}
key="locked"
checked={params.row.lotusNotesUser}
color="primary"
size="small"
//onChange={handleChange}
/>
);
},
},
{
id: 'locked',
field: 'locked',
type: 'bool',
headerName: 'Locked',
flex: 1,
renderCell: (params) => {
return (
<Checkbox
theme={theme}
key="locked"
checked={params.row.locked}
color="primary"
size="small"
//onChange={handleChange}
/>
);
},
},
];

return (
<div style={{height: 400, width: '100%'}}>
<DataGrid
rows={rows}
columns={columns}
editMode="row"
rowModesModel={rowModesModel}
initialState={{
pagination: {
paginationModel: {page: 0, pageSize: 5},
},
}}
pageSizeOptions={[5, 10]}
autoHeight
/>
</div>
);
}

+ 84
- 0
src/pages/pnspsUserSearchPage/index.js Bestand weergeven

@@ -0,0 +1,84 @@
// material-ui
import {
Grid, Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import SearchForm from "./UserSearchForm";
import EventTable from "./UserTable";
import {useEffect, useState} from "react";
import axios from "axios";
import {apiPath} from "../../auth/utils";
import {GET_USER_PATH} from "../../utils/ApiPathConst";
import * as React from "react";
import LoadingComponent from "../extra-pages/LoadingComponent";

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

const UserSettingPage = () => {

const [record,setRecord] = useState([]);
const [searchCriteria, setSearchCriteria] = useState({});
const [onReady, setOnReady] = useState(false);

useEffect(() => {
getUserList();
}, []);

useEffect(() => {
setOnReady(true);
}, [record]);

useEffect(() => {
getUserList();
}, [searchCriteria]);

function getUserList(){
axios.get(`${apiPath}${GET_USER_PATH}`,
{params: searchCriteria}
)
.then((response) => {
if (response.status === 200) {
setRecord(response.data);
}
})
.catch(error => {
console.log(error);
return false;
});
}

function applySearch(input) {
setSearchCriteria(input);
}

return (
!onReady ?
<LoadingComponent/>
:
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
<Grid item xs={12} sx={{mb: -2.25}}>
<Typography variant="h5">View User</Typography>
</Grid>

{/*row 1*/}
<Grid item xs={12} md={12} lg={12}>
<SearchForm applySearch={applySearch}/>
</Grid>
{/*row 2*/}
<Grid item xs={12} md={12} lg={12}>
<MainCard elevation={0}
border={false}
content={false}
>
<EventTable
recordList={record}
/>
</MainCard>
</Grid>

</Grid>

);
};

export default UserSettingPage;

+ 77
- 0
src/pages/pnspsUserSettingPage/DummyComboRecord.js Bestand weergeven

@@ -0,0 +1,77 @@
export const eventType = [
{label: '同心', type: 1},
{label: '創新', type: 2},
{label: '惠民', type: 3},
{label: '傳承', type: 3},
];

export const divisionType = [
{key: 1, label: 'Railways Branch', type: 1},
{key: 2, label: 'Electricity and Energy Efficiency Branch ', type: 2},
{key: 3, label: 'Gas and General Legislation Branch', type: 3},
{key: 4, label: 'Engineering Services Branch 1', type: 4},
{key: 5, label: 'Engineering Services Branch 2', type: 5},
{key: 6, label: 'Engineering Services Branch 3', type: 6},
];

export const subDivision1 = [
{key: 1, label: 'Sub Division 1 of Railways Branch', type: 1},
{key: 2, label: 'Sub Division 2 of Railways Branch', type: 2},
{key: 3, label: 'Sub Division 3 of Railways Branch', type: 3},
{key: 4, label: 'Sub Division 4 of Railways Branch', type: 4},
];

export const subDivision2 = [
{key: 1, label: 'Sub Division 1 of Electricity and Energy Efficiency Branch', type: 1},
{key: 2, label: 'Sub Division 2 of Electricity and Energy Efficiency Branch', type: 2},
{key: 3, label: 'Sub Division 3 of Electricity and Energy Efficiency Branch', type: 3},
];

export const subDivision3 = [
{key: 1, label: 'Sub Division 1 of Gas and General Legislation Branch', type: 1},
{key: 2, label: 'Sub Division 2 of Gas and General Legislation Branch', type: 2},
{key: 3, label: 'Sub Division 3 of Gas and General Legislation Branch', type: 3},
];

export const subDivision4 = [
{key: 1, label: 'Sub Division 1 of Engineering Services Branch 1', type: 1},
{key: 2, label: 'Sub Division 2 of Engineering Services Branch 1', type: 2},
{key: 3, label: 'Sub Division 3 of Engineering Services Branch 1', type: 3},
{key: 4, label: 'Sub Division 4 of Engineering Services Branch 1', type: 4},
];

export const subDivision5 = [
{key: 1, label: 'Sub Division 1 of Engineering Services Branch 2', type: 1},
{key: 2, label: 'Sub Division 2 of Engineering Services Branch 2', type: 2},
{key: 3, label: 'Sub Division 3 of Engineering Services Branch 2', type: 3},
];

export const subDivision6 = [
{key: 1, label: 'Sub Division 1 of Engineering Services Branch 3', type: 1},
{key: 2, label: 'Sub Division 2 of Engineering Services Branch 3', type: 2},
{key: 3, label: 'Sub Division 3 of Engineering Services Branch 3', type: 3},
];

export const tableRecord = [
{trackingNo: 84564564, name: 'Camera', fat: 40, carbs: 2, protein: 4057},
{trackingNo: 98764564, name: 'Laptop', fat: 300, carbs: 0, protein: 180139},
{trackingNo: 98756325, name: 'Mobile', fat: 355, carbs: 1, protein: 90989},
{trackingNo: 98652366, name: 'Handset', fat: 50, carbs: 1, protein: 10239},
{trackingNo: 13286564, name: 'Computer', fat: 100, carbs: 1, protein: 8334},
{trackingNo: 86739658, name: 'TV', fat: 99, carbs: 0, protein: 410780},
{trackingNo: 13256498, name: 'Keyboard', fat: 125, carbs: 2, protein: 70999},
{trackingNo: 98753263, name: 'Mouse', fat: 89, carbs: 2, protein: 10570},
{trackingNo: 98753275, name: 'Desktop', fat: 185, carbs: 1, protein: 98063},
{trackingNo: 98753291, name: 'Chair', fat: 100, carbs: 0, protein: 14001},
];

export const tableRecordTemp = [
{id:1 ,eventNo: 84564564, eventDate:"2022-03-20" , category: '同心', hrmPlan: 'Visionary Leadership', name: 'HKMA Best Annual Reports Awards - The Electrical and Mechanical Services Department Annual Report 2020/21 - Certificate of Excellence'},
{id:2 ,eventNo: 98764564, eventDate:"2022-05-12" , category: '同心', hrmPlan: 'Visionary Leadership', name: 'HKMA Best Annual Reports Awards - The Electrical and Mechanical Services Department Annual Report 2020/21- Best New Entry'},
{id:3 ,eventNo: 98756325, eventDate:"2022-06-04" , category: '創新', hrmPlan: 'Visionary Leadership', name: '19th Hong Kong Occupational Safety and Health Award - Gold Award - The Virtual Reality-based Lift Maintenance training programme'},
{id:4 ,eventNo: 98652366, eventDate:"2022-08-16" , category: '創新', hrmPlan: 'Visionary Leadership', name: 'BIM Achievement 2022 - BIM Organisations 2022'},
{id:5 ,eventNo: 13286564, eventDate:"2022-09-30" , category: '惠民', hrmPlan: 'Visionary Leadership', name: 'Civil Service Outstanding Service Award Scheme 2022 - Excellence in Team Collaboration (Internal Service) - Innovation Facilitator'},
{id:6 ,eventNo: 86739658, eventDate:"2022-10-25" , category: '惠民', hrmPlan: 'Visionary Leadership', name: 'Civil Service Outstanding Service Award Scheme 2022 - Excellence in Team Collaboration (Management of Crisis) - E&M 100 - CHT Rescue Team'},
{id:7 ,eventNo: 13256498, eventDate:"2022-11-21" , category: '傳承', hrmPlan: 'Visionary Leadership', name: '11th Guangzhou/Hong Kong/Macao/Chengdu Youth Skills Competition - Three TTs from the EMSD got the top three prizes in the Electrical Installations trade of the Hong Kong Region qualifying competition'},
{id:8 ,eventNo: 98753263, eventDate:"2022-12-31" , category: '傳承', hrmPlan: 'Visionary Leadership', name: 'VTC 2021 Outstanding Apprentices Scheme - Outstanding Apprentice - Mr. LEE King (TTII)'},
];

+ 232
- 0
src/pages/pnspsUserSettingPage/UserSearchForm.js Bestand weergeven

@@ -0,0 +1,232 @@
// material-ui
import {
Button,
CardContent, FormControlLabel,
Grid, TextField,
Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import {useForm} from "react-hook-form";

import dayjs from "dayjs";
import {useEffect, useState} from "react";
import Autocomplete from '@mui/material/Autocomplete';
import {
subDivision1,
subDivision2,
subDivision3,
subDivision4,
subDivision5,
subDivision6
} from "pages/pnspsUserSettingPage/DummyComboRecord";
import Checkbox from "@mui/material/Checkbox";
import * as React from "react";
// ==============================|| DASHBOARD - DEFAULT ||============================== //

const subDivisionArray =[
...subDivision1,
...subDivision2,
...subDivision3,
...subDivision4,
...subDivision5,
...subDivision6
];

const UserSearchForm = ({applySearch}) => {

const [value, setValue] = useState();
const [type, setType] = useState([]);
const [division, setDivision] = useState(null);
const [subDivision, setSubDivision] = useState(null);
const [isLotusNoteUser, setIsLotusNoteUser] = useState(false);
const [locked, setLocked] = useState(false);


const { reset, register, handleSubmit } = useForm()
const onSubmit = (data) => {

let typeArray = [];

for(let i =0; i < type.length; i++){
typeArray.push(type[i].label);
}

const temp = {
eventName: data.eventName,
eventOrganization: data.eventOrganization,
eventRegion: data.eventRegion,
eventDescription: data.eventDescription,
type: typeArray,
division: division,
subDivision: subDivision,
selectedDate: dayjs(value).format("MM/DD/YYYY")
};
applySearch(temp);
};

useEffect(() => {
if(division != null){
setSubDivision(subDivisionArray[division.type-1][0]);
}

}, [division]);

function resetForm(){
setValue(new Date().toDateString());
setType([]);
setDivision(null);
setSubDivision(null);
setIsLotusNoteUser(false);
setLocked(false);
reset();
}

return (
<MainCard xs={12} md={12} lg={12}
border={false}
content={false}>

<form onSubmit={handleSubmit(onSubmit)}>
{/*row 1*/}
<CardContent sx={{ px: 2.5, pt: 3 }}>
<Grid item justifyContent="space-between" alignItems="center">
Search Form
</Grid>
</CardContent>

{/*row 2*/}
<Grid container alignItems={"center"}>
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("userName")}
id='userName'
label="Username"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("fullName")}
id="fullName"
label="Full Name"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("post")}
id="post"
label="Post"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<Autocomplete
disablePortal
id="sub-division-combo"
value={subDivision === null? null : subDivision}
options={subDivisionArray}
onChange={(event, newValue) => {
setSubDivision(newValue);
}}
renderInput={(params) => <TextField {...params} label="Sub-Division" />}
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("email")}
id="email"
label="Email"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<TextField
fullWidth
{...register("phone")}
id="phone"
label="Phone"
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<FormControlLabel
control={
<Checkbox
checked={isLotusNoteUser}
onChange={(event) => setIsLotusNoteUser(event.target.checked)}
name="checked"
color="primary"
size="small"
/>
}
label={<Typography variant="h6">Lotus Notes User</Typography>}
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
<FormControlLabel
control={
<Checkbox
checked={locked}
onChange={(event) => setLocked(event.target.checked)}
name="checked"
color="primary"
size="small"
/>
}
label={<Typography variant="h6">Locked</Typography>}
/>
</Grid>
{/*<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>*/}
{/* <TextField*/}
{/* fullWidth*/}
{/* {...register("subDivisionId")}*/}
{/* id="subDivision"*/}
{/* label="Sub-Division"*/}
{/* />*/}
{/*</Grid>*/}

</Grid>


{/*last row*/}
<Grid container maxWidth justifyContent="flex-end">

<Grid item sx={{ml:3, mr:3, mb:3, mt:3}}>
<Button
size="large"
variant="contained"
onClick={resetForm}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Clear
</Button>
</Grid>

<Grid item sx={{ml:3, mr:3, mb:3, mt:3}}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
Submit
</Button>
</Grid>
</Grid>
</form>
</MainCard>
);
};

export default UserSearchForm;

+ 137
- 0
src/pages/pnspsUserSettingPage/UserTable.js Bestand weergeven

@@ -0,0 +1,137 @@
// material-ui
import * as React from 'react';
import {
DataGrid,
GridActionsCellItem,
} from "@mui/x-data-grid";
import EditIcon from '@mui/icons-material/Edit';
import {useEffect} from "react";
import {useNavigate} from "react-router-dom";
import { useTheme } from '@mui/material/styles';
import Checkbox from '@mui/material/Checkbox';
// ==============================|| EVENT TABLE ||============================== //

export default function UserTable({recordList}) {
const [rows, setRows] = React.useState(recordList);
const [rowModesModel] = React.useState({});
const theme = useTheme();

const navigate = useNavigate()

useEffect(() => {
setRows(recordList);
}, [recordList]);

const handleEditClick = (id) => () => {
navigate('/user/'+ id);
};

const columns = [
{
field: 'actions',
type: 'actions',
headerName: 'Actions',
width: 100,
cellClassName: 'actions',
getActions: ({id}) => {
return [
<GridActionsCellItem
key="OutSave"
icon={<EditIcon/>}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="primary"
/>]
},
},
{
id: 'username',
field: 'username',
headerName: 'User Name',
flex: 1,
},
{
id: 'name',
field: 'name',
headerName: 'Full Name',
flex: 1,
},
{
id: 'post',
field: 'post',
headerName: 'Post',
flex: 1,
},
{
id: 'email',
field: 'email',
headerName: 'Email',
flex: 1,
},
{
id: 'subDivisionId',
field: 'subDivisionId',
//type: 'date',
//sortable: false,
headerName: 'Sub-Division',
flex: 1,
},
{
id: 'lotusNotesUser',
field: 'lotusNotesUser',
type: 'bool',
headerName: 'Lotus Notes User',
flex: 1,
renderCell: (params) => {
return (
<Checkbox
theme={theme}
key="locked"
checked={params.row.lotusNotesUser}
color="primary"
size="small"
//onChange={handleChange}
/>
);
},
},
{
id: 'locked',
field: 'locked',
type: 'bool',
headerName: 'Locked',
flex: 1,
renderCell: (params) => {
return (
<Checkbox
theme={theme}
key="locked"
checked={params.row.locked}
color="primary"
size="small"
//onChange={handleChange}
/>
);
},
},
];

return (
<div style={{height: 400, width: '100%'}}>
<DataGrid
rows={rows}
columns={columns}
editMode="row"
rowModesModel={rowModesModel}
initialState={{
pagination: {
paginationModel: {page: 0, pageSize: 5},
},
}}
pageSizeOptions={[5, 10]}
autoHeight
/>
</div>
);
}

+ 89
- 0
src/pages/pnspsUserSettingPage/index.js Bestand weergeven

@@ -0,0 +1,89 @@
// material-ui
import {
Grid
} from '@mui/material';
import MainCard from "../../components/MainCard";
import SearchForm from "./UserSearchForm";
import EventTable from "./UserTable";
import {useEffect, useState} from "react";
import axios from "axios";
import {apiPath} from "../../auth/utils";
import {GET_USER_PATH} from "../../utils/ApiPathConst";

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


const UserSettingPage = () => {

const [record,setRecord] = useState([]);
const [searchCriteria, setSearchCriteria] = useState({});
const [sortedRecord, setSortedRecord] = useState([]);

useEffect(() => {
axios.get(`${apiPath}${GET_USER_PATH}`)
.then((response) => {
if (response.status === 200) {
setRecord(response.data);
setSortedRecord(response.data);
}
})
.catch(error => {
console.log(error);
return false;
});
}, [])

const filterSearchName = (array) => {
return array.filter((item) => item.name.toLowerCase().includes(searchCriteria.eventName));
};

const filterSearchType = (array) => {
return array.filter((item) => item.category.includes(searchCriteria.type));
};

function sortData(record) {
let sortedRecord = record;
sortedRecord = filterSearchName(sortedRecord);
sortedRecord = filterSearchType(sortedRecord);
return sortedRecord;
}

function applySearch(input) {
setSearchCriteria(input);
}

useEffect(() => {
//console.log(searchCriteria);
if (Object.keys(searchCriteria).length !== 0) {
const tempSortedRecord = sortData(record);
console.log(tempSortedRecord);
setSortedRecord(tempSortedRecord);
} else {
setSortedRecord(record);
}
}, [searchCriteria]);

return (
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
{/*row 1*/}
<Grid item xs={12} md={12} lg={12}>
<SearchForm applySearch={applySearch}/>
</Grid>
{/*row 2*/}
<Grid item xs={12} md={12} lg={12}>
<MainCard elevation={0}
border={false}
content={false}
>
<EventTable
recordList={sortedRecord}
/>
</MainCard>
</Grid>

</Grid>

);
};

export default UserSettingPage;

+ 0
- 5
src/routes/MainRoutes.js Bestand weergeven

@@ -6,7 +6,6 @@ import MainLayout from 'layout/MainLayout';

// render - dashboard
const DashboardDefault = Loadable(lazy(() => import('pages/dashboard')));
const ARSDashboard = Loadable(lazy(() => import('pages/arsdashboard')));

// render - sample page
const SamplePage = Loadable(lazy(() => import('pages/extra-pages/SamplePage')));
@@ -27,10 +26,6 @@ const MainRoutes = {
path: '/',
element: <DashboardDefault />
},
{
path: '/arsDashboard',
element: <ARSDashboard />
},
{
path: 'color',
element: <Color />


+ 48
- 0
src/routes/SettingRoutes.js Bestand weergeven

@@ -0,0 +1,48 @@
import { lazy } from 'react';

// project import
import Loadable from 'components/Loadable';
import MainLayout from "../layout/MainLayout";

// render - login
const SettingPage = Loadable(lazy(() => import('pages/pnspsSettingPage')));
const PasswordPolicyPage = Loadable(lazy(()=> import('pages/pnspsPasswordPolicyPage')))
const UserSettingPage = Loadable(lazy(()=>import ('pages/pnspsUserSettingPage/')));
const UserGroupSearchPage = Loadable(lazy(() => import('pages/pnspsUserGroupSearchPage')));
const UserSearchPage = Loadable(lazy(()=>import ('pages/pnspsUserSearchPage')));
const UserMaintainPage = Loadable(lazy(() => import('pages/pnspsUserDetailPage')));

// ==============================|| AUTH ROUTING ||============================== //

const SettingRoutes = {
path: '/',
element: <MainLayout />,
children: [
{
path: 'usergroupSearchview',
element: <UserGroupSearchPage />
},
{
path: '/user/:id',
element: <UserMaintainPage />
},
{
path: 'userSearchview',
element: <UserSearchPage />
},
{
path: 'usersetting',
element: <UserSettingPage />
},
{
path: 'setting',
element: <SettingPage />
},
{
path: 'passwordpolicy',
element: <PasswordPolicyPage />
}
]
};

export default SettingRoutes;

+ 3
- 1
src/routes/index.js Bestand weergeven

@@ -9,6 +9,7 @@ import {handleLogoutFunction,
setupAxiosInterceptors,
isTokenValid} from "../auth";
import {useNavigate} from "react-router-dom";
import SettingRoutes from './SettingRoutes';
// ==============================|| ROUTING RENDER ||============================== //

export default function ThemeRoutes() {
@@ -41,7 +42,8 @@ export default function ThemeRoutes() {
]
},
LoginRoutes,
MainRoutes
MainRoutes,
SettingRoutes
]);
//return useRoutes([MainRoutes, LoginRoutes]);
}

+ 3
- 0
src/utils/ApiPathConst.js Bestand weergeven

@@ -0,0 +1,3 @@
export const GET_GROUP_COMBO_PATH = "/group/combo"
export const GET_USER_PATH = "/user"
export const GET_AUTH_LIST = "/user/auth/combo"

Laden…
Annuleren
Opslaan