Move metered billing settings to the subscription tab
This commit is contained in:
@@ -51,7 +51,7 @@ let included = $derived($user === null ? 0 : $user.subscription.monthly_transfer
|
||||
</p>
|
||||
{#if bill_shock}
|
||||
<p>
|
||||
This is your bill shock limit. <a href="/user/sharing">Increase
|
||||
This is your bill shock limit. <a href="/user/subscription/metered_billing">Increase
|
||||
or disable the limit</a> to continue sharing files.
|
||||
</p>
|
||||
{:else if overdrawn}
|
||||
@@ -65,7 +65,7 @@ let included = $derived($user === null ? 0 : $user.subscription.monthly_transfer
|
||||
{:else}
|
||||
<p>
|
||||
Upgrade your plan or enable
|
||||
<a href="/user/sharing">usage based billing</a> to continue
|
||||
<a href="/user/subscription/metered_billing">usage based billing</a> to continue
|
||||
sharing files.
|
||||
</p>
|
||||
<a class="button button_highlight" href="/user/subscription/manage">
|
||||
@@ -82,7 +82,7 @@ let included = $derived($user === null ? 0 : $user.subscription.monthly_transfer
|
||||
{#if bill_shock}
|
||||
<p>
|
||||
This is your bill shock limit, you can change it in the
|
||||
<a href="/user/sharing">sharing settings</a>.
|
||||
<a href="/user/subscription/metered_billing">subscription settings</a>.
|
||||
</p>
|
||||
{:else}
|
||||
<a class="button button_highlight" href="/user/subscription/manage">
|
||||
|
||||
@@ -11,6 +11,7 @@ import { onMount } from "svelte";
|
||||
import { get_user, type User } from "lib/NovaAPI";
|
||||
import SharingSettings from "./SharingSettings.svelte";
|
||||
import SubscriptionManage from "./SubscriptionManage.svelte";
|
||||
import SubscriptionUsage from "./SubscriptionUsage.svelte";
|
||||
|
||||
let pages: Tab[] = [
|
||||
{
|
||||
@@ -39,6 +40,11 @@ let pages: Tab[] = [
|
||||
title: "Transactions",
|
||||
icon: "receipt",
|
||||
component: Transactions,
|
||||
}, {
|
||||
path: "/user/subscription/metered_billing",
|
||||
title: "Metered billing",
|
||||
icon: "data_usage",
|
||||
component: SubscriptionUsage,
|
||||
},
|
||||
],
|
||||
}, {
|
||||
|
||||
@@ -1,26 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { formatDataVolume, formatEuros } from "util/Formatting";
|
||||
import ProgressBar from "util/ProgressBar.svelte";
|
||||
import { loading_run } from "lib/Loading";
|
||||
import { get_endpoint, period_price, put_user } from 'lib/NovaAPI';
|
||||
import { put_user } from 'lib/NovaAPI';
|
||||
import SuccessMessage from 'util/SuccessMessage.svelte';
|
||||
import { user } from "lib/UserStore";
|
||||
|
||||
let success_message: SuccessMessage = $state()
|
||||
|
||||
let transfer_cap = $state($user === null ? 0 : $user.monthly_transfer_cap / 1e12)
|
||||
|
||||
const update_user = async (e: SubmitEvent) => {
|
||||
if (e !== null) {
|
||||
e.preventDefault()
|
||||
}
|
||||
loading_run(async () => {
|
||||
try {
|
||||
await put_user({
|
||||
transfer_cap: transfer_cap*1e12,
|
||||
embed_domains: embed_domains.join(" "),
|
||||
})
|
||||
await put_user({embed_domains: embed_domains.join(" ")})
|
||||
|
||||
success_message.set(true, "Sharing settings updated")
|
||||
} catch (err) {
|
||||
@@ -29,40 +21,6 @@ const update_user = async (e: SubmitEvent) => {
|
||||
})
|
||||
}
|
||||
|
||||
const set_usage_based_billing = (e: Event) => {
|
||||
const input = e.target as HTMLInputElement
|
||||
loading_run(async () => {
|
||||
try {
|
||||
await put_user({usage_based_billing: input.checked})
|
||||
success_message.set(true, "Usage based billing updated")
|
||||
} catch (err) {
|
||||
input.checked = !input.checked
|
||||
success_message.set(false, "Failed to update user: "+err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let transfer_used = $state(0)
|
||||
let load_transfer_used = () => {
|
||||
let today = new Date()
|
||||
let start = new Date()
|
||||
start.setDate(start.getDate() - 30)
|
||||
|
||||
fetch(
|
||||
get_endpoint() + "/user/time_series/egress" +
|
||||
"?start=" + start.toISOString() +
|
||||
"&end=" + today.toISOString() +
|
||||
"&interval=60"
|
||||
).then(resp => {
|
||||
if (!resp.ok) { return Promise.reject("Error: " + resp.status); }
|
||||
return resp.json();
|
||||
}).then(resp => {
|
||||
transfer_used = resp.amounts.reduce((acc, cur) => { return acc + cur }, 0)
|
||||
}).catch(e => {
|
||||
console.error("Error requesting time series: " + e);
|
||||
})
|
||||
}
|
||||
|
||||
// Embedding settings
|
||||
let embed_domains: string[] = $state($user === null ? [] : $user.embed_domains.split(" "))
|
||||
let new_domain: string = $state("")
|
||||
@@ -80,64 +38,11 @@ const del_domain = (index: number) => {
|
||||
embed_domains = embed_domains
|
||||
update_user(null)
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
load_transfer_used()
|
||||
})
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<SuccessMessage bind:this={success_message}/>
|
||||
|
||||
{#if $user !== null && $user.subscription.type === "subscription"}
|
||||
<h2>Usage based billing</h2>
|
||||
<p>
|
||||
When your storage or data transfer goes over the limits of your
|
||||
plan, uploads and downloads are blocked. With usage based billing
|
||||
they keep working and the usage above the limits is billed at
|
||||
{formatEuros($user.subscription.price_per_tb_storage, 2)} per TB per
|
||||
month for storage and
|
||||
{formatEuros($user.subscription.price_per_tb_bandwidth, 2)} per TB
|
||||
for data transfer.
|
||||
</p>
|
||||
<p>
|
||||
This usage is charged from your account credit afterwards. When
|
||||
your balance is more than {formatEuros(period_price($user), 2)} below zero
|
||||
(the price of your subscription period) the limits of your plan
|
||||
apply again, until you top up your credit.
|
||||
</p>
|
||||
<label>
|
||||
<input type="checkbox" checked={$user.usage_based_billing} onchange={set_usage_based_billing}/>
|
||||
Enable usage based billing
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<h2>Bill shock limit</h2>
|
||||
<p>
|
||||
Billshock limit in terabytes per month (1 TB = 1000 GB). Set to 0 to
|
||||
disable.
|
||||
</p>
|
||||
<form onsubmit={update_user} class="billshock_container">
|
||||
<input type="number" bind:value={transfer_cap} step="0.1" min="0" style="width: 5em;"/>
|
||||
<div style="margin: 0.5em;">TB</div>
|
||||
<button type="submit">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p>
|
||||
Bandwidth used in the last 30 days: {formatDataVolume(transfer_used, 3)},
|
||||
new limit: {formatDataVolume(transfer_cap*1e12, 3)}
|
||||
</p>
|
||||
<ProgressBar used={transfer_used} total={transfer_cap*1e12} warn></ProgressBar>
|
||||
<p>
|
||||
The billshock limit limits how much bandwidth your account can use in a
|
||||
30 day window. When this limit is reached your files can't be downloaded
|
||||
until your usage drops below it, and you will no longer be charged for
|
||||
bandwidth usage. This is mostly useful with usage based billing, but it
|
||||
works without it too. Set to 0 to disable the limit.
|
||||
</p>
|
||||
|
||||
<h2>Embedding controls</h2>
|
||||
<p>
|
||||
Here you can control which websites are allowed to embed your files in
|
||||
@@ -172,12 +77,6 @@ onMount(async () => {
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.billshock_container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.highlight_border {
|
||||
text-align: initial;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ let overdrawn = $derived($user !== null && $user.usage_based_billing && price >
|
||||
You are storing more than your plan allows, so you can't upload new
|
||||
files. Your existing files stay available. Delete some files or
|
||||
upgrade your plan to continue uploading, or enable
|
||||
<a href="/user/sharing">usage based billing</a> to pay for the
|
||||
<a href="/user/subscription/metered_billing">usage based billing</a> to pay for the
|
||||
storage above the limit.
|
||||
</p>
|
||||
<a class="button button_highlight" href="/user/subscription/manage">
|
||||
|
||||
101
svelte/src/user_home/SubscriptionUsage.svelte
Normal file
101
svelte/src/user_home/SubscriptionUsage.svelte
Normal file
@@ -0,0 +1,101 @@
|
||||
<script lang="ts">
|
||||
import { formatDataVolume, formatEuros } from "util/Formatting";
|
||||
import ProgressBar from "util/ProgressBar.svelte";
|
||||
import { loading_run } from "lib/Loading";
|
||||
import { period_price, put_user } from "lib/NovaAPI";
|
||||
import SuccessMessage from "util/SuccessMessage.svelte";
|
||||
import { user } from "lib/UserStore";
|
||||
import ToggleButton from "layout/ToggleButton.svelte";
|
||||
|
||||
let success_message: SuccessMessage = $state()
|
||||
|
||||
// The toggle button has already flipped the value in the user store when this
|
||||
// runs. put_user reloads the store from the server, so only a failed request
|
||||
// has to flip it back
|
||||
const set_usage_based_billing = () => {
|
||||
loading_run(async () => {
|
||||
try {
|
||||
await put_user({usage_based_billing: $user.usage_based_billing})
|
||||
success_message.set(true, "Usage based billing updated")
|
||||
} catch (err) {
|
||||
$user.usage_based_billing = !$user.usage_based_billing
|
||||
success_message.set(false, "Failed to update user: "+(err?.message ?? err))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let transfer_cap = $state($user === null ? 0 : $user.monthly_transfer_cap / 1e12)
|
||||
let transfer_used = $derived($user === null ? 0 : $user.monthly_transfer_used)
|
||||
|
||||
const set_transfer_cap = (e: SubmitEvent) => {
|
||||
e.preventDefault()
|
||||
loading_run(async () => {
|
||||
try {
|
||||
await put_user({transfer_cap: transfer_cap*1e12})
|
||||
success_message.set(true, "Bill shock limit updated")
|
||||
} catch (err) {
|
||||
success_message.set(false, "Failed to update user: "+(err?.message ?? err))
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<SuccessMessage bind:this={success_message}/>
|
||||
|
||||
{#if $user !== null && $user.subscription.type === "subscription"}
|
||||
<h2>Usage based billing</h2>
|
||||
<p>
|
||||
When your storage or data transfer goes over the limits of your
|
||||
plan, uploads and downloads are blocked. With usage based billing
|
||||
they keep working and the usage above the limits is billed at
|
||||
{formatEuros($user.subscription.price_per_tb_storage, 2)} per TB per
|
||||
month for storage and
|
||||
{formatEuros($user.subscription.price_per_tb_bandwidth, 2)} per TB
|
||||
for data transfer.
|
||||
</p>
|
||||
<p>
|
||||
This usage is charged from your account credit afterwards. When
|
||||
your balance is more than {formatEuros(period_price($user), 2)} below zero
|
||||
(the price of your subscription period) the limits of your plan
|
||||
apply again, until you top up your credit.
|
||||
</p>
|
||||
<ToggleButton bind:on={$user.usage_based_billing} action={set_usage_based_billing}>
|
||||
Usage based billing
|
||||
</ToggleButton>
|
||||
{/if}
|
||||
|
||||
<h2>Bill shock limit</h2>
|
||||
<p>
|
||||
Billshock limit in terabytes per month (1 TB = 1000 GB). Set to 0 to
|
||||
disable.
|
||||
</p>
|
||||
<form onsubmit={set_transfer_cap} class="billshock_container">
|
||||
<input type="number" bind:value={transfer_cap} step="0.1" min="0" style="width: 5em;"/>
|
||||
<div style="margin: 0.5em;">TB</div>
|
||||
<button type="submit">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p>
|
||||
Bandwidth used in the last 30 days: {formatDataVolume(transfer_used, 3)},
|
||||
new limit: {formatDataVolume(transfer_cap*1e12, 3)}
|
||||
</p>
|
||||
<ProgressBar used={transfer_used} total={transfer_cap*1e12} warn></ProgressBar>
|
||||
<p>
|
||||
The billshock limit limits how much bandwidth your account can use in a
|
||||
30 day window. When this limit is reached your files can't be downloaded
|
||||
until your usage drops below it, and you will no longer be charged for
|
||||
bandwidth usage. This is mostly useful with usage based billing, but it
|
||||
works without it too. Set to 0 to disable the limit.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.billshock_container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -59,6 +59,6 @@ onMount(async () => {
|
||||
<br/><br/>
|
||||
|
||||
Egress used (30 days):
|
||||
(<a href="/user/sharing">set custom limit</a>)
|
||||
(<a href="/user/subscription/metered_billing">set custom limit</a>)
|
||||
<HotlinkProgressBar used={transfer_used} total={transfer_cap}></HotlinkProgressBar>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user