Refactor folder creation logic to reload directory from backend and normalize parent path
This commit is contained in:
@@ -123,24 +123,8 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
event.parentPath,
|
event.parentPath,
|
||||||
event.folderName,
|
event.folderName,
|
||||||
);
|
);
|
||||||
// Add the new folder to local state if in current directory
|
// Reload directory to get the folder with proper ID from backend
|
||||||
if (event.parentPath == _currentPath) {
|
add(LoadDirectory(orgId: event.orgId, path: event.parentPath));
|
||||||
final newFolder = FileItem(
|
|
||||||
name: event.folderName,
|
|
||||||
path: '${event.parentPath}/${event.folderName}',
|
|
||||||
type: FileType.folder,
|
|
||||||
size: 0,
|
|
||||||
lastModified: DateTime.now(),
|
|
||||||
);
|
|
||||||
_currentFiles.add(newFolder);
|
|
||||||
_currentFiles = _sortFiles(_currentFiles, _sortBy, _isAscending);
|
|
||||||
_filteredFiles = _currentFiles
|
|
||||||
.where((f) => f.name.toLowerCase().contains(_currentFilter))
|
|
||||||
.toList();
|
|
||||||
_emitLoadedState(emit);
|
|
||||||
} else {
|
|
||||||
add(LoadDirectory(orgId: event.orgId, path: event.parentPath));
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(DirectoryError(_getErrorMessage(e)));
|
emit(DirectoryError(_getErrorMessage(e)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,9 +119,9 @@ class FileService {
|
|||||||
String parentPath,
|
String parentPath,
|
||||||
String folderName,
|
String folderName,
|
||||||
) async {
|
) async {
|
||||||
final path = parentPath.endsWith('/')
|
// Normalize parent path and construct new folder path
|
||||||
? '$parentPath$folderName'
|
final normalizedParent = parentPath == '/' ? '' : parentPath;
|
||||||
: '$parentPath/$folderName';
|
final path = '$normalizedParent/$folderName';
|
||||||
final data = {
|
final data = {
|
||||||
'name': folderName,
|
'name': folderName,
|
||||||
'path': path,
|
'path': path,
|
||||||
|
|||||||
BIN
go_cloud/bin/api
BIN
go_cloud/bin/api
Binary file not shown.
@@ -264,15 +264,22 @@ func (db *DB) GetOrgFiles(ctx context.Context, orgID uuid.UUID, path string, q s
|
|||||||
}
|
}
|
||||||
offset := (page - 1) * pageSize
|
offset := (page - 1) * pageSize
|
||||||
|
|
||||||
// Basic search and pagination. Returns files under the given path (including nested).
|
// Basic search and pagination. Returns only direct children of the given path.
|
||||||
|
// For root ("/"), we want files where path doesn't contain "/" after the first character.
|
||||||
|
// For subdirs, we want files where path starts with parent but has no additional "/" after parent.
|
||||||
rows, err := db.QueryContext(ctx, `
|
rows, err := db.QueryContext(ctx, `
|
||||||
SELECT id, org_id::text, user_id::text, name, path, type, size, last_modified, created_at
|
SELECT id, org_id::text, user_id::text, name, path, type, size, last_modified, created_at
|
||||||
FROM files
|
FROM files
|
||||||
WHERE org_id = $1 AND path != $2 AND path LIKE $2 || '/%'
|
WHERE org_id = $1
|
||||||
AND ($4 = '' OR name ILIKE '%' || $4 || '%')
|
AND path != $2
|
||||||
|
AND (
|
||||||
|
($2 = '/' AND path LIKE '/%' AND path NOT LIKE '/%/%')
|
||||||
|
OR ($2 != '/' AND path LIKE $2 || '/%' AND path NOT LIKE $2 || '/%/%')
|
||||||
|
)
|
||||||
|
AND ($3 = '' OR name ILIKE '%' || $3 || '%')
|
||||||
ORDER BY name
|
ORDER BY name
|
||||||
LIMIT $5 OFFSET $6
|
LIMIT $4 OFFSET $5
|
||||||
`, orgID, path, path, q, pageSize, offset)
|
`, orgID, path, q, pageSize, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -309,11 +316,17 @@ func (db *DB) GetUserFiles(ctx context.Context, userID uuid.UUID, path string, q
|
|||||||
}
|
}
|
||||||
offset := (page - 1) * pageSize
|
offset := (page - 1) * pageSize
|
||||||
|
|
||||||
|
// Return only direct children of the given path
|
||||||
rows, err := db.QueryContext(ctx, `
|
rows, err := db.QueryContext(ctx, `
|
||||||
SELECT id, org_id::text, user_id::text, name, path, type, size, last_modified, created_at
|
SELECT id, org_id::text, user_id::text, name, path, type, size, last_modified, created_at
|
||||||
FROM files
|
FROM files
|
||||||
WHERE user_id = $1 AND path LIKE $2 || '%'
|
WHERE user_id = $1
|
||||||
AND ($3 = '' OR name ILIKE '%' || $3 || '%')
|
AND path != $2
|
||||||
|
AND (
|
||||||
|
($2 = '/' AND path LIKE '/%' AND path NOT LIKE '/%/%')
|
||||||
|
OR ($2 != '/' AND path LIKE $2 || '/%' AND path NOT LIKE $2 || '/%/%')
|
||||||
|
)
|
||||||
|
AND ($3 = '' OR name ILIKE '%' || $3 || '%')
|
||||||
ORDER BY name
|
ORDER BY name
|
||||||
LIMIT $4 OFFSET $5
|
LIMIT $4 OFFSET $5
|
||||||
`, userID, path, q, pageSize, offset)
|
`, userID, path, q, pageSize, offset)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ func CORS(next http.Handler) http.Handler {
|
|||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||||
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
w.Header().Set("Access-Control-Max-Age", "3600")
|
w.Header().Set("Access-Control-Max-Age", "3600")
|
||||||
|
|
||||||
if r.Method == http.MethodOptions {
|
if r.Method == http.MethodOptions {
|
||||||
|
|||||||
Reference in New Issue
Block a user