Merge pull request #641 from EdouardVanbelle/refactor/front-resource-list

feat(fileDto, folderDto): add is_favorite + is_shared
This commit is contained in:
Dionisio Pozo
2026-07-22 06:51:28 +02:00
committed by GitHub
50 changed files with 1140 additions and 287 deletions
@@ -29,9 +29,7 @@ function fakeRes(opts: { status: number; body?: ResourcePage }): Response {
const emptyListing = (): FolderListing => ({
folders: [],
files: [],
favoriteIds: [],
sharedIds: []
files: []
});
beforeEach(() => {
@@ -56,7 +54,6 @@ describe('fetchFolderListing (cursor-paginated /resources)', () => {
expect(r.status).toBe(200);
expect(r.listing?.folders.map((f) => f.id)).toEqual(['d1']);
expect(r.listing?.files.map((f) => f.id)).toEqual(['x1']);
expect(r.listing?.favoriteIds).toEqual([]);
expect(vi.mocked(apiFetch).mock.calls[0][0]).toContain('/api/folders/f1/resources');
});
@@ -124,9 +121,7 @@ describe('folder name cache (breadcrumbs)', () => {
it("learns its children's names from a cached listing", () => {
cacheFolder('nc-parent', {
folders: [folder('nc-a', 'Alpha'), folder('nc-b', 'Beta')],
files: [],
favoriteIds: [],
sharedIds: []
files: []
});
expect(getFolderName('nc-a')).toBe('Alpha');
expect(getFolderName('nc-b')).toBe('Beta');
+5 -6
View File
@@ -13,10 +13,9 @@ const NO_CACHE: RequestInit = {
export interface FolderListing {
folders: FolderItem[];
files: FileItem[];
/** Ids in this listing the caller has favorited (server-computed badge set). */
favoriteIds: string[];
/** Ids in this listing the caller has an outgoing share/grant on. */
sharedIds: string[];
// Legacy `favoriteIds` / `sharedIds` fields are gone — the same
// signals now live inline on every `FileItem` / `FolderItem`
// (`is_favorite`, `is_shared`). Consumers read those directly.
}
/** Result of a (possibly conditional) listing fetch. */
@@ -213,13 +212,13 @@ export async function fetchFolderListing(
files.push(...page.files);
cursor = page.nextCursor;
} while (cursor);
return { status: 200, listing: { folders, files, favoriteIds: [], sharedIds: [] } };
return { status: 200, listing: { folders, files } };
}
/** Non-conditional listing fetch (e.g. the move-dialog folder tree). */
export async function listFolder(folderId: string, forceRefresh = false): Promise<FolderListing> {
const res = await fetchFolderListing(folderId, { forceRefresh });
return res.listing ?? { folders: [], files: [], favoriteIds: [], sharedIds: [] };
return res.listing ?? { folders: [], files: [] };
}
export async function createFolder(name: string, parentId: string | null): Promise<FolderItem> {
+15
View File
@@ -89,6 +89,21 @@ export function expiryToIso(date: string | null | undefined): string | null {
return date ? new Date(`${date}T00:00:00Z`).toISOString() : null;
}
/**
* Today's date in YYYY-MM-DD form (local time zone). Used as the `min`
* attribute on grant / share expiry date inputs so the native picker
* refuses to select a past date. Callers should also validate the
* changed value in their `onchange` handler as a belt-and-braces guard
* (some browsers still let scripted / paste input bypass `min`).
*/
export function todayIso(): string {
const now = new Date();
const y = now.getFullYear();
const m = String(now.getMonth() + 1).padStart(2, '0');
const d = String(now.getDate()).padStart(2, '0');
return `${y}-${m}-${d}`;
}
export function fetchGrantsForResource(type: GrantResourceType, id: string): Promise<Grant[]> {
const params = new URLSearchParams({ resource_type: type, resource_id: id });
return apiJson<Grant[]>(`/api/grants?${params}`, { credentials: 'same-origin' });