@consilioweb/payload-support 4.0.0 → 6.0.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/README.md +272 -35
- package/dist/components/RichTextEditor/index.js +1 -1
- package/dist/components/TicketConversation/RewriteDropdown.js +1 -1
- package/dist/components/TicketConversation/components/AISummaryPanel.js +3 -0
- package/dist/components/TicketConversation/components/ActionPanels.js +13 -8
- package/dist/components/TicketConversation/components/ClientHistory.js +1 -0
- package/dist/components/TicketConversation/components/CodeBlock.js +1 -0
- package/dist/components/TicketConversation/components/CodeBlockInserter.js +1 -1
- package/dist/components/TicketConversation/components/QuickActions.js +10 -8
- package/dist/components/TicketConversation/components/TicketHeader.js +2 -0
- package/dist/components/TicketConversation/components/TimeTrackingPanel.js +15 -9
- package/dist/components/TicketConversation/index.d.ts +10 -0
- package/dist/components/TicketConversation/index.js +25 -7
- package/dist/index.cjs +421 -73
- package/dist/index.d.cts +127 -38
- package/dist/index.d.ts +127 -38
- package/dist/index.js +415 -72
- package/dist/styles/BillingView.module.scss +11 -11
- package/dist/styles/ChatView.module.scss +7 -7
- package/dist/styles/CommandPalette.module.scss +1 -1
- package/dist/styles/CrmView.module.scss +9 -9
- package/dist/styles/EmailTracking.module.scss +6 -6
- package/dist/styles/ImportConversation.module.scss +5 -5
- package/dist/styles/Logs.module.scss +5 -5
- package/dist/styles/NewTicket.module.scss +2 -2
- package/dist/styles/PendingEmails.module.scss +13 -13
- package/dist/styles/SupportDashboard.module.scss +24 -8
- package/dist/styles/TicketDetail.module.scss +20 -20
- package/dist/styles/TicketInbox.module.scss +6 -6
- package/dist/styles/TicketingSettings.module.scss +10 -10
- package/dist/styles/TimeDashboard.module.scss +6 -6
- package/dist/styles/_tokens.scss +3 -1
- package/dist/utils/db.d.ts +34 -0
- package/dist/utils/readSettings.d.ts +90 -0
- package/dist/views/BillingView/client.js +15 -8
- package/dist/views/BillingView/index.js +4 -4
- package/dist/views/ChatView/client.js +2 -0
- package/dist/views/ChatView/index.js +4 -4
- package/dist/views/CrmView/client.js +2 -0
- package/dist/views/CrmView/index.js +4 -4
- package/dist/views/EmailTrackingView/client.js +23 -11
- package/dist/views/EmailTrackingView/index.js +4 -4
- package/dist/views/ImportConversationView/client.js +1 -0
- package/dist/views/ImportConversationView/index.js +4 -4
- package/dist/views/LogsView/client.js +1 -1
- package/dist/views/LogsView/index.js +4 -2
- package/dist/views/NewTicketView/client.js +20 -13
- package/dist/views/NewTicketView/index.js +4 -2
- package/dist/views/PendingEmailsView/client.js +9 -3
- package/dist/views/PendingEmailsView/index.js +4 -4
- package/dist/views/SupportDashboardView/client.js +17 -19
- package/dist/views/SupportDashboardView/index.js +4 -4
- package/dist/views/TicketDetailView/client.js +23 -11
- package/dist/views/TicketDetailView/index.js +4 -4
- package/dist/views/TicketInboxView/client.js +52 -26
- package/dist/views/TicketInboxView/index.js +4 -2
- package/dist/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
- package/dist/views/TicketingSettingsView/client.js +44 -26
- package/dist/views/TicketingSettingsView/index.js +4 -4
- package/dist/views/TimeDashboardView/client.js +10 -7
- package/dist/views/TimeDashboardView/index.js +4 -4
- package/dist/views/shared/ErrorBoundary.d.ts +36 -1
- package/dist/views/shared/ErrorBoundary.js +59 -28
- package/dist/views/shared/adminTokens.d.ts +15 -5
- package/dist/views/shared/adminTokens.js +23 -7
- package/dist/views/shared/icons.d.ts +49 -0
- package/dist/views/shared/icons.js +92 -0
- package/dist/views/shared/locales/en.json +15 -1
- package/dist/views/shared/locales/fr.json +15 -1
- package/dist/views/shared/viewAccess.d.ts +29 -0
- package/dist/views/shared/viewAccess.js +24 -0
- package/package.json +31 -21
- package/scripts/uninstall-data.mjs +178 -0
- package/scripts/uninstall.mjs +184 -0
- package/src/collections/Tickets.ts +7 -0
- package/src/collections/TimeEntries.ts +11 -3
- package/src/components/RichTextEditor/index.tsx +1 -1
- package/src/components/TicketConversation/RewriteDropdown.tsx +1 -1
- package/src/components/TicketConversation/components/AISummaryPanel.tsx +3 -0
- package/src/components/TicketConversation/components/ActionPanels.tsx +13 -8
- package/src/components/TicketConversation/components/ClientHistory.tsx +1 -0
- package/src/components/TicketConversation/components/CodeBlock.tsx +1 -0
- package/src/components/TicketConversation/components/CodeBlockInserter.tsx +1 -1
- package/src/components/TicketConversation/components/QuickActions.tsx +10 -8
- package/src/components/TicketConversation/components/TicketHeader.tsx +2 -0
- package/src/components/TicketConversation/components/TimeTrackingPanel.tsx +17 -9
- package/src/components/TicketConversation/index.tsx +41 -7
- package/src/endpoints/auth-2fa.ts +53 -8
- package/src/endpoints/capabilities.ts +2 -4
- package/src/endpoints/chatbot.ts +2 -2
- package/src/endpoints/delete-account.ts +191 -47
- package/src/endpoints/export-data.ts +104 -4
- package/src/endpoints/import-conversation.ts +2 -2
- package/src/endpoints/login.ts +13 -3
- package/src/endpoints/purge-logs.ts +6 -15
- package/src/endpoints/push.ts +14 -1
- package/src/endpoints/statuses.ts +17 -0
- package/src/index.ts +2 -0
- package/src/plugin.ts +51 -1
- package/src/portal/LiveChat.tsx +1 -1
- package/src/portal/auth/profile/page.tsx +3 -2
- package/src/portal/icons.tsx +91 -0
- package/src/portal/login/page.tsx +14 -4
- package/src/styles/BillingView.module.scss +11 -11
- package/src/styles/ChatView.module.scss +7 -7
- package/src/styles/CommandPalette.module.scss +1 -1
- package/src/styles/CrmView.module.scss +9 -9
- package/src/styles/EmailTracking.module.scss +6 -6
- package/src/styles/ImportConversation.module.scss +5 -5
- package/src/styles/Logs.module.scss +5 -5
- package/src/styles/NewTicket.module.scss +2 -2
- package/src/styles/PendingEmails.module.scss +13 -13
- package/src/styles/SupportDashboard.module.scss +24 -8
- package/src/styles/TicketDetail.module.scss +20 -20
- package/src/styles/TicketInbox.module.scss +6 -6
- package/src/styles/TicketingSettings.module.scss +10 -10
- package/src/styles/TimeDashboard.module.scss +6 -6
- package/src/styles/_tokens.scss +3 -1
- package/src/types.ts +20 -0
- package/src/utils/push.ts +22 -0
- package/src/utils/rateLimiter.ts +98 -0
- package/src/utils/retention.ts +111 -0
- package/src/utils/slugs.ts +15 -0
- package/src/utils/twoFactorChallenge.ts +6 -1
- package/src/utils/urlSafety.ts +36 -1
- package/src/views/BillingView/client.tsx +17 -8
- package/src/views/BillingView/index.tsx +4 -4
- package/src/views/ChatView/client.tsx +2 -0
- package/src/views/ChatView/index.tsx +4 -4
- package/src/views/CrmView/client.tsx +2 -0
- package/src/views/CrmView/index.tsx +4 -4
- package/src/views/EmailTrackingView/client.tsx +18 -7
- package/src/views/EmailTrackingView/index.tsx +4 -4
- package/src/views/ImportConversationView/client.tsx +1 -0
- package/src/views/ImportConversationView/index.tsx +4 -4
- package/src/views/LogsView/client.tsx +1 -1
- package/src/views/LogsView/index.tsx +4 -2
- package/src/views/NewTicketView/client.tsx +22 -13
- package/src/views/NewTicketView/index.tsx +4 -2
- package/src/views/PendingEmailsView/client.tsx +9 -3
- package/src/views/PendingEmailsView/index.tsx +4 -4
- package/src/views/SupportDashboardView/client.tsx +11 -5
- package/src/views/SupportDashboardView/index.tsx +4 -4
- package/src/views/TicketDetailView/client.tsx +25 -11
- package/src/views/TicketDetailView/index.tsx +4 -4
- package/src/views/TicketInboxView/client.tsx +47 -7
- package/src/views/TicketInboxView/index.tsx +4 -2
- package/src/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
- package/src/views/TicketingSettingsView/client.tsx +201 -144
- package/src/views/TicketingSettingsView/index.tsx +4 -4
- package/src/views/TimeDashboardView/client.tsx +10 -7
- package/src/views/TimeDashboardView/index.tsx +4 -4
- package/src/views/shared/ErrorBoundary.tsx +95 -31
- package/src/views/shared/adminTokens.ts +28 -11
- package/src/views/shared/icons.tsx +146 -0
- package/src/views/shared/locales/en.json +15 -1
- package/src/views/shared/locales/fr.json +15 -1
- package/src/views/shared/viewAccess.ts +73 -0
- package/src/types/lucide-react.d.ts +0 -42
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import React, { useRef, useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import React, { useRef, useId, useState, useEffect, useCallback } from 'react';
|
|
4
4
|
import { useSearchParams } from 'next/navigation';
|
|
5
5
|
import Link from 'next/link';
|
|
6
6
|
import { RichTextEditor } from '../../components/RichTextEditor/index.js';
|
|
@@ -25,6 +25,11 @@ const TicketDetailClient = () => {
|
|
|
25
25
|
const threadEndRef = useRef(null);
|
|
26
26
|
const dropdownRef = useRef(null);
|
|
27
27
|
const fileInputRef = useRef(null);
|
|
28
|
+
const manualTimeId = useId();
|
|
29
|
+
const billingTypeId = useId();
|
|
30
|
+
const flatAmountId = useId();
|
|
31
|
+
const billedAmountId = useId();
|
|
32
|
+
const paymentStatusId = useId();
|
|
28
33
|
const [ticket, setTicket] = useState(null);
|
|
29
34
|
const [messages, setMessages] = useState([]);
|
|
30
35
|
const [client, setClient] = useState(null);
|
|
@@ -755,7 +760,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
755
760
|
Array.isArray(msg.attachments) && msg.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: s.attachments, children: msg.attachments.map((att, i) => {
|
|
756
761
|
const file = typeof att.file === "object" ? att.file : null;
|
|
757
762
|
if (!file) return null;
|
|
758
|
-
return (file.mimeType || "").startsWith("image/") ? /* @__PURE__ */ jsx("a", { href: file.url || "#", target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx("img", { src: file.url || "", alt: "", className: s.attachmentImg }) }, i) : /* @__PURE__ */ jsxs("a", { href: file.url || "#", target: "_blank", rel: "noopener noreferrer", className: s.attachmentFile, children: [
|
|
763
|
+
return (file.mimeType || "").startsWith("image/") ? /* @__PURE__ */ jsx("a", { href: file.url || "#", target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx("img", { src: file.url || "", alt: file.filename || t("detail.file"), className: s.attachmentImg }) }, i) : /* @__PURE__ */ jsxs("a", { href: file.url || "#", target: "_blank", rel: "noopener noreferrer", className: s.attachmentFile, children: [
|
|
759
764
|
"PJ ",
|
|
760
765
|
file.filename || "Fichier"
|
|
761
766
|
] }, i);
|
|
@@ -846,7 +851,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
846
851
|
"\u{1F4CE} ",
|
|
847
852
|
t("detail.file")
|
|
848
853
|
] }),
|
|
849
|
-
/* @__PURE__ */ jsx("input", { ref: fileInputRef, type: "file", multiple: true, className: s.hiddenFileInput, onChange: (e) => handleFileSelect(e.target.files) }),
|
|
854
|
+
/* @__PURE__ */ jsx("input", { ref: fileInputRef, type: "file", multiple: true, "aria-label": t("detail.file"), className: s.hiddenFileInput, onChange: (e) => handleFileSelect(e.target.files) }),
|
|
850
855
|
macros.length > 0 && /* @__PURE__ */ jsxs(
|
|
851
856
|
"select",
|
|
852
857
|
{
|
|
@@ -920,6 +925,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
920
925
|
/* @__PURE__ */ jsxs(
|
|
921
926
|
"select",
|
|
922
927
|
{
|
|
928
|
+
"aria-label": t("detail.sendAs"),
|
|
923
929
|
value: sendAsClient ? "client" : "admin",
|
|
924
930
|
onChange: (e) => {
|
|
925
931
|
const asClient = e.target.value === "client";
|
|
@@ -1132,9 +1138,9 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1132
1138
|
] }),
|
|
1133
1139
|
/* @__PURE__ */ jsx("div", { className: s.timerBar, "aria-hidden": true, children: /* @__PURE__ */ jsx("div", { className: s.timerBarFill, style: { width: `${Math.min(100, (totalMin + Math.floor(timerSeconds / 60)) / 120 * 100)}%` } }) }),
|
|
1134
1140
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, marginTop: 8, alignItems: "center" }, children: [
|
|
1135
|
-
/* @__PURE__ */ jsx("input", { type: "number", min: "1", placeholder: "min", style: { width: 60, padding: "4px 8px", borderRadius: 6, border: "1px solid var(--theme-elevation-200)", fontSize: 12, color: "var(--theme-text)", background: "var(--theme-elevation-0)" }, id:
|
|
1141
|
+
/* @__PURE__ */ jsx("input", { type: "number", min: "1", placeholder: "min", "aria-label": t("detail.manualMinutes"), style: { width: 60, padding: "4px 8px", borderRadius: 6, border: "1px solid var(--theme-elevation-200)", fontSize: 12, color: "var(--theme-text)", background: "var(--theme-elevation-0)" }, id: manualTimeId }),
|
|
1136
1142
|
/* @__PURE__ */ jsx("button", { className: `${s.timerBtn} ${s.timerBtnGhost}`, onClick: async () => {
|
|
1137
|
-
const input = document.getElementById(
|
|
1143
|
+
const input = document.getElementById(manualTimeId);
|
|
1138
1144
|
const mins = Number(input?.value);
|
|
1139
1145
|
if (!mins || mins < 1 || !ticketId) return;
|
|
1140
1146
|
try {
|
|
@@ -1145,7 +1151,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1145
1151
|
}
|
|
1146
1152
|
}, style: { fontSize: 11 }, children: t("detail.addTime") })
|
|
1147
1153
|
] }),
|
|
1148
|
-
/* @__PURE__ */ jsxs("div", { style: { marginTop: 8, fontSize: 11, color: "var(--theme-elevation-
|
|
1154
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: 8, fontSize: 11, color: "var(--theme-elevation-650)" }, children: [
|
|
1149
1155
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "2px 0", alignItems: "center" }, children: [
|
|
1150
1156
|
/* @__PURE__ */ jsx("span", { children: t("detail.billing.billable") }),
|
|
1151
1157
|
/* @__PURE__ */ jsx(
|
|
@@ -1172,7 +1178,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1172
1178
|
] })
|
|
1173
1179
|
] })
|
|
1174
1180
|
] }),
|
|
1175
|
-
timeEntries.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: 8, fontSize: 11 }, children: timeEntries.slice(0, 6).map((e) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "3px 0", color: "var(--theme-elevation-
|
|
1181
|
+
timeEntries.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: 8, fontSize: 11 }, children: timeEntries.slice(0, 6).map((e) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "3px 0", color: "var(--theme-elevation-650)" }, children: [
|
|
1176
1182
|
/* @__PURE__ */ jsx("span", { children: new Date(e.date).toLocaleDateString(DATE_LOCALE, { day: "numeric", month: "short" }) }),
|
|
1177
1183
|
/* @__PURE__ */ jsxs("span", { title: e.description, style: { fontWeight: 600, cursor: e.description ? "help" : "default" }, children: [
|
|
1178
1184
|
e.duration,
|
|
@@ -1191,6 +1197,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1191
1197
|
"input",
|
|
1192
1198
|
{
|
|
1193
1199
|
className: s.tagInput,
|
|
1200
|
+
"aria-label": t("detail.addTag"),
|
|
1194
1201
|
value: newTagValue,
|
|
1195
1202
|
onChange: (e) => setNewTagValue(e.target.value),
|
|
1196
1203
|
onKeyDown: (e) => {
|
|
@@ -1211,10 +1218,11 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1211
1218
|
/* @__PURE__ */ jsx("div", { className: s.sideSectionTitle, children: t("detail.billing.title") }),
|
|
1212
1219
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
1213
1220
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1214
|
-
/* @__PURE__ */ jsx("
|
|
1221
|
+
/* @__PURE__ */ jsx("label", { style: { fontSize: 12 }, htmlFor: billingTypeId, children: t("detail.billing.type") }),
|
|
1215
1222
|
/* @__PURE__ */ jsxs(
|
|
1216
1223
|
"select",
|
|
1217
1224
|
{
|
|
1225
|
+
id: billingTypeId,
|
|
1218
1226
|
value: ticket?.billingType || "hourly",
|
|
1219
1227
|
onChange: async (e) => {
|
|
1220
1228
|
try {
|
|
@@ -1237,11 +1245,12 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1237
1245
|
)
|
|
1238
1246
|
] }),
|
|
1239
1247
|
ticket?.billingType === "flat" && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1240
|
-
/* @__PURE__ */ jsx("
|
|
1248
|
+
/* @__PURE__ */ jsx("label", { style: { fontSize: 12 }, htmlFor: flatAmountId, children: t("detail.billing.flatAmount") }),
|
|
1241
1249
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
1242
1250
|
/* @__PURE__ */ jsx(
|
|
1243
1251
|
"input",
|
|
1244
1252
|
{
|
|
1253
|
+
id: flatAmountId,
|
|
1245
1254
|
type: "number",
|
|
1246
1255
|
defaultValue: ticket?.flatRateAmount ?? "",
|
|
1247
1256
|
placeholder: "0",
|
|
@@ -1265,11 +1274,12 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1265
1274
|
] })
|
|
1266
1275
|
] }),
|
|
1267
1276
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1268
|
-
/* @__PURE__ */ jsx("
|
|
1277
|
+
/* @__PURE__ */ jsx("label", { style: { fontSize: 12 }, htmlFor: billedAmountId, children: t("detail.billing.billedAmount") }),
|
|
1269
1278
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
1270
1279
|
/* @__PURE__ */ jsx(
|
|
1271
1280
|
"input",
|
|
1272
1281
|
{
|
|
1282
|
+
id: billedAmountId,
|
|
1273
1283
|
type: "number",
|
|
1274
1284
|
defaultValue: ticket?.billedAmount ?? "",
|
|
1275
1285
|
placeholder: "0",
|
|
@@ -1293,10 +1303,11 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1293
1303
|
] })
|
|
1294
1304
|
] }),
|
|
1295
1305
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1296
|
-
/* @__PURE__ */ jsx("
|
|
1306
|
+
/* @__PURE__ */ jsx("label", { style: { fontSize: 12 }, htmlFor: paymentStatusId, children: t("detail.billing.payment") }),
|
|
1297
1307
|
/* @__PURE__ */ jsxs(
|
|
1298
1308
|
"select",
|
|
1299
1309
|
{
|
|
1310
|
+
id: paymentStatusId,
|
|
1300
1311
|
value: ticket?.paymentStatus || "unpaid",
|
|
1301
1312
|
onChange: async (e) => {
|
|
1302
1313
|
try {
|
|
@@ -1382,6 +1393,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1382
1393
|
"input",
|
|
1383
1394
|
{
|
|
1384
1395
|
className: s.splitInput,
|
|
1396
|
+
"aria-label": t("detail.split.subjectLabel"),
|
|
1385
1397
|
value: splitSubject,
|
|
1386
1398
|
onChange: (e) => setSplitSubject(e.target.value),
|
|
1387
1399
|
onKeyDown: (e) => {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { DefaultTemplate } from '@payloadcms/next/templates';
|
|
3
3
|
import { redirect } from 'next/navigation';
|
|
4
|
+
import { supportViewRedirectTarget } from '../shared/viewAccess.js';
|
|
4
5
|
import { AdminErrorBoundary } from '../shared/ErrorBoundary.js';
|
|
5
6
|
import { TicketDetailClient } from './client.js';
|
|
6
7
|
|
|
7
8
|
const TicketDetailView = ({ initPageResult }) => {
|
|
8
9
|
const { req, visibleEntities } = initPageResult;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
10
|
+
const redirectTo = supportViewRedirectTarget(initPageResult);
|
|
11
|
+
if (redirectTo) redirect(redirectTo);
|
|
12
12
|
return /* @__PURE__ */ jsx(
|
|
13
13
|
DefaultTemplate,
|
|
14
14
|
{
|
|
@@ -18,7 +18,7 @@ const TicketDetailView = ({ initPageResult }) => {
|
|
|
18
18
|
payload: req.payload,
|
|
19
19
|
permissions: initPageResult.permissions,
|
|
20
20
|
searchParams: {},
|
|
21
|
-
user: req.user,
|
|
21
|
+
user: req.user ?? void 0,
|
|
22
22
|
visibleEntities,
|
|
23
23
|
children: /* @__PURE__ */ jsx(AdminErrorBoundary, { viewName: "TicketDetailView", children: /* @__PURE__ */ jsx(TicketDetailClient, {}) })
|
|
24
24
|
}
|
|
@@ -9,6 +9,7 @@ import { StatusPill } from '../shared/StatusPill.js';
|
|
|
9
9
|
import { computeSlaState, formatSlaRemaining } from '../shared/sla.js';
|
|
10
10
|
import s from '../../styles/TicketInbox.module.scss';
|
|
11
11
|
|
|
12
|
+
const INBOX_TABPANEL_ID = "inbox-tabpanel";
|
|
12
13
|
const PRIORITY_COLORS = {
|
|
13
14
|
urgent: "var(--theme-error-500)",
|
|
14
15
|
high: "var(--theme-warning-500)",
|
|
@@ -213,6 +214,7 @@ const TicketInboxClient = () => {
|
|
|
213
214
|
{
|
|
214
215
|
type: "text",
|
|
215
216
|
className: s.searchInput,
|
|
217
|
+
"aria-label": t("inbox.searchLabel"),
|
|
216
218
|
placeholder: t("inbox.searchPlaceholder"),
|
|
217
219
|
value: search,
|
|
218
220
|
onChange: (e) => setSearch(e.target.value)
|
|
@@ -223,31 +225,55 @@ const TicketInboxClient = () => {
|
|
|
223
225
|
/* @__PURE__ */ jsx(Link, { href: "/admin/support/new-ticket", className: s.newTicketBtn, children: t("inbox.newTicketBtn") })
|
|
224
226
|
] })
|
|
225
227
|
] }),
|
|
226
|
-
/* @__PURE__ */ jsx(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
228
|
+
/* @__PURE__ */ jsx(
|
|
229
|
+
"div",
|
|
230
|
+
{
|
|
231
|
+
className: s.tabs,
|
|
232
|
+
role: "tablist",
|
|
233
|
+
"aria-label": t("inbox.tabsLabel"),
|
|
234
|
+
onKeyDown: (e) => {
|
|
235
|
+
const keys = ["ArrowLeft", "ArrowRight", "Home", "End"];
|
|
236
|
+
if (!keys.includes(e.key)) return;
|
|
237
|
+
e.preventDefault();
|
|
238
|
+
const i = tabs.findIndex((tk) => tk.key === tab);
|
|
239
|
+
const next = e.key === "Home" ? 0 : e.key === "End" ? tabs.length - 1 : e.key === "ArrowLeft" ? (i - 1 + tabs.length) % tabs.length : (i + 1) % tabs.length;
|
|
240
|
+
const target = tabs[next];
|
|
241
|
+
if (!target) return;
|
|
242
|
+
setTab(target.key);
|
|
243
|
+
setSelectedIdx(-1);
|
|
244
|
+
document.getElementById(`inbox-tab-${target.key}`)?.focus();
|
|
242
245
|
},
|
|
243
|
-
tk
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
children: tabs.map((tk) => {
|
|
247
|
+
const isAlert = tk.alert && tk.count > 0;
|
|
248
|
+
return /* @__PURE__ */ jsxs(
|
|
249
|
+
"button",
|
|
250
|
+
{
|
|
251
|
+
type: "button",
|
|
252
|
+
role: "tab",
|
|
253
|
+
id: `inbox-tab-${tk.key}`,
|
|
254
|
+
"aria-selected": tab === tk.key,
|
|
255
|
+
"aria-controls": INBOX_TABPANEL_ID,
|
|
256
|
+
tabIndex: tab === tk.key ? 0 : -1,
|
|
257
|
+
className: `${s.tab} ${tab === tk.key ? s.tabActive : ""} ${isAlert ? s.tabAlert : ""}`,
|
|
258
|
+
onClick: () => {
|
|
259
|
+
setTab(tk.key);
|
|
260
|
+
setSelectedIdx(-1);
|
|
261
|
+
},
|
|
262
|
+
children: [
|
|
263
|
+
tk.label,
|
|
264
|
+
/* @__PURE__ */ jsx("span", { className: `${s.tabCount} ${isAlert ? s.tabCountAlert : ""}`, children: tk.count })
|
|
265
|
+
]
|
|
266
|
+
},
|
|
267
|
+
tk.key
|
|
268
|
+
);
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
),
|
|
246
272
|
/* @__PURE__ */ jsx("div", { className: s.sortRow, children: checkedIds.size > 0 ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center", flex: 1 }, children: [
|
|
247
273
|
/* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: "var(--theme-text)" }, children: checkedIds.size > 1 ? t("inbox.selectedPlural", { count: String(checkedIds.size) }) : t("inbox.selected", { count: String(checkedIds.size) }) }),
|
|
248
|
-
/* @__PURE__ */ jsx("button", { className: s.sortSelect, onClick: () => handleBulkAction("close"), disabled: bulkProcessing, children: t("inbox.closeAction") }),
|
|
249
|
-
/* @__PURE__ */ jsx("button", { className: s.sortSelect, onClick: () => handleBulkAction("reopen"), disabled: bulkProcessing, children: t("inbox.reopenAction") }),
|
|
250
|
-
/* @__PURE__ */ jsxs("select", { className: s.sortSelect, value: bulkAction, onChange: (e) => {
|
|
274
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: s.sortSelect, onClick: () => handleBulkAction("close"), disabled: bulkProcessing, children: t("inbox.closeAction") }),
|
|
275
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: s.sortSelect, onClick: () => handleBulkAction("reopen"), disabled: bulkProcessing, children: t("inbox.reopenAction") }),
|
|
276
|
+
/* @__PURE__ */ jsxs("select", { className: s.sortSelect, "aria-label": t("inbox.moreActions"), value: bulkAction, onChange: (e) => {
|
|
251
277
|
if (e.target.value) handleBulkAction(e.target.value);
|
|
252
278
|
setBulkAction("");
|
|
253
279
|
}, children: [
|
|
@@ -255,14 +281,14 @@ const TicketInboxClient = () => {
|
|
|
255
281
|
/* @__PURE__ */ jsx("option", { value: "set_priority", children: t("inbox.changePriority") }),
|
|
256
282
|
/* @__PURE__ */ jsx("option", { value: "delete", children: t("inbox.deleteAction") })
|
|
257
283
|
] }),
|
|
258
|
-
/* @__PURE__ */ jsx("button", { className: s.sortSelect, onClick: () => setCheckedIds(/* @__PURE__ */ new Set()), style: { marginLeft: "auto" }, children: t("inbox.deselect") })
|
|
259
|
-
] }) : /* @__PURE__ */ jsxs("select", { className: s.sortSelect, value: sort, onChange: (e) => setSort(e.target.value), children: [
|
|
284
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: s.sortSelect, onClick: () => setCheckedIds(/* @__PURE__ */ new Set()), style: { marginLeft: "auto" }, children: t("inbox.deselect") })
|
|
285
|
+
] }) : /* @__PURE__ */ jsxs("select", { className: s.sortSelect, "aria-label": t("inbox.sortLabel"), value: sort, onChange: (e) => setSort(e.target.value), children: [
|
|
260
286
|
/* @__PURE__ */ jsx("option", { value: "-updatedAt", children: t("inbox.sort.newest") }),
|
|
261
287
|
/* @__PURE__ */ jsx("option", { value: "updatedAt", children: t("inbox.sort.oldest") }),
|
|
262
288
|
/* @__PURE__ */ jsx("option", { value: "-createdAt", children: t("inbox.sort.created") }),
|
|
263
289
|
/* @__PURE__ */ jsx("option", { value: "priority", children: t("inbox.sort.priority") })
|
|
264
290
|
] }) }),
|
|
265
|
-
loading ? /* @__PURE__ */ jsx("div", { className: s.loading, children: t("common.loading") }) : tickets.length === 0 ? /* @__PURE__ */ jsxs("div", { className: s.empty, children: [
|
|
291
|
+
/* @__PURE__ */ jsx("div", { role: "tabpanel", id: INBOX_TABPANEL_ID, "aria-labelledby": `inbox-tab-${tab}`, children: loading ? /* @__PURE__ */ jsx("div", { className: s.loading, children: t("common.loading") }) : tickets.length === 0 ? /* @__PURE__ */ jsxs("div", { className: s.empty, children: [
|
|
266
292
|
/* @__PURE__ */ jsx("div", { className: s.emptyIcon, children: "--" }),
|
|
267
293
|
/* @__PURE__ */ jsx("div", { className: s.emptyText, children: t("inbox.empty") })
|
|
268
294
|
] }) : /* @__PURE__ */ jsx("div", { className: s.list, children: tickets.map((tk, idx) => {
|
|
@@ -333,7 +359,7 @@ const TicketInboxClient = () => {
|
|
|
333
359
|
},
|
|
334
360
|
tk.id
|
|
335
361
|
);
|
|
336
|
-
}) }),
|
|
362
|
+
}) }) }),
|
|
337
363
|
/* @__PURE__ */ jsxs("div", { className: s.keyboardHints, children: [
|
|
338
364
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
339
365
|
/* @__PURE__ */ jsx("kbd", { children: "\u2191" }),
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { DefaultTemplate } from '@payloadcms/next/templates';
|
|
3
3
|
import { redirect } from 'next/navigation';
|
|
4
|
+
import { supportViewRedirectTarget } from '../shared/viewAccess.js';
|
|
4
5
|
import { AdminErrorBoundary } from '../shared/ErrorBoundary.js';
|
|
5
6
|
import { TicketInboxClient } from './client.js';
|
|
6
7
|
|
|
7
8
|
const TicketInboxView = ({ initPageResult }) => {
|
|
8
9
|
const { req, visibleEntities } = initPageResult;
|
|
9
|
-
|
|
10
|
+
const redirectTo = supportViewRedirectTarget(initPageResult);
|
|
11
|
+
if (redirectTo) redirect(redirectTo);
|
|
10
12
|
return /* @__PURE__ */ jsx(
|
|
11
13
|
DefaultTemplate,
|
|
12
14
|
{
|
|
@@ -16,7 +18,7 @@ const TicketInboxView = ({ initPageResult }) => {
|
|
|
16
18
|
payload: req.payload,
|
|
17
19
|
permissions: initPageResult.permissions,
|
|
18
20
|
searchParams: {},
|
|
19
|
-
user: req.user,
|
|
21
|
+
user: req.user ?? void 0,
|
|
20
22
|
visibleEntities,
|
|
21
23
|
children: /* @__PURE__ */ jsx(AdminErrorBoundary, { viewName: "TicketInboxView", children: /* @__PURE__ */ jsx(TicketInboxClient, {}) })
|
|
22
24
|
}
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
|
|
71
71
|
.sectionDescription {
|
|
72
72
|
font-size: 0.8125rem;
|
|
73
|
-
color: var(--theme-elevation-
|
|
73
|
+
color: var(--theme-elevation-650);
|
|
74
74
|
margin: 0 0 1rem;
|
|
75
75
|
line-height: 1.5;
|
|
76
76
|
}
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
|
|
144
144
|
.featureDesc {
|
|
145
145
|
font-size: 0.75rem;
|
|
146
|
-
color: var(--theme-elevation-
|
|
146
|
+
color: var(--theme-elevation-650);
|
|
147
147
|
margin-top: 0.125rem;
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
|
|
167
167
|
.fieldDescription {
|
|
168
168
|
font-size: 0.75rem;
|
|
169
|
-
color: var(--theme-elevation-
|
|
169
|
+
color: var(--theme-elevation-650);
|
|
170
170
|
font-weight: 400;
|
|
171
171
|
margin-top: 0.125rem;
|
|
172
172
|
}
|
|
@@ -194,7 +194,7 @@
|
|
|
194
194
|
.inputReadonly {
|
|
195
195
|
composes: input;
|
|
196
196
|
background: var(--theme-elevation-50);
|
|
197
|
-
color: var(--theme-elevation-
|
|
197
|
+
color: var(--theme-elevation-650);
|
|
198
198
|
cursor: not-allowed;
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
|
|
231
231
|
.inlineDesc {
|
|
232
232
|
font-size: 0.75rem;
|
|
233
|
-
color: var(--theme-elevation-
|
|
233
|
+
color: var(--theme-elevation-650);
|
|
234
234
|
margin-top: 0.125rem;
|
|
235
235
|
}
|
|
236
236
|
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
|
|
245
245
|
.slaHint {
|
|
246
246
|
font-size: 0.75rem;
|
|
247
|
-
color: var(--theme-elevation-
|
|
247
|
+
color: var(--theme-elevation-650);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// ── API Key ───────────────────────────────────
|
|
@@ -290,7 +290,7 @@
|
|
|
290
290
|
.aiToggleDesc {
|
|
291
291
|
display: block;
|
|
292
292
|
font-size: 0.6875rem;
|
|
293
|
-
color: var(--theme-elevation-
|
|
293
|
+
color: var(--theme-elevation-650);
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
// ── Signature ─────────────────────────────────
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import React, { useState, useEffect } from 'react';
|
|
4
|
-
import { Settings, Mail, Bot, Clock, Timer, Globe, FileSignature } from '
|
|
3
|
+
import React, { useState, useEffect, useId } from 'react';
|
|
4
|
+
import { Settings, Mail, Bot, Clock, Timer, Globe, FileSignature } from '../shared/icons.js';
|
|
5
5
|
import { btnStyle, V } from '../shared/adminTokens.js';
|
|
6
6
|
import { AdminViewHeader } from '../shared/AdminViewHeader.js';
|
|
7
7
|
import { DEFAULT_FEATURES } from '../../components/TicketConversation/config.js';
|
|
@@ -196,13 +196,16 @@ const CollapsibleSection = ({ title, icon, color, defaultOpen = true, children,
|
|
|
196
196
|
open && /* @__PURE__ */ jsx("div", { className: ts.sectionBody, children })
|
|
197
197
|
] });
|
|
198
198
|
};
|
|
199
|
-
const FieldRow = ({ label, description, children }) =>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
] })
|
|
199
|
+
const FieldRow = ({ label, description, children }) => {
|
|
200
|
+
const id = useId();
|
|
201
|
+
return /* @__PURE__ */ jsxs("div", { className: ts.fieldRow, children: [
|
|
202
|
+
/* @__PURE__ */ jsxs("div", { className: ts.fieldLabel, children: [
|
|
203
|
+
/* @__PURE__ */ jsx("label", { htmlFor: id, children: label }),
|
|
204
|
+
description && /* @__PURE__ */ jsx("div", { className: ts.fieldDescription, children: description })
|
|
205
|
+
] }),
|
|
206
|
+
/* @__PURE__ */ jsx("div", { className: ts.fieldContent, children: typeof children === "function" ? children(id) : children })
|
|
207
|
+
] });
|
|
208
|
+
};
|
|
206
209
|
const TicketingSettingsClient = () => {
|
|
207
210
|
const { t } = useTranslation();
|
|
208
211
|
const FEATURE_LIST = React.useMemo(() => getFeatureList(t), [t]);
|
|
@@ -283,7 +286,7 @@ const TicketingSettingsClient = () => {
|
|
|
283
286
|
title: t("settingsView.configTitle"),
|
|
284
287
|
subtitle: t("settings.subtitle", { enabled: String(enabledCount), total: String(totalCount) }),
|
|
285
288
|
actions: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8 }, children: [
|
|
286
|
-
/* @__PURE__ */ jsx("button", { onClick: handleReset, style: btnStyle(
|
|
289
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: handleReset, style: btnStyle(V.neutralBg, { small: true, fg: V.neutralFg }), children: t("settingsView.reset") }),
|
|
287
290
|
/* @__PURE__ */ jsx(
|
|
288
291
|
"button",
|
|
289
292
|
{
|
|
@@ -358,9 +361,10 @@ const TicketingSettingsClient = () => {
|
|
|
358
361
|
defaultOpen: false,
|
|
359
362
|
children: [
|
|
360
363
|
/* @__PURE__ */ jsx("p", { className: ts.sectionDescription, children: t("settingsView.emailDescription") }),
|
|
361
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.senderAddress"), description: t("settingsView.senderAddressDesc"), children: /* @__PURE__ */ jsx(
|
|
364
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.senderAddress"), description: t("settingsView.senderAddressDesc"), children: (id) => /* @__PURE__ */ jsx(
|
|
362
365
|
"input",
|
|
363
366
|
{
|
|
367
|
+
id,
|
|
364
368
|
type: "email",
|
|
365
369
|
value: settings.email.fromAddress,
|
|
366
370
|
onChange: (e) => updateEmail("fromAddress", e.target.value),
|
|
@@ -368,9 +372,10 @@ const TicketingSettingsClient = () => {
|
|
|
368
372
|
className: ts.input
|
|
369
373
|
}
|
|
370
374
|
) }),
|
|
371
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.senderName"), description: t("settingsView.senderNameDesc"), children: /* @__PURE__ */ jsx(
|
|
375
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.senderName"), description: t("settingsView.senderNameDesc"), children: (id) => /* @__PURE__ */ jsx(
|
|
372
376
|
"input",
|
|
373
377
|
{
|
|
378
|
+
id,
|
|
374
379
|
type: "text",
|
|
375
380
|
value: settings.email.fromName,
|
|
376
381
|
onChange: (e) => updateEmail("fromName", e.target.value),
|
|
@@ -378,9 +383,10 @@ const TicketingSettingsClient = () => {
|
|
|
378
383
|
className: ts.input
|
|
379
384
|
}
|
|
380
385
|
) }),
|
|
381
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.replyTo"), description: t("settingsView.replyToDesc"), children: /* @__PURE__ */ jsx(
|
|
386
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.replyTo"), description: t("settingsView.replyToDesc"), children: (id) => /* @__PURE__ */ jsx(
|
|
382
387
|
"input",
|
|
383
388
|
{
|
|
389
|
+
id,
|
|
384
390
|
type: "email",
|
|
385
391
|
value: settings.email.replyToAddress,
|
|
386
392
|
onChange: (e) => updateEmail("replyToAddress", e.target.value),
|
|
@@ -389,18 +395,20 @@ const TicketingSettingsClient = () => {
|
|
|
389
395
|
}
|
|
390
396
|
) }),
|
|
391
397
|
/* @__PURE__ */ jsx("div", { className: ts.separator }),
|
|
392
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.smtpServer"), description: t("settingsView.smtpServerDesc"), children: /* @__PURE__ */ jsx(
|
|
398
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.smtpServer"), description: t("settingsView.smtpServerDesc"), children: (id) => /* @__PURE__ */ jsx(
|
|
393
399
|
"input",
|
|
394
400
|
{
|
|
401
|
+
id,
|
|
395
402
|
type: "text",
|
|
396
403
|
value: smtpHost,
|
|
397
404
|
readOnly: true,
|
|
398
405
|
className: ts.inputReadonly
|
|
399
406
|
}
|
|
400
407
|
) }),
|
|
401
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.smtpPort"), children: /* @__PURE__ */ jsx(
|
|
408
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.smtpPort"), children: (id) => /* @__PURE__ */ jsx(
|
|
402
409
|
"input",
|
|
403
410
|
{
|
|
411
|
+
id,
|
|
404
412
|
type: "text",
|
|
405
413
|
value: smtpPort,
|
|
406
414
|
readOnly: true,
|
|
@@ -421,9 +429,10 @@ const TicketingSettingsClient = () => {
|
|
|
421
429
|
badge: features.ai ? /* @__PURE__ */ jsx("span", { className: ts.badge, style: { backgroundColor: "#dcfce7", color: "#166534" }, children: t("settingsView.aiBadgeActive") }) : /* @__PURE__ */ jsx("span", { className: ts.badge, style: { backgroundColor: "#fee2e2", color: "#991b1b" }, children: t("settingsView.aiBadgeInactive") }),
|
|
422
430
|
children: [
|
|
423
431
|
/* @__PURE__ */ jsx("p", { className: ts.sectionDescription, children: t("settingsView.aiDescription") }),
|
|
424
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.aiProvider"), description: t("settingsView.aiProviderDesc"), children: /* @__PURE__ */ jsxs(
|
|
432
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.aiProvider"), description: t("settingsView.aiProviderDesc"), children: (id) => /* @__PURE__ */ jsxs(
|
|
425
433
|
"select",
|
|
426
434
|
{
|
|
435
|
+
id,
|
|
427
436
|
value: settings.ai.provider,
|
|
428
437
|
onChange: (e) => updateAI("provider", e.target.value),
|
|
429
438
|
className: ts.select,
|
|
@@ -435,10 +444,11 @@ const TicketingSettingsClient = () => {
|
|
|
435
444
|
]
|
|
436
445
|
}
|
|
437
446
|
) }),
|
|
438
|
-
settings.ai.provider !== "ollama" && /* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.aiApiKey"), description: t("settingsView.aiApiKeyDesc"), children: /* @__PURE__ */ jsxs("div", { className: ts.apiKeyRow, children: [
|
|
447
|
+
settings.ai.provider !== "ollama" && /* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.aiApiKey"), description: t("settingsView.aiApiKeyDesc"), children: (id) => /* @__PURE__ */ jsxs("div", { className: ts.apiKeyRow, children: [
|
|
439
448
|
/* @__PURE__ */ jsx(
|
|
440
449
|
"input",
|
|
441
450
|
{
|
|
451
|
+
id,
|
|
442
452
|
type: showApiKey ? "text" : "password",
|
|
443
453
|
value: settings.ai.apiKey,
|
|
444
454
|
onChange: (e) => updateAI("apiKey", e.target.value),
|
|
@@ -456,9 +466,10 @@ const TicketingSettingsClient = () => {
|
|
|
456
466
|
}
|
|
457
467
|
)
|
|
458
468
|
] }) }),
|
|
459
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.aiModel"), description: t("settingsView.aiModelDesc"), children: /* @__PURE__ */ jsx(
|
|
469
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.aiModel"), description: t("settingsView.aiModelDesc"), children: (id) => /* @__PURE__ */ jsx(
|
|
460
470
|
"input",
|
|
461
471
|
{
|
|
472
|
+
id,
|
|
462
473
|
type: "text",
|
|
463
474
|
value: settings.ai.model,
|
|
464
475
|
onChange: (e) => updateAI("model", e.target.value),
|
|
@@ -500,10 +511,11 @@ const TicketingSettingsClient = () => {
|
|
|
500
511
|
defaultOpen: false,
|
|
501
512
|
children: [
|
|
502
513
|
/* @__PURE__ */ jsx("p", { className: ts.sectionDescription, children: t("settingsView.slaDescription") }),
|
|
503
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.slaFirstResponse"), description: t("settingsView.slaFirstResponseDesc"), children: /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
514
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.slaFirstResponse"), description: t("settingsView.slaFirstResponseDesc"), children: (id) => /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
504
515
|
/* @__PURE__ */ jsx(
|
|
505
516
|
"input",
|
|
506
517
|
{
|
|
518
|
+
id,
|
|
507
519
|
type: "number",
|
|
508
520
|
min: 1,
|
|
509
521
|
value: settings.sla.firstResponseMinutes,
|
|
@@ -520,10 +532,11 @@ const TicketingSettingsClient = () => {
|
|
|
520
532
|
")"
|
|
521
533
|
] })
|
|
522
534
|
] }) }),
|
|
523
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.slaResolution"), description: t("settingsView.slaResolutionDesc"), children: /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
535
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.slaResolution"), description: t("settingsView.slaResolutionDesc"), children: (id) => /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
524
536
|
/* @__PURE__ */ jsx(
|
|
525
537
|
"input",
|
|
526
538
|
{
|
|
539
|
+
id,
|
|
527
540
|
type: "number",
|
|
528
541
|
min: 1,
|
|
529
542
|
value: settings.sla.resolutionMinutes,
|
|
@@ -556,9 +569,10 @@ const TicketingSettingsClient = () => {
|
|
|
556
569
|
] })
|
|
557
570
|
] }),
|
|
558
571
|
/* @__PURE__ */ jsx("div", { className: ts.separator }),
|
|
559
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.escalationEmail"), description: t("settingsView.escalationEmailDesc"), children: /* @__PURE__ */ jsx(
|
|
572
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.escalationEmail"), description: t("settingsView.escalationEmailDesc"), children: (id) => /* @__PURE__ */ jsx(
|
|
560
573
|
"input",
|
|
561
574
|
{
|
|
575
|
+
id,
|
|
562
576
|
type: "email",
|
|
563
577
|
value: settings.sla.escalationEmail,
|
|
564
578
|
onChange: (e) => updateSLA("escalationEmail", e.target.value),
|
|
@@ -594,10 +608,11 @@ const TicketingSettingsClient = () => {
|
|
|
594
608
|
/* @__PURE__ */ jsx("span", { className: ts.inlineLabel, children: t("settingsView.autoCloseEnable") })
|
|
595
609
|
] }),
|
|
596
610
|
settings.autoClose.enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
597
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.autoCloseDelay"), description: t("settingsView.autoCloseDelayDesc"), children: /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
611
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.autoCloseDelay"), description: t("settingsView.autoCloseDelayDesc"), children: (id) => /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
598
612
|
/* @__PURE__ */ jsx(
|
|
599
613
|
"input",
|
|
600
614
|
{
|
|
615
|
+
id,
|
|
601
616
|
type: "number",
|
|
602
617
|
min: 1,
|
|
603
618
|
max: 90,
|
|
@@ -608,10 +623,11 @@ const TicketingSettingsClient = () => {
|
|
|
608
623
|
),
|
|
609
624
|
/* @__PURE__ */ jsx("span", { className: ts.slaHint, children: t("settingsView.days") })
|
|
610
625
|
] }) }),
|
|
611
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.autoCloseReminder"), description: t("settingsView.autoCloseReminderDesc"), children: /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
626
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.autoCloseReminder"), description: t("settingsView.autoCloseReminderDesc"), children: (id) => /* @__PURE__ */ jsxs("div", { className: ts.slaInline, children: [
|
|
612
627
|
/* @__PURE__ */ jsx(
|
|
613
628
|
"input",
|
|
614
629
|
{
|
|
630
|
+
id,
|
|
615
631
|
type: "number",
|
|
616
632
|
min: 1,
|
|
617
633
|
max: settings.autoClose.daysBeforeClose - 1,
|
|
@@ -646,9 +662,10 @@ const TicketingSettingsClient = () => {
|
|
|
646
662
|
defaultOpen: false,
|
|
647
663
|
children: [
|
|
648
664
|
/* @__PURE__ */ jsx("p", { className: ts.sectionDescription, children: t("settingsView.localeDescription") }),
|
|
649
|
-
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.language"), description: t("settingsView.languageDesc"), children: /* @__PURE__ */ jsxs(
|
|
665
|
+
/* @__PURE__ */ jsx(FieldRow, { label: t("settingsView.language"), description: t("settingsView.languageDesc"), children: (id) => /* @__PURE__ */ jsxs(
|
|
650
666
|
"select",
|
|
651
667
|
{
|
|
668
|
+
id,
|
|
652
669
|
value: settings.locale.language,
|
|
653
670
|
onChange: (e) => updateLocale("language", e.target.value),
|
|
654
671
|
className: ts.select,
|
|
@@ -673,6 +690,7 @@ const TicketingSettingsClient = () => {
|
|
|
673
690
|
/* @__PURE__ */ jsx(
|
|
674
691
|
"textarea",
|
|
675
692
|
{
|
|
693
|
+
"aria-label": t("settingsView.signatureTitle"),
|
|
676
694
|
value: signature,
|
|
677
695
|
onChange: (e) => {
|
|
678
696
|
setSignature(e.target.value);
|
|
@@ -710,7 +728,7 @@ const TicketingSettingsClient = () => {
|
|
|
710
728
|
alert(t("import.errorTitle"));
|
|
711
729
|
}
|
|
712
730
|
},
|
|
713
|
-
style: { ...btnStyle(opt.days === 0 ?
|
|
731
|
+
style: { ...btnStyle(opt.days === 0 ? V.red : V.neutralBg, { small: true, fg: opt.days === 0 ? void 0 : V.neutralFg }), fontSize: 11 },
|
|
714
732
|
children: opt.label
|
|
715
733
|
},
|
|
716
734
|
opt.days
|
|
@@ -718,7 +736,7 @@ const TicketingSettingsClient = () => {
|
|
|
718
736
|
] }, col)) })
|
|
719
737
|
] }),
|
|
720
738
|
/* @__PURE__ */ jsxs("div", { className: ts.bottomBar, children: [
|
|
721
|
-
/* @__PURE__ */ jsx("button", { onClick: handleReset, style: btnStyle(
|
|
739
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: handleReset, style: btnStyle(V.neutralBg, { small: true, fg: V.neutralFg }), children: t("settingsView.resetAll") }),
|
|
722
740
|
/* @__PURE__ */ jsx(
|
|
723
741
|
"button",
|
|
724
742
|
{
|