diff --git a/frontend/src/components/OAuth2Session.tsx b/frontend/src/components/OAuth2Session.tsx index a364735f..eb1c0e4e 100644 --- a/frontend/src/components/OAuth2Session.tsx +++ b/frontend/src/components/OAuth2Session.tsx @@ -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 = ({ session }) => { createdAt={data.createdAt} finishedAt={data.finishedAt || undefined} clientName={data.client.clientName} + clientLogoUri={data.client.logoUri || undefined} > {!data.finishedAt && } diff --git a/frontend/src/components/Session/ClientAvatar.module.css b/frontend/src/components/Session/ClientAvatar.module.css new file mode 100644 index 00000000..6bb66a98 --- /dev/null +++ b/frontend/src/components/Session/ClientAvatar.module.css @@ -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; +} \ No newline at end of file diff --git a/frontend/src/components/Session/ClientAvatar.tsx b/frontend/src/components/Session/ClientAvatar.tsx new file mode 100644 index 00000000..5172bee2 --- /dev/null +++ b/frontend/src/components/Session/ClientAvatar.tsx @@ -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 ( + {name} + ); + } + if (withFallback) { + return ; + } + return null; +}; + +export default ClientAvatar; diff --git a/frontend/src/components/Session/Session.module.css b/frontend/src/components/Session/Session.module.css index 593c397c..12f0a220 100644 --- a/frontend/src/components/Session/Session.module.css +++ b/frontend/src/components/Session/Session.module.css @@ -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] { diff --git a/frontend/src/components/Session/Session.tsx b/frontend/src/components/Session/Session.tsx index 648aec3e..bb6fe561 100644 --- a/frontend/src/components/Session/Session.tsx +++ b/frontend/src/components/Session/Session.tsx @@ -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> = ( @@ -30,6 +31,7 @@ export type SessionProps = { createdAt: string; finishedAt?: string; clientName?: string; + clientLogoUri?: string; isCurrent?: boolean; }; const Session: React.FC> = ({ @@ -38,6 +40,7 @@ const Session: React.FC> = ({ createdAt, finishedAt, clientName, + clientLogoUri, isCurrent, children, }) => { @@ -56,7 +59,6 @@ const Session: React.FC> = ({
{name || id}
- Signed in @@ -67,7 +69,11 @@ const Session: React.FC> = ({ )} {!!clientName && ( - Client:{" "} + {" "} {clientName} diff --git a/frontend/src/components/Session/__snapshots__/Session.test.tsx.snap b/frontend/src/components/Session/__snapshots__/Session.test.tsx.snap index 2bc9f0bd..b9d579b1 100644 --- a/frontend/src/components/Session/__snapshots__/Session.test.tsx.snap +++ b/frontend/src/components/Session/__snapshots__/Session.test.tsx.snap @@ -81,7 +81,6 @@ exports[` > uses client name when truthy 1`] = `

- Client: = ({ session }) => { ]; const clientDetails = [ - { label: "Name", value: data.client.clientName }, + { + label: "Name", + value: ( + <> + + {data.client.clientName} + + ), + }, { label: "ID", value: {data.client.clientId} }, { label: "Uri", diff --git a/frontend/src/components/SessionDetail/SessionDetails.module.css b/frontend/src/components/SessionDetail/SessionDetails.module.css index 730be4c5..0da69e9c 100644 --- a/frontend/src/components/SessionDetail/SessionDetails.module.css +++ b/frontend/src/components/SessionDetail/SessionDetails.module.css @@ -33,4 +33,8 @@ .detail-value { overflow-wrap: anywhere; + display: flex; + flex-direction: row; + align-items: center; + gap: var(--cpd-space-1x); } diff --git a/frontend/src/components/__snapshots__/CompatSession.test.tsx.snap b/frontend/src/components/__snapshots__/CompatSession.test.tsx.snap index a1625b5a..1f0039f6 100644 --- a/frontend/src/components/__snapshots__/CompatSession.test.tsx.snap +++ b/frontend/src/components/__snapshots__/CompatSession.test.tsx.snap @@ -36,7 +36,6 @@ exports[` > renders a finished session 1`] = `

- Client: > renders an active session 1`] = `

- Client: > renders a finished session 1`] = `

- Client: > renders an active session 1`] = `

- Client: ; + 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" } }, ], }, }, diff --git a/frontend/src/pages/OAuth2Client.tsx b/frontend/src/pages/OAuth2Client.tsx index 656e2681..3af2e258 100644 --- a/frontend/src/pages/OAuth2Client.tsx +++ b/frontend/src/pages/OAuth2Client.tsx @@ -32,6 +32,7 @@ const QUERY = graphql(/* GraphQL */ ` tosUri policyUri redirectUris + logoUri } } `);