semuthitamku commited on
Commit
7c3fa30
·
verified ·
1 Parent(s): 5058376

Update public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +31 -7
public/index.html CHANGED
@@ -26,7 +26,7 @@
26
  .bread a { color: var(--link); text-decoration:none; }
27
  .bread span.sep { margin: 0 6px; color: var(--muted); }
28
  main { padding:18px 20px; max-width:1100px; margin:auto; }
29
- .bar { display:flex; gap:8px; flex-wrap: wrap; margin-bottom:12px; }
30
  .bar input[type="text"] { background:var(--panel-alt); color:var(--txt);
31
  border:1px solid var(--border); border-radius:8px; padding:8px 10px; min-width: 220px; }
32
  .btn { background:var(--btn-bg); color:var(--txt); border:1px solid var(--border2);
@@ -42,19 +42,19 @@
42
  tbody tr:hover { background:var(--panel-alt); }
43
  .name { display:flex; align-items:center; gap:10px; }
44
  .name a { color: var(--txt); text-decoration:none; }
45
- .muted { color: var(--muted); }
46
  .right { text-align:right; }
47
  .actions { display:flex; gap:6px; }
48
  .chip { font-size:12px; color:#0f172a; background:#a7f3d0; padding:2px 8px; border-radius:999px; }
49
  footer { color: var(--muted); text-align:center; padding:12px; font-size:12px; }
50
- .flex-gap { display:flex; gap:8px; align-items:center; flex-wrap: wrap; }
51
  .spacer { flex:1; }
52
  .hidden { display:none; }
53
  .note { font-size:12px; color:var(--muted); }
54
- .checkbox { width:18px; height:18px; }
55
  .icon { width:18px; text-align:center; }
56
  .toast { position:fixed; right:16px; bottom:16px; background:var(--panel); border:1px solid var(--border2);
57
  padding:10px 12px; border-radius:8px; color:var(--txt); box-shadow:var(--shadow); }
 
58
  </style>
59
  </head>
60
  <body class="theme-dark">
@@ -71,6 +71,8 @@
71
  <input type="text" id="urlInput" placeholder="https://contoh.com/file.tgz" />
72
  <input type="text" id="filenameInput" placeholder="Nama file (opsional)" />
73
  <button class="btn pri" id="fetchBtn">Save dari URL</button>
 
 
74
 
75
  <input type="file" id="fileInput" multiple />
76
  <button class="btn" id="uploadBtn">Upload</button>
@@ -119,6 +121,8 @@
119
  const urlInput = document.getElementById("urlInput");
120
  const filenameInput = document.getElementById("filenameInput");
121
  const fetchBtn = document.getElementById("fetchBtn");
 
 
122
  const fileInput = document.getElementById("fileInput");
123
  const uploadBtn = document.getElementById("uploadBtn");
124
  const newFolderBtn = document.getElementById("newFolderBtn");
@@ -181,6 +185,14 @@
181
  history.replaceState(null, "", url);
182
  load();
183
  }
 
 
 
 
 
 
 
 
184
 
185
  async function load() {
186
  const res = await fetch(`/api/list?path=${encodeURIComponent(currentPath)}`);
@@ -189,6 +201,7 @@
189
  }
190
 
191
  function render(data) {
 
192
  breadcrumb.innerHTML = "";
193
  data.breadcrumb.forEach((c, idx) => {
194
  const a = document.createElement("a");
@@ -204,6 +217,7 @@
204
  }
205
  });
206
 
 
207
  tbody.innerHTML = "";
208
  if (!data.items.length) emptyState.classList.remove("hidden"); else emptyState.classList.add("hidden");
209
 
@@ -287,7 +301,7 @@
287
  unzipBtn.className = "btn warn";
288
  unzipBtn.textContent = "Unarchive";
289
  unzipBtn.onclick = async () => {
290
- const defaultName = item.name.replace(/(\.tar\.gz|\.tgz|\.zip|\.tar)$/i, "");
291
  const destDefault = `${currentPath ? currentPath + "/" : ""}${defaultName}`;
292
  const dest = prompt("Extract ke folder (opsional):", destDefault);
293
  const body = dest ? { zipPath: item.relPath, destDir: dest } : { zipPath: item.relPath };
@@ -352,8 +366,15 @@
352
  const url = urlInput.value.trim();
353
  const filename = filenameInput.value.trim();
354
  if (!url) return showToast("URL kosong");
355
- const body = { url, destDir: currentPath };
 
 
 
 
 
 
356
  if (filename) body.filename = filename;
 
357
  const res = await fetch("/api/fetch-url", {
358
  method: "POST",
359
  headers: { "Content-Type": "application/json" },
@@ -361,7 +382,10 @@
361
  });
362
  const j = await res.json();
363
  if (!res.ok) return showToast(j.error || "Gagal download dari URL");
364
- showToast("Berhasil diunduh ke folder ini");
 
 
 
365
  urlInput.value = ""; filenameInput.value = "";
366
  load();
367
  };
 
26
  .bread a { color: var(--link); text-decoration:none; }
27
  .bread span.sep { margin: 0 6px; color: var(--muted); }
28
  main { padding:18px 20px; max-width:1100px; margin:auto; }
29
+ .bar { display:flex; gap:8px; flex-wrap: wrap; margin-bottom:12px; align-items:center; }
30
  .bar input[type="text"] { background:var(--panel-alt); color:var(--txt);
31
  border:1px solid var(--border); border-radius:8px; padding:8px 10px; min-width: 220px; }
32
  .btn { background:var(--btn-bg); color:var(--txt); border:1px solid var(--border2);
 
42
  tbody tr:hover { background:var(--panel-alt); }
43
  .name { display:flex; align-items:center; gap:10px; }
44
  .name a { color: var(--txt); text-decoration:none; }
45
+ .muted { color:var(--muted); }
46
  .right { text-align:right; }
47
  .actions { display:flex; gap:6px; }
48
  .chip { font-size:12px; color:#0f172a; background:#a7f3d0; padding:2px 8px; border-radius:999px; }
49
  footer { color: var(--muted); text-align:center; padding:12px; font-size:12px; }
 
50
  .spacer { flex:1; }
51
  .hidden { display:none; }
52
  .note { font-size:12px; color:var(--muted); }
53
+ .checkbox { width:18px; height:18px; vertical-align: middle; }
54
  .icon { width:18px; text-align:center; }
55
  .toast { position:fixed; right:16px; bottom:16px; background:var(--panel); border:1px solid var(--border2);
56
  padding:10px 12px; border-radius:8px; color:var(--txt); box-shadow:var(--shadow); }
57
+ label.inline { display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--muted); }
58
  </style>
59
  </head>
60
  <body class="theme-dark">
 
71
  <input type="text" id="urlInput" placeholder="https://contoh.com/file.tgz" />
72
  <input type="text" id="filenameInput" placeholder="Nama file (opsional)" />
73
  <button class="btn pri" id="fetchBtn">Save dari URL</button>
74
+ <label class="inline"><input type="checkbox" id="autoExtract" class="checkbox" checked /> Auto extract</label>
75
+ <label class="inline"><input type="checkbox" id="removeArchive" class="checkbox" /> Hapus arsip</label>
76
 
77
  <input type="file" id="fileInput" multiple />
78
  <button class="btn" id="uploadBtn">Upload</button>
 
121
  const urlInput = document.getElementById("urlInput");
122
  const filenameInput = document.getElementById("filenameInput");
123
  const fetchBtn = document.getElementById("fetchBtn");
124
+ const autoExtractEl = document.getElementById("autoExtract");
125
+ const removeArchiveEl = document.getElementById("removeArchive");
126
  const fileInput = document.getElementById("fileInput");
127
  const uploadBtn = document.getElementById("uploadBtn");
128
  const newFolderBtn = document.getElementById("newFolderBtn");
 
185
  history.replaceState(null, "", url);
186
  load();
187
  }
188
+ function stripArchiveExt(name) {
189
+ const lower = String(name).toLowerCase();
190
+ if (lower.endsWith(".tar.gz")) return name.slice(0, -7);
191
+ if (lower.endsWith(".tgz")) return name.slice(0, -4);
192
+ if (lower.endsWith(".zip")) return name.slice(0, -4);
193
+ if (lower.endsWith(".tar")) return name.slice(0, -4);
194
+ return name;
195
+ }
196
 
197
  async function load() {
198
  const res = await fetch(`/api/list?path=${encodeURIComponent(currentPath)}`);
 
201
  }
202
 
203
  function render(data) {
204
+ // Breadcrumb
205
  breadcrumb.innerHTML = "";
206
  data.breadcrumb.forEach((c, idx) => {
207
  const a = document.createElement("a");
 
217
  }
218
  });
219
 
220
+ // Rows
221
  tbody.innerHTML = "";
222
  if (!data.items.length) emptyState.classList.remove("hidden"); else emptyState.classList.add("hidden");
223
 
 
301
  unzipBtn.className = "btn warn";
302
  unzipBtn.textContent = "Unarchive";
303
  unzipBtn.onclick = async () => {
304
+ const defaultName = stripArchiveExt(item.name);
305
  const destDefault = `${currentPath ? currentPath + "/" : ""}${defaultName}`;
306
  const dest = prompt("Extract ke folder (opsional):", destDefault);
307
  const body = dest ? { zipPath: item.relPath, destDir: dest } : { zipPath: item.relPath };
 
366
  const url = urlInput.value.trim();
367
  const filename = filenameInput.value.trim();
368
  if (!url) return showToast("URL kosong");
369
+
370
+ const body = {
371
+ url,
372
+ destDir: currentPath,
373
+ autoExtract: autoExtractEl.checked,
374
+ removeArchive: removeArchiveEl.checked
375
+ };
376
  if (filename) body.filename = filename;
377
+
378
  const res = await fetch("/api/fetch-url", {
379
  method: "POST",
380
  headers: { "Content-Type": "application/json" },
 
382
  });
383
  const j = await res.json();
384
  if (!res.ok) return showToast(j.error || "Gagal download dari URL");
385
+
386
+ if (j.extractedTo) showToast(`Diunduh & diextract ke: ${j.extractedTo}`);
387
+ else showToast("Berhasil diunduh ke folder ini");
388
+
389
  urlInput.value = ""; filenameInput.value = "";
390
  load();
391
  };