ptechcore_ui 1.0.25 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +648 -38
- package/dist/index.d.cts +471 -1
- package/dist/index.d.ts +471 -1
- package/dist/index.js +643 -38
- package/package.json +57 -55
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
CHOICES: () => Choices_default,
|
|
41
41
|
CountrySelector: () => CountrySelector,
|
|
42
42
|
DateInput: () => DateInput,
|
|
43
|
+
EntityFileManager: () => EntityFileManager,
|
|
43
44
|
FDrawer: () => FDrawer,
|
|
44
45
|
FetchApi: () => FetchApi,
|
|
45
46
|
FileInput: () => FileInput,
|
|
@@ -59,6 +60,7 @@ __export(index_exports, {
|
|
|
59
60
|
SelectCostCenter: () => SelectCostCenter,
|
|
60
61
|
SelectDepartment: () => SelectDepartment,
|
|
61
62
|
SelectInput: () => SelectInput,
|
|
63
|
+
SelectUnit: () => SelectUnit,
|
|
62
64
|
SelectUser: () => SelectUser,
|
|
63
65
|
SelectVendor: () => SelectVendor,
|
|
64
66
|
SessionProvider: () => SessionProvider,
|
|
@@ -68,12 +70,15 @@ __export(index_exports, {
|
|
|
68
70
|
ThemeProvider: () => ThemeContext_default,
|
|
69
71
|
ToastContainer: () => Toast_default,
|
|
70
72
|
ToastProvider: () => ToastProvider,
|
|
73
|
+
UnitServices: () => UnitServices,
|
|
71
74
|
UserServices: () => UserServices,
|
|
75
|
+
fileManagerApi: () => fileManagerApi,
|
|
72
76
|
formatDate: () => formatDate,
|
|
73
77
|
formatFileSize: () => formatFileSize,
|
|
74
78
|
getFileIcon: () => getFileIcon,
|
|
75
79
|
useAlert: () => useAlert,
|
|
76
80
|
useFileManager: () => useFileManager,
|
|
81
|
+
useFileManagerApi: () => useFileManagerApi,
|
|
77
82
|
useSession: () => useSession,
|
|
78
83
|
useToast: () => useToast
|
|
79
84
|
});
|
|
@@ -92,9 +97,9 @@ var PrimaryButton = ({
|
|
|
92
97
|
{
|
|
93
98
|
type: "submit",
|
|
94
99
|
disabled: loading || props.disabled,
|
|
95
|
-
className: `px-4 py-2 text-sm rounded-lg hover:
|
|
100
|
+
className: `px-4 py-2 text-sm rounded-lg hover:opacity-80 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex justify-center items-center ${classname} ${variant === "full" ? "bg-[var(--color-primary)] text-[var(--color-text-inverse)]" : variant === "outline" ? "border border-[var(--color-primary)] text-[var(--color-primary)] bg-transparent" : "bg-transparent text-[var(--color-primary)]"}`,
|
|
96
101
|
...props,
|
|
97
|
-
children: loading ? "
|
|
102
|
+
children: loading ? "Chargement..." : children
|
|
98
103
|
}
|
|
99
104
|
);
|
|
100
105
|
var SecondaryButton = ({
|
|
@@ -107,9 +112,9 @@ var SecondaryButton = ({
|
|
|
107
112
|
{
|
|
108
113
|
type: "button",
|
|
109
114
|
disabled: loading || props.disabled,
|
|
110
|
-
className: `px-4 py-2 rounded-lg hover:
|
|
115
|
+
className: `px-4 py-2 text-sm rounded-lg hover:opacity-80 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center ${variant === "full" ? "bg-[var(--color-secondary)] text-[var(--color-text-inverse)]" : variant === "outline" ? "border border-[var(--color-secondary)] text-[var(--color-secondary)] bg-transparent" : "bg-transparent text-[var(--color-secondary)]"}`,
|
|
111
116
|
...props,
|
|
112
|
-
children: loading ? "
|
|
117
|
+
children: loading ? "Chargement..." : children
|
|
113
118
|
}
|
|
114
119
|
);
|
|
115
120
|
var Buttons_default = PrimaryButton;
|
|
@@ -117,7 +122,7 @@ var Buttons_default = PrimaryButton;
|
|
|
117
122
|
// src/components/common/Modals.tsx
|
|
118
123
|
var import_react_dom = require("react-dom");
|
|
119
124
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
120
|
-
var Modal = ({ title, description, width = "max-w-md", open, onClose, children }) => {
|
|
125
|
+
var Modal = ({ title, description, width = "max-w-md", minContentHeight, open, onClose, children }) => {
|
|
121
126
|
if (!open) return null;
|
|
122
127
|
const modalContent = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[9999]", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `bg-[var(--color-surface)] rounded-lg p-6 mx-4 w-full ${width}`, children: [
|
|
123
128
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex justify-between items-start mb-6", children: [
|
|
@@ -135,7 +140,14 @@ var Modal = ({ title, description, width = "max-w-md", open, onClose, children }
|
|
|
135
140
|
}
|
|
136
141
|
)
|
|
137
142
|
] }),
|
|
138
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
143
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
144
|
+
"div",
|
|
145
|
+
{
|
|
146
|
+
className: "w-full max-h-[80vh] overflow-y-auto",
|
|
147
|
+
style: minContentHeight ? { minHeight: minContentHeight } : void 0,
|
|
148
|
+
children
|
|
149
|
+
}
|
|
150
|
+
)
|
|
139
151
|
] }) });
|
|
140
152
|
return (0, import_react_dom.createPortal)(modalContent, document.body);
|
|
141
153
|
};
|
|
@@ -157,10 +169,10 @@ var InputField = ({
|
|
|
157
169
|
onBlur
|
|
158
170
|
}) => {
|
|
159
171
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col gap-1 w-full", children: [
|
|
160
|
-
label && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { htmlFor: name, className: "block text-
|
|
172
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { htmlFor: name, className: "block text-[var(--color-text-secondary)] text-sm font-medium mb-2", children: [
|
|
161
173
|
label,
|
|
162
174
|
" ",
|
|
163
|
-
required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-
|
|
175
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[var(--color-error)]", children: "*" })
|
|
164
176
|
] }),
|
|
165
177
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
166
178
|
"input",
|
|
@@ -174,13 +186,15 @@ var InputField = ({
|
|
|
174
186
|
disabled,
|
|
175
187
|
onChange,
|
|
176
188
|
onBlur,
|
|
177
|
-
className: `w-full px-3 py-2 border
|
|
178
|
-
|
|
179
|
-
|
|
189
|
+
className: `w-full px-3 py-2 border rounded-lg text-sm
|
|
190
|
+
bg-[var(--color-surface)] text-[var(--color-text-primary)]
|
|
191
|
+
focus:ring-2 focus:ring-[var(--color-primary)]/20 focus:border-[var(--color-primary)] focus:outline-none
|
|
192
|
+
${error ? "border-[var(--color-error)]" : "border-[var(--color-border)]"}
|
|
193
|
+
${disabled ? "bg-[var(--color-background)] cursor-not-allowed opacity-60" : ""}
|
|
180
194
|
`
|
|
181
195
|
}
|
|
182
196
|
),
|
|
183
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-
|
|
197
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-[var(--color-error)]", children: error })
|
|
184
198
|
] });
|
|
185
199
|
};
|
|
186
200
|
var TextInput = (props) => {
|
|
@@ -210,11 +224,11 @@ var SelectInput = ({
|
|
|
210
224
|
"label",
|
|
211
225
|
{
|
|
212
226
|
htmlFor: name,
|
|
213
|
-
className: "block text-
|
|
227
|
+
className: "block text-[var(--color-text-secondary)] text-sm font-medium mb-2",
|
|
214
228
|
children: [
|
|
215
229
|
label,
|
|
216
230
|
" ",
|
|
217
|
-
required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-
|
|
231
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[var(--color-error)]", children: "*" })
|
|
218
232
|
]
|
|
219
233
|
}
|
|
220
234
|
),
|
|
@@ -229,9 +243,10 @@ var SelectInput = ({
|
|
|
229
243
|
onChange,
|
|
230
244
|
onBlur,
|
|
231
245
|
className: `w-full px-4 py-2 border rounded-lg text-sm
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
${
|
|
246
|
+
bg-[var(--color-surface)] text-[var(--color-text-primary)]
|
|
247
|
+
focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]/20 focus:border-[var(--color-primary)]
|
|
248
|
+
${error ? "border-[var(--color-error)]" : "border-[var(--color-border)]"}
|
|
249
|
+
${disabled ? "bg-[var(--color-background)] cursor-not-allowed opacity-60" : ""}
|
|
235
250
|
`,
|
|
236
251
|
children: [
|
|
237
252
|
defaultValue !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: typeof defaultValue === "string" ? defaultValue : "S\xE9lectionnez une option" }),
|
|
@@ -239,7 +254,7 @@ var SelectInput = ({
|
|
|
239
254
|
]
|
|
240
255
|
}
|
|
241
256
|
),
|
|
242
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-
|
|
257
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-[var(--color-error)]", children: error })
|
|
243
258
|
] });
|
|
244
259
|
};
|
|
245
260
|
var addressIpformMedia = "http://localhost:8000/media/";
|
|
@@ -765,7 +780,7 @@ var import_react2 = require("react");
|
|
|
765
780
|
|
|
766
781
|
// src/services/api.ts
|
|
767
782
|
var chooseEnv = localStorage.getItem("env") ?? "prod";
|
|
768
|
-
var ADDRESS_IP = chooseEnv === "prod" ? "backend-
|
|
783
|
+
var ADDRESS_IP = chooseEnv === "prod" ? "core.backend-rewise.praedium-tech.com" : "localhost:8000";
|
|
769
784
|
var ADDRESS_IP_URL = chooseEnv === "prod" ? `https://${ADDRESS_IP}/` : `http://${ADDRESS_IP}/`;
|
|
770
785
|
var API_URL = `${ADDRESS_IP_URL}api`;
|
|
771
786
|
var FetchApi = class {
|
|
@@ -968,6 +983,21 @@ var SessionProvider = ({ children }) => {
|
|
|
968
983
|
localStorage.removeItem("token");
|
|
969
984
|
setToken(null);
|
|
970
985
|
};
|
|
986
|
+
const refreshSession = async () => {
|
|
987
|
+
if (!token) return;
|
|
988
|
+
try {
|
|
989
|
+
const res = await AuthServices.getUserInformations(token);
|
|
990
|
+
const result = res;
|
|
991
|
+
if (result.success === true) {
|
|
992
|
+
setLoggedUser(result.data.user);
|
|
993
|
+
setActiveBusinessEntity(
|
|
994
|
+
result.data.user.centers_access.find((item) => parseInt(String(item.id)) === parseInt(saved_center_id)) || result.data.user.centers_access[0] || null
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
} catch (error) {
|
|
998
|
+
console.error("Failed to refresh session:", error);
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
971
1001
|
(0, import_react2.useEffect)(() => {
|
|
972
1002
|
if (token) {
|
|
973
1003
|
AuthServices.getUserInformations(token).then((res) => {
|
|
@@ -995,10 +1025,12 @@ var SessionProvider = ({ children }) => {
|
|
|
995
1025
|
activeBusinessEntity,
|
|
996
1026
|
setActiveBusinessEntity,
|
|
997
1027
|
token,
|
|
1028
|
+
setToken,
|
|
998
1029
|
login,
|
|
999
1030
|
logout,
|
|
1000
1031
|
showAuthModal,
|
|
1001
1032
|
setShowAuthModal,
|
|
1033
|
+
refreshSession,
|
|
1002
1034
|
vendors,
|
|
1003
1035
|
setVendors,
|
|
1004
1036
|
loadingVendors,
|
|
@@ -1027,9 +1059,8 @@ var UserServices = {
|
|
|
1027
1059
|
deleteUser: (id, token) => FetchApi.delete(`${USERS_API_URL}${id}/`, token),
|
|
1028
1060
|
// Obtenir les utilisateurs d'une entité
|
|
1029
1061
|
getEntityUsers: (entityId, token) => FetchApi.get(`${API_URL}/core/entities/${entityId}/users/`, token),
|
|
1030
|
-
// Obtenir les
|
|
1031
|
-
getuserEntitiesAccess: (id, token) => FetchApi.get(`${API_URL}/core/entities/`, token),
|
|
1032
|
-
// !!! ce n'est pas la bonne url
|
|
1062
|
+
// Obtenir les entités auxquelles un utilisateur a accès
|
|
1063
|
+
getuserEntitiesAccess: (id, token) => FetchApi.get(`${API_URL}/core/users/${id}/entities/`, token),
|
|
1033
1064
|
// Ajouter un utilisateur à une entité
|
|
1034
1065
|
addUserToEntity: (entityId, userId, token) => FetchApi.post(`${API_URL}/core/entities/${entityId}/users/`, { user_id: userId }, token),
|
|
1035
1066
|
// === Nouvelles méthodes pour le profil utilisateur ===
|
|
@@ -1074,16 +1105,17 @@ var ToastProvider = ({ children }) => {
|
|
|
1074
1105
|
const addToast = (0, import_react3.useCallback)((toast) => {
|
|
1075
1106
|
const id = generateId();
|
|
1076
1107
|
const defaultDuration = toast.type === "error" ? 7e3 : 3e3;
|
|
1108
|
+
const duration = toast.duration ?? defaultDuration;
|
|
1077
1109
|
const newToast = {
|
|
1110
|
+
...toast,
|
|
1078
1111
|
id,
|
|
1079
|
-
duration
|
|
1080
|
-
...toast
|
|
1112
|
+
duration
|
|
1081
1113
|
};
|
|
1082
1114
|
setToasts((prev) => [...prev, newToast]);
|
|
1083
|
-
if (
|
|
1115
|
+
if (duration > 0) {
|
|
1084
1116
|
setTimeout(() => {
|
|
1085
|
-
|
|
1086
|
-
},
|
|
1117
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1118
|
+
}, duration);
|
|
1087
1119
|
}
|
|
1088
1120
|
}, []);
|
|
1089
1121
|
const removeToast = (0, import_react3.useCallback)((id) => {
|
|
@@ -1896,7 +1928,7 @@ var RewiseLayout = ({ children, module_name = "Rewise", module_description = "De
|
|
|
1896
1928
|
"organizations": "organizations",
|
|
1897
1929
|
"entities": "entities"
|
|
1898
1930
|
};
|
|
1899
|
-
setSelectedModule(routeMapping[moduleId] ||
|
|
1931
|
+
setSelectedModule(routeMapping[moduleId] || moduleId);
|
|
1900
1932
|
}
|
|
1901
1933
|
}, [location]);
|
|
1902
1934
|
const handleThemeChange = (type) => {
|
|
@@ -3470,6 +3502,16 @@ var Pages = ({
|
|
|
3470
3502
|
};
|
|
3471
3503
|
var Pages_default = Pages;
|
|
3472
3504
|
|
|
3505
|
+
// src/services/UnitServices.ts
|
|
3506
|
+
var URI = `${API_URL}/crm/units/`;
|
|
3507
|
+
var UnitServices = {
|
|
3508
|
+
create: (data) => FetchApi.post(`${URI}`, data),
|
|
3509
|
+
get: (id) => FetchApi.get(`${URI}${id}/`),
|
|
3510
|
+
list: (params) => FetchApi.get(`${URI}?${new URLSearchParams(params).toString()}`),
|
|
3511
|
+
update: (id, data) => FetchApi.put(`${URI}${id}/`, data),
|
|
3512
|
+
delete: (id) => FetchApi.delete(`${URI}${id}/`)
|
|
3513
|
+
};
|
|
3514
|
+
|
|
3473
3515
|
// src/components/common/FDrawer.tsx
|
|
3474
3516
|
var import_react8 = __toESM(require("react"), 1);
|
|
3475
3517
|
var import_react_router_dom4 = require("react-router-dom");
|
|
@@ -5351,7 +5393,7 @@ var ApprovalWorkflow = ({
|
|
|
5351
5393
|
if (CustomBtn) {
|
|
5352
5394
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
5353
5395
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CustomBtn, { onClick: open_modal }),
|
|
5354
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Modals_default, { open: isOpen, onClose: close_modal, title, children: formulaire() })
|
|
5396
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Modals_default, { open: isOpen, onClose: close_modal, title, width: "max-w-lg", children: formulaire() })
|
|
5355
5397
|
] });
|
|
5356
5398
|
}
|
|
5357
5399
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
@@ -5549,7 +5591,7 @@ var AddStageButton = ({
|
|
|
5549
5591
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5550
5592
|
Modals_default,
|
|
5551
5593
|
{
|
|
5552
|
-
width: "",
|
|
5594
|
+
width: "max-w-lg",
|
|
5553
5595
|
title: "Ajouter une personne",
|
|
5554
5596
|
description: "S\xE9lectionnez un utilisateur interne ou ajoutez un validateur externe",
|
|
5555
5597
|
open: showModal,
|
|
@@ -5868,7 +5910,7 @@ var MinimalVendorForm = ({
|
|
|
5868
5910
|
Modals_default,
|
|
5869
5911
|
{
|
|
5870
5912
|
title: "Ajouter un fournisseur",
|
|
5871
|
-
width: "w-
|
|
5913
|
+
width: "max-w-2xl",
|
|
5872
5914
|
description: ``,
|
|
5873
5915
|
open: isOpen,
|
|
5874
5916
|
onClose,
|
|
@@ -5923,17 +5965,17 @@ var MinimalVendorForm = ({
|
|
|
5923
5965
|
};
|
|
5924
5966
|
|
|
5925
5967
|
// src/services/DepartmentServices.ts
|
|
5926
|
-
var
|
|
5968
|
+
var URI2 = `${API_URL}/core/departments/`;
|
|
5927
5969
|
var DepartmentServices = {
|
|
5928
|
-
create: (data) => FetchApi.post(`${
|
|
5929
|
-
get: (id) => FetchApi.get(`${
|
|
5930
|
-
list: (params) => FetchApi.get(`${
|
|
5931
|
-
update: (id, data) => FetchApi.put(`${
|
|
5932
|
-
delete: (id) => FetchApi.delete(`${
|
|
5970
|
+
create: (data) => FetchApi.post(`${URI2}`, data),
|
|
5971
|
+
get: (id) => FetchApi.get(`${URI2}${id}/`),
|
|
5972
|
+
list: (params) => FetchApi.get(`${URI2}?${new URLSearchParams(params).toString()}`),
|
|
5973
|
+
update: (id, data) => FetchApi.put(`${URI2}${id}/`, data),
|
|
5974
|
+
delete: (id) => FetchApi.delete(`${URI2}${id}/`)
|
|
5933
5975
|
};
|
|
5934
5976
|
|
|
5935
5977
|
// src/services/ProfitCostsServices.ts
|
|
5936
|
-
var
|
|
5978
|
+
var URI3 = `${API_URL}/accounting/profit-or-cost-center/`;
|
|
5937
5979
|
var COST_URI = `${API_URL}/accounting/cost-center/`;
|
|
5938
5980
|
var CostServices = {
|
|
5939
5981
|
create: (data) => FetchApi.post(`${COST_URI}`, data),
|
|
@@ -6240,6 +6282,80 @@ var SelectCostCenter = ({
|
|
|
6240
6282
|
loading && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-gray-500 mt-2", children: "Chargement des centres de co\xFBt..." })
|
|
6241
6283
|
] });
|
|
6242
6284
|
};
|
|
6285
|
+
var SelectUnit = ({
|
|
6286
|
+
value,
|
|
6287
|
+
onSelect
|
|
6288
|
+
}) => {
|
|
6289
|
+
const { token, activeBusinessEntity } = useSession();
|
|
6290
|
+
const [units, setUnits] = (0, import_react13.useState)(() => {
|
|
6291
|
+
const cacheKey = `units_cache_${activeBusinessEntity?.id || "default"}`;
|
|
6292
|
+
const cached = sessionStorage.getItem(cacheKey);
|
|
6293
|
+
return cached ? JSON.parse(cached) : [];
|
|
6294
|
+
});
|
|
6295
|
+
const [loading, setLoading] = (0, import_react13.useState)(false);
|
|
6296
|
+
(0, import_react13.useEffect)(() => {
|
|
6297
|
+
const cacheKey = `units_cache_${activeBusinessEntity?.id || "default"}`;
|
|
6298
|
+
const cached = sessionStorage.getItem(cacheKey);
|
|
6299
|
+
if (!cached) {
|
|
6300
|
+
loadUnits();
|
|
6301
|
+
} else {
|
|
6302
|
+
setUnits(JSON.parse(cached));
|
|
6303
|
+
}
|
|
6304
|
+
}, [activeBusinessEntity?.id]);
|
|
6305
|
+
const loadUnits = async () => {
|
|
6306
|
+
if (!token) return;
|
|
6307
|
+
try {
|
|
6308
|
+
setLoading(true);
|
|
6309
|
+
const result = await UnitServices.list({ business_entity_id: activeBusinessEntity?.id });
|
|
6310
|
+
if (result.success) {
|
|
6311
|
+
setUnits(result.data);
|
|
6312
|
+
const cacheKey = `units_cache_${activeBusinessEntity?.id || "default"}`;
|
|
6313
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(result.data));
|
|
6314
|
+
}
|
|
6315
|
+
} catch (error) {
|
|
6316
|
+
console.error(error);
|
|
6317
|
+
} finally {
|
|
6318
|
+
setLoading(false);
|
|
6319
|
+
}
|
|
6320
|
+
};
|
|
6321
|
+
const handleRefresh = () => {
|
|
6322
|
+
const cacheKey = `units_cache_${activeBusinessEntity?.id || "default"}`;
|
|
6323
|
+
sessionStorage.removeItem(cacheKey);
|
|
6324
|
+
loadUnits();
|
|
6325
|
+
};
|
|
6326
|
+
const getUnitOptions = () => {
|
|
6327
|
+
return units.map((unit) => ({
|
|
6328
|
+
value: unit.id,
|
|
6329
|
+
label: `${unit.code ? `[${unit.code}] ` : ""}${unit.name || "Sans nom"}`,
|
|
6330
|
+
object: unit,
|
|
6331
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center space-x-3", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex-1", children: [
|
|
6332
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "font-medium text-gray-900", children: unit.name || "Sans nom" }),
|
|
6333
|
+
unit.code && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "text-sm text-gray-500", children: [
|
|
6334
|
+
"Code: ",
|
|
6335
|
+
unit.code
|
|
6336
|
+
] }),
|
|
6337
|
+
unit.location && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "text-xs text-gray-400", children: unit.location })
|
|
6338
|
+
] }) })
|
|
6339
|
+
}));
|
|
6340
|
+
};
|
|
6341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
|
|
6342
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex justify-between ", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "S\xE9lectionner une unit\xE9" }) }),
|
|
6343
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
6344
|
+
SearchableSelect,
|
|
6345
|
+
{
|
|
6346
|
+
value,
|
|
6347
|
+
options: getUnitOptions(),
|
|
6348
|
+
placeholder: "S\xE9lectionner une unit\xE9 ...",
|
|
6349
|
+
searchPlaceholder: "Rechercher...",
|
|
6350
|
+
onSelect,
|
|
6351
|
+
disabled: loading,
|
|
6352
|
+
refresh: handleRefresh
|
|
6353
|
+
},
|
|
6354
|
+
"unit" + value
|
|
6355
|
+
),
|
|
6356
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-gray-500 mt-2", children: "Chargement des unit\xE9s..." })
|
|
6357
|
+
] });
|
|
6358
|
+
};
|
|
6243
6359
|
|
|
6244
6360
|
// src/components/common/Choices.tsx
|
|
6245
6361
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
@@ -7762,6 +7878,495 @@ var FileManagerContent = ({ className }) => {
|
|
|
7762
7878
|
var FileManager = (props) => {
|
|
7763
7879
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(FileManagerProvider, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(FileManagerContent, { className: props.className }) });
|
|
7764
7880
|
};
|
|
7881
|
+
|
|
7882
|
+
// src/components/common/FileManager/components/EntityFileManager.tsx
|
|
7883
|
+
var import_react22 = __toESM(require("react"), 1);
|
|
7884
|
+
var import_lucide_react17 = require("lucide-react");
|
|
7885
|
+
|
|
7886
|
+
// src/components/common/FileManager/hooks/useFileManagerApi.ts
|
|
7887
|
+
var import_react21 = require("react");
|
|
7888
|
+
|
|
7889
|
+
// src/components/common/FileManager/services/fileManagerApi.ts
|
|
7890
|
+
var API_BASE = "/api/files_manager";
|
|
7891
|
+
var ENTITY_MODEL_MAP = {
|
|
7892
|
+
CLIENT: "accounting.Client",
|
|
7893
|
+
VENDOR: "accounting.Vendor",
|
|
7894
|
+
RFQ: "procurement.RFQ",
|
|
7895
|
+
DEPT: "core.Departments",
|
|
7896
|
+
PROJECT: "core.Project"
|
|
7897
|
+
};
|
|
7898
|
+
async function apiRequest(endpoint, options = {}) {
|
|
7899
|
+
const url = `${API_BASE}${endpoint}`;
|
|
7900
|
+
const headers = {
|
|
7901
|
+
...options.headers
|
|
7902
|
+
};
|
|
7903
|
+
if (!(options.body instanceof FormData)) {
|
|
7904
|
+
headers["Content-Type"] = "application/json";
|
|
7905
|
+
}
|
|
7906
|
+
const csrfToken = getCsrfToken();
|
|
7907
|
+
if (csrfToken) {
|
|
7908
|
+
headers["X-CSRFToken"] = csrfToken;
|
|
7909
|
+
}
|
|
7910
|
+
const response = await fetch(url, {
|
|
7911
|
+
...options,
|
|
7912
|
+
headers,
|
|
7913
|
+
credentials: "include"
|
|
7914
|
+
// Inclure les cookies pour l'auth
|
|
7915
|
+
});
|
|
7916
|
+
if (!response.ok) {
|
|
7917
|
+
let errorMessage = `Erreur HTTP ${response.status}`;
|
|
7918
|
+
try {
|
|
7919
|
+
const errorData = await response.json();
|
|
7920
|
+
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
7921
|
+
} catch {
|
|
7922
|
+
}
|
|
7923
|
+
throw new Error(errorMessage);
|
|
7924
|
+
}
|
|
7925
|
+
if (response.status === 204) {
|
|
7926
|
+
return {};
|
|
7927
|
+
}
|
|
7928
|
+
return response.json();
|
|
7929
|
+
}
|
|
7930
|
+
function getCsrfToken() {
|
|
7931
|
+
const name = "csrftoken";
|
|
7932
|
+
const cookies = document.cookie.split(";");
|
|
7933
|
+
for (const cookie of cookies) {
|
|
7934
|
+
const trimmed = cookie.trim();
|
|
7935
|
+
if (trimmed.startsWith(`${name}=`)) {
|
|
7936
|
+
return trimmed.substring(name.length + 1);
|
|
7937
|
+
}
|
|
7938
|
+
}
|
|
7939
|
+
return null;
|
|
7940
|
+
}
|
|
7941
|
+
function buildQueryString(params) {
|
|
7942
|
+
const searchParams = new URLSearchParams();
|
|
7943
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7944
|
+
if (value !== void 0 && value !== null) {
|
|
7945
|
+
searchParams.append(key, String(value));
|
|
7946
|
+
}
|
|
7947
|
+
}
|
|
7948
|
+
const queryString = searchParams.toString();
|
|
7949
|
+
return queryString ? `?${queryString}` : "";
|
|
7950
|
+
}
|
|
7951
|
+
async function getEntityFolders(entityType, entityId, folderType) {
|
|
7952
|
+
const model = ENTITY_MODEL_MAP[entityType];
|
|
7953
|
+
if (!model) {
|
|
7954
|
+
throw new Error(`Type d'entit\xE9 non support\xE9: ${entityType}`);
|
|
7955
|
+
}
|
|
7956
|
+
const params = buildQueryString({
|
|
7957
|
+
model,
|
|
7958
|
+
id: entityId,
|
|
7959
|
+
type: folderType
|
|
7960
|
+
});
|
|
7961
|
+
return apiRequest(`/folders/for_entity/${params}`);
|
|
7962
|
+
}
|
|
7963
|
+
async function getFolderTree(folderCode) {
|
|
7964
|
+
return apiRequest(`/folders/${folderCode}/tree/`);
|
|
7965
|
+
}
|
|
7966
|
+
async function getFolder(folderCode) {
|
|
7967
|
+
return apiRequest(`/folders/${folderCode}/`);
|
|
7968
|
+
}
|
|
7969
|
+
async function createFolder(name, parentCode, businessEntityId) {
|
|
7970
|
+
return apiRequest("/folders/", {
|
|
7971
|
+
method: "POST",
|
|
7972
|
+
body: JSON.stringify({
|
|
7973
|
+
name,
|
|
7974
|
+
parent: parentCode,
|
|
7975
|
+
business_entity: businessEntityId,
|
|
7976
|
+
folder_type: "MISC",
|
|
7977
|
+
// Type par défaut pour les dossiers créés manuellement
|
|
7978
|
+
is_system_folder: false
|
|
7979
|
+
})
|
|
7980
|
+
});
|
|
7981
|
+
}
|
|
7982
|
+
async function renameFolder(folderCode, newName) {
|
|
7983
|
+
return apiRequest(`/folders/${folderCode}/`, {
|
|
7984
|
+
method: "PATCH",
|
|
7985
|
+
body: JSON.stringify({ name: newName })
|
|
7986
|
+
});
|
|
7987
|
+
}
|
|
7988
|
+
async function deleteFolder(folderCode) {
|
|
7989
|
+
await apiRequest(`/folders/${folderCode}/`, {
|
|
7990
|
+
method: "DELETE"
|
|
7991
|
+
});
|
|
7992
|
+
}
|
|
7993
|
+
async function getFolderFiles(folderId) {
|
|
7994
|
+
const params = buildQueryString({ folder: folderId });
|
|
7995
|
+
return apiRequest(`/files/${params}`);
|
|
7996
|
+
}
|
|
7997
|
+
async function uploadFile(file, folderCode, options = {}) {
|
|
7998
|
+
const formData = new FormData();
|
|
7999
|
+
formData.append("file", file);
|
|
8000
|
+
formData.append("folder_id", folderCode);
|
|
8001
|
+
if (options.name) {
|
|
8002
|
+
formData.append("name", options.name);
|
|
8003
|
+
}
|
|
8004
|
+
if (options.description) {
|
|
8005
|
+
formData.append("description", options.description);
|
|
8006
|
+
}
|
|
8007
|
+
if (options.tags && options.tags.length > 0) {
|
|
8008
|
+
formData.append("tags", JSON.stringify(options.tags));
|
|
8009
|
+
}
|
|
8010
|
+
return apiRequest("/files/", {
|
|
8011
|
+
method: "POST",
|
|
8012
|
+
body: formData
|
|
8013
|
+
});
|
|
8014
|
+
}
|
|
8015
|
+
async function uploadFiles(files, folderCode) {
|
|
8016
|
+
const results = [];
|
|
8017
|
+
for (const file of files) {
|
|
8018
|
+
const uploaded = await uploadFile(file, folderCode);
|
|
8019
|
+
results.push(uploaded);
|
|
8020
|
+
}
|
|
8021
|
+
return results;
|
|
8022
|
+
}
|
|
8023
|
+
async function renameFile(fileCode, newName) {
|
|
8024
|
+
return apiRequest(`/files/${fileCode}/`, {
|
|
8025
|
+
method: "PATCH",
|
|
8026
|
+
body: JSON.stringify({ name: newName })
|
|
8027
|
+
});
|
|
8028
|
+
}
|
|
8029
|
+
async function deleteFile(fileCode) {
|
|
8030
|
+
await apiRequest(`/files/${fileCode}/`, {
|
|
8031
|
+
method: "DELETE"
|
|
8032
|
+
});
|
|
8033
|
+
}
|
|
8034
|
+
function getDownloadUrl(fileCode) {
|
|
8035
|
+
return `${API_BASE}/files/${fileCode}/download/`;
|
|
8036
|
+
}
|
|
8037
|
+
function getFileUrl(fileUrl) {
|
|
8038
|
+
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
|
|
8039
|
+
return fileUrl;
|
|
8040
|
+
}
|
|
8041
|
+
return fileUrl.startsWith("/") ? fileUrl : `/${fileUrl}`;
|
|
8042
|
+
}
|
|
8043
|
+
var fileManagerApi = {
|
|
8044
|
+
// Dossiers
|
|
8045
|
+
getEntityFolders,
|
|
8046
|
+
getFolderTree,
|
|
8047
|
+
getFolder,
|
|
8048
|
+
createFolder,
|
|
8049
|
+
renameFolder,
|
|
8050
|
+
deleteFolder,
|
|
8051
|
+
// Fichiers
|
|
8052
|
+
getFolderFiles,
|
|
8053
|
+
uploadFile,
|
|
8054
|
+
uploadFiles,
|
|
8055
|
+
renameFile,
|
|
8056
|
+
deleteFile,
|
|
8057
|
+
// URLs
|
|
8058
|
+
getDownloadUrl,
|
|
8059
|
+
getFileUrl,
|
|
8060
|
+
// Helpers exposés
|
|
8061
|
+
ENTITY_MODEL_MAP
|
|
8062
|
+
};
|
|
8063
|
+
|
|
8064
|
+
// src/components/common/FileManager/hooks/useFileManagerApi.ts
|
|
8065
|
+
function transformFile(backendFile, parentPath, parentId) {
|
|
8066
|
+
return {
|
|
8067
|
+
id: backendFile.code,
|
|
8068
|
+
name: backendFile.name,
|
|
8069
|
+
type: "file",
|
|
8070
|
+
mimeType: backendFile.mime_type,
|
|
8071
|
+
size: backendFile.size,
|
|
8072
|
+
path: `${parentPath}/${backendFile.name}`,
|
|
8073
|
+
parentId,
|
|
8074
|
+
url: fileManagerApi.getFileUrl(backendFile.file_url),
|
|
8075
|
+
createdAt: backendFile.created_at,
|
|
8076
|
+
updatedAt: backendFile.updated_at,
|
|
8077
|
+
metadata: {
|
|
8078
|
+
extension: backendFile.extension,
|
|
8079
|
+
folderId: backendFile.folder
|
|
8080
|
+
}
|
|
8081
|
+
};
|
|
8082
|
+
}
|
|
8083
|
+
function transformFolder(backendFolder, parentPath = "", parentId = null) {
|
|
8084
|
+
const currentPath = parentPath ? `${parentPath}/${backendFolder.name}` : `/${backendFolder.name}`;
|
|
8085
|
+
const childFolders = (backendFolder.children || []).map(
|
|
8086
|
+
(child) => transformFolder(child, currentPath, backendFolder.code)
|
|
8087
|
+
);
|
|
8088
|
+
const childFiles = (backendFolder.files || []).map(
|
|
8089
|
+
(file) => transformFile(file, currentPath, backendFolder.code)
|
|
8090
|
+
);
|
|
8091
|
+
return {
|
|
8092
|
+
id: backendFolder.code,
|
|
8093
|
+
name: backendFolder.name,
|
|
8094
|
+
type: "folder",
|
|
8095
|
+
path: currentPath,
|
|
8096
|
+
parentId,
|
|
8097
|
+
children: [...childFolders, ...childFiles],
|
|
8098
|
+
metadata: {
|
|
8099
|
+
folderType: backendFolder.folder_type,
|
|
8100
|
+
folderTypeDisplay: backendFolder.folder_type_display,
|
|
8101
|
+
categoryType: backendFolder.category_type,
|
|
8102
|
+
isSystemFolder: backendFolder.is_system_folder,
|
|
8103
|
+
fileCount: backendFolder.file_count,
|
|
8104
|
+
totalSize: backendFolder.total_size
|
|
8105
|
+
}
|
|
8106
|
+
};
|
|
8107
|
+
}
|
|
8108
|
+
function extractRootChildren(entityFolder) {
|
|
8109
|
+
return entityFolder.children || [];
|
|
8110
|
+
}
|
|
8111
|
+
function useFileManagerApi(entityType, entityId, businessEntityId) {
|
|
8112
|
+
const [data, setData] = (0, import_react21.useState)([]);
|
|
8113
|
+
const [loading, setLoading] = (0, import_react21.useState)(true);
|
|
8114
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
8115
|
+
const [rootFolderCode, setRootFolderCode] = (0, import_react21.useState)(null);
|
|
8116
|
+
const loadEntityFolders = (0, import_react21.useCallback)(async () => {
|
|
8117
|
+
setLoading(true);
|
|
8118
|
+
setError(null);
|
|
8119
|
+
try {
|
|
8120
|
+
const folders = await fileManagerApi.getEntityFolders(entityType, entityId);
|
|
8121
|
+
if (!folders || folders.length === 0) {
|
|
8122
|
+
setData([]);
|
|
8123
|
+
setRootFolderCode(null);
|
|
8124
|
+
setLoading(false);
|
|
8125
|
+
return;
|
|
8126
|
+
}
|
|
8127
|
+
const entityFolder = folders.find((f) => f.folder_type === "ENTITY");
|
|
8128
|
+
if (!entityFolder) {
|
|
8129
|
+
console.warn("Dossier ENTITY non trouv\xE9, utilisation du premier dossier");
|
|
8130
|
+
const firstFolder = folders[0];
|
|
8131
|
+
setRootFolderCode(firstFolder.code);
|
|
8132
|
+
const tree = await fileManagerApi.getFolderTree(firstFolder.code);
|
|
8133
|
+
const transformed = transformFolder(tree);
|
|
8134
|
+
setData(extractRootChildren(transformed));
|
|
8135
|
+
} else {
|
|
8136
|
+
setRootFolderCode(entityFolder.code);
|
|
8137
|
+
const tree = await fileManagerApi.getFolderTree(entityFolder.code);
|
|
8138
|
+
const transformed = transformFolder(tree);
|
|
8139
|
+
setData(extractRootChildren(transformed));
|
|
8140
|
+
}
|
|
8141
|
+
} catch (err) {
|
|
8142
|
+
console.error("Erreur lors du chargement des dossiers:", err);
|
|
8143
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
8144
|
+
setData([]);
|
|
8145
|
+
} finally {
|
|
8146
|
+
setLoading(false);
|
|
8147
|
+
}
|
|
8148
|
+
}, [entityType, entityId]);
|
|
8149
|
+
const refresh = (0, import_react21.useCallback)(async () => {
|
|
8150
|
+
await loadEntityFolders();
|
|
8151
|
+
}, [loadEntityFolders]);
|
|
8152
|
+
(0, import_react21.useEffect)(() => {
|
|
8153
|
+
loadEntityFolders();
|
|
8154
|
+
}, [loadEntityFolders]);
|
|
8155
|
+
const handleCreateFolder = (0, import_react21.useCallback)(
|
|
8156
|
+
async (name, parentId) => {
|
|
8157
|
+
try {
|
|
8158
|
+
const created = await fileManagerApi.createFolder(
|
|
8159
|
+
name,
|
|
8160
|
+
parentId,
|
|
8161
|
+
businessEntityId
|
|
8162
|
+
);
|
|
8163
|
+
await refresh();
|
|
8164
|
+
return transformFolder(created, "", parentId);
|
|
8165
|
+
} catch (err) {
|
|
8166
|
+
console.error("Erreur lors de la cr\xE9ation du dossier:", err);
|
|
8167
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
8168
|
+
throw err;
|
|
8169
|
+
}
|
|
8170
|
+
},
|
|
8171
|
+
[businessEntityId, refresh]
|
|
8172
|
+
);
|
|
8173
|
+
const handleUploadFiles = (0, import_react21.useCallback)(
|
|
8174
|
+
async (files, parentId) => {
|
|
8175
|
+
try {
|
|
8176
|
+
const uploaded = await fileManagerApi.uploadFiles(files, parentId);
|
|
8177
|
+
await refresh();
|
|
8178
|
+
return uploaded.map((file) => transformFile(file, "", parentId));
|
|
8179
|
+
} catch (err) {
|
|
8180
|
+
console.error("Erreur lors de l'upload:", err);
|
|
8181
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
8182
|
+
throw err;
|
|
8183
|
+
}
|
|
8184
|
+
},
|
|
8185
|
+
[refresh]
|
|
8186
|
+
);
|
|
8187
|
+
const handleRename = (0, import_react21.useCallback)(
|
|
8188
|
+
async (item, newName) => {
|
|
8189
|
+
try {
|
|
8190
|
+
if (item.type === "folder") {
|
|
8191
|
+
await fileManagerApi.renameFolder(item.id, newName);
|
|
8192
|
+
} else {
|
|
8193
|
+
await fileManagerApi.renameFile(item.id, newName);
|
|
8194
|
+
}
|
|
8195
|
+
await refresh();
|
|
8196
|
+
} catch (err) {
|
|
8197
|
+
console.error("Erreur lors du renommage:", err);
|
|
8198
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
8199
|
+
throw err;
|
|
8200
|
+
}
|
|
8201
|
+
},
|
|
8202
|
+
[refresh]
|
|
8203
|
+
);
|
|
8204
|
+
const handleDelete = (0, import_react21.useCallback)(
|
|
8205
|
+
async (item) => {
|
|
8206
|
+
try {
|
|
8207
|
+
if (item.metadata?.isSystemFolder) {
|
|
8208
|
+
throw new Error("Les dossiers syst\xE8me ne peuvent pas \xEAtre supprim\xE9s");
|
|
8209
|
+
}
|
|
8210
|
+
if (item.type === "folder") {
|
|
8211
|
+
await fileManagerApi.deleteFolder(item.id);
|
|
8212
|
+
} else {
|
|
8213
|
+
await fileManagerApi.deleteFile(item.id);
|
|
8214
|
+
}
|
|
8215
|
+
await refresh();
|
|
8216
|
+
} catch (err) {
|
|
8217
|
+
console.error("Erreur lors de la suppression:", err);
|
|
8218
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
8219
|
+
throw err;
|
|
8220
|
+
}
|
|
8221
|
+
},
|
|
8222
|
+
[refresh]
|
|
8223
|
+
);
|
|
8224
|
+
const handleDownload = (0, import_react21.useCallback)((item) => {
|
|
8225
|
+
if (item.type === "file") {
|
|
8226
|
+
const url = item.url || fileManagerApi.getDownloadUrl(item.id);
|
|
8227
|
+
window.open(url, "_blank");
|
|
8228
|
+
}
|
|
8229
|
+
}, []);
|
|
8230
|
+
return {
|
|
8231
|
+
data,
|
|
8232
|
+
loading,
|
|
8233
|
+
error,
|
|
8234
|
+
rootFolderCode,
|
|
8235
|
+
refresh,
|
|
8236
|
+
handlers: {
|
|
8237
|
+
onCreateFolder: handleCreateFolder,
|
|
8238
|
+
onUploadFiles: handleUploadFiles,
|
|
8239
|
+
onRename: handleRename,
|
|
8240
|
+
onDelete: handleDelete,
|
|
8241
|
+
onDownload: handleDownload
|
|
8242
|
+
}
|
|
8243
|
+
};
|
|
8244
|
+
}
|
|
8245
|
+
|
|
8246
|
+
// src/components/common/FileManager/components/EntityFileManager.tsx
|
|
8247
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
8248
|
+
function getRootName(entityType) {
|
|
8249
|
+
const names = {
|
|
8250
|
+
CLIENT: "Documents Client",
|
|
8251
|
+
VENDOR: "Documents Fournisseur",
|
|
8252
|
+
RFQ: "Documents RFQ",
|
|
8253
|
+
DEPT: "Documents D\xE9partement",
|
|
8254
|
+
PROJECT: "Documents Projet"
|
|
8255
|
+
};
|
|
8256
|
+
return names[entityType] || "Documents";
|
|
8257
|
+
}
|
|
8258
|
+
var LoadingState = ({ height = "400px" }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
8259
|
+
"div",
|
|
8260
|
+
{
|
|
8261
|
+
className: "flex flex-col items-center justify-center bg-gray-50 dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800",
|
|
8262
|
+
style: { height },
|
|
8263
|
+
children: [
|
|
8264
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react17.Loader2, { className: "w-10 h-10 text-blue-500 animate-spin mb-4" }),
|
|
8265
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: "Chargement des documents..." })
|
|
8266
|
+
]
|
|
8267
|
+
}
|
|
8268
|
+
);
|
|
8269
|
+
var ErrorState = ({ error, onRetry, height = "400px" }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
8270
|
+
"div",
|
|
8271
|
+
{
|
|
8272
|
+
className: "flex flex-col items-center justify-center bg-red-50 dark:bg-red-900/20 rounded-xl border border-red-200 dark:border-red-800",
|
|
8273
|
+
style: { height },
|
|
8274
|
+
children: [
|
|
8275
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react17.AlertCircle, { className: "w-10 h-10 text-red-500 mb-4" }),
|
|
8276
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-red-600 dark:text-red-400 text-sm font-medium mb-2", children: "Erreur lors du chargement" }),
|
|
8277
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-red-500 dark:text-red-400 text-xs mb-4 max-w-md text-center px-4", children: error.message }),
|
|
8278
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
8279
|
+
"button",
|
|
8280
|
+
{
|
|
8281
|
+
onClick: onRetry,
|
|
8282
|
+
className: "flex items-center gap-2 px-4 py-2 bg-red-100 dark:bg-red-900/40 text-red-700 dark:text-red-300 rounded-lg hover:bg-red-200 dark:hover:bg-red-900/60 transition-colors text-sm",
|
|
8283
|
+
children: [
|
|
8284
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react17.RefreshCw, { className: "w-4 h-4" }),
|
|
8285
|
+
"R\xE9essayer"
|
|
8286
|
+
]
|
|
8287
|
+
}
|
|
8288
|
+
)
|
|
8289
|
+
]
|
|
8290
|
+
}
|
|
8291
|
+
);
|
|
8292
|
+
var EmptyState = ({ height = "400px" }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
8293
|
+
"div",
|
|
8294
|
+
{
|
|
8295
|
+
className: "flex flex-col items-center justify-center bg-gray-50 dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800",
|
|
8296
|
+
style: { height },
|
|
8297
|
+
children: [
|
|
8298
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react17.FolderX, { className: "w-10 h-10 text-gray-400 mb-4" }),
|
|
8299
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-gray-600 dark:text-gray-400 text-sm font-medium mb-1", children: "Aucun document trouv\xE9" }),
|
|
8300
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-gray-500 dark:text-gray-500 text-xs", children: "La structure de dossiers n'a pas encore \xE9t\xE9 cr\xE9\xE9e pour cette entit\xE9." })
|
|
8301
|
+
]
|
|
8302
|
+
}
|
|
8303
|
+
);
|
|
8304
|
+
var EntityFileManager = ({
|
|
8305
|
+
entityType,
|
|
8306
|
+
entityId,
|
|
8307
|
+
businessEntityId,
|
|
8308
|
+
className,
|
|
8309
|
+
height = "600px",
|
|
8310
|
+
// Permissions (défaut: tout autorisé)
|
|
8311
|
+
allowUpload = true,
|
|
8312
|
+
allowCreateFolder = true,
|
|
8313
|
+
allowRename = true,
|
|
8314
|
+
allowDelete = true,
|
|
8315
|
+
allowDownload = true,
|
|
8316
|
+
// Callbacks
|
|
8317
|
+
onFileSelect,
|
|
8318
|
+
onFileOpen,
|
|
8319
|
+
onUploadSuccess,
|
|
8320
|
+
onError
|
|
8321
|
+
}) => {
|
|
8322
|
+
const { data, loading, error, refresh, handlers } = useFileManagerApi(
|
|
8323
|
+
entityType,
|
|
8324
|
+
entityId,
|
|
8325
|
+
businessEntityId
|
|
8326
|
+
);
|
|
8327
|
+
import_react22.default.useEffect(() => {
|
|
8328
|
+
if (error && onError) {
|
|
8329
|
+
onError(error);
|
|
8330
|
+
}
|
|
8331
|
+
}, [error, onError]);
|
|
8332
|
+
if (loading) {
|
|
8333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(LoadingState, { height });
|
|
8334
|
+
}
|
|
8335
|
+
if (error) {
|
|
8336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ErrorState, { error, onRetry: refresh, height });
|
|
8337
|
+
}
|
|
8338
|
+
if (!data || data.length === 0) {
|
|
8339
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(EmptyState, { height });
|
|
8340
|
+
}
|
|
8341
|
+
const handleUploadFiles = async (files, parentId) => {
|
|
8342
|
+
const result = await handlers.onUploadFiles(files, parentId);
|
|
8343
|
+
if (result && onUploadSuccess) {
|
|
8344
|
+
onUploadSuccess(result);
|
|
8345
|
+
}
|
|
8346
|
+
return result;
|
|
8347
|
+
};
|
|
8348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("relative", className), style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
8349
|
+
FileManager,
|
|
8350
|
+
{
|
|
8351
|
+
data,
|
|
8352
|
+
rootName: getRootName(entityType),
|
|
8353
|
+
onCreateFolder: handlers.onCreateFolder,
|
|
8354
|
+
onUploadFiles: handleUploadFiles,
|
|
8355
|
+
onRename: handlers.onRename,
|
|
8356
|
+
onDelete: handlers.onDelete,
|
|
8357
|
+
onDownload: handlers.onDownload,
|
|
8358
|
+
onSelect: onFileSelect,
|
|
8359
|
+
onOpen: onFileOpen,
|
|
8360
|
+
allowUpload,
|
|
8361
|
+
allowCreateFolder,
|
|
8362
|
+
allowRename,
|
|
8363
|
+
allowDelete,
|
|
8364
|
+
allowDownload,
|
|
8365
|
+
allowMultiSelect: true,
|
|
8366
|
+
className: "h-full"
|
|
8367
|
+
}
|
|
8368
|
+
) });
|
|
8369
|
+
};
|
|
7765
8370
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7766
8371
|
0 && (module.exports = {
|
|
7767
8372
|
Alert,
|
|
@@ -7775,6 +8380,7 @@ var FileManager = (props) => {
|
|
|
7775
8380
|
CHOICES,
|
|
7776
8381
|
CountrySelector,
|
|
7777
8382
|
DateInput,
|
|
8383
|
+
EntityFileManager,
|
|
7778
8384
|
FDrawer,
|
|
7779
8385
|
FetchApi,
|
|
7780
8386
|
FileInput,
|
|
@@ -7794,6 +8400,7 @@ var FileManager = (props) => {
|
|
|
7794
8400
|
SelectCostCenter,
|
|
7795
8401
|
SelectDepartment,
|
|
7796
8402
|
SelectInput,
|
|
8403
|
+
SelectUnit,
|
|
7797
8404
|
SelectUser,
|
|
7798
8405
|
SelectVendor,
|
|
7799
8406
|
SessionProvider,
|
|
@@ -7803,12 +8410,15 @@ var FileManager = (props) => {
|
|
|
7803
8410
|
ThemeProvider,
|
|
7804
8411
|
ToastContainer,
|
|
7805
8412
|
ToastProvider,
|
|
8413
|
+
UnitServices,
|
|
7806
8414
|
UserServices,
|
|
8415
|
+
fileManagerApi,
|
|
7807
8416
|
formatDate,
|
|
7808
8417
|
formatFileSize,
|
|
7809
8418
|
getFileIcon,
|
|
7810
8419
|
useAlert,
|
|
7811
8420
|
useFileManager,
|
|
8421
|
+
useFileManagerApi,
|
|
7812
8422
|
useSession,
|
|
7813
8423
|
useToast
|
|
7814
8424
|
});
|