@edifice.io/react 2.6.2-develop-integration.20260824151812 → 2.6.2-develop-integration.20260824172410

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.
@@ -16,6 +16,25 @@ function findNodeById(data, id) {
16
16
  }
17
17
  }
18
18
  }
19
+ function modifyNode(data, callback) {
20
+ return doModify(data, callback) || data;
21
+ }
22
+ function doModify(current, callback, parent) {
23
+ var _a;
24
+ const result = callback(current, parent);
25
+ if ((_a = result == null ? void 0 : result.children) != null && _a.length) {
26
+ const children = [];
27
+ for (const child of (result == null ? void 0 : result.children) || []) {
28
+ const res = doModify(child, callback, result);
29
+ res && children.push(res);
30
+ }
31
+ return {
32
+ ...result,
33
+ children
34
+ };
35
+ }
36
+ return result;
37
+ }
19
38
  function findPathById(tree, nodeId) {
20
39
  let path = [];
21
40
  function traverse(node, currentPath) {
@@ -40,5 +59,6 @@ function findPathById(tree, nodeId) {
40
59
  }
41
60
  export {
42
61
  findNodeById,
43
- findPathById
62
+ findPathById,
63
+ modifyNode
44
64
  };
@@ -1,6 +1,6 @@
1
1
  import { ID, NextcloudDocument } from '@edifice.io/client';
2
- import { TreeData } from '../../types';
3
- export type NextcloudFolderNode = TreeData & {
2
+ import { TreeItem } from '../../components/Tree/types';
3
+ export type NextcloudFolderNode = TreeItem & {
4
4
  files?: NextcloudDocument[];
5
5
  };
6
6
  export default function useNextcloudSearch(rootId: string, rootName: string, userId?: string): {
@@ -1,29 +1,35 @@
1
- import { useReducer, useCallback } from "react";
1
+ import { useState, useCallback } from "react";
2
2
  import { odeServices } from "@edifice.io/client";
3
3
  import { useQueryClient, useQuery } from "@tanstack/react-query";
4
- import { findNodeById } from "../../components/TreeView/utilities/treeview.js";
4
+ import { findNodeById, modifyNode } from "../../components/Tree/utilities/tree.js";
5
5
  function useNextcloudSearch(rootId, rootName, userId) {
6
6
  var _a;
7
- function treeReducer(state, action) {
8
- switch (action.type) {
9
- case "update": {
10
- const node = findNodeById(state, action.folderId);
11
- return node && (node.children = action.subfolders.map((f) => ({
12
- id: f.path,
13
- name: f.name
14
- })), node.files = action.files), {
15
- ...state
16
- };
17
- }
18
- default:
19
- throw Error("[useNextcloudSearch] Unknown action type: " + action.type);
20
- }
21
- }
22
- const [root, dispatch] = useReducer(treeReducer, {
7
+ const [root, setRoot] = useState({
23
8
  id: rootId,
24
9
  name: rootName,
25
10
  section: !0
26
- }), queryClient = useQueryClient(), oauth2StatusQuery = useQuery({
11
+ }), updateFolder = useCallback((folderId, subfolders, files) => {
12
+ setRoot((prev) => {
13
+ const node = findNodeById(prev, folderId);
14
+ if (!node) return prev;
15
+ const children = subfolders.map((f) => {
16
+ var _a2;
17
+ const existing = (_a2 = node.children) == null ? void 0 : _a2.find((c) => c.id === f.path);
18
+ return existing ? {
19
+ ...existing,
20
+ name: f.name
21
+ } : {
22
+ id: f.path,
23
+ name: f.name
24
+ };
25
+ });
26
+ return modifyNode(prev, (n) => n.id === node.id ? {
27
+ ...n,
28
+ children,
29
+ files
30
+ } : n);
31
+ });
32
+ }, []), queryClient = useQueryClient(), oauth2StatusQuery = useQuery({
27
33
  queryKey: ["nextcloud", "oauth2-status", userId],
28
34
  queryFn: () => odeServices.nextcloud().getOauth2Status(userId),
29
35
  enabled: !!userId
@@ -36,13 +42,8 @@ function useNextcloudSearch(rootId, rootName, userId) {
36
42
  }), subfolders = [], files = [], currentPath = path ?? "/";
37
43
  payload.filter((doc) => doc.path !== currentPath).forEach((doc) => {
38
44
  doc.isFolder ? subfolders.push(doc) : files.push(doc);
39
- }), dispatch({
40
- folderId,
41
- subfolders,
42
- files,
43
- type: "update"
44
- });
45
- }, [rootId, userId, queryClient]);
45
+ }), updateFolder(folderId, subfolders, files);
46
+ }, [rootId, userId, queryClient, updateFolder]);
46
47
  return {
47
48
  root,
48
49
  needsAuth,
@@ -9,6 +9,63 @@ import SvgIconVideo from "../../icons/components/IconVideo.js";
9
9
  import FileIcon from "./FileIcon.js";
10
10
  import useThumbnail from "../../../hooks/useThumbnail/useThumbnail.js";
11
11
  import Card from "../../../components/Card/Card.js";
12
+ const roleMappings = {
13
+ csv: {
14
+ icon: ".CSV",
15
+ color: "bg-orange-200"
16
+ },
17
+ xls: {
18
+ icon: ".XLS",
19
+ color: "bg-green-200"
20
+ },
21
+ doc: {
22
+ icon: ".DOC",
23
+ color: "bg-blue-200"
24
+ },
25
+ txt: {
26
+ icon: ".TXT",
27
+ color: "bg-blue-200"
28
+ },
29
+ pdf: {
30
+ icon: ".PDF",
31
+ color: "bg-red-200"
32
+ },
33
+ audio: {
34
+ icon: /* @__PURE__ */ jsx(SvgIconMic, { width: 22, height: 22 }),
35
+ color: "bg-red-200"
36
+ },
37
+ ppt: {
38
+ icon: ".PPT",
39
+ color: "bg-red-200"
40
+ },
41
+ img: {
42
+ icon: /* @__PURE__ */ jsx(SvgIconLandscape, { width: 22, height: 22 }),
43
+ color: "bg-green-200"
44
+ },
45
+ video: {
46
+ icon: /* @__PURE__ */ jsx(SvgIconVideo, { width: 22, height: 22 }),
47
+ color: "bg-purple-200"
48
+ },
49
+ zip: {
50
+ icon: ".ZIP",
51
+ color: "bg-gray-300"
52
+ },
53
+ md: {
54
+ icon: ".MD",
55
+ color: "bg-blue-200"
56
+ },
57
+ unknown: {
58
+ icon: /* @__PURE__ */ jsx(SvgIconTextPage, { width: 22, height: 22 }),
59
+ color: "bg-gray-300"
60
+ }
61
+ };
62
+ function getRoleMap(type, customIcon, customColor) {
63
+ return customIcon !== void 0 || customColor !== void 0 ? {
64
+ icon: customIcon || /* @__PURE__ */ jsx(SvgIconTextPage, { width: 22, height: 22 }),
65
+ color: customColor || "bg-gray-300",
66
+ hasShadow: !1
67
+ } : roleMappings[type] ?? roleMappings.unknown;
68
+ }
12
69
  const NextcloudFileCard = ({
13
70
  doc,
14
71
  userId,
@@ -23,67 +80,7 @@ const NextcloudFileCard = ({
23
80
  customIcon,
24
81
  customColor
25
82
  }) => {
26
- const ref = useRef(null), type = DocumentHelper.role(doc.contentType, !1);
27
- function getRoleMap(type2) {
28
- if (customIcon !== void 0 || customColor !== void 0)
29
- return {
30
- icon: customIcon || /* @__PURE__ */ jsx(SvgIconTextPage, { width: 22, height: 22 }),
31
- color: customColor || "bg-gray-300",
32
- hasShadow: !1
33
- };
34
- const roleMappings = {
35
- csv: {
36
- icon: ".CSV",
37
- color: "bg-orange-200"
38
- },
39
- xls: {
40
- icon: ".XLS",
41
- color: "bg-green-200"
42
- },
43
- doc: {
44
- icon: ".DOC",
45
- color: "bg-blue-200"
46
- },
47
- txt: {
48
- icon: ".TXT",
49
- color: "bg-blue-200"
50
- },
51
- pdf: {
52
- icon: ".PDF",
53
- color: "bg-red-200"
54
- },
55
- audio: {
56
- icon: /* @__PURE__ */ jsx(SvgIconMic, { width: 22, height: 22 }),
57
- color: "bg-red-200"
58
- },
59
- ppt: {
60
- icon: ".PPT",
61
- color: "bg-red-200"
62
- },
63
- img: {
64
- icon: /* @__PURE__ */ jsx(SvgIconLandscape, { width: 22, height: 22 }),
65
- color: "bg-green-200"
66
- },
67
- video: {
68
- icon: /* @__PURE__ */ jsx(SvgIconVideo, { width: 22, height: 22 }),
69
- color: "bg-purple-200"
70
- },
71
- zip: {
72
- icon: ".ZIP",
73
- color: "bg-gray-300"
74
- },
75
- md: {
76
- icon: ".MD",
77
- color: "bg-blue-200"
78
- },
79
- unknown: {
80
- icon: /* @__PURE__ */ jsx(SvgIconTextPage, { width: 22, height: 22 }),
81
- color: "bg-gray-300"
82
- }
83
- };
84
- return roleMappings[type2] || roleMappings.unknown;
85
- }
86
- const roleMap = getRoleMap(type ?? "unknown"), file = clsx("file position-relative rounded", (roleMap == null ? void 0 : roleMap.color) ?? "bg-yellow-200"), mediaSrc = type === "img" ? odeServices.nextcloud().getFileUrl(userId, doc) : null, hasThumbnail = useThumbnail(mediaSrc, {
83
+ const ref = useRef(null), type = DocumentHelper.role(doc.contentType, !1), roleMap = getRoleMap(type ?? "unknown", customIcon, customColor), file = clsx("file position-relative rounded", (roleMap == null ? void 0 : roleMap.color) ?? "bg-yellow-200"), mediaSrc = type === "img" ? odeServices.nextcloud().getFileUrl(userId, doc) : null, hasThumbnail = useThumbnail(mediaSrc, {
87
84
  ref
88
85
  }), imageStyles = hasThumbnail && {
89
86
  backgroundImage: `url(${mediaSrc})`,
@@ -93,7 +90,7 @@ const NextcloudFileCard = ({
93
90
  /* @__PURE__ */ jsx("div", { ref, className: file, style: {
94
91
  aspectRatio: "16/10",
95
92
  ...imageStyles
96
- }, children: type !== "img" || type === "img" && !hasThumbnail ? /* @__PURE__ */ jsx(FileIcon, { type, roleMap }) : null }),
93
+ }, children: type !== "img" || !hasThumbnail ? /* @__PURE__ */ jsx(FileIcon, { type, roleMap }) : null }),
97
94
  /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
98
95
  /* @__PURE__ */ jsx(Card.Text, { children: doc.name }),
99
96
  /* @__PURE__ */ jsx(Card.Text, { className: "text-black-50", children: doc == null ? void 0 : doc.ownerDisplayName })
@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
5
5
  import SvgIconApplications from "../../icons/components/IconApplications.js";
6
6
  import SvgIconCode from "../../icons/components/IconCode.js";
7
7
  import SvgIconFolder from "../../icons/components/IconFolder.js";
8
+ import SvgIconGlobe2 from "../../icons/components/IconGlobe2.js";
8
9
  import SvgIconGlobe from "../../icons/components/IconGlobe.js";
9
10
  import SvgIconMic from "../../icons/components/IconMic.js";
10
11
  import SvgIconRecordVideo from "../../icons/components/IconRecordVideo.js";
@@ -103,7 +104,7 @@ const orderedTabs = [
103
104
  },
104
105
  nextcloud: {
105
106
  id: "nextcloud",
106
- icon: /* @__PURE__ */ jsx(SvgIconGlobe, {}),
107
+ icon: /* @__PURE__ */ jsx(SvgIconGlobe2, {}),
107
108
  label: t("bbm.nextcloud"),
108
109
  content: /* @__PURE__ */ jsx(InnerTabs.Nextcloud, {}),
109
110
  availableFor: ["audio", "video", "image", "attachment"],
@@ -8,6 +8,7 @@ import SvgIconSortAscendingLetters from "../../icons/components/IconSortAscendin
8
8
  import SvgIconSortDescendingLetters from "../../icons/components/IconSortDescendingLetters.js";
9
9
  import SvgIconSortTime from "../../icons/components/IconSortTime.js";
10
10
  import illuNoContentInFolder from "@edifice.io/bootstrap/dist/images/emptyscreen/illu-no-content-in-folder.svg";
11
+ import illuTrash from "@edifice.io/bootstrap/dist/images/emptyscreen/illu-trash.svg";
11
12
  import useUser from "../../../hooks/useUser/useUser.js";
12
13
  import useNextcloudSearch from "../../../hooks/useNextcloudSearch/useNextcloudSearch.js";
13
14
  import LoadingScreen from "../../../components/LoadingScreen/LoadingScreen.js";
@@ -39,22 +40,22 @@ const Nextcloud = ({
39
40
  isCheckingAuth,
40
41
  refetchAuthStatus,
41
42
  loadContent
42
- } = useNextcloudSearch(ROOT_ID, t("nextcloud"), user == null ? void 0 : user.userId), popupRef = useRef(null), [currentNodeId, setCurrentNodeId] = useState(ROOT_ID), treeRoot = root, currentNode = findNodeById(treeRoot, currentNodeId) ?? root, [searchTerm, setSearchTerm] = useState(null), [sortOrder, setSortOrder] = useState(["modified", "desc"]), [selectedDocuments, setSelectedDocuments] = useState([]), handleTreeItemChange = useCallback((nodeId) => {
43
+ } = useNextcloudSearch(ROOT_ID, t("nextcloud"), user == null ? void 0 : user.userId), popupRef = useRef(null), [currentNodeId, setCurrentNodeId] = useState(ROOT_ID), currentNode = findNodeById(root, currentNodeId) ?? root, [searchTerm, setSearchTerm] = useState(null), [sortOrder, setSortOrder] = useState(["modified", "desc"]), [selectedDocuments, setSelectedDocuments] = useState([]), handleTreeItemChange = useCallback((nodeId) => {
43
44
  setCurrentNodeId(nodeId), loadContent(nodeId);
44
45
  }, [loadContent]);
45
46
  useEffect(() => {
46
- loadContent(ROOT_ID);
47
- }, [loadContent]);
47
+ needsAuth || loadContent(ROOT_ID);
48
+ }, [loadContent, needsAuth]);
48
49
  const documents = useMemo(() => {
49
50
  if (!currentNode.files) return;
50
- let list = [].concat(currentNode.files);
51
- searchTerm && (list = list.filter((f) => f.name.indexOf(searchTerm) >= 0)), roles && (list = list.filter((f) => {
52
- const role = DocumentHelper.role(f.contentType, !1);
53
- return typeof roles == "string" ? roles === role : Array.isArray(roles) ? roles.includes(role) : !1;
54
- }));
55
- const sortFunction = sortOrder[0] === "name" ? sortOrder[1] === "asc" ? (a, b) => compare(a.name, b.name) : (a, b) => compare(b.name, a.name) : (a, b) => compare(b.lastModified, a.lastModified);
56
- return list.sort(sortFunction);
57
- }, [root, currentNode, searchTerm, sortOrder, roles]), selectedPaths = useMemo(() => new Set(selectedDocuments.map((d) => d.path)), [selectedDocuments]), handleSearchChange = useCallback((e) => {
51
+ const matchesRole = (doc) => {
52
+ if (!roles) return !0;
53
+ const role = DocumentHelper.role(doc.contentType, !1);
54
+ return Array.isArray(roles) ? roles.includes(role) : roles === role;
55
+ }, list = currentNode.files.filter((f) => (!searchTerm || f.name.indexOf(searchTerm) >= 0) && matchesRole(f));
56
+ let sortFunction;
57
+ return sortOrder[0] === "name" ? sortFunction = sortOrder[1] === "asc" ? (a, b) => compare(a.name, b.name) : (a, b) => compare(b.name, a.name) : sortFunction = (a, b) => compare(b.lastModified, a.lastModified), list.sort(sortFunction);
58
+ }, [currentNode, searchTerm, sortOrder, roles]), selectedPaths = useMemo(() => new Set(selectedDocuments.map((d) => d.path)), [selectedDocuments]), handleSearchChange = useCallback((e) => {
58
59
  setSearchTerm(e.target.value);
59
60
  }, [setSearchTerm]);
60
61
  function getSortOrderLabel() {
@@ -73,19 +74,23 @@ const Nextcloud = ({
73
74
  event.origin !== window.location.origin || ((_a = event.data) == null ? void 0 : _a.type) !== "nextcloud-connected" || (popupRef.current && !popupRef.current.closed && popupRef.current.close(), refetchAuthStatus());
74
75
  }
75
76
  return window.addEventListener("message", handleMessage), () => window.removeEventListener("message", handleMessage);
76
- }, [refetchAuthStatus]), isCheckingAuth ? /* @__PURE__ */ jsx(LoadingScreen, {}) : needsAuth ? /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "8", className: "h-full w-100", justify: "center", align: "center", children: [
77
- /* @__PURE__ */ jsx(EmptyScreen, { imageSrc: illuNoContentInFolder }),
78
- /* @__PURE__ */ jsx(Button, { onClick: openLoginPopup, children: "Login to nextcloud" })
77
+ }, [refetchAuthStatus]), isCheckingAuth ? /* @__PURE__ */ jsx(LoadingScreen, {}) : needsAuth ? /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "12", className: "h-full w-100", justify: "center", align: "center", children: [
78
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "8", justify: "center", align: "center", children: [
79
+ /* @__PURE__ */ jsx(EmptyScreen, { imageSrc: illuNoContentInFolder }),
80
+ /* @__PURE__ */ jsx("h2", { className: "h2 text-secondary mb-8", children: "Connectez vos Documents Synchronisés" }),
81
+ /* @__PURE__ */ jsx("div", { className: "text", children: "Connectez-vous pour parcourir vos Documents Synchronisés et les insérer ici." })
82
+ ] }),
83
+ /* @__PURE__ */ jsx(Button, { onClick: openLoginPopup, children: "Se connecter" })
79
84
  ] }) : /* @__PURE__ */ jsxs(Grid, { className: nextcloud, children: [
80
85
  /* @__PURE__ */ jsx(Grid.Col, { sm: "12", md: "3", xl: "4", className: "workspace-folders p-12 pt-0 gap-12", children: /* @__PURE__ */ jsx("div", { style: {
81
86
  position: "sticky",
82
87
  top: 0,
83
88
  paddingTop: "1.2rem"
84
- }, children: /* @__PURE__ */ jsx(Tree, { nodes: treeRoot, selectedNodeId: currentNodeId, showIcon: !0, onTreeItemClick: handleTreeItemChange, onTreeItemUnfold: handleTreeItemChange }) }) }),
89
+ }, children: /* @__PURE__ */ jsx(Tree, { nodes: root, selectedNodeId: currentNodeId, showIcon: !0, onTreeItemClick: handleTreeItemChange, onTreeItemUnfold: handleTreeItemChange }) }) }),
85
90
  /* @__PURE__ */ jsx(Grid.Col, { sm: "12", md: "5", xl: "8", children: /* @__PURE__ */ jsxs(Grid, { className: "flex-grow-1 gap-0", children: [
86
91
  /* @__PURE__ */ jsxs(Grid.Col, { sm: "4", md: "8", xl: "12", children: [
87
92
  /* @__PURE__ */ jsx("div", { className: "workspace-search px-16 py-8 ", children: /* @__PURE__ */ jsx(SearchBar, { isVariant: !0, className: "gap-16", onChange: handleSearchChange }) }),
88
- /* @__PURE__ */ jsxs("div", { className: "d-flex align-items-center justify-content-end px-8 py-4", children: [
93
+ /* @__PURE__ */ jsxs(Flex, { className: "px-8 py-4", align: "center", justify: "end", children: [
89
94
  /* @__PURE__ */ jsx("small", { className: "text-muted", children: t("workspace.search.order") }),
90
95
  /* @__PURE__ */ jsxs(Dropdown, { children: [
91
96
  /* @__PURE__ */ jsx(Dropdown.Trigger, { size: "sm", label: getSortOrderLabel(), variant: "ghost" }),
@@ -100,7 +105,7 @@ const Nextcloud = ({
100
105
  /* @__PURE__ */ jsx(Grid.Col, { sm: "4", md: "8", xl: "12", className: "p-8 gap-8", children: documents ? documents.length !== 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-workspace", children: documents.map((doc) => {
101
106
  const isSelected = selectedPaths.has(doc.path);
102
107
  return /* @__PURE__ */ jsx(NextcloudFileCard, { doc, userId: user.userId, isSelected, onClick: () => handleSelectDoc(doc) }, doc.path);
103
- }) }) : /* @__PURE__ */ jsx(EmptyScreen, { imageSrc: illuNoContentInFolder, size: 64, text: t("nextcloud.empty.docSpace") }) : /* @__PURE__ */ jsx(LoadingScreen, {}) })
108
+ }) }) : /* @__PURE__ */ jsx(EmptyScreen, { imageSrc: illuTrash, text: t("workspace.empty.docSpace"), title: t("explorer.emptyScreen.trash.title") }) : /* @__PURE__ */ jsx(LoadingScreen, {}) })
104
109
  ] }) })
105
110
  ] });
106
111
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edifice.io/react",
3
- "version": "2.6.2-develop-integration.20260824151812",
3
+ "version": "2.6.2-develop-integration.20260824172410",
4
4
  "description": "Edifice React Library",
5
5
  "keywords": [
6
6
  "react",
@@ -140,9 +140,9 @@
140
140
  "swiper": "10.1.0",
141
141
  "ua-parser-js": "1.0.36",
142
142
  "zustand": "4.5.7",
143
- "@edifice.io/bootstrap": "2.6.2-develop-integration.20260824151812",
144
- "@edifice.io/tiptap-extensions": "2.6.2-develop-integration.20260824151812",
145
- "@edifice.io/utilities": "2.6.2-develop-integration.20260824151812"
143
+ "@edifice.io/tiptap-extensions": "2.6.2-develop-integration.20260824172410",
144
+ "@edifice.io/utilities": "2.6.2-develop-integration.20260824172410",
145
+ "@edifice.io/bootstrap": "2.6.2-develop-integration.20260824172410"
146
146
  },
147
147
  "devDependencies": {
148
148
  "@babel/plugin-transform-react-pure-annotations": "7.27.1",
@@ -173,8 +173,8 @@
173
173
  "vite": "5.4.14",
174
174
  "vite-plugin-dts": "4.5.4",
175
175
  "vite-tsconfig-paths": "5.1.4",
176
- "@edifice.io/client": "2.6.2-develop-integration.20260824151812",
177
- "@edifice.io/config": "2.6.2-develop-integration.20260824151812"
176
+ "@edifice.io/client": "2.6.2-develop-integration.20260824172410",
177
+ "@edifice.io/config": "2.6.2-develop-integration.20260824172410"
178
178
  },
179
179
  "peerDependencies": {
180
180
  "@react-spring/web": "9.7.5",