mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'main' into feat-project-labels
This commit is contained in:
@@ -27,7 +27,7 @@ export const oAuthProviders: Record<string, Provider> = {
|
||||
apple: {
|
||||
name: 'Apple',
|
||||
icon: 'apple',
|
||||
docs: 'https://developer.apple.com/',
|
||||
docs: 'https://developer.apple.com/sign-in-with-apple/',
|
||||
component: Apple
|
||||
},
|
||||
auth0: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Client, ID, type Models, Sites, Storage } from '@appwrite.io/console';
|
||||
import { Client, Functions, ID, type Models, Sites, Storage } from '@appwrite.io/console';
|
||||
import { writable } from 'svelte/store';
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
import { page } from '$app/state';
|
||||
@@ -32,6 +32,13 @@ const temporarySites = (region: string, projectId: string) => {
|
||||
return new Sites(clientProject);
|
||||
};
|
||||
|
||||
const temporaryFunctions = (region: string, projectId: string) => {
|
||||
const clientProject = new Client().setMode('admin');
|
||||
const endpoint = getApiEndpoint(region);
|
||||
clientProject.setEndpoint(endpoint).setProject(projectId);
|
||||
return new Functions(clientProject);
|
||||
};
|
||||
|
||||
const createUploader = () => {
|
||||
const { subscribe, set, update } = writable<Uploader>({
|
||||
isOpen: false,
|
||||
@@ -110,7 +117,19 @@ const createUploader = () => {
|
||||
newFile.status = 'success';
|
||||
updateFile(newFile.$id, newFile);
|
||||
},
|
||||
uploadSiteDeployment: async (siteId: string, code: File) => {
|
||||
uploadSiteDeployment: async ({
|
||||
siteId,
|
||||
code,
|
||||
buildCommand,
|
||||
installCommand,
|
||||
outputDirectory
|
||||
}: {
|
||||
siteId: string;
|
||||
code: File;
|
||||
buildCommand?: string;
|
||||
installCommand?: string;
|
||||
outputDirectory?: string;
|
||||
}) => {
|
||||
const newDeployment: UploaderFile = {
|
||||
$id: '',
|
||||
resourceId: siteId,
|
||||
@@ -132,6 +151,49 @@ const createUploader = () => {
|
||||
siteId,
|
||||
code,
|
||||
activate: true,
|
||||
buildCommand,
|
||||
installCommand,
|
||||
outputDirectory,
|
||||
onProgress: (progress) => {
|
||||
newDeployment.$id = progress.$id;
|
||||
newDeployment.progress = progress.progress;
|
||||
newDeployment.status = progress.progress === 100 ? 'success' : 'pending';
|
||||
updateFile(progress.$id, newDeployment);
|
||||
}
|
||||
});
|
||||
newDeployment.$id = uploadedFile.$id;
|
||||
newDeployment.progress = 100;
|
||||
newDeployment.status = 'success';
|
||||
updateFile(newDeployment.$id, newDeployment);
|
||||
},
|
||||
uploadFunctionDeployment: async ({
|
||||
functionId,
|
||||
code
|
||||
}: {
|
||||
functionId: string;
|
||||
code: File;
|
||||
}) => {
|
||||
const newDeployment: UploaderFile = {
|
||||
$id: '',
|
||||
resourceId: functionId,
|
||||
name: code.name,
|
||||
size: code.size,
|
||||
progress: 0,
|
||||
status: 'pending'
|
||||
};
|
||||
update((n) => {
|
||||
n.isOpen = true;
|
||||
n.isCollapsed = false;
|
||||
n.files.unshift(newDeployment);
|
||||
return n;
|
||||
});
|
||||
const uploadedFile = await temporaryFunctions(
|
||||
page.params.region,
|
||||
page.params.project
|
||||
).createDeployment({
|
||||
functionId,
|
||||
code,
|
||||
activate: true,
|
||||
onProgress: (progress) => {
|
||||
newDeployment.$id = progress.$id;
|
||||
newDeployment.progress = progress.progress;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT, Dependencies } from '$lib/constants';
|
||||
@@ -23,54 +24,56 @@ export const load: PageLoad = async ({ params, url, route, depends, parent }) =>
|
||||
const archivedPage =
|
||||
Number.isFinite(archivedPageRaw) && archivedPageRaw > 0 ? archivedPageRaw : 1;
|
||||
const archivedOffset = pageToOffset(archivedPage, limit);
|
||||
|
||||
|
||||
const searchQueries = search
|
||||
? [Query.or([Query.search('search', search), Query.contains('labels', search)])]
|
||||
? [Query.or([Query.search('search', search), Query.contains('labels', search)])];
|
||||
const commonQueries = [Query.equal('teamId', params.organization)];
|
||||
const activeQueries = isCloud
|
||||
? [Query.or([Query.equal('status', 'active'), Query.isNull('status')])]
|
||||
: [];
|
||||
|
||||
const [activeProjects, archivedProjects, activeTotal, archivedTotal] = await Promise.all([
|
||||
sdk.forConsole.projects.list({
|
||||
queries: [
|
||||
Query.offset(offset),
|
||||
Query.equal('teamId', params.organization),
|
||||
Query.or([Query.equal('status', 'active'), Query.isNull('status')]),
|
||||
Query.limit(limit),
|
||||
Query.orderDesc(''),
|
||||
...searchQueries
|
||||
...commonQueries,
|
||||
...searchQueries,
|
||||
...activeQueries
|
||||
]
|
||||
}),
|
||||
isCloud
|
||||
? sdk.forConsole.projects.list({
|
||||
queries: [
|
||||
Query.offset(archivedOffset),
|
||||
Query.limit(limit),
|
||||
Query.orderDesc(''),
|
||||
...commonQueries,
|
||||
...searchQueries,
|
||||
Query.equal('status', 'archived')
|
||||
]
|
||||
})
|
||||
: Promise.resolve({ projects: [], total: 0 }),
|
||||
sdk.forConsole.projects.list({
|
||||
queries: [
|
||||
Query.offset(archivedOffset),
|
||||
Query.equal('teamId', params.organization),
|
||||
Query.equal('status', 'archived'),
|
||||
Query.limit(limit),
|
||||
Query.orderDesc(''),
|
||||
...searchQueries
|
||||
]
|
||||
queries: [...commonQueries, ...activeQueries, ...searchQueries]
|
||||
}),
|
||||
sdk.forConsole.projects.list({
|
||||
queries: [
|
||||
Query.equal('teamId', params.organization),
|
||||
Query.or([Query.equal('status', 'active'), Query.isNull('status')]),
|
||||
...searchQueries
|
||||
]
|
||||
}),
|
||||
sdk.forConsole.projects.list({
|
||||
queries: [
|
||||
Query.equal('teamId', params.organization),
|
||||
Query.equal('status', 'archived'),
|
||||
...searchQueries
|
||||
]
|
||||
})
|
||||
isCloud
|
||||
? sdk.forConsole.projects.list({
|
||||
queries: [...commonQueries, ...searchQueries, Query.equal('status', 'archived')],
|
||||
search: search || undefined
|
||||
})
|
||||
: Promise.resolve({ projects: [], total: 0 })
|
||||
]);
|
||||
|
||||
// set `default` if no region!
|
||||
for (const project of activeProjects.projects) {
|
||||
project.region ??= 'default';
|
||||
}
|
||||
for (const project of archivedProjects.projects) {
|
||||
project.region ??= 'default';
|
||||
if (isCloud) {
|
||||
for (const project of archivedProjects.projects) {
|
||||
project.region ??= 'default';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
<style>
|
||||
.layout-level-progress-bars {
|
||||
gap: 1rem;
|
||||
z-index: 2;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
+42
-23
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto, invalidate } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { base, resolve } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Button, Form } from '$lib/elements/forms';
|
||||
@@ -23,6 +23,7 @@
|
||||
import { isCloud } from '$lib/system';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
import { currentPlan } from '$lib/stores/organization';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -61,19 +62,19 @@
|
||||
let specification = specificationOptions[0]?.value || '';
|
||||
|
||||
async function create() {
|
||||
let func: Models.Function | null = null;
|
||||
|
||||
try {
|
||||
const func = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.functions.create({
|
||||
functionId: id || ID.unique(),
|
||||
name,
|
||||
runtime,
|
||||
execute: roles?.length ? roles : undefined,
|
||||
enabled: true,
|
||||
entrypoint,
|
||||
commands: buildCommand,
|
||||
specification: specification || undefined
|
||||
});
|
||||
func = await sdk.forProject(page.params.region, page.params.project).functions.create({
|
||||
functionId: id || ID.unique(),
|
||||
name,
|
||||
runtime,
|
||||
execute: roles?.length ? roles : undefined,
|
||||
enabled: true,
|
||||
entrypoint,
|
||||
commands: buildCommand,
|
||||
specification: specification || undefined
|
||||
});
|
||||
|
||||
// Add domain
|
||||
await sdk.forProject(page.params.region, page.params.project).proxy.createFunctionRule({
|
||||
@@ -92,25 +93,43 @@
|
||||
);
|
||||
await Promise.all(promises);
|
||||
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.functions.createDeployment({
|
||||
functionId: func.$id,
|
||||
code: files[0],
|
||||
activate: true
|
||||
});
|
||||
const promise = uploader.uploadFunctionDeployment({
|
||||
functionId: func.$id,
|
||||
code: files[0]
|
||||
});
|
||||
|
||||
addNotification({
|
||||
message: 'Deployment upload started',
|
||||
type: 'success'
|
||||
});
|
||||
trackEvent(Submit.FunctionCreate, {
|
||||
source: 'repository',
|
||||
runtime: runtime
|
||||
});
|
||||
|
||||
await goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/functions/function-${func.$id}`
|
||||
);
|
||||
await promise;
|
||||
const upload = $uploader.files.find((f) => f.resourceId === func.$id);
|
||||
|
||||
if (upload?.status === 'success') {
|
||||
const deploymentId = upload.$id;
|
||||
const resolvedPath = resolve(
|
||||
`/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]`,
|
||||
{
|
||||
region: page.params.region,
|
||||
project: page.params.project,
|
||||
function: func.$id,
|
||||
deployment: deploymentId
|
||||
}
|
||||
);
|
||||
await goto(resolvedPath);
|
||||
}
|
||||
|
||||
invalidate(Dependencies.FUNCTION);
|
||||
} catch (e) {
|
||||
const upload = $uploader.files.find((f) => f.resourceId === func?.$id);
|
||||
if (upload) {
|
||||
uploader.removeFromQueue(upload.$id);
|
||||
}
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: e.message
|
||||
|
||||
+10
-12
@@ -6,15 +6,14 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { InvalidFileType, removeFile } from '$lib/helpers/files';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Icon, Layout, Tooltip, Typography, Upload } from '@appwrite.io/pink-svelte';
|
||||
import { func } from '../store';
|
||||
import { page } from '$app/state';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { currentPlan } from '$lib/stores/organization';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
|
||||
export let show = false;
|
||||
|
||||
@@ -30,17 +29,16 @@
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.functions.createDeployment({
|
||||
functionId: $func.$id,
|
||||
code: files[0],
|
||||
activate: true
|
||||
});
|
||||
await invalidate(Dependencies.DEPLOYMENTS);
|
||||
files = undefined;
|
||||
uploader.uploadFunctionDeployment({
|
||||
functionId: $func.$id,
|
||||
code: files[0]
|
||||
});
|
||||
show = false;
|
||||
trackEvent(Submit.DeploymentCreate);
|
||||
files = undefined;
|
||||
await invalidate(Dependencies.DEPLOYMENTS);
|
||||
trackEvent(Submit.DeploymentCreate, {
|
||||
type: 'function'
|
||||
});
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: 'Deployment created successfully'
|
||||
|
||||
+34
-15
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { base, resolve } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Button, Form } from '$lib/elements/forms';
|
||||
@@ -21,6 +21,7 @@
|
||||
import { isCloud } from '$lib/system';
|
||||
import { currentPlan } from '$lib/stores/organization';
|
||||
import Domain from '../domain.svelte';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
|
||||
export let data;
|
||||
let showExitModal = false;
|
||||
@@ -50,6 +51,8 @@
|
||||
$: readableMaxSize = humanFileSize(maxSize);
|
||||
|
||||
async function create() {
|
||||
let site: Models.Site | null = null;
|
||||
|
||||
try {
|
||||
if (!domainIsValid) {
|
||||
addNotification({
|
||||
@@ -63,7 +66,7 @@
|
||||
const buildRuntime = Object.values(BuildRuntime).find(
|
||||
(f) => f === framework.buildRuntime
|
||||
);
|
||||
let site = await sdk.forProject(page.params.region, page.params.project).sites.create({
|
||||
site = await sdk.forProject(page.params.region, page.params.project).sites.create({
|
||||
siteId: id || ID.unique(),
|
||||
name,
|
||||
framework: fr,
|
||||
@@ -90,26 +93,42 @@
|
||||
);
|
||||
await Promise.all(promises);
|
||||
|
||||
const deployment = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.sites.createDeployment({
|
||||
siteId: site.$id,
|
||||
code: files[0],
|
||||
activate: true,
|
||||
installCommand: installCommand || undefined,
|
||||
buildCommand: buildCommand || undefined,
|
||||
outputDirectory: outputDirectory || undefined
|
||||
});
|
||||
const promise = uploader.uploadSiteDeployment({
|
||||
siteId: site.$id,
|
||||
code: files[0],
|
||||
buildCommand: buildCommand || undefined,
|
||||
installCommand: installCommand || undefined,
|
||||
outputDirectory: outputDirectory || undefined
|
||||
});
|
||||
|
||||
addNotification({
|
||||
message: 'Deployment upload started',
|
||||
type: 'success'
|
||||
});
|
||||
trackEvent(Submit.SiteCreate, {
|
||||
source: 'manual',
|
||||
framework: framework.key
|
||||
});
|
||||
|
||||
await goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/sites/create-site/deploying?site=${site.$id}&deployment=${deployment.$id}`
|
||||
);
|
||||
await promise;
|
||||
const upload = $uploader.files.find((f) => f.resourceId === site.$id);
|
||||
|
||||
if (upload?.status === 'success') {
|
||||
const deploymentId = upload.$id;
|
||||
const resolvedPath = resolve(
|
||||
`/(console)/project-[region]-[project]/sites/create-site/deploying`,
|
||||
{
|
||||
region: page.params.region,
|
||||
project: page.params.project
|
||||
}
|
||||
);
|
||||
await goto(`${resolvedPath}?site=${site.$id}&deployment=${deploymentId}`);
|
||||
}
|
||||
} catch (e) {
|
||||
const upload = $uploader.files.find((f) => f.resourceId === site?.$id);
|
||||
if (upload) {
|
||||
uploader.removeFromQueue(upload.$id);
|
||||
}
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: e.message
|
||||
|
||||
+9
-1
@@ -13,6 +13,7 @@
|
||||
import { currentPlan } from '$lib/stores/organization';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
export let show = false;
|
||||
export let site: Models.Site;
|
||||
@@ -29,15 +30,22 @@
|
||||
|
||||
async function createDeployment() {
|
||||
try {
|
||||
uploader.uploadSiteDeployment(site.$id, files[0]);
|
||||
uploader.uploadSiteDeployment({
|
||||
siteId: site.$id,
|
||||
code: files[0]
|
||||
});
|
||||
show = false;
|
||||
invalidate(Dependencies.DEPLOYMENTS);
|
||||
trackEvent(Submit.DeploymentCreate, {
|
||||
type: 'site'
|
||||
});
|
||||
addNotification({
|
||||
message: 'Deployment upload started',
|
||||
type: 'success'
|
||||
});
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.DeploymentCreate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user