screen templates - backup before merge from master

This commit is contained in:
Michael Shanks 2020-10-08 15:46:29 +01:00
parent f6d2e48dcc
commit a3bd28d99f
12 changed files with 120 additions and 290 deletions

View File

@ -153,35 +153,13 @@ const _saveScreen = async (store, s, screen) => {
return s return s
} }
const createScreen = store => ({ const createScreen = store => screen => {
screenName,
route,
baseComponent,
screen,
}) => {
store.update(state => { store.update(state => {
const rootComponent = state.currentPreviewItem = screen
state.components[ state.currentComponentInfo = screen.props
baseComponent || "@budibase/standard-components/container"
]
const newScreen = screen || {
description: "",
url: "",
_css: "",
props: createProps(rootComponent).props,
route,
}
newScreen.name = newScreen.props._id
if (screenName) {
newScreen.props._instanceName = screenName
}
state.currentPreviewItem = newScreen
state.currentComponentInfo = newScreen.props
state.currentFrontEndType = "screen" state.currentFrontEndType = "screen"
_saveScreen(store, state, newScreen) _saveScreen(store, state, screen)
return state return state
}) })

View File

@ -0,0 +1,22 @@
export default {
name: `Create from Scratch`,
create: () => createScreen(),
}
const createScreen = () => ({
props: {
_id: "",
_component: "@budibase/standard-components/container",
_styles: {
normal: {},
hover: {},
active: {},
selected: {},
},
type: "div",
_children: [],
_instanceName: "",
},
route: "",
name: "screen-id",
})

View File

@ -0,0 +1,22 @@
export default {
name: `New Record (Empty)`,
create: () => createScreen(),
}
const createScreen = () => ({
props: {
_id: "",
_component: "@budibase/standard-components/recorddetail",
_styles: {
normal: {},
hover: {},
active: {},
selected: {},
},
_children: [],
_instanceName: "",
model: "",
},
route: "",
name: "screen-id",
})

View File

@ -0,0 +1,22 @@
export default {
name: `Record Detail (Empty)`,
create: () => createScreen(),
}
const createScreen = () => ({
props: {
_id: "",
_component: "@budibase/standard-components/recorddetail",
_styles: {
normal: {},
hover: {},
active: {},
selected: {},
},
_children: [],
_instanceName: "",
model: "",
},
route: "",
name: "screen-id",
})

View File

@ -1,11 +1,17 @@
import newRecordScreen from "./newRecordScreen" import newRecordScreen from "./newRecordScreen"
import recordDetailScreen from "./recordDetailScreen" import recordDetailScreen from "./recordDetailScreen"
import emptyNewRecordScreen from "./emptyNewRecordScreen"
import emptyContainerScreen from "./emptyContainerScreen"
import emptyRecordDetailScreen from "./emptyRecordDetailScreen"
import { generateNewIdsForComponent } from "../../storeUtils" import { generateNewIdsForComponent } from "../../storeUtils"
import { uuid } from "builderStore/uuid" import { uuid } from "builderStore/uuid"
const allTemplates = models => [ const allTemplates = models => [
emptyContainerScreen,
...newRecordScreen(models), ...newRecordScreen(models),
emptyNewRecordScreen,
...recordDetailScreen(models), ...recordDetailScreen(models),
emptyRecordDetailScreen,
] ]
// allows us to apply common behaviour to all create() functions // allows us to apply common behaviour to all create() functions

View File

@ -1,6 +1,6 @@
export default function(models) { export default function(models) {
return models.map(model => ({ return models.map(model => ({
name: `New ${model.name}`, name: `New Record - ${model.name}`,
create: () => createScreen(model), create: () => createScreen(model),
})) }))
} }
@ -8,16 +8,14 @@ export default function(models) {
const createScreen = model => ({ const createScreen = model => ({
props: { props: {
_id: "f684460e-1f79-42b4-8ffd-1f708bca93ed", _id: "f684460e-1f79-42b4-8ffd-1f708bca93ed",
_component: "@budibase/standard-components/container", _component: "@budibase/standard-components/newrecord",
_styles: { _styles: {
normal: {}, normal: {},
hover: {}, hover: {},
active: {}, active: {},
selected: {}, selected: {},
}, },
className: "", model: model._id,
onLoad: [],
type: "div",
_children: [ _children: [
{ {
_id: "7d1d6b43-b444-46a5-a75c-267fd6b5baf6", _id: "7d1d6b43-b444-46a5-a75c-267fd6b5baf6",

View File

@ -1,6 +1,6 @@
export default function(models) { export default function(models) {
return models.map(model => ({ return models.map(model => ({
name: `New ${model.name}`, name: `Record Detail - ${model.name}`,
create: () => createScreen(model), create: () => createScreen(model),
})) }))
} }
@ -15,9 +15,7 @@ const createScreen = model => ({
active: {}, active: {},
selected: {}, selected: {},
}, },
className: "", model: model._id,
onLoad: [],
type: "div",
_children: [ _children: [
{ {
_id: "7d1d6b43-b444-46a5-a75c-267fd6b5baf6", _id: "7d1d6b43-b444-46a5-a75c-267fd6b5baf6",
@ -39,6 +37,6 @@ const createScreen = model => ({
], ],
_instanceName: `${model.name} Detail`, _instanceName: `${model.name} Detail`,
}, },
route: `/${model.name}/new`, route: `/${model.name}/:id`,
name: "screen-id", name: "screen-id",
}) })

View File

@ -1,62 +0,0 @@
<script>
import { store, backendUiStore } from "builderStore"
import { Input, Select, Button, Spacer } from "@budibase/bbui"
import getTemplates from "builderStore/store/screenTemplates"
import { createEventDispatcher } from "svelte"
const dispatch = createEventDispatcher()
let screens
let template
$: templates = getTemplates($store, $backendUiStore.models)
const save = () => {
if (!template) return
if (template === "none") {
dispatch("next")
return
}
store.createScreen({
screen: template.create(),
})
dispatch("finished")
}
const cancel = () => {
dispatch("finished")
}
</script>
<div data-cy="new-screen-dialog">
<div class="bb-margin-xl">
<label>Choose a Template</label>
<Select bind:value={template} secondary>
<option value="">Choose an Option</option>
<option value="none">No Template</option>
{#if templates}
{#each templates as template}
<option value={template}>{template.name}</option>
{/each}
{/if}
</Select>
</div>
</div>
<Spacer extraLarge />
<div data-cy="create-screen-footer" class="modal-footer">
<Button secondary medium on:click={cancel}>Cancel</Button>
<Button blue medium on:click={save} disabled={!template}>
{template === 'none' ? 'Next' : 'Create Screen'}
</Button>
</div>
<style>
.modal-footer {
display: flex;
justify-content: space-between;
}
</style>

View File

@ -1,50 +0,0 @@
<script>
import { store } from "builderStore"
import { Modal, Spacer } from "@budibase/bbui"
import ChooseTemplate from "./ChooseTemplate.svelte"
import NoTemplate from "./NoTemplate.svelte"
import { slide, fade } from "svelte/transition"
export const show = () => {
dialog.show()
}
const finished = () => {
dialog.hide()
template = undefined
}
let dialog
let template
</script>
<Modal bind:this={dialog} minWidth="500px">
<h2>New Screen</h2>
<Spacer extraLarge />
{#if template === 'none'}
<div transition:slide={{ delay: 0, duration: 300 }}>
<NoTemplate on:finished={finished} />
</div>
{:else}
<div transition:fade={{ delay: 0, duration: 100 }}>
<ChooseTemplate
on:finished={finished}
on:next={() => (template = 'none')} />
</div>
{/if}
</Modal>
<style>
h2 {
font-size: var(--font-size-xl);
margin: 0;
font-family: var(--font-sans);
font-weight: 600;
}
.modal-footer {
display: flex;
justify-content: space-between;
}
</style>

View File

@ -1,6 +1,7 @@
<script> <script>
import { store, backendUiStore } from "builderStore" import { store, backendUiStore } from "builderStore"
import { Input, Button, Spacer, Select, Modal } from "@budibase/bbui" import { Input, Button, Spacer, Select, Modal } from "@budibase/bbui"
import getTemplates from "builderStore/store/screenTemplates"
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import { some } from "lodash/fp" import { some } from "lodash/fp"
@ -11,17 +12,13 @@
dialog.show() dialog.show()
} }
const finished = () => {
dialog.hide()
template = undefined
}
let screens let screens
let name = "" let name = ""
let routeError let routeError
let baseComponent = CONTAINER let baseComponent = CONTAINER
let dialog let dialog
let template let templateIndex = 0
let draftScreen
$: templates = getTemplates($store, $backendUiStore.models) $: templates = getTemplates($store, $backendUiStore.models)
@ -31,6 +28,24 @@
.filter(componentDefinition => componentDefinition.baseComponent) .filter(componentDefinition => componentDefinition.baseComponent)
.map(c => c._component) .map(c => c._component)
const templateChanged = ev => {
const newTemplateIndex = ev.target.value
if (!newTemplateIndex) return
draftScreen = templates[newTemplateIndex].create()
if (draftScreen.props._instanceName) {
name = draftScreen.props._instanceName
}
if (draftScreen.props._component) {
baseComponent = draftScreen.props._component
}
if (draftScreen.route) {
route = draftScreen.route
}
}
const save = () => { const save = () => {
if (!route) { if (!route) {
routeError = "Url is required" routeError = "Url is required"
@ -44,20 +59,21 @@
if (routeError) return false if (routeError) return false
store.createScreen({ draftScreen.props._instanceName = name
screenName: name, draftScreen.props._component = baseComponent
route, draftScreen.route = route
baseComponent,
})
store.createScreen(draftScreen)
finished()
}
const finished = () => {
templateIndex = 0
name = "" name = ""
route = "" route = ""
baseComponent = CONTAINER baseComponent = CONTAINER
dispatch("finished") dialog.hide()
}
const cancel = () => {
dispatch("finished")
} }
const routeNameExists = route => { const routeNameExists = route => {
@ -90,12 +106,10 @@
<div class="bb-margin-xl"> <div class="bb-margin-xl">
<label>Choose a Template</label> <label>Choose a Template</label>
<Select bind:value={template} secondary> <Select bind:value={templateIndex} secondary on:change={templateChanged}>
<option value="">Choose an Option</option>
<option value="none">No Template</option>
{#if templates} {#if templates}
{#each templates as template} {#each templates as template, index}
<option value={template}>{template.name}</option> <option value={index}>{template.name}</option>
{/each} {/each}
{/if} {/if}
</Select> </Select>
@ -127,7 +141,7 @@
<Spacer extraLarge /> <Spacer extraLarge />
<div data-cy="create-screen-footer" class="modal-footer"> <div data-cy="create-screen-footer" class="modal-footer">
<Button secondary medium on:click={cancel}>Cancel</Button> <Button secondary medium on:click={finished}>Cancel</Button>
<Button blue medium on:click={save}>Create Screen</Button> <Button blue medium on:click={save}>Create Screen</Button>
</div> </div>

View File

@ -1,118 +0,0 @@
<script>
import { store } from "builderStore"
import { Input, Button, Spacer, Select } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import { some } from "lodash/fp"
const dispatch = createEventDispatcher()
const CONTAINER = "@budibase/standard-components/container"
let screens
let name = ""
let routeError
let baseComponent = CONTAINER
$: route = !route && $store.screens.length === 0 ? "*" : route
$: baseComponents = Object.values($store.components)
.filter(componentDefinition => componentDefinition.baseComponent)
.map(c => c._component)
const save = () => {
if (!route) {
routeError = "Url is required"
} else {
if (routeNameExists(route)) {
routeError = "This url is already taken"
} else {
routeError = ""
}
}
if (routeError) return false
store.createScreen({
screenName: name,
route,
baseComponent,
})
name = ""
route = ""
baseComponent = CONTAINER
dispatch("finished")
}
const cancel = () => {
dispatch("finished")
}
const routeNameExists = route => {
return $store.screens.some(
screen => screen.route.toLowerCase() === route.toLowerCase()
)
}
const routeChanged = event => {
if (!event.target.value.startsWith("/")) {
route = "/" + event.target.value
}
}
const componentShortName = fullname => {
const parts = fullname.split("/")
const shortName = parts[parts.length - 1]
// make known ones a bit prettier
if (shortName === "container") return "Container"
if (shortName === "recorddetail") return "Record Detail"
if (shortName === "newrecord") return "New Record"
return shortName
}
</script>
<Spacer extraLarge />
<div data-cy="new-screen-dialog">
<div class="bb-margin-xl">
<Input label="Name" bind:value={name} />
</div>
<div class="bb-margin-xl">
<Input
label="Url"
error={routeError}
bind:value={route}
on:change={routeChanged} />
</div>
<div class="bb-margin-xl">
<label>Screen Type</label>
<Select bind:value={baseComponent} secondary>
{#each baseComponents as component}
<option value={component}>{componentShortName(component)}</option>
{/each}
</Select>
</div>
</div>
<Spacer extraLarge />
<div data-cy="create-screen-footer" class="modal-footer">
<Button secondary medium on:click={cancel}>Cancel</Button>
<Button blue medium on:click={save}>Create Screen</Button>
</div>
<style>
h2 {
font-size: var(--font-size-xl);
margin: 0;
font-family: var(--font-sans);
font-weight: 600;
}
.modal-footer {
display: flex;
justify-content: space-between;
}
</style>

View File

@ -3,7 +3,7 @@
import ComponentsHierarchy from "components/userInterface/ComponentsHierarchy.svelte" import ComponentsHierarchy from "components/userInterface/ComponentsHierarchy.svelte"
import PageLayout from "components/userInterface/PageLayout.svelte" import PageLayout from "components/userInterface/PageLayout.svelte"
import PagesList from "components/userInterface/PagesList.svelte" import PagesList from "components/userInterface/PagesList.svelte"
import CreateScreen from "components/userInterface/CreateScreen/CreateScreen.svelte" import NewScreen from "components/userInterface/CreateScreen/NewScreen.svelte"
const newScreen = () => { const newScreen = () => {
newScreenPicker.show() newScreenPicker.show()
@ -22,7 +22,7 @@
<ComponentsHierarchy screens={$store.screens} /> <ComponentsHierarchy screens={$store.screens} />
</div> </div>
<CreateScreen bind:this={newScreenPicker} /> <NewScreen bind:this={newScreenPicker} />
<style> <style>
.newscreen { .newscreen {