@interware/content-generator 0.5.0 → 0.6.1

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 (32) hide show
  1. package/dist/_chunks/{App-DVTFrZvf.js → App-CJxSC8yt.js} +5 -4
  2. package/dist/_chunks/{App-DPVBu7QB.mjs → App-qbgUXlOZ.mjs} +4 -3
  3. package/dist/_chunks/{ImageStudioTabs-mlNL6aQ2.mjs → ImageStudioTabs-BLAH3KYv.mjs} +8 -36
  4. package/dist/_chunks/{ImageStudioTabs-B2UbKYq7.js → ImageStudioTabs-DtusqpQO.js} +7 -35
  5. package/dist/_chunks/PluginProviders-D79TeGSE.js +34 -0
  6. package/dist/_chunks/PluginProviders-DWMpcAIh.mjs +35 -0
  7. package/dist/_chunks/{Settings-DziRY70a.js → Settings-BQXxV3LO.js} +93 -6
  8. package/dist/_chunks/{Settings-RrBQdijj.mjs → Settings-o2GngLaW.mjs} +94 -7
  9. package/dist/_chunks/{StudioApp-Cswkzh7F.js → StudioApp-BaySMwrk.js} +4 -3
  10. package/dist/_chunks/{StudioApp-AUyPNhh2.mjs → StudioApp-C_znlQRo.mjs} +3 -2
  11. package/dist/_chunks/{getTranslation-DfxaP_TC.mjs → getTranslation-B6Bsu-uq.mjs} +1 -1
  12. package/dist/_chunks/{getTranslation-D88uLXGd.js → getTranslation-BRVMWSf8.js} +1 -1
  13. package/dist/_chunks/{index-Ddp0Qvqo.js → index-BKhe-Jyx.js} +3 -3
  14. package/dist/_chunks/{index-CqDdi211.mjs → index-BKigRXm3.mjs} +3 -3
  15. package/dist/admin/index.js +1 -1
  16. package/dist/admin/index.mjs +1 -1
  17. package/dist/admin/src/components/PluginProviders.d.ts +6 -2
  18. package/dist/admin/src/components/settings/VertexSettings.d.ts +18 -0
  19. package/dist/admin/src/hooks/useAdminTheme.d.ts +1 -1
  20. package/dist/admin/src/lib/use-cases/settings/index.d.ts +1 -0
  21. package/dist/server/index.js +95 -27
  22. package/dist/server/index.mjs +96 -28
  23. package/dist/server/src/controllers/config.d.ts +10 -2
  24. package/dist/server/src/controllers/index.d.ts +1 -0
  25. package/dist/server/src/image-studio/models.d.ts +2 -1
  26. package/dist/server/src/index.d.ts +4 -0
  27. package/dist/server/src/services/image-studio.d.ts +9 -5
  28. package/dist/server/src/services/index.d.ts +3 -0
  29. package/dist/server/src/services/service.d.ts +10 -0
  30. package/dist/server/src/utils/geminiClient.d.ts +24 -0
  31. package/dist/server/src/utils/serviceAccount.d.ts +29 -0
  32. package/package.json +2 -1
@@ -3,16 +3,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const admin = require("@strapi/strapi/admin");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const ImageStudioTabs = require("./ImageStudioTabs-B2UbKYq7.js");
6
+ const PluginProviders = require("./PluginProviders-D79TeGSE.js");
7
7
  const reactIntl = require("react-intl");
8
8
  const react = require("react");
9
9
  const designSystem = require("@strapi/design-system");
10
10
  const reactRedux = require("react-redux");
11
- const index = require("./index-Ddp0Qvqo.js");
11
+ const index = require("./index-BKhe-Jyx.js");
12
12
  const icons = require("@strapi/icons");
13
- const getTranslation = require("./getTranslation-D88uLXGd.js");
13
+ const getTranslation = require("./getTranslation-BRVMWSf8.js");
14
14
  const formik = require("formik");
15
15
  const Yup = require("yup");
16
+ const ImageStudioTabs = require("./ImageStudioTabs-DtusqpQO.js");
16
17
  function _interopNamespace(e) {
17
18
  if (e && e.__esModule) return e;
18
19
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -1090,7 +1091,7 @@ const App = () => {
1090
1091
  if (isLoading) {
1091
1092
  return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Loading, {});
1092
1093
  }
1093
- return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: [...index.pluginPermissions.access], children: /* @__PURE__ */ jsxRuntime.jsx(ImageStudioTabs.PluginProviders, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
1094
+ return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: [...index.pluginPermissions.access], children: /* @__PURE__ */ jsxRuntime.jsx(PluginProviders.PluginProviders, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
1094
1095
  allowedActions.canAccess && /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) }),
1095
1096
  allowedActions.canAccess && /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/generate-content", element: /* @__PURE__ */ jsxRuntime.jsx(GenerateContent, {}) }),
1096
1097
  allowedActions.canAccess && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1,16 +1,17 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useFetchClient, useNotification, Page, useRBAC } from "@strapi/strapi/admin";
3
3
  import { useNavigate, Routes, Route } from "react-router-dom";
4
- import { P as PluginProviders, L as LEGACY_ROUTES, S as StudioRedirect, l as legacyRedirect } from "./ImageStudioTabs-mlNL6aQ2.mjs";
4
+ import { P as PluginProviders } from "./PluginProviders-DWMpcAIh.mjs";
5
5
  import { useIntl } from "react-intl";
6
6
  import { useCallback, memo, useMemo, useState, useRef, useEffect } from "react";
7
7
  import { Box, Table, Thead, Tr, Th, Typography, Flex, Tbody, Td, Button, LinkButton, Dialog, Grid, Field, Textarea, TextInput, Combobox, ComboboxOption, IconButton } from "@strapi/design-system";
8
8
  import { useDispatch, useSelector } from "react-redux";
9
- import { c as closeDialog, o as openDialog, P as PLUGIN_ID, p as pluginPermissions } from "./index-CqDdi211.mjs";
9
+ import { c as closeDialog, o as openDialog, P as PLUGIN_ID, p as pluginPermissions } from "./index-BKigRXm3.mjs";
10
10
  import { Play, ExternalLink, Image, Trash, PlusCircle } from "@strapi/icons";
11
- import { g as getTranslation } from "./getTranslation-DfxaP_TC.mjs";
11
+ import { g as getTranslation } from "./getTranslation-B6Bsu-uq.mjs";
12
12
  import { useFormik } from "formik";
13
13
  import * as Yup from "yup";
14
+ import { L as LEGACY_ROUTES, S as StudioRedirect, l as legacyRedirect } from "./ImageStudioTabs-BLAH3KYv.mjs";
14
15
  const useDialog = (id) => {
15
16
  const dispatch = useDispatch();
16
17
  const state = useSelector((state2) => state2.content_generator_commonDialog.open[id] ?? false);
@@ -1,40 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { DesignSystemProvider, darkTheme, lightTheme, Flex, Box, Typography, Modal, Checkbox, Loader, Button, Grid, Field, TextInput, Dialog, SingleSelect, SingleSelectOption, Link, Badge, IconButtonGroup, IconButton, Toggle, Menu, NumberInput, Divider, Textarea, Tabs } from "@strapi/design-system";
3
- import { useState, useEffect, useRef, useMemo, useId, useReducer, useCallback, useSyncExternalStore, useLayoutEffect, memo, forwardRef } from "react";
2
+ import { Flex, Box, Typography, lightTheme, Modal, Checkbox, Loader, Button, Grid, Field, TextInput, Dialog, SingleSelect, SingleSelectOption, Link, Badge, IconButtonGroup, IconButton, Toggle, Menu, NumberInput, Divider, Textarea, Tabs } from "@strapi/design-system";
4
3
  import { useLocation, Navigate, useSearchParams } from "react-router-dom";
5
- import { S as STUDIO_PATH } from "./index-CqDdi211.mjs";
4
+ import { S as STUDIO_PATH } from "./index-BKigRXm3.mjs";
5
+ import { useState, useRef, useEffect, useMemo, useId, useReducer, useCallback, useSyncExternalStore, useLayoutEffect, memo, forwardRef } from "react";
6
6
  import { Magic, Pencil, ChevronRight, Folder, Upload, Sparkle, Plus, Cross, Download, ArrowClockwise, House, ChevronDown, FilePdf, File as File$1, More, Trash, User, Star, SquaresFour, Quotes, PriceTag, Paragraph, NumberList, Minus, Italic, Image as Image$1, HeadingTwo, HeadingOne, Hashtag, Feather, Drag, BulletList, ArrowLeft, Check, ArrowsCounterClockwise, ArrowLineLeft, ArrowLineRight, Expand, WarningCircle, Play, Phone, Mail, PinMap, Earth, PresentationChart, ChartPie, ChartBubble, Cog, Database, Cloud, Globe, Server, Lightbulb, Crown, SealCheck, Briefcase, Rocket, Shield, CheckCircle, Lightning, Heart, Collapse, Bold, ArrowUp, ArrowDown, Duplicate, Lock, EyeStriked, Eye } from "@strapi/icons";
7
7
  import { useTheme } from "styled-components";
8
8
  import { useFetchClient, useNotification } from "@strapi/strapi/admin";
9
9
  import { toPng, toSvg, toJpeg } from "html-to-image";
10
10
  import qrcode from "qrcode-generator";
11
- const THEME_KEY = "STRAPI_THEME";
12
- const stored = () => {
13
- try {
14
- return localStorage.getItem(THEME_KEY);
15
- } catch {
16
- return null;
17
- }
18
- };
19
- const systemDark = () => typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
20
- const useAdminTheme = () => {
21
- const choice = stored();
22
- const [dark, setDark] = useState(systemDark);
23
- useEffect(() => {
24
- if (choice === "light" || choice === "dark") return;
25
- const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
26
- if (!mq) return;
27
- const onChange = (e) => setDark(e.matches);
28
- mq.addEventListener("change", onChange);
29
- return () => mq.removeEventListener("change", onChange);
30
- }, [choice]);
31
- if (choice === "light" || choice === "dark") return choice;
32
- return dark ? "dark" : "light";
33
- };
34
- const PluginProviders = ({ children }) => {
35
- const scheme = useAdminTheme();
36
- return /* @__PURE__ */ jsx(DesignSystemProvider, { locale: "es-MX", theme: scheme === "dark" ? darkTheme : lightTheme, children });
37
- };
38
11
  const SegmentedSwitch = ({ label, options, value, onChange }) => /* @__PURE__ */ jsx(Flex, { role: "radiogroup", "aria-label": label, gap: 1, padding: 1, background: "neutral150", hasRadius: true, children: options.map(({ value: option, label: text, Icon }) => {
39
12
  const on = value === option;
40
13
  return /* @__PURE__ */ jsx(
@@ -1463,7 +1436,7 @@ const GeneratorTab = () => {
1463
1436
  const [aspectRatio, setAspectRatio] = useState("1:1");
1464
1437
  const [imageSize, setImageSize] = useState();
1465
1438
  const [safety, setSafety] = useState(true);
1466
- const [allowPeople, setAllowPeople] = useState(false);
1439
+ const [allowPeople, setAllowPeople] = useState(true);
1467
1440
  const [grounding, setGrounding] = useState(false);
1468
1441
  const [references, setReferences] = useState([]);
1469
1442
  const [prompt, setPrompt] = useState("");
@@ -2661,8 +2634,8 @@ const useTemplateSaving = () => {
2661
2634
  async (template) => {
2662
2635
  if (!template.documentId) return null;
2663
2636
  try {
2664
- const stored2 = await toStored(template, { name: template.name, folder: template.folder ?? "" }, upload);
2665
- const updated = await api.update(template.documentId, stored2);
2637
+ const stored = await toStored(template, { name: template.name, folder: template.folder ?? "" }, upload);
2638
+ const updated = await api.update(template.documentId, stored);
2666
2639
  notify("success", "Cambios guardados.");
2667
2640
  return fromStored(updated);
2668
2641
  } catch (err) {
@@ -2677,8 +2650,8 @@ const useTemplateSaving = () => {
2677
2650
  const baseId = baseIdOf(template);
2678
2651
  if (!baseId) return null;
2679
2652
  try {
2680
- const stored2 = await toStored(template, { name: template.name, folder: "" }, upload);
2681
- const saved = await api.saveBase(baseId, stored2);
2653
+ const stored = await toStored(template, { name: template.name, folder: "" }, upload);
2654
+ const saved = await api.saveBase(baseId, stored);
2682
2655
  notify("success", "Plantilla base guardada para todos.");
2683
2656
  return fromStored(saved);
2684
2657
  } catch (err) {
@@ -5292,7 +5265,6 @@ const ImageStudioTabs = () => {
5292
5265
  export {
5293
5266
  ImageStudioTabs as I,
5294
5267
  LEGACY_ROUTES as L,
5295
- PluginProviders as P,
5296
5268
  StudioRedirect as S,
5297
5269
  legacyRedirect as l
5298
5270
  };
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  const jsxRuntime = require("react/jsx-runtime");
3
3
  const designSystem = require("@strapi/design-system");
4
- const react = require("react");
5
4
  const reactRouterDom = require("react-router-dom");
6
- const index = require("./index-Ddp0Qvqo.js");
5
+ const index = require("./index-BKhe-Jyx.js");
6
+ const react = require("react");
7
7
  const icons = require("@strapi/icons");
8
8
  const styledComponents = require("styled-components");
9
9
  const admin = require("@strapi/strapi/admin");
@@ -11,33 +11,6 @@ const htmlToImage = require("html-to-image");
11
11
  const qrcode = require("qrcode-generator");
12
12
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
13
13
  const qrcode__default = /* @__PURE__ */ _interopDefault(qrcode);
14
- const THEME_KEY = "STRAPI_THEME";
15
- const stored = () => {
16
- try {
17
- return localStorage.getItem(THEME_KEY);
18
- } catch {
19
- return null;
20
- }
21
- };
22
- const systemDark = () => typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
23
- const useAdminTheme = () => {
24
- const choice = stored();
25
- const [dark, setDark] = react.useState(systemDark);
26
- react.useEffect(() => {
27
- if (choice === "light" || choice === "dark") return;
28
- const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
29
- if (!mq) return;
30
- const onChange = (e) => setDark(e.matches);
31
- mq.addEventListener("change", onChange);
32
- return () => mq.removeEventListener("change", onChange);
33
- }, [choice]);
34
- if (choice === "light" || choice === "dark") return choice;
35
- return dark ? "dark" : "light";
36
- };
37
- const PluginProviders = ({ children }) => {
38
- const scheme = useAdminTheme();
39
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.DesignSystemProvider, { locale: "es-MX", theme: scheme === "dark" ? designSystem.darkTheme : designSystem.lightTheme, children });
40
- };
41
14
  const SegmentedSwitch = ({ label, options, value, onChange }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { role: "radiogroup", "aria-label": label, gap: 1, padding: 1, background: "neutral150", hasRadius: true, children: options.map(({ value: option, label: text, Icon }) => {
42
15
  const on = value === option;
43
16
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1466,7 +1439,7 @@ const GeneratorTab = () => {
1466
1439
  const [aspectRatio, setAspectRatio] = react.useState("1:1");
1467
1440
  const [imageSize, setImageSize] = react.useState();
1468
1441
  const [safety, setSafety] = react.useState(true);
1469
- const [allowPeople, setAllowPeople] = react.useState(false);
1442
+ const [allowPeople, setAllowPeople] = react.useState(true);
1470
1443
  const [grounding, setGrounding] = react.useState(false);
1471
1444
  const [references, setReferences] = react.useState([]);
1472
1445
  const [prompt, setPrompt] = react.useState("");
@@ -2664,8 +2637,8 @@ const useTemplateSaving = () => {
2664
2637
  async (template) => {
2665
2638
  if (!template.documentId) return null;
2666
2639
  try {
2667
- const stored2 = await toStored(template, { name: template.name, folder: template.folder ?? "" }, upload);
2668
- const updated = await api.update(template.documentId, stored2);
2640
+ const stored = await toStored(template, { name: template.name, folder: template.folder ?? "" }, upload);
2641
+ const updated = await api.update(template.documentId, stored);
2669
2642
  notify("success", "Cambios guardados.");
2670
2643
  return fromStored(updated);
2671
2644
  } catch (err) {
@@ -2680,8 +2653,8 @@ const useTemplateSaving = () => {
2680
2653
  const baseId = baseIdOf(template);
2681
2654
  if (!baseId) return null;
2682
2655
  try {
2683
- const stored2 = await toStored(template, { name: template.name, folder: "" }, upload);
2684
- const saved = await api.saveBase(baseId, stored2);
2656
+ const stored = await toStored(template, { name: template.name, folder: "" }, upload);
2657
+ const saved = await api.saveBase(baseId, stored);
2685
2658
  notify("success", "Plantilla base guardada para todos.");
2686
2659
  return fromStored(saved);
2687
2660
  } catch (err) {
@@ -5294,6 +5267,5 @@ const ImageStudioTabs = () => {
5294
5267
  };
5295
5268
  exports.ImageStudioTabs = ImageStudioTabs;
5296
5269
  exports.LEGACY_ROUTES = LEGACY_ROUTES;
5297
- exports.PluginProviders = PluginProviders;
5298
5270
  exports.StudioRedirect = StudioRedirect;
5299
5271
  exports.legacyRedirect = legacyRedirect;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const reactTooltip = require("@radix-ui/react-tooltip");
4
+ const designSystem = require("@strapi/design-system");
5
+ const styledComponents = require("styled-components");
6
+ const react = require("react");
7
+ const THEME_KEY = "STRAPI_THEME";
8
+ const stored = () => {
9
+ try {
10
+ return localStorage.getItem(THEME_KEY);
11
+ } catch {
12
+ return null;
13
+ }
14
+ };
15
+ const systemDark = () => typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
16
+ const useAdminTheme = () => {
17
+ const choice = stored();
18
+ const [dark, setDark] = react.useState(systemDark);
19
+ react.useEffect(() => {
20
+ if (choice === "light" || choice === "dark") return;
21
+ const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
22
+ if (!mq) return;
23
+ const onChange = (e) => setDark(e.matches);
24
+ mq.addEventListener("change", onChange);
25
+ return () => mq.removeEventListener("change", onChange);
26
+ }, [choice]);
27
+ if (choice === "light" || choice === "dark") return choice;
28
+ return dark ? "dark" : "light";
29
+ };
30
+ const PluginProviders = ({ children }) => {
31
+ const scheme = useAdminTheme();
32
+ return /* @__PURE__ */ jsxRuntime.jsx(styledComponents.ThemeProvider, { theme: scheme === "dark" ? designSystem.darkTheme : designSystem.lightTheme, children: /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.Provider, { children }) });
33
+ };
34
+ exports.PluginProviders = PluginProviders;
@@ -0,0 +1,35 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Provider } from "@radix-ui/react-tooltip";
3
+ import { darkTheme, lightTheme } from "@strapi/design-system";
4
+ import { ThemeProvider } from "styled-components";
5
+ import { useState, useEffect } from "react";
6
+ const THEME_KEY = "STRAPI_THEME";
7
+ const stored = () => {
8
+ try {
9
+ return localStorage.getItem(THEME_KEY);
10
+ } catch {
11
+ return null;
12
+ }
13
+ };
14
+ const systemDark = () => typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
15
+ const useAdminTheme = () => {
16
+ const choice = stored();
17
+ const [dark, setDark] = useState(systemDark);
18
+ useEffect(() => {
19
+ if (choice === "light" || choice === "dark") return;
20
+ const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
21
+ if (!mq) return;
22
+ const onChange = (e) => setDark(e.matches);
23
+ mq.addEventListener("change", onChange);
24
+ return () => mq.removeEventListener("change", onChange);
25
+ }, [choice]);
26
+ if (choice === "light" || choice === "dark") return choice;
27
+ return dark ? "dark" : "light";
28
+ };
29
+ const PluginProviders = ({ children }) => {
30
+ const scheme = useAdminTheme();
31
+ return /* @__PURE__ */ jsx(ThemeProvider, { theme: scheme === "dark" ? darkTheme : lightTheme, children: /* @__PURE__ */ jsx(Provider, { children }) });
32
+ };
33
+ export {
34
+ PluginProviders as P
35
+ };
@@ -6,10 +6,11 @@ const reactIntl = require("react-intl");
6
6
  const react = require("react");
7
7
  const designSystem = require("@strapi/design-system");
8
8
  const formik = require("formik");
9
- const index = require("./index-Ddp0Qvqo.js");
10
- const getTranslation = require("./getTranslation-D88uLXGd.js");
9
+ const PluginProviders = require("./PluginProviders-D79TeGSE.js");
10
+ const index = require("./index-BKhe-Jyx.js");
11
+ const getTranslation = require("./getTranslation-BRVMWSf8.js");
11
12
  const useSettings = () => {
12
- const { get, post } = admin.useFetchClient();
13
+ const { get, post, del } = admin.useFetchClient();
13
14
  const getSettings = react.useCallback(
14
15
  async (config) => {
15
16
  return get("/strapi-content-generator-gemini/config", config);
@@ -22,9 +23,11 @@ const useSettings = () => {
22
23
  },
23
24
  [post]
24
25
  );
26
+ const removeVertex = react.useCallback(async () => del("/strapi-content-generator-gemini/config/vertex"), [del]);
25
27
  return {
26
28
  getSettings,
27
- setSettings
29
+ setSettings,
30
+ removeVertex
28
31
  };
29
32
  };
30
33
  const FIELDS = [
@@ -77,7 +80,67 @@ const Form = ({ status, handleSubmit }) => {
77
80
  }
78
81
  ) });
79
82
  };
83
+ const statusLine = ({ configured, projectId, clientEmail }) => configured ? `Configurada · proyecto ${projectId} · ${clientEmail}` : "Sin configurar: el plugin usa la llave de Gemini.";
84
+ const VertexSettings = ({ status, onSave, onRemove }) => {
85
+ const [text, setText] = react.useState("");
86
+ const [error, setError] = react.useState(null);
87
+ const [busy, setBusy] = react.useState(false);
88
+ const save = async () => {
89
+ setBusy(true);
90
+ setError(null);
91
+ try {
92
+ await onSave(text);
93
+ setText("");
94
+ } catch (err) {
95
+ setError(err instanceof Error ? err.message : "No se pudo guardar la cuenta de servicio.");
96
+ } finally {
97
+ setBusy(false);
98
+ }
99
+ };
100
+ const remove = async () => {
101
+ setBusy(true);
102
+ try {
103
+ await onRemove();
104
+ } finally {
105
+ setBusy(false);
106
+ }
107
+ };
108
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, margin: 6, background: "neutral0", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
109
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", gap: 1, children: [
110
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", children: "Vertex AI" }),
111
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: statusLine(status) })
112
+ ] }),
113
+ /* @__PURE__ */ jsxRuntime.jsxs(
114
+ designSystem.Field.Root,
115
+ {
116
+ id: "vertexServiceAccount",
117
+ error: error ?? void 0,
118
+ hint: "Pega el contenido completo del archivo .json de la cuenta de servicio. La llave privada no vuelve a mostrarse.",
119
+ children: [
120
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "JSON de la cuenta de servicio" }),
121
+ /* @__PURE__ */ jsxRuntime.jsx(
122
+ designSystem.Textarea,
123
+ {
124
+ name: "vertexServiceAccount",
125
+ value: text,
126
+ onChange: (e) => setText(e.target.value),
127
+ placeholder: '{ "type": "service_account", … }'
128
+ }
129
+ ),
130
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
131
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
132
+ ]
133
+ }
134
+ ),
135
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "end", gap: 2, children: [
136
+ status.configured && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger-light", onClick: remove, disabled: busy, children: "Quitar cuenta de servicio" }),
137
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: save, disabled: !text.trim() || busy, loading: busy, children: "Guardar cuenta de servicio" })
138
+ ] })
139
+ ] }) });
140
+ };
80
141
  const NOT_CONFIGURED = { configured: false, last4: null };
142
+ const VERTEX_OFF = { configured: false, projectId: null, clientEmail: null };
143
+ const serverMessage = (error, fallback) => error?.response?.data?.error?.message ?? fallback;
81
144
  const initialStatus = {
82
145
  googleGenAI: NOT_CONFIGURED,
83
146
  linkedInAccessToken: NOT_CONFIGURED,
@@ -87,8 +150,9 @@ const initialStatus = {
87
150
  };
88
151
  const SettingsContainer = () => {
89
152
  const [status, setStatus] = react.useState(initialStatus);
153
+ const [vertex, setVertex] = react.useState(VERTEX_OFF);
90
154
  const { formatMessage } = reactIntl.useIntl();
91
- const { getSettings, setSettings } = useSettings();
155
+ const { getSettings, setSettings, removeVertex } = useSettings();
92
156
  const { toggleNotification } = admin.useNotification();
93
157
  const fetchSettings = react.useCallback(async () => {
94
158
  let isMounted = true;
@@ -96,6 +160,7 @@ const SettingsContainer = () => {
96
160
  const { data } = await getSettings();
97
161
  if (isMounted) {
98
162
  setStatus(data);
163
+ setVertex(data.vertex ?? VERTEX_OFF);
99
164
  }
100
165
  } catch (error) {
101
166
  toggleNotification({
@@ -134,14 +199,36 @@ const SettingsContainer = () => {
134
199
  },
135
200
  [setSettings, fetchSettings]
136
201
  );
202
+ const saveVertex = react.useCallback(
203
+ async (json) => {
204
+ try {
205
+ await setSettings({ vertexServiceAccount: json });
206
+ } catch (error) {
207
+ throw new Error(serverMessage(error, "No se pudo guardar la cuenta de servicio."));
208
+ }
209
+ await fetchSettings();
210
+ toggleNotification({ type: "success", message: "Cuenta de servicio de Vertex AI guardada." });
211
+ },
212
+ [setSettings, fetchSettings]
213
+ );
214
+ const deleteVertex = react.useCallback(async () => {
215
+ try {
216
+ await removeVertex();
217
+ await fetchSettings();
218
+ toggleNotification({ type: "success", message: "Cuenta de servicio quitada: el plugin usa la llave de Gemini." });
219
+ } catch {
220
+ toggleNotification({ type: "danger", message: "No se pudo quitar la cuenta de servicio." });
221
+ }
222
+ }, [removeVertex, fetchSettings]);
137
223
  react.useEffect(() => {
138
224
  fetchSettings();
139
225
  }, []);
140
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.DesignSystemProvider, { locale: "es-MX", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { padding: 6, gap: 3, children: [
226
+ return /* @__PURE__ */ jsxRuntime.jsx(PluginProviders.PluginProviders, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { padding: 6, gap: 3, children: [
141
227
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", children: [
142
228
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", children: formatMessage({ id: getTranslation.getTranslation("plugin.name") }) }),
143
229
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: "Para uso exclusivo de InterWare de México" })
144
230
  ] }) }),
231
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(VertexSettings, { status: vertex, onSave: saveVertex, onRemove: deleteVertex }) }),
145
232
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form, { status, handleSubmit }) })
146
233
  ] }) });
147
234
  };
@@ -2,12 +2,13 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useFetchClient, useNotification, Page } from "@strapi/strapi/admin";
3
3
  import { useIntl } from "react-intl";
4
4
  import { useCallback, useState, useEffect } from "react";
5
- import { Box, Grid, Field, Flex, Button, DesignSystemProvider, Typography } from "@strapi/design-system";
5
+ import { Box, Grid, Field, Flex, Button, Typography, Textarea } from "@strapi/design-system";
6
6
  import { Formik } from "formik";
7
- import { P as PLUGIN_ID } from "./index-CqDdi211.mjs";
8
- import { g as getTranslation } from "./getTranslation-DfxaP_TC.mjs";
7
+ import { P as PluginProviders } from "./PluginProviders-DWMpcAIh.mjs";
8
+ import { P as PLUGIN_ID } from "./index-BKigRXm3.mjs";
9
+ import { g as getTranslation } from "./getTranslation-B6Bsu-uq.mjs";
9
10
  const useSettings = () => {
10
- const { get, post } = useFetchClient();
11
+ const { get, post, del } = useFetchClient();
11
12
  const getSettings = useCallback(
12
13
  async (config) => {
13
14
  return get("/strapi-content-generator-gemini/config", config);
@@ -20,9 +21,11 @@ const useSettings = () => {
20
21
  },
21
22
  [post]
22
23
  );
24
+ const removeVertex = useCallback(async () => del("/strapi-content-generator-gemini/config/vertex"), [del]);
23
25
  return {
24
26
  getSettings,
25
- setSettings
27
+ setSettings,
28
+ removeVertex
26
29
  };
27
30
  };
28
31
  const FIELDS = [
@@ -75,7 +78,67 @@ const Form = ({ status, handleSubmit }) => {
75
78
  }
76
79
  ) });
77
80
  };
81
+ const statusLine = ({ configured, projectId, clientEmail }) => configured ? `Configurada · proyecto ${projectId} · ${clientEmail}` : "Sin configurar: el plugin usa la llave de Gemini.";
82
+ const VertexSettings = ({ status, onSave, onRemove }) => {
83
+ const [text, setText] = useState("");
84
+ const [error, setError] = useState(null);
85
+ const [busy, setBusy] = useState(false);
86
+ const save = async () => {
87
+ setBusy(true);
88
+ setError(null);
89
+ try {
90
+ await onSave(text);
91
+ setText("");
92
+ } catch (err) {
93
+ setError(err instanceof Error ? err.message : "No se pudo guardar la cuenta de servicio.");
94
+ } finally {
95
+ setBusy(false);
96
+ }
97
+ };
98
+ const remove = async () => {
99
+ setBusy(true);
100
+ try {
101
+ await onRemove();
102
+ } finally {
103
+ setBusy(false);
104
+ }
105
+ };
106
+ return /* @__PURE__ */ jsx(Box, { padding: 6, margin: 6, background: "neutral0", width: "100%", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
107
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "start", gap: 1, children: [
108
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: "Vertex AI" }),
109
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: statusLine(status) })
110
+ ] }),
111
+ /* @__PURE__ */ jsxs(
112
+ Field.Root,
113
+ {
114
+ id: "vertexServiceAccount",
115
+ error: error ?? void 0,
116
+ hint: "Pega el contenido completo del archivo .json de la cuenta de servicio. La llave privada no vuelve a mostrarse.",
117
+ children: [
118
+ /* @__PURE__ */ jsx(Field.Label, { children: "JSON de la cuenta de servicio" }),
119
+ /* @__PURE__ */ jsx(
120
+ Textarea,
121
+ {
122
+ name: "vertexServiceAccount",
123
+ value: text,
124
+ onChange: (e) => setText(e.target.value),
125
+ placeholder: '{ "type": "service_account", … }'
126
+ }
127
+ ),
128
+ /* @__PURE__ */ jsx(Field.Hint, {}),
129
+ /* @__PURE__ */ jsx(Field.Error, {})
130
+ ]
131
+ }
132
+ ),
133
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "end", gap: 2, children: [
134
+ status.configured && /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: remove, disabled: busy, children: "Quitar cuenta de servicio" }),
135
+ /* @__PURE__ */ jsx(Button, { onClick: save, disabled: !text.trim() || busy, loading: busy, children: "Guardar cuenta de servicio" })
136
+ ] })
137
+ ] }) });
138
+ };
78
139
  const NOT_CONFIGURED = { configured: false, last4: null };
140
+ const VERTEX_OFF = { configured: false, projectId: null, clientEmail: null };
141
+ const serverMessage = (error, fallback) => error?.response?.data?.error?.message ?? fallback;
79
142
  const initialStatus = {
80
143
  googleGenAI: NOT_CONFIGURED,
81
144
  linkedInAccessToken: NOT_CONFIGURED,
@@ -85,8 +148,9 @@ const initialStatus = {
85
148
  };
86
149
  const SettingsContainer = () => {
87
150
  const [status, setStatus] = useState(initialStatus);
151
+ const [vertex, setVertex] = useState(VERTEX_OFF);
88
152
  const { formatMessage } = useIntl();
89
- const { getSettings, setSettings } = useSettings();
153
+ const { getSettings, setSettings, removeVertex } = useSettings();
90
154
  const { toggleNotification } = useNotification();
91
155
  const fetchSettings = useCallback(async () => {
92
156
  let isMounted = true;
@@ -94,6 +158,7 @@ const SettingsContainer = () => {
94
158
  const { data } = await getSettings();
95
159
  if (isMounted) {
96
160
  setStatus(data);
161
+ setVertex(data.vertex ?? VERTEX_OFF);
97
162
  }
98
163
  } catch (error) {
99
164
  toggleNotification({
@@ -132,14 +197,36 @@ const SettingsContainer = () => {
132
197
  },
133
198
  [setSettings, fetchSettings]
134
199
  );
200
+ const saveVertex = useCallback(
201
+ async (json) => {
202
+ try {
203
+ await setSettings({ vertexServiceAccount: json });
204
+ } catch (error) {
205
+ throw new Error(serverMessage(error, "No se pudo guardar la cuenta de servicio."));
206
+ }
207
+ await fetchSettings();
208
+ toggleNotification({ type: "success", message: "Cuenta de servicio de Vertex AI guardada." });
209
+ },
210
+ [setSettings, fetchSettings]
211
+ );
212
+ const deleteVertex = useCallback(async () => {
213
+ try {
214
+ await removeVertex();
215
+ await fetchSettings();
216
+ toggleNotification({ type: "success", message: "Cuenta de servicio quitada: el plugin usa la llave de Gemini." });
217
+ } catch {
218
+ toggleNotification({ type: "danger", message: "No se pudo quitar la cuenta de servicio." });
219
+ }
220
+ }, [removeVertex, fetchSettings]);
135
221
  useEffect(() => {
136
222
  fetchSettings();
137
223
  }, []);
138
- return /* @__PURE__ */ jsx(DesignSystemProvider, { locale: "es-MX", children: /* @__PURE__ */ jsxs(Grid.Root, { padding: 6, gap: 3, children: [
224
+ return /* @__PURE__ */ jsx(PluginProviders, { children: /* @__PURE__ */ jsxs(Grid.Root, { padding: 6, gap: 3, children: [
139
225
  /* @__PURE__ */ jsx(Grid.Item, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "start", children: [
140
226
  /* @__PURE__ */ jsx(Typography, { variant: "alpha", children: formatMessage({ id: getTranslation("plugin.name") }) }),
141
227
  /* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Para uso exclusivo de InterWare de México" })
142
228
  ] }) }),
229
+ /* @__PURE__ */ jsx(Grid.Item, { children: /* @__PURE__ */ jsx(VertexSettings, { status: vertex, onSave: saveVertex, onRemove: deleteVertex }) }),
143
230
  /* @__PURE__ */ jsx(Grid.Item, { children: /* @__PURE__ */ jsx(Form, { status, handleSubmit }) })
144
231
  ] }) });
145
232
  };
@@ -3,14 +3,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const admin = require("@strapi/strapi/admin");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const ImageStudioTabs = require("./ImageStudioTabs-B2UbKYq7.js");
7
- const index = require("./index-Ddp0Qvqo.js");
6
+ const PluginProviders = require("./PluginProviders-D79TeGSE.js");
7
+ const index = require("./index-BKhe-Jyx.js");
8
8
  const designSystem = require("@strapi/design-system");
9
+ const ImageStudioTabs = require("./ImageStudioTabs-DtusqpQO.js");
9
10
  const ImageStudio = () => /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Main, { children: [
10
11
  /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Title, { children: "Estudio de imágenes" }),
11
12
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { height: "100vh" }, children: /* @__PURE__ */ jsxRuntime.jsx(ImageStudioTabs.ImageStudioTabs, {}) })
12
13
  ] });
13
- const StudioApp = () => /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: [...index.pluginPermissions.access], children: /* @__PURE__ */ jsxRuntime.jsx(ImageStudioTabs.PluginProviders, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
14
+ const StudioApp = () => /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: [...index.pluginPermissions.access], children: /* @__PURE__ */ jsxRuntime.jsx(PluginProviders.PluginProviders, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
14
15
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(ImageStudio, {}) }),
15
16
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) })
16
17
  ] }) }) });
@@ -1,9 +1,10 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { Page } from "@strapi/strapi/admin";
3
3
  import { Routes, Route } from "react-router-dom";
4
- import { I as ImageStudioTabs, P as PluginProviders } from "./ImageStudioTabs-mlNL6aQ2.mjs";
5
- import { p as pluginPermissions } from "./index-CqDdi211.mjs";
4
+ import { P as PluginProviders } from "./PluginProviders-DWMpcAIh.mjs";
5
+ import { p as pluginPermissions } from "./index-BKigRXm3.mjs";
6
6
  import { Box } from "@strapi/design-system";
7
+ import { I as ImageStudioTabs } from "./ImageStudioTabs-BLAH3KYv.mjs";
7
8
  const ImageStudio = () => /* @__PURE__ */ jsxs(Page.Main, { children: [
8
9
  /* @__PURE__ */ jsx(Page.Title, { children: "Estudio de imágenes" }),
9
10
  /* @__PURE__ */ jsx(Box, { style: { height: "100vh" }, children: /* @__PURE__ */ jsx(ImageStudioTabs, {}) })
@@ -1,4 +1,4 @@
1
- import { P as PLUGIN_ID } from "./index-CqDdi211.mjs";
1
+ import { P as PLUGIN_ID } from "./index-BKigRXm3.mjs";
2
2
  const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
3
3
  export {
4
4
  getTranslation as g
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
- const index = require("./index-Ddp0Qvqo.js");
2
+ const index = require("./index-BKhe-Jyx.js");
3
3
  const getTranslation = (id) => `${index.PLUGIN_ID}.${id}`;
4
4
  exports.getTranslation = getTranslation;