Update package version, updated Logout function to delete cookies, Cleaned Logs, Added Breadcrumbs, Added Pagination to sources, Cleaned Styles, and improve code structure

This commit is contained in:
luke-hagar-sp
2024-01-22 11:20:59 -06:00
parent a9a4950c1b
commit 13bc01dffb
10 changed files with 291 additions and 179 deletions

View File

@@ -6,7 +6,7 @@ export function formatDate(date: string | null | undefined) {
} }
export function getLimit(url: URL) { export function getLimit(url: URL) {
return url.searchParams.get('limit') || '10'; return url.searchParams.get('limit') || '250';
} }
export function getFilters(url: URL) { export function getFilters(url: URL) {

View File

@@ -17,14 +17,14 @@ export const actions = {
const sessionString = cookies.get('idnSession'); const sessionString = cookies.get('idnSession');
if (sessionString) { if (sessionString) {
console.log('sessionString', sessionString); // console.log('sessionString', sessionString);
const session = JSON.parse(sessionString); const session = JSON.parse(sessionString);
if (session.org == tenant) { if (session.org == tenant) {
console.debug('Credential Cache Hit'); // console.debug('Credential Cache Hit');
throw redirect(302, '/home'); throw redirect(302, '/home');
} else { } else {
console.debug('Credential Cache Miss'); // console.debug('Credential Cache Miss');
} }
} }

View File

@@ -41,7 +41,7 @@ export const load: PageServerLoad = async ({ url, cookies }) => {
}); });
const idnSession: IdnSession = response.data as IdnSession; const idnSession: IdnSession = response.data as IdnSession;
console.log(idnSession); // console.log(idnSession);
cookies.set('idnSession', JSON.stringify(idnSession)); cookies.set('idnSession', JSON.stringify(idnSession));
return { idnSession, counterList }; return { idnSession, counterList };

View File

@@ -1,6 +1,25 @@
<script> <script lang="ts">
import { page } from '$app/stores';
import LeftSidebar from '$lib/sidebar/LeftSidebar.svelte'; import LeftSidebar from '$lib/sidebar/LeftSidebar.svelte';
import { AppBar, AppShell, LightSwitch } from '@skeletonlabs/skeleton'; import { AppBar, AppShell, Avatar, LightSwitch } from '@skeletonlabs/skeleton';
let crumbs: Array<{ label: string; href: string }> = [];
$: {
// Remove zero-length tokens.
const tokens = $page.url.pathname.split('/').filter((t) => t !== '');
// Create { label, href } pairs for each token.
let tokenPath = '';
crumbs = tokens.map((t) => {
tokenPath += '/' + t;
t = t.charAt(0).toUpperCase() + t.slice(1);
return { label: t, href: tokenPath };
});
// Add a way to get home too.
// crumbs.unshift({ label: 'Home', href: '/' });
}
</script> </script>
<AppShell> <AppShell>
@@ -12,7 +31,8 @@
<p class="text-xl">IdentityNow Admin Console</p> <p class="text-xl">IdentityNow Admin Console</p>
<svelte:fragment slot="trail"> <svelte:fragment slot="trail">
<LightSwitch /> <LightSwitch />
<a href="/logout" class="btn variant-filled-primary !text-white text-lg">Logout</a> <Avatar width="w-10" />
<a href="/logout" class="btn variant-filled-primary !text-white text-xs">Logout</a>
</svelte:fragment> </svelte:fragment>
</AppBar> </AppBar>
</svelte:fragment> </svelte:fragment>
@@ -22,8 +42,23 @@
<!-- <svelte:fragment slot="sidebarRight">Sidebar Right</svelte:fragment> --> <!-- <svelte:fragment slot="sidebarRight">Sidebar Right</svelte:fragment> -->
<!-- <svelte:fragment slot="pageHeader">Page Header</svelte:fragment> --> <!-- <svelte:fragment slot="pageHeader">Page Header</svelte:fragment> -->
<!-- Router Slot --> <!-- Router Slot -->
<div class="h-full"> <div class="max-h-screen">
<slot /> <div class="pl-2 pt-2 pr-2">
<ol class="breadcrumb card p-2">
{#each crumbs as crumb, i}
<!-- If crumb index is less than the breadcrumb length minus 1 -->
{#if i < crumbs.length - 1}
<li class="crumb"><a class="anchor" href={crumb.href}>{crumb.label}</a></li>
<li class="crumb-separator" aria-hidden>&rsaquo;</li>
{:else}
<li class="crumb">{crumb.label}</li>
{/if}
{/each}
</ol>
</div>
<div class="p-2">
<slot />
</div>
</div> </div>
<!-- ---- / ---- --> <!-- ---- / ---- -->
<!-- <svelte:fragment slot="pageFooter">Page Footer</svelte:fragment> --> <!-- <svelte:fragment slot="pageFooter">Page Footer</svelte:fragment> -->

View File

@@ -2,7 +2,7 @@
import { reports } from '$lib/sidebar/reports'; import { reports } from '$lib/sidebar/reports';
</script> </script>
<div class="flex flex-row flex-wrap gap-4 p-4 justify-center"> <div class="flex flex-row flex-wrap gap-4 justify-center">
{#each reports as report (report.url)} {#each reports as report (report.url)}
<a <a
class="card card-hover overflow-hidden w-modal-slim" class="card card-hover overflow-hidden w-modal-slim"

View File

@@ -38,117 +38,117 @@
let sorters = ''; let sorters = '';
</script> </script>
<div class="p-4"> <div class="card flex justify-center flex-col align-middle">
<div class="card flex justify-center flex-col align-middle"> <div class=" p-4 flex flex-row justify-between gap-4 flex-wrap">
<div class=" p-4 flex flex-row justify-between gap-4 flex-wrap"> <div class="flex flex-row gap-1">
<div class="flex flex-row gap-1"> <input
<input on:keydown={onGo}
on:keydown={onGo} bind:value={filters}
bind:value={filters} class="input"
class="input" title="Filter"
title="Filter" type="text"
type="text" placeholder="Filter"
placeholder="Filter"
/>
<input
on:keydown={onGo}
bind:value={sorters}
class="input"
title="Sorter"
type="text"
placeholder="Sorter"
/>
<button on:click={onGo} class="btn variant-filled-primary text-white"> Go </button>
</div>
<Paginator
bind:settings
on:page={onPageChange}
on:amount={onAmountChange}
showNumerals
maxNumerals={1}
showFirstLastButtons={true}
showPreviousNextButtons={true}
/> />
</div> <input
<table class="table"> on:keydown={onGo}
<thead> bind:value={sorters}
<th>ID</th> class="input"
<th>Name</th> title="Sorter"
<th>Lifecycle State</th> type="text"
<th>eMail</th> placeholder="Sorter"
<th>Created</th>
<th>Modified</th>
<th />
</thead>
<tbody class="overflow-hidden">
{#each data.identities as identity}
<tr>
<td>
<p class="text-center">{identity.id}</p>
</td>
<td>
<p class="text-center">{identity.name}</p>
</td>
<td>
<p class="text-center">{identity.lifecycleState?.stateName}</p>
</td>
<td>
<p class="text-center">{identity.emailAddress}</p>
</td>
<td>
<p class="text-center">{formatDate(identity.created)}</p>
</td>
<td>
<p class="text-center">{formatDate(identity.modified)}</p>
</td>
<td class="flex flex-col justify-center gap-1">
<a
href={`/home/identities/${identity.id}`}
class="btn variant-filled-primary text-white"
data-sveltekit-preload-data="hover"
>
Open
</a>
<button
on:click={() => TriggerSourceViewModal(identity)}
class="btn variant-filled-primary text-white"
>
View
</button>
</td>
</tr>
{/each}
</tbody>
</table>
<div class=" p-4 flex flex-row justify-between gap-4 flex-wrap">
<div class="flex flex-row gap-1">
<input
on:keydown={onGo}
bind:value={filters}
class="input"
title="Filter"
type="text"
placeholder="Filter"
/>
<input
on:keydown={onGo}
bind:value={sorters}
class="input"
title="Sorter"
type="text"
placeholder="Sorter"
/>
<button on:click={onGo} class="btn variant-filled-primary text-white"> Go </button>
</div>
<Paginator
bind:settings
on:page={onPageChange}
on:amount={onAmountChange}
showNumerals
maxNumerals={1}
showFirstLastButtons={true}
showPreviousNextButtons={true}
/> />
<button on:click={onGo} class="btn variant-filled-primary text-white"> Go </button>
</div> </div>
<p class="my-auto">Total Count: {data.totalCount}</p>
<Paginator
bind:settings
on:page={onPageChange}
on:amount={onAmountChange}
showNumerals
maxNumerals={1}
showFirstLastButtons={true}
showPreviousNextButtons={true}
/>
</div>
<table class="table">
<thead>
<th>ID</th>
<th>Name</th>
<th>Lifecycle State</th>
<th>eMail</th>
<th>Created</th>
<th>Modified</th>
<th />
</thead>
<tbody class="overflow-hidden">
{#each data.identities as identity}
<tr>
<td>
<p class="text-center">{identity.id}</p>
</td>
<td>
<p class="text-center">{identity.name}</p>
</td>
<td>
<p class="text-center">{identity.lifecycleState?.stateName}</p>
</td>
<td>
<p class="text-center">{identity.emailAddress}</p>
</td>
<td>
<p class="text-center">{formatDate(identity.created)}</p>
</td>
<td>
<p class="text-center">{formatDate(identity.modified)}</p>
</td>
<td class="flex flex-col justify-center gap-1">
<a
href={`/home/identities/${identity.id}`}
class="btn variant-filled-primary text-white"
data-sveltekit-preload-data="hover"
>
Open
</a>
<button
on:click={() => TriggerSourceViewModal(identity)}
class="btn variant-filled-primary text-white"
>
View
</button>
</td>
</tr>
{/each}
</tbody>
</table>
<div class=" p-4 flex flex-row justify-between gap-4 flex-wrap">
<div class="flex flex-row gap-1">
<input
on:keydown={onGo}
bind:value={filters}
class="input"
title="Filter"
type="text"
placeholder="Filter"
/>
<input
on:keydown={onGo}
bind:value={sorters}
class="input"
title="Sorter"
type="text"
placeholder="Sorter"
/>
<button on:click={onGo} class="btn variant-filled-primary text-white"> Go </button>
</div>
<p class="my-auto">Total Count: {data.totalCount}</p>
<Paginator
bind:settings
on:page={onPageChange}
on:amount={onAmountChange}
showNumerals
maxNumerals={1}
showFirstLastButtons={true}
showPreviousNextButtons={true}
/>
</div> </div>
</div> </div>

View File

@@ -25,8 +25,6 @@ export const load = async ({ cookies, url }) => {
const apiResponse = await api.listSources(requestParams); const apiResponse = await api.listSources(requestParams);
console.log(apiResponse);
return { return {
totalCount: apiResponse.headers['x-total-count'], totalCount: apiResponse.headers['x-total-count'],
sources: apiResponse.data, sources: apiResponse.data,

View File

@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { ModalSettings } from '@skeletonlabs/skeleton'; import { createOnAmountChange, createOnGo, createOnPageChange } from '$lib/Utils.js';
import { getModalStore } from '@skeletonlabs/skeleton'; import type { ModalSettings, PaginationSettings } from '@skeletonlabs/skeleton';
import { Paginator, getModalStore } from '@skeletonlabs/skeleton';
const modalStore = getModalStore(); const modalStore = getModalStore();
@@ -18,61 +19,138 @@
modalStore.trigger(modal); modalStore.trigger(modal);
} }
$: onPageChange = createOnPageChange({ ...data.params, filters, sorters }, '/home/identities');
$: onAmountChange = createOnAmountChange(
{ ...data.params, filters, sorters },
'/home/identities'
);
$: onGo = createOnGo({ ...data.params, filters, sorters }, '/home/identities');
let settings = {
page: Number(data.params.page),
limit: Number(data.params.limit),
size: data.totalCount,
amounts: [10, 50, 100, 250]
} satisfies PaginationSettings;
let filters = '';
let sorters = '';
</script> </script>
<div class="p-4"> <div class="card flex justify-center flex-col align-middle">
<div class="flex justify-center flex-col align-middle"> <div class=" p-4 flex flex-row justify-between gap-4 flex-wrap">
<table class="table"> <div class="flex flex-row gap-1">
<thead> <input
<th>ID</th> on:keydown={onGo}
<th>Name</th> bind:value={filters}
<th>Description</th> class="input"
<th>Type</th> title="Filter"
<th>Authoritative</th> type="text"
<th>Healthy</th> placeholder="Filter"
<th /> />
</thead> <input
<tbody> on:keydown={onGo}
{#each data.sources as source} bind:value={sorters}
<tr> class="input"
<td> title="Sorter"
<p class="text-center">{source.id}</p> type="text"
</td> placeholder="Sorter"
<td> />
<p class="text-center">{source.name}</p> <button on:click={onGo} class="btn variant-filled-primary text-white"> Go </button>
</td> </div>
<td> <p class="my-auto">Total Count: {data.totalCount}</p>
<p class="text-center">{source.description}</p> <Paginator
</td> bind:settings
<td> on:page={onPageChange}
<p class="text-center">{source.type}</p> on:amount={onAmountChange}
</td> showNumerals={true}
<td> maxNumerals={1}
<p class="text-center">{source.authoritative ? 'True' : 'False'}</p> showFirstLastButtons={true}
</td> showPreviousNextButtons={true}
<td> />
<p class="text-center font-bold {source.healthy ? 'text-green-500' : 'text-red-500'}"> </div>
{source.healthy ? 'True' : 'False'} <table class="table">
</p> <thead>
</td> <th>ID</th>
<td class="flex flex-col justify-center gap-1"> <th>Name</th>
<a <th>Description</th>
href={`/home/sources/${source.id}`} <th>Type</th>
class="btn variant-filled-primary text-white" <th>Authoritative</th>
data-sveltekit-preload-data="hover" <th>Healthy</th>
> <th />
Open </thead>
</a> <tbody>
<button {#each data.sources as source}
on:click={() => TriggerSourceViewModal(source)} <tr>
class="btn variant-filled-primary text-white" <td>
> <p class="text-center">{source.id}</p>
View </td>
</button> <td>
</td> <p class="text-center">{source.name}</p>
</tr> </td>
{/each} <td>
</tbody> <p class="text-center">{source.description}</p>
</table> </td>
<td>
<p class="text-center">{source.type}</p>
</td>
<td>
<p class="text-center">{source.authoritative ? 'True' : 'False'}</p>
</td>
<td>
<p class="text-center font-bold {source.healthy ? 'text-green-500' : 'text-red-500'}">
{source.healthy ? 'True' : 'False'}
</p>
</td>
<td class="flex flex-col justify-center gap-1">
<a
href={`/home/sources/${source.id}`}
class="btn variant-filled-primary text-white"
data-sveltekit-preload-data="hover"
>
Open
</a>
<button
on:click={() => TriggerSourceViewModal(source)}
class="btn variant-filled-primary text-white"
>
View
</button>
</td>
</tr>
{/each}
</tbody>
</table>
<div class=" p-4 flex flex-row justify-between gap-4 flex-wrap">
<div class="flex flex-row gap-1">
<input
on:keydown={onGo}
bind:value={filters}
class="input"
title="Filter"
type="text"
placeholder="Filter"
/>
<input
on:keydown={onGo}
bind:value={sorters}
class="input"
title="Sorter"
type="text"
placeholder="Sorter"
/>
<button on:click={onGo} class="btn variant-filled-primary text-white"> Go </button>
</div>
<p class="my-auto">Total Count: {data.totalCount}</p>
<Paginator
bind:settings
on:page={onPageChange}
on:amount={onAmountChange}
showNumerals={true}
maxNumerals={1}
showFirstLastButtons={true}
showPreviousNextButtons={true}
/>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,6 @@
export const load = async ({ cookies }) => { export const load = async ({ cookies }) => {
cookies.delete('session'); cookies.delete('session');
cookies.delete('idnSession');
return { sessionLoggedOut: true }; return { sessionLoggedOut: true };
}; };

View File

@@ -1,7 +1,7 @@
{ {
"name": "idn-admin-console", "name": "idn-admin-console",
"description": "A troubleshooting and administration app for IdentityNow", "description": "A troubleshooting and administration app for IdentityNow",
"version": "0.0.1", "version": "0.0.2",
"private": true, "private": true,
"author": { "author": {
"name": "Luke Hagar", "name": "Luke Hagar",