Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | 103x 103x 585x 31x 31x 31x 775x 190x 190x 22x 190x 585x 585x 31x 31x 31x 35x 35x 35x 27x 27x 31x | export const ROOT_PROJECT_FOLDER_ID = null;
export const PROJECT_CARD_DRAG_TYPE = "project-card";
export type ProjectFolderId = number | null;
export type ProjectViewMode = "grid" | "list";
export type ProjectFolderPathItem = {
id: number;
name: string;
parentId: ProjectFolderId;
};
export type ProjectFolderItem = ProjectFolderPathItem & {
projectCount: number;
};
export type ProjectFolderIndex = {
foldersById: ReadonlyMap<number, ProjectFolderPathItem>;
};
export type ProjectCardDragItem = {
projectId: number;
projectName: string;
folderId: ProjectFolderId;
};
export type MoveProject = (
projectId: number,
folderId: ProjectFolderId,
) => Promise<void> | void;
export type FolderBreadcrumb = {
id: ProjectFolderId;
name: string;
};
type ProjectFolderRecord = {
id: number;
name: string;
parent: number | null;
project_count: number;
};
type ProjectFolderNavigationRecord = Omit<
ProjectFolderRecord,
"project_count" | "parent"
> & { parent?: number | null };
/** Parse the folder query parameter as a database identity. */
export function parseProjectFolderId(value: string | null) {
if (value === null) return ROOT_PROJECT_FOLDER_ID;
Iif (!/^[1-9]\d*$/.test(value)) return undefined;
const id = Number(value);
return Number.isSafeInteger(id) ? id : undefined;
}
/** Adapt the generated API resource shape for folder UI components. */
export function buildProjectFolderItems(folders: ProjectFolderRecord[]) {
return folders.map<ProjectFolderItem>((folder) => ({
id: folder.id,
name: folder.name,
parentId: folder.parent ?? ROOT_PROJECT_FOLDER_ID,
projectCount: folder.project_count,
}));
}
/** Adapt breadcrumb resources without inventing subtree project counts. */
export function buildProjectFolderPathItems(
folders: ProjectFolderNavigationRecord[],
) {
return folders.map<ProjectFolderPathItem>((folder) => ({
id: folder.id,
name: folder.name,
parentId: folder.parent ?? ROOT_PROJECT_FOLDER_ID,
}));
}
/**
* Index one bounded folder workspace response for path navigation.
*
* Keeping the identity map at the workspace boundary avoids repeated path scans.
*/
export function buildProjectFolderIndex(
folders: ProjectFolderPathItem[],
): ProjectFolderIndex {
const foldersById = new Map<number, ProjectFolderPathItem>();
for (const folder of folders) {
foldersById.set(folder.id, folder);
}
return {
foldersById,
};
}
/** Build breadcrumbs by following stable parent relationships to the root. */
export function getProjectFolderBreadcrumbs(
folderIndex: ProjectFolderIndex,
currentFolderId: ProjectFolderId,
) {
const breadcrumbs: FolderBreadcrumb[] = [
{ id: ROOT_PROJECT_FOLDER_ID, name: "My Projects" },
];
if (currentFolderId === ROOT_PROJECT_FOLDER_ID) return breadcrumbs;
const ancestors: FolderBreadcrumb[] = [];
const visited = new Set<number>();
let nextFolderId: ProjectFolderId = currentFolderId;
while (
nextFolderId !== ROOT_PROJECT_FOLDER_ID &&
!visited.has(nextFolderId)
) {
visited.add(nextFolderId);
const folder = folderIndex.foldersById.get(nextFolderId);
if (!folder) break;
ancestors.push({ id: folder.id, name: folder.name });
nextFolderId = folder.parentId;
}
return [...breadcrumbs, ...ancestors.reverse()];
}
/** Return the parent relationship for Back navigation. */
export function getParentProjectFolderId(
folderIndex: ProjectFolderIndex,
currentFolderId: ProjectFolderId,
) {
if (currentFolderId === ROOT_PROJECT_FOLDER_ID) {
return ROOT_PROJECT_FOLDER_ID;
}
return (
folderIndex.foldersById.get(currentFolderId)?.parentId ??
ROOT_PROJECT_FOLDER_ID
);
}
|