mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'feat-gradient-alert-banner' of https://github.com/appwrite/console into feat-gradient-alert-banner
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { activeHeaderAlert } from '$routes/console/store';
|
||||
import GradientBanner from '../gradientBanner.svelte';
|
||||
|
||||
let show = true;
|
||||
|
||||
function handleClose() {
|
||||
show = false;
|
||||
const now = new Date().getTime();
|
||||
localStorage.setItem($activeHeaderAlert.id, now.toString());
|
||||
trackEvent('close_upgrade_banner', {
|
||||
source: 'cloud_credits_banner',
|
||||
campaign: 'WelcomeManual'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if show && $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && !$page.url.pathname.includes('/console/account')}
|
||||
<GradientBanner on:close={handleClose}>
|
||||
<div class="u-flex u-gap-24 u-main-center u-cross-center u-flex-vertical-mobile">
|
||||
<span class="body-text-1">Get $50 Cloud credits for Appwrite Pro.</span>
|
||||
<Button
|
||||
secondary
|
||||
fullWidthMobile
|
||||
class="u-line-height-1"
|
||||
href={`${base}/console/apply-credit?code=appw50&org=${$organization.$id}`}
|
||||
on:click={() => {
|
||||
trackEvent('click_credits_redeem', {
|
||||
from: 'button',
|
||||
source: 'cloud_credits_banner',
|
||||
campaign: 'WelcomeManual'
|
||||
});
|
||||
}}>
|
||||
Claim credits
|
||||
</Button>
|
||||
</div>
|
||||
</GradientBanner>
|
||||
{/if}
|
||||
@@ -1,34 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { upgradeURL } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import GradientBanner from '../gradientBanner.svelte';
|
||||
|
||||
let show = true;
|
||||
|
||||
function handleClose() {
|
||||
show = false;
|
||||
const now = new Date().getTime();
|
||||
localStorage.setItem('upgradeBanner', now.toString());
|
||||
trackEvent('close_upgrade_banner', {
|
||||
source: 'upgrade_banner'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if show && $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && !$page.url.pathname.includes('/console/account')}
|
||||
<GradientBanner
|
||||
on:close={handleClose}
|
||||
on:click={() => {
|
||||
trackEvent('click_organization_upgrade', {
|
||||
from: 'button',
|
||||
source: 'upgrade_banner'
|
||||
});
|
||||
}}
|
||||
href={$upgradeURL}
|
||||
buttonText="Upgrade">
|
||||
Appwrite Pro is now available!
|
||||
</GradientBanner>
|
||||
{/if}
|
||||
@@ -1,10 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let buttonText: string;
|
||||
export let href: string = null;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
@@ -18,23 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-content u-color-text-primary">
|
||||
{#if href}
|
||||
<a
|
||||
class="u-flex u-gap-16 u-main-center u-cross-center u-flex-vertical-mobile"
|
||||
{href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
<span class="body-text-1 u-bold"><slot /></span>
|
||||
<Button secondary fullWidthMobile on:click class="u-line-height-1"
|
||||
>{buttonText}</Button>
|
||||
</a>
|
||||
{:else}
|
||||
<div class="u-flex u-gap-16 u-main-center u-cross-center u-flex-vertical-mobile">
|
||||
<span class="body-text-1 u-bold"><slot /></span>
|
||||
<Button secondary fullWidthMobile on:click class="u-line-height-1"
|
||||
>{buttonText}</Button>
|
||||
</div>
|
||||
{/if}
|
||||
<slot />
|
||||
</div>
|
||||
<button
|
||||
on:click|preventDefault={() => dispatch('close')}
|
||||
|
||||
@@ -27,9 +27,11 @@ import PaymentMandate from '$lib/components/billing/alerts/paymentMandate.svelte
|
||||
import MissingPaymentMethod from '$lib/components/billing/alerts/missingPaymentMethod.svelte';
|
||||
import LimitReached from '$lib/components/billing/alerts/limitReached.svelte';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import UpgradeToPro from '$lib/components/billing/alerts/upgradeToPro.svelte';
|
||||
import newDevUpgradePro from '$lib/components/billing/alerts/newDevUpgradePro.svelte';
|
||||
import { last } from '$lib/helpers/array';
|
||||
import { sizeToBytes, type Size } from '$lib/helpers/sizeConvertion';
|
||||
import { user } from './user';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
export type Tier = 'tier-0' | 'tier-1' | 'tier-2';
|
||||
|
||||
@@ -389,19 +391,25 @@ export async function checkForMissingPaymentMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function checkForUpgradeBanner(org: Organization) {
|
||||
if (org?.billingPlan !== BillingPlan.FREE) return;
|
||||
// Display upgrade banner for new users after 1 week for 30 days
|
||||
export async function checkForNewDevUpgradePro(org: Organization) {
|
||||
if (org?.billingPlan !== BillingPlan.FREE || !browser) return;
|
||||
|
||||
const orgs = await sdk.forConsole.billing.listOrganization([
|
||||
Query.notEqual('billingPlan', BillingPlan.FREE)
|
||||
]);
|
||||
if (orgs?.total) return;
|
||||
const localData = localStorage.getItem('upgradeBanner');
|
||||
const hideUpgradeBanner = localData ? parseInt(localData) : 0;
|
||||
|
||||
const now = new Date().getTime();
|
||||
if (now - hideUpgradeBanner >= 1000 * 60 * 60 * 24 * 14) {
|
||||
const account = get(user);
|
||||
const accountCreated = new Date(account.$createdAt).getTime();
|
||||
if (now - accountCreated < 1000 * 60 * 60 * 24 * 7) return;
|
||||
const isDismissed = !!localStorage.getItem('newDevUpgradePro');
|
||||
if (isDismissed) return;
|
||||
if (now - accountCreated < 1000 * 60 * 60 * 24 * 37) {
|
||||
headerAlert.add({
|
||||
id: 'upgradeBanner',
|
||||
component: UpgradeToPro,
|
||||
id: 'newDevUpgradePro',
|
||||
component: newDevUpgradePro,
|
||||
show: true,
|
||||
importance: 1
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
checkForMarkedForDeletion,
|
||||
checkForMandate,
|
||||
checkForMissingPaymentMethod,
|
||||
checkForUpgradeBanner,
|
||||
checkForNewDevUpgradePro,
|
||||
plansInfo
|
||||
} from '$lib/stores/billing';
|
||||
import { goto } from '$app/navigation';
|
||||
@@ -267,11 +267,12 @@
|
||||
if (isCloud) {
|
||||
await checkForUsageLimit(org);
|
||||
checkForMarkedForDeletion(org);
|
||||
await checkForNewDevUpgradePro(org);
|
||||
|
||||
if (org?.billingPlan !== BillingPlan.FREE) {
|
||||
await paymentExpired(org);
|
||||
await checkPaymentAuthorizationRequired(org);
|
||||
await checkForMandate(org);
|
||||
await checkForUpgradeBanner(org);
|
||||
|
||||
if ($plansInfo.get(org.billingPlan)?.trialDays) {
|
||||
calculateTrialDay(org);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/i;
|
||||
let previousPage: string = `${base}/console`;
|
||||
let showExitModal = false;
|
||||
let canSelectOrg = true;
|
||||
|
||||
afterNavigate(({ from }) => {
|
||||
if (from?.url?.pathname) {
|
||||
@@ -75,6 +76,10 @@
|
||||
if (!$organizationList?.total || campaign?.onlyNewOrgs) {
|
||||
selectedOrgId = newOrgId;
|
||||
}
|
||||
if ($page.url.searchParams.has('org')) {
|
||||
selectedOrgId = $page.url.searchParams.get('org');
|
||||
canSelectOrg = false;
|
||||
}
|
||||
});
|
||||
|
||||
async function loadPaymentMethods() {
|
||||
@@ -197,7 +202,7 @@
|
||||
<WizardSecondaryContent>
|
||||
<Form bind:this={formComponent} onSubmit={handleSubmit} bind:isSubmitting>
|
||||
<FormList>
|
||||
{#if $organizationList?.total && !campaign?.onlyNewOrgs}
|
||||
{#if $organizationList?.total && !campaign?.onlyNewOrgs && canSelectOrg}
|
||||
<InputSelect
|
||||
bind:value={selectedOrgId}
|
||||
label="Select organization"
|
||||
|
||||
Reference in New Issue
Block a user