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

add client logo to session tile and detail

This commit is contained in:
Kerry Archibald
2023-09-08 13:31:03 +12:00
committed by Quentin Gliech
parent 0bee1284b2
commit 0d726cd7cb
13 changed files with 121 additions and 14 deletions

View File

@@ -34,6 +34,7 @@ export const OAUTH2_SESSION_FRAGMENT = graphql(/* GraphQL */ `
clientId
clientName
clientUri
logoUri
}
}
`);
@@ -48,6 +49,7 @@ export type Oauth2SessionType = {
clientId: string;
clientName: string;
clientUri: string;
logoUri: string | null;
};
};
@@ -103,6 +105,7 @@ const OAuth2Session: React.FC<Props> = ({ session }) => {
createdAt={data.createdAt}
finishedAt={data.finishedAt || undefined}
clientName={data.client.clientName}
clientLogoUri={data.client.logoUri || undefined}
>
{!data.finishedAt && <EndSessionButton endSession={onSessionEnd} />}
</Session>

View File

@@ -0,0 +1,23 @@
/* Copyright 2023 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.
*/
.avatar {
object-fit: cover;
overflow: hidden;
aspect-ratio: 1 / 1;
width: var(--mas-avatar-size);
border-radius: 50%;
display: inline-block;
}

View File

@@ -0,0 +1,51 @@
// Copyright 2023 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 { Avatar } from "@vector-im/compound-web";
import { CSSProperties } from "react";
import styles from "./ClientAvatar.module.css";
const ClientAvatar: React.FC<{
name: string;
logoUri?: string;
/**
* Render a fallback avatar using client name when truthy
* Otherwise return null when no logoUri
*/
withFallback?: boolean;
size: string;
}> = ({ name, logoUri, withFallback, size }) => {
// compound's lazy loading for avatars does not allow CORS requests
if (logoUri) {
return (
<img
className={styles.avatar}
src={logoUri}
alt={name}
style={
{
"--mas-avatar-size": size,
} as CSSProperties
}
/>
);
}
if (withFallback) {
return <Avatar size={size} id={name} name={name} src={logoUri} />;
}
return null;
};
export default ClientAvatar;

View File

@@ -21,6 +21,10 @@
}
.session-metadata {
display: flex;
flex-direction: row;
align-items: center;
gap: var(--cpd-space-1x);
color: var(--cpd-color-text-secondary);
&[data-finished] {

View File

@@ -18,6 +18,7 @@ import { ReactNode } from "react";
import Block from "../Block";
import DateTime from "../DateTime";
import ClientAvatar from "./ClientAvatar";
import styles from "./Session.module.css";
const SessionMetadata: React.FC<React.ComponentProps<typeof Body>> = (
@@ -30,6 +31,7 @@ export type SessionProps = {
createdAt: string;
finishedAt?: string;
clientName?: string;
clientLogoUri?: string;
isCurrent?: boolean;
};
const Session: React.FC<React.PropsWithChildren<SessionProps>> = ({
@@ -38,6 +40,7 @@ const Session: React.FC<React.PropsWithChildren<SessionProps>> = ({
createdAt,
finishedAt,
clientName,
clientLogoUri,
isCurrent,
children,
}) => {
@@ -56,7 +59,6 @@ const Session: React.FC<React.PropsWithChildren<SessionProps>> = ({
<H6 className={styles.sessionName} title={id}>
{name || id}
</H6>
<SessionMetadata weight="semibold">
Signed in <DateTime datetime={createdAt} />
</SessionMetadata>
@@ -67,7 +69,11 @@ const Session: React.FC<React.PropsWithChildren<SessionProps>> = ({
)}
{!!clientName && (
<SessionMetadata>
Client:{" "}
<ClientAvatar
size="var(--cpd-space-4x)"
name={clientName}
logoUri={clientLogoUri}
/>{" "}
<SessionMetadata weight="semibold" as="span">
{clientName}
</SessionMetadata>

View File

@@ -81,7 +81,6 @@ exports[`<Session /> > uses client name when truthy 1`] = `
<p
className="_font-body-sm-regular_1g2sj_45 _sessionMetadata_634806"
>
Client:
<span
className="_font-body-sm-semibold_1g2sj_49 _sessionMetadata_634806"

View File

@@ -24,6 +24,7 @@ import {
Oauth2SessionType,
endSessionFamily,
} from "../OAuth2Session";
import ClientAvatar from "../Session/ClientAvatar";
import EndSessionButton from "../Session/EndSessionButton";
import SessionDetails from "./SessionDetails";
@@ -70,7 +71,19 @@ const OAuth2SessionDetail: React.FC<Props> = ({ session }) => {
];
const clientDetails = [
{ label: "Name", value: data.client.clientName },
{
label: "Name",
value: (
<>
<ClientAvatar
name={data.client.clientName}
logoUri={data.client.logoUri || undefined}
size="var(--cpd-space-4x)"
/>
{data.client.clientName}
</>
),
},
{ label: "ID", value: <code>{data.client.clientId}</code> },
{
label: "Uri",

View File

@@ -33,4 +33,8 @@
.detail-value {
overflow-wrap: anywhere;
display: flex;
flex-direction: row;
align-items: center;
gap: var(--cpd-space-1x);
}

View File

@@ -36,7 +36,6 @@ exports[`<CompatSession /> > renders a finished session 1`] = `
<p
className="_font-body-sm-regular_1g2sj_45 _sessionMetadata_634806"
>
Client:
<span
className="_font-body-sm-semibold_1g2sj_49 _sessionMetadata_634806"
@@ -74,7 +73,6 @@ exports[`<CompatSession /> > renders an active session 1`] = `
<p
className="_font-body-sm-regular_1g2sj_45 _sessionMetadata_634806"
>
Client:
<span
className="_font-body-sm-semibold_1g2sj_49 _sessionMetadata_634806"

View File

@@ -36,7 +36,6 @@ exports[`<OAuth2Session /> > renders a finished session 1`] = `
<p
className="_font-body-sm-regular_1g2sj_45 _sessionMetadata_634806"
>
Client:
<span
className="_font-body-sm-semibold_1g2sj_49 _sessionMetadata_634806"
@@ -74,7 +73,6 @@ exports[`<OAuth2Session /> > renders an active session 1`] = `
<p
className="_font-body-sm-regular_1g2sj_45 _sessionMetadata_634806"
>
Client:
<span
className="_font-body-sm-semibold_1g2sj_49 _sessionMetadata_634806"

View File

@@ -29,7 +29,7 @@ const documents = {
types.EndCompatSessionDocument,
"\n query CompatSessionList(\n $userId: ID!\n $state: CompatSessionState\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n user(id: $userId) {\n id\n compatSessions(\n first: $first\n after: $after\n last: $last\n before: $before\n state: $state\n ) {\n edges {\n node {\n id\n ...CompatSession_session\n }\n }\n\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n":
types.CompatSessionListDocument,
"\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n createdAt\n finishedAt\n client {\n id\n clientId\n clientName\n clientUri\n }\n }\n":
"\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n createdAt\n finishedAt\n client {\n id\n clientId\n clientName\n clientUri\n logoUri\n }\n }\n":
types.OAuth2Session_SessionFragmentDoc,
"\n mutation EndOAuth2Session($id: ID!) {\n endOauth2Session(input: { oauth2SessionId: $id }) {\n status\n oauth2Session {\n id\n ...OAuth2Session_session\n }\n }\n }\n":
types.EndOAuth2SessionDocument,
@@ -65,7 +65,7 @@ const documents = {
types.ResendVerificationEmailDocument,
"\n query BrowserSessionQuery($id: ID!) {\n browserSession(id: $id) {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n user {\n id\n username\n }\n }\n }\n":
types.BrowserSessionQueryDocument,
"\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n":
"\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n logoUri\n }\n }\n":
types.OAuth2ClientQueryDocument,
"\n query SessionsOverviewQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserSessionsOverview_user\n }\n }\n }\n":
types.SessionsOverviewQueryDocument,
@@ -139,8 +139,8 @@ export function graphql(
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
source: "\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n createdAt\n finishedAt\n client {\n id\n clientId\n clientName\n clientUri\n }\n }\n",
): (typeof documents)["\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n createdAt\n finishedAt\n client {\n id\n clientId\n clientName\n clientUri\n }\n }\n"];
source: "\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n createdAt\n finishedAt\n client {\n id\n clientId\n clientName\n clientUri\n logoUri\n }\n }\n",
): (typeof documents)["\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n createdAt\n finishedAt\n client {\n id\n clientId\n clientName\n clientUri\n logoUri\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -247,8 +247,8 @@ export function graphql(
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
source: "\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n",
): (typeof documents)["\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n"];
source: "\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n logoUri\n }\n }\n",
): (typeof documents)["\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n logoUri\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/

View File

@@ -1161,6 +1161,7 @@ export type OAuth2Session_SessionFragment = {
clientId: string;
clientName?: string | null;
clientUri?: any | null;
logoUri?: any | null;
};
} & { " $fragmentName"?: "OAuth2Session_SessionFragment" };
@@ -1505,6 +1506,7 @@ export type OAuth2ClientQueryQuery = {
tosUri?: any | null;
policyUri?: any | null;
redirectUris: Array<any>;
logoUri?: any | null;
} | null;
};
@@ -1631,6 +1633,7 @@ export const OAuth2Session_SessionFragmentDoc = {
{ kind: "Field", name: { kind: "Name", value: "clientId" } },
{ kind: "Field", name: { kind: "Name", value: "clientName" } },
{ kind: "Field", name: { kind: "Name", value: "clientUri" } },
{ kind: "Field", name: { kind: "Name", value: "logoUri" } },
],
},
},
@@ -2688,6 +2691,7 @@ export const EndOAuth2SessionDocument = {
{ kind: "Field", name: { kind: "Name", value: "clientId" } },
{ kind: "Field", name: { kind: "Name", value: "clientName" } },
{ kind: "Field", name: { kind: "Name", value: "clientUri" } },
{ kind: "Field", name: { kind: "Name", value: "logoUri" } },
],
},
},
@@ -2922,6 +2926,7 @@ export const OAuth2SessionListQueryDocument = {
{ kind: "Field", name: { kind: "Name", value: "clientId" } },
{ kind: "Field", name: { kind: "Name", value: "clientName" } },
{ kind: "Field", name: { kind: "Name", value: "clientUri" } },
{ kind: "Field", name: { kind: "Name", value: "logoUri" } },
],
},
},
@@ -3061,6 +3066,7 @@ export const SessionQueryDocument = {
{ kind: "Field", name: { kind: "Name", value: "clientId" } },
{ kind: "Field", name: { kind: "Name", value: "clientName" } },
{ kind: "Field", name: { kind: "Name", value: "clientUri" } },
{ kind: "Field", name: { kind: "Name", value: "logoUri" } },
],
},
},
@@ -4170,6 +4176,7 @@ export const OAuth2ClientQueryDocument = {
kind: "Field",
name: { kind: "Name", value: "redirectUris" },
},
{ kind: "Field", name: { kind: "Name", value: "logoUri" } },
],
},
},

View File

@@ -32,6 +32,7 @@ const QUERY = graphql(/* GraphQL */ `
tosUri
policyUri
redirectUris
logoUri
}
}
`);