@nivaro/react 0.3.23 → 0.3.25
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/hooks/useSessionRecorder.js +1 -1
- package/dist/index.d.ts +50 -26
- package/dist/shared/components/FilePreviewLightbox.js +56 -35
- package/dist/shared/components/ItemEditForm.js +4309 -4263
- package/dist/shared/components/PageRenderer.js +63 -62
- package/dist/shared/components/ProfileView.js +555 -520
- package/dist/shared/components/RecordReadView.js +229 -229
- package/dist/shared/components/ReportView.js +123 -120
- package/dist/shared/components/ai/AiMarkdown.js +168 -148
- package/dist/shared/components/chat/RoomParts.js +120 -119
- package/dist/shared/components/chat/chat-core.js +228 -224
- package/dist/shared/components/item-edit/FieldRenderer.js +333 -333
- package/dist/shared/components/item-edit/FieldRow.js +413 -394
- package/dist/shared/components/item-edit/GroupSection.js +637 -635
- package/dist/shared/components/item-edit/InlineGridField.js +89 -90
- package/dist/shared/components/item-edit/QuickPicker.js +9 -9
- package/dist/shared/components/item-edit/RawEditSheet.js +80 -79
- package/dist/shared/components/item-edit/RowMatchPanel.js +1 -1
- package/dist/shared/components/item-edit/m2m-invalidate.js +19 -0
- package/dist/shared/components/item-edit/record-lookups.js +15 -0
- package/dist/shared/components/item-edit/render-stability.js +147 -0
- package/dist/shared/components/layout-editor/FormMapButton.js +5 -4
- package/dist/shared/components/notifications/DeliveryChips.js +27 -17
- package/dist/shared/components/profile/TeamsConnect.js +71 -0
- package/dist/shared/components/profile/primitives.js +4 -4
- package/dist/shared/lib/safe-href.js +10 -0
- package/dist/shared/lib/socket-realtime.js +107 -78
- package/package.json +6 -6
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
import { jsxs as t, jsx as e, Fragment as oe } from "react/jsx-runtime";
|
|
2
|
-
import { readUser as
|
|
3
|
-
import { useQueryClient as
|
|
4
|
-
import { Loader2 as
|
|
5
|
-
import { useState as
|
|
6
|
-
import { useNivaroClient as
|
|
7
|
-
import { get as
|
|
8
|
-
import { playNotificationSound as
|
|
9
|
-
import { BRAND_ACCENT as se, parseThemeAccents as
|
|
2
|
+
import { readUser as Se, readUserCard as _e, updateUser as be, readMyScopes as qe, saveMyScopeDefaults as Ce, readItems as ne } from "@nivaro/sdk";
|
|
3
|
+
import { useQueryClient as K, useQuery as w, useMutation as _ } from "@tanstack/react-query";
|
|
4
|
+
import { Loader2 as xe, Camera as Pe, Building2 as Ae, Mail as Te, Phone as Oe, Clock as Fe, Undo2 as Le, Check as De, UserRound as Me, Filter as Ee, LogOut as Ke, ShieldCheck as Ie } from "lucide-react";
|
|
5
|
+
import { useState as q, useMemo as $e, useRef as je } from "react";
|
|
6
|
+
import { useNivaroClient as L, useItemEditAuth as ve } from "../context.js";
|
|
7
|
+
import { get as D, patch as G, post as ae, put as Qe, del as Re } from "../lib/commands.js";
|
|
8
|
+
import { playNotificationSound as ge } from "../lib/notification-sound.js";
|
|
9
|
+
import { BRAND_ACCENT as se, parseThemeAccents as Ue, DEFAULT_THEME_ACCENTS as ye } from "../lib/theme-accents.js";
|
|
10
10
|
import { announceLocalPrefs as le } from "../lib/user-sync.js";
|
|
11
|
-
import { cn as R, setDisplayTimezone as
|
|
12
|
-
import { CustomStatusEditor as
|
|
13
|
-
import { AgentsPanel as
|
|
14
|
-
import { AiMemoryCard as
|
|
15
|
-
import { BrowserPushCard as
|
|
16
|
-
import { DelegationCard as
|
|
17
|
-
import { MailSuppressedPill as
|
|
18
|
-
import { TeamLoadCard as
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
import { cn as R, setDisplayTimezone as ze } from "../lib/utils.js";
|
|
12
|
+
import { CustomStatusEditor as Be, activeCustomStatus as He } from "./CustomStatusEditor.js";
|
|
13
|
+
import { AgentsPanel as Ye } from "./profile/AgentsPanel.js";
|
|
14
|
+
import { AiMemoryCard as We, AiHistoryCard as Ge } from "./profile/AiMemoryCard.js";
|
|
15
|
+
import { BrowserPushCard as Je } from "./profile/BrowserPushCard.js";
|
|
16
|
+
import { DelegationCard as Ve } from "./profile/DelegationCard.js";
|
|
17
|
+
import { MailSuppressedPill as Ze } from "./profile/MailSuppressedPill.js";
|
|
18
|
+
import { TeamLoadCard as Xe } from "./profile/PersonExtras.js";
|
|
19
|
+
import { TeamsConnect as et } from "./profile/TeamsConnect.js";
|
|
20
|
+
import { NotificationSourcesCard as tt } from "./NotificationSourcesCard.js";
|
|
21
|
+
import { UserScopesCard as at } from "./profile/PersonAccess.js";
|
|
22
|
+
import { PersonProfile as rt } from "./profile/PersonProfile.js";
|
|
23
|
+
import { Toggle as nt, SectionCard as ie, Field as Y, ConfirmButton as fe } from "./profile/primitives.js";
|
|
24
|
+
import { SimpleSelectXs as E } from "./ui/SimpleSelect.js";
|
|
25
|
+
const st = (i) => [i.first_name, i.last_name].filter(Boolean).join(" ") || (i.email ?? "Unknown"), lt = (i) => {
|
|
26
|
+
var m, r;
|
|
27
|
+
return (`${((m = i.first_name) == null ? void 0 : m[0]) ?? ""}${((r = i.last_name) == null ? void 0 : r[0]) ?? ""}` || (i.email ?? "?").slice(0, 2)).toUpperCase();
|
|
27
28
|
}, te = [
|
|
28
29
|
{
|
|
29
30
|
key: "mentions",
|
|
@@ -86,18 +87,18 @@ const Ze = (i) => [i.first_name, i.last_name].filter(Boolean).join(" ") || (i.em
|
|
|
86
87
|
help: "Any notification that does not fit a category above — direct messages from other users, access requests, task assignments."
|
|
87
88
|
}
|
|
88
89
|
];
|
|
89
|
-
function
|
|
90
|
-
const i =
|
|
90
|
+
function ot() {
|
|
91
|
+
const i = L(), m = K(), { data: r = [] } = w({
|
|
91
92
|
queryKey: ["nvr-profile-fields"],
|
|
92
|
-
queryFn: () => i.request(
|
|
93
|
-
}), [
|
|
94
|
-
mutationFn: (n) => i.request(
|
|
93
|
+
queryFn: () => i.request(D("/profile-fields/mine")).then((n) => n.data ?? []).catch(() => [])
|
|
94
|
+
}), [d, o] = q(null), l = _({
|
|
95
|
+
mutationFn: (n) => i.request(Qe("/profile-fields/mine", { values: n })),
|
|
95
96
|
onSuccess: () => {
|
|
96
97
|
o(null), m.invalidateQueries({ queryKey: ["nvr-profile-fields"] });
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
|
-
if (
|
|
100
|
-
const
|
|
100
|
+
if (r.length === 0) return null;
|
|
101
|
+
const s = d ?? Object.fromEntries(r.map((n) => [n.key, n.value ?? ""])), u = (n) => Array.isArray(n) ? n.map(String) : Array.isArray(n == null ? void 0 : n.choices) ? n.choices.map(
|
|
101
102
|
(b) => typeof b == "object" && b != null ? String(b.value ?? "") : String(b)
|
|
102
103
|
) : [];
|
|
103
104
|
return /* @__PURE__ */ t("div", { className: "rounded-lg border border-slate-200 bg-white dark:border-border dark:bg-card", children: [
|
|
@@ -105,42 +106,42 @@ function et() {
|
|
|
105
106
|
/* @__PURE__ */ e("h3", { className: "text-[13px] font-semibold text-slate-800 dark:text-slate-100", children: "Profile fields" }),
|
|
106
107
|
/* @__PURE__ */ e("p", { className: "mt-0.5 text-[11px] text-slate-400", children: "Extra details your organization tracks about people." })
|
|
107
108
|
] }),
|
|
108
|
-
/* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-3 p-4 sm:grid-cols-2", children:
|
|
109
|
+
/* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-3 p-4 sm:grid-cols-2", children: r.map((n) => /* @__PURE__ */ t("div", { children: [
|
|
109
110
|
/* @__PURE__ */ t("p", { className: "mb-1 text-[11px] font-medium text-slate-500", children: [
|
|
110
111
|
n.label,
|
|
111
112
|
n.required && /* @__PURE__ */ e("span", { className: "ml-0.5 text-red-500", children: "*" })
|
|
112
113
|
] }),
|
|
113
114
|
n.type === "boolean" ? /* @__PURE__ */ e(
|
|
114
|
-
|
|
115
|
+
E,
|
|
115
116
|
{
|
|
116
|
-
value:
|
|
117
|
+
value: s[n.key] || "false",
|
|
117
118
|
options: [
|
|
118
119
|
{ value: "true", label: "Yes" },
|
|
119
120
|
{ value: "false", label: "No" }
|
|
120
121
|
],
|
|
121
|
-
onChange: (b) => o({ ...
|
|
122
|
+
onChange: (b) => o({ ...s, [n.key]: b })
|
|
122
123
|
}
|
|
123
124
|
) : n.type === "select" ? /* @__PURE__ */ e(
|
|
124
|
-
|
|
125
|
+
E,
|
|
125
126
|
{
|
|
126
|
-
value:
|
|
127
|
+
value: s[n.key] || "",
|
|
127
128
|
options: [
|
|
128
129
|
{ value: "", label: "—" },
|
|
129
130
|
...u(n.options).map((b) => ({ value: b, label: b }))
|
|
130
131
|
],
|
|
131
|
-
onChange: (b) => o({ ...
|
|
132
|
+
onChange: (b) => o({ ...s, [n.key]: b })
|
|
132
133
|
}
|
|
133
134
|
) : /* @__PURE__ */ e(
|
|
134
135
|
"input",
|
|
135
136
|
{
|
|
136
137
|
type: n.type === "number" ? "number" : n.type === "date" ? "date" : "text",
|
|
137
|
-
value:
|
|
138
|
-
onChange: (b) => o({ ...
|
|
138
|
+
value: s[n.key] ?? "",
|
|
139
|
+
onChange: (b) => o({ ...s, [n.key]: b.target.value }),
|
|
139
140
|
className: "h-8 w-full rounded-md border border-slate-200 bg-background px-2 text-[12.5px] dark:border-border"
|
|
140
141
|
}
|
|
141
142
|
)
|
|
142
143
|
] }, n.key)) }),
|
|
143
|
-
|
|
144
|
+
d && /* @__PURE__ */ t("div", { className: "flex justify-end gap-2 border-t border-slate-100 px-4 py-2.5 dark:border-border/60", children: [
|
|
144
145
|
/* @__PURE__ */ e(
|
|
145
146
|
"button",
|
|
146
147
|
{
|
|
@@ -155,7 +156,7 @@ function et() {
|
|
|
155
156
|
{
|
|
156
157
|
type: "button",
|
|
157
158
|
disabled: l.isPending,
|
|
158
|
-
onClick: () => l.mutate(
|
|
159
|
+
onClick: () => l.mutate(s),
|
|
159
160
|
className: "h-7 rounded-md bg-nvr-cyan px-3 text-[12px] font-semibold text-white disabled:opacity-50",
|
|
160
161
|
children: l.isPending ? "Saving…" : "Save"
|
|
161
162
|
}
|
|
@@ -163,111 +164,127 @@ function et() {
|
|
|
163
164
|
] })
|
|
164
165
|
] });
|
|
165
166
|
}
|
|
166
|
-
function
|
|
167
|
-
|
|
167
|
+
function it() {
|
|
168
|
+
var me, pe;
|
|
169
|
+
const i = L(), m = K(), { data: r } = w({
|
|
168
170
|
queryKey: ["nvr-profile-prefs"],
|
|
169
|
-
queryFn: () => i.request(
|
|
170
|
-
var
|
|
171
|
-
return ((
|
|
171
|
+
queryFn: () => i.request(D("/users/me")).then((a) => {
|
|
172
|
+
var p;
|
|
173
|
+
return ((p = a.data) == null ? void 0 : p.preferences) ?? {};
|
|
174
|
+
})
|
|
175
|
+
}), { data: d } = w({
|
|
176
|
+
queryKey: ["nvr-profile-teams"],
|
|
177
|
+
queryFn: () => i.request(D("/users/me")).then((a) => {
|
|
178
|
+
var p, x;
|
|
179
|
+
return {
|
|
180
|
+
available: ((p = a.data) == null ? void 0 : p.teams_available) === !0,
|
|
181
|
+
link: ((x = a.data) == null ? void 0 : x.teams_link) ?? null
|
|
182
|
+
};
|
|
172
183
|
})
|
|
173
|
-
}), s = (
|
|
174
|
-
var
|
|
175
|
-
return ((x = (
|
|
176
|
-
}, [
|
|
177
|
-
mutationFn: (
|
|
184
|
+
}), o = (d == null ? void 0 : d.available) === !0, l = ((me = d == null ? void 0 : d.link) == null ? void 0 : me.status) === "active", s = (r == null ? void 0 : r.notification_prefs) ?? {}, u = (r == null ? void 0 : r.email_digest) === "daily" ? "daily" : "instant", n = (a) => {
|
|
185
|
+
var p, x;
|
|
186
|
+
return ((x = (p = s.matrix) == null ? void 0 : p[a]) == null ? void 0 : x.email) ?? u;
|
|
187
|
+
}, [b, h] = q(null), [C, N] = q(null), T = b ?? s.quiet_start ?? "", v = C ?? s.quiet_end ?? "", O = _({
|
|
188
|
+
mutationFn: (a) => i.request(G("/users/me/preferences", { notification_prefs: a })),
|
|
178
189
|
onSuccess: () => {
|
|
179
190
|
m.invalidateQueries({ queryKey: ["nvr-profile-prefs"] }), le(["notification_prefs"]);
|
|
180
191
|
}
|
|
181
|
-
}),
|
|
182
|
-
mutationFn: (
|
|
183
|
-
onSuccess: (
|
|
184
|
-
m.invalidateQueries({ queryKey: ["nvr-profile-prefs"] }), le(Object.keys(
|
|
192
|
+
}), A = _({
|
|
193
|
+
mutationFn: (a) => i.request(G("/users/me/preferences", a)),
|
|
194
|
+
onSuccess: (a, p) => {
|
|
195
|
+
m.invalidateQueries({ queryKey: ["nvr-profile-prefs"] }), le(Object.keys(p));
|
|
185
196
|
}
|
|
186
|
-
}), [
|
|
187
|
-
mutationFn: (
|
|
188
|
-
onSuccess: (
|
|
189
|
-
total:
|
|
190
|
-
current:
|
|
191
|
-
proposed:
|
|
197
|
+
}), [S, f] = q(null), z = _({
|
|
198
|
+
mutationFn: (a) => i.request(ae("/notifications/rules-preview", { notification_prefs: a })),
|
|
199
|
+
onSuccess: (a) => f({
|
|
200
|
+
total: a.data.total_notifications,
|
|
201
|
+
current: a.data.current,
|
|
202
|
+
proposed: a.data.proposed
|
|
192
203
|
})
|
|
193
|
-
}),
|
|
194
|
-
const
|
|
195
|
-
quiet_start:
|
|
196
|
-
quiet_end:
|
|
197
|
-
matrix:
|
|
198
|
-
escalation:
|
|
204
|
+
}), P = (a) => {
|
|
205
|
+
const p = {
|
|
206
|
+
quiet_start: a.quiet_start ?? (T || void 0),
|
|
207
|
+
quiet_end: a.quiet_end ?? (v || void 0),
|
|
208
|
+
matrix: a.matrix ?? s.matrix ?? {},
|
|
209
|
+
escalation: a.escalation ?? s.escalation ?? {},
|
|
210
|
+
// Kept as-is: "mute 1h" said to the bot lives here, and a save must not wipe it.
|
|
211
|
+
...s.teams_muted_until ? { teams_muted_until: s.teams_muted_until } : {}
|
|
199
212
|
};
|
|
200
|
-
|
|
201
|
-
},
|
|
202
|
-
const x = { ...
|
|
203
|
-
|
|
204
|
-
}, { data:
|
|
213
|
+
z.mutate(p), O.mutate(p);
|
|
214
|
+
}, y = (r == null ? void 0 : r.notification_sounds) ?? {}, $ = (a, p) => {
|
|
215
|
+
const x = { ...y };
|
|
216
|
+
p === "default" ? delete x[a] : x[a] = p, p !== "default" && ge(p, { preview: !0 }), A.mutate({ notification_sounds: Object.keys(x).length ? x : null });
|
|
217
|
+
}, { data: U } = w({
|
|
205
218
|
queryKey: ["nvr-noise-suggestions"],
|
|
206
|
-
queryFn: () => i.request(
|
|
219
|
+
queryFn: () => i.request(D("/notifications/noise-suggestions")).then((a) => a.data ?? []),
|
|
207
220
|
staleTime: 6e5
|
|
208
|
-
}), [
|
|
221
|
+
}), [j, c] = q({}), [k, F] = q(() => {
|
|
209
222
|
try {
|
|
210
|
-
const
|
|
211
|
-
return
|
|
223
|
+
const a = JSON.parse(localStorage.getItem("nvr-noise-dismissed") ?? "null");
|
|
224
|
+
return a && Date.now() - a.at < 30 * 864e5 ? a.cats : [];
|
|
212
225
|
} catch {
|
|
213
226
|
return [];
|
|
214
227
|
}
|
|
215
|
-
}),
|
|
216
|
-
const
|
|
217
|
-
|
|
228
|
+
}), J = (a) => {
|
|
229
|
+
const p = [...k, a];
|
|
230
|
+
F(p);
|
|
218
231
|
try {
|
|
219
|
-
localStorage.setItem("nvr-noise-dismissed", JSON.stringify({ at: Date.now(), cats:
|
|
232
|
+
localStorage.setItem("nvr-noise-dismissed", JSON.stringify({ at: Date.now(), cats: p }));
|
|
220
233
|
} catch {
|
|
221
234
|
}
|
|
222
|
-
},
|
|
223
|
-
var
|
|
224
|
-
const g = { ...((
|
|
225
|
-
x ? g[
|
|
235
|
+
}, M = (a, p, x) => {
|
|
236
|
+
var he;
|
|
237
|
+
const g = { ...((he = s.escalation) == null ? void 0 : he[a]) ?? {} };
|
|
238
|
+
x ? g[p] = x : delete g[p];
|
|
226
239
|
const H = { ...s.escalation ?? {} };
|
|
227
|
-
Object.keys(g).length ? H[
|
|
228
|
-
},
|
|
240
|
+
Object.keys(g).length ? H[a] = g : delete H[a], P({ escalation: H });
|
|
241
|
+
}, W = [
|
|
229
242
|
{ value: "", label: "never" },
|
|
230
243
|
{ value: "15", label: "15 min" },
|
|
231
244
|
{ value: "60", label: "1 hour" },
|
|
232
245
|
{ value: "240", label: "4 hours" },
|
|
233
246
|
{ value: "480", label: "8 hours" },
|
|
234
247
|
{ value: "1440", label: "1 day" }
|
|
235
|
-
],
|
|
248
|
+
], Q = (a, p) => {
|
|
236
249
|
var g;
|
|
237
|
-
const x = ((g = s.matrix) == null ? void 0 : g[
|
|
238
|
-
|
|
239
|
-
matrix: { ...s.matrix ?? {}, [
|
|
250
|
+
const x = ((g = s.matrix) == null ? void 0 : g[a]) ?? { inapp: !0, push: !0 };
|
|
251
|
+
P({
|
|
252
|
+
matrix: { ...s.matrix ?? {}, [a]: { ...x, [p]: x[p] === !1 } }
|
|
240
253
|
});
|
|
241
|
-
},
|
|
254
|
+
}, B = (a) => {
|
|
255
|
+
var x;
|
|
256
|
+
const p = ((x = s.matrix) == null ? void 0 : x[a]) ?? { inapp: !0, push: !0 };
|
|
257
|
+
P({ matrix: { ...s.matrix ?? {}, [a]: { ...p, teams: p.teams !== !0 } } });
|
|
258
|
+
}, V = (a, p) => {
|
|
242
259
|
var g;
|
|
243
|
-
const x = ((g = s.matrix) == null ? void 0 : g[
|
|
244
|
-
|
|
245
|
-
},
|
|
260
|
+
const x = ((g = s.matrix) == null ? void 0 : g[a]) ?? { inapp: !0, push: !0 };
|
|
261
|
+
P({ matrix: { ...s.matrix ?? {}, [a]: { ...x, email: p } } });
|
|
262
|
+
}, Z = (a) => {
|
|
246
263
|
var g;
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
},
|
|
264
|
+
const p = ((g = s.matrix) == null ? void 0 : g[a]) ?? { inapp: !0, push: !0 }, x = { ...p };
|
|
265
|
+
p.quiet_override ? delete x.quiet_override : x.quiet_override = !0, P({ matrix: { ...s.matrix ?? {}, [a]: x } });
|
|
266
|
+
}, X = !!(T && v), ee = (a) => {
|
|
250
267
|
var x;
|
|
251
|
-
const
|
|
268
|
+
const p = {};
|
|
252
269
|
for (const g of te)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
},
|
|
270
|
+
p[g.key] = { ...((x = s.matrix) == null ? void 0 : x[g.key]) ?? { inapp: !0, push: !0 }, email: a };
|
|
271
|
+
P({ matrix: p }), a !== "off" && A.mutate({ email_digest: a });
|
|
272
|
+
}, ke = Number.isInteger(Number(r == null ? void 0 : r.digest_hour)) ? Number(r == null ? void 0 : r.digest_hour) : 7, Ne = (a) => `${a % 12 === 0 ? 12 : a % 12}:45 ${a < 12 ? "AM" : "PM"}`, [de, ce] = q(null), re = _({
|
|
256
273
|
mutationFn: () => i.request(ae("/users/me/digest-test", {})),
|
|
257
|
-
onSuccess: (
|
|
258
|
-
onError: () =>
|
|
259
|
-
}),
|
|
274
|
+
onSuccess: (a) => ce(a.data.note),
|
|
275
|
+
onError: () => ce("Test send failed — try again.")
|
|
276
|
+
}), we = te.some((a) => n(a.key) === "daily"), ue = [
|
|
260
277
|
{ value: "instant", label: "Individual email" },
|
|
261
278
|
{ value: "daily", label: "Daily summary" },
|
|
262
279
|
{ value: "off", label: "No email" }
|
|
263
|
-
],
|
|
280
|
+
], I = ({ text: a }) => /* @__PURE__ */ e(
|
|
264
281
|
"span",
|
|
265
282
|
{
|
|
266
283
|
className: "ml-1 inline-flex h-3.5 w-3.5 cursor-help items-center justify-center rounded-full border border-slate-300 text-[9px] font-semibold normal-case tracking-normal text-slate-400 dark:border-border",
|
|
267
284
|
role: "img",
|
|
268
|
-
title:
|
|
269
|
-
"data-tip":
|
|
270
|
-
"aria-label":
|
|
285
|
+
title: a,
|
|
286
|
+
"data-tip": a,
|
|
287
|
+
"aria-label": a,
|
|
271
288
|
children: "?"
|
|
272
289
|
}
|
|
273
290
|
);
|
|
@@ -282,28 +299,28 @@ function tt() {
|
|
|
282
299
|
/* @__PURE__ */ e("p", { className: "mt-0.5 text-[11px] text-slate-400", children: "Per category: whether it lands in your in-app inbox, whether your browser pushes it, and how it reaches your email — each one as it happens, folded into the daily action summary, or not at all. Quiet hours pause pushes and hold emails until morning unless a category is let through them; critical alerts (SLA escalations, maintenance, monitor failures) always get through." })
|
|
283
300
|
] }),
|
|
284
301
|
/* @__PURE__ */ t("div", { className: "space-y-3 p-4", children: [
|
|
285
|
-
(
|
|
302
|
+
(U ?? []).filter((a) => !k.includes(a.category)).map((a) => /* @__PURE__ */ t(
|
|
286
303
|
"div",
|
|
287
304
|
{
|
|
288
|
-
"data-noise-suggestion":
|
|
305
|
+
"data-noise-suggestion": a.category,
|
|
289
306
|
className: "flex flex-wrap items-center gap-2 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-[12px] text-amber-900 dark:border-amber-900/50 dark:bg-amber-950/30 dark:text-amber-200",
|
|
290
307
|
children: [
|
|
291
308
|
/* @__PURE__ */ t("span", { className: "min-w-0 flex-1", children: [
|
|
292
|
-
|
|
309
|
+
a.message,
|
|
293
310
|
" Mute them?"
|
|
294
311
|
] }),
|
|
295
|
-
|
|
312
|
+
a.category in j ? /* @__PURE__ */ e(
|
|
296
313
|
"button",
|
|
297
314
|
{
|
|
298
315
|
type: "button",
|
|
299
316
|
className: "underline",
|
|
300
317
|
onClick: () => {
|
|
301
|
-
|
|
318
|
+
P({
|
|
302
319
|
matrix: {
|
|
303
320
|
...s.matrix ?? {},
|
|
304
|
-
[
|
|
321
|
+
[a.category]: j[a.category]
|
|
305
322
|
}
|
|
306
|
-
}),
|
|
323
|
+
}), c(({ [a.category]: p, ...x }) => x);
|
|
307
324
|
},
|
|
308
325
|
children: "Muted — undo"
|
|
309
326
|
}
|
|
@@ -315,24 +332,24 @@ function tt() {
|
|
|
315
332
|
className: "rounded border border-amber-300 px-2 py-0.5 font-medium dark:border-amber-800",
|
|
316
333
|
onClick: () => {
|
|
317
334
|
var x;
|
|
318
|
-
const
|
|
319
|
-
|
|
335
|
+
const p = ((x = s.matrix) == null ? void 0 : x[a.category]) ?? { inapp: !0, push: !0 };
|
|
336
|
+
c((g) => ({ ...g, [a.category]: p })), P({
|
|
320
337
|
matrix: {
|
|
321
338
|
...s.matrix ?? {},
|
|
322
|
-
[
|
|
339
|
+
[a.category]: { ...p, inapp: !1, push: !1 }
|
|
323
340
|
}
|
|
324
341
|
});
|
|
325
342
|
},
|
|
326
343
|
children: "Mute"
|
|
327
344
|
}
|
|
328
345
|
),
|
|
329
|
-
/* @__PURE__ */ e("button", { type: "button", className: "underline", onClick: () =>
|
|
346
|
+
/* @__PURE__ */ e("button", { type: "button", className: "underline", onClick: () => J(a.category), children: "Not now" })
|
|
330
347
|
] })
|
|
331
348
|
]
|
|
332
349
|
},
|
|
333
|
-
|
|
350
|
+
a.category
|
|
334
351
|
)),
|
|
335
|
-
|
|
352
|
+
S && S.total > 0 && /* @__PURE__ */ t(
|
|
336
353
|
"div",
|
|
337
354
|
{
|
|
338
355
|
"data-rules-preview": !0,
|
|
@@ -340,23 +357,23 @@ function tt() {
|
|
|
340
357
|
children: [
|
|
341
358
|
/* @__PURE__ */ t("span", { className: "min-w-0 flex-1", children: [
|
|
342
359
|
"Last week with this change: ",
|
|
343
|
-
|
|
360
|
+
S.proposed.inapp,
|
|
344
361
|
" in-app instead of",
|
|
345
362
|
" ",
|
|
346
|
-
|
|
363
|
+
S.current.inapp,
|
|
347
364
|
", ",
|
|
348
|
-
|
|
365
|
+
S.proposed.email_sent,
|
|
349
366
|
" emails instead of",
|
|
350
367
|
" ",
|
|
351
|
-
|
|
368
|
+
S.current.email_sent,
|
|
352
369
|
", ",
|
|
353
|
-
|
|
370
|
+
S.proposed.push,
|
|
354
371
|
" pushes instead of",
|
|
355
372
|
" ",
|
|
356
|
-
|
|
373
|
+
S.current.push,
|
|
357
374
|
"."
|
|
358
375
|
] }),
|
|
359
|
-
/* @__PURE__ */ e("button", { type: "button", className: "underline", onClick: () =>
|
|
376
|
+
/* @__PURE__ */ e("button", { type: "button", className: "underline", onClick: () => f(null), children: "Dismiss" })
|
|
360
377
|
]
|
|
361
378
|
}
|
|
362
379
|
),
|
|
@@ -366,9 +383,9 @@ function tt() {
|
|
|
366
383
|
"input",
|
|
367
384
|
{
|
|
368
385
|
type: "time",
|
|
369
|
-
value:
|
|
370
|
-
onChange: (
|
|
371
|
-
onBlur: () =>
|
|
386
|
+
value: T,
|
|
387
|
+
onChange: (a) => h(a.target.value),
|
|
388
|
+
onBlur: () => P({ quiet_start: T || void 0 }),
|
|
372
389
|
className: "h-7 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
|
|
373
390
|
}
|
|
374
391
|
),
|
|
@@ -377,18 +394,18 @@ function tt() {
|
|
|
377
394
|
"input",
|
|
378
395
|
{
|
|
379
396
|
type: "time",
|
|
380
|
-
value:
|
|
381
|
-
onChange: (
|
|
382
|
-
onBlur: () =>
|
|
397
|
+
value: v,
|
|
398
|
+
onChange: (a) => N(a.target.value),
|
|
399
|
+
onBlur: () => P({ quiet_end: v || void 0 }),
|
|
383
400
|
className: "h-7 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
|
|
384
401
|
}
|
|
385
402
|
),
|
|
386
|
-
(
|
|
403
|
+
(T || v) && /* @__PURE__ */ e(
|
|
387
404
|
"button",
|
|
388
405
|
{
|
|
389
406
|
type: "button",
|
|
390
407
|
onClick: () => {
|
|
391
|
-
|
|
408
|
+
h(""), N(""), O.mutate({ matrix: s.matrix ?? {} });
|
|
392
409
|
},
|
|
393
410
|
className: "text-[11.5px] text-slate-400 underline decoration-dotted underline-offset-2",
|
|
394
411
|
children: "Clear"
|
|
@@ -398,16 +415,16 @@ function tt() {
|
|
|
398
415
|
/* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-2 text-[12.5px] text-slate-600 dark:text-muted-foreground", children: [
|
|
399
416
|
"Sound:",
|
|
400
417
|
/* @__PURE__ */ e(
|
|
401
|
-
|
|
418
|
+
E,
|
|
402
419
|
{
|
|
403
|
-
value: String((
|
|
420
|
+
value: String((r == null ? void 0 : r.notification_sound) ?? "off"),
|
|
404
421
|
options: [
|
|
405
422
|
{ value: "off", label: "Off" },
|
|
406
423
|
{ value: "subtle", label: "Subtle blip" },
|
|
407
424
|
{ value: "chime", label: "Chime" }
|
|
408
425
|
],
|
|
409
|
-
onChange: (
|
|
410
|
-
|
|
426
|
+
onChange: (a) => {
|
|
427
|
+
ge(a, { preview: !0 }), A.mutate({ notification_sound: a });
|
|
411
428
|
}
|
|
412
429
|
}
|
|
413
430
|
),
|
|
@@ -415,11 +432,11 @@ function tt() {
|
|
|
415
432
|
] }),
|
|
416
433
|
/* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-2 text-[12.5px] text-slate-600 dark:text-muted-foreground", children: [
|
|
417
434
|
/* @__PURE__ */ e(
|
|
418
|
-
|
|
435
|
+
nt,
|
|
419
436
|
{
|
|
420
|
-
on: (
|
|
421
|
-
onChange: () =>
|
|
422
|
-
huddle_hold_notifications: (
|
|
437
|
+
on: (r == null ? void 0 : r.huddle_hold_notifications) !== !1,
|
|
438
|
+
onChange: () => A.mutate({
|
|
439
|
+
huddle_hold_notifications: (r == null ? void 0 : r.huddle_hold_notifications) === !1
|
|
423
440
|
}),
|
|
424
441
|
label: "Hold notifications during huddles"
|
|
425
442
|
}
|
|
@@ -432,96 +449,114 @@ function tt() {
|
|
|
432
449
|
/* @__PURE__ */ e("th", { className: "py-1 font-semibold", children: "Category" }),
|
|
433
450
|
/* @__PURE__ */ t("th", { className: "py-1 text-center font-semibold", children: [
|
|
434
451
|
"In-app",
|
|
435
|
-
/* @__PURE__ */ e(
|
|
452
|
+
/* @__PURE__ */ e(I, { text: "The notification itself: the bell badge and your Notifications inbox in the app. Off = no row is written for this category, so nothing shows anywhere in the app." })
|
|
436
453
|
] }),
|
|
437
454
|
/* @__PURE__ */ t("th", { className: "py-1 text-center font-semibold", children: [
|
|
438
455
|
"Push",
|
|
439
|
-
/* @__PURE__ */ e(
|
|
456
|
+
/* @__PURE__ */ e(I, { text: "A browser / device alert (the popup you get even with the tab closed) on devices where you allowed notifications. Off keeps the in-app row but stops the device alert. Quiet hours pause pushes too." })
|
|
440
457
|
] }),
|
|
441
458
|
/* @__PURE__ */ t("th", { className: "py-1 text-center font-semibold", children: [
|
|
442
459
|
"Email",
|
|
443
|
-
/* @__PURE__ */ e(
|
|
460
|
+
/* @__PURE__ */ e(I, { text: "Individual email = one message as each event happens. Daily summary = held and delivered once a day in your action summary (deliver-at time below). No email = never emailed for this category (in-app and push are unaffected)." })
|
|
461
|
+
] }),
|
|
462
|
+
o && /* @__PURE__ */ t("th", { className: "py-1 text-center font-semibold", "data-teams-column": "", children: [
|
|
463
|
+
"Teams",
|
|
464
|
+
/* @__PURE__ */ e(I, { text: 'A message from the Nivaro bot in Microsoft Teams. Off by default: connect Teams, then turn on the categories you want there. Say "mute 1h" to the bot to pause them for a while.' }),
|
|
465
|
+
/* @__PURE__ */ e("div", { className: "mt-0.5", children: /* @__PURE__ */ e(et, { linked: l, linkedAt: (pe = d == null ? void 0 : d.link) == null ? void 0 : pe.linked_at }) })
|
|
444
466
|
] }),
|
|
445
467
|
/* @__PURE__ */ t("th", { className: "py-1 text-center font-semibold", children: [
|
|
446
468
|
"Sound",
|
|
447
|
-
/* @__PURE__ */ e(
|
|
469
|
+
/* @__PURE__ */ e(I, { text: "A different sound for this category, or none. Default follows the Sound setting above." })
|
|
448
470
|
] }),
|
|
449
471
|
/* @__PURE__ */ t("th", { className: "py-1 text-center font-semibold", children: [
|
|
450
472
|
"Quiet hours",
|
|
451
|
-
/* @__PURE__ */ e(
|
|
473
|
+
/* @__PURE__ */ e(I, { text: "Ticked = this category still pushes and emails during your quiet hours (the in-app row always lands either way). Leave it off to have quiet hours hold this category until morning. Critical alerts always get through." })
|
|
452
474
|
] })
|
|
453
475
|
] }) }),
|
|
454
|
-
/* @__PURE__ */ e("tbody", { children: te.map((
|
|
476
|
+
/* @__PURE__ */ e("tbody", { children: te.map((a) => {
|
|
455
477
|
var x;
|
|
456
|
-
const
|
|
478
|
+
const p = ((x = s.matrix) == null ? void 0 : x[a.key]) ?? {};
|
|
457
479
|
return /* @__PURE__ */ t("tr", { className: "border-t border-slate-100 dark:border-border", children: [
|
|
458
480
|
/* @__PURE__ */ t("td", { className: "py-1.5 text-slate-700 dark:text-foreground", children: [
|
|
459
|
-
|
|
460
|
-
/* @__PURE__ */ e(
|
|
481
|
+
a.label,
|
|
482
|
+
/* @__PURE__ */ e(I, { text: a.help })
|
|
461
483
|
] }),
|
|
462
484
|
["inapp", "push"].map((g) => /* @__PURE__ */ e("td", { className: "py-1.5 text-center", children: /* @__PURE__ */ e(
|
|
463
485
|
"input",
|
|
464
486
|
{
|
|
465
487
|
type: "checkbox",
|
|
466
|
-
checked:
|
|
467
|
-
onChange: () =>
|
|
468
|
-
disabled:
|
|
469
|
-
"aria-label": `${g === "inapp" ? "In-app" : "Push"} for ${
|
|
470
|
-
"data-notify-channel": `${
|
|
488
|
+
checked: p[g] !== !1,
|
|
489
|
+
onChange: () => Q(a.key, g),
|
|
490
|
+
disabled: O.isPending,
|
|
491
|
+
"aria-label": `${g === "inapp" ? "In-app" : "Push"} for ${a.label}`,
|
|
492
|
+
"data-notify-channel": `${a.key}:${g}`,
|
|
471
493
|
className: "h-3.5 w-3.5"
|
|
472
494
|
}
|
|
473
495
|
) }, g)),
|
|
474
496
|
/* @__PURE__ */ e("td", { className: "py-1 text-center", children: /* @__PURE__ */ e("div", { className: "inline-block", children: /* @__PURE__ */ e(
|
|
475
|
-
|
|
497
|
+
E,
|
|
476
498
|
{
|
|
477
|
-
ariaLabel: `Email for ${
|
|
478
|
-
value:
|
|
479
|
-
options:
|
|
480
|
-
onChange: (g) =>
|
|
499
|
+
ariaLabel: `Email for ${a.label}`,
|
|
500
|
+
value: n(a.key),
|
|
501
|
+
options: ue,
|
|
502
|
+
onChange: (g) => V(a.key, g)
|
|
481
503
|
}
|
|
482
504
|
) }) }),
|
|
505
|
+
o && /* @__PURE__ */ e("td", { className: "py-1.5 text-center", children: /* @__PURE__ */ e(
|
|
506
|
+
"input",
|
|
507
|
+
{
|
|
508
|
+
type: "checkbox",
|
|
509
|
+
checked: p.teams === !0,
|
|
510
|
+
onChange: () => B(a.key),
|
|
511
|
+
disabled: O.isPending || !l,
|
|
512
|
+
"aria-label": `Teams for ${a.label}`,
|
|
513
|
+
title: l ? void 0 : "Connect Teams first",
|
|
514
|
+
"data-notify-channel": `${a.key}:teams`,
|
|
515
|
+
className: "h-3.5 w-3.5"
|
|
516
|
+
}
|
|
517
|
+
) }),
|
|
483
518
|
/* @__PURE__ */ e("td", { className: "py-1 text-center", children: /* @__PURE__ */ e("div", { className: "inline-block", children: /* @__PURE__ */ e(
|
|
484
|
-
|
|
519
|
+
E,
|
|
485
520
|
{
|
|
486
|
-
ariaLabel: `Sound for ${
|
|
487
|
-
value:
|
|
521
|
+
ariaLabel: `Sound for ${a.label}`,
|
|
522
|
+
value: y[a.key] ?? "default",
|
|
488
523
|
options: [
|
|
489
524
|
{ value: "default", label: "Default" },
|
|
490
525
|
{ value: "off", label: "None" },
|
|
491
526
|
{ value: "subtle", label: "Subtle blip" },
|
|
492
527
|
{ value: "chime", label: "Chime" }
|
|
493
528
|
],
|
|
494
|
-
onChange: (g) =>
|
|
529
|
+
onChange: (g) => $(a.key, g)
|
|
495
530
|
}
|
|
496
531
|
) }) }),
|
|
497
532
|
/* @__PURE__ */ e("td", { className: "py-1.5 text-center", children: /* @__PURE__ */ e(
|
|
498
533
|
"input",
|
|
499
534
|
{
|
|
500
535
|
type: "checkbox",
|
|
501
|
-
checked:
|
|
502
|
-
onChange: () =>
|
|
503
|
-
disabled:
|
|
504
|
-
"aria-label": `Let ${
|
|
505
|
-
title:
|
|
506
|
-
"data-quiet-override":
|
|
536
|
+
checked: p.quiet_override === !0,
|
|
537
|
+
onChange: () => Z(a.key),
|
|
538
|
+
disabled: O.isPending,
|
|
539
|
+
"aria-label": `Let ${a.label} through quiet hours`,
|
|
540
|
+
title: X ? void 0 : "Set quiet hours above for this to matter — it is remembered either way",
|
|
541
|
+
"data-quiet-override": a.key,
|
|
507
542
|
className: "h-3.5 w-3.5"
|
|
508
543
|
}
|
|
509
544
|
) })
|
|
510
|
-
] },
|
|
545
|
+
] }, a.key);
|
|
511
546
|
}) })
|
|
512
547
|
] }),
|
|
513
548
|
/* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-2 text-[11.5px] text-slate-500 dark:text-muted-foreground", children: [
|
|
514
549
|
/* @__PURE__ */ e("span", { children: "All email:" }),
|
|
515
|
-
|
|
550
|
+
ue.map((a) => /* @__PURE__ */ e(
|
|
516
551
|
"button",
|
|
517
552
|
{
|
|
518
553
|
type: "button",
|
|
519
|
-
disabled:
|
|
520
|
-
onClick: () =>
|
|
554
|
+
disabled: O.isPending,
|
|
555
|
+
onClick: () => ee(a.value),
|
|
521
556
|
className: "rounded border border-slate-200 px-2 py-0.5 hover:border-slate-400 hover:text-slate-800 dark:border-border dark:hover:text-foreground",
|
|
522
|
-
children:
|
|
557
|
+
children: a.label
|
|
523
558
|
},
|
|
524
|
-
|
|
559
|
+
a.value
|
|
525
560
|
))
|
|
526
561
|
] }),
|
|
527
562
|
/* @__PURE__ */ t("div", { className: "space-y-2 rounded-md border border-slate-100 bg-slate-50/60 px-3 py-2 dark:border-border/60 dark:bg-background/40", children: [
|
|
@@ -534,28 +569,28 @@ function tt() {
|
|
|
534
569
|
/* @__PURE__ */ e("th", { className: "py-1 font-semibold", children: "Category" }),
|
|
535
570
|
/* @__PURE__ */ t("th", { className: "py-1 font-semibold", children: [
|
|
536
571
|
"Push after",
|
|
537
|
-
/* @__PURE__ */ e(
|
|
572
|
+
/* @__PURE__ */ e(I, { text: "Still unread after this long → a browser / device push (needs a registered device; quiet hours do not apply to escalations you asked for)." })
|
|
538
573
|
] }),
|
|
539
574
|
/* @__PURE__ */ t("th", { className: "py-1 font-semibold", children: [
|
|
540
575
|
"Email after",
|
|
541
|
-
/* @__PURE__ */ e(
|
|
576
|
+
/* @__PURE__ */ e(I, { text: "Still unread after this long → one email with the notification, regardless of the Email column above (No email still means no email at delivery time; this is the fallback)." })
|
|
542
577
|
] })
|
|
543
578
|
] }) }),
|
|
544
|
-
/* @__PURE__ */ e("tbody", { children: te.map((
|
|
579
|
+
/* @__PURE__ */ e("tbody", { children: te.map((a) => {
|
|
545
580
|
var x;
|
|
546
|
-
const
|
|
581
|
+
const p = ((x = s.escalation) == null ? void 0 : x[a.key]) ?? {};
|
|
547
582
|
return /* @__PURE__ */ t("tr", { className: "border-t border-slate-100 dark:border-border", children: [
|
|
548
|
-
/* @__PURE__ */ e("td", { className: "py-1 text-slate-700 dark:text-foreground", children:
|
|
583
|
+
/* @__PURE__ */ e("td", { className: "py-1 text-slate-700 dark:text-foreground", children: a.label }),
|
|
549
584
|
["push_after_min", "email_after_min"].map((g) => /* @__PURE__ */ e("td", { className: "py-1", children: /* @__PURE__ */ e(
|
|
550
|
-
|
|
585
|
+
E,
|
|
551
586
|
{
|
|
552
|
-
ariaLabel: `${g === "push_after_min" ? "Push" : "Email"} after for ${
|
|
553
|
-
value:
|
|
554
|
-
options:
|
|
555
|
-
onChange: (H) =>
|
|
587
|
+
ariaLabel: `${g === "push_after_min" ? "Push" : "Email"} after for ${a.label}`,
|
|
588
|
+
value: p[g] ? String(p[g]) : "",
|
|
589
|
+
options: W,
|
|
590
|
+
onChange: (H) => M(a.key, g, H ? Number(H) : null)
|
|
556
591
|
}
|
|
557
592
|
) }, g))
|
|
558
|
-
] },
|
|
593
|
+
] }, a.key);
|
|
559
594
|
}) })
|
|
560
595
|
] })
|
|
561
596
|
] }),
|
|
@@ -564,21 +599,21 @@ function tt() {
|
|
|
564
599
|
"Daily action summary",
|
|
565
600
|
/* @__PURE__ */ t("span", { className: "ml-1.5 text-[11px] font-normal text-slate-400", children: [
|
|
566
601
|
"one morning email — every category set to Daily summary, plus items assigned to you and invoices awaiting your review",
|
|
567
|
-
!
|
|
602
|
+
!we && " · nothing is set to Daily summary yet"
|
|
568
603
|
] })
|
|
569
604
|
] }),
|
|
570
605
|
/* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-2 text-[12px] text-slate-600 dark:text-muted-foreground", children: [
|
|
571
606
|
/* @__PURE__ */ t("span", { className: "flex items-center gap-1.5", children: [
|
|
572
607
|
"Deliver at",
|
|
573
608
|
/* @__PURE__ */ e(
|
|
574
|
-
|
|
609
|
+
E,
|
|
575
610
|
{
|
|
576
611
|
ariaLabel: "Digest delivery hour",
|
|
577
|
-
value: String(
|
|
578
|
-
onChange: (
|
|
579
|
-
options: Array.from({ length: 24 }, (
|
|
580
|
-
value: String(
|
|
581
|
-
label:
|
|
612
|
+
value: String(ke),
|
|
613
|
+
onChange: (a) => A.mutate({ digest_hour: Number(a) }),
|
|
614
|
+
options: Array.from({ length: 24 }, (a, p) => ({
|
|
615
|
+
value: String(p),
|
|
616
|
+
label: Ne(p)
|
|
582
617
|
}))
|
|
583
618
|
}
|
|
584
619
|
),
|
|
@@ -589,8 +624,8 @@ function tt() {
|
|
|
589
624
|
"input",
|
|
590
625
|
{
|
|
591
626
|
type: "checkbox",
|
|
592
|
-
checked: (
|
|
593
|
-
onChange: (
|
|
627
|
+
checked: (r == null ? void 0 : r.digest_layout) === "compact",
|
|
628
|
+
onChange: (a) => A.mutate({ digest_layout: a.target.checked ? "compact" : "detailed" }),
|
|
594
629
|
className: "rounded"
|
|
595
630
|
}
|
|
596
631
|
),
|
|
@@ -606,7 +641,7 @@ function tt() {
|
|
|
606
641
|
children: re.isPending ? "Building…" : "Send me a test summary now"
|
|
607
642
|
}
|
|
608
643
|
),
|
|
609
|
-
|
|
644
|
+
de && /* @__PURE__ */ e("span", { className: "text-[11.5px] text-slate-400", children: de })
|
|
610
645
|
] })
|
|
611
646
|
] }),
|
|
612
647
|
/* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-4 border-t border-slate-100 pt-3 text-[12.5px] text-slate-600 dark:border-border/60 dark:text-muted-foreground", children: [
|
|
@@ -615,25 +650,25 @@ function tt() {
|
|
|
615
650
|
["created", "create"],
|
|
616
651
|
["commented", "comment on"],
|
|
617
652
|
["transitioned", "move through a workflow"]
|
|
618
|
-
].map(([
|
|
653
|
+
].map(([a, p]) => {
|
|
619
654
|
var x;
|
|
620
655
|
return /* @__PURE__ */ t("label", { className: "flex cursor-pointer items-center gap-1.5", children: [
|
|
621
656
|
/* @__PURE__ */ e(
|
|
622
657
|
"input",
|
|
623
658
|
{
|
|
624
659
|
type: "checkbox",
|
|
625
|
-
checked: ((x =
|
|
626
|
-
onChange: (g) =>
|
|
660
|
+
checked: ((x = r == null ? void 0 : r.auto_watch) == null ? void 0 : x[a]) === !0,
|
|
661
|
+
onChange: (g) => A.mutate({
|
|
627
662
|
auto_watch: {
|
|
628
|
-
...(
|
|
629
|
-
[
|
|
663
|
+
...(r == null ? void 0 : r.auto_watch) ?? {},
|
|
664
|
+
[a]: g.target.checked
|
|
630
665
|
}
|
|
631
666
|
}),
|
|
632
667
|
className: "rounded"
|
|
633
668
|
}
|
|
634
669
|
),
|
|
635
|
-
|
|
636
|
-
] },
|
|
670
|
+
p
|
|
671
|
+
] }, a);
|
|
637
672
|
})
|
|
638
673
|
] })
|
|
639
674
|
] })
|
|
@@ -641,15 +676,15 @@ function tt() {
|
|
|
641
676
|
}
|
|
642
677
|
);
|
|
643
678
|
}
|
|
644
|
-
function
|
|
645
|
-
const i =
|
|
679
|
+
function dt() {
|
|
680
|
+
const i = L(), m = K(), { data: r } = w({
|
|
646
681
|
queryKey: ["nvr-profile-prefs"],
|
|
647
|
-
queryFn: () => i.request(
|
|
682
|
+
queryFn: () => i.request(D("/users/me")).then((s) => {
|
|
648
683
|
var u;
|
|
649
|
-
return ((u =
|
|
684
|
+
return ((u = s.data) == null ? void 0 : u.preferences) ?? {};
|
|
650
685
|
})
|
|
651
|
-
}),
|
|
652
|
-
mutationFn: (
|
|
686
|
+
}), d = (r == null ? void 0 : r.link_app) === "portal" || (r == null ? void 0 : r.link_app) === "admin" ? r.link_app : "auto", o = _({
|
|
687
|
+
mutationFn: (s) => i.request(G("/users/me/preferences", { link_app: s })),
|
|
653
688
|
onSuccess: () => void m.invalidateQueries({ queryKey: ["nvr-profile-prefs"] })
|
|
654
689
|
});
|
|
655
690
|
return /* @__PURE__ */ t(
|
|
@@ -664,50 +699,50 @@ function at() {
|
|
|
664
699
|
{ v: "auto", label: "Automatic", hint: "Admins open the admin, everyone else the portal" },
|
|
665
700
|
{ v: "portal", label: "Portal", hint: "Always the front-end app" },
|
|
666
701
|
{ v: "admin", label: "Admin", hint: "Always the admin console" }
|
|
667
|
-
].map((
|
|
702
|
+
].map((s) => /* @__PURE__ */ e(
|
|
668
703
|
"button",
|
|
669
704
|
{
|
|
670
705
|
type: "button",
|
|
671
|
-
title:
|
|
672
|
-
onClick: () => o.mutate(
|
|
673
|
-
className:
|
|
674
|
-
children:
|
|
706
|
+
title: s.hint,
|
|
707
|
+
onClick: () => o.mutate(s.v),
|
|
708
|
+
className: d === s.v ? "rounded bg-nvr-cyan px-3 py-1 text-[12.5px] font-medium text-white" : "rounded px-3 py-1 text-[12.5px] font-medium text-slate-600 hover:bg-slate-100 dark:text-muted-foreground dark:hover:bg-muted",
|
|
709
|
+
children: s.label
|
|
675
710
|
},
|
|
676
|
-
|
|
711
|
+
s.v
|
|
677
712
|
)) })
|
|
678
713
|
]
|
|
679
714
|
}
|
|
680
715
|
);
|
|
681
716
|
}
|
|
682
|
-
function
|
|
683
|
-
const i =
|
|
717
|
+
function ct() {
|
|
718
|
+
const i = L(), m = K(), [r, d] = q(""), o = (() => {
|
|
684
719
|
try {
|
|
685
720
|
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
686
721
|
} catch {
|
|
687
722
|
return "UTC";
|
|
688
723
|
}
|
|
689
724
|
})(), l = (() => {
|
|
690
|
-
var
|
|
725
|
+
var h;
|
|
691
726
|
try {
|
|
692
|
-
return ((
|
|
727
|
+
return ((h = Intl.supportedValuesOf) == null ? void 0 : h.call(
|
|
693
728
|
Intl,
|
|
694
729
|
"timeZone"
|
|
695
730
|
)) ?? [];
|
|
696
731
|
} catch {
|
|
697
732
|
return [];
|
|
698
733
|
}
|
|
699
|
-
})(), { data:
|
|
734
|
+
})(), { data: s } = w({
|
|
700
735
|
queryKey: ["nvr-profile-prefs"],
|
|
701
|
-
queryFn: () => i.request(
|
|
702
|
-
var
|
|
703
|
-
return ((
|
|
736
|
+
queryFn: () => i.request(D("/users/me")).then((h) => {
|
|
737
|
+
var C;
|
|
738
|
+
return ((C = h.data) == null ? void 0 : C.preferences) ?? {};
|
|
704
739
|
})
|
|
705
|
-
}), u = typeof (
|
|
706
|
-
mutationFn: (
|
|
707
|
-
onSuccess: (
|
|
708
|
-
|
|
740
|
+
}), u = typeof (s == null ? void 0 : s.timezone) == "string" ? s.timezone : null, n = _({
|
|
741
|
+
mutationFn: (h) => i.request(G("/users/me/preferences", { timezone: h })),
|
|
742
|
+
onSuccess: (h, C) => {
|
|
743
|
+
ze(C), d(""), m.invalidateQueries({ queryKey: ["nvr-profile-prefs"] });
|
|
709
744
|
}
|
|
710
|
-
}), b =
|
|
745
|
+
}), b = r.length > 1 ? l.filter((h) => h.toLowerCase().includes(r.toLowerCase())).slice(0, 8) : [];
|
|
711
746
|
return /* @__PURE__ */ t(
|
|
712
747
|
"div",
|
|
713
748
|
{
|
|
@@ -737,62 +772,62 @@ function rt() {
|
|
|
737
772
|
/* @__PURE__ */ e(
|
|
738
773
|
"input",
|
|
739
774
|
{
|
|
740
|
-
value:
|
|
741
|
-
onChange: (
|
|
775
|
+
value: r,
|
|
776
|
+
onChange: (h) => d(h.target.value),
|
|
742
777
|
placeholder: "Change zone… (e.g. America/Denver)",
|
|
743
778
|
className: "h-8 w-[280px] rounded-md border border-slate-200 bg-background px-2.5 text-[12.5px] dark:border-border"
|
|
744
779
|
}
|
|
745
780
|
),
|
|
746
|
-
b.length > 0 && /* @__PURE__ */ e("div", { className: "absolute z-10 mt-1 w-[280px] rounded-md border border-slate-200 bg-white shadow-lg dark:border-border dark:bg-card", children: b.map((
|
|
781
|
+
b.length > 0 && /* @__PURE__ */ e("div", { className: "absolute z-10 mt-1 w-[280px] rounded-md border border-slate-200 bg-white shadow-lg dark:border-border dark:bg-card", children: b.map((h) => /* @__PURE__ */ e(
|
|
747
782
|
"button",
|
|
748
783
|
{
|
|
749
784
|
type: "button",
|
|
750
|
-
onClick: () => n.mutate(
|
|
785
|
+
onClick: () => n.mutate(h),
|
|
751
786
|
className: "block w-full px-2.5 py-1.5 text-left text-[12.5px] text-slate-700 hover:bg-muted dark:text-foreground",
|
|
752
|
-
children:
|
|
787
|
+
children: h
|
|
753
788
|
},
|
|
754
|
-
|
|
789
|
+
h
|
|
755
790
|
)) })
|
|
756
791
|
] })
|
|
757
792
|
]
|
|
758
793
|
}
|
|
759
794
|
);
|
|
760
795
|
}
|
|
761
|
-
function
|
|
762
|
-
const i =
|
|
796
|
+
function ut() {
|
|
797
|
+
const i = L(), m = K(), { data: r } = w({
|
|
763
798
|
queryKey: ["nvr-profile-scopes"],
|
|
764
|
-
queryFn: () => i.request(
|
|
765
|
-
}),
|
|
766
|
-
mutationFn: ({ dimension: o, values: l }) => i.request(
|
|
799
|
+
queryFn: () => i.request(qe()).then((o) => o.data)
|
|
800
|
+
}), d = _({
|
|
801
|
+
mutationFn: ({ dimension: o, values: l }) => i.request(Ce(o, l)),
|
|
767
802
|
onSuccess: () => void m.invalidateQueries({ queryKey: ["nvr-profile-scopes"] })
|
|
768
803
|
});
|
|
769
|
-
return !
|
|
804
|
+
return !r || r.dimensions.length === 0 ? null : /* @__PURE__ */ e(
|
|
770
805
|
ie,
|
|
771
806
|
{
|
|
772
807
|
testId: "scopes",
|
|
773
|
-
icon: /* @__PURE__ */ e(
|
|
808
|
+
icon: /* @__PURE__ */ e(Ee, { className: "h-4 w-4" }),
|
|
774
809
|
title: "Default filters",
|
|
775
810
|
hint: "Pre-selected in browsers and reports — clear anytime",
|
|
776
|
-
children: /* @__PURE__ */ e("div", { className: "space-y-3", children:
|
|
777
|
-
|
|
811
|
+
children: /* @__PURE__ */ e("div", { className: "space-y-3", children: r.dimensions.map((o) => /* @__PURE__ */ e(
|
|
812
|
+
mt,
|
|
778
813
|
{
|
|
779
814
|
dimension: o,
|
|
780
|
-
selected:
|
|
781
|
-
restricted:
|
|
782
|
-
onSave: (l) =>
|
|
815
|
+
selected: r.defaults[o.name] ?? [],
|
|
816
|
+
restricted: r.restricted[o.name],
|
|
817
|
+
onSave: (l) => d.mutate({ dimension: o.name, values: l })
|
|
783
818
|
},
|
|
784
819
|
o.name
|
|
785
820
|
)) })
|
|
786
821
|
}
|
|
787
822
|
);
|
|
788
823
|
}
|
|
789
|
-
function
|
|
824
|
+
function mt({
|
|
790
825
|
dimension: i,
|
|
791
826
|
selected: m,
|
|
792
|
-
restricted:
|
|
793
|
-
onSave:
|
|
827
|
+
restricted: r,
|
|
828
|
+
onSave: d
|
|
794
829
|
}) {
|
|
795
|
-
const o =
|
|
830
|
+
const o = L(), l = i.display_field ?? "name", [s, u] = q(""), [n, b] = q(!1), { data: h = [] } = w({
|
|
796
831
|
queryKey: ["nvr-scope-options", i.name],
|
|
797
832
|
queryFn: async () => ((await o.request(
|
|
798
833
|
ne(i.target_collection, {
|
|
@@ -800,31 +835,31 @@ function st({
|
|
|
800
835
|
sort: i.options_sort ? [i.options_sort] : void 0,
|
|
801
836
|
limit: 200
|
|
802
837
|
})
|
|
803
|
-
)).data ?? []).map((
|
|
804
|
-
id:
|
|
805
|
-
label: String(
|
|
838
|
+
)).data ?? []).map((k) => ({
|
|
839
|
+
id: k.id,
|
|
840
|
+
label: String(k[l] ?? k.id)
|
|
806
841
|
}))
|
|
807
|
-
}),
|
|
808
|
-
queryKey: ["nvr-scope-search", i.name,
|
|
842
|
+
}), C = r != null && r.length ? new Set(r.map(String)) : null, N = C ? h.filter((c) => C.has(String(c.id))) : h, T = new Set(m.map(String)), v = N.length > 24 || h.length >= 200 && !C, { data: O = [], isFetching: A } = w({
|
|
843
|
+
queryKey: ["nvr-scope-search", i.name, s],
|
|
809
844
|
queryFn: async () => {
|
|
810
|
-
const
|
|
845
|
+
const k = ((await o.request(
|
|
811
846
|
ne(i.target_collection, {
|
|
812
847
|
fields: ["id", l],
|
|
813
|
-
filter: { [l]: { _contains:
|
|
848
|
+
filter: { [l]: { _contains: s } },
|
|
814
849
|
sort: i.options_sort ? [i.options_sort] : void 0,
|
|
815
850
|
limit: 30
|
|
816
851
|
})
|
|
817
|
-
)).data ?? []).map((
|
|
818
|
-
id:
|
|
819
|
-
label: String(
|
|
852
|
+
)).data ?? []).map((F) => ({
|
|
853
|
+
id: F.id,
|
|
854
|
+
label: String(F[l] ?? F.id)
|
|
820
855
|
}));
|
|
821
|
-
return
|
|
856
|
+
return C ? k.filter((F) => C.has(String(F.id))) : k;
|
|
822
857
|
},
|
|
823
|
-
enabled: v &&
|
|
824
|
-
placeholderData: (
|
|
825
|
-
}), S = new Map(
|
|
826
|
-
for (const
|
|
827
|
-
const f = m.filter((
|
|
858
|
+
enabled: v && s.trim().length > 0,
|
|
859
|
+
placeholderData: (c) => c
|
|
860
|
+
}), S = new Map(h.map((c) => [String(c.id), c.label]));
|
|
861
|
+
for (const c of O) S.set(String(c.id), c.label);
|
|
862
|
+
const f = m.filter((c) => !S.has(String(c))), { data: z = [] } = w({
|
|
828
863
|
queryKey: ["nvr-scope-selected-labels", i.name, f.map(String).sort().join(",")],
|
|
829
864
|
queryFn: async () => ((await o.request(
|
|
830
865
|
ne(i.target_collection, {
|
|
@@ -832,26 +867,26 @@ function st({
|
|
|
832
867
|
filter: { id: { _in: f } },
|
|
833
868
|
limit: 100
|
|
834
869
|
})
|
|
835
|
-
)).data ?? []).map((
|
|
836
|
-
id:
|
|
837
|
-
label: String(
|
|
870
|
+
)).data ?? []).map((k) => ({
|
|
871
|
+
id: k.id,
|
|
872
|
+
label: String(k[l] ?? k.id)
|
|
838
873
|
})),
|
|
839
874
|
enabled: f.length > 0
|
|
840
875
|
});
|
|
841
|
-
for (const
|
|
842
|
-
const
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
}, y =
|
|
876
|
+
for (const c of z) S.set(String(c.id), c.label);
|
|
877
|
+
const P = (c) => {
|
|
878
|
+
const k = T.has(String(c));
|
|
879
|
+
d(k ? m.filter((F) => String(F) !== String(c)) : [...m, c]);
|
|
880
|
+
}, y = s.trim().toLowerCase(), $ = y ? N.filter((c) => c.label.toLowerCase().includes(y)) : N, U = y.length === 0 ? N.slice(0, 30) : A && O.length === 0 ? $.slice(0, 30) : O, j = v && (n || y.length > 0);
|
|
846
881
|
return /* @__PURE__ */ t("div", { children: [
|
|
847
882
|
/* @__PURE__ */ t("p", { className: "mb-1 text-[11px] font-medium uppercase tracking-wide text-slate-400", children: [
|
|
848
883
|
i.label,
|
|
849
|
-
|
|
884
|
+
r != null && r.length ? /* @__PURE__ */ e("span", { className: "ml-1.5 normal-case tracking-normal text-amber-500", children: "(limited by your access)" }) : null,
|
|
850
885
|
m.length > 0 && /* @__PURE__ */ t(
|
|
851
886
|
"button",
|
|
852
887
|
{
|
|
853
888
|
type: "button",
|
|
854
|
-
onClick: () =>
|
|
889
|
+
onClick: () => d([]),
|
|
855
890
|
className: "ml-2 normal-case tracking-normal text-slate-400 underline-offset-2 hover:text-slate-600 hover:underline",
|
|
856
891
|
children: [
|
|
857
892
|
"clear ",
|
|
@@ -861,132 +896,132 @@ function st({
|
|
|
861
896
|
)
|
|
862
897
|
] }),
|
|
863
898
|
v ? /* @__PURE__ */ t("div", { className: "max-w-xl", children: [
|
|
864
|
-
m.length > 0 && /* @__PURE__ */ e("div", { className: "mb-1.5 flex flex-wrap gap-1", children: m.map((
|
|
899
|
+
m.length > 0 && /* @__PURE__ */ e("div", { className: "mb-1.5 flex flex-wrap gap-1", children: m.map((c) => /* @__PURE__ */ t(
|
|
865
900
|
"span",
|
|
866
901
|
{
|
|
867
902
|
className: "inline-flex items-center gap-1 rounded-full border border-nvr-cyan bg-nvr-cyan/10 py-0.5 pl-2.5 pr-1 text-[11.5px] font-medium text-nvr-navy dark:text-nvr-cyan",
|
|
868
903
|
children: [
|
|
869
|
-
S.get(String(
|
|
904
|
+
S.get(String(c)) ?? String(c),
|
|
870
905
|
/* @__PURE__ */ e(
|
|
871
906
|
"button",
|
|
872
907
|
{
|
|
873
908
|
type: "button",
|
|
874
|
-
onClick: () =>
|
|
875
|
-
"aria-label": `Remove ${S.get(String(
|
|
909
|
+
onClick: () => P(c),
|
|
910
|
+
"aria-label": `Remove ${S.get(String(c)) ?? c}`,
|
|
876
911
|
className: "rounded-full px-1 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200",
|
|
877
912
|
children: "×"
|
|
878
913
|
}
|
|
879
914
|
)
|
|
880
915
|
]
|
|
881
916
|
},
|
|
882
|
-
String(
|
|
917
|
+
String(c)
|
|
883
918
|
)) }),
|
|
884
919
|
/* @__PURE__ */ e(
|
|
885
920
|
"input",
|
|
886
921
|
{
|
|
887
|
-
value:
|
|
888
|
-
onChange: (
|
|
922
|
+
value: s,
|
|
923
|
+
onChange: (c) => u(c.target.value),
|
|
889
924
|
onFocus: () => b(!0),
|
|
890
925
|
onBlur: () => b(!1),
|
|
891
926
|
placeholder: `Search ${i.label.toLowerCase()} to add…`,
|
|
892
927
|
className: "h-8 w-full rounded-md border border-slate-200 bg-white px-2.5 text-[12px] outline-none focus:border-nvr-cyan dark:border-border dark:bg-card"
|
|
893
928
|
}
|
|
894
929
|
),
|
|
895
|
-
|
|
930
|
+
j && /* @__PURE__ */ t(
|
|
896
931
|
"div",
|
|
897
932
|
{
|
|
898
|
-
onMouseDown: (
|
|
933
|
+
onMouseDown: (c) => c.preventDefault(),
|
|
899
934
|
className: "mt-1 max-h-44 overflow-y-auto rounded-md border border-slate-200 dark:border-border",
|
|
900
935
|
children: [
|
|
901
|
-
|
|
902
|
-
const
|
|
936
|
+
U.map((c) => {
|
|
937
|
+
const k = T.has(String(c.id));
|
|
903
938
|
return /* @__PURE__ */ t(
|
|
904
939
|
"button",
|
|
905
940
|
{
|
|
906
941
|
type: "button",
|
|
907
|
-
onClick: () =>
|
|
942
|
+
onClick: () => P(c.id),
|
|
908
943
|
className: R(
|
|
909
944
|
"flex w-full items-center justify-between px-2.5 py-1.5 text-left text-[12px] hover:bg-slate-50 dark:hover:bg-muted",
|
|
910
|
-
|
|
945
|
+
k ? "font-medium text-nvr-navy dark:text-nvr-cyan" : "text-slate-600 dark:text-slate-300"
|
|
911
946
|
),
|
|
912
947
|
children: [
|
|
913
|
-
/* @__PURE__ */ e("span", { className: "truncate", children:
|
|
914
|
-
/* @__PURE__ */ e("span", { className: "pl-2 text-[11px] text-slate-400", children:
|
|
948
|
+
/* @__PURE__ */ e("span", { className: "truncate", children: c.label }),
|
|
949
|
+
/* @__PURE__ */ e("span", { className: "pl-2 text-[11px] text-slate-400", children: k ? "Remove" : "Add" })
|
|
915
950
|
]
|
|
916
951
|
},
|
|
917
|
-
String(
|
|
952
|
+
String(c.id)
|
|
918
953
|
);
|
|
919
954
|
}),
|
|
920
|
-
|
|
921
|
-
y.length === 0 &&
|
|
955
|
+
U.length === 0 && /* @__PURE__ */ e("p", { className: "px-2.5 py-2 text-[11.5px] text-slate-400", children: A ? "Searching…" : y ? "No matches." : "No options." }),
|
|
956
|
+
y.length === 0 && N.length > 30 && /* @__PURE__ */ e("p", { className: "border-t border-slate-100 px-2.5 py-1.5 text-[11px] text-slate-400 dark:border-border", children: "Showing first 30 — type to narrow." })
|
|
922
957
|
]
|
|
923
958
|
}
|
|
924
959
|
),
|
|
925
|
-
!
|
|
960
|
+
!j && m.length === 0 && /* @__PURE__ */ e("p", { className: "mt-1 text-[11px] text-slate-400", children: "No defaults set — click to browse or type to search." })
|
|
926
961
|
] }) : /* @__PURE__ */ t("div", { className: "flex flex-wrap gap-1", children: [
|
|
927
|
-
|
|
928
|
-
const
|
|
962
|
+
N.map((c) => {
|
|
963
|
+
const k = T.has(String(c.id));
|
|
929
964
|
return /* @__PURE__ */ e(
|
|
930
965
|
"button",
|
|
931
966
|
{
|
|
932
967
|
type: "button",
|
|
933
|
-
onClick: () =>
|
|
968
|
+
onClick: () => P(c.id),
|
|
934
969
|
className: R(
|
|
935
970
|
"rounded-full border px-2.5 py-0.5 text-[11.5px] transition-colors",
|
|
936
|
-
|
|
971
|
+
k ? "border-nvr-cyan bg-nvr-cyan/10 font-medium text-nvr-navy dark:text-nvr-cyan" : "border-slate-200 text-slate-500 hover:border-slate-300 dark:border-border"
|
|
937
972
|
),
|
|
938
|
-
children:
|
|
973
|
+
children: c.label
|
|
939
974
|
},
|
|
940
|
-
String(
|
|
975
|
+
String(c.id)
|
|
941
976
|
);
|
|
942
977
|
}),
|
|
943
|
-
|
|
978
|
+
N.length === 0 && /* @__PURE__ */ e("span", { className: "text-[11.5px] text-slate-400", children: "No options." })
|
|
944
979
|
] })
|
|
945
980
|
] });
|
|
946
981
|
}
|
|
947
|
-
function
|
|
948
|
-
const { data: i } =
|
|
982
|
+
function pt() {
|
|
983
|
+
const { data: i } = w({
|
|
949
984
|
queryKey: ["nvr-settings-2fa"],
|
|
950
|
-
queryFn: () =>
|
|
985
|
+
queryFn: () => r.request({ _method: "GET", _path: "/settings/" }).then((f) => (f == null ? void 0 : f.data) ?? null).catch(() => null),
|
|
951
986
|
staleTime: 6e5
|
|
952
|
-
}), m = (i == null ? void 0 : i.two_factor_enabled) !== !1,
|
|
987
|
+
}), m = (i == null ? void 0 : i.two_factor_enabled) !== !1, r = L(), d = K(), [o, l] = q(null), [s, u] = q(""), [n, b] = q(null), { data: h } = w({
|
|
953
988
|
queryKey: ["nvr-profile-totp"],
|
|
954
|
-
queryFn: () =>
|
|
955
|
-
}),
|
|
956
|
-
mutationFn: () =>
|
|
989
|
+
queryFn: () => r.request({ _method: "GET", _path: "/two-factor/status" }).then((f) => f.data)
|
|
990
|
+
}), C = () => void d.invalidateQueries({ queryKey: ["nvr-profile-totp"] }), N = _({
|
|
991
|
+
mutationFn: () => r.request({ _method: "POST", _path: "/two-factor/setup" }).then((f) => f.data),
|
|
957
992
|
onSuccess: (f) => l(f)
|
|
958
|
-
}),
|
|
959
|
-
mutationFn: (f) =>
|
|
993
|
+
}), T = _({
|
|
994
|
+
mutationFn: (f) => r.request({
|
|
960
995
|
_method: "POST",
|
|
961
996
|
_path: "/two-factor/verify",
|
|
962
997
|
_body: { token: f }
|
|
963
998
|
}),
|
|
964
999
|
onSuccess: () => {
|
|
965
|
-
l(null), u(""),
|
|
1000
|
+
l(null), u(""), C();
|
|
966
1001
|
}
|
|
967
1002
|
}), v = _({
|
|
968
|
-
mutationFn: (f) =>
|
|
1003
|
+
mutationFn: (f) => r.request({
|
|
969
1004
|
_method: "POST",
|
|
970
1005
|
_path: "/two-factor/disable",
|
|
971
1006
|
_body: { token: f }
|
|
972
1007
|
}),
|
|
973
1008
|
onSuccess: () => {
|
|
974
|
-
u(""),
|
|
1009
|
+
u(""), C();
|
|
975
1010
|
}
|
|
976
1011
|
}), O = _({
|
|
977
|
-
mutationFn: () =>
|
|
1012
|
+
mutationFn: () => r.request({ _method: "POST", _path: "/users/me/token" }).then((f) => f.data),
|
|
978
1013
|
onSuccess: (f) => b(f.token)
|
|
979
|
-
}),
|
|
980
|
-
mutationFn: () =>
|
|
1014
|
+
}), A = _({
|
|
1015
|
+
mutationFn: () => r.request({ _method: "DELETE", _path: "/users/me/token" }),
|
|
981
1016
|
onSuccess: () => b(null)
|
|
982
1017
|
}), S = _({
|
|
983
|
-
mutationFn: () =>
|
|
1018
|
+
mutationFn: () => r.request({ _method: "POST", _path: "/auth/logout-all" }),
|
|
984
1019
|
onSuccess: () => window.location.assign("/login")
|
|
985
1020
|
});
|
|
986
1021
|
return /* @__PURE__ */ e(
|
|
987
1022
|
ie,
|
|
988
1023
|
{
|
|
989
|
-
icon: /* @__PURE__ */ e(
|
|
1024
|
+
icon: /* @__PURE__ */ e(Ie, { className: "h-4 w-4" }),
|
|
990
1025
|
title: "Security",
|
|
991
1026
|
hint: m ? "Two-factor sign-in and API access" : "API access",
|
|
992
1027
|
children: /* @__PURE__ */ t("div", { className: "space-y-4", children: [
|
|
@@ -998,19 +1033,19 @@ function lt() {
|
|
|
998
1033
|
{
|
|
999
1034
|
className: R(
|
|
1000
1035
|
"rounded-full px-1.5 py-px text-[10px] font-semibold",
|
|
1001
|
-
|
|
1036
|
+
h != null && h.enabled ? "bg-emerald-50 text-emerald-600 dark:bg-emerald-500/10 dark:text-emerald-400" : "bg-slate-100 text-slate-500 dark:bg-muted dark:text-slate-400"
|
|
1002
1037
|
),
|
|
1003
|
-
children:
|
|
1038
|
+
children: h != null && h.enabled ? "Enabled" : "Off"
|
|
1004
1039
|
}
|
|
1005
1040
|
)
|
|
1006
1041
|
] }),
|
|
1007
|
-
!(
|
|
1042
|
+
!(h != null && h.enabled) && !o && /* @__PURE__ */ e(
|
|
1008
1043
|
"button",
|
|
1009
1044
|
{
|
|
1010
1045
|
type: "button",
|
|
1011
|
-
onClick: () =>
|
|
1046
|
+
onClick: () => N.mutate(),
|
|
1012
1047
|
className: "mt-2 h-8 rounded-md border border-slate-200 px-3 text-[12px] font-medium text-slate-600 hover:border-nvr-cyan hover:text-nvr-navy dark:border-border dark:text-slate-300 dark:hover:text-nvr-cyan",
|
|
1013
|
-
children:
|
|
1048
|
+
children: N.isPending ? "Preparing…" : "Set up 2FA"
|
|
1014
1049
|
}
|
|
1015
1050
|
),
|
|
1016
1051
|
o && /* @__PURE__ */ t("div", { className: "mt-3 flex flex-wrap items-start gap-4", children: [
|
|
@@ -1028,7 +1063,7 @@ function lt() {
|
|
|
1028
1063
|
/* @__PURE__ */ e(
|
|
1029
1064
|
"input",
|
|
1030
1065
|
{
|
|
1031
|
-
value:
|
|
1066
|
+
value: s,
|
|
1032
1067
|
onChange: (f) => u(f.target.value),
|
|
1033
1068
|
placeholder: "123456",
|
|
1034
1069
|
inputMode: "numeric",
|
|
@@ -1039,8 +1074,8 @@ function lt() {
|
|
|
1039
1074
|
"button",
|
|
1040
1075
|
{
|
|
1041
1076
|
type: "button",
|
|
1042
|
-
disabled:
|
|
1043
|
-
onClick: () =>
|
|
1077
|
+
disabled: s.trim().length < 6 || T.isPending,
|
|
1078
|
+
onClick: () => T.mutate(s.trim()),
|
|
1044
1079
|
className: "h-8 rounded-md bg-nvr-cyan px-3 text-[12px] font-semibold text-white disabled:opacity-50",
|
|
1045
1080
|
children: "Confirm"
|
|
1046
1081
|
}
|
|
@@ -1048,11 +1083,11 @@ function lt() {
|
|
|
1048
1083
|
] })
|
|
1049
1084
|
] })
|
|
1050
1085
|
] }),
|
|
1051
|
-
(
|
|
1086
|
+
(h == null ? void 0 : h.enabled) && /* @__PURE__ */ t("div", { className: "mt-2 flex gap-1.5", children: [
|
|
1052
1087
|
/* @__PURE__ */ e(
|
|
1053
1088
|
"input",
|
|
1054
1089
|
{
|
|
1055
|
-
value:
|
|
1090
|
+
value: s,
|
|
1056
1091
|
onChange: (f) => u(f.target.value),
|
|
1057
1092
|
placeholder: "Code to disable",
|
|
1058
1093
|
inputMode: "numeric",
|
|
@@ -1063,8 +1098,8 @@ function lt() {
|
|
|
1063
1098
|
"button",
|
|
1064
1099
|
{
|
|
1065
1100
|
type: "button",
|
|
1066
|
-
disabled:
|
|
1067
|
-
onClick: () => v.mutate(
|
|
1101
|
+
disabled: s.trim().length < 6 || v.isPending,
|
|
1102
|
+
onClick: () => v.mutate(s.trim()),
|
|
1068
1103
|
className: "h-8 rounded-md border border-red-200 px-3 text-[12px] font-medium text-red-500 transition-colors hover:bg-red-50 disabled:opacity-50 dark:border-red-500/30 dark:hover:bg-red-500/10",
|
|
1069
1104
|
children: v.isPending ? "Disabling…" : "Disable"
|
|
1070
1105
|
}
|
|
@@ -1090,10 +1125,10 @@ function lt() {
|
|
|
1090
1125
|
}
|
|
1091
1126
|
),
|
|
1092
1127
|
/* @__PURE__ */ e(
|
|
1093
|
-
|
|
1128
|
+
fe,
|
|
1094
1129
|
{
|
|
1095
1130
|
title: "Revoke API token",
|
|
1096
|
-
onConfirm: () =>
|
|
1131
|
+
onConfirm: () => A.mutate(),
|
|
1097
1132
|
confirmLabel: "Revoke token?",
|
|
1098
1133
|
className: "h-8 rounded-md px-3 text-[12px] font-medium text-slate-400 transition-colors hover:text-red-500",
|
|
1099
1134
|
armedClassName: "font-semibold text-red-500",
|
|
@@ -1108,7 +1143,7 @@ function lt() {
|
|
|
1108
1143
|
/* @__PURE__ */ e("p", { className: "text-[12.5px] font-medium text-slate-700 dark:text-slate-200", children: "Sessions" }),
|
|
1109
1144
|
/* @__PURE__ */ e("p", { className: "mt-0.5 text-[11.5px] text-slate-400", children: "Signs you out on every device and browser, including this one." }),
|
|
1110
1145
|
/* @__PURE__ */ t(
|
|
1111
|
-
|
|
1146
|
+
fe,
|
|
1112
1147
|
{
|
|
1113
1148
|
title: "Sign out everywhere",
|
|
1114
1149
|
onConfirm: () => S.mutate(),
|
|
@@ -1116,7 +1151,7 @@ function lt() {
|
|
|
1116
1151
|
className: "mt-2 inline-flex h-8 items-center gap-1.5 rounded-md border border-slate-200 px-3 text-[12px] font-medium text-slate-600 transition-colors hover:border-red-300 hover:text-red-500 dark:border-border dark:text-slate-300 dark:hover:border-red-500/40 dark:hover:text-red-400",
|
|
1117
1152
|
armedClassName: "border-red-300 font-semibold text-red-500 dark:border-red-500/40 dark:text-red-400",
|
|
1118
1153
|
children: [
|
|
1119
|
-
/* @__PURE__ */ e(
|
|
1154
|
+
/* @__PURE__ */ e(Ke, { className: "h-3.5 w-3.5" }),
|
|
1120
1155
|
S.isPending ? "Signing out…" : "Sign out everywhere"
|
|
1121
1156
|
]
|
|
1122
1157
|
}
|
|
@@ -1126,31 +1161,31 @@ function lt() {
|
|
|
1126
1161
|
}
|
|
1127
1162
|
);
|
|
1128
1163
|
}
|
|
1129
|
-
function
|
|
1164
|
+
function Yt({
|
|
1130
1165
|
userId: i,
|
|
1131
1166
|
className: m,
|
|
1132
|
-
initialTab:
|
|
1133
|
-
extra:
|
|
1167
|
+
initialTab: r,
|
|
1168
|
+
extra: d,
|
|
1134
1169
|
pushServiceWorker: o = "/sw.js"
|
|
1135
1170
|
}) {
|
|
1136
|
-
const l =
|
|
1137
|
-
return !i || (l == null ? void 0 : l.userId) != null && String(l.userId) === String(i) ? /* @__PURE__ */ e(
|
|
1171
|
+
const l = ve();
|
|
1172
|
+
return !i || (l == null ? void 0 : l.userId) != null && String(l.userId) === String(i) ? /* @__PURE__ */ e(ht, { className: m, extra: d, pushServiceWorker: o }) : /* @__PURE__ */ e(rt, { userId: i, className: m, initialTab: r });
|
|
1138
1173
|
}
|
|
1139
|
-
function
|
|
1174
|
+
function ht({
|
|
1140
1175
|
className: i,
|
|
1141
1176
|
extra: m,
|
|
1142
|
-
pushServiceWorker:
|
|
1177
|
+
pushServiceWorker: r
|
|
1143
1178
|
}) {
|
|
1144
|
-
var
|
|
1145
|
-
const
|
|
1179
|
+
var j;
|
|
1180
|
+
const d = L(), o = K(), l = ve(), s = !0, u = "me", { data: n } = w({
|
|
1146
1181
|
queryKey: ["nvr-profile-user", u],
|
|
1147
|
-
queryFn: () =>
|
|
1148
|
-
enabled:
|
|
1149
|
-
}), b = (n == null ? void 0 : n.id) ?? null, { data:
|
|
1182
|
+
queryFn: () => d.request(Se(u)).then((c) => c.data),
|
|
1183
|
+
enabled: s
|
|
1184
|
+
}), b = (n == null ? void 0 : n.id) ?? null, { data: h } = w({
|
|
1150
1185
|
queryKey: ["nvr-profile-card", b],
|
|
1151
|
-
queryFn: () =>
|
|
1186
|
+
queryFn: () => d.request(_e(b)).then((c) => c.data),
|
|
1152
1187
|
enabled: !!b
|
|
1153
|
-
}), [
|
|
1188
|
+
}), [C, N] = q(null), T = $e(
|
|
1154
1189
|
() => ({
|
|
1155
1190
|
first_name: (n == null ? void 0 : n.first_name) ?? "",
|
|
1156
1191
|
last_name: (n == null ? void 0 : n.last_name) ?? "",
|
|
@@ -1159,33 +1194,33 @@ function ot({
|
|
|
1159
1194
|
phone: (n == null ? void 0 : n.phone) ?? ""
|
|
1160
1195
|
}),
|
|
1161
1196
|
[n]
|
|
1162
|
-
), v =
|
|
1163
|
-
mutationFn: () =>
|
|
1197
|
+
), v = C ?? T, O = JSON.stringify(v) !== JSON.stringify(T), A = _({
|
|
1198
|
+
mutationFn: () => d.request(be(n.id, v)),
|
|
1164
1199
|
onSuccess: () => {
|
|
1165
|
-
|
|
1200
|
+
N(null), o.invalidateQueries({ queryKey: ["nvr-profile-user"] }), o.invalidateQueries({ queryKey: ["nvr-profile-card"] });
|
|
1166
1201
|
}
|
|
1167
|
-
}), [S, f] =
|
|
1168
|
-
mutationFn: async (
|
|
1169
|
-
const
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1202
|
+
}), [S, f] = q(bt), z = je(null), P = _({
|
|
1203
|
+
mutationFn: async (c) => {
|
|
1204
|
+
const k = await new Promise((F, J) => {
|
|
1205
|
+
const M = new Image(), W = URL.createObjectURL(c);
|
|
1206
|
+
M.onload = () => {
|
|
1172
1207
|
URL.revokeObjectURL(W);
|
|
1173
1208
|
const Q = 96, B = document.createElement("canvas");
|
|
1174
1209
|
B.width = Q, B.height = Q;
|
|
1175
|
-
const
|
|
1176
|
-
if (!
|
|
1177
|
-
const
|
|
1178
|
-
|
|
1179
|
-
},
|
|
1180
|
-
URL.revokeObjectURL(W),
|
|
1181
|
-
},
|
|
1210
|
+
const V = B.getContext("2d");
|
|
1211
|
+
if (!V) return J(new Error("canvas unavailable"));
|
|
1212
|
+
const Z = Math.max(Q / M.width, Q / M.height), X = M.width * Z, ee = M.height * Z;
|
|
1213
|
+
V.drawImage(M, (Q - X) / 2, (Q - ee) / 2, X, ee), F(B.toDataURL("image/jpeg", 0.85));
|
|
1214
|
+
}, M.onerror = () => {
|
|
1215
|
+
URL.revokeObjectURL(W), J(new Error("not an image"));
|
|
1216
|
+
}, M.src = W;
|
|
1182
1217
|
});
|
|
1183
|
-
await
|
|
1218
|
+
await d.request(be(n.id, { avatar: k }));
|
|
1184
1219
|
},
|
|
1185
1220
|
onSuccess: () => {
|
|
1186
1221
|
o.invalidateQueries({ queryKey: ["nvr-profile-user"] }), o.invalidateQueries({ queryKey: ["nvr-profile-card"] }), o.invalidateQueries({ queryKey: ["user-card"] }), o.invalidateQueries({ queryKey: ["user-avatar"] });
|
|
1187
1222
|
}
|
|
1188
|
-
}), y =
|
|
1223
|
+
}), y = h ?? (n ? { ...n, role_name: null } : null);
|
|
1189
1224
|
if (!y)
|
|
1190
1225
|
return /* @__PURE__ */ t("div", { className: R("flex animate-pulse flex-col gap-4", i), "aria-busy": "true", children: [
|
|
1191
1226
|
/* @__PURE__ */ t("div", { className: "flex items-center gap-5 rounded-lg border border-slate-200 bg-white p-5 dark:border-border dark:bg-card", children: [
|
|
@@ -1201,26 +1236,26 @@ function ot({
|
|
|
1201
1236
|
/* @__PURE__ */ e("div", { className: "h-64 rounded-lg border border-slate-200 bg-white dark:border-border dark:bg-card" })
|
|
1202
1237
|
] })
|
|
1203
1238
|
] });
|
|
1204
|
-
const
|
|
1239
|
+
const $ = (n == null ? void 0 : n.avatar) ?? null, U = y.status === "active";
|
|
1205
1240
|
return /* @__PURE__ */ t("div", { className: R("flex flex-col gap-4", i), "data-nvr-profile": !0, children: [
|
|
1206
1241
|
/* @__PURE__ */ e("div", { className: "rounded-lg border border-slate-200 bg-white dark:border-border dark:bg-card", children: /* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-x-5 gap-y-4 p-5", children: [
|
|
1207
1242
|
/* @__PURE__ */ t("div", { className: "relative", children: [
|
|
1208
|
-
|
|
1243
|
+
$ ? /* @__PURE__ */ e(
|
|
1209
1244
|
"img",
|
|
1210
1245
|
{
|
|
1211
|
-
src:
|
|
1246
|
+
src: $.startsWith("data:") ? $ : `/api/files/${$}`,
|
|
1212
1247
|
alt: "",
|
|
1213
1248
|
className: "h-[76px] w-[76px] rounded-full border border-slate-200 object-cover dark:border-border"
|
|
1214
1249
|
}
|
|
1215
|
-
) : /* @__PURE__ */ e("span", { className: "flex h-[76px] w-[76px] items-center justify-center rounded-full bg-[#c7f0fb] text-[24px] font-semibold text-[#04516b] dark:bg-nvr-cyan/15 dark:text-nvr-cyan", children:
|
|
1250
|
+
) : /* @__PURE__ */ e("span", { className: "flex h-[76px] w-[76px] items-center justify-center rounded-full bg-[#c7f0fb] text-[24px] font-semibold text-[#04516b] dark:bg-nvr-cyan/15 dark:text-nvr-cyan", children: lt(y) }),
|
|
1216
1251
|
/* @__PURE__ */ e(
|
|
1217
1252
|
"span",
|
|
1218
1253
|
{
|
|
1219
1254
|
className: R(
|
|
1220
1255
|
"absolute bottom-0.5 right-0.5 h-3 w-3 rounded-full border-2 border-white dark:border-card",
|
|
1221
|
-
|
|
1256
|
+
U ? "bg-emerald-500" : "bg-slate-300 dark:bg-slate-600"
|
|
1222
1257
|
),
|
|
1223
|
-
title:
|
|
1258
|
+
title: U ? "Active" : y.status
|
|
1224
1259
|
}
|
|
1225
1260
|
),
|
|
1226
1261
|
/* @__PURE__ */ t(oe, { children: [
|
|
@@ -1231,11 +1266,11 @@ function ot({
|
|
|
1231
1266
|
title: "Change photo",
|
|
1232
1267
|
"aria-label": "Change photo",
|
|
1233
1268
|
onClick: () => {
|
|
1234
|
-
var
|
|
1235
|
-
return (
|
|
1269
|
+
var c;
|
|
1270
|
+
return (c = z.current) == null ? void 0 : c.click();
|
|
1236
1271
|
},
|
|
1237
1272
|
className: "absolute -right-1 -top-1 flex h-7 w-7 items-center justify-center rounded-full border border-slate-200 bg-white text-slate-500 shadow-sm transition-colors hover:border-nvr-cyan hover:text-nvr-navy dark:border-border dark:bg-background dark:text-slate-300 dark:hover:text-nvr-cyan",
|
|
1238
|
-
children:
|
|
1273
|
+
children: P.isPending ? /* @__PURE__ */ e(xe, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ e(Pe, { className: "h-3.5 w-3.5" })
|
|
1239
1274
|
}
|
|
1240
1275
|
),
|
|
1241
1276
|
/* @__PURE__ */ e(
|
|
@@ -1245,10 +1280,10 @@ function ot({
|
|
|
1245
1280
|
type: "file",
|
|
1246
1281
|
accept: "image/*",
|
|
1247
1282
|
className: "hidden",
|
|
1248
|
-
onChange: (
|
|
1249
|
-
var
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1283
|
+
onChange: (c) => {
|
|
1284
|
+
var F;
|
|
1285
|
+
const k = (F = c.target.files) == null ? void 0 : F[0];
|
|
1286
|
+
k && P.mutate(k), c.target.value = "";
|
|
1252
1287
|
}
|
|
1253
1288
|
}
|
|
1254
1289
|
)
|
|
@@ -1256,18 +1291,18 @@ function ot({
|
|
|
1256
1291
|
] }),
|
|
1257
1292
|
/* @__PURE__ */ t("div", { className: "min-w-0 flex-1", children: [
|
|
1258
1293
|
/* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1259
|
-
/* @__PURE__ */ e("h1", { className: "text-[21px] font-semibold tracking-[-0.015em] text-slate-900 dark:text-white", children:
|
|
1294
|
+
/* @__PURE__ */ e("h1", { className: "text-[21px] font-semibold tracking-[-0.015em] text-slate-900 dark:text-white", children: st(y) }),
|
|
1260
1295
|
y.role_name && /* @__PURE__ */ e("span", { className: "rounded-full bg-nvr-cyan/10 px-2 py-px text-[10.5px] font-semibold text-nvr-navy dark:text-nvr-cyan", children: y.role_name }),
|
|
1261
1296
|
y.is_out_of_office && /* @__PURE__ */ e("span", { className: "rounded-full bg-amber-50 px-2 py-px text-[10.5px] font-semibold text-amber-600 dark:bg-amber-500/10 dark:text-amber-400", children: "Out of office" }),
|
|
1262
|
-
/* @__PURE__ */ e(
|
|
1297
|
+
/* @__PURE__ */ e(Ze, { email: y.email, canClear: l.isAdmin })
|
|
1263
1298
|
] }),
|
|
1264
1299
|
n && // The same status the chat panel's Online tab sets — one editor,
|
|
1265
1300
|
// one preference, so the profile always agrees with the top bar.
|
|
1266
1301
|
/* @__PURE__ */ e(
|
|
1267
|
-
|
|
1302
|
+
Be,
|
|
1268
1303
|
{
|
|
1269
|
-
status:
|
|
1270
|
-
(
|
|
1304
|
+
status: He(
|
|
1305
|
+
(j = n.preferences) == null ? void 0 : j.custom_status
|
|
1271
1306
|
),
|
|
1272
1307
|
showExpiry: !0,
|
|
1273
1308
|
className: "mt-1.5"
|
|
@@ -1276,7 +1311,7 @@ function ot({
|
|
|
1276
1311
|
(y.title || y.department) && /* @__PURE__ */ e("p", { className: "mt-0.5 truncate text-[13px] text-slate-500 dark:text-slate-400", children: [y.title, y.department].filter(Boolean).join(" · ") }),
|
|
1277
1312
|
/* @__PURE__ */ t("div", { className: "mt-2 flex flex-wrap items-center gap-x-4 gap-y-1 text-[12.5px] text-slate-500 dark:text-slate-400", children: [
|
|
1278
1313
|
y.company && /* @__PURE__ */ t("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
1279
|
-
/* @__PURE__ */ e(
|
|
1314
|
+
/* @__PURE__ */ e(Ae, { className: "h-3.5 w-3.5" }),
|
|
1280
1315
|
" ",
|
|
1281
1316
|
y.company
|
|
1282
1317
|
] }),
|
|
@@ -1286,7 +1321,7 @@ function ot({
|
|
|
1286
1321
|
href: `mailto:${y.email}`,
|
|
1287
1322
|
className: "inline-flex items-center gap-1.5 transition-colors hover:text-nvr-navy dark:hover:text-nvr-cyan",
|
|
1288
1323
|
children: [
|
|
1289
|
-
/* @__PURE__ */ e(
|
|
1324
|
+
/* @__PURE__ */ e(Te, { className: "h-3.5 w-3.5" }),
|
|
1290
1325
|
" ",
|
|
1291
1326
|
y.email
|
|
1292
1327
|
]
|
|
@@ -1298,14 +1333,14 @@ function ot({
|
|
|
1298
1333
|
href: `tel:${y.phone}`,
|
|
1299
1334
|
className: "inline-flex items-center gap-1.5 transition-colors hover:text-nvr-navy dark:hover:text-nvr-cyan",
|
|
1300
1335
|
children: [
|
|
1301
|
-
/* @__PURE__ */ e(
|
|
1336
|
+
/* @__PURE__ */ e(Oe, { className: "h-3.5 w-3.5" }),
|
|
1302
1337
|
" ",
|
|
1303
1338
|
y.phone
|
|
1304
1339
|
]
|
|
1305
1340
|
}
|
|
1306
1341
|
),
|
|
1307
1342
|
y.last_access && /* @__PURE__ */ t("span", { className: "inline-flex items-center gap-1.5", title: "Last active", children: [
|
|
1308
|
-
/* @__PURE__ */ e(
|
|
1343
|
+
/* @__PURE__ */ e(Fe, { className: "h-3.5 w-3.5" }),
|
|
1309
1344
|
new Date(y.last_access).toLocaleDateString(void 0, {
|
|
1310
1345
|
month: "short",
|
|
1311
1346
|
day: "numeric"
|
|
@@ -1314,8 +1349,8 @@ function ot({
|
|
|
1314
1349
|
] })
|
|
1315
1350
|
] })
|
|
1316
1351
|
] }) }),
|
|
1317
|
-
/* @__PURE__ */ e(
|
|
1318
|
-
S === "agents" ? /* @__PURE__ */ e(
|
|
1352
|
+
/* @__PURE__ */ e(xt, { tab: S, onChange: f }),
|
|
1353
|
+
S === "agents" ? /* @__PURE__ */ e(Ye, {}) : n ? (
|
|
1319
1354
|
// One list in reading order — you, then notifications, then access
|
|
1320
1355
|
// and security — flowing into two balanced columns. Two fixed stacks
|
|
1321
1356
|
// left thirteen cards on one side and four on the other, and the page
|
|
@@ -1329,7 +1364,7 @@ function ot({
|
|
|
1329
1364
|
/* @__PURE__ */ e(
|
|
1330
1365
|
ie,
|
|
1331
1366
|
{
|
|
1332
|
-
icon: /* @__PURE__ */ e(
|
|
1367
|
+
icon: /* @__PURE__ */ e(Me, { className: "h-4 w-4" }),
|
|
1333
1368
|
title: "About you",
|
|
1334
1369
|
hint: "Shown on your contact card across the app",
|
|
1335
1370
|
actions: O && /* @__PURE__ */ t("span", { className: "flex items-center gap-1.5", children: [
|
|
@@ -1338,10 +1373,10 @@ function ot({
|
|
|
1338
1373
|
{
|
|
1339
1374
|
type: "button",
|
|
1340
1375
|
title: "Discard changes",
|
|
1341
|
-
onClick: () =>
|
|
1376
|
+
onClick: () => N(null),
|
|
1342
1377
|
className: "inline-flex h-7 items-center gap-1 rounded-md px-2 text-[11.5px] font-medium text-slate-400 transition-colors hover:text-slate-600 dark:hover:text-slate-200",
|
|
1343
1378
|
children: [
|
|
1344
|
-
/* @__PURE__ */ e(
|
|
1379
|
+
/* @__PURE__ */ e(Le, { className: "h-3 w-3" }),
|
|
1345
1380
|
" Reset"
|
|
1346
1381
|
]
|
|
1347
1382
|
}
|
|
@@ -1350,11 +1385,11 @@ function ot({
|
|
|
1350
1385
|
"button",
|
|
1351
1386
|
{
|
|
1352
1387
|
type: "button",
|
|
1353
|
-
disabled:
|
|
1354
|
-
onClick: () =>
|
|
1388
|
+
disabled: A.isPending,
|
|
1389
|
+
onClick: () => A.mutate(),
|
|
1355
1390
|
className: "inline-flex h-7 items-center gap-1 rounded-md bg-nvr-cyan px-2.5 text-[11.5px] font-semibold text-white transition-opacity disabled:opacity-50",
|
|
1356
1391
|
children: [
|
|
1357
|
-
|
|
1392
|
+
A.isPending ? /* @__PURE__ */ e(xe, { className: "h-3 w-3 animate-spin" }) : /* @__PURE__ */ e(De, { className: "h-3 w-3" }),
|
|
1358
1393
|
" ",
|
|
1359
1394
|
"Save"
|
|
1360
1395
|
]
|
|
@@ -1367,7 +1402,7 @@ function ot({
|
|
|
1367
1402
|
{
|
|
1368
1403
|
label: "First name",
|
|
1369
1404
|
value: v.first_name,
|
|
1370
|
-
onChange: (
|
|
1405
|
+
onChange: (c) => N({ ...v, first_name: c })
|
|
1371
1406
|
}
|
|
1372
1407
|
),
|
|
1373
1408
|
/* @__PURE__ */ e(
|
|
@@ -1375,7 +1410,7 @@ function ot({
|
|
|
1375
1410
|
{
|
|
1376
1411
|
label: "Last name",
|
|
1377
1412
|
value: v.last_name,
|
|
1378
|
-
onChange: (
|
|
1413
|
+
onChange: (c) => N({ ...v, last_name: c })
|
|
1379
1414
|
}
|
|
1380
1415
|
),
|
|
1381
1416
|
/* @__PURE__ */ e(
|
|
@@ -1383,7 +1418,7 @@ function ot({
|
|
|
1383
1418
|
{
|
|
1384
1419
|
label: "Title",
|
|
1385
1420
|
value: v.title,
|
|
1386
|
-
onChange: (
|
|
1421
|
+
onChange: (c) => N({ ...v, title: c }),
|
|
1387
1422
|
placeholder: "e.g. Construction Manager"
|
|
1388
1423
|
}
|
|
1389
1424
|
),
|
|
@@ -1392,7 +1427,7 @@ function ot({
|
|
|
1392
1427
|
{
|
|
1393
1428
|
label: "Department",
|
|
1394
1429
|
value: v.department,
|
|
1395
|
-
onChange: (
|
|
1430
|
+
onChange: (c) => N({ ...v, department: c })
|
|
1396
1431
|
}
|
|
1397
1432
|
),
|
|
1398
1433
|
/* @__PURE__ */ e(
|
|
@@ -1400,7 +1435,7 @@ function ot({
|
|
|
1400
1435
|
{
|
|
1401
1436
|
label: "Phone",
|
|
1402
1437
|
value: v.phone,
|
|
1403
|
-
onChange: (
|
|
1438
|
+
onChange: (c) => N({ ...v, phone: c }),
|
|
1404
1439
|
placeholder: "+1 …",
|
|
1405
1440
|
type: "tel"
|
|
1406
1441
|
}
|
|
@@ -1410,7 +1445,7 @@ function ot({
|
|
|
1410
1445
|
}
|
|
1411
1446
|
),
|
|
1412
1447
|
/* @__PURE__ */ e(
|
|
1413
|
-
|
|
1448
|
+
Ve,
|
|
1414
1449
|
{
|
|
1415
1450
|
user: n,
|
|
1416
1451
|
onSaved: () => {
|
|
@@ -1418,23 +1453,23 @@ function ot({
|
|
|
1418
1453
|
}
|
|
1419
1454
|
}
|
|
1420
1455
|
),
|
|
1421
|
-
/* @__PURE__ */ e(
|
|
1422
|
-
/* @__PURE__ */ e(
|
|
1423
|
-
/* @__PURE__ */ e(
|
|
1424
|
-
/* @__PURE__ */ e(
|
|
1425
|
-
/* @__PURE__ */ e(Re, {}),
|
|
1426
|
-
/* @__PURE__ */ e(Ue, {}),
|
|
1427
|
-
l.isAdmin && (n != null && n.id) ? /* @__PURE__ */ e(Ge, { userId: String(n.id) }) : /* @__PURE__ */ e(nt, {}),
|
|
1428
|
-
/* @__PURE__ */ e(ut, {}),
|
|
1429
|
-
/* @__PURE__ */ e(Ye, { userId: "me" }),
|
|
1430
|
-
/* @__PURE__ */ e(mt, {}),
|
|
1431
|
-
/* @__PURE__ */ e(tt, {}),
|
|
1456
|
+
/* @__PURE__ */ e(ot, {}),
|
|
1457
|
+
/* @__PURE__ */ e(ct, {}),
|
|
1458
|
+
/* @__PURE__ */ e(Nt, {}),
|
|
1459
|
+
/* @__PURE__ */ e(dt, {}),
|
|
1432
1460
|
/* @__PURE__ */ e(We, {}),
|
|
1433
|
-
|
|
1461
|
+
/* @__PURE__ */ e(Ge, {}),
|
|
1462
|
+
l.isAdmin && (n != null && n.id) ? /* @__PURE__ */ e(at, { userId: String(n.id) }) : /* @__PURE__ */ e(ut, {}),
|
|
1463
|
+
/* @__PURE__ */ e(yt, {}),
|
|
1464
|
+
/* @__PURE__ */ e(Xe, { userId: "me" }),
|
|
1465
|
+
/* @__PURE__ */ e(ft, {}),
|
|
1466
|
+
/* @__PURE__ */ e(it, {}),
|
|
1467
|
+
/* @__PURE__ */ e(tt, {}),
|
|
1468
|
+
r !== !1 && /* @__PURE__ */ e(Je, { serviceWorkerPath: r }),
|
|
1469
|
+
/* @__PURE__ */ e(vt, {}),
|
|
1434
1470
|
/* @__PURE__ */ e(pt, {}),
|
|
1435
|
-
/* @__PURE__ */ e(
|
|
1436
|
-
/* @__PURE__ */ e(
|
|
1437
|
-
/* @__PURE__ */ e(ct, {}),
|
|
1471
|
+
/* @__PURE__ */ e(kt, {}),
|
|
1472
|
+
/* @__PURE__ */ e(gt, {}),
|
|
1438
1473
|
m
|
|
1439
1474
|
]
|
|
1440
1475
|
}
|
|
@@ -1442,18 +1477,18 @@ function ot({
|
|
|
1442
1477
|
) : null
|
|
1443
1478
|
] });
|
|
1444
1479
|
}
|
|
1445
|
-
function
|
|
1480
|
+
function bt() {
|
|
1446
1481
|
try {
|
|
1447
1482
|
return new URLSearchParams(window.location.search).get("tab") === "agents" ? "agents" : "profile";
|
|
1448
1483
|
} catch {
|
|
1449
1484
|
return "profile";
|
|
1450
1485
|
}
|
|
1451
1486
|
}
|
|
1452
|
-
function
|
|
1487
|
+
function xt({
|
|
1453
1488
|
tab: i,
|
|
1454
1489
|
onChange: m
|
|
1455
1490
|
}) {
|
|
1456
|
-
const
|
|
1491
|
+
const r = (o) => {
|
|
1457
1492
|
m(o);
|
|
1458
1493
|
try {
|
|
1459
1494
|
const l = new URL(window.location.href);
|
|
@@ -1476,7 +1511,7 @@ function dt({
|
|
|
1476
1511
|
type: "button",
|
|
1477
1512
|
role: "tab",
|
|
1478
1513
|
"aria-selected": i === o,
|
|
1479
|
-
onClick: () =>
|
|
1514
|
+
onClick: () => r(o),
|
|
1480
1515
|
className: R(
|
|
1481
1516
|
"-mb-px border-b-2 px-3 py-2 text-[13px] font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-nvr-cyan/40",
|
|
1482
1517
|
i === o ? "border-nvr-cyan text-slate-900 dark:text-white" : "border-transparent text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-slate-200"
|
|
@@ -1488,23 +1523,23 @@ function dt({
|
|
|
1488
1523
|
}
|
|
1489
1524
|
);
|
|
1490
1525
|
}
|
|
1491
|
-
function
|
|
1492
|
-
const i =
|
|
1526
|
+
function gt() {
|
|
1527
|
+
const i = L(), [m, r] = q(!1), { data: d = [], isLoading: o } = w({
|
|
1493
1528
|
queryKey: ["my-matrix-seats"],
|
|
1494
|
-
queryFn: () => i.request(
|
|
1529
|
+
queryFn: () => i.request(D("/pipelines/my-seats")).then((s) => s.data ?? []).catch(() => []),
|
|
1495
1530
|
enabled: m,
|
|
1496
1531
|
staleTime: 6e4
|
|
1497
1532
|
}), l = /* @__PURE__ */ new Map();
|
|
1498
|
-
for (const
|
|
1499
|
-
const u = l.get(
|
|
1500
|
-
u.push(
|
|
1533
|
+
for (const s of d) {
|
|
1534
|
+
const u = l.get(s.template_name) ?? [];
|
|
1535
|
+
u.push(s), l.set(s.template_name, u);
|
|
1501
1536
|
}
|
|
1502
1537
|
return /* @__PURE__ */ t("div", { className: "rounded-lg border border-slate-200 bg-white p-4 dark:border-border dark:bg-card", children: [
|
|
1503
1538
|
/* @__PURE__ */ t(
|
|
1504
1539
|
"button",
|
|
1505
1540
|
{
|
|
1506
1541
|
type: "button",
|
|
1507
|
-
onClick: () =>
|
|
1542
|
+
onClick: () => r((s) => !s),
|
|
1508
1543
|
className: "flex w-full items-center justify-between text-left",
|
|
1509
1544
|
children: [
|
|
1510
1545
|
/* @__PURE__ */ t("div", { children: [
|
|
@@ -1515,8 +1550,8 @@ function ct() {
|
|
|
1515
1550
|
]
|
|
1516
1551
|
}
|
|
1517
1552
|
),
|
|
1518
|
-
m && (o ? /* @__PURE__ */ e("p", { className: "mt-3 text-[12.5px] text-slate-400", children: "Loading…" }) :
|
|
1519
|
-
/* @__PURE__ */ e("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-slate-400", children:
|
|
1553
|
+
m && (o ? /* @__PURE__ */ e("p", { className: "mt-3 text-[12.5px] text-slate-400", children: "Loading…" }) : d.length === 0 ? /* @__PURE__ */ e("p", { className: "mt-3 text-[12.5px] text-slate-400", children: "You're not in any owner groups — approvals never route to you automatically." }) : /* @__PURE__ */ e("div", { className: "mt-3 space-y-3", children: [...l.entries()].map(([s, u]) => /* @__PURE__ */ t("div", { children: [
|
|
1554
|
+
/* @__PURE__ */ e("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-slate-400", children: s }),
|
|
1520
1555
|
/* @__PURE__ */ t("ul", { className: "mt-1 space-y-1.5", children: [
|
|
1521
1556
|
u.slice(0, 40).map((n) => /* @__PURE__ */ t("li", { className: "text-[12.5px]", children: [
|
|
1522
1557
|
/* @__PURE__ */ e("span", { className: "font-medium", children: n.state_label || n.state_key }),
|
|
@@ -1549,21 +1584,21 @@ function ct() {
|
|
|
1549
1584
|
" more"
|
|
1550
1585
|
] })
|
|
1551
1586
|
] })
|
|
1552
|
-
] },
|
|
1587
|
+
] }, s)) }))
|
|
1553
1588
|
] });
|
|
1554
1589
|
}
|
|
1555
|
-
function
|
|
1556
|
-
const i =
|
|
1590
|
+
function yt() {
|
|
1591
|
+
const i = L(), m = K(), { data: r = [] } = w({
|
|
1557
1592
|
queryKey: ["my-reminders"],
|
|
1558
|
-
queryFn: () => i.request(
|
|
1593
|
+
queryFn: () => i.request(D("/reminders")).then((h) => h.data).catch(() => []),
|
|
1559
1594
|
staleTime: 3e4
|
|
1560
|
-
}), [
|
|
1561
|
-
mutationFn: () => i.request(ae("/reminders", { note:
|
|
1595
|
+
}), [d, o] = q(""), [l, s] = q(""), u = () => void m.invalidateQueries({ queryKey: ["my-reminders"] }), n = _({
|
|
1596
|
+
mutationFn: () => i.request(ae("/reminders", { note: d, remind_at: new Date(l).toISOString() })),
|
|
1562
1597
|
onSuccess: () => {
|
|
1563
|
-
o(""),
|
|
1598
|
+
o(""), s(""), u();
|
|
1564
1599
|
}
|
|
1565
1600
|
}), b = _({
|
|
1566
|
-
mutationFn: (
|
|
1601
|
+
mutationFn: (h) => i.request(Re(`/reminders/${h}`)),
|
|
1567
1602
|
onSuccess: u
|
|
1568
1603
|
});
|
|
1569
1604
|
return /* @__PURE__ */ t("div", { className: "rounded-lg border border-slate-200 bg-white dark:border-border dark:bg-card", children: [
|
|
@@ -1572,35 +1607,35 @@ function ut() {
|
|
|
1572
1607
|
/* @__PURE__ */ e("p", { className: "mt-0.5 text-[11px] text-slate-400", children: `Personal nudges delivered as notifications at the time you pick. The chat bot's "remind me…" requests land here too.` })
|
|
1573
1608
|
] }),
|
|
1574
1609
|
/* @__PURE__ */ t("div", { className: "space-y-2 px-4 py-3", children: [
|
|
1575
|
-
|
|
1576
|
-
|
|
1610
|
+
r.length === 0 && /* @__PURE__ */ e("p", { className: "text-[12px] text-slate-400", children: "No upcoming reminders." }),
|
|
1611
|
+
r.map((h) => /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [
|
|
1577
1612
|
/* @__PURE__ */ t("div", { className: "min-w-0 flex-1", children: [
|
|
1578
|
-
/* @__PURE__ */ e("p", { className: "truncate text-[12.5px] text-slate-700 dark:text-slate-200", children:
|
|
1579
|
-
/* @__PURE__ */ e("p", { className: "text-[11px] text-slate-400", children: new Date(
|
|
1613
|
+
/* @__PURE__ */ e("p", { className: "truncate text-[12.5px] text-slate-700 dark:text-slate-200", children: h.note }),
|
|
1614
|
+
/* @__PURE__ */ e("p", { className: "text-[11px] text-slate-400", children: new Date(h.remind_at).toLocaleString() })
|
|
1580
1615
|
] }),
|
|
1581
1616
|
/* @__PURE__ */ e(
|
|
1582
1617
|
"button",
|
|
1583
1618
|
{
|
|
1584
1619
|
type: "button",
|
|
1585
|
-
onClick: () => b.mutate(
|
|
1620
|
+
onClick: () => b.mutate(h.id),
|
|
1586
1621
|
className: "shrink-0 rounded px-1.5 py-0.5 text-[11px] text-slate-400 hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-500/10",
|
|
1587
1622
|
children: "Cancel"
|
|
1588
1623
|
}
|
|
1589
1624
|
)
|
|
1590
|
-
] },
|
|
1625
|
+
] }, h.id)),
|
|
1591
1626
|
/* @__PURE__ */ t(
|
|
1592
1627
|
"form",
|
|
1593
1628
|
{
|
|
1594
1629
|
className: "flex flex-wrap items-center gap-2 pt-1",
|
|
1595
|
-
onSubmit: (
|
|
1596
|
-
|
|
1630
|
+
onSubmit: (h) => {
|
|
1631
|
+
h.preventDefault(), d.trim() && l && n.mutate();
|
|
1597
1632
|
},
|
|
1598
1633
|
children: [
|
|
1599
1634
|
/* @__PURE__ */ e(
|
|
1600
1635
|
"input",
|
|
1601
1636
|
{
|
|
1602
|
-
value:
|
|
1603
|
-
onChange: (
|
|
1637
|
+
value: d,
|
|
1638
|
+
onChange: (h) => o(h.target.value),
|
|
1604
1639
|
placeholder: "Remind me to…",
|
|
1605
1640
|
className: "h-7 min-w-[160px] flex-1 rounded border border-slate-200 px-2 text-[12px] outline-none focus:border-nvr-cyan dark:border-border dark:bg-background"
|
|
1606
1641
|
}
|
|
@@ -1610,7 +1645,7 @@ function ut() {
|
|
|
1610
1645
|
{
|
|
1611
1646
|
type: "datetime-local",
|
|
1612
1647
|
value: l,
|
|
1613
|
-
onChange: (
|
|
1648
|
+
onChange: (h) => s(h.target.value),
|
|
1614
1649
|
className: "h-7 rounded border border-slate-200 px-2 text-[12px] outline-none focus:border-nvr-cyan dark:border-border dark:bg-background"
|
|
1615
1650
|
}
|
|
1616
1651
|
),
|
|
@@ -1618,7 +1653,7 @@ function ut() {
|
|
|
1618
1653
|
"button",
|
|
1619
1654
|
{
|
|
1620
1655
|
type: "submit",
|
|
1621
|
-
disabled: !
|
|
1656
|
+
disabled: !d.trim() || !l || n.isPending,
|
|
1622
1657
|
className: "h-7 rounded bg-nvr-cyan px-2.5 text-[11.5px] font-medium text-white hover:bg-nvr-cyan-dark disabled:opacity-50",
|
|
1623
1658
|
children: n.isPending ? "Adding…" : "Add"
|
|
1624
1659
|
}
|
|
@@ -1629,14 +1664,14 @@ function ut() {
|
|
|
1629
1664
|
] })
|
|
1630
1665
|
] });
|
|
1631
1666
|
}
|
|
1632
|
-
function
|
|
1633
|
-
const i =
|
|
1667
|
+
function ft() {
|
|
1668
|
+
const i = L(), { data: m } = w({
|
|
1634
1669
|
queryKey: ["my-stats"],
|
|
1635
|
-
queryFn: () => i.request(
|
|
1670
|
+
queryFn: () => i.request(D("/users/me/stats")).then((d) => d.data).catch(() => null),
|
|
1636
1671
|
staleTime: 5 * 6e4
|
|
1637
1672
|
});
|
|
1638
1673
|
if (!m) return null;
|
|
1639
|
-
const
|
|
1674
|
+
const r = Math.max(1, ...m.weeks.map((d) => d.transitions + d.tasks_done + d.created));
|
|
1640
1675
|
return /* @__PURE__ */ t("div", { className: "rounded-lg border border-slate-200 bg-white dark:border-border dark:bg-card", children: [
|
|
1641
1676
|
/* @__PURE__ */ t("header", { className: "flex items-center justify-between border-b border-slate-100 px-4 py-2.5 dark:border-border/60", children: [
|
|
1642
1677
|
/* @__PURE__ */ t("div", { children: [
|
|
@@ -1649,14 +1684,14 @@ function mt() {
|
|
|
1649
1684
|
] })
|
|
1650
1685
|
] }),
|
|
1651
1686
|
/* @__PURE__ */ t("div", { className: "px-4 py-3", children: [
|
|
1652
|
-
/* @__PURE__ */ e("div", { className: "flex items-end gap-1.5", style: { height: 56 }, children: m.weeks.map((
|
|
1653
|
-
const l =
|
|
1687
|
+
/* @__PURE__ */ e("div", { className: "flex items-end gap-1.5", style: { height: 56 }, children: m.weeks.map((d, o) => {
|
|
1688
|
+
const l = d.transitions + d.tasks_done + d.created;
|
|
1654
1689
|
return /* @__PURE__ */ e(
|
|
1655
1690
|
"div",
|
|
1656
1691
|
{
|
|
1657
1692
|
className: "flex-1 rounded-t bg-nvr-cyan/60 transition-all dark:bg-nvr-cyan/40",
|
|
1658
|
-
style: { height: `${Math.max(4, l /
|
|
1659
|
-
"data-tip": `${l} action${l === 1 ? "" : "s"}: ${
|
|
1693
|
+
style: { height: `${Math.max(4, l / r * 100)}%` },
|
|
1694
|
+
"data-tip": `${l} action${l === 1 ? "" : "s"}: ${d.transitions} transitions, ${d.tasks_done} tasks done, ${d.created} created`
|
|
1660
1695
|
},
|
|
1661
1696
|
o
|
|
1662
1697
|
);
|
|
@@ -1685,25 +1720,25 @@ function mt() {
|
|
|
1685
1720
|
] })
|
|
1686
1721
|
] });
|
|
1687
1722
|
}
|
|
1688
|
-
function
|
|
1689
|
-
const i =
|
|
1723
|
+
function vt() {
|
|
1724
|
+
const i = L(), m = K(), { data: r } = w({
|
|
1690
1725
|
queryKey: ["my-security"],
|
|
1691
|
-
queryFn: () => i.request(
|
|
1726
|
+
queryFn: () => i.request(D("/security/my/sessions")).then((l) => l.data).catch(() => ({ sessions: [], logins: [] })),
|
|
1692
1727
|
staleTime: 3e4
|
|
1693
|
-
}),
|
|
1728
|
+
}), d = _({
|
|
1694
1729
|
mutationFn: () => i.request(ae("/security/my/sessions/sign-out-others", {})).then((l) => l.data),
|
|
1695
1730
|
onSuccess: (l) => {
|
|
1696
1731
|
m.invalidateQueries({ queryKey: ["my-security"] }), o(`Signed out ${(l == null ? void 0 : l.revoked) ?? 0} other session(s)`);
|
|
1697
1732
|
},
|
|
1698
1733
|
onError: (l) => {
|
|
1699
1734
|
var u, n;
|
|
1700
|
-
const
|
|
1701
|
-
import("sonner").then(({ toast: b }) => b.error(
|
|
1735
|
+
const s = ((n = (u = l == null ? void 0 : l.response) == null ? void 0 : u.data) == null ? void 0 : n.error) ?? "Could not sign out your other sessions — try again.";
|
|
1736
|
+
import("sonner").then(({ toast: b }) => b.error(s)).catch(() => {
|
|
1702
1737
|
});
|
|
1703
1738
|
}
|
|
1704
1739
|
}), o = (l) => {
|
|
1705
1740
|
try {
|
|
1706
|
-
import("sonner").then(({ toast:
|
|
1741
|
+
import("sonner").then(({ toast: s }) => s.success(l));
|
|
1707
1742
|
} catch {
|
|
1708
1743
|
}
|
|
1709
1744
|
};
|
|
@@ -1713,12 +1748,12 @@ function pt() {
|
|
|
1713
1748
|
/* @__PURE__ */ e("h3", { className: "text-[13px] font-semibold text-slate-800 dark:text-slate-100", children: "Security" }),
|
|
1714
1749
|
/* @__PURE__ */ e("p", { className: "mt-0.5 text-[11px] text-slate-400", children: "Your active sessions and recent sign-ins." })
|
|
1715
1750
|
] }),
|
|
1716
|
-
((
|
|
1751
|
+
((r == null ? void 0 : r.sessions.length) ?? 0) > 1 && /* @__PURE__ */ e(
|
|
1717
1752
|
"button",
|
|
1718
1753
|
{
|
|
1719
1754
|
type: "button",
|
|
1720
|
-
disabled:
|
|
1721
|
-
onClick: () =>
|
|
1755
|
+
disabled: d.isPending,
|
|
1756
|
+
onClick: () => d.mutate(),
|
|
1722
1757
|
className: "rounded-md border border-red-200 px-2 py-1 text-[11.5px] text-red-600 hover:bg-red-50 disabled:opacity-50 dark:border-red-500/30",
|
|
1723
1758
|
children: "Sign out everywhere else"
|
|
1724
1759
|
}
|
|
@@ -1727,10 +1762,10 @@ function pt() {
|
|
|
1727
1762
|
/* @__PURE__ */ t("div", { className: "space-y-2 p-4", children: [
|
|
1728
1763
|
/* @__PURE__ */ t("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-slate-400", children: [
|
|
1729
1764
|
"Active sessions (",
|
|
1730
|
-
(
|
|
1765
|
+
(r == null ? void 0 : r.sessions.length) ?? 0,
|
|
1731
1766
|
")"
|
|
1732
1767
|
] }),
|
|
1733
|
-
((
|
|
1768
|
+
((r == null ? void 0 : r.sessions) ?? []).map((l) => /* @__PURE__ */ t(
|
|
1734
1769
|
"p",
|
|
1735
1770
|
{
|
|
1736
1771
|
className: "flex items-center gap-2 text-[12px] text-slate-600 dark:text-slate-300",
|
|
@@ -1749,24 +1784,24 @@ function pt() {
|
|
|
1749
1784
|
},
|
|
1750
1785
|
l.sid_prefix
|
|
1751
1786
|
)),
|
|
1752
|
-
((
|
|
1787
|
+
((r == null ? void 0 : r.logins) ?? []).length > 0 && /* @__PURE__ */ t(oe, { children: [
|
|
1753
1788
|
/* @__PURE__ */ e("p", { className: "pt-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400", children: "Recent sign-ins" }),
|
|
1754
|
-
((
|
|
1789
|
+
((r == null ? void 0 : r.logins) ?? []).slice(0, 8).map((l, s) => (
|
|
1755
1790
|
// biome-ignore lint/suspicious/noArrayIndexKey: log rows
|
|
1756
1791
|
/* @__PURE__ */ t("p", { className: "flex items-center gap-2 text-[11.5px] text-slate-500", children: [
|
|
1757
1792
|
/* @__PURE__ */ e("span", { className: "font-mono", children: l.ip ?? "—" }),
|
|
1758
1793
|
l.new_ip && /* @__PURE__ */ e("span", { className: "rounded bg-amber-100 px-1 text-[9.5px] font-semibold text-amber-700 dark:bg-amber-400/15 dark:text-amber-400", children: "new IP" }),
|
|
1759
1794
|
/* @__PURE__ */ e("span", { className: "ml-auto text-slate-400", children: new Date(l.created_at).toLocaleString() })
|
|
1760
|
-
] },
|
|
1795
|
+
] }, s)
|
|
1761
1796
|
))
|
|
1762
1797
|
] })
|
|
1763
1798
|
] })
|
|
1764
1799
|
] });
|
|
1765
1800
|
}
|
|
1766
|
-
function
|
|
1767
|
-
const i =
|
|
1801
|
+
function kt() {
|
|
1802
|
+
const i = L(), [m, r] = q(!1), { data: d } = w({
|
|
1768
1803
|
queryKey: ["my-permissions"],
|
|
1769
|
-
queryFn: () => i.request(
|
|
1804
|
+
queryFn: () => i.request(D("/security/my/permissions")).then((o) => o.data),
|
|
1770
1805
|
enabled: m,
|
|
1771
1806
|
staleTime: 5 * 6e4
|
|
1772
1807
|
});
|
|
@@ -1775,7 +1810,7 @@ function ht() {
|
|
|
1775
1810
|
"button",
|
|
1776
1811
|
{
|
|
1777
1812
|
type: "button",
|
|
1778
|
-
onClick: () =>
|
|
1813
|
+
onClick: () => r((o) => !o),
|
|
1779
1814
|
className: "flex w-full items-center justify-between px-4 py-2.5 text-left",
|
|
1780
1815
|
children: [
|
|
1781
1816
|
/* @__PURE__ */ t("div", { children: [
|
|
@@ -1786,25 +1821,25 @@ function ht() {
|
|
|
1786
1821
|
]
|
|
1787
1822
|
}
|
|
1788
1823
|
),
|
|
1789
|
-
m &&
|
|
1824
|
+
m && d && /* @__PURE__ */ t("div", { className: "space-y-2 border-t border-slate-100 px-4 py-3 text-[12.5px] text-slate-600 dark:border-border/60 dark:text-slate-300", children: [
|
|
1790
1825
|
/* @__PURE__ */ t("p", { children: [
|
|
1791
1826
|
"Your role is ",
|
|
1792
|
-
/* @__PURE__ */ e("b", { children:
|
|
1793
|
-
|
|
1827
|
+
/* @__PURE__ */ e("b", { children: d.role ?? "unassigned" }),
|
|
1828
|
+
d.is_admin && " — an administrator role with access to everything",
|
|
1794
1829
|
"."
|
|
1795
1830
|
] }),
|
|
1796
|
-
|
|
1831
|
+
d.scopes.length > 0 && /* @__PURE__ */ t("p", { children: [
|
|
1797
1832
|
"Your data is limited to:",
|
|
1798
1833
|
" ",
|
|
1799
|
-
|
|
1834
|
+
d.scopes.map((o) => `${o.dimension}: ${o.values.join(", ")}`).join(" · ")
|
|
1800
1835
|
] }),
|
|
1801
|
-
!
|
|
1836
|
+
!d.is_admin && /* @__PURE__ */ t("div", { children: [
|
|
1802
1837
|
/* @__PURE__ */ t("p", { className: "mb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400", children: [
|
|
1803
1838
|
"Collections (",
|
|
1804
|
-
|
|
1839
|
+
d.collections.length,
|
|
1805
1840
|
")"
|
|
1806
1841
|
] }),
|
|
1807
|
-
/* @__PURE__ */ e("div", { className: "max-h-48 overflow-y-auto", children:
|
|
1842
|
+
/* @__PURE__ */ e("div", { className: "max-h-48 overflow-y-auto", children: d.collections.map((o) => /* @__PURE__ */ t(
|
|
1808
1843
|
"p",
|
|
1809
1844
|
{
|
|
1810
1845
|
className: "flex items-center gap-2 border-b border-slate-50 py-0.5 text-[12px] last:border-b-0 dark:border-border/40",
|
|
@@ -1819,33 +1854,33 @@ function ht() {
|
|
|
1819
1854
|
] })
|
|
1820
1855
|
] });
|
|
1821
1856
|
}
|
|
1822
|
-
function
|
|
1823
|
-
const i =
|
|
1857
|
+
function Nt() {
|
|
1858
|
+
const i = L(), m = K(), { data: r } = w({
|
|
1824
1859
|
queryKey: ["nvr-profile-prefs"],
|
|
1825
|
-
queryFn: () => i.request(
|
|
1860
|
+
queryFn: () => i.request(D("/users/me")).then((u) => {
|
|
1826
1861
|
var n;
|
|
1827
1862
|
return ((n = u.data) == null ? void 0 : n.preferences) ?? {};
|
|
1828
1863
|
})
|
|
1829
|
-
}),
|
|
1830
|
-
mutationFn: (u) => i.request(
|
|
1864
|
+
}), d = _({
|
|
1865
|
+
mutationFn: (u) => i.request(G("/users/me/preferences", u)),
|
|
1831
1866
|
onSuccess: (u, n) => {
|
|
1832
1867
|
m.invalidateQueries({ queryKey: ["nvr-profile-prefs"] }), le(Object.keys(n)), import("sonner").then(
|
|
1833
1868
|
({ toast: b }) => b.success("Saved — applied on all your open tabs and devices")
|
|
1834
1869
|
);
|
|
1835
1870
|
}
|
|
1836
|
-
}), o = (
|
|
1871
|
+
}), o = (r == null ? void 0 : r.number_format) ?? {}, { data: l = [se, ...ye] } = w({
|
|
1837
1872
|
queryKey: ["nvr-theme-accents"],
|
|
1838
1873
|
queryFn: () => i.request(
|
|
1839
|
-
|
|
1874
|
+
D("/settings")
|
|
1840
1875
|
).then((u) => {
|
|
1841
1876
|
var n, b;
|
|
1842
1877
|
return [
|
|
1843
1878
|
{ ...se, color: ((n = u.data) == null ? void 0 : n.project_color) ?? null },
|
|
1844
|
-
...
|
|
1879
|
+
...Ue((b = u.data) == null ? void 0 : b.theme_accents)
|
|
1845
1880
|
];
|
|
1846
|
-
}).catch(() => [se, ...
|
|
1881
|
+
}).catch(() => [se, ...ye]),
|
|
1847
1882
|
staleTime: 5 * 6e4
|
|
1848
|
-
}),
|
|
1883
|
+
}), s = typeof (r == null ? void 0 : r.theme_accent) == "string" ? r.theme_accent : "brand";
|
|
1849
1884
|
return /* @__PURE__ */ t(
|
|
1850
1885
|
"div",
|
|
1851
1886
|
{
|
|
@@ -1860,10 +1895,10 @@ function bt() {
|
|
|
1860
1895
|
/* @__PURE__ */ t("label", { className: "flex items-center gap-1.5", children: [
|
|
1861
1896
|
"Timestamps",
|
|
1862
1897
|
/* @__PURE__ */ e(
|
|
1863
|
-
|
|
1898
|
+
E,
|
|
1864
1899
|
{
|
|
1865
|
-
value: String((
|
|
1866
|
-
onChange: (u) =>
|
|
1900
|
+
value: String((r == null ? void 0 : r.time_display) ?? "relative"),
|
|
1901
|
+
onChange: (u) => d.mutate({ time_display: u }),
|
|
1867
1902
|
options: [
|
|
1868
1903
|
{ value: "relative", label: "Relative (3h ago)" },
|
|
1869
1904
|
{ value: "exact", label: "Exact (Aug 24, 3:12 PM)" }
|
|
@@ -1877,7 +1912,7 @@ function bt() {
|
|
|
1877
1912
|
{
|
|
1878
1913
|
type: "checkbox",
|
|
1879
1914
|
checked: o.compact === !0,
|
|
1880
|
-
onChange: (u) =>
|
|
1915
|
+
onChange: (u) => d.mutate({ number_format: { ...o, compact: u.target.checked } }),
|
|
1881
1916
|
className: "rounded"
|
|
1882
1917
|
}
|
|
1883
1918
|
),
|
|
@@ -1889,7 +1924,7 @@ function bt() {
|
|
|
1889
1924
|
"input",
|
|
1890
1925
|
{
|
|
1891
1926
|
defaultValue: o.locale ?? "",
|
|
1892
|
-
onBlur: (u) =>
|
|
1927
|
+
onBlur: (u) => d.mutate({ number_format: { ...o, locale: u.target.value.trim() || void 0 } }),
|
|
1893
1928
|
placeholder: "en-US",
|
|
1894
1929
|
className: "h-7 w-20 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
|
|
1895
1930
|
}
|
|
@@ -1898,10 +1933,10 @@ function bt() {
|
|
|
1898
1933
|
/* @__PURE__ */ t("label", { className: "flex items-center gap-1.5", children: [
|
|
1899
1934
|
"Week starts",
|
|
1900
1935
|
/* @__PURE__ */ e(
|
|
1901
|
-
|
|
1936
|
+
E,
|
|
1902
1937
|
{
|
|
1903
|
-
value: String((
|
|
1904
|
-
onChange: (u) =>
|
|
1938
|
+
value: String((r == null ? void 0 : r.week_start) ?? "sun"),
|
|
1939
|
+
onChange: (u) => d.mutate({ week_start: u }),
|
|
1905
1940
|
options: [
|
|
1906
1941
|
{ value: "sun", label: "Sunday" },
|
|
1907
1942
|
{ value: "mon", label: "Monday" }
|
|
@@ -1912,7 +1947,7 @@ function bt() {
|
|
|
1912
1947
|
/* @__PURE__ */ t("div", { className: "flex items-center gap-1.5", "data-theme-accent-picker": !0, children: [
|
|
1913
1948
|
"Accent",
|
|
1914
1949
|
/* @__PURE__ */ e("span", { className: "flex items-center gap-1", children: l.map((u) => {
|
|
1915
|
-
const n = u.key === "brand" &&
|
|
1950
|
+
const n = u.key === "brand" && s === "brand" || u.key === s;
|
|
1916
1951
|
return /* @__PURE__ */ e(
|
|
1917
1952
|
"button",
|
|
1918
1953
|
{
|
|
@@ -1921,7 +1956,7 @@ function bt() {
|
|
|
1921
1956
|
"aria-label": `Accent ${u.label}`,
|
|
1922
1957
|
"aria-pressed": n,
|
|
1923
1958
|
"data-theme-accent": u.key,
|
|
1924
|
-
onClick: () =>
|
|
1959
|
+
onClick: () => d.mutate({ theme_accent: u.key === "brand" ? null : u.key }),
|
|
1925
1960
|
className: R(
|
|
1926
1961
|
"h-5 w-5 rounded-full border-2 transition-transform",
|
|
1927
1962
|
n ? "scale-110 border-slate-800 dark:border-slate-100" : "border-transparent hover:scale-105"
|
|
@@ -1935,10 +1970,10 @@ function bt() {
|
|
|
1935
1970
|
/* @__PURE__ */ t("label", { className: "flex items-center gap-1.5", children: [
|
|
1936
1971
|
"Text size",
|
|
1937
1972
|
/* @__PURE__ */ e(
|
|
1938
|
-
|
|
1973
|
+
E,
|
|
1939
1974
|
{
|
|
1940
|
-
value: String((
|
|
1941
|
-
onChange: (u) =>
|
|
1975
|
+
value: String((r == null ? void 0 : r.font_size) ?? "default"),
|
|
1976
|
+
onChange: (u) => d.mutate({ font_size: u }),
|
|
1942
1977
|
options: [
|
|
1943
1978
|
{ value: "small", label: "Small" },
|
|
1944
1979
|
{ value: "default", label: "Default" },
|
|
@@ -1953,11 +1988,11 @@ function bt() {
|
|
|
1953
1988
|
);
|
|
1954
1989
|
}
|
|
1955
1990
|
export {
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1991
|
+
Ve as DelegationCard,
|
|
1992
|
+
Nt as DisplayPrefsCard,
|
|
1993
|
+
dt as LinkAppCard,
|
|
1994
|
+
it as NotificationRulesCard,
|
|
1995
|
+
ot as ProfileFieldsCard,
|
|
1996
|
+
Yt as ProfileView,
|
|
1997
|
+
ct as TimezoneCard
|
|
1963
1998
|
};
|