Skip to content

Commit

Permalink
Redesign home page
Browse files Browse the repository at this point in the history
  • Loading branch information
myieye committed Jun 20, 2024
1 parent ef7d13d commit ad568a2
Showing 1 changed file with 151 additions and 126 deletions.
277 changes: 151 additions & 126 deletions frontend/viewer/src/HomeView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
mdiBookEditOutline,
mdiBookPlusOutline,
mdiBookSyncOutline,
mdiTestTube
mdiTestTube,
} from '@mdi/js';
import {navigate} from 'svelte-routing';
import {Button, Card, type ColumnDef, ListItem, Table, TextField, tableCell, Icon} from 'svelte-ux';
import { navigate } from 'svelte-routing';
import { Button, Card, type ColumnDef, ListItem, Table, TextField, tableCell, Icon } from 'svelte-ux';
import flexLogo from './lib/assets/flex-logo.png';
import DevContent, { isDev } from './lib/layout/DevContent.svelte';
type Project = { name: string, crdt: boolean, fwdata: boolean, lexbox: boolean };
type Project = { name: string; crdt: boolean; fwdata: boolean; lexbox: boolean };
let newProjectName = '';
let projectsPromise = fetchProjects();
Expand All @@ -22,11 +23,11 @@
createError = '';
if (!newProjectName) {
createError = 'Project name is required.'
createError = 'Project name is required.';
return;
}
const response = await fetch(`/api/project?name=${newProjectName}`, {
method: 'POST'
method: 'POST',
});
if (!response.ok) {
Expand All @@ -44,7 +45,7 @@
async function importFwDataProject(name: string) {
loading = name;
await fetch(`/api/import/fwdata/${name}`, {
method: 'POST'
method: 'POST',
});
projectsPromise = fetchProjects();
await projectsPromise;
Expand All @@ -55,7 +56,7 @@
async function downloadCrdtProject(name: string) {
downloading = name;
await fetch(`/api/download/crdt/${name}`, {method: 'POST'});
await fetch(`/api/download/crdt/${name}`, { method: 'POST' });
projectsPromise = fetchProjects();
await projectsPromise;
downloading = '';
Expand All @@ -64,15 +65,15 @@
let uploading = '';
async function uploadCrdtProject(name: string) {
uploading = name;
await fetch(`/api/upload/crdt/${name}`, {method: 'POST'});
await fetch(`/api/upload/crdt/${name}`, { method: 'POST' });
projectsPromise = fetchProjects();
await projectsPromise;
uploading = '';
}
async function fetchProjects() {
let r = await fetch('/api/projects');
return await r.json() as Promise<Project[]>;
return (await r.json()) as Promise<Project[]>;
}
let username = '';
Expand All @@ -85,134 +86,158 @@
fetchMe();
$: columns = [
{
name: 'name'
name: 'name',
header: 'Name',
},
{
name: 'fwdata',
header: 'FieldWorks'
},
{
name: 'crdt',
header: 'CRDT'
header: 'FieldWorks',
},
...(loggedIn ? [{
name: 'lexbox',
header: 'Lexbox CRDT',
}] : []),
...($isDev
? [
{
name: 'crdt',
header: 'CRDT',
},
]
: []),
...(loggedIn
? [
{
name: 'lexbox',
header: 'Lexbox CRDT',
},
]
: []),
] satisfies ColumnDef<Project>[];
</script>

<div class="home">
<DevContent>
<div>
<Card title="Create Project" class="w-fit m-4">
<TextField
label="New Project Name"
class="m-4"
placeholder="Project Name"
bind:value={newProjectName}
error={createError}
/>
<Button slot="actions" variant="fill" icon={mdiBookPlusOutline} on:click={createProject}>Create Project</Button>
</Card>
<Card title="Account" class="w-fit m-4">
{#if loggedIn}
<p>{username}</p>
<Button slot="actions" variant="fill" href="/api/auth/logout/default">Logout</Button>
{:else}
<Button slot="actions" variant="fill" href="/api/auth/login/default">Login</Button>
{/if}
</Card>
</div>
</DevContent>
<div class="col-start-2 p-6 flex flex-col">
<div class="flex-grow"></div>
<div>
<div class="text-center text-3xl mb-8">My projects</div>
<Card class="p-6 shadow-2xl">
<div slot="contents">
{#await projectsPromise}
<p>loading...</p>
{:then projects}
<Table {columns} data={projects.filter((p) => $isDev || p.fwdata).sort((p1, p2) => p1.name.localeCompare(p2.name))} classes={{ th: 'p-4' }}>
<tbody slot="data" let:columns let:data let:getCellValue let:getCellContent>
{#each data ?? [] as rowData, rowIndex}
<tr class="tabular-nums">
{#each columns as column (column.name)}
<td use:tableCell={{ column, rowData, rowIndex, tableData: data }}>
{#if column.name === 'fwdata'}
{#if rowData.fwdata}
<Button size="md" on:click={() => navigate(`/fwdata/${rowData.name}`)}>
<img src={flexLogo} alt="FieldWorks logo" class="h-6" />
Open
</Button>
{/if}
{:else if column.name === 'lexbox'}
{#if rowData.lexbox && !rowData.crdt}
<Button
icon={mdiBookArrowDownOutline}
size="md"
loading={downloading === rowData.name}
on:click={() => downloadCrdtProject(rowData.name)}
>
Download
</Button>
{:else if !rowData.lexbox && rowData.crdt && loggedIn}
<Button
icon={mdiBookArrowUpOutline}
size="md"
loading={uploading === rowData.name}
on:click={() => uploadCrdtProject(rowData.name)}
>
Upload
</Button>
{:else if rowData.lexbox && rowData.crdt}
<Button disabled color="success" icon={mdiBookSyncOutline} size="md">Synced</Button>
{/if}
{:else if column.name === 'crdt'}
{#if rowData.crdt}
<Button
icon={mdiBookEditOutline}
size="md"
on:click={() => navigate(`/project/${rowData.name}`)}
>
Open
</Button>
{:else if rowData.fwdata}
<Button
size="md"
icon={mdiBookArrowLeftOutline}
on:click={() => importFwDataProject(rowData.name)}
>
Import
</Button>
{/if}
{:else}
{getCellContent(column, rowData, rowIndex)}
{/if}
</td>
{/each}
</tr>
{/each}

<DevContent>
<tr class="tabular-nums">
<td>
Test project
</td>
<td>
<Button size="md" icon={mdiTestTube} on:click={() => navigate('/testing/project-view')}>
Open
</Button>
</td>
</tr>
</DevContent>
</tbody>
</Table>
{/await}
</div>
</Card>
</div>
<div class="flex-grow-[2]"></div>
</div>
</div>

<style>
.home {
min-height: 100%;
display: grid;
grid-template-columns: auto;
grid-template-columns: 1fr auto 1fr;
}
.home :global(.column-name), .home :global(.column-crdt), .home :global(.column-fwdata), .home :global(.column-lexbox) {
padding: 0.5rem;
.home :global(*:is(td, th)) {
@apply px-10;
}
</style>
<div class="home">
<div>
<Card title="Create Project" class="w-fit m-4">
<TextField label="New Project Name" class="m-4" placeholder="Project Name" bind:value={newProjectName} error={createError} />
<Button slot="actions" variant="fill" icon={mdiBookPlusOutline} on:click={createProject}>Create Project</Button>
</Card>
<Card title="Account" class="w-fit m-4">
{#if loggedIn}
<p>{username}</p>
<Button slot="actions" variant="fill" href="/api/auth/logout/default">Logout</Button>
{:else}
<Button slot="actions" variant="fill" href="/api/auth/login/default">Login</Button>
{/if}
</Card>

</div>
<Card title="Projects" class="w-fit m-4">
<div slot="contents">
{#await projectsPromise}
<p>loading...</p>
{:then projects}
<Table columns={columns} data={projects} classes={{th: 'p-4'}}>

<tbody slot="data" let:columns let:data let:getCellValue let:getCellContent>
{#each data ?? [] as rowData, rowIndex}
<tr class="tabular-nums">
{#each columns as column (column.name)}
{@const value = getCellValue(column, rowData, rowIndex)}

<td use:tableCell={{ column, rowData, rowIndex, tableData: data }}>
{#if column.name === "fwdata"}
{#if rowData.fwdata}
<Button
size="md"
on:click={() => navigate(`/fwdata/${rowData.name}`)}>
<img src={flexLogo} alt="FieldWorks logo" class="h-6">
Edit
</Button>
{/if}
{:else if column.name === "lexbox"}
{#if rowData.lexbox && !rowData.crdt}
<Button
icon={mdiBookArrowDownOutline}
size="md"
loading={downloading === rowData.name}
on:click={() => downloadCrdtProject(rowData.name)}>
Download
</Button>
{:else if !rowData.lexbox && rowData.crdt && loggedIn}
<Button
icon={mdiBookArrowUpOutline}
size="md"
loading={uploading === rowData.name}
on:click={() => uploadCrdtProject(rowData.name)}>
Upload
</Button>
{:else if rowData.lexbox && rowData.crdt}
<Button
disabled
color="success"
icon={mdiBookSyncOutline}
size="md">
Synced
</Button>
{/if}
{:else if column.name === "crdt"}
{#if rowData.crdt}
<Button
icon={mdiBookEditOutline}
size="md"
on:click={() => navigate(`/project/${rowData.name}`)}>
Edit
</Button>
{:else if rowData.fwdata}
<Button
size="md"
icon={mdiBookArrowLeftOutline}
on:click={() => importFwDataProject(rowData.name)}>
Import
</Button>
{/if}
{:else}
{getCellContent(column, rowData, rowIndex)}
{/if}
</td>
{/each}
</tr>
{/each}
</tbody>
</Table>
{/await}

<ListItem
class="cursor-pointer hover:bg-primary/5"
noShadow
icon={mdiTestTube}
title="Test Project"
on:click={() => navigate('/testing/project-view')}/>
</div>
</Card>

</div>

0 comments on commit ad568a2

Please sign in to comment.