Confirm your details
- Confirm the details of your new organization and start your free trial.
+ Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE
+ ? '.'
+ : ' and start your free trial.'}
This amount, and any additional usage fees, will be charged on a recurring 30-day
- billing cycle after your trial period ends on {toLocaleDate(billingPayDate.toString())}.
+ billing cycle{TRIAL_PERIOD_OVERRIDE
+ ? '.'
+ : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.
{/if}
diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
index f6a3a8fa9..ef9231712 100644
--- a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
@@ -8,6 +8,7 @@
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { organizationList, type Organization } from '$lib/stores/organization';
import { updateStepStatus } from '$lib/stores/wizard';
+ import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
import { createOrganization, createOrgSteps } from './store';
let showCustomId = false;
@@ -108,7 +109,9 @@
{tierPro.description}
- 14 DAY FREE TRIAL
+ {#if !TRIAL_PERIOD_OVERRIDE}
+ 14 DAY FREE TRIAL
+ {/if}
@@ -131,7 +134,6 @@
-
COMING SOON
diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
index b9378f5f1..ed4c76719 100644
--- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
@@ -12,6 +12,7 @@
import { toLocaleDate } from '$lib/helpers/date';
import { showUsageRatesModal } from '$lib/stores/billing';
import { PaymentBoxes } from '$lib/components/billing';
+ import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
const today = new Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
@@ -74,9 +75,9 @@
Payment details
- Add a payment method to your organization. You will not be charged until your trial ends on {toLocaleDate(billingPayDate.toString())}.
+ Add a payment method to your organization. {#if !TRIAL_PERIOD_OVERRIDE}You will not be
+ charged until your trial ends on {toLocaleDate(billingPayDate.toString())}.
+ {/if}
diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts
index 613259fe0..90749d5e3 100644
--- a/src/routes/console/wizard/cloudOrganization/store.ts
+++ b/src/routes/console/wizard/cloudOrganization/store.ts
@@ -1,10 +1,13 @@
import { BillingPlan } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import type { Tier } from '$lib/stores/billing';
+import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
import { writable } from 'svelte/store';
export const createOrgSteps = writable(new Map());
-export const createOrganizationFinalAction = writable('Start trial');
+export const createOrganizationFinalAction = writable(
+ TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial'
+);
export const createOrganization = writable<{
id?: string;
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
index 5a94e9ec8..da01e2449 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
@@ -13,6 +13,7 @@
import { Pill } from '$lib/elements';
import { BillingPlan } from '$lib/constants';
import { formatCurrency } from '$lib/helpers/numbers';
+ import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
let usage: OrganizationUsage = null;
let members: Models.MembershipList = null;
@@ -161,7 +162,7 @@
{#if $organization.billingPlan === BillingPlan.PRO}
CURRENT PLAN
- {:else}
+ {:else if !TRIAL_PERIOD_OVERRIDE}
14 DAY FREE TRIAL
{/if}
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
index a67c5086e..604907f43 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
@@ -16,6 +16,7 @@
feedbackDowngradeOptions,
isUpgrade
} from './store';
+ import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
const plan = $plansInfo.get($changeOrganizationTier.billingPlan);
const collaboratorPrice = plan?.addons.member?.price ?? 0;
@@ -77,7 +78,9 @@
Confirm your details
- Confirm the details of your new organization and start your free trial.
+ Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE
+ ? '.'
+ : ' and start your free trial.'}
Organization name
@@ -144,9 +147,9 @@
This amount, and any additional usage fees, will be charged on a recurring 30-day
- billing cycle after your trial period ends on {toLocaleDate(billingPayDate.toString())}.
+ billing cycle{TRIAL_PERIOD_OVERRIDE
+ ? '.'
+ : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
index 846dbabcc..f9cf2af84 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
@@ -1,11 +1,14 @@
import { BillingPlan } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import type { Tier } from '$lib/stores/billing';
+import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
import { writable } from 'svelte/store';
export const changeTierSteps = writable(new Map());
export const isUpgrade = writable(false);
-export const changeOrganizationFinalAction = writable('Start trial');
+export const changeOrganizationFinalAction = writable(
+ TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial'
+);
export const changeOrganizationTier = writable<{
billingPlan: Tier;
From 79a2853984031a1faff3173ea6d11f300d723953 Mon Sep 17 00:00:00 2001
From: loks0n <22452787+loks0n@users.noreply.github.com>
Date: Tue, 2 Apr 2024 14:52:21 +0100
Subject: [PATCH 09/46] feat: new templates
---
src/lib/stores/marketplace.ts | 732 ++++++++++++++++++++++++++++++++++
1 file changed, 732 insertions(+)
diff --git a/src/lib/stores/marketplace.ts b/src/lib/stores/marketplace.ts
index 5e74be642..e7190d2a3 100644
--- a/src/lib/stores/marketplace.ts
+++ b/src/lib/stores/marketplace.ts
@@ -902,6 +902,738 @@ export const marketplace: MarketplaceTemplate[] = [
type: 'text'
}
]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'text-generation-with-huggingface',
+ name: 'Text generation',
+ tagline: 'Generate text using the Hugging Face inference API.',
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 30,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/text-generation-with-huggingface'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'HUGGINGFACE_ACCESS_TOKEN',
+ description: `Secret for sending requests to the Hugging Face API. Learn more.`,
+ placeholder: 'hf_MUvn...',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'language-translation-with-huggingface',
+ name: 'Language translation',
+ tagline: 'Translate text using the Hugging Face inference API.',
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 30,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/language-translation-with-huggingface'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'HUGGINGFACE_ACCESS_TOKEN',
+ description: `Secret for sending requests to the Hugging Face API. Learn more.`,
+ placeholder: 'hf_MUvn...',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'image-classification-with-huggingface',
+ name: 'Image classification',
+ tagline: 'Classify images using the Hugging Face inference API.',
+ permissions: ['any'],
+ events: ['buckets.*.files.*.create'],
+ cron: '',
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install && npm run setup',
+ 'src/main.js',
+ 'node/image-classification-with-huggingface'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's Server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the responses are stored. Learn more.`,
+ value: 'ai',
+ placeholder: 'ai',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the responses are stored. Learn more.`,
+ value: 'image_classification',
+ placeholder: 'image_classification',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_BUCKET_ID',
+ description: `The ID of the bucket where the images are stored. Learn more.`,
+ value: 'image_classification',
+ placeholder: 'image_classification',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'HUGGINGFACE_ACCESS_TOKEN',
+ description: `Secret for sending requests to the Hugging Face API. Learn more.`,
+ placeholder: 'hf_MUvn...',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'object-detection-with-huggingface',
+ name: 'Object detection',
+ tagline: 'Detect objects in images using the Hugging Face inference API.',
+ permissions: ['any'],
+ events: ['buckets.*.files.*.create'],
+ cron: '',
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install && npm run setup',
+ 'src/main.js',
+ 'node/object-detection-with-huggingface'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the responses are stored. Learn more.`,
+ value: 'ai',
+ placeholder: 'ai',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the responses are stored. Learn more.`,
+ value: 'object_detection',
+ placeholder: 'object_detection',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_BUCKET_ID',
+ description: `The ID of the bucket where the images are stored. Learn more.`,
+ value: 'object_detection',
+ placeholder: 'object_detection',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'HUGGINGFACE_ACCESS_TOKEN',
+ description: `Secret for sending requests to the Hugging Face API. Learn more.`,
+ placeholder: 'hf_MUvn...',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'speech-recognition-with-huggingface',
+ name: 'Speech recognition',
+ tagline: 'Transcribe audio to text using the Hugging Face inference API.',
+ permissions: ['any'],
+ events: ['buckets.*.files.*.create'],
+ cron: '',
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install && npm run setup',
+ 'src/main.js',
+ 'node/speech-recognition-with-huggingface'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the responses are stored. Learn more.`,
+ value: 'ai',
+ placeholder: 'ai',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the responses are stored. Learn more.`,
+ value: 'speech_recognition',
+ placeholder: 'speech_recognition',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_BUCKET_ID',
+ description: `The ID of the bucket where audio is stored. Learn more.`,
+ value: 'speech_recognition',
+ placeholder: 'speech_recognition',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'HUGGINGFACE_ACCESS_TOKEN',
+ description: `Secret for sending requests to the Hugging Face API. Learn more.`,
+ placeholder: 'hf_MUvn...',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'text-to-speech-with-huggingface',
+ name: 'Text to speech',
+ tagline: 'Convert text to speech using the Hugging Face inference API.',
+ permissions: ['any'],
+ events: ['databases.*.collections.*.documents.*.create'],
+ cron: '',
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install && npm run setup',
+ 'src/main.js',
+ 'node/text-to-speech-with-huggingface'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the responses are stored. Learn more.`,
+ value: 'ai',
+ placeholder: 'ai',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the responses are stored. Learn more.`,
+ value: 'speech_recognition',
+ placeholder: 'speech_recognition',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_BUCKET_ID',
+ description: `The ID of the bucket where audio is stored. Learn more.`,
+ value: 'speech_recognition',
+ placeholder: 'speech_recognition',
+ required: false,
+ type: 'text'
+ },
+ {
+ name: 'HUGGINGFACE_ACCESS_TOKEN',
+ description: `Secret for sending requests to the Hugging Face API. Learn more.`,
+ placeholder: 'hf_MUvn...',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'chat-with-perplexity-ai',
+ name: 'Chat with Perplexity AI',
+ tagline: 'Create a chatbot using the Perplexity AI API.',
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/chat-with-perplexity-ai'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'PERPLEXITY_API_KEY',
+ description: `A unique key used to authenticate with the Perplexity API. Learn more.`,
+ placeholder: `pplex-68...999`,
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'PERPLEXITY_MAX_TOKENS',
+ description: `The maximum number of tokens to generate. Learn more.`,
+ placeholder: `512`,
+ required: false,
+ type: 'number'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'generate-with-replicate',
+ name: 'Generate with Replicate',
+ tagline: "Generate text, audio and images using Replicate's API.",
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 300,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/generate-with-replicate'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'REPLICATE_API_KEY',
+ description: `A unique key used to authenticate with the Replicate API. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'chat-with-perplexity-ai',
+ name: 'Chat with Perplexity AI',
+ tagline: 'Create a chatbot using the Perplexity AI API.',
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/chat-with-perplexity-ai'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'PERPLEXITY_API_KEY',
+ description: `A unique key used to authenticate with the Perplexity API. Learn more.`,
+ placeholder: `pplex-68...999`,
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'PERPLEXITY_MAX_TOKENS',
+ description: `The maximum number of tokens to generate. Learn more.`,
+ placeholder: `512`,
+ required: false,
+ type: 'number'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'generate-with-replicate',
+ name: 'Generate with Replicate',
+ tagline: "Generate text, audio and images using Replicate's API.",
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 300,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/generate-with-replicate'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'REPLICATE_API_KEY',
+ description: `A unique key used to authenticate with the Replicate API. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'sync-with-pinecone',
+ name: 'Sync with Pinecone',
+ tagline: "Sync your Appwrite database with Pinecone's vector database.",
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 30,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/sync-with-pinecone'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'OPENAI_API_KEY',
+ description: `A unique key used to authenticate with the OpenAI API. This is a paid service and you will be charged for each request made to the API. Learn more.`,
+ value: '',
+ placeholder: 'sk-wzG...vcy',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'PINECONE_API_KEY',
+ description: `A unique key used to authenticate with the Pinecone API. Learn more.`,
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'PINECONE_INDEX_NAME',
+ description: `The name of the index in Pinecone. Learn more.`,
+ placeholder: 'my-index',
+ required: true,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the documents are stored. Learn more.`,
+ placeholder: 'my-database',
+ required: true,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the documents are stored. Learn more.`,
+ placeholder: 'my-collection',
+ required: true,
+ type: 'text'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'rag-with-langchain',
+ name: 'RAG with LangChain',
+ tagline: 'Generate text using a LangChain RAG model',
+ permissions: ['any'],
+ events: [],
+ cron: '',
+ timeout: 30,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/rag-with-langchain'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'OPENAI_API_KEY',
+ description: `A unique key used to authenticate with the OpenAI API. This is a paid service and you will be charged for each request made to the API. Learn more.`,
+ value: '',
+ placeholder: 'sk-wzG...vcy',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'PINECONE_API_KEY',
+ description: `A unique key used to authenticate with the Pinecone API. Learn more.`,
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'PINECONE_INDEX_NAME',
+ description: `The name of the index in Pinecone. Learn more.`,
+ placeholder: 'my-index',
+ required: true,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the documents are stored. Learn more.`,
+ placeholder: 'my-database',
+ required: true,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the documents are stored. Learn more.`,
+ placeholder: 'my-collection',
+ required: true,
+ type: 'text'
+ }
+ ]
+ },
+ {
+ icon: 'icon-chip',
+ id: 'speak-with-elevenlabs',
+ name: 'Speak with ElevenLabs',
+ tagline: 'Convert text to speech using the ElevenLabs API.',
+ permissions: ['any'],
+ cron: '',
+ events: [],
+ timeout: 15,
+ usecases: ['AI'],
+ runtimes: [
+ ...getRuntimes(
+ TemplateRuntimes.NODE,
+ 'npm install',
+ 'src/main.js',
+ 'node/speak-with-elevenlabs'
+ )
+ ],
+ instructions: `For documentation and instructions check out file.`,
+ vcsProvider: 'github',
+ providerRepositoryId: 'templates',
+ providerOwner: 'appwrite',
+ providerBranch: 'main',
+ variables: [
+ {
+ name: 'ELEVENLABS_API_KEY',
+ description: `A unique key used to authenticate with the ElevenLabs API. Learn more.`,
+ placeholder: 'd03xxxxxxxx26',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_API_KEY',
+ description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`,
+ value: '',
+ placeholder: 'd1efb...aec35',
+ required: true,
+ type: 'password'
+ },
+ {
+ name: 'APPWRITE_ENDPOINT',
+ description: `The URL endpoint of the Appwrite server. Learn more.`,
+ value: 'https://cloud.appwrite.io/v1',
+ placeholder: 'https://cloud.appwrite.io/v1',
+ required: false,
+ type: 'url'
+ },
+ {
+ name: 'APPWRITE_DATABASE_ID',
+ description: `The ID of the database where the responses are stored. Learn more.`,
+ placeholder: 'my-database',
+ required: true,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_COLLECTION_ID',
+ description: `The ID of the collection where the responses are stored. Learn more.`,
+ placeholder: 'my-collection',
+ required: true,
+ type: 'text'
+ },
+ {
+ name: 'APPWRITE_BUCKET_ID',
+ description: `The ID of the bucket where audio is stored. Learn more.`,
+ placeholder: 'generated_speech',
+ required: true,
+ type: 'text'
+ }
+ ]
}
];
From ec6a93cdc3e709d0a4612e5a437b7b5e7c4c9891 Mon Sep 17 00:00:00 2001
From: loks0n <22452787+loks0n@users.noreply.github.com>
Date: Tue, 2 Apr 2024 15:27:11 +0100
Subject: [PATCH 10/46] chore: remove duplicate perplexity
---
src/lib/stores/marketplace.ts | 40 -----------------------------------
1 file changed, 40 deletions(-)
diff --git a/src/lib/stores/marketplace.ts b/src/lib/stores/marketplace.ts
index e7190d2a3..02484e498 100644
--- a/src/lib/stores/marketplace.ts
+++ b/src/lib/stores/marketplace.ts
@@ -1261,46 +1261,6 @@ export const marketplace: MarketplaceTemplate[] = [
}
]
},
- {
- icon: 'icon-chip',
- id: 'chat-with-perplexity-ai',
- name: 'Chat with Perplexity AI',
- tagline: 'Create a chatbot using the Perplexity AI API.',
- permissions: ['any'],
- events: [],
- cron: '',
- timeout: 15,
- usecases: ['AI'],
- runtimes: [
- ...getRuntimes(
- TemplateRuntimes.NODE,
- 'npm install',
- 'src/main.js',
- 'node/chat-with-perplexity-ai'
- )
- ],
- instructions: `For documentation and instructions check out file.`,
- vcsProvider: 'github',
- providerRepositoryId: 'templates',
- providerOwner: 'appwrite',
- providerBranch: 'main',
- variables: [
- {
- name: 'PERPLEXITY_API_KEY',
- description: `A unique key used to authenticate with the Perplexity API. Learn more.`,
- placeholder: `pplex-68...999`,
- required: true,
- type: 'password'
- },
- {
- name: 'PERPLEXITY_MAX_TOKENS',
- description: `The maximum number of tokens to generate. Learn more.`,
- placeholder: `512`,
- required: false,
- type: 'number'
- }
- ]
- },
{
icon: 'icon-chip',
id: 'generate-with-replicate',
From 95dc555ee3a02577056c39c701b2fdf08a107043 Mon Sep 17 00:00:00 2001
From: Arman
Date: Tue, 2 Apr 2024 17:23:12 +0200
Subject: [PATCH 11/46] fix: race condition during invalidation
---
.../function-[function]/settings/+page.svelte | 11 +++++------
.../console/project-[project]/updateVariables.svelte | 8 +++++---
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte
index 4dac5f427..2384dc1bd 100644
--- a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte
+++ b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte
@@ -24,21 +24,20 @@
const sdkCreateVariable = async (key: string, value: string) => {
await sdk.forProject.functions.createVariable($func.$id, key, value);
- await invalidate(Dependencies.VARIABLES);
- await invalidate(Dependencies.FUNCTION);
+ await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]);
};
const sdkUpdateVariable = async (variableId: string, key: string, value: string) => {
await sdk.forProject.functions.updateVariable($func.$id, variableId, key, value);
- await invalidate(Dependencies.VARIABLES);
- await invalidate(Dependencies.FUNCTION);
+ await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]);
};
const sdkDeleteVariable = async (variableId: string) => {
await sdk.forProject.functions.deleteVariable($func.$id, variableId);
- await invalidate(Dependencies.VARIABLES);
- await invalidate(Dependencies.FUNCTION);
+ await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]);
};
+
+ $: console.log(data.variables);
diff --git a/src/routes/console/project-[project]/updateVariables.svelte b/src/routes/console/project-[project]/updateVariables.svelte
index 8a17fa61d..892ed7ef4 100644
--- a/src/routes/console/project-[project]/updateVariables.svelte
+++ b/src/routes/console/project-[project]/updateVariables.svelte
@@ -138,9 +138,11 @@
selectedVar = null;
showPromoteModal = false;
- await invalidate(Dependencies.FUNCTION);
- await invalidate(Dependencies.VARIABLES);
- await invalidate(Dependencies.PROJECT_VARIABLES);
+ await Promise.all([
+ await invalidate(Dependencies.FUNCTION),
+ await invalidate(Dependencies.VARIABLES),
+ await invalidate(Dependencies.PROJECT_VARIABLES)
+ ]);
addNotification({
type: 'success',
From 230a7621b446d9f5976b383b722b781a4deabb00 Mon Sep 17 00:00:00 2001
From: Arman
Date: Tue, 2 Apr 2024 17:23:49 +0200
Subject: [PATCH 12/46] remove console log
---
.../functions/function-[function]/settings/+page.svelte | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte
index 2384dc1bd..db5149a6a 100644
--- a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte
+++ b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte
@@ -36,8 +36,6 @@
await sdk.forProject.functions.deleteVariable($func.$id, variableId);
await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]);
};
-
- $: console.log(data.variables);
From b79e0347a5dcaffa1393b0bb39ba60ad3d6a879d Mon Sep 17 00:00:00 2001
From: Arman
Date: Tue, 2 Apr 2024 17:30:40 +0200
Subject: [PATCH 13/46] fix: upload wizard not closing
---
.../storage/bucket-[bucket]/create-file/create.svelte | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte
index 99c989561..aeed538c9 100644
--- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte
+++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte
@@ -29,7 +29,7 @@
async function create() {
try {
- await uploader.uploadFile(
+ uploader.uploadFile(
bucketId,
$createFile.id ?? ID.unique(),
$createFile.files[0],
From b3b42ee512fd89c7b5240eae1ea8f130737a564c Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 3 Apr 2024 14:03:13 +0200
Subject: [PATCH 14/46] feat: add downgrade alerts
---
.../confirmDetails.svelte | 26 +++++++++++++++----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
index a67c5086e..b89bc897c 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
@@ -1,5 +1,5 @@
{#if $organization}
@@ -54,7 +56,7 @@
{tierToPlan($organization?.billingPlan)?.name} plan
- {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && }
+ {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && !TRIAL_PERIOD_OVERRIDE}
TRIAL
{/if}
From 806c71bcc00142688405a474a95a8364199cc649 Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 3 Apr 2024 14:12:36 +0200
Subject: [PATCH 16/46] copy fix
---
.../console/organization-[organization]/billing/+page.svelte | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte
index 379814dd1..6095081f8 100644
--- a/src/routes/console/organization-[organization]/billing/+page.svelte
+++ b/src/routes/console/organization-[organization]/billing/+page.svelte
@@ -95,9 +95,8 @@
{/if}
{#if $organization?.billingPlanDowngrade}
- Your organization will change to a Starter plan once your current billing cycle ends on {toLocaleDate(
- $organization.billingNextInvoiceDate
- )}.
+ Your organization will change to a Starter plan once your current billing cycle ends and
+ your invoice is paid on {toLocaleDate($organization.billingNextInvoiceDate)}.
{/if}
From dae1177ba00942efb034ad4f73eb63dd2dd41e49 Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 3 Apr 2024 14:14:55 +0200
Subject: [PATCH 17/46] fix: date
---
.../wizard/cloudOrganizationChangeTier/confirmDetails.svelte | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
index b89bc897c..8c1a3e3da 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
@@ -62,11 +62,11 @@
Your {tierToPlan($organization.billingPlan).name} plan subscription will end on {toLocaleDate(
- $organization.billingCurrentInvoiceDate
+ $organization.billingNextInvoiceDate
)}
Following the payment of your final invoice on {toLocaleDate(
- $organization.billingCurrentInvoiceDate
+ $organization.billingNextInvoiceDate
)}, your organization will switch to the {tierToPlan(
$changeOrganizationTier.billingPlan
).name} plan. Until then, you can continue to use the resources available to the {tierToPlan(
From e2dd89338fa09bc150bbad867d7197a6b35d334c Mon Sep 17 00:00:00 2001
From: loks0n <22452787+loks0n@users.noreply.github.com>
Date: Fri, 5 Apr 2024 15:31:43 +0100
Subject: [PATCH 18/46] feat: hide python-ml
---
src/routes/console/project-[project]/functions/store.ts | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts
index 3acf62136..4a52582a7 100644
--- a/src/routes/console/project-[project]/functions/store.ts
+++ b/src/routes/console/project-[project]/functions/store.ts
@@ -2,10 +2,11 @@ import { page } from '$app/stores';
import { derived } from 'svelte/store';
import type { Models } from '@appwrite.io/console';
-export const runtimesList = derived(
- page,
- async ($page) => (await $page.data.runtimesList) as Models.RuntimeList
-);
+export const runtimesList = derived(page, async ($page) => {
+ const { runtimes } = (await $page.data.runtimes) as Models.RuntimeList;
+ const filtered = runtimes.filter((runtime) => !runtime.name.startsWith('python-ml'));
+ return { runtimes: filtered, total: filtered.length };
+});
export const baseRuntimesList = derived(runtimesList, async ($runtimesList) => {
const baseRuntimes = new Map();
From 04ac6cc5cf97dd2561dce33036abd5e349cca504 Mon Sep 17 00:00:00 2001
From: Arman
Date: Fri, 5 Apr 2024 16:56:05 +0200
Subject: [PATCH 19/46] feat: add `limitReached` banner and delete previous
modal
---
.../billing/alerts/limitReached.svelte | 43 +++++++
src/lib/layout/header.svelte | 14 ---
src/lib/stores/billing.ts | 24 +++-
src/routes/console/+layout.svelte | 6 +-
.../excesLimitModal.svelte | 106 ------------------
.../organization-[organization]/store.ts | 3 +-
.../usage/[[invoice]]/+page.svelte | 3 +-
.../settings/usage/[[invoice]]/+page.svelte | 5 +-
8 files changed, 74 insertions(+), 130 deletions(-)
create mode 100644 src/lib/components/billing/alerts/limitReached.svelte
delete mode 100644 src/routes/console/organization-[organization]/excesLimitModal.svelte
diff --git a/src/lib/components/billing/alerts/limitReached.svelte b/src/lib/components/billing/alerts/limitReached.svelte
new file mode 100644
index 000000000..9844136b6
--- /dev/null
+++ b/src/lib/components/billing/alerts/limitReached.svelte
@@ -0,0 +1,43 @@
+
+
+{#if $organization?.$id && $organization?.billingPlan === BillingPlan.STARTER && $readOnly && !$page.url.pathname.includes('/console/account')}
+
+
+ Usage for the {$organization.name} organization has reached the limits of the Starter
+ plan. Consider upgrading to increase your resource usage.
+
+
+
+
+
+
+{/if}
diff --git a/src/lib/layout/header.svelte b/src/lib/layout/header.svelte
index 9dbc534c5..16c97001a 100644
--- a/src/lib/layout/header.svelte
+++ b/src/lib/layout/header.svelte
@@ -24,9 +24,6 @@
import CreateOrganizationCloud from '$routes/console/createOrganizationCloud.svelte';
import { Feedback } from '$lib/components/feedback';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
- import { Pill } from '$lib/elements';
- import { showExcess } from '$routes/console/organization-[organization]/store';
- import { readOnly } from '$lib/stores/billing';
import { BillingPlan } from '$lib/constants';
let showDropdown = false;
@@ -105,17 +102,6 @@
{/if}
-{#if !$page.url.pathname.includes('/console/account') && $readOnly}
-
- ($showExcess = true)}>
-
-
- limit reached
-
-
-
-{/if}
-
Bandwidth
-
Calculated for all bandwidth used in your project.
+
+ Calculated for all bandwidth used across your project. Resets at the start of each
+ billing cycle.
+
{#if network}
{@const humanized = humanFileSize(total(network))}
From ada46586e8a547ba117b82e6acf82cf7b2e24d1e Mon Sep 17 00:00:00 2001
From: Arman
Date: Fri, 5 Apr 2024 17:15:17 +0200
Subject: [PATCH 20/46] feat: add notificaiton for when a service is over the
75% mark
---
src/lib/stores/billing.ts | 62 +++++++++++++++++++++++++++++----------
1 file changed, 46 insertions(+), 16 deletions(-)
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index 8155f4a4a..50f03d7a4 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -24,6 +24,10 @@ import { BillingPlan } from '$lib/constants';
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 { wizard } from './wizard';
+import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
+import { trackEvent } from '$lib/actions/analytics';
+import { browser } from '$app/environment';
export type Tier = 'tier-0' | 'tier-1' | 'tier-2';
@@ -189,19 +193,20 @@ export async function checkForUsageLimit(org: Organization) {
return;
}
const { bandwidth, documents, executions, storage, users } = org?.billingLimits ?? {};
+ const resources = [
+ { value: bandwidth, name: 'bandwidth' },
+ { value: documents, name: 'documents' },
+ { value: executions, name: 'executions' },
+ { value: storage, name: 'storage' },
+ { value: users, name: 'users' }
+ ];
+
const members = await sdk.forConsole.teams.listMemberships(org.$id);
const plan = get(plansInfo)?.get(org.billingPlan);
const membersOverflow =
members?.total > plan.members ? members.total - (plan.members || members.total) : 0;
- if (
- bandwidth >= 100 ||
- documents >= 100 ||
- executions >= 100 ||
- storage >= 100 ||
- users >= 100 ||
- membersOverflow > 0
- ) {
+ if (resources.some((r) => r.value >= 100) || membersOverflow > 0) {
readOnly.set(true);
headerAlert.add({
id: 'limitReached',
@@ -209,15 +214,40 @@ export async function checkForUsageLimit(org: Organization) {
show: true,
importance: 7
});
- } else if (
- bandwidth >= 75 ||
- documents >= 75 ||
- executions >= 75 ||
- storage >= 75 ||
- users >= 75
- ) {
+ } else if (resources.some((r) => r.value >= 75)) {
readOnly.set(false);
- //show notification
+ if (browser) {
+ const lastNotification =
+ parseInt(localStorage.getItem('limitReachedNotification')) ?? 0;
+ const now = new Date().getTime();
+ if (now - lastNotification < 1000 * 60 * 60 * 24 * 3) return;
+
+ localStorage.setItem('limitReachedNotification', now.toString());
+ addNotification({
+ type: 'warning',
+ isHtml: true,
+ timeout: 0,
+ message: `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`,
+ buttons: [
+ {
+ name: 'View usage',
+ method: () => {
+ goto(`${base}/console/organization-${org.$id}/usage`);
+ }
+ },
+ {
+ name: 'Upgrade plan',
+ method: () => {
+ wizard.start(ChangeOrganizationTierCloud);
+ trackEvent('click_organization_upgrade', {
+ from: 'button',
+ source: 'limit_reached_notification'
+ });
+ }
+ }
+ ]
+ });
+ }
} else {
readOnly.set(false);
}
From 9210a73b412e4e9f4fb6282da87f1355c4b5b468 Mon Sep 17 00:00:00 2001
From: loks0n <22452787+loks0n@users.noreply.github.com>
Date: Fri, 5 Apr 2024 18:22:00 +0100
Subject: [PATCH 21/46] fix: runtimes list
---
src/routes/console/project-[project]/functions/store.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts
index 4a52582a7..8e8c7db77 100644
--- a/src/routes/console/project-[project]/functions/store.ts
+++ b/src/routes/console/project-[project]/functions/store.ts
@@ -3,7 +3,7 @@ import { derived } from 'svelte/store';
import type { Models } from '@appwrite.io/console';
export const runtimesList = derived(page, async ($page) => {
- const { runtimes } = (await $page.data.runtimes) as Models.RuntimeList;
+ const { runtimes } = (await $page.data.runtimesList) as Models.RuntimeList;
const filtered = runtimes.filter((runtime) => !runtime.name.startsWith('python-ml'));
return { runtimes: filtered, total: filtered.length };
});
From 4d5950a6372d7cbf0c25f178a915ae45444692f7 Mon Sep 17 00:00:00 2001
From: loks0n <22452787+loks0n@users.noreply.github.com>
Date: Fri, 5 Apr 2024 19:05:55 +0100
Subject: [PATCH 22/46] fix: runtimes list
---
src/routes/console/project-[project]/functions/store.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts
index 8e8c7db77..172a5ce42 100644
--- a/src/routes/console/project-[project]/functions/store.ts
+++ b/src/routes/console/project-[project]/functions/store.ts
@@ -4,7 +4,7 @@ import type { Models } from '@appwrite.io/console';
export const runtimesList = derived(page, async ($page) => {
const { runtimes } = (await $page.data.runtimesList) as Models.RuntimeList;
- const filtered = runtimes.filter((runtime) => !runtime.name.startsWith('python-ml'));
+ const filtered = runtimes.filter((runtime) => !runtime.$id.startsWith('python-ml'));
return { runtimes: filtered, total: filtered.length };
});
From 330a447196011ec3841b7431807bcc135265d505 Mon Sep 17 00:00:00 2001
From: Arman
Date: Mon, 8 Apr 2024 13:26:41 +0200
Subject: [PATCH 23/46] feat: show notification once a day
---
src/lib/stores/billing.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index 50f03d7a4..362dcdf6e 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -220,7 +220,7 @@ export async function checkForUsageLimit(org: Organization) {
const lastNotification =
parseInt(localStorage.getItem('limitReachedNotification')) ?? 0;
const now = new Date().getTime();
- if (now - lastNotification < 1000 * 60 * 60 * 24 * 3) return;
+ if (now - lastNotification < 1000 * 60 * 60 * 24) return;
localStorage.setItem('limitReachedNotification', now.toString());
addNotification({
From 6e09e6cc756de7d58e984b2692737c26e062bfa8 Mon Sep 17 00:00:00 2001
From: Arman
Date: Mon, 8 Apr 2024 13:32:18 +0200
Subject: [PATCH 24/46] feat: update message
---
src/lib/stores/billing.ts | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index 362dcdf6e..be97eab8a 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -223,11 +223,15 @@ export async function checkForUsageLimit(org: Organization) {
if (now - lastNotification < 1000 * 60 * 60 * 24) return;
localStorage.setItem('limitReachedNotification', now.toString());
+ let message = `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
+ if (resources.filter((r) => r.value >= 75)?.length > 1) {
+ message = `Usage for ${org.name} has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`;
+ }
addNotification({
type: 'warning',
isHtml: true,
timeout: 0,
- message: `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`,
+ message,
buttons: [
{
name: 'View usage',
From 3da6609257e0afd197bd94705b21c3662b6aece7 Mon Sep 17 00:00:00 2001
From: Arman
Date: Mon, 8 Apr 2024 15:08:14 +0200
Subject: [PATCH 25/46] chore: remove old upload modal
---
.../storage/bucket-[bucket]/create.svelte | 105 ------------------
1 file changed, 105 deletions(-)
delete mode 100644 src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte
diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte
deleted file mode 100644
index 209f1ded2..000000000
--- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
- The {isBackup ? 'backup' : 'default'} payment method cannot be deleted as
+ The {isBackup ? 'backup' : 'default'} payment method cannot be removed as
{$organization?.name}
- has an upcoming invoice. To proceed with deletion, set a {isBackup
- ? 'default'
- : 'backup'} or add a new {isBackup ? 'backup' : 'default'} payment method.
+ has an upcoming invoice. To proceed, set a {isBackup ? 'default' : 'backup'} or add a new
+ {isBackup ? 'backup' : 'default'} payment method.
- Are you sure you want to delete the payment method from {$organization?.name}?
+ Are you sure you want to remove the payment method from {$organization?.name}?
-
+
{/if}
diff --git a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte
index ae44de05e..5a41e40a7 100644
--- a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte
+++ b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte
@@ -137,7 +137,7 @@
showDelete = true;
showDropdown = false;
}}>
- Delete
+ Remove
From cd550315df9865e9e977c82cafbd50a342705807 Mon Sep 17 00:00:00 2001
From: Arman
Date: Tue, 9 Apr 2024 15:34:12 +0200
Subject: [PATCH 32/46] fix: retry payment modal No method selected when the
organization paymentMethod belongs to someone else
---
.../billing/retryPaymentModal.svelte | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte b/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte
index e0f034029..06dde940f 100644
--- a/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte
+++ b/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte
@@ -30,8 +30,21 @@
let paymentMethodId: string;
let setAsDefault = false;
- onMount(() => {
- paymentMethodId = $organization.paymentMethodId;
+ onMount(async () => {
+ if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) {
+ paymentMethodId = $paymentMethods?.total ? $paymentMethods.paymentMethods[0].$id : null;
+ } else {
+ paymentMethodId = $organization.paymentMethodId
+ ? $organization.paymentMethodId
+ : $organization.backupPaymentMethodId;
+ // If the selected payment method does not belong to the current user, select the first one.
+ if (
+ $paymentMethods?.total &&
+ !$paymentMethods.paymentMethods.some((method) => method.$id === paymentMethodId)
+ ) {
+ paymentMethodId = $paymentMethods.paymentMethods[0].$id;
+ }
+ }
});
async function handleSubmit() {
From 01f1d4f6621707fdf19cf3c2fdca85777d9a5b5f Mon Sep 17 00:00:00 2001
From: Arman
Date: Tue, 9 Apr 2024 16:26:55 +0200
Subject: [PATCH 33/46] chore: remove browser check
---
src/lib/stores/billing.ts | 66 ++++++++++++++++++---------------------
1 file changed, 31 insertions(+), 35 deletions(-)
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index be97eab8a..3d827cf5c 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -27,7 +27,6 @@ import LimitReached from '$lib/components/billing/alerts/limitReached.svelte';
import { wizard } from './wizard';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
import { trackEvent } from '$lib/actions/analytics';
-import { browser } from '$app/environment';
export type Tier = 'tier-0' | 'tier-1' | 'tier-2';
@@ -216,42 +215,39 @@ export async function checkForUsageLimit(org: Organization) {
});
} else if (resources.some((r) => r.value >= 75)) {
readOnly.set(false);
- if (browser) {
- const lastNotification =
- parseInt(localStorage.getItem('limitReachedNotification')) ?? 0;
- const now = new Date().getTime();
- if (now - lastNotification < 1000 * 60 * 60 * 24) return;
+ const lastNotification = parseInt(localStorage.getItem('limitReachedNotification')) ?? 0;
+ const now = new Date().getTime();
+ if (now - lastNotification < 1000 * 60 * 60 * 24) return;
- localStorage.setItem('limitReachedNotification', now.toString());
- let message = `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
- if (resources.filter((r) => r.value >= 75)?.length > 1) {
- message = `Usage for ${org.name} has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`;
- }
- addNotification({
- type: 'warning',
- isHtml: true,
- timeout: 0,
- message,
- buttons: [
- {
- name: 'View usage',
- method: () => {
- goto(`${base}/console/organization-${org.$id}/usage`);
- }
- },
- {
- name: 'Upgrade plan',
- method: () => {
- wizard.start(ChangeOrganizationTierCloud);
- trackEvent('click_organization_upgrade', {
- from: 'button',
- source: 'limit_reached_notification'
- });
- }
- }
- ]
- });
+ localStorage.setItem('limitReachedNotification', now.toString());
+ let message = `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
+ if (resources.filter((r) => r.value >= 75)?.length > 1) {
+ message = `Usage for ${org.name} has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`;
}
+ addNotification({
+ type: 'warning',
+ isHtml: true,
+ timeout: 0,
+ message,
+ buttons: [
+ {
+ name: 'View usage',
+ method: () => {
+ goto(`${base}/console/organization-${org.$id}/usage`);
+ }
+ },
+ {
+ name: 'Upgrade plan',
+ method: () => {
+ wizard.start(ChangeOrganizationTierCloud);
+ trackEvent('click_organization_upgrade', {
+ from: 'button',
+ source: 'limit_reached_notification'
+ });
+ }
+ }
+ ]
+ });
} else {
readOnly.set(false);
}
From 240eda2619d1212f36862c7eccc4444b8c7d8d0e Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 10 Apr 2024 15:35:20 +0200
Subject: [PATCH 34/46] chore: rename variable for more clarity
---
src/lib/stores/billing.ts | 4 ++--
src/lib/system.ts | 2 +-
src/routes/console/account/organizations/+page.svelte | 4 ++--
.../billing/planSummary.svelte | 6 +++---
.../console/organization-[organization]/header.svelte | 5 ++---
.../wizard/cloudOrganization/confirmDetails.svelte | 6 +++---
.../cloudOrganization/organizationDetails.svelte | 4 ++--
.../wizard/cloudOrganization/paymentDetails.svelte | 8 ++------
src/routes/console/wizard/cloudOrganization/store.ts | 4 ++--
.../cloudOrganizationChangeTier/choosePlan.svelte | 4 ++--
.../cloudOrganizationChangeTier/confirmDetails.svelte | 10 +++++-----
.../wizard/cloudOrganizationChangeTier/store.ts | 4 ++--
12 files changed, 28 insertions(+), 33 deletions(-)
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index 1a00cc840..1462f5125 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -10,7 +10,7 @@ import type {
PlansMap,
PaymentMethodData
} from '$lib/sdk/billing';
-import { TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system';
+import { IS_TRIAL_DISABLED, isCloud } from '$lib/system';
import { cachedStore } from '$lib/helpers/cache';
import { Query } from '@appwrite.io/console';
import { headerAlert } from './headerAlert';
@@ -169,7 +169,7 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num
}
export function calculateTrialDay(org: Organization) {
- if (TRIAL_PERIOD_OVERRIDE) return;
+ if (IS_TRIAL_DISABLED) return;
if (org?.billingPlan === BillingPlan.STARTER) return false;
const endDate = new Date(org?.billingStartDate);
const today = new Date();
diff --git a/src/lib/system.ts b/src/lib/system.ts
index 521833161..adc04027e 100644
--- a/src/lib/system.ts
+++ b/src/lib/system.ts
@@ -24,4 +24,4 @@ export const isCloud = MODE === Mode.CLOUD;
export const isSelfHosted = MODE !== Mode.CLOUD;
export const hasStripePublicKey = !!VARS.STRIPE_PUBLIC_KEY;
export const GRACE_PERIOD_OVERRIDE = false;
-export const TRIAL_PERIOD_OVERRIDE = true;
+export const IS_TRIAL_DISABLED = true;
diff --git a/src/routes/console/account/organizations/+page.svelte b/src/routes/console/account/organizations/+page.svelte
index 33b397915..be2b778a2 100644
--- a/src/routes/console/account/organizations/+page.svelte
+++ b/src/routes/console/account/organizations/+page.svelte
@@ -13,7 +13,7 @@
import CreateOrganization from '../../createOrganization.svelte';
import { sdk } from '$lib/stores/sdk';
import type { PageData } from './$types';
- import { TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system';
+ import { IS_TRIAL_DISABLED, isCloud } from '$lib/system';
import { Pill } from '$lib/elements';
import type { Models } from '@appwrite.io/console';
import type { Organization } from '$lib/stores/organization';
@@ -82,7 +82,7 @@
FREE
diff --git a/src/routes/console/organization-[organization]/header.svelte b/src/routes/console/organization-[organization]/header.svelte
index 04213a412..7d8facfd9 100644
--- a/src/routes/console/organization-[organization]/header.svelte
+++ b/src/routes/console/organization-[organization]/header.svelte
@@ -19,8 +19,7 @@
} from '$lib/stores/organization';
import { wizard } from '$lib/stores/wizard';
import { GRACE_PERIOD_OVERRIDE, TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system';
- import CreateOrganizationCloud from '../createOrganizationCloud.svelte';
-
+ import CreateOrganizationCloud from '../createOrganizationCloud.sveltIS_TRIAL_ENABLED
let areMembersLimited: boolean;
$: organization.subscribe(() => {
const limit = getServiceLimit('members') || Infinity;
@@ -102,7 +101,7 @@
$organization.billingStartDate
)}. ${$daysLeftInTrial} days remaining.`
}}>
- TRIAL
+ TRIALIS_TRIAL_ENABLED
{/if}
diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
index 3be83c868..fac476d10 100644
--- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
@@ -9,7 +9,7 @@
import type { Coupon } from '$lib/sdk/billing';
import { plansInfo } from '$lib/stores/billing';
import { sdk } from '$lib/stores/sdk';
- import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
+ import { IS_TRIAL_DISABLED } from '$lib/system';
import { createOrganization, createOrganizationFinalAction } from './store';
const plan = $plansInfo?.get($createOrganization.billingPlan);
@@ -54,7 +54,7 @@
Confirm your details
- Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE
+ Confirm the details of your new organization{IS_TRIAL_DISABLED
? '.'
: ' and start your free trial.'}
@@ -126,7 +126,7 @@
{#if $createOrganization.billingPlan !== BillingPlan.STARTER}
This amount, and any additional usage fees, will be charged on a recurring 30-day
- billing cycle{TRIAL_PERIOD_OVERRIDE
+ billing cycle{IS_TRIAL_DISABLED
? '.'
: ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.
diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
index ef9231712..dfe8c80d6 100644
--- a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
@@ -8,7 +8,7 @@
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { organizationList, type Organization } from '$lib/stores/organization';
import { updateStepStatus } from '$lib/stores/wizard';
- import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
+ import { IS_TRIAL_DISABLED } from '$lib/system';
import { createOrganization, createOrgSteps } from './store';
let showCustomId = false;
@@ -109,7 +109,7 @@
{tierPro.description}
- {#if !TRIAL_PERIOD_OVERRIDE}
+ {#if !IS_TRIAL_DISABLED}
14 DAY FREE TRIAL
{/if}
diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
index ed4c76719..023f42ad0 100644
--- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
@@ -13,8 +13,7 @@
import { showUsageRatesModal } from '$lib/stores/billing';
import { PaymentBoxes } from '$lib/components/billing';
import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
-
- const today = new Date();
+IS_TRIAL_ENABLEDnew Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
let methods: PaymentList;
@@ -83,10 +82,7 @@
-
- (new Map());
export const createOrganizationFinalAction = writable(
- TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial'
+ IS_TRIAL_DISABLED ? 'Create' : 'Start trial'
);
export const createOrganization = writable<{
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
index da01e2449..d3fe6418b 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
@@ -15,8 +15,7 @@
import { formatCurrency } from '$lib/helpers/numbers';
import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
- let usage: OrganizationUsage = null;
- let members: Models.MembershipList = null;
+ IS_TRIAL_ENABLED let members: Models.MembershipList = null;
$: if ($changeOrganizationTier.billingPlan === BillingPlan.STARTER && $changeTierSteps) {
$changeTierSteps = updateStepStatus($changeTierSteps, 2, true);
@@ -142,6 +141,7 @@
This amount, and any additional usage fees, will be charged on a recurring 30-day
billing cycle{IS_TRIAL_DISABLED
- ? '.'
+ ? ''
: ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.
{/if}
diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
index 023f42ad0..5b03cee1e 100644
--- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
@@ -12,8 +12,9 @@
import { toLocaleDate } from '$lib/helpers/date';
import { showUsageRatesModal } from '$lib/stores/billing';
import { PaymentBoxes } from '$lib/components/billing';
- import { TRIAL_PERIOD_OVERRIDE } from '$lib/system';
-IS_TRIAL_ENABLEDnew Date();
+ import { IS_TRIAL_DISABLED } from '$lib/system';
+
+ const today = new Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
let methods: PaymentList;
@@ -74,15 +75,18 @@ IS_TRIAL_ENABLEDnew Date();
Payment details
- Add a payment method to your organization. {#if !TRIAL_PERIOD_OVERRIDE}You will not be
- charged until your trial ends on {toLocaleDate(billingPayDate.toString())}.
+ Add a payment method to your organization. {#if !IS_TRIAL_DISABLED}You will not be charged
+ until your trial ends on {toLocaleDate(billingPayDate.toString())}.
{/if}
+
+
- IS_TRIAL_ENABLED
{#if $organization.billingPlan === BillingPlan.PRO}
CURRENT PLAN
- {:else if !TRIAL_PERIOD_OVERRIDE}
+ {:else if !IS_TRIAL_DISABLED}
14 DAY FREE TRIAL
{/if}
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
index 7f29df8ee..dc5e16fb1 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
@@ -1,5 +1,5 @@
-
+
From becf053f33ccd6d864265bd02af944538d49fb83 Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 17 Apr 2024 12:04:55 +0200
Subject: [PATCH 42/46] chore: add tracking
---
src/lib/layout/wizard.svelte | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/lib/layout/wizard.svelte b/src/lib/layout/wizard.svelte
index e8e525572..145926af6 100644
--- a/src/lib/layout/wizard.svelte
+++ b/src/lib/layout/wizard.svelte
@@ -97,6 +97,7 @@
$wizard.nextDisabled = true;
if (finalMethod) {
await finalMethod();
+ trackEvent('wizard_finish');
$wizard.nextDisabled = false;
} else {
trackEvent('wizard_finish');
From 6d85d134ff6daf0674dbf52657b107dae8cfbcdf Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 17 Apr 2024 14:37:28 +0200
Subject: [PATCH 43/46] refactor: remove global variable and use backend data
---
src/lib/sdk/billing.ts | 1 +
src/lib/stores/billing.ts | 3 +--
src/lib/system.ts | 1 -
.../console/account/organizations/+page.svelte | 6 +++---
.../billing/planSummary.svelte | 5 ++---
.../organization-[organization]/header.svelte | 12 +++++++++---
.../wizard/cloudOrganization/confirmDetails.svelte | 5 ++---
.../cloudOrganization/organizationDetails.svelte | 3 +--
.../wizard/cloudOrganization/paymentDetails.svelte | 9 +++++----
src/routes/console/wizard/cloudOrganization/store.ts | 8 ++++----
.../cloudOrganizationChangeTier/choosePlan.svelte | 5 ++---
.../confirmDetails.svelte | 7 ++++---
.../wizard/cloudOrganizationChangeTier/store.ts | 8 ++++----
13 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index d935bd84e..0dda5f294 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -261,6 +261,7 @@ export type Plan = {
storage: AdditionalResource;
users: AdditionalResource;
};
+ trialDays: number;
};
export type PlansInfo = {
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index 1462f5125..fcdb3ab83 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -10,7 +10,7 @@ import type {
PlansMap,
PaymentMethodData
} from '$lib/sdk/billing';
-import { IS_TRIAL_DISABLED, isCloud } from '$lib/system';
+import { isCloud } from '$lib/system';
import { cachedStore } from '$lib/helpers/cache';
import { Query } from '@appwrite.io/console';
import { headerAlert } from './headerAlert';
@@ -169,7 +169,6 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num
}
export function calculateTrialDay(org: Organization) {
- if (IS_TRIAL_DISABLED) return;
if (org?.billingPlan === BillingPlan.STARTER) return false;
const endDate = new Date(org?.billingStartDate);
const today = new Date();
diff --git a/src/lib/system.ts b/src/lib/system.ts
index adc04027e..5cb998dca 100644
--- a/src/lib/system.ts
+++ b/src/lib/system.ts
@@ -24,4 +24,3 @@ export const isCloud = MODE === Mode.CLOUD;
export const isSelfHosted = MODE !== Mode.CLOUD;
export const hasStripePublicKey = !!VARS.STRIPE_PUBLIC_KEY;
export const GRACE_PERIOD_OVERRIDE = false;
-export const IS_TRIAL_DISABLED = true;
diff --git a/src/routes/console/account/organizations/+page.svelte b/src/routes/console/account/organizations/+page.svelte
index be2b778a2..33811a134 100644
--- a/src/routes/console/account/organizations/+page.svelte
+++ b/src/routes/console/account/organizations/+page.svelte
@@ -13,11 +13,11 @@
import CreateOrganization from '../../createOrganization.svelte';
import { sdk } from '$lib/stores/sdk';
import type { PageData } from './$types';
- import { IS_TRIAL_DISABLED, isCloud } from '$lib/system';
+ import { isCloud } from '$lib/system';
import { Pill } from '$lib/elements';
import type { Models } from '@appwrite.io/console';
import type { Organization } from '$lib/stores/organization';
- import { daysLeftInTrial } from '$lib/stores/billing';
+ import { daysLeftInTrial, plansInfo } from '$lib/stores/billing';
import { tooltip } from '$lib/actions/tooltip';
import { toLocaleDate } from '$lib/helpers/date';
import { wizard } from '$lib/stores/wizard';
@@ -82,7 +82,7 @@
FREE
{/if}
- {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && !IS_TRIAL_DISABLED}
+ {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && $plansInfo.get(organization.billingPlan)?.trialDays}
Confirm your details
- Confirm the details of your new organization{IS_TRIAL_DISABLED
+ Confirm the details of your new organization{!plan.trialDays
? '.'
: ' and start your free trial.'}
@@ -126,7 +125,7 @@
{#if $createOrganization.billingPlan !== BillingPlan.STARTER}
This amount, and any additional usage fees, will be charged on a recurring 30-day
- billing cycle{IS_TRIAL_DISABLED
+ billing cycle{!plan.trialDays
? ''
: ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.
diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
index dfe8c80d6..67bed9a75 100644
--- a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte
@@ -8,7 +8,6 @@
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { organizationList, type Organization } from '$lib/stores/organization';
import { updateStepStatus } from '$lib/stores/wizard';
- import { IS_TRIAL_DISABLED } from '$lib/system';
import { createOrganization, createOrgSteps } from './store';
let showCustomId = false;
@@ -109,7 +108,7 @@
{tierPro.description}
diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
index 5b03cee1e..956064b66 100644
--- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte
@@ -10,9 +10,8 @@
import { initializeStripe, isStripeInitialized, submitStripeCard } from '$lib/stores/stripe';
import { sdk } from '$lib/stores/sdk';
import { toLocaleDate } from '$lib/helpers/date';
- import { showUsageRatesModal } from '$lib/stores/billing';
+ import { plansInfo, showUsageRatesModal } from '$lib/stores/billing';
import { PaymentBoxes } from '$lib/components/billing';
- import { IS_TRIAL_DISABLED } from '$lib/system';
const today = new Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
@@ -75,8 +74,10 @@
Payment details
- Add a payment method to your organization. {#if !IS_TRIAL_DISABLED}You will not be charged
- until your trial ends on {toLocaleDate(billingPayDate.toString())}.
+ Add a payment method to your organization. {#if $plansInfo.get($createOrganization.billingPlan)?.trialDays}You
+ will not be charged until your trial ends on {toLocaleDate(billingPayDate.toString())}.
{/if}
diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts
index 73b050b60..f25d7d5f8 100644
--- a/src/routes/console/wizard/cloudOrganization/store.ts
+++ b/src/routes/console/wizard/cloudOrganization/store.ts
@@ -1,12 +1,12 @@
import { BillingPlan } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
-import type { Tier } from '$lib/stores/billing';
-import { IS_TRIAL_DISABLED } from '$lib/system';
-import { writable } from 'svelte/store';
+import { plansInfo, type Tier } from '$lib/stores/billing';
+import { organization } from '$lib/stores/organization';
+import { get, writable } from 'svelte/store';
export const createOrgSteps = writable(new Map());
export const createOrganizationFinalAction = writable(
- IS_TRIAL_DISABLED ? 'Create' : 'Start trial'
+ get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create'
);
export const createOrganization = writable<{
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
index ad1d62aa1..84b9ff788 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte
@@ -13,7 +13,6 @@
import { Pill } from '$lib/elements';
import { BillingPlan } from '$lib/constants';
import { formatCurrency } from '$lib/helpers/numbers';
- import { IS_TRIAL_DISABLED } from '$lib/system';
let usage: OrganizationUsage = null;
let members: Models.MembershipList = null;
@@ -162,8 +161,8 @@
{#if $organization.billingPlan === BillingPlan.PRO}
CURRENT PLAN
- {:else if !IS_TRIAL_DISABLED}
- 14 DAY FREE TRIAL
+ {:else if proPlan?.trialDays}
+ {proPlan?.trialDays} DAY FREE TRIAL
{/if}
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
index dc5e16fb1..9b87670bf 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
@@ -16,7 +16,6 @@
feedbackDowngradeOptions,
isUpgrade
} from './store';
- import { IS_TRIAL_DISABLED } from '$lib/system';
const plan = $plansInfo.get($changeOrganizationTier.billingPlan);
const collaboratorPrice = plan?.addons.member?.price ?? 0;
@@ -78,7 +77,9 @@
Confirm your details
- Confirm the details of your new organization{IS_TRIAL_DISABLED
+ Confirm the details of your new organization{!$plansInfo.get(
+ $changeOrganizationTier.billingPlan
+ )?.trialDays
? '.'
: ' and start your free trial.'}
@@ -147,7 +148,7 @@
This amount, and any additional usage fees, will be charged on a recurring 30-day
- billing cycle{IS_TRIAL_DISABLED
+ billing cycle{!$plansInfo.get($changeOrganizationTier.billingPlan)?.trialDays
? ''
: ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
index 2c3ae0501..8d5fad783 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
@@ -1,13 +1,13 @@
import { BillingPlan } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
-import type { Tier } from '$lib/stores/billing';
-import { IS_TRIAL_DISABLED } from '$lib/system';
-import { writable } from 'svelte/store';
+import { plansInfo, type Tier } from '$lib/stores/billing';
+import { organization } from '$lib/stores/organization';
+import { get, writable } from 'svelte/store';
export const changeTierSteps = writable(new Map());
export const isUpgrade = writable(false);
export const changeOrganizationFinalAction = writable(
- IS_TRIAL_DISABLED ? 'Create' : 'Start trial'
+ get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create'
);
export const changeOrganizationTier = writable<{
From 16c1f6b39764f7318a4bdc8fb085636370f90d61 Mon Sep 17 00:00:00 2001
From: Arman
Date: Wed, 17 Apr 2024 14:46:43 +0200
Subject: [PATCH 44/46] fix: plan final action text
---
src/routes/console/+layout.svelte | 7 +++++--
.../wizard/cloudOrganization/confirmDetails.svelte | 7 +++++++
src/routes/console/wizard/cloudOrganization/store.ts | 9 +++------
.../cloudOrganizationChangeTier/confirmDetails.svelte | 4 ++++
.../console/wizard/cloudOrganizationChangeTier/store.ts | 9 +++------
5 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/src/routes/console/+layout.svelte b/src/routes/console/+layout.svelte
index dd45948cc..81fdcc85e 100644
--- a/src/routes/console/+layout.svelte
+++ b/src/routes/console/+layout.svelte
@@ -21,7 +21,8 @@
paymentExpired,
checkForMarkedForDeletion,
checkForMandate,
- checkForMissingPaymentMethod
+ checkForMissingPaymentMethod,
+ plansInfo
} from '$lib/stores/billing';
import { goto } from '$app/navigation';
import { CommandCenter, registerCommands, registerSearchers } from '$lib/commandCenter';
@@ -269,10 +270,12 @@
await checkForUsageLimit(org);
checkForMarkedForDeletion(org);
if (org?.billingPlan !== BillingPlan.STARTER) {
- calculateTrialDay(org);
await paymentExpired(org);
await checkPaymentAuthorizationRequired(org);
await checkForMandate(org);
+ if ($plansInfo.get(org.billingPlan)?.trialDays) {
+ calculateTrialDay(org);
+ }
}
}
});
diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
index 214a2cc24..36b0ec6df 100644
--- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
@@ -9,6 +9,7 @@
import type { Coupon } from '$lib/sdk/billing';
import { plansInfo } from '$lib/stores/billing';
import { sdk } from '$lib/stores/sdk';
+ import { onMount } from 'svelte';
import { createOrganization, createOrganizationFinalAction } from './store';
const plan = $plansInfo?.get($createOrganization.billingPlan);
@@ -18,6 +19,8 @@
const today = new Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
+ onMount(() => {});
+
let coupon: string = null;
let couponData: Partial = {
code: null,
@@ -48,6 +51,10 @@
$: if ($createOrganization.billingPlan === BillingPlan.STARTER) {
$createOrganizationFinalAction = 'Create organization';
}
+
+ $: if (plan?.trialDays) {
+ $createOrganizationFinalAction = 'Start trial';
+ }
diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts
index f25d7d5f8..55a53175c 100644
--- a/src/routes/console/wizard/cloudOrganization/store.ts
+++ b/src/routes/console/wizard/cloudOrganization/store.ts
@@ -1,13 +1,10 @@
import { BillingPlan } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
-import { plansInfo, type Tier } from '$lib/stores/billing';
-import { organization } from '$lib/stores/organization';
-import { get, writable } from 'svelte/store';
+import { type Tier } from '$lib/stores/billing';
+import { writable } from 'svelte/store';
export const createOrgSteps = writable(new Map());
-export const createOrganizationFinalAction = writable(
- get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create'
-);
+export const createOrganizationFinalAction = writable('Create');
export const createOrganization = writable<{
id?: string;
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
index 9b87670bf..a0545d583 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte
@@ -49,6 +49,10 @@
$: if (!$isUpgrade) {
$changeOrganizationFinalAction = 'Confirm plan change';
}
+
+ $: if (plan?.trialDays) {
+ $changeOrganizationFinalAction = 'Start trial';
+ }
{#if downgradeToStarter}
diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
index 8d5fad783..57463d106 100644
--- a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
+++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts
@@ -1,14 +1,11 @@
import { BillingPlan } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
-import { plansInfo, type Tier } from '$lib/stores/billing';
-import { organization } from '$lib/stores/organization';
-import { get, writable } from 'svelte/store';
+import { type Tier } from '$lib/stores/billing';
+import { writable } from 'svelte/store';
export const changeTierSteps = writable(new Map());
export const isUpgrade = writable(false);
-export const changeOrganizationFinalAction = writable(
- get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create'
-);
+export const changeOrganizationFinalAction = writable('Create');
export const changeOrganizationTier = writable<{
billingPlan: Tier;
From 5fe0e370aff6dd17a5a21aaa2a871347ac3f9ad5 Mon Sep 17 00:00:00 2001
From: Torsten Dittmann
Date: Fri, 26 Apr 2024 12:14:48 +0200
Subject: [PATCH 45/46] fix: error message
---
src/hooks.client.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/hooks.client.ts b/src/hooks.client.ts
index 2345ffb2c..ad54c45cc 100644
--- a/src/hooks.client.ts
+++ b/src/hooks.client.ts
@@ -2,10 +2,11 @@ import { AppwriteException } from '@appwrite.io/console';
import type { HandleClientError } from '@sveltejs/kit';
export const handleError: HandleClientError = async ({ error, message, status }) => {
- if (error instanceof AppwriteException && error.code === 0) {
- status = undefined;
+ if (error instanceof AppwriteException) {
+ status = error.code === 0 ? undefined : error.code;
message = error.message;
}
+
return {
message,
status
From cb937865cc58d7c3c42b8046a6971e02ab728548 Mon Sep 17 00:00:00 2001
From: Torsten Dittmann
Date: Fri, 26 Apr 2024 12:17:15 +0200
Subject: [PATCH 46/46] chore: remove unused code
---
.../console/wizard/cloudOrganization/confirmDetails.svelte | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
index e3038c79d..e3eb21d55 100644
--- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
+++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte
@@ -9,7 +9,6 @@
import type { Coupon } from '$lib/sdk/billing';
import { plansInfo } from '$lib/stores/billing';
import { sdk } from '$lib/stores/sdk';
- import { onMount } from 'svelte';
import { createOrganization, createOrganizationFinalAction } from './store';
const plan = $plansInfo?.get($createOrganization.billingPlan);
@@ -19,8 +18,6 @@
const today = new Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
- onMount(() => {});
-
let coupon: string = null;
let couponData: Partial = {
code: null,