Skip to content

Commit 2f77f1f

Browse files
author
SM_SAYEED
committed
inline edit redefined
1 parent 2e883e2 commit 2f77f1f

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

app.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,8 +1060,7 @@ def property_detail(property_name, tab):
10601060
conn.commit()
10611061
upload_message = f"Linked folder: imported {imported} item(s)."
10621062

1063-
# 3) Upload a ZIP → push contents to Drive <root>/<property>/<tab> → import--Right now I am not using this due to not having a shared drive in google workspace.
1064-
# When I do use workspace, this Zip branch must be further refined such that it becomes deterministic on computed parent folder.
1063+
# 3) Upload a ZIP → push contents to Drive <root>/<property>/<tab> → import
10651064
elif request.form.get('zip_upload'):
10661065
if 'zipfile' not in request.files or request.files['zipfile'].filename == '':
10671066
upload_message = "No ZIP file selected."
@@ -1074,6 +1073,10 @@ def property_detail(property_name, tab):
10741073
service = get_drive_service()
10751074
target_folder_id = drive_ensure_property_tab_folder(service, root_id, property_name, tab)
10761075

1076+
# Hard guard so we never upload into Drive 'root'
1077+
if not target_folder_id or target_folder_id in ("root", "", None):
1078+
raise RuntimeError("Refusing to upload: invalid Drive parent (would create in root).")
1079+
10771080
data = zf.read()
10781081
z = zipfile.ZipFile(io.BytesIO(data))
10791082
uploaded = 0
@@ -1146,9 +1149,16 @@ def property_detail(property_name, tab):
11461149
(new_desc, property_name, tab, row_filename),
11471150
)
11481151
conn.commit()
1152+
# AJAX? return JSON so the page doesn't reload
1153+
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
1154+
return jsonify({"ok": True, "filename": row_filename})
1155+
# Non-AJAX fallback
11491156
edit_message = f"Updated info for {row_filename}."
11501157

11511158
except Exception as e:
1159+
# AJAX error?
1160+
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
1161+
return jsonify({"ok": False, "error": str(e)}), 400
11521162
upload_message = f"Error: {e}"
11531163

11541164
# ---- fetch current uploads (Drive-only for property pages) ----

templates/property_detail.html

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,18 @@ <h3>Add a {{ pretty_title }} {{ tab.title() }} from Google Drive</h3>
6868

6969
<!-- Link a FOLDER (import all allowed files) -->
7070
<form method="post" class="stack" style="margin-bottom:1em;">
71-
<div class="small">Or link a Drive FOLDER (we’ll import all allowed files directly under it).</div>
71+
<div class="small">Or link a Drive FOLDER (we’ll import all allowed files, including subfolders).</div>
7272
<div>
7373
<input type="text" name="drive_folder_link" placeholder="Drive FOLDER link or folder ID" style="width:560px" required>
7474
<button type="submit" name="link_folder" value="1">Link Folder</button>
7575
</div>
7676
</form>
7777

78-
<!-- Upload a ZIP and push to Drive -->
78+
<!-- Upload a ZIP and push to Drive (currently optional) -->
7979
<form method="post" enctype="multipart/form-data" class="stack">
8080
<div class="small">Or upload a .zip; allowed files inside will be uploaded to Drive automatically.</div>
8181
<div>
82-
<input type="file" name="zipfile" accept=".zip" required>
82+
<input type="file" name="zipfile" accept=".zip">
8383
<button type="submit" name="zip_upload" value="1">Upload ZIP to Drive</button>
8484
</div>
8585
</form>
@@ -115,7 +115,7 @@ <h3>Add a {{ pretty_title }} {{ tab.title() }} from Google Drive</h3>
115115
{% if tab == 'dataset' %}
116116
<td>
117117
{% if admin %}
118-
<form method="post" style="display:inline;">
118+
<form method="post" class="row-edit" style="display:inline;">
119119
<input type="hidden" name="row_filename" value="{{ filename }}">
120120
<input type="text" name="row_source" value="{{ source or '' }}" size="18">
121121
{% else %}
@@ -131,7 +131,7 @@ <h3>Add a {{ pretty_title }} {{ tab.title() }} from Google Drive</h3>
131131
<button type="submit" name="edit_row" value="1" style="margin-left:6px;">Save</button>
132132
</form>
133133
{% else %}
134-
<form method="post" style="display:inline;">
134+
<form method="post" class="row-edit" style="display:inline;">
135135
<input type="hidden" name="row_filename" value="{{ filename }}">
136136
<input type="text" name="row_description" value="{{ description or '' }}" size="22">
137137
<button type="submit" name="edit_row" value="1" style="margin-left:6px;">Save</button>
@@ -150,18 +150,18 @@ <h3>Add a {{ pretty_title }} {{ tab.title() }} from Google Drive</h3>
150150

151151
<td>
152152
{% if (storage or 'local') == 'drive' %}
153-
{% if preview_url %}<a href="{{ preview_url }}" target="_blank">View</a>{% endif %}
154-
{% if download_url %} | <a href="{{ download_url }}" target="_blank">Download</a>{% endif %}
153+
{% if preview_url %}<a href="{{ preview_url }}" target="_blank" rel="noopener">View</a>{% endif %}
154+
{% if download_url %} | <a href="{{ download_url }}" target="_blank" rel="noopener">Download</a>{% endif %}
155155
{% else %}
156156
{% if tab == 'dataset' and (filename.endswith('.csv') or filename.endswith('.npy')) %}
157157
{% set tname = table_map.get(filename) %}
158158
{% if tname %}
159-
<a href="{{ url_for('public_view', table=tname) }}" target="_blank">View</a>
159+
<a href="{{ url_for('public_view', table=tname) }}" target="_blank" rel="noopener">View</a>
160160
{% else %}
161161
<span class="small">No table yet</span>
162162
{% endif %}
163163
{% elif tab == 'results' %}
164-
<a href="{{ url_for('view_result_file', property_name=property_name, tab=tab, filename=filename) }}" target="_blank">View</a>
164+
<a href="{{ url_for('view_result_file', property_name=property_name, tab=tab, filename=filename) }}" target="_blank" rel="noopener">View</a>
165165
{% endif %}
166166
| <a href="{{ url_for('uploaded_file', filename=property_name ~ '/' ~ tab ~ '/' ~ filename) }}" download>Download</a>
167167
{% endif %}
@@ -187,5 +187,37 @@ <h3>Add a {{ pretty_title }} {{ tab.title() }} from Google Drive</h3>
187187
<a class="return-home" href="{{ url_for('public_home') }}">Return to Home</a>
188188
<a class="return-home" href="{{ url_for('materials_portal') }}" style="margin-left:1.5em;">Back to Materials Database</a>
189189
</div>
190+
191+
{% if admin %}
192+
<script>
193+
// Intercept per-row Save to avoid page reload (preserves other unsaved edits)
194+
document.querySelectorAll('form.row-edit').forEach(function(form) {
195+
form.addEventListener('submit', async function (e) {
196+
e.preventDefault();
197+
const fd = new FormData(form);
198+
// Ensure the intent flag is present
199+
if (!fd.has('edit_row')) fd.append('edit_row', '1');
200+
const btn = form.querySelector('button[type="submit"]');
201+
const old = btn.textContent;
202+
btn.disabled = true;
203+
204+
try {
205+
const resp = await fetch(location.href, {
206+
method: 'POST',
207+
body: fd,
208+
headers: { 'X-Requested-With': 'XMLHttpRequest' }
209+
});
210+
let data = {};
211+
try { data = await resp.json(); } catch { /* ignore */ }
212+
btn.textContent = data.ok ? 'Saved ✓' : 'Saved';
213+
} catch (err) {
214+
btn.textContent = 'Error';
215+
}
216+
217+
setTimeout(() => { btn.disabled = false; btn.textContent = old; }, 1200);
218+
});
219+
});
220+
</script>
221+
{% endif %}
190222
</body>
191223
</html>

0 commit comments

Comments
 (0)