@peers-app/peers-ui 0.27.3 → 0.27.5
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/screens/network-viewer/group-details-modal.d.ts +4 -0
- package/dist/screens/network-viewer/group-details-modal.js +6 -46
- package/dist/screens/network-viewer/network-viewer-ipc.d.ts +3 -2
- package/dist/screens/network-viewer/network-viewer-ipc.js +6 -0
- package/dist/screens/network-viewer/sync-recovery.js +103 -1
- package/dist/screens/variables/variable-details.js +2 -1
- package/dist/tabs-layout/network-status-indicator.js +26 -12
- package/dist/tabs-layout/use-network-status.d.ts +6 -1
- package/dist/tabs-layout/use-network-status.js +27 -4
- package/package.json +9 -3
- package/.claude/settings.local.json +0 -34
- package/.github/README.md +0 -52
- package/.github/workflows/delete-all-artifacts.yml +0 -49
- package/.github/workflows/publish.yml +0 -51
- package/babel.config.js +0 -7
- package/biome.json +0 -198
- package/dist/app-updates/app-updates-consumer.test.d.ts +0 -1
- package/dist/app-updates/app-updates-consumer.test.js +0 -56
- package/dist/app-updates/app-updates-settings.test.d.ts +0 -1
- package/dist/app-updates/app-updates-settings.test.js +0 -93
- package/dist/app-updates/remote-app-update-panel.test.d.ts +0 -1
- package/dist/app-updates/remote-app-update-panel.test.js +0 -165
- package/dist/components/access-level-field.test.d.ts +0 -1
- package/dist/components/access-level-field.test.js +0 -28
- package/dist/components/message-logs/tool-access-approval-card.test.d.ts +0 -1
- package/dist/components/message-logs/tool-access-approval-card.test.js +0 -102
- package/dist/components/responsive-section-nav.test.d.ts +0 -1
- package/dist/components/responsive-section-nav.test.js +0 -45
- package/dist/globals-hash.test.d.ts +0 -1
- package/dist/globals-hash.test.js +0 -16
- package/dist/hooks/use-observable-state.test.d.ts +0 -1
- package/dist/hooks/use-observable-state.test.js +0 -64
- package/dist/hooks/use-observable.test.d.ts +0 -1
- package/dist/hooks/use-observable.test.js +0 -191
- package/dist/hooks/use-rows.test.d.ts +0 -1
- package/dist/hooks/use-rows.test.js +0 -175
- package/dist/hooks/use-tool.test.d.ts +0 -1
- package/dist/hooks/use-tool.test.js +0 -190
- package/dist/host-shell/host-shell-consumer.test.d.ts +0 -1
- package/dist/host-shell/host-shell-consumer.test.js +0 -28
- package/dist/root-layout/root-layout-host.test.d.ts +0 -1
- package/dist/root-layout/root-layout-host.test.js +0 -86
- package/dist/screens/account/account-screen.test.d.ts +0 -1
- package/dist/screens/account/account-screen.test.js +0 -51
- package/dist/screens/assistants/assistant-config.test.d.ts +0 -1
- package/dist/screens/assistants/assistant-config.test.js +0 -57
- package/dist/screens/contacts/contact-list.test.d.ts +0 -1
- package/dist/screens/contacts/contact-list.test.js +0 -48
- package/dist/screens/device-pairing/device-pairing.test.d.ts +0 -1
- package/dist/screens/device-pairing/device-pairing.test.js +0 -119
- package/dist/screens/devices/devices-list.test.d.ts +0 -1
- package/dist/screens/devices/devices-list.test.js +0 -53
- package/dist/screens/groups/group-list.test.d.ts +0 -1
- package/dist/screens/groups/group-list.test.js +0 -38
- package/dist/screens/identity/identity-routes.test.d.ts +0 -1
- package/dist/screens/identity/identity-routes.test.js +0 -51
- package/dist/screens/identity/identity-screen.test.d.ts +0 -1
- package/dist/screens/identity/identity-screen.test.js +0 -103
- package/dist/screens/invites/accept-invite.test.d.ts +0 -1
- package/dist/screens/invites/accept-invite.test.js +0 -103
- package/dist/screens/invites/activity-view.test.d.ts +0 -1
- package/dist/screens/invites/activity-view.test.js +0 -108
- package/dist/screens/invites/invite-classify.test.d.ts +0 -1
- package/dist/screens/invites/invite-classify.test.js +0 -115
- package/dist/screens/network-viewer/network-viewer-ipc.test.d.ts +0 -1
- package/dist/screens/network-viewer/network-viewer-ipc.test.js +0 -61
- package/dist/screens/network-viewer/network-viewer.section.test.d.ts +0 -1
- package/dist/screens/network-viewer/network-viewer.section.test.js +0 -63
- package/dist/screens/network-viewer/sync-recovery.test.d.ts +0 -1
- package/dist/screens/network-viewer/sync-recovery.test.js +0 -104
- package/dist/screens/packages/package-helpers.test.d.ts +0 -1
- package/dist/screens/packages/package-helpers.test.js +0 -53
- package/dist/screens/packages/package-runtime-status.test.d.ts +0 -1
- package/dist/screens/packages/package-runtime-status.test.js +0 -50
- package/dist/screens/packages/packages-ipc.test.d.ts +0 -1
- package/dist/screens/packages/packages-ipc.test.js +0 -43
- package/dist/screens/settings/settings-page.test.d.ts +0 -1
- package/dist/screens/settings/settings-page.test.js +0 -19
- package/dist/screens/tools/tool-access-ipc.test.d.ts +0 -1
- package/dist/screens/tools/tool-access-ipc.test.js +0 -40
- package/dist/screens/tools/tool-catalog-ipc.test.d.ts +0 -1
- package/dist/screens/tools/tool-catalog-ipc.test.js +0 -52
- package/dist/tabs-layout/network-status-indicator.test.d.ts +0 -1
- package/dist/tabs-layout/network-status-indicator.test.js +0 -665
- package/dist/tabs-layout/tabs-state.test.d.ts +0 -1
- package/dist/tabs-layout/tabs-state.test.js +0 -110
- package/dist/tabs-layout/use-network-status.test.d.ts +0 -1
- package/dist/tabs-layout/use-network-status.test.js +0 -45
- package/dist/ui-router/ui-loader.test.d.ts +0 -1
- package/dist/ui-router/ui-loader.test.js +0 -91
- package/jest.config.js +0 -25
- package/release-guard.js +0 -10
- package/src/app-updates/app-update-controls.tsx +0 -73
- package/src/app-updates/app-updates-consumer.test.ts +0 -83
- package/src/app-updates/app-updates-consumer.ts +0 -121
- package/src/app-updates/app-updates-settings.test.tsx +0 -109
- package/src/app-updates/app-updates-settings.tsx +0 -136
- package/src/app-updates/remote-app-update-panel.test.tsx +0 -205
- package/src/app-updates/remote-app-update-panel.tsx +0 -210
- package/src/app-updates/use-app-update-status.ts +0 -16
- package/src/command-palette/command-palette-ui.tsx +0 -564
- package/src/command-palette/command-palette.ts +0 -242
- package/src/components/access-level-field.test.tsx +0 -32
- package/src/components/access-level-field.tsx +0 -68
- package/src/components/checkbox.tsx +0 -25
- package/src/components/group-switcher.tsx +0 -526
- package/src/components/input-date.tsx +0 -29
- package/src/components/input-number.tsx +0 -83
- package/src/components/input.tsx +0 -25
- package/src/components/inverse-lazy-list.tsx +0 -107
- package/src/components/io-schema-values.tsx +0 -103
- package/src/components/io-schema.tsx +0 -259
- package/src/components/lazy-list.tsx +0 -115
- package/src/components/list-screen.tsx +0 -126
- package/src/components/loading-indicator.tsx +0 -7
- package/src/components/markdown-editor/autolink-plugin.tsx +0 -29
- package/src/components/markdown-editor/editor-inline.tsx +0 -9
- package/src/components/markdown-editor/editor.tsx +0 -158
- package/src/components/markdown-editor/markdown-plugin.tsx +0 -202
- package/src/components/markdown-editor/mention-node.ts +0 -204
- package/src/components/markdown-editor/mentions-plugin.tsx +0 -354
- package/src/components/markdown-editor/move-line-plugin.tsx +0 -186
- package/src/components/markdown-editor/select-line-boundary-plugin.tsx +0 -95
- package/src/components/markdown-editor/theme.ts +0 -46
- package/src/components/markdown-editor/toolbar.tsx +0 -269
- package/src/components/markdown-with-mentions.tsx +0 -198
- package/src/components/message-logs/message-logs.tsx +0 -523
- package/src/components/message-logs/tool-access-approval-card.test.tsx +0 -127
- package/src/components/message-logs/tool-access-approval-card.tsx +0 -178
- package/src/components/messages/avatar.tsx +0 -171
- package/src/components/messages/channel-message-list.tsx +0 -189
- package/src/components/messages/channel-view.tsx +0 -92
- package/src/components/messages/message-compose.tsx +0 -192
- package/src/components/messages/message-display.tsx +0 -231
- package/src/components/messages/thread-message-list.tsx +0 -135
- package/src/components/qr-scanner.tsx +0 -180
- package/src/components/responsive-section-nav.test.tsx +0 -88
- package/src/components/responsive-section-nav.tsx +0 -92
- package/src/components/router.tsx +0 -175
- package/src/components/save-button.tsx +0 -134
- package/src/components/sortable-list.tsx +0 -130
- package/src/components/tabs.tsx +0 -76
- package/src/components/tooltip.tsx +0 -43
- package/src/components/trust-level-badge.tsx +0 -44
- package/src/components/trust-level-dropdown.tsx +0 -136
- package/src/components/typeahead.tsx +0 -357
- package/src/globals-hash.test.ts +0 -19
- package/src/globals.tsx +0 -226
- package/src/hooks/index.ts +0 -8
- package/src/hooks/use-host-contract.ts +0 -75
- package/src/hooks/use-observable-state.test.tsx +0 -101
- package/src/hooks/use-observable-state.ts +0 -29
- package/src/hooks/use-observable.test.tsx +0 -258
- package/src/hooks/use-observable.ts +0 -67
- package/src/hooks/use-on-screen.ts +0 -24
- package/src/hooks/use-promise.ts +0 -34
- package/src/hooks/use-rows.test.tsx +0 -196
- package/src/hooks/use-rows.ts +0 -120
- package/src/hooks/use-subscription.ts +0 -24
- package/src/hooks/use-tool.test.tsx +0 -225
- package/src/hooks/use-tool.ts +0 -116
- package/src/host-shell/host-shell-consumer.test.ts +0 -32
- package/src/host-shell/host-shell-consumer.ts +0 -53
- package/src/index.tsx +0 -42
- package/src/mention-configs.ts +0 -185
- package/src/operator-console/operator-console-state.ts +0 -119
- package/src/operator-console/operator-console.tsx +0 -233
- package/src/peers-services-registration.ts +0 -6
- package/src/root-layout/global-overlays.ts +0 -50
- package/src/root-layout/layout-picker.tsx +0 -47
- package/src/root-layout/layouts/full-screen-layout.tsx +0 -144
- package/src/root-layout/layouts/tabs-with-console-layout.tsx +0 -260
- package/src/root-layout/root-layout-host.test.tsx +0 -108
- package/src/root-layout/root-layout-host.tsx +0 -147
- package/src/root-layout/root-layout-registry.ts +0 -51
- package/src/root-layout/root-layout-state.ts +0 -55
- package/src/root-layout/root-layout.ts +0 -32
- package/src/screens/account/account-screen.test.tsx +0 -65
- package/src/screens/account/account-screen.tsx +0 -942
- package/src/screens/assistants/assistant-config.test.tsx +0 -54
- package/src/screens/assistants/assistant-config.tsx +0 -121
- package/src/screens/assistants/assistant-details.tsx +0 -89
- package/src/screens/assistants/assistant-info.tsx +0 -66
- package/src/screens/assistants/assistant-list.tsx +0 -145
- package/src/screens/assistants/assistant-tools.tsx +0 -82
- package/src/screens/console-logs/console-logs-list.tsx +0 -374
- package/src/screens/console-logs/log-display.tsx +0 -137
- package/src/screens/console-logs/log-filters.tsx +0 -64
- package/src/screens/console-logs/mobile-log-card.tsx +0 -161
- package/src/screens/console-logs/resizable-table-header.tsx +0 -110
- package/src/screens/contacts/contact-details.tsx +0 -123
- package/src/screens/contacts/contact-list.test.tsx +0 -59
- package/src/screens/contacts/contact-list.tsx +0 -286
- package/src/screens/contacts/index.ts +0 -2
- package/src/screens/data-explorer/data-explorer.tsx +0 -633
- package/src/screens/data-explorer/index.ts +0 -6
- package/src/screens/data-explorer/query-executor.tsx +0 -520
- package/src/screens/device-pairing/device-pairing.test.tsx +0 -143
- package/src/screens/device-pairing/device-pairing.tsx +0 -461
- package/src/screens/device-pairing/identity-ipc.ts +0 -25
- package/src/screens/device-pairing/index.ts +0 -2
- package/src/screens/device-pairing/use-device-pairing-state.ts +0 -15
- package/src/screens/devices/devices-list.test.tsx +0 -68
- package/src/screens/devices/devices-list.tsx +0 -365
- package/src/screens/devices/index.ts +0 -1
- package/src/screens/groups/group-details.tsx +0 -160
- package/src/screens/groups/group-invite-panel.tsx +0 -311
- package/src/screens/groups/group-list.test.tsx +0 -44
- package/src/screens/groups/group-list.tsx +0 -317
- package/src/screens/groups/group-members.tsx +0 -343
- package/src/screens/groups/index.ts +0 -3
- package/src/screens/identity/identity-routes.test.ts +0 -70
- package/src/screens/identity/identity-routes.ts +0 -301
- package/src/screens/identity/identity-screen.test.tsx +0 -138
- package/src/screens/identity/identity-screen.tsx +0 -282
- package/src/screens/identity/index.ts +0 -2
- package/src/screens/identity/invite-contact-panel.tsx +0 -45
- package/src/screens/identity/profile-invite.tsx +0 -93
- package/src/screens/invites/accept-invite.test.tsx +0 -115
- package/src/screens/invites/accept-invite.tsx +0 -318
- package/src/screens/invites/activity-view.test.tsx +0 -127
- package/src/screens/invites/activity-view.tsx +0 -162
- package/src/screens/invites/index.ts +0 -6
- package/src/screens/invites/invite-capture.ts +0 -104
- package/src/screens/invites/invite-classify.test.ts +0 -129
- package/src/screens/invites/invite-share.tsx +0 -104
- package/src/screens/invites/invites-ipc.ts +0 -25
- package/src/screens/invites/pending-invites-list.tsx +0 -256
- package/src/screens/network-viewer/connection-troubleshooter.tsx +0 -395
- package/src/screens/network-viewer/cpu-usage-graph.tsx +0 -294
- package/src/screens/network-viewer/device-details-modal.tsx +0 -339
- package/src/screens/network-viewer/group-details-modal.tsx +0 -421
- package/src/screens/network-viewer/index.ts +0 -8
- package/src/screens/network-viewer/network-viewer-ipc.test.ts +0 -72
- package/src/screens/network-viewer/network-viewer-ipc.ts +0 -39
- package/src/screens/network-viewer/network-viewer-section.ts +0 -12
- package/src/screens/network-viewer/network-viewer.section.test.tsx +0 -68
- package/src/screens/network-viewer/network-viewer.tsx +0 -708
- package/src/screens/network-viewer/remote-logs-panel.tsx +0 -190
- package/src/screens/network-viewer/sync-recovery.test.tsx +0 -114
- package/src/screens/network-viewer/sync-recovery.tsx +0 -461
- package/src/screens/network-viewer/usage-graph.tsx +0 -455
- package/src/screens/packages/local-folder-grants-panel.tsx +0 -290
- package/src/screens/packages/local-folders-ipc.ts +0 -28
- package/src/screens/packages/package-details.tsx +0 -166
- package/src/screens/packages/package-helpers.test.ts +0 -57
- package/src/screens/packages/package-helpers.ts +0 -137
- package/src/screens/packages/package-info.tsx +0 -354
- package/src/screens/packages/package-list.tsx +0 -519
- package/src/screens/packages/package-network-panel.tsx +0 -82
- package/src/screens/packages/package-new-local.tsx +0 -100
- package/src/screens/packages/package-runtime-status.test.tsx +0 -58
- package/src/screens/packages/package-runtime-status.tsx +0 -68
- package/src/screens/packages/package-versions.tsx +0 -298
- package/src/screens/packages/packages-ipc.test.ts +0 -47
- package/src/screens/packages/packages-ipc.ts +0 -125
- package/src/screens/peer-types/peer-type-details.tsx +0 -172
- package/src/screens/peer-types/peer-type-list.tsx +0 -64
- package/src/screens/search/global-search.tsx +0 -406
- package/src/screens/settings/color-mode-dropdown.tsx +0 -82
- package/src/screens/settings/settings-page.test.tsx +0 -24
- package/src/screens/settings/settings-page.tsx +0 -426
- package/src/screens/setup-user.tsx +0 -355
- package/src/screens/tools/tool-access-ipc.test.ts +0 -55
- package/src/screens/tools/tool-access-ipc.ts +0 -27
- package/src/screens/tools/tool-catalog-ipc.test.ts +0 -52
- package/src/screens/tools/tool-catalog-ipc.ts +0 -51
- package/src/screens/tools/tool-details.tsx +0 -52
- package/src/screens/tools/tool-info.tsx +0 -45
- package/src/screens/tools/tool-list.tsx +0 -106
- package/src/screens/tools/tool-schema.tsx +0 -44
- package/src/screens/tools/tool-test-details.tsx +0 -89
- package/src/screens/tools/tool-test-list.tsx +0 -73
- package/src/screens/variables/variable-details.tsx +0 -289
- package/src/screens/variables/variable-list.tsx +0 -110
- package/src/screens/welcome-modal.tsx +0 -294
- package/src/screens/workflows/workflow-details.tsx +0 -115
- package/src/screens/workflows/workflow-info.tsx +0 -22
- package/src/screens/workflows/workflow-instructions.tsx +0 -134
- package/src/screens/workflows/workflow-list.tsx +0 -117
- package/src/setupTests.ts +0 -38
- package/src/system-apps/assistants.app.ts +0 -7
- package/src/system-apps/console-logs.app.ts +0 -7
- package/src/system-apps/data-explorer.app.ts +0 -8
- package/src/system-apps/identity.app.ts +0 -9
- package/src/system-apps/index.ts +0 -77
- package/src/system-apps/mobile-settings.app.ts +0 -7
- package/src/system-apps/network-viewer.app.ts +0 -8
- package/src/system-apps/packages.app.ts +0 -7
- package/src/system-apps/search.app.ts +0 -8
- package/src/system-apps/settings.app.ts +0 -7
- package/src/system-apps/threads.app.ts +0 -7
- package/src/system-apps/tools.app.ts +0 -7
- package/src/system-apps/types.app.ts +0 -7
- package/src/system-apps/variables.app.ts +0 -7
- package/src/system-apps/workflows.app.ts +0 -7
- package/src/tabs-layout/network-status-indicator.test.tsx +0 -799
- package/src/tabs-layout/network-status-indicator.tsx +0 -756
- package/src/tabs-layout/tabs-layout.tsx +0 -857
- package/src/tabs-layout/tabs-state.test.ts +0 -152
- package/src/tabs-layout/tabs-state.ts +0 -587
- package/src/tabs-layout/use-network-status.test.tsx +0 -58
- package/src/tabs-layout/use-network-status.ts +0 -68
- package/src/ui-defaults/index.ts +0 -2
- package/src/ui-defaults/list-screen.tsx +0 -94
- package/src/ui-defaults/markdown-field.tsx +0 -87
- package/src/ui-router/routes-loader.ts +0 -193
- package/src/ui-router/ui-loader.test.tsx +0 -108
- package/src/ui-router/ui-loader.tsx +0 -606
- package/src/utils.ts +0 -95
- package/tsconfig.json +0 -18
|
@@ -1,633 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from "react";
|
|
2
|
-
import { LoadingIndicator } from "../../components/loading-indicator";
|
|
3
|
-
import { isDesktop } from "../../globals";
|
|
4
|
-
import { registerInternalPeersUI } from "../../ui-router/ui-loader";
|
|
5
|
-
|
|
6
|
-
interface ITableInfo {
|
|
7
|
-
tableName: string;
|
|
8
|
-
tableId?: string;
|
|
9
|
-
isRegistered: boolean;
|
|
10
|
-
sql?: string;
|
|
11
|
-
type?: string;
|
|
12
|
-
rowCount?: number;
|
|
13
|
-
bytes?: number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface IDeletedTableInfo {
|
|
17
|
-
tableName: string;
|
|
18
|
-
tableId: string;
|
|
19
|
-
deletedAt: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type DataExplorerElectronApi = {
|
|
23
|
-
getCurrentContext: () => Promise<{ contextName: string }>;
|
|
24
|
-
getAllTables: () => Promise<ITableInfo[]>;
|
|
25
|
-
compactDatabase: (beforeTimestamp?: number) => Promise<void>;
|
|
26
|
-
resetChangeTracking: () => Promise<void>;
|
|
27
|
-
deleteTable: (tableName: string) => Promise<void>;
|
|
28
|
-
getDeletedTables: () => Promise<IDeletedTableInfo[]>;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
type WindowWithDataExplorer = Window & {
|
|
32
|
-
electronAPI?: { dataExplorer?: DataExplorerElectronApi };
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
function getDataExplorerApi(): DataExplorerElectronApi | undefined {
|
|
36
|
-
return (window as WindowWithDataExplorer).electronAPI?.dataExplorer;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function formatRelativeTime(isoString: string): string {
|
|
40
|
-
const date = new Date(isoString);
|
|
41
|
-
const now = Date.now();
|
|
42
|
-
const diffMs = now - date.getTime();
|
|
43
|
-
const diffMin = Math.floor(diffMs / 60_000);
|
|
44
|
-
if (diffMin < 1) return "just now";
|
|
45
|
-
if (diffMin < 60) return `${diffMin}m ago`;
|
|
46
|
-
const diffHrs = Math.floor(diffMin / 60);
|
|
47
|
-
if (diffHrs < 24) return `${diffHrs}h ago`;
|
|
48
|
-
const diffDays = Math.floor(diffHrs / 24);
|
|
49
|
-
if (diffDays < 30) return `${diffDays}d ago`;
|
|
50
|
-
return date.toLocaleDateString();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function DeleteConfirmModal({
|
|
54
|
-
tableName,
|
|
55
|
-
onConfirm,
|
|
56
|
-
onCancel,
|
|
57
|
-
}: {
|
|
58
|
-
tableName: string;
|
|
59
|
-
onConfirm: () => void;
|
|
60
|
-
onCancel: () => void;
|
|
61
|
-
}) {
|
|
62
|
-
const [confirmText, setConfirmText] = useState("");
|
|
63
|
-
const [deleting, setDeleting] = useState(false);
|
|
64
|
-
|
|
65
|
-
const handleConfirm = async () => {
|
|
66
|
-
setDeleting(true);
|
|
67
|
-
try {
|
|
68
|
-
await onConfirm();
|
|
69
|
-
} finally {
|
|
70
|
-
setDeleting(false);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<div
|
|
76
|
-
className="position-fixed top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center"
|
|
77
|
-
style={{ zIndex: 1050, backgroundColor: "rgba(0,0,0,0.5)" }}
|
|
78
|
-
onClick={onCancel}
|
|
79
|
-
>
|
|
80
|
-
<div
|
|
81
|
-
className="card shadow-lg"
|
|
82
|
-
style={{ maxWidth: 480, width: "100%" }}
|
|
83
|
-
onClick={(e) => e.stopPropagation()}
|
|
84
|
-
>
|
|
85
|
-
<div className="card-header bg-danger text-white d-flex justify-content-between align-items-center">
|
|
86
|
-
<strong>Delete Table</strong>
|
|
87
|
-
<button type="button" className="btn-close btn-close-white" onClick={onCancel} />
|
|
88
|
-
</div>
|
|
89
|
-
<div className="card-body">
|
|
90
|
-
<div className="alert alert-danger mb-3">
|
|
91
|
-
<i className="bi bi-exclamation-triangle-fill me-2" />
|
|
92
|
-
This will permanently delete all data for <strong>{tableName}</strong> on this device
|
|
93
|
-
and all synced devices once synced.
|
|
94
|
-
</div>
|
|
95
|
-
<label className="form-label">
|
|
96
|
-
Type <strong>{tableName}</strong> to confirm:
|
|
97
|
-
</label>
|
|
98
|
-
<input
|
|
99
|
-
type="text"
|
|
100
|
-
className="form-control"
|
|
101
|
-
value={confirmText}
|
|
102
|
-
onChange={(e) => setConfirmText(e.target.value)}
|
|
103
|
-
placeholder={tableName}
|
|
104
|
-
// biome-ignore lint/a11y/noAutofocus: confirmation input needs immediate focus
|
|
105
|
-
autoFocus
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
108
|
-
<div className="card-footer d-flex justify-content-end gap-2">
|
|
109
|
-
<button
|
|
110
|
-
type="button"
|
|
111
|
-
className="btn btn-secondary"
|
|
112
|
-
onClick={onCancel}
|
|
113
|
-
disabled={deleting}
|
|
114
|
-
>
|
|
115
|
-
Cancel
|
|
116
|
-
</button>
|
|
117
|
-
<button
|
|
118
|
-
type="button"
|
|
119
|
-
className="btn btn-danger"
|
|
120
|
-
disabled={confirmText !== tableName || deleting}
|
|
121
|
-
onClick={handleConfirm}
|
|
122
|
-
>
|
|
123
|
-
{deleting ? (
|
|
124
|
-
<>
|
|
125
|
-
<span className="spinner-border spinner-border-sm me-1" />
|
|
126
|
-
Deleting...
|
|
127
|
-
</>
|
|
128
|
-
) : (
|
|
129
|
-
"Delete Table"
|
|
130
|
-
)}
|
|
131
|
-
</button>
|
|
132
|
-
</div>
|
|
133
|
-
</div>
|
|
134
|
-
</div>
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function DataExplorerList() {
|
|
139
|
-
const [tables, setTables] = useState<ITableInfo[]>([]);
|
|
140
|
-
const [deletedTables, setDeletedTables] = useState<IDeletedTableInfo[]>([]);
|
|
141
|
-
const [loading, setLoading] = useState(true);
|
|
142
|
-
const [currentContext, setCurrentContext] = useState<string>("");
|
|
143
|
-
const [compacting, setCompacting] = useState(false);
|
|
144
|
-
const [deleteTarget, setDeleteTarget] = useState<string | null>(null);
|
|
145
|
-
|
|
146
|
-
const formatBytes = (bytes: number | undefined) => {
|
|
147
|
-
if (bytes === undefined) return "-";
|
|
148
|
-
if (bytes === 0) return "0 B";
|
|
149
|
-
const k = 1024;
|
|
150
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
151
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
152
|
-
return `${Math.round(bytes / k ** i)} ${sizes[i]}`;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const getBytesColorClass = (bytes: number | undefined): string => {
|
|
156
|
-
if (bytes === undefined) return "text-secondary";
|
|
157
|
-
const kb = 1024;
|
|
158
|
-
const mb = kb * 1024;
|
|
159
|
-
|
|
160
|
-
if (bytes < 10 * kb) return "text-secondary";
|
|
161
|
-
if (bytes < 10 * mb) return "text-primary";
|
|
162
|
-
if (bytes < 100 * mb) return "text-warning";
|
|
163
|
-
return "text-danger";
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const loadTables = useCallback(async () => {
|
|
167
|
-
try {
|
|
168
|
-
if (!isDesktop()) return;
|
|
169
|
-
|
|
170
|
-
const api = getDataExplorerApi();
|
|
171
|
-
if (!api) {
|
|
172
|
-
console.warn("Data Explorer API not available");
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const contextInfo = await api.getCurrentContext();
|
|
177
|
-
setCurrentContext(contextInfo.contextName);
|
|
178
|
-
|
|
179
|
-
const allTablesInfo = await api.getAllTables();
|
|
180
|
-
allTablesInfo.sort((a: ITableInfo, b: ITableInfo) => {
|
|
181
|
-
if (a.isRegistered !== b.isRegistered) {
|
|
182
|
-
return a.isRegistered ? -1 : 1;
|
|
183
|
-
}
|
|
184
|
-
return a.tableName.localeCompare(b.tableName);
|
|
185
|
-
});
|
|
186
|
-
setTables(allTablesInfo);
|
|
187
|
-
|
|
188
|
-
const deleted = await api.getDeletedTables();
|
|
189
|
-
deleted.sort((a, b) => a.tableName.localeCompare(b.tableName));
|
|
190
|
-
setDeletedTables(deleted);
|
|
191
|
-
} catch (error) {
|
|
192
|
-
console.error("Error loading tables:", error);
|
|
193
|
-
} finally {
|
|
194
|
-
setLoading(false);
|
|
195
|
-
}
|
|
196
|
-
}, []);
|
|
197
|
-
|
|
198
|
-
const handleDeleteTable = async () => {
|
|
199
|
-
if (!deleteTarget) return;
|
|
200
|
-
const api = getDataExplorerApi();
|
|
201
|
-
if (!api) return;
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
await api.deleteTable(deleteTarget);
|
|
205
|
-
setDeleteTarget(null);
|
|
206
|
-
setLoading(true);
|
|
207
|
-
await loadTables();
|
|
208
|
-
} catch (error: unknown) {
|
|
209
|
-
console.error("Error deleting table:", error);
|
|
210
|
-
alert(`Error deleting table: ${error instanceof Error ? error.message : String(error)}`);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
const compactDatabase = async (beforeTimestamp?: number) => {
|
|
215
|
-
try {
|
|
216
|
-
setCompacting(true);
|
|
217
|
-
const api = getDataExplorerApi();
|
|
218
|
-
if (!api) {
|
|
219
|
-
alert("Data Explorer API not available");
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const isExtreme = beforeTimestamp !== undefined;
|
|
224
|
-
if (isExtreme) {
|
|
225
|
-
const confirmed = window.confirm(
|
|
226
|
-
"Extreme Compaction will remove ALL change history. This cannot be undone. Continue?",
|
|
227
|
-
);
|
|
228
|
-
if (!confirmed) {
|
|
229
|
-
setCompacting(false);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
await api.compactDatabase(beforeTimestamp);
|
|
235
|
-
alert(`Database compacted successfully!${isExtreme ? " (Extreme mode)" : ""}`);
|
|
236
|
-
|
|
237
|
-
setLoading(true);
|
|
238
|
-
await loadTables();
|
|
239
|
-
} catch (error: unknown) {
|
|
240
|
-
console.error("Error compacting database:", error);
|
|
241
|
-
alert(`Error compacting database: ${error instanceof Error ? error.message : String(error)}`);
|
|
242
|
-
} finally {
|
|
243
|
-
setCompacting(false);
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
const resetChangeTracking = async () => {
|
|
248
|
-
try {
|
|
249
|
-
setCompacting(true);
|
|
250
|
-
const api = getDataExplorerApi();
|
|
251
|
-
if (!api) {
|
|
252
|
-
alert("Data Explorer API not available");
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const confirmed = window.confirm(
|
|
257
|
-
"Reset Change Tracking will clear all change history and rebuild it from scratch. This may take a while. Continue?",
|
|
258
|
-
);
|
|
259
|
-
if (!confirmed) {
|
|
260
|
-
setCompacting(false);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
await api.resetChangeTracking();
|
|
265
|
-
alert("Change tracking reset successfully!");
|
|
266
|
-
|
|
267
|
-
setLoading(true);
|
|
268
|
-
await loadTables();
|
|
269
|
-
} catch (error: unknown) {
|
|
270
|
-
console.error("Error resetting change tracking:", error);
|
|
271
|
-
alert(
|
|
272
|
-
`Error resetting change tracking: ${error instanceof Error ? error.message : String(error)}`,
|
|
273
|
-
);
|
|
274
|
-
} finally {
|
|
275
|
-
setCompacting(false);
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
useEffect(() => {
|
|
280
|
-
loadTables();
|
|
281
|
-
}, [loadTables]);
|
|
282
|
-
|
|
283
|
-
if (loading) {
|
|
284
|
-
return <LoadingIndicator />;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (!isDesktop()) {
|
|
288
|
-
return (
|
|
289
|
-
<div className="container-fluid p-4">
|
|
290
|
-
<div className="alert alert-info">
|
|
291
|
-
Data Explorer is only available in the desktop application.
|
|
292
|
-
</div>
|
|
293
|
-
</div>
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (!currentContext && tables.length === 0) {
|
|
298
|
-
return (
|
|
299
|
-
<div className="container-fluid p-4">
|
|
300
|
-
<div className="alert alert-warning">Unable to load database information.</div>
|
|
301
|
-
</div>
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const registeredTables = tables.filter((t) => t.isRegistered);
|
|
306
|
-
const unregisteredTables = tables.filter((t) => !t.isRegistered);
|
|
307
|
-
|
|
308
|
-
return (
|
|
309
|
-
<div className="container-fluid p-4">
|
|
310
|
-
{deleteTarget && (
|
|
311
|
-
<DeleteConfirmModal
|
|
312
|
-
tableName={deleteTarget}
|
|
313
|
-
onConfirm={handleDeleteTable}
|
|
314
|
-
onCancel={() => setDeleteTarget(null)}
|
|
315
|
-
/>
|
|
316
|
-
)}
|
|
317
|
-
|
|
318
|
-
{/* Navigation Tabs */}
|
|
319
|
-
<ul className="nav nav-tabs mb-4">
|
|
320
|
-
<li className="nav-item">
|
|
321
|
-
<a className="nav-link active" href="#/data-explorer">
|
|
322
|
-
<i className="bi bi-table"></i> Tables
|
|
323
|
-
</a>
|
|
324
|
-
</li>
|
|
325
|
-
<li className="nav-item">
|
|
326
|
-
<a className="nav-link" href="#/data-explorer/query">
|
|
327
|
-
<i className="bi bi-terminal"></i> Query
|
|
328
|
-
</a>
|
|
329
|
-
</li>
|
|
330
|
-
</ul>
|
|
331
|
-
|
|
332
|
-
<div className="d-flex justify-content-between align-items-center mb-4">
|
|
333
|
-
<h2>Data Explorer</h2>
|
|
334
|
-
<div className="d-flex gap-2">
|
|
335
|
-
{/* Split button for Compact Database */}
|
|
336
|
-
<div className="btn-group" role="group">
|
|
337
|
-
<button
|
|
338
|
-
type="button"
|
|
339
|
-
className="btn btn-sm btn-warning"
|
|
340
|
-
onClick={() => compactDatabase()}
|
|
341
|
-
disabled={compacting || loading}
|
|
342
|
-
title="Compact database (cleanup changes older than 2 weeks)"
|
|
343
|
-
>
|
|
344
|
-
{compacting ? (
|
|
345
|
-
<>
|
|
346
|
-
<span
|
|
347
|
-
className="spinner-border spinner-border-sm me-1"
|
|
348
|
-
role="status"
|
|
349
|
-
aria-hidden="true"
|
|
350
|
-
></span>
|
|
351
|
-
Compacting...
|
|
352
|
-
</>
|
|
353
|
-
) : (
|
|
354
|
-
<>
|
|
355
|
-
<i className="bi bi-disc"></i> Compact Database
|
|
356
|
-
</>
|
|
357
|
-
)}
|
|
358
|
-
</button>
|
|
359
|
-
<button
|
|
360
|
-
type="button"
|
|
361
|
-
className="btn btn-sm btn-warning dropdown-toggle dropdown-toggle-split"
|
|
362
|
-
data-bs-toggle="dropdown"
|
|
363
|
-
aria-expanded="false"
|
|
364
|
-
disabled={compacting || loading}
|
|
365
|
-
title="More compaction options"
|
|
366
|
-
>
|
|
367
|
-
<span className="visually-hidden">Toggle Dropdown</span>
|
|
368
|
-
</button>
|
|
369
|
-
<ul className="dropdown-menu">
|
|
370
|
-
<li>
|
|
371
|
-
<a
|
|
372
|
-
className="dropdown-item"
|
|
373
|
-
href="#"
|
|
374
|
-
onClick={(e) => {
|
|
375
|
-
e.preventDefault();
|
|
376
|
-
compactDatabase(Date.now());
|
|
377
|
-
}}
|
|
378
|
-
>
|
|
379
|
-
<i className="bi bi-exclamation-triangle text-danger me-2"></i>
|
|
380
|
-
Extreme Compaction
|
|
381
|
-
<div className="small text-muted">Remove ALL change history</div>
|
|
382
|
-
</a>
|
|
383
|
-
</li>
|
|
384
|
-
<li>
|
|
385
|
-
<hr className="dropdown-divider" />
|
|
386
|
-
</li>
|
|
387
|
-
<li>
|
|
388
|
-
<a
|
|
389
|
-
className="dropdown-item"
|
|
390
|
-
href="#"
|
|
391
|
-
onClick={(e) => {
|
|
392
|
-
e.preventDefault();
|
|
393
|
-
resetChangeTracking();
|
|
394
|
-
}}
|
|
395
|
-
>
|
|
396
|
-
<i className="bi bi-arrow-clockwise text-warning me-2"></i>
|
|
397
|
-
Reset Change Tracking
|
|
398
|
-
<div className="small text-muted">Clear and rebuild all change history</div>
|
|
399
|
-
</a>
|
|
400
|
-
</li>
|
|
401
|
-
</ul>
|
|
402
|
-
</div>
|
|
403
|
-
|
|
404
|
-
<button
|
|
405
|
-
className="btn btn-sm btn-primary"
|
|
406
|
-
onClick={() => {
|
|
407
|
-
setLoading(true);
|
|
408
|
-
loadTables();
|
|
409
|
-
}}
|
|
410
|
-
disabled={compacting}
|
|
411
|
-
>
|
|
412
|
-
<i className="bi bi-arrow-clockwise"></i> Refresh
|
|
413
|
-
</button>
|
|
414
|
-
</div>
|
|
415
|
-
</div>
|
|
416
|
-
|
|
417
|
-
{/* Current Context Info */}
|
|
418
|
-
<div className="card mb-4">
|
|
419
|
-
<div className="card-body">
|
|
420
|
-
<div className="d-flex justify-content-between align-items-center">
|
|
421
|
-
<div>
|
|
422
|
-
<h5 className="card-title mb-2">Current Data Context</h5>
|
|
423
|
-
<p className="mb-0">{currentContext}</p>
|
|
424
|
-
</div>
|
|
425
|
-
<div className="text-end">
|
|
426
|
-
<div className="text-muted small">Total DB Size</div>
|
|
427
|
-
<div className="fs-4 fw-bold">
|
|
428
|
-
{formatBytes(tables.reduce((sum, t) => sum + (t.bytes || 0), 0))}
|
|
429
|
-
</div>
|
|
430
|
-
</div>
|
|
431
|
-
</div>
|
|
432
|
-
</div>
|
|
433
|
-
</div>
|
|
434
|
-
|
|
435
|
-
{/* Registered Tables */}
|
|
436
|
-
<div className="card mb-4">
|
|
437
|
-
<div className="card-body">
|
|
438
|
-
<h5 className="card-title">
|
|
439
|
-
Registered Tables ({registeredTables.length})
|
|
440
|
-
<span className="badge bg-success ms-2">Active</span>
|
|
441
|
-
</h5>
|
|
442
|
-
<p className="text-muted small">
|
|
443
|
-
These tables are registered with the TableContainer and actively used by the
|
|
444
|
-
application.
|
|
445
|
-
</p>
|
|
446
|
-
{registeredTables.length === 0 ? (
|
|
447
|
-
<p className="text-muted">No registered tables found</p>
|
|
448
|
-
) : (
|
|
449
|
-
<div className="table-responsive">
|
|
450
|
-
<table className="table table-hover table-sm">
|
|
451
|
-
<thead>
|
|
452
|
-
<tr>
|
|
453
|
-
<th>Table Name</th>
|
|
454
|
-
<th>Table ID</th>
|
|
455
|
-
<th className="text-end">Row Count</th>
|
|
456
|
-
<th className="text-end">Bytes</th>
|
|
457
|
-
<th style={{ width: "1%" }}></th>
|
|
458
|
-
</tr>
|
|
459
|
-
</thead>
|
|
460
|
-
<tbody>
|
|
461
|
-
{registeredTables.map((table) => (
|
|
462
|
-
<tr key={table.tableName}>
|
|
463
|
-
<td>
|
|
464
|
-
<strong>{table.tableName}</strong>
|
|
465
|
-
</td>
|
|
466
|
-
<td>
|
|
467
|
-
<code className="text-muted small">{table.tableId || "system"}</code>
|
|
468
|
-
</td>
|
|
469
|
-
<td className="text-end">
|
|
470
|
-
{table.rowCount !== undefined ? table.rowCount.toLocaleString() : "-"}
|
|
471
|
-
</td>
|
|
472
|
-
<td className={`text-end fw-bold ${getBytesColorClass(table.bytes)}`}>
|
|
473
|
-
{formatBytes(table.bytes)}
|
|
474
|
-
</td>
|
|
475
|
-
<td>
|
|
476
|
-
<button
|
|
477
|
-
type="button"
|
|
478
|
-
className="btn btn-sm btn-outline-danger border-0"
|
|
479
|
-
title={`Delete ${table.tableName}`}
|
|
480
|
-
onClick={() => setDeleteTarget(table.tableName)}
|
|
481
|
-
>
|
|
482
|
-
<i className="bi bi-trash" />
|
|
483
|
-
</button>
|
|
484
|
-
</td>
|
|
485
|
-
</tr>
|
|
486
|
-
))}
|
|
487
|
-
</tbody>
|
|
488
|
-
</table>
|
|
489
|
-
</div>
|
|
490
|
-
)}
|
|
491
|
-
</div>
|
|
492
|
-
</div>
|
|
493
|
-
|
|
494
|
-
{/* Unregistered Tables (Raw SQLite) */}
|
|
495
|
-
{unregisteredTables.length > 0 && (
|
|
496
|
-
<div className="card mb-4">
|
|
497
|
-
<div className="card-body">
|
|
498
|
-
<h5 className="card-title">
|
|
499
|
-
Unregistered Tables ({unregisteredTables.length})
|
|
500
|
-
<span className="badge bg-warning text-dark ms-2">Raw SQLite</span>
|
|
501
|
-
</h5>
|
|
502
|
-
<p className="text-muted small">
|
|
503
|
-
These tables exist in the SQLite database but are not registered with the
|
|
504
|
-
TableContainer. They may be system tables, change tracking tables, or legacy tables.
|
|
505
|
-
</p>
|
|
506
|
-
<div className="table-responsive">
|
|
507
|
-
<table className="table table-hover table-sm">
|
|
508
|
-
<thead>
|
|
509
|
-
<tr>
|
|
510
|
-
<th>Table Name</th>
|
|
511
|
-
<th>Type</th>
|
|
512
|
-
<th className="text-end">Row Count</th>
|
|
513
|
-
<th className="text-end">Bytes</th>
|
|
514
|
-
<th>SQL Definition</th>
|
|
515
|
-
<th style={{ width: "1%" }}></th>
|
|
516
|
-
</tr>
|
|
517
|
-
</thead>
|
|
518
|
-
<tbody>
|
|
519
|
-
{unregisteredTables.map((table) => (
|
|
520
|
-
<tr key={table.tableName}>
|
|
521
|
-
<td>
|
|
522
|
-
<strong>{table.tableName}</strong>
|
|
523
|
-
</td>
|
|
524
|
-
<td>
|
|
525
|
-
<span className="badge bg-secondary">{table.type || "table"}</span>
|
|
526
|
-
</td>
|
|
527
|
-
<td className="text-end">
|
|
528
|
-
{table.rowCount !== undefined ? table.rowCount.toLocaleString() : "-"}
|
|
529
|
-
</td>
|
|
530
|
-
<td className={`text-end fw-bold ${getBytesColorClass(table.bytes)}`}>
|
|
531
|
-
{formatBytes(table.bytes)}
|
|
532
|
-
</td>
|
|
533
|
-
<td>
|
|
534
|
-
{table.sql ? (
|
|
535
|
-
<details>
|
|
536
|
-
<summary
|
|
537
|
-
className="cursor-pointer text-primary"
|
|
538
|
-
style={{ cursor: "pointer" }}
|
|
539
|
-
>
|
|
540
|
-
<small>View SQL</small>
|
|
541
|
-
</summary>
|
|
542
|
-
<pre
|
|
543
|
-
className="mt-2 p-2 bg-body-secondary border rounded"
|
|
544
|
-
style={{
|
|
545
|
-
fontSize: "0.75rem",
|
|
546
|
-
maxHeight: "300px",
|
|
547
|
-
overflow: "auto",
|
|
548
|
-
}}
|
|
549
|
-
>
|
|
550
|
-
<code className="text-body">{table.sql}</code>
|
|
551
|
-
</pre>
|
|
552
|
-
</details>
|
|
553
|
-
) : (
|
|
554
|
-
<span className="text-muted small">-</span>
|
|
555
|
-
)}
|
|
556
|
-
</td>
|
|
557
|
-
<td>
|
|
558
|
-
<button
|
|
559
|
-
type="button"
|
|
560
|
-
className="btn btn-sm btn-outline-danger border-0"
|
|
561
|
-
title={`Delete ${table.tableName}`}
|
|
562
|
-
onClick={() => setDeleteTarget(table.tableName)}
|
|
563
|
-
>
|
|
564
|
-
<i className="bi bi-trash" />
|
|
565
|
-
</button>
|
|
566
|
-
</td>
|
|
567
|
-
</tr>
|
|
568
|
-
))}
|
|
569
|
-
</tbody>
|
|
570
|
-
</table>
|
|
571
|
-
</div>
|
|
572
|
-
</div>
|
|
573
|
-
</div>
|
|
574
|
-
)}
|
|
575
|
-
|
|
576
|
-
{/* Deleted Tables */}
|
|
577
|
-
{deletedTables.length > 0 && (
|
|
578
|
-
<div className="card mb-4">
|
|
579
|
-
<div className="card-body">
|
|
580
|
-
<h5 className="card-title">
|
|
581
|
-
Deleted Tables ({deletedTables.length})
|
|
582
|
-
<span className="badge bg-danger ms-2">Deleted</span>
|
|
583
|
-
</h5>
|
|
584
|
-
<p className="text-muted small">
|
|
585
|
-
These tables have been deleted. Their definitions are retained so other devices know
|
|
586
|
-
to stop syncing data for them.
|
|
587
|
-
</p>
|
|
588
|
-
<div className="table-responsive">
|
|
589
|
-
<table className="table table-hover table-sm">
|
|
590
|
-
<thead>
|
|
591
|
-
<tr>
|
|
592
|
-
<th>Table Name</th>
|
|
593
|
-
<th>Table ID</th>
|
|
594
|
-
<th>Deleted At</th>
|
|
595
|
-
</tr>
|
|
596
|
-
</thead>
|
|
597
|
-
<tbody>
|
|
598
|
-
{deletedTables.map((table) => (
|
|
599
|
-
<tr key={table.tableId}>
|
|
600
|
-
<td>
|
|
601
|
-
<strong className="text-muted">{table.tableName}</strong>
|
|
602
|
-
</td>
|
|
603
|
-
<td>
|
|
604
|
-
<code className="text-muted small">{table.tableId}</code>
|
|
605
|
-
</td>
|
|
606
|
-
<td>
|
|
607
|
-
<span title={new Date(table.deletedAt).toLocaleString()}>
|
|
608
|
-
{formatRelativeTime(table.deletedAt)}
|
|
609
|
-
</span>
|
|
610
|
-
</td>
|
|
611
|
-
</tr>
|
|
612
|
-
))}
|
|
613
|
-
</tbody>
|
|
614
|
-
</table>
|
|
615
|
-
</div>
|
|
616
|
-
</div>
|
|
617
|
-
</div>
|
|
618
|
-
)}
|
|
619
|
-
</div>
|
|
620
|
-
);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
registerInternalPeersUI({
|
|
624
|
-
peersUIId: "data-explorer-list-ui",
|
|
625
|
-
component: DataExplorerList,
|
|
626
|
-
routes: [
|
|
627
|
-
{
|
|
628
|
-
isMatch: (_props, context) => context.path === "data-explorer",
|
|
629
|
-
uiCategory: "screen",
|
|
630
|
-
priority: 2,
|
|
631
|
-
},
|
|
632
|
-
],
|
|
633
|
-
});
|