@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,455 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
|
|
3
|
-
interface IDataPoint {
|
|
4
|
-
timestamp: number;
|
|
5
|
-
value: number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
interface IColorZone {
|
|
9
|
-
/**
|
|
10
|
-
* Maximum value for this zone (exclusive). Use Infinity for the last zone.
|
|
11
|
-
*/
|
|
12
|
-
maxValue: number;
|
|
13
|
-
/**
|
|
14
|
-
* Color to use in this zone
|
|
15
|
-
*/
|
|
16
|
-
color: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface IUsageGraphProps {
|
|
20
|
-
/**
|
|
21
|
-
* Function to fetch current usage value
|
|
22
|
-
*/
|
|
23
|
-
fetchUsage: () => Promise<number>;
|
|
24
|
-
/**
|
|
25
|
-
* Label to display in the overlay (e.g., "CPU", "Memory")
|
|
26
|
-
*/
|
|
27
|
-
label: string;
|
|
28
|
-
/**
|
|
29
|
-
* Duration in minutes to display
|
|
30
|
-
*/
|
|
31
|
-
durationMinutes?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Update interval in milliseconds
|
|
34
|
-
*/
|
|
35
|
-
updateInterval?: number;
|
|
36
|
-
/**
|
|
37
|
-
* Minimum height in pixels (optional, defaults to 80)
|
|
38
|
-
*/
|
|
39
|
-
minHeight?: number;
|
|
40
|
-
/**
|
|
41
|
-
* Color for the graph line and gradient (optional, defaults to blue)
|
|
42
|
-
*/
|
|
43
|
-
color?: string;
|
|
44
|
-
/**
|
|
45
|
-
* Color for the overlay text (optional, defaults to transparent white)
|
|
46
|
-
*/
|
|
47
|
-
overlayTextColor?: string;
|
|
48
|
-
/**
|
|
49
|
-
* Minimum value for y-axis (optional, defaults to 0)
|
|
50
|
-
*/
|
|
51
|
-
minValue?: number;
|
|
52
|
-
/**
|
|
53
|
-
* Maximum value for y-axis (optional, defaults to 100)
|
|
54
|
-
*/
|
|
55
|
-
maxValue?: number;
|
|
56
|
-
/**
|
|
57
|
-
* Custom function to format the overlay text (optional, defaults to showing percentage)
|
|
58
|
-
*/
|
|
59
|
-
formatOverlayText?: (value: number, label: string) => string;
|
|
60
|
-
/**
|
|
61
|
-
* Color zones based on value thresholds (optional)
|
|
62
|
-
* Example: [{ maxValue: 50, color: 'green' }, { maxValue: 75, color: 'orange' }, { maxValue: Infinity, color: 'red' }]
|
|
63
|
-
* If not provided, uses single color throughout
|
|
64
|
-
*/
|
|
65
|
-
colorZones?: IColorZone[];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function UsageGraph({
|
|
69
|
-
fetchUsage,
|
|
70
|
-
label,
|
|
71
|
-
durationMinutes = 5,
|
|
72
|
-
updateInterval = 5000,
|
|
73
|
-
minHeight = 80,
|
|
74
|
-
color = "rgba(13, 110, 253, 1)",
|
|
75
|
-
overlayTextColor = "rgba(255, 255, 255, 0.7)",
|
|
76
|
-
minValue = 0,
|
|
77
|
-
maxValue = 100,
|
|
78
|
-
formatOverlayText,
|
|
79
|
-
colorZones,
|
|
80
|
-
}: IUsageGraphProps) {
|
|
81
|
-
const [dataPoints, setDataPoints] = useState<IDataPoint[]>([]);
|
|
82
|
-
const [currentValue, setCurrentValue] = useState<number>(0);
|
|
83
|
-
const [width, setWidth] = useState<number>(400);
|
|
84
|
-
const [height, setHeight] = useState<number>(minHeight);
|
|
85
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
86
|
-
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
87
|
-
|
|
88
|
-
// const maxDataPoints = ((durationMinutes * 60 * 1000) / updateInterval) + 2;
|
|
89
|
-
|
|
90
|
-
// Observe container size and update width and height
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
if (!containerRef.current) return;
|
|
93
|
-
|
|
94
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
95
|
-
for (const entry of entries) {
|
|
96
|
-
const newWidth = entry.contentRect.width;
|
|
97
|
-
const newHeight = entry.contentRect.height;
|
|
98
|
-
if (newWidth > 0) {
|
|
99
|
-
setWidth(newWidth);
|
|
100
|
-
}
|
|
101
|
-
if (newHeight > 0) {
|
|
102
|
-
setHeight(Math.max(newHeight, minHeight));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
resizeObserver.observe(containerRef.current);
|
|
108
|
-
|
|
109
|
-
return () => {
|
|
110
|
-
resizeObserver.disconnect();
|
|
111
|
-
};
|
|
112
|
-
}, [minHeight]);
|
|
113
|
-
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
const updateData = async () => {
|
|
116
|
-
try {
|
|
117
|
-
const value = await fetchUsage();
|
|
118
|
-
setCurrentValue(value);
|
|
119
|
-
|
|
120
|
-
setDataPoints((prev) => {
|
|
121
|
-
const newPoint: IDataPoint = {
|
|
122
|
-
timestamp: Date.now(),
|
|
123
|
-
value: value,
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const updated = [...prev, newPoint];
|
|
127
|
-
const oldestAllowedTime = Date.now() - durationMinutes * 60 * 1000;
|
|
128
|
-
const filtered = updated.filter((point) => point.timestamp >= oldestAllowedTime);
|
|
129
|
-
return filtered;
|
|
130
|
-
});
|
|
131
|
-
} catch (error) {
|
|
132
|
-
console.error(`Error fetching ${label} usage:`, error);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
// Initial fetch
|
|
137
|
-
updateData();
|
|
138
|
-
|
|
139
|
-
// Set up interval
|
|
140
|
-
intervalRef.current = setInterval(updateData, updateInterval);
|
|
141
|
-
|
|
142
|
-
return () => {
|
|
143
|
-
if (intervalRef.current) {
|
|
144
|
-
clearInterval(intervalRef.current);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}, [fetchUsage, updateInterval, label, durationMinutes]);
|
|
148
|
-
|
|
149
|
-
// Get color for a value based on color zones
|
|
150
|
-
const getColorForValue = (value: number): string => {
|
|
151
|
-
if (!colorZones || colorZones.length === 0) {
|
|
152
|
-
return color;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Find the appropriate color zone
|
|
156
|
-
for (const zone of colorZones) {
|
|
157
|
-
if (value < zone.maxValue) {
|
|
158
|
-
return zone.color;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Default to last zone color if value exceeds all zones
|
|
163
|
-
return colorZones[colorZones.length - 1].color;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// Calculate SVG path segments with colors
|
|
167
|
-
const getLineSegments = (): Array<{ path: string; color: string }> => {
|
|
168
|
-
if (dataPoints.length < 2) return [];
|
|
169
|
-
|
|
170
|
-
const paddingLeft = 25;
|
|
171
|
-
const paddingRight = 10;
|
|
172
|
-
const paddingTop = 10;
|
|
173
|
-
const paddingBottom = 10;
|
|
174
|
-
const chartWidth = width - paddingLeft - paddingRight;
|
|
175
|
-
const chartHeight = height - paddingTop - paddingBottom;
|
|
176
|
-
|
|
177
|
-
// Use full time range, but adjust minTime to start at oldest data point
|
|
178
|
-
const now = Date.now();
|
|
179
|
-
const timeRange = durationMinutes * 60 * 1000;
|
|
180
|
-
const minTime = Math.min(dataPoints[0].timestamp, now - timeRange);
|
|
181
|
-
|
|
182
|
-
const points = dataPoints.map((point) => {
|
|
183
|
-
// X: Map timestamp to chart width
|
|
184
|
-
const x = paddingLeft + ((point.timestamp - minTime) / timeRange) * chartWidth;
|
|
185
|
-
|
|
186
|
-
// Y: Map value (minValue-maxValue) to chart height (inverted because SVG Y grows downward)
|
|
187
|
-
const valueRange = maxValue - minValue;
|
|
188
|
-
const normalizedValue = (point.value - minValue) / valueRange;
|
|
189
|
-
const y = paddingTop + chartHeight - normalizedValue * chartHeight;
|
|
190
|
-
|
|
191
|
-
return { x, y, value: point.value };
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// If no color zones, return single segment
|
|
195
|
-
if (!colorZones || colorZones.length === 0) {
|
|
196
|
-
const pathData = points
|
|
197
|
-
.map((point, idx) => {
|
|
198
|
-
if (idx === 0) {
|
|
199
|
-
return `M ${point.x} ${point.y}`;
|
|
200
|
-
}
|
|
201
|
-
return `L ${point.x} ${point.y}`;
|
|
202
|
-
})
|
|
203
|
-
.join(" ");
|
|
204
|
-
return [{ path: pathData, color }];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Create segments based on color zones
|
|
208
|
-
const segments: Array<{ path: string; color: string }> = [];
|
|
209
|
-
let currentPath = `M ${points[0].x} ${points[0].y}`;
|
|
210
|
-
let currentColor = getColorForValue(points[0].value);
|
|
211
|
-
|
|
212
|
-
for (let i = 1; i < points.length; i++) {
|
|
213
|
-
const pointColor = getColorForValue(points[i].value);
|
|
214
|
-
|
|
215
|
-
if (pointColor !== currentColor) {
|
|
216
|
-
// Color changed, finish current segment and start new one
|
|
217
|
-
segments.push({ path: currentPath, color: currentColor });
|
|
218
|
-
currentPath = `M ${points[i - 1].x} ${points[i - 1].y} L ${points[i].x} ${points[i].y}`;
|
|
219
|
-
currentColor = pointColor;
|
|
220
|
-
} else {
|
|
221
|
-
// Same color, continue path
|
|
222
|
-
currentPath += ` L ${points[i].x} ${points[i].y}`;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Add final segment
|
|
227
|
-
if (currentPath) {
|
|
228
|
-
segments.push({ path: currentPath, color: currentColor });
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return segments;
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// Calculate SVG path (for gradient fill)
|
|
235
|
-
const getLinePath = (): string => {
|
|
236
|
-
if (dataPoints.length < 2) return "";
|
|
237
|
-
|
|
238
|
-
const paddingLeft = 25;
|
|
239
|
-
const paddingRight = 10;
|
|
240
|
-
const paddingTop = 10;
|
|
241
|
-
const paddingBottom = 10;
|
|
242
|
-
const chartWidth = width - paddingLeft - paddingRight;
|
|
243
|
-
const chartHeight = height - paddingTop - paddingBottom;
|
|
244
|
-
|
|
245
|
-
// Use full time range, but adjust minTime to start at oldest data point
|
|
246
|
-
const now = Date.now();
|
|
247
|
-
const timeRange = durationMinutes * 60 * 1000;
|
|
248
|
-
const minTime = Math.min(dataPoints[0].timestamp, now - timeRange);
|
|
249
|
-
|
|
250
|
-
const points = dataPoints.map((point) => {
|
|
251
|
-
// X: Map timestamp to chart width
|
|
252
|
-
const x = paddingLeft + ((point.timestamp - minTime) / timeRange) * chartWidth;
|
|
253
|
-
|
|
254
|
-
// Y: Map value (minValue-maxValue) to chart height (inverted because SVG Y grows downward)
|
|
255
|
-
const valueRange = maxValue - minValue;
|
|
256
|
-
const normalizedValue = (point.value - minValue) / valueRange;
|
|
257
|
-
const y = paddingTop + chartHeight - normalizedValue * chartHeight;
|
|
258
|
-
|
|
259
|
-
return { x, y };
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Create SVG path
|
|
263
|
-
const pathData = points
|
|
264
|
-
.map((point, idx) => {
|
|
265
|
-
if (idx === 0) {
|
|
266
|
-
return `M ${point.x} ${point.y}`;
|
|
267
|
-
}
|
|
268
|
-
return `L ${point.x} ${point.y}`;
|
|
269
|
-
})
|
|
270
|
-
.join(" ");
|
|
271
|
-
|
|
272
|
-
return pathData;
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
// Get gradient path for fill
|
|
276
|
-
const getGradientPath = (): string => {
|
|
277
|
-
const linePath = getLinePath();
|
|
278
|
-
if (!linePath) return "";
|
|
279
|
-
|
|
280
|
-
const paddingLeft = 25;
|
|
281
|
-
const paddingRight = 10;
|
|
282
|
-
const paddingBottom = 10;
|
|
283
|
-
|
|
284
|
-
// Close the path at the bottom
|
|
285
|
-
return `${linePath} L ${width - paddingRight} ${height - paddingBottom} L ${paddingLeft} ${height - paddingBottom} Z`;
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const _linePath = getLinePath();
|
|
289
|
-
const gradientPath = getGradientPath();
|
|
290
|
-
const lineSegments = getLineSegments();
|
|
291
|
-
|
|
292
|
-
// Parse color for gradient
|
|
293
|
-
const rgbaMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/);
|
|
294
|
-
const gradientColor = rgbaMatch
|
|
295
|
-
? `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, 0.3)`
|
|
296
|
-
: "rgba(13, 110, 253, 0.3)";
|
|
297
|
-
const gradientColorLight = rgbaMatch
|
|
298
|
-
? `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, 0.05)`
|
|
299
|
-
: "rgba(13, 110, 253, 0.05)";
|
|
300
|
-
|
|
301
|
-
return (
|
|
302
|
-
<div
|
|
303
|
-
ref={containerRef}
|
|
304
|
-
className="usage-graph"
|
|
305
|
-
style={{
|
|
306
|
-
margin: 0,
|
|
307
|
-
padding: 0,
|
|
308
|
-
position: "relative",
|
|
309
|
-
width: "100%",
|
|
310
|
-
height: "100%",
|
|
311
|
-
minHeight: `${minHeight}px`,
|
|
312
|
-
}}
|
|
313
|
-
>
|
|
314
|
-
<svg
|
|
315
|
-
width={width}
|
|
316
|
-
height={height}
|
|
317
|
-
style={{
|
|
318
|
-
border: "1px solid rgba(128, 128, 128, 0.2)",
|
|
319
|
-
borderRadius: "4px",
|
|
320
|
-
backgroundColor: "rgba(0, 0, 0, 0.02)",
|
|
321
|
-
display: "block",
|
|
322
|
-
}}
|
|
323
|
-
>
|
|
324
|
-
<defs>
|
|
325
|
-
<linearGradient id={`${label}Gradient`} x1="0%" y1="0%" x2="0%" y2="100%">
|
|
326
|
-
<stop offset="0%" stopColor={gradientColor} />
|
|
327
|
-
<stop offset="100%" stopColor={gradientColorLight} />
|
|
328
|
-
</linearGradient>
|
|
329
|
-
</defs>
|
|
330
|
-
|
|
331
|
-
{/* Grid lines */}
|
|
332
|
-
{[0, 0.25, 0.5, 0.75, 1].map((fraction) => {
|
|
333
|
-
const paddingLeft = 25;
|
|
334
|
-
const paddingRight = 10;
|
|
335
|
-
const paddingTop = 10;
|
|
336
|
-
const paddingBottom = 10;
|
|
337
|
-
const chartHeight = height - paddingTop - paddingBottom;
|
|
338
|
-
const value = minValue + fraction * (maxValue - minValue);
|
|
339
|
-
const y = paddingTop + chartHeight - fraction * chartHeight;
|
|
340
|
-
return (
|
|
341
|
-
<g key={fraction}>
|
|
342
|
-
<line
|
|
343
|
-
x1={paddingLeft}
|
|
344
|
-
y1={y}
|
|
345
|
-
x2={width - paddingRight}
|
|
346
|
-
y2={y}
|
|
347
|
-
stroke="rgba(128, 128, 128, 0.1)"
|
|
348
|
-
strokeWidth="1"
|
|
349
|
-
/>
|
|
350
|
-
<text
|
|
351
|
-
x={paddingLeft - 5}
|
|
352
|
-
y={y + 4}
|
|
353
|
-
fontSize="10"
|
|
354
|
-
fill="rgba(128, 128, 128, 0.6)"
|
|
355
|
-
textAnchor="end"
|
|
356
|
-
>
|
|
357
|
-
{Math.round(value)}
|
|
358
|
-
</text>
|
|
359
|
-
</g>
|
|
360
|
-
);
|
|
361
|
-
})}
|
|
362
|
-
|
|
363
|
-
{/* Fill area under the line */}
|
|
364
|
-
{gradientPath && <path d={gradientPath} fill={`url(#${label}Gradient)`} />}
|
|
365
|
-
|
|
366
|
-
{/* Line segments with color zones */}
|
|
367
|
-
{lineSegments.map((segment, idx) => (
|
|
368
|
-
<path
|
|
369
|
-
key={idx}
|
|
370
|
-
d={segment.path}
|
|
371
|
-
stroke={segment.color}
|
|
372
|
-
strokeWidth="2"
|
|
373
|
-
fill="none"
|
|
374
|
-
strokeLinecap="round"
|
|
375
|
-
strokeLinejoin="round"
|
|
376
|
-
/>
|
|
377
|
-
))}
|
|
378
|
-
|
|
379
|
-
{/* Data points */}
|
|
380
|
-
{dataPoints.map((point, idx) => {
|
|
381
|
-
const paddingLeft = 25;
|
|
382
|
-
const paddingRight = 10;
|
|
383
|
-
const paddingTop = 10;
|
|
384
|
-
const paddingBottom = 10;
|
|
385
|
-
const chartWidth = width - paddingLeft - paddingRight;
|
|
386
|
-
const chartHeight = height - paddingTop - paddingBottom;
|
|
387
|
-
|
|
388
|
-
// Use full time range, but adjust minTime to start at oldest data point
|
|
389
|
-
const now = Date.now();
|
|
390
|
-
const timeRange = durationMinutes * 60 * 1000;
|
|
391
|
-
const minTime = Math.min(dataPoints[0].timestamp, now - timeRange);
|
|
392
|
-
|
|
393
|
-
const x = paddingLeft + ((point.timestamp - minTime) / timeRange) * chartWidth;
|
|
394
|
-
const valueRange = maxValue - minValue;
|
|
395
|
-
const normalizedValue = (point.value - minValue) / valueRange;
|
|
396
|
-
const y = paddingTop + chartHeight - normalizedValue * chartHeight;
|
|
397
|
-
|
|
398
|
-
// Only show the last point as a visible dot
|
|
399
|
-
if (idx !== dataPoints.length - 1) return null;
|
|
400
|
-
|
|
401
|
-
const pointColor = getColorForValue(point.value);
|
|
402
|
-
|
|
403
|
-
return (
|
|
404
|
-
<circle
|
|
405
|
-
key={idx}
|
|
406
|
-
cx={x}
|
|
407
|
-
cy={y}
|
|
408
|
-
r="3"
|
|
409
|
-
fill={pointColor}
|
|
410
|
-
stroke="white"
|
|
411
|
-
strokeWidth="1.5"
|
|
412
|
-
/>
|
|
413
|
-
);
|
|
414
|
-
})}
|
|
415
|
-
|
|
416
|
-
{/* No data message */}
|
|
417
|
-
{dataPoints.length === 0 && (
|
|
418
|
-
<text
|
|
419
|
-
x={width / 2}
|
|
420
|
-
y={height / 2}
|
|
421
|
-
fontSize="12"
|
|
422
|
-
fill="rgba(128, 128, 128, 0.6)"
|
|
423
|
-
textAnchor="middle"
|
|
424
|
-
>
|
|
425
|
-
Collecting data...
|
|
426
|
-
</text>
|
|
427
|
-
)}
|
|
428
|
-
</svg>
|
|
429
|
-
|
|
430
|
-
{/* Centered overlay text */}
|
|
431
|
-
<div
|
|
432
|
-
style={{
|
|
433
|
-
position: "absolute",
|
|
434
|
-
top: "50%",
|
|
435
|
-
left: "50%",
|
|
436
|
-
transform: "translate(-50%, -50%)",
|
|
437
|
-
fontSize: "2rem",
|
|
438
|
-
fontWeight: "bold",
|
|
439
|
-
color: overlayTextColor,
|
|
440
|
-
pointerEvents: "none",
|
|
441
|
-
userSelect: "none",
|
|
442
|
-
textAlign: "center",
|
|
443
|
-
lineHeight: "1.2",
|
|
444
|
-
whiteSpace: "nowrap",
|
|
445
|
-
maxWidth: "95%",
|
|
446
|
-
overflowWrap: "break-word",
|
|
447
|
-
}}
|
|
448
|
-
>
|
|
449
|
-
{formatOverlayText
|
|
450
|
-
? formatOverlayText(currentValue, label)
|
|
451
|
-
: `${label} ${Math.round(currentValue)}%`}
|
|
452
|
-
</div>
|
|
453
|
-
</div>
|
|
454
|
-
);
|
|
455
|
-
}
|