@sudobility/devops-components-rn 1.0.0 → 1.0.1
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/AlertDialog.d.ts.map +1 -1
- package/dist/ApiPlayground.d.ts.map +1 -1
- package/dist/ApiReference.d.ts.map +1 -1
- package/dist/AuditLog.d.ts +26 -4
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/BodyMetrics.d.ts.map +1 -1
- package/dist/BuildLog.d.ts +16 -5
- package/dist/BuildLog.d.ts.map +1 -1
- package/dist/ChangelogDisplay.d.ts.map +1 -1
- package/dist/CodePlayground.d.ts.map +1 -1
- package/dist/ConflictResolver.d.ts.map +1 -1
- package/dist/DealPipeline.d.ts.map +1 -1
- package/dist/DeploymentStatus.d.ts +11 -4
- package/dist/DeploymentStatus.d.ts.map +1 -1
- package/dist/DriverLog.d.ts.map +1 -1
- package/dist/MemoryUsage.d.ts.map +1 -1
- package/dist/MetricsGrid.d.ts +12 -19
- package/dist/MetricsGrid.d.ts.map +1 -1
- package/dist/PipelineView.d.ts +21 -5
- package/dist/PipelineView.d.ts.map +1 -1
- package/dist/RegressionTest.d.ts.map +1 -1
- package/dist/SystemStatusIndicator.d.ts +9 -8
- package/dist/SystemStatusIndicator.d.ts.map +1 -1
- package/dist/TestResult.d.ts.map +1 -1
- package/dist/TestRunner.d.ts.map +1 -1
- package/dist/WebhookLogger.d.ts.map +1 -1
- package/dist/WorkflowBuilder.d.ts.map +1 -1
- package/dist/WorkflowTemplate.d.ts.map +1 -1
- package/dist/XmlParser.d.ts.map +1 -1
- package/dist/{index.cjs.js → index.cjs} +634 -614
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +6 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/{index.esm.js → index.mjs} +637 -617
- package/dist/index.mjs.map +1 -0
- package/package.json +8 -15
- package/src/AlertDialog.tsx +21 -16
- package/src/ApiPlayground.tsx +7 -3
- package/src/ApiReference.tsx +6 -2
- package/src/AuditLog.tsx +244 -21
- package/src/BodyMetrics.tsx +6 -2
- package/src/BuildLog.tsx +132 -26
- package/src/ChangelogDisplay.tsx +6 -2
- package/src/CodePlayground.tsx +7 -3
- package/src/ConflictResolver.tsx +7 -3
- package/src/DealPipeline.tsx +6 -2
- package/src/DeploymentStatus.tsx +159 -25
- package/src/DriverLog.tsx +4 -2
- package/src/MemoryUsage.tsx +6 -2
- package/src/MetricsGrid.tsx +99 -94
- package/src/PipelineView.tsx +225 -26
- package/src/RegressionTest.tsx +6 -2
- package/src/SystemStatusIndicator.tsx +70 -47
- package/src/TestResult.tsx +6 -2
- package/src/TestRunner.tsx +7 -3
- package/src/WebhookLogger.tsx +6 -2
- package/src/WorkflowBuilder.tsx +7 -3
- package/src/WorkflowTemplate.tsx +7 -3
- package/src/XmlParser.tsx +4 -2
- package/src/index.ts +41 -30
- package/src/nativewind.d.ts +3 -0
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.esm.js.map +0 -1
package/src/DeploymentStatus.tsx
CHANGED
|
@@ -1,32 +1,166 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Text, Pressable
|
|
3
|
-
import { cn } from '@sudobility/components-rn';
|
|
2
|
+
import { View, Text, Pressable } from 'react-native';
|
|
3
|
+
import { cn, Card } from '@sudobility/components-rn';
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
|
|
5
|
+
export type DeploymentState =
|
|
6
|
+
| 'pending'
|
|
7
|
+
| 'building'
|
|
8
|
+
| 'deploying'
|
|
9
|
+
| 'success'
|
|
10
|
+
| 'failed'
|
|
11
|
+
| 'cancelled';
|
|
12
|
+
|
|
13
|
+
export interface DeploymentStatusProps {
|
|
14
|
+
state: DeploymentState;
|
|
15
|
+
environment: string;
|
|
16
|
+
version: string;
|
|
17
|
+
timestamp: Date;
|
|
18
|
+
commitHash?: string;
|
|
19
|
+
commitMessage?: string;
|
|
20
|
+
duration?: number;
|
|
7
21
|
onPress?: () => void;
|
|
8
|
-
|
|
22
|
+
className?: string;
|
|
9
23
|
}
|
|
10
24
|
|
|
25
|
+
const stateConfig: Record<
|
|
26
|
+
DeploymentState,
|
|
27
|
+
{
|
|
28
|
+
color: string;
|
|
29
|
+
bgColor: string;
|
|
30
|
+
darkBgColor: string;
|
|
31
|
+
label: string;
|
|
32
|
+
icon: string;
|
|
33
|
+
}
|
|
34
|
+
> = {
|
|
35
|
+
pending: {
|
|
36
|
+
color: 'text-gray-600 dark:text-gray-400',
|
|
37
|
+
bgColor: 'bg-gray-100',
|
|
38
|
+
darkBgColor: 'dark:bg-gray-800',
|
|
39
|
+
label: 'Pending',
|
|
40
|
+
icon: '⏳',
|
|
41
|
+
},
|
|
42
|
+
building: {
|
|
43
|
+
color: 'text-blue-600 dark:text-blue-400',
|
|
44
|
+
bgColor: 'bg-blue-100',
|
|
45
|
+
darkBgColor: 'dark:bg-blue-900',
|
|
46
|
+
label: 'Building',
|
|
47
|
+
icon: '🔨',
|
|
48
|
+
},
|
|
49
|
+
deploying: {
|
|
50
|
+
color: 'text-purple-600 dark:text-purple-400',
|
|
51
|
+
bgColor: 'bg-purple-100',
|
|
52
|
+
darkBgColor: 'dark:bg-purple-900',
|
|
53
|
+
label: 'Deploying',
|
|
54
|
+
icon: '🚀',
|
|
55
|
+
},
|
|
56
|
+
success: {
|
|
57
|
+
color: 'text-green-600 dark:text-green-400',
|
|
58
|
+
bgColor: 'bg-green-100',
|
|
59
|
+
darkBgColor: 'dark:bg-green-900',
|
|
60
|
+
label: 'Success',
|
|
61
|
+
icon: '✓',
|
|
62
|
+
},
|
|
63
|
+
failed: {
|
|
64
|
+
color: 'text-red-600 dark:text-red-400',
|
|
65
|
+
bgColor: 'bg-red-100',
|
|
66
|
+
darkBgColor: 'dark:bg-red-900',
|
|
67
|
+
label: 'Failed',
|
|
68
|
+
icon: '✗',
|
|
69
|
+
},
|
|
70
|
+
cancelled: {
|
|
71
|
+
color: 'text-orange-600 dark:text-orange-400',
|
|
72
|
+
bgColor: 'bg-orange-100',
|
|
73
|
+
darkBgColor: 'dark:bg-orange-900',
|
|
74
|
+
label: 'Cancelled',
|
|
75
|
+
icon: '⊘',
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const formatDuration = (seconds: number): string => {
|
|
80
|
+
if (seconds < 60) return `${seconds}s`;
|
|
81
|
+
const minutes = Math.floor(seconds / 60);
|
|
82
|
+
const remainingSeconds = seconds % 60;
|
|
83
|
+
if (minutes < 60) return `${minutes}m ${remainingSeconds}s`;
|
|
84
|
+
const hours = Math.floor(minutes / 60);
|
|
85
|
+
const remainingMinutes = minutes % 60;
|
|
86
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
87
|
+
};
|
|
88
|
+
|
|
11
89
|
export const DeploymentStatus: React.FC<DeploymentStatusProps> = ({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
90
|
+
state,
|
|
91
|
+
environment,
|
|
92
|
+
version,
|
|
93
|
+
timestamp,
|
|
94
|
+
commitHash,
|
|
95
|
+
commitMessage,
|
|
96
|
+
duration,
|
|
15
97
|
onPress,
|
|
16
|
-
|
|
17
|
-
}) =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
98
|
+
className,
|
|
99
|
+
}) => {
|
|
100
|
+
const config = stateConfig[state];
|
|
101
|
+
|
|
102
|
+
const content = (
|
|
103
|
+
<Card className={cn('p-4', className)}>
|
|
104
|
+
<View className='flex-row items-start justify-between'>
|
|
105
|
+
<View className='flex-1'>
|
|
106
|
+
<View className='flex-row items-center'>
|
|
107
|
+
<View
|
|
108
|
+
className={cn(
|
|
109
|
+
'px-2 py-1 rounded-md mr-2',
|
|
110
|
+
config.bgColor,
|
|
111
|
+
config.darkBgColor
|
|
112
|
+
)}
|
|
113
|
+
>
|
|
114
|
+
<Text className={cn('text-xs font-medium', config.color)}>
|
|
115
|
+
{config.icon} {config.label}
|
|
116
|
+
</Text>
|
|
117
|
+
</View>
|
|
118
|
+
<View className='bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-md'>
|
|
119
|
+
<Text className='text-xs font-medium text-gray-700 dark:text-gray-300'>
|
|
120
|
+
{environment}
|
|
121
|
+
</Text>
|
|
122
|
+
</View>
|
|
123
|
+
</View>
|
|
124
|
+
<Text className='mt-2 text-base font-semibold text-gray-900 dark:text-gray-100'>
|
|
125
|
+
{version}
|
|
126
|
+
</Text>
|
|
127
|
+
{commitHash && (
|
|
128
|
+
<Text className='mt-1 text-sm font-mono text-gray-600 dark:text-gray-400'>
|
|
129
|
+
{commitHash.substring(0, 7)}
|
|
130
|
+
</Text>
|
|
131
|
+
)}
|
|
132
|
+
{commitMessage && (
|
|
133
|
+
<Text
|
|
134
|
+
className='mt-1 text-sm text-gray-600 dark:text-gray-400'
|
|
135
|
+
numberOfLines={2}
|
|
136
|
+
>
|
|
137
|
+
{commitMessage}
|
|
138
|
+
</Text>
|
|
139
|
+
)}
|
|
140
|
+
</View>
|
|
141
|
+
</View>
|
|
142
|
+
<View className='flex-row items-center justify-between mt-3 pt-3 border-t border-gray-200 dark:border-gray-700'>
|
|
143
|
+
<Text className='text-xs text-gray-500 dark:text-gray-500'>
|
|
144
|
+
{timestamp.toLocaleString()}
|
|
145
|
+
</Text>
|
|
146
|
+
{duration !== undefined && (
|
|
147
|
+
<Text className='text-xs text-gray-500 dark:text-gray-500'>
|
|
148
|
+
Duration: {formatDuration(duration)}
|
|
149
|
+
</Text>
|
|
150
|
+
)}
|
|
151
|
+
</View>
|
|
152
|
+
</Card>
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
if (onPress) {
|
|
156
|
+
return (
|
|
157
|
+
<Pressable onPress={onPress} accessibilityRole='button'>
|
|
158
|
+
{content}
|
|
159
|
+
</Pressable>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return content;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export default DeploymentStatus;
|
package/src/DriverLog.tsx
CHANGED
|
@@ -19,9 +19,11 @@ export const DriverLog: React.FC<DriverLogProps> = ({
|
|
|
19
19
|
disabled && 'opacity-50',
|
|
20
20
|
className
|
|
21
21
|
)}
|
|
22
|
-
accessibilityLabel=
|
|
22
|
+
accessibilityLabel='Driver Log'
|
|
23
23
|
{...props}
|
|
24
24
|
>
|
|
25
|
-
{children ||
|
|
25
|
+
{children || (
|
|
26
|
+
<Text className='text-gray-900 dark:text-white'>DriverLog Component</Text>
|
|
27
|
+
)}
|
|
26
28
|
</View>
|
|
27
29
|
);
|
package/src/MemoryUsage.tsx
CHANGED
|
@@ -19,9 +19,13 @@ export const MemoryUsage: React.FC<MemoryUsageProps> = ({
|
|
|
19
19
|
disabled && 'opacity-50',
|
|
20
20
|
className
|
|
21
21
|
)}
|
|
22
|
-
accessibilityLabel=
|
|
22
|
+
accessibilityLabel='Memory Usage'
|
|
23
23
|
{...props}
|
|
24
24
|
>
|
|
25
|
-
{children ||
|
|
25
|
+
{children || (
|
|
26
|
+
<Text className='text-gray-900 dark:text-white'>
|
|
27
|
+
MemoryUsage Component
|
|
28
|
+
</Text>
|
|
29
|
+
)}
|
|
26
30
|
</View>
|
|
27
31
|
);
|
package/src/MetricsGrid.tsx
CHANGED
|
@@ -1,115 +1,120 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { View, Text,
|
|
3
|
-
import { cn } from '@sudobility/components-rn';
|
|
2
|
+
import { View, Text, Pressable } from 'react-native';
|
|
3
|
+
import { cn, Card } from '@sudobility/components-rn';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export interface MetricItem {
|
|
8
|
-
value: string | number;
|
|
5
|
+
export interface Metric {
|
|
6
|
+
id: string;
|
|
9
7
|
label: string;
|
|
10
|
-
|
|
8
|
+
value: number | string;
|
|
9
|
+
unit?: string;
|
|
10
|
+
change?: number;
|
|
11
|
+
changeLabel?: string;
|
|
11
12
|
icon?: React.ReactNode;
|
|
12
|
-
trend?: {
|
|
13
|
-
direction: 'up' | 'down';
|
|
14
|
-
value: string;
|
|
15
|
-
};
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
export interface MetricsGridProps
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
export interface MetricsGridProps {
|
|
16
|
+
metrics: Metric[];
|
|
17
|
+
columns?: 1 | 2 | 3 | 4;
|
|
18
|
+
onMetricPress?: (metric: Metric) => void;
|
|
19
|
+
className?: string;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
purple: 'text-purple-600 dark:text-purple-400',
|
|
29
|
-
orange: 'text-orange-600 dark:text-orange-400',
|
|
30
|
-
pink: 'text-pink-600 dark:text-pink-400',
|
|
31
|
-
gray: 'text-gray-600 dark:text-gray-400',
|
|
22
|
+
const formatChange = (change: number): string => {
|
|
23
|
+
const sign = change >= 0 ? '+' : '';
|
|
24
|
+
return sign + change.toFixed(1) + '%';
|
|
32
25
|
};
|
|
33
26
|
|
|
34
|
-
interface MetricCardProps {
|
|
35
|
-
metric: MetricItem;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const MetricCard: React.FC<MetricCardProps> = ({ metric }) => {
|
|
39
|
-
const colorClass = metric.color ? colorClasses[metric.color] : colorClasses.blue;
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<View className="bg-white dark:bg-gray-800 rounded-xl p-6 border border-gray-200 dark:border-gray-700 items-center mb-4 mx-2">
|
|
43
|
-
{metric.icon && (
|
|
44
|
-
<View className={cn('mb-4', colorClass)}>{metric.icon}</View>
|
|
45
|
-
)}
|
|
46
|
-
|
|
47
|
-
<View className="gap-2 items-center">
|
|
48
|
-
<Text className={cn('text-3xl font-bold', colorClass)}>
|
|
49
|
-
{metric.value}
|
|
50
|
-
</Text>
|
|
51
|
-
|
|
52
|
-
<Text className="text-gray-600 dark:text-gray-400 font-medium">
|
|
53
|
-
{metric.label}
|
|
54
|
-
</Text>
|
|
55
|
-
|
|
56
|
-
{metric.trend && (
|
|
57
|
-
<Text
|
|
58
|
-
className={cn(
|
|
59
|
-
'text-sm font-semibold',
|
|
60
|
-
metric.trend.direction === 'up'
|
|
61
|
-
? 'text-green-600 dark:text-green-400'
|
|
62
|
-
: 'text-red-600 dark:text-red-400'
|
|
63
|
-
)}
|
|
64
|
-
>
|
|
65
|
-
{metric.trend.direction === 'up' ? '↑' : '↓'} {metric.trend.value}
|
|
66
|
-
</Text>
|
|
67
|
-
)}
|
|
68
|
-
</View>
|
|
69
|
-
</View>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* MetricsGrid component for React Native
|
|
75
|
-
* Grid display of metric cards
|
|
76
|
-
*/
|
|
77
27
|
export const MetricsGrid: React.FC<MetricsGridProps> = ({
|
|
78
|
-
title,
|
|
79
|
-
description,
|
|
80
28
|
metrics,
|
|
81
29
|
columns = 2,
|
|
30
|
+
onMetricPress,
|
|
82
31
|
className,
|
|
83
|
-
...props
|
|
84
32
|
}) => {
|
|
33
|
+
const columnWidthClass = {
|
|
34
|
+
1: 'w-full',
|
|
35
|
+
2: 'w-1/2',
|
|
36
|
+
3: 'w-1/3',
|
|
37
|
+
4: 'w-1/4',
|
|
38
|
+
}[columns];
|
|
39
|
+
|
|
85
40
|
return (
|
|
86
|
-
<View className={cn('
|
|
87
|
-
{(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
41
|
+
<View className={cn('flex-row flex-wrap -m-1', className)}>
|
|
42
|
+
{metrics.map(metric => {
|
|
43
|
+
const content = (
|
|
44
|
+
<Card className='p-4 m-1 flex-1'>
|
|
45
|
+
<View className='flex-row items-start justify-between'>
|
|
46
|
+
<View className='flex-1'>
|
|
47
|
+
<Text className='text-sm text-gray-600 dark:text-gray-400 mb-1'>
|
|
48
|
+
{metric.label}
|
|
49
|
+
</Text>
|
|
50
|
+
<View className='flex-row items-baseline'>
|
|
51
|
+
<Text className='text-2xl font-bold text-gray-900 dark:text-gray-100'>
|
|
52
|
+
{metric.value}
|
|
53
|
+
</Text>
|
|
54
|
+
{metric.unit && (
|
|
55
|
+
<Text className='text-sm text-gray-500 dark:text-gray-500 ml-1'>
|
|
56
|
+
{metric.unit}
|
|
57
|
+
</Text>
|
|
58
|
+
)}
|
|
59
|
+
</View>
|
|
60
|
+
{metric.change !== undefined && (
|
|
61
|
+
<View className='flex-row items-center mt-2'>
|
|
62
|
+
<View
|
|
63
|
+
className={cn(
|
|
64
|
+
'px-1.5 py-0.5 rounded',
|
|
65
|
+
metric.change >= 0
|
|
66
|
+
? 'bg-green-100 dark:bg-green-900'
|
|
67
|
+
: 'bg-red-100 dark:bg-red-900'
|
|
68
|
+
)}
|
|
69
|
+
>
|
|
70
|
+
<Text
|
|
71
|
+
className={cn(
|
|
72
|
+
'text-xs font-medium',
|
|
73
|
+
metric.change >= 0
|
|
74
|
+
? 'text-green-700 dark:text-green-300'
|
|
75
|
+
: 'text-red-700 dark:text-red-300'
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
78
|
+
{formatChange(metric.change)}
|
|
79
|
+
</Text>
|
|
80
|
+
</View>
|
|
81
|
+
{metric.changeLabel && (
|
|
82
|
+
<Text className='text-xs text-gray-500 dark:text-gray-500 ml-2'>
|
|
83
|
+
{metric.changeLabel}
|
|
84
|
+
</Text>
|
|
85
|
+
)}
|
|
86
|
+
</View>
|
|
87
|
+
)}
|
|
88
|
+
</View>
|
|
89
|
+
{metric.icon && <View className='ml-2'>{metric.icon}</View>}
|
|
90
|
+
</View>
|
|
91
|
+
</Card>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (onMetricPress) {
|
|
95
|
+
return (
|
|
96
|
+
<View key={metric.id} className={columnWidthClass}>
|
|
97
|
+
<Pressable
|
|
98
|
+
onPress={() => onMetricPress(metric)}
|
|
99
|
+
accessibilityRole='button'
|
|
100
|
+
accessibilityLabel={
|
|
101
|
+
metric.label + ': ' + metric.value + (metric.unit || '')
|
|
102
|
+
}
|
|
103
|
+
>
|
|
104
|
+
{content}
|
|
105
|
+
</Pressable>
|
|
106
|
+
</View>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
numColumns={columns > 2 ? 2 : columns}
|
|
106
|
-
renderItem={({ item }) => (
|
|
107
|
-
<View className="flex-1">
|
|
108
|
-
<MetricCard metric={item} />
|
|
110
|
+
return (
|
|
111
|
+
<View key={metric.id} className={columnWidthClass}>
|
|
112
|
+
{content}
|
|
109
113
|
</View>
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
/>
|
|
114
|
+
);
|
|
115
|
+
})}
|
|
113
116
|
</View>
|
|
114
117
|
);
|
|
115
118
|
};
|
|
119
|
+
|
|
120
|
+
export default MetricsGrid;
|