1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

DateTime component

This commit is contained in:
Quentin Gliech
2022-11-16 15:54:45 +01:00
parent 408a7ba363
commit 10815d8101
6 changed files with 156 additions and 7 deletions

View File

@@ -8,6 +8,7 @@
"name": "mas-frontend",
"version": "0.0.0",
"dependencies": {
"date-fns": "^2.29.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-relay": "^14.1.0",
@@ -9105,6 +9106,18 @@
"integrity": "sha512-qTcEYLen3r7ojZNgVUaRggOI+KM7jrKxXeSHhogh/TWxYMeONEMqY+hmkobiYQozsGIyg9OYVzO4ZIfoB4I0pQ==",
"dev": true
},
"node_modules/date-fns": {
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
"engines": {
"node": ">=0.11"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -30395,6 +30408,11 @@
"integrity": "sha512-qTcEYLen3r7ojZNgVUaRggOI+KM7jrKxXeSHhogh/TWxYMeONEMqY+hmkobiYQozsGIyg9OYVzO4ZIfoB4I0pQ==",
"dev": true
},
"date-fns": {
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",

View File

@@ -15,6 +15,7 @@
"build-storybook": "storybook build"
},
"dependencies": {
"date-fns": "^2.29.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-relay": "^14.1.0",

View File

@@ -14,8 +14,10 @@
import type { BrowserSession_session$key } from "./__generated__/BrowserSession_session.graphql";
import { graphql, useFragment } from "react-relay";
import Block from "./Block";
import { Body, Code, Subtitle } from "./Typography";
import { Body, Subtitle } from "./Typography";
import DateTime from "./DateTime";
type Props = {
session: BrowserSession_session$key;
@@ -37,17 +39,22 @@ const BrowserSession: React.FC<Props> = ({ session, isCurrent }) => {
session
);
const lastAuthentication = data.lastAuthentication?.createdAt || "never";
const lastAuthentication = data.lastAuthentication?.createdAt;
const createdAt = data.createdAt;
return (
<Block>
{isCurrent && <Subtitle>Current session</Subtitle>}
<Body>
Started: <Code>{createdAt}</Code>
Started: <DateTime datetime={createdAt} />
</Body>
<Body>
Last authentication: <Code>{lastAuthentication}</Code>
Last authentication:{" "}
{lastAuthentication ? (
<DateTime datetime={lastAuthentication} />
) : (
"never"
)}
</Body>
</Block>
);

View File

@@ -16,6 +16,7 @@ import type { CompatSsoLogin_login$key } from "./__generated__/CompatSsoLogin_lo
import { graphql, useFragment } from "react-relay";
import Block from "./Block";
import { Body, Bold, Code } from "./Typography";
import DateTime from "./DateTime";
type Props = {
login: CompatSsoLogin_login$key;
@@ -44,11 +45,11 @@ const CompatSsoLogin: React.FC<Props> = ({ login }) => {
info = (
<>
<Body>
Started: <Code>{data.session.createdAt}</Code>
Started: <DateTime datetime={data.session.createdAt} />
</Body>
{data.session.finishedAt ? (
<Body>
Finished: <Code>{data.session.createdAt}</Code>
Finished: <DateTime datetime={data.session.finishedAt} />
</Body>
) : null}
<Body>
@@ -61,7 +62,7 @@ const CompatSsoLogin: React.FC<Props> = ({ login }) => {
return (
<Block>
<Body>
Requested: <Code>{data.createdAt}</Code>
Requested: <DateTime datetime={data.createdAt} />
</Body>
{info}
<Body>

View File

@@ -0,0 +1,67 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import type { Meta, StoryObj } from "@storybook/react";
import { sub } from "date-fns";
import DateTime from "./DateTime";
const now = new Date(2022, 11, 16, 15, 32, 10);
const meta: Meta<typeof DateTime> = {
title: "UI/DateTime",
component: DateTime,
tags: ["docsPage"],
args: {
now,
datetime: sub(now, { minutes: 30 }),
},
argTypes: {
now: {
control: "date",
},
datetime: {
control: "date",
},
},
};
export default meta;
type Story = StoryObj<typeof DateTime>;
export const Basic: Story = {};
export const Now: Story = {
args: {
datetime: now,
},
};
export const SecondsAgo: Story = {
args: {
datetime: sub(now, { seconds: 30 }),
},
};
export const MinutesAgo: Story = {
args: {
datetime: sub(now, { minutes: 5 }),
},
};
export const HoursAgo: Story = {
args: {
datetime: sub(now, { hours: 5 }),
},
};

View File

@@ -0,0 +1,55 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {
formatISO,
intlFormat,
intlFormatDistance,
differenceInHours,
parseISO,
} from "date-fns";
type Props = {
className?: string;
datetime: Date | string;
now?: Date;
};
const DateTime = ({
datetime: datetimeProps,
now: nowProps,
className,
}: Props) => {
const datetime =
typeof datetimeProps === "string" ? parseISO(datetimeProps) : datetimeProps;
const now = nowProps || new Date();
const text =
Math.abs(differenceInHours(now, datetime, { roundingMethod: "round" })) > 1
? intlFormat(datetime, {
year: "numeric",
month: "short",
day: "numeric",
weekday: "short",
hour: "numeric",
minute: "numeric",
})
: intlFormatDistance(datetime, now);
return (
<time className={className} dateTime={formatISO(datetime)}>
{text}
</time>
);
};
export default DateTime;