mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-16 06:41:11 +00:00
feat: display all accessible oidc clients in the dashboard (#832)
Co-authored-by: Kyle Mendell <ksm@ofkm.us>
This commit is contained in:
@@ -4,23 +4,26 @@
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import userStore from '$lib/stores/user-store';
|
||||
import type { AuthorizedOidcClient, OidcClientMetaData } from '$lib/types/oidc.type';
|
||||
import type { AccessibleOidcClient, OidcClientMetaData } from '$lib/types/oidc.type';
|
||||
import { cachedApplicationLogo, cachedOidcClientLogo } from '$lib/utils/cached-image-util';
|
||||
import {
|
||||
LucideBan,
|
||||
LucideEllipsisVertical,
|
||||
LucideExternalLink,
|
||||
LucideLogIn,
|
||||
LucidePencil
|
||||
} from '@lucide/svelte';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { mode } from 'mode-watcher';
|
||||
|
||||
let {
|
||||
authorizedClient,
|
||||
client,
|
||||
onRevoke
|
||||
}: {
|
||||
authorizedClient: AuthorizedOidcClient;
|
||||
client: AccessibleOidcClient;
|
||||
onRevoke: (client: OidcClientMetaData) => Promise<void>;
|
||||
} = $props();
|
||||
|
||||
@@ -28,7 +31,7 @@
|
||||
</script>
|
||||
|
||||
<Card.Root
|
||||
class="border-muted group h-[140px] p-5 transition-all duration-200 hover:shadow-md"
|
||||
class="border-muted group relative h-[140px] p-5 transition-all duration-200 hover:shadow-md"
|
||||
data-testid="authorized-oidc-client-card"
|
||||
>
|
||||
<Card.Content class=" p-0">
|
||||
@@ -36,60 +39,84 @@
|
||||
<div class="aspect-square h-[56px]">
|
||||
<ImageBox
|
||||
class="grow rounded-lg object-contain"
|
||||
src={authorizedClient.client.hasLogo
|
||||
? cachedOidcClientLogo.getUrl(authorizedClient.client.id)
|
||||
src={client.hasLogo
|
||||
? cachedOidcClientLogo.getUrl(client.id)
|
||||
: cachedApplicationLogo.getUrl(isLightMode)}
|
||||
alt={m.name_logo({ name: authorizedClient.client.name })}
|
||||
alt={m.name_logo({ name: client.name })}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex w-full justify-between gap-3">
|
||||
<div>
|
||||
<div class="mb-1 flex items-start gap-2">
|
||||
<h3
|
||||
class="text-foreground line-clamp-2 leading-tight font-semibold break-words break-all text-ellipsis"
|
||||
class="text-foreground line-clamp-2 text-ellipsis break-words break-all font-semibold leading-tight"
|
||||
>
|
||||
{authorizedClient.client.name}
|
||||
{client.name}
|
||||
</h3>
|
||||
</div>
|
||||
{#if authorizedClient.client.launchURL}
|
||||
{#if client.launchURL}
|
||||
<p
|
||||
class="text-muted-foreground line-clamp-1 text-xs break-words break-all text-ellipsis"
|
||||
class="text-muted-foreground line-clamp-1 text-ellipsis break-words break-all text-xs"
|
||||
>
|
||||
{new URL(authorizedClient.client.launchURL).hostname}
|
||||
{new URL(client.launchURL).hostname}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
<LucideEllipsisVertical class="size-4" />
|
||||
<span class="sr-only">{m.toggle_menu()}</span>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content align="end">
|
||||
{#if $userStore?.isAdmin}
|
||||
<DropdownMenu.Item
|
||||
onclick={() => goto(`/settings/admin/oidc-clients/${authorizedClient.client.id}`)}
|
||||
><LucidePencil class="mr-2 size-4" /> {m.edit()}</DropdownMenu.Item
|
||||
>
|
||||
{/if}
|
||||
<DropdownMenu.Item
|
||||
class="text-red-500 focus:!text-red-700"
|
||||
onclick={() => onRevoke(authorizedClient.client)}
|
||||
><LucideBan class="mr-2 size-4" />{m.revoke()}</DropdownMenu.Item
|
||||
>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</div>
|
||||
{#if $userStore?.isAdmin || client.lastUsedAt}
|
||||
<div>
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
<LucideEllipsisVertical class="size-4" />
|
||||
<span class="sr-only">{m.toggle_menu()}</span>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content align="end">
|
||||
{#if $userStore?.isAdmin}
|
||||
<DropdownMenu.Item
|
||||
onclick={() => goto(`/settings/admin/oidc-clients/${client.id}`)}
|
||||
><LucidePencil class="mr-2 size-4" /> {m.edit()}</DropdownMenu.Item
|
||||
>
|
||||
{/if}
|
||||
{#if client.lastUsedAt}
|
||||
<DropdownMenu.Item
|
||||
class="text-red-500 focus:!text-red-700"
|
||||
onclick={() => onRevoke(client)}
|
||||
><LucideBan class="mr-2 size-4" />{m.revoke()}</DropdownMenu.Item
|
||||
>
|
||||
{/if}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 flex justify-end">
|
||||
<div class="mt-2 flex items-end justify-between">
|
||||
{#if client.lastUsedAt}
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<p class="text-muted-foreground flex items-center text-xs">
|
||||
<LucideLogIn class="mr-1 size-3" />
|
||||
{formatDistanceToNow(client.lastUsedAt, { addSuffix: true })}
|
||||
</p>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content
|
||||
>{m.last_signed_in_ago({
|
||||
time: formatDistanceToNow(client.lastUsedAt)
|
||||
})}</Tooltip.Content
|
||||
>
|
||||
</Tooltip.Root></Tooltip.Provider
|
||||
>
|
||||
{:else}
|
||||
<div></div>
|
||||
{/if}
|
||||
<Button
|
||||
href={authorizedClient.client.launchURL}
|
||||
href={client.launchURL}
|
||||
target="_blank"
|
||||
size="sm"
|
||||
class="h-8 text-xs"
|
||||
disabled={!authorizedClient.client.launchURL}
|
||||
rel="noopener noreferrer"
|
||||
disabled={!client.launchURL}
|
||||
>
|
||||
{m.launch()}
|
||||
<LucideExternalLink class="ml-1 size-3" />
|
||||
|
||||
Reference in New Issue
Block a user