From b3d291c3eee9824675b9656a7bb0c5045ac77441 Mon Sep 17 00:00:00 2001 From: Julian Lobbes Date: Fri, 2 Jun 2023 13:08:40 +0100 Subject: [PATCH] feat(frontend): make data-table fully responsive --- frontend/docs/theme/colorscheme.gpl | 3 + frontend/src/app.css | 63 ++++- .../lib/components/data-table/Table.svelte | 219 ++++++++++++------ .../src/lib/components/data-table/Td.svelte | 82 +++++-- .../src/lib/components/navbar/Navbar.svelte | 64 +---- frontend/src/routes/+layout.svelte | 8 +- .../routes/users/[user]/todos/+page.svelte | 41 ++-- frontend/src/routes/users/all/+page.svelte | 34 +-- frontend/tailwind.config.js | 3 + 9 files changed, 325 insertions(+), 192 deletions(-) diff --git a/frontend/docs/theme/colorscheme.gpl b/frontend/docs/theme/colorscheme.gpl index 11a6474..3f758b9 100644 --- a/frontend/docs/theme/colorscheme.gpl +++ b/frontend/docs/theme/colorscheme.gpl @@ -42,3 +42,6 @@ Columns: 1 163 163 163 background-700 112 112 112 background-800 51 51 51 background-900 +0 204 0 success +237 192 0 warning +228 0 0 failure diff --git a/frontend/src/app.css b/frontend/src/app.css index 5206e31..eb3203c 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -70,7 +70,36 @@ } button:disabled { @apply opacity-25; - @apply bg-neutral-100; + @apply cursor-not-allowed; + } + button:disabled:hover { + @apply bg-accent; + @apply text-primary-400 font-semibold; + @apply cursor-not-allowed; + } + button.outlineButton { + @apply bg-secondary/20; + @apply border-2 border-secondary; + @apply text-secondary font-medium; + } + button.outlineButton:hover { + @apply bg-secondary; + @apply text-secondary-900 font-bold; + } + button.outlineButton:active { + @apply bg-secondary-600; + @apply text-secondary-900; + } + button.outlineButton:focus { + @apply ring-secondary-400; + } + button.outlineButton:disabled { + @apply opacity-25; + } + button.outlineButton:disabled:hover { + @apply bg-secondary/20; + @apply text-secondary font-medium; + @apply cursor-not-allowed; } a.button { @apply p-2; @@ -114,24 +143,27 @@ tr:last-of-type td:last-of-type { @apply rounded-br-md; } - tr { - @apply hover:bg-secondary-300/50; - @apply border-y border-primary/50; - @apply bg-secondary-100/10; - } tr:first-of-type, tr:last-of-type { @apply border-y-0; } + tr:nth-child(odd) { + @apply bg-secondary/5; + } + tr:nth-child(even) { + @apply bg-secondary/20; + } + tr { + @apply hover:bg-accent/25; + } th { @apply bg-primary font-semibold text-secondary-100; - } - caption, th, td { @apply p-1; } - @media screen(sm) { - caption, th, td { - @apply p-2 text-start; - } + td { + @apply p-1; + } + caption { + @apply p-1 text-start font-semibold text-xl; } fieldset { @@ -158,4 +190,11 @@ label { @apply text-sm text-secondary font-light; } + select { + @apply text-primary font-semibold; + @apply border border-secondary; + @apply bg-secondary/20; + @apply rounded-md; + @apply p-1; + } } diff --git a/frontend/src/lib/components/data-table/Table.svelte b/frontend/src/lib/components/data-table/Table.svelte index 5bec6ce..45b6c44 100644 --- a/frontend/src/lib/components/data-table/Table.svelte +++ b/frontend/src/lib/components/data-table/Table.svelte @@ -31,17 +31,34 @@ args: [], } + export let defaultSortField: string = columns[0].field; + export let defaultSortOrder: 'asc' | 'desc' = 'asc'; + + let viewportWidth: number = 0; + let table: Element; + let tableMaxWidth: number = 0; + let compactView = false; + function checkForTableResize() { + if (!table) return; + + if (table.scrollWidth > tableMaxWidth) { + tableMaxWidth = table.scrollWidth; + } + + compactView = tableMaxWidth >= viewportWidth; + } + type SortEvent = { detail: { order: null | 'asc' | 'desc', field: string, } } - let currentSortField: string = columns[0].field; - let currentSortOrder: 'asc' | 'desc' = 'asc'; + let currentSortField: string = defaultSortField; + let currentSortOrder: 'asc' | 'desc' = defaultSortOrder; let currentState: 'finished' | 'loading' | 'error' = 'finished'; - let errorMessages: string[] = []; + let errorMessage: string; let currentItems: any[] = []; // TODO apply generics here let totalItemCount: number | null = null; @@ -134,15 +151,12 @@ ); currentState = 'finished'; } catch (error: any) { - if (!errorMessages.length) { - // Make sure we have an error message to show to the user - if (typeof error.message === 'string') { - errorMessages.push(error.message); - } else { - errorMessages.push("An unknown error occurred."); - } + if (typeof error.body.message === 'string') { + errorMessage = error.body.message; + } else { + errorMessage = "An unknown error occurred."; } - + console.log(error) currentState = 'error'; } } @@ -155,73 +169,140 @@ } onMount(async () => { + checkForTableResize(); await updateTable(); + checkForTableResize(); }); - - {#if caption !== null} - - {/if} - - + + +
+
{caption}
+ {#if caption !== null} + + {/if} + {#if compactView} +
+ Sort by: +
- - - {#if currentState === 'finished'} - {#each currentItems as item} + + Order: + + + {/if} + {#if !compactView} + {#each columns as column} - - {/each} - {:else if currentState === 'loading'} - - - - {:else if currentState === 'error'} - {#each errorMessages as message} - - - - {/each} + {/if} - -
{caption}
+ {/each} -
{/each}
Loading...
{message}
- - - -of {lastPage + 1} - - - + + {#if currentState === 'finished'} + {#each currentItems as item} + + {#each columns as column} + + {/each} + + {/each} + {:else if currentState === 'loading'} + + Loading... + + {:else if currentState === 'error'} + + {errorMessage} + + {/if} + + +
+ + + Total: {totalItemCount} +
+
+ + + + + of {lastPage + 1} + + +
+ + + diff --git a/frontend/src/lib/components/data-table/Td.svelte b/frontend/src/lib/components/data-table/Td.svelte index c7fbdf7..95ed0d0 100644 --- a/frontend/src/lib/components/data-table/Td.svelte +++ b/frontend/src/lib/components/data-table/Td.svelte @@ -1,30 +1,76 @@ - - {#if type === 'date'} - {#if data !== null && data !== undefined} - {new Date(data).toLocaleDateString()} - {:else} - - {/if} - {:else if type === 'boolean'} - {#if data} - - {:else} - - {/if} + + {#if compactView} +

{fieldName}:

+ {/if} + + {#if data === null || data === undefined} + {:else} - {#if isLink} - {data} + {#if type === 'date'} +

{new Date(data).toLocaleDateString()}

+ {:else if type === 'boolean'} + {#if data} + + {:else} + + {/if} {:else} - {data} + {#if isLink} + {data} + {:else} +

{data}

+ {/if} {/if} {/if} + + diff --git a/frontend/src/lib/components/navbar/Navbar.svelte b/frontend/src/lib/components/navbar/Navbar.svelte index 644c25f..c6f76ed 100644 --- a/frontend/src/lib/components/navbar/Navbar.svelte +++ b/frontend/src/lib/components/navbar/Navbar.svelte @@ -29,7 +29,7 @@ } - +