@rainlanguage/ui-components 0.0.1-alpha.196 → 0.0.1-alpha.200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__mocks__/stores.d.ts +15 -0
- package/dist/__mocks__/stores.js +18 -0
- package/dist/components/CheckboxInactiveOrdersVault.svelte +20 -0
- package/dist/components/CheckboxInactiveOrdersVault.svelte.d.ts +19 -0
- package/dist/components/ListViewOrderbookFilters.svelte +14 -0
- package/dist/components/ListViewOrderbookFilters.svelte.d.ts +3 -0
- package/dist/components/LocalDbStatusBadge.svelte +27 -0
- package/dist/components/LocalDbStatusBadge.svelte.d.ts +19 -0
- package/dist/components/LocalDbStatusCard.svelte +40 -0
- package/dist/components/LocalDbStatusCard.svelte.d.ts +20 -0
- package/dist/components/LocalDbStatusModal.svelte +103 -0
- package/dist/components/LocalDbStatusModal.svelte.d.ts +21 -0
- package/dist/components/TanstackAppTable.svelte +176 -29
- package/dist/components/TanstackAppTable.svelte.d.ts +5 -0
- package/dist/components/VaultBalanceChangeTypeFilter.svelte +23 -0
- package/dist/components/VaultBalanceChangeTypeFilter.svelte.d.ts +19 -0
- package/dist/components/VaultCard.svelte +2 -2
- package/dist/components/charts/OrderTradesChart.svelte +295 -13
- package/dist/components/charts/OrderTradesChart.svelte.d.ts +2 -2
- package/dist/components/deployment/TokenSelectionModal.svelte +20 -0
- package/dist/components/deployment/TokenSelectionModal.svelte.d.ts +3 -3
- package/dist/components/detail/OrderDetail.svelte +20 -6
- package/dist/components/detail/OrderDetail.svelte.d.ts +0 -1
- package/dist/components/detail/TanstackOrderQuote.svelte +25 -7
- package/dist/components/detail/VaultDetail.svelte +20 -2
- package/dist/components/dropdown/DropdownActiveNetworks.svelte +6 -11
- package/dist/components/dropdown/DropdownCheckbox.svelte +2 -2
- package/dist/components/dropdown/DropdownOrderbooksFilter.svelte +172 -0
- package/dist/components/dropdown/DropdownOrderbooksFilter.svelte.d.ts +25 -0
- package/dist/components/dropdown/DropdownTokensFilter.svelte +13 -10
- package/dist/components/tables/OrderTradesListTable.svelte +65 -33
- package/dist/components/tables/OrderVaultsVolTable.svelte +26 -37
- package/dist/components/tables/OrderVaultsVolTable.svelte.d.ts +4 -1
- package/dist/components/tables/OrdersListTable.svelte +64 -75
- package/dist/components/tables/OrdersListTable.svelte.d.ts +2 -1
- package/dist/components/tables/VaultBalanceChangesTable.svelte +76 -28
- package/dist/components/tables/VaultsListTable.svelte +75 -31
- package/dist/components/tables/VaultsListTable.svelte.d.ts +2 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +8 -0
- package/dist/models/Transaction.d.ts +4 -8
- package/dist/models/Transaction.js +17 -49
- package/dist/providers/dotrainRegistry/DotrainRegistryProvider.svelte +8 -0
- package/dist/providers/dotrainRegistry/DotrainRegistryProvider.svelte.d.ts +24 -0
- package/dist/providers/dotrainRegistry/context.d.ts +9 -0
- package/dist/providers/dotrainRegistry/context.js +40 -0
- package/dist/providers/dotrainRegistry/useDotrainRegistry.d.ts +5 -0
- package/dist/providers/dotrainRegistry/useDotrainRegistry.js +35 -0
- package/dist/providers/transactions/TransactionManager.d.ts +20 -4
- package/dist/providers/transactions/TransactionManager.js +99 -46
- package/dist/services/getExplorerLink.d.ts +1 -1
- package/dist/services/getExplorerLink.js +2 -4
- package/dist/services/pairTradesChartData.d.ts +47 -0
- package/dist/services/pairTradesChartData.js +190 -0
- package/dist/types/appStores.d.ts +2 -0
- package/dist/types/transaction.d.ts +23 -2
- package/dist/utils/vaultBalanceChangeLabels.d.ts +4 -0
- package/dist/utils/vaultBalanceChangeLabels.js +18 -0
- package/package.json +7 -2
|
@@ -36,6 +36,11 @@ export declare const mockHideZeroBalanceVaultsStore: {
|
|
|
36
36
|
set: (this: void, value: boolean) => void;
|
|
37
37
|
mockSetSubscribeValue: (value: boolean) => void;
|
|
38
38
|
};
|
|
39
|
+
export declare const mockHideInactiveOrdersVaultsStore: {
|
|
40
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<boolean>, invalidate?: import("svelte/store").Invalidator<boolean> | undefined) => import("svelte/store").Unsubscriber;
|
|
41
|
+
set: (this: void, value: boolean) => void;
|
|
42
|
+
mockSetSubscribeValue: (value: boolean) => void;
|
|
43
|
+
};
|
|
39
44
|
export declare const mockActiveNetworkRefStore: {
|
|
40
45
|
subscribe: (this: void, run: import("svelte/store").Subscriber<string>, invalidate?: import("svelte/store").Invalidator<string> | undefined) => import("svelte/store").Unsubscriber;
|
|
41
46
|
set: (this: void, value: string) => void;
|
|
@@ -137,4 +142,14 @@ export declare const mockPageStore: {
|
|
|
137
142
|
mockSetSubscribeValue: (newValue: Partial<typeof initialPageState>) => void;
|
|
138
143
|
reset: () => void;
|
|
139
144
|
};
|
|
145
|
+
export declare const mockActiveTokensStore: {
|
|
146
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<string[]>, invalidate?: import("svelte/store").Invalidator<string[]> | undefined) => import("svelte/store").Unsubscriber;
|
|
147
|
+
set: (this: void, value: string[]) => void;
|
|
148
|
+
mockSetSubscribeValue: (value: string[]) => void;
|
|
149
|
+
};
|
|
150
|
+
export declare const mockActiveOrderbookAddressesStore: {
|
|
151
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<string[]>, invalidate?: import("svelte/store").Invalidator<string[]> | undefined) => import("svelte/store").Unsubscriber;
|
|
152
|
+
set: (this: void, value: string[]) => void;
|
|
153
|
+
mockSetSubscribeValue: (value: string[]) => void;
|
|
154
|
+
};
|
|
140
155
|
export {};
|
package/dist/__mocks__/stores.js
CHANGED
|
@@ -29,6 +29,7 @@ const mockActiveAccountsItemsWritable = writable({});
|
|
|
29
29
|
const mockShowInactiveOrdersWritable = writable(true);
|
|
30
30
|
const mockOrderHashWritable = writable('');
|
|
31
31
|
const mockHideZeroBalanceVaultsWritable = writable(false);
|
|
32
|
+
const mockHideInactiveOrdersVaultsWritable = writable(false);
|
|
32
33
|
const mockActiveNetworkRefWritable = writable('');
|
|
33
34
|
const mockActiveOrderbookRefWritable = writable('');
|
|
34
35
|
const mockActiveAccountsWritable = writable({});
|
|
@@ -38,6 +39,8 @@ const mockConnectedWritable = writable(true);
|
|
|
38
39
|
const mockWagmiConfigWritable = writable(mockWeb3Config);
|
|
39
40
|
const mockShowMyItemsOnlyWritable = writable(false);
|
|
40
41
|
const mockSelectedChainIdsWritable = writable([]);
|
|
42
|
+
const mockActiveTokensWritable = writable([]);
|
|
43
|
+
const mockActiveOrderbookAddressesWritable = writable([]);
|
|
41
44
|
export const mockActiveAccountsItemsStore = {
|
|
42
45
|
subscribe: mockActiveAccountsItemsWritable.subscribe,
|
|
43
46
|
set: mockActiveAccountsItemsWritable.set,
|
|
@@ -58,6 +61,11 @@ export const mockHideZeroBalanceVaultsStore = {
|
|
|
58
61
|
set: mockHideZeroBalanceVaultsWritable.set,
|
|
59
62
|
mockSetSubscribeValue: (value) => mockHideZeroBalanceVaultsWritable.set(value)
|
|
60
63
|
};
|
|
64
|
+
export const mockHideInactiveOrdersVaultsStore = {
|
|
65
|
+
subscribe: mockHideInactiveOrdersVaultsWritable.subscribe,
|
|
66
|
+
set: mockHideInactiveOrdersVaultsWritable.set,
|
|
67
|
+
mockSetSubscribeValue: (value) => mockHideInactiveOrdersVaultsWritable.set(value)
|
|
68
|
+
};
|
|
61
69
|
export const mockActiveNetworkRefStore = {
|
|
62
70
|
subscribe: mockActiveNetworkRefWritable.subscribe,
|
|
63
71
|
set: mockActiveNetworkRefWritable.set,
|
|
@@ -116,3 +124,13 @@ export const mockPageStore = {
|
|
|
116
124
|
},
|
|
117
125
|
reset: () => mockPageWritable.set(initialPageState)
|
|
118
126
|
};
|
|
127
|
+
export const mockActiveTokensStore = {
|
|
128
|
+
subscribe: mockActiveTokensWritable.subscribe,
|
|
129
|
+
set: mockActiveTokensWritable.set,
|
|
130
|
+
mockSetSubscribeValue: (value) => mockActiveTokensWritable.set(value)
|
|
131
|
+
};
|
|
132
|
+
export const mockActiveOrderbookAddressesStore = {
|
|
133
|
+
subscribe: mockActiveOrderbookAddressesWritable.subscribe,
|
|
134
|
+
set: mockActiveOrderbookAddressesWritable.set,
|
|
135
|
+
mockSetSubscribeValue: (value) => mockActiveOrderbookAddressesWritable.set(value)
|
|
136
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script>import { Checkbox, Label } from "flowbite-svelte";
|
|
2
|
+
export let hideInactiveOrdersVaults;
|
|
3
|
+
function handleHideInactiveOrdersVaultsChange() {
|
|
4
|
+
$hideInactiveOrdersVaults = !$hideInactiveOrdersVaults;
|
|
5
|
+
}
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div data-testid="inactive-orders-vault-checkbox" class="flex items-center gap-x-2">
|
|
9
|
+
<Label
|
|
10
|
+
for="hide-inactive-orders-vaults"
|
|
11
|
+
class="cursor-pointer whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-300"
|
|
12
|
+
>
|
|
13
|
+
Hide vaults without active orders
|
|
14
|
+
</Label>
|
|
15
|
+
<Checkbox
|
|
16
|
+
id="hide-inactive-orders-vaults"
|
|
17
|
+
checked={$hideInactiveOrdersVaults}
|
|
18
|
+
on:change={handleHideInactiveOrdersVaultsChange}
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { AppStoresInterface } from '../types/appStores';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
hideInactiveOrdersVaults: AppStoresInterface["hideInactiveOrdersVaults"];
|
|
6
|
+
};
|
|
7
|
+
events: {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
};
|
|
10
|
+
slots: {};
|
|
11
|
+
exports?: {} | undefined;
|
|
12
|
+
bindings?: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
export type CheckboxInactiveOrdersVaultProps = typeof __propDef.props;
|
|
15
|
+
export type CheckboxInactiveOrdersVaultEvents = typeof __propDef.events;
|
|
16
|
+
export type CheckboxInactiveOrdersVaultSlots = typeof __propDef.slots;
|
|
17
|
+
export default class CheckboxInactiveOrdersVault extends SvelteComponent<CheckboxInactiveOrdersVaultProps, CheckboxInactiveOrdersVaultEvents, CheckboxInactiveOrdersVaultSlots> {
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -7,11 +7,14 @@ import Tooltip from "./Tooltip.svelte";
|
|
|
7
7
|
import CheckboxActiveOrders from "./checkbox/CheckboxActiveOrders.svelte";
|
|
8
8
|
import DropdownOrderListAccounts from "./dropdown/DropdownOrderListAccounts.svelte";
|
|
9
9
|
import DropdownTokensFilter from "./dropdown/DropdownTokensFilter.svelte";
|
|
10
|
+
import DropdownOrderbooksFilter from "./dropdown/DropdownOrderbooksFilter.svelte";
|
|
10
11
|
import InputOrderHash from "./input/InputOrderHash.svelte";
|
|
11
12
|
import CheckboxZeroBalanceVault from "./CheckboxZeroBalanceVault.svelte";
|
|
13
|
+
import CheckboxInactiveOrdersVault from "./CheckboxInactiveOrdersVault.svelte";
|
|
12
14
|
import CheckboxMyItemsOnly from "./CheckboxMyItemsOnly.svelte";
|
|
13
15
|
import { useAccount } from "../providers/wallet/useAccount";
|
|
14
16
|
export let hideZeroBalanceVaults;
|
|
17
|
+
export let hideInactiveOrdersVaults;
|
|
15
18
|
export let activeAccountsItems;
|
|
16
19
|
export let showMyItemsOnly;
|
|
17
20
|
export let selectedChainIds;
|
|
@@ -20,6 +23,8 @@ export let orderHash;
|
|
|
20
23
|
export let activeTokens;
|
|
21
24
|
export let selectedTokens;
|
|
22
25
|
export let tokensQuery;
|
|
26
|
+
export let activeOrderbookAddresses;
|
|
27
|
+
export let selectedOrderbookAddresses;
|
|
23
28
|
$: isVaultsPage = $page.url.pathname === "/vaults";
|
|
24
29
|
$: isOrdersPage = $page.url.pathname === "/orders";
|
|
25
30
|
const { account } = useAccount();
|
|
@@ -49,6 +54,9 @@ $: accounts = raindexClient.getAllAccounts();
|
|
|
49
54
|
<div class="mt-4 w-full lg:w-auto">
|
|
50
55
|
<CheckboxZeroBalanceVault {hideZeroBalanceVaults} />
|
|
51
56
|
</div>
|
|
57
|
+
<div class="mt-4 w-full lg:w-auto">
|
|
58
|
+
<CheckboxInactiveOrdersVault {hideInactiveOrdersVaults} />
|
|
59
|
+
</div>
|
|
52
60
|
{/if}
|
|
53
61
|
|
|
54
62
|
{#if isOrdersPage}
|
|
@@ -61,6 +69,12 @@ $: accounts = raindexClient.getAllAccounts();
|
|
|
61
69
|
<DropdownOrderListAccounts {activeAccountsItems} />
|
|
62
70
|
{/if}
|
|
63
71
|
<DropdownTokensFilter {tokensQuery} {activeTokens} {selectedTokens} label="Tokens" />
|
|
72
|
+
<DropdownOrderbooksFilter
|
|
73
|
+
{activeOrderbookAddresses}
|
|
74
|
+
{selectedOrderbookAddresses}
|
|
75
|
+
selectedChainIds={$selectedChainIds}
|
|
76
|
+
label="Orderbooks"
|
|
77
|
+
/>
|
|
64
78
|
<DropdownActiveNetworks {selectedChainIds} />
|
|
65
79
|
{/if}
|
|
66
80
|
</div>
|
|
@@ -6,6 +6,7 @@ import type { AppStoresInterface } from '../types/appStores';
|
|
|
6
6
|
declare const __propDef: {
|
|
7
7
|
props: {
|
|
8
8
|
hideZeroBalanceVaults: AppStoresInterface["hideZeroBalanceVaults"];
|
|
9
|
+
hideInactiveOrdersVaults: AppStoresInterface["hideInactiveOrdersVaults"];
|
|
9
10
|
activeAccountsItems: AppStoresInterface["activeAccountsItems"];
|
|
10
11
|
showMyItemsOnly: AppStoresInterface["showMyItemsOnly"];
|
|
11
12
|
selectedChainIds: AppStoresInterface["selectedChainIds"];
|
|
@@ -14,6 +15,8 @@ declare const __propDef: {
|
|
|
14
15
|
activeTokens: AppStoresInterface["activeTokens"];
|
|
15
16
|
selectedTokens: Address[];
|
|
16
17
|
tokensQuery: Readable<QueryObserverResult<RaindexVaultToken[], Error>>;
|
|
18
|
+
activeOrderbookAddresses: AppStoresInterface["activeOrderbookAddresses"];
|
|
19
|
+
selectedOrderbookAddresses: Address[];
|
|
17
20
|
};
|
|
18
21
|
events: {
|
|
19
22
|
[evt: string]: CustomEvent<any>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script>const STATUS_LABELS = {
|
|
2
|
+
active: "Active",
|
|
3
|
+
syncing: "Syncing",
|
|
4
|
+
failure: "Failure"
|
|
5
|
+
};
|
|
6
|
+
const DOT_CLASSES = {
|
|
7
|
+
active: "bg-emerald-400",
|
|
8
|
+
syncing: "bg-sky-400",
|
|
9
|
+
failure: "bg-red-500"
|
|
10
|
+
};
|
|
11
|
+
const TEXT_CLASSES = {
|
|
12
|
+
active: "text-emerald-400",
|
|
13
|
+
syncing: "text-sky-400",
|
|
14
|
+
failure: "text-red-400"
|
|
15
|
+
};
|
|
16
|
+
export let status = "active";
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<span
|
|
20
|
+
class="inline-flex items-center gap-2 rounded-full border border-gray-200 bg-gray-100 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-gray-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300"
|
|
21
|
+
data-testid="local-db-status"
|
|
22
|
+
>
|
|
23
|
+
<span class={`h-2 w-2 rounded-full ${DOT_CLASSES[status]}`} aria-hidden="true" />
|
|
24
|
+
<span class={TEXT_CLASSES[status]}>
|
|
25
|
+
{STATUS_LABELS[status]}
|
|
26
|
+
</span>
|
|
27
|
+
</span>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { LocalDbStatus } from '@rainlanguage/orderbook';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
status?: LocalDbStatus;
|
|
6
|
+
};
|
|
7
|
+
events: {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
};
|
|
10
|
+
slots: {};
|
|
11
|
+
exports?: {} | undefined;
|
|
12
|
+
bindings?: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
export type LocalDbStatusBadgeProps = typeof __propDef.props;
|
|
15
|
+
export type LocalDbStatusBadgeEvents = typeof __propDef.events;
|
|
16
|
+
export type LocalDbStatusBadgeSlots = typeof __propDef.slots;
|
|
17
|
+
export default class LocalDbStatusBadge extends SvelteComponent<LocalDbStatusBadgeProps, LocalDbStatusBadgeEvents, LocalDbStatusBadgeSlots> {
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script>import LocalDbStatusBadge from "./LocalDbStatusBadge.svelte";
|
|
2
|
+
import LocalDbStatusModal from "./LocalDbStatusModal.svelte";
|
|
3
|
+
import { ChevronRightOutline } from "flowbite-svelte-icons";
|
|
4
|
+
export let networkStatuses = /* @__PURE__ */ new Map();
|
|
5
|
+
export let orderbookStatuses = /* @__PURE__ */ new Map();
|
|
6
|
+
let modalOpen = false;
|
|
7
|
+
$: networkList = Array.from(networkStatuses.values());
|
|
8
|
+
$: hasNetworks = networkList.length > 0;
|
|
9
|
+
$: hasFailure = networkList.some((s) => s.status === "failure");
|
|
10
|
+
$: displayStatus = hasFailure ? "failure" : "active";
|
|
11
|
+
function openModal() {
|
|
12
|
+
modalOpen = true;
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class="rounded-lg border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900"
|
|
18
|
+
data-testid="local-db-status-card"
|
|
19
|
+
>
|
|
20
|
+
<button
|
|
21
|
+
type="button"
|
|
22
|
+
class="flex w-full items-center justify-between px-3 py-3 text-left transition hover:bg-gray-50 dark:hover:bg-gray-800"
|
|
23
|
+
on:click={openModal}
|
|
24
|
+
data-testid="local-db-status-header"
|
|
25
|
+
>
|
|
26
|
+
<div class="flex items-center gap-2">
|
|
27
|
+
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400"
|
|
28
|
+
>LocalDB</span
|
|
29
|
+
>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="flex items-center gap-2">
|
|
32
|
+
<LocalDbStatusBadge status={displayStatus} />
|
|
33
|
+
{#if hasNetworks}
|
|
34
|
+
<ChevronRightOutline class="h-3 w-3 shrink-0" />
|
|
35
|
+
{/if}
|
|
36
|
+
</div>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<LocalDbStatusModal bind:open={modalOpen} {networkStatuses} {orderbookStatuses} />
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { NetworkSyncStatus, OrderbookSyncStatus } from '@rainlanguage/orderbook';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
networkStatuses?: Map<number, NetworkSyncStatus>;
|
|
6
|
+
orderbookStatuses?: Map<string, OrderbookSyncStatus>;
|
|
7
|
+
};
|
|
8
|
+
events: {
|
|
9
|
+
[evt: string]: CustomEvent<any>;
|
|
10
|
+
};
|
|
11
|
+
slots: {};
|
|
12
|
+
exports?: {} | undefined;
|
|
13
|
+
bindings?: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
export type LocalDbStatusCardProps = typeof __propDef.props;
|
|
16
|
+
export type LocalDbStatusCardEvents = typeof __propDef.events;
|
|
17
|
+
export type LocalDbStatusCardSlots = typeof __propDef.slots;
|
|
18
|
+
export default class LocalDbStatusCard extends SvelteComponent<LocalDbStatusCardProps, LocalDbStatusCardEvents, LocalDbStatusCardSlots> {
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script>import { Modal } from "flowbite-svelte";
|
|
2
|
+
import LocalDbStatusBadge from "./LocalDbStatusBadge.svelte";
|
|
3
|
+
import { getNetworkName } from "../utils/getNetworkName";
|
|
4
|
+
export let open = false;
|
|
5
|
+
export let networkStatuses = /* @__PURE__ */ new Map();
|
|
6
|
+
export let orderbookStatuses = /* @__PURE__ */ new Map();
|
|
7
|
+
$: networkList = Array.from(networkStatuses.values());
|
|
8
|
+
$: orderbookList = Array.from(orderbookStatuses.values());
|
|
9
|
+
$: networkGroups = buildNetworkGroups(networkList, orderbookList);
|
|
10
|
+
function buildNetworkGroups(networks, orderbooks) {
|
|
11
|
+
const groups = [];
|
|
12
|
+
for (const network of networks) {
|
|
13
|
+
const networkOrderbooks = orderbooks.filter((ob) => ob.obId.chainId === network.chainId);
|
|
14
|
+
groups.push({
|
|
15
|
+
chainId: network.chainId,
|
|
16
|
+
networkName: getNetworkName(network.chainId) ?? `Chain ${network.chainId}`,
|
|
17
|
+
status: network,
|
|
18
|
+
orderbooks: networkOrderbooks
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return groups;
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<Modal
|
|
26
|
+
bind:open
|
|
27
|
+
size="lg"
|
|
28
|
+
class="dark:border dark:border-gray-700 dark:bg-gray-900"
|
|
29
|
+
dialogClass="fixed top-0 start-0 end-1 h-modal md:inset-0 md:h-full z-50 w-full p-4 flex justify-center items-center h-full"
|
|
30
|
+
data-testid="local-db-status-modal"
|
|
31
|
+
>
|
|
32
|
+
<div class="flex flex-col gap-4" slot="header">
|
|
33
|
+
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Database Sync Status</h3>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="max-h-[60vh] overflow-y-auto">
|
|
37
|
+
{#if networkList.length === 0}
|
|
38
|
+
<p class="text-sm text-gray-500 dark:text-gray-400">No networks are being synced.</p>
|
|
39
|
+
{:else}
|
|
40
|
+
<div class="space-y-4">
|
|
41
|
+
{#each networkGroups as group (group.chainId)}
|
|
42
|
+
<div
|
|
43
|
+
class="rounded-lg border border-gray-200 dark:border-gray-700"
|
|
44
|
+
data-testid="network-group-{group.chainId}"
|
|
45
|
+
>
|
|
46
|
+
<div
|
|
47
|
+
class="flex items-center justify-between border-b border-gray-200 bg-gray-50 px-4 py-3 dark:border-gray-700 dark:bg-gray-800"
|
|
48
|
+
>
|
|
49
|
+
<div class="flex items-center gap-2">
|
|
50
|
+
<span class="font-medium text-gray-900 dark:text-white">{group.networkName}</span>
|
|
51
|
+
{#if group.status.schedulerState === 'notLeader'}
|
|
52
|
+
<span
|
|
53
|
+
class="rounded bg-amber-100 px-1.5 py-0.5 text-[10px] font-medium uppercase text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"
|
|
54
|
+
>
|
|
55
|
+
Observing
|
|
56
|
+
</span>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
<LocalDbStatusBadge status={group.status.status} />
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{#if group.orderbooks.length > 0}
|
|
63
|
+
<ul class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
64
|
+
{#each group.orderbooks as obStatus (obStatus.obId.orderbookAddress)}
|
|
65
|
+
<li class="px-4 py-3">
|
|
66
|
+
<div class="flex items-start justify-between gap-4">
|
|
67
|
+
<div class="min-w-0 flex-1">
|
|
68
|
+
<span
|
|
69
|
+
class="font-mono text-sm text-gray-700 dark:text-gray-300"
|
|
70
|
+
title={obStatus.obId.orderbookAddress}
|
|
71
|
+
>
|
|
72
|
+
{obStatus.obId.orderbookAddress}
|
|
73
|
+
</span>
|
|
74
|
+
{#if obStatus.status === 'syncing' && obStatus.phaseMessage && obStatus.schedulerState !== 'notLeader'}
|
|
75
|
+
<div class="mt-2 text-sm text-sky-600 dark:text-sky-400">
|
|
76
|
+
{obStatus.phaseMessage}
|
|
77
|
+
</div>
|
|
78
|
+
{/if}
|
|
79
|
+
{#if obStatus.status === 'failure' && obStatus.error}
|
|
80
|
+
<div class="mt-2 text-sm text-red-600 dark:text-red-400">
|
|
81
|
+
{obStatus.error}
|
|
82
|
+
</div>
|
|
83
|
+
{/if}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</li>
|
|
87
|
+
{/each}
|
|
88
|
+
</ul>
|
|
89
|
+
{/if}
|
|
90
|
+
|
|
91
|
+
{#if group.status.status === 'failure' && group.status.error}
|
|
92
|
+
<div class="border-t border-gray-200 px-4 py-3 dark:border-gray-700">
|
|
93
|
+
<div class="text-sm text-red-600 dark:text-red-400">
|
|
94
|
+
{group.status.error}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
{/if}
|
|
98
|
+
</div>
|
|
99
|
+
{/each}
|
|
100
|
+
</div>
|
|
101
|
+
{/if}
|
|
102
|
+
</div>
|
|
103
|
+
</Modal>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { NetworkSyncStatus, OrderbookSyncStatus } from '@rainlanguage/orderbook';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
open?: boolean;
|
|
6
|
+
networkStatuses?: Map<number, NetworkSyncStatus>;
|
|
7
|
+
orderbookStatuses?: Map<string, OrderbookSyncStatus>;
|
|
8
|
+
};
|
|
9
|
+
events: {
|
|
10
|
+
[evt: string]: CustomEvent<any>;
|
|
11
|
+
};
|
|
12
|
+
slots: {};
|
|
13
|
+
exports?: {} | undefined;
|
|
14
|
+
bindings?: string | undefined;
|
|
15
|
+
};
|
|
16
|
+
export type LocalDbStatusModalProps = typeof __propDef.props;
|
|
17
|
+
export type LocalDbStatusModalEvents = typeof __propDef.events;
|
|
18
|
+
export type LocalDbStatusModalSlots = typeof __propDef.slots;
|
|
19
|
+
export default class LocalDbStatusModal extends SvelteComponent<LocalDbStatusModalProps, LocalDbStatusModalEvents, LocalDbStatusModalSlots> {
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script generics="DataItem, InputData = DataItem[]">import { invalidateTanstackQueries } from "../queries/queryClient";
|
|
2
2
|
import Refresh from "./icon/Refresh.svelte";
|
|
3
3
|
import { Button, Table, TableBody, TableBodyRow, TableHead } from "flowbite-svelte";
|
|
4
|
-
import { createEventDispatcher } from "svelte";
|
|
4
|
+
import { afterUpdate, createEventDispatcher, onDestroy, onMount } from "svelte";
|
|
5
5
|
import { useQueryClient } from "@tanstack/svelte-query";
|
|
6
|
+
import { createWindowVirtualizer } from "@tanstack/svelte-virtual";
|
|
6
7
|
const queryClient = useQueryClient();
|
|
7
8
|
const dispatch = createEventDispatcher();
|
|
8
9
|
export let queryKey;
|
|
@@ -10,10 +11,128 @@ export let query;
|
|
|
10
11
|
export let emptyMessage = "None found";
|
|
11
12
|
export let rowHoverable = true;
|
|
12
13
|
export let dataSelector = (pageData) => Array.isArray(pageData) ? pageData : [];
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export let virtualization = {};
|
|
15
|
+
$: enableVirtualization = virtualization.enabled ?? true;
|
|
16
|
+
$: estimatedRowHeight = virtualization.estimatedRowHeight ?? 56;
|
|
17
|
+
$: virtualizationOverscan = virtualization.overscan ?? 8;
|
|
18
|
+
let measuredRowHeight = null;
|
|
19
|
+
$: rowHeight = measuredRowHeight ?? estimatedRowHeight;
|
|
20
|
+
let transformedPages = [];
|
|
21
|
+
let lastPagesRef;
|
|
22
|
+
let lastSelector = dataSelector;
|
|
23
|
+
$: {
|
|
24
|
+
const currentData = $query.data;
|
|
25
|
+
const currentPages = currentData?.pages;
|
|
26
|
+
const selectorChanged = lastSelector !== dataSelector;
|
|
27
|
+
if (!currentPages) {
|
|
28
|
+
transformedPages = [];
|
|
29
|
+
lastPagesRef = void 0;
|
|
30
|
+
lastSelector = dataSelector;
|
|
31
|
+
} else if (currentPages !== lastPagesRef || selectorChanged) {
|
|
32
|
+
transformedPages = currentPages.map((page) => dataSelector(page));
|
|
33
|
+
lastPagesRef = currentPages;
|
|
34
|
+
lastSelector = dataSelector;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
$: flattenedRows = transformedPages.flat();
|
|
38
|
+
$: totalRows = flattenedRows.length;
|
|
39
|
+
$: hasData = totalRows > 0;
|
|
40
|
+
const hasWindow = typeof window !== "undefined";
|
|
41
|
+
let tableContainerElement = null;
|
|
42
|
+
let tableOffsetTop = 0;
|
|
43
|
+
let virtualizerStore = null;
|
|
44
|
+
let virtualizer = null;
|
|
45
|
+
let unsubscribeVirtualizer = null;
|
|
46
|
+
let virtualizationActive = false;
|
|
47
|
+
function updateTableOffset() {
|
|
48
|
+
if (!enableVirtualization || !hasWindow || !tableContainerElement) {
|
|
49
|
+
tableOffsetTop = 0;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const rect = tableContainerElement.getBoundingClientRect();
|
|
53
|
+
tableOffsetTop = rect.top + window.scrollY;
|
|
54
|
+
}
|
|
55
|
+
onMount(() => {
|
|
56
|
+
if (!hasWindow) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
virtualizerStore = createWindowVirtualizer({
|
|
60
|
+
count: totalRows,
|
|
61
|
+
estimateSize: () => rowHeight,
|
|
62
|
+
overscan: virtualizationOverscan,
|
|
63
|
+
scrollMargin: tableOffsetTop,
|
|
64
|
+
getItemKey: (index) => index,
|
|
65
|
+
enabled: enableVirtualization && totalRows > 0
|
|
66
|
+
});
|
|
67
|
+
unsubscribeVirtualizer = virtualizerStore.subscribe((instance) => {
|
|
68
|
+
virtualizer = instance;
|
|
69
|
+
});
|
|
70
|
+
updateTableOffset();
|
|
71
|
+
return () => {
|
|
72
|
+
unsubscribeVirtualizer?.();
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
afterUpdate(() => {
|
|
76
|
+
if (enableVirtualization) {
|
|
77
|
+
updateTableOffset();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
$: if (virtualizer) {
|
|
81
|
+
virtualizer.setOptions({
|
|
82
|
+
count: totalRows,
|
|
83
|
+
estimateSize: () => rowHeight,
|
|
84
|
+
overscan: virtualizationOverscan,
|
|
85
|
+
scrollMargin: tableOffsetTop,
|
|
86
|
+
getItemKey: (index) => index,
|
|
87
|
+
enabled: enableVirtualization && totalRows > 0
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
$: virtualizationActive = enableVirtualization && Boolean(virtualizer);
|
|
91
|
+
let virtualItems = [];
|
|
92
|
+
let totalSize = 0;
|
|
93
|
+
let topPadding = 0;
|
|
94
|
+
let bottomPadding = 0;
|
|
95
|
+
let scrollMargin = 0;
|
|
96
|
+
$: {
|
|
97
|
+
const hasRows = totalRows > 0;
|
|
98
|
+
scrollMargin = virtualizationActive ? tableOffsetTop : 0;
|
|
99
|
+
if (virtualizationActive && virtualizer && hasRows) {
|
|
100
|
+
virtualItems = virtualizer.getVirtualItems();
|
|
101
|
+
totalSize = virtualizer.getTotalSize();
|
|
102
|
+
const firstItem = virtualItems[0];
|
|
103
|
+
const lastItem = virtualItems[virtualItems.length - 1];
|
|
104
|
+
topPadding = firstItem ? Math.max(0, firstItem.start - scrollMargin) : 0;
|
|
105
|
+
bottomPadding = lastItem ? Math.max(0, totalSize - (lastItem.end - scrollMargin)) : Math.max(0, totalSize);
|
|
106
|
+
} else {
|
|
107
|
+
virtualItems = [];
|
|
108
|
+
totalSize = 0;
|
|
109
|
+
topPadding = 0;
|
|
110
|
+
bottomPadding = 0;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
onDestroy(() => {
|
|
114
|
+
unsubscribeVirtualizer?.();
|
|
115
|
+
});
|
|
116
|
+
afterUpdate(() => {
|
|
117
|
+
if (!virtualizationActive || !virtualizer || !tableContainerElement) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const rows = Array.from(
|
|
121
|
+
tableContainerElement.querySelectorAll('tbody tr[data-virtual-row="true"]')
|
|
122
|
+
);
|
|
123
|
+
if (!rows.length) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
for (const row of rows) {
|
|
127
|
+
virtualizer.measureElement(row);
|
|
128
|
+
}
|
|
129
|
+
if (measuredRowHeight === null) {
|
|
130
|
+
const sampleHeight = rows[0].getBoundingClientRect().height;
|
|
131
|
+
if (sampleHeight > 0) {
|
|
132
|
+
measuredRowHeight = sampleHeight;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
17
136
|
</script>
|
|
18
137
|
|
|
19
138
|
<div data-testid="title" class="flex h-16 w-full items-center justify-end">
|
|
@@ -31,34 +150,62 @@ $: data = $query.data ? {
|
|
|
31
150
|
}}
|
|
32
151
|
/>
|
|
33
152
|
</div>
|
|
34
|
-
{#if
|
|
153
|
+
{#if totalRows === 0}
|
|
35
154
|
<div data-testid="emptyMessage" class="text-center text-gray-900 dark:text-white">
|
|
36
155
|
{emptyMessage}
|
|
37
156
|
</div>
|
|
38
|
-
{:else if
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
157
|
+
{:else if hasData}
|
|
158
|
+
<div
|
|
159
|
+
class="cursor-pointer overflow-x-auto rounded-lg border dark:border-none"
|
|
160
|
+
data-testid="tanstackTableContainer"
|
|
161
|
+
bind:this={tableContainerElement}
|
|
42
162
|
>
|
|
43
|
-
<
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{#
|
|
49
|
-
<
|
|
50
|
-
class="
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
163
|
+
<Table divClass="min-w-full" class="w-full table-fixed" hoverable={rowHoverable}>
|
|
164
|
+
<TableHead data-testid="head">
|
|
165
|
+
<slot name="head" />
|
|
166
|
+
</TableHead>
|
|
167
|
+
<TableBody>
|
|
168
|
+
{#if virtualizationActive && topPadding > 0}
|
|
169
|
+
<tr aria-hidden="true">
|
|
170
|
+
<td colspan="1000" class="border-0 p-0" style={`height:${topPadding}px;`} />
|
|
171
|
+
</tr>
|
|
172
|
+
{/if}
|
|
173
|
+
{#if virtualizationActive}
|
|
174
|
+
{#each virtualItems as virtualItem (virtualItem.key)}
|
|
175
|
+
<TableBodyRow
|
|
176
|
+
class="whitespace-nowrap"
|
|
177
|
+
data-testid="bodyRow"
|
|
178
|
+
data-virtual-row="true"
|
|
179
|
+
on:click={() => {
|
|
180
|
+
dispatch('clickRow', { item: flattenedRows[virtualItem.index] });
|
|
181
|
+
}}
|
|
182
|
+
>
|
|
183
|
+
<slot name="bodyRow" item={flattenedRows[virtualItem.index]} />
|
|
184
|
+
</TableBodyRow>
|
|
185
|
+
{/each}
|
|
186
|
+
{:else}
|
|
187
|
+
{#each transformedPages as page}
|
|
188
|
+
{#each page as item}
|
|
189
|
+
<TableBodyRow
|
|
190
|
+
class="whitespace-nowrap"
|
|
191
|
+
data-testid="bodyRow"
|
|
192
|
+
on:click={() => {
|
|
193
|
+
dispatch('clickRow', { item });
|
|
194
|
+
}}
|
|
195
|
+
>
|
|
196
|
+
<slot name="bodyRow" {item} />
|
|
197
|
+
</TableBodyRow>
|
|
198
|
+
{/each}
|
|
199
|
+
{/each}
|
|
200
|
+
{/if}
|
|
201
|
+
{#if virtualizationActive && bottomPadding > 0}
|
|
202
|
+
<tr aria-hidden="true">
|
|
203
|
+
<td colspan="1000" class="border-0 p-0" style={`height:${bottomPadding}px;`} />
|
|
204
|
+
</tr>
|
|
205
|
+
{/if}
|
|
206
|
+
</TableBody>
|
|
207
|
+
</Table>
|
|
208
|
+
</div>
|
|
62
209
|
<div class="mt-2 flex justify-center">
|
|
63
210
|
<Button
|
|
64
211
|
data-testid="loadMoreButton"
|
|
@@ -7,6 +7,11 @@ declare class __sveltets_Render<DataItem, InputData = DataItem[]> {
|
|
|
7
7
|
emptyMessage?: string;
|
|
8
8
|
rowHoverable?: boolean;
|
|
9
9
|
dataSelector?: ((pageData: InputData) => DataItem[]) | undefined;
|
|
10
|
+
virtualization?: {
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
estimatedRowHeight?: number;
|
|
13
|
+
overscan?: number;
|
|
14
|
+
} | undefined;
|
|
10
15
|
};
|
|
11
16
|
events(): {
|
|
12
17
|
clickRow: CustomEvent<any>;
|