@wakastellar/ui 2.3.4 → 2.4.0

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.
Files changed (194) hide show
  1. package/dist/blocks/dashboard/index.d.ts +4 -1
  2. package/dist/blocks/empty-states/index.d.ts +4 -1
  3. package/dist/blocks/error-pages/index.d.ts +4 -1
  4. package/dist/blocks/index.d.ts +1 -1
  5. package/dist/blocks/landing/index.d.ts +4 -1
  6. package/dist/blocks/pricing/index.d.ts +5 -1
  7. package/dist/blocks/sidebar/index.d.ts +5 -1
  8. package/dist/index.cjs.js +130 -130
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.es.js +7905 -7856
  11. package/dist/stories/Button.d.ts +14 -0
  12. package/dist/stories/Button.stories.d.ts +8 -0
  13. package/dist/stories/Header.d.ts +11 -0
  14. package/dist/stories/Header.stories.d.ts +6 -0
  15. package/dist/stories/Page.d.ts +2 -0
  16. package/dist/stories/Page.stories.d.ts +6 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/link.d.ts +23 -0
  19. package/package.json +11 -3
  20. package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
  21. package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
  22. package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
  23. package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
  24. package/src/blocks/chat/Chat.stories.tsx +466 -0
  25. package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
  26. package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
  27. package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
  28. package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
  29. package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
  30. package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
  31. package/src/blocks/dashboard/index.tsx +68 -27
  32. package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
  33. package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
  34. package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
  35. package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
  36. package/src/blocks/empty-states/index.tsx +26 -8
  37. package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
  38. package/src/blocks/error-pages/index.tsx +26 -8
  39. package/src/blocks/faq/FAQ.stories.tsx +416 -0
  40. package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
  41. package/src/blocks/footer/Footer.stories.tsx +328 -0
  42. package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
  43. package/src/blocks/header/WakaHeader.stories.tsx +455 -0
  44. package/src/blocks/headtab/Headtab.stories.tsx +369 -0
  45. package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
  46. package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
  47. package/src/blocks/index.ts +1 -1
  48. package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
  49. package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
  50. package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
  51. package/src/blocks/landing/index.tsx +125 -66
  52. package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
  53. package/src/blocks/layout/Layout.stories.tsx +373 -0
  54. package/src/blocks/login/Login.stories.tsx +443 -0
  55. package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
  56. package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
  57. package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
  58. package/src/blocks/pricing/index.tsx +38 -4
  59. package/src/blocks/profile/Profile.stories.tsx +371 -0
  60. package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
  61. package/src/blocks/settings/Settings.stories.tsx +520 -0
  62. package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
  63. package/src/blocks/sidebar/index.tsx +49 -20
  64. package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
  65. package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
  66. package/src/blocks/wizard/Wizard.stories.tsx +683 -0
  67. package/src/components/accordion/Accordion.stories.tsx +93 -0
  68. package/src/components/alert/Alert.stories.tsx +95 -0
  69. package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
  70. package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
  71. package/src/components/avatar/Avatar.stories.tsx +104 -0
  72. package/src/components/button/Button.stories.tsx +12 -1
  73. package/src/components/calendar/Calendar.stories.tsx +102 -0
  74. package/src/components/card/Card.stories.tsx +125 -0
  75. package/src/components/checkbox/Checkbox.stories.tsx +100 -0
  76. package/src/components/code/Code.stories.tsx +402 -0
  77. package/src/components/collapsible/Collapsible.stories.tsx +123 -0
  78. package/src/components/command/Command.stories.tsx +207 -0
  79. package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
  80. package/src/components/dialog/Dialog.stories.tsx +157 -0
  81. package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
  82. package/src/components/form/Form.stories.tsx +413 -0
  83. package/src/components/hover-card/HoverCard.stories.tsx +148 -0
  84. package/src/components/input-otp/InputOTP.stories.tsx +255 -0
  85. package/src/components/label/Label.stories.tsx +68 -0
  86. package/src/components/menubar/Menubar.stories.tsx +278 -0
  87. package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
  88. package/src/components/popover/Popover.stories.tsx +199 -0
  89. package/src/components/progress/Progress.stories.tsx +104 -0
  90. package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
  91. package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
  92. package/src/components/select/Select.stories.tsx +146 -0
  93. package/src/components/separator/Separator.stories.tsx +117 -0
  94. package/src/components/sheet/Sheet.stories.tsx +195 -0
  95. package/src/components/skeleton/Skeleton.stories.tsx +114 -0
  96. package/src/components/slider/Slider.stories.tsx +157 -0
  97. package/src/components/switch/Switch.stories.tsx +114 -0
  98. package/src/components/table/Table.stories.tsx +153 -0
  99. package/src/components/tabs/Tabs.stories.tsx +155 -0
  100. package/src/components/textarea/Textarea.stories.tsx +116 -0
  101. package/src/components/toast/Toast.stories.tsx +160 -0
  102. package/src/components/toggle/Toggle.stories.tsx +125 -0
  103. package/src/components/tooltip/Tooltip.stories.tsx +133 -0
  104. package/src/components/typography/Typography.stories.tsx +207 -0
  105. package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
  106. package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
  107. package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
  108. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
  109. package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
  110. package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
  111. package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
  112. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
  113. package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
  114. package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
  115. package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
  116. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
  117. package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
  118. package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
  119. package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
  120. package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
  121. package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
  122. package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
  123. package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
  124. package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
  125. package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
  126. package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
  127. package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
  128. package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
  129. package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
  130. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
  131. package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
  132. package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
  133. package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
  134. package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
  135. package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
  136. package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
  137. package/src/components/waka-image/WakaImage.stories.tsx +255 -0
  138. package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
  139. package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
  140. package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
  141. package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
  142. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
  143. package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
  144. package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
  145. package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
  146. package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
  147. package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
  148. package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
  149. package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
  150. package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
  151. package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
  152. package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
  153. package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
  154. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
  155. package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
  156. package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
  157. package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
  158. package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
  159. package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
  160. package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
  161. package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
  162. package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
  163. package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
  164. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
  165. package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
  166. package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
  167. package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
  168. package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
  169. package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
  170. package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
  171. package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
  172. package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
  173. package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
  174. package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
  175. package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
  176. package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
  177. package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
  178. package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
  179. package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
  180. package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
  181. package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
  182. package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
  183. package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
  184. package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
  185. package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
  186. package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
  187. package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
  188. package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
  189. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
  190. package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
  191. package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
  192. package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
  193. package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
  194. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +305 -0
@@ -0,0 +1,461 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import {
3
+ ContainerOrchestrator,
4
+ defaultOrchestratorServices,
5
+ } from './index'
6
+ import type { OrchestratorService, OrchestratorContainer, ServiceStatus } from './index'
7
+ import * as React from 'react'
8
+
9
+ const meta: Meta<typeof ContainerOrchestrator> = {
10
+ title: 'Blocks/ContainerOrchestrator',
11
+ component: ContainerOrchestrator,
12
+ parameters: {
13
+ layout: 'fullscreen',
14
+ docs: {
15
+ description: {
16
+ component:
17
+ 'A container orchestration dashboard for managing Docker/Kubernetes services with scaling controls, container status monitoring, resource usage, and service management.',
18
+ },
19
+ },
20
+ },
21
+ tags: ['autodocs'],
22
+ }
23
+
24
+ export default meta
25
+ type Story = StoryObj<typeof ContainerOrchestrator>
26
+
27
+ export const Default: Story = {
28
+ render: () => (
29
+ <div className="p-6">
30
+ <ContainerOrchestrator
31
+ services={defaultOrchestratorServices}
32
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
33
+ onRestartService={(service) => console.log('Restart:', service.name)}
34
+ onStopService={(service) => console.log('Stop:', service.name)}
35
+ onDeleteService={(service) => console.log('Delete:', service.name)}
36
+ onViewLogs={(container) => console.log('Logs:', container.name)}
37
+ onExecShell={(container) => console.log('Shell:', container.name)}
38
+ onRefresh={() => console.log('Refresh')}
39
+ />
40
+ </div>
41
+ ),
42
+ }
43
+
44
+ export const AllRunning: Story = {
45
+ render: () => {
46
+ const healthyServices: OrchestratorService[] = defaultOrchestratorServices.map(service => ({
47
+ ...service,
48
+ status: 'running' as ServiceStatus,
49
+ replicas: {
50
+ desired: service.replicas.desired,
51
+ running: service.replicas.desired,
52
+ ready: service.replicas.desired,
53
+ },
54
+ containers: service.containers.map(c => ({
55
+ ...c,
56
+ status: 'running' as const,
57
+ healthCheck: 'healthy' as const,
58
+ })),
59
+ }))
60
+
61
+ return (
62
+ <div className="p-6">
63
+ <ContainerOrchestrator
64
+ services={healthyServices}
65
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
66
+ onRestartService={(service) => console.log('Restart:', service.name)}
67
+ onRefresh={() => console.log('Refresh')}
68
+ />
69
+ </div>
70
+ )
71
+ },
72
+ }
73
+
74
+ export const WithFailedService: Story = {
75
+ render: () => {
76
+ const servicesWithFailure: OrchestratorService[] = [
77
+ {
78
+ id: 'failed-1',
79
+ name: 'critical-service',
80
+ image: 'myregistry/critical:v1.0.0',
81
+ status: 'failed',
82
+ replicas: { desired: 3, running: 0, ready: 0 },
83
+ containers: [
84
+ {
85
+ id: 'critical-1',
86
+ name: 'critical-service-1',
87
+ image: 'myregistry/critical:v1.0.0',
88
+ status: 'exited',
89
+ createdAt: new Date(Date.now() - 3600000),
90
+ healthCheck: 'unhealthy',
91
+ restartCount: 10,
92
+ node: 'node-1',
93
+ resources: { cpu: 0, memory: 0, memoryLimit: 1024, networkRx: 0, networkTx: 0 },
94
+ },
95
+ ],
96
+ createdAt: new Date(Date.now() - 86400000),
97
+ updatedAt: new Date(Date.now() - 3600000),
98
+ },
99
+ ...defaultOrchestratorServices,
100
+ ]
101
+
102
+ return (
103
+ <div className="p-6">
104
+ <ContainerOrchestrator
105
+ services={servicesWithFailure}
106
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
107
+ onRestartService={(service) => console.log('Restart:', service.name)}
108
+ onDeleteService={(service) => console.log('Delete:', service.name)}
109
+ onRefresh={() => console.log('Refresh')}
110
+ />
111
+ </div>
112
+ )
113
+ },
114
+ }
115
+
116
+ export const Updating: Story = {
117
+ render: () => {
118
+ const updatingServices: OrchestratorService[] = [
119
+ {
120
+ ...defaultOrchestratorServices[0],
121
+ status: 'updating',
122
+ updateStatus: {
123
+ state: 'updating',
124
+ progress: 67,
125
+ message: 'Rolling update: 2/3 replicas updated',
126
+ },
127
+ replicas: { desired: 3, running: 3, ready: 2 },
128
+ },
129
+ {
130
+ ...defaultOrchestratorServices[1],
131
+ status: 'updating',
132
+ updateStatus: {
133
+ state: 'updating',
134
+ progress: 25,
135
+ message: 'Pulling new image...',
136
+ },
137
+ },
138
+ ...defaultOrchestratorServices.slice(2),
139
+ ]
140
+
141
+ return (
142
+ <div className="p-6">
143
+ <ContainerOrchestrator
144
+ services={updatingServices}
145
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
146
+ onRefresh={() => console.log('Refresh')}
147
+ />
148
+ </div>
149
+ )
150
+ },
151
+ }
152
+
153
+ export const HighResourceUsage: Story = {
154
+ render: () => {
155
+ const highResourceServices: OrchestratorService[] = defaultOrchestratorServices.map(service => ({
156
+ ...service,
157
+ containers: service.containers.map(c => ({
158
+ ...c,
159
+ resources: {
160
+ cpu: 75 + Math.random() * 20,
161
+ memory: 800 + Math.random() * 200,
162
+ memoryLimit: 1024,
163
+ networkRx: Math.floor(Math.random() * 5000000),
164
+ networkTx: Math.floor(Math.random() * 2500000),
165
+ },
166
+ })),
167
+ }))
168
+
169
+ return (
170
+ <div className="p-6">
171
+ <ContainerOrchestrator
172
+ services={highResourceServices}
173
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
174
+ onRefresh={() => console.log('Refresh')}
175
+ />
176
+ </div>
177
+ )
178
+ },
179
+ }
180
+
181
+ export const ManyServices: Story = {
182
+ render: () => {
183
+ const generateService = (index: number): OrchestratorService => ({
184
+ id: `service-${index}`,
185
+ name: `service-${index}`,
186
+ image: `myregistry/service-${index}:latest`,
187
+ status: (['running', 'running', 'running', 'updating', 'failed'] as ServiceStatus[])[index % 5],
188
+ replicas: {
189
+ desired: (index % 3) + 1,
190
+ running: (index % 3) + 1,
191
+ ready: (index % 3) + 1,
192
+ },
193
+ containers: Array.from({ length: (index % 3) + 1 }, (_, i) => ({
194
+ id: `service-${index}-container-${i}`,
195
+ name: `service-${index}-${i}`,
196
+ image: `myregistry/service-${index}:latest`,
197
+ status: 'running' as const,
198
+ createdAt: new Date(Date.now() - index * 3600000),
199
+ startedAt: new Date(Date.now() - index * 3600000 + 60000),
200
+ healthCheck: 'healthy' as const,
201
+ node: `node-${(i % 3) + 1}`,
202
+ resources: {
203
+ cpu: 20 + Math.random() * 40,
204
+ memory: 200 + Math.random() * 300,
205
+ memoryLimit: 1024,
206
+ networkRx: Math.floor(Math.random() * 1000000),
207
+ networkTx: Math.floor(Math.random() * 500000),
208
+ },
209
+ })),
210
+ ports: [{ published: 8080 + index, target: 8080 }],
211
+ createdAt: new Date(Date.now() - index * 86400000),
212
+ updatedAt: new Date(Date.now() - index * 3600000),
213
+ })
214
+
215
+ const manyServices = Array.from({ length: 15 }, (_, i) => generateService(i))
216
+
217
+ return (
218
+ <div className="p-6">
219
+ <ContainerOrchestrator
220
+ services={manyServices}
221
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
222
+ onRefresh={() => console.log('Refresh')}
223
+ />
224
+ </div>
225
+ )
226
+ },
227
+ }
228
+
229
+ export const Empty: Story = {
230
+ render: () => (
231
+ <div className="p-6">
232
+ <ContainerOrchestrator
233
+ services={[]}
234
+ onRefresh={() => console.log('Refresh')}
235
+ />
236
+ </div>
237
+ ),
238
+ }
239
+
240
+ export const Interactive: Story = {
241
+ render: () => {
242
+ const [services, setServices] = React.useState(defaultOrchestratorServices)
243
+
244
+ const handleScale = (service: OrchestratorService, replicas: number) => {
245
+ setServices(prev =>
246
+ prev.map(s =>
247
+ s.id === service.id
248
+ ? {
249
+ ...s,
250
+ status: 'scaled' as ServiceStatus,
251
+ replicas: { ...s.replicas, desired: replicas },
252
+ }
253
+ : s
254
+ )
255
+ )
256
+
257
+ // Simulate scaling completion
258
+ setTimeout(() => {
259
+ setServices(prev =>
260
+ prev.map(s =>
261
+ s.id === service.id
262
+ ? {
263
+ ...s,
264
+ status: 'running' as ServiceStatus,
265
+ replicas: { desired: replicas, running: replicas, ready: replicas },
266
+ }
267
+ : s
268
+ )
269
+ )
270
+ }, 2000)
271
+ }
272
+
273
+ const handleRestart = (service: OrchestratorService) => {
274
+ setServices(prev =>
275
+ prev.map(s =>
276
+ s.id === service.id
277
+ ? {
278
+ ...s,
279
+ containers: s.containers.map(c => ({
280
+ ...c,
281
+ status: 'restarting' as const,
282
+ })),
283
+ }
284
+ : s
285
+ )
286
+ )
287
+
288
+ setTimeout(() => {
289
+ setServices(prev =>
290
+ prev.map(s =>
291
+ s.id === service.id
292
+ ? {
293
+ ...s,
294
+ containers: s.containers.map(c => ({
295
+ ...c,
296
+ status: 'running' as const,
297
+ startedAt: new Date(),
298
+ restartCount: (c.restartCount || 0) + 1,
299
+ })),
300
+ }
301
+ : s
302
+ )
303
+ )
304
+ }, 3000)
305
+ }
306
+
307
+ const handleDelete = (service: OrchestratorService) => {
308
+ if (confirm(`Delete service ${service.name}?`)) {
309
+ setServices(prev => prev.filter(s => s.id !== service.id))
310
+ }
311
+ }
312
+
313
+ return (
314
+ <div className="p-6">
315
+ <ContainerOrchestrator
316
+ services={services}
317
+ onScaleService={handleScale}
318
+ onRestartService={handleRestart}
319
+ onStopService={(service) => console.log('Stop:', service.name)}
320
+ onDeleteService={handleDelete}
321
+ onViewLogs={(container) => alert(`Viewing logs for ${container.name}`)}
322
+ onExecShell={(container) => alert(`Opening shell for ${container.name}`)}
323
+ onRefresh={() => setServices([...defaultOrchestratorServices])}
324
+ />
325
+ </div>
326
+ )
327
+ },
328
+ }
329
+
330
+ export const KubernetesDashboard: Story = {
331
+ render: () => (
332
+ <div className="min-h-screen bg-muted/30">
333
+ <header className="bg-background border-b px-6 py-4">
334
+ <div className="flex items-center justify-between">
335
+ <div>
336
+ <h1 className="font-bold text-xl">Kubernetes Dashboard</h1>
337
+ <p className="text-sm text-muted-foreground">Cluster: production-us-east-1</p>
338
+ </div>
339
+ <nav className="flex gap-4 text-sm">
340
+ <a href="#" className="text-foreground font-medium">Workloads</a>
341
+ <a href="#" className="text-muted-foreground hover:text-foreground">Services</a>
342
+ <a href="#" className="text-muted-foreground hover:text-foreground">Config</a>
343
+ <a href="#" className="text-muted-foreground hover:text-foreground">Storage</a>
344
+ <a href="#" className="text-muted-foreground hover:text-foreground">Cluster</a>
345
+ </nav>
346
+ </div>
347
+ </header>
348
+ <main className="p-6">
349
+ <ContainerOrchestrator
350
+ services={defaultOrchestratorServices}
351
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
352
+ onRestartService={(service) => console.log('Restart:', service.name)}
353
+ onStopService={(service) => console.log('Stop:', service.name)}
354
+ onDeleteService={(service) => console.log('Delete:', service.name)}
355
+ onViewLogs={(container) => console.log('Logs:', container.name)}
356
+ onExecShell={(container) => console.log('Shell:', container.name)}
357
+ onRefresh={() => console.log('Refresh')}
358
+ />
359
+ </main>
360
+ </div>
361
+ ),
362
+ }
363
+
364
+ export const DockerSwarm: Story = {
365
+ render: () => {
366
+ const swarmServices: OrchestratorService[] = [
367
+ {
368
+ id: 'web',
369
+ name: 'web',
370
+ image: 'nginx:alpine',
371
+ status: 'running',
372
+ replicas: { desired: 5, running: 5, ready: 5 },
373
+ containers: Array.from({ length: 5 }, (_, i) => ({
374
+ id: `web-${i}`,
375
+ name: `web.${i + 1}`,
376
+ image: 'nginx:alpine',
377
+ status: 'running' as const,
378
+ createdAt: new Date(Date.now() - 86400000),
379
+ startedAt: new Date(Date.now() - 86400000),
380
+ healthCheck: 'healthy' as const,
381
+ node: `swarm-node-${(i % 3) + 1}`,
382
+ resources: {
383
+ cpu: 5 + Math.random() * 10,
384
+ memory: 50 + Math.random() * 50,
385
+ memoryLimit: 256,
386
+ networkRx: Math.floor(Math.random() * 500000),
387
+ networkTx: Math.floor(Math.random() * 250000),
388
+ },
389
+ })),
390
+ ports: [{ published: 80, target: 80 }, { published: 443, target: 443 }],
391
+ createdAt: new Date(Date.now() - 7 * 86400000),
392
+ updatedAt: new Date(Date.now() - 86400000),
393
+ },
394
+ {
395
+ id: 'api',
396
+ name: 'api',
397
+ image: 'myapp/api:v2.0',
398
+ status: 'running',
399
+ replicas: { desired: 3, running: 3, ready: 3 },
400
+ containers: Array.from({ length: 3 }, (_, i) => ({
401
+ id: `api-${i}`,
402
+ name: `api.${i + 1}`,
403
+ image: 'myapp/api:v2.0',
404
+ status: 'running' as const,
405
+ createdAt: new Date(Date.now() - 172800000),
406
+ startedAt: new Date(Date.now() - 172800000),
407
+ healthCheck: 'healthy' as const,
408
+ node: `swarm-node-${(i % 3) + 1}`,
409
+ resources: {
410
+ cpu: 25 + Math.random() * 20,
411
+ memory: 256 + Math.random() * 128,
412
+ memoryLimit: 512,
413
+ networkRx: Math.floor(Math.random() * 1000000),
414
+ networkTx: Math.floor(Math.random() * 500000),
415
+ },
416
+ })),
417
+ ports: [{ published: 8080, target: 8080 }],
418
+ createdAt: new Date(Date.now() - 14 * 86400000),
419
+ updatedAt: new Date(Date.now() - 172800000),
420
+ },
421
+ {
422
+ id: 'redis',
423
+ name: 'redis',
424
+ image: 'redis:7-alpine',
425
+ status: 'running',
426
+ replicas: { desired: 1, running: 1, ready: 1 },
427
+ containers: [{
428
+ id: 'redis-1',
429
+ name: 'redis.1',
430
+ image: 'redis:7-alpine',
431
+ status: 'running' as const,
432
+ createdAt: new Date(Date.now() - 259200000),
433
+ startedAt: new Date(Date.now() - 259200000),
434
+ healthCheck: 'healthy' as const,
435
+ node: 'swarm-node-1',
436
+ resources: {
437
+ cpu: 8,
438
+ memory: 180,
439
+ memoryLimit: 512,
440
+ networkRx: 250000,
441
+ networkTx: 125000,
442
+ },
443
+ }],
444
+ ports: [{ published: 6379, target: 6379 }],
445
+ createdAt: new Date(Date.now() - 30 * 86400000),
446
+ updatedAt: new Date(Date.now() - 259200000),
447
+ },
448
+ ]
449
+
450
+ return (
451
+ <div className="p-6">
452
+ <ContainerOrchestrator
453
+ services={swarmServices}
454
+ onScaleService={(service, replicas) => console.log('Scale:', service.name, replicas)}
455
+ onRestartService={(service) => console.log('Restart:', service.name)}
456
+ onRefresh={() => console.log('Refresh')}
457
+ />
458
+ </div>
459
+ )
460
+ },
461
+ }