@littlebearapps/platform-admin-sdk 2.1.0 → 2.2.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 (115) hide show
  1. package/README.md +2 -5
  2. package/dist/templates.d.ts +1 -1
  3. package/dist/templates.js +121 -3
  4. package/package.json +1 -1
  5. package/templates/full/dashboard/src/components/notifications/NotificationDropdown.tsx +130 -0
  6. package/templates/full/dashboard/src/components/notifications/NotificationItem.tsx +264 -0
  7. package/templates/full/dashboard/src/components/patterns/PatternInfoButton.tsx +60 -0
  8. package/templates/full/dashboard/src/components/reports/FeatureUsageReport.tsx +339 -0
  9. package/templates/full/dashboard/src/components/search/SearchResultGroup.tsx +46 -0
  10. package/templates/full/dashboard/src/components/search/SearchResultItem.tsx +212 -0
  11. package/templates/full/dashboard/src/pages/api/patterns/[id]/approve.ts +49 -0
  12. package/templates/full/dashboard/src/pages/api/patterns/[id]/reject.ts +50 -0
  13. package/templates/full/dashboard/src/pages/api/reports/digests/stats.ts +38 -0
  14. package/templates/full/dashboard/src/pages/api/reports/digests.ts +39 -0
  15. package/templates/full/dashboard/src/pages/api/search/reindex/[type].ts +56 -0
  16. package/templates/full/dashboard/src/pages/api/test-reports/[id].ts +102 -0
  17. package/templates/full/dashboard/src/pages/feedback.astro +365 -0
  18. package/templates/full/dashboard/src/pages/kiosk.astro +206 -0
  19. package/templates/full/dashboard/src/pages/map.astro +561 -0
  20. package/templates/full/dashboard/src/pages/revenue.astro +72 -0
  21. package/templates/full/dashboard/src/pages/tests.astro +431 -0
  22. package/templates/full/scripts/ops/audit-cost-anomaly.ts +430 -0
  23. package/templates/full/scripts/ops/verify-account-total.ts +256 -0
  24. package/templates/full/tests/integration/feedback-schema.test.ts +361 -0
  25. package/templates/full/tests/integration/r2-archive.test.ts +108 -0
  26. package/templates/shared/.github/workflows/dependabot-automerge.yml +41 -0
  27. package/templates/shared/.github/workflows/validate-controls.yml +27 -0
  28. package/templates/shared/dashboard/src/components/Breadcrumbs.astro +101 -0
  29. package/templates/shared/dashboard/src/components/EmptyState.astro +46 -0
  30. package/templates/shared/dashboard/src/components/ErrorBoundary.astro +79 -0
  31. package/templates/shared/dashboard/src/components/LoadingSkeleton.astro +105 -0
  32. package/templates/shared/dashboard/src/components/PageShell.astro +72 -0
  33. package/templates/shared/dashboard/src/components/SkipLinks.astro +22 -0
  34. package/templates/shared/dashboard/src/components/Toast.astro +170 -0
  35. package/templates/shared/dashboard/src/components/ToastContainer.astro +156 -0
  36. package/templates/shared/dashboard/src/components/costs/ProviderCostsGrid.tsx +401 -0
  37. package/templates/shared/dashboard/src/components/costs/index.ts +4 -0
  38. package/templates/shared/dashboard/src/components/overview/AlertBanner.tsx +94 -0
  39. package/templates/shared/dashboard/src/components/overview/index.ts +9 -0
  40. package/templates/shared/dashboard/src/components/resources/CostChart.tsx +170 -0
  41. package/templates/shared/dashboard/src/components/resources/ProviderCard.tsx +272 -0
  42. package/templates/shared/dashboard/src/components/resources/ProviderDetail.tsx +293 -0
  43. package/templates/shared/dashboard/src/components/settings/SettingsCard.astro +102 -0
  44. package/templates/shared/dashboard/src/components/usage/AllowanceGauge.astro +170 -0
  45. package/templates/shared/dashboard/src/components/usage/AnomalyAlerts.astro +633 -0
  46. package/templates/shared/dashboard/src/components/usage/BillingCycleCountdown.astro +192 -0
  47. package/templates/shared/dashboard/src/components/usage/BurnRateHero.astro +539 -0
  48. package/templates/shared/dashboard/src/components/usage/CircuitBreakerEventLog.astro +542 -0
  49. package/templates/shared/dashboard/src/components/usage/CircuitBreakerPanel.tsx +292 -0
  50. package/templates/shared/dashboard/src/components/usage/CircuitBreakerStatus.astro +669 -0
  51. package/templates/shared/dashboard/src/components/usage/CompactThresholdBanner.astro +531 -0
  52. package/templates/shared/dashboard/src/components/usage/ComparisonModeSelector.astro +651 -0
  53. package/templates/shared/dashboard/src/components/usage/CostBreakdownChart.astro +381 -0
  54. package/templates/shared/dashboard/src/components/usage/CostBreakdownTable.astro +210 -0
  55. package/templates/shared/dashboard/src/components/usage/CostDataTable.astro +0 -0
  56. package/templates/shared/dashboard/src/components/usage/CostDonutChart.astro +311 -0
  57. package/templates/shared/dashboard/src/components/usage/DailyCostChart.astro +632 -0
  58. package/templates/shared/dashboard/src/components/usage/ExportButton.astro +114 -0
  59. package/templates/shared/dashboard/src/components/usage/FeatureBudgetsTable.astro +872 -0
  60. package/templates/shared/dashboard/src/components/usage/FilterBar.astro +190 -0
  61. package/templates/shared/dashboard/src/components/usage/FilterToggles.astro +175 -0
  62. package/templates/shared/dashboard/src/components/usage/GitHubUsageCard.astro +537 -0
  63. package/templates/shared/dashboard/src/components/usage/OverageCostCard.astro +212 -0
  64. package/templates/shared/dashboard/src/components/usage/PlanUtilizationCard.astro +193 -0
  65. package/templates/shared/dashboard/src/components/usage/ProjectCard.astro +640 -0
  66. package/templates/shared/dashboard/src/components/usage/ProjectCardsGrid.astro +272 -0
  67. package/templates/shared/dashboard/src/components/usage/ResourceSearch.astro +279 -0
  68. package/templates/shared/dashboard/src/components/usage/ServiceUtilizationList.astro +604 -0
  69. package/templates/shared/dashboard/src/components/usage/SparklineCard.astro +399 -0
  70. package/templates/shared/dashboard/src/components/usage/StatsHero.astro +600 -0
  71. package/templates/shared/dashboard/src/components/usage/TableFilters.astro +1033 -0
  72. package/templates/shared/dashboard/src/components/usage/ThresholdAlert.astro +271 -0
  73. package/templates/shared/dashboard/src/components/usage/ThresholdSettings.astro +618 -0
  74. package/templates/shared/dashboard/src/components/usage/TopSpenderCard.astro +170 -0
  75. package/templates/shared/dashboard/src/components/usage/UnifiedResourceTable.astro +1737 -0
  76. package/templates/shared/dashboard/src/components/usage/UsageCard.astro +135 -0
  77. package/templates/shared/dashboard/src/components/usage/UsageHealthBanner.astro +387 -0
  78. package/templates/shared/dashboard/src/components/usage/UtilizationBar.astro +159 -0
  79. package/templates/shared/dashboard/src/components/usage/WorkersBreakdownTable.astro +659 -0
  80. package/templates/shared/dashboard/src/components/usage/daily/CostChart.astro +461 -0
  81. package/templates/shared/dashboard/src/components/usage/daily/CostTable.astro +946 -0
  82. package/templates/shared/dashboard/src/components/usage/daily/DailyOverview.astro +1079 -0
  83. package/templates/shared/dashboard/src/components/usage/design-tokens.ts +187 -0
  84. package/templates/shared/dashboard/src/components/usage/filters/InlineDateRange.astro +285 -0
  85. package/templates/shared/dashboard/src/components/usage/filters/PeriodButtons.astro +157 -0
  86. package/templates/shared/dashboard/src/components/usage/filters/ProjectSelect.astro +284 -0
  87. package/templates/shared/dashboard/src/components/usage/scripts/ai-tab-controller.ts +419 -0
  88. package/templates/shared/dashboard/src/components/usage/scripts/constants.ts +60 -0
  89. package/templates/shared/dashboard/src/components/usage/scripts/formatters.ts +62 -0
  90. package/templates/shared/dashboard/src/components/usage/scripts/overview-controller.ts +1633 -0
  91. package/templates/shared/dashboard/src/components/usage/scripts/resource-table-builder.ts +294 -0
  92. package/templates/shared/dashboard/src/components/usage/scripts/tabs-filters-controller.ts +464 -0
  93. package/templates/shared/dashboard/src/components/usage/state/index.ts +55 -0
  94. package/templates/shared/dashboard/src/components/usage/state/usageActions.ts +439 -0
  95. package/templates/shared/dashboard/src/components/usage/state/usageStore.ts +376 -0
  96. package/templates/shared/dashboard/src/components/usage/types.ts +283 -0
  97. package/templates/shared/dashboard/src/components/usage/usage-colors.ts +292 -0
  98. package/templates/shared/dashboard/src/pages/api/usage/ai-models.ts +235 -0
  99. package/templates/shared/dashboard/src/pages/api/usage/billing-context.ts +296 -0
  100. package/templates/shared/scripts/test-telemetry-flow.ts +464 -0
  101. package/templates/shared/tests/e2e/usage-export.test.ts +784 -0
  102. package/templates/shared/tests/e2e/usage-mobile.test.ts +531 -0
  103. package/templates/standard/dashboard/src/components/errors/PriorityBadge.astro +27 -0
  104. package/templates/standard/dashboard/src/components/infrastructure/HealthchecksStatus.tsx +293 -0
  105. package/templates/standard/dashboard/src/components/infrastructure/InfrastructureTabs.tsx +268 -0
  106. package/templates/standard/dashboard/src/pages/analytics.astro +64 -0
  107. package/templates/standard/dashboard/src/pages/api/infrastructure/alerts.ts +85 -0
  108. package/templates/standard/dashboard/src/pages/api/infrastructure/healthchecks/[id]/flips.ts +110 -0
  109. package/templates/standard/dashboard/src/pages/api/infrastructure/healthchecks.ts +101 -0
  110. package/templates/standard/dashboard/src/pages/api/infrastructure/uptime/[id]/response-times.ts +121 -0
  111. package/templates/standard/dashboard/src/pages/api/infrastructure/uptime.ts +89 -0
  112. package/templates/standard/dashboard/src/pages/api/test/service-auth.ts +178 -0
  113. package/templates/standard/tests/integration/connectors.test.ts +241 -0
  114. package/templates/standard/tests/integration/github-monitor.test.ts +143 -0
  115. package/templates/standard/tests/integration/ingestion.test.ts +211 -0
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Resource Table Builder
3
+ *
4
+ * Builds the unified resource table and mobile cards view.
5
+ * Extracted from index.astro for task-22.5 (slim to <300 lines)
6
+ */
7
+
8
+ // ========== Types ==========
9
+
10
+ export interface UnifiedResource {
11
+ id: string;
12
+ name: string;
13
+ type: string;
14
+ project: string;
15
+ /** GitHub repository URL for the project (if available) */
16
+ repoUrl?: string | null;
17
+ usage: {
18
+ value: number;
19
+ formatted: string;
20
+ unit: string;
21
+ };
22
+ /** Percentage of monthly limit used (0-100+) */
23
+ limitPct?: number | null;
24
+ costCurrent: number;
25
+ costPrior: number;
26
+ costDelta: number;
27
+ costDeltaPct: number | 'NEW';
28
+ status: 'healthy' | 'warning' | 'high' | 'critical';
29
+ }
30
+
31
+ // ========== Constants ==========
32
+
33
+ const TYPE_LABELS: Record<string, string> = {
34
+ worker: 'Worker',
35
+ d1: 'D1 Database',
36
+ kv: 'KV Namespace',
37
+ r2: 'R2 Bucket',
38
+ vectorize: 'Vectorize',
39
+ pages: 'Pages',
40
+ do: 'Durable Object',
41
+ 'ai-gateway': 'AI Gateway',
42
+ queues: 'Queues',
43
+ workflows: 'Workflows',
44
+ };
45
+
46
+ const STATUS_LABELS: Record<string, string> = {
47
+ healthy: 'Healthy',
48
+ warning: 'Warning',
49
+ high: 'High',
50
+ critical: 'Critical',
51
+ };
52
+
53
+ const STATUS_COLORS: Record<string, string> = {
54
+ healthy: 'status-healthy',
55
+ warning: 'status-warning',
56
+ high: 'status-high',
57
+ critical: 'status-critical',
58
+ };
59
+
60
+ const TABLE_HEADERS = [
61
+ { key: 'project', label: 'Project', align: 'left' },
62
+ { key: 'type', label: 'Type', align: 'left' },
63
+ { key: 'usage', label: 'Usage', align: 'right' },
64
+ { key: 'costCurrent', label: 'Est. Cost', align: 'right' },
65
+ { key: 'costDeltaPct', label: 'vs Prior', align: 'right' },
66
+ { key: 'status', label: 'Status', align: 'left' },
67
+ ];
68
+
69
+ // ========== DOM Helpers ==========
70
+
71
+ function clearElement(el: HTMLElement): void {
72
+ while (el.firstChild) {
73
+ el.removeChild(el.firstChild);
74
+ }
75
+ }
76
+
77
+ function createEmptyState(message: string): HTMLElement {
78
+ const div = document.createElement('div');
79
+ div.className = 'empty-state';
80
+ div.textContent = message;
81
+ return div;
82
+ }
83
+
84
+ // ========== Table Building ==========
85
+
86
+ function createTableHeader(): HTMLElement {
87
+ const thead = document.createElement('thead');
88
+ const headerRow = document.createElement('tr');
89
+
90
+ TABLE_HEADERS.forEach((header) => {
91
+ const th = document.createElement('th');
92
+ th.className = 'sortable';
93
+ th.setAttribute('data-sort', header.key);
94
+ if (header.align === 'right') {
95
+ th.style.textAlign = 'right';
96
+ }
97
+ th.textContent = header.label;
98
+ headerRow.appendChild(th);
99
+ });
100
+
101
+ thead.appendChild(headerRow);
102
+ return thead;
103
+ }
104
+
105
+ function createDeltaBadge(deltaPct: number | 'NEW'): HTMLElement {
106
+ const badge = document.createElement('span');
107
+
108
+ if (deltaPct === 'NEW') {
109
+ badge.className = 'delta-badge delta-new';
110
+ badge.textContent = 'NEW';
111
+ } else if (typeof deltaPct === 'number') {
112
+ // Show dash for unchanged values (within ±0.5%)
113
+ if (Math.abs(deltaPct) < 0.5) {
114
+ badge.className = 'delta-badge delta-neutral';
115
+ badge.textContent = '—';
116
+ } else {
117
+ const sign = deltaPct >= 0 ? '+' : '';
118
+ const colorClass = deltaPct > 5 ? 'delta-up' : deltaPct < -5 ? 'delta-down' : 'delta-neutral';
119
+ badge.className = 'delta-badge ' + colorClass;
120
+ badge.textContent = sign + deltaPct.toFixed(1) + '%';
121
+ }
122
+ }
123
+
124
+ return badge;
125
+ }
126
+
127
+ function createStatusBadge(status: string): HTMLElement {
128
+ const badge = document.createElement('span');
129
+ badge.className = 'status-badge ' + (STATUS_COLORS[status] || '');
130
+ badge.textContent = STATUS_LABELS[status] || status;
131
+ return badge;
132
+ }
133
+
134
+ function createTableRow(resource: UnifiedResource): HTMLElement {
135
+ const row = document.createElement('tr');
136
+
137
+ // Add data-status for critical row highlighting
138
+ row.setAttribute('data-status', resource.status);
139
+
140
+ // Project cell (monospace for project IDs)
141
+ const projectCell = document.createElement('td');
142
+ projectCell.className = 'script-name';
143
+ projectCell.textContent = resource.name || resource.project || resource.id || 'Unknown';
144
+ row.appendChild(projectCell);
145
+
146
+ // Type cell
147
+ const typeCell = document.createElement('td');
148
+ typeCell.textContent = TYPE_LABELS[resource.type] || resource.type;
149
+ row.appendChild(typeCell);
150
+
151
+ // Usage cell (right-aligned)
152
+ const usageCell = document.createElement('td');
153
+ usageCell.className = 'text-right';
154
+ usageCell.textContent = resource.usage.formatted + ' ' + resource.usage.unit;
155
+ row.appendChild(usageCell);
156
+
157
+ // Cost cell (right-aligned)
158
+ const costCell = document.createElement('td');
159
+ costCell.className = 'font-semibold text-right';
160
+ costCell.textContent = '$' + resource.costCurrent.toFixed(2);
161
+ row.appendChild(costCell);
162
+
163
+ // Delta cell (right-aligned)
164
+ const deltaCell = document.createElement('td');
165
+ deltaCell.className = 'text-right';
166
+ if (resource.costDeltaPct === 'NEW' || typeof resource.costDeltaPct === 'number') {
167
+ deltaCell.appendChild(createDeltaBadge(resource.costDeltaPct));
168
+ } else {
169
+ deltaCell.textContent = '—';
170
+ }
171
+ row.appendChild(deltaCell);
172
+
173
+ // Status cell
174
+ const statusCell = document.createElement('td');
175
+ statusCell.appendChild(createStatusBadge(resource.status));
176
+ row.appendChild(statusCell);
177
+
178
+ return row;
179
+ }
180
+
181
+ function createTableBody(resources: UnifiedResource[]): HTMLElement {
182
+ const tbody = document.createElement('tbody');
183
+
184
+ resources.forEach((resource) => {
185
+ tbody.appendChild(createTableRow(resource));
186
+ });
187
+
188
+ return tbody;
189
+ }
190
+
191
+ // ========== Mobile Cards ==========
192
+
193
+ function createMobileCard(resource: UnifiedResource): HTMLElement {
194
+ const card = document.createElement('div');
195
+ card.className = 'mobile-card';
196
+
197
+ // Add data-status for critical card highlighting
198
+ card.setAttribute('data-status', resource.status);
199
+
200
+ const cardHeader = document.createElement('div');
201
+ cardHeader.className = 'mobile-card-header';
202
+ cardHeader.textContent = resource.name || resource.project || resource.id || 'Unknown';
203
+ card.appendChild(cardHeader);
204
+
205
+ const cardBody = document.createElement('div');
206
+ cardBody.className = 'mobile-card-body';
207
+
208
+ const rows = [
209
+ { label: 'Type', value: TYPE_LABELS[resource.type] || resource.type },
210
+ { label: 'Usage', value: resource.usage.formatted + ' ' + resource.usage.unit },
211
+ { label: 'Est. Cost', value: '$' + resource.costCurrent.toFixed(2) },
212
+ { label: 'Status', value: STATUS_LABELS[resource.status] || resource.status },
213
+ ];
214
+
215
+ rows.forEach((rowData) => {
216
+ const row = document.createElement('div');
217
+ row.className = 'mobile-card-row';
218
+
219
+ const label = document.createElement('span');
220
+ label.className = 'mobile-card-label';
221
+ label.textContent = rowData.label;
222
+ row.appendChild(label);
223
+
224
+ const value = document.createElement('span');
225
+ value.className = 'mobile-card-value';
226
+ value.textContent = rowData.value;
227
+ row.appendChild(value);
228
+
229
+ cardBody.appendChild(row);
230
+ });
231
+
232
+ card.appendChild(cardBody);
233
+ return card;
234
+ }
235
+
236
+ function createMobileCards(resources: UnifiedResource[]): HTMLElement {
237
+ const mobileCards = document.createElement('div');
238
+ mobileCards.className = 'mobile-cards';
239
+
240
+ resources.forEach((resource) => {
241
+ mobileCards.appendChild(createMobileCard(resource));
242
+ });
243
+
244
+ return mobileCards;
245
+ }
246
+
247
+ // ========== Main Render Function ==========
248
+
249
+ export function renderResourceTable(resources: UnifiedResource[]): void {
250
+ const container = document.getElementById('unified-table-container');
251
+ if (!container) return;
252
+
253
+ // Clear container
254
+ clearElement(container);
255
+
256
+ if (resources.length === 0) {
257
+ container.appendChild(createEmptyState('No resources match the current filters.'));
258
+ return;
259
+ }
260
+
261
+ // Create table
262
+ const tableWrapper = document.createElement('div');
263
+ tableWrapper.className = 'table-container responsive-table';
264
+
265
+ const tableDiv = document.createElement('div');
266
+ tableDiv.className = 'table-wrapper';
267
+
268
+ const table = document.createElement('table');
269
+ table.className = 'detail-table sortable-table';
270
+
271
+ table.appendChild(createTableHeader());
272
+ table.appendChild(createTableBody(resources));
273
+
274
+ tableDiv.appendChild(table);
275
+ tableWrapper.appendChild(tableDiv);
276
+
277
+ // Add mobile cards view
278
+ tableWrapper.appendChild(createMobileCards(resources));
279
+
280
+ container.appendChild(tableWrapper);
281
+ }
282
+
283
+ // ========== Resource Count Update ==========
284
+
285
+ export function updateResourceCount(count: number): void {
286
+ const countEl = document.getElementById('resource-count-value');
287
+ if (countEl) {
288
+ countEl.textContent = String(count);
289
+ }
290
+ }
291
+
292
+ // ========== Type/Status Label Exports ==========
293
+
294
+ export { TYPE_LABELS, STATUS_LABELS, STATUS_COLORS };