Minor UI updates for the create app modal. A spinner has been added to the modal confirmation UX. The app name is pre-populated using the app name. The app URL can no longer be null
This commit is contained in:
parent
9f9832f36b
commit
bc4d0b7e51
|
@ -5,6 +5,7 @@
|
||||||
import Divider from "../Divider/Divider.svelte"
|
import Divider from "../Divider/Divider.svelte"
|
||||||
import Icon from "../Icon/Icon.svelte"
|
import Icon from "../Icon/Icon.svelte"
|
||||||
import Context from "../context"
|
import Context from "../context"
|
||||||
|
import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte"
|
||||||
|
|
||||||
export let title = undefined
|
export let title = undefined
|
||||||
export let size = "S"
|
export let size = "S"
|
||||||
|
@ -102,15 +103,22 @@
|
||||||
<Button group secondary on:click={close}>{cancelText}</Button>
|
<Button group secondary on:click={close}>{cancelText}</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if showConfirmButton}
|
{#if showConfirmButton}
|
||||||
<Button
|
<span class="confirm-wrap">
|
||||||
group
|
<Button
|
||||||
cta
|
group
|
||||||
{...$$restProps}
|
cta
|
||||||
disabled={confirmDisabled}
|
{...$$restProps}
|
||||||
on:click={confirm}
|
disabled={confirmDisabled}
|
||||||
>
|
on:click={confirm}
|
||||||
{confirmText}
|
>
|
||||||
</Button>
|
{#if loading}
|
||||||
|
<ProgressCircle overBackground={true} size="S" />
|
||||||
|
{/if}
|
||||||
|
{#if !loading}
|
||||||
|
{confirmText}
|
||||||
|
{/if}
|
||||||
|
</Button>
|
||||||
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -169,4 +177,8 @@
|
||||||
.spectrum-Dialog-buttonGroup {
|
.spectrum-Dialog-buttonGroup {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.confirm-wrap :global(.spectrum-Button-label) {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,18 +13,20 @@
|
||||||
|
|
||||||
export let template
|
export let template
|
||||||
|
|
||||||
|
let creating = false
|
||||||
|
|
||||||
const values = writable({ name: "", url: null })
|
const values = writable({ name: "", url: null })
|
||||||
const validation = createValidationStore()
|
const validation = createValidationStore()
|
||||||
$: validation.check($values)
|
$: validation.check($values)
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
$values.url = resolveAppUrl(template, $values.name, $values.url)
|
|
||||||
$values.name = resolveAppName(template, $values.name)
|
$values.name = resolveAppName(template, $values.name)
|
||||||
|
nameToUrl($values.name)
|
||||||
await setupValidation()
|
await setupValidation()
|
||||||
})
|
})
|
||||||
|
|
||||||
$: appUrl = `${window.location.origin}${
|
$: appUrl = `${window.location.origin}${
|
||||||
$values.url ? $values.url : `/${resolveAppUrl(template, $values.name)}`
|
$values.url ? $values.url : `${resolveAppUrl(template, $values.name)}`
|
||||||
}`
|
}`
|
||||||
|
|
||||||
const resolveAppUrl = (template, name) => {
|
const resolveAppUrl = (template, name) => {
|
||||||
|
@ -39,7 +41,19 @@
|
||||||
if (template && !name) {
|
if (template && !name) {
|
||||||
return template.name
|
return template.name
|
||||||
}
|
}
|
||||||
return name.trim()
|
return name ? name.trim() : null
|
||||||
|
}
|
||||||
|
|
||||||
|
const tidyUrl = url => {
|
||||||
|
if (url && !url.startsWith("/")) {
|
||||||
|
url = `/${url}`
|
||||||
|
}
|
||||||
|
$values.url = url === "" ? null : url
|
||||||
|
}
|
||||||
|
|
||||||
|
const nameToUrl = appName => {
|
||||||
|
let resolvedUrl = resolveAppUrl(template, appName)
|
||||||
|
tidyUrl(resolvedUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupValidation = async () => {
|
const setupValidation = async () => {
|
||||||
|
@ -52,6 +66,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNewApp() {
|
async function createNewApp() {
|
||||||
|
creating = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create form data to create app
|
// Create form data to create app
|
||||||
let data = new FormData()
|
let data = new FormData()
|
||||||
|
@ -86,17 +102,11 @@
|
||||||
await auth.setInitInfo({})
|
await auth.setInitInfo({})
|
||||||
$goto(`/builder/app/${createdApp.instance._id}`)
|
$goto(`/builder/app/${createdApp.instance._id}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
creating = false
|
||||||
console.error(error)
|
console.error(error)
|
||||||
notifications.error("Error creating app")
|
notifications.error("Error creating app")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto add slash to url
|
|
||||||
$: {
|
|
||||||
if ($values.url && !$values.url.startsWith("/")) {
|
|
||||||
$values.url = `/${$values.url}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent
|
<ModalContent
|
||||||
|
@ -128,41 +138,38 @@
|
||||||
{/if}
|
{/if}
|
||||||
<Input
|
<Input
|
||||||
bind:value={$values.name}
|
bind:value={$values.name}
|
||||||
|
disabled={creating}
|
||||||
error={$validation.touched.name && $validation.errors.name}
|
error={$validation.touched.name && $validation.errors.name}
|
||||||
on:blur={() => ($validation.touched.name = true)}
|
on:blur={() => ($validation.touched.name = true)}
|
||||||
|
on:change={nameToUrl($values.name)}
|
||||||
label="Name"
|
label="Name"
|
||||||
placeholder={$auth.user.firstName
|
placeholder={$auth.user?.firstName
|
||||||
? `${$auth.user.firstName}s app`
|
? `${$auth.user.firstName}s app`
|
||||||
: "My app"}
|
: "My app"}
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
<Input
|
<Input
|
||||||
bind:value={$values.url}
|
bind:value={$values.url}
|
||||||
|
disabled={creating}
|
||||||
error={$validation.touched.url && $validation.errors.url}
|
error={$validation.touched.url && $validation.errors.url}
|
||||||
on:blur={() => ($validation.touched.url = true)}
|
on:blur={() => ($validation.touched.url = true)}
|
||||||
|
on:change={tidyUrl($values.url)}
|
||||||
label="URL"
|
label="URL"
|
||||||
placeholder={$values.url
|
placeholder={$values.url
|
||||||
? $values.url
|
? $values.url
|
||||||
: `/${resolveAppUrl(template, $values.name)}`}
|
: `/${resolveAppUrl(template, $values.name)}`}
|
||||||
/>
|
/>
|
||||||
{#if $values.name}
|
{#if $values.url && $values.url !== "" && !$validation.errors.url}
|
||||||
<div class="app-server-wrap" title={appUrl}>
|
<div class="app-server" title={appUrl}>
|
||||||
<span class="app-server-prefix">
|
{`${window.location.origin}${$values.url}`}
|
||||||
{window.location.origin}
|
|
||||||
</span>
|
|
||||||
{$values.url
|
|
||||||
? $values.url
|
|
||||||
: `/${resolveAppUrl(template, $values.name)}`}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.app-server-prefix {
|
.app-server {
|
||||||
color: var(--spectrum-global-color-gray-500);
|
color: var(--spectrum-global-color-gray-600);
|
||||||
}
|
|
||||||
.app-server-wrap {
|
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
|
@ -35,13 +35,14 @@ export const url = (validation, { apps, currentApp } = { apps: [] }) => {
|
||||||
validation.addValidator(
|
validation.addValidator(
|
||||||
"url",
|
"url",
|
||||||
string()
|
string()
|
||||||
|
.trim()
|
||||||
.nullable()
|
.nullable()
|
||||||
.matches(APP_URL_REGEX, "App URL must not contain spaces")
|
.required("Your application must have a url")
|
||||||
|
.matches(APP_URL_REGEX, "Please enter a valid url")
|
||||||
.test(
|
.test(
|
||||||
"non-existing-app-url",
|
"non-existing-app-url",
|
||||||
"Another app with the same URL already exists",
|
"Another app with the same URL already exists",
|
||||||
value => {
|
value => {
|
||||||
// url is nullable
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
Body,
|
Body,
|
||||||
Modal,
|
Modal,
|
||||||
Divider,
|
Divider,
|
||||||
|
Link,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||||
import TemplateDisplay from "components/common/TemplateDisplay.svelte"
|
import TemplateDisplay from "components/common/TemplateDisplay.svelte"
|
||||||
|
@ -60,14 +61,15 @@
|
||||||
<Page wide>
|
<Page wide>
|
||||||
<Layout noPadding gap="XL">
|
<Layout noPadding gap="XL">
|
||||||
<span>
|
<span>
|
||||||
<Button
|
<Link
|
||||||
primary
|
quiet
|
||||||
|
secondary
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
$goto("../")
|
$goto("../")
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Back
|
< Back
|
||||||
</Button>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="title">
|
<div class="title">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { Layout, Page, notifications, Button } from "@budibase/bbui"
|
import { Layout, Page, notifications, Link } from "@budibase/bbui"
|
||||||
import TemplateDisplay from "components/common/TemplateDisplay.svelte"
|
import TemplateDisplay from "components/common/TemplateDisplay.svelte"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { templates } from "stores/portal"
|
import { templates } from "stores/portal"
|
||||||
|
@ -25,14 +25,15 @@
|
||||||
<Page wide>
|
<Page wide>
|
||||||
<Layout noPadding gap="XL">
|
<Layout noPadding gap="XL">
|
||||||
<span>
|
<span>
|
||||||
<Button
|
<Link
|
||||||
primary
|
quiet
|
||||||
|
secondary
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
$goto("../")
|
$goto("../")
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Back
|
< Back
|
||||||
</Button>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
{#if loaded && $templates?.length}
|
{#if loaded && $templates?.length}
|
||||||
<TemplateDisplay templates={$templates} />
|
<TemplateDisplay templates={$templates} />
|
||||||
|
|
Loading…
Reference in New Issue