mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch '1.6.x' of github.com:appwrite/console into fix-deployment-activate-button
This commit is contained in:
@@ -7,3 +7,4 @@ node_modules
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
/playwright-report
|
||||
@@ -1,32 +1,29 @@
|
||||
name: E2E
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
pull_request:
|
||||
branches: ['**']
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
- 'static/**/*'
|
||||
|
||||
env:
|
||||
VITE_STRIPE_PUBLIC_KEY: ${{ vars.VITE_STRIPE_PUBLIC_KEY }}
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
run: pnpm exec playwright install --with-deps chromium
|
||||
- name: E2E Tests
|
||||
run: npm run e2e
|
||||
run: pnpm run e2e
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: appwrite/console
|
||||
tags: |
|
||||
type=semver,pattern={{major}}.{{minor}}.{{patch}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
"VITE_CONSOLE_MODE=self-hosted"
|
||||
"VITE_APPWRITE_GROWTH_ENDPOINT=${{ secrets.VITE_APPWRITE_GROWTH_ENDPOINT }}"
|
||||
@@ -14,20 +14,22 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
- name: Audit dependencies
|
||||
run: npm audit --audit-level critical
|
||||
run: pnpm audit --audit-level high
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Svelte Diagnostics
|
||||
run: npm run check
|
||||
run: pnpm run check
|
||||
- name: Linter
|
||||
run: npm run lint
|
||||
run: pnpm run lint
|
||||
- name: Unit Tests
|
||||
run: npm run test
|
||||
run: pnpm run test
|
||||
- name: Build Console
|
||||
run: npm run build
|
||||
run: pnpm run build
|
||||
|
||||
@@ -10,6 +10,8 @@ node_modules
|
||||
!.env.example
|
||||
test-results/
|
||||
playwright-report/
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
.DS_STORE
|
||||
.cache
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
FROM --platform=$BUILDPLATFORM node:20-alpine AS build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable
|
||||
|
||||
ADD ./package.json /app/package.json
|
||||
ADD ./pnpm-lock.yaml /app/pnpm-lock.yaml
|
||||
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||
|
||||
ADD ./build.js /app/build.js
|
||||
ADD ./tsconfig.json /app/tsconfig.json
|
||||
ADD ./svelte.config.js /app/svelte.config.js
|
||||
ADD ./vite.config.ts /app/vite.config.ts
|
||||
ADD ./src /app/src
|
||||
ADD ./static /app/static
|
||||
|
||||
ARG VITE_CONSOLE_MODE
|
||||
ARG VITE_APPWRITE_ENDPOINT
|
||||
ARG VITE_APPWRITE_GROWTH_ENDPOINT
|
||||
ARG VITE_STRIPE_PUBLIC_KEY
|
||||
|
||||
ENV VITE_APPWRITE_ENDPOINT=$VITE_APPWRITE_ENDPOINT
|
||||
ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT
|
||||
ENV VITE_CONSOLE_MODE=$VITE_CONSOLE_MODE
|
||||
ENV VITE_STRIPE_PUBLIC_KEY=$VITE_STRIPE_PUBLIC_KEY
|
||||
|
||||
RUN pnpm run sync && pnpm run build
|
||||
|
||||
FROM nginx:1.25-alpine
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/build /usr/share/nginx/html/console
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
console:
|
||||
image: appwrite/console:dev
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
VITE_CONSOLE_MODE: ${VITE_CONSOLE_MODE}
|
||||
VITE_APPWRITE_ENDPOINT: ${VITE_APPWRITE_ENDPOINT}
|
||||
VITE_APPWRITE_GROWTH_ENDPOINT: ${VITE_APPWRITE_GROWTH_ENDPOINT}
|
||||
VITE_STRIPE_PUBLIC_KEY: ${VITE_STRIPE_PUBLIC_KEY}
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: ./
|
||||
ignore:
|
||||
- .github
|
||||
- tests/
|
||||
- node_modules/
|
||||
- build/
|
||||
environment:
|
||||
- VITE_CONSOLE_MODE
|
||||
- VITE_APPWRITE_ENDPOINT
|
||||
- VITE_APPWRITE_GROWTH_ENDPOINT
|
||||
- VITE_STRIPE_PUBLIC_KEY
|
||||
ports:
|
||||
- '3000:80'
|
||||
@@ -0,0 +1,16 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
location /console {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri /console/index.html;
|
||||
}
|
||||
|
||||
location / {
|
||||
absolute_redirect off;
|
||||
return 301 /console;
|
||||
}
|
||||
}
|
||||
Generated
-9325
File diff suppressed because it is too large
Load Diff
+43
-44
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@appwrite/console",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=20"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -20,59 +20,58 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@appwrite.io/console": "npm:matej-appwrite-console-16x@0.6.7",
|
||||
"@appwrite.io/pink": "0.23.0",
|
||||
"@appwrite.io/pink-icons": "0.23.0",
|
||||
"@appwrite.io/pink": "0.25.0",
|
||||
"@appwrite.io/pink-icons": "0.25.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@sentry/svelte": "^7.66.0",
|
||||
"@sentry/tracing": "^7.66.0",
|
||||
"@stripe/stripe-js": "^3.4.0",
|
||||
"ai": "^2.2.11",
|
||||
"analytics": "^0.8.9",
|
||||
"@stripe/stripe-js": "^3.5.0",
|
||||
"ai": "^2.2.37",
|
||||
"analytics": "^0.8.13",
|
||||
"cron-parser": "^4.9.0",
|
||||
"dayjs": "^1.11.9",
|
||||
"deep-equal": "^2.2.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"echarts": "^5.4.3",
|
||||
"nanoid": "^4.0.2",
|
||||
"plausible-tracker": "^0.3.8",
|
||||
"dayjs": "^1.11.11",
|
||||
"deep-equal": "^2.2.3",
|
||||
"echarts": "^5.5.1",
|
||||
"envfile": "^7.1.0",
|
||||
"nanoid": "^5.0.7",
|
||||
"plausible-tracker": "^0.3.9",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"prismjs": "^1.29.0",
|
||||
"svelte-confetti": "^1.3.0",
|
||||
"svelte-confetti": "^1.4.0",
|
||||
"tippy.js": "^6.3.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@melt-ui/pp": "^0.1.4",
|
||||
"@melt-ui/svelte": "^0.61.2",
|
||||
"@playwright/test": "^1.44.0",
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/kit": "^2.3.4",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.1",
|
||||
"@testing-library/dom": "^9.0.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/svelte": "^4.0.3",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/deep-equal": "^1.0.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
||||
"@typescript-eslint/parser": "^7.7.0",
|
||||
"@vitest/ui": "^1.2.1",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-svelte": "^2.33.0",
|
||||
"@melt-ui/pp": "^0.3.2",
|
||||
"@melt-ui/svelte": "^0.83.0",
|
||||
"@playwright/test": "^1.45.2",
|
||||
"@sveltejs/adapter-static": "^3.0.2",
|
||||
"@sveltejs/kit": "^2.5.18",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
||||
"@testing-library/dom": "^10.3.2",
|
||||
"@testing-library/jest-dom": "^6.4.6",
|
||||
"@testing-library/svelte": "^5.2.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/deep-equal": "^1.0.4",
|
||||
"@types/prismjs": "^1.26.4",
|
||||
"@typescript-eslint/eslint-plugin": "^7.16.1",
|
||||
"@typescript-eslint/parser": "^7.16.1",
|
||||
"@vitest/ui": "^1.6.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.42.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"kleur": "^4.1.5",
|
||||
"prettier": "^3.2.2",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"sass": "^1.66.1",
|
||||
"svelte": "^4.2.9",
|
||||
"svelte-check": "^3.5.1",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"sass": "^1.77.8",
|
||||
"svelte": "^4.2.18",
|
||||
"svelte-check": "^3.8.4",
|
||||
"svelte-jester": "^2.3.2",
|
||||
"svelte-preprocess": "^5.0.4",
|
||||
"svelte-preprocess": "^6.0.2",
|
||||
"svelte-sequential-preprocessor": "^2.0.1",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.0.11",
|
||||
"vitest": "^1.2.1"
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.5.3",
|
||||
"vite": "^5.3.4",
|
||||
"vitest": "^1.6.0"
|
||||
},
|
||||
"type": "module"
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@9.5.0+sha512.140036830124618d624a2187b50d04289d5a087f326c9edfc0ccd733d76c4f52c3a313d4fc148794a2a9d81553016004e6742e8cf850670268a7387fc220c903"
|
||||
}
|
||||
|
||||
@@ -4,13 +4,18 @@ const config: PlaywrightTestConfig = {
|
||||
timeout: 120000,
|
||||
reportSlowTests: null,
|
||||
reporter: [['html', { open: 'never' }]],
|
||||
use: {
|
||||
baseURL: 'http://localhost:4173/console/'
|
||||
},
|
||||
webServer: {
|
||||
timeout: 120000,
|
||||
env: {
|
||||
VITE_APPWRITE_ENDPOINT: 'http://console-tests.appwrite.org/v1',
|
||||
VITE_CONSOLE_MODE: 'cloud'
|
||||
VITE_CONSOLE_MODE: 'cloud',
|
||||
VITE_STRIPE_PUBLIC_KEY:
|
||||
'pk_test_51LT5nsGYD1ySxNCyd7b304wPD8Y1XKKWR6hqo6cu3GIRwgvcVNzoZv4vKt5DfYXL1gRGw4JOqE19afwkJYJq1g3K004eVfpdWn'
|
||||
},
|
||||
command: 'npm run build && npm run preview',
|
||||
command: 'pnpm run build && pnpm run preview',
|
||||
port: 4173
|
||||
}
|
||||
};
|
||||
|
||||
Generated
+6535
File diff suppressed because it is too large
Load Diff
+51
-13
@@ -4,42 +4,42 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="" />
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/logos/appwrite-icon.svg" />
|
||||
<link rel="mask-icon" type="image/png" href="/logos/appwrite-icon.png" />
|
||||
<link rel="icon" type="image/svg+xml" href="/console/logos/appwrite-icon.svg" />
|
||||
<link rel="mask-icon" type="image/png" href="/console/logos/appwrite-icon.png" />
|
||||
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/inter-v8-latin-600.woff2"
|
||||
href="/console/fonts/inter/inter-v8-latin-600.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/inter-v8-latin-regular.woff2"
|
||||
href="/console/fonts/inter/inter-v8-latin-regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/poppins/poppins-v19-latin-500.woff2"
|
||||
href="/console/fonts/poppins/poppins-v19-latin-500.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/poppins/poppins-v19-latin-600.woff2"
|
||||
href="/console/fonts/poppins/poppins-v19-latin-600.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/poppins/poppins-v19-latin-700.woff2"
|
||||
href="/console/fonts/poppins/poppins-v19-latin-700.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/source-code-pro/source-code-pro-v20-latin-regular.woff2"
|
||||
href="/console/fonts/source-code-pro/source-code-pro-v20-latin-regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
@@ -127,14 +127,52 @@
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link rel="preload" as="style" type="text/css" href="/fonts/main.css" />
|
||||
<link rel="stylesheet" href="/fonts/main.css" />
|
||||
<link rel="preload" as="style" type="text/css" href="/console/fonts/main.css" />
|
||||
<link rel="stylesheet" href="/console/css/loading.css" />
|
||||
<link rel="stylesheet" href="/console/fonts/main.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!-- {{CLOUD_OG}} -->
|
||||
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<body data-sveltekit-preload-data="hover" data-loading="true">
|
||||
<script>
|
||||
let themeInUse = 'auto';
|
||||
const appwrite = localStorage.getItem('appwrite');
|
||||
|
||||
if (appwrite) {
|
||||
try {
|
||||
const localPrefs = JSON.parse(appwrite);
|
||||
if (localPrefs) themeInUse = localPrefs.theme;
|
||||
} catch (ignore) {
|
||||
// Ignore any errors during JSON parsing
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
themeInUse =
|
||||
themeInUse === 'auto' ? (systemPrefersDark ? 'dark' : 'light') : themeInUse;
|
||||
|
||||
document.body.setAttribute('class', `theme-${themeInUse}`);
|
||||
</script>
|
||||
<div id="svelte">%sveltekit.body%</div>
|
||||
<div class="page-loader">
|
||||
<div class="animation">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<img
|
||||
src="/console/images/appwrite-logo-light.svg"
|
||||
width="120"
|
||||
height="22"
|
||||
class="logo-light"
|
||||
alt="Appwrite Logo" />
|
||||
<img
|
||||
src="/console/images/appwrite-logo-dark.svg"
|
||||
width="120"
|
||||
height="22"
|
||||
class="logo-dark"
|
||||
alt="Appwrite Logo" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
import { isLanguage, type Language } from '$lib/components/code.svelte';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import { VARS } from '$lib/system';
|
||||
|
||||
const endpoint = VARS.APPWRITE_ENDPOINT ?? `${globalThis?.location?.origin}/v1`;
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
|
||||
const endpoint = getApiEndpoint();
|
||||
const { input, handleSubmit, completion, isLoading, complete, error } = useCompletion({
|
||||
api: endpoint + '/console/assistant',
|
||||
headers: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { initCreateAttribute } from '$routes/console/project-[project]/databases/database-[database]/collection-[collection]/+layout.svelte';
|
||||
import { attributeOptions } from '$routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/store';
|
||||
import { initCreateAttribute } from '$routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/+layout.svelte';
|
||||
import { attributeOptions } from '$routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/attributes/store';
|
||||
import Template from './template.svelte';
|
||||
|
||||
let search = '';
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { providers } from '$routes/console/project-[project]/messaging/providers/store';
|
||||
import { providers } from '$routes/(console)/project-[project]/messaging/providers/store';
|
||||
import {
|
||||
messageParams,
|
||||
providerType,
|
||||
targetsById
|
||||
} from '$routes/console/project-[project]/messaging/wizard/store';
|
||||
} from '$routes/(console)/project-[project]/messaging/wizard/store';
|
||||
import { MessagingProviderType } from '@appwrite.io/console';
|
||||
import Template from './template.svelte';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import Create from '$routes/console/project-[project]/messaging/create.svelte';
|
||||
import { topicsById } from '$routes/console/project-[project]/messaging/store';
|
||||
import Create from '$routes/(console)/project-[project]/messaging/create.svelte';
|
||||
import { topicsById } from '$routes/(console)/project-[project]/messaging/store';
|
||||
|
||||
let search = '';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import {
|
||||
Platform,
|
||||
addPlatform
|
||||
} from '$routes/console/project-[project]/overview/platforms/+page.svelte';
|
||||
} from '$routes/(console)/project-[project]/overview/platforms/+page.svelte';
|
||||
import Template from './template.svelte';
|
||||
|
||||
let search = '';
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Command, Searcher } from '../commands';
|
||||
import { addSubPanel } from '../subPanels';
|
||||
import { FilesPanel } from '../panels';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const getBucketCommand = (bucket: Models.Bucket, projectId: string) => {
|
||||
return {
|
||||
label: `${bucket.name}`,
|
||||
callback() {
|
||||
goto(`/console/project-${projectId}/storage/bucket-${bucket.$id}`);
|
||||
goto(`${base}/project-${projectId}/storage/bucket-${bucket.$id}`);
|
||||
},
|
||||
group: 'buckets',
|
||||
icon: 'folder'
|
||||
@@ -31,7 +32,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Find files',
|
||||
async callback() {
|
||||
await goto(`/console/project-${$project.$id}/storage/bucket-${bucket.$id}`);
|
||||
await goto(`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}`);
|
||||
addSubPanel(FilesPanel);
|
||||
},
|
||||
group: 'buckets',
|
||||
@@ -43,7 +44,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
label: 'Permissions',
|
||||
async callback() {
|
||||
await goto(
|
||||
`/console/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#permissions`
|
||||
`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#permissions`
|
||||
);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
@@ -55,7 +56,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
label: 'Extensions',
|
||||
async callback() {
|
||||
await goto(
|
||||
`/console/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#extensions`
|
||||
`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#extensions`
|
||||
);
|
||||
},
|
||||
group: 'buckets',
|
||||
@@ -66,7 +67,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
label: 'File Security',
|
||||
async callback() {
|
||||
await goto(
|
||||
`/console/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#file-security`
|
||||
`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#file-security`
|
||||
);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { database } from '$routes/console/project-[project]/databases/database-[database]/store';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { database } from '$routes/(console)/project-[project]/databases/database-[database]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const collectionsSearcher = (async (query: string) => {
|
||||
const databaseId = get(database).$id;
|
||||
@@ -19,7 +20,7 @@ export const collectionsSearcher = (async (query: string) => {
|
||||
label: col.name,
|
||||
callback: () => {
|
||||
goto(
|
||||
`/console/project-${projectId}/databases/database-${databaseId}/collection-${col.$id}`
|
||||
`${base}/project-${projectId}/databases/database-${databaseId}/collection-${col.$id}`
|
||||
);
|
||||
}
|
||||
}) as const
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const dbSearcher = (async (query: string) => {
|
||||
const { databases } = await sdk.forProject.databases.list();
|
||||
@@ -15,7 +16,7 @@ export const dbSearcher = (async (query: string) => {
|
||||
group: 'databases',
|
||||
label: db.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${get(project).$id}/databases/database-${db.$id}`);
|
||||
goto(`${base}/project-${get(project).$id}/databases/database-${db.$id}`);
|
||||
},
|
||||
icon: 'database'
|
||||
}) as const
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { bucket } from '$routes/console/project-[project]/storage/bucket-[bucket]/store';
|
||||
import { bucket } from '$routes/(console)/project-[project]/storage/bucket-[bucket]/store';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const fileSearcher = (async (query: string) => {
|
||||
const $bucket = get(bucket);
|
||||
@@ -19,7 +20,7 @@ export const fileSearcher = (async (query: string) => {
|
||||
return files.map((file) => ({
|
||||
label: file.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/storage/bucket-${$bucket.$id}/file-${file.$id}`);
|
||||
goto(`${base}/project-${$project.$id}/storage/bucket-${$bucket.$id}/file-${file.$id}`);
|
||||
},
|
||||
icon: 'document',
|
||||
group: 'files'
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { page } from '$app/stores';
|
||||
import { showCreateDeployment } from '$routes/console/project-[project]/functions/function-[function]/store';
|
||||
import { showCreateDeployment } from '$routes/(console)/project-[project]/functions/function-[function]/store';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const getFunctionCommand = (fn: Models.Function, projectId: string) => {
|
||||
return {
|
||||
label: fn.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/functions/function-${fn.$id}`);
|
||||
goto(`${base}/project-${projectId}/functions/function-${fn.$id}`);
|
||||
},
|
||||
group: 'functions',
|
||||
icon: 'lightning-bolt'
|
||||
@@ -35,7 +36,7 @@ export const functionsSearcher = (async (query: string) => {
|
||||
async callback() {
|
||||
const $page = get(page);
|
||||
if (!$page.url.pathname.endsWith(func.$id)) {
|
||||
await goto(`/console/project-${projectId}/functions/function-${func.$id}`);
|
||||
await goto(`${base}/project-${projectId}/functions/function-${func.$id}`);
|
||||
}
|
||||
showCreateDeployment.set(true);
|
||||
},
|
||||
@@ -46,7 +47,7 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to deployments',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`/console/project-${projectId}/functions/function-${func.$id}`);
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}`);
|
||||
},
|
||||
group: 'functions'
|
||||
},
|
||||
@@ -54,7 +55,7 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to usage',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`/console/project-${projectId}/functions/function-${func.$id}/usage`);
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}/usage`);
|
||||
},
|
||||
group: 'functions'
|
||||
},
|
||||
@@ -62,7 +63,7 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to executions',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`/console/project-${projectId}/functions/function-${func.$id}/executions`);
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}/executions`);
|
||||
},
|
||||
group: 'functions'
|
||||
},
|
||||
@@ -70,7 +71,7 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to settings',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`/console/project-${projectId}/functions/function-${func.$id}/settings`);
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}/settings`);
|
||||
},
|
||||
group: 'functions'
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import { type Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { MessagingProviderType } from '@appwrite.io/console';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const getLabel = (message) => {
|
||||
switch (message.providerType) {
|
||||
@@ -44,7 +45,7 @@ export const messagesSearcher = (async (query: string) => {
|
||||
group: 'messages',
|
||||
label: getLabel(message),
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/messaging/message-${message.$id}`);
|
||||
goto(`${base}/project-${projectId}/messaging/message-${message.$id}`);
|
||||
},
|
||||
icon: getIcon(message)
|
||||
}) as const
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Searcher } from '../commands';
|
||||
|
||||
@@ -10,7 +11,7 @@ export const orgSearcher = (async (query: string) => {
|
||||
return {
|
||||
label: organization.name,
|
||||
callback: () => {
|
||||
goto(`/console/organization-${organization.$id}`);
|
||||
goto(`${base}/organization-${organization.$id}`);
|
||||
},
|
||||
group: 'organizations'
|
||||
} as const;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const projectsSearcher = (async (query: string) => {
|
||||
const { projects } = await sdk.forConsole.projects.list([
|
||||
@@ -17,7 +18,7 @@ export const projectsSearcher = (async (query: string) => {
|
||||
return {
|
||||
label: project.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${project.$id}`);
|
||||
goto(`${base}/project-${project.$id}`);
|
||||
},
|
||||
group: 'projects'
|
||||
} as const;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getProviderDisplayNameAndIcon } from '$routes/console/project-[project]/messaging/provider.svelte';
|
||||
import { getProviderDisplayNameAndIcon } from '$routes/(console)/project-[project]/messaging/provider.svelte';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const getIcon = (provider: string) => {
|
||||
const { icon } = getProviderDisplayNameAndIcon(provider);
|
||||
@@ -24,7 +25,7 @@ export const providersSearcher = (async (query: string) => {
|
||||
label: provider.name,
|
||||
callback: () => {
|
||||
goto(
|
||||
`/console/project-${projectId}/messaging/providers/provider-${provider.$id}`
|
||||
`${base}/project-${projectId}/messaging/providers/provider-${provider.$id}`
|
||||
);
|
||||
},
|
||||
image: getIcon(provider.provider)
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Command, Searcher } from '../commands';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const getTeamCommand = (team: Models.Team<Models.Preferences>, projectId: string) =>
|
||||
({
|
||||
label: team.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/teams/team-${team.$id}`);
|
||||
goto(`${base}/project-${projectId}/auth/teams/team-${team.$id}`);
|
||||
},
|
||||
group: 'teams',
|
||||
icon: 'user-circle'
|
||||
@@ -25,7 +26,7 @@ export const teamSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to members',
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/teams/team-${teams[0].$id}/members`);
|
||||
goto(`${base}/project-${projectId}/auth/teams/team-${teams[0].$id}/members`);
|
||||
},
|
||||
group: 'teams',
|
||||
nested: true
|
||||
@@ -34,7 +35,7 @@ export const teamSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to activity',
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/teams/team-${teams[0].$id}/activity`);
|
||||
goto(`${base}/project-${projectId}/auth/teams/team-${teams[0].$id}/activity`);
|
||||
},
|
||||
group: 'teams',
|
||||
nested: true
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const topicsSearcher = (async (query: string) => {
|
||||
const { topics } = await sdk.forProject.messaging.listTopics([], query || undefined);
|
||||
@@ -17,7 +18,7 @@ export const topicsSearcher = (async (query: string) => {
|
||||
group: 'topics',
|
||||
label: topic.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/messaging/topics/topic-${topic.$id}`);
|
||||
goto(`${base}/project-${projectId}/messaging/topics/topic-${topic.$id}`);
|
||||
},
|
||||
icon: 'send'
|
||||
}) as const
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { project } from '$routes/console/project-[project]/store';
|
||||
import { project } from '$routes/(console)/project-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Command, Searcher } from '../commands';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { promptDeleteUser } from '$routes/console/project-[project]/auth/user-[user]/dangerZone.svelte';
|
||||
import { promptDeleteUser } from '$routes/(console)/project-[project]/auth/user-[user]/dangerZone.svelte';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const getUserCommand = (user: Models.User<Models.Preferences>, projectId: string) =>
|
||||
({
|
||||
label: user.name,
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/user-${user.$id}`);
|
||||
goto(`${base}/project-${projectId}/auth/user-${user.$id}`);
|
||||
},
|
||||
group: 'users',
|
||||
icon: 'user-circle'
|
||||
@@ -35,7 +36,7 @@ export const userSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to activity',
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/user-${users[0].$id}/activity`);
|
||||
goto(`${base}/project-${projectId}/auth/user-${users[0].$id}/activity`);
|
||||
},
|
||||
group: 'users',
|
||||
nested: true
|
||||
@@ -43,7 +44,7 @@ export const userSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to sessions',
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/user-${users[0].$id}/sessions`);
|
||||
goto(`${base}/project-${projectId}/auth/user-${users[0].$id}/sessions`);
|
||||
},
|
||||
group: 'users',
|
||||
nested: true
|
||||
@@ -51,7 +52,7 @@ export const userSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to memberships',
|
||||
callback: () => {
|
||||
goto(`/console/project-${projectId}/auth/user-${users[0].$id}/memberships`);
|
||||
goto(`${base}/project-${projectId}/auth/user-${users[0].$id}/memberships`);
|
||||
},
|
||||
group: 'users',
|
||||
nested: true
|
||||
|
||||
@@ -20,10 +20,7 @@
|
||||
plan. Consider upgrading to increase your resource usage.
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="buttons">
|
||||
<Button
|
||||
href={`${base}/console/organization-${$organization.$id}/usage`}
|
||||
text
|
||||
fullWidthMobile>
|
||||
<Button href={`${base}/organization-${$organization.$id}/usage`} text fullWidthMobile>
|
||||
<span class="text">View usage</span>
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { HeaderAlert } from '$lib/layout';
|
||||
import { hideBillingHeaderRoutes } from '$lib/stores/billing';
|
||||
import { orgMissingPaymentMethod } from '$routes/console/store';
|
||||
import { orgMissingPaymentMethod } from '$routes/(console)/store';
|
||||
</script>
|
||||
|
||||
{#if ($orgMissingPaymentMethod.billingPlan === BillingPlan.PRO || $orgMissingPaymentMethod.billingPlan === BillingPlan.SCALE) && !$orgMissingPaymentMethod.paymentMethodId && !$orgMissingPaymentMethod.backupPaymentMethodId && !hideBillingHeaderRoutes.includes($page.url.pathname)}
|
||||
@@ -16,9 +17,7 @@
|
||||
your projects.
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="buttons">
|
||||
<Button
|
||||
secondary
|
||||
href={`/console/organization-${$orgMissingPaymentMethod.$id}/billing`}>
|
||||
<Button secondary href={`${base}/organization-${$orgMissingPaymentMethod.$id}/billing`}>
|
||||
Add payment method
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -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}/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,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { HeaderAlert } from '$lib/layout';
|
||||
import { actionRequiredInvoices, hideBillingHeaderRoutes } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { VARS } from '$lib/system';
|
||||
|
||||
const endpoint = VARS.APPWRITE_ENDPOINT ?? `${$page.url.origin}/v1`;
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
const endpoint = getApiEndpoint();
|
||||
</script>
|
||||
|
||||
{#if $actionRequiredInvoices && $actionRequiredInvoices?.invoices?.length && !hideBillingHeaderRoutes.includes($page.url.pathname)}
|
||||
@@ -21,7 +21,7 @@
|
||||
</Button>
|
||||
<Button
|
||||
secondary
|
||||
href={`/console/organization-${$organization.$id}/billing?type=confirmation&invoice=${$actionRequiredInvoices.invoices[0].$id}`}>
|
||||
href={`${base}/organization-${$organization.$id}/billing?type=confirmation&invoice=${$actionRequiredInvoices.invoices[0].$id}`}>
|
||||
Authorize payment
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="buttons">
|
||||
<Button
|
||||
href={`${base}/console/organization-${$failedInvoice?.teamId}/billing#paymentMethods`}
|
||||
href={`${base}/organization-${$failedInvoice?.teamId}/billing#paymentMethods`}
|
||||
secondary
|
||||
fullWidthMobile>
|
||||
<span class="text">Update billing details</span>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
<div class="top-banner">
|
||||
<div class="top-banner-bg">
|
||||
<div class="top-banner-bg-1">
|
||||
<img
|
||||
src={`${base}/images/top-banner/bg-pink-desktop.svg`}
|
||||
width="1283"
|
||||
height="1278"
|
||||
alt="" />
|
||||
</div>
|
||||
<div class="top-banner-bg-2">
|
||||
<img
|
||||
src={`${base}/images/top-banner/bg-mint-desktop.svg`}
|
||||
width="1051"
|
||||
height="1271"
|
||||
alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-content u-color-text-primary">
|
||||
<slot />
|
||||
</div>
|
||||
<button
|
||||
on:click|preventDefault={() => dispatch('close')}
|
||||
type="button"
|
||||
class="top-banner-button"
|
||||
aria-label="close upgrade message">
|
||||
<span class="icon-x" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -1,14 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { formatNum } from '$lib/helpers/string';
|
||||
import { plansInfo } from '$lib/stores/billing';
|
||||
import { Box, SecondaryTabs, SecondaryTabsItem } from '..';
|
||||
import { Card, SecondaryTabs, SecondaryTabsItem } from '..';
|
||||
|
||||
let selectedTab: 'tier-0' | 'tier-1' = 'tier-0';
|
||||
export let downgrade = false;
|
||||
|
||||
$: plan = $plansInfo.get(selectedTab);
|
||||
</script>
|
||||
|
||||
<Box>
|
||||
<Card>
|
||||
<SecondaryTabs stretch>
|
||||
<SecondaryTabsItem
|
||||
disabled={selectedTab === 'tier-0'}
|
||||
@@ -25,16 +26,66 @@
|
||||
<div class="u-margin-block-start-24">
|
||||
{#if selectedTab === 'tier-0'}
|
||||
<h3 class="u-bold body-text-1">{plan.name} plan</h3>
|
||||
<ul class="un-order-list u-margin-block-start-8">
|
||||
<li>
|
||||
Limited to {plan.databases} Database, {plan.buckets} Buckets, {plan.functions} Functions
|
||||
per project
|
||||
</li>
|
||||
<li>Limited to 1 organization member</li>
|
||||
<li>{plan.bandwidth}GB bandwidth</li>
|
||||
<li>{plan.storage}GB storage</li>
|
||||
<li>{formatNum(plan.executions)} executions</li>
|
||||
</ul>
|
||||
{#if downgrade}
|
||||
<ul class="u-margin-block-start-8 list u-gap-4 u-small">
|
||||
<li class="list-item u-gap-4 u-cross-center">
|
||||
<span class="icon-arrow-down u-color-text-danger" aria-hidden="true"></span>
|
||||
<span class="text">
|
||||
Limited to {plan.databases} Database, {plan.buckets} Buckets, {plan.functions}
|
||||
Functions per project
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-item u-gap-4 u-cross-center">
|
||||
<span class="icon-arrow-down u-color-text-danger" aria-hidden="true"></span>
|
||||
<span class="text"> Limited to 1 organization member </span>
|
||||
</li>
|
||||
<li class="list-item u-gap-4 u-cross-center">
|
||||
<span class="icon-arrow-down u-color-text-danger" aria-hidden="true"></span>
|
||||
<span class="text">
|
||||
{plan.bandwidth}GB bandwidth
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-item u-gap-4 u-cross-center">
|
||||
<span class="icon-arrow-down u-color-text-danger" aria-hidden="true"></span>
|
||||
<span class="text">
|
||||
{plan.storage}GB storage
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-item u-gap-4 u-cross-center">
|
||||
<span class="icon-arrow-down u-color-text-danger" aria-hidden="true"></span>
|
||||
<span class="text">
|
||||
{formatNum(plan.executions)} executions
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
{:else}
|
||||
<ul class="u-margin-block-start-8 un-order-list">
|
||||
<li>
|
||||
<span class="text">
|
||||
Limited to {plan.databases} Database, {plan.buckets} Buckets, {plan.functions}
|
||||
Functions per project
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text"> Limited to 1 organization member </span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text">
|
||||
{plan.bandwidth}GB bandwidth
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text">
|
||||
{plan.storage}GB storage
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text">
|
||||
{formatNum(plan.executions)} executions
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
{/if}
|
||||
{:else if selectedTab === 'tier-1'}
|
||||
<h3 class="u-bold body-text-1">{plan.name} plan</h3>
|
||||
<ul class="un-order-list u-margin-block-start-8">
|
||||
@@ -47,4 +98,4 @@
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
</Box>
|
||||
</Card>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import type { OrganizationUsage } from '$lib/sdk/billing';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
|
||||
export let tier: Tier;
|
||||
|
||||
@@ -67,11 +68,15 @@
|
||||
</svelte:fragment>
|
||||
</Alert>
|
||||
|
||||
<TableScroll dense noMargin class="u-margin-block-start-16">
|
||||
<TableScroll noMargin dense class="u-margin-block-start-16">
|
||||
<TableHeader>
|
||||
<TableCellHead>Resource</TableCellHead>
|
||||
<TableCellHead>Free limit</TableCellHead>
|
||||
<TableCellHead>Excess usage</TableCellHead>
|
||||
<TableCellHead>
|
||||
Excess usage <span
|
||||
use:tooltip={{ content: 'Metrics are estimates updated every 24 hours' }}
|
||||
class="icon-info"></span>
|
||||
</TableCellHead>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#if excess?.members}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Button, InputChoice, InputSelectSearch, InputText } from '$lib/elements/forms';
|
||||
import { Button, Helper, InputChoice, InputSelectSearch, InputText } from '$lib/elements/forms';
|
||||
import type { PaymentList, PaymentMethodData } from '$lib/sdk/billing';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { hasStripePublicKey, isCloud } from '$lib/system';
|
||||
@@ -14,6 +14,18 @@
|
||||
|
||||
let showTaxId = false;
|
||||
let showPaymentModal = false;
|
||||
let input: HTMLInputElement;
|
||||
let error: string;
|
||||
|
||||
function handleInvalid(event: Event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (input.validity.valueMissing) {
|
||||
error = 'This field is required';
|
||||
return;
|
||||
}
|
||||
error = input.validationMessage;
|
||||
}
|
||||
|
||||
async function cardSaved(event: CustomEvent<PaymentMethodData>) {
|
||||
value = event.detail.$id;
|
||||
@@ -85,22 +97,33 @@
|
||||
</svelte:fragment>
|
||||
</InputSelectSearch>
|
||||
{:else}
|
||||
<Card
|
||||
isDashed
|
||||
style="--p-card-padding:0.75rem; --p-card-bg-color: transparent; --p-card-border-radius: 0.5rem"
|
||||
isTile>
|
||||
<div class="u-flex u-main-space-between u-cross-center">
|
||||
<p class="u-flex u-gap-8 u-cross-center">
|
||||
<span
|
||||
class="icon-exclamation u-color-text-warning"
|
||||
style:font-size="var(--icon-size-medium)"></span>
|
||||
<span class="text">A payment method is required</span>
|
||||
</p>
|
||||
<Button secondary on:click={() => (showPaymentModal = true)}>
|
||||
<span class="icon-plus"></span> <span class="text">Add</span>
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<div>
|
||||
<input
|
||||
bind:this={input}
|
||||
on:invalid={handleInvalid}
|
||||
required
|
||||
class="u-hide"
|
||||
type="text"
|
||||
name="method"
|
||||
id="method" />
|
||||
<Card
|
||||
isDashed
|
||||
style="--p-card-padding:0.75rem; --p-card-bg-color: transparent; --p-card-border-radius: 0.5rem"
|
||||
isTile>
|
||||
<div class="u-flex u-main-space-between u-cross-center">
|
||||
<p>
|
||||
<span class="icon-exclamation-circle"></span>
|
||||
<span class="text">No saved payment methods</span>
|
||||
</p>
|
||||
<Button secondary on:click={() => (showPaymentModal = true)}>
|
||||
<span class="icon-plus"></span> <span class="text">Add</span>
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
{#if error}
|
||||
<Helper class="u-position-relative" type="warning">{error}</Helper>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if showPaymentModal && isCloud && hasStripePublicKey}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
export let href: string = null;
|
||||
let classes = '';
|
||||
export { classes as class };
|
||||
export let style: string = '';
|
||||
export let style = '';
|
||||
|
||||
function getElement() {
|
||||
switch (true) {
|
||||
|
||||
@@ -58,11 +58,11 @@
|
||||
// TODO: remove once pink is updated
|
||||
.collapsible-item {
|
||||
.collapsible-wrapper.is-disabled {
|
||||
cursor: not-allowed;
|
||||
|
||||
&[open] .icon-cheveron-down {
|
||||
rotate: unset;
|
||||
}
|
||||
|
||||
cursor: not-allowed;
|
||||
* {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<script>
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { getNextTier, tierToPlan, upgradeURL } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import Card from './card.svelte';
|
||||
|
||||
export let source = 'empty_state_card';
|
||||
export let noAspectRatio = false;
|
||||
</script>
|
||||
|
||||
<Card style="--card-padding:1.5rem; --card-padding-mobile: 2rem">
|
||||
<div class="u-flex u-gap-24 u-flex-vertical-mobile">
|
||||
{#if $$slots?.image}
|
||||
<div class="u-stretch">
|
||||
<div
|
||||
style:--p-file-preview-border-color="transparent"
|
||||
class="file-preview is-full-cover-image u-width-full-line u-height-100-percent"
|
||||
style={noAspectRatio ? 'aspect-ratio: auto' : ''}>
|
||||
<slot name="image" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="u-stretch u-flex-vertical">
|
||||
<h3 class="body-text-2 u-bold"><slot name="title" /></h3>
|
||||
<p class="u-margin-block-start-8">
|
||||
<slot nextTier={tierToPlan(getNextTier($organization.billingPlan)).name} />
|
||||
</p>
|
||||
<Button
|
||||
class="u-margin-block-start-32"
|
||||
secondary
|
||||
fullWidth
|
||||
href={$upgradeURL}
|
||||
on:click={() => {
|
||||
trackEvent('click_organization_upgrade', {
|
||||
from: 'button',
|
||||
source
|
||||
});
|
||||
}}>Upgrade plan</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -2,11 +2,13 @@
|
||||
export let value: number = null;
|
||||
</script>
|
||||
|
||||
<fieldset class="u-margin-block-start-8">
|
||||
<fieldset class="u-margin-block-start-8 u-min-width-0">
|
||||
<legend class="label is-required u-margin-0 u-line-height-1-5 u-bold">
|
||||
<slot />
|
||||
</legend>
|
||||
<ul class="u-flex u-main-space-between u-margin-block-start-16">
|
||||
<ol
|
||||
class="u-flex u-main-space-between u-margin-block-start-16 u-overflow-x-auto"
|
||||
style="padding-block: 0.13rem">
|
||||
{#each Array(11) as _, i}
|
||||
<li>
|
||||
<input
|
||||
@@ -18,9 +20,9 @@
|
||||
checked={value === i} />
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</ol>
|
||||
<div class="u-flex u-main-space-between u-margin-block-start-8">
|
||||
<span>Not at all likely</span>
|
||||
<span>Extremely likely</span>
|
||||
<span class:u-color-text-gray={value === null}>Not at all likely</span>
|
||||
<span class:u-color-text-gray={value === null}>Extremely likely</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: 'Feedback submitted successfully'
|
||||
message: 'Thank you for your feedback'
|
||||
});
|
||||
feedback.toggleFeedback();
|
||||
feedbackData.reset();
|
||||
@@ -33,15 +33,15 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="drop-section">
|
||||
<section class="drop-section u-padding-24">
|
||||
<header class="u-flex u-main-space-between u-gap-16">
|
||||
<h4 class="body-text-1 u-bold">{$selectedFeedback.title}</h4>
|
||||
<h4 class="label u-bold" style:font-size="var(--font-size-1)">{$selectedFeedback.title}</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="button is-text is-only-icon u-margin-inline-start-auto"
|
||||
style="--button-size:1.5rem;"
|
||||
aria-label="Close Modal"
|
||||
title="Close Modal"
|
||||
aria-label="Close feedback"
|
||||
title="Close feedback"
|
||||
on:click={() => feedback.toggleFeedback()}>
|
||||
<span class="icon-x" aria-hidden="true" />
|
||||
</button>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
import Evaluation from './evaluation.svelte';
|
||||
</script>
|
||||
|
||||
<Evaluation bind:value={$feedbackData.value}>
|
||||
How likely are you to recommend Appwrite to a friend or colleague?
|
||||
</Evaluation>
|
||||
{#if $feedbackData.value}
|
||||
<FormList>
|
||||
<FormList>
|
||||
<Evaluation bind:value={$feedbackData.value}>
|
||||
How likely are you to recommend Appwrite to a friend or colleague?
|
||||
</Evaluation>
|
||||
{#if $feedbackData.value !== null}
|
||||
<InputTextarea
|
||||
id="feedback"
|
||||
placeholder="Your message here"
|
||||
@@ -26,5 +26,5 @@
|
||||
id="email"
|
||||
bind:value={$feedbackData.email}
|
||||
placeholder="Enter email" />
|
||||
</FormList>
|
||||
{/if}
|
||||
{/if}
|
||||
</FormList>
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
<Button
|
||||
secondary
|
||||
external
|
||||
href={`${base}/console/project-${$page.params.project}/storage`}>
|
||||
href={`${base}/project-${$page.params.project}/storage`}>
|
||||
Create bucket
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -72,5 +72,6 @@ export { default as FakeModal } from './fakeModal.svelte';
|
||||
export { default as RadioBoxes } from './radioBoxes.svelte';
|
||||
export { default as ModalWrapper } from './modalWrapper.svelte';
|
||||
export { default as ModalSideCol } from './modalSideCol.svelte';
|
||||
export { default as EmptyCardImageCloud } from './emptyCardImageCloud.svelte';
|
||||
export { default as ImagePreview } from './imagePreview.svelte';
|
||||
export { default as MfaChallengeFormList } from './mfaChallengeFormList.svelte';
|
||||
|
||||
@@ -121,11 +121,6 @@
|
||||
--p-drop-bg-color: var(--color-neutral-105);
|
||||
--p-drop-border-color: var(--color-neutral-85);
|
||||
|
||||
body.theme-light & {
|
||||
--p-drop-bg-color: var(--color-neutral-0);
|
||||
--p-drop-border-color: var(--color-neutral-10);
|
||||
}
|
||||
|
||||
inset-inline-start: -0.625rem;
|
||||
inset-block-end: calc(100% + 0.625rem);
|
||||
background-color: hsl(var(--p-drop-bg-color));
|
||||
@@ -138,6 +133,11 @@
|
||||
margin-inline: auto;
|
||||
line-height: 1.5;
|
||||
|
||||
body.theme-light & {
|
||||
--p-drop-bg-color: var(--color-neutral-0);
|
||||
--p-drop-border-color: var(--color-neutral-10);
|
||||
}
|
||||
|
||||
.tippy-content {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import SupportWizard from '../../routes/console/supportWizard.svelte';
|
||||
import { showSupportModal } from '../../routes/console/wizard/support/store';
|
||||
import SupportWizard from '$routes/(console)/supportWizard.svelte';
|
||||
import { showSupportModal } from '$routes/(console)/wizard/support/store';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
{#if file.completed || file.progress === 100}
|
||||
<a
|
||||
class="upload-box-item"
|
||||
href={`${base}/console/project-${$page.params.project}/storage/bucket-${$page.params.bucket}/file-${file.$id}`}>
|
||||
href={`${base}/project-${$page.params.project}/storage/bucket-${$page.params.bucket}/file-${file.$id}`}>
|
||||
<div class="u-margin-inline-end-16">
|
||||
<Avatar
|
||||
size={32}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script lang="ts">
|
||||
export let type: 'success' | 'warning' | 'error' | 'info' | 'neutral' = 'warning';
|
||||
let classes = '';
|
||||
export { classes as class };
|
||||
</script>
|
||||
|
||||
<p
|
||||
class="helper u-margin-block-start-8"
|
||||
class="helper u-margin-block-start-8 {classes}"
|
||||
class:u-color-text-info={type === 'info'}
|
||||
class:u-color-text-danger={type === 'error'}
|
||||
class:u-color-text-success={type === 'success'}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
endSegment,
|
||||
trigger
|
||||
},
|
||||
states: { months, headingValue, daysOfWeek, segmentContents, value },
|
||||
states: { months, headingValue, weekdays, segmentContents, value },
|
||||
helpers: { isDateDisabled, isDateUnavailable }
|
||||
} = createDateRangePicker();
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<table use:melt={$grid}>
|
||||
<thead aria-hidden="true">
|
||||
<tr>
|
||||
{#each $daysOfWeek as day}
|
||||
{#each $weekdays as day}
|
||||
<th class="dt-cell">
|
||||
<span class="u-flex u-main-center u-cross-center">
|
||||
{day}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { DropList } from '$lib/components';
|
||||
import { clickOnEnter } from '$lib/helpers/a11y';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { Label } from '.';
|
||||
import { Helper, Label } from '.';
|
||||
|
||||
/* eslint no-undef: "off" */
|
||||
type Option = $$Generic<{
|
||||
@@ -36,6 +36,7 @@
|
||||
let element: HTMLInputElement;
|
||||
let hasFocus = false;
|
||||
let selected: number = null;
|
||||
let error: string;
|
||||
|
||||
$: if (!hasFocus) {
|
||||
selected = null;
|
||||
@@ -105,7 +106,18 @@
|
||||
dispatch('reset');
|
||||
}
|
||||
|
||||
function handleInvalid(event: Event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (element.validity.valueMissing) {
|
||||
error = 'This field is required';
|
||||
return;
|
||||
}
|
||||
error = element.validationMessage;
|
||||
}
|
||||
|
||||
$: showClearBtn = (hasFocus && search) || value;
|
||||
$: if (value || search) error = null;
|
||||
</script>
|
||||
|
||||
<li
|
||||
@@ -147,6 +159,7 @@
|
||||
bind:this={element}
|
||||
on:focus={() => (hasFocus = true)}
|
||||
on:click={() => (hasFocus = true)}
|
||||
on:invalid={handleInvalid}
|
||||
on:input={handleInput}
|
||||
on:keydown={handleKeydown} />
|
||||
{/if}
|
||||
@@ -205,6 +218,9 @@
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
{#if error}
|
||||
<Helper class="u-position-relative" type="warning">{error}</Helper>
|
||||
{/if}
|
||||
</li>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -21,7 +21,7 @@ export enum View {
|
||||
export function getView(url: URL, route: Page['route'], fallback: View): View {
|
||||
return (url.searchParams.get('view') ?? preferences.get(route).view) === View.Grid
|
||||
? View.Grid
|
||||
: View.Table ?? fallback;
|
||||
: (View.Table ?? fallback);
|
||||
}
|
||||
|
||||
export function getColumns(route: Page['route'], fallback: string[]): string[] {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { settings } from '$lib/components/consent.svelte';
|
||||
import { clickOnEnter } from '$lib/helpers/a11y';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { version } from '$routes/console/store';
|
||||
import { version } from '$routes/(console)/store';
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
</script>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
function createOrg() {
|
||||
showDropdown = false;
|
||||
if (isCloud) {
|
||||
goto(`${base}/console/create-organization`);
|
||||
goto(`${base}/create-organization`);
|
||||
} else newOrgModal.set(true);
|
||||
}
|
||||
|
||||
@@ -78,10 +78,7 @@
|
||||
<svelte:window on:click={onBlur} />
|
||||
|
||||
<div class="logo u-inline-flex u-gap-16 u-cross-center">
|
||||
<a
|
||||
href={$organization
|
||||
? `${base}/console/organization-${$organization.$id}`
|
||||
: `${base}/console`}>
|
||||
<a href={$organization ? `${base}/organization-${$organization.$id}` : base}>
|
||||
<img
|
||||
src={$app.themeInUse == 'dark' ? AppwriteLogoDark : AppwriteLogoLight}
|
||||
width="120"
|
||||
@@ -124,6 +121,11 @@
|
||||
{/if}
|
||||
<DropList show={$feedback.show} scrollable on:blur={toggleFeedback}>
|
||||
<button class="button is-small is-text" on:click={toggleFeedback}>
|
||||
{#if $feedback.notification}
|
||||
<span
|
||||
class="notification u-position-absolute u-inset-block-start-8 u-inset-inline-end-8"
|
||||
></span>
|
||||
{/if}
|
||||
<span class="text">Feedback</span>
|
||||
</button>
|
||||
<svelte:fragment slot="other">
|
||||
@@ -179,10 +181,14 @@
|
||||
transition:slideFade|global={{ duration: 150 }}>
|
||||
{#if $organizationList?.total}
|
||||
<section class="drop-section u-overflow-y-auto u-max-height-200">
|
||||
<ul class="drop-list">
|
||||
<ul
|
||||
class="drop-list"
|
||||
data-sveltekit-preload-data={$page.params.organization
|
||||
? false
|
||||
: 'hover'}>
|
||||
{#each $organizationList.teams as org}
|
||||
<DropListLink
|
||||
href={`${base}/console/organization-${org.$id}`}
|
||||
href={`${base}/organization-${org.$id}`}
|
||||
on:click={() => {
|
||||
showDropdown = false;
|
||||
}}>{org.name}</DropListLink>
|
||||
@@ -196,7 +202,7 @@
|
||||
New organization
|
||||
</DropListItem>
|
||||
<DropListLink
|
||||
href={`${base}/console/account`}
|
||||
href={`${base}/account`}
|
||||
on:click={() => (showDropdown = false)}>
|
||||
Your account
|
||||
</DropListLink>
|
||||
|
||||
@@ -21,5 +21,4 @@ export { default as HeaderAlert } from './headerAlert.svelte';
|
||||
export { default as ContainerButton } from './containerButton.svelte';
|
||||
export { default as WizardSecondaryContainer } from './wizardSecondaryContainer.svelte';
|
||||
export { default as WizardSecondaryContent } from './wizardSecondaryContent.svelte';
|
||||
export { default as WizardSecondaryHeader } from './wizardSecondaryHeader.svelte';
|
||||
export { default as WizardSecondaryFooter } from './wizardSecondaryFooter.svelte';
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { isCloud } from '$lib/system';
|
||||
import Create from '$routes/console/feedbackWizard.svelte';
|
||||
import { showSupportModal } from '$routes/console/wizard/support/store';
|
||||
import Create from '$routes/(console)/feedbackWizard.svelte';
|
||||
import { showSupportModal } from '$routes/(console)/wizard/support/store';
|
||||
|
||||
export let isOpen = false;
|
||||
|
||||
$: project = $page.params.project;
|
||||
$: projectPath = `${base}/console/project-${project}`;
|
||||
$: projectPath = `${base}/project-${project}`;
|
||||
|
||||
$: subNavigation = $page.data.subNavigation;
|
||||
// We need to have this second variable, because we only want narrow
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import { log } from '$lib/stores/logs';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { activeHeaderAlert } from '$routes/console/store';
|
||||
import { activeHeaderAlert } from '$routes/(console)/store';
|
||||
|
||||
export let isOpen = false;
|
||||
export let showSideNavigation = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { Avatar, AvatarInitials, Card, Heading } from '$lib/components';
|
||||
import AppwriteLogoDark from '$lib/images/appwrite-logo-dark.svg';
|
||||
import AppwriteLogoLight from '$lib/images/appwrite-logo-light.svg';
|
||||
@@ -7,7 +8,6 @@
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { campaigns, type CampaignData } from '$lib/stores/campaigns';
|
||||
import { user } from '$lib/stores/user';
|
||||
|
||||
export const imgLight = LoginLight;
|
||||
export const imgDark = LoginDark;
|
||||
@@ -16,7 +16,7 @@
|
||||
export let coupon: Coupon = null;
|
||||
|
||||
$: selectedCampaign = campaigns.get(coupon?.campaign ?? campaign);
|
||||
$: variation = (coupon?.campaign ?? campaign ? selectedCampaign?.template : 'default') as
|
||||
$: variation = ((coupon?.campaign ?? campaign) ? selectedCampaign?.template : 'default') as
|
||||
| 'default'
|
||||
| CampaignData['template'];
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
class="logo u-flex u-gap-16"
|
||||
class:is-not-mobile={variation === 'default'}
|
||||
class:logo-variation={variation !== 'default'}>
|
||||
<a href={user ? '/console' : '/'}>
|
||||
<a href={base}>
|
||||
{#if $app.themeInUse === 'dark'}
|
||||
<img
|
||||
src={AppwriteLogoDark}
|
||||
@@ -80,7 +80,7 @@
|
||||
<section
|
||||
class="u-flex u-flex-vertical u-main-center u-cross-center u-height-100-percent u-width-full-line">
|
||||
<img
|
||||
src={`/images/campaigns/${coupon?.campaign ?? campaign}/${$app.themeInUse}.png`}
|
||||
src={`${base}/images/campaigns/${coupon?.campaign ?? campaign}/${$app.themeInUse}.png`}
|
||||
class="u-block u-image-object-fit-cover side-bg-img"
|
||||
alt="promo" />
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="u-margin-block-start-16 u-flex u-gap-16">
|
||||
{#if currentReview?.img}
|
||||
<Avatar
|
||||
src={`/images/campaigns/${coupon?.campaign ?? campaign}/reviewers/${currentReview.img}`}
|
||||
src={`${base}/images/campaigns/${coupon?.campaign ?? campaign}/reviewers/${currentReview.img}`}
|
||||
name={currentReview.name}
|
||||
size={40} />
|
||||
{:else}
|
||||
@@ -164,7 +164,7 @@
|
||||
<p class="u-bold" style:text-transform="uppercase">provided to you by</p>
|
||||
<img
|
||||
style:max-block-size="2.5rem"
|
||||
src={`/images/campaigns/${coupon?.campaign ?? campaign}/footer/${$app.themeInUse}.png`}
|
||||
src={`${base}/images/campaigns/${coupon?.campaign ?? campaign}/footer/${$app.themeInUse}.png`}
|
||||
alt={coupon?.campaign ?? campaign} />
|
||||
</div>
|
||||
{/if}
|
||||
@@ -195,7 +195,7 @@
|
||||
</div>
|
||||
<div
|
||||
class="logo u-flex u-gap-16 u-margin-inline-auto is-only-mobile u-margin-block-start-32">
|
||||
<a href={user ? '/console' : '/'}>
|
||||
<a href={base}>
|
||||
{#if $app.themeInUse === 'dark'}
|
||||
<img
|
||||
src={AppwriteLogoDark}
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
<svelte:component this={component} />
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="form-footer">
|
||||
<div class="u-z-index-20 form-footer">
|
||||
<div class="u-flex u-main-end u-gap-12">
|
||||
{#if !isLastStep && currentStep?.optional}
|
||||
<Button text on:click={() => dispatch('finish')}>
|
||||
|
||||
@@ -1,13 +1,70 @@
|
||||
<script lang="ts">
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { Heading } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import WizardExitModal from './wizardExitModal.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let showExitModal = false;
|
||||
export let href = '';
|
||||
type $$Props =
|
||||
| {
|
||||
confirmExit: boolean;
|
||||
showExitModal: boolean;
|
||||
href?: string;
|
||||
}
|
||||
| {
|
||||
confirmExit?: boolean;
|
||||
showExitModal?: boolean;
|
||||
href: string;
|
||||
};
|
||||
|
||||
export let confirmExit: $$Props['confirmExit'] = false;
|
||||
export let href: $$Props['href'] = '';
|
||||
export let showExitModal: $$Props['showExitModal'] = false;
|
||||
|
||||
function handleKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
if (confirmExit) {
|
||||
showExitModal = true;
|
||||
} else {
|
||||
goto(href);
|
||||
trackEvent('wizard_exit', {
|
||||
from: 'escape'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={handleKeydown} />
|
||||
|
||||
<section class="wizard-secondary c-wizard-position">
|
||||
<div class="wizard-secondary-container">
|
||||
<header class="wizard-secondary-header">
|
||||
<div class="u-flex u-main-space-between u-gap-32 u-cross-center">
|
||||
<Heading size={5} tag="h1"><slot name="title" /></Heading>
|
||||
<Button
|
||||
text
|
||||
round
|
||||
ariaLabel="close modal"
|
||||
href={confirmExit ? null : href}
|
||||
on:click={() => {
|
||||
if (confirmExit) {
|
||||
showExitModal = true;
|
||||
} else {
|
||||
trackEvent('wizard_exit', {
|
||||
from: 'button'
|
||||
});
|
||||
}
|
||||
}}>
|
||||
<span class="icon-x u-font-size-20" aria-hidden="true"></span>
|
||||
</Button>
|
||||
</div>
|
||||
{#if $$slots.description}
|
||||
<p class="body-text-2"><slot name="description" /></p>
|
||||
{/if}
|
||||
</header>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { Heading } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
type $$Props =
|
||||
| {
|
||||
confirmExit: boolean;
|
||||
href?: string;
|
||||
}
|
||||
| {
|
||||
confirmExit?: boolean;
|
||||
href: string;
|
||||
};
|
||||
|
||||
export let confirmExit: $$Props['confirmExit'] = false;
|
||||
export let href: $$Props['href'] = '';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
<header class="wizard-secondary-header">
|
||||
<div class="u-flex u-main-space-between u-gap-32 u-cross-center">
|
||||
<Heading size={5} tag="h1"><slot /></Heading>
|
||||
<Button
|
||||
text
|
||||
round
|
||||
ariaLabel="close modal"
|
||||
href={confirmExit ? null : href}
|
||||
on:click={() => {
|
||||
if (confirmExit) {
|
||||
dispatch('exit');
|
||||
} else {
|
||||
trackEvent('wizard_exit', {
|
||||
from: 'button'
|
||||
});
|
||||
}
|
||||
}}>
|
||||
<span class="icon-x u-font-size-20" aria-hidden="true"></span>
|
||||
</Button>
|
||||
</div>
|
||||
{#if $$slots.description}
|
||||
<p class="body-text-2"><slot name="description" /></p>
|
||||
{/if}
|
||||
</header>
|
||||
@@ -5,9 +5,9 @@
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { isSelfHosted } from '$lib/system';
|
||||
import { func } from '$routes/console/project-[project]/functions/function-[function]/store';
|
||||
import { func } from '$routes/(console)/project-[project]/functions/function-[function]/store';
|
||||
import { domain, typeStore } from './store';
|
||||
import { consoleVariables } from '$routes/console/store';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { ResourceType } from '@appwrite.io/console';
|
||||
|
||||
let error = null;
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
import { AppwriteException, Runtime, type Client, type Payload } from '@appwrite.io/console';
|
||||
|
||||
export type Specs = {
|
||||
cpus: number[];
|
||||
memory: number[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Variable
|
||||
*/
|
||||
type Variable = {
|
||||
/**
|
||||
* Variable ID.
|
||||
*/
|
||||
$id: string;
|
||||
/**
|
||||
* Variable creation date in ISO 8601 format.
|
||||
*/
|
||||
$createdAt: string;
|
||||
/**
|
||||
* Variable creation date in ISO 8601 format.
|
||||
*/
|
||||
$updatedAt: string;
|
||||
/**
|
||||
* Variable key.
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* Variable value.
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* Service to which the variable belongs. Possible values are "project", "function"
|
||||
*/
|
||||
resourceType: string;
|
||||
/**
|
||||
* ID of resource to which the variable belongs. If resourceType is "project", it is empty. If resourceType is "function", it is ID of the function.
|
||||
*/
|
||||
resourceId: string;
|
||||
};
|
||||
|
||||
export type Func = {
|
||||
/**
|
||||
* Function ID.
|
||||
*/
|
||||
$id: string;
|
||||
/**
|
||||
* Function creation date in ISO 8601 format.
|
||||
*/
|
||||
$createdAt: string;
|
||||
/**
|
||||
* Function update date in ISO 8601 format.
|
||||
*/
|
||||
$updatedAt: string;
|
||||
/**
|
||||
* Execution permissions.
|
||||
*/
|
||||
execute: string[];
|
||||
/**
|
||||
* Function name.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Function enabled.
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* Is the function deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the function to update it with the latest configuration.
|
||||
*/
|
||||
live: boolean;
|
||||
/**
|
||||
* Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.
|
||||
*/
|
||||
logging: boolean;
|
||||
/**
|
||||
* Function execution runtime.
|
||||
*/
|
||||
runtime: string;
|
||||
/**
|
||||
* Function's active deployment ID.
|
||||
*/
|
||||
deployment: string;
|
||||
/**
|
||||
* Function variables.
|
||||
*/
|
||||
vars: Variable[];
|
||||
/**
|
||||
* Function trigger events.
|
||||
*/
|
||||
events: string[];
|
||||
/**
|
||||
* Function execution schedult in CRON format.
|
||||
*/
|
||||
schedule: string;
|
||||
/**
|
||||
* Function execution timeout in seconds.
|
||||
*/
|
||||
timeout: number;
|
||||
/**
|
||||
* The entrypoint file used to execute the deployment.
|
||||
*/
|
||||
entrypoint: string;
|
||||
/**
|
||||
* The build command used to build the deployment.
|
||||
*/
|
||||
commands: string;
|
||||
/**
|
||||
* Version of Open Runtimes used for the function.
|
||||
*/
|
||||
version: string;
|
||||
/**
|
||||
* Function VCS (Version Control System) installation id.
|
||||
*/
|
||||
installationId: string;
|
||||
/**
|
||||
* VCS (Version Control System) Repository ID
|
||||
*/
|
||||
providerRepositoryId: string;
|
||||
/**
|
||||
* VCS (Version Control System) branch name
|
||||
*/
|
||||
providerBranch: string;
|
||||
/**
|
||||
* Path to function in VCS (Version Control System) repository
|
||||
*/
|
||||
providerRootDirectory: string;
|
||||
/**
|
||||
* Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests
|
||||
*/
|
||||
providerSilentMode: boolean;
|
||||
/**
|
||||
* CPU limit
|
||||
*/
|
||||
cpus: number;
|
||||
/**
|
||||
* Memory limit
|
||||
*/
|
||||
memory: number;
|
||||
};
|
||||
|
||||
export class SpecsFunctions {
|
||||
client: Client;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async getSpecs(): Promise<Specs> {
|
||||
const path = '/functions/specs';
|
||||
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call('GET', uri, {
|
||||
'content-type': 'application/json'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update function
|
||||
*
|
||||
* Update function by its unique ID.
|
||||
*
|
||||
* @param {string} functionId
|
||||
* @param {string} name
|
||||
* @param {Runtime} runtime
|
||||
* @param {string[]} execute
|
||||
* @param {string[]} events
|
||||
* @param {string} schedule
|
||||
* @param {number} timeout
|
||||
* @param {boolean} enabled
|
||||
* @param {boolean} logging
|
||||
* @param {string} entrypoint
|
||||
* @param {string} commands
|
||||
* @param {string} installationId
|
||||
* @param {string} providerRepositoryId
|
||||
* @param {string} providerBranch
|
||||
* @param {boolean} providerSilentMode
|
||||
* @param {string} providerRootDirectory
|
||||
* @param {number} cpus
|
||||
* @param {number} memory
|
||||
* @throws {AppwriteException}
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async update(
|
||||
functionId: string,
|
||||
name: string,
|
||||
runtime?: Runtime,
|
||||
execute?: string[],
|
||||
events?: string[],
|
||||
schedule?: string,
|
||||
timeout?: number,
|
||||
enabled?: boolean,
|
||||
logging?: boolean,
|
||||
entrypoint?: string,
|
||||
commands?: string,
|
||||
installationId?: string,
|
||||
providerRepositoryId?: string,
|
||||
providerBranch?: string,
|
||||
providerSilentMode?: boolean,
|
||||
providerRootDirectory?: string,
|
||||
cpus?: number,
|
||||
memory?: number
|
||||
): Promise<Func> {
|
||||
if (typeof functionId === 'undefined') {
|
||||
throw new AppwriteException('Missing required parameter: "functionId"');
|
||||
}
|
||||
|
||||
if (typeof name === 'undefined') {
|
||||
throw new AppwriteException('Missing required parameter: "name"');
|
||||
}
|
||||
|
||||
const apiPath = '/functions/{functionId}'.replace('{functionId}', functionId);
|
||||
const payload: Payload = {};
|
||||
|
||||
if (typeof name !== 'undefined') {
|
||||
payload['name'] = name;
|
||||
}
|
||||
|
||||
if (typeof runtime !== 'undefined') {
|
||||
payload['runtime'] = runtime;
|
||||
}
|
||||
|
||||
if (typeof execute !== 'undefined') {
|
||||
payload['execute'] = execute;
|
||||
}
|
||||
|
||||
if (typeof events !== 'undefined') {
|
||||
payload['events'] = events;
|
||||
}
|
||||
|
||||
if (typeof schedule !== 'undefined') {
|
||||
payload['schedule'] = schedule;
|
||||
}
|
||||
|
||||
if (typeof timeout !== 'undefined') {
|
||||
payload['timeout'] = timeout;
|
||||
}
|
||||
|
||||
if (typeof enabled !== 'undefined') {
|
||||
payload['enabled'] = enabled;
|
||||
}
|
||||
|
||||
if (typeof logging !== 'undefined') {
|
||||
payload['logging'] = logging;
|
||||
}
|
||||
|
||||
if (typeof entrypoint !== 'undefined') {
|
||||
payload['entrypoint'] = entrypoint;
|
||||
}
|
||||
|
||||
if (typeof commands !== 'undefined') {
|
||||
payload['commands'] = commands;
|
||||
}
|
||||
|
||||
if (typeof installationId !== 'undefined') {
|
||||
payload['installationId'] = installationId;
|
||||
}
|
||||
|
||||
if (typeof providerRepositoryId !== 'undefined') {
|
||||
payload['providerRepositoryId'] = providerRepositoryId;
|
||||
}
|
||||
|
||||
if (typeof providerBranch !== 'undefined') {
|
||||
payload['providerBranch'] = providerBranch;
|
||||
}
|
||||
|
||||
if (typeof providerSilentMode !== 'undefined') {
|
||||
payload['providerSilentMode'] = providerSilentMode;
|
||||
}
|
||||
|
||||
if (typeof providerRootDirectory !== 'undefined') {
|
||||
payload['providerRootDirectory'] = providerRootDirectory;
|
||||
}
|
||||
|
||||
if (typeof cpus !== 'undefined') {
|
||||
payload['cpus'] = cpus;
|
||||
}
|
||||
|
||||
if (typeof memory !== 'undefined') {
|
||||
payload['memory'] = memory;
|
||||
}
|
||||
|
||||
const uri = new URL(this.client.config.endpoint + apiPath);
|
||||
return await this.client.call(
|
||||
'put',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
payload
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,18 @@ import PaymentAuthRequired from '$lib/components/billing/alerts/paymentAuthRequi
|
||||
import { addNotification, notifications } from './notifications';
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { activeHeaderAlert, orgMissingPaymentMethod } from '$routes/console/store';
|
||||
import { activeHeaderAlert, orgMissingPaymentMethod } from '$routes/(console)/store';
|
||||
import MarkedForDeletion from '$lib/components/billing/alerts/markedForDeletion.svelte';
|
||||
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 { trackEvent } from '$lib/actions/analytics';
|
||||
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';
|
||||
|
||||
@@ -51,6 +54,28 @@ export function tierToPlan(tier: Tier) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getNextTier(tier: Tier) {
|
||||
switch (tier) {
|
||||
case BillingPlan.FREE:
|
||||
return BillingPlan.PRO;
|
||||
case BillingPlan.PRO:
|
||||
return BillingPlan.SCALE;
|
||||
default:
|
||||
return BillingPlan.PRO;
|
||||
}
|
||||
}
|
||||
|
||||
export function getPreviousTier(tier: Tier) {
|
||||
switch (tier) {
|
||||
case BillingPlan.PRO:
|
||||
return BillingPlan.FREE;
|
||||
case BillingPlan.SCALE:
|
||||
return BillingPlan.PRO;
|
||||
default:
|
||||
return BillingPlan.FREE;
|
||||
}
|
||||
}
|
||||
|
||||
export type PlanServices =
|
||||
| 'bandwidth'
|
||||
| 'bandwidthAddon'
|
||||
@@ -234,13 +259,13 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
{
|
||||
name: 'View usage',
|
||||
method: () => {
|
||||
goto(`${base}/console/organization-${org.$id}/usage`);
|
||||
goto(`${base}/organization-${org.$id}/usage`);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Upgrade plan',
|
||||
method: () => {
|
||||
goto(`${base}/console/organization-${org.$id}/change-plan`);
|
||||
goto(`${base}/organization-${org.$id}/change-plan`);
|
||||
trackEvent('click_organization_upgrade', {
|
||||
from: 'button',
|
||||
source: 'limit_reached_notification'
|
||||
@@ -298,7 +323,7 @@ export async function paymentExpired(org: Organization) {
|
||||
{
|
||||
name: 'Update payment details',
|
||||
method: () => {
|
||||
goto(`${base}/console/account/payments`);
|
||||
goto(`${base}/account/payments`);
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -312,7 +337,7 @@ export async function paymentExpired(org: Organization) {
|
||||
{
|
||||
name: 'Update payment details',
|
||||
method: () => {
|
||||
goto(`${base}/console/account/payments`);
|
||||
goto(`${base}/account/payments`);
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -366,9 +391,33 @@ export async function checkForMissingPaymentMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
// 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 now = new Date().getTime();
|
||||
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: 'newDevUpgradePro',
|
||||
component: newDevUpgradePro,
|
||||
show: true,
|
||||
importance: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
export const upgradeURL = derived(
|
||||
page,
|
||||
($page) => `${base}/console/organization-${$page.data?.organization?.$id}/change-plan`
|
||||
($page) => `${base}/organization-${$page.data?.organization?.$id}/change-plan`
|
||||
);
|
||||
|
||||
export const hideBillingHeaderRoutes = ['/console/create-organization', '/console/account'];
|
||||
|
||||
@@ -76,10 +76,10 @@ campaigns
|
||||
data: {
|
||||
reviews: [
|
||||
{
|
||||
name: 'Marius Bloki',
|
||||
desc: 'CTO // mySHOEFITTER',
|
||||
img: 'js_mastery_reviewer_1.png',
|
||||
review: 'Appwrite has been a tremendous asset in implementing our IT infrastructure. Not only is the software an absolute game-changer, but the team is always there when you need them.'
|
||||
name: 'Adrian Hajdin',
|
||||
desc: 'Founder & CEO at JavaScript Mastery',
|
||||
img: 'js_mastery_reviewer_2.webp',
|
||||
review: 'Appwrite is the fastest-to-implement open-source BaaS with a growing community and a practical suite of products and APIs'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -30,14 +30,14 @@ export type FeedbackOption = {
|
||||
export const feedbackOptions: FeedbackOption[] = [
|
||||
{
|
||||
type: 'general',
|
||||
title: 'How can we improve?',
|
||||
desc: 'Your feedback is important to us. Please be honest and tell us what you think.',
|
||||
title: 'Help us improve Appwrite',
|
||||
desc: 'Appwrite evolves with your input. Share your thoughts and help us improve Appwrite.',
|
||||
component: FeedbackGeneral
|
||||
},
|
||||
{
|
||||
type: 'nps',
|
||||
title: 'How are we doing?',
|
||||
desc: "At Appwrite, we value the feedback of our users. That means you! We'd love to hear what you think.",
|
||||
title: 'Help us improve Appwrite',
|
||||
desc: 'Appwrite evolves with your input. Share your thoughts and help us improve Appwrite. If you would like to be contacted regarding your feedback, please share your contact details below.',
|
||||
component: FeedbackNps
|
||||
}
|
||||
];
|
||||
@@ -49,7 +49,7 @@ function createFeedbackDataStore() {
|
||||
message: '',
|
||||
name: '',
|
||||
email: '',
|
||||
value: 0
|
||||
value: null
|
||||
});
|
||||
return {
|
||||
set,
|
||||
@@ -60,7 +60,7 @@ function createFeedbackDataStore() {
|
||||
feedbackData.message = '';
|
||||
feedbackData.name = '';
|
||||
feedbackData.email = '';
|
||||
feedbackData.value = 0;
|
||||
feedbackData.value = null;
|
||||
return feedbackData;
|
||||
});
|
||||
}
|
||||
@@ -71,8 +71,8 @@ export const feedbackData = createFeedbackDataStore();
|
||||
|
||||
function createFeedbackStore() {
|
||||
const { subscribe, update } = writable<Feedback>({
|
||||
elapsed: browser ? parseInt(localStorage.getItem('feedbackElapsed')) : 0,
|
||||
visualized: browser ? parseInt(localStorage.getItem('feedbackVisualized')) : 0,
|
||||
elapsed: browser ? (parseInt(localStorage.getItem('feedbackElapsed')) ?? 0) : 0,
|
||||
visualized: browser ? (parseInt(localStorage.getItem('feedbackVisualized')) ?? 0) : 0,
|
||||
notification: false,
|
||||
type: 'general',
|
||||
show: false
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { SvelteComponent } from 'svelte';
|
||||
import Apple from '../../routes/console/project-[project]/auth/(providers)/appleOAuth.svelte';
|
||||
import Auth0 from '../../routes/console/project-[project]/auth/(providers)/auth0OAuth.svelte';
|
||||
import Authentik from '../../routes/console/project-[project]/auth/(providers)/authentikOAuth.svelte';
|
||||
import GitLab from '../../routes/console/project-[project]/auth/(providers)/gitlabOAuth.svelte';
|
||||
import Google from '../../routes/console/project-[project]/auth/(providers)/googleOAuth.svelte';
|
||||
import Main from '../../routes/console/project-[project]/auth/(providers)/mainOAuth.svelte';
|
||||
import Microsoft from '../../routes/console/project-[project]/auth/(providers)/microsoftOAuth.svelte';
|
||||
import Oidc from '../../routes/console/project-[project]/auth/(providers)/oidcOAuth.svelte';
|
||||
import Okta from '../../routes/console/project-[project]/auth/(providers)/oktaOAuth.svelte';
|
||||
import Apple from '$routes/(console)/project-[project]/auth/(providers)/appleOAuth.svelte';
|
||||
import Auth0 from '$routes/(console)/project-[project]/auth/(providers)/auth0OAuth.svelte';
|
||||
import Authentik from '$routes/(console)/project-[project]/auth/(providers)/authentikOAuth.svelte';
|
||||
import GitLab from '$routes/(console)/project-[project]/auth/(providers)/gitlabOAuth.svelte';
|
||||
import Google from '$routes/(console)/project-[project]/auth/(providers)/googleOAuth.svelte';
|
||||
import Main from '$routes/(console)/project-[project]/auth/(providers)/mainOAuth.svelte';
|
||||
import Microsoft from '$routes/(console)/project-[project]/auth/(providers)/microsoftOAuth.svelte';
|
||||
import Oidc from '$routes/(console)/project-[project]/auth/(providers)/oidcOAuth.svelte';
|
||||
import Okta from '$routes/(console)/project-[project]/auth/(providers)/oktaOAuth.svelte';
|
||||
|
||||
export type Provider = {
|
||||
name: string;
|
||||
|
||||
@@ -23,9 +23,13 @@ import {
|
||||
} from '@appwrite.io/console';
|
||||
import { Billing } from '../sdk/billing';
|
||||
import { Sources } from '$lib/sdk/sources';
|
||||
import { SpecsFunctions } from '$lib/sdk/functionsSpec';
|
||||
|
||||
const endpoint = VARS.APPWRITE_ENDPOINT ?? `${globalThis?.location?.origin}/v1`;
|
||||
export function getApiEndpoint(): string {
|
||||
if (VARS.APPWRITE_ENDPOINT) return VARS.APPWRITE_ENDPOINT;
|
||||
return globalThis?.location?.origin + '/v1';
|
||||
}
|
||||
|
||||
const endpoint = getApiEndpoint();
|
||||
|
||||
const clientConsole = new Client();
|
||||
clientConsole.setEndpoint(endpoint).setProject('console');
|
||||
@@ -39,7 +43,6 @@ const sdkForProject = {
|
||||
avatars: new Avatars(clientProject),
|
||||
databases: new Databases(clientProject),
|
||||
functions: new Functions(clientProject),
|
||||
specsFunctions: new SpecsFunctions(clientProject),
|
||||
health: new Health(clientProject),
|
||||
locale: new Locale(clientProject),
|
||||
messaging: new Messaging(clientProject),
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { PaymentMethodData } from '$lib/sdk/billing';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { addNotification } from './notifications';
|
||||
import { organization } from './organization';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const stripe = writable<Stripe>();
|
||||
let paymentMethod: PaymentMethodData;
|
||||
@@ -120,7 +121,7 @@ export async function confirmPayment(
|
||||
) {
|
||||
try {
|
||||
const url =
|
||||
window.location.origin + (route ? route : `/console/organization-${orgId}/billing`);
|
||||
window.location.origin + (route ? route : `${base}/organization-${orgId}/billing`);
|
||||
|
||||
const paymentMethod = await sdk.forConsole.billing.getPaymentMethod(paymentMethodId);
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { page } from '$app/stores';
|
||||
import { derived } from 'svelte/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
export const user = derived(
|
||||
page,
|
||||
($page) => $page.data.account as Models.User<Record<string, string>>
|
||||
);
|
||||
export type Account = Models.User<{ organization?: string } & Record<string, string>>;
|
||||
|
||||
export const user = derived(page, ($page) => {
|
||||
if (browser) sessionStorage.setItem('account', JSON.stringify($page.data.account));
|
||||
return $page.data.account as Account;
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { timeFromNow } from '$lib/helpers/date';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { repositories } from '$routes/console/project-[project]/functions/function-[function]/store';
|
||||
import { repositories } from '$routes/(console)/project-[project]/functions/function-[function]/store';
|
||||
import { installation, installations, repository } from '../store';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
<p class="text u-margin-block-start-16">
|
||||
Manage organization configuration in your <a
|
||||
class="link"
|
||||
href={`${base}/console/project-${$page.params.project}/settings`}>project settings</a
|
||||
href={`${base}/project-${$page.params.project}/settings`}>project settings</a
|
||||
>.
|
||||
</p>
|
||||
{#if selectedInstallation}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import GitConfiguration from './steps/gitConfiguration.svelte';
|
||||
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { func } from '$routes/console/project-[project]/functions/function-[function]/store';
|
||||
import { func } from '$routes/(console)/project-[project]/functions/function-[function]/store';
|
||||
import { choices, installation, repository } from './store';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { invalidate } from '$app/navigation';
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
import { marketplace, type MarketplaceTemplate } from '$lib/stores/marketplace';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { page } from '$app/stores';
|
||||
import { baseRuntimesList } from '$routes/console/project-[project]/functions/store';
|
||||
import { baseRuntimesList } from '$routes/(console)/project-[project]/functions/store';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import WizardCover from '$lib/layout/wizardCover.svelte';
|
||||
@@ -40,7 +40,7 @@
|
||||
import CreateGit from './createGit.svelte';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import { isSelfHosted } from '$lib/system';
|
||||
import { consoleVariables } from '$routes/console/store';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
|
||||
const isVcsEnabled = $consoleVariables?._APP_VCS_ENABLED === true;
|
||||
let hasInstallations: boolean;
|
||||
@@ -252,7 +252,7 @@
|
||||
text
|
||||
noMargin
|
||||
class="u-margin-inline-start-auto u-margin-block-start-16"
|
||||
href={`${base}/console/project-${$page.params.project}/functions/templates`}>
|
||||
href={`${base}/project-${$page.params.project}/functions/templates`}>
|
||||
<span> All templates </span>
|
||||
<span class="icon-cheveron-right" aria-hidden="true" />
|
||||
</Button>
|
||||
|
||||
@@ -39,9 +39,7 @@
|
||||
$choices.silentMode || undefined,
|
||||
$choices.rootDir || undefined
|
||||
);
|
||||
goto(
|
||||
`${base}/console/project-${$page.params.project}/functions/function-${response.$id}`
|
||||
);
|
||||
goto(`${base}/project-${$page.params.project}/functions/function-${response.$id}`);
|
||||
addNotification({
|
||||
message: `${$createFunction.name} has been created`,
|
||||
type: 'success'
|
||||
|
||||
@@ -44,9 +44,7 @@
|
||||
$createFunctionDeployment[0],
|
||||
true
|
||||
);
|
||||
goto(
|
||||
`${base}/console/project-${$page.params.project}/functions/function-${response.$id}`
|
||||
);
|
||||
goto(`${base}/project-${$page.params.project}/functions/function-${response.$id}`);
|
||||
addNotification({
|
||||
message: `${$createFunction.name} has been created`,
|
||||
type: 'success'
|
||||
|
||||
@@ -69,9 +69,7 @@
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
goto(
|
||||
`${base}/console/project-${$page.params.project}/functions/function-${response.$id}`
|
||||
);
|
||||
goto(`${base}/project-${$page.params.project}/functions/function-${response.$id}`);
|
||||
addNotification({
|
||||
message: `${response.name} has been created`,
|
||||
type: 'success'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { onMount } from 'svelte';
|
||||
import { createFunction } from '../store';
|
||||
import { runtimesList } from '$routes/console/project-[project]/functions/store';
|
||||
import { runtimesList } from '$routes/(console)/project-[project]/functions/store';
|
||||
|
||||
let showCustomId = false;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { choices, createFunction, installation, repository } from '../store';
|
||||
import { runtimesList } from '$routes/console/project-[project]/functions/store';
|
||||
import { runtimesList } from '$routes/(console)/project-[project]/functions/store';
|
||||
|
||||
let showCustomId = false;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import InputSelectSearch from '$lib/elements/forms/inputSelectSearch.svelte';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { sortBranches } from '$routes/console/project-[project]/functions/function-[function]/settings/updateConfiguration.svelte';
|
||||
import { sortBranches } from '$routes/(console)/project-[project]/functions/function-[function]/settings/updateConfiguration.svelte';
|
||||
import { choices, installation, repository } from '../store';
|
||||
|
||||
$choices.rootDir ??= '';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { Pill } from '$lib/elements';
|
||||
import { FormList, InputSelect, InputText } from '$lib/elements/forms';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { runtimesList } from '$routes/console/project-[project]/functions/store';
|
||||
import { runtimesList } from '$routes/(console)/project-[project]/functions/store';
|
||||
import { template, templateConfig } from '../store';
|
||||
|
||||
let showCustomId = false;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { base } from '$app/paths';
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
export const load: LayoutLoad = async ({ parent }) => {
|
||||
const { account } = await parent();
|
||||
|
||||
if (!account) {
|
||||
redirect(303, base);
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { Container } from '$lib/layout';
|
||||
import { loading } from '../store';
|
||||
import { loading } from '$routes/store';
|
||||
|
||||
loading.set(false);
|
||||
</script>
|
||||
+2
-2
@@ -2,8 +2,9 @@
|
||||
import { page } from '$app/stores';
|
||||
import { Vcs, Client } from '@appwrite.io/console';
|
||||
import { onMount } from 'svelte';
|
||||
import { VARS } from '$lib/system';
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
|
||||
const endpoint = getApiEndpoint();
|
||||
const client = new Client();
|
||||
const vcs = new Vcs(client);
|
||||
|
||||
@@ -16,7 +17,6 @@
|
||||
let success = '';
|
||||
|
||||
onMount(async () => {
|
||||
const endpoint = VARS.APPWRITE_ENDPOINT ?? `${$page.url.origin}/v1`;
|
||||
const projectId = $page.url.searchParams.get('projectId');
|
||||
client.setEndpoint(endpoint).setProject(projectId).setMode('admin');
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
async function back() {
|
||||
await sdk.forConsole.account.deleteSession('current');
|
||||
await goto(`${base}/`);
|
||||
await goto(base);
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
@@ -30,12 +30,12 @@
|
||||
const redirect = $page.url.searchParams.get('redirect');
|
||||
$page.url.searchParams.delete('redirect');
|
||||
if (redirect) {
|
||||
await goto(`${base}${redirect}${$page.url.search}`);
|
||||
await goto(`${redirect}${$page.url.search}`);
|
||||
} else {
|
||||
await goto(`${base}/console${$page.url.search ?? ''}`);
|
||||
await goto(`${base}/${$page.url.search ?? ''}`);
|
||||
}
|
||||
} else {
|
||||
await goto(`${base}/console`);
|
||||
await goto(base);
|
||||
}
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
+2
-1
@@ -10,6 +10,7 @@
|
||||
import Step1 from './step1.svelte';
|
||||
import Step2 from './step2.svelte';
|
||||
import { requestedMigration } from '$routes/store';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
const onExit = () => {
|
||||
formData.reset();
|
||||
@@ -30,7 +31,7 @@
|
||||
await invalidateAll();
|
||||
wizard.hide();
|
||||
|
||||
goto(`/console/project-${$selectedProject}/settings/migrations`);
|
||||
goto(`${base}/project-${$selectedProject}/settings/migrations`);
|
||||
};
|
||||
|
||||
onDestroy(onExit);
|
||||
@@ -1,4 +1,5 @@
|
||||
<script>
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Heading } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
@@ -9,6 +10,6 @@
|
||||
<div class="u-flex-vertical u-gap-16">
|
||||
<Heading size="1" tag="h3">{$page.error.status || 'Invalid Argument'}</Heading>
|
||||
<Heading size="4" tag="h4" trimmed={false}>{$page.error.message}</Heading>
|
||||
<Button href="/console">Back to the console</Button>
|
||||
<Button href={base}>Back to the console</Button>
|
||||
</div>
|
||||
</Container>
|
||||
@@ -11,7 +11,8 @@
|
||||
import { newOrgModal, organization } from '$lib/stores/organization';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { afterUpdate, onMount } from 'svelte';
|
||||
import { loading, requestedMigration } from '../store';
|
||||
import { loading } from '$routes/store';
|
||||
import { requestedMigration } from '../store';
|
||||
import Create from './createOrganization.svelte';
|
||||
import {
|
||||
showUsageRatesModal,
|
||||
@@ -22,6 +23,7 @@
|
||||
checkForMarkedForDeletion,
|
||||
checkForMandate,
|
||||
checkForMissingPaymentMethod,
|
||||
checkForNewDevUpgradePro,
|
||||
plansInfo
|
||||
} from '$lib/stores/billing';
|
||||
import { goto } from '$app/navigation';
|
||||
@@ -40,6 +42,7 @@
|
||||
import { activeHeaderAlert, consoleVariables } from './store';
|
||||
import { headerAlert } from '$lib/stores/headerAlert';
|
||||
import { UsageRates } from '$lib/components/billing';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
function kebabToSentenceCase(str: string) {
|
||||
return str
|
||||
@@ -58,7 +61,7 @@
|
||||
{
|
||||
label: 'Go to Projects',
|
||||
callback: () => {
|
||||
goto('/console');
|
||||
goto(base);
|
||||
},
|
||||
keys: ['g', 'p'],
|
||||
group: 'navigation',
|
||||
@@ -146,7 +149,7 @@
|
||||
({
|
||||
label: kebabToSentenceCase(heading),
|
||||
async callback() {
|
||||
await goto(`/console/project-${$project.$id}/auth/security#${heading}`);
|
||||
await goto(`${base}/project-${$project.$id}/auth/security#${heading}`);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
disabled: !$project?.$id,
|
||||
@@ -160,7 +163,7 @@
|
||||
|
||||
keys: isOnSettingsLayout ? ['g', 'o'] : undefined,
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings`);
|
||||
goto(`${base}/project-${$project.$id}/settings`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.endsWith('settings')),
|
||||
@@ -172,7 +175,7 @@
|
||||
|
||||
keys: isOnSettingsLayout ? ['g', 'd'] : undefined,
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings/domains`);
|
||||
goto(`${base}/project-${$project.$id}/settings/domains`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('domains')),
|
||||
@@ -183,7 +186,7 @@
|
||||
label: 'Go to webhooks',
|
||||
keys: isOnSettingsLayout ? ['g', 'w'] : undefined,
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings/webhooks`);
|
||||
goto(`${base}/project-${$project.$id}/settings/webhooks`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('webhooks')),
|
||||
@@ -195,7 +198,7 @@
|
||||
label: 'Go to migrations',
|
||||
keys: isOnSettingsLayout ? ['g', 'm'] : undefined,
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings/migrations`);
|
||||
goto(`${base}/project-${$project.$id}/settings/migrations`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('migrations')),
|
||||
@@ -207,8 +210,7 @@
|
||||
label: 'Go to SMTP settings',
|
||||
keys: isOnSettingsLayout ? ['g', 's'] : undefined,
|
||||
callback: () => {
|
||||
console.log('withing callback of go to smtp');
|
||||
goto(`/console/project-${$project.$id}/settings/smtp`);
|
||||
goto(`${base}/project-${$project.$id}/settings/smtp`);
|
||||
},
|
||||
disabled: !$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('smtp')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
@@ -235,7 +237,9 @@
|
||||
let isOpen = false;
|
||||
onMount(async () => {
|
||||
loading.set(false);
|
||||
|
||||
if (!localStorage.getItem('feedbackElapsed')) {
|
||||
localStorage.setItem('feedbackElapsed', '0');
|
||||
}
|
||||
setInterval(() => {
|
||||
checkForFeedback(INTERVAL);
|
||||
}, INTERVAL);
|
||||
@@ -266,10 +270,13 @@
|
||||
if (isCloud) {
|
||||
await checkForUsageLimit(org);
|
||||
checkForMarkedForDeletion(org);
|
||||
await checkForNewDevUpgradePro(org);
|
||||
|
||||
if (org?.billingPlan !== BillingPlan.FREE) {
|
||||
await paymentExpired(org);
|
||||
await checkPaymentAuthorizationRequired(org);
|
||||
await checkForMandate(org);
|
||||
|
||||
if ($plansInfo.get(org.billingPlan)?.trialDays) {
|
||||
calculateTrialDay(org);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { isCloud } from '$lib/system';
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
export const load: LayoutLoad = async ({ fetch, depends, parent }) => {
|
||||
await parent(); // ensure user is authenticated before proceeding
|
||||
await parent();
|
||||
|
||||
depends(Dependencies.RUNTIMES);
|
||||
depends(Dependencies.CONSOLE_VARIABLES);
|
||||
@@ -8,12 +8,10 @@ export const load: LayoutLoad = async ({ depends }) => {
|
||||
depends(Dependencies.FACTORS);
|
||||
depends(Dependencies.IDENTITIES);
|
||||
|
||||
const promises = [
|
||||
const [factors, identities] = await Promise.all([
|
||||
sdk.forConsole.account.listMfaFactors(),
|
||||
sdk.forConsole.account.listIdentities()
|
||||
];
|
||||
|
||||
const [factors, identities] = await Promise.all(promises);
|
||||
]);
|
||||
|
||||
return {
|
||||
factors,
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { Breadcrumbs } from '$lib/layout';
|
||||
import { user } from '$lib/stores/user';
|
||||
|
||||
$: breadcrumbs = [
|
||||
{
|
||||
href: `/console/account`,
|
||||
href: `${base}/account`,
|
||||
title: $user?.name
|
||||
}
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user