]> OzVa Git service - ozva-cloud/commitdiff
feat: ui supports view file (#301)
authorsigoden <sigoden@gmail.com>
Mon, 27 Nov 2023 23:14:53 +0000 (07:14 +0800)
committerGitHub <noreply@github.com>
Mon, 27 Nov 2023 23:14:53 +0000 (07:14 +0800)
assets/index.css
assets/index.html
assets/index.js
src/server.rs

index 6740b2d4343b4bf296049793d117c981c601c46f..d0ab5a8320d2d5d754a1ac3cbc4ad03ffc671d82 100644 (file)
@@ -212,6 +212,7 @@ body {
   height: calc(100vh - 5rem);
   border: 1px solid #ced4da;
   outline: none;
+  padding: 5px;
 }
 
 .toolbox-right {
index 20732213f529a15d8481e24b775d424e1d3a7ec0..3fdcb3f27999fd37575b4eab3a182d26e13aadb5 100644 (file)
     </div>
     <div class="editor-page hidden">
       <div class="not-editable hidden"></div>
-      <textarea id="editor" class="editor hidden" title="Edit file" cols="10"></textarea>
+      <textarea id="editor" class="editor hidden" aria-label="Editor" cols="10"></textarea>
     </div>
   </div>
   <script>
index 0c825d04de2633621986e89de1a955564cc98bf9..299850f3a563042712b71dfe437a6e1cace02a94 100644 (file)
@@ -10,7 +10,7 @@
  * @typedef {object} DATA
  * @property {string} href
  * @property {string} uri_prefix
- * @property {"Index" | "Edit"} kind
+ * @property {"Index" | "Edit" | "View"} kind
  * @property {PathItem[]} paths
  * @property {boolean} allow_upload
  * @property {boolean} allow_delete
@@ -55,7 +55,8 @@ const ICONS = {
   download: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/><path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/></svg>`,
   move: `<svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z"/></svg>`,
   edit: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg>`,
-  delete: `<svg width="16" height="16" fill="currentColor"viewBox="0 0 16 16"><path d="M6.854 7.146a.5.5 0 1 0-.708.708L7.293 9l-1.147 1.146a.5.5 0 0 0 .708.708L8 9.707l1.146 1.147a.5.5 0 0 0 .708-.708L8.707 9l1.147-1.146a.5.5 0 0 0-.708-.708L8 8.293 6.854 7.146z"/><path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/></svg>`,
+  delete: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M6.854 7.146a.5.5 0 1 0-.708.708L7.293 9l-1.147 1.146a.5.5 0 0 0 .708.708L8 9.707l1.146 1.147a.5.5 0 0 0 .708-.708L8.707 9l1.147-1.146a.5.5 0 0 0-.708-.708L8 8.293 6.854 7.146z"/><path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/></svg>`,
+  view: `<svg width="16" height="16" viewBox="0 0 16 16"><path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1"/></svg>`,
 }
 
 /**
@@ -113,7 +114,12 @@ function ready() {
     document.title = `Edit ${DATA.href} - Dufs`;
     document.querySelector(".editor-page").classList.remove("hidden");;
 
-    setupEditPage();
+    setupEditorPage();
+  } else if (DATA.kind == "View") {
+    document.title = `View ${DATA.href} - Dufs`;
+    document.querySelector(".editor-page").classList.remove("hidden");;
+
+    setupEditorPage();
   }
 }
 
@@ -369,6 +375,7 @@ function addPath(file, index) {
   let actionDownload = "";
   let actionMove = "";
   let actionEdit = "";
+  let actionView = "";
   let isDir = file.path_type.endsWith("Dir");
   if (isDir) {
     url += "/";
@@ -394,9 +401,13 @@ function addPath(file, index) {
     actionDelete = `
     <div onclick="deletePath(${index})" class="action-btn" id="deleteBtn${index}" title="Delete">${ICONS.delete}</div>`;
   }
+  if (!actionEdit && !isDir) {
+    actionView = `<a class="action-btn" title="View file" target="_blank" href="${url}?view">${ICONS.view}</a>`;
+  }
   let actionCell = `
   <td class="cell-actions">
     ${actionDownload}
+    ${actionView}
     ${actionMove}
     ${actionDelete}
     ${actionEdit}
@@ -504,32 +515,40 @@ function setupNewFile() {
   });
 }
 
-async function setupEditPage() {
+async function setupEditorPage() {
   const url = baseUrl();
 
   const $download = document.querySelector(".download");
   $download.classList.remove("hidden");
   $download.href = url;
 
-  const $moveFile = document.querySelector(".move-file");
-  $moveFile.classList.remove("hidden");
-  $moveFile.addEventListener("click", async () => {
-    const query = location.href.slice(url.length);
-    const newFileUrl = await doMovePath(url);
-    if (newFileUrl) {
-      location.href = newFileUrl + query;
-    }
-  });
-
-  const $deleteFile = document.querySelector(".delete-file");
-  $deleteFile.classList.remove("hidden");
-  $deleteFile.addEventListener("click", async () => {
-    const url = baseUrl();
-    const name = baseName(url);
-    await doDeletePath(name, url, () => {
-      location.href = location.href.split("/").slice(0, -1).join("/");
+  if (DATA.kind == "Edit") {
+    const $moveFile = document.querySelector(".move-file");
+    $moveFile.classList.remove("hidden");
+    $moveFile.addEventListener("click", async () => {
+      const query = location.href.slice(url.length);
+      const newFileUrl = await doMovePath(url);
+      if (newFileUrl) {
+        location.href = newFileUrl + query;
+      }
     });
-  })
+
+    const $deleteFile = document.querySelector(".delete-file");
+    $deleteFile.classList.remove("hidden");
+    $deleteFile.addEventListener("click", async () => {
+      const url = baseUrl();
+      const name = baseName(url);
+      await doDeletePath(name, url, () => {
+        location.href = location.href.split("/").slice(0, -1).join("/");
+      });
+    })
+
+    const $saveBtn = document.querySelector(".save-btn");
+    $saveBtn.classList.remove("hidden");
+    $saveBtn.addEventListener("click", saveChange);
+  } else if (DATA.kind == "View") {
+    $editor.readonly = true;
+  }
 
   if (!DATA.editable) {
     const $notEditable = document.querySelector(".not-editable");
@@ -544,10 +563,6 @@ async function setupEditPage() {
     return;
   }
 
-  const $saveBtn = document.querySelector(".save-btn");
-  $saveBtn.classList.remove("hidden");
-  $saveBtn.addEventListener("click", saveChange);
-
   $editor.classList.remove("hidden");
   try {
     const res = await fetch(baseUrl());
index ebc26613b9974c5d7018917f03c08ce062923bd2..dc76d61a8581fdbad16369092b26ddc176abf31c 100644 (file)
@@ -290,7 +290,10 @@ impl Server {
                     }
                 } else if is_file {
                     if query_params.contains_key("edit") {
-                        self.handle_edit_file(path, head_only, user, &mut res)
+                        self.handle_deal_file(path, DataKind::Edit, head_only, user, &mut res)
+                            .await?;
+                    } else if query_params.contains_key("view") {
+                        self.handle_deal_file(path, DataKind::View, head_only, user, &mut res)
                             .await?;
                     } else {
                         self.handle_send_file(path, headers, head_only, &mut res)
@@ -773,9 +776,10 @@ impl Server {
         Ok(())
     }
 
-    async fn handle_edit_file(
+    async fn handle_deal_file(
         &self,
         path: &Path,
+        kind: DataKind,
         head_only: bool,
         user: Option<String>,
         res: &mut Response,
@@ -791,7 +795,7 @@ impl Server {
         let editable = meta.len() <= TEXT_MAX_SIZE && content_inspector::inspect(&buffer).is_text();
         let data = EditData {
             href,
-            kind: DataKind::Edit,
+            kind,
             uri_prefix: self.args.uri_prefix.clone(),
             allow_upload: self.args.allow_upload,
             allow_delete: self.args.allow_delete,
@@ -1198,10 +1202,11 @@ impl Server {
     }
 }
 
-#[derive(Debug, Serialize)]
+#[derive(Debug, Serialize, PartialEq)]
 enum DataKind {
     Index,
     Edit,
+    View,
 }
 
 #[derive(Debug, Serialize)]