Skip to content

Commit b686ac9

Browse files
committed
use MutationObserver on <finder-file-select>
1 parent 8432e23 commit b686ac9

File tree

7 files changed

+53
-39
lines changed

7 files changed

+53
-39
lines changed

client/browser/FinderFileSelect.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import React, {useEffect, useRef, useState} from 'react';
22
import FileSelectDialog from './FileSelectDialog';
3-
import {useMutationObserver} from '../common/MutationObserver';
43

54

65
export default function FinderFileSelect(props) {
76
const shadowRoot = props.container;
87
const baseUrl = props['base-url'];
98
const styleUrl = props['style-url'];
10-
const [selectedFile, setSelectedFile] = useState(props['selected-file']);
119
const selectRef = useRef(null);
1210
const slotRef = useRef(null);
1311
const dialogRef = useRef(null);
12+
const [selectedFile, setSelectedFile] = useState({});
1413
const csrfToken = getCSRFToken();
1514

1615
useEffect(() => {
@@ -20,6 +19,15 @@ export default function FinderFileSelect(props) {
2019
link.media = 'all';
2120
link.rel = 'stylesheet';
2221
shadowRoot.insertBefore(link, shadowRoot.firstChild);
22+
const observer = new MutationObserver(attributesChanged);
23+
const inputElement = slotRef.current.assignedElements()[0];
24+
if (inputElement instanceof HTMLInputElement) {
25+
setSelectedFile(JSON.parse(inputElement.getAttribute('data-selected_file')));
26+
observer.observe(inputElement, {attributes: true});
27+
}
28+
return () => {
29+
observer.disconnect();
30+
};
2331
}, []);
2432

2533
useEffect(() => {
@@ -44,6 +52,21 @@ export default function FinderFileSelect(props) {
4452
}
4553
}, []);
4654

55+
async function attributesChanged(mutationList) {
56+
for (const mutation of mutationList) {
57+
if (mutation.type === 'attributes' && mutation.attributeName === 'data-file_id') {
58+
const fileId = mutation.target.dataset.file_id;
59+
const response = await fetch(`${baseUrl}${fileId}/fetch`);
60+
if (response.ok) {
61+
setSelectedFile(await response.json());
62+
} else {
63+
console.error(`Failed to fetch file info for ID ${fileId}:`, response.statusText);
64+
}
65+
66+
}
67+
}
68+
}
69+
4770
function getCSRFToken() {
4871
const csrfToken = shadowRoot.host.closest('form')?.querySelector('input[name="csrfmiddlewaretoken"]')?.value;
4972
if (csrfToken)

client/common/MutationObserver.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

client/finder-select.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ window.addEventListener('DOMContentLoaded', (event) => {
66
window.customElements.define(
77
'finder-file-select',
88
r2wc(FinderFileSelect, {
9-
props: {'base-url': 'string', 'selected-file': 'json', 'style-url': 'string', realm: 'string'},
9+
props: {'base-url': 'string', 'style-url': 'string', realm: 'string'},
1010
shadow: 'open',
1111
}),
1212
);

finder/browser/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
BrowserView.as_view(action='structure'),
1212
),
1313
path(
14-
'<uuid:folder_id>/fetch',
14+
'<uuid:inode_id>/fetch',
1515
BrowserView.as_view(action='fetch'),
1616
),
1717
path(

finder/browser/views.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.utils.html import strip_spaces_between_tags
77
from django.utils.safestring import mark_safe
88
from django.views import View
9+
from django.views.decorators.http import last_modified
910

1011
from finder.lookups import annotate_unified_queryset, lookup_by_label, sort_by_attribute
1112
from finder.models.file import FileModel
@@ -100,24 +101,26 @@ def structure(self, request, slug):
100101
**self.list(request, request.session['finder.last_folder']),
101102
}
102103

103-
def fetch(self, request, folder_id):
104+
def fetch(self, request, inode_id):
104105
"""
105106
Open the given folder and fetch children data for the folder.
106107
"""
107-
folder = FolderModel.objects.get(id=folder_id)
108-
folder_id = str(folder_id)
109-
request.session.setdefault('finder.open_folders', [])
110-
if folder_id not in request.session['finder.open_folders']:
111-
request.session['finder.open_folders'].append(folder_id)
112-
request.session.modified = True
113-
114-
return {
115-
'id': folder_id,
116-
'name': folder.name,
117-
'children': self._get_children(request.session['finder.open_folders'], folder),
118-
'is_open': True,
119-
'has_subfolders': folder.subfolders.exists(),
120-
}
108+
inode = FileModel.objects.get_inode(id=inode_id)
109+
inode_id = str(inode_id)
110+
if inode.is_folder:
111+
request.session.setdefault('finder.open_folders', [])
112+
if inode_id not in request.session['finder.open_folders']:
113+
request.session['finder.open_folders'].append(inode_id)
114+
request.session.modified = True
115+
return {
116+
'id': inode_id,
117+
'name': inode.name,
118+
'children': self._get_children(request.session['finder.open_folders'], inode),
119+
'is_open': True,
120+
'has_subfolders': inode.subfolders.exists(),
121+
}
122+
else:
123+
return inode.as_dict
121124

122125
def open(self, request, folder_id):
123126
"""

finder/forms/widgets.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@ def get_context(self, name, value, attrs):
2525
css_classes = attrs.get('class', '').split()
2626
css_classes.append('finder-file-field')
2727
attrs['class'] = ' '.join(css_classes)
28-
context = super().get_context(name, value, attrs)
29-
context.update(
30-
base_url=reverse('finder-api:base-url'),
31-
realm='admin',
32-
style_url=static('finder/css/finder-browser.css'),
33-
)
3428
if isinstance(value, str):
3529
# file reference has not been stored using a `finder.models.fields.FinderFileField`
3630
try:
3731
value = FileModel.objects.get_inode(id=uuid.UUID(value), is_folder=False)
3832
except (ValueError, FileModel.DoesNotExist):
3933
pass
4034
if isinstance(value, AbstractFileModel):
41-
context['selected_file'] = json.dumps(value.as_dict, cls=DjangoJSONEncoder)
35+
attrs['data-selected_file'] = json.dumps(value.as_dict, cls=DjangoJSONEncoder)
36+
context = super().get_context(name, value, attrs)
37+
context.update(
38+
base_url=reverse('finder-api:base-url'),
39+
realm='admin',
40+
style_url=static('finder/css/finder-browser.css'),
41+
)
4242
return context
4343

4444
def format_value(self, value):
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<finder-file-select base-url="{{ base_url }}" style-url="{{ style_url }}" realm="{{ realm }}" selected-file="{{ selected_file }}">{% include "django/forms/widgets/input.html" %}</finder-file-select>
1+
<finder-file-select base-url="{{ base_url }}" style-url="{{ style_url }}" realm="{{ realm }}">{% include "django/forms/widgets/input.html" %}</finder-file-select>

0 commit comments

Comments
 (0)