Skip to content

Commit

Permalink
Merge pull request #196 from rainlanguage/2024-02-07-gui-generic-table
Browse files Browse the repository at this point in the history
2024 02 07 gui generic table
  • Loading branch information
thedavidmeister authored Feb 8, 2024
2 parents 2539e43 + 05b5ff8 commit eed945f
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 174 deletions.
48 changes: 48 additions & 0 deletions tauri-app/src/lib/components/AppTable.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script lang="ts" generics="T">
import {
Table,
TableBody,
TableBodyRow,
TableHead,
} from 'flowbite-svelte';
import { FileCsvOutline } from 'flowbite-svelte-icons';
import ButtonsPagination from '$lib/components/ButtonsPagination.svelte';
import type { PaginatedCachedStore } from '$lib/storesGeneric/listStore';
import ButtonLoading from './ButtonLoading.svelte';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
// eslint-disable-next-line no-undef
export let listStore: PaginatedCachedStore<T>;
export let emptyMessage: string = "None found"
export let rowHoverable = true;
export let enableCsvExport = true;
</script>

{#if $listStore.currentPage.length === 0}
<div class="text-center text-gray-900 dark:text-white">{emptyMessage}</div>
{:else}
<Table divClass="cursor-pointer" hoverable={rowHoverable}>
<TableHead>
<slot name="head" {listStore}></slot>
</TableHead>
<TableBody>
{#each $listStore.currentPage as item}
<TableBodyRow on:click={() => { dispatch('clickRow', {item}) }}>
<slot name="bodyRow" {item}></slot>
</TableBodyRow>
{/each}
</TableBody>
</Table>

{#if enableCsvExport}
<div class="flex justify-between mt-2">
<ButtonLoading size="xs" color="blue" on:click={() => listStore.exportCsv()} loading={$listStore.isExporting}>
<FileCsvOutline class="w-4 h-4 mr-2"/>
Export to CSV
</ButtonLoading>
<ButtonsPagination index={$listStore.index} on:previous={listStore.fetchPrev} on:next={listStore.fetchNext} loading={$listStore.isFetching} />
</div>
{/if}
{/if}
4 changes: 2 additions & 2 deletions tauri-app/src/lib/components/ModalVaultDeposit.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { TokenVault as TokenVaultListItem } from '$lib/typeshare/vaultsList';
import InputTokenAmount from '$lib/components/InputTokenAmount.svelte';
import { vaultDeposit } from '$lib/utils/vaultDeposit';
import { toHex } from 'viem';
import { bigintStringToHex } from '$lib/utils/hex';
import ButtonLoading from '$lib/components/ButtonLoading.svelte';
export let open = false;
Expand Down Expand Up @@ -35,7 +35,7 @@
Vault ID
</h5>
<p class="break-all font-normal leading-tight text-gray-700 dark:text-gray-400">
{toHex(vault.vault_id)}
{bigintStringToHex(vault.vault_id)}
</p>
</div>

Expand Down
4 changes: 2 additions & 2 deletions tauri-app/src/lib/components/ModalVaultWithdraw.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { TokenVault as TokenVaultListItem } from '$lib/typeshare/vaultsList';
import InputTokenAmount from '$lib/components/InputTokenAmount.svelte';
import { vaultWithdraw } from '$lib/utils/vaultWithdraw';
import { toHex } from 'viem';
import { bigintStringToHex } from '$lib/utils/hex';
import ButtonLoading from '$lib/components/ButtonLoading.svelte';
export let open = false;
Expand Down Expand Up @@ -37,7 +37,7 @@
Vault ID
</h5>
<p class="break-all font-normal leading-tight text-gray-700 dark:text-gray-400">
{toHex(vault.vault_id)}
{bigintStringToHex(vault.vault_id)}
</p>
</div>

Expand Down
112 changes: 46 additions & 66 deletions tauri-app/src/lib/components/TableOrders.svelte
Original file line number Diff line number Diff line change
@@ -1,87 +1,67 @@
<script lang="ts">
import {
Button,
Table,
TableBody,
TableBodyCell,
TableBodyRow,
TableHead,
TableHeadCell,
Badge,
Dropdown,
DropdownItem,
} from 'flowbite-svelte';
import { DotsVerticalOutline, FileCsvOutline } from 'flowbite-svelte-icons';
import { DotsVerticalOutline } from 'flowbite-svelte-icons';
import { goto } from '$app/navigation';
import { orderRemove } from '$lib/utils/orderRemove';
import { formatTimestampSecondsAsLocal } from '$lib/utils/time';
import { walletAddressMatchesOrBlank } from '$lib/stores/settings';
import ButtonsPagination from '$lib/components/ButtonsPagination.svelte';
import type { PaginatedCachedStore } from '$lib/stores/paginatedStore';
import type { PaginatedCachedStore } from '$lib/storesGeneric/listStore';
import type { Order } from '$lib/typeshare/ordersList';
import ButtonLoading from './ButtonLoading.svelte';
import Hash from './Hash.svelte';
import { HashType } from '$lib/utils/hash';
import AppTable from '$lib/components/AppTable.svelte';
export let ordersList: PaginatedCachedStore<Order>;
</script>

{#if $ordersList.currentPage.length === 0}
<div class="text-center text-gray-900 dark:text-white">No Orders found</div>
{:else}
<Table divClass="cursor-pointer" hoverable={true}>
<TableHead>
<TableHeadCell>Active</TableHeadCell>
<TableHeadCell>Order ID</TableHeadCell>
<TableHeadCell>Owner</TableHeadCell>
<TableHeadCell>Created At</TableHeadCell>
<TableHeadCell>Input Token(s)</TableHeadCell>
<TableHeadCell>Output Token(s)</TableHeadCell>
<TableHeadCell padding="px-0"></TableHeadCell>
</TableHead>
<TableBody>
{#each $ordersList.currentPage as order}
<TableBodyRow on:click={() => goto(`/orders/${order.id}`)}>
<TableBodyCell tdClass="px-4 py-2">
{#if order.order_active}
<Badge color="green">Active</Badge>
{:else}
<Badge color="yellow">Inactive</Badge>
{/if}
</TableBodyCell>
<TableBodyCell tdClass="break-all px-4 py-2"><Hash type={HashType.Identifier} value={order.id} /></TableBodyCell>
<TableBodyCell tdClass="break-all px-4 py-2"><Hash type={HashType.Wallet} value={order.owner.id} /></TableBodyCell>
<TableBodyCell tdClass="break-word px-4 py-2">
{formatTimestampSecondsAsLocal(BigInt(order.timestamp))}
</TableBodyCell>
<TableBodyCell tdClass="break-word p-2">
{order.valid_inputs?.map((t) => t.token.symbol)}
</TableBodyCell>
<TableBodyCell tdClass="break-word p-2">
{order.valid_outputs?.map((t) => t.token.symbol)}
</TableBodyCell>
<TableBodyCell tdClass="px-0">
{#if $walletAddressMatchesOrBlank(order.owner.id) && order.order_active}
<Button color="alternative" outline={false} id={`order-menu-${order.id}`} class="border-none px-2 mr-2" on:click={(e)=> {e.stopPropagation();}}>
<DotsVerticalOutline class="dark:text-white"/>
</Button>
{/if}
</TableBodyCell>
{#if $walletAddressMatchesOrBlank(order.owner.id) && order.order_active}
<Dropdown placement="bottom-end" triggeredBy={`#order-menu-${order.id}`}>
<DropdownItem on:click={(e) => {e.stopPropagation(); orderRemove(order.id);}}>Remove</DropdownItem>
</Dropdown>
{/if}
</TableBodyRow>
{/each}
</TableBody>
</Table>
<AppTable listStore={ordersList} emptyMessage="No Orders Found" on:clickRow={(e) => { goto(`/orders/${e.detail.item.id}`); }}>
<svelte:fragment slot="head">
<TableHeadCell>Active</TableHeadCell>
<TableHeadCell>Order ID</TableHeadCell>
<TableHeadCell>Owner</TableHeadCell>
<TableHeadCell>Created At</TableHeadCell>
<TableHeadCell>Input Token(s)</TableHeadCell>
<TableHeadCell>Output Token(s)</TableHeadCell>
<TableHeadCell></TableHeadCell>
</svelte:fragment>

<div class="flex justify-between mt-2">
<ButtonLoading size="xs" color="blue" on:click={() => ordersList.exportCsv()} loading={$ordersList.isExporting}>
<FileCsvOutline class="w-4 h-4 mr-2"/>
Export to CSV
</ButtonLoading>
<ButtonsPagination index={$ordersList.index} on:previous={ordersList.fetchPrev} on:next={ordersList.fetchNext} loading={$ordersList.isFetching} />
</div>
{/if}
<svelte:fragment slot="bodyRow" let:item>
<TableBodyCell tdClass="px-4 py-2">
{#if item.order_active}
<Badge color="green">Active</Badge>
{:else}
<Badge color="yellow">Inactive</Badge>
{/if}
</TableBodyCell>
<TableBodyCell tdClass="break-all px-4 py-2"><Hash type={HashType.Identifier} value={item.id} /></TableBodyCell>
<TableBodyCell tdClass="break-all px-4 py-2"><Hash type={HashType.Wallet} value={item.owner.id} /></TableBodyCell>
<TableBodyCell tdClass="break-word px-4 py-2">
{formatTimestampSecondsAsLocal(BigInt(item.timestamp))}
</TableBodyCell>
<TableBodyCell tdClass="break-word p-2">
{item.valid_inputs?.map((t) => t.token.symbol)}
</TableBodyCell>
<TableBodyCell tdClass="break-word p-2">
{item.valid_outputs?.map((t) => t.token.symbol)}
</TableBodyCell>
<TableBodyCell tdClass="px-0">
{#if $walletAddressMatchesOrBlank(item.owner.id) && item.order_active}
<Button color="alternative" outline={false} id={`order-menu-${item.id}`} class="border-none px-2 mr-2" on:click={(e)=> {e.stopPropagation();}}>
<DotsVerticalOutline class="dark:text-white"/>
</Button>
{/if}
</TableBodyCell>
{#if $walletAddressMatchesOrBlank(item.owner.id) && item.order_active}
<Dropdown placement="bottom-end" triggeredBy={`#order-menu-${item.id}`}>
<DropdownItem on:click={(e) => {e.stopPropagation(); orderRemove(item.id);}}>Remove</DropdownItem>
</Dropdown>
{/if}
</svelte:fragment>
</AppTable>
91 changes: 35 additions & 56 deletions tauri-app/src/routes/vaults/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,22 @@
Button,
Dropdown,
DropdownItem,
Table,
TableBody,
TableBodyCell,
TableBodyRow,
TableHead,
TableHeadCell,
} from 'flowbite-svelte';
import { goto } from '$app/navigation';
import { vaultsList } from '$lib/stores/vaultsList';
import PageHeader from '$lib/components/PageHeader.svelte';
import { DotsVerticalOutline, FileCsvOutline } from 'flowbite-svelte-icons';
import { DotsVerticalOutline } from 'flowbite-svelte-icons';
import { walletAddressMatchesOrBlank } from '$lib/stores/settings';
import ModalVaultWithdraw from '$lib/components/ModalVaultWithdraw.svelte';
import ModalVaultDeposit from '$lib/components/ModalVaultDeposit.svelte';
import ModalVaultDepositGeneric from '$lib/components/ModalVaultDepositGeneric.svelte';
import type { TokenVault } from '$lib/typeshare/vaultsList';
import ButtonsPagination from '$lib/components/ButtonsPagination.svelte';
import ButtonLoading from '$lib/components/ButtonLoading.svelte';
import Hash from '$lib/components/Hash.svelte';
import { HashType } from '$lib/utils/hash';
import { bigintStringToHex } from '$lib/utils/hex';
import AppTable from '$lib/components/AppTable.svelte';
let showDepositModal = false;
let showWithdrawModal = false;
Expand All @@ -33,60 +28,44 @@
let withdrawModalVault: TokenVault;
redirectIfSettingsNotDefined();
vaultsList.fetchFirst();
</script>

<PageHeader title="Vaults" />

{#if $vaultsList.currentPage.length === 0}
<div class="text-center text-gray-900 dark:text-white">No Vaults found</div>
{:else}
<Table divClass="cursor-pointer" hoverable={true}>
<TableHead>
<TableHeadCell>Vault ID</TableHeadCell>
<TableHeadCell>Owner</TableHeadCell>
<TableHeadCell>Token</TableHeadCell>
<TableHeadCell>Balance</TableHeadCell>
<TableHeadCell></TableHeadCell>
</TableHead>
<TableBody>
{#each $vaultsList.currentPage as vault}
<TableBodyRow on:click={() => {goto(`/vaults/${vault.id}`)}}>
<TableBodyCell tdClass="break-all px-4 py-2">{bigintStringToHex(vault.vault_id)}</TableBodyCell>
<TableBodyCell tdClass="break-all px-4 py-2 min-w-48"><Hash type={HashType.Wallet} value={vault.owner.id} /></TableBodyCell>
<TableBodyCell tdClass="break-word p-2 min-w-48">{vault.token.name}</TableBodyCell>
<TableBodyCell tdClass="break-all p-2 min-w-48">
{vault.balance_display}
{vault.token.symbol}
</TableBodyCell>
<TableBodyCell tdClass="px-0">
{#if $walletAddressMatchesOrBlank(vault.owner.id)}
<Button color="alternative" outline={false} id={`vault-menu-${vault.id}`} class="border-none px-2 mr-2" on:click={(e)=> {e.stopPropagation();}}>
<DotsVerticalOutline class="dark:text-white"/>
</Button>
{/if}
</TableBodyCell>
{#if $walletAddressMatchesOrBlank(vault.owner.id)}
<Dropdown placement="bottom-end" triggeredBy={`#vault-menu-${vault.id}`}>
<DropdownItem on:click={(e) => {e.stopPropagation(); depositModalVault=vault; showDepositModal = true;}}>Deposit</DropdownItem>
<DropdownItem on:click={(e) => {e.stopPropagation(); withdrawModalVault=vault; showWithdrawModal = true;}}>Withdraw</DropdownItem>
</Dropdown>
{/if}
</TableBodyRow>
{/each}
</TableBody>
</Table>
<AppTable listStore={vaultsList} emptyMessage="No Vaults Found" on:clickRow={(e) => { goto(`/vaults/${e.detail.item.id}`); }}>
<svelte:fragment slot="head">
<TableHeadCell>Vault ID</TableHeadCell>
<TableHeadCell>Owner</TableHeadCell>
<TableHeadCell>Token</TableHeadCell>
<TableHeadCell>Balance</TableHeadCell>
<TableHeadCell></TableHeadCell>
</svelte:fragment>

<div class="flex justify-between mt-2">
<ButtonLoading size="xs" color="blue" on:click={() => vaultsList.exportCsv()} loading={$vaultsList.isExporting}>
<FileCsvOutline class="w-4 h-4 mr-2"/>
Export to CSV
</ButtonLoading>
<ButtonsPagination index={$vaultsList.index} on:previous={vaultsList.fetchPrev} on:next={vaultsList.fetchNext} loading={$vaultsList.isFetching} />
</div>
<svelte:fragment slot="bodyRow" let:item>
<TableBodyCell tdClass="break-all px-4 py-2">{bigintStringToHex(item.vault_id)}</TableBodyCell>
<TableBodyCell tdClass="break-all px-4 py-2 min-w-48"><Hash type={HashType.Wallet} value={item.owner.id} /></TableBodyCell>
<TableBodyCell tdClass="break-word p-2 min-w-48">{item.token.name}</TableBodyCell>
<TableBodyCell tdClass="break-all p-2 min-w-48">
{item.balance_display}
{item.token.symbol}
</TableBodyCell>
<TableBodyCell tdClass="px-0">
{#if $walletAddressMatchesOrBlank(item.owner.id)}
<Button color="alternative" outline={false} id={`vault-menu-${item.id}`} class="border-none px-2 mr-2" on:click={(e)=> {e.stopPropagation();}}>
<DotsVerticalOutline class="dark:text-white"/>
</Button>
{/if}
</TableBodyCell>
{#if $walletAddressMatchesOrBlank(item.owner.id)}
<Dropdown placement="bottom-end" triggeredBy={`#vault-menu-${item.id}`}>
<DropdownItem on:click={(e) => {e.stopPropagation(); depositModalVault=item; showDepositModal = true;}}>Deposit</DropdownItem>
<DropdownItem on:click={(e) => {e.stopPropagation(); withdrawModalVault=item; showWithdrawModal = true;}}>Withdraw</DropdownItem>
</Dropdown>
{/if}

<ModalVaultDeposit bind:open={showDepositModal} vault={depositModalVault} />
<ModalVaultWithdraw bind:open={showWithdrawModal} vault={withdrawModalVault} />
{/if}
<ModalVaultDeposit bind:open={showDepositModal} vault={depositModalVault} />
<ModalVaultWithdraw bind:open={showWithdrawModal} vault={withdrawModalVault} />
</svelte:fragment>
</AppTable>

<ModalVaultDepositGeneric bind:open={showDepositGenericModal} />
Loading

0 comments on commit eed945f

Please sign in to comment.