Upgrade dependencies and try to silence some accessibility warnings
This commit is contained in:
@@ -3,6 +3,7 @@ import { onDestroy, onMount } from "svelte";
|
||||
import { formatDataVolume, formatThousands, formatDate, formatNumber, formatDuration } from "../util/Formatting.svelte";
|
||||
import Chart from "../util/Chart.svelte";
|
||||
import { color_by_name } from "../util/Util.svelte";
|
||||
import ServerDiagnostics from "./ServerDiagnostics.svelte";
|
||||
|
||||
let graphViews
|
||||
let graphBandwidth
|
||||
@@ -63,23 +64,24 @@ const loadGraph = (minutes, interval, live) => {
|
||||
|
||||
let lastOrder;
|
||||
let status = {
|
||||
db_latency: 0,
|
||||
db_time: "",
|
||||
local_read_size: 0,
|
||||
local_read_size_per_sec: 0,
|
||||
local_reads: 0,
|
||||
local_reads_per_sec: 0,
|
||||
peers: [],
|
||||
query_statistics: [],
|
||||
remote_read_size: 0,
|
||||
remote_read_size_per_sec: 0,
|
||||
remote_reads: 0,
|
||||
remote_reads_per_sec: 0,
|
||||
running_since: "",
|
||||
stats_watcher_listeners: 0,
|
||||
stats_watcher_threads: 0,
|
||||
download_clients: 0,
|
||||
download_connections: 0,
|
||||
cpu_profile_running_since: "",
|
||||
db_latency: 0,
|
||||
db_time: "",
|
||||
local_read_size: 0,
|
||||
local_read_size_per_sec: 0,
|
||||
local_reads: 0,
|
||||
local_reads_per_sec: 0,
|
||||
peers: [],
|
||||
query_statistics: [],
|
||||
remote_read_size: 0,
|
||||
remote_read_size_per_sec: 0,
|
||||
remote_reads: 0,
|
||||
remote_reads_per_sec: 0,
|
||||
running_since: "",
|
||||
stats_watcher_listeners: 0,
|
||||
stats_watcher_threads: 0,
|
||||
download_clients: 0,
|
||||
download_connections: 0,
|
||||
}
|
||||
|
||||
function getStats(order) {
|
||||
@@ -148,7 +150,7 @@ onMount(() => {
|
||||
getStats("calls")
|
||||
statsInterval = setInterval(() => {
|
||||
getStats(lastOrder)
|
||||
}, 20000)
|
||||
}, 10000)
|
||||
})
|
||||
onDestroy(() => {
|
||||
if (graphTimeout !== null) {
|
||||
@@ -183,9 +185,7 @@ onDestroy(() => {
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<a class="button" href="/api/admin/call_stack">Call stack</a>
|
||||
<a class="button" href="/api/admin/heap_profile">Heap profile</a>
|
||||
<a class="button" href="/api/admin/cpu_profile">CPU profile (wait 1 min)</a>
|
||||
<ServerDiagnostics running_since={status.cpu_profile_running_since} on:refresh={() => getStats(lastOrder)}/>
|
||||
<br/>
|
||||
|
||||
<section>
|
||||
@@ -291,10 +291,18 @@ onDestroy(() => {
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('query_name') }}>Query</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('calls') }}>Calls</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('average_duration') }}>Avg dur</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('total_duration') }}>Total dur</td>
|
||||
<td>
|
||||
<button on:click={() => { getStats('query_name') }}>Query</button>
|
||||
</td>
|
||||
<td>
|
||||
<button style="cursor: pointer;" on:click={() => { getStats('calls') }}>Calls</button>
|
||||
</td>
|
||||
<td>
|
||||
<button style="cursor: pointer;" on:click={() => { getStats('average_duration') }}>Avg dur</button>
|
||||
</td>
|
||||
<td>
|
||||
<button style="cursor: pointer;" on:click={() => { getStats('total_duration') }}>Total dur</button>
|
||||
</td>
|
||||
<td>Callers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
52
svelte/src/admin_panel/ServerDiagnostics.svelte
Normal file
52
svelte/src/admin_panel/ServerDiagnostics.svelte
Normal file
@@ -0,0 +1,52 @@
|
||||
<script>
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { formatDuration } from "../util/Formatting.svelte";
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let running_since = ""
|
||||
|
||||
$: profile_running = running_since != "0001-01-01T00:00:00Z" && running_since != ""
|
||||
|
||||
const start = async () => {
|
||||
if (!profile_running) {
|
||||
const resp = await fetch(
|
||||
window.api_endpoint+"/admin/cpu_profile",
|
||||
{ method: "POST" }
|
||||
);
|
||||
if(resp.status >= 400) {
|
||||
throw new Error(await resp.text());
|
||||
}
|
||||
} else {
|
||||
window.open(window.api_endpoint+"/admin/cpu_profile")
|
||||
}
|
||||
|
||||
dispatch("refresh")
|
||||
}
|
||||
|
||||
let interval
|
||||
let running_time = "0s"
|
||||
onMount(() => {
|
||||
interval = setInterval(() => {
|
||||
if (profile_running) {
|
||||
running_time = formatDuration(
|
||||
(new Date()).getTime() - Date.parse(running_since),
|
||||
)
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
return () => {
|
||||
clearInterval(interval)
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<a class="button" href="/api/admin/call_stack">Call stack</a>
|
||||
<a class="button" href="/api/admin/heap_profile">Heap profile</a>
|
||||
<button on:click={start} class:button_red={profile_running}>
|
||||
{#if profile_running}
|
||||
Stop CPU profiling (running for {running_time})
|
||||
{:else}
|
||||
Start CPU profiling
|
||||
{/if}
|
||||
</button>
|
@@ -15,14 +15,11 @@ onMount(() => {
|
||||
}
|
||||
|
||||
// 10% pixeldrain socials
|
||||
// 45% nextmillennium
|
||||
// 45% pixfuture
|
||||
// 90% pixfuture
|
||||
|
||||
let rand = Math.random()
|
||||
if (rand < 0.1) {
|
||||
set_ad_type("pixeldrain_social")
|
||||
} else if (rand < 0.55) {
|
||||
set_ad_type("nextmillennium")
|
||||
} else {
|
||||
set_ad_type("pixfuture")
|
||||
}
|
||||
|
@@ -139,10 +139,21 @@ const drop = (e, index) => {
|
||||
class:wide={file_type(file) === "image" || file_type(file) === "video"}
|
||||
style="background-image: url('{file.icon_href}?width=256&height=256');">
|
||||
{#if list.can_edit}
|
||||
<i class="icon" on:click|stopPropagation|preventDefault style="cursor: grab;">drag_indicator</i>
|
||||
<i class="icon" on:click|stopPropagation|preventDefault={() => {move_left(index)}}>chevron_left</i>
|
||||
<i class="icon" on:click|stopPropagation|preventDefault={() => {move_right(index)}}>chevron_right</i>
|
||||
<i class="icon" on:click|stopPropagation|preventDefault={() => {delete_file(index)}}>delete</i>
|
||||
<div class="button_row">
|
||||
<i class="icon" style="cursor: grab;">
|
||||
drag_indicator
|
||||
</i>
|
||||
<div class="separator"></div>
|
||||
<button class="icon" on:click|stopPropagation|preventDefault={() => {move_left(index)}}>
|
||||
chevron_left
|
||||
</button>
|
||||
<button class="icon" on:click|stopPropagation|preventDefault={() => {move_right(index)}}>
|
||||
chevron_right
|
||||
</button>
|
||||
<button class="icon" on:click|stopPropagation|preventDefault={() => {delete_file(index)}}>
|
||||
delete
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{file.name}
|
||||
@@ -150,15 +161,20 @@ const drop = (e, index) => {
|
||||
{/each}
|
||||
|
||||
{#if list.can_edit}
|
||||
<div class="file" on:click={file_picker.open} style="font-size: 1.5em; padding-top: 2.5em; cursor: pointer;">
|
||||
<button class="file" on:click={file_picker.open} style="font-size: 1.5em; cursor: pointer;">
|
||||
<i class="icon">add</i>
|
||||
<br/>
|
||||
Add files
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<FilePicker bind:this={file_picker} on:files={e => {add_files(e.detail)}} multi_select={true} title="Select files to add to album"></FilePicker>
|
||||
<FilePicker
|
||||
bind:this={file_picker}
|
||||
on:files={e => {add_files(e.detail)}}
|
||||
multi_select={true}
|
||||
title="Select files to add to album">
|
||||
</FilePicker>
|
||||
|
||||
<style>
|
||||
.gallery{
|
||||
@@ -185,14 +201,14 @@ const drop = (e, index) => {
|
||||
text-decoration: none;
|
||||
vertical-align: top;
|
||||
color: var(--body_text_color);
|
||||
transition: background 0.2s;
|
||||
transition: background 0.2s, padding 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.file:hover {
|
||||
background: var(--input_hover_background);
|
||||
}
|
||||
|
||||
.highlight {
|
||||
box-shadow: 0 0 2px 2px var(--highlight_color);
|
||||
box-shadow: 0 0 0px 2px var(--highlight_color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.icon_container {
|
||||
@@ -208,14 +224,22 @@ const drop = (e, index) => {
|
||||
.icon_container.editing {
|
||||
box-shadow: inset 0 60px 40px -20px var(--body_color);
|
||||
}
|
||||
.icon_container > .icon {
|
||||
color: var(--body_text_color);
|
||||
}
|
||||
.icon_container > .icon:hover {
|
||||
color: var(--highlight_color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon_container.wide {
|
||||
background-size: cover;
|
||||
}
|
||||
.button_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.button_row > .icon {
|
||||
flex: 0 0 auto;
|
||||
color: var(--body_text_color);
|
||||
}
|
||||
.button_row > button {
|
||||
flex: 0 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
.button_row>.separator {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
</style>
|
||||
|
@@ -295,7 +295,7 @@ const share = () => {
|
||||
</div>
|
||||
<div class="list_navigator"></div>
|
||||
<div class="file_viewer_window">
|
||||
<div class="toolbar" class:toolbar_visible><div><div>
|
||||
<div class="toolbar" class:toolbar_visible>
|
||||
{#if state.base.type === "file"}
|
||||
<div class="toolbar_label">Size</div>
|
||||
<div class="toolbar_statistic">{formatDataVolume(state.base.file_size, 3)}</div>
|
||||
@@ -308,6 +308,8 @@ const share = () => {
|
||||
<div class="toolbar_statistic">{formatDataVolume(total_file_size, 3)}</div>
|
||||
{/if}
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div class="button_row">
|
||||
<button on:click={() => {open_sibling(-1)}}>
|
||||
<i class="icon">skip_previous</i>
|
||||
@@ -340,7 +342,7 @@ const share = () => {
|
||||
<button id="btn_edit" class="toolbar_button" style="display: none;">
|
||||
<i class="icon">edit</i> <u>E</u>dit
|
||||
</button>
|
||||
</div></div></div>
|
||||
</div>
|
||||
<Sharebar bind:this={sharebar}></Sharebar>
|
||||
|
||||
<div class="file_viewer_file_preview checkers" class:toolbar_visible>
|
||||
@@ -482,7 +484,6 @@ const share = () => {
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
border-radius: 16px;
|
||||
display: inline-block;
|
||||
min-height: 100px;
|
||||
min-width: 100px;
|
||||
@@ -490,7 +491,8 @@ const share = () => {
|
||||
vertical-align: middle;
|
||||
transition: left 0.5s;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 0 3px -1px var(--shadow_color);
|
||||
border-radius: 12px;
|
||||
border: 2px solid var(--separator);
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
@@ -510,23 +512,11 @@ const share = () => {
|
||||
.toolbar.toolbar_visible { left: 0; }
|
||||
.file_viewer > .file_viewer_window > .file_viewer_file_preview.toolbar_visible { left: 8em; }
|
||||
|
||||
/* Workaround to hide the scrollbar in non webkit browsers, it's really ugly' */
|
||||
.toolbar > div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: -30px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.toolbar > div > div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 8em;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
.toolbar > .separator {
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
margin: 4px 0;
|
||||
background-color: var(--separator);
|
||||
}
|
||||
.toolbar_button {
|
||||
text-align: left;
|
||||
|
@@ -230,7 +230,8 @@ const paste = (e) => {
|
||||
margin: 6px 0 0 0;
|
||||
padding: 0;
|
||||
background: var(--body_color);
|
||||
box-shadow: 1px 1px 4px -1px var(--shadow_color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.upload_progress_bar {
|
||||
|
@@ -66,15 +66,12 @@ const node_icon = node => {
|
||||
justify-content: center;
|
||||
}
|
||||
.file{
|
||||
position: relative;
|
||||
width: 200px;
|
||||
max-width: 45%;
|
||||
max-width: 42%;
|
||||
height: 200px;
|
||||
margin: 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
box-shadow: 1px 1px 3px -1px var(--shadow_color);
|
||||
background: var(--input_background);
|
||||
word-break: break-all;
|
||||
text-align: center;
|
||||
@@ -94,8 +91,9 @@ const node_icon = node => {
|
||||
text-decoration: none;
|
||||
}
|
||||
.icon_container {
|
||||
width: 100%;
|
||||
height: 116px;
|
||||
margin: 3px;
|
||||
height: 148px;
|
||||
border-radius: 6px;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
|
@@ -77,7 +77,6 @@ const node_icon = node => {
|
||||
margin: 8px auto 16px auto;
|
||||
text-align: left;
|
||||
background: var(--body_color);
|
||||
box-shadow: 1px 1px 6px var(--shadow_color);
|
||||
border-collapse: collapse;
|
||||
border-radius: 8px;
|
||||
|
||||
|
@@ -62,20 +62,6 @@ onMount(() => {
|
||||
free plan will apply
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label">
|
||||
Download speed
|
||||
</div>
|
||||
<div class="feat_normal">
|
||||
Bandwidth is fairly distributed across free users, may be slow
|
||||
during busy periods
|
||||
</div>
|
||||
<div class="feat_pro">
|
||||
<span class="text_highlight">High priority</span>
|
||||
bandwidth for files you download and files you share from your
|
||||
account
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label">
|
||||
Hotlinking / embedding files
|
||||
|
@@ -20,25 +20,24 @@ import UploadWidget from "./UploadWidget.svelte";
|
||||
<section>
|
||||
<p>
|
||||
Pixeldrain is a file sharing website built for speed and ease of
|
||||
use. You can upload files you want to share online to our
|
||||
servers and we will hold on to them for at least a month. During
|
||||
this time anyone with the link will be able to download your
|
||||
files. Pixeldrain is built to be as fast as possible, so you
|
||||
don't have to do any unnecessary waiting when downloading files.
|
||||
use. You can upload files you want to share online to our servers
|
||||
and we will hold on to them for at least two months. During this
|
||||
time anyone with the link will be able to download your files.
|
||||
Pixeldrain is built to be as fast as possible, so you don't have to
|
||||
do any unnecessary waiting when downloading files.
|
||||
</p>
|
||||
<p>
|
||||
Files can be uploaded by clicking the big green upload
|
||||
button, or by dragging them onto this page from your file
|
||||
manager.
|
||||
Files can be uploaded by clicking the big green upload button, or by
|
||||
dragging them onto this page from your file manager.
|
||||
</p>
|
||||
<h2>Accounts</h2>
|
||||
<p>
|
||||
An account is not required to use pixeldrain, but it enables some useful
|
||||
features. With a pixeldrain account you can access your files and albums
|
||||
on all your devices. You can also rename and delete files you have
|
||||
uploaded. And create and reorder albums you have created. Sign up for a
|
||||
pixeldrain account on <a href="/register">the registration page</a>.
|
||||
More about pixeldrain's features below.
|
||||
An account is not required to use pixeldrain, but it enables some
|
||||
useful features. With a pixeldrain account you can access your files
|
||||
and albums on all your devices. You can also rename and delete files
|
||||
you have uploaded. And create and reorder albums you have created.
|
||||
Sign up for a pixeldrain account on <a href="/register">the
|
||||
registration page</a>. More about pixeldrain's features below.
|
||||
</p>
|
||||
</section>
|
||||
<header>
|
||||
@@ -46,11 +45,11 @@ import UploadWidget from "./UploadWidget.svelte";
|
||||
</header>
|
||||
<section>
|
||||
<p>
|
||||
By purchasing a subscription you support pixeldrain on its mission to
|
||||
make content sharing easier, safer and faster for everyone. The standard
|
||||
subscription plans use Patreon for payment processing. Check out our <a
|
||||
href="#prepaid">prepaid plans</a> if you are interested in more
|
||||
professional services.
|
||||
By purchasing a subscription you support pixeldrain on its mission
|
||||
to make content sharing easier, safer and faster for everyone. The
|
||||
standard subscription plans use Patreon for payment processing.
|
||||
Check out our <a href="#prepaid">prepaid plans</a> if you are
|
||||
interested in more professional services.
|
||||
</p>
|
||||
<br/>
|
||||
<FeatureTable></FeatureTable>
|
||||
|
@@ -302,7 +302,11 @@ const node_click = (index) => {
|
||||
<div id="directory_element">
|
||||
<div bind:this={directorySorters} id="sorters" class="directory_sorters">
|
||||
{#each tableColumns as col}
|
||||
<div on:click={sortBy(col.field)} style="min-width: {col.width}">{col.name}</div>
|
||||
<!-- <div style="min-width: {col.width}"> -->
|
||||
<button style="min-width: {col.width}" on:click={sortBy(col.field)} class="sorter_button">
|
||||
{col.name}
|
||||
</button>
|
||||
<!-- </div> -->
|
||||
{/each}
|
||||
</div>
|
||||
<div bind:this={directoryArea} on:scroll={onScroll} id="directory_area" class="directory_area">
|
||||
@@ -356,13 +360,16 @@ const node_click = (index) => {
|
||||
background: var(--body_background);
|
||||
min-width: 850px;
|
||||
border-top-left-radius: 16px;
|
||||
border-bottom: 1px solid var(--separator);
|
||||
}
|
||||
#sorters > div {
|
||||
.sorter_button {
|
||||
display: inline-block;
|
||||
margin: 4px 10px;
|
||||
padding: 4px;
|
||||
border-bottom: 1px solid var(--separator);
|
||||
cursor: pointer;
|
||||
text-align: initial;
|
||||
background: none;
|
||||
}
|
||||
.sorter_button:hover {
|
||||
background: var(--input_hover_background);
|
||||
}
|
||||
|
||||
#sorters > :first-child,
|
||||
@@ -405,7 +412,7 @@ const node_click = (index) => {
|
||||
|
||||
/* I use padding instead of margin here because it goves me more precise
|
||||
control over the size.
|
||||
Check out https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing*/
|
||||
Check out https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing */
|
||||
margin: 0;
|
||||
color: var(--body_text_color);
|
||||
text-decoration: none;
|
||||
|
Reference in New Issue
Block a user