@pablo2410/shared-ui 0.18.2 → 0.19.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/{chunk-NXE653CX.js → chunk-K6FHU4HN.js} +7 -7
- package/dist/chunk-K6FHU4HN.js.map +1 -0
- package/dist/{chunk-TTDKZK6L.js → chunk-NLQ45OYS.js} +3 -3
- package/dist/{chunk-CPRJSW7F.js → chunk-VJEXXX2P.js} +2 -2
- package/dist/hierarchy/index.js +2 -2
- package/dist/layout/index.js +3 -3
- package/dist/primitives/index.d.ts +3 -3
- package/dist/primitives/index.js +1 -1
- package/dist/reporting/index.d.ts +100 -42
- package/dist/reporting/index.js +193 -206
- package/dist/reporting/index.js.map +1 -1
- package/dist/shell/index.js +3 -3
- package/dist/shell/oplytics-shell.css +1 -1
- package/package.json +8 -8
- package/dist/chunk-NXE653CX.js.map +0 -1
- /package/dist/{chunk-TTDKZK6L.js.map → chunk-NLQ45OYS.js.map} +0 -0
- /package/dist/{chunk-CPRJSW7F.js.map → chunk-VJEXXX2P.js.map} +0 -0
package/dist/reporting/index.js
CHANGED
|
@@ -12,8 +12,9 @@ import {
|
|
|
12
12
|
SelectItem,
|
|
13
13
|
SelectTrigger,
|
|
14
14
|
SelectValue,
|
|
15
|
+
Switch,
|
|
15
16
|
Textarea
|
|
16
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-K6FHU4HN.js";
|
|
17
18
|
import {
|
|
18
19
|
cn
|
|
19
20
|
} from "../chunk-JT3XLKKD.js";
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
} from "../chunk-BKGUIIN2.js";
|
|
30
31
|
|
|
31
32
|
// src/reporting/ReportingToolbar.tsx
|
|
32
|
-
import { useState } from "react";
|
|
33
|
+
import { useRef, useState } from "react";
|
|
33
34
|
import {
|
|
34
35
|
ShieldAlert,
|
|
35
36
|
Leaf,
|
|
@@ -38,6 +39,8 @@ import {
|
|
|
38
39
|
Lightbulb,
|
|
39
40
|
ChevronDown,
|
|
40
41
|
Send,
|
|
42
|
+
ImagePlus,
|
|
43
|
+
X,
|
|
41
44
|
UserCog
|
|
42
45
|
} from "lucide-react";
|
|
43
46
|
import { toast } from "sonner";
|
|
@@ -68,7 +71,7 @@ var ALL_REPORT_OPTIONS = [
|
|
|
68
71
|
var ALL_FEEDBACK_OPTIONS = [
|
|
69
72
|
{
|
|
70
73
|
category: "problem",
|
|
71
|
-
label: "Report Problem",
|
|
74
|
+
label: "Report a Problem",
|
|
72
75
|
description: "Something isn't working",
|
|
73
76
|
icon: Bug,
|
|
74
77
|
color: "#EF4444"
|
|
@@ -76,17 +79,11 @@ var ALL_FEEDBACK_OPTIONS = [
|
|
|
76
79
|
{
|
|
77
80
|
category: "suggestion",
|
|
78
81
|
label: "Suggestion",
|
|
79
|
-
description: "
|
|
82
|
+
description: "An idea for improvement",
|
|
80
83
|
icon: Lightbulb,
|
|
81
84
|
color: "#8C34E9"
|
|
82
85
|
}
|
|
83
86
|
];
|
|
84
|
-
var SEVERITY_OPTIONS = [
|
|
85
|
-
{ value: "critical", label: "Critical", color: "#EF4444" },
|
|
86
|
-
{ value: "high", label: "High", color: "#F59E0B" },
|
|
87
|
-
{ value: "medium", label: "Medium", color: "#3b82f6" },
|
|
88
|
-
{ value: "low", label: "Low", color: "#22C55E" }
|
|
89
|
-
];
|
|
90
87
|
function ReportingToolbar({
|
|
91
88
|
moduleName = "Oplytics",
|
|
92
89
|
showIncidentReporting = true,
|
|
@@ -95,7 +92,12 @@ function ReportingToolbar({
|
|
|
95
92
|
feedbackCategories = ["problem", "suggestion"],
|
|
96
93
|
onReportSubmit,
|
|
97
94
|
onFeedbackSubmit,
|
|
98
|
-
|
|
95
|
+
hierarchyContext,
|
|
96
|
+
currentUser,
|
|
97
|
+
services = OPLYTICS_SERVICES,
|
|
98
|
+
defaultServiceSlug,
|
|
99
|
+
enableScreenshot = true,
|
|
100
|
+
reportsComingSoon = true,
|
|
99
101
|
className
|
|
100
102
|
}) {
|
|
101
103
|
const reportOptions = ALL_REPORT_OPTIONS.filter(
|
|
@@ -104,91 +106,82 @@ function ReportingToolbar({
|
|
|
104
106
|
const feedbackOptions = ALL_FEEDBACK_OPTIONS.filter(
|
|
105
107
|
(opt) => feedbackCategories.includes(opt.category)
|
|
106
108
|
);
|
|
107
|
-
const [
|
|
108
|
-
const [
|
|
109
|
-
const [
|
|
110
|
-
const [
|
|
111
|
-
const [
|
|
112
|
-
const [
|
|
113
|
-
const [
|
|
114
|
-
const [
|
|
115
|
-
const [
|
|
116
|
-
const [feedbackDescription, setFeedbackDescription] = useState("");
|
|
109
|
+
const firstServiceSlug = defaultServiceSlug ?? services[0]?.slug ?? "portal";
|
|
110
|
+
const [feedbackOpen, setFeedbackOpen] = useState(false);
|
|
111
|
+
const [category, setCategory] = useState("problem");
|
|
112
|
+
const [serviceSlug, setServiceSlug] = useState(firstServiceSlug);
|
|
113
|
+
const [isBlocking, setIsBlocking] = useState(false);
|
|
114
|
+
const [summary, setSummary] = useState("");
|
|
115
|
+
const [details, setDetails] = useState("");
|
|
116
|
+
const [screenshot, setScreenshot] = useState(null);
|
|
117
|
+
const [screenshotName, setScreenshotName] = useState(null);
|
|
117
118
|
const [submitting, setSubmitting] = useState(false);
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
setFeedbackSubject("");
|
|
129
|
-
setFeedbackDescription("");
|
|
130
|
-
setFeedbackDialogOpen(true);
|
|
119
|
+
const fileInputRef = useRef(null);
|
|
120
|
+
const openFeedback = (c) => {
|
|
121
|
+
setCategory(c);
|
|
122
|
+
setServiceSlug(firstServiceSlug);
|
|
123
|
+
setIsBlocking(false);
|
|
124
|
+
setSummary("");
|
|
125
|
+
setDetails("");
|
|
126
|
+
setScreenshot(null);
|
|
127
|
+
setScreenshotName(null);
|
|
128
|
+
setFeedbackOpen(true);
|
|
131
129
|
};
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
const handlePickFile = async (e) => {
|
|
131
|
+
const file = e.target.files?.[0];
|
|
132
|
+
e.target.value = "";
|
|
133
|
+
if (!file) return;
|
|
134
|
+
const check = isAcceptableScreenshot(file);
|
|
135
|
+
if (!check.ok) {
|
|
136
|
+
toast.error(check.reason);
|
|
135
137
|
return;
|
|
136
138
|
}
|
|
137
|
-
setSubmitting(true);
|
|
138
139
|
try {
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
location: reportLocation || void 0,
|
|
143
|
-
severity: reportSeverity,
|
|
144
|
-
immediateAction: reportImmediateAction || void 0,
|
|
145
|
-
moduleName,
|
|
146
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
147
|
-
};
|
|
148
|
-
await onReportSubmit(report);
|
|
149
|
-
toast.success("Report submitted successfully", {
|
|
150
|
-
description: selectedReportCategory === "stop-work" ? "Stop Work authority raised \u2014 management has been notified" : "Your report has been logged and assigned for review"
|
|
151
|
-
});
|
|
152
|
-
setReportDialogOpen(false);
|
|
140
|
+
const shot = await readFileAsScreenshot(file);
|
|
141
|
+
setScreenshot(shot);
|
|
142
|
+
setScreenshotName(file.name);
|
|
153
143
|
} catch (err) {
|
|
154
|
-
console.error("[ReportingToolbar]
|
|
155
|
-
toast.error("
|
|
156
|
-
} finally {
|
|
157
|
-
setSubmitting(false);
|
|
144
|
+
console.error("[ReportingToolbar] screenshot read failed:", err);
|
|
145
|
+
toast.error("Could not read that image.");
|
|
158
146
|
}
|
|
159
147
|
};
|
|
160
|
-
const
|
|
161
|
-
if (!
|
|
162
|
-
toast.error("Please
|
|
148
|
+
const submitFeedback = async () => {
|
|
149
|
+
if (!details.trim()) {
|
|
150
|
+
toast.error("Please describe the problem or idea.");
|
|
163
151
|
return;
|
|
164
152
|
}
|
|
165
153
|
setSubmitting(true);
|
|
166
154
|
try {
|
|
167
155
|
const feedback = {
|
|
168
|
-
category
|
|
169
|
-
|
|
170
|
-
|
|
156
|
+
category,
|
|
157
|
+
serviceSlug,
|
|
158
|
+
summary: summary.trim() || void 0,
|
|
159
|
+
details: details.trim(),
|
|
160
|
+
isBlocking,
|
|
171
161
|
moduleName,
|
|
172
162
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
173
|
-
pageContext: typeof window !== "undefined" ? window.location.pathname : void 0
|
|
163
|
+
pageContext: typeof window !== "undefined" ? window.location.pathname : void 0,
|
|
164
|
+
submittedBy: currentUser,
|
|
165
|
+
screenshot: screenshot ?? void 0
|
|
174
166
|
};
|
|
175
167
|
await onFeedbackSubmit(feedback);
|
|
176
168
|
toast.success(
|
|
177
|
-
|
|
169
|
+
category === "problem" ? "Thanks \u2014 we've logged it. You'll get a confirmation email." : "Thanks for the suggestion \u2014 you'll get a confirmation email."
|
|
178
170
|
);
|
|
179
|
-
|
|
171
|
+
setFeedbackOpen(false);
|
|
180
172
|
} catch (err) {
|
|
181
173
|
console.error("[ReportingToolbar] feedback submit failed:", err);
|
|
182
|
-
toast.error("
|
|
174
|
+
toast.error("Couldn't submit that. Please try again.");
|
|
183
175
|
} finally {
|
|
184
176
|
setSubmitting(false);
|
|
185
177
|
}
|
|
186
178
|
};
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
);
|
|
179
|
+
const showReportGroup = showIncidentReporting && reportOptions.length > 0;
|
|
180
|
+
const showFeedbackGroup = showFeedback && feedbackOptions.length > 0;
|
|
181
|
+
if (!showReportGroup && !showFeedbackGroup) return null;
|
|
182
|
+
void hierarchyContext;
|
|
190
183
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
191
|
-
/* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), children:
|
|
184
|
+
/* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
192
185
|
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
193
186
|
Button,
|
|
194
187
|
{
|
|
@@ -202,13 +195,28 @@ function ReportingToolbar({
|
|
|
202
195
|
]
|
|
203
196
|
}
|
|
204
197
|
) }),
|
|
205
|
-
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-
|
|
206
|
-
|
|
207
|
-
/* @__PURE__ */
|
|
198
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-60", children: [
|
|
199
|
+
showReportGroup && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
200
|
+
/* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex items-center gap-2 text-[10px] uppercase tracking-wide text-muted-foreground", children: [
|
|
201
|
+
"Report",
|
|
202
|
+
reportsComingSoon && /* @__PURE__ */ jsx(
|
|
203
|
+
Badge,
|
|
204
|
+
{
|
|
205
|
+
variant: "outline",
|
|
206
|
+
className: "border-[#8C34E9]/40 text-[9px] font-normal text-[#C084FC]",
|
|
207
|
+
children: "Coming soon"
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
] }),
|
|
208
211
|
reportOptions.map((opt) => /* @__PURE__ */ jsxs(
|
|
209
212
|
DropdownMenuItem,
|
|
210
213
|
{
|
|
211
|
-
|
|
214
|
+
disabled: reportsComingSoon,
|
|
215
|
+
onClick: () => {
|
|
216
|
+
if (!reportsComingSoon) {
|
|
217
|
+
void onReportSubmit;
|
|
218
|
+
}
|
|
219
|
+
},
|
|
212
220
|
className: "gap-3 py-2.5",
|
|
213
221
|
children: [
|
|
214
222
|
/* @__PURE__ */ jsx(
|
|
@@ -227,13 +235,13 @@ function ReportingToolbar({
|
|
|
227
235
|
opt.category
|
|
228
236
|
))
|
|
229
237
|
] }),
|
|
230
|
-
|
|
231
|
-
|
|
238
|
+
showReportGroup && showFeedbackGroup && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
239
|
+
showFeedbackGroup && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
232
240
|
/* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Feedback" }),
|
|
233
241
|
feedbackOptions.map((opt) => /* @__PURE__ */ jsxs(
|
|
234
242
|
DropdownMenuItem,
|
|
235
243
|
{
|
|
236
|
-
onClick: () =>
|
|
244
|
+
onClick: () => openFeedback(opt.category),
|
|
237
245
|
className: "gap-3 py-2.5",
|
|
238
246
|
children: [
|
|
239
247
|
/* @__PURE__ */ jsx(
|
|
@@ -253,176 +261,117 @@ function ReportingToolbar({
|
|
|
253
261
|
))
|
|
254
262
|
] })
|
|
255
263
|
] })
|
|
256
|
-
] })
|
|
257
|
-
/* @__PURE__ */ jsx(Dialog, { open:
|
|
264
|
+
] }) }),
|
|
265
|
+
/* @__PURE__ */ jsx(Dialog, { open: feedbackOpen, onOpenChange: setFeedbackOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[520px]", children: [
|
|
258
266
|
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
259
267
|
/* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
{
|
|
263
|
-
className: "h-5 w-5",
|
|
264
|
-
style: { color: reportConfig.color }
|
|
265
|
-
}
|
|
266
|
-
),
|
|
267
|
-
reportConfig?.label || "Report",
|
|
268
|
-
selectedReportCategory === "stop-work" && /* @__PURE__ */ jsx(Badge, { className: "bg-[#F59E0B] text-white text-[9px] border-0", children: "URGENT" })
|
|
268
|
+
category === "problem" ? /* @__PURE__ */ jsx(Bug, { className: "h-5 w-5 text-[#EF4444]" }) : /* @__PURE__ */ jsx(Lightbulb, { className: "h-5 w-5 text-[#8C34E9]" }),
|
|
269
|
+
category === "problem" ? "Report a Problem" : "Share a Suggestion"
|
|
269
270
|
] }),
|
|
270
|
-
/* @__PURE__ */
|
|
271
|
-
reportConfig?.description,
|
|
272
|
-
". All reports are logged and tracked."
|
|
273
|
-
] })
|
|
271
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: category === "problem" ? "Tell us what went wrong. We triage within 24 hours." : "We review every suggestion and schedule improvements against the roadmap." })
|
|
274
272
|
] }),
|
|
275
273
|
/* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
|
|
276
274
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
277
|
-
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "
|
|
278
|
-
/* @__PURE__ */ jsxs(
|
|
279
|
-
|
|
280
|
-
{
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
"div",
|
|
290
|
-
{
|
|
291
|
-
className: "h-2 w-2 rounded-full",
|
|
292
|
-
style: { backgroundColor: s.color }
|
|
293
|
-
}
|
|
294
|
-
),
|
|
295
|
-
s.label
|
|
296
|
-
] }) }, s.value)) })
|
|
297
|
-
]
|
|
298
|
-
}
|
|
299
|
-
)
|
|
275
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "Which service?" }),
|
|
276
|
+
/* @__PURE__ */ jsxs(Select, { value: serviceSlug, onValueChange: setServiceSlug, children: [
|
|
277
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-9", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
278
|
+
/* @__PURE__ */ jsx(SelectContent, { children: services.map((s) => /* @__PURE__ */ jsx(SelectItem, { value: s.slug, children: s.label }, s.slug)) })
|
|
279
|
+
] })
|
|
280
|
+
] }),
|
|
281
|
+
category === "problem" && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-md border border-[#1E2738] px-3 py-2", children: [
|
|
282
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
283
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Is this blocking you?" }),
|
|
284
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: "Blocking issues are treated as high priority." })
|
|
285
|
+
] }),
|
|
286
|
+
/* @__PURE__ */ jsx(Switch, { checked: isBlocking, onCheckedChange: setIsBlocking })
|
|
300
287
|
] }),
|
|
301
288
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
302
|
-
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "
|
|
289
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "Summary" }),
|
|
303
290
|
/* @__PURE__ */ jsx(
|
|
304
291
|
Input,
|
|
305
292
|
{
|
|
306
|
-
value:
|
|
307
|
-
onChange: (e) =>
|
|
308
|
-
placeholder: "
|
|
293
|
+
value: summary,
|
|
294
|
+
onChange: (e) => setSummary(e.target.value),
|
|
295
|
+
placeholder: category === "problem" ? "Brief summary of the issue" : "Brief summary of your idea",
|
|
309
296
|
className: "h-9"
|
|
310
297
|
}
|
|
311
298
|
)
|
|
312
299
|
] }),
|
|
313
300
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
314
|
-
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "
|
|
301
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "Details *" }),
|
|
315
302
|
/* @__PURE__ */ jsx(
|
|
316
303
|
Textarea,
|
|
317
304
|
{
|
|
318
|
-
value:
|
|
319
|
-
onChange: (e) =>
|
|
320
|
-
placeholder: "
|
|
321
|
-
rows:
|
|
305
|
+
value: details,
|
|
306
|
+
onChange: (e) => setDetails(e.target.value),
|
|
307
|
+
placeholder: category === "problem" ? "What were you trying to do? What happened instead?" : "Describe your suggestion and how it would help\u2026",
|
|
308
|
+
rows: 5
|
|
322
309
|
}
|
|
323
310
|
)
|
|
324
311
|
] }),
|
|
325
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
326
|
-
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "
|
|
312
|
+
enableScreenshot && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
313
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "Screenshot (optional)" }),
|
|
327
314
|
/* @__PURE__ */ jsx(
|
|
328
|
-
|
|
315
|
+
"input",
|
|
329
316
|
{
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
317
|
+
ref: fileInputRef,
|
|
318
|
+
type: "file",
|
|
319
|
+
accept: "image/*",
|
|
320
|
+
className: "hidden",
|
|
321
|
+
onChange: handlePickFile
|
|
334
322
|
}
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
backgroundColor: reportConfig?.color,
|
|
355
|
-
color: "white"
|
|
356
|
-
},
|
|
357
|
-
children: [
|
|
358
|
-
/* @__PURE__ */ jsx(Send, { className: "h-3.5 w-3.5" }),
|
|
359
|
-
submitting ? "Submitting..." : "Submit Report"
|
|
360
|
-
]
|
|
361
|
-
}
|
|
362
|
-
)
|
|
363
|
-
] })
|
|
364
|
-
] }) }),
|
|
365
|
-
/* @__PURE__ */ jsx(Dialog, { open: feedbackDialogOpen, onOpenChange: setFeedbackDialogOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[500px]", children: [
|
|
366
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
367
|
-
/* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
368
|
-
selectedFeedbackCategory === "problem" ? /* @__PURE__ */ jsx(Bug, { className: "h-5 w-5 text-[#EF4444]" }) : /* @__PURE__ */ jsx(Lightbulb, { className: "h-5 w-5 text-[#8C34E9]" }),
|
|
369
|
-
selectedFeedbackCategory === "problem" ? "Report a Problem" : "Submit a Suggestion"
|
|
370
|
-
] }),
|
|
371
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: selectedFeedbackCategory === "problem" ? "Help us fix issues \u2014 describe what went wrong." : "We'd love to hear your ideas for improving Oplytics." })
|
|
372
|
-
] }),
|
|
373
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
|
|
374
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
375
|
-
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "Subject" }),
|
|
376
|
-
/* @__PURE__ */ jsx(
|
|
377
|
-
Input,
|
|
378
|
-
{
|
|
379
|
-
value: feedbackSubject,
|
|
380
|
-
onChange: (e) => setFeedbackSubject(e.target.value),
|
|
381
|
-
placeholder: selectedFeedbackCategory === "problem" ? "Brief summary of the issue" : "Brief summary of your idea",
|
|
382
|
-
className: "h-9"
|
|
383
|
-
}
|
|
384
|
-
)
|
|
385
|
-
] }),
|
|
386
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
387
|
-
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium", children: "Description *" }),
|
|
388
|
-
/* @__PURE__ */ jsx(
|
|
389
|
-
Textarea,
|
|
323
|
+
),
|
|
324
|
+
screenshot ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-md border border-[#1E2738] px-3 py-2", children: [
|
|
325
|
+
/* @__PURE__ */ jsx(ImagePlus, { className: "h-4 w-4 text-[#8C34E9]" }),
|
|
326
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-xs text-[#E2E8F0]", children: screenshotName ?? "screenshot" }),
|
|
327
|
+
/* @__PURE__ */ jsx(
|
|
328
|
+
"button",
|
|
329
|
+
{
|
|
330
|
+
type: "button",
|
|
331
|
+
onClick: () => {
|
|
332
|
+
setScreenshot(null);
|
|
333
|
+
setScreenshotName(null);
|
|
334
|
+
},
|
|
335
|
+
className: "text-muted-foreground hover:text-[#E2E8F0]",
|
|
336
|
+
"aria-label": "Remove screenshot",
|
|
337
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
338
|
+
}
|
|
339
|
+
)
|
|
340
|
+
] }) : /* @__PURE__ */ jsxs(
|
|
341
|
+
Button,
|
|
390
342
|
{
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
343
|
+
type: "button",
|
|
344
|
+
variant: "outline",
|
|
345
|
+
size: "sm",
|
|
346
|
+
className: "h-9 gap-1.5",
|
|
347
|
+
onClick: () => fileInputRef.current?.click(),
|
|
348
|
+
children: [
|
|
349
|
+
/* @__PURE__ */ jsx(ImagePlus, { className: "h-3.5 w-3.5" }),
|
|
350
|
+
"Attach an image"
|
|
351
|
+
]
|
|
395
352
|
}
|
|
396
353
|
)
|
|
397
354
|
] }),
|
|
398
|
-
/* @__PURE__ */ jsxs("
|
|
399
|
-
"Module: ",
|
|
355
|
+
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground", children: [
|
|
400
356
|
moduleName,
|
|
401
|
-
" \
|
|
357
|
+
" \xB7 you'll get a confirmation email once this is logged."
|
|
402
358
|
] })
|
|
403
359
|
] }),
|
|
404
360
|
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
405
|
-
/* @__PURE__ */ jsx(
|
|
406
|
-
Button,
|
|
407
|
-
{
|
|
408
|
-
variant: "outline",
|
|
409
|
-
onClick: () => setFeedbackDialogOpen(false),
|
|
410
|
-
children: "Cancel"
|
|
411
|
-
}
|
|
412
|
-
),
|
|
361
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => setFeedbackOpen(false), children: "Cancel" }),
|
|
413
362
|
/* @__PURE__ */ jsxs(
|
|
414
363
|
Button,
|
|
415
364
|
{
|
|
416
|
-
onClick:
|
|
417
|
-
disabled: submitting || !
|
|
365
|
+
onClick: submitFeedback,
|
|
366
|
+
disabled: submitting || !details.trim(),
|
|
418
367
|
className: "gap-2",
|
|
419
368
|
style: {
|
|
420
|
-
backgroundColor:
|
|
369
|
+
backgroundColor: category === "problem" ? "#EF4444" : "#8C34E9",
|
|
421
370
|
color: "white"
|
|
422
371
|
},
|
|
423
372
|
children: [
|
|
424
373
|
/* @__PURE__ */ jsx(Send, { className: "h-3.5 w-3.5" }),
|
|
425
|
-
submitting ? "Submitting
|
|
374
|
+
submitting ? "Submitting\u2026" : "Submit"
|
|
426
375
|
]
|
|
427
376
|
}
|
|
428
377
|
)
|
|
@@ -432,6 +381,14 @@ function ReportingToolbar({
|
|
|
432
381
|
}
|
|
433
382
|
|
|
434
383
|
// src/reporting/index.ts
|
|
384
|
+
var OPLYTICS_SERVICES = [
|
|
385
|
+
{ slug: "sqdcp", label: "SQDCP" },
|
|
386
|
+
{ slug: "oee-manager", label: "OEE Manager" },
|
|
387
|
+
{ slug: "action-manager", label: "Action Manager" },
|
|
388
|
+
{ slug: "policy-deployment", label: "Policy Deployment" },
|
|
389
|
+
{ slug: "connect", label: "Connect" },
|
|
390
|
+
{ slug: "portal", label: "Portal" }
|
|
391
|
+
];
|
|
435
392
|
var REPORT_BUTTONS = [
|
|
436
393
|
{
|
|
437
394
|
category: "safety",
|
|
@@ -481,10 +438,40 @@ function createReportingConfig(moduleName, handlers) {
|
|
|
481
438
|
...handlers
|
|
482
439
|
};
|
|
483
440
|
}
|
|
441
|
+
var FEEDBACK_SCREENSHOT_MAX_BYTES = 300 * 1024;
|
|
442
|
+
function isAcceptableScreenshot(file, maxBytes = FEEDBACK_SCREENSHOT_MAX_BYTES) {
|
|
443
|
+
if (!file.type.startsWith("image/")) {
|
|
444
|
+
return { ok: false, reason: "Please choose an image file." };
|
|
445
|
+
}
|
|
446
|
+
if (file.size > maxBytes) {
|
|
447
|
+
return {
|
|
448
|
+
ok: false,
|
|
449
|
+
reason: `Image is too large (max ${Math.round(maxBytes / 1024)} KB).`
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
return { ok: true };
|
|
453
|
+
}
|
|
454
|
+
function readFileAsScreenshot(file) {
|
|
455
|
+
return new Promise((resolve, reject) => {
|
|
456
|
+
const reader = new FileReader();
|
|
457
|
+
reader.onerror = () => reject(new Error("Could not read the file."));
|
|
458
|
+
reader.onload = () => {
|
|
459
|
+
const result = String(reader.result || "");
|
|
460
|
+
const comma = result.indexOf(",");
|
|
461
|
+
const dataBase64 = comma >= 0 ? result.slice(comma + 1) : result;
|
|
462
|
+
resolve({ dataBase64, mime: file.type || "image/png" });
|
|
463
|
+
};
|
|
464
|
+
reader.readAsDataURL(file);
|
|
465
|
+
});
|
|
466
|
+
}
|
|
484
467
|
export {
|
|
485
468
|
FEEDBACK_BUTTONS,
|
|
469
|
+
FEEDBACK_SCREENSHOT_MAX_BYTES,
|
|
470
|
+
OPLYTICS_SERVICES,
|
|
486
471
|
REPORT_BUTTONS,
|
|
487
472
|
ReportingToolbar,
|
|
488
|
-
createReportingConfig
|
|
473
|
+
createReportingConfig,
|
|
474
|
+
isAcceptableScreenshot,
|
|
475
|
+
readFileAsScreenshot
|
|
489
476
|
};
|
|
490
477
|
//# sourceMappingURL=index.js.map
|