Merge pull request #75 from appwrite/feat-platforms

feat: platforms wizard
This commit is contained in:
Torsten Dittmann
2022-10-17 13:12:15 +02:00
committed by GitHub
33 changed files with 1158 additions and 157 deletions
+21 -21
View File
@@ -9,8 +9,8 @@
"version": "0.0.1",
"dependencies": {
"@aw-labs/appwrite-console": "^6.0.0",
"@aw-labs/icons": "0.0.0-61",
"@aw-labs/ui": "0.0.0-61",
"@aw-labs/icons": "0.0.0-63",
"@aw-labs/ui": "0.0.0-63",
"echarts": "^5.4.0",
"prismjs": "^1.29.0",
"tippy.js": "^6.3.7",
@@ -37,7 +37,7 @@
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.8.0",
"sass": "^1.55.0",
"svelte": "^3.51.0",
"svelte": "^3.52.0",
"svelte-check": "^2.9.2",
"svelte-jester": "^2.3.2",
"svelte-preprocess": "^4.10.7",
@@ -79,14 +79,14 @@
}
},
"node_modules/@aw-labs/icons": {
"version": "0.0.0-61",
"resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-61.tgz",
"integrity": "sha512-kZdiDF+ywVvcoC8R+lZNnxwuxNeCmMNwyoqoFL+VANNeRL6pfABYDUwTRG4cZmY4n/oswe5FeILjl/HlSSf5/w=="
"version": "0.0.0-63",
"resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-63.tgz",
"integrity": "sha512-aSVriQp0x2cfyhld3LodKrDBZwkS/rOErjvQtR5HWmrYTjDNm21dmehfg6rVhV5Al8Bvpd82HihAWdTVYP5cwA=="
},
"node_modules/@aw-labs/ui": {
"version": "0.0.0-61",
"resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-61.tgz",
"integrity": "sha512-v0+4CWP7x7cNo0sqZlZOeqp3RK45fS+LMg/lVEpyByaluMqXDIPe7p522vp0hgsN2YKtpilbxg0vlqLCIvEa8w==",
"version": "0.0.0-63",
"resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-63.tgz",
"integrity": "sha512-+lNFpbMBT/AU2sVefN6gmBJE06Z1L93iqpr6B4Xl8T5YxDwrAeoxjTB5I50vVhughN/JkYxTJd+rMOCSOfh/DQ==",
"dependencies": {
"@aw-labs/icons": "*",
"normalize.css": "^8.0.1",
@@ -6989,9 +6989,9 @@
}
},
"node_modules/svelte": {
"version": "3.51.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.51.0.tgz",
"integrity": "sha512-PBITYIrsNOuW+Dtds00gSY68raNZQn7i59Dg/fjgf6WwyawPKeBwle692coO7ILZqSO+UJe9899aDn9sMdeOHA==",
"version": "3.52.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.52.0.tgz",
"integrity": "sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==",
"dev": true,
"engines": {
"node": ">= 8"
@@ -7789,14 +7789,14 @@
}
},
"@aw-labs/icons": {
"version": "0.0.0-61",
"resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-61.tgz",
"integrity": "sha512-kZdiDF+ywVvcoC8R+lZNnxwuxNeCmMNwyoqoFL+VANNeRL6pfABYDUwTRG4cZmY4n/oswe5FeILjl/HlSSf5/w=="
"version": "0.0.0-63",
"resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-63.tgz",
"integrity": "sha512-aSVriQp0x2cfyhld3LodKrDBZwkS/rOErjvQtR5HWmrYTjDNm21dmehfg6rVhV5Al8Bvpd82HihAWdTVYP5cwA=="
},
"@aw-labs/ui": {
"version": "0.0.0-61",
"resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-61.tgz",
"integrity": "sha512-v0+4CWP7x7cNo0sqZlZOeqp3RK45fS+LMg/lVEpyByaluMqXDIPe7p522vp0hgsN2YKtpilbxg0vlqLCIvEa8w==",
"version": "0.0.0-63",
"resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-63.tgz",
"integrity": "sha512-+lNFpbMBT/AU2sVefN6gmBJE06Z1L93iqpr6B4Xl8T5YxDwrAeoxjTB5I50vVhughN/JkYxTJd+rMOCSOfh/DQ==",
"requires": {
"@aw-labs/icons": "*",
"normalize.css": "^8.0.1",
@@ -12991,9 +12991,9 @@
"dev": true
},
"svelte": {
"version": "3.51.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.51.0.tgz",
"integrity": "sha512-PBITYIrsNOuW+Dtds00gSY68raNZQn7i59Dg/fjgf6WwyawPKeBwle692coO7ILZqSO+UJe9899aDn9sMdeOHA==",
"version": "3.52.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.52.0.tgz",
"integrity": "sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==",
"dev": true
},
"svelte-check": {
+3 -3
View File
@@ -19,8 +19,8 @@
},
"dependencies": {
"@aw-labs/appwrite-console": "^6.0.0",
"@aw-labs/icons": "0.0.0-61",
"@aw-labs/ui": "0.0.0-61",
"@aw-labs/icons": "0.0.0-63",
"@aw-labs/ui": "0.0.0-63",
"echarts": "^5.4.0",
"prismjs": "^1.29.0",
"tippy.js": "^6.3.7",
@@ -47,7 +47,7 @@
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.8.0",
"sass": "^1.55.0",
"svelte": "^3.51.0",
"svelte": "^3.52.0",
"svelte-check": "^2.9.2",
"svelte-jester": "^2.3.2",
"svelte-preprocess": "^4.10.7",
+73 -53
View File
@@ -4,49 +4,66 @@
import 'prismjs/components/prism-dart';
import 'prismjs/components/prism-kotlin';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-yaml';
import 'prismjs/components/prism-swift';
import 'prismjs/plugins/autoloader/prism-autoloader';
import 'prismjs/plugins/custom-class/prism-custom-class';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import { afterUpdate } from 'svelte';
import { Copy } from '.';
export let label: string = null;
export let labelIcon: 'code' | 'android' | 'flutter' | 'apple' = null;
export let code: string;
export let language: 'js' | 'html' | 'dart' | 'kotlin' | 'json';
export let showLineNumbers = false;
export let showCopy = false;
export let language: 'js' | 'html' | 'dart' | 'kotlin' | 'json' | 'sh' | 'yml' | 'swift';
export let withLineNumbers = false;
export let withCopy = false;
Prism.plugins.customClass.prefix('prism-');
afterUpdate(async () => {
Prism.highlightAll();
});
</script>
<div class="code">
<div class="controls">
<section class="box u-overflow-hidden common-section">
<div
class="controls u-position-absolute u-inset-inline-end-8 u-inset-block-start-8 u-flex u-gap-8">
{#if label}
<Pill>{label}</Pill>
<Pill>
{#if labelIcon}
<span class={`icon-${labelIcon}`} aria-hidden="true" />
{/if}
{label}
</Pill>
{/if}
{#if showCopy}
{#if withCopy}
<Copy value={code}>
<span class="icon-duplicate" aria-hidden="true" style="cursor: pointer;" />
<button class="button is-small is-text is-only-icon" aria-label="copy code">
<span class="icon-duplicate" aria-hidden="true" />
</button>
</Copy>
{/if}
</div>
<pre class={`language-${language}`} class:line-numbers={showLineNumbers}><code
<pre class={`language-${language}`} class:line-numbers={withLineNumbers}><code
>{code}</code></pre>
</div>
</section>
<style lang="scss" global>
@import 'prismjs/themes/prism.css';
div.code {
position: relative;
.box {
--p-box-background-color: var(--color-neutral-300) !important;
div.controls {
position: absolute;
right: 0.5rem;
top: 0.5rem;
z-index: 1;
body.theme-light & {
--p-box-background-color: var(--color-neutral-5) !important;
}
.controls {
z-index: 2;
}
}
@@ -56,6 +73,10 @@
color: #fcfcff;
text-shadow: none;
font-family: 'Source Code Pro';
&.line-numbers {
padding-left: 2.5em;
}
body.theme-light & {
color: #373b4d;
}
@@ -77,49 +98,48 @@
:not(pre) > code[class*='language-'],
pre[class*='language-'] {
background: #1b1b28;
body.theme-light & {
background: #fcfcff;
}
background: hsl(var(--p-box-background-color));
padding: 0;
margin: 0;
}
.token {
&.comment,
&.prolog,
&.doctype,
&.cdata {
.prism-token {
&.prism-comment,
&.prism-prolog,
&.prism-doctype,
&.prism-cdata {
color: #868ea3;
}
&.punctuation {
&.prism-punctuation {
color: #fcfcff;
body.theme-light & {
color: #373b4d;
}
}
&.property,
&.tag,
&.boolean,
&.number,
&.constant,
&.symbol,
&.deleted,
&.selector,
&.attr-name,
&.string,
&.char,
&.builtin,
&.inserted {
&.prism-property,
&.prism-tag,
&.prism-boolean,
&.prism-number,
&.prism-constant,
&.prism-symbol,
&.prism-deleted,
&.prism-selector,
&.prism-attr-name,
&.prism-string,
&.prism-char,
&.prism-builtin,
&.prism-inserted {
color: #fdc584;
body.theme-light & {
color: #e49545;
}
}
&.operator,
&.entity,
&.url,
.language-css &.string,
.style &.string {
&.prism-operator,
&.prism-entity,
&.prism-url,
.language-css &.prism-string,
.style &.prism-string {
color: #fcfcff;
background: none;
body.theme-light & {
@@ -127,29 +147,29 @@
}
}
&.atrule,
&.attr-value,
&.keyword {
&.prism-atrule,
&.prism-attr-value,
&.prism-keyword {
color: #cbb1fc;
body.theme-light & {
color: #6a6af7;
}
}
&.function {
&.prism-function {
color: #ffa1ce;
body.theme-light & {
color: #f02e7f;
}
}
&.class-name {
&.prism-class-name {
color: #a1c4ff;
body.theme-light & {
color: #62aed2;
}
}
&.regex,
&.important,
&.variable {
&.prism-regex,
&.prism-important,
&.prism-variable {
color: #a1c4ff;
body.theme-light & {
color: #62aed2;
+1 -1
View File
@@ -4,4 +4,4 @@
export let code: string;
</script>
<Code showLineNumbers showCopy language="json" {code} />
<Code withLineNumbers withCopy language="json" {code} />
+1 -1
View File
@@ -28,7 +28,7 @@
{:else}
<div class="bullet" class:is-current={current} />
{/if}
<div class="step-item-content">
<div class="steps-item-content">
<span class="text">{step.text}</span>
{#if step?.substeps}
<ul class="steps-sub">
+5 -1
View File
@@ -1,3 +1,7 @@
<ul class="form-list">
<script lang="ts">
export let isCommonSection = false;
</script>
<ul class="form-list" class:common-section={isCommonSection}>
<slot />
</ul>
+17 -4
View File
@@ -2,13 +2,21 @@
<div class="container">
<ul class="inline-links is-center">
<li class="inline-links-item">
<a class="link" href="https://github.com/appwrite/appwrite" target="_blank">
<a
class="link"
href="https://github.com/appwrite/appwrite"
target="_blank"
rel="noopener noreferrer">
<span class="icon-github-circled" aria-hidden="true" />
<span class="text">GitHub</span>
</a>
</li>
<li class="inline-links-item">
<a class="link" href="https://appwrite.io/discord" target="_blank">
<a
class="link"
href="https://appwrite.io/discord"
target="_blank"
rel="noopener noreferrer">
<span class="icon-discord" aria-hidden="true" />
<span class="text">Discord</span>
</a>
@@ -17,12 +25,17 @@
<a
class="link"
href="https://github.com/appwrite/appwrite/issues/new"
target="_blank">
target="_blank"
rel="noopener noreferrer">
<span class="text">Open an Issue</span>
</a>
</li>
<li class="inline-links-item">
<a class="link" href="https://appwrite.io/docs" target="_blank">
<a
class="link"
href="https://appwrite.io/docs"
target="_blank"
rel="noopener noreferrer">
<span class="text">Docs</span>
</a>
</li>
+1 -1
View File
@@ -13,7 +13,7 @@
class="alert-sticky"
class:is-success={type === 'success'}
class:is-warning={type === 'warning'}
class:is-error={type === 'error'}
class:is-danger={type === 'error'}
class:is-info={type === 'info'}>
<button class="x-button" aria-label="close alert" on:click={() => dispatch('dismiss')}>
<span class="icon-x" aria-hidden="true" />
+2 -2
View File
@@ -113,8 +113,8 @@
{/each}
<div class="form-footer">
<div class="u-flex u-main-end u-gap-12">
{#if sortedSteps[currentStep - 1][1].optional}
<Button text on:click={() => (isLastStep = true)} submit
{#if !isLastStep && sortedSteps[currentStep - 1][1].optional}
<Button text on:click={() => dispatch('finish')}
>Skip optional steps</Button>
{/if}
{#if currentStep === 1}
@@ -1,23 +1,63 @@
<script lang="ts">
import { page } from '$app/stores';
import { GridItem1 } from '$lib/components';
import { DropList, DropListItem, GridItem1 } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { toLocaleDateTime } from '$lib/helpers/date';
import { wizard } from '$lib/stores/wizard';
import { project } from '../../store';
import Create from './create.svelte';
let show = false;
import CreateAndroid from './createAndroid.svelte';
import CreateApple from './createApple.svelte';
import CreateFlutter from './createFlutter.svelte';
import CreateWeb from './createWeb.svelte';
import { versions } from './wizard/store';
let showDropdown = false;
const path = `/console/project-${$page.params.project}/overview/platforms`;
enum Platform {
Web,
Flutter,
Android,
Apple
}
const platforms = {
[Platform.Web]: CreateWeb,
[Platform.Flutter]: CreateFlutter,
[Platform.Android]: CreateAndroid,
[Platform.Apple]: CreateApple
};
async function addPlatform(type: Platform) {
await versions.load();
wizard.start(platforms[type]);
}
</script>
<div class="common-section u-flex u-gap-12">
<h3 class="heading-level-7">Platforms</h3>
<span class="u-margin-inline-start-auto">
<Button on:click={() => (show = true)}>
<span class="icon-plus" aria-hidden="true" />
<span class="text">Add Platform</span>
</Button>
<DropList
bind:show={showDropdown}
position="bottom"
horizontal="right"
arrow={true}
arrowPosition="start">
<Button on:click={() => (showDropdown = !showDropdown)}>
<span class="icon-plus" aria-hidden="true" />
<span class="text">Add platform</span>
</Button>
<svelte:fragment slot="list">
<DropListItem on:click={() => addPlatform(Platform.Web)}>Web App</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Flutter)}>
Flutter App
</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Android)}>
Android App
</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Apple)}>Apple App</DropListItem>
</svelte:fragment>
</DropList>
</span>
</div>
@@ -25,7 +65,6 @@
{#each $project.platforms as platform}
<GridItem1 href={`${path}/${platform.$id}`}>
<svelte:fragment slot="title">{platform.name}</svelte:fragment>
<div class="grid-item-1-end-start">
<p>Last Updated</p>
<p>{toLocaleDateTime(platform.$updatedAt)}</p>
@@ -33,5 +72,3 @@
</GridItem1>
{/each}
</div>
<Create bind:show />
@@ -19,8 +19,8 @@
message: `${$platform.name} has been deleted`
});
project.load($project.$id);
platform.set(null);
await goto(`${base}/console/project-${$project.$id}/overview/platforms`);
platform.set(null);
} catch (error) {
addNotification({
type: 'error',
@@ -1,47 +0,0 @@
<script lang="ts">
import { Modal } from '$lib/components';
import { InputText, Button, Form, FormList } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import { project } from '../../.../../store';
export let show = false;
let name: string;
let hostname: string;
async function create() {
try {
await sdkForConsole.projects.createPlatform(
$project.$id,
'web',
name,
undefined,
undefined,
hostname
);
name = hostname = null;
project.load($project.$id);
show = false;
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
}
}
</script>
<Form on:submit={create}>
<Modal bind:show>
<svelte:fragment slot="header">Add Platform</svelte:fragment>
<FormList>
<InputText id="name" label="Name" bind:value={name} autofocus required />
<InputText id="host" label="Hostname" bind:value={hostname} required />
</FormList>
<svelte:fragment slot="footer">
<Button submit>Register</Button>
<Button secondary on:click={() => (show = false)}>Cancel</Button>
</svelte:fragment>
</Modal>
</Form>
@@ -0,0 +1,53 @@
<script lang="ts">
import { Wizard } from '$lib/layout';
import { beforeNavigate } from '$app/navigation';
import { page } from '$app/stores';
import { wizard } from '$lib/stores/wizard';
import { project } from '../../store';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import Step1 from './wizard/android/step1.svelte';
import Step2 from './wizard/android/step2.svelte';
import Step3 from './wizard/android/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { createPlatform } from './wizard/store';
const projectId = $page.params.project;
async function create() {
project.load(projectId);
createPlatform.reset();
wizard.hide();
}
beforeNavigate(() => {
wizard.hide();
});
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Register your app',
component: Step1
});
stepsComponents.set(2, {
label: 'Get the SDK',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: "Let's get coding",
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'All set',
component: Step4,
optional: true
});
</script>
<Wizard
title="Add an Android Project"
steps={stepsComponents}
on:finish={create}
on:exit={createPlatform.reset}
finalAction="Take me to my Dashboard" />
@@ -0,0 +1,53 @@
<script lang="ts">
import { Wizard } from '$lib/layout';
import { beforeNavigate } from '$app/navigation';
import { page } from '$app/stores';
import { wizard } from '$lib/stores/wizard';
import { project } from '../../store';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import Step1 from './wizard/apple/step1.svelte';
import Step2 from './wizard/apple/step2.svelte';
import Step3 from './wizard/apple/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { createPlatform } from './wizard/store';
const projectId = $page.params.project;
async function create() {
project.load(projectId);
createPlatform.reset();
wizard.hide();
}
beforeNavigate(() => {
wizard.hide();
});
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Register your app',
component: Step1
});
stepsComponents.set(2, {
label: 'Get the SDK',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: "Let's get coding",
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'All set',
component: Step4,
optional: true
});
</script>
<Wizard
title="Add an Apple Project"
steps={stepsComponents}
on:finish={create}
on:exit={createPlatform.reset}
finalAction="Take me to my Dashboard" />
@@ -0,0 +1,53 @@
<script lang="ts">
import { Wizard } from '$lib/layout';
import { beforeNavigate } from '$app/navigation';
import { page } from '$app/stores';
import { wizard } from '$lib/stores/wizard';
import { project } from '../../store';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import Step1 from './wizard/flutter/step1.svelte';
import Step2 from './wizard/flutter/step2.svelte';
import Step3 from './wizard/flutter/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { createPlatform } from './wizard/store';
const projectId = $page.params.project;
async function create() {
project.load(projectId);
createPlatform.reset();
wizard.hide();
}
beforeNavigate(() => {
wizard.hide();
});
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Register your app',
component: Step1
});
stepsComponents.set(2, {
label: 'Get the SDK',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: "Let's get coding",
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'All set',
component: Step4,
optional: true
});
</script>
<Wizard
title="Add a Flutter Project"
steps={stepsComponents}
on:finish={create}
on:exit={createPlatform.reset}
finalAction="Take me to my Dashboard" />
@@ -0,0 +1,53 @@
<script lang="ts">
import { Wizard } from '$lib/layout';
import { beforeNavigate } from '$app/navigation';
import { page } from '$app/stores';
import { wizard } from '$lib/stores/wizard';
import { project } from '../../store';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import Step1 from './wizard/web/step1.svelte';
import Step2 from './wizard/web/step2.svelte';
import Step3 from './wizard/web/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { createPlatform } from './wizard/store';
const projectId = $page.params.project;
async function create() {
project.load(projectId);
createPlatform.reset();
wizard.hide();
}
beforeNavigate(() => {
wizard.hide();
});
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Register your app',
component: Step1
});
stepsComponents.set(2, {
label: 'Get the SDK',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: "Let's get coding",
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'All set',
component: Step4,
optional: true
});
</script>
<Wizard
title="Add a Web Project"
steps={stepsComponents}
on:finish={create}
on:exit={createPlatform.reset}
finalAction="Take me to my Dashboard" />
@@ -0,0 +1,53 @@
<script lang="ts">
import { page } from '$app/stores';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdkForConsole } from '$lib/stores/sdk';
import { createPlatform } from '../store';
const projectId = $page.params.project;
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdkForConsole.projects.updatePlatform(
projectId,
$createPlatform.$id,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
return;
}
const platform = await sdkForConsole.projects.createPlatform(
projectId,
'android',
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
$createPlatform.$id = platform.$id;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Register your Android app</svelte:fragment>
<FormList>
<InputText
id="name"
label="Name"
placeholder="My Android App"
required
bind:value={$createPlatform.name} />
<InputText
id="hostname"
label="Package Name"
placeholder="com.company.appname"
required
bind:value={$createPlatform.hostname} />
</FormList>
</WizardStep>
@@ -0,0 +1,18 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { versions } from '../store';
const example1 = `repositories {
mavenCentral()
}`;
const example2 = `implementation("io.appwrite:sdk-for-android:${versions['client-android']}")`;
</script>
<WizardStep>
<svelte:fragment slot="title">Get the SDK</svelte:fragment>
<p>First, add this to your root level build.gradle file:</p>
<Code label="Groovy" labelIcon="android" language="kotlin" code={example1} withCopy />
<p class="common-section">And add this to your project's build.gradle file:</p>
<Code label="Groovy" labelIcon="android" language="kotlin" code={example2} withCopy />
</WizardStep>
@@ -0,0 +1,23 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { sdkForProject } from '$lib/stores/sdk';
const { endpoint, project } = sdkForProject.client.config;
const code = `const appwrite = new Appwrite();
appwrite
.setEndpoint('${endpoint}')
.setProject('${project}');`;
</script>
<WizardStep>
<svelte:fragment slot="title">Let's get coding</svelte:fragment>
<h2 class="heading-level-7">Init your SDK</h2>
<p>
Now that you've downloaded the SDK, it's time to initialze it. Use your project ID, which
can be found in your project settings page.
</p>
<Code label="Web SDK" labelIcon="code" language="js" {code} withCopy withLineNumbers />
</WizardStep>
@@ -0,0 +1,98 @@
<script lang="ts">
import { page } from '$app/stores';
import { Alert } from '$lib/components';
import { Pill } from '$lib/elements';
import { FormItem, FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdkForConsole } from '$lib/stores/sdk';
import { createPlatform } from '../store';
enum Platform {
iOS = 'apple-ios',
macOS = 'apple-macos',
watchOS = 'apple-watchos',
tvOS = 'apple-tvos'
}
let platform: Platform = Platform.iOS;
const projectId = $page.params.project;
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdkForConsole.projects.updatePlatform(
projectId,
$createPlatform.$id,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
return;
}
const response = await sdkForConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
$createPlatform.$id = response.$id;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Register your Flutter app</svelte:fragment>
<Alert type="warning">
Note: If you are building your Flutter application for multiple devices, you will have to
follow this process for each different device.
</Alert>
<FormList isCommonSection>
<FormItem>
<p>Choose a platform</p>
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill
button
on:click={() => (platform = Platform.iOS)}
selected={platform === Platform.iOS}>
iOS
</Pill>
<Pill
button
on:click={() => (platform = Platform.macOS)}
selected={platform === Platform.macOS}>
macOS
</Pill>
<Pill
button
on:click={() => (platform = Platform.watchOS)}
selected={platform === Platform.watchOS}>
watchOS
</Pill>
<Pill
button
on:click={() => (platform = Platform.tvOS)}
selected={platform === Platform.tvOS}>
tvOS
</Pill>
</div>
</FormItem>
<InputText
id="name"
label="Name"
placeholder="My Apple App"
required
bind:value={$createPlatform.name} />
<InputText
id="hostname"
label="Bundle ID"
placeholder="com.company.appname"
required
bind:value={$createPlatform.hostname} />
</FormList>
</WizardStep>
@@ -0,0 +1,78 @@
<script lang="ts">
import { Code } from '$lib/components';
import { Pill } from '$lib/elements';
import { WizardStep } from '$lib/layout';
import { versions } from '../store';
enum Method {
Xcode,
Swift
}
let method: Method = Method.Xcode;
const example1 = `dependencies: [
.package(
name: "Appwrite",
url: "https://github.com/appwrite/sdk-for-swift",
.exact("${$versions['client-apple']}")
)
]')`;
const example2 = `targets: [
.target(
name: "[YOUR_TARGET]",
dependencies: [
"Appwrite"
]
)
]`;
</script>
<WizardStep>
<svelte:fragment slot="title">Get the SDK</svelte:fragment>
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill button on:click={() => (method = Method.Xcode)} selected={method === Method.Xcode}>
Xcode
</Pill>
<Pill button on:click={() => (method = Method.Swift)} selected={method === Method.Swift}>
Swift Packages
</Pill>
</div>
<div class="common-section">
{#if method === Method.Xcode}
<ol class="numeric-list">
<li class="numeric-list-item">
<span class="text">
Select File > Swift Packages > Add Package Dependency
</span>
</li>
<li class="numeric-list-item">
<span class="text">
Search for the Appwrite SDK with the URL
<a class="link" href="https://github.com/appwrite/sdk-for-apple">
https://github.com/appwrite/sdk-for-apple
</a>
</span>
</li>
<li class="numeric-list-item">
<span class="text"> Add version rules </span>
</li>
<li class="numeric-list-item">
<span class="text">
Select next and wait for package resolution to complete
</span>
</li>
<li class="numeric-list-item">
<span class="text">
Make sure `Appwrite` is selected to add to your target and select finish
</span>
</li>
</ol>
{:else if method === Method.Swift}
<p>Add this to your Package.swift file:</p>
<Code withCopy withLineNumbers label="Swift" language="swift" code={example1} />
<p class="common-section">Then add the dependency to your target:</p>
<Code withCopy withLineNumbers label="Swift" language="swift" code={example2} />
{/if}
</div>
</WizardStep>
@@ -0,0 +1,37 @@
<script lang="ts">
import { Alert, Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { sdkForProject } from '$lib/stores/sdk';
const { endpoint, project } = sdkForProject.client.config;
const code = `import Appwrite
let client = Client()
.setEndpoint("${endpoint}")
.setProject("${project}")
.setSelfSigned(status: true) // For self signed certificates, only use for development`;
</script>
<WizardStep>
<svelte:fragment slot="title">Let's get coding</svelte:fragment>
<h2 class="heading-level-7">Init your SDK</h2>
<p>
Now that you've downloaded the SDK, it's time to initialze it. Use your project ID, which
can be found in your project settings page.
</p>
<Code label="Apple SDK" labelIcon="apple" language="swift" {code} withCopy withLineNumbers />
<p>
Before sending any API calls to your new Appwrite project, make sure your device or emulator
has network access to your Appwrite project's hostname or IP address.
</p>
<div class="common-section">
<Alert type="info">
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
you should use the private IP of the device running your Appwrite project as the hostname
of the endpoint instead of localhost. You can also use a service like ngrok to proxy the
Appwrite server.
</Alert>
</div>
</WizardStep>
@@ -0,0 +1,167 @@
<script lang="ts">
import { page } from '$app/stores';
import { Alert } from '$lib/components';
import { Pill } from '$lib/elements';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdkForConsole } from '$lib/stores/sdk';
import { createPlatform } from '../store';
enum Platform {
Android = 'flutter-android',
Ios = 'flutter-ios',
Linux = 'flutter-linux',
Macos = 'flutter-macos',
Windows = 'flutter-windows',
Web = 'flutter-web'
}
let platform: Platform = Platform.Android;
const projectId = $page.params.project;
const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.app'];
const placeholder: Record<
Platform,
{
name: string;
hostname: string;
}
> = {
[Platform.Android]: {
name: 'My Android App',
hostname: 'com.company.appname'
},
[Platform.Ios]: {
name: 'My iOS App',
hostname: 'com.company.appname'
},
[Platform.Linux]: {
name: 'My Linux App',
hostname: 'com.company.appname'
},
[Platform.Macos]: {
name: 'My mac OS App',
hostname: 'com.company.appname'
},
[Platform.Web]: {
name: 'My Web App',
hostname: 'com.company.appname'
},
[Platform.Windows]: {
name: 'My Windows App',
hostname: 'localhost'
}
};
const hostname: Record<Platform, string> = {
[Platform.Android]: 'Package Name',
[Platform.Ios]: 'Package Name',
[Platform.Linux]: 'Package Name',
[Platform.Macos]: 'Bundle ID',
[Platform.Web]: 'Hostname',
[Platform.Windows]: 'Package Name'
};
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdkForConsole.projects.updatePlatform(
projectId,
$createPlatform.$id,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
return;
}
const response = await sdkForConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
$createPlatform.$id = response.$id;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Register your Flutter app</svelte:fragment>
<svelte:fragment slot="subtitle">
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill
button
on:click={() => (platform = Platform.Android)}
selected={platform === Platform.Android}>
Android
</Pill>
<Pill
button
on:click={() => (platform = Platform.Ios)}
selected={platform === Platform.Ios}>
iOS
</Pill>
<Pill
button
on:click={() => (platform = Platform.Linux)}
selected={platform === Platform.Linux}>
Linux
</Pill>
<Pill
button
on:click={() => (platform = Platform.Macos)}
selected={platform === Platform.Macos}>
Mac OS
</Pill>
<Pill
button
on:click={() => (platform = Platform.Windows)}
selected={platform === Platform.Windows}>
Windows
</Pill>
<Pill
button
on:click={() => (platform = Platform.Web)}
selected={platform === Platform.Web}>
Web
</Pill>
</div>
</svelte:fragment>
<Alert type="warning">
Note: If you are building your Flutter application for multiple devices, you will have to
follow this process for each different device.
</Alert>
<FormList isCommonSection>
<InputText
id="name"
label="Name"
placeholder={placeholder[platform].name}
required
bind:value={$createPlatform.name} />
<div>
<InputText
id="hostname"
label={hostname[platform]}
placeholder={placeholder[platform].hostname}
required
bind:value={$createPlatform.hostname} />
{#if platform === Platform.Web}
<div class="u-flex u-gap-16 u-margin-block-start-8">
{#each suggestions as suggestion}
<Pill
button
selected={$createPlatform.hostname === suggestion}
on:click={() => ($createPlatform.hostname = suggestion)}>
{suggestion}
</Pill>
{/each}
</div>
{/if}
</div>
</FormList>
</WizardStep>
@@ -0,0 +1,20 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { versions } from '../store';
const example1 = `dependencies:
appwrite: ^${$versions['client-flutter']}`;
const example2 = `pub get appwrite`;
</script>
<WizardStep>
<svelte:fragment slot="title">Get the SDK</svelte:fragment>
<p>Add Appwrite SDK to your package's pubspec.yaml file. You can view an example here.</p>
<Code label="YAML" language="yml" code={example1} withCopy />
<p class="common-section">
You can also install the SDK using the Dart package manager from your terminal:
</p>
<Code label="Bash" language="sh" code={example2} withCopy />
</WizardStep>
@@ -0,0 +1,38 @@
<script lang="ts">
import { Alert, Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { sdkForProject } from '$lib/stores/sdk';
const { endpoint, project } = sdkForProject.client.config;
const code = `import 'package:appwrite/appwrite.dart';
Client client = Client();
client
.setEndpoint('${endpoint}')
.setProject('${project}')
.setSelfSigned(status: true); // For self signed certificates, only use for development`;
</script>
<WizardStep>
<svelte:fragment slot="title">Let's get coding</svelte:fragment>
<h2 class="heading-level-7">Init your SDK</h2>
<p>
Now that you've downloaded the SDK, it's time to initialze it. Use your project ID, which
can be found in your project settings page.
</p>
<Code label="Flutter SDK" labelIcon="flutter" language="dart" {code} withCopy withLineNumbers />
<p class="common-section">
Before sending any API calls to your new Appwrite project, make sure your device or emulator
has network access to your Appwrite project's hostname or IP address.
</p>
<div class="common-section">
<Alert type="info">
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
you should use the private IP of the device running your Appwrite project as the hostname
of the endpoint instead of localhost. You can also use a service like ngrok to proxy the
Appwrite server.
</Alert>
</div>
</WizardStep>
@@ -0,0 +1,12 @@
<script lang="ts">
import { WizardStep } from '$lib/layout';
</script>
<WizardStep>
<svelte:fragment slot="title">You're ready to go 🎉</svelte:fragment>
<p>
Congrats, you've just added your first platform to your Appwrite dashboard! Are you ready to
give it a go? Why not add a database to your project, or start uploading files? The choice
is up to you.
</p>
</WizardStep>
@@ -0,0 +1,60 @@
import { writable } from 'svelte/store';
import { sdkForConsole } from '$lib/stores/sdk';
import { cachedStore } from '$lib/helpers/cache';
import type { Models } from '@aw-labs/appwrite-console';
function createPlatformStore() {
const { subscribe, update, set } = writable<Partial<Models.Platform>>({
$id: null,
name: null,
hostname: null,
type: null
});
return {
subscribe,
update,
set,
reset() {
set({
$id: null,
name: null,
hostname: null,
type: null
});
}
};
}
export const createPlatform = createPlatformStore();
export const versions = cachedStore<
{
server: string;
'client-web': string;
'client-flutter': string;
'client-apple': string;
'client-android': string;
'console-web': string;
'console-cli': string;
'server-nodejs': string;
'server-deno': string;
'server-php': string;
'server-python': string;
'server-ruby': string;
'server-dart': string;
'server-kotlin': string;
'server-swift': string;
},
{
load: () => Promise<void>;
}
>('versions', function ({ set }) {
return {
load: async () => {
const { endpoint } = sdkForConsole.client.config;
const response = await fetch(`${endpoint}/../versions`);
set(await response.json());
}
};
});
@@ -0,0 +1,72 @@
<script lang="ts">
import { page } from '$app/stores';
import { Alert } from '$lib/components';
import { Pill } from '$lib/elements';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdkForConsole } from '$lib/stores/sdk';
import { createPlatform } from '../store';
const projectId = $page.params.project;
const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.app'];
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdkForConsole.projects.updatePlatform(
projectId,
$createPlatform.$id,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
return;
}
const platform = await sdkForConsole.projects.createPlatform(
projectId,
'web',
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname
);
$createPlatform.$id = platform.$id;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Register your Web app</svelte:fragment>
<FormList>
<InputText
id="name"
label="Name"
placeholder="My Web App"
required
bind:value={$createPlatform.name} />
<div>
<InputText
id="hostname"
label="Hostname"
placeholder="localhost"
required
bind:value={$createPlatform.hostname} />
<div class="u-flex u-gap-16 u-margin-block-start-8">
{#each suggestions as suggestion}
<Pill
button
selected={$createPlatform.hostname === suggestion}
on:click={() => ($createPlatform.hostname = suggestion)}>
{suggestion}
</Pill>
{/each}
</div>
</div>
<Alert type="warning">
Tip: Avoid using wildcard hostnames in production to keep your project secure. Check out
our documentation for more info.
</Alert>
</FormList>
</WizardStep>
@@ -0,0 +1,57 @@
<script lang="ts">
import { versions } from '../store';
import { Code } from '$lib/components';
import { Pill } from '$lib/elements';
import { WizardStep } from '$lib/layout';
enum Method {
NPM,
CDN
}
let method: Method = Method.NPM;
const example1 = `import { Appwrite } from 'appwrite';`;
const example2 = `<script src="https://cdn.jsdelivr.net/npm/appwrite@${$versions['client-web']}" />`;
</script>
<WizardStep>
<svelte:fragment slot="title">Get the SDK</svelte:fragment>
<svelte:fragment slot="subtitle">
Choose your preferred method of installation
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill button on:click={() => (method = Method.NPM)} selected={method === Method.NPM}>
NPM
</Pill>
<Pill button on:click={() => (method = Method.CDN)} selected={method === Method.CDN}>
CDN
</Pill>
</div>
</svelte:fragment>
{#if method === Method.NPM}
<p>
Use <a href="https://npmjs.org" target="_blank" rel="noopener noreferrer" class="link"
>NPM (node package manager)</a> from your command line to add Appwrite SDK to your project.
</p>
<Code label="Bash" language="sh" code="npm install appwrite" withCopy />
<p class="common-section">
When you're using a bundler (like <a
href="https://vitejs.dev"
target="_blank"
rel="noopener noreferrer"
class="link">Vite</a>
or
<a href="https://rollupjs.org" target="_blank" rel="noopener noreferrer" class="link"
>Rollup</a
>), import the Appwrite module when you need it:
</p>
<Code label="Web SDK" labelIcon="code" language="js" code={example1} withCopy />
{:else if method === Method.CDN}
<p>
To install with a CDN (content delivery network) add the following scripts to the bottom
of your tag, but before you use any Appwrite services:
</p>
<Code label="HTML" language="html" code={example2} withCopy />
{/if}
</WizardStep>
@@ -0,0 +1,23 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { sdkForProject } from '$lib/stores/sdk';
const { endpoint, project } = sdkForProject.client.config;
const code = `const appwrite = new Appwrite();
appwrite
.setEndpoint('${endpoint}')
.setProject('${project}');`;
</script>
<WizardStep>
<svelte:fragment slot="title">Let's get coding</svelte:fragment>
<h2 class="heading-level-7">Init your SDK</h2>
<p>
Now that you've downloaded the SDK, it's time to initialze it. Use your project ID, which
can be found in your project settings page.
</p>
<Code label="Web SDK" labelIcon="code" language="js" {code} withCopy withLineNumbers />
</WizardStep>
@@ -70,6 +70,7 @@
href={downloadFile()}
class="file-preview is-with-image"
target="_blank"
rel="noopener noreferrer"
aria-label="open file in new window">
<div class="file-preview-image">
<img
+7 -2
View File
@@ -59,9 +59,14 @@
By accepting the invitation, you agree to the <a
class="link"
href="https://appwrite.io/policy/terms"
target="_blank">Terms and Conditions</a>
target="_blank"
rel="noopener noreferrer">Terms and Conditions</a>
and
<a class="link" href="https://appwrite.io/policy/privacy" target="_blank">
<a
class="link"
href="https://appwrite.io/policy/privacy"
target="_blank"
rel="noopener noreferrer">
Privacy Policy</a
>.</InputChoice>
+9 -9
View File
@@ -26,7 +26,7 @@ test('shows line numbers', async () => {
const { container } = render(Code, {
code: 'a\nb;\nc;',
language: 'js',
showLineNumbers: true
withLineNumbers: true
});
expect(container.querySelectorAll('.line-numbers').length).toEqual(1);
@@ -39,9 +39,9 @@ test('shows code highlighted javascript', async () => {
language: 'js'
});
expect(container.querySelectorAll('.token.function').length).toEqual(1);
expect(container.querySelectorAll('.token.string').length).toEqual(1);
expect(container.querySelectorAll('.token.punctuation').length).toEqual(4);
expect(container.querySelectorAll('.prism-token.prism-function').length).toEqual(1);
expect(container.querySelectorAll('.prism-token.prism-string').length).toEqual(1);
expect(container.querySelectorAll('.prism-token.prism-punctuation').length).toEqual(4);
});
test('shows code highlighted json', async () => {
@@ -50,17 +50,17 @@ test('shows code highlighted json', async () => {
language: 'json'
});
expect(container.querySelectorAll('.token.property').length).toEqual(1);
expect(container.querySelectorAll('.token.operator').length).toEqual(1);
expect(container.querySelectorAll('.token.string').length).toEqual(1);
expect(container.querySelectorAll('.token.punctuation').length).toEqual(2);
expect(container.querySelectorAll('.prism-token.prism-property').length).toEqual(1);
expect(container.querySelectorAll('.prism-token.prism-operator').length).toEqual(1);
expect(container.querySelectorAll('.prism-token.prism-string').length).toEqual(1);
expect(container.querySelectorAll('.prism-token.prism-punctuation').length).toEqual(2);
});
test('copy to clipboard function called on click', async () => {
const { container } = render(Code, {
code: 'console.log("test");',
language: 'js',
showCopy: true
withCopy: true
});
Object.assign(window.navigator, {