Skip to content

Commit 29ecd14

Browse files
committed
allow to list files recursively
1 parent c70ef23 commit 29ecd14

File tree

3 files changed

+68
-18
lines changed

3 files changed

+68
-18
lines changed

client/browser/FileSelectDialog.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,36 @@ export default function FileSelectDialog(props) {
133133
last_folder: folderId,
134134
files: [],
135135
offset: null,
136+
recursive: false,
136137
search_query: '',
137138
});
138139
fetchFiles();
139140
return newStructure;
140141
});
141142
};
142143

144+
async function toggleRecursive(folderId: string) {
145+
setStructure(prevStructure => {
146+
const newStructure = Object.assign(structure, {
147+
...prevStructure,
148+
last_folder: folderId,
149+
files: [],
150+
offset: null,
151+
recursive: prevStructure.recursive ? false : true,
152+
search_query: '',
153+
});
154+
fetchFiles();
155+
return newStructure;
156+
});
157+
}
158+
143159
const setSearchQuery = (query) => {
144160
setStructure(prevStructure => {
145161
const newStructure = Object.assign(structure, {
146162
...prevStructure,
147163
files: [],
148164
offset: null,
165+
recursive: false,
149166
search_query: query,
150167
});
151168
fetchFiles();
@@ -180,6 +197,9 @@ export default function FileSelectDialog(props) {
180197
async function fetchFiles() {
181198
const fetchUrl = (() => {
182199
const params = new URLSearchParams();
200+
if (structure.recursive) {
201+
params.set('recursive', '');
202+
}
183203
if (structure.offset !== null) {
184204
params.set('offset', String(structure.offset));
185205
}
@@ -203,7 +223,6 @@ export default function FileSelectDialog(props) {
203223
}
204224

205225
function refreshStructure() {
206-
console.log('refreshStructure');
207226
setStructure({...structure});
208227
}
209228

client/browser/FolderStructure.tsx

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,28 @@ import RootIcon from '../icons/root.svg';
88

99

1010
function FolderEntry(props) {
11-
const {folder, toggleOpen, setCurrentFolder, isCurrent} = props;
11+
const {folder, toggleOpen, setCurrentFolder, openRecursive, isCurrent, isListed} = props;
1212

1313
if (folder.is_root) {
14-
return (<span onClick={() => setCurrentFolder(folder.id)}><RootIcon/></span>);
14+
return (<i onClick={() => setCurrentFolder(folder.id)}><RootIcon/></i>);
1515
}
1616

17-
return (<>
18-
<i onClick={toggleOpen}>{
19-
folder.has_subfolders ? folder.is_open ? <ArrowDownIcon/> : <ArrowRightIcon/> : <EmptyIcon/>
20-
}</i>
21-
{isCurrent ?
22-
<strong><FolderOpenIcon/>{folder.name}</strong> :
23-
<span onClick={() => setCurrentFolder(folder.id)} role="button">
24-
<FolderIcon/>{folder.name}
25-
</span>
17+
return (<>{
18+
folder.has_subfolders ? <i onClick={toggleOpen}>{
19+
folder.is_open ? <ArrowDownIcon/> : <ArrowRightIcon/>
20+
}</i> : <i><EmptyIcon/></i>}
21+
<i onClick={openRecursive} role="button">{isListed || isCurrent ? <FolderOpenIcon/> : <FolderIcon/>}</i>
22+
{isCurrent
23+
? <strong>{folder.name}</strong>
24+
: <span onClick={() => setCurrentFolder(folder.id)} role="button">{folder.name}</span>
2625
}
2726
</>);
2827
}
2928

3029

3130
export default function FolderStructure(props) {
32-
const {baseUrl, folder, lastFolderId, setCurrentFolder, refreshStructure} = props;
31+
const {baseUrl, folder, lastFolderId, setCurrentFolder, toggleRecursive, refreshStructure} = props;
32+
const isListed = props.isListed === false ? lastFolderId === folder.id : props.isListed;
3333

3434
async function fetchChildren() {
3535
const response = await fetch(`${baseUrl}${folder.id}/fetch`);
@@ -44,28 +44,47 @@ export default function FolderStructure(props) {
4444
}
4545

4646
async function toggleOpen() {
47-
folder.is_open = !folder.is_open;
4847
if (folder.is_open) {
48+
folder.is_open = false;
49+
await fetch(`${baseUrl}${folder.id}/close`);
50+
} else {
51+
folder.is_open = true;
4952
if (folder.children === null) {
5053
await fetchChildren();
5154
} else {
5255
await fetch(`${baseUrl}${folder.id}/open`);
5356
}
54-
} else {
55-
await fetch(`${baseUrl}${folder.id}/close`);
5657
}
5758
refreshStructure();
5859
}
5960

61+
async function openRecursive() {
62+
if (lastFolderId === folder.id) {
63+
if (folder.is_open === false) {
64+
folder.is_open = true;
65+
if (folder.children === null) {
66+
await fetchChildren();
67+
} else {
68+
await fetch(`${baseUrl}${folder.id}/open`);
69+
}
70+
}
71+
toggleRecursive(folder.id);
72+
} else {
73+
setCurrentFolder(folder.id);
74+
}
75+
}
76+
6077
return folder ? (
6178
<li>
6279
<FolderEntry
6380
folder={folder}
6481
toggleOpen={toggleOpen}
6582
setCurrentFolder={setCurrentFolder}
83+
openRecursive={openRecursive}
6684
isCurrent={lastFolderId === folder.id}
85+
isListed={isListed}
6786
/>
68-
{folder.is_open && (
87+
{folder.is_open && folder.children && (
6988
<ul>
7089
{folder.children.map(child => (
7190
<FolderStructure
@@ -74,7 +93,9 @@ export default function FolderStructure(props) {
7493
folder={child}
7594
lastFolderId={lastFolderId}
7695
setCurrentFolder={setCurrentFolder}
96+
toggleRecursive={toggleRecursive}
7797
refreshStructure={refreshStructure}
98+
isListed={isListed}
7899
/>
79100
))}
80101
</ul>)}

finder/browser/views.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,17 @@ def list(self, request, folder_id):
139139
"""
140140
request.session['finder.last_folder'] = str(folder_id)
141141
offset = int(request.GET.get('offset', 0))
142+
recursive = 'recursive' in request.GET
142143
lookup = lookup_by_label(request)
143-
unified_queryset = FileModel.objects.filter_unified(parent_id=folder_id, is_folder=False, **lookup)
144+
if recursive:
145+
descendants = FolderModel.objects.get(id=folder_id).descendants
146+
if isinstance(descendants, QuerySet):
147+
parent_ids = Subquery(descendants.values('id'))
148+
else:
149+
parent_ids = [descendant.id for descendant in descendants]
150+
unified_queryset = FileModel.objects.filter_unified(parent_id__in=parent_ids, is_folder=False, **lookup)
151+
else:
152+
unified_queryset = FileModel.objects.filter_unified(parent_id=folder_id, is_folder=False, **lookup)
144153
next_offset = offset + self.limit
145154
if next_offset >= unified_queryset.count():
146155
next_offset = None
@@ -149,6 +158,7 @@ def list(self, request, folder_id):
149158
return {
150159
'files': list(unified_queryset[offset:offset + self.limit]),
151160
'offset': next_offset,
161+
'recursive': recursive,
152162
'search_query': '',
153163
}
154164

0 commit comments

Comments
 (0)