Use plain text viewer for plain text files

Fixes #29
This commit is contained in:
2021-02-15 11:27:04 +01:00
parent 3a3cdaa59d
commit 443f8c1af5
6 changed files with 152 additions and 27 deletions

View File

@@ -1,7 +1,7 @@
function TextViewer(viewer, file) { function TextViewer(viewer, file) {
this.viewer = viewer this.viewer = viewer
this.file = file this.file = file
this.pre = null this.pre = null
this.prettyprint = null this.prettyprint = null
this.container = document.createElement("div") this.container = document.createElement("div")
@@ -9,18 +9,20 @@ function TextViewer(viewer, file) {
if (this.file.name.endsWith(".md") || this.file.name.endsWith(".markdown") || file.mime_type === "text/demo") { if (this.file.name.endsWith(".md") || this.file.name.endsWith(".markdown") || file.mime_type === "text/demo") {
this.getMarkdown() this.getMarkdown()
} else { } else if (this.file.name.endsWith(".txt")) {
this.getText() this.getText()
} else {
this.getCode()
} }
} }
TextViewer.prototype.getText = function() { TextViewer.prototype.getCode = function () {
this.pre = document.createElement("pre") this.pre = document.createElement("pre")
this.pre.classList = "pre-container prettyprint linenums" this.pre.classList = "pre-container prettyprint linenums"
this.pre.innerText = "Loading..." this.pre.innerText = "Loading..."
this.container.appendChild(this.pre) this.container.appendChild(this.pre)
if (this.file.size > 1<<20) { // File larger than 1 MiB if (this.file.size > 1 << 20) { // File larger than 1 MiB
this.pre.innerText = "File is too large to view online.\nPlease download and view it locally." this.pre.innerText = "File is too large to view online.\nPlease download and view it locally."
return return
} }
@@ -36,23 +38,43 @@ TextViewer.prototype.getText = function() {
this.prettyprint.src = "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert" this.prettyprint.src = "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert"
this.container.appendChild(this.prettyprint) this.container.appendChild(this.prettyprint)
}).catch(err => { }).catch(err => {
this.pre.innerText = "Error loading file: "+err this.pre.innerText = "Error loading file: " + err
}) })
} }
TextViewer.prototype.getMarkdown = function() { TextViewer.prototype.getText = function () {
this.pre = document.createElement("pre")
this.pre.innerText = "Loading..."
this.container.appendChild(this.pre)
if (this.file.size > 1 << 20) { // File larger than 1 MiB
this.pre.innerText = "File is too large to view online.\nPlease download and view it locally."
return
}
fetch(this.file.get_href).then(resp => {
if (!resp.ok) { return Promise.reject(resp.status) }
return resp.text()
}).then(resp => {
this.pre.innerText = resp
}).catch(err => {
this.pre.innerText = "Error loading file: " + err
})
}
TextViewer.prototype.getMarkdown = function () {
fetch( fetch(
domainURL()+window.location.pathname+"/preview" domainURL() + window.location.pathname + "/preview"
).then(resp => { ).then(resp => {
if (!resp.ok) { return Promise.reject(resp.status) } if (!resp.ok) { return Promise.reject(resp.status) }
return resp.text() return resp.text()
}).then(resp => { }).then(resp => {
this.container.innerHTML = resp this.container.innerHTML = resp
}).catch(err => { }).catch(err => {
this.container.innerText = "Error loading file: "+err this.container.innerText = "Error loading file: " + err
}) })
} }
TextViewer.prototype.render = function(parent) { TextViewer.prototype.render = function (parent) {
parent.appendChild(this.container) parent.appendChild(this.container)
} }

View File

@@ -132,8 +132,9 @@
<a href="https://nypost.com/2021/02/14/hundreds-of-thousands-without-power-after-oregon-ice-storm/" target="_blank">an ice storm in Oregon</a> <a href="https://nypost.com/2021/02/14/hundreds-of-thousands-without-power-after-oregon-ice-storm/" target="_blank">an ice storm in Oregon</a>
the datacenter where pixeldrain is hosted in North America the datacenter where pixeldrain is hosted in North America
was cut off from the internet and has lost power. This was cut off from the internet and has lost power. This
caused an outage of a few hours yesterday (it happened when caused an outage of a few hours last saturday (it happened
I was out ice skating). when I was out ice skating, so I didn't notice it until I
got back).
</p> </p>
<p> <p>
I am now redirecting all American (north and south) traffic I am now redirecting all American (north and south) traffic

View File

@@ -1,5 +1,19 @@
<script context="module"> <script context="module">
export const fs_create_bucket = async (name) => {
const form = new FormData()
form.append("name", name)
const resp = await fetch(
window.api_endpoint+"/filesystem",
{ method: "POST", body: form }
);
if(resp.status >= 400) {
throw new Error(resp.text());
}
return resp.json()
}
export const fs_get_buckets = async () => { export const fs_get_buckets = async () => {
const resp = await fetch(window.api_endpoint+"/filesystem"); const resp = await fetch(window.api_endpoint+"/filesystem");
if(resp.status >= 400) { if(resp.status >= 400) {
@@ -8,6 +22,18 @@ export const fs_get_buckets = async () => {
return resp.json(); return resp.json();
} }
export const fs_delete_bucket = async (id, recursive) => {
let uri = window.api_endpoint+"/filesystem/"+encodeURIComponent(id)
if (recursive) {
uri += "?recursive"
}
const resp = await fetch(uri, { method: "DELETE" });
if(resp.status >= 400) {
throw new Error(resp.text());
}
}
export const fs_create_directory = async (bucket, path, dir_name) => { export const fs_create_directory = async (bucket, path, dir_name) => {
if (!path.startsWith("/")) { if (!path.startsWith("/")) {
path = "/" + path path = "/" + path
@@ -16,12 +42,12 @@ export const fs_create_directory = async (bucket, path, dir_name) => {
const form = new FormData() const form = new FormData()
form.append("type", "dir") form.append("type", "dir")
const resp=await fetch( const resp = await fetch(
window.api_endpoint+"/filesystem/"+bucket+encodeURIComponent(path+"/"+dir_name), window.api_endpoint+"/filesystem/"+bucket+encodeURIComponent(path+"/"+dir_name),
{ method: "POST", body: form } { method: "POST", body: form }
); );
if(resp.status >= 400) { if(resp.status >= 400) {
throw new Error(resp.text()); throw new Error(resp.text())
} }
} }
@@ -34,9 +60,9 @@ export const fs_get_node = async (bucket, path) => {
window.api_endpoint+"/filesystem/"+bucket+encodeURIComponent(path)+"?stat" window.api_endpoint+"/filesystem/"+bucket+encodeURIComponent(path)+"?stat"
); );
if(resp.status >= 400) { if(resp.status >= 400) {
throw new Error(resp.text()); throw new Error(resp.text())
} }
return resp.json(); return resp.json()
} }
export const fs_get_file_url = (bucket, path) => { export const fs_get_file_url = (bucket, path) => {
@@ -56,9 +82,9 @@ export const fs_rename_node = async (bucket, old_path, new_path) => {
const resp=await fetch( const resp=await fetch(
window.api_endpoint+"/filesystem/"+bucket+encodeURIComponent(old_path), window.api_endpoint+"/filesystem/"+bucket+encodeURIComponent(old_path),
{ method: "PUT", body: form } { method: "PUT", body: form }
); )
if(resp.status >= 400) { if(resp.status >= 400) {
throw new Error(resp.text()); throw new Error(resp.text())
} }
} }
@@ -72,7 +98,7 @@ export const fs_delete_node = async (bucket, path) => {
{ method: "DELETE" } { method: "DELETE" }
); );
if(resp.status >= 400) { if(resp.status >= 400) {
throw new Error(resp.text()); throw new Error(resp.text())
} }
} }

View File

@@ -1,4 +1,5 @@
<script> <script>
import { fs_delete_bucket } from "../filesystem/FilesystemAPI.svelte";
export let bucket export let bucket
let details_hidden = true let details_hidden = true
@@ -6,6 +7,25 @@ const expand_bucket = () => {
details_hidden = !details_hidden details_hidden = !details_hidden
} }
const save_bucket = () => {
alert("save")
}
const delete_bucket = async () => {
if (!confirm(
"Are you sure you want to delete this bucket? All the files within "+
"the bucket will be irrevocably deleted. There is no way to recover "+
"from this! Press OK to proceed"
)) {
return
}
try {
await fs_delete_bucket(bucket.id, true)
} catch (err) {
alert("Failed to delete bucket! "+err)
}
}
</script> </script>
<div class="bucket"> <div class="bucket">
@@ -23,7 +43,7 @@ const expand_bucket = () => {
</button> </button>
</div> </div>
<div class="bucket_details" class:hidden={details_hidden}> <div class="bucket_details" class:hidden={details_hidden}>
<form> <form on:submit|preventDefault={save_bucket}>
<table class="form"> <table class="form">
<tr class="form"> <tr class="form">
<td>Name</td> <td>Name</td>
@@ -31,10 +51,10 @@ const expand_bucket = () => {
</tr> </tr>
<tr class="form"> <tr class="form">
<td colspan="2"> <td colspan="2">
<button class="button_red"> <button class="button_red" on:click|preventDefault={delete_bucket}>
<i class="icon">delete</i> Delete <i class="icon">delete</i> Delete
</button> </button>
<button class="button_highlight" style="float: right;"> <button class="button_highlight" type="submit" style="float: right;">
<i class="icon">save</i> Save <i class="icon">save</i> Save
</button> </button>
</td> </td>
@@ -50,6 +70,7 @@ const expand_bucket = () => {
background-color: var(--layer_3_color); background-color: var(--layer_3_color);
transition: box-shadow 0.5s; transition: box-shadow 0.5s;
box-shadow: 1px 1px var(--layer_3_shadow) 0 var(--shadow_color); box-shadow: 1px 1px var(--layer_3_shadow) 0 var(--shadow_color);
margin: 1em 0;
} }
.bucket_header { .bucket_header {
display: flex; display: flex;

View File

@@ -0,0 +1,42 @@
<script>
import { fs_create_bucket } from "../filesystem/FilesystemAPI.svelte";
let name
const submit = async () => {
if (!name.value) {
alert("Please enter a name!")
return
}
try {
let bucket = await fs_create_bucket(name.value)
console.log(bucket)
} catch (err) {
alert("Failed to create bucket! "+err)
}
}
</script>
<div class="highlight_light">
<form on:submit|preventDefault={submit}>
<table class="form">
<tr>
<td>
Name
</td>
<td>
<input type="text" bind:this={name}/>
</td>
</tr>
<tr>
<td colspan="2">
<button class="button_highlight" type="submit" style="float: right;">
<i class="icon">save</i> Save
</button>
</td>
</tr>
</table>
</form>
</div>

View File

@@ -3,10 +3,14 @@ import { onMount } from "svelte";
import Bucket from "./Bucket.svelte"; import Bucket from "./Bucket.svelte";
import Spinner from "../util/Spinner.svelte"; import Spinner from "../util/Spinner.svelte";
import { fs_get_buckets } from "../filesystem/FilesystemAPI.svelte"; import { fs_get_buckets } from "../filesystem/FilesystemAPI.svelte";
import NewBucket from "./NewBucket.svelte";
let loading = true; let loading = true;
let buckets = []; let buckets = [];
let new_bucket;
let creating_bucket = false;
const get_buckets = async () => { const get_buckets = async () => {
try { try {
let resp = await fs_get_buckets(); let resp = await fs_get_buckets();
@@ -29,10 +33,18 @@ onMount(get_buckets);
{/if} {/if}
<div class="limit_width"> <div class="limit_width">
<button style="float: right;"> <div class="toolbar" style="text-align: right;">
<i class="icon">create_new_folder</i> New bucket <button
</button> class:button_highlight={creating_bucket}
<br/> on:click={() => {creating_bucket = !creating_bucket}}
>
<i class="icon">create_new_folder</i> New bucket
</button>
</div>
{#if creating_bucket}
<NewBucket bind:this={new_bucket}></NewBucket>
{/if}
<h2>Persistent buckets</h2> <h2>Persistent buckets</h2>
<p> <p>
These buckets don't expire, but have limited storage space and These buckets don't expire, but have limited storage space and
@@ -47,6 +59,7 @@ onMount(get_buckets);
</p> </p>
</div> </div>
</div> </div>
<style> <style>