pocketbase/ui/src/components/admins/PageAdmins.svelte

209 lines
8.0 KiB
Svelte
Raw Normal View History

2022-07-07 05:19:05 +08:00
<script>
2022-08-01 19:20:21 +08:00
import { replace, querystring } from "svelte-spa-router";
2022-07-07 05:19:05 +08:00
import ApiClient from "@/utils/ApiClient";
import CommonHelper from "@/utils/CommonHelper";
import { pageTitle } from "@/stores/app";
2022-07-07 05:19:05 +08:00
import { admin as loggedAdmin } from "@/stores/admin";
2022-08-09 21:16:09 +08:00
import PageWrapper from "@/components/base/PageWrapper.svelte";
2022-07-07 05:19:05 +08:00
import Searchbar from "@/components/base/Searchbar.svelte";
import RefreshButton from "@/components/base/RefreshButton.svelte";
2022-07-07 05:19:05 +08:00
import SortHeader from "@/components/base/SortHeader.svelte";
import IdLabel from "@/components/base/IdLabel.svelte";
import FormattedDate from "@/components/base/FormattedDate.svelte";
2022-10-30 16:28:14 +08:00
import HorizontalScroller from "@/components/base/HorizontalScroller.svelte";
2022-07-07 05:19:05 +08:00
import SettingsSidebar from "@/components/settings/SettingsSidebar.svelte";
import AdminUpsertPanel from "@/components/admins/AdminUpsertPanel.svelte";
$pageTitle = "Admins";
2022-08-01 19:20:21 +08:00
const queryParams = new URLSearchParams($querystring);
2022-07-07 05:19:05 +08:00
let adminUpsertPanel;
let admins = [];
let isLoading = false;
2022-08-01 19:20:21 +08:00
let filter = queryParams.get("filter") || "";
let sort = queryParams.get("sort") || "-created";
2022-07-07 05:19:05 +08:00
$: if (sort !== -1 && filter !== -1) {
// keep listing params in sync
2022-08-01 19:20:21 +08:00
const query = new URLSearchParams({ filter, sort }).toString();
replace("/settings/admins?" + query);
2022-07-07 05:19:05 +08:00
loadAdmins();
}
export function loadAdmins() {
isLoading = true;
2022-07-07 05:19:05 +08:00
admins = []; // reset
2022-08-09 21:16:09 +08:00
return ApiClient.admins
.getFullList(100, {
sort: sort || "-created",
filter: filter,
})
2022-07-07 05:19:05 +08:00
.then((result) => {
admins = result;
isLoading = false;
})
.catch((err) => {
if (!err?.isAbort) {
2022-07-07 05:19:05 +08:00
isLoading = false;
console.warn(err);
clearList();
ApiClient.errorResponseHandler(err, false);
}
});
}
function clearList() {
admins = [];
}
</script>
<SettingsSidebar />
2022-08-09 21:16:09 +08:00
<PageWrapper>
2022-07-07 05:19:05 +08:00
<header class="page-header">
<nav class="breadcrumbs">
<div class="breadcrumb-item">Settings</div>
<div class="breadcrumb-item">{$pageTitle}</div>
2022-07-07 05:19:05 +08:00
</nav>
<RefreshButton on:refresh={() => loadAdmins()} />
2022-07-07 05:19:05 +08:00
<div class="flex-fill" />
<button type="button" class="btn btn-expanded" on:click={() => adminUpsertPanel?.show()}>
<i class="ri-add-line" />
<span class="txt">New admin</span>
</button>
</header>
<Searchbar
value={filter}
placeholder={"Search filter, eg. email='test@example.com'"}
extraAutocompleteKeys={["email"]}
on:submit={(e) => (filter = e.detail)}
/>
2022-10-30 16:28:14 +08:00
<HorizontalScroller class="table-wrapper">
2022-07-07 05:19:05 +08:00
<table class="table" class:table-loading={isLoading}>
<thead>
<tr>
<th class="min-width" />
<SortHeader class="col-type-text" name="id" bind:sort>
<div class="col-header-content">
<i class={CommonHelper.getFieldTypeIcon("primary")} />
<span class="txt">id</span>
</div>
</SortHeader>
<SortHeader class="col-type-email col-field-email" name="email" bind:sort>
<div class="col-header-content">
<i class={CommonHelper.getFieldTypeIcon("email")} />
<span class="txt">email</span>
</div>
</SortHeader>
<SortHeader class="col-type-date col-field-created" name="created" bind:sort>
<div class="col-header-content">
<i class={CommonHelper.getFieldTypeIcon("date")} />
<span class="txt">created</span>
</div>
</SortHeader>
<SortHeader class="col-type-date col-field-updated" name="updated" bind:sort>
<div class="col-header-content">
<i class={CommonHelper.getFieldTypeIcon("date")} />
<span class="txt">updated</span>
</div>
</SortHeader>
<th class="col-type-action min-width" />
</tr>
</thead>
<tbody>
{#each admins as admin (admin.id)}
<tr
tabindex="0"
class="row-handle"
on:click={() => adminUpsertPanel?.show(admin)}
on:keydown={(e) => {
if (e.code === "Enter" || e.code === "Space") {
e.preventDefault();
adminUpsertPanel?.show(admin);
}
}}
>
<td class="min-width">
<figure class="thumb thumb-sm thumb-circle">
<img
src="{import.meta.env.BASE_URL}images/avatars/avatar{admin.avatar ||
0}.svg"
alt="Admin avatar"
/>
</figure>
</td>
2022-10-30 16:28:14 +08:00
2022-07-07 05:19:05 +08:00
<td class="col-type-text col-field-id">
<IdLabel id={admin.id} />
{#if admin.id === $loggedAdmin.id}
<span class="label label-warning m-l-5">You</span>
{/if}
</td>
<td class="col-type-email col-field-email">
<span class="txt txt-ellipsis" title={admin.email}>
{admin.email}
</span>
</td>
<td class="col-type-date col-field-created">
<FormattedDate date={admin.created} />
</td>
2022-10-30 16:28:14 +08:00
2022-07-07 05:19:05 +08:00
<td class="col-type-date col-field-updated">
<FormattedDate date={admin.updated} />
</td>
2022-10-30 16:28:14 +08:00
2022-07-07 05:19:05 +08:00
<td class="col-type-action min-width">
<i class="ri-arrow-right-line" />
</td>
</tr>
{:else}
{#if isLoading}
<tr>
<td colspan="99" class="p-xs">
<span class="skeleton-loader" />
</td>
</tr>
{:else}
<tr>
<td colspan="99" class="txt-center txt-hint p-xs">
<h6>No admins found.</h6>
{#if filter?.length}
<button
type="button"
class="btn btn-hint btn-expanded m-t-sm"
on:click={() => (filter = "")}
>
<span class="txt">Clear filters</span>
</button>
{/if}
</td>
</tr>
{/if}
{/each}
</tbody>
</table>
2022-10-30 16:28:14 +08:00
</HorizontalScroller>
2022-07-07 05:19:05 +08:00
{#if admins.length}
<small class="block txt-hint txt-right m-t-sm">Showing {admins.length} of {admins.length}</small>
{/if}
2022-08-09 21:16:09 +08:00
</PageWrapper>
2022-07-07 05:19:05 +08:00
<AdminUpsertPanel bind:this={adminUpsertPanel} on:save={() => loadAdmins()} on:delete={() => loadAdmins()} />