diff --git a/client/components/status/index.css b/client/components/status/index.css index 79e3429d..ec1c32ff 100644 --- a/client/components/status/index.css +++ b/client/components/status/index.css @@ -68,6 +68,52 @@ overflow-wrap: break-word; word-wrap: break-word; } +.flex-wrapper { + flex-wrap: wrap; + max-width: 1000px; + margin: 0 auto; +} + +.flex-row { + flex-grow: 1; + flex-direction: column; + flex-wrap: wrap; + width: 100%; +} + +.flex-row > .row { + padding: 3%; + margin: 0 0 10px; + box-sizing: border-box; +} + +.limit-info { + text-align: center; + margin-bottom: 15px; +} + +.limit-info h3 { + margin: 0 0 10px; +} +.limit-info progress { + width: 80%; + height: 40px; +} +.limit-info p.progress { + font-size: 20px; +} +.limit-info p:last-child { + margin-bottom: 0; +} +.limit-info .button { + margin-top: 5px; +} + +.limit-info .exahusted { + color: #ba2121f7; + margin-top: 15px; + line-height: 1.5em; +} @media screen and (min-width: 0px) and (max-width: 500px) { .logout-modal-container p.message { diff --git a/client/components/status/status.js b/client/components/status/status.js index 9c648296..f4946243 100644 --- a/client/components/status/status.js +++ b/client/components/status/status.js @@ -12,7 +12,13 @@ import {Link} from "react-router-dom"; import {toast} from "react-toastify"; import InfinteScroll from "react-infinite-scroll-component"; import {t, gettext} from "ttag"; -import {getUserRadiusSessionsUrl, mainToastId} from "../../constants"; +import prettyBytes from "pretty-bytes"; +import {timeFromSeconds} from "duration-formatter"; +import { + getUserRadiusSessionsUrl, + getUserRadiusUsageUrl, + mainToastId, +} from "../../constants"; import LoadingContext from "../../utils/loading-context"; import getText from "../../utils/get-text"; import logError from "../../utils/log-error"; @@ -48,6 +54,8 @@ export default class Status extends React.Component { loadSpinner: true, modalActive: false, rememberMe: false, + userChecks: [], + userPlan: {}, }; this.repeatLogin = false; this.getUserRadiusSessions = this.getUserRadiusSessions.bind(this); @@ -196,6 +204,7 @@ export default class Status extends React.Component { componentWillUnmount = () => { clearInterval(this.intervalId); + clearInterval(this.getUserRadiusUsageIntervalId); window.removeEventListener("resize", this.updateScreenWidth); }; @@ -238,6 +247,10 @@ export default class Status extends React.Component { this.intervalId = setInterval(() => { this.getUserActiveRadiusSessions(); }, 60000); + await this.getUserRadiusUsage(); + this.getUserRadiusUsageIntervalId = setInterval(() => { + this.getUserRadiusUsage(); + }, 60000); window.addEventListener("resize", this.updateScreenWidth); this.updateSpinner(); } @@ -288,6 +301,41 @@ export default class Status extends React.Component { } } + async getUserRadiusUsage() { + const {cookies, orgSlug, logout, userData} = this.props; + const url = getUserRadiusUsageUrl(orgSlug); + const auth_token = cookies.get(`${orgSlug}_auth_token`); + handleSession(orgSlug, auth_token, cookies); + const options = {}; + try { + const response = await axios({ + method: "get", + headers: { + "content-type": "application/x-www-form-urlencoded", + Authorization: `Bearer ${userData.auth_token}`, + }, + url, + }); + options.userChecks = response.data.checks; + if (response.data.plan) { + options.userPlan = response.data.plan; + } + this.setState(options); + } catch (error) { + // logout only if unauthorized or forbidden + if ( + error.response && + (error.response.status === 401 || error.response.status === 403) + ) { + logout(cookies, orgSlug); + toast.error(t`ERR_OCCUR`, { + onOpen: () => toast.dismiss(mainToastId), + }); + } + logError(error, t`ERR_OCCUR`); + } + } + async getUserActiveRadiusSessions(params = {}) { const para = { is_open: true, @@ -752,6 +800,17 @@ export default class Status extends React.Component { }, }); + getUserCheckFormattedValue = (value, type) => { + switch (type) { + case "bytes": + return prettyBytes(parseInt(value, 10)); + case "seconds": + return timeFromSeconds(parseInt(value, 10)); + default: + return value; + } + }; + render() { const { statusPage, @@ -762,6 +821,7 @@ export default class Status extends React.Component { isAuthenticated, userData, internetMode, + settings, } = this.props; const {links} = statusPage; const { @@ -769,6 +829,8 @@ export default class Status extends React.Component { password, userInfo, activeSessions, + userChecks, + userPlan, pastSessions, sessionsToLogout, hasMoreSessions, @@ -787,7 +849,42 @@ export default class Status extends React.Component { handleResponse={this.handleLogout} content={
{t`LOGOUT_MODAL_CONTENT`}
} /> -+ + {this.getUserCheckFormattedValue( + check.result, + check.type, + )} + {" "} + of{" "} + {this.getUserCheckFormattedValue(check.value, check.type)}{" "} + used +
++ +
+ )} +