@variamosple/variamos-components 0.2.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +27 -42
  2. package/dist/Common/Events.d.ts +3 -2
  3. package/dist/Common/Events.js +18 -11
  4. package/dist/Common/fieldOf.d.ts +2 -0
  5. package/dist/Common/fieldOf.js +7 -0
  6. package/dist/Common/isAllowedFor.d.ts +7 -0
  7. package/dist/Common/isAllowedFor.js +9 -0
  8. package/dist/Components/AuthWrapper/index.js +6 -6
  9. package/dist/Components/ConfirmationModal/index.js +3 -3
  10. package/dist/Components/Footer/index.js +1 -1
  11. package/dist/Components/Header/BugFormModal.d.ts +2 -0
  12. package/dist/Components/Header/BugFormModal.js +39 -37
  13. package/dist/Components/Header/HeaderOptions.js +80 -86
  14. package/dist/Components/Header/MenuItem.js +24 -34
  15. package/dist/Components/Header/SubHeader.js +17 -29
  16. package/dist/Components/Header/index.js +25 -13
  17. package/dist/Components/Header/submitBugReport.d.ts +15 -0
  18. package/dist/Components/Header/submitBugReport.js +23 -0
  19. package/dist/Components/NotAuthorized/index.js +1 -1
  20. package/dist/Components/Notifications/NotificationBell.js +10 -10
  21. package/dist/Components/Notifications/NotificationCard.d.ts +9 -0
  22. package/dist/Components/Notifications/NotificationCard.js +81 -0
  23. package/dist/Components/Notifications/NotificationDrawer.js +139 -191
  24. package/dist/Components/Notifications/NotificationSettings.js +32 -28
  25. package/dist/Components/Notifications/mutedEventTypes.js +9 -9
  26. package/dist/Components/Notifications/notificationText.d.ts +7 -0
  27. package/dist/Components/Notifications/notificationText.js +38 -0
  28. package/dist/Components/Paginator/index.js +22 -22
  29. package/dist/Components/ProtectedRoute/index.js +18 -18
  30. package/dist/Components/index.d.ts +1 -1
  31. package/dist/Components/index.js +10 -10
  32. package/dist/Context/AnalyticsContext.d.ts +2 -2
  33. package/dist/Context/AnalyticsContext.js +15 -15
  34. package/dist/Context/MenuContext.js +39 -47
  35. package/dist/Context/NotificationContext.d.ts +2 -14
  36. package/dist/Context/NotificationContext.js +393 -458
  37. package/dist/Context/SessionContext.js +74 -81
  38. package/dist/Context/index.d.ts +1 -1
  39. package/dist/Context/index.js +11 -11
  40. package/dist/Context/notificationAccessToken.js +13 -13
  41. package/dist/Context/notificationApi.d.ts +43 -0
  42. package/dist/Context/notificationApi.js +83 -0
  43. package/dist/Context/useNotificationState.d.ts +35 -0
  44. package/dist/Context/useNotificationState.js +92 -0
  45. package/dist/Hooks/useDebouncedValue.js +20 -16
  46. package/dist/Hooks/usePaginatedQuery.js +14 -20
  47. package/dist/Hooks/useQuery.js +6 -6
  48. package/dist/Model/ResponseModel.d.ts +2 -2
  49. package/dist/Model/ResponseModel.js +9 -4
  50. package/dist/main.js +21 -21
  51. package/package.json +19 -17
@@ -1,39 +1,27 @@
1
- import { jsx as s } from "react/jsx-runtime";
2
- import { useMemo as w } from "react";
3
- import { Navbar as h, Container as g, Nav as d } from "react-bootstrap";
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import { useMemo as m } from "react";
3
+ import { Navbar as l, Container as u, Nav as s } from "react-bootstrap";
4
+ import { isAllowedFor as c } from "../../Common/isAllowedFor.js";
4
5
  import "../../Context/AnalyticsContext.js";
5
- import { useMenu as N } from "../../Context/MenuContext.js";
6
- import { useRouter as v } from "../../Context/RouterContext.js";
7
- import { useSession as R } from "../../Context/SessionContext.js";
6
+ import { useMenu as p } from "../../Context/MenuContext.js";
8
7
  import "../../Context/NotificationContext.js";
9
- const L = () => {
10
- const { navigate: p } = v(), { subMenu: n } = N(), { user: r } = R(), t = w(() => {
11
- const l = (r == null ? void 0 : r.roles) || [], m = (r == null ? void 0 : r.permissions) || [];
12
- return n ? n.filter((o) => {
13
- var a, c;
14
- if (!((a = o == null ? void 0 : o.allowedRoles) != null && a.length) && !((c = o == null ? void 0 : o.allowedPermissions) != null && c.length))
15
- return !0;
16
- let i = !0;
17
- return o.allowedRoles && (i = i && o.allowedRoles.some(
18
- (e) => l.includes(e)
19
- )), o.allowedPermissions && (i = i && o.allowedPermissions.some(
20
- (e) => m.includes(e)
21
- )), i;
22
- }) : [];
23
- }, [n, r]), f = (l) => () => {
24
- p(l);
8
+ import { useRouter as f } from "../../Context/RouterContext.js";
9
+ import { useSession as b } from "../../Context/SessionContext.js";
10
+ const j = () => {
11
+ const { navigate: i } = f(), { subMenu: r } = p(), { user: e } = b(), n = m(() => r ? r.filter((o) => c(o, e)) : [], [r, e]), a = (o) => () => {
12
+ i(o);
25
13
  };
26
- return t.length ? /* @__PURE__ */ s(h, { className: "py-1 shadow-sm bg-white", children: /* @__PURE__ */ s(g, { children: /* @__PURE__ */ s(d, { className: "d-flex justify-content-center w-100 gap-3", children: t.map((l) => /* @__PURE__ */ s(
27
- d.Link,
14
+ return n.length === 0 ? null : /* @__PURE__ */ t(l, { className: "py-1 shadow-sm bg-white", children: /* @__PURE__ */ t(u, { children: /* @__PURE__ */ t(s, { className: "d-flex justify-content-center w-100 gap-3", children: n.map((o) => /* @__PURE__ */ t(
15
+ s.Link,
28
16
  {
29
17
  as: "button",
30
18
  className: "btn btn-link p-0",
31
- onClick: f(l.location),
32
- children: l.title
19
+ onClick: a(o.location),
20
+ children: o.title
33
21
  },
34
- l.location
35
- )) }) }) }) : null;
22
+ o.location
23
+ )) }) }) });
36
24
  };
37
25
  export {
38
- L as SubHeader
26
+ j as SubHeader
39
27
  };
@@ -3,21 +3,21 @@ import { useState as N } from "react";
3
3
  import { Navbar as a, Container as k, Nav as n } from "react-bootstrap";
4
4
  import "../../Context/AnalyticsContext.js";
5
5
  import { useMenu as w } from "../../Context/MenuContext.js";
6
+ import "../../Context/NotificationContext.js";
6
7
  import { useRouter as C } from "../../Context/RouterContext.js";
7
8
  import { useSession as S } from "../../Context/SessionContext.js";
8
- import "../../Context/NotificationContext.js";
9
- import { HeaderOptions as b } from "./HeaderOptions.js";
9
+ import { NotificationBell as b } from "../Notifications/NotificationBell.js";
10
+ import { NotificationDrawer as v } from "../Notifications/NotificationDrawer.js";
11
+ import { HeaderOptions as x } from "./HeaderOptions.js";
10
12
  import { MenuItemComponent as m } from "./MenuItem.js";
11
- import { SubHeader as v } from "./SubHeader.js";
12
- import { NotificationBell as x } from "../Notifications/NotificationBell.js";
13
- import { NotificationDrawer as D } from "../Notifications/NotificationDrawer.js";
13
+ import { SubHeader as D } from "./SubHeader.js";
14
14
  const E = ({
15
15
  logoUrl: s,
16
16
  logoAlt: l = "App logo",
17
17
  signInUrl: c,
18
18
  adminApiUrl: p
19
19
  }) => {
20
- const { items: d } = w(), { navigate: f } = C(), { isAuthenticated: r, isLoading: h } = S(), [u, t] = N(!1);
20
+ const { items: d } = w(), { navigate: f } = C(), { isAuthenticated: r, isLoading: u } = S(), [h, t] = N(!1);
21
21
  return /* @__PURE__ */ o("header", { className: "sticky-top", children: [
22
22
  /* @__PURE__ */ e(a, { bg: "dark", variant: "dark", children: /* @__PURE__ */ o(k, { fluid: !0, children: [
23
23
  /* @__PURE__ */ e(a.Brand, { onClick: () => f("/"), children: /* @__PURE__ */ e(
@@ -31,12 +31,24 @@ const E = ({
31
31
  ) }),
32
32
  /* @__PURE__ */ e(n, { className: "me-auto", children: d.map((i) => /* @__PURE__ */ e(m, { ...i }, i.title)) }),
33
33
  /* @__PURE__ */ o(n, { className: "me-5 pe-5 align-items-center", children: [
34
- r && /* @__PURE__ */ o(g, { children: [
35
- /* @__PURE__ */ e(x, { onClick: () => t(!0), className: "me-2" }),
36
- /* @__PURE__ */ e(D, { show: u, onClose: () => t(!1) })
37
- ] }),
38
- /* @__PURE__ */ e(b, { adminApiUrl: p }),
39
- !h && !r && /* @__PURE__ */ e(
34
+ r ? /* @__PURE__ */ o(g, { children: [
35
+ /* @__PURE__ */ e(
36
+ b,
37
+ {
38
+ onClick: () => t(!0),
39
+ className: "me-2"
40
+ }
41
+ ),
42
+ /* @__PURE__ */ e(
43
+ v,
44
+ {
45
+ show: h,
46
+ onClose: () => t(!1)
47
+ }
48
+ )
49
+ ] }) : null,
50
+ /* @__PURE__ */ e(x, { adminApiUrl: p }),
51
+ !u && !r && /* @__PURE__ */ e(
40
52
  m,
41
53
  {
42
54
  title: "Sign In",
@@ -46,7 +58,7 @@ const E = ({
46
58
  )
47
59
  ] })
48
60
  ] }) }),
49
- /* @__PURE__ */ e(v, {})
61
+ /* @__PURE__ */ e(D, {})
50
62
  ] });
51
63
  };
52
64
  export {
@@ -0,0 +1,15 @@
1
+ export interface BugReport {
2
+ title: string;
3
+ description: string;
4
+ category: string;
5
+ }
6
+ export interface BugReportSender {
7
+ adminApiUrl: string;
8
+ reporterEmail?: string;
9
+ authToken?: string | null;
10
+ fetchImpl?: typeof fetch;
11
+ }
12
+ /** The bug route, next to the versioned API: ".../v1" and ".../" give "/bugs". */
13
+ export declare const bugReportUrl: (adminApiUrl: string) => string;
14
+ /** Sends the report; resolves to null once sent, or to the message to show. */
15
+ export declare function submitBugReport(report: BugReport, file: File | undefined, { adminApiUrl, reporterEmail, authToken, fetchImpl }: BugReportSender): Promise<string | null>;
@@ -0,0 +1,23 @@
1
+ import { fieldOf as p } from "../../Common/fieldOf.js";
2
+ const c = "Failed to submit bug. Please try again.", u = (t) => `${t.replace(/\/v1$/, "").replace(/\/$/, "")}/bugs`;
3
+ async function f(t, a, { adminApiUrl: d, reporterEmail: n, authToken: i, fetchImpl: l = fetch }) {
4
+ const e = new FormData();
5
+ e.append("title", t.title), e.append("description", t.description), e.append("priority", "medium"), e.append("category", t.category), n && e.append("reporterEmail", n), a && e.append("file", a);
6
+ try {
7
+ const r = await l(u(d), {
8
+ method: "POST",
9
+ headers: i ? { Authorization: `Bearer ${i}` } : {},
10
+ body: e,
11
+ credentials: "include"
12
+ }), s = await r.json();
13
+ if (r.ok && !p(s, "errorCode")) return null;
14
+ const o = p(s, "message");
15
+ return typeof o == "string" && o !== "" ? o : c;
16
+ } catch (r) {
17
+ return console.error(r), c;
18
+ }
19
+ }
20
+ export {
21
+ u as bugReportUrl,
22
+ f as submitBugReport
23
+ };
@@ -2,9 +2,9 @@ import { jsxs as o, jsx as t } from "react/jsx-runtime";
2
2
  import { Container as i, Button as n } from "react-bootstrap";
3
3
  import "../../Context/AnalyticsContext.js";
4
4
  import "../../Context/MenuContext.js";
5
+ import "../../Context/NotificationContext.js";
5
6
  import { useRouter as a } from "../../Context/RouterContext.js";
6
7
  import "../../Context/SessionContext.js";
7
- import "../../Context/NotificationContext.js";
8
8
  const h = ({ homePath: e }) => {
9
9
  const { navigate: r } = a();
10
10
  return /* @__PURE__ */ o(i, { className: "d-flex flex-column justify-content-center align-items-center vh-100 text-center", children: [
@@ -1,32 +1,32 @@
1
1
  import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
- import { Button as a, Badge as n } from "react-bootstrap";
2
+ import { Button as n, Badge as a } from "react-bootstrap";
3
3
  import { Bell as l } from "react-bootstrap-icons";
4
4
  import { useNotifications as s } from "../../Context/NotificationContext.js";
5
5
  const f = ({
6
- onClick: o,
7
- className: i = ""
6
+ onClick: i,
7
+ className: o = ""
8
8
  }) => {
9
9
  const { unreadCount: t } = s();
10
10
  return /* @__PURE__ */ r(
11
- a,
11
+ n,
12
12
  {
13
13
  variant: "link",
14
- onClick: o,
15
- className: `position-relative p-2 text-light ${i}`,
14
+ onClick: i,
15
+ className: `position-relative p-2 text-light ${o}`,
16
16
  "aria-label": "Notifications",
17
17
  style: { boxShadow: "none" },
18
18
  children: [
19
19
  /* @__PURE__ */ e(l, { size: 22 }),
20
- t > 0 && /* @__PURE__ */ e(
21
- n,
20
+ t > 0 ? /* @__PURE__ */ e(
21
+ a,
22
22
  {
23
23
  pill: !0,
24
24
  bg: "danger",
25
25
  className: "position-absolute translate-middle-y start-50 top-0 border border-white",
26
26
  style: { fontSize: "0.65rem", padding: "0.25em 0.5em" },
27
- children: t > 99 ? "99+" : t
27
+ children: t > 99 ? "99+" : String(t)
28
28
  }
29
- )
29
+ ) : null
30
30
  ]
31
31
  }
32
32
  );
@@ -0,0 +1,9 @@
1
+ import { FC } from 'react';
2
+ import { NotificationItem } from '../../Context/notificationApi';
3
+ export interface NotificationCardProps {
4
+ item: NotificationItem;
5
+ inInbox: boolean;
6
+ onMarkAsRead: (id: string) => void;
7
+ onDelete: (id: string) => void;
8
+ }
9
+ export declare const NotificationCard: FC<NotificationCardProps>;
@@ -0,0 +1,81 @@
1
+ import { jsx as e, jsxs as s } from "react/jsx-runtime";
2
+ import { Button as n } from "react-bootstrap";
3
+ import { CircleFill as h, Trash as u } from "react-bootstrap-icons";
4
+ import { notificationTextOf as g } from "./notificationText.js";
5
+ const x = (t) => new Date(t).toLocaleDateString(void 0, {
6
+ hour: "2-digit",
7
+ minute: "2-digit"
8
+ }), a = { boxShadow: "none" }, v = ({
9
+ item: t,
10
+ inInbox: o,
11
+ onMarkAsRead: d,
12
+ onDelete: c
13
+ }) => {
14
+ const { title: m, body: f } = g(t), r = o && !t.isRead;
15
+ return /* @__PURE__ */ e(
16
+ "div",
17
+ {
18
+ className: `p-3 mb-2 rounded border shadow-sm ${r ? "bg-white border-primary-subtle" : "bg-white border-light"}`,
19
+ style: {
20
+ transition: "all 0.2s ease-in-out",
21
+ borderLeft: r ? "4px solid #0d6efd" : "1px solid #dee2e6"
22
+ },
23
+ children: /* @__PURE__ */ s("div", { className: "d-flex justify-content-between align-items-start", children: [
24
+ /* @__PURE__ */ s("div", { className: "pe-2 flex-grow-1", children: [
25
+ /* @__PURE__ */ e(
26
+ "h6",
27
+ {
28
+ className: `mb-1 ${r ? "fw-bold text-dark" : "text-secondary fw-semibold"}`,
29
+ style: { fontSize: "0.9rem", lineHeight: "1.25" },
30
+ children: m
31
+ }
32
+ ),
33
+ /* @__PURE__ */ e(
34
+ "p",
35
+ {
36
+ className: "mb-2 text-muted",
37
+ style: { fontSize: "0.8rem", color: "#6c757d", lineHeight: "1.3" },
38
+ children: f
39
+ }
40
+ ),
41
+ /* @__PURE__ */ e("span", { className: "text-muted d-block", style: { fontSize: "0.7rem" }, children: x(t.createdAt) })
42
+ ] }),
43
+ /* @__PURE__ */ s("div", { className: "d-flex align-items-center gap-2", children: [
44
+ r ? /* @__PURE__ */ e(
45
+ n,
46
+ {
47
+ variant: "link",
48
+ className: "p-1 text-primary border-0 d-flex align-items-center",
49
+ onClick: () => d(t.id),
50
+ title: "Mark as read",
51
+ style: a,
52
+ children: /* @__PURE__ */ e(h, { size: 8, className: "text-primary" })
53
+ }
54
+ ) : null,
55
+ o ? /* @__PURE__ */ e(
56
+ n,
57
+ {
58
+ variant: "link",
59
+ className: "p-1 text-secondary border-0 d-flex align-items-center",
60
+ onClick: () => c(t.id),
61
+ title: "Move to trash",
62
+ style: a,
63
+ onMouseEnter: (l) => {
64
+ const i = l.currentTarget.querySelector("svg");
65
+ i && (i.style.fill = "#dc3545");
66
+ },
67
+ onMouseLeave: (l) => {
68
+ const i = l.currentTarget.querySelector("svg");
69
+ i && (i.style.fill = "currentColor");
70
+ },
71
+ children: /* @__PURE__ */ e(u, { size: 14, style: { transition: "fill 0.2s" } })
72
+ }
73
+ ) : null
74
+ ] })
75
+ ] })
76
+ }
77
+ );
78
+ };
79
+ export {
80
+ v as NotificationCard
81
+ };