add loading state

This commit is contained in:
kevmodrome 2020-05-27 12:54:53 +02:00
parent 075b264d21
commit 3a72eddd78
5 changed files with 207 additions and 182 deletions

View File

@ -26,6 +26,4 @@
<AppNotification /> <AppNotification />
<Modal> <Router {routes} />
<Router {routes} />
</Modal>

View File

@ -1,30 +1,36 @@
<script> <script>
import Spinner from "components/common/Spinner.svelte"
import { Input, TextArea, Button } from "@budibase/bbui" import { Input, TextArea, Button } from "@budibase/bbui"
import { goto } from "@sveltech/routify"
import { AppsIcon, InfoIcon, CloseIcon } from "components/common/Icons/" import { AppsIcon, InfoIcon, CloseIcon } from "components/common/Icons/"
import { getContext } from "svelte" import { getContext } from "svelte"
export let onCancel = () => {} import { fade } from "svelte/transition"
export let onOkay = () => {}
const { close } = getContext("simple-modal") const { open, close } = getContext("simple-modal")
let name = "" let name = ""
let description = "" let description = ""
let loading = false
const createNewApp = async () => { const createNewApp = async () => {
const data = { name, description} const data = { name, description }
loading = true
try { try {
const response = await fetch('/api/applications', { const response = await fetch("/api/applications", {
method: 'POST', // *GET, POST, PUT, DELETE, etc. method: "POST", // *GET, POST, PUT, DELETE, etc.
credentials: 'same-origin', // include, *same-origin, omit credentials: "same-origin", // include, *same-origin, omit
headers: { headers: {
'Content-Type': 'application/json' "Content-Type": "application/json",
// 'Content-Type': 'application/x-www-form-urlencoded', // 'Content-Type': 'application/x-www-form-urlencoded',
}, },
body: JSON.stringify(data) // body data type must match "Content-Type" header body: JSON.stringify(data), // body data type must match "Content-Type" header
}); })
} catch (error) {
const res = await response.json()
$goto(`./${res._id}`)
} catch (error) {
console.error(error)
} }
} }
@ -32,23 +38,28 @@
let onChange = () => {} let onChange = () => {}
function _onCancel() { function _onCancel() {
onCancel()
close() close()
} }
async function _onOkay() { async function _onOkay() {
await createNewApp() await createNewApp()
close()
} }
</script> </script>
<div class="container"> <div class="container">
<div class="body"> <div class="body">
<div class="heading"> <div class="heading">
<span class="icon"><AppsIcon /></span> <span class="icon">
<AppsIcon />
</span>
<h3>Create new web app</h3> <h3>Create new web app</h3>
</div> </div>
<Input name="name" label="Name" placeholder="Enter application name" on:change={(e) => name = e.target.value} on:input={(e) => name = e.target.value} /> <Input
name="name"
label="Name"
placeholder="Enter application name"
on:change={e => (name = e.target.value)}
on:input={e => (name = e.target.value)} />
<TextArea <TextArea
bind:value={description} bind:value={description}
name="description" name="description"
@ -56,22 +67,28 @@
placeholder="Describe your application" /> placeholder="Describe your application" />
</div> </div>
<div class="footer"> <div class="footer">
<a href="./#" class="info"><InfoIcon />How to get started</a> <a href="./#" class="info">
<Button outline thin on:click={_onCancel}> <InfoIcon />
Cancel How to get started
</Button> </a>
<Button primary thin on:click={_onOkay}> <Button outline thin on:click={_onCancel}>Cancel</Button>
Save <Button primary thin on:click={_onOkay}>Save</Button>
</Button>
</div> </div>
<div class="close-button" on:click={_onCancel}><CloseIcon /></div> <div class="close-button" on:click={_onCancel}>
<CloseIcon />
</div>
{#if loading}
<div in:fade class="spinner-container">
<Spinner />
<span class="spinner-text">Creating your app...</span>
</div>
{/if}
</div> </div>
<style> <style>
.container {
.container { position: relative;
position: relative; }
}
.close-button { .close-button {
cursor: pointer; cursor: pointer;
@ -130,4 +147,20 @@
border-bottom-right-radius: 50px; border-bottom-right-radius: 50px;
background-color: var(--grey-light); background-color: var(--grey-light);
} }
.spinner-container {
background: white;
position: absolute;
border-radius: 5px;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: grid;
justify-items: center;
align-content: center;
grid-gap: 50px;
}
.spinner-text {
font-size: 2em;
}
</style> </style>

View File

@ -1,4 +1,5 @@
<script> <script>
import Modal from "svelte-simple-modal"
import { store } from "builderStore" import { store } from "builderStore"
import { fade } from "svelte/transition" import { fade } from "svelte/transition"
@ -20,62 +21,63 @@
await store.setPackage(pkg) await store.setPackage(pkg)
return pkg return pkg
} else { } else {
console.log(pkg)
throw new Error(pkg) throw new Error(pkg)
} }
} }
</script> </script>
<div class="root"> <Modal>
<div class="root">
<div class="top-nav"> <div class="top-nav">
<div class="topleftnav"> <div class="topleftnav">
<button class="home-logo"> <button class="home-logo">
<img <img
src="/_builder/assets/bb-logo.svg" src="/_builder/assets/bb-logo.svg"
alt="budibase icon" alt="budibase icon"
on:click={() => $goto(`/`)} /> on:click={() => $goto(`/`)} />
</button> </button>
<!-- This gets all indexable subroutes and sticks them in the top nav. --> <!-- This gets all indexable subroutes and sticks them in the top nav. -->
{#each $layout.children as { path, title }} {#each $layout.children as { path, title }}
<span <span
class:active={$isActive(path)} class:active={$isActive(path)}
class="topnavitem" class="topnavitem"
on:click={() => $goto(path)}> on:click={() => $goto(path)}>
{title} {title}
</span> </span>
{/each} {/each}
<!-- <IconButton icon="home" <!-- <IconButton icon="home"
color="var(--slate)" color="var(--slate)"
hoverColor="var(--secondary75)"/> --> hoverColor="var(--secondary75)"/> -->
</div>
<div class="toprightnav">
<span
class:active={$isActive(`/settings`)}
class="topnavitemright"
on:click={() => $goto(`/settings`)}>
<SettingsIcon />
</span>
<span
class:active={false}
class="topnavitemright"
on:click={() => (location = `/${application}`)}>
<PreviewIcon />
</span>
</div>
</div> </div>
<div class="toprightnav">
<span {#await promise}
class:active={$isActive(`/settings`)} <!-- This should probably be some kind of loading state? -->
class="topnavitemright" <div />
on:click={() => $goto(`/settings`)}> {:then}
<SettingsIcon /> <slot />
</span> {:catch error}
<span <p>Something went wrong: {error.message}</p>
class:active={false} {/await}
class="topnavitemright"
on:click={() => (location = `/${application}`)}>
<PreviewIcon />
</span>
</div>
</div> </div>
</Modal>
{#await promise}
<!-- This should probably be some kind of loading state? -->
<div />
{:then}
<slot />
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}
</div>
<style> <style>
.root { .root {

View File

@ -1,4 +1,5 @@
<script> <script>
import Modal from "svelte-simple-modal"
import { import {
SettingsIcon, SettingsIcon,
AppsIcon, AppsIcon,
@ -14,104 +15,106 @@
} from "components/common/Icons/" } from "components/common/Icons/"
</script> </script>
<div class="root"> <Modal>
<div class="ui-nav"> <div class="root">
<div class="home-logo"> <div class="ui-nav">
<img src="/_builder/assets/bb-logo.svg" alt="Budibase icon" /> <div class="home-logo">
</div> <img src="/_builder/assets/bb-logo.svg" alt="Budibase icon" />
<div class="nav-section">
<div class="nav-section-title">Build</div>
<div class="nav-item-home">
<span class="nav-item-icon">
<AppsIcon />
</span>
<div class="nav-item-title">Apps</div>
</div> </div>
<div class="nav-item">
<span class="nav-item-icon"> <div class="nav-section">
<SettingsIcon /> <div class="nav-section-title">Build</div>
</span> <div class="nav-item-home">
<div class="nav-item-title">Settings</div> <span class="nav-item-icon">
<AppsIcon />
</span>
<div class="nav-item-title">Apps</div>
</div>
<div class="nav-item">
<span class="nav-item-icon">
<SettingsIcon />
</span>
<div class="nav-item-title">Settings</div>
</div>
<a href="https://budibase.con/login" target="_blank" class="nav-item">
<span class="nav-item-icon">
<UpdatesIcon />
</span>
<div class="nav-item-title">Updates</div>
</a>
<a href="https://budibase.con/login" target="_blank" class="nav-item">
<span class="nav-item-icon">
<HostingIcon />
</span>
<div class="nav-item-title">Hosting</div>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Learn</div>
<a href="https://docs.budibase.com/" target="_blank" class="nav-item">
<span class="nav-item-icon">
<DocumentationIcon />
</span>
<div class="nav-item-title">Documentation</div>
</a>
<a
href="https://docs.budibase.com/tutorial/quick-start"
target="_blank"
class="nav-item">
<span class="nav-item-icon">
<TutorialsIcon />
</span>
<div class="nav-item-title">Tutorials</div>
</a>
<a href="https://forum.budibase.com/" target="_blank" class="nav-item">
<span class="nav-item-icon">
<CommunityIcon />
</span>
<div class="nav-item-title">Community</div>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Contact</div>
<a
href="https://github.com/Budibase/budibase/blob/master/CONTRIBUTING.md"
target="_blank"
class="nav-item">
<span class="nav-item-icon">
<ContributionIcon />
</span>
<div class="nav-item-title">Contribute to our product</div>
</a>
<a
href="https://github.com/Budibase/budibase/issues"
target="_blank"
class="nav-item">
<span class="nav-item-icon">
<BugIcon />
</span>
<div class="nav-item-title">Report bug</div>
</a>
<a href="mailto:support@budibase.com" target="_blank" class="nav-item">
<span class="nav-item-icon">
<EmailIcon />
</span>
<div class="nav-item-title">Email</div>
</a>
<a href="https://twitter.com/budibase" target="_blank" class="nav-item">
<span class="nav-item-icon">
<TwitterIcon />
</span>
<div class="nav-item-title">Twitter</div>
</a>
</div> </div>
<a href="https://budibase.con/login" target="_blank" class="nav-item">
<span class="nav-item-icon">
<UpdatesIcon />
</span>
<div class="nav-item-title">Updates</div>
</a>
<a href="https://budibase.con/login" target="_blank" class="nav-item">
<span class="nav-item-icon">
<HostingIcon />
</span>
<div class="nav-item-title">Hosting</div>
</a>
</div> </div>
<div class="nav-section"> <div class="main">
<div class="nav-section-title">Learn</div> <slot />
<a href="https://docs.budibase.com/" target="_blank" class="nav-item">
<span class="nav-item-icon">
<DocumentationIcon />
</span>
<div class="nav-item-title">Documentation</div>
</a>
<a
href="https://docs.budibase.com/tutorial/quick-start"
target="_blank"
class="nav-item">
<span class="nav-item-icon">
<TutorialsIcon />
</span>
<div class="nav-item-title">Tutorials</div>
</a>
<a href="https://forum.budibase.com/" target="_blank" class="nav-item">
<span class="nav-item-icon">
<CommunityIcon />
</span>
<div class="nav-item-title">Community</div>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Contact</div>
<a
href="https://github.com/Budibase/budibase/blob/master/CONTRIBUTING.md"
target="_blank"
class="nav-item">
<span class="nav-item-icon">
<ContributionIcon />
</span>
<div class="nav-item-title">Contribute to our product</div>
</a>
<a
href="https://github.com/Budibase/budibase/issues"
target="_blank"
class="nav-item">
<span class="nav-item-icon">
<BugIcon />
</span>
<div class="nav-item-title">Report bug</div>
</a>
<a href="mailto:support@budibase.com" target="_blank" class="nav-item">
<span class="nav-item-icon">
<EmailIcon />
</span>
<div class="nav-item-title">Email</div>
</a>
<a href="https://twitter.com/budibase" target="_blank" class="nav-item">
<span class="nav-item-icon">
<TwitterIcon />
</span>
<div class="nav-item-title">Twitter</div>
</a>
</div> </div>
</div> </div>
</Modal>
<div class="main">
<slot />
</div>
</div>
<style> <style>
.root { .root {

View File

@ -24,15 +24,6 @@
// Handle create app modal // Handle create app modal
const { open } = getContext("simple-modal") const { open } = getContext("simple-modal")
const onCancel = text => {
name = ""
status = -1
}
const onOkay = text => {
name = text
status = 1
}
const showCreateAppModal = () => { const showCreateAppModal = () => {
open( open(
@ -40,15 +31,13 @@
{ {
message: "What is your name?", message: "What is your name?",
hasForm: true, hasForm: true,
onCancel,
onOkay,
}, },
{ {
closeButton: false, closeButton: false,
closeOnEsc: false, closeOnEsc: false,
closeOnOuterClick: false, closeOnOuterClick: false,
styleContent: { padding: 0 }, styleContent: { padding: 0 },
closeOnOuterClick: true closeOnOuterClick: true,
} }
) )
} }