Skip to content

Commit 708df82

Browse files
Mas carpetas
1 parent a56cc99 commit 708df82

1 file changed

Lines changed: 131 additions & 99 deletions

File tree

src/Services/Bibliotecas.service.ts

Lines changed: 131 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,34 @@
11
import type { GraphRest } from "../graph/graphRest";
22
import type { Archivo } from "../models/archivos";
33

4+
type GraphPaged<T> = {
5+
value: T[];
6+
"@odata.nextLink"?: string;
7+
};
8+
9+
function toRelativePath(nextLink: string): string {
10+
const u = new URL(nextLink);
11+
12+
// u.pathname normalmente es "/v1.0/drives/..."
13+
// tu wrapper ya tiene base ".../v1.0/", así que quitamos ese prefijo
14+
const p = u.pathname.replace(/^\/v1\.0/i, "");
15+
16+
return p + u.search; // queda "/drives/...?$skiptoken=..."
17+
}
18+
19+
function mapToArchivo(item: any): Archivo {
20+
return {
21+
id: item.id,
22+
name: item.name,
23+
webUrl: item.webUrl,
24+
isFolder: !!item.folder,
25+
size: item.size,
26+
lastModified: item.lastModifiedDateTime,
27+
childCount: item.folder?.childCount ?? undefined,
28+
created: item.createdDateTime,
29+
};
30+
}
31+
432
class BibliotecaBaseService {
533
protected graph: GraphRest;
634
protected hostname: string;
@@ -73,101 +101,110 @@ class BibliotecaBaseService {
73101
}
74102
}
75103

76-
// Listar archivos de una carpeta (por si lo necesitas)
104+
private encodePath(p: string) {
105+
const clean = (p ?? "").replace(/^\/|\/$/g, "");
106+
if (!clean) return "";
107+
return clean
108+
.split("/")
109+
.map((s) => encodeURIComponent(s))
110+
.join("/");
111+
}
112+
113+
// =========================
114+
// LISTAR / PAGINAR
115+
// =========================
116+
117+
// Listar archivos de una carpeta (por ruta)
77118
async getFilesInFolder(folderPath: string): Promise<Archivo[]> {
78119
await this.ensureIds();
79120

80-
const cleanFolder = folderPath.replace(/^\/|\/$/g, "");
81-
let url: string;
121+
const encodedPath = this.encodePath(folderPath);
122+
let url =
123+
encodedPath.length > 0
124+
? `/drives/${this.driveId}/root:/${encodedPath}:/children?$top=200`
125+
: `/drives/${this.driveId}/root/children?$top=200`;
82126

83-
if (cleanFolder.length > 0) {
84-
const segments = cleanFolder.split("/").map((s) => encodeURIComponent(s));
85-
const encodedPath = segments.join("/");
127+
const all: any[] = [];
86128

87-
url = `/drives/${this.driveId}/root:/${encodedPath}:/children`;
88-
} else {
89-
url = `/drives/${this.driveId}/root/children`;
129+
while (url) {
130+
const res = await this.graph.get<GraphPaged<any>>(url);
131+
all.push(...(res.value ?? []));
132+
const next = res["@odata.nextLink"];
133+
url = next ? toRelativePath(next) : "";
90134
}
91135

92-
const res = await this.graph.get<any>(url);
93-
94-
return (res.value ?? []).map((item: any) => ({
95-
id: item.id,
96-
name: item.name,
97-
webUrl: item.webUrl,
98-
isFolder: !!item.folder,
99-
size: item.size,
100-
lastModified: item.lastModifiedDateTime,
101-
childCount: item.folder?.childCount ?? undefined,
102-
created: item.createdDateTime,
103-
}));
136+
return all.map(mapToArchivo);
104137
}
105-
async findFolderByDocNumber(docNumber: string): Promise<Archivo | null> {
106-
await this.ensureIds();
107-
108-
const baseFolder = "Colaboradores Activos"; // O el nombre EXACTO de esa carpeta
109-
const cleanFolder = baseFolder.replace(/^\/|\/$/g, "");
110-
const segments = cleanFolder.split("/").map((s) => encodeURIComponent(s));
111-
const encodedPath = segments.join("/");
112138

113-
// Traemos los hijos directos de "Colaboradores Activos"
114-
const res = await this.graph.get<any>(
115-
`/drives/${this.driveId}/root:/${encodedPath}:/children`
116-
);
117-
118-
const items: any[] = res.value ?? [];
139+
// Listar archivos de una carpeta (por ID) - con paginación
140+
async getFilesByFolderId(folderId: string): Promise<Archivo[]> {
141+
await this.ensureIds();
119142

120-
const folder = items.find((item) => {
121-
const isFolder = !!item.folder;
122-
const name: string = item.name ?? "";
123-
return isFolder && name.startsWith(`${docNumber} -`);
124-
});
143+
let url = `/drives/${this.driveId}/items/${folderId}/children?$top=200`;
144+
const all: any[] = [];
125145

126-
if (!folder) return null;
146+
while (url) {
147+
const res = await this.graph.get<GraphPaged<any>>(url);
148+
all.push(...(res.value ?? []));
149+
const next = res["@odata.nextLink"];
150+
url = next ? toRelativePath(next) : "";
151+
}
127152

128-
return {
129-
id: folder.id,
130-
name: folder.name,
131-
webUrl: folder.webUrl,
132-
isFolder: !!folder.folder,
133-
size: folder.size,
134-
lastModified: folder.lastModified
135-
136-
};
153+
return all.map(mapToArchivo);
137154
}
138155

139-
async getFilesByFolderId(folderId: string): Promise<Archivo[]> {
156+
// Buscar carpeta por número de documento dentro de "Colaboradores Activos"
157+
// (OJO: ahora pagina también, por si hay miles de carpetas)
158+
async findFolderByDocNumber(docNumber: string): Promise<Archivo | null> {
140159
await this.ensureIds();
141160

142-
const res = await this.graph.get<any>(
143-
`/drives/${this.driveId}/items/${folderId}/children`
144-
);
161+
const baseFolder = "Colaboradores Activos";
162+
const encodedBase = this.encodePath(baseFolder);
163+
164+
let url = `/drives/${this.driveId}/root:/${encodedBase}:/children?$top=200`;
165+
166+
while (url) {
167+
const res = await this.graph.get<GraphPaged<any>>(url);
168+
const items: any[] = res.value ?? [];
169+
170+
const folder = items.find((item) => {
171+
const isFolder = !!item.folder;
172+
const name: string = item.name ?? "";
173+
return isFolder && name.startsWith(`${docNumber} -`);
174+
});
175+
176+
if (folder) {
177+
// Importante: aquí usas lastModifiedDateTime (no lastModified)
178+
return {
179+
id: folder.id,
180+
name: folder.name,
181+
webUrl: folder.webUrl,
182+
isFolder: !!folder.folder,
183+
size: folder.size,
184+
lastModified: folder.lastModifiedDateTime,
185+
childCount: folder.folder?.childCount ?? undefined,
186+
created: folder.createdDateTime,
187+
};
188+
}
145189

146-
return (res.value ?? []).map((item: any) => ({
147-
id: item.id,
148-
name: item.name,
149-
webUrl: item.webUrl,
150-
isFolder: !!item.folder,
151-
size: item.size,
152-
lastModified: item.lastModifiedDateTime,
153-
childCount: item.folder?.childCount ?? undefined,
154-
created: item.createdDateTime,
155-
}));
190+
const next = res["@odata.nextLink"];
191+
url = next ? toRelativePath(next) : "";
192+
}
193+
194+
return null;
156195
}
157196

197+
// =========================
198+
// UPLOAD / RENOMBRE / MOVER
199+
// =========================
158200

159-
async uploadFile(
160-
folderPath: string,
161-
file: File
162-
): Promise<Archivo> {
201+
async uploadFile(folderPath: string, file: File): Promise<Archivo> {
163202
await this.ensureIds();
164203

165-
const cleanFolder = folderPath.replace(/^\/|\/$/g, "");
204+
const cleanFolder = (folderPath ?? "").replace(/^\/|\/$/g, "");
166205
const fileName = file.name;
167-
const serverPath =
168-
cleanFolder.length > 0
169-
? `${cleanFolder}/${fileName}`
170-
: fileName; // raíz de la biblioteca
206+
207+
const serverPath = cleanFolder.length > 0 ? `${cleanFolder}/${fileName}` : fileName;
171208

172209
const driveItem = await this.graph.putBinary<any>(
173210
`/drives/${this.driveId}/root:/${encodeURI(serverPath)}:/content`,
@@ -182,26 +219,22 @@ class BibliotecaBaseService {
182219
isFolder: !!driveItem.folder,
183220
size: driveItem.size,
184221
lastModified: driveItem.lastModifiedDateTime,
222+
childCount: driveItem.folder?.childCount ?? undefined,
223+
created: driveItem.createdDateTime,
185224
};
186225
}
187226

188-
// Renombrar archivo
189-
async renameArchivo(archivo: Archivo,
190-
nuevoNombreSinExtension: string
191-
): Promise<Archivo> {
227+
async renameArchivo(archivo: Archivo, nuevoNombreSinExtension: string): Promise<Archivo> {
192228
await this.ensureIds();
193229

194-
// Mantener extensión original si NO es carpeta
195230
let ext = "";
196231
if (!archivo.isFolder) {
197232
const dot = archivo.name.lastIndexOf(".");
198-
if (dot > 0) {
199-
ext = archivo.name.slice(dot); // incluye el punto, ej: ".pdf"
200-
}
233+
if (dot > 0) ext = archivo.name.slice(dot);
201234
}
202235

203236
const newName = `${nuevoNombreSinExtension}${ext}`;
204-
// PATCH al driveItem
237+
205238
const item = await this.graph.patch<any>(
206239
`/drives/${this.driveId}/items/${archivo.id}`,
207240
{ name: newName }
@@ -214,39 +247,38 @@ class BibliotecaBaseService {
214247
isFolder: !!item.folder,
215248
size: item.size,
216249
lastModified: item.lastModifiedDateTime,
250+
childCount: item.folder?.childCount ?? undefined,
251+
created: item.createdDateTime,
217252
};
218253
}
219254

220-
//Mover carpeta completa
221-
async moveFolderByPath(sourceFolderPath: string, destParentFolderPath: string, opts?: { newName?: string }): Promise<Archivo> {
255+
async moveFolderByPath(
256+
sourceFolderPath: string,
257+
destParentFolderPath: string,
258+
opts?: { newName?: string }
259+
): Promise<Archivo> {
222260
await this.ensureIds();
223261

224262
const enc = (p: string) =>
225-
p.replace(/^\/|\/$/g, "")
263+
(p ?? "")
264+
.replace(/^\/|\/$/g, "")
226265
.split("/")
227266
.map(encodeURIComponent)
228267
.join("/");
229268

230269
const srcPath = enc(sourceFolderPath);
231270
const dstPath = enc(destParentFolderPath);
232271

233-
// 1) Resolver item origen (carpeta a mover)
234-
const src = await this.graph.get<any>(
235-
`/drives/${this.driveId}/root:/${srcPath}`
236-
);
272+
const src = await this.graph.get<any>(`/drives/${this.driveId}/root:/${srcPath}`);
237273
if (!src?.id || !src?.folder) {
238274
throw new Error("La ruta origen no es una carpeta válida o no existe.");
239275
}
240276

241-
// 2) Resolver item destino (carpeta PADRE)
242-
const dst = await this.graph.get<any>(
243-
`/drives/${this.driveId}/root:/${dstPath}`
244-
);
277+
const dst = await this.graph.get<any>(`/drives/${this.driveId}/root:/${dstPath}`);
245278
if (!dst?.id || !dst?.folder) {
246279
throw new Error("La ruta destino no es una carpeta válida o no existe.");
247280
}
248281

249-
// 3) Mover (Forma A)
250282
const body: any = { parentReference: { id: dst.id } };
251283
const newName = opts?.newName?.trim();
252284
if (newName) body.name = newName;
@@ -263,13 +295,16 @@ class BibliotecaBaseService {
263295
isFolder: !!moved.folder,
264296
size: moved.size,
265297
lastModified: moved.lastModifiedDateTime,
298+
childCount: moved.folder?.childCount ?? undefined,
299+
created: moved.createdDateTime,
266300
};
267301
}
268-
269-
270302
}
271303

272-
// Específicos para cada biblioteca (por si luego quieres métodos extra)
304+
// =========================
305+
// Subclases por biblioteca
306+
// =========================
307+
273308
export class ColaboradoresEDMService extends BibliotecaBaseService {
274309
constructor(graph: GraphRest, hostname: string, sitePath: string, name: string) {
275310
super(graph, hostname, sitePath, name);
@@ -294,17 +329,14 @@ export class ColaboradoresDenimService extends BibliotecaBaseService {
294329
}
295330
}
296331

297-
298332
export class ColaboradoresVisualService extends BibliotecaBaseService {
299333
constructor(graph: GraphRest, hostname: string, sitePath: string, name: string) {
300334
super(graph, hostname, sitePath, name);
301335
}
302336
}
303337

304-
305338
export class ColaboradoresMetaService extends BibliotecaBaseService {
306339
constructor(graph: GraphRest, hostname: string, sitePath: string, name: string) {
307340
super(graph, hostname, sitePath, name);
308341
}
309342
}
310-

0 commit comments

Comments
 (0)