Skip to main content

max / makenotwork

4.5 KB · 114 lines History Blame Raw
1 function mediaCopyRef(ref) {
2 var text = '![](' + ref + ')';
3 navigator.clipboard.writeText(text).then(function() {
4 showToast('Copied: ' + text);
5 });
6 }
7
8 function mediaFilterFolder(folder, btn) {
9 var cards = document.querySelectorAll('.media-card');
10 cards.forEach(function(card) {
11 if (folder === null) {
12 card.classList.remove('hidden');
13 } else {
14 card.classList.toggle('hidden', card.dataset.folder !== folder);
15 }
16 });
17 // Update selected button
18 var buttons = btn.parentElement.querySelectorAll('.btn-small');
19 buttons.forEach(function(b) { b.classList.remove('is-selected'); });
20 btn.classList.add('is-selected');
21 }
22
23 function mediaDeleteFile(id, name) {
24 if (!confirm('Delete "' + name + '"? This cannot be undone. Existing references in your content will break.')) return;
25 fetch('/api/media/' + id, {
26 method: 'DELETE',
27 credentials: 'same-origin',
28 headers: csrfHeaders()
29 }).then(function(res) {
30 if (res.ok) {
31 document.getElementById('tab-media').click();
32 } else {
33 res.text().then(function(t) { showToast(t || 'Failed to delete file.'); });
34 }
35 }).catch(function() {
36 showToast('Network error. Please check your connection and try again.');
37 });
38 }
39
40 function mediaHandleDrop(e) {
41 e.preventDefault();
42 if (e.dataTransfer && e.dataTransfer.files.length > 0) {
43 mediaUploadFiles(e.dataTransfer.files);
44 }
45 }
46
47 function mediaUploadFiles(fileList) {
48 var folder = (document.getElementById('media-folder-input').value || '').trim();
49 var progress = document.getElementById('media-upload-progress');
50 progress.innerHTML = '';
51
52 for (var i = 0; i < fileList.length; i++) {
53 (function(file) {
54 var statusEl = document.createElement('div');
55 statusEl.className = 'user-media-upload-status';
56 statusEl.textContent = 'Uploading ' + file.name + '...';
57 progress.appendChild(statusEl);
58
59 // 1. Presign
60 fetch('/api/media/presign', {
61 method: 'POST',
62 credentials: 'same-origin',
63 headers: { 'Content-Type': 'application/json', ...csrfHeaders() },
64 body: JSON.stringify({
65 file_name: file.name,
66 content_type: file.type,
67 folder: folder
68 })
69 }).then(function(res) {
70 if (!res.ok) return res.text().then(function(t) { throw new Error(t); });
71 return res.json();
72 }).then(function(data) {
73 // 2. Upload to S3
74 var headers = { 'Content-Type': file.type };
75 if (data.cache_control) headers['Cache-Control'] = data.cache_control;
76 return fetch(data.upload_url, {
77 method: 'PUT',
78 headers: headers,
79 body: file
80 }).then(function(putRes) {
81 if (!putRes.ok) throw new Error('S3 upload failed');
82 return data;
83 });
84 }).then(function(data) {
85 // 3. Confirm
86 return fetch('/api/media/confirm', {
87 method: 'POST',
88 credentials: 'same-origin',
89 headers: { 'Content-Type': 'application/json', ...csrfHeaders() },
90 body: JSON.stringify({
91 s3_key: data.s3_key,
92 file_name: file.name,
93 content_type: file.type,
94 folder: folder
95 })
96 }).then(function(res) {
97 if (!res.ok) return res.text().then(function(t) { throw new Error(t); });
98 statusEl.textContent = file.name + ' uploaded.';
99 statusEl.classList.add('user-media-upload-status--ok');
100 });
101 }).catch(function(err) {
102 statusEl.textContent = file.name + ': ' + (err.message || 'Upload failed');
103 statusEl.classList.add('user-media-upload-status--err');
104 }).finally(function() {
105 // Refresh tab after last file
106 var remaining = progress.querySelectorAll('.user-media-upload-status:not(.user-media-upload-status--ok):not(.user-media-upload-status--err)');
107 if (remaining.length === 0) {
108 setTimeout(function() { document.getElementById('tab-media').click(); }, 1000);
109 }
110 });
111 })(fileList[i]);
112 }
113 }
114