@nexus-ai-fs/tui 0.9.18
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/README.md +30 -0
- package/package.json +48 -0
- package/src/app.tsx +349 -0
- package/src/index.tsx +137 -0
- package/src/opentui-env.d.ts +61 -0
- package/src/panels/access/access-panel.tsx +597 -0
- package/src/panels/access/alert-list.tsx +77 -0
- package/src/panels/access/constraint-creator.tsx +128 -0
- package/src/panels/access/constraint-list.tsx +72 -0
- package/src/panels/access/credential-list.tsx +68 -0
- package/src/panels/access/delegation-chain-view.tsx +110 -0
- package/src/panels/access/delegation-completer.tsx +120 -0
- package/src/panels/access/delegation-creator.tsx +237 -0
- package/src/panels/access/delegation-list.tsx +74 -0
- package/src/panels/access/fraud-score-view.tsx +94 -0
- package/src/panels/access/manifest-creator.tsx +167 -0
- package/src/panels/access/manifest-list.tsx +105 -0
- package/src/panels/access/namespace-config-view.tsx +525 -0
- package/src/panels/access/permission-checker.tsx +231 -0
- package/src/panels/agents/agent-status-view.tsx +196 -0
- package/src/panels/agents/agents-panel.tsx +493 -0
- package/src/panels/agents/delegation-list.tsx +154 -0
- package/src/panels/agents/inbox-view.tsx +96 -0
- package/src/panels/agents/trajectories-tab.tsx +40 -0
- package/src/panels/api-console/api-console-panel.tsx +189 -0
- package/src/panels/api-console/codegen-viewer.tsx +36 -0
- package/src/panels/api-console/codegen.ts +112 -0
- package/src/panels/api-console/endpoint-list.tsx +57 -0
- package/src/panels/api-console/request-builder.tsx +69 -0
- package/src/panels/api-console/response-viewer.tsx +54 -0
- package/src/panels/connectors/available-tab.tsx +357 -0
- package/src/panels/connectors/connector-row.tsx +121 -0
- package/src/panels/connectors/connectors-panel.tsx +88 -0
- package/src/panels/connectors/error-parser.ts +116 -0
- package/src/panels/connectors/mounted-tab.tsx +179 -0
- package/src/panels/connectors/skills-tab.tsx +235 -0
- package/src/panels/connectors/template-generator.ts +211 -0
- package/src/panels/connectors/write-tab.tsx +514 -0
- package/src/panels/events/audit-tab.tsx +69 -0
- package/src/panels/events/audit-trail.tsx +75 -0
- package/src/panels/events/connector-detail.tsx +49 -0
- package/src/panels/events/connector-list.tsx +73 -0
- package/src/panels/events/connectors-tab.tsx +92 -0
- package/src/panels/events/event-replay.tsx +80 -0
- package/src/panels/events/events-panel.tsx +414 -0
- package/src/panels/events/events-tab.tsx +212 -0
- package/src/panels/events/lock-list.tsx +54 -0
- package/src/panels/events/locks-tab.tsx +103 -0
- package/src/panels/events/mcl-replay.tsx +77 -0
- package/src/panels/events/mcl-tab.tsx +83 -0
- package/src/panels/events/operations-tab-wrapper.tsx +62 -0
- package/src/panels/events/operations-tab.tsx +41 -0
- package/src/panels/events/replay-tab.tsx +76 -0
- package/src/panels/events/secrets-audit.tsx +64 -0
- package/src/panels/events/secrets-tab.tsx +75 -0
- package/src/panels/events/subscription-list.tsx +54 -0
- package/src/panels/events/subscriptions-tab.tsx +82 -0
- package/src/panels/files/file-aspects.tsx +93 -0
- package/src/panels/files/file-editor.tsx +160 -0
- package/src/panels/files/file-explorer-keybindings.ts +468 -0
- package/src/panels/files/file-explorer-panel.tsx +545 -0
- package/src/panels/files/file-lineage.tsx +163 -0
- package/src/panels/files/file-list-item.tsx +28 -0
- package/src/panels/files/file-metadata.tsx +62 -0
- package/src/panels/files/file-preview.tsx +108 -0
- package/src/panels/files/file-schema.tsx +89 -0
- package/src/panels/files/file-tree-node.tsx +44 -0
- package/src/panels/files/file-tree.tsx +169 -0
- package/src/panels/files/share-links-tab.tsx +33 -0
- package/src/panels/files/uploads-tab.tsx +45 -0
- package/src/panels/payments/approval-list.tsx +83 -0
- package/src/panels/payments/balance-card.tsx +43 -0
- package/src/panels/payments/budget-card.tsx +70 -0
- package/src/panels/payments/payments-panel.tsx +451 -0
- package/src/panels/payments/policy-list.tsx +64 -0
- package/src/panels/payments/reservation-list.tsx +78 -0
- package/src/panels/payments/transaction-list.tsx +103 -0
- package/src/panels/payments/transfer-form.tsx +109 -0
- package/src/panels/search/column-search.tsx +79 -0
- package/src/panels/search/knowledge-view.tsx +100 -0
- package/src/panels/search/memory-list.tsx +197 -0
- package/src/panels/search/playbook-list.tsx +77 -0
- package/src/panels/search/rlm-answer-view.tsx +105 -0
- package/src/panels/search/search-panel.tsx +405 -0
- package/src/panels/search/search-results.tsx +116 -0
- package/src/panels/stack/stack-panel.tsx +474 -0
- package/src/panels/versions/conflicts-tab.tsx +59 -0
- package/src/panels/versions/entry-detail.tsx +89 -0
- package/src/panels/versions/transaction-actions.tsx +34 -0
- package/src/panels/versions/transaction-list.tsx +90 -0
- package/src/panels/versions/versions-panel.tsx +276 -0
- package/src/panels/workflows/execution-list.tsx +102 -0
- package/src/panels/workflows/scheduler-view.tsx +135 -0
- package/src/panels/workflows/workflow-list.tsx +88 -0
- package/src/panels/workflows/workflows-panel.tsx +295 -0
- package/src/panels/zones/brick-detail.tsx +136 -0
- package/src/panels/zones/brick-list.tsx +56 -0
- package/src/panels/zones/cache-tab.tsx +118 -0
- package/src/panels/zones/drift-view.tsx +97 -0
- package/src/panels/zones/mcp-mounts-tab.tsx +38 -0
- package/src/panels/zones/memories-tab.tsx +37 -0
- package/src/panels/zones/reindex-status.tsx +84 -0
- package/src/panels/zones/workspaces-tab.tsx +37 -0
- package/src/panels/zones/zone-list.tsx +73 -0
- package/src/panels/zones/zones-panel.tsx +559 -0
- package/src/services/command-runner.ts +303 -0
- package/src/shared/accessibility-announcements.ts +44 -0
- package/src/shared/action-registry.ts +466 -0
- package/src/shared/brick-states.ts +91 -0
- package/src/shared/command-palette.ts +35 -0
- package/src/shared/components/announcement-bar.tsx +30 -0
- package/src/shared/components/app-confirm-dialog.tsx +29 -0
- package/src/shared/components/breadcrumb.tsx +21 -0
- package/src/shared/components/brick-gate.tsx +60 -0
- package/src/shared/components/command-output.tsx +95 -0
- package/src/shared/components/command-palette.tsx +97 -0
- package/src/shared/components/confirm-dialog.tsx +61 -0
- package/src/shared/components/diff-viewer.tsx +219 -0
- package/src/shared/components/empty-state.tsx +36 -0
- package/src/shared/components/error-bar.tsx +60 -0
- package/src/shared/components/error-boundary.tsx +53 -0
- package/src/shared/components/help-overlay.tsx +99 -0
- package/src/shared/components/identity-switcher.tsx +168 -0
- package/src/shared/components/loading-indicator.tsx +40 -0
- package/src/shared/components/pagination-bar.tsx +68 -0
- package/src/shared/components/pre-connection-screen.tsx +398 -0
- package/src/shared/components/scroll-indicator.tsx +46 -0
- package/src/shared/components/side-nav-utils.ts +68 -0
- package/src/shared/components/side-nav.tsx +287 -0
- package/src/shared/components/spinner.tsx +26 -0
- package/src/shared/components/status-bar.tsx +117 -0
- package/src/shared/components/styled-text.tsx +72 -0
- package/src/shared/components/sub-tab-bar-utils.ts +100 -0
- package/src/shared/components/sub-tab-bar.tsx +40 -0
- package/src/shared/components/tab-bar-utils.ts +36 -0
- package/src/shared/components/tab-bar.tsx +50 -0
- package/src/shared/components/text-input.tsx +73 -0
- package/src/shared/components/tooltip.tsx +53 -0
- package/src/shared/components/virtual-list.tsx +93 -0
- package/src/shared/components/welcome-screen.tsx +111 -0
- package/src/shared/hooks/use-api.ts +10 -0
- package/src/shared/hooks/use-brick-available.ts +42 -0
- package/src/shared/hooks/use-confirm.ts +66 -0
- package/src/shared/hooks/use-connection-state.ts +67 -0
- package/src/shared/hooks/use-copy.ts +31 -0
- package/src/shared/hooks/use-fresh-server.ts +62 -0
- package/src/shared/hooks/use-keyboard.ts +58 -0
- package/src/shared/hooks/use-list-navigation.ts +106 -0
- package/src/shared/hooks/use-swr.ts +117 -0
- package/src/shared/hooks/use-tab-fallback.ts +32 -0
- package/src/shared/hooks/use-text-input.ts +113 -0
- package/src/shared/hooks/use-visible-tabs.ts +61 -0
- package/src/shared/lib/circular-buffer.ts +82 -0
- package/src/shared/lib/clipboard.ts +14 -0
- package/src/shared/nav-items.ts +73 -0
- package/src/shared/navigation.ts +110 -0
- package/src/shared/status-breadcrumb.ts +74 -0
- package/src/shared/syntax-style.ts +3 -0
- package/src/shared/tab-visibility.ts +15 -0
- package/src/shared/text-style.ts +23 -0
- package/src/shared/theme.ts +179 -0
- package/src/shared/utils/format-size.ts +20 -0
- package/src/shared/utils/format-text.ts +10 -0
- package/src/shared/utils/format-time.ts +72 -0
- package/src/shared/utils/lru-cache.ts +75 -0
- package/src/stores/access-store-types.ts +154 -0
- package/src/stores/access-store.ts +674 -0
- package/src/stores/agents-store.ts +404 -0
- package/src/stores/announcement-store.ts +46 -0
- package/src/stores/api-console-store.ts +476 -0
- package/src/stores/connectors-store.ts +434 -0
- package/src/stores/create-api-action.ts +140 -0
- package/src/stores/delegation-store.ts +300 -0
- package/src/stores/error-store.ts +102 -0
- package/src/stores/events-store.ts +163 -0
- package/src/stores/files-store.ts +630 -0
- package/src/stores/first-run-store.ts +34 -0
- package/src/stores/global-store.ts +255 -0
- package/src/stores/infra-store.ts +461 -0
- package/src/stores/knowledge-store.ts +358 -0
- package/src/stores/lineage-store.ts +126 -0
- package/src/stores/mcp-store.ts +147 -0
- package/src/stores/payments-store.ts +545 -0
- package/src/stores/search-store-types.ts +155 -0
- package/src/stores/search-store.ts +656 -0
- package/src/stores/share-link-store.ts +151 -0
- package/src/stores/stack-store.ts +352 -0
- package/src/stores/ui-store.ts +161 -0
- package/src/stores/upload-store.ts +131 -0
- package/src/stores/versions-store.ts +355 -0
- package/src/stores/workflows-store.ts +402 -0
- package/src/stores/workspace-store.ts +185 -0
- package/src/stores/zones-store.ts +378 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Share Links tab: displays a scrollable list of share links with
|
|
3
|
+
* columns for path, permission, status, access count, and expiry.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import type { ShareLink } from "../../stores/share-link-store.js";
|
|
8
|
+
|
|
9
|
+
interface ShareLinksTabProps {
|
|
10
|
+
readonly links: readonly ShareLink[];
|
|
11
|
+
readonly selectedIndex: number;
|
|
12
|
+
readonly loading: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function ShareLinksTab({ links, selectedIndex, loading }: ShareLinksTabProps): React.ReactNode {
|
|
16
|
+
if (loading) return <text>Loading share links...</text>;
|
|
17
|
+
if (links.length === 0) return <text>{"No share links. Press 'n' to create one."}</text>;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<scrollbox height="100%" width="100%">
|
|
21
|
+
{links.map((link, i) => {
|
|
22
|
+
const isSelected = i === selectedIndex;
|
|
23
|
+
const prefix = isSelected ? "> " : " ";
|
|
24
|
+
const statusBadge = link.status === "active" ? "\u25CF" : link.status === "revoked" ? "\u00D7" : "\u25CB";
|
|
25
|
+
return (
|
|
26
|
+
<box key={link.link_id} height={1} width="100%">
|
|
27
|
+
<text>{`${prefix}${statusBadge} ${link.path} ${link.permission_level} ${link.access_count} views ${link.expires_at ?? "no expiry"}`}</text>
|
|
28
|
+
</box>
|
|
29
|
+
);
|
|
30
|
+
})}
|
|
31
|
+
</scrollbox>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uploads tab: displays upload sessions with progress bars,
|
|
3
|
+
* filename, progress (offset/length), status, and expiry.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import type { UploadSession } from "../../stores/upload-store.js";
|
|
8
|
+
|
|
9
|
+
interface UploadsTabProps {
|
|
10
|
+
readonly sessions: readonly UploadSession[];
|
|
11
|
+
readonly selectedIndex: number;
|
|
12
|
+
readonly loading: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function formatProgress(offset: number, length: number): string {
|
|
16
|
+
if (length <= 0) return `${offset} bytes`;
|
|
17
|
+
const pct = Math.min(100, Math.round((offset / length) * 100));
|
|
18
|
+
const barWidth = 20;
|
|
19
|
+
const filled = Math.round((pct / 100) * barWidth);
|
|
20
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(barWidth - filled);
|
|
21
|
+
return `[${bar}] ${pct}% (${offset}/${length})`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function UploadsTab({ sessions, selectedIndex, loading }: UploadsTabProps): React.ReactNode {
|
|
25
|
+
if (loading) return <text>Loading upload sessions...</text>;
|
|
26
|
+
if (sessions.length === 0) return <text>No active upload sessions.</text>;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<scrollbox height="100%" width="100%">
|
|
30
|
+
{sessions.map((session, i) => {
|
|
31
|
+
const isSelected = i === selectedIndex;
|
|
32
|
+
const prefix = isSelected ? "> " : " ";
|
|
33
|
+
const filename = session.filename ?? "(unknown)";
|
|
34
|
+
const progress = formatProgress(session.offset, session.length);
|
|
35
|
+
const expiry = session.expires_at ? `expires ${session.expires_at}` : "no expiry";
|
|
36
|
+
return (
|
|
37
|
+
<box key={session.id} height={2} width="100%" flexDirection="column">
|
|
38
|
+
<text>{`${prefix}${filename} ${session.id.slice(0, 8)}... ${expiry}`}</text>
|
|
39
|
+
<text>{` ${progress}`}</text>
|
|
40
|
+
</box>
|
|
41
|
+
);
|
|
42
|
+
})}
|
|
43
|
+
</scrollbox>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval list: displays spending approval requests with status coloring.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from "react";
|
|
6
|
+
import type { ApprovalRequest } from "../../stores/payments-store.js";
|
|
7
|
+
import { LoadingIndicator } from "../../shared/components/loading-indicator.js";
|
|
8
|
+
import { textStyle } from "../../shared/text-style.js";
|
|
9
|
+
import { statusColor } from "../../shared/theme.js";
|
|
10
|
+
|
|
11
|
+
interface ApprovalListProps {
|
|
12
|
+
readonly approvals: readonly ApprovalRequest[];
|
|
13
|
+
readonly selectedIndex: number;
|
|
14
|
+
readonly loading: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function shortId(id: string): string {
|
|
18
|
+
if (id.length <= 12) return id;
|
|
19
|
+
return `${id.slice(0, 8)}..`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function formatTime(ts: string): string {
|
|
23
|
+
try {
|
|
24
|
+
return new Date(ts).toLocaleString();
|
|
25
|
+
} catch {
|
|
26
|
+
return ts;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const STATUS_COLOR: Record<string, string> = {
|
|
31
|
+
pending: statusColor.warning,
|
|
32
|
+
approved: statusColor.healthy,
|
|
33
|
+
rejected: statusColor.error,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function ApprovalList({
|
|
37
|
+
approvals,
|
|
38
|
+
selectedIndex,
|
|
39
|
+
loading,
|
|
40
|
+
}: ApprovalListProps): React.ReactNode {
|
|
41
|
+
if (loading) {
|
|
42
|
+
return <LoadingIndicator message="Loading approvals..." />;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (approvals.length === 0) {
|
|
46
|
+
return (
|
|
47
|
+
<box height="100%" width="100%" justifyContent="center" alignItems="center">
|
|
48
|
+
<text style={textStyle({ dim: true })}>No approval requests found</text>
|
|
49
|
+
</box>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<scrollbox height="100%" width="100%">
|
|
55
|
+
{/* Header */}
|
|
56
|
+
<box height={1} width="100%">
|
|
57
|
+
<text>{" ID AMOUNT PURPOSE STATUS REQUESTER CREATED"}</text>
|
|
58
|
+
</box>
|
|
59
|
+
<box height={1} width="100%">
|
|
60
|
+
<text>{" ---------- ----------- ------------------------- --------- ------------ -----------------------"}</text>
|
|
61
|
+
</box>
|
|
62
|
+
|
|
63
|
+
{/* Rows */}
|
|
64
|
+
{approvals.map((a, i) => {
|
|
65
|
+
const isSelected = i === selectedIndex;
|
|
66
|
+
const prefix = isSelected ? "> " : " ";
|
|
67
|
+
const amount = String(a.amount).padEnd(11);
|
|
68
|
+
const purpose = (a.purpose.length > 25 ? a.purpose.slice(0, 22) + "..." : a.purpose).padEnd(25);
|
|
69
|
+
const color = STATUS_COLOR[a.status];
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<box key={a.id} height={1} width="100%">
|
|
73
|
+
<text>
|
|
74
|
+
{`${prefix}${shortId(a.id).padEnd(10)} ${amount} ${purpose} `}
|
|
75
|
+
<span style={color ? textStyle({ fg: color }) : undefined}>{a.status.padEnd(9)}</span>
|
|
76
|
+
{` ${shortId(a.requester_id).padEnd(12)} ${formatTime(a.created_at)}`}
|
|
77
|
+
</text>
|
|
78
|
+
</box>
|
|
79
|
+
);
|
|
80
|
+
})}
|
|
81
|
+
</scrollbox>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Balance card: displays available, reserved, and total credit amounts.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from "react";
|
|
6
|
+
import type { BalanceInfo } from "../../stores/payments-store.js";
|
|
7
|
+
import { LoadingIndicator } from "../../shared/components/loading-indicator.js";
|
|
8
|
+
|
|
9
|
+
interface BalanceCardProps {
|
|
10
|
+
readonly balance: BalanceInfo | null;
|
|
11
|
+
readonly loading: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function BalanceCard({ balance, loading }: BalanceCardProps): React.ReactNode {
|
|
15
|
+
if (loading) {
|
|
16
|
+
return <LoadingIndicator message="Loading balance..." />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!balance) {
|
|
20
|
+
return (
|
|
21
|
+
<box height="100%" width="100%" justifyContent="center" alignItems="center">
|
|
22
|
+
<text>No balance data available</text>
|
|
23
|
+
</box>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<scrollbox height="100%" width="100%">
|
|
29
|
+
<box height={1} width="100%" marginTop={1}>
|
|
30
|
+
<text>--- Balances ---</text>
|
|
31
|
+
</box>
|
|
32
|
+
<box height={1} width="100%">
|
|
33
|
+
<text>{`Available: ${balance.available}`}</text>
|
|
34
|
+
</box>
|
|
35
|
+
<box height={1} width="100%">
|
|
36
|
+
<text>{`Reserved: ${balance.reserved}`}</text>
|
|
37
|
+
</box>
|
|
38
|
+
<box height={1} width="100%">
|
|
39
|
+
<text>{`Total: ${balance.total}`}</text>
|
|
40
|
+
</box>
|
|
41
|
+
</scrollbox>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget card: displays spending limits vs spent vs remaining for each period.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from "react";
|
|
6
|
+
import type { BudgetSummary } from "../../stores/payments-store.js";
|
|
7
|
+
|
|
8
|
+
interface BudgetCardProps {
|
|
9
|
+
readonly budget: BudgetSummary | null;
|
|
10
|
+
readonly loading: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function BudgetCard({ budget, loading }: BudgetCardProps): React.ReactNode {
|
|
14
|
+
if (loading) {
|
|
15
|
+
return (
|
|
16
|
+
<box height="100%" width="100%" justifyContent="center" alignItems="center">
|
|
17
|
+
<text>Loading budget...</text>
|
|
18
|
+
</box>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!budget) {
|
|
23
|
+
return (
|
|
24
|
+
<box height="100%" width="100%" justifyContent="center" alignItems="center">
|
|
25
|
+
<text>No budget data available. Press b to fetch.</text>
|
|
26
|
+
</box>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!budget.has_policy) {
|
|
31
|
+
return (
|
|
32
|
+
<box height="100%" width="100%" justifyContent="center" alignItems="center">
|
|
33
|
+
<text>No spending policy configured</text>
|
|
34
|
+
</box>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<scrollbox height="100%" width="100%">
|
|
40
|
+
<box height={1} width="100%" marginTop={1}>
|
|
41
|
+
<text>--- Budget Summary ---</text>
|
|
42
|
+
</box>
|
|
43
|
+
|
|
44
|
+
{/* Header */}
|
|
45
|
+
<box height={1} width="100%" marginTop={1}>
|
|
46
|
+
<text>{"PERIOD LIMIT SPENT REMAINING"}</text>
|
|
47
|
+
</box>
|
|
48
|
+
<box height={1} width="100%">
|
|
49
|
+
<text>{"--------- ------------- ------------- -------------"}</text>
|
|
50
|
+
</box>
|
|
51
|
+
|
|
52
|
+
{/* Rows */}
|
|
53
|
+
<box height={1} width="100%">
|
|
54
|
+
<text>{`${"Daily".padEnd(9)} ${budget.limits.daily.padEnd(13)} ${budget.spent.daily.padEnd(13)} ${budget.remaining.daily}`}</text>
|
|
55
|
+
</box>
|
|
56
|
+
<box height={1} width="100%">
|
|
57
|
+
<text>{`${"Weekly".padEnd(9)} ${budget.limits.weekly.padEnd(13)} ${budget.spent.weekly.padEnd(13)} ${budget.remaining.weekly}`}</text>
|
|
58
|
+
</box>
|
|
59
|
+
<box height={1} width="100%">
|
|
60
|
+
<text>{`${"Monthly".padEnd(9)} ${budget.limits.monthly.padEnd(13)} ${budget.spent.monthly.padEnd(13)} ${budget.remaining.monthly}`}</text>
|
|
61
|
+
</box>
|
|
62
|
+
|
|
63
|
+
{budget.policy_id && (
|
|
64
|
+
<box height={1} width="100%" marginTop={1}>
|
|
65
|
+
<text>{`Policy: ${budget.policy_id}`}</text>
|
|
66
|
+
</box>
|
|
67
|
+
)}
|
|
68
|
+
</scrollbox>
|
|
69
|
+
);
|
|
70
|
+
}
|