Skip to content

Commit

Permalink
Merge pull request #614 from ianmcorvidae/login-table
Browse files Browse the repository at this point in the history
Login table
  • Loading branch information
ianmcorvidae authored Jan 24, 2025
2 parents 886c95d + 8449029 commit 55ee566
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,7 @@ storybook-static
public/locales*

.VSCodeCounter

# editor backup/swap files
*.swp
*.bak
3 changes: 3 additions & 0 deletions public/static/locales/en/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@
"goToVice": "Go to analysis",
"instantLaunches": "Instant Launches",
"integratedBy": "Integrated by",
"ipAddress": "IP Address",
"launchAction": "Launch",
"launchAria": "launch",
"learnMore": "Learn More",
"login": "Login",
"loginTime": "Login Time",
"loginsTableError": "Unable to get recent logins.",
"loginSignUp": "Login or sign-up to access additional features.",
"newsFeed": "News",
"noAnalysesStats": "Looks like you haven't run any analyses yet.",
Expand Down
85 changes: 85 additions & 0 deletions src/components/dashboard/dashboardItem/LoginTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
*
* @author mian
*
* A table of recent logins for the user.
*
*/

import React from "react";
import { useQuery } from "react-query";

import { logins, LOGINS_QUERY_KEY } from "serviceFacades/users";
import ErrorTypographyWithDialog from "components/error/ErrorTypographyWithDialog";
import { useTranslation } from "i18n";
import {
formatDate,
getFormattedDistance,
} from "components/utils/DateFormatter";
import {
useTheme,
Skeleton,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
} from "@mui/material";

export default function LoginsTable() {
const { t } = useTranslation(["dashboard", "common"]);

const theme = useTheme();
const { status, data, error } = useQuery({
queryKey: [LOGINS_QUERY_KEY],
queryFn: () => logins({ limit: 5 }),
});

if (status === "error") {
return (
<div style={{ padding: theme.spacing(1) }}>
<ErrorTypographyWithDialog
errorObject={error}
errorMessage={t("loginsTableError")}
/>
</div>
);
}
if (status === "loading") {
return <Skeleton variant="rectangular" height={200} />;
}
return (
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>{t("loginTime")}</TableCell>
<TableCell>{t("ipAddress")}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data?.logins.map((row, index) => (
<TableRow key={index}>
<TableCell>
{formatDate(row["login_time"])}
&nbsp;
<em>
(
{t("common:timestamp", {
timestamp: getFormattedDistance(
row["login_time"] / 1000
),
})}
)
</em>
</TableCell>
<TableCell>{row["ip_address"]}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
8 changes: 7 additions & 1 deletion src/components/dashboard/dashboardItem/ResourceUsageItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {

import DataConsumption from "./DataConsumption";
import AnalysesStats from "./AnalysesStats";
import LoginTable from "./LoginTable";
import CPUConsumption from "./CPUConsumption";
import ExternalLink from "components/utils/ExternalLink";
import ErrorTypographyWithDialog from "components/error/ErrorTypographyWithDialog";
Expand Down Expand Up @@ -145,11 +146,16 @@ export default function ResourceUsageItem(props) {
</Card>
</Grid>
)}
<Grid item xs={12} md={12}>
<Grid item xs={12} md={6}>
<Card>
<AnalysesStats />
</Card>
</Grid>
<Grid item xs={12} md={6}>
<Card>
<LoginTable />
</Card>
</Grid>
</Grid>
</>
)}
Expand Down
10 changes: 10 additions & 0 deletions src/server/api/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ export default function userRouter() {
})
);

logger.info("adding the GET /logins handler");
api.get(
"/logins",
auth.authnTokenMiddleware,
terrainHandler({
method: "GET",
pathname: "/secured/logins",
})
);

logger.info("adding the POST /preferences handler");
api.post(
"/preferences",
Expand Down
12 changes: 12 additions & 0 deletions src/serviceFacades/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const WEBHOOKS_TOPICS_QUERY_KEY = "fetchHookTopics";
const WEBHOOK_TEST_KEY = "testWebhook";
const USER_PORTAL_QUERY_KEY = "fetchUserPortalStatus";
const USER_PORTAL_DETAILS_QUERY_KEY = "fetchUserPortalDetails;";
const LOGINS_QUERY_KEY = "logins";

const getUserInfo = ({ userIds }) => {
const userQuery = userIds.join("&username=");
Expand All @@ -41,6 +42,15 @@ function bootstrap() {
});
}

function logins({ limit }) {
return callApi({
endpoint: `/api/logins`,
params: { limit },
method: "GET",
credentials: "include",
});
}

function savePreferences({ preferences, webhooks }) {
let promises = [];

Expand Down Expand Up @@ -198,10 +208,12 @@ export {
WEBHOOKS_TOPICS_QUERY_KEY,
WEBHOOKS_TYPES_QUERY_KEY,
WEBHOOK_TEST_KEY,
LOGINS_QUERY_KEY,
getUserInfo,
getUserPortalDetails,
getUserProfile,
bootstrap,
logins,
savePreferences,
resetToken,
getRedirectURIs,
Expand Down

0 comments on commit 55ee566

Please sign in to comment.