@burdenoff/microfe-organization 2026.527.3 → 2026.527.5
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/generated/global-types.js +3 -1
- package/dist/generated/global-types.js.map +1 -1
- package/dist/organization-management/UserOrganizationRoot.js +39 -28
- package/dist/organization-management/UserOrganizationRoot.js.map +1 -1
- package/dist/organization-management/UserOrganizationRoutes.js +12 -8
- package/dist/organization-management/UserOrganizationRoutes.js.map +1 -1
- package/dist/organization-management/modules/members/components/BulkInviteForm.js +291 -0
- package/dist/organization-management/modules/members/components/BulkInviteForm.js.map +1 -0
- package/dist/organization-management/modules/members/pages/InviteMemberPage.js +65 -42
- package/dist/organization-management/modules/members/pages/InviteMemberPage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/InvitePeoplePage.js +95 -0
- package/dist/organization-management/modules/members/pages/InvitePeoplePage.js.map +1 -0
- package/dist/organization-management/modules/members/utils/bulkInviteCsv.js +52 -0
- package/dist/organization-management/modules/members/utils/bulkInviteCsv.js.map +1 -0
- package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +163 -151
- package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js +16 -0
- package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js.map +1 -1
- package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js +7 -7
- package/package.json +1 -1
package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js
CHANGED
|
@@ -98,6 +98,22 @@ function v({ open: v, onOpenChange: y, workspaceId: b, organizationId: x, existi
|
|
|
98
98
|
},
|
|
99
99
|
className: "mt-2 inline-flex items-center gap-2 text-sm font-medium text-[var(--color-action-primary-bg)] hover:underline",
|
|
100
100
|
children: w("workspaces.addMember.inviteInstead", "Invite a new organization member instead")
|
|
101
|
+
}) : null,
|
|
102
|
+
C ? /* @__PURE__ */ _("p", {
|
|
103
|
+
className: "mt-2 text-xs text-[var(--color-text-muted)]",
|
|
104
|
+
children: [
|
|
105
|
+
w("workspaces.addMember.bulkInviteHint", "Need to add many people who are not in this organization yet?"),
|
|
106
|
+
" ",
|
|
107
|
+
/* @__PURE__ */ g("button", {
|
|
108
|
+
type: "button",
|
|
109
|
+
onClick: () => {
|
|
110
|
+
y(!1), C();
|
|
111
|
+
},
|
|
112
|
+
className: "font-medium text-[var(--color-action-primary-bg)] hover:underline",
|
|
113
|
+
children: w("workspaces.addMember.bulkInviteLink", "Bulk-invite them from the organization invite page")
|
|
114
|
+
}),
|
|
115
|
+
"."
|
|
116
|
+
]
|
|
101
117
|
}) : null
|
|
102
118
|
] }),
|
|
103
119
|
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
|
package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddWorkspaceMemberDialog.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { AlertCircle, Loader2, UserPlus } from 'lucide-react';\nimport { toast } from 'sonner';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useMembers } from '../../members/hooks/useMembers';\nimport { useAddWorkspaceMember } from '../hooks/useWorkspaceMembers';\nimport type { WorkspaceMember } from '../types';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface AddWorkspaceMemberDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n workspaceId: string;\n organizationId: string;\n existingMembers: WorkspaceMember[];\n onInviteOrganizationMember?: () => void;\n}\n\nexport function AddWorkspaceMemberDialog({\n open,\n onOpenChange,\n workspaceId,\n organizationId,\n existingMembers,\n onInviteOrganizationMember,\n}: AddWorkspaceMemberDialogProps) {\n const tr = useTr();\n const [selectedUserId, setSelectedUserId] = useState('');\n const [selectedRole, setSelectedRole] = useState<'MEMBER' | 'WORKSPACE_ADMIN'>('MEMBER');\n const [submissionError, setSubmissionError] = useState<string | null>(null);\n\n const { members: organizationMembers, loading: membersLoading } = useMembers(\n // react-doctor-disable-next-line react-doctor/no-event-handler\n organizationId,\n 100,\n 0,\n // react-doctor-disable-next-line react-doctor/no-event-handler\n open\n );\n const { addWorkspaceMember, loading: addingMember } = useAddWorkspaceMember();\n\n const existingUserIds = useMemo(\n // react-doctor-disable-next-line react-doctor/no-event-handler\n () => new Set(existingMembers.map((member) => member.userId)),\n [existingMembers]\n );\n\n const availableMembers = useMemo(\n () => organizationMembers.filter((member) => !existingUserIds.has(member.userId)),\n [existingUserIds, organizationMembers]\n );\n\n useEffect(() => {\n if (!open) {\n setSelectedUserId('');\n setSelectedRole('MEMBER');\n setSubmissionError(null);\n return;\n }\n\n // react-doctor-disable-next-line react-doctor/no-event-handler\n if (!selectedUserId && availableMembers.length > 0) {\n setSelectedUserId(availableMembers[0]?.userId ?? '');\n }\n }, [availableMembers, open, selectedUserId]);\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n\n if (!selectedUserId) {\n setSubmissionError(\n tr(\n 'workspaces.addMember.selectRequired',\n 'Select an organization member to add to this workspace.'\n )\n );\n return;\n }\n\n try {\n setSubmissionError(null);\n const result = await addWorkspaceMember({\n workspaceId,\n userId: selectedUserId,\n role: selectedRole,\n });\n\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr('workspaces.addMember.failed', 'Failed to add workspace member')\n );\n }\n\n toast.success(tr('workspaces.addMember.success', 'Workspace member added successfully'));\n onOpenChange(false);\n } catch (error) {\n setSubmissionError(\n error instanceof Error\n ? error.message\n : tr('workspaces.addMember.failed', 'Failed to add workspace member')\n );\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-[520px] border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)]\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2 text-[var(--color-text-primary)]\">\n <UserPlus size={18} aria-hidden=\"true\" />\n {tr('workspaces.addMember.title', 'Add workspace member')}\n </DialogTitle>\n <DialogDescription className=\"text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.addMember.description',\n 'Choose an existing organization member and assign their workspace role.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {submissionError ? (\n <div className=\"flex items-start gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3 text-sm text-[var(--color-status-error-text)]\">\n <AlertCircle size={16} className=\"mt-0.5 shrink-0\" aria-hidden=\"true\" />\n <span>{submissionError}</span>\n </div>\n ) : null}\n\n <div>\n <label\n htmlFor=\"workspace-member-user\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.addMember.memberLabel', 'Organization member')}\n </label>\n <select\n id=\"workspace-member-user\"\n value={selectedUserId}\n onChange={(event) => setSelectedUserId(event.target.value)}\n disabled={membersLoading || addingMember || availableMembers.length === 0}\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n >\n {availableMembers.length === 0 ? (\n <option value=\"\">\n {tr(\n 'workspaces.addMember.noneAvailable',\n 'No eligible organization members available'\n )}\n </option>\n ) : null}\n {availableMembers.map((member) => (\n <option key={member.id} value={member.userId}>\n {member.userId} ({member.role})\n </option>\n ))}\n </select>\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'workspaces.addMember.filterHelp',\n 'Only members that belong to this organization and are not already in the workspace are listed.'\n )}\n </p>\n {availableMembers.length === 0 && onInviteOrganizationMember ? (\n <button\n type=\"button\"\n onClick={() => {\n onOpenChange(false);\n onInviteOrganizationMember();\n }}\n className=\"mt-2 inline-flex items-center gap-2 text-sm font-medium text-[var(--color-action-primary-bg)] hover:underline\"\n >\n {tr(\n 'workspaces.addMember.inviteInstead',\n 'Invite a new organization member instead'\n )}\n </button>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor=\"workspace-member-role\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.addMember.roleLabel', 'Workspace role')}\n </label>\n <select\n id=\"workspace-member-role\"\n value={selectedRole}\n onChange={(event) =>\n setSelectedRole(event.target.value as 'MEMBER' | 'WORKSPACE_ADMIN')\n }\n disabled={addingMember}\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n >\n <option value=\"MEMBER\">{tr('members.role.member', 'Member')}</option>\n <option value=\"WORKSPACE_ADMIN\">\n {tr('members.role.workspaceAdmin', 'Workspace Admin')}\n </option>\n </select>\n </div>\n\n <DialogFooter className=\"gap-3 sm:gap-0\">\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"rounded-lg border border-[var(--color-border-default)] px-4 py-2 text-[var(--color-text-primary)] transition-colors hover:bg-[var(--color-bg-subtle)]\"\n disabled={addingMember}\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={addingMember || membersLoading || availableMembers.length === 0}\n >\n {addingMember ? <Loader2 size={16} className=\"animate-spin\" /> : null}\n {tr('workspaces.addMember.submit', 'Add member')}\n </button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AddWorkspaceMemberDialog.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { AlertCircle, Loader2, UserPlus } from 'lucide-react';\nimport { toast } from 'sonner';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useMembers } from '../../members/hooks/useMembers';\nimport { useAddWorkspaceMember } from '../hooks/useWorkspaceMembers';\nimport type { WorkspaceMember } from '../types';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface AddWorkspaceMemberDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n workspaceId: string;\n organizationId: string;\n existingMembers: WorkspaceMember[];\n onInviteOrganizationMember?: () => void;\n}\n\nexport function AddWorkspaceMemberDialog({\n open,\n onOpenChange,\n workspaceId,\n organizationId,\n existingMembers,\n onInviteOrganizationMember,\n}: AddWorkspaceMemberDialogProps) {\n const tr = useTr();\n const [selectedUserId, setSelectedUserId] = useState('');\n const [selectedRole, setSelectedRole] = useState<'MEMBER' | 'WORKSPACE_ADMIN'>('MEMBER');\n const [submissionError, setSubmissionError] = useState<string | null>(null);\n\n const { members: organizationMembers, loading: membersLoading } = useMembers(\n // react-doctor-disable-next-line react-doctor/no-event-handler\n organizationId,\n 100,\n 0,\n // react-doctor-disable-next-line react-doctor/no-event-handler\n open\n );\n const { addWorkspaceMember, loading: addingMember } = useAddWorkspaceMember();\n\n const existingUserIds = useMemo(\n // react-doctor-disable-next-line react-doctor/no-event-handler\n () => new Set(existingMembers.map((member) => member.userId)),\n [existingMembers]\n );\n\n const availableMembers = useMemo(\n () => organizationMembers.filter((member) => !existingUserIds.has(member.userId)),\n [existingUserIds, organizationMembers]\n );\n\n useEffect(() => {\n if (!open) {\n setSelectedUserId('');\n setSelectedRole('MEMBER');\n setSubmissionError(null);\n return;\n }\n\n // react-doctor-disable-next-line react-doctor/no-event-handler\n if (!selectedUserId && availableMembers.length > 0) {\n setSelectedUserId(availableMembers[0]?.userId ?? '');\n }\n }, [availableMembers, open, selectedUserId]);\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n\n if (!selectedUserId) {\n setSubmissionError(\n tr(\n 'workspaces.addMember.selectRequired',\n 'Select an organization member to add to this workspace.'\n )\n );\n return;\n }\n\n try {\n setSubmissionError(null);\n const result = await addWorkspaceMember({\n workspaceId,\n userId: selectedUserId,\n role: selectedRole,\n });\n\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr('workspaces.addMember.failed', 'Failed to add workspace member')\n );\n }\n\n toast.success(tr('workspaces.addMember.success', 'Workspace member added successfully'));\n onOpenChange(false);\n } catch (error) {\n setSubmissionError(\n error instanceof Error\n ? error.message\n : tr('workspaces.addMember.failed', 'Failed to add workspace member')\n );\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-[520px] border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)]\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2 text-[var(--color-text-primary)]\">\n <UserPlus size={18} aria-hidden=\"true\" />\n {tr('workspaces.addMember.title', 'Add workspace member')}\n </DialogTitle>\n <DialogDescription className=\"text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.addMember.description',\n 'Choose an existing organization member and assign their workspace role.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {submissionError ? (\n <div className=\"flex items-start gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3 text-sm text-[var(--color-status-error-text)]\">\n <AlertCircle size={16} className=\"mt-0.5 shrink-0\" aria-hidden=\"true\" />\n <span>{submissionError}</span>\n </div>\n ) : null}\n\n <div>\n <label\n htmlFor=\"workspace-member-user\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.addMember.memberLabel', 'Organization member')}\n </label>\n <select\n id=\"workspace-member-user\"\n value={selectedUserId}\n onChange={(event) => setSelectedUserId(event.target.value)}\n disabled={membersLoading || addingMember || availableMembers.length === 0}\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n >\n {availableMembers.length === 0 ? (\n <option value=\"\">\n {tr(\n 'workspaces.addMember.noneAvailable',\n 'No eligible organization members available'\n )}\n </option>\n ) : null}\n {availableMembers.map((member) => (\n <option key={member.id} value={member.userId}>\n {member.userId} ({member.role})\n </option>\n ))}\n </select>\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'workspaces.addMember.filterHelp',\n 'Only members that belong to this organization and are not already in the workspace are listed.'\n )}\n </p>\n {availableMembers.length === 0 && onInviteOrganizationMember ? (\n <button\n type=\"button\"\n onClick={() => {\n onOpenChange(false);\n onInviteOrganizationMember();\n }}\n className=\"mt-2 inline-flex items-center gap-2 text-sm font-medium text-[var(--color-action-primary-bg)] hover:underline\"\n >\n {tr(\n 'workspaces.addMember.inviteInstead',\n 'Invite a new organization member instead'\n )}\n </button>\n ) : null}\n {onInviteOrganizationMember ? (\n <p className=\"mt-2 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'workspaces.addMember.bulkInviteHint',\n 'Need to add many people who are not in this organization yet?'\n )}{' '}\n <button\n type=\"button\"\n onClick={() => {\n onOpenChange(false);\n onInviteOrganizationMember();\n }}\n className=\"font-medium text-[var(--color-action-primary-bg)] hover:underline\"\n >\n {tr(\n 'workspaces.addMember.bulkInviteLink',\n 'Bulk-invite them from the organization invite page'\n )}\n </button>\n .\n </p>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor=\"workspace-member-role\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.addMember.roleLabel', 'Workspace role')}\n </label>\n <select\n id=\"workspace-member-role\"\n value={selectedRole}\n onChange={(event) =>\n setSelectedRole(event.target.value as 'MEMBER' | 'WORKSPACE_ADMIN')\n }\n disabled={addingMember}\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n >\n <option value=\"MEMBER\">{tr('members.role.member', 'Member')}</option>\n <option value=\"WORKSPACE_ADMIN\">\n {tr('members.role.workspaceAdmin', 'Workspace Admin')}\n </option>\n </select>\n </div>\n\n <DialogFooter className=\"gap-3 sm:gap-0\">\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"rounded-lg border border-[var(--color-border-default)] px-4 py-2 text-[var(--color-text-primary)] transition-colors hover:bg-[var(--color-bg-subtle)]\"\n disabled={addingMember}\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={addingMember || membersLoading || availableMembers.length === 0}\n >\n {addingMember ? <Loader2 size={16} className=\"animate-spin\" /> : null}\n {tr('workspaces.addMember.submit', 'Add member')}\n </button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useOrganizations as e } from "../../organizations/hooks/useOrganizations.js";
|
|
2
2
|
import { useTr as t } from "../../../shared/hooks/useTr.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { useOrgsWithPermission as n } from "../../organizations/hooks/useOrgsWithPermission.js";
|
|
4
|
+
import { useTenants as r } from "../hooks/useWorkspaces.js";
|
|
5
|
+
import { ZodError as i } from "../../../../node_modules/zod/v3/ZodError.js";
|
|
6
|
+
import { createWorkspaceSchema as a, updateWorkspaceSchema as o } from "../schemas/index.js";
|
|
7
7
|
import { useEffect as s, useMemo as c, useState as l } from "react";
|
|
8
8
|
import { Building as u, Home as d, Loader2 as f } from "lucide-react";
|
|
9
9
|
import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
@@ -15,7 +15,7 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
|
|
|
15
15
|
type: g?.type || "PERSONAL",
|
|
16
16
|
tenantId: _ || g?.tenantId || "",
|
|
17
17
|
organizationId: y || g?.organizationId || ""
|
|
18
|
-
}), [O, k] = l({}), A = !g && x && !_, j = !g && x && !y, { tenants: M, loading: N } =
|
|
18
|
+
}), [O, k] = l({}), A = !g && x && !_, j = !g && x && !y, { tenants: M, loading: N } = r(100, 0, A), { organizations: P, loading: F } = e(E.tenantId ? { tenantId: E.tenantId } : void 0, 100, 0, j), { allowedIds: I, loading: L } = n(c(() => P.map((e) => e.id), [P]), "workspace", "create"), R = !g && x && !y, z = c(() => R ? P.filter((e) => I.has(e.id)) : P, [
|
|
19
19
|
P,
|
|
20
20
|
I,
|
|
21
21
|
R
|
|
@@ -51,9 +51,9 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
|
|
|
51
51
|
z
|
|
52
52
|
]), H = () => {
|
|
53
53
|
try {
|
|
54
|
-
return (g ?
|
|
54
|
+
return (g ? o : a).parse(E), k({}), !0;
|
|
55
55
|
} catch (e) {
|
|
56
|
-
if (e instanceof
|
|
56
|
+
if (e instanceof i) {
|
|
57
57
|
let t = {};
|
|
58
58
|
e.issues.forEach((e) => {
|
|
59
59
|
let n = e.path.join(".");
|