Add thead and tbody to every table for svelte 5 compatibility

This commit is contained in:
2024-11-06 19:12:52 +01:00
parent a6880b528a
commit 83ec1fc516
17 changed files with 1452 additions and 1639 deletions

1852
svelte/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,25 +7,25 @@
"dev": "rollup -c -w"
},
"devDependencies": {
"@babel/core": "^7.22.20",
"@babel/preset-env": "^7.22.20",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^26.0.0",
"@rollup/plugin-node-resolve": "^15.2.1",
"@rollup/plugin-terser": "^0.4.3",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^26.0.3",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/jsmediatags": "^3.9.3",
"rollup": "^4.0.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.1.6",
"svelte": "^4.2.0"
"@types/jsmediatags": "^3.9.6",
"rollup": "^4.24.4",
"rollup-plugin-livereload": "^2.0.5",
"rollup-plugin-svelte": "^7.2.2",
"svelte": "^4.2.19"
},
"dependencies": {
"behave-js": "^1.5.0",
"chart.js": "^4.2.0",
"chart.js": "^4.4.6",
"pure-color": "^1.3.0",
"rollup-plugin-includepaths": "^0.2.4",
"svelte-preprocess": "^6.0.2",
"tslib": "^2.7.0"
"svelte-preprocess": "^6.0.3",
"tslib": "^2.8.1"
}
}

View File

@@ -82,42 +82,46 @@ let set_status = async (action, report_type) => {
</div>
<div class="table_scroll">
<table>
<tr>
<td>Time</td>
<td>IP</td>
<td>Type</td>
<td>Status</td>
<td colspan="2">Reports from this IP</td>
</tr>
{#each report.reports as user_report}
<thead>
<tr>
<td>{formatDate(user_report.time, true, true, false)}</td>
<td>{user_report.ip_address}</td>
<td>{user_report.type}</td>
<td>{user_report.status}</td>
<td>{ip_report_count[user_report.ip_address]}</td>
<td>
{#if can_grant}
<button on:click={() => dispatch("resolve_by_ip", {ip: user_report.ip_address, action: "grant"})}>
Accept all
</button>
{/if}
{#if can_reject}
<button on:click={() => dispatch("resolve_by_ip", {ip: user_report.ip_address, action: "reject"})}>
Ignore all
</button>
{/if}
</td>
<td>Time</td>
<td>IP</td>
<td>Type</td>
<td>Status</td>
<td colspan="2">Reports from this IP</td>
</tr>
{#if user_report.description !== ""}
</thead>
<tbody>
{#each report.reports as user_report}
<tr>
<td>Description</td>
<td colspan="5" style="white-space: pre-wrap; word-wrap: break-word;">
{user_report.description}
<td>{formatDate(user_report.time, true, true, false)}</td>
<td>{user_report.ip_address}</td>
<td>{user_report.type}</td>
<td>{user_report.status}</td>
<td>{ip_report_count[user_report.ip_address]}</td>
<td>
{#if can_grant}
<button on:click={() => dispatch("resolve_by_ip", {ip: user_report.ip_address, action: "grant"})}>
Accept all
</button>
{/if}
{#if can_reject}
<button on:click={() => dispatch("resolve_by_ip", {ip: user_report.ip_address, action: "reject"})}>
Ignore all
</button>
{/if}
</td>
</tr>
{/if}
{/each}
{#if user_report.description !== ""}
<tr>
<td>Description</td>
<td colspan="5" style="white-space: pre-wrap; word-wrap: break-word;">
{user_report.description}
</td>
</tr>
{/if}
{/each}
</tbody>
</table>
</div>
</div>

View File

@@ -54,46 +54,50 @@ const toggle_preview = (rep) => {
<div class="table_scroll">
<table>
<tr>
<td><SortButton field="from_address" active_field={sort_field} asc={asc} sort_func={sort}>Address</SortButton></td>
<td><SortButton field="name" active_field={sort_field} asc={asc} sort_func={sort}>Name</SortButton></td>
<td><SortButton field="reports_sent" active_field={sort_field} asc={asc} sort_func={sort}>Reports</SortButton></td>
<td><SortButton field="files_blocked" active_field={sort_field} asc={asc} sort_func={sort}>Blocked</SortButton></td>
<td><SortButton field="last_used" active_field={sort_field} asc={asc} sort_func={sort}>Last used</SortButton></td>
<td><SortButton field="created" active_field={sort_field} asc={asc} sort_func={sort}>Created</SortButton></td>
<td></td>
</tr>
{#each reporters as rep (rep.from_address)}
<tr animate:flip={{duration: 500}}>
<td>{rep.from_address}</td>
<td>{rep.name}</td>
<td>{rep.reports_sent}</td>
<td>{rep.files_blocked}</td>
<td>{formatDate(rep.last_used, true, true, false)}</td>
<td>{formatDate(rep.created, false, false, false)}</td>
<td>
<button on:click|preventDefault={() => toggle_preview(rep)} class="button round">
<i class="icon">email</i>
</button>
<button on:click|preventDefault={() => {dispatch("edit", rep)}} class="button round">
<i class="icon">edit</i>
</button>
{#if rep.status !== "trusted"}
<button on:click|preventDefault={() => {dispatch("approve", rep)}} class="button button_highlight round">
<i class="icon">check</i>
</button>
{/if}
{#if rep.status !== "rejected"}
<button on:click|preventDefault={() => {dispatch("spam", rep)}} class="button button_red round">
<i class="icon">block</i>
</button>
{/if}
<button on:click|preventDefault={() => {dispatch("delete", rep)}} class="button button_red round">
<i class="icon">delete</i>
</button>
</td>
<thead>
<tr>
<td><SortButton field="from_address" active_field={sort_field} asc={asc} sort_func={sort}>Address</SortButton></td>
<td><SortButton field="name" active_field={sort_field} asc={asc} sort_func={sort}>Name</SortButton></td>
<td><SortButton field="reports_sent" active_field={sort_field} asc={asc} sort_func={sort}>Reports</SortButton></td>
<td><SortButton field="files_blocked" active_field={sort_field} asc={asc} sort_func={sort}>Blocked</SortButton></td>
<td><SortButton field="last_used" active_field={sort_field} asc={asc} sort_func={sort}>Last used</SortButton></td>
<td><SortButton field="created" active_field={sort_field} asc={asc} sort_func={sort}>Created</SortButton></td>
<td></td>
</tr>
{/each}
</thead>
<tbody>
{#each reporters as rep (rep.from_address)}
<tr animate:flip={{duration: 500}}>
<td>{rep.from_address}</td>
<td>{rep.name}</td>
<td>{rep.reports_sent}</td>
<td>{rep.files_blocked}</td>
<td>{formatDate(rep.last_used, true, true, false)}</td>
<td>{formatDate(rep.created, false, false, false)}</td>
<td>
<button on:click|preventDefault={() => toggle_preview(rep)} class="button round">
<i class="icon">email</i>
</button>
<button on:click|preventDefault={() => {dispatch("edit", rep)}} class="button round">
<i class="icon">edit</i>
</button>
{#if rep.status !== "trusted"}
<button on:click|preventDefault={() => {dispatch("approve", rep)}} class="button button_highlight round">
<i class="icon">check</i>
</button>
{/if}
{#if rep.status !== "rejected"}
<button on:click|preventDefault={() => {dispatch("spam", rep)}} class="button button_red round">
<i class="icon">block</i>
</button>
{/if}
<button on:click|preventDefault={() => {dispatch("delete", rep)}} class="button button_red round">
<i class="icon">delete</i>
</button>
</td>
</tr>
{/each}
</tbody>
</table>
</div>

View File

@@ -209,14 +209,16 @@ onDestroy(() => {
<section>
<h3>Process stats</h3>
<table>
<tr>
<td>DB Time</td>
<td>{formatDate(new Date(status.db_time), true, true, true)}</td>
<td>DB Latency</td>
<td>{formatNumber(status.db_latency / 1000, 3)} ms</td>
<td>PID</td>
<td>{status.pid}</td>
</tr>
<tbody>
<tr>
<td>DB Time</td>
<td>{formatDate(new Date(status.db_time), true, true, true)}</td>
<td>DB Latency</td>
<td>{formatNumber(status.db_latency / 1000, 3)} ms</td>
<td>PID</td>
<td>{status.pid}</td>
</tr>
</tbody>
</table>
<h3>Pixelstore stats</h3>

View File

@@ -157,28 +157,32 @@ onMount(get_bans);
</div>
<div class="table_scroll">
<table>
<tr>
<td>Reason</td>
<td>Reporter</td>
<td>Ban time</td>
<td>Expire time</td>
<td>File</td>
</tr>
{#each row.offences as offence (offence.ban_time)}
<thead>
<tr>
<td>{offence.reason}</td>
<td>{offence.reporter}</td>
<td>{formatDate(offence.ban_time, true, true, false)}</td>
<td>{formatDate(offence.expire_time, true, true, false)}</td>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
<td>Reason</td>
<td>Reporter</td>
<td>Ban time</td>
<td>Expire time</td>
<td>File</td>
</tr>
{/each}
</thead>
<tbody>
{#each row.offences as offence (offence.ban_time)}
<tr>
<td>{offence.reason}</td>
<td>{offence.reporter}</td>
<td>{formatDate(offence.ban_time, true, true, false)}</td>
<td>{formatDate(offence.expire_time, true, true, false)}</td>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
</Expandable>

View File

@@ -71,30 +71,34 @@ onMount(get_payments);
{#if per_country.NL}
<table>
<tr>
<td>Bedrag</td>
<td>BTW-code</td>
<td>BTW</td>
<td>Tegenrekening</td>
</tr>
<tr>
<td><Euro amount={per_country.NL.amount + per_country.NL.vat}/></td>
<td>BTW hoog 21%</td>
<td><Euro amount={per_country.NL.vat}/></td>
<td>8030 - Omzet Mollie inkomsten</td>
</tr>
<tr>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>1651 - BTW OSS</td>
</tr>
<tr>
<td><Euro amount={(settlement.amount.value*1e6)-totals.vat-per_country.NL.amount}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>8030 - Omzet Mollie inkomsten</td>
</tr>
<thead>
<tr>
<td>Bedrag</td>
<td>BTW-code</td>
<td>BTW</td>
<td>Tegenrekening</td>
</tr>
</thead>
<tbody>
<tr>
<td><Euro amount={per_country.NL.amount + per_country.NL.vat}/></td>
<td>BTW hoog 21%</td>
<td><Euro amount={per_country.NL.vat}/></td>
<td>8030 - Omzet Mollie inkomsten</td>
</tr>
<tr>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>1651 - BTW OSS</td>
</tr>
<tr>
<td><Euro amount={(settlement.amount.value*1e6)-totals.vat-per_country.NL.amount}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>8030 - Omzet Mollie inkomsten</td>
</tr>
</tbody>
</table>
{/if}
@@ -103,68 +107,76 @@ onMount(get_payments);
<div class="table_scroll">
<table>
<tr>
<td>Country</td>
<td>Payments</td>
<td>Amount</td>
<td>VAT</td>
<td>VAT%</td>
<td>Total</td>
</tr>
{#each Object.entries(per_country) as [country, row]}
<thead>
<tr>
<td>{country}</td>
<td>{row.count}</td>
<td><Euro amount={row.amount}/></td>
<td><Euro amount={row.vat}/></td>
<td>{row.vat_fraction*100}%</td>
<td><Euro amount={row.vat+row.amount}/></td>
<td>Country</td>
<td>Payments</td>
<td>Amount</td>
<td>VAT</td>
<td>VAT%</td>
<td>Total</td>
</tr>
{/each}
</thead>
<tbody>
{#each Object.entries(per_country) as [country, row]}
<tr>
<td>{country}</td>
<td>{row.count}</td>
<td><Euro amount={row.amount}/></td>
<td><Euro amount={row.vat}/></td>
<td>{row.vat_fraction*100}%</td>
<td><Euro amount={row.vat+row.amount}/></td>
</tr>
{/each}
<tr>
<td>Total</td>
<td>{totals.count}</td>
<td><Euro amount={totals.amount}/></td>
<td><Euro amount={totals.vat}/></td>
<td></td>
<td><Euro amount={totals.vat+totals.amount}/></td>
</tr>
{#if per_country.NL}
<tr>
<td>Total - NL</td>
<td>{totals.count - per_country.NL.count}</td>
<td><Euro amount={totals.amount-per_country.NL.amount}/></td>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td>Total</td>
<td>{totals.count}</td>
<td><Euro amount={totals.amount}/></td>
<td><Euro amount={totals.vat}/></td>
<td></td>
<td><Euro amount={(totals.vat-per_country.NL.vat)+(totals.amount-per_country.NL.amount)}/></td>
<td><Euro amount={totals.vat+totals.amount}/></td>
</tr>
{/if}
{#if per_country.NL}
<tr>
<td>Total - NL</td>
<td>{totals.count - per_country.NL.count}</td>
<td><Euro amount={totals.amount-per_country.NL.amount}/></td>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td></td>
<td><Euro amount={(totals.vat-per_country.NL.vat)+(totals.amount-per_country.NL.amount)}/></td>
</tr>
{/if}
</tbody>
</table>
</div>
<h3>All payments ({payments.length})</h3>
<div class="table_scroll">
<table>
<tr>
<td>ID</td>
<td>Created</td>
<td>Status</td>
<td>Country</td>
<td>Amount</td>
<td>VAT</td>
<td>Total</td>
</tr>
{#each payments as row (row.id)}
<thead>
<tr>
<td><a href={row._links.dashboard.href} target="_blank">{row.id}</a></td>
<td>{formatDate(row.createdAt, true, true, false)}</td>
<td>{row.status}</td>
<td>{row.metadata.country}</td>
<td><Euro amount={row.metadata.amount}/></td>
<td><Euro amount={row.metadata.vat}/></td>
<td><Euro amount={row.amount.value*1e6}/></td>
<td>ID</td>
<td>Created</td>
<td>Status</td>
<td>Country</td>
<td>Amount</td>
<td>VAT</td>
<td>Total</td>
</tr>
{/each}
</thead>
<tbody>
{#each payments as row (row.id)}
<tr>
<td><a href={row._links.dashboard.href} target="_blank">{row.id}</a></td>
<td>{formatDate(row.createdAt, true, true, false)}</td>
<td>{row.status}</td>
<td>{row.metadata.country}</td>
<td><Euro amount={row.metadata.amount}/></td>
<td><Euro amount={row.metadata.vat}/></td>
<td><Euro amount={row.amount.value*1e6}/></td>
</tr>
{/each}
</tbody>
</table>
</div>

View File

@@ -140,30 +140,34 @@ onMount(() => {
{#if per_country.NL}
<h2>Accounting information</h2>
<table>
<tr>
<td>Bedrag</td>
<td>BTW-code</td>
<td>BTW</td>
<td>Tegenrekening</td>
</tr>
<tr>
<td><Euro amount={per_country.NL.amount + per_country.NL.vat}/></td>
<td>BTW hoog 21%</td>
<td><Euro amount={per_country.NL.vat}/></td>
<td>8040 - Omzet PayPal inkomsten</td>
</tr>
<tr>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>1651 - BTW OSS</td>
</tr>
<tr>
<td><Euro amount={totals.amount-totals.fee-per_country.NL.amount}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>8040 - Omzet PayPal inkomsten</td>
</tr>
<thead>
<tr>
<td>Bedrag</td>
<td>BTW-code</td>
<td>BTW</td>
<td>Tegenrekening</td>
</tr>
</thead>
<tbody>
<tr>
<td><Euro amount={per_country.NL.amount + per_country.NL.vat}/></td>
<td>BTW hoog 21%</td>
<td><Euro amount={per_country.NL.vat}/></td>
<td>8040 - Omzet PayPal inkomsten</td>
</tr>
<tr>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>1651 - BTW OSS</td>
</tr>
<tr>
<td><Euro amount={totals.amount-totals.fee-per_country.NL.amount}/></td>
<td>Geen BTW</td>
<td><Euro amount={0}/></td>
<td>8040 - Omzet PayPal inkomsten</td>
</tr>
</tbody>
</table>
{/if}
@@ -171,51 +175,55 @@ onMount(() => {
<div class="table_scroll">
<table>
<tr>
<td>Country</td>
<td>Payments</td>
<td>Amount</td>
<td>VAT</td>
<td>VAT%</td>
<td>Total</td>
<td>Fee</td>
<td>Total</td>
</tr>
{#each Object.entries(per_country) as [country, row]}
<thead>
<tr>
<td>{country}</td>
<td>{row.count}</td>
<td><Euro amount={row.amount}/></td>
<td><Euro amount={row.vat}/></td>
<td>{row.vat_fraction*100}%</td>
<td><Euro amount={row.vat+row.amount}/></td>
<td><Euro amount={-row.fee}/></td>
<td><Euro amount={row.vat+row.amount-row.fee}/></td>
<td>Country</td>
<td>Payments</td>
<td>Amount</td>
<td>VAT</td>
<td>VAT%</td>
<td>Total</td>
<td>Fee</td>
<td>Total</td>
</tr>
{/each}
</thead>
<tbody>
{#each Object.entries(per_country) as [country, row]}
<tr>
<td>{country}</td>
<td>{row.count}</td>
<td><Euro amount={row.amount}/></td>
<td><Euro amount={row.vat}/></td>
<td>{row.vat_fraction*100}%</td>
<td><Euro amount={row.vat+row.amount}/></td>
<td><Euro amount={-row.fee}/></td>
<td><Euro amount={row.vat+row.amount-row.fee}/></td>
</tr>
{/each}
<tr>
<td>Total</td>
<td>{totals.count}</td>
<td><Euro amount={totals.amount}/></td>
<td><Euro amount={totals.vat}/></td>
<td></td>
<td><Euro amount={totals.vat+totals.amount}/></td>
<td><Euro amount={-totals.fee}/></td>
<td><Euro amount={(totals.vat+totals.amount)-totals.fee}/></td>
</tr>
{#if per_country.NL}
<tr>
<td>Total ex NL</td>
<td>{totals.count - per_country.NL.count}</td>
<td><Euro amount={totals.amount-per_country.NL.amount}/></td>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td>Total</td>
<td>{totals.count}</td>
<td><Euro amount={totals.amount}/></td>
<td><Euro amount={totals.vat}/></td>
<td></td>
<td><Euro amount={(totals.vat-per_country.NL.vat)+(totals.amount-per_country.NL.amount)}/></td>
<td><Euro amount={-(totals.fee-per_country.NL.fee)}/></td>
<td><Euro amount={(totals.vat-per_country.NL.vat)+(totals.amount-per_country.NL.amount)-(totals.fee-per_country.NL.fee)}/></td>
<td><Euro amount={totals.vat+totals.amount}/></td>
<td><Euro amount={-totals.fee}/></td>
<td><Euro amount={(totals.vat+totals.amount)-totals.fee}/></td>
</tr>
{/if}
{#if per_country.NL}
<tr>
<td>Total ex NL</td>
<td>{totals.count - per_country.NL.count}</td>
<td><Euro amount={totals.amount-per_country.NL.amount}/></td>
<td><Euro amount={totals.vat-per_country.NL.vat}/></td>
<td></td>
<td><Euro amount={(totals.vat-per_country.NL.vat)+(totals.amount-per_country.NL.amount)}/></td>
<td><Euro amount={-(totals.fee-per_country.NL.fee)}/></td>
<td><Euro amount={(totals.vat-per_country.NL.vat)+(totals.amount-per_country.NL.amount)-(totals.fee-per_country.NL.fee)}/></td>
</tr>
{/if}
</tbody>
</table>
</div>

View File

@@ -6,59 +6,65 @@ export let row = {}
</script>
<table>
<tr>
<td>Username</td>
<td>{row.user.username}</td>
</tr>
<tr>
<td>ID</td>
<td>{row.user_id}</td>
</tr>
<tr>
<td>Email</td>
<td>{row.user.email}</td>
</tr>
<tr>
<td>Subscription</td>
<td>{row.user.subscription.name}</td>
</tr>
<tr>
<td>Credit balance</td>
<td><Euro amount={row.user.balance_micro_eur}/></td>
</tr>
<tr>
<td>Storage used</td>
<td>{formatDataVolume(row.user.storage_space_used, 3)}</td>
</tr>
<tr>
<td>FS Storage used</td>
<td>{formatDataVolume(row.user.filesystem_storage_used, 3)}</td>
</tr>
<tbody>
<tr>
<td>Username</td>
<td>{row.user.username}</td>
</tr>
<tr>
<td>ID</td>
<td>{row.user_id}</td>
</tr>
<tr>
<td>Email</td>
<td>{row.user.email}</td>
</tr>
<tr>
<td>Subscription</td>
<td>{row.user.subscription.name}</td>
</tr>
<tr>
<td>Credit balance</td>
<td><Euro amount={row.user.balance_micro_eur}/></td>
</tr>
<tr>
<td>Storage used</td>
<td>{formatDataVolume(row.user.storage_space_used, 3)}</td>
</tr>
<tr>
<td>FS Storage used</td>
<td>{formatDataVolume(row.user.filesystem_storage_used, 3)}</td>
</tr>
</tbody>
</table>
<br/>
<div class="table_scroll">
<table>
<tr>
<td>Reason</td>
<td>Reporter</td>
<td>Ban time</td>
<td>Expire time</td>
<td>File</td>
</tr>
{#each row.offences as offence (offence.ban_time)}
<thead>
<tr>
<td>{offence.reason}</td>
<td>{offence.reporter}</td>
<td>{formatDate(offence.ban_time, true, true, false)}</td>
<td>{formatDate(offence.expire_time, true, true, false)}</td>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
<td>Reason</td>
<td>Reporter</td>
<td>Ban time</td>
<td>Expire time</td>
<td>File</td>
</tr>
{/each}
</thead>
<tbody>
{#each row.offences as offence (offence.ban_time)}
<tr>
<td>{offence.reason}</td>
<td>{offence.reporter}</td>
<td>{formatDate(offence.ban_time, true, true, false)}</td>
<td>{formatDate(offence.expire_time, true, true, false)}</td>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>

View File

@@ -117,81 +117,83 @@ onMount(() => {
<div class="indent">
<table>
<tr>
<td>Name</td>
<td>{file.name}</td>
</tr>
<tr>
<td>URL</td>
<td><a href="/u/{file.id}">{domain_url()}/u/{file.id}</a></td>
</tr>
<tr>
<td>Mime Type</td>
<td>{file.mime_type}</td>
</tr>
<tr>
<td>ID</td>
<td>{file.id}</td>
</tr>
<tr>
<td>Size</td>
<td>{formatDataVolume(file.size, 4)} ( {formatThousands(file.size)} B )</td>
</tr>
<tr>
<td>Free bandwidth used</td>
<td>
{formatDataVolume(file.bandwidth_used, 4)}
( {formatThousands(file.bandwidth_used)} B ),
{(file.bandwidth_used/file.size).toFixed(1)}x file size
</td>
</tr>
<tr>
<td>Premium bandwidth used</td>
<td>
{formatDataVolume(file.bandwidth_used_paid, 4)}
( {formatThousands(file.bandwidth_used_paid)} B ),
{(file.bandwidth_used_paid/file.size).toFixed(1)}x file size
</td>
</tr>
<tr>
<td>
Unique downloads
<button class="button small_button round"
class:button_highlight={download_info}
style="margin: 0;"
on:click={() => download_info = !download_info}
>
<i class="icon">help</i>
</button>
</td>
<td>{formatThousands(file.downloads)}</td>
</tr>
{#if download_info}
<tbody>
<tr>
<td colspan="2">
The unique download counter only counts downloads once per IP
address. So this number shows how many individual people have
attempted to download the file. The download counter on the
toolbar on the other hand shows how many real downloads the file
has had. Real downloads are counted by dividing the total
bandwidth usage by the size of the file.
<td>Name</td>
<td>{file.name}</td>
</tr>
<tr>
<td>URL</td>
<td><a href="/u/{file.id}">{domain_url()}/u/{file.id}</a></td>
</tr>
<tr>
<td>Mime Type</td>
<td>{file.mime_type}</td>
</tr>
<tr>
<td>ID</td>
<td>{file.id}</td>
</tr>
<tr>
<td>Size</td>
<td>{formatDataVolume(file.size, 4)} ( {formatThousands(file.size)} B )</td>
</tr>
<tr>
<td>Free bandwidth used</td>
<td>
{formatDataVolume(file.bandwidth_used, 4)}
( {formatThousands(file.bandwidth_used)} B ),
{(file.bandwidth_used/file.size).toFixed(1)}x file size
</td>
</tr>
{/if}
<tr>
<td>Upload Date</td>
<td>{formatDate(file.date_upload, true, true, true)}</td>
</tr>
{#if file.description}
<tr>
<td>Description</td>
<td>{file.description}</td>
<td>Premium bandwidth used</td>
<td>
{formatDataVolume(file.bandwidth_used_paid, 4)}
( {formatThousands(file.bandwidth_used_paid)} B ),
{(file.bandwidth_used_paid/file.size).toFixed(1)}x file size
</td>
</tr>
{/if}
<tr>
<td>SHA256 hash</td>
<td style="word-break: break-all;">{file.hash_sha256}</td>
</tr>
<tr>
<td>
Unique downloads
<button class="button small_button round"
class:button_highlight={download_info}
style="margin: 0;"
on:click={() => download_info = !download_info}
>
<i class="icon">help</i>
</button>
</td>
<td>{formatThousands(file.downloads)}</td>
</tr>
{#if download_info}
<tr>
<td colspan="2">
The unique download counter only counts downloads once per IP
address. So this number shows how many individual people have
attempted to download the file. The download counter on the
toolbar on the other hand shows how many real downloads the file
has had. Real downloads are counted by dividing the total
bandwidth usage by the size of the file.
</td>
</tr>
{/if}
<tr>
<td>Upload Date</td>
<td>{formatDate(file.date_upload, true, true, true)}</td>
</tr>
{#if file.description}
<tr>
<td>Description</td>
<td>{file.description}</td>
</tr>
{/if}
<tr>
<td>SHA256 hash</td>
<td style="word-break: break-all;">{file.hash_sha256}</td>
</tr>
</tbody>
</table>
<h2>Views and downloads</h2>

View File

@@ -122,78 +122,80 @@ let update_chart = async (base, timespan, interval) => {
<Modal bind:visible={visible} title="Details" width={($nav.base.type === "file" ? 1000 : 750) + "px"}>
<table style="width: 100%;">
<tr>
<td>Name</td>
<td>{$nav.base.name}</td>
</tr>
<tr>
<td>Path</td>
<td>{$nav.base.path}</td>
</tr>
<tr>
<td>Created</td>
<td>{formatDate($nav.base.created, true, true, true)}</td>
</tr>
<tr>
<td>Modified</td>
<td>{formatDate($nav.base.modified, true, true, true)}</td>
</tr>
<tr>
<td>Mode</td>
<td>{$nav.base.mode_string}</td>
</tr>
{#if $nav.base.id}
<tbody>
<tr>
<td>Public ID</td>
<td><a href="/d/{$nav.base.id}">{$nav.base.id}</a></td>
</tr>
{/if}
{#if $nav.base.type === "file"}
<tr>
<td>File type</td>
<td>{$nav.base.file_type}</td>
<td>Name</td>
<td>{$nav.base.name}</td>
</tr>
<tr>
<td>File size</td>
<td>{formatDataVolume($nav.base.file_size, 4)} ( {formatThousands($nav.base.file_size)} B )</td>
<td>Path</td>
<td>{$nav.base.path}</td>
</tr>
<tr>
<td>Downloads</td>
<td>{formatThousands(total_downloads)} (unique, counted once per IP)</td>
<td>Created</td>
<td>{formatDate($nav.base.created, true, true, true)}</td>
</tr>
<tr>
<td>Transfer used</td>
<td>Modified</td>
<td>{formatDate($nav.base.modified, true, true, true)}</td>
</tr>
<tr>
<td>Mode</td>
<td>{$nav.base.mode_string}</td>
</tr>
{#if $nav.base.id}
<tr>
<td>Public ID</td>
<td><a href="/d/{$nav.base.id}">{$nav.base.id}</a></td>
</tr>
{/if}
{#if $nav.base.type === "file"}
<tr>
<td>File type</td>
<td>{$nav.base.file_type}</td>
</tr>
<tr>
<td>File size</td>
<td>{formatDataVolume($nav.base.file_size, 4)} ( {formatThousands($nav.base.file_size)} B )</td>
</tr>
<tr>
<td>Downloads</td>
<td>{formatThousands(total_downloads)} (unique, counted once per IP)</td>
</tr>
<tr>
<td>Transfer used</td>
<td>
{formatDataVolume(total_transfer_paid, 4)}
( {formatThousands(total_transfer_paid)} B ),
{(total_transfer_paid/$nav.base.file_size).toFixed(1)}x file size
</td>
</tr>
<tr><td>SHA256 sum</td><td>{$nav.base.sha256_sum}</td></tr>
{/if}
<tr>
<td>Direct link</td>
<td>
{formatDataVolume(total_transfer_paid, 4)}
( {formatThousands(total_transfer_paid)} B ),
{(total_transfer_paid/$nav.base.file_size).toFixed(1)}x file size
<CopyButton text={direct_url}>Copy</CopyButton>
<a href="{direct_url}">{direct_url}</a>
</td>
</tr>
<tr><td>SHA256 sum</td><td>{$nav.base.sha256_sum}</td></tr>
{/if}
<tr>
<td>Direct link</td>
<td>
<CopyButton text={direct_url}>Copy</CopyButton>
<a href="{direct_url}">{direct_url}</a>
</td>
</tr>
{#if share_url !== ""}
<tr>
<td>Sharing link</td>
<td>
<CopyButton text={share_url}>Copy</CopyButton>
<a href="{share_url}">{share_url}</a>
</td>
</tr>
<tr>
<td>Direct sharing link</td>
<td>
<CopyButton text={direct_share_url}>Copy</CopyButton>
<a href="{direct_share_url}">{direct_share_url}</a>
</td>
</tr>
{/if}
{#if share_url !== ""}
<tr>
<td>Sharing link</td>
<td>
<CopyButton text={share_url}>Copy</CopyButton>
<a href="{share_url}">{share_url}</a>
</td>
</tr>
<tr>
<td>Direct sharing link</td>
<td>
<CopyButton text={direct_share_url}>Copy</CopyButton>
<a href="{direct_share_url}">{direct_share_url}</a>
</td>
</tr>
{/if}
</tbody>
</table>
{#if $nav.base.type === "file"}

View File

@@ -109,36 +109,29 @@ const open_result = index => {
</form>
</div>
<div class="directory center">
<tr>
<td></td>
<td>Name</td>
</tr>
<div class="results center">
{#each search_results as result, index}
<a
href={"/d"+fs_encode_path(result)}
on:click|preventDefault={() => open_result(index)}
class="node"
>
<td>
<img src={fs_thumbnail_url(result, 32, 32)} class="node_icon" alt="icon"/>
</td>
<td class="node_name">
<img src={fs_thumbnail_url(result, 32, 32)} class="node_icon" alt="icon"/>
<span class="node_name">
<!-- Remove the search directory from the result -->
{result.slice($nav.base.path.length+1)}
</td>
</span>
</a>
{/each}
{#if search_results.length === last_limit}
<div class="node">
<td></td>
<td class="node_name">
<div class="node_name" style="text-align: center;">
<button on:click={() => {search(last_limit + 100)}}>
<i class="icon">expand_more</i>
More results
</button>
</td>
</div>
</div>
{/if}
</div>
@@ -164,8 +157,9 @@ const open_result = index => {
flex: 1 1 auto;
}
.directory {
display: table;
.results {
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
margin: 8px auto 16px auto;
@@ -174,17 +168,18 @@ const open_result = index => {
border-collapse: collapse;
border-radius: 8px;
}
.directory > * {
display: table-row;
}
.directory > * > * {
display: table-cell;
.results > * {
display: flex;
flex-direction: row;
}
.node {
display: table-row;
display: flex;
flex-direction: row;
align-items: center;
gap: 6px;
text-decoration: none;
color: var(--text-color);
padding: 6px;
padding: 4px;
}
.node:not(:last-child) {
border-bottom: 1px solid var(--separator);
@@ -194,17 +189,15 @@ const open_result = index => {
color: var(--input_text);
text-decoration: none;
}
td {
padding: 4px;
vertical-align: middle;
}
.node_icon {
flex: 0 0 auto;
height: 32px;
width: 32px;
vertical-align: middle;
border-radius: 4px;
}
.node_name {
flex: 1 1 auto;
width: 100%;
overflow: hidden;
line-height: 1.2em;

View File

@@ -33,26 +33,30 @@ onMount(async () => {
<div class="table_scroll">
<table>
<tr>
<td>File</td>
<td>Reason</td>
<td>Ban date</td>
<td>Expiry date</td>
</tr>
{#each result.user_offences as offence (offence.ban_time)}
<thead>
<tr>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
<td>{offence.reason}</td>
<td>{formatDate(offence.ban_time, false, false, false)}</td>
<td>{formatDate(offence.expire_time, false, false, false)}</td>
<td>File</td>
<td>Reason</td>
<td>Ban date</td>
<td>Expiry date</td>
</tr>
{/each}
</thead>
<tbody>
{#each result.user_offences as offence (offence.ban_time)}
<tr>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
<td>{offence.reason}</td>
<td>{formatDate(offence.ban_time, false, false, false)}</td>
<td>{formatDate(offence.expire_time, false, false, false)}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<p>
@@ -95,26 +99,30 @@ onMount(async () => {
<div class="table_scroll">
<table>
<tr>
<td>File</td>
<td>Reason</td>
<td>Ban date</td>
<td>Expiry date</td>
</tr>
{#each result.ip_offences as offence (offence.ban_time)}
<thead>
<tr>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
<td>{offence.reason}</td>
<td>{formatDate(offence.ban_time, false, false, false)}</td>
<td>{formatDate(offence.expire_time, false, false, false)}</td>
<td>File</td>
<td>Reason</td>
<td>Ban date</td>
<td>Expiry date</td>
</tr>
{/each}
</thead>
<tbody>
{#each result.ip_offences as offence (offence.ban_time)}
<tr>
<td>
{#if offence.file_link}
<a href={offence.file_link} target="_blank" rel="noreferrer">
{offence.file_name}
</a>
{/if}
</td>
<td>{offence.reason}</td>
<td>{formatDate(offence.ban_time, false, false, false)}</td>
<td>{formatDate(offence.expire_time, false, false, false)}</td>
</tr>
{/each}
</tbody>
</table>
</div>

View File

@@ -51,9 +51,11 @@ export let icon_href = ""
<IconBlock icon_href={icon_href}>
<table>
<tr><td colspan="2">{file_name}</td></tr>
<tr><td>Type</td><td>{file_type}</td></tr>
<tr><td>Size</td><td>{formatDataVolume(file_size, 3)}</td></tr>
<tbody>
<tr><td colspan="2">{file_name}</td></tr>
<tr><td>Type</td><td>{file_type}</td></tr>
<tr><td>Size</td><td>{formatDataVolume(file_size, 3)}</td></tr>
</tbody>
</table>
<button on:click={() => {dispatch("download")}}>
<i class="icon">download</i> Download

View File

@@ -117,46 +117,50 @@ const logout = async (key) => {
</section>
<div class="table_scroll">
<table style="text-align: left;">
<tr>
<td>Key</td>
<td>Created</td>
<td>Last used ▼</td>
<td>IP address</td>
<td></td>
</tr>
{#each rows as row (row.auth_key)}
<tr style="border-bottom: none;">
<td>{row.auth_key}</td>
<td>{formatDate(row.creation_time, true, true, false)}</td>
<td>{formatDate(row.last_used_time, true, true, false)}</td>
<td>{row.creation_ip_address}</td>
<td>
<button on:click|preventDefault={() => {logout(row.auth_key)}} class="button button_red round">
<i class="icon">delete</i>
</button>
</td>
</tr>
<thead>
<tr>
<td colspan="1">
{#if row.app_name === "website login"}
<img src="/res/img/pixeldrain_32.png" alt="Pixeldrain logo" class="app_icon"/>
Pixeldrain website
{:else if row.app_name === "website keys page"}
<i class="icon">vpn_key</i>
Pixeldrain keys page
{:else if row.app_name === "sharex"}
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
ShareX
{:else if row.app_name === "jdownloader"}
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon"/>
JDownloader
{:else}
Unknown app: {row.app_name}
{/if}
</td>
<td colspan="4">User-Agent: {row.user_agent}</td>
<td>Key</td>
<td>Created</td>
<td>Last used ▼</td>
<td>IP address</td>
<td></td>
</tr>
{/each}
</thead>
<tbody>
{#each rows as row (row.auth_key)}
<tr style="border-bottom: none;">
<td>{row.auth_key}</td>
<td>{formatDate(row.creation_time, true, true, false)}</td>
<td>{formatDate(row.last_used_time, true, true, false)}</td>
<td>{row.creation_ip_address}</td>
<td>
<button on:click|preventDefault={() => {logout(row.auth_key)}} class="button button_red round">
<i class="icon">delete</i>
</button>
</td>
</tr>
<tr>
<td colspan="1">
{#if row.app_name === "website login"}
<img src="/res/img/pixeldrain_32.png" alt="Pixeldrain logo" class="app_icon"/>
Pixeldrain website
{:else if row.app_name === "website keys page"}
<i class="icon">vpn_key</i>
Pixeldrain keys page
{:else if row.app_name === "sharex"}
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
ShareX
{:else if row.app_name === "jdownloader"}
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon"/>
JDownloader
{:else}
Unknown app: {row.app_name}
{/if}
</td>
<td colspan="4">User-Agent: {row.user_agent}</td>
</tr>
{/each}
</tbody>
</table>
<br/>
</div>

View File

@@ -117,40 +117,42 @@ onMount(() => {
</div>
<table>
<tr>
<td>Opening balance</td>
<td><Euro amount={transactions.balance_start} precision="4"/></td>
</tr>
<tr>
<td>Closing balance</td>
<td><Euro amount={transactions.balance_end} precision="4"/></td>
</tr>
<tr>
<td>Total charge</td>
<td><Euro amount={transactions.total_deducted} precision="4"/></td>
</tr>
<tr>
<td>Subscription charge</td>
<td><Euro amount={transactions.total_subscription_charge} precision="4"/></td>
</tr>
<tr>
<td>Storage charge</td>
<td>
<Euro amount={transactions.total_storage_charge} precision="4"/>
(used {formatDataVolume(transactions.total_storage_used, 3)})
</td>
</tr>
<tr>
<td>Bandwidth charge</td>
<td>
<Euro amount={transactions.total_bandwidth_charge} precision="4"/>
(used {formatDataVolume(transactions.total_bandwidth_used, 3)})
</td>
</tr>
<tr>
<td>Deposited</td>
<td><Euro amount={transactions.total_deposited} precision="4"/></td>
</tr>
<tbody>
<tr>
<td>Opening balance</td>
<td><Euro amount={transactions.balance_start} precision="4"/></td>
</tr>
<tr>
<td>Closing balance</td>
<td><Euro amount={transactions.balance_end} precision="4"/></td>
</tr>
<tr>
<td>Total charge</td>
<td><Euro amount={transactions.total_deducted} precision="4"/></td>
</tr>
<tr>
<td>Subscription charge</td>
<td><Euro amount={transactions.total_subscription_charge} precision="4"/></td>
</tr>
<tr>
<td>Storage charge</td>
<td>
<Euro amount={transactions.total_storage_charge} precision="4"/>
(used {formatDataVolume(transactions.total_storage_used, 3)})
</td>
</tr>
<tr>
<td>Bandwidth charge</td>
<td>
<Euro amount={transactions.total_bandwidth_charge} precision="4"/>
(used {formatDataVolume(transactions.total_bandwidth_used, 3)})
</td>
</tr>
<tr>
<td>Deposited</td>
<td><Euro amount={transactions.total_deposited} precision="4"/></td>
</tr>
</tbody>
</table>
<style>

View File

@@ -0,0 +1,56 @@
<script>
import Button from "../layout/Button.svelte";
// {icon: "", label: ""}
export let tabs = []
export let active = 0
export const open_tab = (name = "") => {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].name === name) {
active = i
return
}
}
}
</script>
<div class="tab_bar">
{#each tabs as t, i}
<Button
icon={t.icon}
label={t.label}
highlight={i === active}
click={() => active = i}
/>
{/each}
</div>
<!-- Can't find a way to do this dynamically unfortunately-->
{#if active === 0}
<slot name="0"></slot>
{:else if active === 1}
<slot name="1"></slot>
{:else if active === 2}
<slot name="2"></slot>
{:else if active === 3}
<slot name="3"></slot>
{:else if active === 4}
<slot name="4"></slot>
{:else if active === 5}
<slot name="5"></slot>
{:else if active === 6}
<slot name="6"></slot>
{:else if active === 7}
<slot name="7"></slot>
{:else if active === 8}
<slot name="8"></slot>
{:else if active === 9}
<slot name="9"></slot>
{/if}
<style>
.tab_bar {
border-bottom: 2px solid var(--separator);
}
</style>