Merge remote-tracking branch 'origin/main' into feat/project-premium-geo-db-addon

# Conflicts:
#	bun.lock
#	package.json
This commit is contained in:
Damodar Lohani
2026-05-04 08:15:52 +00:00
12 changed files with 215 additions and 149 deletions
+15 -1
View File
@@ -1,5 +1,7 @@
export function getIconFromRuntime(runtime: string) {
export function getIconFromRuntime(runtime?: string) {
switch (true) {
case !runtime:
return undefined;
case runtime.includes('node'):
return 'node';
case runtime.includes('php'):
@@ -18,6 +20,18 @@ export function getIconFromRuntime(runtime: string) {
return 'deno';
case runtime.includes('flutter'):
return 'flutter';
case runtime.includes('dotnet'):
return 'dotnet';
case runtime.includes('java'):
return 'java';
case runtime.includes('swift'):
return 'swift';
case runtime.includes('kotlin'):
return 'kotlin';
case runtime.includes('cpp'):
return 'cpp';
case runtime.includes('rust'):
return 'rust';
default:
return undefined;
}
@@ -21,6 +21,7 @@
import Wizard from '$lib/layout/wizard.svelte';
import { Link } from '$lib/elements';
import { Button } from '$lib/elements/forms';
import { getIconFromRuntime } from '$lib/stores/runtimes';
import { regionalConsoleVariables } from '../../store';
export let data;
@@ -36,17 +37,17 @@
const starterTemplate = data.templates.find((template) => template.id === 'starter');
const baseRuntimesList = [
...new Map(
data.runtimesList.runtimes.map((runtime) => {
const base = runtime.name.split('-')[0];
return [base, runtime];
})
).values()
];
const latestRuntimesByKey = new Map<string, Models.Runtime>();
for (const runtime of data.runtimesList.runtimes) {
latestRuntimesByKey.set(runtime.key, runtime);
}
const starterTemplateRuntimes = starterTemplate.runtimes.filter((r) =>
baseRuntimesList.some((base) => base.$id === r.name)
const starterTemplateRuntimeIds = new Set<string>(
starterTemplate?.runtimes.map((runtime) => runtime.name) ?? []
);
const starterTemplateRuntimes = [...latestRuntimesByKey.values()].filter((runtime) =>
starterTemplateRuntimeIds.has(runtime.$id)
);
function connect(e: Models.ProviderRepository) {
@@ -131,11 +132,8 @@
<Layout.Stack gap="xl">
<Typography.Title size="s">Quick start</Typography.Title>
<Layout.Grid columnsXXS={1} columnsXS={2} columnsS={3} columns={4} gap="s">
{#each starterTemplateRuntimes.slice(0, 6) as template}
{@const iconName = template.name.split('-')[0]}
{@const runtimeDetail = baseRuntimesList.find(
(runtime) => runtime.$id === template.name
)}
{#each starterTemplateRuntimes as runtime}
{@const iconName = getIconFromRuntime(runtime.key)}
<Card.Link
variant="secondary"
radius="s"
@@ -144,7 +142,7 @@
trackEvent('click_connect_template', {
from: 'cover',
template: starterTemplate.id,
runtime: template.name
runtime: runtime.$id
});
}}
href={resolveRoute(
@@ -153,14 +151,16 @@
...page.params,
template: starterTemplate.id
}
) + `?runtime=${runtimeDetail.$id}`}>
) + `?runtime=${runtime.$id}`}>
<Layout.Stack direction="row" gap="s" alignItems="center">
<Avatar size="xs" alt={template.name} empty={!template.name}>
<SvgIcon name={iconName} iconSize="small" />
<Avatar size="xs" alt={runtime.name} empty={!iconName}>
{#if iconName}
<SvgIcon name={iconName} iconSize="small" />
{/if}
</Avatar>
<Typography.Text color="--fgcolor-neutral-primary">
<Layout.Stack direction="row" gap="xs" alignItems="center">
{runtimeDetail?.name}
{runtime.name}
<!--{#if runtimeDetail?.name?.toLowerCase() === 'deno'}-->
<!-- <Badge-->
<!-- variant="secondary"-->
@@ -59,13 +59,16 @@
data.runtimesList?.runtimes?.map((r) => ({
value: r.$id,
label: `${r.name} - ${r.version}`,
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(r.$id), 'color')}' style='inline-size: var(--icon-size-m)' />`
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(r.key) ?? 'empty', 'color')}' style='inline-size: var(--icon-size-m)' />`
})) || []
);
onMount(() => {
const runtimeParam = data.runtime || page.url.searchParams.get('runtime') || 'node-18.0';
runtime = runtimeParam as Runtime;
const runtimeParam = data.runtime || page.url.searchParams.get('runtime');
const runtimeOption = data.runtimesList.runtimes.find(
(runtime) => runtime.$id === runtimeParam
);
runtime = (runtimeOption?.$id ?? data.runtimesList.runtimes[0]?.$id) as Runtime;
entrypoint = page.url.searchParams.get('entrypoint') || '';
@@ -32,7 +32,7 @@
const runtimeOptions = data.runtimesList.runtimes.map((runtime) => {
const { $id: value, name, version, key } = runtime;
const label = `${name} - ${version}`;
const iconName = getIconFromRuntime(key);
const iconName = getIconFromRuntime(key) ?? 'empty';
const iconSrc = iconFor(iconName, 'color');
const leadingHtml = `<img src='${iconSrc}' alt='${iconName}' style='inline-size: var(--icon-size-m)' />`;
@@ -37,7 +37,7 @@
return {
value: runtime.$id,
label: `${runtime.name} - ${runtime.version}`,
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key), 'color')}' style='inline-size: var(--icon-size-m)' />`
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key) ?? 'empty', 'color')}' style='inline-size: var(--icon-size-m)' />`
};
});
@@ -11,7 +11,7 @@
import { installation, repository } from '$lib/stores/vcs';
import { Fieldset, Layout, Icon, Divider, Empty, Typography } from '@appwrite.io/pink-svelte';
import { IconGithub } from '@appwrite.io/pink-icons-svelte';
import { onMount } from 'svelte';
import { onMount, untrack } from 'svelte';
import { writable } from 'svelte/store';
import ProductionBranch from '$lib/components/git/productionBranchFieldset.svelte';
import Configuration from './configuration.svelte';
@@ -37,64 +37,83 @@
import { Dependencies } from '$lib/constants';
import { getIconFromRuntime } from '$lib/stores/runtimes';
import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store';
import type { PageData } from './$types';
export let data;
let { data }: { data: PageData } = $props();
const specificationOptions = (data.specificationsList?.specifications ?? []).map((size) => ({
label:
`${size.cpus} CPU, ${size.memory} MB RAM` +
(!size.enabled ? ` (Upgrade to use this)` : ''),
value: size.slug,
disabled: !size.enabled
}));
const specificationOptions = $derived(
(data.specificationsList?.specifications ?? []).map((size) => ({
label:
`${size.cpus} CPU, ${size.memory} MB RAM` +
(!size.enabled ? ` (Upgrade to use this)` : ''),
value: size.slug,
disabled: !size.enabled
}))
);
let showExitModal = false;
let isCreatingRepository = false;
let showExitModal = $state(false);
let isCreatingRepository = $state(false);
let formComponent: Form;
let isSubmitting = writable(false);
let formComponent = $state<Form>();
let isSubmitting = $state(writable(false));
let name = data.template.name;
let id: string | null = null;
let runtime: Runtime;
let branch = 'main';
let rootDir = './';
let connectBehaviour: 'now' | 'later' = 'now';
let repositoryBehaviour: 'new' | 'existing' = 'new';
let repositoryName = undefined;
let repositoryPrivate = true;
let selectedInstallationId = '';
let selectedRepository = '';
let showConfig = false;
let silentMode = false;
let entrypoint = '';
let selectedScopes: Scopes[] = [];
let execute = true;
let variables: Partial<Models.TemplateVariable>[] = [];
let specification = specificationOptions[0]?.value || '';
let name = $state(untrack(() => data.template.name));
let id = $state<string | null>(null);
let runtime = $state<Runtime>();
let branch = $state('main');
let rootDir = $state('./');
let connectBehaviour = $state<'now' | 'later'>('now');
let repositoryBehaviour = $state<'new' | 'existing'>('new');
let repositoryName = $state<string | undefined>();
let repositoryPrivate = $state(true);
let selectedInstallationId = $state('');
let selectedRepository = $state<string | null>('');
let showConfig = $state(false);
let silentMode = $state(false);
let entrypoint = $state('');
let selectedScopes = $state<Scopes[]>([]);
let execute = $state(true);
let variables = $state<Partial<Models.TemplateVariable>[]>([]);
let specification = $state(untrack(() => specificationOptions[0]?.value || ''));
const availableRuntimes: Models.Runtime[] = $derived(
data.runtimesList.runtimes.filter((runtime) =>
data.template.runtimes.some((templateRuntime) => templateRuntime.name === runtime.$id)
)
);
function sortRuntimesByVersionDesc(a: Models.Runtime, b: Models.Runtime) {
return b.version.localeCompare(a.version, undefined, { numeric: true });
}
function selectInitialRuntime() {
const runtimeParam = page.url.searchParams.get('runtime');
const requestedRuntime = availableRuntimes.find((runtime) => runtime.$id === runtimeParam);
if (requestedRuntime) {
return requestedRuntime.$id as Runtime;
}
const runtimeById = new Map(
data.runtimesList.runtimes.map((runtime) => [runtime.$id, runtime])
);
const preferredRuntime = data.template.runtimes
.map((runtime) => runtimeById.get(runtime.name))
.find(Boolean);
const preferredRuntimes = preferredRuntime
? availableRuntimes.filter((runtime) => runtime.key === preferredRuntime.key)
: [];
const runtimes = preferredRuntimes.length ? preferredRuntimes : availableRuntimes;
return [...runtimes].sort(sortRuntimesByVersionDesc)[0]?.$id as Runtime;
}
onMount(async () => {
if (!$installation?.$id) {
$installation = data.installations.installations[0];
}
selectedInstallationId = $installation?.$id;
if (data.template.runtimes && data.template.runtimes.length > 0) {
const targetRuntime = data.template.runtimes[0].name;
const matchingRuntimes = Object.values(Runtime).filter((r) =>
r.startsWith(targetRuntime.split('-')[0])
);
matchingRuntimes.sort((a, b) => {
const versionA = a.split('-')[1];
const versionB = b.split('-')[1];
return versionB.localeCompare(versionA, undefined, { numeric: true });
});
if (page.url.searchParams.has('runtime')) {
runtime = page.url.searchParams.get('runtime') as Runtime;
} else {
runtime = matchingRuntimes[0] as Runtime;
}
}
runtime = selectInitialRuntime();
});
async function createRepository() {
@@ -210,18 +229,18 @@
}
}
$: if (repositoryBehaviour === 'new') {
selectedInstallationId ??= $installation?.$id;
repositoryName ??= name.split(' ').join('-').toLowerCase();
}
$effect(() => {
if (repositoryBehaviour === 'new') {
selectedInstallationId ??= $installation?.$id;
repositoryName ??= name.split(' ').join('-').toLowerCase();
}
});
$: if (connectBehaviour === 'later') {
selectedRepository = null;
}
$: availableRuntimes = data.runtimesList.runtimes.filter((runtime) =>
data.template.runtimes.some((templateRuntime) => templateRuntime.name === runtime.$id)
);
$effect(() => {
if (connectBehaviour === 'later') {
selectedRepository = null;
}
});
</script>
<svelte:head>
@@ -259,7 +278,7 @@
return {
value: runtime.$id,
label: `${runtime.name} - ${runtime.version}`,
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.$id), 'color')}' style='inline-size: var(--icon-size-m)' />`
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key) ?? 'empty', 'color')}' style='inline-size: var(--icon-size-m)' />`
};
})}
@@ -37,7 +37,15 @@
type ScopeDefinition
} from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
import { Accordion, Alert, Badge, Divider, Layout, Selector } from '@appwrite.io/pink-svelte';
import {
Accordion,
Alert,
Badge,
Divider,
Layout,
Selector,
Typography
} from '@appwrite.io/pink-svelte';
import type { Scopes } from '@appwrite.io/console';
let { scopes = $bindable([]) }: { scopes: Scopes[] } = $props();
@@ -51,68 +59,51 @@
Database: 'Databases'
};
enum Category {
Project = 'Project',
Auth = 'Auth',
Databases = 'Databases',
Functions = 'Functions',
Messaging = 'Messaging',
Sites = 'Sites',
Storage = 'Storage',
Domains = 'Domains',
Other = 'Other'
}
const categoryOrder = [
Category.Project,
Category.Auth,
Category.Databases,
Category.Functions,
Category.Storage,
Category.Messaging,
Category.Sites,
Category.Domains,
Category.Other
];
function normalizeCategory(category: string): string {
return categoryAliasMap[category] ?? category;
}
const filteredScopes = $derived.by(() => {
const scopesById = new Map(allScopesList.map((scope) => [scope.scope, scope]));
const databasesWriteIndex = allScopesList.findIndex((s) => s.scope === 'databases.write');
if (isCloud && databasesWriteIndex !== -1) {
const normalizedBackupScopes = cloudOnlyBackupScopes.map((scope) => ({
...scope,
category: normalizeCategory(scope.category)
}));
const backupScopeIds = new Set(normalizedBackupScopes.map((scope) => scope.scope));
for (const scope of normalizedBackupScopes) {
if (!scopesById.has(scope.scope)) {
scopesById.set(scope.scope, scope);
}
}
const mergedScopes = Array.from(scopesById.values());
const nonBackupScopes = mergedScopes.filter(
(scope) => !backupScopeIds.has(scope.scope)
);
const mergedDatabasesWriteIndex = nonBackupScopes.findIndex(
(s) => s.scope === 'databases.write'
);
return [
...allScopesList.slice(0, databasesWriteIndex + 1),
...cloudOnlyBackupScopes.map((scope) => ({
...scope,
category: normalizeCategory(scope.category)
})),
...allScopesList.slice(databasesWriteIndex + 1)
...nonBackupScopes.slice(0, mergedDatabasesWriteIndex + 1),
...normalizedBackupScopes.map((scope) => scopesById.get(scope.scope) ?? scope),
...nonBackupScopes.slice(mergedDatabasesWriteIndex + 1)
];
}
return allScopesList;
});
const categories = $derived.by(() => {
const availableCategories = new Set(
filteredScopes.map((scope) => normalizeCategory(scope.category))
return Array.from(
new Set(filteredScopes.map((scope) => normalizeCategory(scope.category)))
);
return [
...categoryOrder.filter((category) => availableCategories.has(category)),
...Array.from(availableCategories).filter(
(category) => !categoryOrder.includes(category as Category)
)
];
});
const scopeCatalog = $derived(
new Set([
...filteredScopes.map((s) => s.scope),
...(isCloud ? cloudOnlyBackupScopes.map((s) => s.scope) : [])
])
);
const scopeCatalog = $derived(new Set(filteredScopes.map((s) => s.scope)));
let activeScopes: Record<string, boolean> = $state({});
@@ -130,13 +121,6 @@
const result = await sdk.forConsole.console.listProjectScopes();
const scopesById = new Map<string, ScopeDefinition>();
for (const scope of localScopes) {
scopesById.set(scope.scope, {
...scope,
category: normalizeCategory(scope.category)
});
}
for (const scope of result.scopes) {
scopesById.set(scope.$id, {
scope: scope.$id,
@@ -147,6 +131,15 @@
});
}
for (const scope of localScopes) {
if (!scopesById.has(scope.scope)) {
scopesById.set(scope.scope, {
...scope,
category: normalizeCategory(scope.category)
});
}
}
allScopesList = Array.from(scopesById.values());
for (const s of filteredScopes) {
@@ -235,16 +228,36 @@
on:change={(event) => onCategoryChange(event, category)}>
<Layout.Stack>
{#each filteredScopes.filter((s) => s.category === category) as scope}
<Layout.Stack direction="row" alignItems="center" gap="s">
<Layout.Stack inline direction="row" alignItems="flex-start" gap="s">
<Selector.Checkbox
size="s"
id={scope.scope}
label={`${scope.scope}${scope.deprecated ? ' (Deprecated)' : ''}`}
description={scope.description}
bind:checked={activeScopes[scope.scope]} />
{#if scope.deprecated}
<Badge size="xs" variant="secondary" content="Deprecated" />
{/if}
<Layout.Stack gap="xxs">
<label for={scope.scope}>
<Layout.Stack gap="xxs">
<Layout.Stack
inline
direction="row"
alignItems="center"
gap="xxs">
<Typography.Text variant="m-500"
>{scope.scope}</Typography.Text>
{#if scope.deprecated}
<Badge
size="xs"
variant="secondary"
content="Deprecated" />
{/if}
</Layout.Stack>
<Typography.Text
variant="m-400"
color="--fgcolor-neutral-tertiary">
{scope.description}
</Typography.Text>
</Layout.Stack>
</label>
</Layout.Stack>
</Layout.Stack>
{/each}
</Layout.Stack>
@@ -252,3 +265,9 @@
{/each}
</Layout.Stack>
</Layout.Stack>
<style>
label {
cursor: pointer;
}
</style>
+11 -4
View File
@@ -31,6 +31,16 @@ export const load: PageLoad = async ({ parent, url }) => {
const envParam = url.searchParams.get('env');
const envKeys = envParam ? envParam.split(',').map((key: string) => key.trim()) : [];
// Get available runtimes
const runtimesList = await sdk.forConsole.functions.listRuntimes();
const runtimeOption = runtimesList.runtimes.find((option) => option.$id === runtime);
const runtimeId = runtimeOption?.$id ?? runtimesList.runtimes[0]?.$id;
if (!runtimeId) {
redirect(302, base + '/');
}
const deploymentData: {
type: 'repo';
repository: {
@@ -48,12 +58,9 @@ export const load: PageLoad = async ({ parent, url }) => {
rootDirectory: null
},
name: name || '',
runtime: runtime || 'node-18.0'
runtime: runtimeId
};
// Get available runtimes
const runtimesList = await sdk.forConsole.functions.listRuntimes();
const info = getRepositoryInfo(repository);
if (!info) {
redirect(302, base + '/');
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z" fill="#CE422B"/></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z" fill="#C4C6D7"/></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z" fill="#CE422B"/></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z" fill="#373B4D"/></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB