new auto screen ux
This commit is contained in:
parent
969d2f5377
commit
1a265149e2
|
@ -2,6 +2,7 @@ import { Screen } from "./utils/Screen"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: `Create from scratch`,
|
name: `Create from scratch`,
|
||||||
|
id: `createFromScratch`,
|
||||||
create: () => createScreen(),
|
create: () => createScreen(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
]
|
]
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
|
let navSelectionModal
|
||||||
$: selected = tabs.find(t => t.key === $params.assetType)?.title || "Screens"
|
$: selected = tabs.find(t => t.key === $params.assetType)?.title || "Screens"
|
||||||
|
|
||||||
const navigate = ({ detail }) => {
|
const navigate = ({ detail }) => {
|
||||||
|
@ -85,9 +86,9 @@
|
||||||
<div class="nav-items-container">
|
<div class="nav-items-container">
|
||||||
<ComponentNavigationTree />
|
<ComponentNavigationTree />
|
||||||
</div>
|
</div>
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}
|
||||||
<NewScreenModal />
|
><svelte:component this={NewScreenModal} {navSelectionModal} /></Modal
|
||||||
</Modal>
|
>
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Layouts">
|
<Tab title="Layouts">
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<script>
|
||||||
|
import { ModalContent, Body, Detail } from "@budibase/bbui"
|
||||||
|
|
||||||
|
let selectedNav
|
||||||
|
export let navSelectionModal
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ModalContent
|
||||||
|
title="Select navigation"
|
||||||
|
cancelText="Back"
|
||||||
|
onCancel={() => navSelectionModal.show()}
|
||||||
|
size="M"
|
||||||
|
disabled={!selectedNav}
|
||||||
|
>
|
||||||
|
<Body size="S"
|
||||||
|
>Please select your preferred layout for the new application:</Body
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<div
|
||||||
|
on:click={() => (selectedNav = "sideNav")}
|
||||||
|
class:unselected={selectedNav && selectedNav !== "sideNav"}
|
||||||
|
>
|
||||||
|
<div class="box">
|
||||||
|
<div class="side-nav" />
|
||||||
|
</div>
|
||||||
|
<div><Detail>Side Nav</Detail></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
on:click={() => (selectedNav = "topNav")}
|
||||||
|
class:unselected={selectedNav && selectedNav !== "topNav"}
|
||||||
|
>
|
||||||
|
<div class="box">
|
||||||
|
<div class="top-nav" />
|
||||||
|
</div>
|
||||||
|
<div><Detail>Top Nav</Detail></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
on:click={() => (selectedNav = "noNav")}
|
||||||
|
class:unselected={selectedNav && selectedNav !== "noNav"}
|
||||||
|
>
|
||||||
|
<div class="box" />
|
||||||
|
<div><Detail>No Nav</Detail></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalContent>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.side-nav {
|
||||||
|
float: left;
|
||||||
|
background: #d3d3d3 0% 0% no-repeat padding-box;
|
||||||
|
border-radius: 2px 0px 0px 2px;
|
||||||
|
height: 100%;
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav {
|
||||||
|
background: #d3d3d3 0% 0% no-repeat padding-box;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 100%;
|
||||||
|
height: 15%;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
display: inline-block;
|
||||||
|
background: #eaeaea 0% 0% no-repeat padding-box;
|
||||||
|
border: 1px solid #d3d3d3;
|
||||||
|
border-radius: 2px;
|
||||||
|
opacity: 1;
|
||||||
|
width: 120px;
|
||||||
|
height: 70px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
padding-top: 4%;
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
.unselected {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,21 +1,20 @@
|
||||||
<script>
|
<script>
|
||||||
import { store, allScreens, selectedAccessRole } from "builderStore"
|
import { store, allScreens } from "builderStore"
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import { roles } from "stores/backend"
|
import { ModalContent, Body, Detail, Layout, Icon } from "@budibase/bbui"
|
||||||
import { Input, Select, ModalContent, Toggle } from "@budibase/bbui"
|
|
||||||
import getTemplates from "builderStore/store/screenTemplates"
|
import getTemplates from "builderStore/store/screenTemplates"
|
||||||
import analytics, { Events } from "analytics"
|
|
||||||
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
|
||||||
|
|
||||||
const CONTAINER = "@budibase/standard-components/container"
|
const CONTAINER = "@budibase/standard-components/container"
|
||||||
|
const blankScreen = "createFromScratch"
|
||||||
|
let selectedScreens = []
|
||||||
|
let navigationSelectionModal
|
||||||
let name = ""
|
let name = ""
|
||||||
let routeError
|
|
||||||
let baseComponent = CONTAINER
|
let baseComponent = CONTAINER
|
||||||
let templateIndex
|
let templateIndex
|
||||||
let draftScreen
|
let draftScreen
|
||||||
let createLink = true
|
|
||||||
let roleId = $selectedAccessRole || "BASIC"
|
$: blankSelected = selectedScreens.includes(blankScreen)
|
||||||
|
$: autoSelected = selectedScreens.length > 0 && !blankSelected
|
||||||
|
|
||||||
$: templates = getTemplates($store, $tables.list)
|
$: templates = getTemplates($store, $tables.list)
|
||||||
$: route = !route && $allScreens.length === 0 ? "*" : route
|
$: route = !route && $allScreens.length === 0 ? "*" : route
|
||||||
|
@ -42,6 +41,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
if (!route) {
|
if (!route) {
|
||||||
routeError = "URL is required"
|
routeError = "URL is required"
|
||||||
|
@ -72,46 +72,99 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
const routeExists = (route, roleId) => {
|
const toggleScreenSelection = template => {
|
||||||
return $allScreens.some(
|
if (selectedScreens.includes(template.id)) {
|
||||||
screen =>
|
selectedScreens = selectedScreens.filter(screen => screen !== template.id)
|
||||||
screen.routing.route.toLowerCase() === route.toLowerCase() &&
|
} else {
|
||||||
screen.routing.roleId === roleId
|
selectedScreens = [template.id, ...selectedScreens]
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const routeChanged = event => {
|
|
||||||
if (!event.detail.startsWith("/")) {
|
|
||||||
route = "/" + event.detail
|
|
||||||
}
|
}
|
||||||
route = sanitizeUrl(route)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent title="New Screen" confirmText="Create Screen" onConfirm={save}>
|
<ModalContent
|
||||||
<Select
|
title="Add screens"
|
||||||
label="Choose a Template"
|
confirmText="Add Screens"
|
||||||
bind:value={templateIndex}
|
cancelText="Cancel"
|
||||||
on:change={ev => templateChanged(ev.detail)}
|
onConfirm={() => navigationSelectionModal.show()}
|
||||||
options={templates}
|
disabled={!selectedScreens.length}
|
||||||
placeholder={null}
|
size="L"
|
||||||
getOptionLabel={x => x.name}
|
>
|
||||||
getOptionValue={(x, idx) => idx}
|
<Body size="XS"
|
||||||
/>
|
>Please select the screens you would like to add to your application.
|
||||||
<Input label="Name" bind:value={name} />
|
Autogenerated screens come with CRUD functionality.</Body
|
||||||
<Input
|
>
|
||||||
label="Url"
|
|
||||||
error={routeError}
|
<Layout noPadding>
|
||||||
bind:value={route}
|
<Detail size="S">Blank screen</Detail>
|
||||||
on:change={routeChanged}
|
<div
|
||||||
/>
|
class="item"
|
||||||
<Select
|
class:selected={selectedScreens.includes(blankScreen)}
|
||||||
label="Access"
|
on:click={() => toggleScreenSelection({ id: blankScreen })}
|
||||||
bind:value={roleId}
|
class:disabled={autoSelected}
|
||||||
options={$roles}
|
>
|
||||||
getOptionLabel={x => x.name}
|
<div class="content">
|
||||||
getOptionValue={x => x._id}
|
<Body size="S">Blank</Body>
|
||||||
/>
|
</div>
|
||||||
<Toggle text="Create link in navigation bar" bind:value={createLink} />
|
<div style="color: var(--spectrum-global-color-green-600); float: right">
|
||||||
|
{#if selectedScreens.includes(blankScreen)}
|
||||||
|
<Icon size="S" name="CheckmarkCircleOutline" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Detail size="S">Autogenerated Screens</Detail>
|
||||||
|
|
||||||
|
{#each templates.filter(x => x.id !== blankScreen) as template}
|
||||||
|
<div
|
||||||
|
class:disabled={blankSelected}
|
||||||
|
class:selected={selectedScreens.includes(template.id)}
|
||||||
|
on:click={() => toggleScreenSelection(template)}
|
||||||
|
class="item"
|
||||||
|
>
|
||||||
|
<div class="content">
|
||||||
|
{template.name}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="color: var(--spectrum-global-color-green-600); float: right"
|
||||||
|
>
|
||||||
|
{#if selectedScreens.includes(template.id)}
|
||||||
|
<Icon size="S" name="CheckmarkCircleOutline" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</Layout>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding-left: 10px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
cursor: pointer;
|
||||||
|
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
|
||||||
|
padding: var(--spectrum-alias-item-padding-s);
|
||||||
|
background: var(--background);
|
||||||
|
transition: 0.3s all;
|
||||||
|
border: solid var(--spectrum-alias-border-color);
|
||||||
|
border-radius: 2px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-width: 1px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover,
|
||||||
|
.selected {
|
||||||
|
background: var(--spectrum-alias-background-color-tertiary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue