mirror of
https://github.com/pocket-id/pocket-id.git
synced 2025-12-23 09:15:13 +03:00
fix: make sorting consistent around tables
This commit is contained in:
@@ -18,35 +18,21 @@
|
|||||||
selectedIds = $bindable(),
|
selectedIds = $bindable(),
|
||||||
withoutSearch = false,
|
withoutSearch = false,
|
||||||
selectionDisabled = false,
|
selectionDisabled = false,
|
||||||
defaultSort,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
columns,
|
columns,
|
||||||
rows
|
rows
|
||||||
}: {
|
}: {
|
||||||
items: Paginated<T>;
|
items: Paginated<T>;
|
||||||
requestOptions?: SearchPaginationSortRequest;
|
requestOptions: SearchPaginationSortRequest;
|
||||||
selectedIds?: string[];
|
selectedIds?: string[];
|
||||||
withoutSearch?: boolean;
|
withoutSearch?: boolean;
|
||||||
selectionDisabled?: boolean;
|
selectionDisabled?: boolean;
|
||||||
defaultSort?: { column: string; direction: 'asc' | 'desc' };
|
|
||||||
onRefresh: (requestOptions: SearchPaginationSortRequest) => Promise<Paginated<T>>;
|
onRefresh: (requestOptions: SearchPaginationSortRequest) => Promise<Paginated<T>>;
|
||||||
columns: { label: string; hidden?: boolean; sortColumn?: string }[];
|
columns: { label: string; hidden?: boolean; sortColumn?: string }[];
|
||||||
rows: Snippet<[{ item: T }]>;
|
rows: Snippet<[{ item: T }]>;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let searchValue = $state('');
|
let searchValue = $state('');
|
||||||
|
|
||||||
if (!requestOptions) {
|
|
||||||
requestOptions = {
|
|
||||||
search: '',
|
|
||||||
sort: defaultSort,
|
|
||||||
pagination: {
|
|
||||||
page: items.pagination.currentPage,
|
|
||||||
limit: items.pagination.itemsPerPage
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let availablePageSizes: number[] = [10, 20, 50, 100];
|
let availablePageSizes: number[] = [10, 20, 50, 100];
|
||||||
|
|
||||||
let allChecked = $derived.by(() => {
|
let allChecked = $derived.by(() => {
|
||||||
@@ -83,20 +69,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onPageChange(page: number) {
|
async function onPageChange(page: number) {
|
||||||
requestOptions!.pagination = { limit: items.pagination.itemsPerPage, page };
|
requestOptions.pagination = { limit: items.pagination.itemsPerPage, page };
|
||||||
onRefresh(requestOptions!);
|
onRefresh(requestOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onPageSizeChange(size: number) {
|
async function onPageSizeChange(size: number) {
|
||||||
requestOptions!.pagination = { limit: size, page: 1 };
|
requestOptions.pagination = { limit: size, page: 1 };
|
||||||
onRefresh(requestOptions!);
|
onRefresh(requestOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSort(column?: string, direction: 'asc' | 'desc' = 'asc') {
|
async function onSort(column?: string, direction: 'asc' | 'desc' = 'asc') {
|
||||||
if (!column) return;
|
if (!column) return;
|
||||||
|
|
||||||
requestOptions!.sort = { column, direction };
|
requestOptions.sort = { column, direction };
|
||||||
onRefresh(requestOptions!);
|
onRefresh(requestOptions);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,32 +2,44 @@
|
|||||||
import AdvancedTable from '$lib/components/advanced-table.svelte';
|
import AdvancedTable from '$lib/components/advanced-table.svelte';
|
||||||
import * as Table from '$lib/components/ui/table';
|
import * as Table from '$lib/components/ui/table';
|
||||||
import UserGroupService from '$lib/services/user-group-service';
|
import UserGroupService from '$lib/services/user-group-service';
|
||||||
import type { Paginated } from '$lib/types/pagination.type';
|
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||||
import type { UserGroup } from '$lib/types/user-group.type';
|
import type { UserGroup } from '$lib/types/user-group.type';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
groups: initialGroups,
|
|
||||||
selectionDisabled = false,
|
selectionDisabled = false,
|
||||||
selectedGroupIds = $bindable()
|
selectedGroupIds = $bindable()
|
||||||
}: {
|
}: {
|
||||||
groups: Paginated<UserGroup>;
|
|
||||||
selectionDisabled?: boolean;
|
selectionDisabled?: boolean;
|
||||||
selectedGroupIds: string[];
|
selectedGroupIds: string[];
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
const userGroupService = new UserGroupService();
|
const userGroupService = new UserGroupService();
|
||||||
|
|
||||||
let groups = $state(initialGroups);
|
let groups: Paginated<UserGroup> | undefined = $state();
|
||||||
|
let requestOptions: SearchPaginationSortRequest = $state({
|
||||||
|
sort: {
|
||||||
|
column: 'friendlyName',
|
||||||
|
direction: 'asc'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
groups = await userGroupService.list(requestOptions);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AdvancedTable
|
{#if groups}
|
||||||
items={groups}
|
<AdvancedTable
|
||||||
onRefresh={async (o) => (groups = await userGroupService.list(o))}
|
items={groups}
|
||||||
columns={[{ label: 'Name', sortColumn: 'name' }]}
|
{requestOptions}
|
||||||
bind:selectedIds={selectedGroupIds}
|
onRefresh={async (o) => (groups = await userGroupService.list(o))}
|
||||||
{selectionDisabled}
|
columns={[{ label: 'Name', sortColumn: 'friendlyName' }]}
|
||||||
>
|
bind:selectedIds={selectedGroupIds}
|
||||||
{#snippet rows({ item })}
|
{selectionDisabled}
|
||||||
<Table.Cell>{item.name}</Table.Cell>
|
>
|
||||||
{/snippet}
|
{#snippet rows({ item })}
|
||||||
</AdvancedTable>
|
<Table.Cell>{item.name}</Table.Cell>
|
||||||
|
{/snippet}
|
||||||
|
</AdvancedTable>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -6,19 +6,14 @@ import type { PageServerLoad } from './$types';
|
|||||||
export const load: PageServerLoad = async ({ cookies }) => {
|
export const load: PageServerLoad = async ({ cookies }) => {
|
||||||
const oidcService = new OIDCService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
const oidcService = new OIDCService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
||||||
|
|
||||||
// Create request options with default sorting
|
const clientsRequestOptions: SearchPaginationSortRequest = {
|
||||||
const requestOptions: SearchPaginationSortRequest = {
|
|
||||||
sort: {
|
sort: {
|
||||||
column: 'name',
|
column: 'name',
|
||||||
direction: 'asc'
|
direction: 'asc'
|
||||||
},
|
|
||||||
pagination: {
|
|
||||||
page: 1,
|
|
||||||
limit: 10
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const clients = await oidcService.listClients(requestOptions);
|
const clients = await oidcService.listClients(clientsRequestOptions);
|
||||||
|
|
||||||
return clients;
|
return { clients, clientsRequestOptions };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
import OIDCClientList from './oidc-client-list.svelte';
|
import OIDCClientList from './oidc-client-list.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let clients = $state(data);
|
let clients = $state(data.clients);
|
||||||
|
let clientsRequestOptions = $state(data.clientsRequestOptions);
|
||||||
let expandAddClient = $state(false);
|
let expandAddClient = $state(false);
|
||||||
|
|
||||||
const oidcService = new OIDCService();
|
const oidcService = new OIDCService();
|
||||||
@@ -71,6 +72,6 @@
|
|||||||
<Card.Title>Manage OIDC Clients</Card.Title>
|
<Card.Title>Manage OIDC Clients</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<OIDCClientList {clients} />
|
<OIDCClientList {clients} requestOptions={clientsRequestOptions} />
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import Label from '$lib/components/ui/label/label.svelte';
|
import Label from '$lib/components/ui/label/label.svelte';
|
||||||
import UserGroupSelection from '$lib/components/user-group-selection.svelte';
|
import UserGroupSelection from '$lib/components/user-group-selection.svelte';
|
||||||
import OidcService from '$lib/services/oidc-service';
|
import OidcService from '$lib/services/oidc-service';
|
||||||
import UserGroupService from '$lib/services/user-group-service';
|
|
||||||
import clientSecretStore from '$lib/stores/client-secret-store';
|
import clientSecretStore from '$lib/stores/client-secret-store';
|
||||||
import type { OidcClientCreateWithLogo } from '$lib/types/oidc.type';
|
import type { OidcClientCreateWithLogo } from '$lib/types/oidc.type';
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
@@ -26,7 +25,6 @@
|
|||||||
let showAllDetails = $state(false);
|
let showAllDetails = $state(false);
|
||||||
|
|
||||||
const oidcService = new OidcService();
|
const oidcService = new OidcService();
|
||||||
const userGroupService = new UserGroupService();
|
|
||||||
|
|
||||||
const setupDetails = $state({
|
const setupDetails = $state({
|
||||||
'Authorization URL': `https://${$page.url.hostname}/authorize`,
|
'Authorization URL': `https://${$page.url.hostname}/authorize`,
|
||||||
@@ -177,9 +175,7 @@
|
|||||||
title="Allowed User Groups"
|
title="Allowed User Groups"
|
||||||
description="Add user groups to this client to restrict access to users in these groups. If no user groups are selected, all users will have access to this client."
|
description="Add user groups to this client to restrict access to users in these groups. If no user groups are selected, all users will have access to this client."
|
||||||
>
|
>
|
||||||
{#await userGroupService.list() then groups}
|
<UserGroupSelection bind:selectedGroupIds={client.allowedUserGroupIds} />
|
||||||
<UserGroupSelection {groups} bind:selectedGroupIds={client.allowedUserGroupIds} />
|
|
||||||
{/await}
|
|
||||||
<div class="mt-5 flex justify-end">
|
<div class="mt-5 flex justify-end">
|
||||||
<Button on:click={() => updateUserGroupClients(client.allowedUserGroupIds)}>Save</Button>
|
<Button on:click={() => updateUserGroupClients(client.allowedUserGroupIds)}>Save</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,23 +12,14 @@
|
|||||||
import OneTimeLinkModal from './client-secret.svelte';
|
import OneTimeLinkModal from './client-secret.svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
clients: initialClients
|
clients = $bindable(),
|
||||||
|
requestOptions
|
||||||
}: {
|
}: {
|
||||||
clients: Paginated<OidcClient>;
|
clients: Paginated<OidcClient>;
|
||||||
|
requestOptions: SearchPaginationSortRequest;
|
||||||
} = $props();
|
} = $props();
|
||||||
let clients = $state<Paginated<OidcClient>>(initialClients);
|
|
||||||
let oneTimeLink = $state<string | null>(null);
|
|
||||||
let requestOptions: SearchPaginationSortRequest | undefined = $state({
|
|
||||||
sort: { column: 'name', direction: 'asc' },
|
|
||||||
pagination: {
|
|
||||||
page: initialClients.pagination.currentPage,
|
|
||||||
limit: initialClients.pagination.itemsPerPage
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$effect(() => {
|
let oneTimeLink = $state<string | null>(null);
|
||||||
clients = initialClients;
|
|
||||||
});
|
|
||||||
|
|
||||||
const oidcService = new OIDCService();
|
const oidcService = new OIDCService();
|
||||||
|
|
||||||
@@ -56,7 +47,6 @@
|
|||||||
<AdvancedTable
|
<AdvancedTable
|
||||||
items={clients}
|
items={clients}
|
||||||
{requestOptions}
|
{requestOptions}
|
||||||
defaultSort={{ column: 'name', direction: 'asc' }}
|
|
||||||
onRefresh={async (o) => (clients = await oidcService.listClients(o))}
|
onRefresh={async (o) => (clients = await oidcService.listClients(o))}
|
||||||
columns={[
|
columns={[
|
||||||
{ label: 'Logo' },
|
{ label: 'Logo' },
|
||||||
|
|||||||
@@ -6,18 +6,13 @@ import type { PageServerLoad } from './$types';
|
|||||||
export const load: PageServerLoad = async ({ cookies }) => {
|
export const load: PageServerLoad = async ({ cookies }) => {
|
||||||
const userGroupService = new UserGroupService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
const userGroupService = new UserGroupService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
||||||
|
|
||||||
// Create request options with default sorting
|
const userGroupsRequestOptions: SearchPaginationSortRequest = {
|
||||||
const requestOptions: SearchPaginationSortRequest = {
|
|
||||||
sort: {
|
sort: {
|
||||||
column: 'friendlyName',
|
column: 'friendlyName',
|
||||||
direction: 'asc'
|
direction: 'asc'
|
||||||
},
|
},
|
||||||
pagination: {
|
|
||||||
page: 1,
|
|
||||||
limit: 10
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const userGroups = await userGroupService.list(requestOptions);
|
const userGroups = await userGroupService.list(userGroupsRequestOptions);
|
||||||
return userGroups;
|
return {userGroups, userGroupsRequestOptions};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
import UserGroupList from './user-group-list.svelte';
|
import UserGroupList from './user-group-list.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let userGroups: Paginated<UserGroupWithUserCount> = $state(data);
|
let userGroups = $state(data.userGroups);
|
||||||
|
let userGroupsRequestOptions = $state(data.userGroupsRequestOptions);
|
||||||
let expandAddUserGroup = $state(false);
|
let expandAddUserGroup = $state(false);
|
||||||
|
|
||||||
const userGroupService = new UserGroupService();
|
const userGroupService = new UserGroupService();
|
||||||
@@ -68,6 +69,6 @@
|
|||||||
<Card.Title>Manage User Groups</Card.Title>
|
<Card.Title>Manage User Groups</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<UserGroupList {userGroups} />
|
<UserGroupList {userGroups} requestOptions={userGroupsRequestOptions} />
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|||||||
@@ -6,14 +6,13 @@
|
|||||||
import * as Card from '$lib/components/ui/card';
|
import * as Card from '$lib/components/ui/card';
|
||||||
import CustomClaimService from '$lib/services/custom-claim-service';
|
import CustomClaimService from '$lib/services/custom-claim-service';
|
||||||
import UserGroupService from '$lib/services/user-group-service';
|
import UserGroupService from '$lib/services/user-group-service';
|
||||||
import UserService from '$lib/services/user-service';
|
import appConfigStore from '$lib/stores/application-configuration-store';
|
||||||
import type { UserGroupCreate } from '$lib/types/user-group.type';
|
import type { UserGroupCreate } from '$lib/types/user-group.type';
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
import { LucideChevronLeft } from 'lucide-svelte';
|
import { LucideChevronLeft } from 'lucide-svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import UserGroupForm from '../user-group-form.svelte';
|
import UserGroupForm from '../user-group-form.svelte';
|
||||||
import UserSelection from '../user-selection.svelte';
|
import UserSelection from '../user-selection.svelte';
|
||||||
import appConfigStore from '$lib/stores/application-configuration-store';
|
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let userGroup = $state({
|
let userGroup = $state({
|
||||||
@@ -22,7 +21,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const userGroupService = new UserGroupService();
|
const userGroupService = new UserGroupService();
|
||||||
const userService = new UserService();
|
|
||||||
const customClaimService = new CustomClaimService();
|
const customClaimService = new CustomClaimService();
|
||||||
|
|
||||||
async function updateUserGroup(updatedUserGroup: UserGroupCreate) {
|
async function updateUserGroup(updatedUserGroup: UserGroupCreate) {
|
||||||
@@ -86,16 +84,14 @@
|
|||||||
</Card.Header>
|
</Card.Header>
|
||||||
|
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
{#await userService.list() then users}
|
<UserSelection
|
||||||
<UserSelection
|
bind:selectedUserIds={userGroup.userIds}
|
||||||
{users}
|
selectionDisabled={!!userGroup.ldapId && $appConfigStore.ldapEnabled}
|
||||||
bind:selectedUserIds={userGroup.userIds}
|
/>
|
||||||
selectionDisabled={!!userGroup.ldapId && $appConfigStore.ldapEnabled}
|
|
||||||
/>
|
|
||||||
{/await}
|
|
||||||
<div class="mt-5 flex justify-end">
|
<div class="mt-5 flex justify-end">
|
||||||
<Button disabled={!!userGroup.ldapId && $appConfigStore.ldapEnabled} on:click={() => updateUserGroupUsers(userGroup.userIds)}
|
<Button
|
||||||
>Save</Button
|
disabled={!!userGroup.ldapId && $appConfigStore.ldapEnabled}
|
||||||
|
on:click={() => updateUserGroupUsers(userGroup.userIds)}>Save</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
|
|||||||
@@ -14,17 +14,13 @@
|
|||||||
import Ellipsis from 'lucide-svelte/icons/ellipsis';
|
import Ellipsis from 'lucide-svelte/icons/ellipsis';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
|
|
||||||
let { userGroups: initialUserGroups }: { userGroups: Paginated<UserGroupWithUserCount> } =
|
let {
|
||||||
$props();
|
userGroups,
|
||||||
|
requestOptions
|
||||||
let userGroups = $state<Paginated<UserGroupWithUserCount>>(initialUserGroups);
|
}: {
|
||||||
let requestOptions: SearchPaginationSortRequest | undefined = $state({
|
userGroups: Paginated<UserGroupWithUserCount>;
|
||||||
sort: { column: 'friendlyName', direction: 'asc' },
|
requestOptions: SearchPaginationSortRequest;
|
||||||
pagination: {
|
} = $props();
|
||||||
page: initialUserGroups.pagination.currentPage,
|
|
||||||
limit: initialUserGroups.pagination.itemsPerPage
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const userGroupService = new UserGroupService();
|
const userGroupService = new UserGroupService();
|
||||||
|
|
||||||
@@ -53,7 +49,6 @@
|
|||||||
items={userGroups}
|
items={userGroups}
|
||||||
onRefresh={async (o) => (userGroups = await userGroupService.list(o))}
|
onRefresh={async (o) => (userGroups = await userGroupService.list(o))}
|
||||||
{requestOptions}
|
{requestOptions}
|
||||||
defaultSort={{ column: 'friendlyName', direction: 'asc' }}
|
|
||||||
columns={[
|
columns={[
|
||||||
{ label: 'Friendly Name', sortColumn: 'friendlyName' },
|
{ label: 'Friendly Name', sortColumn: 'friendlyName' },
|
||||||
{ label: 'Name', sortColumn: 'name' },
|
{ label: 'Name', sortColumn: 'name' },
|
||||||
|
|||||||
@@ -4,39 +4,46 @@
|
|||||||
import UserService from '$lib/services/user-service';
|
import UserService from '$lib/services/user-service';
|
||||||
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||||
import type { User } from '$lib/types/user.type';
|
import type { User } from '$lib/types/user.type';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
users: initialUsers,
|
|
||||||
selectionDisabled = false,
|
selectionDisabled = false,
|
||||||
selectedUserIds = $bindable()
|
selectedUserIds = $bindable()
|
||||||
}: { users: Paginated<User>; selectionDisabled?: boolean; selectedUserIds: string[] } = $props();
|
}: {
|
||||||
let requestOptions: SearchPaginationSortRequest | undefined = $state({
|
selectionDisabled?: boolean;
|
||||||
sort: { column: 'friendlyName', direction: 'asc' },
|
selectedUserIds: string[];
|
||||||
pagination: {
|
} = $props();
|
||||||
page: initialUsers.pagination.currentPage,
|
|
||||||
limit: initialUsers.pagination.itemsPerPage
|
const userService = new UserService();
|
||||||
|
|
||||||
|
let users: Paginated<User> | undefined = $state();
|
||||||
|
let requestOptions: SearchPaginationSortRequest = $state({
|
||||||
|
sort: {
|
||||||
|
column: 'firstName',
|
||||||
|
direction: 'asc'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let users = $state<Paginated<User>>(initialUsers);
|
onMount(async () => {
|
||||||
|
users = await userService.list(requestOptions);
|
||||||
const userService = new UserService();
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AdvancedTable
|
{#if users}
|
||||||
items={users}
|
<AdvancedTable
|
||||||
onRefresh={async (o) => (users = await userService.list(o))}
|
items={users}
|
||||||
{requestOptions}
|
onRefresh={async (o) => (users = await userService.list(o))}
|
||||||
defaultSort={{ column: 'name', direction: 'asc' }}
|
{requestOptions}
|
||||||
columns={[
|
columns={[
|
||||||
{ label: 'Name', sortColumn: 'name' },
|
{ label: 'Name', sortColumn: 'firstName' },
|
||||||
{ label: 'Email', sortColumn: 'email' }
|
{ label: 'Email', sortColumn: 'email' }
|
||||||
]}
|
]}
|
||||||
bind:selectedIds={selectedUserIds}
|
bind:selectedIds={selectedUserIds}
|
||||||
{selectionDisabled}
|
{selectionDisabled}
|
||||||
>
|
>
|
||||||
{#snippet rows({ item })}
|
{#snippet rows({ item })}
|
||||||
<Table.Cell>{item.firstName} {item.lastName}</Table.Cell>
|
<Table.Cell>{item.firstName} {item.lastName}</Table.Cell>
|
||||||
<Table.Cell>{item.email}</Table.Cell>
|
<Table.Cell>{item.email}</Table.Cell>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</AdvancedTable>
|
</AdvancedTable>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -6,18 +6,13 @@ import type { PageServerLoad } from './$types';
|
|||||||
export const load: PageServerLoad = async ({ cookies }) => {
|
export const load: PageServerLoad = async ({ cookies }) => {
|
||||||
const userService = new UserService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
const userService = new UserService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
||||||
|
|
||||||
// Create request options with default sorting
|
const usersRequestOptions: SearchPaginationSortRequest = {
|
||||||
const requestOptions: SearchPaginationSortRequest = {
|
|
||||||
sort: {
|
sort: {
|
||||||
column: 'firstName',
|
column: 'firstName',
|
||||||
direction: 'asc'
|
direction: 'asc'
|
||||||
},
|
|
||||||
pagination: {
|
|
||||||
page: 1,
|
|
||||||
limit: 10
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const users = await userService.list(requestOptions);
|
const users = await userService.list(usersRequestOptions);
|
||||||
return users;
|
return {users, usersRequestOptions};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
import * as Card from '$lib/components/ui/card';
|
import * as Card from '$lib/components/ui/card';
|
||||||
import UserService from '$lib/services/user-service';
|
import UserService from '$lib/services/user-service';
|
||||||
import appConfigStore from '$lib/stores/application-configuration-store';
|
import appConfigStore from '$lib/stores/application-configuration-store';
|
||||||
import type { Paginated } from '$lib/types/pagination.type';
|
import type { UserCreate } from '$lib/types/user.type';
|
||||||
import type { User, UserCreate } from '$lib/types/user.type';
|
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
import { LucideMinus } from 'lucide-svelte';
|
import { LucideMinus } from 'lucide-svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
@@ -13,7 +12,9 @@
|
|||||||
import UserList from './user-list.svelte';
|
import UserList from './user-list.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let users: Paginated<User> = $state(data);
|
let users = $state(data.users);
|
||||||
|
let usersRequestOptions = $state(data.usersRequestOptions);
|
||||||
|
|
||||||
let expandAddUser = $state(false);
|
let expandAddUser = $state(false);
|
||||||
|
|
||||||
const userService = new UserService();
|
const userService = new UserService();
|
||||||
@@ -28,7 +29,7 @@
|
|||||||
success = false;
|
success = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
users = await userService.list();
|
users = await userService.list(usersRequestOptions);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -67,6 +68,6 @@
|
|||||||
<Card.Title>Manage Users</Card.Title>
|
<Card.Title>Manage Users</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<UserList {users} />
|
<UserList {users} requestOptions={usersRequestOptions} />
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|||||||
@@ -5,15 +5,14 @@
|
|||||||
import Badge from '$lib/components/ui/badge/badge.svelte';
|
import Badge from '$lib/components/ui/badge/badge.svelte';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
import * as Card from '$lib/components/ui/card';
|
import * as Card from '$lib/components/ui/card';
|
||||||
|
import UserGroupSelection from '$lib/components/user-group-selection.svelte';
|
||||||
import CustomClaimService from '$lib/services/custom-claim-service';
|
import CustomClaimService from '$lib/services/custom-claim-service';
|
||||||
import UserGroupService from '$lib/services/user-group-service';
|
|
||||||
import UserService from '$lib/services/user-service';
|
import UserService from '$lib/services/user-service';
|
||||||
import appConfigStore from '$lib/stores/application-configuration-store';
|
import appConfigStore from '$lib/stores/application-configuration-store';
|
||||||
import type { UserCreate } from '$lib/types/user.type';
|
import type { UserCreate } from '$lib/types/user.type';
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
import { LucideChevronLeft } from 'lucide-svelte';
|
import { LucideChevronLeft } from 'lucide-svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import UserGroupSelection from '$lib/components/user-group-selection.svelte';
|
|
||||||
import UserForm from '../user-form.svelte';
|
import UserForm from '../user-form.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
@@ -24,7 +23,6 @@
|
|||||||
|
|
||||||
const userService = new UserService();
|
const userService = new UserService();
|
||||||
const customClaimService = new CustomClaimService();
|
const customClaimService = new CustomClaimService();
|
||||||
const userGroupService = new UserGroupService();
|
|
||||||
|
|
||||||
async function updateUserGroups(userIds: string[]) {
|
async function updateUserGroups(userIds: string[]) {
|
||||||
await userService
|
await userService
|
||||||
@@ -101,14 +99,10 @@
|
|||||||
title="User Groups"
|
title="User Groups"
|
||||||
description="Manage which groups this user belongs to."
|
description="Manage which groups this user belongs to."
|
||||||
>
|
>
|
||||||
{#await userGroupService.list() then groups}
|
<UserGroupSelection
|
||||||
<UserGroupSelection
|
bind:selectedGroupIds={user.userGroupIds}
|
||||||
{groups}
|
selectionDisabled={!!user.ldapId && $appConfigStore.ldapEnabled}
|
||||||
bind:selectedGroupIds={user.userGroupIds}
|
/>
|
||||||
selectionDisabled={!!user.ldapId && $appConfigStore.ldapEnabled}
|
|
||||||
/>
|
|
||||||
{/await}
|
|
||||||
|
|
||||||
<div class="mt-5 flex justify-end">
|
<div class="mt-5 flex justify-end">
|
||||||
<Button
|
<Button
|
||||||
on:click={() => updateUserGroups(user.userGroupIds)}
|
on:click={() => updateUserGroups(user.userGroupIds)}
|
||||||
|
|||||||
@@ -16,18 +16,13 @@
|
|||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import OneTimeLinkModal from './one-time-link-modal.svelte';
|
import OneTimeLinkModal from './one-time-link-modal.svelte';
|
||||||
|
|
||||||
let { users = $bindable() }: { users: Paginated<User> } = $props();
|
let {
|
||||||
|
users = $bindable(),
|
||||||
|
requestOptions
|
||||||
|
}: { users: Paginated<User>; requestOptions: SearchPaginationSortRequest } = $props();
|
||||||
|
|
||||||
let userIdToCreateOneTimeLink: string | null = $state(null);
|
let userIdToCreateOneTimeLink: string | null = $state(null);
|
||||||
|
|
||||||
let requestOptions: SearchPaginationSortRequest | undefined = $state({
|
|
||||||
sort: { column: 'firstName', direction: 'asc' },
|
|
||||||
pagination: {
|
|
||||||
page: users.pagination.currentPage,
|
|
||||||
limit: users.pagination.itemsPerPage
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const userService = new UserService();
|
const userService = new UserService();
|
||||||
|
|
||||||
async function deleteUser(user: User) {
|
async function deleteUser(user: User) {
|
||||||
@@ -54,7 +49,6 @@
|
|||||||
<AdvancedTable
|
<AdvancedTable
|
||||||
items={users}
|
items={users}
|
||||||
{requestOptions}
|
{requestOptions}
|
||||||
defaultSort={{ column: 'firstName', direction: 'asc' }}
|
|
||||||
onRefresh={async (options) => (users = await userService.list(options))}
|
onRefresh={async (options) => (users = await userService.list(options))}
|
||||||
columns={[
|
columns={[
|
||||||
{ label: 'First name', sortColumn: 'firstName' },
|
{ label: 'First name', sortColumn: 'firstName' },
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { ACCESS_TOKEN_COOKIE_NAME } from '$lib/constants';
|
import { ACCESS_TOKEN_COOKIE_NAME } from '$lib/constants';
|
||||||
import AuditLogService from '$lib/services/audit-log-service';
|
import AuditLogService from '$lib/services/audit-log-service';
|
||||||
|
import type { SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ cookies }) => {
|
export const load: PageServerLoad = async ({ cookies }) => {
|
||||||
const auditLogService = new AuditLogService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
const auditLogService = new AuditLogService(cookies.get(ACCESS_TOKEN_COOKIE_NAME));
|
||||||
const auditLogs = await auditLogService.list({
|
const auditLogsRequestOptions: SearchPaginationSortRequest = {
|
||||||
sort: {
|
sort: {
|
||||||
column: 'createdAt',
|
column: 'createdAt',
|
||||||
direction: 'desc'
|
direction: 'desc'
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return {
|
|
||||||
auditLogs
|
|
||||||
};
|
};
|
||||||
|
const auditLogs = await auditLogService.list(auditLogsRequestOptions);
|
||||||
|
return { auditLogs, auditLogsRequestOptions };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import AuditLogList from './audit-log-list.svelte';
|
import AuditLogList from './audit-log-list.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
let { auditLogs } = data;
|
||||||
|
let auditLogsRequestOptions = $state(data.auditLogsRequestOptions);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -17,6 +19,6 @@
|
|||||||
>
|
>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<AuditLogList auditLogs={data.auditLogs} />
|
<AuditLogList auditLogs={data.auditLogs} requestOptions={auditLogsRequestOptions} />
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
import * as Table from '$lib/components/ui/table';
|
import * as Table from '$lib/components/ui/table';
|
||||||
import AuditLogService from '$lib/services/audit-log-service';
|
import AuditLogService from '$lib/services/audit-log-service';
|
||||||
import type { AuditLog } from '$lib/types/audit-log.type';
|
import type { AuditLog } from '$lib/types/audit-log.type';
|
||||||
import type { Paginated } from '$lib/types/pagination.type';
|
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||||
|
|
||||||
let { auditLogs: initialAuditLog }: { auditLogs: Paginated<AuditLog> } = $props();
|
let {
|
||||||
let auditLogs = $state<Paginated<AuditLog>>(initialAuditLog);
|
auditLogs,
|
||||||
|
requestOptions
|
||||||
|
}: { auditLogs: Paginated<AuditLog>; requestOptions: SearchPaginationSortRequest } = $props();
|
||||||
|
|
||||||
const auditLogService = new AuditLogService();
|
const auditLogService = new AuditLogService();
|
||||||
|
|
||||||
@@ -22,8 +24,8 @@
|
|||||||
|
|
||||||
<AdvancedTable
|
<AdvancedTable
|
||||||
items={auditLogs}
|
items={auditLogs}
|
||||||
|
{requestOptions}
|
||||||
onRefresh={async (options) => (auditLogs = await auditLogService.list(options))}
|
onRefresh={async (options) => (auditLogs = await auditLogService.list(options))}
|
||||||
defaultSort={{ column: 'createdAt', direction: 'desc' }}
|
|
||||||
columns={[
|
columns={[
|
||||||
{ label: 'Time', sortColumn: 'createdAt' },
|
{ label: 'Time', sortColumn: 'createdAt' },
|
||||||
{ label: 'Event', sortColumn: 'event' },
|
{ label: 'Event', sortColumn: 'event' },
|
||||||
|
|||||||
Reference in New Issue
Block a user