@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.
- package/README.md +27 -42
- package/dist/Common/Events.d.ts +3 -2
- package/dist/Common/Events.js +18 -11
- package/dist/Common/fieldOf.d.ts +2 -0
- package/dist/Common/fieldOf.js +7 -0
- package/dist/Common/isAllowedFor.d.ts +7 -0
- package/dist/Common/isAllowedFor.js +9 -0
- package/dist/Components/AuthWrapper/index.js +6 -6
- package/dist/Components/ConfirmationModal/index.js +3 -3
- package/dist/Components/Footer/index.js +1 -1
- package/dist/Components/Header/BugFormModal.d.ts +2 -0
- package/dist/Components/Header/BugFormModal.js +39 -37
- package/dist/Components/Header/HeaderOptions.js +80 -86
- package/dist/Components/Header/MenuItem.js +24 -34
- package/dist/Components/Header/SubHeader.js +17 -29
- package/dist/Components/Header/index.js +25 -13
- package/dist/Components/Header/submitBugReport.d.ts +15 -0
- package/dist/Components/Header/submitBugReport.js +23 -0
- package/dist/Components/NotAuthorized/index.js +1 -1
- package/dist/Components/Notifications/NotificationBell.js +10 -10
- package/dist/Components/Notifications/NotificationCard.d.ts +9 -0
- package/dist/Components/Notifications/NotificationCard.js +81 -0
- package/dist/Components/Notifications/NotificationDrawer.js +139 -191
- package/dist/Components/Notifications/NotificationSettings.js +32 -28
- package/dist/Components/Notifications/mutedEventTypes.js +9 -9
- package/dist/Components/Notifications/notificationText.d.ts +7 -0
- package/dist/Components/Notifications/notificationText.js +38 -0
- package/dist/Components/Paginator/index.js +22 -22
- package/dist/Components/ProtectedRoute/index.js +18 -18
- package/dist/Components/index.d.ts +1 -1
- package/dist/Components/index.js +10 -10
- package/dist/Context/AnalyticsContext.d.ts +2 -2
- package/dist/Context/AnalyticsContext.js +15 -15
- package/dist/Context/MenuContext.js +39 -47
- package/dist/Context/NotificationContext.d.ts +2 -14
- package/dist/Context/NotificationContext.js +393 -458
- package/dist/Context/SessionContext.js +74 -81
- package/dist/Context/index.d.ts +1 -1
- package/dist/Context/index.js +11 -11
- package/dist/Context/notificationAccessToken.js +13 -13
- package/dist/Context/notificationApi.d.ts +43 -0
- package/dist/Context/notificationApi.js +83 -0
- package/dist/Context/useNotificationState.d.ts +35 -0
- package/dist/Context/useNotificationState.js +92 -0
- package/dist/Hooks/useDebouncedValue.js +20 -16
- package/dist/Hooks/usePaginatedQuery.js +14 -20
- package/dist/Hooks/useQuery.js +6 -6
- package/dist/Model/ResponseModel.d.ts +2 -2
- package/dist/Model/ResponseModel.js +9 -4
- package/dist/main.js +21 -21
- package/package.json +19 -17
package/README.md
CHANGED
|
@@ -1,50 +1,35 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @variamosple/variamos-components
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components and contexts shared by the VariaMos front ends: the session, the menu, the header with its user menu and bug report form, the notification bell and drawer, and a few page helpers (paginator, protected route, confirmation modal).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install @variamosple/variamos-components
|
|
9
|
+
```
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
Peer dependencies: `react` and `react-dom` 18 or 19, `react-bootstrap` 2, `react-bootstrap-icons` 1.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
```tsx
|
|
14
|
+
import { Header, SessionProvider } from "@variamosple/variamos-components";
|
|
15
|
+
```
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
The user menu of the header has the class `variamos-header-options`; its id is generated, so tests and styles should use the class.
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
export default tseslint.config({
|
|
18
|
-
languageOptions: {
|
|
19
|
-
// other options...
|
|
20
|
-
parserOptions: {
|
|
21
|
-
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
22
|
-
tsconfigRootDir: import.meta.dirname,
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
})
|
|
26
|
-
```
|
|
19
|
+
## Development
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
rules: {
|
|
44
|
-
// other rules...
|
|
45
|
-
// Enable its recommended rules
|
|
46
|
-
...react.configs.recommended.rules,
|
|
47
|
-
...react.configs['jsx-runtime'].rules,
|
|
48
|
-
},
|
|
49
|
-
})
|
|
50
|
-
```
|
|
21
|
+
Requires Node 26 (`.nvmrc`, `.mise.toml`). `npm install` sets up the Git hooks: Biome and cspell on the staged files before a commit, the conventional commit format, and typecheck, lint and tests before a push.
|
|
22
|
+
|
|
23
|
+
| Command | What it does |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `npm run dev` | Demo page (`src/`), built from the library sources |
|
|
26
|
+
| `npm run typecheck` | Types of the library, the demo and the Vite configuration |
|
|
27
|
+
| `npm run lint` | Biome (shared configuration of the VariaMos admin module) and the check that no rule is silenced in a comment |
|
|
28
|
+
| `npm run format` | Formats the code with Biome |
|
|
29
|
+
| `npm run spell` | Spelling (cspell) |
|
|
30
|
+
| `npm run find-deadcode` | Unused files, exports and dependencies (knip) |
|
|
31
|
+
| `npm test` | Unit tests (Vitest) |
|
|
32
|
+
| `npm run build` | Builds `dist/` |
|
|
33
|
+
| `npm run check-package` | What `npm pack` would publish, then publint |
|
|
34
|
+
|
|
35
|
+
The CI runs the same commands on every pull request. The package is published to npm by hand.
|
package/dist/Common/Events.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
declare function
|
|
1
|
+
type Listener<T> = (event: CustomEvent<T>) => void;
|
|
2
|
+
declare function subscribe<T>(eventName: string, listener: Listener<T>): void;
|
|
3
|
+
declare function unsubscribe<T>(eventName: string, listener: Listener<T>): void;
|
|
3
4
|
declare function publish<T>(eventName: string, data: T): void;
|
|
4
5
|
export declare const Events: Readonly<{
|
|
5
6
|
subscribe: typeof subscribe;
|
package/dist/Common/Events.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const o = /* @__PURE__ */ new WeakMap();
|
|
2
|
+
function s(t) {
|
|
3
|
+
let e = o.get(t);
|
|
4
|
+
return e || (e = (n) => {
|
|
5
|
+
n instanceof CustomEvent && t(n);
|
|
6
|
+
}, o.set(t, e)), e;
|
|
3
7
|
}
|
|
4
|
-
function
|
|
5
|
-
document.
|
|
8
|
+
function c(t, e) {
|
|
9
|
+
document.addEventListener(t, s(e));
|
|
6
10
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
document.dispatchEvent(t);
|
|
11
|
+
function i(t, e) {
|
|
12
|
+
document.removeEventListener(t, s(e));
|
|
10
13
|
}
|
|
11
|
-
|
|
14
|
+
function u(t, e) {
|
|
15
|
+
const n = new CustomEvent(t, { detail: e });
|
|
16
|
+
document.dispatchEvent(n);
|
|
17
|
+
}
|
|
18
|
+
const d = Object.freeze({
|
|
12
19
|
subscribe: c,
|
|
13
|
-
unsubscribe:
|
|
14
|
-
publish:
|
|
20
|
+
unsubscribe: i,
|
|
21
|
+
publish: u
|
|
15
22
|
});
|
|
16
23
|
export {
|
|
17
|
-
|
|
24
|
+
d as Events
|
|
18
25
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MenuItemBase, SessionUser } from '../Model';
|
|
2
|
+
/**
|
|
3
|
+
* Whether the user may see a menu entry: an entry without roles nor
|
|
4
|
+
* permissions is for everyone; otherwise the user needs one of the roles
|
|
5
|
+
* listed and one of the permissions listed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isAllowedFor(item: Pick<MenuItemBase, "allowedRoles" | "allowedPermissions">, user: Pick<SessionUser, "roles" | "permissions"> | null | undefined): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
function m(s, n) {
|
|
2
|
+
const { allowedRoles: o, allowedPermissions: t } = s;
|
|
3
|
+
if (!(o != null && o.length) && !(t != null && t.length)) return !0;
|
|
4
|
+
const c = (n == null ? void 0 : n.roles) ?? [], e = (n == null ? void 0 : n.permissions) ?? [], h = !o || o.some((i) => c.includes(i)), l = !t || t.some((i) => e.includes(i));
|
|
5
|
+
return h && l;
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
m as isAllowedFor
|
|
9
|
+
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsx as o, Fragment as f } from "react/jsx-runtime";
|
|
2
|
-
import p,
|
|
2
|
+
import { useState as p, useEffect as m } from "react";
|
|
3
3
|
import { Spinner as h } from "react-bootstrap";
|
|
4
4
|
import "../../Context/AnalyticsContext.js";
|
|
5
5
|
import "../../Context/MenuContext.js";
|
|
6
|
-
import { useRouter as u } from "../../Context/RouterContext.js";
|
|
7
|
-
import { useSession as g } from "../../Context/SessionContext.js";
|
|
8
6
|
import "../../Context/NotificationContext.js";
|
|
9
|
-
import {
|
|
7
|
+
import { useRouter as u } from "../../Context/RouterContext.js";
|
|
8
|
+
import { useSession as l } from "../../Context/SessionContext.js";
|
|
9
|
+
import { addressWithoutToken as w } from "./addressWithoutToken.js";
|
|
10
10
|
const j = ({
|
|
11
11
|
redirectPath: i,
|
|
12
12
|
children: c
|
|
13
13
|
}) => {
|
|
14
|
-
const [n, d] = p
|
|
14
|
+
const [n, d] = p(!1), { isAuthenticated: t, isLoading: r } = l(), { navigate: s } = u();
|
|
15
15
|
return m(() => {
|
|
16
16
|
if (!r && !t && !n) {
|
|
17
17
|
const e = window.location.href, a = new URLSearchParams();
|
|
@@ -21,7 +21,7 @@ const j = ({
|
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
}, [t, r, i, s, n]), m(() => {
|
|
24
|
-
const e =
|
|
24
|
+
const e = w(window.location.href);
|
|
25
25
|
e && window.history.replaceState({}, "", e);
|
|
26
26
|
}, []), r || !t ? /* @__PURE__ */ o("div", { className: "d-flex justify-content-center align-items-center w-100 h-100", children: /* @__PURE__ */ o(
|
|
27
27
|
h,
|
|
@@ -13,8 +13,8 @@ function u({
|
|
|
13
13
|
onCancel: r,
|
|
14
14
|
onConfirm: t,
|
|
15
15
|
message: c,
|
|
16
|
-
confirmLabel:
|
|
17
|
-
confirmButtonVariant:
|
|
16
|
+
confirmLabel: d = "Accept",
|
|
17
|
+
confirmButtonVariant: l = "primary",
|
|
18
18
|
cancelButtonVariant: s = "secondary",
|
|
19
19
|
cancelLabel: f = "Cancel"
|
|
20
20
|
}) {
|
|
@@ -22,7 +22,7 @@ function u({
|
|
|
22
22
|
/* @__PURE__ */ o(n.Body, { children: c }),
|
|
23
23
|
/* @__PURE__ */ e(n.Footer, { children: [
|
|
24
24
|
/* @__PURE__ */ o(i, { variant: s, onClick: r, children: f }),
|
|
25
|
-
/* @__PURE__ */ o(i, { variant:
|
|
25
|
+
/* @__PURE__ */ o(i, { variant: l, onClick: t, children: d })
|
|
26
26
|
] })
|
|
27
27
|
] });
|
|
28
28
|
}
|
|
@@ -4,7 +4,7 @@ import '../../assets/index.css';const e = "_footer_cvhpi_1", s = {
|
|
|
4
4
|
}, i = ({ version: o = "" }) => /* @__PURE__ */ r("footer", { className: `container-fluid ${s.footer}`, children: /* @__PURE__ */ r("div", { className: "row copyright", children: /* @__PURE__ */ t("p", { className: "mb-0", children: [
|
|
5
5
|
"©",
|
|
6
6
|
" Copyright 2023 VariaMos.",
|
|
7
|
-
o
|
|
7
|
+
o ? ` ${o}` : null
|
|
8
8
|
] }) }) });
|
|
9
9
|
export {
|
|
10
10
|
i as Footer
|
|
@@ -9,6 +9,8 @@ interface BugFormModalProps {
|
|
|
9
9
|
}, file?: File) => void;
|
|
10
10
|
categories: string[];
|
|
11
11
|
isSubmitting: boolean;
|
|
12
|
+
/** Why the last submission failed, shown above the form. */
|
|
13
|
+
errorMessage?: string | null;
|
|
12
14
|
}
|
|
13
15
|
export declare const BugFormModal: FC<BugFormModalProps>;
|
|
14
16
|
export {};
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import { jsxs as l, jsx as
|
|
2
|
-
import { useState as a, useEffect as
|
|
3
|
-
import { Modal as o, Form as t, Button as y } from "react-bootstrap";
|
|
4
|
-
const
|
|
1
|
+
import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useState as a, useEffect as N } from "react";
|
|
3
|
+
import { Modal as o, Form as t, Alert as k, Button as y } from "react-bootstrap";
|
|
4
|
+
const G = ({
|
|
5
5
|
show: i,
|
|
6
6
|
onHide: d,
|
|
7
7
|
onSubmit: C,
|
|
8
8
|
categories: n,
|
|
9
|
-
isSubmitting: c
|
|
9
|
+
isSubmitting: c,
|
|
10
|
+
errorMessage: s
|
|
10
11
|
}) => {
|
|
11
|
-
const [
|
|
12
|
-
|
|
13
|
-
i && (
|
|
12
|
+
const [u, h] = a(""), [p, m] = a(""), [g, b] = a(""), [F, f] = a(null), [x, v] = a(!1);
|
|
13
|
+
N(() => {
|
|
14
|
+
i && (h(""), m(""), b(n[0] || "Other"), f(null), v(!1));
|
|
14
15
|
}, [i, n]);
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
17
|
-
|
|
16
|
+
const B = (r) => {
|
|
17
|
+
if (r.preventDefault(), r.currentTarget.checkValidity() === !1) {
|
|
18
|
+
r.stopPropagation(), v(!0);
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
|
-
C({ title:
|
|
21
|
+
C({ title: u, description: p, category: g }, F ?? void 0);
|
|
21
22
|
};
|
|
22
23
|
return /* @__PURE__ */ l(
|
|
23
24
|
o,
|
|
@@ -28,67 +29,68 @@ const q = ({
|
|
|
28
29
|
keyboard: !1,
|
|
29
30
|
centered: !0,
|
|
30
31
|
children: [
|
|
31
|
-
/* @__PURE__ */
|
|
32
|
-
/* @__PURE__ */ l(t, { noValidate: !0, validated:
|
|
32
|
+
/* @__PURE__ */ e(o.Header, { closeButton: !0, children: /* @__PURE__ */ e(o.Title, { children: "Report a New Bug" }) }),
|
|
33
|
+
/* @__PURE__ */ l(t, { noValidate: !0, validated: x, onSubmit: B, children: [
|
|
33
34
|
/* @__PURE__ */ l(o.Body, { children: [
|
|
35
|
+
s ? /* @__PURE__ */ e(k, { variant: "danger", role: "alert", children: s }) : null,
|
|
34
36
|
/* @__PURE__ */ l(t.Group, { className: "mb-3", controlId: "bugTitle", children: [
|
|
35
|
-
/* @__PURE__ */
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ e(t.Label, { children: "Title *" }),
|
|
38
|
+
/* @__PURE__ */ e(
|
|
37
39
|
t.Control,
|
|
38
40
|
{
|
|
39
41
|
required: !0,
|
|
40
42
|
type: "text",
|
|
41
43
|
placeholder: "e.g. Build error on auth routes",
|
|
42
|
-
value:
|
|
43
|
-
onChange: (
|
|
44
|
+
value: u,
|
|
45
|
+
onChange: (r) => h(r.target.value),
|
|
44
46
|
maxLength: 100
|
|
45
47
|
}
|
|
46
48
|
),
|
|
47
|
-
/* @__PURE__ */
|
|
49
|
+
/* @__PURE__ */ e(t.Control.Feedback, { type: "invalid", children: "Title is required (max 100 characters)" })
|
|
48
50
|
] }),
|
|
49
51
|
/* @__PURE__ */ l(t.Group, { className: "mb-3", controlId: "bugDescription", children: [
|
|
50
|
-
/* @__PURE__ */
|
|
51
|
-
/* @__PURE__ */
|
|
52
|
+
/* @__PURE__ */ e(t.Label, { children: "Description *" }),
|
|
53
|
+
/* @__PURE__ */ e(
|
|
52
54
|
t.Control,
|
|
53
55
|
{
|
|
54
56
|
required: !0,
|
|
55
57
|
as: "textarea",
|
|
56
58
|
rows: 4,
|
|
57
59
|
placeholder: "Describe step-by-step how to reproduce the bug...",
|
|
58
|
-
value:
|
|
59
|
-
onChange: (
|
|
60
|
+
value: p,
|
|
61
|
+
onChange: (r) => m(r.target.value)
|
|
60
62
|
}
|
|
61
63
|
),
|
|
62
|
-
/* @__PURE__ */
|
|
64
|
+
/* @__PURE__ */ e(t.Control.Feedback, { type: "invalid", children: "Description is required" })
|
|
63
65
|
] }),
|
|
64
|
-
/* @__PURE__ */
|
|
65
|
-
/* @__PURE__ */
|
|
66
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ e("div", { className: "row", children: /* @__PURE__ */ e("div", { className: "col-md-12", children: /* @__PURE__ */ l(t.Group, { className: "mb-3", controlId: "bugCategory", children: [
|
|
67
|
+
/* @__PURE__ */ e(t.Label, { children: "Category *" }),
|
|
68
|
+
/* @__PURE__ */ e(
|
|
67
69
|
t.Select,
|
|
68
70
|
{
|
|
69
71
|
required: !0,
|
|
70
|
-
value:
|
|
71
|
-
onChange: (
|
|
72
|
-
children: n.map((
|
|
72
|
+
value: g,
|
|
73
|
+
onChange: (r) => b(r.target.value),
|
|
74
|
+
children: n.map((r) => /* @__PURE__ */ e("option", { value: r, children: r }, r))
|
|
73
75
|
}
|
|
74
76
|
)
|
|
75
77
|
] }) }) }),
|
|
76
78
|
/* @__PURE__ */ l(t.Group, { className: "mb-3", controlId: "bugFile", children: [
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ e(t.Label, { children: "Attachment (Optional)" }),
|
|
80
|
+
/* @__PURE__ */ e(
|
|
79
81
|
t.Control,
|
|
80
82
|
{
|
|
81
83
|
type: "file",
|
|
82
|
-
onChange: (
|
|
83
|
-
|
|
84
|
+
onChange: (r) => {
|
|
85
|
+
r.target.files && r.target.files.length > 0 && f(r.target.files[0]);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
)
|
|
87
89
|
] })
|
|
88
90
|
] }),
|
|
89
91
|
/* @__PURE__ */ l(o.Footer, { children: [
|
|
90
|
-
/* @__PURE__ */
|
|
91
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ e(y, { variant: "secondary", onClick: d, disabled: c, children: "Cancel" }),
|
|
93
|
+
/* @__PURE__ */ e(y, { variant: "primary", type: "submit", disabled: c, children: c ? "Creating..." : "Report Bug" })
|
|
92
94
|
] })
|
|
93
95
|
] })
|
|
94
96
|
]
|
|
@@ -96,5 +98,5 @@ const q = ({
|
|
|
96
98
|
);
|
|
97
99
|
};
|
|
98
100
|
export {
|
|
99
|
-
|
|
101
|
+
G as BugFormModal
|
|
100
102
|
};
|
|
@@ -1,96 +1,90 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { NavDropdown as
|
|
1
|
+
import { jsxs as f, Fragment as T, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useId as k, useState as m, useCallback as v, useEffect as C, useMemo as O } from "react";
|
|
3
|
+
import { NavDropdown as i } from "react-bootstrap";
|
|
4
|
+
import { Events as h } from "../../Common/Events.js";
|
|
5
|
+
import { isAllowedFor as U } from "../../Common/isAllowedFor.js";
|
|
4
6
|
import "../../Context/AnalyticsContext.js";
|
|
5
|
-
import { useMenu as
|
|
6
|
-
import { useRouter as b } from "../../Context/RouterContext.js";
|
|
7
|
-
import { useSession as x } from "../../Context/SessionContext.js";
|
|
7
|
+
import { useMenu as j } from "../../Context/MenuContext.js";
|
|
8
8
|
import "../../Context/NotificationContext.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
y.unsubscribe("openReportBugModal", t);
|
|
28
|
-
};
|
|
9
|
+
import { useRouter as x } from "../../Context/RouterContext.js";
|
|
10
|
+
import { useSession as D } from "../../Context/SessionContext.js";
|
|
11
|
+
import { mapToWebTarget as F } from "../../Model/Router.js";
|
|
12
|
+
import { BugFormModal as L } from "./BugFormModal.js";
|
|
13
|
+
import { submitBugReport as N } from "./submitBugReport.js";
|
|
14
|
+
const c = {}, y = [
|
|
15
|
+
"Editor",
|
|
16
|
+
"Model",
|
|
17
|
+
"Language",
|
|
18
|
+
"Project",
|
|
19
|
+
"Simulation",
|
|
20
|
+
"Account/Security",
|
|
21
|
+
"Other"
|
|
22
|
+
], $ = ({
|
|
23
|
+
adminApiUrl: b
|
|
24
|
+
}) => {
|
|
25
|
+
const { user: o, isAuthenticated: n, logout: S } = D(), { options: d } = j(), { navigate: M } = x(), I = k(), [B, s] = m(!1), [E, p] = m(!1), [A, l] = m(null), w = b || (c == null ? void 0 : c.VITE_ADMIN_API_URL) || "/v1", e = v(() => {
|
|
26
|
+
l(null), s(!0);
|
|
29
27
|
}, []);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return l != null && l.length ? l.filter((e) => {
|
|
52
|
-
var s, n;
|
|
53
|
-
if (!((s = e == null ? void 0 : e.allowedPermissions) != null && s.length) && !((n = e == null ? void 0 : e.allowedRoles) != null && n.length))
|
|
54
|
-
return !0;
|
|
55
|
-
let r = !0;
|
|
56
|
-
return e.allowedRoles && (r = r && e.allowedRoles.some((a) => d.includes(a))), e.allowedPermissions && (r = r && e.allowedPermissions.some(
|
|
57
|
-
(a) => t.includes(a)
|
|
58
|
-
)), r;
|
|
59
|
-
}) : [];
|
|
60
|
-
}, [l, o]);
|
|
61
|
-
return !(i != null && i.length) && !m ? null : /* @__PURE__ */ S(F, { children: [
|
|
62
|
-
/* @__PURE__ */ S(g, { title: (o == null ? void 0 : o.name) || "Options", id: "nav-dropdown", children: [
|
|
63
|
-
i == null ? void 0 : i.map((t) => /* @__PURE__ */ p(
|
|
64
|
-
g.Item,
|
|
65
|
-
{
|
|
66
|
-
onClick: () => {
|
|
67
|
-
if (t.location.endsWith("#report-bug")) {
|
|
68
|
-
c(!0);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
A(t.location, {
|
|
72
|
-
target: L(t.target)
|
|
73
|
-
});
|
|
74
|
-
},
|
|
75
|
-
children: t.title
|
|
76
|
-
},
|
|
77
|
-
t.title
|
|
78
|
-
)),
|
|
79
|
-
m && !!(i != null && i.length) && /* @__PURE__ */ p(g.Divider, {}),
|
|
80
|
-
m && /* @__PURE__ */ p(g.Item, { onClick: P, children: "Logout" })
|
|
81
|
-
] }),
|
|
82
|
-
/* @__PURE__ */ p(
|
|
83
|
-
U,
|
|
28
|
+
C(() => (h.subscribe("openReportBugModal", e), () => {
|
|
29
|
+
h.unsubscribe(
|
|
30
|
+
"openReportBugModal",
|
|
31
|
+
e
|
|
32
|
+
);
|
|
33
|
+
}), [e]);
|
|
34
|
+
const R = async (t, u) => {
|
|
35
|
+
p(!0), l(null);
|
|
36
|
+
const g = await N(t, u, {
|
|
37
|
+
adminApiUrl: w,
|
|
38
|
+
reporterEmail: o == null ? void 0 : o.email,
|
|
39
|
+
authToken: localStorage.getItem("authToken")
|
|
40
|
+
});
|
|
41
|
+
p(!1), g ? l(g) : s(!1);
|
|
42
|
+
}, a = O(
|
|
43
|
+
() => (d ?? []).filter((t) => U(t, o)),
|
|
44
|
+
[d, o]
|
|
45
|
+
);
|
|
46
|
+
return a.length === 0 && !n ? null : /* @__PURE__ */ f(T, { children: [
|
|
47
|
+
/* @__PURE__ */ f(
|
|
48
|
+
i,
|
|
84
49
|
{
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
50
|
+
title: (o == null ? void 0 : o.name) || "Options",
|
|
51
|
+
id: I,
|
|
52
|
+
className: "variamos-header-options",
|
|
53
|
+
children: [
|
|
54
|
+
a.map((t) => /* @__PURE__ */ r(
|
|
55
|
+
i.Item,
|
|
56
|
+
{
|
|
57
|
+
onClick: () => {
|
|
58
|
+
if (t.location.endsWith("#report-bug")) {
|
|
59
|
+
e();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
M(t.location, {
|
|
63
|
+
target: F(t.target)
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
children: t.title
|
|
67
|
+
},
|
|
68
|
+
t.title
|
|
69
|
+
)),
|
|
70
|
+
n && a.length > 0 ? /* @__PURE__ */ r(i.Divider, {}) : null,
|
|
71
|
+
n ? /* @__PURE__ */ r(i.Item, { onClick: S, children: "Logout" }) : null
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
/* @__PURE__ */ r(
|
|
76
|
+
L,
|
|
77
|
+
{
|
|
78
|
+
show: B,
|
|
79
|
+
onHide: () => s(!1),
|
|
80
|
+
onSubmit: (t, u) => void R(t, u),
|
|
81
|
+
categories: y,
|
|
82
|
+
isSubmitting: E,
|
|
83
|
+
errorMessage: A
|
|
90
84
|
}
|
|
91
85
|
)
|
|
92
86
|
] });
|
|
93
87
|
};
|
|
94
88
|
export {
|
|
95
|
-
|
|
89
|
+
$ as HeaderOptions
|
|
96
90
|
};
|
|
@@ -1,51 +1,41 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useMemo as
|
|
3
|
-
import { Nav as
|
|
1
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as c } from "react";
|
|
3
|
+
import { Nav as g, NavDropdown as p } from "react-bootstrap";
|
|
4
|
+
import { isAllowedFor as k } from "../../Common/isAllowedFor.js";
|
|
4
5
|
import "../../Context/AnalyticsContext.js";
|
|
5
6
|
import "../../Context/MenuContext.js";
|
|
6
|
-
import { useRouter as C } from "../../Context/RouterContext.js";
|
|
7
|
-
import { useSession as N } from "../../Context/SessionContext.js";
|
|
8
7
|
import "../../Context/NotificationContext.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
import { useRouter as u } from "../../Context/RouterContext.js";
|
|
9
|
+
import { useSession as d } from "../../Context/SessionContext.js";
|
|
10
|
+
import { mapToWebTarget as s } from "../../Model/Router.js";
|
|
11
|
+
const D = ({
|
|
12
|
+
title: n,
|
|
13
|
+
type: f,
|
|
14
|
+
location: e,
|
|
15
|
+
target: l,
|
|
15
16
|
children: t
|
|
16
17
|
}) => {
|
|
17
|
-
const { user:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var c, f;
|
|
21
|
-
if (!((c = o == null ? void 0 : o.allowedPermissions) != null && c.length) && !((f = o == null ? void 0 : o.allowedRoles) != null && f.length))
|
|
22
|
-
return !0;
|
|
23
|
-
let l = !0;
|
|
24
|
-
return o.allowedRoles && (l = l && o.allowedRoles.some((n) => R.includes(n))), o.allowedPermissions && (l = l && o.allowedPermissions.some(
|
|
25
|
-
(n) => i.includes(n)
|
|
26
|
-
)), l;
|
|
27
|
-
}) : [];
|
|
28
|
-
}, [t, r]);
|
|
29
|
-
return w === "location" ? /* @__PURE__ */ s(
|
|
30
|
-
v.Link,
|
|
18
|
+
const { user: m } = d(), { navigate: a } = u(), r = c(() => t ? t.filter((o) => k(o, m)) : [], [t, m]);
|
|
19
|
+
return f === "location" && e ? /* @__PURE__ */ i(
|
|
20
|
+
g.Link,
|
|
31
21
|
{
|
|
32
22
|
as: "button",
|
|
33
23
|
className: "btn btn-link",
|
|
34
|
-
onClick: () =>
|
|
35
|
-
children:
|
|
24
|
+
onClick: () => a(e, { target: s(l) }),
|
|
25
|
+
children: n
|
|
36
26
|
}
|
|
37
|
-
) : /* @__PURE__ */
|
|
38
|
-
|
|
27
|
+
) : /* @__PURE__ */ i(p, { title: n, children: r == null ? void 0 : r.map((o) => /* @__PURE__ */ i(
|
|
28
|
+
p.Item,
|
|
39
29
|
{
|
|
40
30
|
as: "button",
|
|
41
|
-
onClick: () =>
|
|
42
|
-
target:
|
|
31
|
+
onClick: () => a(o.location, {
|
|
32
|
+
target: s(o.target)
|
|
43
33
|
}),
|
|
44
|
-
children:
|
|
34
|
+
children: o.title
|
|
45
35
|
},
|
|
46
|
-
|
|
36
|
+
o.title
|
|
47
37
|
)) });
|
|
48
38
|
};
|
|
49
39
|
export {
|
|
50
|
-
|
|
40
|
+
D as MenuItemComponent
|
|
51
41
|
};
|