Porting UI, still needs testing.
This commit is contained in:
parent
e9d19b3a02
commit
b24a108d80
|
@ -0,0 +1,55 @@
|
||||||
|
<script>
|
||||||
|
import { Body, ProgressBar, Label } from "@budibase/bbui"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
export let usage
|
||||||
|
|
||||||
|
let percentage
|
||||||
|
let unlimited = false
|
||||||
|
|
||||||
|
const isUnlimited = () => {
|
||||||
|
if (usage.total === -1) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPercentage = () => {
|
||||||
|
return (usage.used / usage.total) * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
unlimited = isUnlimited()
|
||||||
|
percentage = getPercentage()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="usage">
|
||||||
|
<div class="info">
|
||||||
|
<Label size="XL">{usage.name}</Label>
|
||||||
|
{#if unlimited}
|
||||||
|
<Body size="S">{usage.used}</Body>
|
||||||
|
{:else}
|
||||||
|
<Body size="S">{usage.used} / {usage.total}</Body>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{#if unlimited}
|
||||||
|
<Body size="S">Unlimited</Body>
|
||||||
|
{:else}
|
||||||
|
<ProgressBar width={"100%"} duration={1} value={percentage} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.usage {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -61,6 +61,10 @@
|
||||||
])
|
])
|
||||||
|
|
||||||
if (isEnabled(FEATURE_FLAGS.LICENSING)) {
|
if (isEnabled(FEATURE_FLAGS.LICENSING)) {
|
||||||
|
menu = menu.concat({
|
||||||
|
title: "Billing",
|
||||||
|
href: "/builder/portal/settings/billing",
|
||||||
|
})
|
||||||
menu = menu.concat({
|
menu = menu.concat({
|
||||||
title: "Upgrade",
|
title: "Upgrade",
|
||||||
href: "/builder/portal/settings/upgrade",
|
href: "/builder/portal/settings/upgrade",
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
Body,
|
||||||
|
Divider,
|
||||||
|
Heading,
|
||||||
|
Layout,
|
||||||
|
notifications,
|
||||||
|
Page,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import { auth, licensing } from "stores/portal"
|
||||||
|
import Usage from "components/billing/Usage.svelte"
|
||||||
|
|
||||||
|
let staticUsage = []
|
||||||
|
let monthlyUsage = []
|
||||||
|
let loaded = false
|
||||||
|
|
||||||
|
$: quotaUsage = $licensing.quotaUsage
|
||||||
|
$: license = $auth.user?.license
|
||||||
|
|
||||||
|
const setMonthlyUsage = () => {
|
||||||
|
monthlyUsage = []
|
||||||
|
if (quotaUsage.monthly) {
|
||||||
|
for (let [key, value] of Object.entries(license.quotas.usage.monthly)) {
|
||||||
|
const used = quotaUsage.monthly.current[key]
|
||||||
|
if (used !== undefined) {
|
||||||
|
monthlyUsage.push({
|
||||||
|
name: value.name,
|
||||||
|
used: used,
|
||||||
|
total: value.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setStaticUsage = () => {
|
||||||
|
staticUsage = []
|
||||||
|
for (let [key, value] of Object.entries(license.quotas.usage.static)) {
|
||||||
|
const used = quotaUsage.usageQuota[key]
|
||||||
|
if (used !== undefined) {
|
||||||
|
staticUsage.push({
|
||||||
|
name: value.name,
|
||||||
|
used: used,
|
||||||
|
total: value.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const capitalise = string => {
|
||||||
|
if (string) {
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = async () => {
|
||||||
|
try {
|
||||||
|
await licensing.getQuotaUsage()
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
notifications.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
await init()
|
||||||
|
loaded = true
|
||||||
|
})
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (license && quotaUsage) {
|
||||||
|
setMonthlyUsage()
|
||||||
|
setStaticUsage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Page maxWidth={"100ch"}>
|
||||||
|
{#if loaded}
|
||||||
|
<Layout>
|
||||||
|
<Heading>Billing</Heading>
|
||||||
|
<Body>Get information about your current usage and manage your plan</Body>
|
||||||
|
</Layout>
|
||||||
|
<Layout gap="S">
|
||||||
|
<Divider />
|
||||||
|
</Layout>
|
||||||
|
<Layout gap="S" noPadding>
|
||||||
|
<Layout gap="XS">
|
||||||
|
<Body size="S">Your plan</Body>
|
||||||
|
<Heading size="S">{capitalise(license?.plan.type)}</Heading>
|
||||||
|
</Layout>
|
||||||
|
<Layout gap="S">
|
||||||
|
<Body size="S">Usage</Body>
|
||||||
|
<div class="usages">
|
||||||
|
{#each staticUsage as usage}
|
||||||
|
<div class="usage">
|
||||||
|
<Usage {usage} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
{#if monthlyUsage.length}
|
||||||
|
<Layout gap="S">
|
||||||
|
<Body size="S">Monthly</Body>
|
||||||
|
<div class="usages">
|
||||||
|
{#each monthlyUsage as usage}
|
||||||
|
<div class="usage">
|
||||||
|
<Usage {usage} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
<div />
|
||||||
|
{/if}
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
|
</Page>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.usages {
|
||||||
|
display: grid;
|
||||||
|
column-gap: 60px;
|
||||||
|
row-gap: 50px;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -6,3 +6,4 @@ export { email } from "./email"
|
||||||
export { auth } from "./auth"
|
export { auth } from "./auth"
|
||||||
export { oidc } from "./oidc"
|
export { oidc } from "./oidc"
|
||||||
export { templates } from "./templates"
|
export { templates } from "./templates"
|
||||||
|
export { licensing } from "./licensing"
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import { API } from "api"
|
||||||
|
|
||||||
|
export const createLicensingStore = () => {
|
||||||
|
const DEFAULT = {
|
||||||
|
plans: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = writable(DEFAULT)
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
getQuotaUsage: async () => {
|
||||||
|
const quotaUsage = await API.getQuotaUsage()
|
||||||
|
store.update(state => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
quotaUsage,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe: store.subscribe,
|
||||||
|
...actions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const licensing = createLicensingStore()
|
|
@ -27,4 +27,10 @@ export const buildLicensingEndpoints = API => ({
|
||||||
url: "/api/global/license/refresh",
|
url: "/api/global/license/refresh",
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getQuotaUsage: async () => {
|
||||||
|
return API.get({
|
||||||
|
url: "/api/license/usage",
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue