@alliance-droid/status-feedback-system 0.1.0 → 0.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.
- package/dist/api.d.ts +94 -0
- package/dist/api.js +100 -0
- package/dist/components/FeedbackBoard.svelte +842 -0
- package/dist/components/FeedbackBoard.svelte.d.ts +19 -0
- package/dist/components/FeedbackButton.svelte +3 -3
- package/dist/components/FeedbackButton.svelte.d.ts +1 -1
- package/dist/components/FeedbackForm.svelte +3 -3
- package/dist/components/FeedbackForm.svelte.d.ts +1 -1
- package/dist/components/StatusBanner.svelte +36 -3
- package/dist/components/StatusBanner.svelte.d.ts +7 -1
- package/dist/components/StatusPage.svelte +150 -83
- package/dist/components/StatusPage.svelte.d.ts +10 -3
- package/dist/index.d.ts +7 -9
- package/dist/index.js +6 -8
- package/dist/types.d.ts +13 -6
- package/package.json +2 -13
- package/dist/components/admin/AdminDashboard.svelte +0 -274
- package/dist/components/admin/AdminDashboard.svelte.d.ts +0 -9
- package/dist/components/admin/ApiKeyManager.svelte +0 -68
- package/dist/components/admin/ApiKeyManager.svelte.d.ts +0 -7
- package/dist/components/admin/FeedbackList.svelte +0 -160
- package/dist/components/admin/FeedbackList.svelte.d.ts +0 -17
- package/dist/components/admin/IncidentForm.svelte +0 -135
- package/dist/components/admin/IncidentForm.svelte.d.ts +0 -14
- package/dist/components/admin/IncidentManager.svelte +0 -153
- package/dist/components/admin/IncidentManager.svelte.d.ts +0 -13
- package/dist/components/admin/ProjectForm.svelte +0 -106
- package/dist/components/admin/ProjectForm.svelte.d.ts +0 -13
- package/dist/components/admin/ProjectList.svelte +0 -57
- package/dist/components/admin/ProjectList.svelte.d.ts +0 -10
- package/dist/components/admin/StatusControl.svelte +0 -62
- package/dist/components/admin/StatusControl.svelte.d.ts +0 -8
- package/dist/components/admin/SystemManager.svelte +0 -119
- package/dist/components/admin/SystemManager.svelte.d.ts +0 -13
- package/dist/components/admin/index.d.ts +0 -9
- package/dist/components/admin/index.js +0 -9
- package/dist/server/db.d.ts +0 -17
- package/dist/server/db.js +0 -68
- package/dist/server/feedback.d.ts +0 -27
- package/dist/server/feedback.js +0 -124
- package/dist/server/handlers.d.ts +0 -41
- package/dist/server/handlers.js +0 -251
- package/dist/server/incidents.d.ts +0 -27
- package/dist/server/incidents.js +0 -180
- package/dist/server/index.d.ts +0 -101
- package/dist/server/index.js +0 -71
- package/dist/server/projects.d.ts +0 -45
- package/dist/server/projects.js +0 -156
- package/dist/server/schema.d.ts +0 -9
- package/dist/server/schema.js +0 -94
- package/dist/server/systems.d.ts +0 -20
- package/dist/server/systems.js +0 -146
- package/dist/server/types.d.ts +0 -4
- package/dist/server/types.js +0 -4
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
apiUrl: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
/** Category labels and icons — order determines sidebar order */
|
|
5
|
+
categoryConfig?: Record<string, {
|
|
6
|
+
label?: string;
|
|
7
|
+
icon?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
}>;
|
|
10
|
+
/** Title shown at the top */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Show the submit form inline */
|
|
13
|
+
showSubmit?: boolean;
|
|
14
|
+
/** Available categories for the submit form */
|
|
15
|
+
submitCategories?: string[];
|
|
16
|
+
}
|
|
17
|
+
declare const FeedbackBoard: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type FeedbackBoard = ReturnType<typeof FeedbackBoard>;
|
|
19
|
+
export default FeedbackBoard;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
apiKey: string;
|
|
6
|
-
|
|
6
|
+
apiUrl: string;
|
|
7
7
|
categories?: string[];
|
|
8
8
|
userEmail?: string;
|
|
9
9
|
position?: 'bottom-right' | 'bottom-left';
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
let {
|
|
13
13
|
apiKey,
|
|
14
|
-
|
|
14
|
+
apiUrl,
|
|
15
15
|
categories,
|
|
16
16
|
userEmail,
|
|
17
17
|
position = 'bottom-right',
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
<div class="p-4">
|
|
52
52
|
<FeedbackForm
|
|
53
53
|
{apiKey}
|
|
54
|
-
{
|
|
54
|
+
{apiUrl}
|
|
55
55
|
{categories}
|
|
56
56
|
{userEmail}
|
|
57
57
|
onSuccess={() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
3
|
apiKey: string;
|
|
4
|
-
|
|
4
|
+
apiUrl: string;
|
|
5
5
|
categories?: string[];
|
|
6
6
|
userEmail?: string;
|
|
7
7
|
onSuccess?: () => void;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
let {
|
|
12
12
|
apiKey,
|
|
13
|
-
|
|
13
|
+
apiUrl,
|
|
14
14
|
categories = ['Bug', 'Feature Request', 'General'],
|
|
15
15
|
userEmail,
|
|
16
16
|
onSuccess,
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
errorMsg = '';
|
|
33
33
|
|
|
34
34
|
try {
|
|
35
|
-
const res = await fetch(`${
|
|
35
|
+
const res = await fetch(`${apiUrl.replace(/\/$/, '')}/api/feedback`, {
|
|
36
36
|
method: 'POST',
|
|
37
37
|
headers: {
|
|
38
38
|
'Content-Type': 'application/json',
|
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
2
3
|
import type { System, SystemStatus } from '../types.js';
|
|
4
|
+
import { createStatusClient } from '../api.js';
|
|
3
5
|
import StatusIndicator from './shared/StatusIndicator.svelte';
|
|
4
6
|
|
|
5
7
|
interface Props {
|
|
6
|
-
|
|
8
|
+
/** Systems data (pass-through mode) */
|
|
9
|
+
systems?: System[];
|
|
10
|
+
/** API URL for self-fetching mode */
|
|
11
|
+
apiUrl?: string;
|
|
12
|
+
/** API key for self-fetching mode */
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
/** Link to full status page */
|
|
7
15
|
statusUrl?: string;
|
|
8
16
|
}
|
|
9
17
|
|
|
10
|
-
let { systems, statusUrl }: Props = $props();
|
|
18
|
+
let { systems: systemsProp, apiUrl, apiKey, statusUrl }: Props = $props();
|
|
19
|
+
|
|
20
|
+
let systems: System[] = $state(systemsProp ?? []);
|
|
21
|
+
let loading = $state(!systemsProp && !!apiUrl && !!apiKey);
|
|
22
|
+
|
|
23
|
+
onMount(async () => {
|
|
24
|
+
if (systemsProp || !apiUrl || !apiKey) return;
|
|
25
|
+
try {
|
|
26
|
+
const client = createStatusClient({ apiUrl, apiKey });
|
|
27
|
+
const data = await client.getStatus();
|
|
28
|
+
systems = data.systems;
|
|
29
|
+
} catch (err) {
|
|
30
|
+
console.error('StatusBanner fetch error:', err);
|
|
31
|
+
} finally {
|
|
32
|
+
loading = false;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
$effect(() => {
|
|
37
|
+
if (systemsProp) systems = systemsProp;
|
|
38
|
+
});
|
|
11
39
|
|
|
12
40
|
let overallStatus = $derived.by((): SystemStatus => {
|
|
13
41
|
if (systems.length === 0) return 'operational';
|
|
@@ -25,7 +53,12 @@
|
|
|
25
53
|
};
|
|
26
54
|
</script>
|
|
27
55
|
|
|
28
|
-
{#if
|
|
56
|
+
{#if loading}
|
|
57
|
+
<div class="inline-flex items-center gap-2 rounded-full border border-border px-3 py-1.5 text-xs text-foreground-tertiary">
|
|
58
|
+
<div class="h-2 w-2 animate-pulse rounded-full bg-foreground-tertiary"></div>
|
|
59
|
+
<span>Loading...</span>
|
|
60
|
+
</div>
|
|
61
|
+
{:else if statusUrl}
|
|
29
62
|
<a
|
|
30
63
|
href={statusUrl}
|
|
31
64
|
class="inline-flex items-center gap-2 rounded-full border border-border px-3 py-1.5 text-xs text-foreground-secondary transition-colors hover:bg-surface-hover"
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { System } from '../types.js';
|
|
2
2
|
interface Props {
|
|
3
|
-
|
|
3
|
+
/** Systems data (pass-through mode) */
|
|
4
|
+
systems?: System[];
|
|
5
|
+
/** API URL for self-fetching mode */
|
|
6
|
+
apiUrl?: string;
|
|
7
|
+
/** API key for self-fetching mode */
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/** Link to full status page */
|
|
4
10
|
statusUrl?: string;
|
|
5
11
|
}
|
|
6
12
|
declare const StatusBanner: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,26 +1,81 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
2
3
|
import type { System, Incident, StatusHistoryEntry, SystemStatus } from '../types.js';
|
|
4
|
+
import { createStatusClient } from '../api.js';
|
|
3
5
|
import StatusIndicator from './shared/StatusIndicator.svelte';
|
|
4
6
|
import SystemCard from './shared/SystemCard.svelte';
|
|
5
7
|
import IncidentTimeline from './shared/IncidentTimeline.svelte';
|
|
6
8
|
|
|
7
9
|
interface Props {
|
|
10
|
+
/** Project display name */
|
|
8
11
|
projectName: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
+
/** API URL for fetching data (self-fetching mode) */
|
|
13
|
+
apiUrl?: string;
|
|
14
|
+
/** API key for fetching data (self-fetching mode) */
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
/** Systems data (pass-through mode — overrides API fetching) */
|
|
17
|
+
systems?: System[];
|
|
18
|
+
/** Incidents data (pass-through mode) */
|
|
19
|
+
incidents?: Incident[];
|
|
20
|
+
/** Map of systemId → StatusHistoryEntry[] for uptime bars (pass-through mode) */
|
|
12
21
|
statusHistory?: Record<string, StatusHistoryEntry[]>;
|
|
13
22
|
showUptime?: boolean;
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
let {
|
|
17
26
|
projectName,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
apiUrl,
|
|
28
|
+
apiKey,
|
|
29
|
+
systems: systemsProp,
|
|
30
|
+
incidents: incidentsProp,
|
|
31
|
+
statusHistory: statusHistoryProp,
|
|
21
32
|
showUptime = true,
|
|
22
33
|
}: Props = $props();
|
|
23
34
|
|
|
35
|
+
// ── State ──
|
|
36
|
+
let systems: System[] = $state(systemsProp ?? []);
|
|
37
|
+
let incidents: Incident[] = $state(incidentsProp ?? []);
|
|
38
|
+
let statusHistory: Record<string, StatusHistoryEntry[]> = $state(statusHistoryProp ?? {});
|
|
39
|
+
let loading = $state(!systemsProp);
|
|
40
|
+
let error = $state('');
|
|
41
|
+
|
|
42
|
+
// ── Self-fetching mode ──
|
|
43
|
+
const usesApi = $derived(!!apiUrl && !!apiKey && !systemsProp);
|
|
44
|
+
|
|
45
|
+
onMount(async () => {
|
|
46
|
+
if (!usesApi) return;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const client = createStatusClient({ apiUrl: apiUrl!, apiKey: apiKey! });
|
|
50
|
+
|
|
51
|
+
const [statusData, incidentData, uptimeData] = await Promise.all([
|
|
52
|
+
client.getStatus(),
|
|
53
|
+
client.getIncidents(),
|
|
54
|
+
client.getUptime(),
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
systems = statusData.systems;
|
|
58
|
+
incidents = incidentData.incidents;
|
|
59
|
+
statusHistory = uptimeData.history;
|
|
60
|
+
} catch (err) {
|
|
61
|
+
error = err instanceof Error ? err.message : 'Failed to load status data';
|
|
62
|
+
console.error('StatusPage fetch error:', err);
|
|
63
|
+
} finally {
|
|
64
|
+
loading = false;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// ── Sync props when in pass-through mode ──
|
|
69
|
+
$effect(() => {
|
|
70
|
+
if (systemsProp) systems = systemsProp;
|
|
71
|
+
});
|
|
72
|
+
$effect(() => {
|
|
73
|
+
if (incidentsProp) incidents = incidentsProp;
|
|
74
|
+
});
|
|
75
|
+
$effect(() => {
|
|
76
|
+
if (statusHistoryProp) statusHistory = statusHistoryProp;
|
|
77
|
+
});
|
|
78
|
+
|
|
24
79
|
// ── Derived state ──
|
|
25
80
|
|
|
26
81
|
let overallStatus = $derived.by((): SystemStatus => {
|
|
@@ -65,92 +120,104 @@
|
|
|
65
120
|
<h1 class="text-2xl font-semibold text-foreground">{projectName} Status</h1>
|
|
66
121
|
</div>
|
|
67
122
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<
|
|
72
|
-
<span class="text-lg font-semibold text-foreground">{overallMessages[overallStatus]}</span>
|
|
123
|
+
{#if loading}
|
|
124
|
+
<div class="rounded-lg border border-border bg-surface p-12 text-center">
|
|
125
|
+
<div class="mx-auto mb-3 h-8 w-8 animate-spin rounded-full border-2 border-foreground-tertiary border-t-primary"></div>
|
|
126
|
+
<p class="text-sm text-foreground-secondary">Loading status...</p>
|
|
73
127
|
</div>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
{showUptime}
|
|
86
|
-
/>
|
|
87
|
-
{/each}
|
|
128
|
+
{:else if error}
|
|
129
|
+
<div class="rounded-lg border border-red-500/30 bg-red-500/10 p-6 text-center">
|
|
130
|
+
<i class="fa-solid fa-circle-exclamation mb-2 text-2xl text-red-500"></i>
|
|
131
|
+
<p class="text-sm text-red-400">{error}</p>
|
|
132
|
+
</div>
|
|
133
|
+
{:else}
|
|
134
|
+
<!-- Overall Status Banner -->
|
|
135
|
+
<div class="rounded-lg border p-4 text-center {overallBgClasses[overallStatus]}">
|
|
136
|
+
<div class="flex items-center justify-center gap-2">
|
|
137
|
+
<StatusIndicator status={overallStatus} size="lg" />
|
|
138
|
+
<span class="text-lg font-semibold text-foreground">{overallMessages[overallStatus]}</span>
|
|
88
139
|
</div>
|
|
89
|
-
</
|
|
90
|
-
{/if}
|
|
140
|
+
</div>
|
|
91
141
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
142
|
+
<!-- Systems -->
|
|
143
|
+
{#if systems.length > 0}
|
|
144
|
+
<section>
|
|
145
|
+
<h2 class="mb-4 text-lg font-semibold text-foreground">Systems</h2>
|
|
146
|
+
<div class="space-y-3">
|
|
147
|
+
{#each systems as system}
|
|
148
|
+
<SystemCard
|
|
149
|
+
{system}
|
|
150
|
+
history={statusHistory[system.id] || []}
|
|
151
|
+
{showUptime}
|
|
152
|
+
/>
|
|
153
|
+
{/each}
|
|
154
|
+
</div>
|
|
155
|
+
</section>
|
|
156
|
+
{/if}
|
|
157
|
+
|
|
158
|
+
<!-- Active Incidents -->
|
|
159
|
+
{#if activeIncidents.length > 0}
|
|
160
|
+
<section>
|
|
161
|
+
<h2 class="mb-4 text-lg font-semibold text-foreground">Active Incidents</h2>
|
|
162
|
+
<div class="space-y-4">
|
|
163
|
+
{#each activeIncidents as incident}
|
|
164
|
+
<div class="rounded-lg border border-border bg-surface p-4">
|
|
165
|
+
<div class="flex items-start justify-between">
|
|
166
|
+
<div>
|
|
167
|
+
<h3 class="font-semibold text-foreground">{incident.title}</h3>
|
|
168
|
+
<div class="mt-1 flex items-center gap-2 text-xs text-foreground-tertiary">
|
|
169
|
+
<span class="rounded bg-red-500/10 px-1.5 py-0.5 text-red-500">
|
|
170
|
+
{incident.severity}
|
|
171
|
+
</span>
|
|
172
|
+
<span>{formatDate(incident.createdAt)}</span>
|
|
173
|
+
</div>
|
|
107
174
|
</div>
|
|
175
|
+
<StatusIndicator status={incident.status === 'resolved' ? 'operational' : 'outage'} size="sm" />
|
|
108
176
|
</div>
|
|
109
|
-
|
|
177
|
+
{#if incident.updates && incident.updates.length > 0}
|
|
178
|
+
<div class="mt-4 border-t border-border pt-4">
|
|
179
|
+
<IncidentTimeline updates={incident.updates} />
|
|
180
|
+
</div>
|
|
181
|
+
{/if}
|
|
110
182
|
</div>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
{/if}
|
|
116
|
-
</div>
|
|
117
|
-
{/each}
|
|
118
|
-
</div>
|
|
119
|
-
</section>
|
|
120
|
-
{/if}
|
|
183
|
+
{/each}
|
|
184
|
+
</div>
|
|
185
|
+
</section>
|
|
186
|
+
{/if}
|
|
121
187
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
188
|
+
<!-- Resolved Incidents -->
|
|
189
|
+
{#if recentResolved.length > 0}
|
|
190
|
+
<section>
|
|
191
|
+
<h2 class="mb-4 text-lg font-semibold text-foreground">Past Incidents</h2>
|
|
192
|
+
<div class="space-y-4">
|
|
193
|
+
{#each recentResolved as incident}
|
|
194
|
+
<div class="rounded-lg border border-border bg-surface p-4">
|
|
195
|
+
<div class="flex items-start justify-between">
|
|
196
|
+
<div>
|
|
197
|
+
<h3 class="font-semibold text-foreground">{incident.title}</h3>
|
|
198
|
+
<p class="mt-1 text-xs text-foreground-tertiary">
|
|
199
|
+
Resolved {incident.resolvedAt ? formatDate(incident.resolvedAt) : ''}
|
|
200
|
+
</p>
|
|
201
|
+
</div>
|
|
202
|
+
<StatusIndicator status="operational" size="sm" />
|
|
135
203
|
</div>
|
|
136
|
-
|
|
204
|
+
{#if incident.updates && incident.updates.length > 0}
|
|
205
|
+
<div class="mt-4 border-t border-border pt-4">
|
|
206
|
+
<IncidentTimeline updates={incident.updates} />
|
|
207
|
+
</div>
|
|
208
|
+
{/if}
|
|
137
209
|
</div>
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
{/if}
|
|
143
|
-
</div>
|
|
144
|
-
{/each}
|
|
145
|
-
</div>
|
|
146
|
-
</section>
|
|
147
|
-
{/if}
|
|
210
|
+
{/each}
|
|
211
|
+
</div>
|
|
212
|
+
</section>
|
|
213
|
+
{/if}
|
|
148
214
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
215
|
+
<!-- No Incidents -->
|
|
216
|
+
{#if activeIncidents.length === 0 && recentResolved.length === 0}
|
|
217
|
+
<div class="rounded-lg border border-border bg-surface p-8 text-center">
|
|
218
|
+
<i class="fa-solid fa-circle-check mb-2 text-2xl text-green-500"></i>
|
|
219
|
+
<p class="text-sm text-foreground-secondary">No incidents reported</p>
|
|
220
|
+
</div>
|
|
221
|
+
{/if}
|
|
155
222
|
{/if}
|
|
156
223
|
</div>
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import type { System, Incident, StatusHistoryEntry } from '../types.js';
|
|
2
2
|
interface Props {
|
|
3
|
+
/** Project display name */
|
|
3
4
|
projectName: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
5
|
+
/** API URL for fetching data (self-fetching mode) */
|
|
6
|
+
apiUrl?: string;
|
|
7
|
+
/** API key for fetching data (self-fetching mode) */
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/** Systems data (pass-through mode — overrides API fetching) */
|
|
10
|
+
systems?: System[];
|
|
11
|
+
/** Incidents data (pass-through mode) */
|
|
12
|
+
incidents?: Incident[];
|
|
13
|
+
/** Map of systemId → StatusHistoryEntry[] for uptime bars (pass-through mode) */
|
|
7
14
|
statusHistory?: Record<string, StatusHistoryEntry[]>;
|
|
8
15
|
showUptime?: boolean;
|
|
9
16
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,20 +2,18 @@
|
|
|
2
2
|
* @alliance-droid/status-feedback-system
|
|
3
3
|
*
|
|
4
4
|
* Drop-in system status pages and user feedback forms for SvelteKit apps.
|
|
5
|
+
* All data is fetched from a remote status-feedback-admin backend via API.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
* import { StatusPage,
|
|
8
|
-
*
|
|
9
|
-
* Server exports:
|
|
10
|
-
* import { createStatusServer } from '@alliance-droid/status-feedback-system/server';
|
|
11
|
-
*
|
|
12
|
-
* Admin exports:
|
|
13
|
-
* import { AdminDashboard } from '@alliance-droid/status-feedback-system/admin';
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { StatusPage, FeedbackButton, createStatusClient } from '@alliance-droid/status-feedback-system';
|
|
14
9
|
*/
|
|
15
|
-
export type { Project, System, Incident, IncidentUpdate, Feedback, StatusHistoryEntry, SystemStatus, IncidentStatus, IncidentSeverity, FeedbackStatus,
|
|
10
|
+
export type { Project, System, Incident, IncidentUpdate, Feedback, FeedbackResponse, FeedbackVisibility, StatusHistoryEntry, SystemStatus, IncidentStatus, IncidentSeverity, FeedbackStatus, ApiResponse, } from './types.js';
|
|
11
|
+
export { createStatusClient } from './api.js';
|
|
12
|
+
export type { StatusClient, StatusClientConfig, StatusData, IncidentData, UptimeData, BoardData, BoardItem, BoardCategory } from './api.js';
|
|
16
13
|
export { default as StatusPage } from './components/StatusPage.svelte';
|
|
17
14
|
export { default as StatusBanner } from './components/StatusBanner.svelte';
|
|
18
15
|
export { default as FeedbackForm } from './components/FeedbackForm.svelte';
|
|
16
|
+
export { default as FeedbackBoard } from './components/FeedbackBoard.svelte';
|
|
19
17
|
export { default as FeedbackButton } from './components/FeedbackButton.svelte';
|
|
20
18
|
export { default as StatusIndicator } from './components/shared/StatusIndicator.svelte';
|
|
21
19
|
export { default as UptimeBar } from './components/shared/UptimeBar.svelte';
|
package/dist/index.js
CHANGED
|
@@ -2,20 +2,18 @@
|
|
|
2
2
|
* @alliance-droid/status-feedback-system
|
|
3
3
|
*
|
|
4
4
|
* Drop-in system status pages and user feedback forms for SvelteKit apps.
|
|
5
|
+
* All data is fetched from a remote status-feedback-admin backend via API.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
* import { StatusPage,
|
|
8
|
-
*
|
|
9
|
-
* Server exports:
|
|
10
|
-
* import { createStatusServer } from '@alliance-droid/status-feedback-system/server';
|
|
11
|
-
*
|
|
12
|
-
* Admin exports:
|
|
13
|
-
* import { AdminDashboard } from '@alliance-droid/status-feedback-system/admin';
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { StatusPage, FeedbackButton, createStatusClient } from '@alliance-droid/status-feedback-system';
|
|
14
9
|
*/
|
|
10
|
+
// ── API Client ──
|
|
11
|
+
export { createStatusClient } from './api.js';
|
|
15
12
|
// ── Client Components ──
|
|
16
13
|
export { default as StatusPage } from './components/StatusPage.svelte';
|
|
17
14
|
export { default as StatusBanner } from './components/StatusBanner.svelte';
|
|
18
15
|
export { default as FeedbackForm } from './components/FeedbackForm.svelte';
|
|
16
|
+
export { default as FeedbackBoard } from './components/FeedbackBoard.svelte';
|
|
19
17
|
export { default as FeedbackButton } from './components/FeedbackButton.svelte';
|
|
20
18
|
// ── Shared Components ──
|
|
21
19
|
export { default as StatusIndicator } from './components/shared/StatusIndicator.svelte';
|
package/dist/types.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export type FeedbackStatus = 'new' | 'reviewed' | 'resolved' | 'archived';
|
|
|
8
8
|
export interface Project {
|
|
9
9
|
id: string;
|
|
10
10
|
name: string;
|
|
11
|
-
apiKey: string;
|
|
12
11
|
description: string | null;
|
|
13
12
|
allowedOrigins: string[];
|
|
14
13
|
createdAt: number;
|
|
@@ -43,9 +42,18 @@ export interface IncidentUpdate {
|
|
|
43
42
|
message: string;
|
|
44
43
|
createdAt: number;
|
|
45
44
|
}
|
|
45
|
+
export type FeedbackVisibility = 'public' | 'private';
|
|
46
|
+
export interface FeedbackResponse {
|
|
47
|
+
id: string;
|
|
48
|
+
feedbackId: string;
|
|
49
|
+
message: string;
|
|
50
|
+
author: string | null;
|
|
51
|
+
createdAt: number;
|
|
52
|
+
}
|
|
46
53
|
export interface Feedback {
|
|
47
54
|
id: string;
|
|
48
55
|
projectId: string;
|
|
56
|
+
title: string | null;
|
|
49
57
|
category: string | null;
|
|
50
58
|
message: string;
|
|
51
59
|
email: string | null;
|
|
@@ -53,6 +61,10 @@ export interface Feedback {
|
|
|
53
61
|
pageUrl: string | null;
|
|
54
62
|
metadata: Record<string, unknown> | null;
|
|
55
63
|
status: FeedbackStatus;
|
|
64
|
+
visibility: FeedbackVisibility;
|
|
65
|
+
votes: number;
|
|
66
|
+
adminResponse: string | null;
|
|
67
|
+
responses?: FeedbackResponse[];
|
|
56
68
|
createdAt: number;
|
|
57
69
|
}
|
|
58
70
|
export interface StatusHistoryEntry {
|
|
@@ -61,11 +73,6 @@ export interface StatusHistoryEntry {
|
|
|
61
73
|
status: SystemStatus;
|
|
62
74
|
changedAt: number;
|
|
63
75
|
}
|
|
64
|
-
export interface StatusServerConfig {
|
|
65
|
-
database: {
|
|
66
|
-
connectionString: string;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
76
|
export interface ApiResponse<T = unknown> {
|
|
70
77
|
success: boolean;
|
|
71
78
|
data?: T;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alliance-droid/status-feedback-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Drop-in system status pages and user feedback forms for SvelteKit apps",
|
|
6
6
|
"svelte": "./dist/index.js",
|
|
@@ -9,14 +9,6 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"svelte": "./dist/index.js"
|
|
12
|
-
},
|
|
13
|
-
"./server": {
|
|
14
|
-
"types": "./dist/server/index.d.ts",
|
|
15
|
-
"default": "./dist/server/index.js"
|
|
16
|
-
},
|
|
17
|
-
"./admin": {
|
|
18
|
-
"types": "./dist/components/admin/index.d.ts",
|
|
19
|
-
"svelte": "./dist/components/admin/index.js"
|
|
20
12
|
}
|
|
21
13
|
},
|
|
22
14
|
"files": [
|
|
@@ -37,9 +29,7 @@
|
|
|
37
29
|
"svelte": "^5.0.0"
|
|
38
30
|
},
|
|
39
31
|
"dependencies": {
|
|
40
|
-
"@alliance-droid/svelte-component-library": "^0.1.27"
|
|
41
|
-
"mssql": "^11.0.0",
|
|
42
|
-
"nanoid": "^5.0.0"
|
|
32
|
+
"@alliance-droid/svelte-component-library": "^0.1.27"
|
|
43
33
|
},
|
|
44
34
|
"devDependencies": {
|
|
45
35
|
"@sveltejs/adapter-auto": "^7.0.0",
|
|
@@ -47,7 +37,6 @@
|
|
|
47
37
|
"@sveltejs/package": "^2.3.0",
|
|
48
38
|
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
|
49
39
|
"@tailwindcss/vite": "^4.1.0",
|
|
50
|
-
"@types/mssql": "^9.1.0",
|
|
51
40
|
"publint": "^0.3.0",
|
|
52
41
|
"svelte": "^5.48.0",
|
|
53
42
|
"svelte-check": "^4.3.0",
|