Updated approach to focus behaviour. Placeholder now updates to direct the user to the next required field they haven't entered

This commit is contained in:
Dean 2022-05-30 12:57:10 +01:00
parent b06235efc0
commit f1111fffca
15 changed files with 116 additions and 176 deletions

View File

@ -33,7 +33,7 @@
let focus = false
let pickerButton
$: focus = autofocus && pickerButton
$: focus = autofocus && pickerButton !== null
$: sortedOptions = getSortedOptions(options, getOptionLabel, sort)
$: filteredOptions = getFilteredOptions(
@ -88,6 +88,14 @@
class:is-focused={focus}
bind:this={pickerButton}
on:mousedown={onClick}
on:keydown={e => {
var keycode = e.key
if (focus) {
if (keycode === "Enter") {
onClick(e)
}
}
}}
on:focus={() => {
focus = true
}}

View File

@ -417,28 +417,12 @@ export const getFrontendStore = () => {
}
parentComponent._children.push(componentInstance)
const definition = store.actions.components.getDefinition(componentName)
// Save components and update UI
await store.actions.preview.saveSelected()
store.update(state => {
state.currentView = "component"
state.selectedComponentId = componentInstance._id
const focusSetting = definition.settings.filter(setting => {
return setting.required
})
const mappedSettings = focusSetting.map(setting => {
return {
key: setting.key,
target: state.selectedComponentId,
location: "component_settings",
}
})
if (focusSetting.length) {
state.builderFocus = mappedSettings
}
return state
})

View File

@ -6,6 +6,7 @@
import ResetFieldsButton from "./PropertyControls/ResetFieldsButton.svelte"
import { getComponentForSettingType } from "./PropertyControls/componentSettings"
import { Utils } from "@budibase/frontend-core"
import { onMount } from "svelte"
export let componentDefinition
export let componentInstance
@ -78,8 +79,41 @@
if (!$store.builderFocus) {
return false
}
return setting.required === true
return (
setting.required === true && $store.builderFocus[0].key === setting.key
)
}
onMount(() => {
const emptyFields = (definition, options) => {
if (!options) {
return []
}
return definition?.settings
? definition.settings.filter(setting => {
return (
setting.required &&
(!options[setting.key] || options[setting.key] == "")
)
})
: []
}
let target = emptyFields(componentDefinition, componentInstance)[0]
if (target) {
store.update(state => ({
...state,
builderFocus: [
{
location: "component_settings",
key: target.key,
target: componentInstance._id,
},
],
}))
}
})
</script>
{#each sections as section, idx (section.name)}

View File

@ -25,6 +25,7 @@
export let otherSources
export let showAllQueries
export let bindings = []
export let autofocus = false
const dispatch = createEventDispatcher()
const arrayTypes = ["attachment", "array"]
@ -158,6 +159,7 @@
value={text}
options={[text]}
on:click={dropdownRight.show}
{autofocus}
/>
{#if value?.type === "query"}
<i class="ri-settings-5-line" on:click={openQueryParamsDrawer} />

View File

@ -975,7 +975,8 @@
{
"type": "text",
"label": "URL",
"key": "url"
"key": "url",
"required": true
},
{
"type": "select",
@ -3255,7 +3256,8 @@
{
"type": "dataSource",
"label": "Data",
"key": "dataSource"
"key": "dataSource",
"required": true
},
{
"type": "filter",
@ -3324,7 +3326,7 @@
],
"hasChildren": true,
"showEmptyState": false,
"info": "Row selection is only compatible with internal or SQL tables",
"info": "Row selection is only compatible with internal or SQL tables",
"settings": [
{
"type": "dataProvider",

View File

@ -154,6 +154,7 @@
selected,
name,
editing,
type: instance._component,
})
const initialise = instance => {

View File

@ -28,25 +28,7 @@
class="placeholder"
use:styleable={{ ...$component.styles, empty: true }}
>
<Placeholder>
<div slot="content">
Add the <mark>URL</mark> and start updating your background image&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "url",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
</div>
{/if}

View File

@ -28,25 +28,7 @@
/>
{:else if $builderStore.inBuilder}
<div use:styleable={styles}>
<Placeholder>
<div slot="content">
Add the <mark>Icon</mark> in the settings menu&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "icon",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
</div>
{/if}

View File

@ -15,25 +15,7 @@
class="placeholder"
use:styleable={{ ...$component.styles, empty: true }}
>
<Placeholder>
<div slot="content">
Add the <mark>URL</mark> and start updating your image&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "url",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
</div>
{/if}

View File

@ -82,31 +82,7 @@
{:else if $builderStore.inBuilder || componentText}
{#if !url && !text}
<div use:styleable={{ ...$component.styles, empty: true }}>
<Placeholder>
<div slot="content">
Add the <mark>URL</mark> and <mark>Text</mark> settings and start
using your link&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "url",
target: $component.id,
},
{
location: "component_settings",
key: "text",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
</div>
{:else if externalLink || openInNewTab}
<a

View File

@ -14,25 +14,6 @@
{#if value}
<MarkdownViewer {value} {height} />
{:else if $builderStore.inBuilder}
<Placeholder>
<div slot="content">
Add some <mark>Markdown</mark> in the field setting to start using your
component&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "value",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
{/if}
</div>

View File

@ -1,18 +1,71 @@
<script>
import { getContext } from "svelte"
import Manifest from "manifest.json"
import { builderStore } from "stores"
const { builderStore } = getContext("sdk")
const { componentStore } = getContext("sdk")
const component = getContext("component")
export let text
$: componentInstance = componentStore.actions.getComponentById($component.id)
const getComponentKey = compId => {
if (!compId) {
return
}
const prefix = "@budibase/standard-components/"
let componentKey = compId.replace(prefix, "")
return componentKey
}
//Corify this somewhere
const emptyFields = (definition, options) => {
if (!options) {
return []
}
return definition?.settings
? definition.settings.filter(setting => {
return (
setting.required &&
(!options[setting.key] || options[setting.key] == "")
)
})
: []
}
const definition = Manifest[getComponentKey($component.type)]
$: focus_setting = emptyFields(definition, componentInstance)[0]
</script>
{#if $builderStore.inBuilder}
<div class="placeholder_wrap">
{#if !$$slots.content}
{#if componentInstance && focus_setting}
<div>
<span>
Add the <mark>{focus_setting?.label}</mark> setting to start using your
component &nbsp;
</span>
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: focus_setting.key,
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
{:else}
{text || $component.name || "Placeholder"}
<!-- {#if definition.hasChildren}
<span>: Add a component or two!</span>
{/if} -->
{/if}
<slot name="content" />
</div>
{/if}

View File

@ -39,7 +39,7 @@
}}
>
{#if $component.empty}
<Placeholder text={$component.name} />
<Placeholder />
{:else}
<BlockComponent
type="repeater"

View File

@ -13,35 +13,7 @@
<div use:chart={options} use:styleable={$component.styles} />
{:else if $builderStore.inBuilder}
<div use:styleable={$component.styles}>
<Placeholder>
<div slot="content">
Use the settings panel start building your chart&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "dataProvider",
target: $component.id,
},
{
location: "component_settings",
key: "valueColumns",
target: $component.id,
},
{
location: "component_settings",
key: "dataColumns",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
</div>
{/if}

View File

@ -77,26 +77,7 @@
<Placeholder text="Form components need to be wrapped in a form" />
{:else if !fieldState}
{#if $builderStore.inBuilder}
<Placeholder>
<div slot="content">
Add the <mark>Field</mark> setting to start using your
component&nbsp;
<span
class="showMe spectrum-Link"
on:click={() => {
builderStore.actions.setFocus([
{
location: "component_settings",
key: "field",
target: $component.id,
},
])
}}
>
Show me
</span>
</div>
</Placeholder>
<Placeholder />
{/if}
{:else if schemaType && schemaType !== type && type !== "options"}
<Placeholder