diff --git a/src/pages/AuditLog/UserSearchForm.js b/src/pages/AuditLog/UserSearchForm.js
new file mode 100644
index 0000000..c815e34
--- /dev/null
+++ b/src/pages/AuditLog/UserSearchForm.js
@@ -0,0 +1,198 @@
+// 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 AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
+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)
+ })
+ }
+
+ const handleNewUserClick = () => {
+ // console.log(id)
+ navigate('/user/-1');
+ // navigate('/user/' + id);
+ };
+
+ return (
+
+
+
+
+ );
+};
+
+export default UserSearchForm;
diff --git a/src/pages/AuditLog/UserTable.js b/src/pages/AuditLog/UserTable.js
new file mode 100644
index 0000000..9f866bc
--- /dev/null
+++ b/src/pages/AuditLog/UserTable.js
@@ -0,0 +1,142 @@
+// 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 [
+ }
+ 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 (
+
+ );
+ },
+ },
+ ];
+
+ function handleRowDoubleClick(params) {
+ navigate('/user/'+ params.id);
+ }
+
+ return (
+
+ 'auto'}
+ />
+
+ );
+}
diff --git a/src/pages/AuditLog/index.js b/src/pages/AuditLog/index.js
new file mode 100644
index 0000000..0e408b9
--- /dev/null
+++ b/src/pages/AuditLog/index.js
@@ -0,0 +1,110 @@
+// material-ui
+import {
+ Grid,
+ Typography,
+ Stack,
+ // Button
+} from '@mui/material';
+import MainCard from "components/MainCard";
+import { useEffect, useState } from "react";
+import axios from "axios";
+import { GLD_USER_PATH } from "utils/ApiPathConst";
+import * as React from "react";
+
+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')));
+import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
+
+const BackgroundHead = {
+ backgroundImage: `url(${titleBackgroundImg})`,
+ width: '100%',
+ height: '100%',
+ backgroundSize: 'contain',
+ backgroundRepeat: 'no-repeat',
+ backgroundColor: '#0C489E',
+ backgroundPosition: 'right'
+}
+// ==============================|| DASHBOARD - DEFAULT ||============================== //
+
+const AuditLogPage = () => {
+ const [record, setRecord] = useState([]);
+ const [searchCriteria, setSearchCriteria] = useState({});
+ const [onReady, setOnReady] = useState(false);
+ const [changelocked, setChangeLocked] = React.useState(false);
+
+ React.useLayoutEffect(() => {
+ getUserList();
+ }, [changelocked]);
+
+ useEffect(() => {
+ if (record.length > 0) {
+ setOnReady(true);
+ }
+ }, [record]);
+
+ React.useLayoutEffect(() => {
+ getUserList();
+ }, [searchCriteria]);
+
+ function getUserList() {
+ axios.get(`${GLD_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 ?
+
+
+
+
+
+ :
+
+
+
+
+ View GLD User
+
+
+
+
+ {/*row 1*/}
+
+
+
+ {/*row 2*/}
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AuditLogPage;
diff --git a/src/pages/User/DetailsPage_Individual/LoginGrid.js b/src/pages/User/DetailsPage_Individual/LoginGrid.js
index e806bf9..df785cc 100644
--- a/src/pages/User/DetailsPage_Individual/LoginGrid.js
+++ b/src/pages/User/DetailsPage_Individual/LoginGrid.js
@@ -46,10 +46,20 @@ export default function LoginGrid({rows}) {
field: 'result',
headerName: 'Result',
width: isMdOrLg ? 'auto' : 300,
- flex: isMdOrLg ? 1 : undefined,
- // valueGetter:(params)=>{
- // return DateUtils.datetimeStr(params?.value);
- // }
+ flex: isMdOrLg ? 2 : undefined,
+ valueGetter:(params)=>{
+ let resultMessage = "";
+ if (params.row.success>0){
+ resultMessage="Success"
+ }
+ if (params.row.success==0){
+ resultMessage="Fail"
+ }
+ if (params.row.success<0){
+ resultMessage= params.row.actionType + " by " + params.row.modifiedBy
+ }
+ return resultMessage;
+ }
},
];
diff --git a/src/pages/User/DetailsPage_Individual/index.js b/src/pages/User/DetailsPage_Individual/index.js
index e0e0b9f..70e7d04 100644
--- a/src/pages/User/DetailsPage_Individual/index.js
+++ b/src/pages/User/DetailsPage_Individual/index.js
@@ -43,6 +43,7 @@ const UserMaintainPage_Individual = () => {
const params = useParams();
const navigate = useNavigate();
const [formData, setFormData] = React.useState({})
+ const [loginLogData, setLoginLogData] = React.useState([])
const [isLoading, setLoding] = React.useState(true);
const [selectedTab, setSelectedTab] = React.useState("1");
@@ -90,6 +91,7 @@ const UserMaintainPage_Individual = () => {
response.data["preferLocale"] = getObjectByType(ComboData.Locale, "type", response.data?.preferLocale);
setFormData(response.data);
+ getLoginLogList()
}
});
}
@@ -121,10 +123,23 @@ const UserMaintainPage_Individual = () => {
}
};
+ const getLoginLogList = () => {
+ HttpUtils.get({
+ url: `${UrlUtils.GET_Login_Log_List}`,
+ params:{
+ userId:params.id
+ },
+ onSuccess: function (response) {
+ // console.log(response)
+ setLoginLogData(response);
+ }
+ });
+ }
+
React.useEffect(() => {
setLoding(false);
- }, [formData]);
+ }, [loginLogData]);
return (
isLoading ?
@@ -195,8 +210,7 @@ const UserMaintainPage_Individual = () => {
diff --git a/src/pages/User/DetailsPage_Organization/LoginGrid.js b/src/pages/User/DetailsPage_Organization/LoginGrid.js
new file mode 100644
index 0000000..df785cc
--- /dev/null
+++ b/src/pages/User/DetailsPage_Organization/LoginGrid.js
@@ -0,0 +1,81 @@
+// material-ui
+import * as React from 'react';
+import {FiDataGrid} from "components/FiDataGrid";
+import {
+ // Button,
+ // Typography,
+ useMediaQuery
+} from '@mui/material';
+import * as DateUtils from "utils/DateUtils"
+// import {useNavigate} from "react-router-dom";
+// import {
+// isORGLoggedIn,
+// } from "utils/Utils";
+import {useTheme} from "@emotion/react";
+// import {getStatusIntl} from "utils/statusUtils/PublicNoteStatusUtils";
+// import {
+// FormattedMessage,
+// useIntl} from "react-intl";
+// ==============================|| EVENT TABLE ||============================== //
+
+export default function LoginGrid({rows}) {
+ // const navigate = useNavigate()
+ const theme = useTheme();
+ const isMdOrLg = useMediaQuery(theme.breakpoints.up('md'));
+ // const intl = useIntl();
+
+ // const handleDetailClick = (params) => () => {
+ // navigate('/publicNotice/'+ params.id);
+ // };
+
+ // const remarkHeadername = rows.orgId===null?"我的備註":"Care Of / 我的備註"
+
+ const columns = [
+ {
+ id: 'loginTime',
+ field: 'loginTime',
+ headerName: "Date Time",
+ width: isMdOrLg ? 'auto' : 160,
+ flex: isMdOrLg ? 1 : undefined,
+ valueGetter:(params)=>{
+ return DateUtils.datetimeStr(params?.value);
+ }
+ },
+ {
+ id: 'result',
+ field: 'result',
+ headerName: 'Result',
+ width: isMdOrLg ? 'auto' : 300,
+ flex: isMdOrLg ? 2 : undefined,
+ valueGetter:(params)=>{
+ let resultMessage = "";
+ if (params.row.success>0){
+ resultMessage="Success"
+ }
+ if (params.row.success==0){
+ resultMessage="Fail"
+ }
+ if (params.row.success<0){
+ resultMessage= params.row.actionType + " by " + params.row.modifiedBy
+ }
+ return resultMessage;
+ }
+ },
+ ];
+
+ // function handleRowDoubleClick(params) {
+ // navigate('/publicNotice/'+ params.id);
+ // }
+
+ return (
+
+ 'auto'}
+ />
+
+ );
+}
diff --git a/src/pages/User/DetailsPage_Organization/index.js b/src/pages/User/DetailsPage_Organization/index.js
index 7e9bcc0..5a82336 100644
--- a/src/pages/User/DetailsPage_Organization/index.js
+++ b/src/pages/User/DetailsPage_Organization/index.js
@@ -1,5 +1,7 @@
// material-ui
-import { Grid, Typography, Stack, Box, Button } from '@mui/material';
+import { Grid, Typography, Stack, Box, Button, Tab } from '@mui/material';
+import { TabPanel, TabContext, TabList } from '@mui/lab';
+
import { useEffect, useState } from "react";
import * as React from "react";
//import axios from "axios";
@@ -20,6 +22,7 @@ import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import { useNavigate } from 'react-router-dom';
import * as ComboData from "utils/ComboData";
import {getObjectByValue,getObjectByType} from "utils/CommonFunction";
+const LoginGrid = Loadable(React.lazy(() => import('./LoginGrid')));
const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
@@ -45,32 +48,38 @@ const UserMaintainPage_Organization = () => {
const params = useParams();
const navigate = useNavigate();
const [userData, setUserData] = useState({})
+ const [loginLogData, setLoginLogData] = React.useState([])
const [orgData, setOrgData] = useState({})
const [isLoading, setLoding] = useState(true);
const intl = useIntl();
const { locale } = intl;
+ const [selectedTab, setSelectedTab] = React.useState("1");
const isPrimaryLocale = locale === 'en' ?"Yes":locale === 'zh-HK' ?"是":"是";
const notPrimaryLocale = locale === 'en' ?"No":locale === 'zh-HK' ?"否":"否";
- const _sx = {
- ml: 3,
- mb: 3,
- mt: 3,
- mr: 6,
- padding: "4 2 4 2",
- boxShadow: 1,
- border: 1,
- borderColor: '#DDD',
- '& .MuiDataGrid-cell': {
- borderTop: 1,
- borderBottom: 1,
- borderColor: "#EEE"
- },
- '& .MuiDataGrid-footerContainer': {
- border: 1,
- borderColor: "#EEE"
- }
+ // const _sx = {
+ // ml: 3,
+ // mb: 3,
+ // mt: 3,
+ // mr: 6,
+ // padding: "4 2 4 2",
+ // boxShadow: 1,
+ // border: 1,
+ // borderColor: '#DDD',
+ // '& .MuiDataGrid-cell': {
+ // borderTop: 1,
+ // borderBottom: 1,
+ // borderColor: "#EEE"
+ // },
+ // '& .MuiDataGrid-footerContainer': {
+ // border: 1,
+ // borderColor: "#EEE"
+ // }
+ // }
+
+ const handleChange = (event, newValue) => {
+ setSelectedTab(newValue);
}
useEffect(() => {
@@ -148,6 +157,7 @@ const UserMaintainPage_Organization = () => {
// console.log(response.data)
setUserData(response.data);
setOrgData(response.orgList);
+ getLoginLogList()
}
});
}
@@ -175,10 +185,24 @@ const UserMaintainPage_Organization = () => {
}
};
+ const getLoginLogList = () => {
+ HttpUtils.get({
+ url: `${UrlUtils.GET_Login_Log_List}`,
+ params:{
+ userId:params.id
+ },
+ onSuccess: function (response) {
+ // console.log(response)
+ setLoginLogData(response);
+ }
+ });
+ }
+
+
useEffect(() => {
setLoding(false);
- }, [userData]);
+ }, [loginLogData]);
return (
isLoading ?
@@ -236,17 +260,27 @@ const UserMaintainPage_Organization = () => {
}
{isGLDLoggedIn()?
-
-
-
- Files
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
:null
diff --git a/src/routes/GLDUserRoutes.js b/src/routes/GLDUserRoutes.js
index efa9b76..b317f62 100644
--- a/src/routes/GLDUserRoutes.js
+++ b/src/routes/GLDUserRoutes.js
@@ -27,6 +27,7 @@ const EmailTemplateDetailPage = Loadable(lazy(() => import('pages/EmailTemplate/
const HolidayPage = Loadable(lazy(() => import('pages/Holiday')));
const GazetteIssuePage = Loadable(lazy(() => import('pages/GazetteIssue/index')));
const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport')));
+const AuditLogPage = Loadable(lazy(() => import('pages/AuditLog/index')));
// ==============================|| MAIN ROUTING ||============================== //
@@ -125,6 +126,10 @@ const GLDUserRoutes = {
path: '/setting/drImport',
element:
},
+ {
+ path: '/setting/auditLog',
+ element:
+ },
]
},
]
diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js
index 8b5311b..28bda55 100644
--- a/src/utils/ApiPathConst.js
+++ b/src/utils/ApiPathConst.js
@@ -105,6 +105,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_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';