Просмотр исходного кода

export audit log and add audit log page

master
Alex Cheung 1 год назад
Родитель
Сommit
c291975daf
9 измененных файлов: 284 добавлений и 334 удалений
  1. +3
    -0
      src/layout/MainLayout/Header/index.js
  2. +180
    -0
      src/pages/AuditLog/AuditLogSearchForm.js
  3. +81
    -0
      src/pages/AuditLog/AuditLogTable.js
  4. +0
    -182
      src/pages/AuditLog/UserSearchForm.js
  5. +0
    -142
      src/pages/AuditLog/UserTable.js
  6. +15
    -7
      src/pages/AuditLog/index.js
  7. +1
    -1
      src/pages/User/DetailsPage_Individual/index.js
  8. +1
    -1
      src/pages/User/DetailsPage_Organization/index.js
  9. +3
    -1
      src/utils/ApiPathConst.js

+ 3
- 0
src/layout/MainLayout/Header/index.js Просмотреть файл

@@ -158,6 +158,9 @@ function Header(props) {
<li>
<Link className="gazetteissueSetting" to='/setting/gazetteissuepage'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Gazette Issue</Typography></Link>
</li>
<li>
<Link className="auditLogSetting" to='/setting/auditLog'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Audit Log</Typography></Link>
</li>
</ul>
</li>
<Box sx={{display: {xs: 'none', sm: 'none', md: 'block'}}}>


+ 180
- 0
src/pages/AuditLog/AuditLogSearchForm.js Просмотреть файл

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

import {
// useEffect,
// useState
} from "react";

import * as React from "react";
// import { useNavigate } from "react-router";
import {PNSPS_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";
import * as DateUtils from "utils/DateUtils";
import * as UrlUtils from "utils/ApiPathConst";
import * as HttpUtils from "utils/HttpUtils";
import Loadable from 'components/Loadable';

const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));

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


const AuditLogSearchForm = ({ applySearch, searchCriteria}) => {
// const navigate = useNavigate();

const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
const [onDownload, setOnDownload] = React.useState(false);

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

const temp = {
username: data.userName,
modifiedTo: data.modifiedTo,
modifiedFrom: data.modifiedFrom,
};
applySearch(temp);
};


function resetForm() {
reset();
}

function exportExcel() {
setOnDownload(true)
HttpUtils.fileDownload({
url: UrlUtils.AUDIT_LOG_EXPORT,
onResponse:()=>{
setOnDownload(false)
},
onError:()=>{
setOnDownload(false)
}
});
}

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

<form onSubmit={handleSubmit(onSubmit)}>
<Grid container sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1}} width="98%">
{/*row 1*/}
<Grid item justifyContent="space-between" alignItems="center" sx={{mt:1,ml:3,mb:2.5}}>
<Typography variant="pnspsFormHeader" >
Search
</Typography>
</Grid>
{/*row 2*/}

<Grid container display="flex" alignItems={"center"}>
<Grid item xs={9} md={5} lg={5} sx={{ ml: 3, mr: 3, mb: 3 }}>
<TextField
fullWidth
{...register("userName")}
id='userName'
label="Username"
InputLabelProps={{
shrink: true
}}
/>
</Grid>
<Grid item xs={9} md={5} lg={5} sx={{ ml: 3, mr: 3, mb: 3 }}></Grid>

<Grid item xs={9} s={6} md={5} lg={5} sx={{ ml: 3, mr: 3, mb: 3 }}>
<TextField
fullWidth
{...register("modifiedFrom")}
id="modifiedFrom"
type="date"
label="Modified From"
defaultValue={searchCriteria.modifiedFrom}
InputProps={{ inputProps: { max: maxDate } }}
onChange={(newValue) => {
setMinDate(DateUtils.dateStr(newValue));
}}
InputLabelProps={{
shrink: true
}}
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={5} sx={{ ml: 3, mr: 3, mb: 3 }}>
<TextField
fullWidth
InputLabelProps={{
shrink: true
}}
{...register("modifiedTo")}
InputProps={{ inputProps: { min: minDate } }}
onChange={(newValue) => {
console.log(newValue)
setMaxDate(DateUtils.dateStr(newValue));
}}
id="modifiedTo"
type="date"
label="Modified To"
defaultValue={searchCriteria.modifiedTo}
/>
</Grid>

</Grid>

{/*last row*/}
<Grid container direction="row"
justifyContent="space-between"
alignItems="center">
<ThemeProvider theme={PNSPS_BUTTON_THEME}>
<Grid item xs={12} md={12}>
<Grid container maxWidth justifyContent="flex-end">
<Grid item sx={{ ml: 3, mr: 3, mb: 3,}}>
{onDownload?
<LoadingComponent disableText={true} alignItems="flex-start"/>
:
<Button
variant="contained"
onClick={exportExcel}
>
Export
</Button>
}
</Grid>
<Grid item sx={{ ml: 3, mr: 3, mb: 3,}}>
<Button
variant="contained"
onClick={resetForm}
>
Clear
</Button>
</Grid>
<Grid item sx={{ ml: 3, mb: 3 }}>
<Button
variant="contained"
type="submit"
>
Search
</Button>
</Grid>
</Grid>
</Grid>
</ThemeProvider>
</Grid>
</Grid>
</form>
</MainCard>
);
};

export default AuditLogSearchForm;

+ 81
- 0
src/pages/AuditLog/AuditLogTable.js Просмотреть файл

@@ -0,0 +1,81 @@
// material-ui
import * as React from 'react';
import {FiDataGrid} from "components/FiDataGrid";
import {useEffect} from "react";
import * as DateUtils from "utils/DateUtils"
import {useTheme} from "@emotion/react";
import {
// Button,
// Typography,
useMediaQuery
} from '@mui/material';
// ==============================|| EVENT TABLE ||============================== //

export default function AuditLogTable({recordList}) {
const [rows, setRows] = React.useState(recordList);

useEffect(() => {
setRows(recordList);
// console.log(recordList)
}, [recordList]);
const theme = useTheme();
const isMdOrLg = useMediaQuery(theme.breakpoints.up('md'));

const columns = [
{
id: 'modified',
field: 'modified',
headerName: 'Date',
flex: isMdOrLg ? 1 : undefined,
valueGetter:(params)=>{
return DateUtils.datetimeStr(params?.value);
}
},
{
id: 'modifiedByName',
field: 'modifiedByName',
headerName: 'Username',
flex: isMdOrLg ? 1 : undefined,
},
{
id: 'tableName',
field: 'tableName',
headerName: 'Table Name',
flex: isMdOrLg ? 1 : undefined,
},
{
id: 'ref',
field: 'ref',
headerName: 'Ref',
flex: isMdOrLg ? 1 : undefined,
},
{
id: 'oldData',
field: 'oldData',
headerName: 'Old Data',
flex: isMdOrLg ? 2 : undefined,
},
{
id: 'newData',
field: 'newData',
headerName: 'New Data',
flex: isMdOrLg ? 2 : undefined,
},
];

// function handleRowDoubleClick(params) {
// navigate('/user/'+ params.id);
// }

return (
<div style={{height: "fit-content", width: '100%'}}>
<FiDataGrid
rows={rows}
columns={columns}
customPageSize={5}
// onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'}
/>
</div>
);
}

+ 0
- 182
src/pages/AuditLog/UserSearchForm.js Просмотреть файл

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

import {
// useEffect,
useState
} from "react";

import Checkbox from "@mui/material/Checkbox";
import * as React from "react";
// import { useNavigate } from "react-router";
import axios from "axios";
import { GET_EMAIL_LIST } from 'utils/ApiPathConst';
import {PNSPS_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";

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


const UserSearchForm = ({ applySearch }) => {
// const navigate = useNavigate();

const [type, setType] = useState([]);
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,
enName: data.fullenName,
post: data.post,
email: data.email,
locked: locked,
};
applySearch(temp);
};


function resetForm() {
setType([]);
setLocked(false);
reset();
axios.get(`${GET_EMAIL_LIST}`)
.then(r => {
console.log(r)
})
.catch(err => {
console.log(err)
})
}

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

<form onSubmit={handleSubmit(onSubmit)}>
<Grid container sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1}} width="98%">
{/*row 1*/}
<Grid item justifyContent="space-between" alignItems="center" sx={{mt:1,ml:3,mb:2.5}}>
<Typography variant="pnspsFormHeader" >
Search
</Typography>
</Grid>
{/*row 2*/}

<Grid container display="flex" 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"
InputLabelProps={{
shrink: true
}}
/>
</Grid>

<Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
<TextField
fullWidth
{...register("fullenName")}
id="fullenName"
label="Full Name"
InputLabelProps={{
shrink: true
}}
/>
</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"
InputLabelProps={{
shrink: true
}}
/>
</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"
InputLabelProps={{
shrink: true
}}
/>
</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>

{/*last row*/}
<Grid container direction="row"
justifyContent="space-between"
alignItems="center">
<ThemeProvider theme={PNSPS_BUTTON_THEME}>

<Grid item xs={12} md={12}>
<Grid container maxWidth justifyContent="flex-end">
<Grid item sx={{ ml: 3, mr: 3, mb: 3,}}>
<Button
variant="contained"
onClick={resetForm}
>
Clear
</Button>
</Grid>

<Grid item sx={{ mb: 3 }}>
<Button
variant="contained"
type="submit"
>
Search
</Button>
</Grid>
</Grid>
</Grid>
</ThemeProvider>
</Grid>
</Grid>
</form>
</MainCard>
);
};

export default UserSearchForm;

+ 0
- 142
src/pages/AuditLog/UserTable.js Просмотреть файл

@@ -1,142 +0,0 @@
// material-ui
import * as React from 'react';
import { GridActionsCellItem,} from "@mui/x-data-grid";
import {FiDataGrid} from "components/FiDataGrid";
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';
import * as UrlUtils from "utils/ApiPathConst";
import * as HttpUtils from 'utils/HttpUtils';
import { notifyLockSuccess, notifyUnlockSuccess } from 'utils/CommonFunction';

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

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

const navigate = useNavigate()

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

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

const handleLock = (params) => () => {
setChangeLocked(false)
if (params.row.locked==true){
doUnlock(params.id)
}else{
doLock(params.id)
setRows(recordList);
}
}

const doLock = (id) => {
HttpUtils.get({
url: UrlUtils.GET_USER_LOCK+"/"+id,
onSuccess: function(){
setRows(recordList);
setChangeLocked(true)
notifyLockSuccess()
}
});
};

const doUnlock = (id) => {
HttpUtils.get({
url: UrlUtils.GET_USER_UNLOCK+"/"+id,
onSuccess: function(){
setRows(recordList);
setChangeLocked(true)
notifyUnlockSuccess()
}
});
};

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: 'enName',
field: 'enName',
headerName: 'Full Name',
flex: 1,
},
{
id: 'post',
field: 'post',
headerName: 'Post',
flex: 1,
},
{
id: 'emailAddress',
field: 'emailAddress',
headerName: 'Email',
flex: 1,
},

{
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"
onClick={handleLock(params)}
/>
);
},
},
];

function handleRowDoubleClick(params) {
navigate('/user/'+ params.id);
}

return (
<div style={{height: "fit-content", width: '100%'}}>
<FiDataGrid
rows={rows}
columns={columns}
customPageSize={5}
onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'}
/>
</div>
);
}

+ 15
- 7
src/pages/AuditLog/index.js Просмотреть файл

@@ -8,14 +8,15 @@ import {
import MainCard from "components/MainCard";
import { useEffect, useState } from "react";
import axios from "axios";
import { GLD_USER_PATH } from "utils/ApiPathConst";
import { GET_AUDIT_LOG_LIST } from "utils/ApiPathConst";
import * as React from "react";
import * as DateUtils from "utils/DateUtils";

import Loadable from 'components/Loadable';
import { lazy } from 'react';
const LoadingComponent = Loadable(lazy(() => import('../extra-pages/LoadingComponent')));
const SearchForm = Loadable(lazy(() => import('./UserSearchForm')));
const EventTable = Loadable(lazy(() => import('./UserTable')));
const SearchForm = Loadable(lazy(() => import('./AuditLogSearchForm')));
const EventTable = Loadable(lazy(() => import('./AuditLogTable')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'

const BackgroundHead = {
@@ -31,7 +32,10 @@ const BackgroundHead = {

const AuditLogPage = () => {
const [record, setRecord] = useState([]);
const [searchCriteria, setSearchCriteria] = useState({});
const [searchCriteria, setSearchCriteria] = React.useState({
modifiedTo: DateUtils.dateStr(new Date()),
modifiedFrom: DateUtils.dateStr(new Date().setDate(new Date().getDate()-14)),
});
const [onReady, setOnReady] = useState(false);
const [changelocked, setChangeLocked] = React.useState(false);

@@ -50,7 +54,7 @@ const AuditLogPage = () => {
}, [searchCriteria]);

function getUserList() {
axios.get(`${GLD_USER_PATH}`,
axios.get(`${GET_AUDIT_LOG_LIST}`,
{ params: searchCriteria }
)
.then((response) => {
@@ -80,14 +84,18 @@ const AuditLogPage = () => {
<Grid item xs={12}>
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4">View GLD User</Typography>
<Typography ml={15} color='#FFF' variant="h4">Audit Log</Typography>
</Stack>
</div>
</Grid>

{/*row 1*/}
<Grid item xs={12} md={12} lg={12} sx={{mb:-1}}>
<SearchForm applySearch={applySearch} />
<SearchForm
applySearch={applySearch}
searchCriteria={searchCriteria}
/>
</Grid>
{/*row 2*/}
<Grid item xs={12} md={12} lg={12}>


+ 1
- 1
src/pages/User/DetailsPage_Individual/index.js Просмотреть файл

@@ -125,7 +125,7 @@ const UserMaintainPage_Individual = () => {

const getLoginLogList = () => {
HttpUtils.get({
url: `${UrlUtils.GET_Login_Log_List}`,
url: `${UrlUtils.GET_LOGIN_LOG_LIST}`,
params:{
userId:params.id
},


+ 1
- 1
src/pages/User/DetailsPage_Organization/index.js Просмотреть файл

@@ -187,7 +187,7 @@ const UserMaintainPage_Organization = () => {

const getLoginLogList = () => {
HttpUtils.get({
url: `${UrlUtils.GET_Login_Log_List}`,
url: `${UrlUtils.GET_LOGIN_LOG_LIST}`,
params:{
userId:params.id
},


+ 3
- 1
src/utils/ApiPathConst.js Просмотреть файл

@@ -69,6 +69,7 @@ export const GET_FILE_DELETE = apiPath+'/file/delete';

export const DR_EXPORT = apiPath+'/settings/dr/export';
export const DR_IMPORT = apiPath+'/settings/dr/import';
export const AUDIT_LOG_EXPORT = apiPath+'/settings/auditLog-export';



@@ -105,7 +106,7 @@ export const POST_CHECK_APP_EXPRITY_DATE = apiPath+'/application/checkExprityDat
//GLD User
export const POST_ADMIN_USER_REGISTER = apiPath+'/user/registry';
export const DELETE_USER = apiPath+'/user';
export const GET_Login_Log_List = apiPath+'/user/loginLogList';
export const GET_LOGIN_LOG_LIST = apiPath+'/user/loginLogList';
export const GET_PUBLIC_NOTICE_APPLY_DETAIL = apiPath+'/application/application-detail';
export const SET_PUBLIC_NOTICE_GROUP_DETAIL = apiPath+'/application/application-group-detail';
export const SET_PUBLIC_NOTICE_STATUS_NOT_ACCEPT = apiPath+'/application/application-detail-status-not-accept';
@@ -116,6 +117,7 @@ export const SET_PUBLIC_NOTICE_STATUS_RESUBMIT = apiPath+'/application/applicati
export const SET_PUBLIC_NOTICE_STATUS_REVIEWED = apiPath+'/application/application-detail-status-reviewed';
export const SET_PUBLIC_NOTICE_STATUS_PUBLISH = apiPath+'/application/application-detail-status-publish';
export const UPDATE_PUBLIC_NOTICE_APPLY_DETAIL = apiPath+'/application/save';
export const GET_AUDIT_LOG_LIST = apiPath+'/settings/auditLogList';

//gazette
export const GET_ISSUE_COMBO = apiPath+'/gazette-issue/combo';//GET


Загрузка…
Отмена
Сохранить