diff --git a/src/stores/Auth.js b/src/stores/Auth.js index c1e5bd1..4a8f7e8 100644 --- a/src/stores/Auth.js +++ b/src/stores/Auth.js @@ -29,8 +29,10 @@ class Auth { return postForm(postUrl, formData) .then(json => { if (json.errcode == 0) { - this.login.token = json.Result.token; - this.login.timeout = false; + runInAction(() => { + this.login.token = json.Result.token; + this.login.timeout = false; + }); this.root.putSession(KEY_LOGIN_TOKEN, json.Result.token); return json.Result.WU_LMI_SN; } else { @@ -58,7 +60,7 @@ class Auth { this.root.putSession(KEY_TRAVEL_AGENCY_ID, this.login.travelAgencyId); this.root.putSession(KEY_USER_ID, this.login.userId); }); - this.startTokenInterval(this.login.token); + this.startTokenInterval(); return this.login; } else { throw new Error(json.errmsg + ': ' + json.errcode); @@ -66,11 +68,11 @@ class Auth { }); } - startTokenInterval(loginToken) { + startTokenInterval() { const authStore = this; async function fetchLastRequet() { const fetchUrl = prepareUrl(HT_HOST + '/service-CooperateSOA/GetLastReqDate') - .append('token', loginToken) + .append('token', authStore.login.token) .build(); const json = await fetchJSON(fetchUrl) if (json.errcode == 0 && isNotEmpty(json.result)) { @@ -80,26 +82,29 @@ class Auth { } } - setInterval(async () => { + async function checkTokenTimeout() { const lastRequest = await fetchLastRequet(); - console.info(lastRequest); const lastReqDate = new Date(lastRequest); const now = new Date(); const diffTime = now.getTime() - lastReqDate.getTime(); - const diffMinute = diffTime/1000/60; - console.info(now); - console.info(lastReqDate); - console.info('diffTime: ' + diffTime); - console.info('diffMinute: ' + diffMinute); - if (diffMinute > 3) { - console.info('timeout...'); - runInAction(() => { - authStore.login.timeout = true; - }); + const diffHours = diffTime/1000/60/60; + if (diffHours > 4) { + authStore.logout(); } - }, 1000*60*1); + } + + this.tokenInterval = setInterval(() => checkTokenTimeout(), 1000*60*20); } + logout() { + this.root.clearSession(); + runInAction(() => { + this.login.timeout = true; + }); + } + + tokenInterval = null; + changeUserPassword(password, newPassword) { const formData = new FormData(); formData.append('UserID', this.login.userId); diff --git a/src/stores/Root.js b/src/stores/Root.js index a1642ed..f165325 100644 --- a/src/stores/Root.js +++ b/src/stores/Root.js @@ -15,6 +15,15 @@ class Root { makeAutoObservable(this); } + clearSession() { + if (window.sessionStorage) { + const sessionStorage = window.sessionStorage; + sessionStorage.clear(); + } else { + console.error('browser not support sessionStorage!'); + } + } + getSession(key) { if (window.sessionStorage) { const sessionStorage = window.sessionStorage; diff --git a/src/views/App.jsx b/src/views/App.jsx index da0e7ce..0fce29c 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -1,5 +1,5 @@ import { Outlet, Link, useHref, useNavigate, NavLink } from "react-router-dom"; -import { useEffect } from "react"; +import { useEffect, useState } from 'react'; import { observer } from "mobx-react"; import { toJS } from "mobx"; import { Layout, Menu, ConfigProvider, theme, Dropdown, Space, Row, Col, Badge, Typography, Modal, Input, Button, App as AntApp } from "antd"; @@ -25,13 +25,15 @@ const items = [ type: "divider", }, { - label: Logout, + label: Logout, key: "3", }, ]; function App() { + const [password, setPassword] = useState(''); const { authStore, noticeStore } = useStore(); + const { notification } = AntApp.useApp(); const login = toJS(authStore.login); const { noticeUnRead } = noticeStore; const href = useHref(); @@ -45,6 +47,30 @@ function App() { } }, [href]); + const onSubmit = () => { + authStore.valdateUserPassword(login.username, password) + .then(() => { + authStore.fetchUserDetail() + .catch(ex => { + notification.error({ + message: `Notification`, + description: 'Failed to get user information.', + placement: 'top', + duration: 4, + }); + }); + }) + .catch(ex => { + notification.error({ + message: `Notification`, + description: ex.message, + placement: 'top', + duration: 4, + }); + }); + setPassword(''); + }; + const splitPath = href.split("/"); let defaultPath = "reservation"; @@ -70,18 +96,18 @@ function App() { closable={false} maskClosable={false} footer={null} - open={false} - // open={isModalOpen} onOk={handleOk} onCancel={handleCancel} + open={login.timeout} > - Login timeout + Login timeout + Please input your password - + setPassword(e.target.value)} + onPressEnter={() => onSubmit()} + addonBefore={login.username} /> + onClick={() => onSubmit()} + >Submit + }} + trigger={['click']} + > e.preventDefault()}> {authStore.login.username} diff --git a/src/views/Login.jsx b/src/views/Login.jsx index 92509de..ac540b2 100644 --- a/src/views/Login.jsx +++ b/src/views/Login.jsx @@ -1,15 +1,27 @@ -import { useNavigate } from "react-router-dom"; +import { useNavigate, useLocation } from "react-router-dom"; +import { useEffect } from 'react'; import { Button, Checkbox, Form, Input, Row, App } from 'antd'; import { useStore } from '@/stores/StoreContext.js'; function Login() { - const { authStore,noticeStore } = useStore(); + const { authStore, noticeStore } = useStore(); const { notification } = App.useApp(); const navigate = useNavigate(); + const location = useLocation(); const [form] = Form.useForm(); + useEffect (() => { + if (location.search === '?out') { + authStore.logout(); + navigate('/login'); + } + return () => { + // unmount... + }; + }, []); + const onFinish = (values) => { authStore.valdateUserPassword(values.username, values.password) .then((userId) => { @@ -22,7 +34,7 @@ function Login() { .catch(ex => { notification.error({ message: `Notification`, - description: ex.message, + description: 'Failed to get user information.', placement: 'top', duration: 4, }); @@ -31,7 +43,7 @@ function Login() { .catch(ex => { notification.error({ message: `Notification`, - description: ex.message, + description: 'Login failed. Incorrect username or password.', placement: 'top', duration: 4, }); diff --git a/src/views/reservation/Newest.jsx b/src/views/reservation/Newest.jsx index d05923b..36fc5e4 100644 --- a/src/views/reservation/Newest.jsx +++ b/src/views/reservation/Newest.jsx @@ -5,7 +5,6 @@ import { toJS } from "mobx"; import { Row, Col, Space, Button, Table, Input, Typography, DatePicker, Radio, Modal, App, Select } from 'antd'; import { useStore } from '@/stores/StoreContext.js'; import { DATE_PRESETS } from "@/config"; -import dayjs from "dayjs"; const { Title } = Typography; @@ -91,7 +90,6 @@ function Newest() { const location = useLocation(); const { reservationStore } = useStore(); const { reservationList, reservationPage, referenceNo, arrivalDateRange, cityList, cityGuideList } = reservationStore; - console.info(reservationPage); const [isModalOpen, setIsModalOpen] = useState(false); const [dataLoading, setDataLoading] = useState(false); const { notification } = App.useApp(); @@ -193,11 +191,11 @@ function Newest() { - - + + { reservationStore.updatePropertyValue('referenceNo', e.target.value)} } /> - + Arrival Date - + + +