@wakastellar/ui 2.1.1 → 2.1.2
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/blocks/auth-2fa/index.d.ts +38 -0
- package/dist/blocks/chat-interface/index.d.ts +66 -0
- package/dist/blocks/checkout-flow/index.d.ts +76 -0
- package/dist/blocks/dashboard-kpi/index.d.ts +69 -0
- package/dist/blocks/deployment-dashboard/index.d.ts +68 -0
- package/dist/blocks/index.d.ts +7 -0
- package/dist/blocks/player-profile/index.d.ts +78 -0
- package/dist/index.cjs.js +136 -134
- package/dist/index.es.js +17304 -15120
- package/package.json +1 -1
- package/src/blocks/auth-2fa/index.tsx +655 -0
- package/src/blocks/chat-interface/index.tsx +611 -0
- package/src/blocks/checkout-flow/index.tsx +771 -0
- package/src/blocks/dashboard-kpi/index.tsx +424 -0
- package/src/blocks/deployment-dashboard/index.tsx +609 -0
- package/src/blocks/index.ts +24 -0
- package/src/blocks/player-profile/index.tsx +541 -0
- package/src/components/language-selector/index.tsx +21 -11
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cn } from "../../utils"
|
|
5
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/card"
|
|
6
|
+
import { Button } from "../../components/button"
|
|
7
|
+
import { Badge } from "../../components/badge"
|
|
8
|
+
import { Progress } from "../../components/progress"
|
|
9
|
+
import { Avatar, AvatarFallback, AvatarImage } from "../../components/avatar"
|
|
10
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../components/tabs"
|
|
11
|
+
import { Separator } from "../../components/separator"
|
|
12
|
+
import {
|
|
13
|
+
Select,
|
|
14
|
+
SelectContent,
|
|
15
|
+
SelectItem,
|
|
16
|
+
SelectTrigger,
|
|
17
|
+
SelectValue,
|
|
18
|
+
} from "../../components/select"
|
|
19
|
+
import {
|
|
20
|
+
Rocket,
|
|
21
|
+
GitBranch,
|
|
22
|
+
GitCommit,
|
|
23
|
+
GitMerge,
|
|
24
|
+
Clock,
|
|
25
|
+
CheckCircle,
|
|
26
|
+
XCircle,
|
|
27
|
+
AlertCircle,
|
|
28
|
+
Loader2,
|
|
29
|
+
Play,
|
|
30
|
+
Pause,
|
|
31
|
+
RotateCcw,
|
|
32
|
+
ExternalLink,
|
|
33
|
+
Terminal,
|
|
34
|
+
Server,
|
|
35
|
+
Globe,
|
|
36
|
+
Shield,
|
|
37
|
+
Activity,
|
|
38
|
+
ChevronRight,
|
|
39
|
+
RefreshCw,
|
|
40
|
+
Settings,
|
|
41
|
+
MoreVertical,
|
|
42
|
+
Zap,
|
|
43
|
+
Cloud,
|
|
44
|
+
Database,
|
|
45
|
+
} from "lucide-react"
|
|
46
|
+
|
|
47
|
+
// ============================================
|
|
48
|
+
// TYPES
|
|
49
|
+
// ============================================
|
|
50
|
+
|
|
51
|
+
export type DeploymentStatus = "pending" | "building" | "deploying" | "success" | "failed" | "cancelled" | "rollback"
|
|
52
|
+
export type Environment = "development" | "staging" | "production"
|
|
53
|
+
|
|
54
|
+
export interface Deployment {
|
|
55
|
+
id: string
|
|
56
|
+
status: DeploymentStatus
|
|
57
|
+
environment: Environment
|
|
58
|
+
branch: string
|
|
59
|
+
commit: string
|
|
60
|
+
commitMessage: string
|
|
61
|
+
author: {
|
|
62
|
+
name: string
|
|
63
|
+
avatar?: string
|
|
64
|
+
}
|
|
65
|
+
startedAt: Date | string
|
|
66
|
+
finishedAt?: Date | string
|
|
67
|
+
duration?: string
|
|
68
|
+
url?: string
|
|
69
|
+
logs?: string[]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface Pipeline {
|
|
73
|
+
id: string
|
|
74
|
+
name: string
|
|
75
|
+
status: DeploymentStatus
|
|
76
|
+
stages: PipelineStage[]
|
|
77
|
+
trigger: string
|
|
78
|
+
branch: string
|
|
79
|
+
startedAt: Date | string
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface PipelineStage {
|
|
83
|
+
id: string
|
|
84
|
+
name: string
|
|
85
|
+
status: DeploymentStatus
|
|
86
|
+
duration?: string
|
|
87
|
+
logs?: string[]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface EnvironmentStatus {
|
|
91
|
+
name: Environment
|
|
92
|
+
status: "healthy" | "degraded" | "down"
|
|
93
|
+
url: string
|
|
94
|
+
lastDeployment?: Deployment
|
|
95
|
+
uptime?: string
|
|
96
|
+
responseTime?: string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface DeploymentDashboardProps {
|
|
100
|
+
/** Recent deployments */
|
|
101
|
+
deployments?: Deployment[]
|
|
102
|
+
/** Active pipelines */
|
|
103
|
+
pipelines?: Pipeline[]
|
|
104
|
+
/** Environment statuses */
|
|
105
|
+
environments?: EnvironmentStatus[]
|
|
106
|
+
/** Handler for deploying */
|
|
107
|
+
onDeploy?: (environment: Environment, branch: string) => void
|
|
108
|
+
/** Handler for rollback */
|
|
109
|
+
onRollback?: (deploymentId: string) => void
|
|
110
|
+
/** Handler for cancelling */
|
|
111
|
+
onCancel?: (deploymentId: string) => void
|
|
112
|
+
/** Handler for retrying */
|
|
113
|
+
onRetry?: (deploymentId: string) => void
|
|
114
|
+
/** Available branches */
|
|
115
|
+
branches?: string[]
|
|
116
|
+
/** Custom className */
|
|
117
|
+
className?: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ============================================
|
|
121
|
+
// SUBCOMPONENTS
|
|
122
|
+
// ============================================
|
|
123
|
+
|
|
124
|
+
const statusConfig: Record<DeploymentStatus, { color: string; icon: React.ReactNode; label: string }> = {
|
|
125
|
+
pending: { color: "text-yellow-500 bg-yellow-500/10", icon: <Clock className="h-4 w-4" />, label: "Pending" },
|
|
126
|
+
building: { color: "text-blue-500 bg-blue-500/10", icon: <Loader2 className="h-4 w-4 animate-spin" />, label: "Building" },
|
|
127
|
+
deploying: { color: "text-purple-500 bg-purple-500/10", icon: <Rocket className="h-4 w-4 animate-pulse" />, label: "Deploying" },
|
|
128
|
+
success: { color: "text-green-500 bg-green-500/10", icon: <CheckCircle className="h-4 w-4" />, label: "Success" },
|
|
129
|
+
failed: { color: "text-red-500 bg-red-500/10", icon: <XCircle className="h-4 w-4" />, label: "Failed" },
|
|
130
|
+
cancelled: { color: "text-gray-500 bg-gray-500/10", icon: <XCircle className="h-4 w-4" />, label: "Cancelled" },
|
|
131
|
+
rollback: { color: "text-orange-500 bg-orange-500/10", icon: <RotateCcw className="h-4 w-4" />, label: "Rollback" },
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const environmentConfig: Record<Environment, { color: string; icon: React.ReactNode }> = {
|
|
135
|
+
development: { color: "text-blue-500 border-blue-500/30 bg-blue-500/10", icon: <Terminal className="h-4 w-4" /> },
|
|
136
|
+
staging: { color: "text-yellow-500 border-yellow-500/30 bg-yellow-500/10", icon: <Server className="h-4 w-4" /> },
|
|
137
|
+
production: { color: "text-green-500 border-green-500/30 bg-green-500/10", icon: <Globe className="h-4 w-4" /> },
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function StatusBadge({ status }: { status: DeploymentStatus }) {
|
|
141
|
+
const config = statusConfig[status]
|
|
142
|
+
return (
|
|
143
|
+
<Badge variant="outline" className={cn("gap-1", config.color)}>
|
|
144
|
+
{config.icon}
|
|
145
|
+
{config.label}
|
|
146
|
+
</Badge>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function EnvironmentBadge({ environment }: { environment: Environment }) {
|
|
151
|
+
const config = environmentConfig[environment]
|
|
152
|
+
return (
|
|
153
|
+
<Badge variant="outline" className={cn("gap-1 capitalize", config.color)}>
|
|
154
|
+
{config.icon}
|
|
155
|
+
{environment}
|
|
156
|
+
</Badge>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function DeploymentCard({
|
|
161
|
+
deployment,
|
|
162
|
+
onRollback,
|
|
163
|
+
onCancel,
|
|
164
|
+
onRetry,
|
|
165
|
+
}: {
|
|
166
|
+
deployment: Deployment
|
|
167
|
+
onRollback?: () => void
|
|
168
|
+
onCancel?: () => void
|
|
169
|
+
onRetry?: () => void
|
|
170
|
+
}) {
|
|
171
|
+
const isInProgress = deployment.status === "building" || deployment.status === "deploying"
|
|
172
|
+
const canRollback = deployment.status === "success" && deployment.environment === "production"
|
|
173
|
+
const canRetry = deployment.status === "failed"
|
|
174
|
+
const canCancel = isInProgress
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div className="p-4 rounded-lg border bg-card hover:bg-muted/50 transition-colors">
|
|
178
|
+
<div className="flex items-start justify-between gap-4">
|
|
179
|
+
<div className="flex items-start gap-3">
|
|
180
|
+
<Avatar className="h-10 w-10">
|
|
181
|
+
<AvatarImage src={deployment.author.avatar} />
|
|
182
|
+
<AvatarFallback>{deployment.author.name.slice(0, 2).toUpperCase()}</AvatarFallback>
|
|
183
|
+
</Avatar>
|
|
184
|
+
<div>
|
|
185
|
+
<div className="flex items-center gap-2 flex-wrap">
|
|
186
|
+
<StatusBadge status={deployment.status} />
|
|
187
|
+
<EnvironmentBadge environment={deployment.environment} />
|
|
188
|
+
</div>
|
|
189
|
+
<p className="text-sm mt-1 line-clamp-1">{deployment.commitMessage}</p>
|
|
190
|
+
<div className="flex items-center gap-3 mt-2 text-xs text-muted-foreground">
|
|
191
|
+
<span className="flex items-center gap-1">
|
|
192
|
+
<GitBranch className="h-3 w-3" />
|
|
193
|
+
{deployment.branch}
|
|
194
|
+
</span>
|
|
195
|
+
<span className="flex items-center gap-1">
|
|
196
|
+
<GitCommit className="h-3 w-3" />
|
|
197
|
+
{deployment.commit.slice(0, 7)}
|
|
198
|
+
</span>
|
|
199
|
+
<span className="flex items-center gap-1">
|
|
200
|
+
<Clock className="h-3 w-3" />
|
|
201
|
+
{typeof deployment.startedAt === "string"
|
|
202
|
+
? deployment.startedAt
|
|
203
|
+
: formatRelativeTime(deployment.startedAt)}
|
|
204
|
+
</span>
|
|
205
|
+
{deployment.duration && <span>{deployment.duration}</span>}
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<div className="flex items-center gap-1">
|
|
211
|
+
{deployment.url && (
|
|
212
|
+
<Button variant="ghost" size="icon" asChild>
|
|
213
|
+
<a href={deployment.url} target="_blank" rel="noopener noreferrer">
|
|
214
|
+
<ExternalLink className="h-4 w-4" />
|
|
215
|
+
</a>
|
|
216
|
+
</Button>
|
|
217
|
+
)}
|
|
218
|
+
{canCancel && (
|
|
219
|
+
<Button variant="ghost" size="icon" onClick={onCancel}>
|
|
220
|
+
<Pause className="h-4 w-4" />
|
|
221
|
+
</Button>
|
|
222
|
+
)}
|
|
223
|
+
{canRetry && (
|
|
224
|
+
<Button variant="ghost" size="icon" onClick={onRetry}>
|
|
225
|
+
<RefreshCw className="h-4 w-4" />
|
|
226
|
+
</Button>
|
|
227
|
+
)}
|
|
228
|
+
{canRollback && (
|
|
229
|
+
<Button variant="ghost" size="icon" onClick={onRollback}>
|
|
230
|
+
<RotateCcw className="h-4 w-4" />
|
|
231
|
+
</Button>
|
|
232
|
+
)}
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function PipelineCard({ pipeline }: { pipeline: Pipeline }) {
|
|
240
|
+
const completedStages = pipeline.stages.filter((s) => s.status === "success").length
|
|
241
|
+
const progress = (completedStages / pipeline.stages.length) * 100
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<Card>
|
|
245
|
+
<CardHeader className="pb-2">
|
|
246
|
+
<div className="flex items-center justify-between">
|
|
247
|
+
<div className="flex items-center gap-2">
|
|
248
|
+
<StatusBadge status={pipeline.status} />
|
|
249
|
+
<span className="font-medium">{pipeline.name}</span>
|
|
250
|
+
</div>
|
|
251
|
+
<span className="text-xs text-muted-foreground">
|
|
252
|
+
{typeof pipeline.startedAt === "string"
|
|
253
|
+
? pipeline.startedAt
|
|
254
|
+
: formatRelativeTime(pipeline.startedAt)}
|
|
255
|
+
</span>
|
|
256
|
+
</div>
|
|
257
|
+
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
258
|
+
<GitBranch className="h-3 w-3" />
|
|
259
|
+
{pipeline.branch}
|
|
260
|
+
<span className="mx-1">•</span>
|
|
261
|
+
Triggered by {pipeline.trigger}
|
|
262
|
+
</div>
|
|
263
|
+
</CardHeader>
|
|
264
|
+
<CardContent>
|
|
265
|
+
<div className="space-y-3">
|
|
266
|
+
<Progress value={progress} className="h-2" />
|
|
267
|
+
<div className="flex items-center justify-between">
|
|
268
|
+
{pipeline.stages.map((stage, index) => (
|
|
269
|
+
<React.Fragment key={stage.id}>
|
|
270
|
+
<div className="flex flex-col items-center gap-1">
|
|
271
|
+
<div
|
|
272
|
+
className={cn(
|
|
273
|
+
"h-8 w-8 rounded-full flex items-center justify-center",
|
|
274
|
+
statusConfig[stage.status].color
|
|
275
|
+
)}
|
|
276
|
+
>
|
|
277
|
+
{statusConfig[stage.status].icon}
|
|
278
|
+
</div>
|
|
279
|
+
<span className="text-xs">{stage.name}</span>
|
|
280
|
+
{stage.duration && (
|
|
281
|
+
<span className="text-xs text-muted-foreground">{stage.duration}</span>
|
|
282
|
+
)}
|
|
283
|
+
</div>
|
|
284
|
+
{index < pipeline.stages.length - 1 && (
|
|
285
|
+
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
|
286
|
+
)}
|
|
287
|
+
</React.Fragment>
|
|
288
|
+
))}
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
</CardContent>
|
|
292
|
+
</Card>
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function EnvironmentCard({ env }: { env: EnvironmentStatus }) {
|
|
297
|
+
const healthColors = {
|
|
298
|
+
healthy: "text-green-500",
|
|
299
|
+
degraded: "text-yellow-500",
|
|
300
|
+
down: "text-red-500",
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const healthIcons = {
|
|
304
|
+
healthy: <CheckCircle className="h-5 w-5" />,
|
|
305
|
+
degraded: <AlertCircle className="h-5 w-5" />,
|
|
306
|
+
down: <XCircle className="h-5 w-5" />,
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return (
|
|
310
|
+
<Card>
|
|
311
|
+
<CardHeader className="pb-2">
|
|
312
|
+
<div className="flex items-center justify-between">
|
|
313
|
+
<CardTitle className="capitalize flex items-center gap-2">
|
|
314
|
+
{environmentConfig[env.name].icon}
|
|
315
|
+
{env.name}
|
|
316
|
+
</CardTitle>
|
|
317
|
+
<div className={cn("flex items-center gap-1", healthColors[env.status])}>
|
|
318
|
+
{healthIcons[env.status]}
|
|
319
|
+
<span className="text-sm capitalize">{env.status}</span>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
</CardHeader>
|
|
323
|
+
<CardContent className="space-y-4">
|
|
324
|
+
<div className="flex items-center gap-2 text-sm">
|
|
325
|
+
<ExternalLink className="h-4 w-4 text-muted-foreground" />
|
|
326
|
+
<a
|
|
327
|
+
href={env.url}
|
|
328
|
+
target="_blank"
|
|
329
|
+
rel="noopener noreferrer"
|
|
330
|
+
className="text-primary hover:underline truncate"
|
|
331
|
+
>
|
|
332
|
+
{env.url}
|
|
333
|
+
</a>
|
|
334
|
+
</div>
|
|
335
|
+
|
|
336
|
+
<div className="grid grid-cols-2 gap-4 text-sm">
|
|
337
|
+
{env.uptime && (
|
|
338
|
+
<div>
|
|
339
|
+
<p className="text-muted-foreground">Uptime</p>
|
|
340
|
+
<p className="font-medium">{env.uptime}</p>
|
|
341
|
+
</div>
|
|
342
|
+
)}
|
|
343
|
+
{env.responseTime && (
|
|
344
|
+
<div>
|
|
345
|
+
<p className="text-muted-foreground">Response Time</p>
|
|
346
|
+
<p className="font-medium">{env.responseTime}</p>
|
|
347
|
+
</div>
|
|
348
|
+
)}
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
{env.lastDeployment && (
|
|
352
|
+
<div className="pt-2 border-t">
|
|
353
|
+
<p className="text-xs text-muted-foreground mb-1">Last Deployment</p>
|
|
354
|
+
<div className="flex items-center gap-2 text-sm">
|
|
355
|
+
<StatusBadge status={env.lastDeployment.status} />
|
|
356
|
+
<span className="text-muted-foreground">
|
|
357
|
+
{typeof env.lastDeployment.startedAt === "string"
|
|
358
|
+
? env.lastDeployment.startedAt
|
|
359
|
+
: formatRelativeTime(env.lastDeployment.startedAt)}
|
|
360
|
+
</span>
|
|
361
|
+
</div>
|
|
362
|
+
</div>
|
|
363
|
+
)}
|
|
364
|
+
</CardContent>
|
|
365
|
+
</Card>
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function formatRelativeTime(date: Date): string {
|
|
370
|
+
const now = new Date()
|
|
371
|
+
const diff = now.getTime() - date.getTime()
|
|
372
|
+
const minutes = Math.floor(diff / 60000)
|
|
373
|
+
const hours = Math.floor(minutes / 60)
|
|
374
|
+
const days = Math.floor(hours / 24)
|
|
375
|
+
|
|
376
|
+
if (minutes < 1) return "just now"
|
|
377
|
+
if (minutes < 60) return `${minutes}m ago`
|
|
378
|
+
if (hours < 24) return `${hours}h ago`
|
|
379
|
+
return `${days}d ago`
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// ============================================
|
|
383
|
+
// MAIN COMPONENT
|
|
384
|
+
// ============================================
|
|
385
|
+
|
|
386
|
+
export function DeploymentDashboard({
|
|
387
|
+
deployments = [],
|
|
388
|
+
pipelines = [],
|
|
389
|
+
environments = [],
|
|
390
|
+
onDeploy,
|
|
391
|
+
onRollback,
|
|
392
|
+
onCancel,
|
|
393
|
+
onRetry,
|
|
394
|
+
branches = ["main", "develop", "staging"],
|
|
395
|
+
className,
|
|
396
|
+
}: DeploymentDashboardProps) {
|
|
397
|
+
const [selectedBranch, setSelectedBranch] = React.useState(branches[0])
|
|
398
|
+
const [selectedEnvironment, setSelectedEnvironment] = React.useState<Environment>("staging")
|
|
399
|
+
|
|
400
|
+
const activeDeployments = deployments.filter(
|
|
401
|
+
(d) => d.status === "building" || d.status === "deploying"
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
return (
|
|
405
|
+
<div className={cn("space-y-6", className)}>
|
|
406
|
+
{/* Header */}
|
|
407
|
+
<div className="flex flex-col sm:flex-row gap-4 justify-between">
|
|
408
|
+
<div>
|
|
409
|
+
<h1 className="text-2xl font-bold">Deployments</h1>
|
|
410
|
+
<p className="text-muted-foreground">Manage and monitor your deployments</p>
|
|
411
|
+
</div>
|
|
412
|
+
<div className="flex items-center gap-2">
|
|
413
|
+
<Select value={selectedBranch} onValueChange={setSelectedBranch}>
|
|
414
|
+
<SelectTrigger className="w-[160px]">
|
|
415
|
+
<GitBranch className="h-4 w-4 mr-2" />
|
|
416
|
+
<SelectValue />
|
|
417
|
+
</SelectTrigger>
|
|
418
|
+
<SelectContent>
|
|
419
|
+
{branches.map((branch) => (
|
|
420
|
+
<SelectItem key={branch} value={branch}>
|
|
421
|
+
{branch}
|
|
422
|
+
</SelectItem>
|
|
423
|
+
))}
|
|
424
|
+
</SelectContent>
|
|
425
|
+
</Select>
|
|
426
|
+
<Select value={selectedEnvironment} onValueChange={(v) => setSelectedEnvironment(v as Environment)}>
|
|
427
|
+
<SelectTrigger className="w-[160px]">
|
|
428
|
+
<Server className="h-4 w-4 mr-2" />
|
|
429
|
+
<SelectValue />
|
|
430
|
+
</SelectTrigger>
|
|
431
|
+
<SelectContent>
|
|
432
|
+
<SelectItem value="development">Development</SelectItem>
|
|
433
|
+
<SelectItem value="staging">Staging</SelectItem>
|
|
434
|
+
<SelectItem value="production">Production</SelectItem>
|
|
435
|
+
</SelectContent>
|
|
436
|
+
</Select>
|
|
437
|
+
<Button onClick={() => onDeploy?.(selectedEnvironment, selectedBranch)}>
|
|
438
|
+
<Rocket className="h-4 w-4 mr-2" />
|
|
439
|
+
Deploy
|
|
440
|
+
</Button>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
|
|
444
|
+
{/* Active Deployments Alert */}
|
|
445
|
+
{activeDeployments.length > 0 && (
|
|
446
|
+
<Card className="border-blue-500/50 bg-blue-500/5">
|
|
447
|
+
<CardContent className="py-4">
|
|
448
|
+
<div className="flex items-center gap-3">
|
|
449
|
+
<div className="h-10 w-10 rounded-full bg-blue-500/10 flex items-center justify-center">
|
|
450
|
+
<Rocket className="h-5 w-5 text-blue-500 animate-pulse" />
|
|
451
|
+
</div>
|
|
452
|
+
<div>
|
|
453
|
+
<p className="font-medium">
|
|
454
|
+
{activeDeployments.length} deployment{activeDeployments.length > 1 ? "s" : ""} in progress
|
|
455
|
+
</p>
|
|
456
|
+
<p className="text-sm text-muted-foreground">
|
|
457
|
+
{activeDeployments.map((d) => d.environment).join(", ")}
|
|
458
|
+
</p>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
</CardContent>
|
|
462
|
+
</Card>
|
|
463
|
+
)}
|
|
464
|
+
|
|
465
|
+
{/* Environments Grid */}
|
|
466
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
467
|
+
{environments.map((env) => (
|
|
468
|
+
<EnvironmentCard key={env.name} env={env} />
|
|
469
|
+
))}
|
|
470
|
+
</div>
|
|
471
|
+
|
|
472
|
+
{/* Tabs */}
|
|
473
|
+
<Tabs defaultValue="deployments" className="w-full">
|
|
474
|
+
<TabsList>
|
|
475
|
+
<TabsTrigger value="deployments">Recent Deployments</TabsTrigger>
|
|
476
|
+
<TabsTrigger value="pipelines">Pipelines</TabsTrigger>
|
|
477
|
+
</TabsList>
|
|
478
|
+
|
|
479
|
+
<TabsContent value="deployments" className="mt-4 space-y-3">
|
|
480
|
+
{deployments.length > 0 ? (
|
|
481
|
+
deployments.map((deployment) => (
|
|
482
|
+
<DeploymentCard
|
|
483
|
+
key={deployment.id}
|
|
484
|
+
deployment={deployment}
|
|
485
|
+
onRollback={() => onRollback?.(deployment.id)}
|
|
486
|
+
onCancel={() => onCancel?.(deployment.id)}
|
|
487
|
+
onRetry={() => onRetry?.(deployment.id)}
|
|
488
|
+
/>
|
|
489
|
+
))
|
|
490
|
+
) : (
|
|
491
|
+
<Card>
|
|
492
|
+
<CardContent className="py-12 text-center">
|
|
493
|
+
<Rocket className="h-12 w-12 mx-auto text-muted-foreground mb-4" />
|
|
494
|
+
<p className="text-muted-foreground">No deployments yet</p>
|
|
495
|
+
<p className="text-sm text-muted-foreground">
|
|
496
|
+
Deploy your first version to get started
|
|
497
|
+
</p>
|
|
498
|
+
</CardContent>
|
|
499
|
+
</Card>
|
|
500
|
+
)}
|
|
501
|
+
</TabsContent>
|
|
502
|
+
|
|
503
|
+
<TabsContent value="pipelines" className="mt-4 space-y-4">
|
|
504
|
+
{pipelines.length > 0 ? (
|
|
505
|
+
pipelines.map((pipeline) => (
|
|
506
|
+
<PipelineCard key={pipeline.id} pipeline={pipeline} />
|
|
507
|
+
))
|
|
508
|
+
) : (
|
|
509
|
+
<Card>
|
|
510
|
+
<CardContent className="py-12 text-center">
|
|
511
|
+
<Activity className="h-12 w-12 mx-auto text-muted-foreground mb-4" />
|
|
512
|
+
<p className="text-muted-foreground">No active pipelines</p>
|
|
513
|
+
<p className="text-sm text-muted-foreground">
|
|
514
|
+
Pipelines will appear here when triggered
|
|
515
|
+
</p>
|
|
516
|
+
</CardContent>
|
|
517
|
+
</Card>
|
|
518
|
+
)}
|
|
519
|
+
</TabsContent>
|
|
520
|
+
</Tabs>
|
|
521
|
+
</div>
|
|
522
|
+
)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// ============================================
|
|
526
|
+
// PRESET DATA
|
|
527
|
+
// ============================================
|
|
528
|
+
|
|
529
|
+
export const defaultDeployments: Deployment[] = [
|
|
530
|
+
{
|
|
531
|
+
id: "d1",
|
|
532
|
+
status: "success",
|
|
533
|
+
environment: "production",
|
|
534
|
+
branch: "main",
|
|
535
|
+
commit: "a1b2c3d4e5f6",
|
|
536
|
+
commitMessage: "feat: Add new dashboard component",
|
|
537
|
+
author: { name: "John Doe" },
|
|
538
|
+
startedAt: new Date(Date.now() - 3600000),
|
|
539
|
+
finishedAt: new Date(Date.now() - 3300000),
|
|
540
|
+
duration: "5m 12s",
|
|
541
|
+
url: "https://app.example.com",
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
id: "d2",
|
|
545
|
+
status: "building",
|
|
546
|
+
environment: "staging",
|
|
547
|
+
branch: "develop",
|
|
548
|
+
commit: "f6e5d4c3b2a1",
|
|
549
|
+
commitMessage: "fix: Resolve login issue",
|
|
550
|
+
author: { name: "Jane Smith" },
|
|
551
|
+
startedAt: new Date(Date.now() - 180000),
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
id: "d3",
|
|
555
|
+
status: "failed",
|
|
556
|
+
environment: "development",
|
|
557
|
+
branch: "feature/new-api",
|
|
558
|
+
commit: "1a2b3c4d5e6f",
|
|
559
|
+
commitMessage: "wip: New API endpoints",
|
|
560
|
+
author: { name: "Bob Wilson" },
|
|
561
|
+
startedAt: new Date(Date.now() - 7200000),
|
|
562
|
+
finishedAt: new Date(Date.now() - 7000000),
|
|
563
|
+
duration: "3m 20s",
|
|
564
|
+
},
|
|
565
|
+
]
|
|
566
|
+
|
|
567
|
+
export const defaultPipelines: Pipeline[] = [
|
|
568
|
+
{
|
|
569
|
+
id: "p1",
|
|
570
|
+
name: "CI/CD Pipeline",
|
|
571
|
+
status: "building",
|
|
572
|
+
trigger: "push to main",
|
|
573
|
+
branch: "main",
|
|
574
|
+
startedAt: new Date(Date.now() - 300000),
|
|
575
|
+
stages: [
|
|
576
|
+
{ id: "s1", name: "Build", status: "success", duration: "1m 30s" },
|
|
577
|
+
{ id: "s2", name: "Test", status: "success", duration: "2m 45s" },
|
|
578
|
+
{ id: "s3", name: "Deploy", status: "building" },
|
|
579
|
+
{ id: "s4", name: "Verify", status: "pending" },
|
|
580
|
+
],
|
|
581
|
+
},
|
|
582
|
+
]
|
|
583
|
+
|
|
584
|
+
export const defaultEnvironments: EnvironmentStatus[] = [
|
|
585
|
+
{
|
|
586
|
+
name: "production",
|
|
587
|
+
status: "healthy",
|
|
588
|
+
url: "https://app.example.com",
|
|
589
|
+
uptime: "99.9%",
|
|
590
|
+
responseTime: "120ms",
|
|
591
|
+
lastDeployment: defaultDeployments[0],
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
name: "staging",
|
|
595
|
+
status: "degraded",
|
|
596
|
+
url: "https://staging.example.com",
|
|
597
|
+
uptime: "98.5%",
|
|
598
|
+
responseTime: "250ms",
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
name: "development",
|
|
602
|
+
status: "healthy",
|
|
603
|
+
url: "https://dev.example.com",
|
|
604
|
+
uptime: "95.0%",
|
|
605
|
+
responseTime: "180ms",
|
|
606
|
+
},
|
|
607
|
+
]
|
|
608
|
+
|
|
609
|
+
export default DeploymentDashboard
|
package/src/blocks/index.ts
CHANGED
|
@@ -78,3 +78,27 @@ export * from './wizard'
|
|
|
78
78
|
// Theme & i18n
|
|
79
79
|
// export * from './theme-creator-block' // TODO: Refactor to match new theme-provider API
|
|
80
80
|
export * from './i18n-editor'
|
|
81
|
+
|
|
82
|
+
// New Blocks - KPI, E-commerce, Gaming, Security, Communication, DevOps
|
|
83
|
+
export * from './dashboard-kpi'
|
|
84
|
+
export * from './checkout-flow'
|
|
85
|
+
export * from './player-profile'
|
|
86
|
+
export * from './auth-2fa'
|
|
87
|
+
|
|
88
|
+
// Chat Interface - export with aliases to avoid conflicts with ./chat block
|
|
89
|
+
export {
|
|
90
|
+
ChatInterface,
|
|
91
|
+
defaultUsers as defaultChatInterfaceUsers,
|
|
92
|
+
defaultConversations as defaultChatInterfaceConversations,
|
|
93
|
+
defaultMessages as defaultChatInterfaceMessages,
|
|
94
|
+
} from './chat-interface'
|
|
95
|
+
export type {
|
|
96
|
+
ChatInterfaceProps,
|
|
97
|
+
ChatUser as ChatInterfaceUser,
|
|
98
|
+
ChatMessage as ChatInterfaceMessage,
|
|
99
|
+
ChatConversation as ChatInterfaceConversation,
|
|
100
|
+
ChatAttachment as ChatInterfaceAttachment,
|
|
101
|
+
ChatReaction as ChatInterfaceReaction,
|
|
102
|
+
} from './chat-interface'
|
|
103
|
+
|
|
104
|
+
export * from './deployment-dashboard'
|