Feat: persist project tree hierarchy
This commit is contained in:
@@ -841,19 +841,34 @@ func (service *Service) loadProjectByID(ctx context.Context, projectID string) (
|
||||
}
|
||||
|
||||
func (service *Service) GetProjectHierarchyFolders(ctx context.Context, projectID string) ([]ProjectHierarchyFolderRecord, error) {
|
||||
return service.getProjectHierarchyFoldersByRootPath(ctx, projectID, projectHierarchyRootPath)
|
||||
}
|
||||
|
||||
func (service *Service) GetProjectTreeFolders(ctx context.Context, projectID string) ([]ProjectHierarchyFolderRecord, error) {
|
||||
return service.getProjectHierarchyFoldersByRootPath(ctx, projectID, projectTreeRootPath)
|
||||
}
|
||||
|
||||
func (service *Service) getProjectHierarchyFoldersByRootPath(
|
||||
ctx context.Context,
|
||||
projectID string,
|
||||
rootPath func(projectSlug string) string,
|
||||
) ([]ProjectHierarchyFolderRecord, error) {
|
||||
project, err := service.loadProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootParentPath := rootPath(project.Slug)
|
||||
|
||||
rows, err := service.db.Pool.Query(ctx, `
|
||||
SELECT path, COALESCE(parent_path, ''), COALESCE(resource_name, '')
|
||||
FROM posix_nodes
|
||||
WHERE node_kind = 'directory'::posix_node_kind
|
||||
AND logical_type = 'hierarchy_folder'
|
||||
AND project_slug = $1
|
||||
AND path LIKE $2
|
||||
ORDER BY depth ASC, path ASC;
|
||||
`, project.Slug)
|
||||
`, project.Slug, rootParentPath+"/%")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -872,16 +887,29 @@ func (service *Service) GetProjectHierarchyFolders(ctx context.Context, projectI
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buildProjectHierarchyFolderTree(folderRows, projectHierarchyRootPath(project.Slug)), nil
|
||||
return buildProjectHierarchyFolderTree(folderRows, rootParentPath), nil
|
||||
}
|
||||
|
||||
func (service *Service) CreateProjectFolder(ctx context.Context, input CreateProjectFolderInput) (CreateProjectFolderResult, error) {
|
||||
return service.createProjectHierarchyFolder(ctx, input, projectHierarchyRootPath, service.createProjectHierarchyFolderOnDisk)
|
||||
}
|
||||
|
||||
func (service *Service) CreateProjectTreeFolder(ctx context.Context, input CreateProjectFolderInput) (CreateProjectFolderResult, error) {
|
||||
return service.createProjectHierarchyFolder(ctx, input, projectTreeRootPath, service.createProjectTreeFolderOnDisk)
|
||||
}
|
||||
|
||||
func (service *Service) createProjectHierarchyFolder(
|
||||
ctx context.Context,
|
||||
input CreateProjectFolderInput,
|
||||
rootPath func(projectSlug string) string,
|
||||
createOnDisk func(projectSlug, parentFolderID, name string) (string, string, error),
|
||||
) (CreateProjectFolderResult, error) {
|
||||
project, err := service.loadProjectByID(ctx, strings.TrimSpace(input.ProjectID))
|
||||
if err != nil {
|
||||
return CreateProjectFolderResult{}, err
|
||||
}
|
||||
|
||||
createdPath, _, err := service.createProjectHierarchyFolderOnDisk(project.Slug, strings.TrimSpace(input.ParentFolderID), input.Name)
|
||||
createdPath, _, err := createOnDisk(project.Slug, strings.TrimSpace(input.ParentFolderID), input.Name)
|
||||
if err != nil {
|
||||
return CreateProjectFolderResult{}, err
|
||||
}
|
||||
@@ -890,7 +918,7 @@ func (service *Service) CreateProjectFolder(ctx context.Context, input CreatePro
|
||||
return CreateProjectFolderResult{}, fmt.Errorf("rebuild POSIX projection: %w", err)
|
||||
}
|
||||
|
||||
folders, err := service.GetProjectHierarchyFolders(ctx, project.ID)
|
||||
folders, err := service.getProjectHierarchyFoldersByRootPath(ctx, project.ID, rootPath)
|
||||
if err != nil {
|
||||
return CreateProjectFolderResult{}, err
|
||||
}
|
||||
@@ -1183,8 +1211,19 @@ func (service *Service) ensureBootstrapPOSIXSkeleton(
|
||||
}
|
||||
|
||||
func (service *Service) createProjectHierarchyFolderOnDisk(projectSlug, parentFolderID, name string) (string, string, error) {
|
||||
rootPath := strings.TrimSpace(service.posixRoot)
|
||||
if rootPath == "" {
|
||||
return service.createProjectFolderOnDisk(projectSlug, parentFolderID, name, projectHierarchyRootPath)
|
||||
}
|
||||
|
||||
func (service *Service) createProjectTreeFolderOnDisk(projectSlug, parentFolderID, name string) (string, string, error) {
|
||||
return service.createProjectFolderOnDisk(projectSlug, parentFolderID, name, projectTreeRootPath)
|
||||
}
|
||||
|
||||
func (service *Service) createProjectFolderOnDisk(
|
||||
projectSlug, parentFolderID, name string,
|
||||
rootPathBuilder func(projectSlug string) string,
|
||||
) (string, string, error) {
|
||||
posixRoot := strings.TrimSpace(service.posixRoot)
|
||||
if posixRoot == "" {
|
||||
return "", "", fmt.Errorf("POSIX root is not configured")
|
||||
}
|
||||
|
||||
@@ -1193,14 +1232,12 @@ func (service *Service) createProjectHierarchyFolderOnDisk(projectSlug, parentFo
|
||||
return "", "", fmt.Errorf("folder name is required")
|
||||
}
|
||||
|
||||
projectRoot := filepath.Join(rootPath, "projects", slugDir("project", projectSlug))
|
||||
childrenRoot := filepath.Join(projectRoot, "children")
|
||||
parentDir := childrenRoot
|
||||
containerProjectionPath := projectHierarchyRootPath(projectSlug)
|
||||
containerProjectionPath := rootPathBuilder(projectSlug)
|
||||
parentDir := filepath.Join(posixRoot, filepath.FromSlash(containerProjectionPath))
|
||||
|
||||
if strings.TrimSpace(parentFolderID) != "" {
|
||||
containerProjectionPath = filepath.ToSlash(filepath.Join(strings.TrimSpace(parentFolderID), "children"))
|
||||
parentDir = filepath.Join(rootPath, filepath.FromSlash(containerProjectionPath))
|
||||
parentDir = filepath.Join(posixRoot, filepath.FromSlash(containerProjectionPath))
|
||||
info, err := os.Stat(parentDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@@ -1324,6 +1361,10 @@ func projectHierarchyRootPath(projectSlug string) string {
|
||||
return filepath.ToSlash(filepath.Join("projects", slugDir("project", projectSlug), "children"))
|
||||
}
|
||||
|
||||
func projectTreeRootPath(projectSlug string) string {
|
||||
return filepath.ToSlash(filepath.Join("projects", slugDir("project", projectSlug), "tree"))
|
||||
}
|
||||
|
||||
func normalizePOSIXSlug(value string) string {
|
||||
trimmed := strings.TrimSpace(strings.ToLower(value))
|
||||
if trimmed == "" {
|
||||
|
||||
Reference in New Issue
Block a user