diff --git a/packages/builder/src/components/usage/Usage.svelte b/packages/builder/src/components/usage/Usage.svelte
index cd9071785d..27383019e8 100644
--- a/packages/builder/src/components/usage/Usage.svelte
+++ b/packages/builder/src/components/usage/Usage.svelte
@@ -1,10 +1,13 @@
-
+
{#if unlimited}
- {usage.used}
+ {usage.used} / Unlimited
{:else}
{usage.used} / {usage.total}
{/if}
{#if unlimited}
- Unlimited
+
{:else}
-
+
+ {/if}
+ {#if showWarning}
+
+ To get more queries
upgrade your plan
+
{/if}
@@ -51,6 +82,13 @@
display: flex;
flex-direction: row;
justify-content: space-between;
- gap: var(--spacing-m);
+ margin-bottom: 12px;
+ }
+ .header-container {
+ display: flex;
+ }
+ .heading {
+ margin-top: 3px;
+ margin-left: 5px;
}
diff --git a/packages/builder/src/components/usage/UsageDashCard.svelte b/packages/builder/src/components/usage/UsageDashCard.svelte
new file mode 100644
index 0000000000..ff0ac7ca49
--- /dev/null
+++ b/packages/builder/src/components/usage/UsageDashCard.svelte
@@ -0,0 +1,108 @@
+
+
+
+
+
diff --git a/packages/builder/src/components/usage/index.js b/packages/builder/src/components/usage/index.js
new file mode 100644
index 0000000000..48c0e2ea2c
--- /dev/null
+++ b/packages/builder/src/components/usage/index.js
@@ -0,0 +1,2 @@
+export { default as Usage } from "./Usage.svelte"
+export { default as DashCard } from "./UsageDashCard.svelte"
diff --git a/packages/builder/src/constants/index.js b/packages/builder/src/constants/index.js
index 4e2ca37b9c..bcfbfffb81 100644
--- a/packages/builder/src/constants/index.js
+++ b/packages/builder/src/constants/index.js
@@ -57,3 +57,10 @@ export const DefaultAppTheme = {
navBackground: "var(--spectrum-global-color-gray-50)",
navTextColor: "var(--spectrum-global-color-gray-800)",
}
+
+export const PlanType = {
+ FREE: "free",
+ PRO: "pro",
+ BUSINESS: "business",
+ ENTERPRISE: "enterprise",
+}
diff --git a/packages/builder/src/pages/builder/portal/settings/usage.svelte b/packages/builder/src/pages/builder/portal/settings/usage.svelte
index 069c37b555..6ee7e45e25 100644
--- a/packages/builder/src/pages/builder/portal/settings/usage.svelte
+++ b/packages/builder/src/pages/builder/portal/settings/usage.svelte
@@ -5,20 +5,39 @@
Heading,
Layout,
notifications,
- Link,
+ Page,
+ Detail,
} from "@budibase/bbui"
import { onMount } from "svelte"
- import { admin, auth, licensing } from "stores/portal"
- import Usage from "components/usage/Usage.svelte"
+ import { admin, auth, licensing } from "../../../../stores/portal"
+ import { PlanType } from "../../../../constants"
+ import { DashCard, Usage } from "../../../../components/usage"
let staticUsage = []
let monthlyUsage = []
+ let price
+ let lastPayment
+ let cancelAt
+ let nextPayment
+ let balance
let loaded = false
+ let textRows = []
+ let daysRemainingInMonth
+
+ const upgradeUrl = `${$admin.accountPortalUrl}/portal/upgrade`
+ const manageUrl = `${$admin.accountPortalUrl}/portal/billing`
+
+ const warnUsage = ["Queries", "Automations", "Rows"]
$: quotaUsage = $licensing.quotaUsage
$: license = $auth.user?.license
- const upgradeUrl = `${$admin.accountPortalUrl}/portal/upgrade`
+ const numberFormatter = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ })
const setMonthlyUsage = () => {
monthlyUsage = []
@@ -34,6 +53,7 @@
}
}
}
+ monthlyUsage = monthlyUsage.sort((a, b) => a.name.localeCompare(b.name))
}
const setStaticUsage = () => {
@@ -48,6 +68,52 @@
})
}
}
+ staticUsage = staticUsage.sort((a, b) => a.name.localeCompare(b.name))
+ }
+
+ const setNextPayment = () => {
+ const periodEnd = license?.billing.subscription?.currentPeriodEnd
+ const cancelAt = license?.billing.subscription?.cancelAt
+ if (periodEnd) {
+ if (cancelAt && periodEnd <= cancelAt) {
+ return
+ }
+ nextPayment = `Next payment: ${getLocaleDataString(periodEnd)}`
+ }
+ }
+
+ const setCancelAt = () => {
+ cancelAt = license?.billing.subscription?.cancelAt
+ }
+
+ const setLastPayment = () => {
+ const periodStart = license?.billing.subscription?.currentPeriodStart
+ if (periodStart) {
+ lastPayment = `Last payment: ${getLocaleDataString(periodStart)}`
+ }
+ }
+
+ const setBalance = () => {
+ const customerBalance = license?.billing.customer.balance
+ if (customerBalance) {
+ balance = `Balance: ${numberFormatter.format(
+ (customerBalance / 100) * -1
+ )}`
+ }
+ }
+
+ const getLocaleDataString = epoch => {
+ const date = new Date(epoch * 1000)
+ return date.toLocaleDateString("default", {
+ day: "numeric",
+ month: "long",
+ year: "numeric",
+ })
+ }
+
+ const setPrice = () => {
+ const planPrice = license.plan.price
+ price = `${numberFormatter.format(planPrice.amountMonthly / 100)} per month`
}
const capitalise = string => {
@@ -56,6 +122,69 @@
}
}
+ const planTitle = () => {
+ return capitalise(license?.plan.type)
+ }
+
+ const planSubtitle = () => {
+ return `${license?.plan.price.sessions} day passes`
+ }
+
+ const getDaysRemaining = timestamp => {
+ if (!timestamp) {
+ return
+ }
+ const now = new Date()
+ now.setHours(0)
+ now.setMinutes(0)
+
+ const thenDate = new Date(timestamp)
+ thenDate.setHours(0)
+ thenDate.setMinutes(0)
+
+ const difference = thenDate.getTime() - now
+ // return the difference in days
+ return (difference / (1000 * 3600 * 24)).toFixed(0)
+ }
+
+ const setTextRows = () => {
+ textRows = []
+
+ if (cancelAt) {
+ textRows.push("Subscription has been cancelled")
+ textRows.push(`${getDaysRemaining(cancelAt * 1000)} days remaining`)
+ } else {
+ if (price) {
+ textRows.push(price)
+ }
+ if (lastPayment) {
+ textRows.push(lastPayment)
+ }
+ if (nextPayment) {
+ textRows.push(nextPayment)
+ }
+ }
+ }
+
+ const setDaysRemainingInMonth = () => {
+ let now = new Date()
+ now = new Date(now.getFullYear(), now.getMonth(), now.getDate())
+
+ const firstNextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1)
+ const difference = firstNextMonth.getTime() - now.getTime()
+
+ // return the difference in days
+ daysRemainingInMonth = (difference / (1000 * 3600 * 24)).toFixed(0)
+ }
+
+ const goToAccountPortal = () => {
+ if (license?.plan.type === PlanType.FREE) {
+ window.location.href = upgradeUrl
+ } else {
+ window.location.href = manageUrl
+ }
+ }
+
const init = async () => {
try {
await licensing.getQuotaUsage()
@@ -71,69 +200,99 @@
})
$: {
- if (license && quotaUsage) {
- setMonthlyUsage()
- setStaticUsage()
+ if (license) {
+ setPrice()
+ setBalance()
+ setLastPayment()
+ setNextPayment()
+ setCancelAt()
+ setTextRows()
+ setDaysRemainingInMonth()
+
+ if (quotaUsage) {
+ setMonthlyUsage()
+ setStaticUsage()
+ }
}
}
-{#if loaded}
-
- Usage
- Get information about your current usage within Budibase.
- {#if $admin.cloud}
- {#if $auth.user?.accountPortalAccess}
- To upgrade your plan and usage limits visit your Account.
- {:else}
- Contact your account holder to upgrade your usage limits.
- {/if}
- {/if}
-
-
-
-
-
-
-
- YOUR PLAN
- {capitalise(license?.plan.type)}
-
-
- USAGE
-
- {#each staticUsage as usage}
-
-
-
- {/each}
-
-
- {#if monthlyUsage.length}
-
- MONTHLY
-
- {#each monthlyUsage as usage}
-
-
-
- {/each}
-
+
+ {#if loaded}
+
+
+ Billing
+ Get information about your current usage and manage your plan
-
- {/if}
-
-{/if}
+
+
+
+
+
+
+ {#each staticUsage as usage}
+
+
+
+ {/each}
+
+
+
+ {#if monthlyUsage.length}
+
+
+ Monthly
+
+ Resets in {daysRemainingInMonth} days
+
+
+
+ {#each monthlyUsage as usage}
+
+
+
+ {/each}
+
+
+
+
+ {/if}
+
+
+
+ {/if}
+