mirror of
https://github.com/sigoden/dufs.git
synced 2026-04-09 09:09:03 +03:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b48a7473fc | ||
|
|
a84c3b353d | ||
|
|
e9383d71ed | ||
|
|
8258dabe4a | ||
|
|
0e236b61f6 | ||
|
|
09788ed031 | ||
|
|
46ebe978ae | ||
|
|
e01f2030e1 | ||
|
|
8d03ec151a |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -2,6 +2,24 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.15.1] - 2022-06-11
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Cannot upload ([#32](https://github.com/sigoden/duf/issues/32))
|
||||
|
||||
## [0.15.0] - 2022-06-10
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Encode webdav href as uri ([#28](https://github.com/sigoden/duf/issues/28))
|
||||
- Query dir param
|
||||
|
||||
### Features
|
||||
|
||||
- Add basic dark theme ([#29](https://github.com/sigoden/duf/issues/29))
|
||||
- Add empty state placeholder to page([#30](https://github.com/sigoden/duf/issues/30))
|
||||
|
||||
## [0.14.0] - 2022-06-07
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -286,7 +286,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "duf"
|
||||
version = "0.14.0"
|
||||
version = "0.15.1"
|
||||
dependencies = [
|
||||
"async-walkdir",
|
||||
"async_zip",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "duf"
|
||||
version = "0.14.0"
|
||||
version = "0.15.1"
|
||||
edition = "2021"
|
||||
authors = ["sigoden <sigoden@gmail.com>"]
|
||||
description = "Duf is a simple file server."
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -97,6 +97,11 @@ body {
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.empty-folder {
|
||||
padding-top: 1rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.uploaders-table th,
|
||||
.paths-table th {
|
||||
text-align: left;
|
||||
@@ -173,3 +178,39 @@ body {
|
||||
.uploader {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
/* dark theme */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
html,
|
||||
.breadcrumb>b,
|
||||
.searchbar #search {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uploaders-table th,
|
||||
.paths-table th {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
svg,
|
||||
.path svg {
|
||||
fill: #d0e6ff;
|
||||
}
|
||||
|
||||
.searchbar {
|
||||
background-color: #111;
|
||||
border-color: #fff6;
|
||||
}
|
||||
|
||||
.searchbar svg {
|
||||
fill: #fff6;
|
||||
}
|
||||
|
||||
.path a {
|
||||
color: #3191ff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="empty-folder hidden"></div>
|
||||
<table class="uploaders-table hidden">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -7,11 +7,29 @@
|
||||
* @property {number} size
|
||||
*/
|
||||
|
||||
// https://stackoverflow.com/a/901144/3642588
|
||||
const params = new Proxy(new URLSearchParams(window.location.search), {
|
||||
get: (searchParams, prop) => searchParams.get(prop),
|
||||
});
|
||||
|
||||
const dirEmptyNote = params.q ? 'No results' : DATA.dir_exists ? 'Empty folder' : 'Folder will be created when a file is uploaded';
|
||||
|
||||
/**
|
||||
* @type Element
|
||||
*/
|
||||
let $pathsTable, $pathsTableBody, $uploadersTable;
|
||||
let $pathsTable;
|
||||
/**
|
||||
* @type Element
|
||||
*/
|
||||
let $pathsTableBody;
|
||||
/**
|
||||
* @type Element
|
||||
*/
|
||||
let $uploadersTable;
|
||||
/**
|
||||
* @type Element
|
||||
*/
|
||||
let $emptyFolder;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -53,6 +71,7 @@ class Uploader {
|
||||
<td class="cell-status" id="uploadStatus${idx}"></td>
|
||||
</tr>`);
|
||||
$uploadersTable.classList.remove("hidden");
|
||||
$emptyFolder.classList.add("hidden");
|
||||
this.$uploadStatus = document.getElementById(`uploadStatus${idx}`);
|
||||
|
||||
const ajax = new XMLHttpRequest();
|
||||
@@ -180,6 +199,8 @@ async function deletePath(index) {
|
||||
DATA.paths[index] = null;
|
||||
if (!DATA.paths.find(v => !!v)) {
|
||||
$pathsTable.classList.add("hidden");
|
||||
$emptyFolder.textContent = dirEmptyNote;
|
||||
$emptyFolder.classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
throw new Error(await res.text())
|
||||
@@ -274,6 +295,11 @@ function ready() {
|
||||
$pathsTable = document.querySelector(".paths-table")
|
||||
$pathsTableBody = document.querySelector(".paths-table tbody");
|
||||
$uploadersTable = document.querySelector(".uploaders-table");
|
||||
$emptyFolder = document.querySelector(".empty-folder");
|
||||
|
||||
if (params.q) {
|
||||
document.getElementById('search').value = params.q;
|
||||
}
|
||||
|
||||
addBreadcrumb(DATA.breadcrumb);
|
||||
if (Array.isArray(DATA.paths)) {
|
||||
@@ -284,6 +310,10 @@ function ready() {
|
||||
for (let i = 0; i < len; i++) {
|
||||
addPath(DATA.paths[i], i);
|
||||
}
|
||||
if (len == 0) {
|
||||
$emptyFolder.textContent = dirEmptyNote;
|
||||
$emptyFolder.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
if (DATA.allow_upload) {
|
||||
dropzone();
|
||||
|
||||
@@ -191,8 +191,8 @@ impl InnerService {
|
||||
self.handle_render_index(path, headers, &mut res).await?;
|
||||
} else if query == "zip" {
|
||||
self.handle_zip_dir(path, &mut res).await?;
|
||||
} else if query.starts_with("q=") {
|
||||
self.handle_query_dir(path, &query[3..], &mut res).await?;
|
||||
} else if let Some(q) = query.strip_prefix("q=") {
|
||||
self.handle_query_dir(path, q, &mut res).await?;
|
||||
} else {
|
||||
self.handle_ls_dir(path, true, &mut res).await?;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ impl InnerService {
|
||||
}
|
||||
}
|
||||
};
|
||||
self.send_index(path, paths, res)
|
||||
self.send_index(path, paths, res, exist)
|
||||
}
|
||||
|
||||
async fn handle_query_dir(
|
||||
@@ -354,7 +354,7 @@ impl InnerService {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.send_index(path, paths, res)
|
||||
self.send_index(path, paths, res, true)
|
||||
}
|
||||
|
||||
async fn handle_zip_dir(&self, path: &Path, res: &mut Response) -> BoxResult<()> {
|
||||
@@ -645,6 +645,7 @@ impl InnerService {
|
||||
path: &Path,
|
||||
mut paths: Vec<PathItem>,
|
||||
res: &mut Response,
|
||||
exist: bool,
|
||||
) -> BoxResult<()> {
|
||||
paths.sort_unstable();
|
||||
let rel_path = match self.args.path.parent() {
|
||||
@@ -656,6 +657,7 @@ impl InnerService {
|
||||
paths,
|
||||
allow_upload: self.args.allow_upload,
|
||||
allow_delete: self.args.allow_delete,
|
||||
dir_exists: exist,
|
||||
};
|
||||
let data = serde_json::to_string(&data).unwrap();
|
||||
let output = INDEX_HTML.replace(
|
||||
@@ -802,6 +804,7 @@ struct IndexData {
|
||||
paths: Vec<PathItem>,
|
||||
allow_upload: bool,
|
||||
allow_delete: bool,
|
||||
dir_exists: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Eq, PartialEq, Ord, PartialOrd)]
|
||||
@@ -816,10 +819,12 @@ struct PathItem {
|
||||
impl PathItem {
|
||||
pub fn to_dav_xml(&self, prefix: &str) -> String {
|
||||
let mtime = Utc.timestamp_millis(self.mtime as i64).to_rfc2822();
|
||||
let href = encode_uri(&format!("{}{}", prefix, &self.name));
|
||||
let displayname = escape_str_pcdata(&self.base_name);
|
||||
match self.path_type {
|
||||
PathType::Dir | PathType::SymlinkDir => format!(
|
||||
r#"<D:response>
|
||||
<D:href>{}{}</D:href>
|
||||
<D:href>{}</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:displayname>{}</D:displayname>
|
||||
@@ -829,14 +834,11 @@ impl PathItem {
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>"#,
|
||||
escape_str_pcdata(prefix),
|
||||
escape_str_pcdata(&self.name),
|
||||
escape_str_pcdata(&self.base_name),
|
||||
mtime
|
||||
href, displayname, mtime
|
||||
),
|
||||
PathType::File | PathType::SymlinkFile => format!(
|
||||
r#"<D:response>
|
||||
<D:href>{}{}</D:href>
|
||||
<D:href>{}</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:displayname>{}</D:displayname>
|
||||
@@ -847,9 +849,8 @@ impl PathItem {
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>"#,
|
||||
escape_str_pcdata(prefix),
|
||||
escape_str_pcdata(&self.name),
|
||||
escape_str_pcdata(&self.base_name),
|
||||
href,
|
||||
displayname,
|
||||
self.size.unwrap_or_default(),
|
||||
mtime
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user