@burdenoff/microfe-conversations 2026.624.1 → 2026.625.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/conversations/components/ConversationRow.js +1 -1
- package/dist/conversations/components/ConversationRow.js.map +1 -1
- package/dist/conversations/components/EmptyState.js +15 -9
- package/dist/conversations/components/EmptyState.js.map +1 -1
- package/dist/conversations/components/InboxLayout.js +65 -81
- package/dist/conversations/components/InboxLayout.js.map +1 -1
- package/dist/conversations/pages/AdminConversationsLandingPage.js +56 -46
- package/dist/conversations/pages/AdminConversationsLandingPage.js.map +1 -1
- package/dist/conversations/pages/ConversationAdminPages.js +182 -154
- package/dist/conversations/pages/ConversationAdminPages.js.map +1 -1
- package/dist/conversations/pages/ConversationDetailPage.js +3 -3
- package/dist/conversations/pages/ConversationDetailPage.js.map +1 -1
- package/dist/conversations/pages/ConversationListPage.js +64 -58
- package/dist/conversations/pages/ConversationListPage.js.map +1 -1
- package/dist/conversations/pages/ConversationsSettingsPage.js +87 -83
- package/dist/conversations/pages/ConversationsSettingsPage.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminConversationsLandingPage.js","names":[],"sources":["../../../src/conversations/pages/AdminConversationsLandingPage.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useMemo } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport {\n MessageCircle,\n ShieldCheck,\n ListChecks,\n Activity,\n Package,\n ChevronRight,\n} from \"lucide-react\";\nimport { useTr } from \"../utils/i18n\";\n\ninterface AdminSectionDefinition {\n id: string;\n /** i18n key used for the card label */\n labelKey: string;\n /** English fallback rendered when the i18n key is not resolved */\n labelFallback: string;\n /** i18n key used for the card description */\n descriptionKey: string;\n /** English fallback for the description */\n descriptionFallback: string;\n /** Route path relative to the admin basePath */\n path: string;\n icon: ReactNode;\n}\n\n// Module-scoped section catalogue. The icon JSX is stable (purely presentational,\n// no context or dynamic props) so constructing once at parse time avoids rebuilding\n// four lucide nodes on every render. If icons ever need to respond to context\n// (theme, RBAC), move the icon field into the useMemo mapper below.\nconst SECTION_DEFINITIONS: AdminSectionDefinition[] = [\n {\n id: \"moderation\",\n labelKey: \"conversations.admin.moderation\",\n labelFallback: \"Moderation\",\n descriptionKey: \"conversations.admin.moderationDescription\",\n descriptionFallback:\n \"Reported and flagged messages, moderation actions, and reviewer assignments.\",\n path: \"moderation\",\n icon: <ShieldCheck className=\"size-5\" aria-hidden=\"true\" />,\n },\n {\n id: \"bulk\",\n labelKey: \"conversations.admin.bulkOperations\",\n labelFallback: \"Bulk Operations\",\n descriptionKey: \"conversations.admin.bulkOperationsDescription\",\n descriptionFallback:\n \"Bulk archive / unarchive, participant edits, and cross-conversation actions.\",\n path: \"bulk\",\n icon: <ListChecks className=\"size-5\" aria-hidden=\"true\" />,\n },\n {\n id: \"audit\",\n labelKey: \"conversations.admin.auditLog\",\n labelFallback: \"Audit Log\",\n descriptionKey: \"conversations.admin.auditLogDescription\",\n descriptionFallback:\n \"Activity stream for admin / moderator actions on workspace conversations.\",\n path: \"audit\",\n icon: <Activity className=\"size-5\" aria-hidden=\"true\" />,\n },\n {\n id: \"apps\",\n labelKey: \"conversations.admin.appInstallations\",\n labelFallback: \"App Installations\",\n descriptionKey: \"conversations.admin.appInstallationsDescription\",\n descriptionFallback:\n \"Install, configure, and remove conversation apps and integrations.\",\n path: \"apps\",\n icon: <Package className=\"size-5\" aria-hidden=\"true\" />,\n },\n];\n\n/**\n * Admin-facing landing page for the Conversations microfrontend.\n *\n * Lightweight overview + section directory. Each card links to its canonical\n * sub-route (`/moderation`, `/bulk`, `/audit`, `/apps`) for the API-backed\n * admin surfaces.\n */\nexport function AdminConversationsLandingPage() {\n const tr = useTr();\n\n const sections = useMemo(\n () =>\n SECTION_DEFINITIONS.map((section) => ({\n ...section,\n label: tr(section.labelKey, section.labelFallback),\n description: tr(section.descriptionKey, section.descriptionFallback),\n })),\n [tr],\n );\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"
|
|
1
|
+
{"version":3,"file":"AdminConversationsLandingPage.js","names":[],"sources":["../../../src/conversations/pages/AdminConversationsLandingPage.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useMemo } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport {\n MessageCircle,\n ShieldCheck,\n ListChecks,\n Activity,\n Package,\n ChevronRight,\n} from \"lucide-react\";\nimport { GlassCard, EmphasisPanel, GradientText } from \"@burdenoff/fe-libs/ui\";\nimport { useTr } from \"../utils/i18n\";\n\ninterface AdminSectionDefinition {\n id: string;\n /** i18n key used for the card label */\n labelKey: string;\n /** English fallback rendered when the i18n key is not resolved */\n labelFallback: string;\n /** i18n key used for the card description */\n descriptionKey: string;\n /** English fallback for the description */\n descriptionFallback: string;\n /** Route path relative to the admin basePath */\n path: string;\n icon: ReactNode;\n /** The single featured section — gets the glowing glass treatment. */\n featured?: boolean;\n}\n\n// Module-scoped section catalogue. The icon JSX is stable (purely presentational,\n// no context or dynamic props) so constructing once at parse time avoids rebuilding\n// four lucide nodes on every render. If icons ever need to respond to context\n// (theme, RBAC), move the icon field into the useMemo mapper below.\nconst SECTION_DEFINITIONS: AdminSectionDefinition[] = [\n {\n id: \"moderation\",\n labelKey: \"conversations.admin.moderation\",\n labelFallback: \"Moderation\",\n descriptionKey: \"conversations.admin.moderationDescription\",\n descriptionFallback:\n \"Reported and flagged messages, moderation actions, and reviewer assignments.\",\n path: \"moderation\",\n icon: <ShieldCheck className=\"size-5\" aria-hidden=\"true\" />,\n featured: true,\n },\n {\n id: \"bulk\",\n labelKey: \"conversations.admin.bulkOperations\",\n labelFallback: \"Bulk Operations\",\n descriptionKey: \"conversations.admin.bulkOperationsDescription\",\n descriptionFallback:\n \"Bulk archive / unarchive, participant edits, and cross-conversation actions.\",\n path: \"bulk\",\n icon: <ListChecks className=\"size-5\" aria-hidden=\"true\" />,\n },\n {\n id: \"audit\",\n labelKey: \"conversations.admin.auditLog\",\n labelFallback: \"Audit Log\",\n descriptionKey: \"conversations.admin.auditLogDescription\",\n descriptionFallback:\n \"Activity stream for admin / moderator actions on workspace conversations.\",\n path: \"audit\",\n icon: <Activity className=\"size-5\" aria-hidden=\"true\" />,\n },\n {\n id: \"apps\",\n labelKey: \"conversations.admin.appInstallations\",\n labelFallback: \"App Installations\",\n descriptionKey: \"conversations.admin.appInstallationsDescription\",\n descriptionFallback:\n \"Install, configure, and remove conversation apps and integrations.\",\n path: \"apps\",\n icon: <Package className=\"size-5\" aria-hidden=\"true\" />,\n },\n];\n\n/**\n * Admin-facing landing page for the Conversations microfrontend.\n *\n * Lightweight overview + section directory. Each card links to its canonical\n * sub-route (`/moderation`, `/bulk`, `/audit`, `/apps`) for the API-backed\n * admin surfaces.\n */\nexport function AdminConversationsLandingPage() {\n const tr = useTr();\n\n const sections = useMemo(\n () =>\n SECTION_DEFINITIONS.map((section) => ({\n ...section,\n label: tr(section.labelKey, section.labelFallback),\n description: tr(section.descriptionKey, section.descriptionFallback),\n })),\n [tr],\n );\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex-1 min-h-0 overflow-auto p-4 sm:p-6\">\n <div className=\"mx-auto w-full max-w-3xl space-y-6\">\n {/* Hero / summary zone — the single emphasis panel on this page. */}\n <EmphasisPanel>\n <div className=\"flex items-start gap-3\">\n <div className=\"p-2 rounded-lg bg-gloss-card text-text-secondary border border-border-seam\">\n <MessageCircle className=\"size-5\" aria-hidden=\"true\" />\n </div>\n <div className=\"min-w-0\">\n <h1 className=\"text-lg font-semibold text-text-primary\">\n <GradientText>\n {tr(\n \"conversations.admin.landingTitle\",\n \"Conversations admin\",\n )}\n </GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"conversations.admin.landingDescription\",\n \"Governance tools for workspace conversations. Select a section below to continue.\",\n )}\n </p>\n </div>\n </div>\n </EmphasisPanel>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {sections.map((section) => (\n <Link\n key={section.id}\n to={section.path}\n className=\"group rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <GlassCard\n treatment=\"glass\"\n glow={section.featured}\n className=\"flex items-start gap-3 border-border-seam p-4 shadow-[var(--shadow-pop)]\"\n >\n <div className=\"p-2 rounded-md bg-bg-sunken text-text-secondary group-hover:text-text-primary\">\n {section.icon}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {section.label}\n </span>\n <ChevronRight\n className=\"size-4 text-text-secondary\"\n aria-hidden=\"true\"\n />\n </div>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {section.description}\n </p>\n </div>\n </GlassCard>\n </Link>\n ))}\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAmCA,IAAM,IAAgD;CACpD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,gBAAgB;EAChB,qBACE;EACF,MAAM;EACN,MAAM,kBAAC,GAAD;GAAa,WAAU;GAAS,eAAY;GAAS,CAAA;EAC3D,UAAU;EACX;CACD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,gBAAgB;EAChB,qBACE;EACF,MAAM;EACN,MAAM,kBAAC,GAAD;GAAY,WAAU;GAAS,eAAY;GAAS,CAAA;EAC3D;CACD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,gBAAgB;EAChB,qBACE;EACF,MAAM;EACN,MAAM,kBAAC,GAAD;GAAU,WAAU;GAAS,eAAY;GAAS,CAAA;EACzD;CACD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,gBAAgB;EAChB,qBACE;EACF,MAAM;EACN,MAAM,kBAAC,GAAD;GAAS,WAAU;GAAS,eAAY;GAAS,CAAA;EACxD;CACF;AASD,SAAgB,IAAgC;CAC9C,IAAM,IAAK,GAAO,EAEZ,IAAW,QAEb,EAAoB,KAAK,OAAa;EACpC,GAAG;EACH,OAAO,EAAG,EAAQ,UAAU,EAAQ,cAAc;EAClD,aAAa,EAAG,EAAQ,gBAAgB,EAAQ,oBAAoB;EACrE,EAAE,EACL,CAAC,EAAG,CACL;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAe,WAAU;OAAS,eAAY;OAAS,CAAA;MACnD,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBACZ,kBAAC,GAAD,EAAA,UACG,EACC,oCACA,sBACD,EACY,CAAA;OACZ,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,0CACA,oFACD;OACC,CAAA,CACA;QACF;QACQ,CAAA,EAEhB,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAS,KAAK,MACb,kBAAC,GAAD;MAEE,IAAI,EAAQ;MACZ,WAAU;gBAEV,kBAAC,GAAD;OACE,WAAU;OACV,MAAM,EAAQ;OACd,WAAU;iBAHZ,CAKE,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAQ;QACL,CAAA,EACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAQ;UACJ,CAAA,EACP,kBAAC,GAAD;UACE,WAAU;UACV,eAAY;UACZ,CAAA,CACE;YACN,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAQ;SACP,CAAA,CACA;UACI;;MACP,EA3BA,EAAQ,GA2BR,CACP;KACE,CAAA,CACF;;GACF,CAAA;EACF,CAAA"}
|
|
@@ -8,8 +8,9 @@ import { Activity as c, Archive as l, CheckCircle2 as u, Package as d, ShieldChe
|
|
|
8
8
|
import { gql as m } from "@apollo/client";
|
|
9
9
|
import { useMutation as h, useQuery as g } from "@apollo/client/react";
|
|
10
10
|
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
11
|
+
import { Button as y, CTAOverflowMenu as b, GlassCard as x, ShowMore as S } from "@burdenoff/fe-libs/ui";
|
|
11
12
|
//#region src/conversations/pages/ConversationAdminPages.tsx
|
|
12
|
-
var
|
|
13
|
+
var C = m`
|
|
13
14
|
query ConversationAdminMessageReports(
|
|
14
15
|
$first: Int
|
|
15
16
|
$filter: MessageReportFilter
|
|
@@ -37,7 +38,7 @@ var y = m`
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
`,
|
|
41
|
+
`, w = m`
|
|
41
42
|
mutation ConversationAdminResolveMessageReport(
|
|
42
43
|
$input: ResolveMessageReportInput!
|
|
43
44
|
) {
|
|
@@ -52,7 +53,7 @@ var y = m`
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
|
-
`,
|
|
56
|
+
`, T = m`
|
|
56
57
|
query ConversationAdminBulkConversations(
|
|
57
58
|
$first: Int
|
|
58
59
|
$filter: ConversationFilter
|
|
@@ -69,7 +70,7 @@ var y = m`
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
`,
|
|
73
|
+
`, E = m`
|
|
73
74
|
mutation ConversationAdminBulkUpdate(
|
|
74
75
|
$input: BulkConversationOperationInput!
|
|
75
76
|
) {
|
|
@@ -85,7 +86,7 @@ var y = m`
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
`,
|
|
89
|
+
`, D = m`
|
|
89
90
|
query ConversationAdminAuditLog($filter: ActivityLogFilter) {
|
|
90
91
|
getActivities(filter: $filter) {
|
|
91
92
|
id
|
|
@@ -97,7 +98,7 @@ var y = m`
|
|
|
97
98
|
timestamp
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
|
-
`,
|
|
101
|
+
`, O = m`
|
|
101
102
|
query ConversationAdminAppInstallations($workspaceId: ID) {
|
|
102
103
|
appInstallations(workspaceId: $workspaceId) {
|
|
103
104
|
id
|
|
@@ -111,7 +112,7 @@ var y = m`
|
|
|
111
112
|
updatedAt
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
|
-
`,
|
|
115
|
+
`, k = m`
|
|
115
116
|
mutation ConversationAdminInstallApp($input: InstallAppInput!) {
|
|
116
117
|
installApp(input: $input) {
|
|
117
118
|
id
|
|
@@ -121,7 +122,7 @@ var y = m`
|
|
|
121
122
|
installedAt
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
|
-
`,
|
|
125
|
+
`, A = m`
|
|
125
126
|
mutation ConversationAdminUpdateAppSettings($id: ID!, $settings: JSON!) {
|
|
126
127
|
updateAppSettings(id: $id, settings: $settings) {
|
|
127
128
|
id
|
|
@@ -129,7 +130,7 @@ var y = m`
|
|
|
129
130
|
updatedAt
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
|
-
`,
|
|
133
|
+
`, j = m`
|
|
133
134
|
mutation ConversationAdminUninstallApp($id: ID!) {
|
|
134
135
|
uninstallApp(id: $id) {
|
|
135
136
|
appInstallationId
|
|
@@ -137,7 +138,7 @@ var y = m`
|
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
`;
|
|
140
|
-
function
|
|
141
|
+
function M(e) {
|
|
141
142
|
if (typeof e == "string") return e;
|
|
142
143
|
if (e && typeof e == "object" && "text" in e) {
|
|
143
144
|
let t = e.text;
|
|
@@ -149,27 +150,27 @@ function O(e) {
|
|
|
149
150
|
return "Message content unavailable";
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
|
-
var
|
|
153
|
+
var N = new Intl.DateTimeFormat(void 0, {
|
|
153
154
|
dateStyle: "medium",
|
|
154
155
|
timeStyle: "short"
|
|
155
156
|
});
|
|
156
|
-
function
|
|
157
|
-
return
|
|
157
|
+
function P(e) {
|
|
158
|
+
return N.format(new Date(e));
|
|
158
159
|
}
|
|
159
|
-
function
|
|
160
|
+
function F({ children: e }) {
|
|
160
161
|
return /* @__PURE__ */ _("span", {
|
|
161
162
|
className: "rounded-full border border-border-subtle bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
|
|
162
163
|
children: e
|
|
163
164
|
});
|
|
164
165
|
}
|
|
165
|
-
function
|
|
166
|
-
let n = t(), { workspaceId: a } = e(), { data: o, loading: s, error: c, refetch: l } = g(
|
|
166
|
+
function I() {
|
|
167
|
+
let n = t(), { workspaceId: a } = e(), { data: o, loading: s, error: c, refetch: l } = g(C, {
|
|
167
168
|
variables: {
|
|
168
169
|
first: 50,
|
|
169
170
|
filter: { statuses: ["PENDING", "REVIEWING"] }
|
|
170
171
|
},
|
|
171
172
|
skip: !a
|
|
172
|
-
}), [d, { loading: p }] = h(
|
|
173
|
+
}), [d, { loading: p }] = h(w, { onCompleted: () => void l() }), m = o?.messageReports.edges.map((e) => e.node) ?? [];
|
|
173
174
|
return /* @__PURE__ */ v(i, {
|
|
174
175
|
title: n("conversations.admin.moderationPageTitle", "Moderation queue"),
|
|
175
176
|
subtitle: n("conversations.admin.moderationPageDescription", "Review reported messages and apply moderator decisions."),
|
|
@@ -185,7 +186,8 @@ function M() {
|
|
|
185
186
|
icon: /* @__PURE__ */ _(f, {
|
|
186
187
|
className: "size-6",
|
|
187
188
|
"aria-hidden": "true"
|
|
188
|
-
})
|
|
189
|
+
}),
|
|
190
|
+
illustration: "empty-generic"
|
|
189
191
|
}),
|
|
190
192
|
a && s && /* @__PURE__ */ _("p", {
|
|
191
193
|
className: "text-sm text-text-secondary",
|
|
@@ -201,25 +203,27 @@ function M() {
|
|
|
201
203
|
icon: /* @__PURE__ */ _(u, {
|
|
202
204
|
className: "size-6",
|
|
203
205
|
"aria-hidden": "true"
|
|
204
|
-
})
|
|
206
|
+
}),
|
|
207
|
+
illustration: "empty-notifications"
|
|
205
208
|
}),
|
|
206
209
|
/* @__PURE__ */ _("div", {
|
|
207
210
|
className: "grid gap-3",
|
|
208
|
-
children: m.map((e) => /* @__PURE__ */ _(
|
|
209
|
-
|
|
211
|
+
children: m.map((e) => /* @__PURE__ */ _(x, {
|
|
212
|
+
treatment: "glass",
|
|
213
|
+
className: "border-border-seam p-4",
|
|
210
214
|
children: /* @__PURE__ */ v("div", {
|
|
211
215
|
className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",
|
|
212
216
|
children: [/* @__PURE__ */ v("div", {
|
|
213
|
-
className: "space-y-2",
|
|
217
|
+
className: "space-y-2 min-w-0",
|
|
214
218
|
children: [
|
|
215
219
|
/* @__PURE__ */ v("div", {
|
|
216
220
|
className: "flex flex-wrap items-center gap-2",
|
|
217
221
|
children: [
|
|
218
|
-
/* @__PURE__ */ _(
|
|
219
|
-
e.message.isHidden && /* @__PURE__ */ _(
|
|
222
|
+
/* @__PURE__ */ _(F, { children: e.status }),
|
|
223
|
+
e.message.isHidden && /* @__PURE__ */ _(F, { children: "Hidden" }),
|
|
220
224
|
/* @__PURE__ */ v("span", {
|
|
221
225
|
className: "text-xs text-text-secondary",
|
|
222
|
-
children: ["Reported ",
|
|
226
|
+
children: ["Reported ", P(e.createdAt)]
|
|
223
227
|
})
|
|
224
228
|
]
|
|
225
229
|
}),
|
|
@@ -228,8 +232,8 @@ function M() {
|
|
|
228
232
|
children: e.reason
|
|
229
233
|
}),
|
|
230
234
|
/* @__PURE__ */ _("p", {
|
|
231
|
-
className: "rounded-md bg-bg-sunken p-3 text-sm text-text-secondary",
|
|
232
|
-
children:
|
|
235
|
+
className: "rounded-md border border-border-seam bg-bg-sunken p-3 text-sm text-text-secondary",
|
|
236
|
+
children: M(e.message.content)
|
|
233
237
|
}),
|
|
234
238
|
/* @__PURE__ */ v("p", {
|
|
235
239
|
className: "text-xs text-text-secondary",
|
|
@@ -246,27 +250,24 @@ function M() {
|
|
|
246
250
|
]
|
|
247
251
|
})
|
|
248
252
|
]
|
|
249
|
-
}), /* @__PURE__ */
|
|
250
|
-
className: "
|
|
251
|
-
|
|
252
|
-
|
|
253
|
+
}), /* @__PURE__ */ _(b, {
|
|
254
|
+
className: "shrink-0",
|
|
255
|
+
primary: {
|
|
256
|
+
label: "Hide and resolve",
|
|
253
257
|
disabled: p,
|
|
254
|
-
|
|
255
|
-
onClick: () => void d({ variables: { input: {
|
|
258
|
+
onSelect: () => void d({ variables: { input: {
|
|
256
259
|
reportId: e.id,
|
|
257
|
-
action: "
|
|
258
|
-
} } })
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
260
|
+
action: "HIDE_MESSAGE"
|
|
261
|
+
} } })
|
|
262
|
+
},
|
|
263
|
+
actions: [{
|
|
264
|
+
label: "Dismiss",
|
|
262
265
|
disabled: p,
|
|
263
|
-
|
|
264
|
-
onClick: () => void d({ variables: { input: {
|
|
266
|
+
onSelect: () => void d({ variables: { input: {
|
|
265
267
|
reportId: e.id,
|
|
266
|
-
action: "
|
|
267
|
-
} } })
|
|
268
|
-
|
|
269
|
-
})]
|
|
268
|
+
action: "DISMISS"
|
|
269
|
+
} } })
|
|
270
|
+
}]
|
|
270
271
|
})]
|
|
271
272
|
})
|
|
272
273
|
}, e.id))
|
|
@@ -274,13 +275,13 @@ function M() {
|
|
|
274
275
|
]
|
|
275
276
|
});
|
|
276
277
|
}
|
|
277
|
-
function
|
|
278
|
-
let n = t(), { workspaceId: a } = e(), [o, c] = s(() => /* @__PURE__ */ new Set()), [u, d] = s("ARCHIVE"), { data: f, loading: p, error: m, refetch:
|
|
278
|
+
function L() {
|
|
279
|
+
let n = t(), { workspaceId: a } = e(), [o, c] = s(() => /* @__PURE__ */ new Set()), [u, d] = s("ARCHIVE"), { data: f, loading: p, error: m, refetch: b } = g(T, {
|
|
279
280
|
variables: { first: 100 },
|
|
280
281
|
skip: !a
|
|
281
|
-
}), [
|
|
282
|
-
c(/* @__PURE__ */ new Set()),
|
|
283
|
-
} }),
|
|
282
|
+
}), [S, { data: C, loading: w }] = h(E, { onCompleted: () => {
|
|
283
|
+
c(/* @__PURE__ */ new Set()), b();
|
|
284
|
+
} }), D = f?.conversations.edges.map((e) => e.node) ?? [], O = (e) => {
|
|
284
285
|
c((t) => {
|
|
285
286
|
let n = new Set(t);
|
|
286
287
|
return n.has(e) ? n.delete(e) : n.add(e), n;
|
|
@@ -299,7 +300,8 @@ function N() {
|
|
|
299
300
|
children: [/* @__PURE__ */ v("select", {
|
|
300
301
|
value: u,
|
|
301
302
|
onChange: (e) => d(e.target.value),
|
|
302
|
-
|
|
303
|
+
"aria-label": "Bulk action",
|
|
304
|
+
className: "min-h-11 rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
|
|
303
305
|
children: [
|
|
304
306
|
/* @__PURE__ */ _("option", {
|
|
305
307
|
value: "ARCHIVE",
|
|
@@ -314,11 +316,11 @@ function N() {
|
|
|
314
316
|
children: "Delete"
|
|
315
317
|
})
|
|
316
318
|
]
|
|
317
|
-
}), /* @__PURE__ */ v(
|
|
319
|
+
}), /* @__PURE__ */ v(y, {
|
|
318
320
|
type: "button",
|
|
321
|
+
size: "sm",
|
|
319
322
|
disabled: o.size === 0 || w,
|
|
320
|
-
|
|
321
|
-
onClick: () => void b({ variables: { input: {
|
|
323
|
+
onClick: () => void S({ variables: { input: {
|
|
322
324
|
conversationIds: Array.from(o),
|
|
323
325
|
action: u
|
|
324
326
|
} } }),
|
|
@@ -332,7 +334,8 @@ function N() {
|
|
|
332
334
|
icon: /* @__PURE__ */ _(l, {
|
|
333
335
|
className: "size-6",
|
|
334
336
|
"aria-hidden": "true"
|
|
335
|
-
})
|
|
337
|
+
}),
|
|
338
|
+
illustration: "empty-generic"
|
|
336
339
|
}),
|
|
337
340
|
a && p && /* @__PURE__ */ _("p", {
|
|
338
341
|
className: "text-sm text-text-secondary",
|
|
@@ -342,25 +345,32 @@ function N() {
|
|
|
342
345
|
className: "text-sm text-status-error-text",
|
|
343
346
|
children: m.message
|
|
344
347
|
}),
|
|
345
|
-
C?.bulkUpdateConversations && /* @__PURE__ */ v(
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
"
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
"
|
|
353
|
-
|
|
348
|
+
C?.bulkUpdateConversations && /* @__PURE__ */ v(x, {
|
|
349
|
+
treatment: "metric",
|
|
350
|
+
className: "grid grid-cols-2 gap-4 border-border-seam p-4 sm:max-w-md",
|
|
351
|
+
children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
|
|
352
|
+
className: "text-2xl font-semibold tabular-nums text-status-success-text",
|
|
353
|
+
children: C.bulkUpdateConversations.successCount
|
|
354
|
+
}), /* @__PURE__ */ _("p", {
|
|
355
|
+
className: "text-xs text-text-secondary",
|
|
356
|
+
children: "Succeeded"
|
|
357
|
+
})] }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
|
|
358
|
+
className: "text-2xl font-semibold tabular-nums text-text-primary",
|
|
359
|
+
children: C.bulkUpdateConversations.failureCount
|
|
360
|
+
}), /* @__PURE__ */ _("p", {
|
|
361
|
+
className: "text-xs text-text-secondary",
|
|
362
|
+
children: "Failed"
|
|
363
|
+
})] })]
|
|
354
364
|
}),
|
|
355
365
|
a && /* @__PURE__ */ _("div", {
|
|
356
|
-
className: "overflow-hidden rounded-lg border border-border-
|
|
357
|
-
children:
|
|
358
|
-
className: "flex cursor-pointer items-center gap-3 border-b border-border-
|
|
366
|
+
className: "overflow-hidden rounded-lg border border-border-seam bg-bg-surface",
|
|
367
|
+
children: D.map((e) => /* @__PURE__ */ v("label", {
|
|
368
|
+
className: "flex min-h-11 cursor-pointer items-center gap-3 border-b border-border-seam px-4 py-3 last:border-b-0 hover:bg-accent",
|
|
359
369
|
children: [/* @__PURE__ */ _("input", {
|
|
360
370
|
type: "checkbox",
|
|
361
371
|
"aria-label": `Select ${e.title || "untitled conversation"}`,
|
|
362
372
|
checked: o.has(e.id),
|
|
363
|
-
onChange: () =>
|
|
373
|
+
onChange: () => O(e.id)
|
|
364
374
|
}), /* @__PURE__ */ v("div", {
|
|
365
375
|
className: "min-w-0 flex-1",
|
|
366
376
|
children: [/* @__PURE__ */ _("p", {
|
|
@@ -374,7 +384,7 @@ function N() {
|
|
|
374
384
|
e.state,
|
|
375
385
|
" · Updated",
|
|
376
386
|
" ",
|
|
377
|
-
|
|
387
|
+
P(e.updatedAt)
|
|
378
388
|
]
|
|
379
389
|
})]
|
|
380
390
|
})]
|
|
@@ -383,8 +393,8 @@ function N() {
|
|
|
383
393
|
]
|
|
384
394
|
});
|
|
385
395
|
}
|
|
386
|
-
function
|
|
387
|
-
let n = t(), { workspaceId: a } = e(), { data: o, loading: s, error: l } = g(
|
|
396
|
+
function R() {
|
|
397
|
+
let n = t(), { workspaceId: a } = e(), { data: o, loading: s, error: l } = g(D, {
|
|
388
398
|
variables: { filter: {
|
|
389
399
|
workspaceId: a,
|
|
390
400
|
resourceType: "conversation",
|
|
@@ -411,12 +421,14 @@ function P() {
|
|
|
411
421
|
}),
|
|
412
422
|
!s && !l && u.length === 0 && /* @__PURE__ */ _(r, {
|
|
413
423
|
title: "No activity found",
|
|
414
|
-
description: "Conversation admin actions will appear here."
|
|
424
|
+
description: "Conversation admin actions will appear here.",
|
|
425
|
+
illustration: "empty-data"
|
|
415
426
|
}),
|
|
416
427
|
/* @__PURE__ */ _("div", {
|
|
417
428
|
className: "grid gap-3",
|
|
418
|
-
children: u.map((e) => /* @__PURE__ */ v(
|
|
419
|
-
|
|
429
|
+
children: u.map((e) => /* @__PURE__ */ v(x, {
|
|
430
|
+
treatment: "plain",
|
|
431
|
+
className: "border-border-seam p-4",
|
|
420
432
|
children: [
|
|
421
433
|
/* @__PURE__ */ v("div", {
|
|
422
434
|
className: "flex flex-wrap items-center justify-between gap-2",
|
|
@@ -424,8 +436,8 @@ function P() {
|
|
|
424
436
|
className: "text-sm font-medium text-text-primary",
|
|
425
437
|
children: e.action
|
|
426
438
|
}), /* @__PURE__ */ _("span", {
|
|
427
|
-
className: "text-xs text-text-secondary",
|
|
428
|
-
children:
|
|
439
|
+
className: "text-xs tabular-nums text-text-secondary",
|
|
440
|
+
children: P(e.timestamp)
|
|
429
441
|
})]
|
|
430
442
|
}),
|
|
431
443
|
/* @__PURE__ */ _("p", {
|
|
@@ -447,20 +459,20 @@ function P() {
|
|
|
447
459
|
]
|
|
448
460
|
});
|
|
449
461
|
}
|
|
450
|
-
function
|
|
451
|
-
let r = t(), { workspaceId: c } = e(), [l, u] = s(""), [f, m] = s("{}"), [
|
|
462
|
+
function z() {
|
|
463
|
+
let r = t(), { workspaceId: c } = e(), [l, u] = s(""), [f, m] = s("{}"), [C, w] = s({}), [T, E] = s(null), { data: D, loading: M, error: N, refetch: I } = g(O, {
|
|
452
464
|
variables: { workspaceId: c },
|
|
453
465
|
skip: !c
|
|
454
|
-
}), [
|
|
466
|
+
}), [L, { loading: R }] = h(k, { onCompleted: () => void I() }), [z, { loading: B }] = h(A, { onCompleted: () => void I() }), [V, { loading: H }] = h(j, { onCompleted: () => void I() }), U = o(() => D?.appInstallations ?? [], [D?.appInstallations]);
|
|
455
467
|
a(() => {
|
|
456
|
-
|
|
457
|
-
if (
|
|
468
|
+
w((e) => {
|
|
469
|
+
if (U.every((t) => e[t.id])) return e;
|
|
458
470
|
let t = { ...e };
|
|
459
|
-
for (let e of
|
|
471
|
+
for (let e of U) t[e.id] || (t[e.id] = JSON.stringify(e.settings ?? {}, null, 2));
|
|
460
472
|
return t;
|
|
461
473
|
});
|
|
462
|
-
}, [
|
|
463
|
-
let
|
|
474
|
+
}, [U]);
|
|
475
|
+
let W = (e) => {
|
|
464
476
|
try {
|
|
465
477
|
let t = JSON.parse(e);
|
|
466
478
|
return t && typeof t == "object" && !Array.isArray(t) ? t : null;
|
|
@@ -481,33 +493,33 @@ function F() {
|
|
|
481
493
|
title: "Install app",
|
|
482
494
|
description: "Install a workspace-scoped conversation app by app ID.",
|
|
483
495
|
children: [/* @__PURE__ */ v("div", {
|
|
484
|
-
className: "grid gap-3 rounded-lg border border-border-
|
|
496
|
+
className: "grid gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 sm:grid-cols-[minmax(0,1fr)_minmax(0,2fr)_auto]",
|
|
485
497
|
children: [
|
|
486
498
|
/* @__PURE__ */ _("input", {
|
|
487
499
|
value: l,
|
|
488
500
|
onChange: (e) => u(e.target.value),
|
|
489
501
|
placeholder: "app-id",
|
|
490
502
|
"aria-label": "App ID",
|
|
491
|
-
className: "rounded-md border border-border-
|
|
503
|
+
className: "min-h-11 rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]"
|
|
492
504
|
}),
|
|
493
505
|
/* @__PURE__ */ _("textarea", {
|
|
494
506
|
value: f,
|
|
495
507
|
onChange: (e) => m(e.target.value),
|
|
496
508
|
rows: 3,
|
|
497
509
|
"aria-label": "App settings JSON",
|
|
498
|
-
className: "rounded-md border border-border-
|
|
510
|
+
className: "rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]"
|
|
499
511
|
}),
|
|
500
|
-
/* @__PURE__ */ _(
|
|
512
|
+
/* @__PURE__ */ _(y, {
|
|
501
513
|
type: "button",
|
|
502
|
-
|
|
503
|
-
|
|
514
|
+
size: "sm",
|
|
515
|
+
disabled: R,
|
|
504
516
|
onClick: () => {
|
|
505
|
-
let e =
|
|
517
|
+
let e = W(f);
|
|
506
518
|
if (!l.trim() || !e) {
|
|
507
|
-
|
|
519
|
+
E("Enter an app ID and a valid JSON settings object.");
|
|
508
520
|
return;
|
|
509
521
|
}
|
|
510
|
-
|
|
522
|
+
E(null), L({ variables: { input: {
|
|
511
523
|
appId: l.trim(),
|
|
512
524
|
workspaceId: c,
|
|
513
525
|
settings: e
|
|
@@ -516,81 +528,97 @@ function F() {
|
|
|
516
528
|
children: "Install"
|
|
517
529
|
})
|
|
518
530
|
]
|
|
519
|
-
}),
|
|
531
|
+
}), T && /* @__PURE__ */ _("p", {
|
|
520
532
|
className: "text-sm text-status-error-text",
|
|
521
|
-
children:
|
|
533
|
+
children: T
|
|
522
534
|
})]
|
|
523
535
|
}),
|
|
524
|
-
|
|
536
|
+
M && /* @__PURE__ */ _("p", {
|
|
525
537
|
className: "text-sm text-text-secondary",
|
|
526
538
|
children: "Loading app installations…"
|
|
527
539
|
}),
|
|
528
|
-
|
|
540
|
+
N && /* @__PURE__ */ _("p", {
|
|
529
541
|
className: "text-sm text-status-error-text",
|
|
530
|
-
children:
|
|
542
|
+
children: N.message
|
|
531
543
|
}),
|
|
532
544
|
/* @__PURE__ */ _("div", {
|
|
533
545
|
className: "grid gap-3",
|
|
534
|
-
children:
|
|
535
|
-
|
|
546
|
+
children: U.map((e) => /* @__PURE__ */ v(x, {
|
|
547
|
+
treatment: "glass",
|
|
548
|
+
className: "border-border-seam p-4",
|
|
536
549
|
children: [/* @__PURE__ */ v("div", {
|
|
537
550
|
className: "flex flex-wrap items-start justify-between gap-3",
|
|
538
|
-
children: [/* @__PURE__ */ v("div", {
|
|
539
|
-
className: "
|
|
540
|
-
children: [/* @__PURE__ */
|
|
541
|
-
className: "
|
|
542
|
-
children:
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
"
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
value: y[e.id] ?? "{}",
|
|
572
|
-
onChange: (t) => b((n) => ({
|
|
573
|
-
...n,
|
|
574
|
-
[e.id]: t.target.value
|
|
575
|
-
})),
|
|
576
|
-
className: "rounded-md border border-border-subtle bg-bg-surface px-3 py-2 font-mono text-xs text-text-primary"
|
|
577
|
-
}), /* @__PURE__ */ _("button", {
|
|
578
|
-
type: "button",
|
|
579
|
-
disabled: I,
|
|
580
|
-
className: "w-fit rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground hover:bg-secondary/90 disabled:opacity-50",
|
|
581
|
-
onClick: () => {
|
|
582
|
-
let t = B(y[e.id] ?? "{}");
|
|
583
|
-
if (!t) {
|
|
584
|
-
S("Installation settings must be a valid JSON object.");
|
|
585
|
-
return;
|
|
551
|
+
children: [/* @__PURE__ */ v("div", {
|
|
552
|
+
className: "min-w-0",
|
|
553
|
+
children: [/* @__PURE__ */ v("div", {
|
|
554
|
+
className: "flex items-center gap-2",
|
|
555
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
556
|
+
className: "text-sm font-semibold text-text-primary",
|
|
557
|
+
children: e.appId
|
|
558
|
+
}), /* @__PURE__ */ _(F, { children: e.state })]
|
|
559
|
+
}), /* @__PURE__ */ v("p", {
|
|
560
|
+
className: "text-xs text-text-secondary",
|
|
561
|
+
children: [
|
|
562
|
+
"Version ",
|
|
563
|
+
e.appVersion,
|
|
564
|
+
" · Installed by",
|
|
565
|
+
" ",
|
|
566
|
+
e.installedBy,
|
|
567
|
+
" on",
|
|
568
|
+
" ",
|
|
569
|
+
P(e.installedAt)
|
|
570
|
+
]
|
|
571
|
+
})]
|
|
572
|
+
}), /* @__PURE__ */ _(b, {
|
|
573
|
+
className: "shrink-0",
|
|
574
|
+
actions: [{
|
|
575
|
+
label: "Uninstall",
|
|
576
|
+
intent: "destructive",
|
|
577
|
+
disabled: H,
|
|
578
|
+
icon: /* @__PURE__ */ _(p, {
|
|
579
|
+
className: "size-4",
|
|
580
|
+
"aria-hidden": "true"
|
|
581
|
+
}),
|
|
582
|
+
onSelect: () => {
|
|
583
|
+
window.confirm(`Uninstall ${e.appId}? This removes the app and its settings from this workspace.`) && V({ variables: { id: e.id } });
|
|
586
584
|
}
|
|
587
|
-
|
|
588
|
-
id: e.id,
|
|
589
|
-
settings: t
|
|
590
|
-
} });
|
|
591
|
-
},
|
|
592
|
-
children: "Save settings"
|
|
585
|
+
}]
|
|
593
586
|
})]
|
|
587
|
+
}), /* @__PURE__ */ _(S, {
|
|
588
|
+
className: "mt-3",
|
|
589
|
+
collapsedHeight: 0,
|
|
590
|
+
label: "Edit settings (JSON)",
|
|
591
|
+
children: /* @__PURE__ */ v("div", {
|
|
592
|
+
className: "grid gap-2 pt-2",
|
|
593
|
+
children: [/* @__PURE__ */ _("textarea", {
|
|
594
|
+
rows: 5,
|
|
595
|
+
"aria-label": `Settings for ${e.appId}`,
|
|
596
|
+
value: C[e.id] ?? "{}",
|
|
597
|
+
onChange: (t) => w((n) => ({
|
|
598
|
+
...n,
|
|
599
|
+
[e.id]: t.target.value
|
|
600
|
+
})),
|
|
601
|
+
className: "rounded-md border border-border-seam bg-bg-surface px-3 py-2 font-mono text-xs text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]"
|
|
602
|
+
}), /* @__PURE__ */ _(y, {
|
|
603
|
+
type: "button",
|
|
604
|
+
variant: "secondary",
|
|
605
|
+
size: "sm",
|
|
606
|
+
disabled: B,
|
|
607
|
+
className: "w-fit",
|
|
608
|
+
onClick: () => {
|
|
609
|
+
let t = W(C[e.id] ?? "{}");
|
|
610
|
+
if (!t) {
|
|
611
|
+
E("Installation settings must be a valid JSON object.");
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
E(null), z({ variables: {
|
|
615
|
+
id: e.id,
|
|
616
|
+
settings: t
|
|
617
|
+
} });
|
|
618
|
+
},
|
|
619
|
+
children: "Save settings"
|
|
620
|
+
})]
|
|
621
|
+
})
|
|
594
622
|
})]
|
|
595
623
|
}, e.id))
|
|
596
624
|
})
|
|
@@ -598,6 +626,6 @@ function F() {
|
|
|
598
626
|
});
|
|
599
627
|
}
|
|
600
628
|
//#endregion
|
|
601
|
-
export {
|
|
629
|
+
export { z as AppInstallationsPage, L as BulkOperationsPage, R as ConversationAuditLogPage, I as ModerationQueuePage };
|
|
602
630
|
|
|
603
631
|
//# sourceMappingURL=ConversationAdminPages.js.map
|