@oondemand/oon-core-front 0.7.28 → 0.7.31

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 CHANGED
@@ -25,4 +25,4 @@ import { CorePageHeader, CoreKpiGrid, CoreDataTable, CoreDetailDrawer, CoreStatu
25
25
  </CoreDetailDrawer>
26
26
  ```
27
27
 
28
- Menu: `section` agrupa, `order` ordena e `requires` liga o item a uma condição de `registry.menuConditions` (hook). Cabeçalho: `registry.layoutSlots.organization` recebe o seletor de organização (`CoreOrganizationSwitcher`); um item de menu com `action: "profile"` aparece em "Meu perfil".
28
+ Menu: `section` agrupa, `order` ordena e `requires` liga o item a uma condição de `registry.menuConditions` (hook). Cabeçalho: `registry.layoutSlots.organization` recebe o seletor de organização (`CoreOrganizationSwitcher`); um item de menu com `action: "profile"` aparece em "Meu perfil"; itens com `action: "user-menu"` entram no menu do usuário (entre "Meu perfil" e "Sair", na ordem de `order`) e saem do menu lateral; `registry.layoutSlots.topbarEnd` fica à direita do avatar (ex.: botão de tema).
@@ -9,7 +9,7 @@ import {
9
9
  MissingRenderer,
10
10
  coreInitials,
11
11
  resolveComponent
12
- } from "./chunk-MRRN2HAU.js";
12
+ } from "./chunk-GIDNQRK6.js";
13
13
  import {
14
14
  OON_RESERVED_ROUTES,
15
15
  defineOonNavigation,
@@ -110,6 +110,38 @@ import { useEffect, useState, useRef } from "react";
110
110
  import { Box, Button, Flex, Heading, Input, Text, VStack } from "@chakra-ui/react";
111
111
  import { useLocation } from "react-router-dom";
112
112
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
113
+ var GENERIC_FAILURE = "Houve um erro inesperado!";
114
+ var ACCEPT_ERROR_MESSAGES = {
115
+ INVITATION_LEGACY_DISABLED: "Este convite foi emitido antes da atualiza\xE7\xE3o do aplicativo e n\xE3o vale mais. Pe\xE7a ao administrador um novo convite.",
116
+ RBAC_INVITATION_INVALID: "Este convite \xE9 inv\xE1lido, expirou, foi revogado ou j\xE1 foi utilizado. Solicite um novo convite ao administrador.",
117
+ INVITATION_UNAVAILABLE: "Este convite \xE9 inv\xE1lido, expirou, foi revogado ou j\xE1 foi utilizado. Solicite um novo convite ao administrador.",
118
+ INVITATION_IDENTITY_CHANGED: "Os dados da sua conta mudaram desde que voc\xEA abriu o convite. Recarregue a p\xE1gina e tente de novo.",
119
+ USER_LIMIT_REACHED: "A organiza\xE7\xE3o atingiu o limite de usu\xE1rios do plano. Avise o administrador para liberar o acesso.",
120
+ RBAC_OPERATIONAL_CREDENTIAL_REQUIRED: "Este aplicativo ainda n\xE3o est\xE1 ativado para aceitar convites. Avise o administrador.",
121
+ APP_LICENSE_INTEGRATION_NOT_READY: "O acesso por convite ainda n\xE3o est\xE1 liberado para este aplicativo. Avise o administrador.",
122
+ SAAS_ADOPTION_NOT_READY: "O acesso por convite ainda n\xE3o est\xE1 liberado para esta organiza\xE7\xE3o. Avise o administrador.",
123
+ INVITATION_TENANT_UNAVAILABLE: "A organiza\xE7\xE3o deste convite n\xE3o est\xE1 dispon\xEDvel. Avise o administrador.",
124
+ INVITATION_MEMBERSHIP_INACTIVE: "Seu v\xEDnculo com a organiza\xE7\xE3o est\xE1 inativo. Pe\xE7a ao administrador para regulariz\xE1-lo.",
125
+ INVITATION_ACCESS_INACTIVE: "Seu acesso a este aplicativo est\xE1 inativo. Pe\xE7a ao administrador para regulariz\xE1-lo.",
126
+ CONTROL_PLANE_IDENTITY_DISABLED: "Sua conta Oon est\xE1 bloqueada. Fale com o suporte.",
127
+ RBAC_IDENTITY_PROVIDER_UNREACHABLE: "N\xE3o foi poss\xEDvel falar com a Central Oon. Tente novamente em instantes."
128
+ };
129
+ var SERVER_FAILURES = /* @__PURE__ */ new Set(["RBAC_IDENTITY_PROVIDER_ERROR", "INTERNAL_ERROR", "SERVER_ERROR"]);
130
+ function describeAcceptError(error) {
131
+ const code = typeof error?.code === "string" ? error.code : void 0;
132
+ const details = error?.details && typeof error.details === "object" ? error.details : {};
133
+ const providerCode = typeof details.providerCode === "string" ? details.providerCode : void 0;
134
+ const known = code && ACCEPT_ERROR_MESSAGES[code] || providerCode && ACCEPT_ERROR_MESSAGES[providerCode];
135
+ const serverFailure = code && SERVER_FAILURES.has(code) || Number(error?.status) >= 500;
136
+ const raw = typeof error?.message === "string" ? error.message.trim() : "";
137
+ const text = known || (serverFailure ? "N\xE3o foi poss\xEDvel concluir o convite por uma falha no servidor. Tente novamente; se persistir, envie a refer\xEAncia abaixo ao administrador." : "") || (raw && raw !== GENERIC_FAILURE ? raw : "N\xE3o foi poss\xEDvel concluir o convite.");
138
+ const parts = [
139
+ code && !["REQUEST_ERROR", "UNKNOWN"].includes(code) ? `C\xF3digo: ${providerCode && providerCode !== code ? `${code}/${providerCode}` : code}` : null,
140
+ typeof error?.requestId === "string" ? `Protocolo: ${error.requestId}` : null,
141
+ typeof details.providerRequestId === "string" ? `Central: ${details.providerRequestId}` : null
142
+ ].filter(Boolean);
143
+ return { text, ...parts.length ? { reference: parts.join(" \xB7 ") } : {} };
144
+ }
113
145
  function AcceptInvitePage() {
114
146
  const { http } = useOonApi();
115
147
  const location = useLocation();
@@ -122,6 +154,7 @@ function AcceptInvitePage() {
122
154
  const [password, setPassword] = useState("");
123
155
  const [confirm, setConfirm] = useState("");
124
156
  const [message, setMessage] = useState(null);
157
+ const [reference, setReference] = useState(null);
125
158
  const [inspectionAttempt, setInspectionAttempt] = useState(0);
126
159
  const [submitting, setSubmitting] = useState(false);
127
160
  const [done, setDone] = useState(false);
@@ -133,6 +166,7 @@ function AcceptInvitePage() {
133
166
  setInvitation(null);
134
167
  setDone(false);
135
168
  setMessage(null);
169
+ setReference(null);
136
170
  setPassword("");
137
171
  setConfirm("");
138
172
  if (!token) {
@@ -165,6 +199,7 @@ function AcceptInvitePage() {
165
199
  event.preventDefault();
166
200
  if (submitting || otherSession || auth.status === "loading") return;
167
201
  setMessage(null);
202
+ setReference(null);
168
203
  if (!sameSession && register && password.length < 8) {
169
204
  setMessage("A senha deve possuir pelo menos 8 caracteres.");
170
205
  return;
@@ -183,10 +218,13 @@ function AcceptInvitePage() {
183
218
  ...sameSession ? {} : { password }
184
219
  }, { headers: { "idempotency-key": operationKey.current, ...sameSession ? {} : { Authorization: false }, "x-oon-tenant-id": false } });
185
220
  setDone(true);
221
+ setReference(null);
186
222
  setMessage("Convite aceito. Seu acesso est\xE1 dispon\xEDvel.");
187
223
  } catch (error) {
188
224
  if (sameSession && error?.status === 401) clearSession();
189
- setMessage(error?.message || "N\xE3o foi poss\xEDvel concluir o convite.");
225
+ const described = describeAcceptError(error);
226
+ setMessage(described.text);
227
+ setReference(described.reference || null);
190
228
  } finally {
191
229
  setSubmitting(false);
192
230
  }
@@ -247,7 +285,10 @@ function AcceptInvitePage() {
247
285
  /* @__PURE__ */ jsx(Button, { type: "submit", disabled: submitting || auth.status === "loading" || Boolean(invitation.allowedActions && !invitation.allowedActions.includes("accept")), children: submitting ? "Aceitando\u2026" : "Aceitar convite" })
248
286
  ] }) })
249
287
  ] }) : null,
250
- message ? /* @__PURE__ */ jsx(Box, { role: "status", bg: done ? "green.50" : "red.50", borderRadius: "md", p: 3, children: /* @__PURE__ */ jsx(Text, { fontSize: "sm", children: message }) }) : null,
288
+ message ? /* @__PURE__ */ jsxs(Box, { role: "status", bg: done ? "green.50" : "red.50", borderRadius: "md", p: 3, children: [
289
+ /* @__PURE__ */ jsx(Text, { fontSize: "sm", children: message }),
290
+ reference && !done ? /* @__PURE__ */ jsx(Text, { mt: 2, fontSize: "xs", color: "gray.600", fontFamily: "mono", style: { wordBreak: "break-all" }, children: reference }) : null
291
+ ] }) : null,
251
292
  !loading && !invitation && token ? /* @__PURE__ */ jsx(Button, { onClick: () => setInspectionAttempt((value2) => value2 + 1), children: "Tentar novamente" }) : null,
252
293
  done ? /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx("a", { href: sameSession ? "/" : "/login", children: sameSession ? "Abrir aplicativo" : "Ir para o login" }) }) : null
253
294
  ] }) }) });
@@ -609,6 +650,13 @@ function groupBySection(items) {
609
650
  }
610
651
  return Array.from(groups.entries());
611
652
  }
653
+ var USER_MENU_ACTION = "user-menu";
654
+ function isUserMenuItem(item) {
655
+ return item.action === USER_MENU_ACTION;
656
+ }
657
+ function orderedUserMenu(visible) {
658
+ return visible.filter(isUserMenuItem).map((item, index) => ({ item, index })).sort((a, b) => (a.item.order ?? Number.MAX_SAFE_INTEGER) - (b.item.order ?? Number.MAX_SAFE_INTEGER) || a.index - b.index).map(({ item }) => item);
659
+ }
612
660
  function launchAppCode(action) {
613
661
  const match = /^launch-app:([a-z][a-z0-9-]{2,62})$/.exec(String(action || ""));
614
662
  return match?.[1] || "";
@@ -695,7 +743,7 @@ function useVisibleMenu(menu, registry) {
695
743
  return menu.filter((item) => !item.hidden && hasPermission(item.permissions) && (!item.requires || conditions[item.requires] === true));
696
744
  }
697
745
  function SidebarNav({ menu, registry, onNavigate, compact = false }) {
698
- const visible = useVisibleMenu(menu, registry);
746
+ const visible = useVisibleMenu(menu, registry).filter((item) => !isUserMenuItem(item));
699
747
  return /* @__PURE__ */ jsx7(Stack, { gap: 5, children: groupBySection(visible).map(([section, items]) => /* @__PURE__ */ jsxs5(Stack, { gap: 1, role: "group", "aria-label": section, children: [
700
748
  /* @__PURE__ */ jsx7(
701
749
  Text4,
@@ -793,7 +841,7 @@ function Sidebar({ app, menu, registry }) {
793
841
  // package.json
794
842
  var package_default = {
795
843
  name: "@oondemand/oon-core-front",
796
- version: "0.7.28",
844
+ version: "0.7.31",
797
845
  repository: {
798
846
  type: "git",
799
847
  url: "git+https://github.com/oondemand/oon-platform.git",
@@ -1021,6 +1069,8 @@ function CoreTopbar({ app, menu, registry }) {
1021
1069
  );
1022
1070
  const profileHref = menu.find((item) => item.action === "profile")?.href ?? null;
1023
1071
  const OrganizationSlot = registry?.layoutSlots?.organization;
1072
+ const TopbarEndSlot = registry?.layoutSlots?.topbarEnd;
1073
+ const userMenu = orderedUserMenu(useVisibleMenu(menu, registry));
1024
1074
  const avatar = user?.fotoPerfilUrl;
1025
1075
  const tenant = user?.tenant;
1026
1076
  const tenantLabel = String(tenant?.nome || tenant?.slug || "").trim();
@@ -1086,9 +1136,22 @@ ${details}`, children: [
1086
1136
  /* @__PURE__ */ jsx8(Menu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx8(Button3, { size: "sm", variant: "ghost", borderRadius: "full", px: 1, "aria-label": "Abrir menu do usu\xE1rio", children: avatar ? /* @__PURE__ */ jsx8(Image2, { src: avatar, alt: "", boxSize: "32px", borderRadius: "full", objectFit: "cover" }) : /* @__PURE__ */ jsx8(Flex4, { boxSize: "32px", borderRadius: "full", bg: "brand.100", color: "brand.700", align: "center", justify: "center", fontWeight: "700", fontSize: "xs", children: coreInitials(user.nome) }) }) }),
1087
1137
  /* @__PURE__ */ jsx8(Portal, { children: /* @__PURE__ */ jsx8(Menu.Positioner, { children: /* @__PURE__ */ jsxs6(Menu.Content, { children: [
1088
1138
  profileHref ? /* @__PURE__ */ jsx8(Menu.Item, { value: "perfil", onClick: () => navigate(profileHref), children: "Meu perfil" }) : null,
1139
+ userMenu.map((item) => /* @__PURE__ */ jsxs6(
1140
+ Menu.Item,
1141
+ {
1142
+ value: "user-menu:" + item.href,
1143
+ onClick: () => item.external ? window.open(item.href, "_blank", "noopener,noreferrer") : navigate(item.href),
1144
+ children: [
1145
+ item.icon,
1146
+ item.label
1147
+ ]
1148
+ },
1149
+ item.href
1150
+ )),
1089
1151
  /* @__PURE__ */ jsx8(Menu.Item, { value: "sair", onClick: logout, children: "Sair" })
1090
1152
  ] }) }) })
1091
- ] })
1153
+ ] }),
1154
+ TopbarEndSlot ? /* @__PURE__ */ jsx8(TopbarEndSlot, { app, menu }) : null
1092
1155
  ] }) : null
1093
1156
  ]
1094
1157
  }
@@ -2203,4 +2266,4 @@ export {
2203
2266
  appDefinitionToConfig,
2204
2267
  startOonApp
2205
2268
  };
2206
- //# sourceMappingURL=chunk-JZ7337PM.js.map
2269
+ //# sourceMappingURL=chunk-3OC4CZF7.js.map