@littlebearapps/platform-admin-sdk 2.1.0 → 2.3.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 (122) hide show
  1. package/README.md +2 -5
  2. package/dist/check-upgrade.d.ts +29 -0
  3. package/dist/check-upgrade.js +97 -0
  4. package/dist/index.js +59 -4
  5. package/dist/manifest.d.ts +2 -0
  6. package/dist/scaffold.js +5 -1
  7. package/dist/templates.d.ts +6 -1
  8. package/dist/templates.js +141 -3
  9. package/dist/upgrade.d.ts +1 -0
  10. package/dist/upgrade.js +21 -2
  11. package/package.json +1 -1
  12. package/templates/full/dashboard/src/components/notifications/NotificationDropdown.tsx +130 -0
  13. package/templates/full/dashboard/src/components/notifications/NotificationItem.tsx +264 -0
  14. package/templates/full/dashboard/src/components/patterns/PatternInfoButton.tsx +60 -0
  15. package/templates/full/dashboard/src/components/reports/FeatureUsageReport.tsx +339 -0
  16. package/templates/full/dashboard/src/components/search/SearchResultGroup.tsx +46 -0
  17. package/templates/full/dashboard/src/components/search/SearchResultItem.tsx +212 -0
  18. package/templates/full/dashboard/src/pages/api/patterns/[id]/approve.ts +49 -0
  19. package/templates/full/dashboard/src/pages/api/patterns/[id]/reject.ts +50 -0
  20. package/templates/full/dashboard/src/pages/api/reports/digests/stats.ts +38 -0
  21. package/templates/full/dashboard/src/pages/api/reports/digests.ts +39 -0
  22. package/templates/full/dashboard/src/pages/api/search/reindex/[type].ts +56 -0
  23. package/templates/full/dashboard/src/pages/api/test-reports/[id].ts +102 -0
  24. package/templates/full/dashboard/src/pages/feedback.astro +365 -0
  25. package/templates/full/dashboard/src/pages/kiosk.astro +206 -0
  26. package/templates/full/dashboard/src/pages/map.astro +561 -0
  27. package/templates/full/dashboard/src/pages/revenue.astro +72 -0
  28. package/templates/full/dashboard/src/pages/tests.astro +431 -0
  29. package/templates/full/scripts/ops/audit-cost-anomaly.ts +430 -0
  30. package/templates/full/scripts/ops/verify-account-total.ts +256 -0
  31. package/templates/full/tests/integration/feedback-schema.test.ts +361 -0
  32. package/templates/full/tests/integration/r2-archive.test.ts +108 -0
  33. package/templates/shared/.github/workflows/dependabot-automerge.yml +41 -0
  34. package/templates/shared/.github/workflows/validate-controls.yml +27 -0
  35. package/templates/shared/dashboard/src/components/Breadcrumbs.astro +101 -0
  36. package/templates/shared/dashboard/src/components/EmptyState.astro +46 -0
  37. package/templates/shared/dashboard/src/components/ErrorBoundary.astro +79 -0
  38. package/templates/shared/dashboard/src/components/LoadingSkeleton.astro +105 -0
  39. package/templates/shared/dashboard/src/components/PageShell.astro +72 -0
  40. package/templates/shared/dashboard/src/components/SkipLinks.astro +22 -0
  41. package/templates/shared/dashboard/src/components/Toast.astro +170 -0
  42. package/templates/shared/dashboard/src/components/ToastContainer.astro +156 -0
  43. package/templates/shared/dashboard/src/components/costs/ProviderCostsGrid.tsx +401 -0
  44. package/templates/shared/dashboard/src/components/costs/index.ts +4 -0
  45. package/templates/shared/dashboard/src/components/overview/AlertBanner.tsx +94 -0
  46. package/templates/shared/dashboard/src/components/overview/index.ts +9 -0
  47. package/templates/shared/dashboard/src/components/resources/CostChart.tsx +170 -0
  48. package/templates/shared/dashboard/src/components/resources/ProviderCard.tsx +272 -0
  49. package/templates/shared/dashboard/src/components/resources/ProviderDetail.tsx +293 -0
  50. package/templates/shared/dashboard/src/components/settings/SettingsCard.astro +102 -0
  51. package/templates/shared/dashboard/src/components/usage/AllowanceGauge.astro +170 -0
  52. package/templates/shared/dashboard/src/components/usage/AnomalyAlerts.astro +633 -0
  53. package/templates/shared/dashboard/src/components/usage/BillingCycleCountdown.astro +192 -0
  54. package/templates/shared/dashboard/src/components/usage/BurnRateHero.astro +539 -0
  55. package/templates/shared/dashboard/src/components/usage/CircuitBreakerEventLog.astro +542 -0
  56. package/templates/shared/dashboard/src/components/usage/CircuitBreakerPanel.tsx +292 -0
  57. package/templates/shared/dashboard/src/components/usage/CircuitBreakerStatus.astro +669 -0
  58. package/templates/shared/dashboard/src/components/usage/CompactThresholdBanner.astro +531 -0
  59. package/templates/shared/dashboard/src/components/usage/ComparisonModeSelector.astro +651 -0
  60. package/templates/shared/dashboard/src/components/usage/CostBreakdownChart.astro +381 -0
  61. package/templates/shared/dashboard/src/components/usage/CostBreakdownTable.astro +210 -0
  62. package/templates/shared/dashboard/src/components/usage/CostDataTable.astro +0 -0
  63. package/templates/shared/dashboard/src/components/usage/CostDonutChart.astro +311 -0
  64. package/templates/shared/dashboard/src/components/usage/DailyCostChart.astro +632 -0
  65. package/templates/shared/dashboard/src/components/usage/ExportButton.astro +114 -0
  66. package/templates/shared/dashboard/src/components/usage/FeatureBudgetsTable.astro +872 -0
  67. package/templates/shared/dashboard/src/components/usage/FilterBar.astro +190 -0
  68. package/templates/shared/dashboard/src/components/usage/FilterToggles.astro +175 -0
  69. package/templates/shared/dashboard/src/components/usage/GitHubUsageCard.astro +537 -0
  70. package/templates/shared/dashboard/src/components/usage/OverageCostCard.astro +212 -0
  71. package/templates/shared/dashboard/src/components/usage/PlanUtilizationCard.astro +193 -0
  72. package/templates/shared/dashboard/src/components/usage/ProjectCard.astro +640 -0
  73. package/templates/shared/dashboard/src/components/usage/ProjectCardsGrid.astro +272 -0
  74. package/templates/shared/dashboard/src/components/usage/ResourceSearch.astro +279 -0
  75. package/templates/shared/dashboard/src/components/usage/ServiceUtilizationList.astro +604 -0
  76. package/templates/shared/dashboard/src/components/usage/SparklineCard.astro +399 -0
  77. package/templates/shared/dashboard/src/components/usage/StatsHero.astro +600 -0
  78. package/templates/shared/dashboard/src/components/usage/TableFilters.astro +1033 -0
  79. package/templates/shared/dashboard/src/components/usage/ThresholdAlert.astro +271 -0
  80. package/templates/shared/dashboard/src/components/usage/ThresholdSettings.astro +618 -0
  81. package/templates/shared/dashboard/src/components/usage/TopSpenderCard.astro +170 -0
  82. package/templates/shared/dashboard/src/components/usage/UnifiedResourceTable.astro +1737 -0
  83. package/templates/shared/dashboard/src/components/usage/UsageCard.astro +135 -0
  84. package/templates/shared/dashboard/src/components/usage/UsageHealthBanner.astro +387 -0
  85. package/templates/shared/dashboard/src/components/usage/UtilizationBar.astro +159 -0
  86. package/templates/shared/dashboard/src/components/usage/WorkersBreakdownTable.astro +659 -0
  87. package/templates/shared/dashboard/src/components/usage/daily/CostChart.astro +461 -0
  88. package/templates/shared/dashboard/src/components/usage/daily/CostTable.astro +946 -0
  89. package/templates/shared/dashboard/src/components/usage/daily/DailyOverview.astro +1079 -0
  90. package/templates/shared/dashboard/src/components/usage/design-tokens.ts +187 -0
  91. package/templates/shared/dashboard/src/components/usage/filters/InlineDateRange.astro +285 -0
  92. package/templates/shared/dashboard/src/components/usage/filters/PeriodButtons.astro +157 -0
  93. package/templates/shared/dashboard/src/components/usage/filters/ProjectSelect.astro +284 -0
  94. package/templates/shared/dashboard/src/components/usage/scripts/ai-tab-controller.ts +419 -0
  95. package/templates/shared/dashboard/src/components/usage/scripts/constants.ts +60 -0
  96. package/templates/shared/dashboard/src/components/usage/scripts/formatters.ts +62 -0
  97. package/templates/shared/dashboard/src/components/usage/scripts/overview-controller.ts +1633 -0
  98. package/templates/shared/dashboard/src/components/usage/scripts/resource-table-builder.ts +294 -0
  99. package/templates/shared/dashboard/src/components/usage/scripts/tabs-filters-controller.ts +464 -0
  100. package/templates/shared/dashboard/src/components/usage/state/index.ts +55 -0
  101. package/templates/shared/dashboard/src/components/usage/state/usageActions.ts +439 -0
  102. package/templates/shared/dashboard/src/components/usage/state/usageStore.ts +376 -0
  103. package/templates/shared/dashboard/src/components/usage/types.ts +283 -0
  104. package/templates/shared/dashboard/src/components/usage/usage-colors.ts +292 -0
  105. package/templates/shared/dashboard/src/pages/api/usage/ai-models.ts +235 -0
  106. package/templates/shared/dashboard/src/pages/api/usage/billing-context.ts +296 -0
  107. package/templates/shared/scripts/test-telemetry-flow.ts +464 -0
  108. package/templates/shared/tests/e2e/usage-export.test.ts +784 -0
  109. package/templates/shared/tests/e2e/usage-mobile.test.ts +531 -0
  110. package/templates/standard/dashboard/src/components/errors/PriorityBadge.astro +27 -0
  111. package/templates/standard/dashboard/src/components/infrastructure/HealthchecksStatus.tsx +293 -0
  112. package/templates/standard/dashboard/src/components/infrastructure/InfrastructureTabs.tsx +268 -0
  113. package/templates/standard/dashboard/src/pages/analytics.astro +64 -0
  114. package/templates/standard/dashboard/src/pages/api/infrastructure/alerts.ts +85 -0
  115. package/templates/standard/dashboard/src/pages/api/infrastructure/healthchecks/[id]/flips.ts +110 -0
  116. package/templates/standard/dashboard/src/pages/api/infrastructure/healthchecks.ts +101 -0
  117. package/templates/standard/dashboard/src/pages/api/infrastructure/uptime/[id]/response-times.ts +121 -0
  118. package/templates/standard/dashboard/src/pages/api/infrastructure/uptime.ts +89 -0
  119. package/templates/standard/dashboard/src/pages/api/test/service-auth.ts +178 -0
  120. package/templates/standard/tests/integration/connectors.test.ts +241 -0
  121. package/templates/standard/tests/integration/github-monitor.test.ts +143 -0
  122. package/templates/standard/tests/integration/ingestion.test.ts +211 -0
@@ -0,0 +1,399 @@
1
+ ---
2
+ /**
3
+ * SparklineCard Component
4
+ *
5
+ * Enhanced usage card with mini sparkline chart, trend indicator, and status dot.
6
+ * Part of Usage Dashboard improvements.
7
+ */
8
+
9
+ export interface SparklinePoint {
10
+ date: string;
11
+ value: number;
12
+ }
13
+
14
+ export interface Props {
15
+ label: string;
16
+ icon: string;
17
+ primaryValue: string;
18
+ primaryLabel: string;
19
+ sparklineData?: SparklinePoint[];
20
+ trend?: 'up' | 'down' | 'stable';
21
+ percentChange?: number;
22
+ status?: 'healthy' | 'warning' | 'high' | 'critical';
23
+ secondaryValue?: string;
24
+ secondaryLabel?: string;
25
+ comparisonText?: string;
26
+ cardId: string;
27
+ }
28
+
29
+ const {
30
+ label,
31
+ icon,
32
+ primaryValue,
33
+ primaryLabel,
34
+ sparklineData = [],
35
+ trend = 'stable',
36
+ percentChange = 0,
37
+ status = 'healthy',
38
+ secondaryValue,
39
+ secondaryLabel,
40
+ comparisonText,
41
+ cardId,
42
+ } = Astro.props;
43
+
44
+ // Status colours
45
+ const statusColours = {
46
+ healthy: '#10B981',
47
+ warning: '#F59E0B',
48
+ high: '#F97316',
49
+ critical: '#EF4444',
50
+ };
51
+
52
+ const statusColour = statusColours[status];
53
+
54
+ // Trend colours (inverted for errors - down is good)
55
+ const isErrorMetric = label.toLowerCase().includes('error');
56
+ const trendColour =
57
+ trend === 'stable'
58
+ ? '#6B7280'
59
+ : trend === 'up'
60
+ ? isErrorMetric
61
+ ? '#EF4444'
62
+ : '#10B981'
63
+ : isErrorMetric
64
+ ? '#10B981'
65
+ : '#EF4444';
66
+
67
+ // Trend arrow
68
+ const trendArrow = trend === 'up' ? '↑' : trend === 'down' ? '↓' : '→';
69
+ ---
70
+
71
+ <div class="sparkline-card" role="region" aria-label={label} data-card-id={cardId}>
72
+ <div class="card-header">
73
+ <div class="header-left">
74
+ <span
75
+ class="status-dot"
76
+ style={`background-color: ${statusColour};`}
77
+ title={`Status: ${status}`}></span>
78
+ <span class="card-icon" aria-hidden="true" set:html={icon} />
79
+ <span class="card-label">{label}</span>
80
+ </div>
81
+ {
82
+ trend !== 'stable' && (
83
+ <div
84
+ class="trend-badge"
85
+ style={`color: ${trendColour}; background-color: ${trendColour}15;`}
86
+ >
87
+ <span class="trend-arrow">{trendArrow}</span>
88
+ <span class="trend-value">{Math.abs(percentChange).toFixed(1)}%</span>
89
+ </div>
90
+ )
91
+ }
92
+ </div>
93
+
94
+ <div class="card-primary">
95
+ <span class="primary-value">{primaryValue}</span>
96
+ <span class="primary-label">{primaryLabel}</span>
97
+ </div>
98
+
99
+ {
100
+ sparklineData.length > 1 && (
101
+ <div class="sparkline-container">
102
+ <canvas
103
+ id={`sparkline-${cardId}`}
104
+ class="sparkline-canvas"
105
+ aria-label={`${label} trend over time`}
106
+ />
107
+ </div>
108
+ )
109
+ }
110
+
111
+ {
112
+ (secondaryValue || comparisonText) && (
113
+ <div class="card-footer">
114
+ {secondaryValue && (
115
+ <div class="secondary-metric">
116
+ <span class="secondary-value">{secondaryValue}</span>
117
+ {secondaryLabel && <span class="secondary-label">{secondaryLabel}</span>}
118
+ </div>
119
+ )}
120
+ {comparisonText && (
121
+ <div class="comparison-text" style={`color: ${trendColour};`}>
122
+ {comparisonText}
123
+ </div>
124
+ )}
125
+ </div>
126
+ )
127
+ }
128
+ </div>
129
+
130
+ <style>
131
+ .sparkline-card {
132
+ background-color: white;
133
+ border: 1px solid #e5e7eb;
134
+ border-radius: 0.5rem;
135
+ padding: 1rem;
136
+ transition: all 0.15s ease;
137
+ display: flex;
138
+ flex-direction: column;
139
+ height: 100%;
140
+ min-height: 180px;
141
+ }
142
+
143
+ :global(.dark) .sparkline-card {
144
+ background-color: #1f2937;
145
+ border-color: #374151;
146
+ }
147
+
148
+ .sparkline-card:hover {
149
+ border-color: #d1d5db;
150
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
151
+ }
152
+
153
+ :global(.dark) .sparkline-card:hover {
154
+ border-color: #4b5563;
155
+ }
156
+
157
+ .card-header {
158
+ display: flex;
159
+ align-items: center;
160
+ justify-content: space-between;
161
+ margin-bottom: 0.5rem;
162
+ }
163
+
164
+ .header-left {
165
+ display: flex;
166
+ align-items: center;
167
+ gap: 0.5rem;
168
+ }
169
+
170
+ .status-dot {
171
+ width: 8px;
172
+ height: 8px;
173
+ border-radius: 50%;
174
+ flex-shrink: 0;
175
+ }
176
+
177
+ .card-icon {
178
+ font-size: 1rem;
179
+ line-height: 1;
180
+ }
181
+
182
+ .card-label {
183
+ font-size: 0.75rem;
184
+ font-weight: 600;
185
+ color: #374151;
186
+ text-transform: uppercase;
187
+ letter-spacing: 0.025em;
188
+ }
189
+
190
+ :global(.dark) .card-label {
191
+ color: #d1d5db;
192
+ }
193
+
194
+ .trend-badge {
195
+ display: inline-flex;
196
+ align-items: center;
197
+ gap: 0.25rem;
198
+ padding: 0.125rem 0.375rem;
199
+ border-radius: 9999px;
200
+ font-size: 0.625rem;
201
+ font-weight: 600;
202
+ }
203
+
204
+ .trend-arrow {
205
+ font-size: 0.75rem;
206
+ }
207
+
208
+ .card-primary {
209
+ margin-bottom: 0.5rem;
210
+ }
211
+
212
+ .primary-value {
213
+ display: block;
214
+ font-size: 1.75rem;
215
+ font-weight: 700;
216
+ color: #1f2937;
217
+ line-height: 1;
218
+ margin-bottom: 0.125rem;
219
+ }
220
+
221
+ :global(.dark) .primary-value {
222
+ color: #f9fafb;
223
+ }
224
+
225
+ .primary-label {
226
+ font-size: 0.625rem;
227
+ color: #6b7280;
228
+ text-transform: uppercase;
229
+ letter-spacing: 0.05em;
230
+ }
231
+
232
+ :global(.dark) .primary-label {
233
+ color: #9ca3af;
234
+ }
235
+
236
+ .sparkline-container {
237
+ flex: 1;
238
+ min-height: 40px;
239
+ max-height: 60px;
240
+ margin: 0.25rem 0;
241
+ }
242
+
243
+ .sparkline-canvas {
244
+ width: 100%;
245
+ height: 100%;
246
+ }
247
+
248
+ .card-footer {
249
+ display: flex;
250
+ justify-content: space-between;
251
+ align-items: center;
252
+ padding-top: 0.5rem;
253
+ border-top: 1px solid #f3f4f6;
254
+ margin-top: auto;
255
+ }
256
+
257
+ :global(.dark) .card-footer {
258
+ border-color: #374151;
259
+ }
260
+
261
+ .secondary-metric {
262
+ display: flex;
263
+ flex-direction: column;
264
+ }
265
+
266
+ .secondary-value {
267
+ font-size: 0.875rem;
268
+ font-weight: 600;
269
+ color: #374151;
270
+ }
271
+
272
+ :global(.dark) .secondary-value {
273
+ color: #d1d5db;
274
+ }
275
+
276
+ .secondary-label {
277
+ font-size: 0.625rem;
278
+ color: #6b7280;
279
+ }
280
+
281
+ :global(.dark) .secondary-label {
282
+ color: #9ca3af;
283
+ }
284
+
285
+ .comparison-text {
286
+ font-size: 0.625rem;
287
+ font-weight: 500;
288
+ }
289
+
290
+ @media (max-width: 640px) {
291
+ .sparkline-card {
292
+ padding: 0.75rem;
293
+ min-height: 140px;
294
+ }
295
+
296
+ .primary-value {
297
+ font-size: 1.25rem;
298
+ }
299
+
300
+ .sparkline-container {
301
+ display: none;
302
+ }
303
+ }
304
+ </style>
305
+
306
+ <script define:vars={{ sparklineData, cardId, statusColour, trend, isErrorMetric }}>
307
+ // Only render sparkline if we have data
308
+ if (sparklineData && sparklineData.length > 1) {
309
+ // Wait for DOM and Chart.js to be ready
310
+ document.addEventListener('DOMContentLoaded', async () => {
311
+ try {
312
+ const { Chart, registerables } = await import('chart.js');
313
+ Chart.register(...registerables);
314
+
315
+ const canvas = document.getElementById(`sparkline-${cardId}`);
316
+ if (!canvas) return;
317
+
318
+ const ctx = canvas.getContext('2d');
319
+ if (!ctx) return;
320
+
321
+ // Determine line colour based on trend and metric type
322
+ const lineColour =
323
+ trend === 'stable'
324
+ ? '#6B7280'
325
+ : trend === 'up'
326
+ ? isErrorMetric
327
+ ? '#EF4444'
328
+ : '#10B981'
329
+ : isErrorMetric
330
+ ? '#10B981'
331
+ : '#EF4444';
332
+
333
+ // Create gradient fill
334
+ const gradient = ctx.createLinearGradient(0, 0, 0, 50);
335
+ gradient.addColorStop(0, `${lineColour}40`);
336
+ gradient.addColorStop(1, `${lineColour}05`);
337
+
338
+ new Chart(ctx, {
339
+ type: 'line',
340
+ data: {
341
+ labels: sparklineData.map((p) => p.date),
342
+ datasets: [
343
+ {
344
+ data: sparklineData.map((p) => p.value),
345
+ borderColor: lineColour,
346
+ backgroundColor: gradient,
347
+ fill: true,
348
+ borderWidth: 1.5,
349
+ tension: 0.4,
350
+ pointRadius: 0,
351
+ pointHoverRadius: 3,
352
+ pointHoverBackgroundColor: lineColour,
353
+ },
354
+ ],
355
+ },
356
+ options: {
357
+ responsive: true,
358
+ maintainAspectRatio: false,
359
+ plugins: {
360
+ legend: { display: false },
361
+ tooltip: {
362
+ enabled: true,
363
+ mode: 'index',
364
+ intersect: false,
365
+ backgroundColor: '#1f2937',
366
+ titleFont: { size: 10 },
367
+ bodyFont: { size: 10 },
368
+ padding: 6,
369
+ displayColors: false,
370
+ callbacks: {
371
+ title: (items) => {
372
+ return items[0]?.label || '';
373
+ },
374
+ label: (item) => {
375
+ const value = item.raw;
376
+ if (typeof value === 'number') {
377
+ return value.toLocaleString();
378
+ }
379
+ return String(value);
380
+ },
381
+ },
382
+ },
383
+ },
384
+ scales: {
385
+ x: { display: false },
386
+ y: { display: false, beginAtZero: true },
387
+ },
388
+ interaction: {
389
+ mode: 'index',
390
+ intersect: false,
391
+ },
392
+ },
393
+ });
394
+ } catch (e) {
395
+ console.error('Failed to render sparkline:', e);
396
+ }
397
+ });
398
+ }
399
+ </script>