@burdenoff/microfe-devportal 2026.608.1 → 2026.609.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/devportal/DevportalRoutes.js +9 -5
- package/dist/devportal/DevportalRoutes.js.map +1 -1
- package/dist/devportal/hooks/useGraphQL.js +49 -36
- package/dist/devportal/hooks/useGraphQL.js.map +1 -1
- package/dist/devportal/pages/DashboardPage.js +152 -134
- package/dist/devportal/pages/DashboardPage.js.map +1 -1
- package/dist/devportal/pages/SetupPage.js +501 -0
- package/dist/devportal/pages/SetupPage.js.map +1 -0
- package/dist/devportal/pages/StoreSubmissionPage.js +98 -76
- package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
- package/dist/node_modules/@apollo/client/link/core/ApolloLink.js +52 -0
- package/dist/node_modules/@apollo/client/link/core/ApolloLink.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/subscriptions/index.js +41 -0
- package/dist/node_modules/@apollo/client/link/subscriptions/index.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/utils/createOperation.js +34 -0
- package/dist/node_modules/@apollo/client/link/utils/createOperation.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/caching/sizes.js +6 -0
- package/dist/node_modules/@apollo/client/utilities/caching/sizes.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/graphql/print.js +16 -0
- package/dist/node_modules/@apollo/client/utilities/graphql/print.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/caches.js +19 -0
- package/dist/node_modules/@apollo/client/utilities/internal/caches.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/checkDocument.js +21 -0
- package/dist/node_modules/@apollo/client/utilities/internal/checkDocument.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getMainDefinition.js +17 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getMainDefinition.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js +9 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js +9 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js +8 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/global.js +9 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/global.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js +10 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/isNonNullObject.js +8 -0
- package/dist/node_modules/@apollo/client/utilities/internal/isNonNullObject.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/makeUniqueId.js +10 -0
- package/dist/node_modules/@apollo/client/utilities/internal/makeUniqueId.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/memoize.js +23 -0
- package/dist/node_modules/@apollo/client/utilities/internal/memoize.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js +10 -0
- package/dist/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/invariant/index.js +57 -0
- package/dist/node_modules/@apollo/client/utilities/invariant/index.js.map +1 -0
- package/dist/node_modules/@apollo/client/version.js +6 -0
- package/dist/node_modules/@apollo/client/version.js.map +1 -0
- package/dist/node_modules/@wry/caches/lib/weak.js +67 -0
- package/dist/node_modules/@wry/caches/lib/weak.js.map +1 -0
- package/dist/node_modules/@wry/trie/lib/index.js +53 -0
- package/dist/node_modules/@wry/trie/lib/index.js.map +1 -0
- package/dist/node_modules/graphql-ws/dist/client.js +272 -0
- package/dist/node_modules/graphql-ws/dist/client.js.map +1 -0
- package/dist/node_modules/graphql-ws/dist/common-CGW11Fyb.js +62 -0
- package/dist/node_modules/graphql-ws/dist/common-CGW11Fyb.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js +21 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Observable.js +78 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Observable.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscriber.js +117 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscriber.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscription.js +93 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscription.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/config.js +12 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/config.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/observable/empty.js +9 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/observable/empty.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js +16 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/symbol/observable.js +8 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/symbol/observable.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js +13 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js +11 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js +11 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/errorContext.js +22 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/errorContext.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js +8 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js +8 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js +6 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/pipe.js +13 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/pipe.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js +14 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js.map +1 -0
- package/dist/node_modules/rxjs/node_modules/tslib/tslib.es6.js +52 -0
- package/dist/node_modules/rxjs/node_modules/tslib/tslib.es6.js.map +1 -0
- package/package.json +2 -1
|
@@ -8,234 +8,252 @@ import { PermissionGuard as c } from "../components/PermissionGuard.js";
|
|
|
8
8
|
import "../components/index.js";
|
|
9
9
|
import { DEVPORTAL_PERMISSIONS as l } from "../constants/permissions.js";
|
|
10
10
|
import "../hooks/index.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { useEffect as u } from "react";
|
|
12
|
+
import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
13
|
+
import { Activity as f, AppWindow as p, ArrowRight as m, Building2 as h, DollarSign as g, Key as _, Loader2 as v, Plus as y, TrendingUp as b, Users as x, Webhook as S } from "lucide-react";
|
|
14
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
14
15
|
//#region src/devportal/pages/DashboardPage.tsx
|
|
15
|
-
var
|
|
16
|
-
let { navigate:
|
|
17
|
-
let n =
|
|
16
|
+
var T = () => {
|
|
17
|
+
let { navigate: T, basePath: O } = e(), { t: k } = d(), A = (e, t) => {
|
|
18
|
+
let n = k(e);
|
|
18
19
|
return n === e ? t : n;
|
|
19
|
-
}, { data:
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
}, { data: j, loading: M } = s({ fetchPolicy: "cache-and-network" }), N = j?.myDeveloperOrganizations ?? [];
|
|
21
|
+
u(() => {
|
|
22
|
+
if (!(M || !j) && !(N.length > 0)) {
|
|
23
|
+
try {
|
|
24
|
+
if (localStorage.getItem("devportal_setup_dismissed")) return;
|
|
25
|
+
} catch {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
T?.(`${O}/setup`);
|
|
29
|
+
}
|
|
30
|
+
}, [
|
|
31
|
+
M,
|
|
32
|
+
j,
|
|
33
|
+
N.length,
|
|
34
|
+
T,
|
|
35
|
+
O
|
|
36
|
+
]);
|
|
37
|
+
let P = j?.applications?.edges?.map((e) => e.node) ?? [], F = {
|
|
38
|
+
totalApps: j?.applications?.totalCount ?? 0,
|
|
39
|
+
totalOrgs: N.length,
|
|
22
40
|
totalApiKeys: 0,
|
|
23
41
|
totalWebhooks: 0,
|
|
24
|
-
totalApiCalls:
|
|
25
|
-
activeInstalls:
|
|
26
|
-
monthlyRevenue:
|
|
42
|
+
totalApiCalls: N.reduce((e, t) => e + parseInt(t.totalApiCalls || "0"), 0),
|
|
43
|
+
activeInstalls: N.reduce((e, t) => e + (t.activeInstalls || 0), 0),
|
|
44
|
+
monthlyRevenue: N.reduce((e, t) => e + (t.totalRevenue || 0), 0),
|
|
27
45
|
errorRate: 0
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
-
return /* @__PURE__ */
|
|
46
|
+
}, I = (e) => {
|
|
47
|
+
T?.(`${O}${e}`);
|
|
48
|
+
}, L = M;
|
|
49
|
+
return /* @__PURE__ */ C(c, {
|
|
32
50
|
permission: l.APP_READ,
|
|
33
|
-
children: /* @__PURE__ */
|
|
34
|
-
title:
|
|
35
|
-
description:
|
|
36
|
-
actions: /* @__PURE__ */
|
|
51
|
+
children: /* @__PURE__ */ w(n, {
|
|
52
|
+
title: A("devportal.developerPortal", "Developer Portal"),
|
|
53
|
+
description: A("devportal.buildManageMonitor", "Build, manage, and monitor your applications"),
|
|
54
|
+
actions: /* @__PURE__ */ w("button", {
|
|
37
55
|
"data-tour": "devportal-dashboard-create-app-button",
|
|
38
|
-
onClick: () =>
|
|
56
|
+
onClick: () => I("/apps/new"),
|
|
39
57
|
className: "inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
40
|
-
children: [/* @__PURE__ */
|
|
58
|
+
children: [/* @__PURE__ */ C(y, { size: 16 }), A("devportal.createApp", "Create App")]
|
|
41
59
|
}),
|
|
42
60
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
61
|
+
/* @__PURE__ */ C(r, {
|
|
44
62
|
"data-tour": "devportal-dashboard-stats-overview",
|
|
45
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ w(a, {
|
|
46
64
|
columns: 4,
|
|
47
65
|
children: [
|
|
48
|
-
/* @__PURE__ */
|
|
49
|
-
title:
|
|
50
|
-
value:
|
|
51
|
-
icon: /* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ C(i, {
|
|
67
|
+
title: A("devportal.totalApps", "Total Apps"),
|
|
68
|
+
value: L ? /* @__PURE__ */ C(v, { className: "h-5 w-5 animate-spin" }) : F.totalApps,
|
|
69
|
+
icon: /* @__PURE__ */ C(p, { size: 20 }),
|
|
52
70
|
trend: void 0
|
|
53
71
|
}),
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
-
title:
|
|
56
|
-
value:
|
|
57
|
-
icon: /* @__PURE__ */
|
|
72
|
+
/* @__PURE__ */ C(i, {
|
|
73
|
+
title: A("devportal.organizations", "Organizations"),
|
|
74
|
+
value: L ? /* @__PURE__ */ C(v, { className: "h-5 w-5 animate-spin" }) : F.totalOrgs,
|
|
75
|
+
icon: /* @__PURE__ */ C(h, { size: 20 })
|
|
58
76
|
}),
|
|
59
|
-
/* @__PURE__ */
|
|
60
|
-
title:
|
|
61
|
-
value:
|
|
62
|
-
icon: /* @__PURE__ */
|
|
63
|
-
description:
|
|
77
|
+
/* @__PURE__ */ C(i, {
|
|
78
|
+
title: A("devportal.apiKeys", "API Keys"),
|
|
79
|
+
value: F.totalApiKeys,
|
|
80
|
+
icon: /* @__PURE__ */ C(_, { size: 20 }),
|
|
81
|
+
description: A("devportal.activeKeys", "Active keys")
|
|
64
82
|
}),
|
|
65
|
-
/* @__PURE__ */
|
|
66
|
-
title:
|
|
67
|
-
value:
|
|
68
|
-
icon: /* @__PURE__ */ S
|
|
69
|
-
description:
|
|
83
|
+
/* @__PURE__ */ C(i, {
|
|
84
|
+
title: A("devportal.webhooks", "Webhooks"),
|
|
85
|
+
value: F.totalWebhooks,
|
|
86
|
+
icon: /* @__PURE__ */ C(S, { size: 20 }),
|
|
87
|
+
description: A("devportal.configured", "Configured")
|
|
70
88
|
})
|
|
71
89
|
]
|
|
72
90
|
})
|
|
73
91
|
}),
|
|
74
|
-
/* @__PURE__ */
|
|
75
|
-
title:
|
|
92
|
+
/* @__PURE__ */ C(r, {
|
|
93
|
+
title: A("devportal.usageOverview", "Usage Overview"),
|
|
76
94
|
"data-tour": "devportal-dashboard-usage-overview",
|
|
77
|
-
children: /* @__PURE__ */
|
|
95
|
+
children: /* @__PURE__ */ w(a, {
|
|
78
96
|
columns: 4,
|
|
79
97
|
children: [
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
-
title:
|
|
82
|
-
value:
|
|
83
|
-
icon: /* @__PURE__ */
|
|
98
|
+
/* @__PURE__ */ C(i, {
|
|
99
|
+
title: A("devportal.apiCalls", "API Calls"),
|
|
100
|
+
value: L ? /* @__PURE__ */ C(v, { className: "h-5 w-5 animate-spin" }) : F.totalApiCalls > 1e6 ? `${(F.totalApiCalls / 1e6).toFixed(1)}M` : F.totalApiCalls > 1e3 ? `${(F.totalApiCalls / 1e3).toFixed(1)}K` : F.totalApiCalls.toString(),
|
|
101
|
+
icon: /* @__PURE__ */ C(f, { size: 20 }),
|
|
84
102
|
trend: void 0
|
|
85
103
|
}),
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
title:
|
|
88
|
-
value:
|
|
89
|
-
icon: /* @__PURE__ */
|
|
104
|
+
/* @__PURE__ */ C(i, {
|
|
105
|
+
title: A("devportal.activeInstalls", "Active Installs"),
|
|
106
|
+
value: L ? /* @__PURE__ */ C(v, { className: "h-5 w-5 animate-spin" }) : F.activeInstalls > 1e3 ? `${(F.activeInstalls / 1e3).toFixed(1)}K` : F.activeInstalls.toString(),
|
|
107
|
+
icon: /* @__PURE__ */ C(x, { size: 20 }),
|
|
90
108
|
trend: void 0
|
|
91
109
|
}),
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
title:
|
|
94
|
-
value:
|
|
95
|
-
icon: /* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ C(i, {
|
|
111
|
+
title: A("devportal.monthlyRevenue", "Monthly Revenue"),
|
|
112
|
+
value: L ? /* @__PURE__ */ C(v, { className: "h-5 w-5 animate-spin" }) : `$${F.monthlyRevenue.toLocaleString()}`,
|
|
113
|
+
icon: /* @__PURE__ */ C(g, { size: 20 }),
|
|
96
114
|
trend: void 0
|
|
97
115
|
}),
|
|
98
|
-
/* @__PURE__ */
|
|
99
|
-
title:
|
|
100
|
-
value: `${
|
|
101
|
-
icon: /* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ C(i, {
|
|
117
|
+
title: A("devportal.errorRate", "Error Rate"),
|
|
118
|
+
value: `${F.errorRate}%`,
|
|
119
|
+
icon: /* @__PURE__ */ C(b, { size: 20 }),
|
|
102
120
|
trend: void 0
|
|
103
121
|
})
|
|
104
122
|
]
|
|
105
123
|
})
|
|
106
124
|
}),
|
|
107
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ w("div", {
|
|
108
126
|
className: "grid gap-6 lg:grid-cols-2",
|
|
109
|
-
children: [/* @__PURE__ */
|
|
127
|
+
children: [/* @__PURE__ */ C(r, {
|
|
110
128
|
"data-tour": "devportal-dashboard-recent-apps",
|
|
111
|
-
title:
|
|
112
|
-
actions: /* @__PURE__ */
|
|
113
|
-
onClick: () =>
|
|
129
|
+
title: A("devportal.recentApplications", "Recent Applications"),
|
|
130
|
+
actions: /* @__PURE__ */ w("button", {
|
|
131
|
+
onClick: () => I("/apps"),
|
|
114
132
|
className: "text-sm text-primary hover:underline flex items-center gap-1",
|
|
115
133
|
children: [
|
|
116
|
-
|
|
134
|
+
A("devportal.viewAll", "View all"),
|
|
117
135
|
" ",
|
|
118
|
-
/* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ C(m, { size: 14 })
|
|
119
137
|
]
|
|
120
138
|
}),
|
|
121
|
-
children:
|
|
139
|
+
children: L ? /* @__PURE__ */ C("div", {
|
|
122
140
|
className: "flex items-center justify-center py-8",
|
|
123
|
-
children: /* @__PURE__ */
|
|
124
|
-
}) :
|
|
141
|
+
children: /* @__PURE__ */ C(v, { className: "h-6 w-6 animate-spin text-muted-foreground" })
|
|
142
|
+
}) : P.length > 0 ? /* @__PURE__ */ C("div", {
|
|
125
143
|
className: "space-y-2",
|
|
126
|
-
children:
|
|
144
|
+
children: P.slice(0, 3).map((e) => /* @__PURE__ */ C(o, {
|
|
127
145
|
app: e,
|
|
128
|
-
onClick: () =>
|
|
146
|
+
onClick: () => I(`/apps/${e.id}`)
|
|
129
147
|
}, e.id))
|
|
130
|
-
}) : /* @__PURE__ */
|
|
131
|
-
icon: /* @__PURE__ */
|
|
132
|
-
title:
|
|
133
|
-
description:
|
|
134
|
-
action: /* @__PURE__ */
|
|
135
|
-
onClick: () =>
|
|
148
|
+
}) : /* @__PURE__ */ C(t, {
|
|
149
|
+
icon: /* @__PURE__ */ C(p, { size: 24 }),
|
|
150
|
+
title: A("devportal.noApplicationsYet", "No applications yet"),
|
|
151
|
+
description: A("devportal.createFirstApplicationToGetStarted", "Create your first application to get started"),
|
|
152
|
+
action: /* @__PURE__ */ w("button", {
|
|
153
|
+
onClick: () => I("/apps/new"),
|
|
136
154
|
className: "inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90",
|
|
137
|
-
children: [/* @__PURE__ */
|
|
155
|
+
children: [/* @__PURE__ */ C(y, { size: 16 }), A("devportal.createApp", "Create App")]
|
|
138
156
|
})
|
|
139
157
|
})
|
|
140
|
-
}), /* @__PURE__ */
|
|
141
|
-
title:
|
|
158
|
+
}), /* @__PURE__ */ C(r, {
|
|
159
|
+
title: A("devportal.quickActions", "Quick Actions"),
|
|
142
160
|
"data-tour": "devportal-dashboard-quick-actions",
|
|
143
|
-
children: /* @__PURE__ */
|
|
161
|
+
children: /* @__PURE__ */ w("div", {
|
|
144
162
|
className: "grid gap-3",
|
|
145
163
|
children: [
|
|
146
|
-
/* @__PURE__ */
|
|
147
|
-
title:
|
|
148
|
-
description:
|
|
149
|
-
icon: /* @__PURE__ */
|
|
150
|
-
onClick: () =>
|
|
164
|
+
/* @__PURE__ */ C(E, {
|
|
165
|
+
title: A("devportal.createNewApp", "Create New App"),
|
|
166
|
+
description: A("devportal.startBuildingANewApplication", "Start building a new application"),
|
|
167
|
+
icon: /* @__PURE__ */ C(p, { size: 20 }),
|
|
168
|
+
onClick: () => I("/apps/new")
|
|
151
169
|
}),
|
|
152
|
-
/* @__PURE__ */
|
|
153
|
-
title:
|
|
154
|
-
description:
|
|
155
|
-
icon: /* @__PURE__ */
|
|
156
|
-
onClick: () =>
|
|
170
|
+
/* @__PURE__ */ C(E, {
|
|
171
|
+
title: A("devportal.createOrganization", "Create Organization"),
|
|
172
|
+
description: A("devportal.setUpATeamToCollaborate", "Set up a team to collaborate"),
|
|
173
|
+
icon: /* @__PURE__ */ C(h, { size: 20 }),
|
|
174
|
+
onClick: () => I("/organizations/new")
|
|
157
175
|
}),
|
|
158
|
-
/* @__PURE__ */
|
|
159
|
-
title:
|
|
160
|
-
description:
|
|
161
|
-
icon: /* @__PURE__ */
|
|
162
|
-
onClick: () =>
|
|
176
|
+
/* @__PURE__ */ C(E, {
|
|
177
|
+
title: A("devportal.generateApiKey", "Generate API Key"),
|
|
178
|
+
description: A("devportal.createCredentialsForYourApps", "Create credentials for your apps"),
|
|
179
|
+
icon: /* @__PURE__ */ C(_, { size: 20 }),
|
|
180
|
+
onClick: () => I("/api-keys")
|
|
163
181
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
-
title:
|
|
166
|
-
description:
|
|
167
|
-
icon: /* @__PURE__ */ S
|
|
168
|
-
onClick: () =>
|
|
182
|
+
/* @__PURE__ */ C(E, {
|
|
183
|
+
title: A("devportal.configureWebhooks", "Configure Webhooks"),
|
|
184
|
+
description: A("devportal.setUpEventNotifications", "Set up event notifications"),
|
|
185
|
+
icon: /* @__PURE__ */ C(S, { size: 20 }),
|
|
186
|
+
onClick: () => I("/webhooks")
|
|
169
187
|
})
|
|
170
188
|
]
|
|
171
189
|
})
|
|
172
190
|
})]
|
|
173
191
|
}),
|
|
174
|
-
|
|
192
|
+
L ? /* @__PURE__ */ C(r, {
|
|
175
193
|
"data-tour": "devportal-dashboard-organizations",
|
|
176
|
-
title:
|
|
177
|
-
children: /* @__PURE__ */
|
|
194
|
+
title: A("devportal.yourOrganizations", "Your Organizations"),
|
|
195
|
+
children: /* @__PURE__ */ C("div", {
|
|
178
196
|
className: "flex items-center justify-center py-8",
|
|
179
|
-
children: /* @__PURE__ */
|
|
197
|
+
children: /* @__PURE__ */ C(v, { className: "h-6 w-6 animate-spin text-muted-foreground" })
|
|
180
198
|
})
|
|
181
|
-
}) :
|
|
182
|
-
title:
|
|
183
|
-
actions: /* @__PURE__ */
|
|
184
|
-
onClick: () =>
|
|
199
|
+
}) : N.length > 0 ? /* @__PURE__ */ C(r, {
|
|
200
|
+
title: A("devportal.yourOrganizations", "Your Organizations"),
|
|
201
|
+
actions: /* @__PURE__ */ w("button", {
|
|
202
|
+
onClick: () => I("/organizations"),
|
|
185
203
|
className: "text-sm text-primary hover:underline flex items-center gap-1",
|
|
186
204
|
children: [
|
|
187
|
-
|
|
205
|
+
A("devportal.viewAll", "View all"),
|
|
188
206
|
" ",
|
|
189
|
-
/* @__PURE__ */
|
|
207
|
+
/* @__PURE__ */ C(m, { size: 14 })
|
|
190
208
|
]
|
|
191
209
|
}),
|
|
192
|
-
children: /* @__PURE__ */
|
|
210
|
+
children: /* @__PURE__ */ C("div", {
|
|
193
211
|
className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
194
|
-
children:
|
|
212
|
+
children: N.slice(0, 3).map((e) => /* @__PURE__ */ C(D, {
|
|
195
213
|
org: e,
|
|
196
|
-
onClick: () =>
|
|
214
|
+
onClick: () => I(`/organizations/${e.id}`)
|
|
197
215
|
}, e.id))
|
|
198
216
|
})
|
|
199
217
|
}) : null
|
|
200
218
|
]
|
|
201
219
|
})
|
|
202
220
|
});
|
|
203
|
-
},
|
|
221
|
+
}, E = ({ title: e, description: t, icon: n, onClick: r }) => /* @__PURE__ */ w("button", {
|
|
204
222
|
onClick: r,
|
|
205
223
|
className: "flex items-center gap-4 rounded-lg border bg-card p-4 text-left hover:bg-accent transition-colors",
|
|
206
|
-
children: [/* @__PURE__ */
|
|
224
|
+
children: [/* @__PURE__ */ C("div", {
|
|
207
225
|
className: "rounded-lg bg-primary/10 p-2 text-primary",
|
|
208
226
|
children: n
|
|
209
|
-
}), /* @__PURE__ */
|
|
227
|
+
}), /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
|
|
210
228
|
className: "font-medium",
|
|
211
229
|
children: e
|
|
212
|
-
}), /* @__PURE__ */
|
|
230
|
+
}), /* @__PURE__ */ C("p", {
|
|
213
231
|
className: "text-sm text-muted-foreground",
|
|
214
232
|
children: t
|
|
215
233
|
})] })]
|
|
216
|
-
}),
|
|
217
|
-
let { t: n } =
|
|
234
|
+
}), D = ({ org: e, onClick: t }) => {
|
|
235
|
+
let { t: n } = d(), r = (e, t) => {
|
|
218
236
|
let r = n(e);
|
|
219
237
|
return r === e ? t : r;
|
|
220
238
|
};
|
|
221
|
-
return /* @__PURE__ */
|
|
239
|
+
return /* @__PURE__ */ w("button", {
|
|
222
240
|
onClick: t,
|
|
223
241
|
className: "rounded-lg border bg-card p-4 text-left hover:bg-accent transition-colors",
|
|
224
|
-
children: [/* @__PURE__ */
|
|
242
|
+
children: [/* @__PURE__ */ w("div", {
|
|
225
243
|
className: "flex items-center gap-3",
|
|
226
|
-
children: [e.logoUrl ? /* @__PURE__ */
|
|
244
|
+
children: [e.logoUrl ? /* @__PURE__ */ C("img", {
|
|
227
245
|
src: e.logoUrl,
|
|
228
246
|
alt: e.name,
|
|
229
247
|
className: "h-10 w-10 rounded-lg object-cover"
|
|
230
|
-
}) : /* @__PURE__ */
|
|
248
|
+
}) : /* @__PURE__ */ C("div", {
|
|
231
249
|
className: "flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary",
|
|
232
|
-
children: /* @__PURE__ */
|
|
233
|
-
}), /* @__PURE__ */
|
|
250
|
+
children: /* @__PURE__ */ C(h, { size: 20 })
|
|
251
|
+
}), /* @__PURE__ */ w("div", {
|
|
234
252
|
className: "flex-1 min-w-0",
|
|
235
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ C("p", {
|
|
236
254
|
className: "font-medium truncate",
|
|
237
255
|
children: e.name
|
|
238
|
-
}), /* @__PURE__ */
|
|
256
|
+
}), /* @__PURE__ */ w("p", {
|
|
239
257
|
className: "text-sm text-muted-foreground",
|
|
240
258
|
children: [
|
|
241
259
|
e.publishedApps,
|
|
@@ -244,13 +262,13 @@ var w = () => {
|
|
|
244
262
|
]
|
|
245
263
|
})]
|
|
246
264
|
})]
|
|
247
|
-
}), /* @__PURE__ */
|
|
265
|
+
}), /* @__PURE__ */ w("div", {
|
|
248
266
|
className: "mt-3 flex gap-4 text-sm text-muted-foreground",
|
|
249
|
-
children: [/* @__PURE__ */
|
|
267
|
+
children: [/* @__PURE__ */ w("span", { children: [
|
|
250
268
|
(e.totalInstalls || 0).toLocaleString(),
|
|
251
269
|
" ",
|
|
252
270
|
r("devportal.installs", "installs")
|
|
253
|
-
] }), /* @__PURE__ */
|
|
271
|
+
] }), /* @__PURE__ */ w("span", { children: [
|
|
254
272
|
"$",
|
|
255
273
|
(e.totalRevenue || 0).toLocaleString(),
|
|
256
274
|
" ",
|
|
@@ -260,6 +278,6 @@ var w = () => {
|
|
|
260
278
|
});
|
|
261
279
|
};
|
|
262
280
|
//#endregion
|
|
263
|
-
export {
|
|
281
|
+
export { T as DashboardPage };
|
|
264
282
|
|
|
265
283
|
//# sourceMappingURL=DashboardPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/devportal/pages/DashboardPage.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n AppWindow,\n Building2,\n Key,\n Webhook,\n TrendingUp,\n Users,\n DollarSign,\n Activity,\n Plus,\n ArrowRight,\n Loader2,\n} from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { AppListItem } from \"../components/AppCard\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport type { Application, DeveloperOrganization } from \"../types\";\nimport {\n useGetDevportalDashboardBootstrapQuery,\n type OrganizationFieldsFragment,\n type ApplicationFieldsFragment,\n} from \"../hooks\";\n\n/**\n * Developer Portal Dashboard Page\n *\n * Shows an overview of the developer's applications, organizations,\n * and key metrics using real data from the GraphQL API.\n */\nexport const DashboardPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n // Fetch dashboard bootstrap in a single global query\n const { data, loading } = useGetDevportalDashboardBootstrapQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations: OrganizationFieldsFragment[] =\n data?.myDeveloperOrganizations ?? [];\n const applications: ApplicationFieldsFragment[] =\n data?.applications?.edges?.map(\n (e: { node: ApplicationFieldsFragment }) => e.node,\n ) ?? [];\n\n // Calculate aggregate stats\n const stats = {\n totalApps: data?.applications?.totalCount ?? 0,\n totalOrgs: organizations.length,\n totalApiKeys: 0,\n totalWebhooks: 0,\n totalApiCalls: organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + parseInt(org.totalApiCalls || \"0\"),\n 0,\n ),\n activeInstalls: organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.activeInstalls || 0),\n 0,\n ),\n monthlyRevenue: organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.totalRevenue || 0),\n 0,\n ),\n errorRate: 0,\n };\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const isLoading = loading;\n\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_READ}>\n <PageLayout\n title={tr(\"devportal.developerPortal\", \"Developer Portal\")}\n description={tr(\n \"devportal.buildManageMonitor\",\n \"Build, manage, and monitor your applications\",\n )}\n actions={\n <button\n data-tour=\"devportal-dashboard-create-app-button\"\n onClick={() => handleNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n }\n >\n {/* Stats Overview */}\n <PageSection data-tour=\"devportal-dashboard-stats-overview\">\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.totalApps\", \"Total Apps\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n stats.totalApps\n )\n }\n icon={<AppWindow size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.organizations\", \"Organizations\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n stats.totalOrgs\n )\n }\n icon={<Building2 size={20} />}\n />\n <StatCard\n title={tr(\"devportal.apiKeys\", \"API Keys\")}\n value={stats.totalApiKeys}\n icon={<Key size={20} />}\n description={tr(\"devportal.activeKeys\", \"Active keys\")}\n />\n <StatCard\n title={tr(\"devportal.webhooks\", \"Webhooks\")}\n value={stats.totalWebhooks}\n icon={<Webhook size={20} />}\n description={tr(\"devportal.configured\", \"Configured\")}\n />\n </StatCardGrid>\n </PageSection>\n\n {/* Usage Stats */}\n <PageSection\n title={tr(\"devportal.usageOverview\", \"Usage Overview\")}\n data-tour=\"devportal-dashboard-usage-overview\"\n >\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.apiCalls\", \"API Calls\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : stats.totalApiCalls > 1000000 ? (\n `${(stats.totalApiCalls / 1000000).toFixed(1)}M`\n ) : stats.totalApiCalls > 1000 ? (\n `${(stats.totalApiCalls / 1000).toFixed(1)}K`\n ) : (\n stats.totalApiCalls.toString()\n )\n }\n icon={<Activity size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.activeInstalls\", \"Active Installs\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : stats.activeInstalls > 1000 ? (\n `${(stats.activeInstalls / 1000).toFixed(1)}K`\n ) : (\n stats.activeInstalls.toString()\n )\n }\n icon={<Users size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.monthlyRevenue\", \"Monthly Revenue\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n `$${stats.monthlyRevenue.toLocaleString()}`\n )\n }\n icon={<DollarSign size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.errorRate\", \"Error Rate\")}\n value={`${stats.errorRate}%`}\n icon={<TrendingUp size={20} />}\n trend={undefined}\n />\n </StatCardGrid>\n </PageSection>\n\n {/* Quick Actions & Recent Items */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n {/* Recent Apps */}\n <PageSection\n data-tour=\"devportal-dashboard-recent-apps\"\n title={tr(\"devportal.recentApplications\", \"Recent Applications\")}\n actions={\n <button\n onClick={() => handleNavigate(\"/apps\")}\n className=\"text-sm text-primary hover:underline flex items-center gap-1\"\n >\n {tr(\"devportal.viewAll\", \"View all\")} <ArrowRight size={14} />\n </button>\n }\n >\n {isLoading ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n ) : applications.length > 0 ? (\n <div className=\"space-y-2\">\n {applications\n .slice(0, 3)\n .map((app: ApplicationFieldsFragment) => (\n <AppListItem\n key={app.id}\n app={app as Application}\n onClick={() => handleNavigate(`/apps/${app.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<AppWindow size={24} />}\n title={tr(\"devportal.noApplicationsYet\", \"No applications yet\")}\n description={tr(\n \"devportal.createFirstApplicationToGetStarted\",\n \"Create your first application to get started\",\n )}\n action={\n <button\n onClick={() => handleNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n }\n />\n )}\n </PageSection>\n\n {/* Quick Actions */}\n <PageSection\n title={tr(\"devportal.quickActions\", \"Quick Actions\")}\n data-tour=\"devportal-dashboard-quick-actions\"\n >\n <div className=\"grid gap-3\">\n <QuickActionCard\n title={tr(\"devportal.createNewApp\", \"Create New App\")}\n description={tr(\n \"devportal.startBuildingANewApplication\",\n \"Start building a new application\",\n )}\n icon={<AppWindow size={20} />}\n onClick={() => handleNavigate(\"/apps/new\")}\n />\n <QuickActionCard\n title={tr(\n \"devportal.createOrganization\",\n \"Create Organization\",\n )}\n description={tr(\n \"devportal.setUpATeamToCollaborate\",\n \"Set up a team to collaborate\",\n )}\n icon={<Building2 size={20} />}\n onClick={() => handleNavigate(\"/organizations/new\")}\n />\n <QuickActionCard\n title={tr(\"devportal.generateApiKey\", \"Generate API Key\")}\n description={tr(\n \"devportal.createCredentialsForYourApps\",\n \"Create credentials for your apps\",\n )}\n icon={<Key size={20} />}\n onClick={() => handleNavigate(\"/api-keys\")}\n />\n <QuickActionCard\n title={tr(\"devportal.configureWebhooks\", \"Configure Webhooks\")}\n description={tr(\n \"devportal.setUpEventNotifications\",\n \"Set up event notifications\",\n )}\n icon={<Webhook size={20} />}\n onClick={() => handleNavigate(\"/webhooks\")}\n />\n </div>\n </PageSection>\n </div>\n\n {/* Organizations */}\n {isLoading ? (\n <PageSection\n data-tour=\"devportal-dashboard-organizations\"\n title={tr(\"devportal.yourOrganizations\", \"Your Organizations\")}\n >\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n </PageSection>\n ) : organizations.length > 0 ? (\n <PageSection\n title={tr(\"devportal.yourOrganizations\", \"Your Organizations\")}\n actions={\n <button\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"text-sm text-primary hover:underline flex items-center gap-1\"\n >\n {tr(\"devportal.viewAll\", \"View all\")} <ArrowRight size={14} />\n </button>\n }\n >\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {organizations\n .slice(0, 3)\n .map((org: OrganizationFieldsFragment) => (\n <OrgCard\n key={org.id}\n org={org as DeveloperOrganization}\n onClick={() => handleNavigate(`/organizations/${org.id}`)}\n />\n ))}\n </div>\n </PageSection>\n ) : null}\n </PageLayout>\n </PermissionGuard>\n );\n};\n\n// Quick action card component\nconst QuickActionCard: FC<{\n title: string;\n description: string;\n icon: React.ReactNode;\n onClick: () => void;\n}> = ({ title, description, icon, onClick }) => (\n <button\n onClick={onClick}\n className=\"flex items-center gap-4 rounded-lg border bg-card p-4 text-left hover:bg-accent transition-colors\"\n >\n <div className=\"rounded-lg bg-primary/10 p-2 text-primary\">{icon}</div>\n <div>\n <p className=\"font-medium\">{title}</p>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n </button>\n);\n\n// Organization card component\nconst OrgCard: FC<{\n org: DeveloperOrganization;\n onClick: () => void;\n}> = ({ org, onClick }) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n return (\n <button\n onClick={onClick}\n className=\"rounded-lg border bg-card p-4 text-left hover:bg-accent transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n {org.logoUrl ? (\n <img\n src={org.logoUrl}\n alt={org.name}\n className=\"h-10 w-10 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Building2 size={20} />\n </div>\n )}\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{org.name}</p>\n <p className=\"text-sm text-muted-foreground\">\n {org.publishedApps}{\" \"}\n {tr(\"devportal.appsPublished\", \"apps published\")}\n </p>\n </div>\n </div>\n <div className=\"mt-3 flex gap-4 text-sm text-muted-foreground\">\n <span>\n {(org.totalInstalls || 0).toLocaleString()}{\" \"}\n {tr(\"devportal.installs\", \"installs\")}\n </span>\n <span>\n ${(org.totalRevenue || 0).toLocaleString()}{\" \"}\n {tr(\"devportal.revenue\", \"revenue\")}\n </span>\n </div>\n </button>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAmCA,IAAa,UAA0B;CACrC,IAAM,EAAE,aAAU,gBAAa,GAAc,EACvC,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAI9B,EAAE,SAAM,eAAY,EAAuC,EAC/D,aAAa,qBACd,CAAC,EAEI,IACJ,GAAM,4BAA4B,EAAE,EAChC,IACJ,GAAM,cAAc,OAAO,KACxB,MAA2C,EAAE,KAC/C,IAAI,EAAE,EAGH,IAAQ;EACZ,WAAW,GAAM,cAAc,cAAc;EAC7C,WAAW,EAAc;EACzB,cAAc;EACd,eAAe;EACf,eAAe,EAAc,QAC1B,GAAa,MACZ,IAAM,SAAS,EAAI,iBAAiB,IAAI,EAC1C,EACD;EACD,gBAAgB,EAAc,QAC3B,GAAa,MACZ,KAAO,EAAI,kBAAkB,IAC/B,EACD;EACD,gBAAgB,EAAc,QAC3B,GAAa,MACZ,KAAO,EAAI,gBAAgB,IAC7B,EACD;EACD,WAAW;EACZ,EAEK,KAAkB,MAAiB;AACvC,MAAW,GAAG,IAAW,IAAO;IAG5B,IAAY;AAElB,QACE,kBAAC,GAAD;EAAiB,YAAY,EAAsB;YACjD,kBAAC,GAAD;GACE,OAAO,EAAG,6BAA6B,mBAAmB;GAC1D,aAAa,EACX,gCACA,+CACD;GACD,SACE,kBAAC,UAAD;IACE,aAAU;IACV,eAAe,EAAe,YAAY;IAC1C,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,uBAAuB,aAAa,CACjC;;aAdb;IAkBE,kBAAC,GAAD;KAAa,aAAU;eACrB,kBAAC,GAAD;MAAc,SAAS;gBAAvB;OACE,kBAAC,GAAD;QACE,OAAO,EAAG,uBAAuB,aAAa;QAC9C,OACE,IACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAE5C,EAAM;QAGV,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;QAC7B,OAAO,KAAA;QACP,CAAA;OACF,kBAAC,GAAD;QACE,OAAO,EAAG,2BAA2B,gBAAgB;QACrD,OACE,IACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAE5C,EAAM;QAGV,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;QAC7B,CAAA;OACF,kBAAC,GAAD;QACE,OAAO,EAAG,qBAAqB,WAAW;QAC1C,OAAO,EAAM;QACb,MAAM,kBAAC,GAAD,EAAK,MAAM,IAAM,CAAA;QACvB,aAAa,EAAG,wBAAwB,cAAc;QACtD,CAAA;OACF,kBAAC,GAAD;QACE,OAAO,EAAG,sBAAsB,WAAW;QAC3C,OAAO,EAAM;QACb,MAAM,kBAAC,GAAD,EAAS,MAAM,IAAM,CAAA;QAC3B,aAAa,EAAG,wBAAwB,aAAa;QACrD,CAAA;OACW;;KACH,CAAA;IAGd,kBAAC,GAAD;KACE,OAAO,EAAG,2BAA2B,iBAAiB;KACtD,aAAU;eAEV,kBAAC,GAAD;MAAc,SAAS;gBAAvB;OACE,kBAAC,GAAD;QACE,OAAO,EAAG,sBAAsB,YAAY;QAC5C,OACE,IACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAC1C,EAAM,gBAAgB,MACxB,IAAI,EAAM,gBAAgB,KAAS,QAAQ,EAAE,CAAC,KAC5C,EAAM,gBAAgB,MACxB,IAAI,EAAM,gBAAgB,KAAM,QAAQ,EAAE,CAAC,KAE3C,EAAM,cAAc,UAAU;QAGlC,MAAM,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;QAC5B,OAAO,KAAA;QACP,CAAA;OACF,kBAAC,GAAD;QACE,OAAO,EAAG,4BAA4B,kBAAkB;QACxD,OACE,IACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAC1C,EAAM,iBAAiB,MACzB,IAAI,EAAM,iBAAiB,KAAM,QAAQ,EAAE,CAAC,KAE5C,EAAM,eAAe,UAAU;QAGnC,MAAM,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA;QACzB,OAAO,KAAA;QACP,CAAA;OACF,kBAAC,GAAD;QACE,OAAO,EAAG,4BAA4B,kBAAkB;QACxD,OACE,IACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAE5C,IAAI,EAAM,eAAe,gBAAgB;QAG7C,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;QAC9B,OAAO,KAAA;QACP,CAAA;OACF,kBAAC,GAAD;QACE,OAAO,EAAG,uBAAuB,aAAa;QAC9C,OAAO,GAAG,EAAM,UAAU;QAC1B,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;QAC9B,OAAO,KAAA;QACP,CAAA;OACW;;KACH,CAAA;IAGd,kBAAC,OAAD;KAAK,WAAU;eAAf,CAEE,kBAAC,GAAD;MACE,aAAU;MACV,OAAO,EAAG,gCAAgC,sBAAsB;MAChE,SACE,kBAAC,UAAD;OACE,eAAe,EAAe,QAAQ;OACtC,WAAU;iBAFZ;QAIG,EAAG,qBAAqB,WAAW;QAAC;QAAC,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;QACvD;;gBAGV,IACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAS,WAAU,8CAA+C,CAAA;OAC9D,CAAA,GACJ,EAAa,SAAS,IACxB,kBAAC,OAAD;OAAK,WAAU;iBACZ,EACE,MAAM,GAAG,EAAE,CACX,KAAK,MACJ,kBAAC,GAAD;QAEO;QACL,eAAe,EAAe,SAAS,EAAI,KAAK;QAChD,EAHK,EAAI,GAGT,CACF;OACA,CAAA,GAEN,kBAAC,GAAD;OACE,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;OAC7B,OAAO,EAAG,+BAA+B,sBAAsB;OAC/D,aAAa,EACX,gDACA,+CACD;OACD,QACE,kBAAC,UAAD;QACE,eAAe,EAAe,YAAY;QAC1C,WAAU;kBAFZ,CAIE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,uBAAuB,aAAa,CACjC;;OAEX,CAAA;MAEQ,CAAA,EAGd,kBAAC,GAAD;MACE,OAAO,EAAG,0BAA0B,gBAAgB;MACpD,aAAU;gBAEV,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD;SACE,OAAO,EAAG,0BAA0B,iBAAiB;SACrD,aAAa,EACX,0CACA,mCACD;SACD,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;SAC7B,eAAe,EAAe,YAAY;SAC1C,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EACL,gCACA,sBACD;SACD,aAAa,EACX,qCACA,+BACD;SACD,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;SAC7B,eAAe,EAAe,qBAAqB;SACnD,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAG,4BAA4B,mBAAmB;SACzD,aAAa,EACX,0CACA,mCACD;SACD,MAAM,kBAAC,GAAD,EAAK,MAAM,IAAM,CAAA;SACvB,eAAe,EAAe,YAAY;SAC1C,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAG,+BAA+B,qBAAqB;SAC9D,aAAa,EACX,qCACA,6BACD;SACD,MAAM,kBAAC,GAAD,EAAS,MAAM,IAAM,CAAA;SAC3B,eAAe,EAAe,YAAY;SAC1C,CAAA;QACE;;MACM,CAAA,CACV;;IAGL,IACC,kBAAC,GAAD;KACE,aAAU;KACV,OAAO,EAAG,+BAA+B,qBAAqB;eAE9D,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,WAAU,8CAA+C,CAAA;MAC9D,CAAA;KACM,CAAA,GACZ,EAAc,SAAS,IACzB,kBAAC,GAAD;KACE,OAAO,EAAG,+BAA+B,qBAAqB;KAC9D,SACE,kBAAC,UAAD;MACE,eAAe,EAAe,iBAAiB;MAC/C,WAAU;gBAFZ;OAIG,EAAG,qBAAqB,WAAW;OAAC;OAAC,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;OACvD;;eAGX,kBAAC,OAAD;MAAK,WAAU;gBACZ,EACE,MAAM,GAAG,EAAE,CACX,KAAK,MACJ,kBAAC,GAAD;OAEO;OACL,eAAe,EAAe,kBAAkB,EAAI,KAAK;OACzD,EAHK,EAAI,GAGT,CACF;MACA,CAAA;KACM,CAAA,GACZ;IACO;;EACG,CAAA;GAKhB,KAKA,EAAE,UAAO,gBAAa,SAAM,iBAChC,kBAAC,UAAD;CACW;CACT,WAAU;WAFZ,CAIE,kBAAC,OAAD;EAAK,WAAU;YAA6C;EAAW,CAAA,EACvE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;EAAG,WAAU;YAAe;EAAU,CAAA,EACtC,kBAAC,KAAD;EAAG,WAAU;YAAiC;EAAgB,CAAA,CAC1D,EAAA,CAAA,CACC;IAIL,KAGA,EAAE,QAAK,iBAAc;CACzB,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;;AAEpC,QACE,kBAAC,UAAD;EACW;EACT,WAAU;YAFZ,CAIE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,EAAI,UACH,kBAAC,OAAD;IACE,KAAK,EAAI;IACT,KAAK,EAAI;IACT,WAAU;IACV,CAAA,GAEF,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;IACnB,CAAA,EAER,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAwB,EAAI;KAAS,CAAA,EAClD,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAI;MAAe;MACnB,EAAG,2BAA2B,iBAAiB;MAC9C;OACA;MACF;MACN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,QAAD,EAAA,UAAA;KACI,EAAI,iBAAiB,GAAG,gBAAgB;IAAE;IAC3C,EAAG,sBAAsB,WAAW;IAChC,EAAA,CAAA,EACP,kBAAC,QAAD,EAAA,UAAA;IAAM;KACD,EAAI,gBAAgB,GAAG,gBAAgB;IAAE;IAC3C,EAAG,qBAAqB,UAAU;IAC9B,EAAA,CAAA,CACH;KACC"}
|
|
1
|
+
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/devportal/pages/DashboardPage.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport { useEffect } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n AppWindow,\n Building2,\n Key,\n Webhook,\n TrendingUp,\n Users,\n DollarSign,\n Activity,\n Plus,\n ArrowRight,\n Loader2,\n} from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { AppListItem } from \"../components/AppCard\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport type { Application, DeveloperOrganization } from \"../types\";\nimport {\n useGetDevportalDashboardBootstrapQuery,\n type OrganizationFieldsFragment,\n type ApplicationFieldsFragment,\n} from \"../hooks\";\n\n/**\n * Developer Portal Dashboard Page\n *\n * Shows an overview of the developer's applications, organizations,\n * and key metrics using real data from the GraphQL API.\n */\nexport const DashboardPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n // Fetch dashboard bootstrap in a single global query\n const { data, loading } = useGetDevportalDashboardBootstrapQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations: OrganizationFieldsFragment[] =\n data?.myDeveloperOrganizations ?? [];\n\n // First-time users: redirect to setup wizard when no org exists and they\n // haven't already dismissed the wizard in this browser.\n useEffect(() => {\n if (loading || !data) return;\n if (organizations.length > 0) return;\n try {\n if (localStorage.getItem(\"devportal_setup_dismissed\")) return;\n } catch {\n // localStorage unavailable — don't redirect\n return;\n }\n navigate?.(`${basePath}/setup`);\n }, [loading, data, organizations.length, navigate, basePath]);\n const applications: ApplicationFieldsFragment[] =\n data?.applications?.edges?.map(\n (e: { node: ApplicationFieldsFragment }) => e.node,\n ) ?? [];\n\n // Calculate aggregate stats\n const stats = {\n totalApps: data?.applications?.totalCount ?? 0,\n totalOrgs: organizations.length,\n totalApiKeys: 0,\n totalWebhooks: 0,\n totalApiCalls: organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + parseInt(org.totalApiCalls || \"0\"),\n 0,\n ),\n activeInstalls: organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.activeInstalls || 0),\n 0,\n ),\n monthlyRevenue: organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.totalRevenue || 0),\n 0,\n ),\n errorRate: 0,\n };\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const isLoading = loading;\n\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_READ}>\n <PageLayout\n title={tr(\"devportal.developerPortal\", \"Developer Portal\")}\n description={tr(\n \"devportal.buildManageMonitor\",\n \"Build, manage, and monitor your applications\",\n )}\n actions={\n <button\n data-tour=\"devportal-dashboard-create-app-button\"\n onClick={() => handleNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n }\n >\n {/* Stats Overview */}\n <PageSection data-tour=\"devportal-dashboard-stats-overview\">\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.totalApps\", \"Total Apps\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n stats.totalApps\n )\n }\n icon={<AppWindow size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.organizations\", \"Organizations\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n stats.totalOrgs\n )\n }\n icon={<Building2 size={20} />}\n />\n <StatCard\n title={tr(\"devportal.apiKeys\", \"API Keys\")}\n value={stats.totalApiKeys}\n icon={<Key size={20} />}\n description={tr(\"devportal.activeKeys\", \"Active keys\")}\n />\n <StatCard\n title={tr(\"devportal.webhooks\", \"Webhooks\")}\n value={stats.totalWebhooks}\n icon={<Webhook size={20} />}\n description={tr(\"devportal.configured\", \"Configured\")}\n />\n </StatCardGrid>\n </PageSection>\n\n {/* Usage Stats */}\n <PageSection\n title={tr(\"devportal.usageOverview\", \"Usage Overview\")}\n data-tour=\"devportal-dashboard-usage-overview\"\n >\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.apiCalls\", \"API Calls\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : stats.totalApiCalls > 1000000 ? (\n `${(stats.totalApiCalls / 1000000).toFixed(1)}M`\n ) : stats.totalApiCalls > 1000 ? (\n `${(stats.totalApiCalls / 1000).toFixed(1)}K`\n ) : (\n stats.totalApiCalls.toString()\n )\n }\n icon={<Activity size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.activeInstalls\", \"Active Installs\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : stats.activeInstalls > 1000 ? (\n `${(stats.activeInstalls / 1000).toFixed(1)}K`\n ) : (\n stats.activeInstalls.toString()\n )\n }\n icon={<Users size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.monthlyRevenue\", \"Monthly Revenue\")}\n value={\n isLoading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n `$${stats.monthlyRevenue.toLocaleString()}`\n )\n }\n icon={<DollarSign size={20} />}\n trend={undefined}\n />\n <StatCard\n title={tr(\"devportal.errorRate\", \"Error Rate\")}\n value={`${stats.errorRate}%`}\n icon={<TrendingUp size={20} />}\n trend={undefined}\n />\n </StatCardGrid>\n </PageSection>\n\n {/* Quick Actions & Recent Items */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n {/* Recent Apps */}\n <PageSection\n data-tour=\"devportal-dashboard-recent-apps\"\n title={tr(\"devportal.recentApplications\", \"Recent Applications\")}\n actions={\n <button\n onClick={() => handleNavigate(\"/apps\")}\n className=\"text-sm text-primary hover:underline flex items-center gap-1\"\n >\n {tr(\"devportal.viewAll\", \"View all\")} <ArrowRight size={14} />\n </button>\n }\n >\n {isLoading ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n ) : applications.length > 0 ? (\n <div className=\"space-y-2\">\n {applications\n .slice(0, 3)\n .map((app: ApplicationFieldsFragment) => (\n <AppListItem\n key={app.id}\n app={app as Application}\n onClick={() => handleNavigate(`/apps/${app.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<AppWindow size={24} />}\n title={tr(\"devportal.noApplicationsYet\", \"No applications yet\")}\n description={tr(\n \"devportal.createFirstApplicationToGetStarted\",\n \"Create your first application to get started\",\n )}\n action={\n <button\n onClick={() => handleNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n }\n />\n )}\n </PageSection>\n\n {/* Quick Actions */}\n <PageSection\n title={tr(\"devportal.quickActions\", \"Quick Actions\")}\n data-tour=\"devportal-dashboard-quick-actions\"\n >\n <div className=\"grid gap-3\">\n <QuickActionCard\n title={tr(\"devportal.createNewApp\", \"Create New App\")}\n description={tr(\n \"devportal.startBuildingANewApplication\",\n \"Start building a new application\",\n )}\n icon={<AppWindow size={20} />}\n onClick={() => handleNavigate(\"/apps/new\")}\n />\n <QuickActionCard\n title={tr(\n \"devportal.createOrganization\",\n \"Create Organization\",\n )}\n description={tr(\n \"devportal.setUpATeamToCollaborate\",\n \"Set up a team to collaborate\",\n )}\n icon={<Building2 size={20} />}\n onClick={() => handleNavigate(\"/organizations/new\")}\n />\n <QuickActionCard\n title={tr(\"devportal.generateApiKey\", \"Generate API Key\")}\n description={tr(\n \"devportal.createCredentialsForYourApps\",\n \"Create credentials for your apps\",\n )}\n icon={<Key size={20} />}\n onClick={() => handleNavigate(\"/api-keys\")}\n />\n <QuickActionCard\n title={tr(\"devportal.configureWebhooks\", \"Configure Webhooks\")}\n description={tr(\n \"devportal.setUpEventNotifications\",\n \"Set up event notifications\",\n )}\n icon={<Webhook size={20} />}\n onClick={() => handleNavigate(\"/webhooks\")}\n />\n </div>\n </PageSection>\n </div>\n\n {/* Organizations */}\n {isLoading ? (\n <PageSection\n data-tour=\"devportal-dashboard-organizations\"\n title={tr(\"devportal.yourOrganizations\", \"Your Organizations\")}\n >\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n </PageSection>\n ) : organizations.length > 0 ? (\n <PageSection\n title={tr(\"devportal.yourOrganizations\", \"Your Organizations\")}\n actions={\n <button\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"text-sm text-primary hover:underline flex items-center gap-1\"\n >\n {tr(\"devportal.viewAll\", \"View all\")} <ArrowRight size={14} />\n </button>\n }\n >\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {organizations\n .slice(0, 3)\n .map((org: OrganizationFieldsFragment) => (\n <OrgCard\n key={org.id}\n org={org as DeveloperOrganization}\n onClick={() => handleNavigate(`/organizations/${org.id}`)}\n />\n ))}\n </div>\n </PageSection>\n ) : null}\n </PageLayout>\n </PermissionGuard>\n );\n};\n\n// Quick action card component\nconst QuickActionCard: FC<{\n title: string;\n description: string;\n icon: React.ReactNode;\n onClick: () => void;\n}> = ({ title, description, icon, onClick }) => (\n <button\n onClick={onClick}\n className=\"flex items-center gap-4 rounded-lg border bg-card p-4 text-left hover:bg-accent transition-colors\"\n >\n <div className=\"rounded-lg bg-primary/10 p-2 text-primary\">{icon}</div>\n <div>\n <p className=\"font-medium\">{title}</p>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n </button>\n);\n\n// Organization card component\nconst OrgCard: FC<{\n org: DeveloperOrganization;\n onClick: () => void;\n}> = ({ org, onClick }) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n return (\n <button\n onClick={onClick}\n className=\"rounded-lg border bg-card p-4 text-left hover:bg-accent transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n {org.logoUrl ? (\n <img\n src={org.logoUrl}\n alt={org.name}\n className=\"h-10 w-10 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Building2 size={20} />\n </div>\n )}\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{org.name}</p>\n <p className=\"text-sm text-muted-foreground\">\n {org.publishedApps}{\" \"}\n {tr(\"devportal.appsPublished\", \"apps published\")}\n </p>\n </div>\n </div>\n <div className=\"mt-3 flex gap-4 text-sm text-muted-foreground\">\n <span>\n {(org.totalInstalls || 0).toLocaleString()}{\" \"}\n {tr(\"devportal.installs\", \"installs\")}\n </span>\n <span>\n ${(org.totalRevenue || 0).toLocaleString()}{\" \"}\n {tr(\"devportal.revenue\", \"revenue\")}\n </span>\n </div>\n </button>\n );\n};\n"],"mappings":"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"}
|