Make filesystem list view columns sortable
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import { formatDate } from "util/Formatting";
|
import { formatDate } from "util/Formatting";
|
||||||
import Modal from "util/Modal.svelte"
|
import Modal from "util/Modal.svelte"
|
||||||
import SortButton from "./SortButton.svelte";
|
import SortButton from "layout/SortButton.svelte";
|
||||||
import { flip } from "svelte/animate";
|
import { flip } from "svelte/animate";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { flip } from "svelte/animate";
|
import { flip } from "svelte/animate";
|
||||||
import { formatDataVolume } from "util/Formatting";
|
import { formatDataVolume } from "util/Formatting";
|
||||||
import SortButton from "./SortButton.svelte";
|
import SortButton from "layout/SortButton.svelte";
|
||||||
|
|
||||||
export let peers = [];
|
export let peers = [];
|
||||||
$: update_peers(peers)
|
$: update_peers(peers)
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import LoadingIndicator from "util/LoadingIndicator.svelte";
|
import LoadingIndicator from "util/LoadingIndicator.svelte";
|
||||||
import { formatDataVolume, formatDate } from "util/Formatting";
|
import { formatDataVolume, formatDate } from "util/Formatting";
|
||||||
import SortButton from "admin_panel/SortButton.svelte";
|
import SortButton from "layout/SortButton.svelte";
|
||||||
|
|
||||||
export let user_id = ""
|
export let user_id = ""
|
||||||
let files = []
|
let files = []
|
||||||
|
@@ -39,7 +39,7 @@ export class FSNavigator {
|
|||||||
// If you set the loading property to a boolean writable store the navigator
|
// If you set the loading property to a boolean writable store the navigator
|
||||||
// will use it to publish its loading states
|
// will use it to publish its loading states
|
||||||
loading: Writable<boolean> | null = null
|
loading: Writable<boolean> | null = null
|
||||||
set_loading(b: boolean) {
|
set_loading = (b: boolean) => {
|
||||||
if (this.loading !== null) {
|
if (this.loading !== null) {
|
||||||
this.loading.set(b)
|
this.loading.set(b)
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ export class FSNavigator {
|
|||||||
// This works by implementing the store contract:
|
// This works by implementing the store contract:
|
||||||
// https://svelte.dev/docs/svelte-components#script-4-prefix-stores-with-$-to-access-their-values
|
// https://svelte.dev/docs/svelte-components#script-4-prefix-stores-with-$-to-access-their-values
|
||||||
subscribers: Array<(nav: FSNavigator) => void> = []
|
subscribers: Array<(nav: FSNavigator) => void> = []
|
||||||
subscribe(sub_func: (nav: FSNavigator) => void) {
|
subscribe = (sub_func: (nav: FSNavigator) => void) => {
|
||||||
// Immediately return the current value
|
// Immediately return the current value
|
||||||
sub_func(this)
|
sub_func(this)
|
||||||
|
|
||||||
@@ -58,8 +58,13 @@ export class FSNavigator {
|
|||||||
// Return the unsubscribe function
|
// Return the unsubscribe function
|
||||||
return () => this.subscribers.splice(this.subscribers.indexOf(sub_func), 1)
|
return () => this.subscribers.splice(this.subscribers.indexOf(sub_func), 1)
|
||||||
}
|
}
|
||||||
|
notify_subscribers = () => {
|
||||||
|
for (let i = 0; i < this.subscribers.length; i++) {
|
||||||
|
this.subscribers[i](this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async navigate(path: string, push_history: boolean) {
|
navigate = async (path: string, push_history: boolean) => {
|
||||||
if (path[0] !== "/") {
|
if (path[0] !== "/") {
|
||||||
path = "/" + path
|
path = "/" + path
|
||||||
}
|
}
|
||||||
@@ -88,17 +93,17 @@ export class FSNavigator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async navigate_up() {
|
navigate_up = async () => {
|
||||||
if (this.path.length > 1) {
|
if (this.path.length > 1) {
|
||||||
await this.navigate(this.path[this.path.length - 2].path, false)
|
await this.navigate(this.path[this.path.length - 2].path, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async reload() {
|
reload = async () => {
|
||||||
await this.navigate(this.base.path, false)
|
await this.navigate(this.base.path, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
open_node(node: FSPath, push_history: boolean) {
|
open_node = (node: FSPath, push_history: boolean) => {
|
||||||
// Update window title and navigation history. If push_history is false
|
// Update window title and navigation history. If push_history is false
|
||||||
// we still replace the URL with replaceState. This way the user is not
|
// we still replace the URL with replaceState. This way the user is not
|
||||||
// greeted to a 404 page when refreshing after renaming a file
|
// greeted to a 404 page when refreshing after renaming a file
|
||||||
@@ -122,7 +127,7 @@ export class FSNavigator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort directory children
|
// Sort directory children
|
||||||
sort_children(node.children)
|
sort_children(node.children, this.sort_last_field, this.sort_asc)
|
||||||
|
|
||||||
// Update shared state
|
// Update shared state
|
||||||
this.path = node.path
|
this.path = node.path
|
||||||
@@ -137,9 +142,7 @@ export class FSNavigator {
|
|||||||
|
|
||||||
// Signal to our subscribers that the new node is loaded. This triggers
|
// Signal to our subscribers that the new node is loaded. This triggers
|
||||||
// the reactivity
|
// the reactivity
|
||||||
for (let i = 0; i < this.subscribers.length; i++) {
|
this.notify_subscribers()
|
||||||
this.subscribers[i](this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are used to navigate forward and backward within a directory (using
|
// These are used to navigate forward and backward within a directory (using
|
||||||
@@ -151,7 +154,7 @@ export class FSNavigator {
|
|||||||
cached_siblings_path = ""
|
cached_siblings_path = ""
|
||||||
cached_siblings: Array<FSNode> | null = null
|
cached_siblings: Array<FSNode> | null = null
|
||||||
|
|
||||||
async get_siblings() {
|
get_siblings = async () => {
|
||||||
// If this node is a filesystem root then there are no siblings
|
// If this node is a filesystem root then there are no siblings
|
||||||
if (this.path.length < 2) {
|
if (this.path.length < 2) {
|
||||||
return []
|
return []
|
||||||
@@ -166,7 +169,7 @@ export class FSNavigator {
|
|||||||
const resp = await fs_get_node(this.path[this.path.length - 2].path)
|
const resp = await fs_get_node(this.path[this.path.length - 2].path)
|
||||||
|
|
||||||
// Sort directory children to make sure the order is consistent
|
// Sort directory children to make sure the order is consistent
|
||||||
sort_children(resp.children)
|
sort_children(resp.children, this.sort_last_field, this.sort_asc)
|
||||||
|
|
||||||
// Save new siblings in navigator state
|
// Save new siblings in navigator state
|
||||||
this.cached_siblings_path = this.path[this.path.length - 2].path
|
this.cached_siblings_path = this.path[this.path.length - 2].path
|
||||||
@@ -179,7 +182,7 @@ export class FSNavigator {
|
|||||||
// Opens a sibling of the currently open file. The offset is relative to the
|
// Opens a sibling of the currently open file. The offset is relative to the
|
||||||
// file which is currently open. Give a positive number to move forward and
|
// file which is currently open. Give a positive number to move forward and
|
||||||
// a negative number to move backward
|
// a negative number to move backward
|
||||||
async open_sibling(offset: number) {
|
open_sibling = async (offset: number) => {
|
||||||
if (this.path.length <= 1) {
|
if (this.path.length <= 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -233,14 +236,51 @@ export class FSNavigator {
|
|||||||
console.debug("No siblings found")
|
console.debug("No siblings found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort_last_field: string = "name"
|
||||||
|
sort_asc: boolean = true
|
||||||
|
sort_children = (field: string) => {
|
||||||
|
// If the field is the same as last time we invert the direction
|
||||||
|
if (field !== "" && field === this.sort_last_field) {
|
||||||
|
this.sort_asc = !this.sort_asc
|
||||||
|
}
|
||||||
|
// If the field is empty we reuse the last field
|
||||||
|
if (field === "") {
|
||||||
|
field = this.sort_last_field
|
||||||
|
}
|
||||||
|
this.sort_last_field = field
|
||||||
|
|
||||||
|
sort_children(this.children, field, this.sort_asc)
|
||||||
|
|
||||||
|
// Signal to our subscribers that the order has changed. This triggers
|
||||||
|
// the reactivity
|
||||||
|
this.notify_subscribers()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sort_children = (children: Array<FSNode>) => {
|
const sort_children = (children: FSNode[], field: string, asc: boolean) => {
|
||||||
|
console.log("Sorting directory children by", field, "asc", asc)
|
||||||
children.sort((a, b) => {
|
children.sort((a, b) => {
|
||||||
// Sort directories before files
|
// Sort directories before files
|
||||||
if (a.type !== b.type) {
|
if (a.type !== b.type) {
|
||||||
return a.type === "dir" ? -1 : 1
|
return a.type === "dir" ? -1 : 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If sort is descending we swap the arguments
|
||||||
|
if (asc === false) {
|
||||||
|
[a, b] = [b, a]
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the two values are equal then we force sort by name, since names
|
||||||
|
// are always unique
|
||||||
|
if (a[field] === b[field]) {
|
||||||
return a.name.localeCompare(b.name, undefined, { numeric: true })
|
return a.name.localeCompare(b.name, undefined, { numeric: true })
|
||||||
|
} else if (typeof (a[field]) === "number") {
|
||||||
|
// Sort ints from high to low
|
||||||
|
return a[field] - b[field]
|
||||||
|
} else {
|
||||||
|
// Sort strings alphabetically
|
||||||
|
return a[field].localeCompare(b[field], undefined, { numeric: true })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -65,13 +65,6 @@ const update_shared = () => {
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<p>
|
|
||||||
When a file or directory is shared it can be accessed through a
|
|
||||||
unique link. You can get the URL with the 'Copy link' button on
|
|
||||||
the toolbar, or share the link with the 'Share' button. If you
|
|
||||||
share a directory all the files within the directory are also
|
|
||||||
accessible from the link.
|
|
||||||
</p>
|
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
form="edit_form"
|
form="edit_form"
|
||||||
@@ -83,13 +76,21 @@ const update_shared = () => {
|
|||||||
/>
|
/>
|
||||||
<label for="shared">Share this file or directory</label>
|
<label for="shared">Share this file or directory</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form_grid">
|
<div class="form_grid">
|
||||||
{#if is_shared}
|
{#if is_shared}
|
||||||
<span>Your sharing link: <a href={share_link}>{share_link}</a></span>
|
<span>Public link: <a href={share_link}>{share_link}</a></span>
|
||||||
<CopyButton text={share_link}>Copy</CopyButton>
|
<CopyButton text={share_link}>Copy</CopyButton>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When a file or directory is shared it can be accessed through a
|
||||||
|
unique link. You can get the URL with the 'Copy link' button on
|
||||||
|
the toolbar, or share the link with the 'Share' button. If you
|
||||||
|
share a directory all the files within the directory are also
|
||||||
|
accessible from the link.
|
||||||
|
</p>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@@ -8,6 +8,7 @@ let dispatch = createEventDispatcher()
|
|||||||
export let nav: FSNavigator
|
export let nav: FSNavigator
|
||||||
export let show_hidden = false
|
export let show_hidden = false
|
||||||
export let large_icons = false
|
export let large_icons = false
|
||||||
|
export let hide_edit = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="directory">
|
<div class="directory">
|
||||||
@@ -28,11 +29,17 @@ export let large_icons = false
|
|||||||
<a
|
<a
|
||||||
href="/d/{child.id}"
|
href="/d/{child.id}"
|
||||||
on:click|preventDefault|stopPropagation={e => {dispatch("node_share_click", {index: index, original: e})}}
|
on:click|preventDefault|stopPropagation={e => {dispatch("node_share_click", {index: index, original: e})}}
|
||||||
class="button action_button"
|
class="button flat action_button"
|
||||||
>
|
>
|
||||||
<i class="icon" title="This file / directory is shared. Click to open public link">share</i>
|
<i class="icon" title="This file / directory is shared. Click to open public link">share</i>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if $nav.permissions.write && !hide_edit}
|
||||||
|
<button class="action_button flat" on:click|preventDefault|stopPropagation={e => dispatch("node_settings", {index: index, original: e})}>
|
||||||
|
<i class="icon">edit</i>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -42,7 +49,7 @@ export let large_icons = false
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin: 8px;
|
padding: 8px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@@ -55,6 +62,7 @@ export let large_icons = false
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--input_background);
|
background: var(--input_background);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
box-shadow: 1px 1px 8px 0px var(--shadow_color);
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
.node:hover:not(.node_selected) {
|
.node:hover:not(.node_selected) {
|
||||||
@@ -83,6 +91,12 @@ export let large_icons = false
|
|||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.flat {
|
||||||
|
background: none;
|
||||||
|
color: var(--body_text_color);
|
||||||
|
box-shadow: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Large icon mode only supported on wide screens */
|
/* Large icon mode only supported on wide screens */
|
||||||
@media (min-width: 500px) {
|
@media (min-width: 500px) {
|
||||||
|
@@ -66,7 +66,7 @@ let node_context = (e: CustomEvent<FMNodeEvent>) => {
|
|||||||
}
|
}
|
||||||
const node_share_click = (e: CustomEvent<FMNodeEvent>) => {
|
const node_share_click = (e: CustomEvent<FMNodeEvent>) => {
|
||||||
creating_dir = false
|
creating_dir = false
|
||||||
nav.navigate(nav.children[e.detail.index].id, true)
|
edit_window.edit(nav.children[e.detail.index], false, "share")
|
||||||
}
|
}
|
||||||
const node_select = (e: CustomEvent<FMNodeEvent>) => {
|
const node_select = (e: CustomEvent<FMNodeEvent>) => {
|
||||||
const index = e.detail.index
|
const index = e.detail.index
|
||||||
|
@@ -189,6 +189,7 @@ onMount(() => {
|
|||||||
nav={nav}
|
nav={nav}
|
||||||
show_hidden={show_hidden}
|
show_hidden={show_hidden}
|
||||||
large_icons={large_icons}
|
large_icons={large_icons}
|
||||||
|
hide_edit
|
||||||
on:node_click={node_click}
|
on:node_click={node_click}
|
||||||
on:node_context={node_context}
|
on:node_context={node_context}
|
||||||
on:node_select={node_select}
|
on:node_select={node_select}
|
||||||
|
@@ -3,6 +3,8 @@ import { createEventDispatcher } from "svelte";
|
|||||||
import { formatDataVolume } from "util/Formatting";
|
import { formatDataVolume } from "util/Formatting";
|
||||||
import { fs_encode_path, fs_node_icon } from "filesystem/FilesystemAPI"
|
import { fs_encode_path, fs_node_icon } from "filesystem/FilesystemAPI"
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||||
|
import SortButton from "layout/SortButton.svelte";
|
||||||
|
import { flip } from "svelte/animate";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@@ -16,8 +18,8 @@ export let hide_branding = false
|
|||||||
<div class="directory">
|
<div class="directory">
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>Name</td>
|
<td><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="name">Name</SortButton></td>
|
||||||
<td class="hide_small">Size</td>
|
<td><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="file_size">Size</SortButton></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
{#each $nav.children as child, index (child.path)}
|
{#each $nav.children as child, index (child.path)}
|
||||||
@@ -25,6 +27,7 @@ export let hide_branding = false
|
|||||||
href={"/d"+fs_encode_path(child.path)}
|
href={"/d"+fs_encode_path(child.path)}
|
||||||
on:click|preventDefault={e => dispatch("node_click", {index: index, original: e})}
|
on:click|preventDefault={e => dispatch("node_click", {index: index, original: e})}
|
||||||
on:contextmenu={e => dispatch("node_context", {index: index, original: e})}
|
on:contextmenu={e => dispatch("node_context", {index: index, original: e})}
|
||||||
|
animate:flip={{duration: 500}}
|
||||||
class="node"
|
class="node"
|
||||||
class:node_selected={child.fm_selected}
|
class:node_selected={child.fm_selected}
|
||||||
class:hidden={child.name.startsWith(".") && !show_hidden}
|
class:hidden={child.name.startsWith(".") && !show_hidden}
|
||||||
@@ -53,7 +56,7 @@ export let hide_branding = false
|
|||||||
<i class="icon" title="This file / directory is shared. Click to open public link">share</i>
|
<i class="icon" title="This file / directory is shared. Click to open public link">share</i>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{#if child.properties !== undefined && child.properties.branding_enabled !== undefined && !hide_branding}
|
{#if child.properties !== undefined && child.properties.branding_enabled === "true" && !hide_branding}
|
||||||
<button class="action_button" on:click|preventDefault|stopPropagation={e => dispatch("node_branding", {index: index, original: e})}>
|
<button class="action_button" on:click|preventDefault|stopPropagation={e => dispatch("node_branding", {index: index, original: e})}>
|
||||||
<i class="icon">palette</i>
|
<i class="icon">palette</i>
|
||||||
</button>
|
</button>
|
||||||
@@ -78,7 +81,7 @@ export let hide_branding = false
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
max-width: 99%;
|
max-width: 99%;
|
||||||
width: 1000px;
|
width: 1200px;
|
||||||
}
|
}
|
||||||
.directory > * {
|
.directory > * {
|
||||||
display: table-row;
|
display: table-row;
|
||||||
@@ -120,7 +123,7 @@ td {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
.node_size {
|
.node_size {
|
||||||
min-width: 50px;
|
min-width: 5em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.icons_wrap {
|
.icons_wrap {
|
||||||
|
@@ -1,17 +1,13 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
export let field = ""
|
export let field = ""
|
||||||
export let active_field = ""
|
export let active_field = ""
|
||||||
export let asc = true
|
export let asc = true
|
||||||
export let sort_func
|
export let sort_func: (field: string) => void
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class:button_highlight={active_field === field} on:click={() => sort_func(field)}>
|
<button class:button_highlight={active_field === field} on:click={() => sort_func(field)}>
|
||||||
{#if active_field === field}
|
{#if active_field === field}
|
||||||
{#if asc}
|
{#if asc}↓{:else}↑{/if}
|
||||||
↓
|
|
||||||
{:else}
|
|
||||||
↑
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</button>
|
</button>
|
@@ -9,7 +9,7 @@ import SuccessMessage from "util/SuccessMessage.svelte";
|
|||||||
let loading = false
|
let loading = false
|
||||||
let success_message
|
let success_message
|
||||||
let hotlinking = window.user.hotlinking_enabled
|
let hotlinking = window.user.hotlinking_enabled
|
||||||
let transfer_cap = window.user.monthly_transfer_cap / 1e9
|
let transfer_cap = window.user.monthly_transfer_cap / 1e12
|
||||||
let skip_viewer = window.user.skip_file_viewer
|
let skip_viewer = window.user.skip_file_viewer
|
||||||
|
|
||||||
const update = async () => {
|
const update = async () => {
|
||||||
@@ -17,7 +17,7 @@ const update = async () => {
|
|||||||
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("hotlinking_enabled", hotlinking)
|
form.append("hotlinking_enabled", hotlinking)
|
||||||
form.append("transfer_cap", transfer_cap*1e9)
|
form.append("transfer_cap", transfer_cap*1e12)
|
||||||
form.append("skip_file_viewer", skip_viewer)
|
form.append("skip_file_viewer", skip_viewer)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -31,7 +31,7 @@ const update = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.user.hotlinking_enabled = hotlinking
|
window.user.hotlinking_enabled = hotlinking
|
||||||
window.user.monthly_transfer_cap = transfer_cap*1e9
|
window.user.monthly_transfer_cap = transfer_cap*1e12
|
||||||
|
|
||||||
success_message.set(true, "Sharing settings updated")
|
success_message.set(true, "Sharing settings updated")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -102,11 +102,12 @@ onMount(() => {
|
|||||||
|
|
||||||
<h2><Pro/>Bill shock limit</h2>
|
<h2><Pro/>Bill shock limit</h2>
|
||||||
<p>
|
<p>
|
||||||
Billshock limit in gigabytes per month (1 TB = 1000 GB). Set to 0 to disable.
|
Billshock limit in terabytes per month (1 TB = 1000 GB). Set to 0 to
|
||||||
|
disable.
|
||||||
</p>
|
</p>
|
||||||
<form on:submit|preventDefault={update} class="billshock_container">
|
<form on:submit|preventDefault={update} class="billshock_container">
|
||||||
<input type="number" bind:value={transfer_cap} step="100" min="0"/>
|
<input type="number" bind:value={transfer_cap} step="0.1" min="0" style="width: 5em;"/>
|
||||||
<div style="margin: 0.5em;">GB</div>
|
<div style="margin: 0.5em;">TB</div>
|
||||||
<button type="submit">
|
<button type="submit">
|
||||||
<i class="icon">save</i> Save
|
<i class="icon">save</i> Save
|
||||||
</button>
|
</button>
|
||||||
@@ -114,9 +115,9 @@ onMount(() => {
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Bandwidth used in the last 30 days: {formatDataVolume(transfer_used, 3)},
|
Bandwidth used in the last 30 days: {formatDataVolume(transfer_used, 3)},
|
||||||
new limit: {formatDataVolume(transfer_cap*1e9, 3)}
|
new limit: {formatDataVolume(transfer_cap*1e12, 3)}
|
||||||
</p>
|
</p>
|
||||||
<ProgressBar used={transfer_used} total={transfer_cap*1e9}></ProgressBar>
|
<ProgressBar used={transfer_used} total={transfer_cap*1e12}></ProgressBar>
|
||||||
<p>
|
<p>
|
||||||
The billshock limit limits how much bandwidth your account can use in a
|
The billshock limit limits how much bandwidth your account can use in a
|
||||||
30 day window. When this limit is reached hotlinking will be disabled
|
30 day window. When this limit is reached hotlinking will be disabled
|
||||||
|
Reference in New Issue
Block a user