@lv-x-software-house/x_view 1.2.6-dev.65 → 1.2.6-dev.67

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 (3) hide show
  1. package/dist/index.js +252 -44
  2. package/dist/index.mjs +252 -44
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3966,6 +3966,11 @@ function XViewSidebar({
3966
3966
  onOpenMilestoneManager = () => {
3967
3967
  },
3968
3968
  onActivateReshapeLens = () => {
3969
+ },
3970
+ view_google_folder_id,
3971
+ view_google_folder_name,
3972
+ open_google_picker_action,
3973
+ onSaveConfig = () => {
3969
3974
  }
3970
3975
  }) {
3971
3976
  const [query, setQuery] = (0, import_react3.useState)("");
@@ -3986,6 +3991,17 @@ function XViewSidebar({
3986
3991
  const [reshapeCenterNodeId, setReshapeCenterNodeId] = (0, import_react3.useState)("");
3987
3992
  const [isTypeDropdownOpen, setIsTypeDropdownOpen] = (0, import_react3.useState)(false);
3988
3993
  const [highlightedTypeIndex, setHighlightedTypeIndex] = (0, import_react3.useState)(-1);
3994
+ const [folderId, setFolderId] = (0, import_react3.useState)(view_google_folder_id || "");
3995
+ const [folderName, setFolderName] = (0, import_react3.useState)(view_google_folder_name || "");
3996
+ const [isPickingGoogleFolder, setIsPickingGoogleFolder] = (0, import_react3.useState)(false);
3997
+ (0, import_react3.useEffect)(() => {
3998
+ if (view_google_folder_id !== void 0) {
3999
+ setFolderId(view_google_folder_id || "");
4000
+ }
4001
+ if (view_google_folder_name !== void 0) {
4002
+ setFolderName(view_google_folder_name || "");
4003
+ }
4004
+ }, [view_google_folder_id, view_google_folder_name]);
3989
4005
  const containerRef = (0, import_react3.useRef)(null);
3990
4006
  const inputRef = (0, import_react3.useRef)(null);
3991
4007
  const filterMenuRef = (0, import_react3.useRef)(null);
@@ -4691,7 +4707,46 @@ function XViewSidebar({
4691
4707
  className: buttonBaseClass
4692
4708
  },
4693
4709
  "Gerenciar Milestones"
4694
- ))),
4710
+ )), userRole === "owner" && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Google Drive"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center justify-between bg-slate-900/50 p-2 rounded-md border border-white/5" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex flex-col truncate" }, /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold" }, "Pasta Atual"), /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-xs text-indigo-200 truncate", title: folderId ? folderId : "Padr\xE3o do Criador" }, folderName ? folderName : folderId ? folderId : "Padr\xE3o do Criador")), folderId && /* @__PURE__ */ import_react3.default.createElement(
4711
+ "button",
4712
+ {
4713
+ title: "Remover v\xEDnculo da pasta",
4714
+ onClick: () => {
4715
+ setFolderId("");
4716
+ setFolderName("");
4717
+ onSaveConfig({ view_google_folder_id: "", view_google_folder_name: "" });
4718
+ },
4719
+ className: "p-1 hover:bg-red-500/20 text-slate-400 hover:text-red-400 rounded transition-colors"
4720
+ },
4721
+ /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }))
4722
+ )), /* @__PURE__ */ import_react3.default.createElement(
4723
+ "button",
4724
+ {
4725
+ onClick: async () => {
4726
+ if (!open_google_picker_action) return;
4727
+ setIsPickingGoogleFolder(true);
4728
+ try {
4729
+ const result = await open_google_picker_action();
4730
+ if (result && result.folderId) {
4731
+ setFolderId(result.folderId);
4732
+ setFolderName(result.folderName || "");
4733
+ onSaveConfig({
4734
+ view_google_folder_id: result.folderId,
4735
+ view_google_folder_name: result.folderName || ""
4736
+ });
4737
+ }
4738
+ } catch (e) {
4739
+ console.error("Erro ao selecionar pasta Google Drive", e);
4740
+ alert("Erro ao abrir Picker. Verifique o console.");
4741
+ } finally {
4742
+ setIsPickingGoogleFolder(false);
4743
+ }
4744
+ },
4745
+ disabled: isPickingGoogleFolder,
4746
+ className: "w-full px-3 py-2 rounded-md bg-indigo-600/20 hover:bg-indigo-600/40 border border-indigo-500/50 text-xs text-indigo-100 transition-colors flex items-center justify-center gap-2 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
4747
+ },
4748
+ isPickingGoogleFolder ? /* @__PURE__ */ import_react3.default.createElement("svg", { className: "animate-spin h-4 w-4 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react3.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react3.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })) : "Selecionar Pasta no Drive"
4749
+ ), /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[9px] text-slate-500 italic" }, "Documentos criados nesta View ser\xE3o salvos nesta pasta."))))),
4695
4750
  /* @__PURE__ */ import_react3.default.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/30" }, /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Navega\xE7\xE3o"), ability.can("update", "Scene") && /* @__PURE__ */ import_react3.default.createElement(
4696
4751
  "button",
4697
4752
  {
@@ -8987,7 +9042,8 @@ function InSceneCreationForm({
8987
9042
  availableDatasets = [],
8988
9043
  sourceNodeDatasetId,
8989
9044
  viewType,
8990
- create_google_doc_action
9045
+ create_google_doc_action,
9046
+ view_google_folder_id
8991
9047
  }) {
8992
9048
  var _a;
8993
9049
  const [name, setName] = (0, import_react15.useState)("");
@@ -9008,6 +9064,7 @@ function InSceneCreationForm({
9008
9064
  );
9009
9065
  const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = (0, import_react15.useState)(false);
9010
9066
  const [isLoadingDocs, setIsLoadingDocs] = (0, import_react15.useState)(false);
9067
+ const [docError, setDocError] = (0, import_react15.useState)(null);
9011
9068
  const datasetDropdownRef = (0, import_react15.useRef)(null);
9012
9069
  (0, import_react15.useEffect)(() => {
9013
9070
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
@@ -9154,7 +9211,8 @@ function InSceneCreationForm({
9154
9211
  if (!create_google_doc_action) return;
9155
9212
  try {
9156
9213
  setIsLoadingDocs(true);
9157
- const res = await create_google_doc_action(name);
9214
+ setDocError(null);
9215
+ const res = await create_google_doc_action(name, view_google_folder_id);
9158
9216
  if (res.success) {
9159
9217
  const existingLinksPropIndex = customProps.findIndex(
9160
9218
  (p) => p.type === "links" && p.key === "Links"
@@ -9181,11 +9239,21 @@ function InSceneCreationForm({
9181
9239
  window.open(res.link, "_blank");
9182
9240
  }
9183
9241
  } else {
9184
- alert("Erro ao criar documento: " + res.error);
9242
+ if (res.errorType === "PERMISSIONS_ERROR") {
9243
+ setDocError(
9244
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
9245
+ );
9246
+ } else {
9247
+ setDocError(
9248
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
9249
+ );
9250
+ }
9185
9251
  }
9186
9252
  } catch (error) {
9187
9253
  console.error(error);
9188
- alert("Erro ao processar cria\xE7\xE3o do documento.");
9254
+ setDocError(
9255
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
9256
+ );
9189
9257
  } finally {
9190
9258
  setIsLoadingDocs(false);
9191
9259
  }
@@ -9429,7 +9497,14 @@ function InSceneCreationForm({
9429
9497
  className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}`
9430
9498
  },
9431
9499
  useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Selecione a cor e ajuste o brilho."
9432
- )), /* @__PURE__ */ import_react15.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react15.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ import_react15.default.createElement(
9500
+ )), /* @__PURE__ */ import_react15.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react15.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ import_react15.default.createElement(
9501
+ "p",
9502
+ {
9503
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
9504
+ title: docError
9505
+ },
9506
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
9507
+ ) : /* @__PURE__ */ import_react15.default.createElement(
9433
9508
  "button",
9434
9509
  {
9435
9510
  type: "button",
@@ -9438,8 +9513,20 @@ function InSceneCreationForm({
9438
9513
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
9439
9514
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
9440
9515
  },
9441
- isLoadingDocs ? /* @__PURE__ */ import_react15.default.createElement(import_ai.AiOutlineLoading3Quarters, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ import_react15.default.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
9442
- ), /* @__PURE__ */ import_react15.default.createElement(
9516
+ isLoadingDocs ? /* @__PURE__ */ import_react15.default.createElement(
9517
+ import_ai.AiOutlineLoading3Quarters,
9518
+ {
9519
+ className: "animate-spin",
9520
+ size: 18
9521
+ }
9522
+ ) : /* @__PURE__ */ import_react15.default.createElement(
9523
+ GoogleDocsIcon_default,
9524
+ {
9525
+ size: 18,
9526
+ className: "group-hover:scale-110 transition-transform"
9527
+ }
9528
+ )
9529
+ )), /* @__PURE__ */ import_react15.default.createElement(
9443
9530
  "button",
9444
9531
  {
9445
9532
  type: "button",
@@ -10000,7 +10087,8 @@ function InSceneQuestForm({
10000
10087
  milestones = [],
10001
10088
  onUpdateMilestones = () => {
10002
10089
  },
10003
- create_google_doc_action
10090
+ create_google_doc_action,
10091
+ view_google_folder_id
10004
10092
  }) {
10005
10093
  var _a, _b;
10006
10094
  const [name, setName] = (0, import_react18.useState)("");
@@ -10029,6 +10117,7 @@ function InSceneQuestForm({
10029
10117
  const [assigneeSearchQuery, setAssigneeSearchQuery] = (0, import_react18.useState)("");
10030
10118
  const [isNameCopied, setIsNameCopied] = (0, import_react18.useState)(false);
10031
10119
  const [isLoadingDocs, setIsLoadingDocs] = (0, import_react18.useState)(false);
10120
+ const [docError, setDocError] = (0, import_react18.useState)(null);
10032
10121
  const [customProps, setCustomProps] = (0, import_react18.useState)([]);
10033
10122
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react18.useState)(false);
10034
10123
  const propsEndRef = (0, import_react18.useRef)(null);
@@ -10124,7 +10213,8 @@ function InSceneQuestForm({
10124
10213
  if (!create_google_doc_action) return;
10125
10214
  try {
10126
10215
  setIsLoadingDocs(true);
10127
- const res = await create_google_doc_action(standardizedName);
10216
+ setDocError(null);
10217
+ const res = await create_google_doc_action(standardizedName, view_google_folder_id);
10128
10218
  if (res.success) {
10129
10219
  const existingLinksPropIndex = customProps.findIndex(
10130
10220
  (p) => p.type === "links" && p.key === "Links"
@@ -10151,11 +10241,21 @@ function InSceneQuestForm({
10151
10241
  window.open(res.link, "_blank");
10152
10242
  }
10153
10243
  } else {
10154
- alert("Erro ao criar documento: " + res.error);
10244
+ if (res.errorType === "PERMISSIONS_ERROR") {
10245
+ setDocError(
10246
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
10247
+ );
10248
+ } else {
10249
+ setDocError(
10250
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
10251
+ );
10252
+ }
10155
10253
  }
10156
10254
  } catch (error) {
10157
10255
  console.error(error);
10158
- alert("Erro ao processar cria\xE7\xE3o do documento.");
10256
+ setDocError(
10257
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
10258
+ );
10159
10259
  } finally {
10160
10260
  setIsLoadingDocs(false);
10161
10261
  }
@@ -10678,7 +10778,14 @@ function InSceneQuestForm({
10678
10778
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
10679
10779
  },
10680
10780
  "Adicionar descri\xE7\xE3o..."
10681
- ))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react18.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ import_react18.default.createElement(
10781
+ ))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react18.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ import_react18.default.createElement(
10782
+ "p",
10783
+ {
10784
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
10785
+ title: docError
10786
+ },
10787
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
10788
+ ) : /* @__PURE__ */ import_react18.default.createElement(
10682
10789
  "button",
10683
10790
  {
10684
10791
  type: "button",
@@ -10687,8 +10794,20 @@ function InSceneQuestForm({
10687
10794
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
10688
10795
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
10689
10796
  },
10690
- isLoadingDocs ? /* @__PURE__ */ import_react18.default.createElement(import_ai2.AiOutlineLoading3Quarters, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ import_react18.default.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
10691
- ), /* @__PURE__ */ import_react18.default.createElement(
10797
+ isLoadingDocs ? /* @__PURE__ */ import_react18.default.createElement(
10798
+ import_ai2.AiOutlineLoading3Quarters,
10799
+ {
10800
+ className: "animate-spin",
10801
+ size: 18
10802
+ }
10803
+ ) : /* @__PURE__ */ import_react18.default.createElement(
10804
+ GoogleDocsIcon_default,
10805
+ {
10806
+ size: 18,
10807
+ className: "group-hover:scale-110 transition-transform"
10808
+ }
10809
+ )
10810
+ )), /* @__PURE__ */ import_react18.default.createElement(
10692
10811
  "button",
10693
10812
  {
10694
10813
  type: "button",
@@ -10819,7 +10938,8 @@ function NodeDetailsPanel({
10819
10938
  onUploadFile,
10820
10939
  userRole,
10821
10940
  currentDatasetName,
10822
- create_google_doc_action
10941
+ create_google_doc_action,
10942
+ view_google_folder_id
10823
10943
  }) {
10824
10944
  const [name, setName] = (0, import_react19.useState)((node == null ? void 0 : node.name) ?? "");
10825
10945
  const [types, setTypes] = (0, import_react19.useState)([]);
@@ -10836,6 +10956,7 @@ function NodeDetailsPanel({
10836
10956
  const [existingSections, setExistingSections] = (0, import_react19.useState)((node == null ? void 0 : node.description_sections) || []);
10837
10957
  const [isSaving, setIsSaving] = (0, import_react19.useState)(false);
10838
10958
  const [isLoadingDocs, setIsLoadingDocs] = (0, import_react19.useState)(false);
10959
+ const [docError, setDocError] = (0, import_react19.useState)(null);
10839
10960
  const [isLinkCopied, setIsLinkCopied] = (0, import_react19.useState)(false);
10840
10961
  const [useImageAsTexture, setUseImageAsTexture] = (0, import_react19.useState)(() => {
10841
10962
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
@@ -10998,7 +11119,8 @@ function NodeDetailsPanel({
10998
11119
  if (!create_google_doc_action) return;
10999
11120
  try {
11000
11121
  setIsLoadingDocs(true);
11001
- const res = await create_google_doc_action(name);
11122
+ setDocError(null);
11123
+ const res = await create_google_doc_action(name, view_google_folder_id);
11002
11124
  if (res.success) {
11003
11125
  const existingLinksPropIndex = customProps.findIndex(
11004
11126
  (p) => p.type === "links" && p.key === "Links"
@@ -11028,11 +11150,21 @@ function NodeDetailsPanel({
11028
11150
  window.open(res.link, "_blank");
11029
11151
  }
11030
11152
  } else {
11031
- alert("Erro ao criar documento: " + res.error);
11153
+ if (res.errorType === "PERMISSIONS_ERROR") {
11154
+ setDocError(
11155
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
11156
+ );
11157
+ } else {
11158
+ setDocError(
11159
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
11160
+ );
11161
+ }
11032
11162
  }
11033
11163
  } catch (error) {
11034
11164
  console.error(error);
11035
- alert("Erro ao processar cria\xE7\xE3o do documento.");
11165
+ setDocError(
11166
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
11167
+ );
11036
11168
  } finally {
11037
11169
  setIsLoadingDocs(false);
11038
11170
  }
@@ -11313,7 +11445,14 @@ function NodeDetailsPanel({
11313
11445
  className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
11314
11446
  title: `Intensidade do brilho: ${intensity}`
11315
11447
  }
11316
- ), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react19.default.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ import_react19.default.createElement(
11448
+ ), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react19.default.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ import_react19.default.createElement(
11449
+ "p",
11450
+ {
11451
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
11452
+ title: docError
11453
+ },
11454
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
11455
+ ) : /* @__PURE__ */ import_react19.default.createElement(
11317
11456
  "button",
11318
11457
  {
11319
11458
  type: "button",
@@ -11322,8 +11461,20 @@ function NodeDetailsPanel({
11322
11461
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
11323
11462
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
11324
11463
  },
11325
- isLoadingDocs ? /* @__PURE__ */ import_react19.default.createElement(import_ai3.AiOutlineLoading3Quarters, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ import_react19.default.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
11326
- ), canEdit && /* @__PURE__ */ import_react19.default.createElement(
11464
+ isLoadingDocs ? /* @__PURE__ */ import_react19.default.createElement(
11465
+ import_ai3.AiOutlineLoading3Quarters,
11466
+ {
11467
+ className: "animate-spin",
11468
+ size: 18
11469
+ }
11470
+ ) : /* @__PURE__ */ import_react19.default.createElement(
11471
+ GoogleDocsIcon_default,
11472
+ {
11473
+ size: 18,
11474
+ className: "group-hover:scale-110 transition-transform"
11475
+ }
11476
+ )
11477
+ )), canEdit && /* @__PURE__ */ import_react19.default.createElement(
11327
11478
  "button",
11328
11479
  {
11329
11480
  type: "button",
@@ -11486,7 +11637,8 @@ function QuestDetailsPanel({
11486
11637
  onUpdateMilestones = () => {
11487
11638
  },
11488
11639
  onFocusNode,
11489
- create_google_doc_action
11640
+ create_google_doc_action,
11641
+ view_google_folder_id
11490
11642
  }) {
11491
11643
  var _a, _b;
11492
11644
  const initialRawTitle = (node == null ? void 0 : node.raw_title) || (((_a = node == null ? void 0 : node.name) == null ? void 0 : _a.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
@@ -11521,6 +11673,7 @@ function QuestDetailsPanel({
11521
11673
  const [isLinkCopied, setIsLinkCopied] = (0, import_react21.useState)(false);
11522
11674
  const [isNameCopied, setIsNameCopied] = (0, import_react21.useState)(false);
11523
11675
  const [isLoadingDocs, setIsLoadingDocs] = (0, import_react21.useState)(false);
11676
+ const [docError, setDocError] = (0, import_react21.useState)(null);
11524
11677
  const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react21.useState)(false);
11525
11678
  const [questDate, setQuestDate] = (0, import_react21.useState)((node == null ? void 0 : node.Date) || null);
11526
11679
  const [noteText, setNoteText] = (0, import_react21.useState)("");
@@ -11929,7 +12082,8 @@ ${noteText}` : noteText : entry.notes,
11929
12082
  if (!create_google_doc_action) return;
11930
12083
  try {
11931
12084
  setIsLoadingDocs(true);
11932
- const res = await create_google_doc_action(standardizedName);
12085
+ setDocError(null);
12086
+ const res = await create_google_doc_action(standardizedName, view_google_folder_id);
11933
12087
  if (res.success) {
11934
12088
  const existingLinksPropIndex = customProps.findIndex(
11935
12089
  (p) => p.type === "links" && p.key === "Links"
@@ -11959,11 +12113,21 @@ ${noteText}` : noteText : entry.notes,
11959
12113
  window.open(res.link, "_blank");
11960
12114
  }
11961
12115
  } else {
11962
- alert("Erro ao criar documento: " + res.error);
12116
+ if (res.errorType === "PERMISSIONS_ERROR") {
12117
+ setDocError(
12118
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
12119
+ );
12120
+ } else {
12121
+ setDocError(
12122
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
12123
+ );
12124
+ }
11963
12125
  }
11964
12126
  } catch (error) {
11965
12127
  console.error(error);
11966
- alert("Erro ao processar cria\xE7\xE3o do documento.");
12128
+ setDocError(
12129
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
12130
+ );
11967
12131
  } finally {
11968
12132
  setIsLoadingDocs(false);
11969
12133
  }
@@ -12573,7 +12737,14 @@ ${noteText}` : noteText : entry.notes,
12573
12737
  },
12574
12738
  /* @__PURE__ */ import_react21.default.createElement("span", { className: "truncate" }, q.raw_title || q.name),
12575
12739
  /* @__PURE__ */ import_react21.default.createElement("span", { className: `text-[10px] px-1.5 py-0.5 rounded border ${q.status === "Done" ? "text-green-400 border-green-500/30" : "text-slate-500 border-white/5"}` }, q.status || "Backlog")
12576
- )) : /* @__PURE__ */ import_react21.default.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ import_react21.default.createElement(import_fi19.FiRepeat, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ import_react21.default.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react21.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ import_react21.default.createElement(
12740
+ )) : /* @__PURE__ */ import_react21.default.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ import_react21.default.createElement(import_fi19.FiRepeat, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ import_react21.default.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react21.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ import_react21.default.createElement(
12741
+ "p",
12742
+ {
12743
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
12744
+ title: docError
12745
+ },
12746
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
12747
+ ) : /* @__PURE__ */ import_react21.default.createElement(
12577
12748
  "button",
12578
12749
  {
12579
12750
  type: "button",
@@ -12582,8 +12753,20 @@ ${noteText}` : noteText : entry.notes,
12582
12753
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
12583
12754
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
12584
12755
  },
12585
- isLoadingDocs ? /* @__PURE__ */ import_react21.default.createElement(import_ai4.AiOutlineLoading3Quarters, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ import_react21.default.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
12586
- ), canEdit && /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react21.default.createElement(import_fi19.FiPlus, { size: 14 }), " Adicionar"))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react21.default.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ import_react21.default.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ import_react21.default.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ import_react21.default.createElement(
12756
+ isLoadingDocs ? /* @__PURE__ */ import_react21.default.createElement(
12757
+ import_ai4.AiOutlineLoading3Quarters,
12758
+ {
12759
+ className: "animate-spin",
12760
+ size: 18
12761
+ }
12762
+ ) : /* @__PURE__ */ import_react21.default.createElement(
12763
+ GoogleDocsIcon_default,
12764
+ {
12765
+ size: 18,
12766
+ className: "group-hover:scale-110 transition-transform"
12767
+ }
12768
+ )
12769
+ )), canEdit && /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react21.default.createElement(import_fi19.FiPlus, { size: 14 }), " Adicionar"))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react21.default.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ import_react21.default.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ import_react21.default.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ import_react21.default.createElement(
12587
12770
  "button",
12588
12771
  {
12589
12772
  type: "button",
@@ -14822,9 +15005,10 @@ function XViewScene({
14822
15005
  delete_file_action,
14823
15006
  check_user_permission,
14824
15007
  get_view_members,
14825
- create_google_doc_action
15008
+ create_google_doc_action,
15009
+ open_google_picker_action
14826
15010
  }) {
14827
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
15011
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
14828
15012
  const { data: session, status } = (0, import_react33.useSession)();
14829
15013
  const router = (0, import_navigation.useRouter)();
14830
15014
  const searchParams = (0, import_navigation.useSearchParams)();
@@ -15201,6 +15385,23 @@ function XViewScene({
15201
15385
  add_new_parent_file_to_scene_at_firebase_action
15202
15386
  ]
15203
15387
  );
15388
+ const handleSaveConfig = (0, import_react32.useCallback)(
15389
+ async (newConfig) => {
15390
+ if (!sceneDataRef.current || !save_view_data || !sceneSaveUrl) return;
15391
+ const updatedData = {
15392
+ ...sceneDataRef.current,
15393
+ ...newConfig
15394
+ };
15395
+ sceneDataRef.current = updatedData;
15396
+ try {
15397
+ await save_view_data(sceneSaveUrl, updatedData);
15398
+ setSceneVersion((v) => v + 1);
15399
+ } catch (error) {
15400
+ console.error("Erro ao salvar configura\xE7\xE3o da View:", error);
15401
+ }
15402
+ },
15403
+ [save_view_data, sceneSaveUrl]
15404
+ );
15204
15405
  const handleOpenImageViewer = (images, startIndex) => {
15205
15406
  setImageViewer({ visible: true, images, startIndex });
15206
15407
  };
@@ -19504,13 +19705,16 @@ function XViewScene({
19504
19705
  onOpenBoards: handleOpenBoards,
19505
19706
  viewType: viewParams == null ? void 0 : viewParams.type,
19506
19707
  viewName: viewParams == null ? void 0 : viewParams.name,
19507
- onNavigateBack: handleNavigateBack,
19708
+ milestones: (viewParams == null ? void 0 : viewParams.milestones) || [],
19709
+ onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true),
19710
+ view_google_folder_id: viewParams == null ? void 0 : viewParams.view_google_folder_id,
19711
+ view_google_folder_name: viewParams == null ? void 0 : viewParams.view_google_folder_name,
19712
+ open_google_picker_action,
19713
+ onSaveConfig: handleSaveConfig,
19508
19714
  isOpen: isSidebarOpen,
19509
19715
  onToggle: setIsSidebarOpen,
19510
19716
  userRole: userPermissionRole,
19511
- viewMembers,
19512
- milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
19513
- onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
19717
+ viewMembers
19514
19718
  }
19515
19719
  ),
19516
19720
  creationMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
@@ -19534,8 +19738,8 @@ function XViewScene({
19534
19738
  },
19535
19739
  refEl: formRef,
19536
19740
  existingTypes: existingNodeTypes,
19537
- initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
19538
- sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
19741
+ initialColor: (_c = creationMode.sourceNodeData) == null ? void 0 : _c.color,
19742
+ sourceTypes: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.type,
19539
19743
  onIntensityChange: handleGhostNodeIntensityChange,
19540
19744
  onUploadFile: upload_file_action,
19541
19745
  availableDatasets,
@@ -19543,7 +19747,8 @@ function XViewScene({
19543
19747
  viewType: viewParams == null ? void 0 : viewParams.type,
19544
19748
  availableNodes: allAvailableNodes,
19545
19749
  availableAncestries: allAvailableAncestries,
19546
- create_google_doc_action
19750
+ create_google_doc_action,
19751
+ view_google_folder_id: (_e = sceneDataRef.current) == null ? void 0 : _e.view_google_folder_id
19547
19752
  }
19548
19753
  ),
19549
19754
  versionMode.isActive && /* @__PURE__ */ import_react32.default.createElement(
@@ -19598,7 +19803,8 @@ function XViewScene({
19598
19803
  viewMembers,
19599
19804
  milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
19600
19805
  onUpdateMilestones: handleUpdateMilestones,
19601
- create_google_doc_action
19806
+ create_google_doc_action,
19807
+ view_google_folder_id: (_j = sceneDataRef.current) == null ? void 0 : _j.view_google_folder_id
19602
19808
  }
19603
19809
  ),
19604
19810
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react32.default.createElement(
@@ -19732,9 +19938,10 @@ function XViewScene({
19732
19938
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
19733
19939
  viewMembers,
19734
19940
  currentUser: session == null ? void 0 : session.user,
19735
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
19941
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
19736
19942
  onUpdateMilestones: handleUpdateMilestones,
19737
- create_google_doc_action
19943
+ create_google_doc_action,
19944
+ view_google_folder_id: (_l = sceneDataRef.current) == null ? void 0 : _l.view_google_folder_id
19738
19945
  }
19739
19946
  ),
19740
19947
  detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react32.default.createElement(
@@ -19767,7 +19974,8 @@ function XViewScene({
19767
19974
  onUploadFile: upload_file_action,
19768
19975
  userRole: userPermissionRole,
19769
19976
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
19770
- create_google_doc_action
19977
+ create_google_doc_action,
19978
+ view_google_folder_id: (_m = sceneDataRef.current) == null ? void 0 : _m.view_google_folder_id
19771
19979
  }
19772
19980
  ),
19773
19981
  detailsLink && /* @__PURE__ */ import_react32.default.createElement(
@@ -19925,7 +20133,7 @@ function XViewScene({
19925
20133
  {
19926
20134
  isOpen: isMilestoneManagerOpen,
19927
20135
  onClose: () => setIsMilestoneManagerOpen(false),
19928
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
20136
+ milestones: ((_n = sceneDataRef.current) == null ? void 0 : _n.milestones) || [],
19929
20137
  onUpdateMilestones: handleUpdateMilestones
19930
20138
  }
19931
20139
  ),
@@ -19936,7 +20144,7 @@ function XViewScene({
19936
20144
  onClose: () => setIsImportModalOpen(false),
19937
20145
  onConfirm: handleConfirmImport,
19938
20146
  session,
19939
- parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
20147
+ parentDbs: ((_o = sceneDataRef.current) == null ? void 0 : _o.parent_dbs) || [],
19940
20148
  onFetchAvailableFiles: import_parent_file_modal_get,
19941
20149
  currentViewName: viewParams == null ? void 0 : viewParams.name,
19942
20150
  currentAncestries: ancestryDataRef.current || []
package/dist/index.mjs CHANGED
@@ -3927,6 +3927,11 @@ function XViewSidebar({
3927
3927
  onOpenMilestoneManager = () => {
3928
3928
  },
3929
3929
  onActivateReshapeLens = () => {
3930
+ },
3931
+ view_google_folder_id,
3932
+ view_google_folder_name,
3933
+ open_google_picker_action,
3934
+ onSaveConfig = () => {
3930
3935
  }
3931
3936
  }) {
3932
3937
  const [query, setQuery] = useState3("");
@@ -3947,6 +3952,17 @@ function XViewSidebar({
3947
3952
  const [reshapeCenterNodeId, setReshapeCenterNodeId] = useState3("");
3948
3953
  const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState3(false);
3949
3954
  const [highlightedTypeIndex, setHighlightedTypeIndex] = useState3(-1);
3955
+ const [folderId, setFolderId] = useState3(view_google_folder_id || "");
3956
+ const [folderName, setFolderName] = useState3(view_google_folder_name || "");
3957
+ const [isPickingGoogleFolder, setIsPickingGoogleFolder] = useState3(false);
3958
+ useEffect2(() => {
3959
+ if (view_google_folder_id !== void 0) {
3960
+ setFolderId(view_google_folder_id || "");
3961
+ }
3962
+ if (view_google_folder_name !== void 0) {
3963
+ setFolderName(view_google_folder_name || "");
3964
+ }
3965
+ }, [view_google_folder_id, view_google_folder_name]);
3950
3966
  const containerRef = useRef2(null);
3951
3967
  const inputRef = useRef2(null);
3952
3968
  const filterMenuRef = useRef2(null);
@@ -4652,7 +4668,46 @@ function XViewSidebar({
4652
4668
  className: buttonBaseClass
4653
4669
  },
4654
4670
  "Gerenciar Milestones"
4655
- ))),
4671
+ )), userRole === "owner" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ React2.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Google Drive"), /* @__PURE__ */ React2.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between bg-slate-900/50 p-2 rounded-md border border-white/5" }, /* @__PURE__ */ React2.createElement("div", { className: "flex flex-col truncate" }, /* @__PURE__ */ React2.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold" }, "Pasta Atual"), /* @__PURE__ */ React2.createElement("span", { className: "text-xs text-indigo-200 truncate", title: folderId ? folderId : "Padr\xE3o do Criador" }, folderName ? folderName : folderId ? folderId : "Padr\xE3o do Criador")), folderId && /* @__PURE__ */ React2.createElement(
4672
+ "button",
4673
+ {
4674
+ title: "Remover v\xEDnculo da pasta",
4675
+ onClick: () => {
4676
+ setFolderId("");
4677
+ setFolderName("");
4678
+ onSaveConfig({ view_google_folder_id: "", view_google_folder_name: "" });
4679
+ },
4680
+ className: "p-1 hover:bg-red-500/20 text-slate-400 hover:text-red-400 rounded transition-colors"
4681
+ },
4682
+ /* @__PURE__ */ React2.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React2.createElement("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }))
4683
+ )), /* @__PURE__ */ React2.createElement(
4684
+ "button",
4685
+ {
4686
+ onClick: async () => {
4687
+ if (!open_google_picker_action) return;
4688
+ setIsPickingGoogleFolder(true);
4689
+ try {
4690
+ const result = await open_google_picker_action();
4691
+ if (result && result.folderId) {
4692
+ setFolderId(result.folderId);
4693
+ setFolderName(result.folderName || "");
4694
+ onSaveConfig({
4695
+ view_google_folder_id: result.folderId,
4696
+ view_google_folder_name: result.folderName || ""
4697
+ });
4698
+ }
4699
+ } catch (e) {
4700
+ console.error("Erro ao selecionar pasta Google Drive", e);
4701
+ alert("Erro ao abrir Picker. Verifique o console.");
4702
+ } finally {
4703
+ setIsPickingGoogleFolder(false);
4704
+ }
4705
+ },
4706
+ disabled: isPickingGoogleFolder,
4707
+ className: "w-full px-3 py-2 rounded-md bg-indigo-600/20 hover:bg-indigo-600/40 border border-indigo-500/50 text-xs text-indigo-100 transition-colors flex items-center justify-center gap-2 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
4708
+ },
4709
+ isPickingGoogleFolder ? /* @__PURE__ */ React2.createElement("svg", { className: "animate-spin h-4 w-4 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React2.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React2.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })) : "Selecionar Pasta no Drive"
4710
+ ), /* @__PURE__ */ React2.createElement("p", { className: "text-[9px] text-slate-500 italic" }, "Documentos criados nesta View ser\xE3o salvos nesta pasta."))))),
4656
4711
  /* @__PURE__ */ React2.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/30" }, /* @__PURE__ */ React2.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Navega\xE7\xE3o"), ability.can("update", "Scene") && /* @__PURE__ */ React2.createElement(
4657
4712
  "button",
4658
4713
  {
@@ -8987,7 +9042,8 @@ function InSceneCreationForm({
8987
9042
  availableDatasets = [],
8988
9043
  sourceNodeDatasetId,
8989
9044
  viewType,
8990
- create_google_doc_action
9045
+ create_google_doc_action,
9046
+ view_google_folder_id
8991
9047
  }) {
8992
9048
  var _a;
8993
9049
  const [name, setName] = useState14("");
@@ -9008,6 +9064,7 @@ function InSceneCreationForm({
9008
9064
  );
9009
9065
  const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState14(false);
9010
9066
  const [isLoadingDocs, setIsLoadingDocs] = useState14(false);
9067
+ const [docError, setDocError] = useState14(null);
9011
9068
  const datasetDropdownRef = useRef10(null);
9012
9069
  useEffect13(() => {
9013
9070
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
@@ -9154,7 +9211,8 @@ function InSceneCreationForm({
9154
9211
  if (!create_google_doc_action) return;
9155
9212
  try {
9156
9213
  setIsLoadingDocs(true);
9157
- const res = await create_google_doc_action(name);
9214
+ setDocError(null);
9215
+ const res = await create_google_doc_action(name, view_google_folder_id);
9158
9216
  if (res.success) {
9159
9217
  const existingLinksPropIndex = customProps.findIndex(
9160
9218
  (p) => p.type === "links" && p.key === "Links"
@@ -9181,11 +9239,21 @@ function InSceneCreationForm({
9181
9239
  window.open(res.link, "_blank");
9182
9240
  }
9183
9241
  } else {
9184
- alert("Erro ao criar documento: " + res.error);
9242
+ if (res.errorType === "PERMISSIONS_ERROR") {
9243
+ setDocError(
9244
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
9245
+ );
9246
+ } else {
9247
+ setDocError(
9248
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
9249
+ );
9250
+ }
9185
9251
  }
9186
9252
  } catch (error) {
9187
9253
  console.error(error);
9188
- alert("Erro ao processar cria\xE7\xE3o do documento.");
9254
+ setDocError(
9255
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
9256
+ );
9189
9257
  } finally {
9190
9258
  setIsLoadingDocs(false);
9191
9259
  }
@@ -9429,7 +9497,14 @@ function InSceneCreationForm({
9429
9497
  className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}`
9430
9498
  },
9431
9499
  useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Selecione a cor e ajuste o brilho."
9432
- )), /* @__PURE__ */ React14.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React14.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React14.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ React14.createElement(
9500
+ )), /* @__PURE__ */ React14.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React14.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React14.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ React14.createElement(
9501
+ "p",
9502
+ {
9503
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
9504
+ title: docError
9505
+ },
9506
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
9507
+ ) : /* @__PURE__ */ React14.createElement(
9433
9508
  "button",
9434
9509
  {
9435
9510
  type: "button",
@@ -9438,8 +9513,20 @@ function InSceneCreationForm({
9438
9513
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
9439
9514
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
9440
9515
  },
9441
- isLoadingDocs ? /* @__PURE__ */ React14.createElement(AiOutlineLoading3Quarters, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ React14.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
9442
- ), /* @__PURE__ */ React14.createElement(
9516
+ isLoadingDocs ? /* @__PURE__ */ React14.createElement(
9517
+ AiOutlineLoading3Quarters,
9518
+ {
9519
+ className: "animate-spin",
9520
+ size: 18
9521
+ }
9522
+ ) : /* @__PURE__ */ React14.createElement(
9523
+ GoogleDocsIcon_default,
9524
+ {
9525
+ size: 18,
9526
+ className: "group-hover:scale-110 transition-transform"
9527
+ }
9528
+ )
9529
+ )), /* @__PURE__ */ React14.createElement(
9443
9530
  "button",
9444
9531
  {
9445
9532
  type: "button",
@@ -10020,7 +10107,8 @@ function InSceneQuestForm({
10020
10107
  milestones = [],
10021
10108
  onUpdateMilestones = () => {
10022
10109
  },
10023
- create_google_doc_action
10110
+ create_google_doc_action,
10111
+ view_google_folder_id
10024
10112
  }) {
10025
10113
  var _a, _b;
10026
10114
  const [name, setName] = useState17("");
@@ -10049,6 +10137,7 @@ function InSceneQuestForm({
10049
10137
  const [assigneeSearchQuery, setAssigneeSearchQuery] = useState17("");
10050
10138
  const [isNameCopied, setIsNameCopied] = useState17(false);
10051
10139
  const [isLoadingDocs, setIsLoadingDocs] = useState17(false);
10140
+ const [docError, setDocError] = useState17(null);
10052
10141
  const [customProps, setCustomProps] = useState17([]);
10053
10142
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
10054
10143
  const propsEndRef = useRef12(null);
@@ -10144,7 +10233,8 @@ function InSceneQuestForm({
10144
10233
  if (!create_google_doc_action) return;
10145
10234
  try {
10146
10235
  setIsLoadingDocs(true);
10147
- const res = await create_google_doc_action(standardizedName);
10236
+ setDocError(null);
10237
+ const res = await create_google_doc_action(standardizedName, view_google_folder_id);
10148
10238
  if (res.success) {
10149
10239
  const existingLinksPropIndex = customProps.findIndex(
10150
10240
  (p) => p.type === "links" && p.key === "Links"
@@ -10171,11 +10261,21 @@ function InSceneQuestForm({
10171
10261
  window.open(res.link, "_blank");
10172
10262
  }
10173
10263
  } else {
10174
- alert("Erro ao criar documento: " + res.error);
10264
+ if (res.errorType === "PERMISSIONS_ERROR") {
10265
+ setDocError(
10266
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
10267
+ );
10268
+ } else {
10269
+ setDocError(
10270
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
10271
+ );
10272
+ }
10175
10273
  }
10176
10274
  } catch (error) {
10177
10275
  console.error(error);
10178
- alert("Erro ao processar cria\xE7\xE3o do documento.");
10276
+ setDocError(
10277
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
10278
+ );
10179
10279
  } finally {
10180
10280
  setIsLoadingDocs(false);
10181
10281
  }
@@ -10698,7 +10798,14 @@ function InSceneQuestForm({
10698
10798
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
10699
10799
  },
10700
10800
  "Adicionar descri\xE7\xE3o..."
10701
- ))), /* @__PURE__ */ React17.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React17.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ React17.createElement(
10801
+ ))), /* @__PURE__ */ React17.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React17.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ React17.createElement(
10802
+ "p",
10803
+ {
10804
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
10805
+ title: docError
10806
+ },
10807
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
10808
+ ) : /* @__PURE__ */ React17.createElement(
10702
10809
  "button",
10703
10810
  {
10704
10811
  type: "button",
@@ -10707,8 +10814,20 @@ function InSceneQuestForm({
10707
10814
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
10708
10815
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
10709
10816
  },
10710
- isLoadingDocs ? /* @__PURE__ */ React17.createElement(AiOutlineLoading3Quarters2, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ React17.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
10711
- ), /* @__PURE__ */ React17.createElement(
10817
+ isLoadingDocs ? /* @__PURE__ */ React17.createElement(
10818
+ AiOutlineLoading3Quarters2,
10819
+ {
10820
+ className: "animate-spin",
10821
+ size: 18
10822
+ }
10823
+ ) : /* @__PURE__ */ React17.createElement(
10824
+ GoogleDocsIcon_default,
10825
+ {
10826
+ size: 18,
10827
+ className: "group-hover:scale-110 transition-transform"
10828
+ }
10829
+ )
10830
+ )), /* @__PURE__ */ React17.createElement(
10712
10831
  "button",
10713
10832
  {
10714
10833
  type: "button",
@@ -10839,7 +10958,8 @@ function NodeDetailsPanel({
10839
10958
  onUploadFile,
10840
10959
  userRole,
10841
10960
  currentDatasetName,
10842
- create_google_doc_action
10961
+ create_google_doc_action,
10962
+ view_google_folder_id
10843
10963
  }) {
10844
10964
  const [name, setName] = useState18((node == null ? void 0 : node.name) ?? "");
10845
10965
  const [types, setTypes] = useState18([]);
@@ -10856,6 +10976,7 @@ function NodeDetailsPanel({
10856
10976
  const [existingSections, setExistingSections] = useState18((node == null ? void 0 : node.description_sections) || []);
10857
10977
  const [isSaving, setIsSaving] = useState18(false);
10858
10978
  const [isLoadingDocs, setIsLoadingDocs] = useState18(false);
10979
+ const [docError, setDocError] = useState18(null);
10859
10980
  const [isLinkCopied, setIsLinkCopied] = useState18(false);
10860
10981
  const [useImageAsTexture, setUseImageAsTexture] = useState18(() => {
10861
10982
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
@@ -11018,7 +11139,8 @@ function NodeDetailsPanel({
11018
11139
  if (!create_google_doc_action) return;
11019
11140
  try {
11020
11141
  setIsLoadingDocs(true);
11021
- const res = await create_google_doc_action(name);
11142
+ setDocError(null);
11143
+ const res = await create_google_doc_action(name, view_google_folder_id);
11022
11144
  if (res.success) {
11023
11145
  const existingLinksPropIndex = customProps.findIndex(
11024
11146
  (p) => p.type === "links" && p.key === "Links"
@@ -11048,11 +11170,21 @@ function NodeDetailsPanel({
11048
11170
  window.open(res.link, "_blank");
11049
11171
  }
11050
11172
  } else {
11051
- alert("Erro ao criar documento: " + res.error);
11173
+ if (res.errorType === "PERMISSIONS_ERROR") {
11174
+ setDocError(
11175
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
11176
+ );
11177
+ } else {
11178
+ setDocError(
11179
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
11180
+ );
11181
+ }
11052
11182
  }
11053
11183
  } catch (error) {
11054
11184
  console.error(error);
11055
- alert("Erro ao processar cria\xE7\xE3o do documento.");
11185
+ setDocError(
11186
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
11187
+ );
11056
11188
  } finally {
11057
11189
  setIsLoadingDocs(false);
11058
11190
  }
@@ -11333,7 +11465,14 @@ function NodeDetailsPanel({
11333
11465
  className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
11334
11466
  title: `Intensidade do brilho: ${intensity}`
11335
11467
  }
11336
- ), /* @__PURE__ */ React18.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React18.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ React18.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ React18.createElement(
11468
+ ), /* @__PURE__ */ React18.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React18.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ React18.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ React18.createElement(
11469
+ "p",
11470
+ {
11471
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
11472
+ title: docError
11473
+ },
11474
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
11475
+ ) : /* @__PURE__ */ React18.createElement(
11337
11476
  "button",
11338
11477
  {
11339
11478
  type: "button",
@@ -11342,8 +11481,20 @@ function NodeDetailsPanel({
11342
11481
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
11343
11482
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
11344
11483
  },
11345
- isLoadingDocs ? /* @__PURE__ */ React18.createElement(AiOutlineLoading3Quarters3, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ React18.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
11346
- ), canEdit && /* @__PURE__ */ React18.createElement(
11484
+ isLoadingDocs ? /* @__PURE__ */ React18.createElement(
11485
+ AiOutlineLoading3Quarters3,
11486
+ {
11487
+ className: "animate-spin",
11488
+ size: 18
11489
+ }
11490
+ ) : /* @__PURE__ */ React18.createElement(
11491
+ GoogleDocsIcon_default,
11492
+ {
11493
+ size: 18,
11494
+ className: "group-hover:scale-110 transition-transform"
11495
+ }
11496
+ )
11497
+ )), canEdit && /* @__PURE__ */ React18.createElement(
11347
11498
  "button",
11348
11499
  {
11349
11500
  type: "button",
@@ -11518,7 +11669,8 @@ function QuestDetailsPanel({
11518
11669
  onUpdateMilestones = () => {
11519
11670
  },
11520
11671
  onFocusNode,
11521
- create_google_doc_action
11672
+ create_google_doc_action,
11673
+ view_google_folder_id
11522
11674
  }) {
11523
11675
  var _a, _b;
11524
11676
  const initialRawTitle = (node == null ? void 0 : node.raw_title) || (((_a = node == null ? void 0 : node.name) == null ? void 0 : _a.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
@@ -11553,6 +11705,7 @@ function QuestDetailsPanel({
11553
11705
  const [isLinkCopied, setIsLinkCopied] = useState19(false);
11554
11706
  const [isNameCopied, setIsNameCopied] = useState19(false);
11555
11707
  const [isLoadingDocs, setIsLoadingDocs] = useState19(false);
11708
+ const [docError, setDocError] = useState19(null);
11556
11709
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState19(false);
11557
11710
  const [questDate, setQuestDate] = useState19((node == null ? void 0 : node.Date) || null);
11558
11711
  const [noteText, setNoteText] = useState19("");
@@ -11961,7 +12114,8 @@ ${noteText}` : noteText : entry.notes,
11961
12114
  if (!create_google_doc_action) return;
11962
12115
  try {
11963
12116
  setIsLoadingDocs(true);
11964
- const res = await create_google_doc_action(standardizedName);
12117
+ setDocError(null);
12118
+ const res = await create_google_doc_action(standardizedName, view_google_folder_id);
11965
12119
  if (res.success) {
11966
12120
  const existingLinksPropIndex = customProps.findIndex(
11967
12121
  (p) => p.type === "links" && p.key === "Links"
@@ -11991,11 +12145,21 @@ ${noteText}` : noteText : entry.notes,
11991
12145
  window.open(res.link, "_blank");
11992
12146
  }
11993
12147
  } else {
11994
- alert("Erro ao criar documento: " + res.error);
12148
+ if (res.errorType === "PERMISSIONS_ERROR") {
12149
+ setDocError(
12150
+ "Erro: Voc\xEA n\xE3o possui permiss\xE3o de escrita na pasta configurada pela View. Solicite acesso ao Owner."
12151
+ );
12152
+ } else {
12153
+ setDocError(
12154
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
12155
+ );
12156
+ }
11995
12157
  }
11996
12158
  } catch (error) {
11997
12159
  console.error(error);
11998
- alert("Erro ao processar cria\xE7\xE3o do documento.");
12160
+ setDocError(
12161
+ "Falha ao conectar com seu Google Drive. Verifique a integra\xE7\xE3o na sua conta."
12162
+ );
11999
12163
  } finally {
12000
12164
  setIsLoadingDocs(false);
12001
12165
  }
@@ -12605,7 +12769,14 @@ ${noteText}` : noteText : entry.notes,
12605
12769
  },
12606
12770
  /* @__PURE__ */ React20.createElement("span", { className: "truncate" }, q.raw_title || q.name),
12607
12771
  /* @__PURE__ */ React20.createElement("span", { className: `text-[10px] px-1.5 py-0.5 rounded border ${q.status === "Done" ? "text-green-400 border-green-500/30" : "text-slate-500 border-white/5"}` }, q.status || "Backlog")
12608
- )) : /* @__PURE__ */ React20.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ React20.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ React20.createElement(FiRepeat2, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ React20.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ React20.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React20.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React20.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ React20.createElement(
12772
+ )) : /* @__PURE__ */ React20.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ React20.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ React20.createElement(FiRepeat2, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ React20.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ React20.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React20.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React20.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ React20.createElement("div", { className: "flex items-center gap-2" }, docError ? /* @__PURE__ */ React20.createElement(
12773
+ "p",
12774
+ {
12775
+ className: "text-[10px] text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20 max-w-[200px]",
12776
+ title: docError
12777
+ },
12778
+ docError.length > 50 ? docError.substring(0, 47) + "..." : docError
12779
+ ) : /* @__PURE__ */ React20.createElement(
12609
12780
  "button",
12610
12781
  {
12611
12782
  type: "button",
@@ -12614,8 +12785,20 @@ ${noteText}` : noteText : entry.notes,
12614
12785
  className: "flex items-center justify-center text-slate-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
12615
12786
  title: isLoadingDocs ? "Criando Documento..." : "Criar Documento no Google Docs"
12616
12787
  },
12617
- isLoadingDocs ? /* @__PURE__ */ React20.createElement(AiOutlineLoading3Quarters4, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ React20.createElement(GoogleDocsIcon_default, { size: 18, className: "group-hover:scale-110 transition-transform" })
12618
- ), canEdit && /* @__PURE__ */ React20.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React20.createElement(FiPlus8, { size: 14 }), " Adicionar"))), /* @__PURE__ */ React20.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React20.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ React20.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ React20.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ React20.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ React20.createElement(
12788
+ isLoadingDocs ? /* @__PURE__ */ React20.createElement(
12789
+ AiOutlineLoading3Quarters4,
12790
+ {
12791
+ className: "animate-spin",
12792
+ size: 18
12793
+ }
12794
+ ) : /* @__PURE__ */ React20.createElement(
12795
+ GoogleDocsIcon_default,
12796
+ {
12797
+ size: 18,
12798
+ className: "group-hover:scale-110 transition-transform"
12799
+ }
12800
+ )
12801
+ )), canEdit && /* @__PURE__ */ React20.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React20.createElement(FiPlus8, { size: 14 }), " Adicionar"))), /* @__PURE__ */ React20.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React20.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ React20.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ React20.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ React20.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ React20.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ React20.createElement(
12619
12802
  "button",
12620
12803
  {
12621
12804
  type: "button",
@@ -14879,9 +15062,10 @@ function XViewScene({
14879
15062
  delete_file_action,
14880
15063
  check_user_permission,
14881
15064
  get_view_members,
14882
- create_google_doc_action
15065
+ create_google_doc_action,
15066
+ open_google_picker_action
14883
15067
  }) {
14884
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
15068
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
14885
15069
  const { data: session, status } = useSession();
14886
15070
  const router = useRouter();
14887
15071
  const searchParams = useSearchParams();
@@ -15258,6 +15442,23 @@ function XViewScene({
15258
15442
  add_new_parent_file_to_scene_at_firebase_action
15259
15443
  ]
15260
15444
  );
15445
+ const handleSaveConfig = useCallback6(
15446
+ async (newConfig) => {
15447
+ if (!sceneDataRef.current || !save_view_data || !sceneSaveUrl) return;
15448
+ const updatedData = {
15449
+ ...sceneDataRef.current,
15450
+ ...newConfig
15451
+ };
15452
+ sceneDataRef.current = updatedData;
15453
+ try {
15454
+ await save_view_data(sceneSaveUrl, updatedData);
15455
+ setSceneVersion((v) => v + 1);
15456
+ } catch (error) {
15457
+ console.error("Erro ao salvar configura\xE7\xE3o da View:", error);
15458
+ }
15459
+ },
15460
+ [save_view_data, sceneSaveUrl]
15461
+ );
15261
15462
  const handleOpenImageViewer = (images, startIndex) => {
15262
15463
  setImageViewer({ visible: true, images, startIndex });
15263
15464
  };
@@ -19561,13 +19762,16 @@ function XViewScene({
19561
19762
  onOpenBoards: handleOpenBoards,
19562
19763
  viewType: viewParams == null ? void 0 : viewParams.type,
19563
19764
  viewName: viewParams == null ? void 0 : viewParams.name,
19564
- onNavigateBack: handleNavigateBack,
19765
+ milestones: (viewParams == null ? void 0 : viewParams.milestones) || [],
19766
+ onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true),
19767
+ view_google_folder_id: viewParams == null ? void 0 : viewParams.view_google_folder_id,
19768
+ view_google_folder_name: viewParams == null ? void 0 : viewParams.view_google_folder_name,
19769
+ open_google_picker_action,
19770
+ onSaveConfig: handleSaveConfig,
19565
19771
  isOpen: isSidebarOpen,
19566
19772
  onToggle: setIsSidebarOpen,
19567
19773
  userRole: userPermissionRole,
19568
- viewMembers,
19569
- milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
19570
- onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
19774
+ viewMembers
19571
19775
  }
19572
19776
  ),
19573
19777
  creationMode.isActive && /* @__PURE__ */ React31.createElement(
@@ -19591,8 +19795,8 @@ function XViewScene({
19591
19795
  },
19592
19796
  refEl: formRef,
19593
19797
  existingTypes: existingNodeTypes,
19594
- initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
19595
- sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
19798
+ initialColor: (_c = creationMode.sourceNodeData) == null ? void 0 : _c.color,
19799
+ sourceTypes: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.type,
19596
19800
  onIntensityChange: handleGhostNodeIntensityChange,
19597
19801
  onUploadFile: upload_file_action,
19598
19802
  availableDatasets,
@@ -19600,7 +19804,8 @@ function XViewScene({
19600
19804
  viewType: viewParams == null ? void 0 : viewParams.type,
19601
19805
  availableNodes: allAvailableNodes,
19602
19806
  availableAncestries: allAvailableAncestries,
19603
- create_google_doc_action
19807
+ create_google_doc_action,
19808
+ view_google_folder_id: (_e = sceneDataRef.current) == null ? void 0 : _e.view_google_folder_id
19604
19809
  }
19605
19810
  ),
19606
19811
  versionMode.isActive && /* @__PURE__ */ React31.createElement(
@@ -19655,7 +19860,8 @@ function XViewScene({
19655
19860
  viewMembers,
19656
19861
  milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
19657
19862
  onUpdateMilestones: handleUpdateMilestones,
19658
- create_google_doc_action
19863
+ create_google_doc_action,
19864
+ view_google_folder_id: (_j = sceneDataRef.current) == null ? void 0 : _j.view_google_folder_id
19659
19865
  }
19660
19866
  ),
19661
19867
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React31.createElement(
@@ -19789,9 +19995,10 @@ function XViewScene({
19789
19995
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
19790
19996
  viewMembers,
19791
19997
  currentUser: session == null ? void 0 : session.user,
19792
- milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
19998
+ milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
19793
19999
  onUpdateMilestones: handleUpdateMilestones,
19794
- create_google_doc_action
20000
+ create_google_doc_action,
20001
+ view_google_folder_id: (_l = sceneDataRef.current) == null ? void 0 : _l.view_google_folder_id
19795
20002
  }
19796
20003
  ),
19797
20004
  detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React31.createElement(
@@ -19824,7 +20031,8 @@ function XViewScene({
19824
20031
  onUploadFile: upload_file_action,
19825
20032
  userRole: userPermissionRole,
19826
20033
  currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
19827
- create_google_doc_action
20034
+ create_google_doc_action,
20035
+ view_google_folder_id: (_m = sceneDataRef.current) == null ? void 0 : _m.view_google_folder_id
19828
20036
  }
19829
20037
  ),
19830
20038
  detailsLink && /* @__PURE__ */ React31.createElement(
@@ -19982,7 +20190,7 @@ function XViewScene({
19982
20190
  {
19983
20191
  isOpen: isMilestoneManagerOpen,
19984
20192
  onClose: () => setIsMilestoneManagerOpen(false),
19985
- milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
20193
+ milestones: ((_n = sceneDataRef.current) == null ? void 0 : _n.milestones) || [],
19986
20194
  onUpdateMilestones: handleUpdateMilestones
19987
20195
  }
19988
20196
  ),
@@ -19993,7 +20201,7 @@ function XViewScene({
19993
20201
  onClose: () => setIsImportModalOpen(false),
19994
20202
  onConfirm: handleConfirmImport,
19995
20203
  session,
19996
- parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
20204
+ parentDbs: ((_o = sceneDataRef.current) == null ? void 0 : _o.parent_dbs) || [],
19997
20205
  onFetchAvailableFiles: import_parent_file_modal_get,
19998
20206
  currentViewName: viewParams == null ? void 0 : viewParams.name,
19999
20207
  currentAncestries: ancestryDataRef.current || []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lv-x-software-house/x_view",
3
- "version": "1.2.6-dev.65",
3
+ "version": "1.2.6-dev.67",
4
4
  "description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
5
5
  "author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
6
6
  "license": "UNLICENSED",