Add complete generation popover with both automation and screen generation

This commit is contained in:
Andrew Kingston 2024-08-23 12:00:19 +01:00
parent 495c01c1a2
commit bf998f6e6c
No known key found for this signature in database
7 changed files with 135 additions and 66 deletions

View File

@ -6,11 +6,18 @@
export let title = null export let title = null
export let subtitle = null export let subtitle = null
export let url = null export let url = null
export let hoverable = false
export let showArrow = false
</script> </script>
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<a href={url} class="list-item" class:hoverable={url != null} on:click> <a
href={url}
class="list-item"
class:hoverable={hoverable || url != null}
on:click
>
<div class="left"> <div class="left">
{#if icon} {#if icon}
<Icon name={icon} color={iconColor} /> <Icon name={icon} color={iconColor} />
@ -30,7 +37,9 @@
</div> </div>
<div class="right"> <div class="right">
<slot name="right" /> <slot name="right" />
<Icon name="ChevronRight" /> {#if showArrow}
<Icon name="ChevronRight" />
{/if}
</div> </div>
</a> </a>

View File

@ -34,7 +34,7 @@
const generateAutomation = () => { const generateAutomation = () => {
popover?.hide() popover?.hide()
dispatch("generate-automation") dispatch("request-generate")
} }
</script> </script>
@ -62,6 +62,7 @@
: "var(--spectrum-global-color-green-600)"} : "var(--spectrum-global-color-green-600)"}
title={automation.name} title={automation.name}
url={`/builder/app/${$appStore.appId}/automation/${automation._id}`} url={`/builder/app/${$appStore.appId}/automation/${automation._id}`}
showArrow
/> />
{/each} {/each}
</List> </List>

View File

@ -1,5 +1,5 @@
<script> <script>
import { ActionButton, Menu, MenuItem, notifications } from "@budibase/bbui" import { ActionButton, ListItem, notifications } from "@budibase/bbui"
import { getContext } from "svelte" import { getContext } from "svelte"
import { import {
automationStore, automationStore,
@ -13,12 +13,12 @@
import MagicWand from "./magic-wand.svg" import MagicWand from "./magic-wand.svg"
import { AutoScreenTypes } from "constants" import { AutoScreenTypes } from "constants"
import CreateScreenModal from "pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte" import CreateScreenModal from "pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte"
import { getSequentialName } from "helpers/duplicate"
const { datasource } = getContext("grid") const { datasource } = getContext("grid")
let popover let popover
let createScreenModal let createScreenModal
let isCreatingScreen
$: triggers = $automationStore.blockDefinitions.CREATABLE_TRIGGER $: triggers = $automationStore.blockDefinitions.CREATABLE_TRIGGER
$: table = $tables.list.find(table => table._id === $datasource.tableId) $: table = $tables.list.find(table => table._id === $datasource.tableId)
@ -39,9 +39,19 @@
return return
} }
const automationName = `${table.name} : Row ${ const suffixMap = {
type === TriggerStepID.ROW_SAVED ? "created" : "updated" [TriggerStepID.ROW_SAVED]: "created",
}` [TriggerStepID.ROW_UPDATED]: "updated",
[TriggerStepID.ROW_DELETED]: "deleted",
}
const namePrefix = `Row ${suffixMap[type]} `
const automationName = getSequentialName(
$automationStore.automations,
namePrefix,
{
getName: x => x.name,
}
)
const triggerBlock = automationStore.actions.constructBlock( const triggerBlock = automationStore.actions.constructBlock(
"TRIGGER", "TRIGGER",
triggerType.stepId, triggerType.stepId,
@ -59,10 +69,10 @@
"/builder/app/:application/data", "/builder/app/:application/data",
window.location.pathname window.location.pathname
) )
$goto(`/builder/app/${response.appId}/automation/${response.id}`) $goto(`/builder/app/${response.appId}/automation/${response._id}`)
notifications.success(`Automation created`) notifications.success(`Automation created successfully`)
} catch (e) { } catch (e) {
console.error("Error creating automation", e) console.error(e)
notifications.error("Error creating automation") notifications.error("Error creating automation")
} }
} }
@ -79,7 +89,7 @@
} }
</script> </script>
<DetailPopover title="Generate" bind:this={popover}> <DetailPopover title="Generate" bind:this={popover} minWidth={400}>
<svelte:fragment slot="anchor" let:open> <svelte:fragment slot="anchor" let:open>
<ActionButton selected={open}> <ActionButton selected={open}>
<div class="center"> <div class="center">
@ -88,60 +98,94 @@
</div> </div>
</ActionButton> </ActionButton>
</svelte:fragment> </svelte:fragment>
<div class="menu">
<Menu> {#if $datasource.type === "table"}
<MenuItem Generate a new app screen or automation from this data.
icon="ShareAndroid" {:else}
on:click={() => { Generate a new app screen from this data.
open = false {/if}
createAutomation(TriggerStepID.ROW_SAVED)
}} <div class="generate-section">
> <div class="generate-section__title">App screens</div>
Automation: when row is created <div class="generate-section__options">
</MenuItem> <div>
<MenuItem <ListItem
icon="ShareAndroid" title="CRUD app"
on:click={() => { icon="TableEdit"
open = false hoverable
createAutomation(TriggerStepID.ROW_UPDATED) on:click={() => startScreenWizard(AutoScreenTypes.TABLE)}
}} iconColor="var(--spectrum-global-color-gray-600)"
> />
Automation: when row is updated </div>
</MenuItem> <div>
<MenuItem <ListItem
icon="WebPage" title="Form"
on:click={() => { icon="Form"
open = false hoverable
startScreenWizard(AutoScreenTypes.TABLE) on:click={() => startScreenWizard(AutoScreenTypes.FORM)}
}} iconColor="var(--spectrum-global-color-gray-600)"
> />
CRUD app </div>
</MenuItem> </div>
<MenuItem
icon="WebPage"
on:click={() => {
open = false
startScreenWizard(AutoScreenTypes.FORM)
}}
>
Form
</MenuItem>
</Menu>
</div> </div>
{#if $datasource.type === "table"}
<div class="generate-section">
<div class="generate-section__title">Automation triggers (When a...)</div>
<div class="generate-section__options">
<div>
<ListItem
title="Row is created"
icon="TableRowAddBottom"
hoverable
on:click={() => createAutomation(TriggerStepID.ROW_SAVED)}
iconColor="var(--spectrum-global-color-gray-600)"
/>
</div>
<div>
<ListItem
title="Row is updated"
icon="Refresh"
hoverable
on:click={() => createAutomation(TriggerStepID.ROW_UPDATED)}
iconColor="var(--spectrum-global-color-gray-600)"
/>
</div>
<div>
<ListItem
title="Row is deleted"
icon="TableRowRemoveCenter"
hoverable
on:click={() => createAutomation(TriggerStepID.ROW_DELETED)}
iconColor="var(--spectrum-global-color-gray-600)"
/>
</div>
</div>
</div>
{/if}
</DetailPopover> </DetailPopover>
<CreateScreenModal bind:this={createScreenModal} /> <CreateScreenModal bind:this={createScreenModal} />
<style> <style>
.menu {
margin: 0 calc(-1 * var(--spacing-xl));
display: flex;
flex-direction: column;
align-items: stretch;
}
.center { .center {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
} }
.generate-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.generate-section__title {
color: var(--spectrum-global-color-gray-600);
}
.generate-section__options {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 16px;
grid-row-gap: 8px;
}
</style> </style>

View File

@ -83,7 +83,7 @@
{:else} {:else}
<List> <List>
{#each rowActions as action} {#each rowActions as action}
<ListItem title={action.name} url={$rowActionUrl(action)}> <ListItem title={action.name} url={$rowActionUrl(action)} showArrow>
<svelte:fragment slot="right"> <svelte:fragment slot="right">
{#if isView} {#if isView}
<span> <span>

View File

@ -1,10 +1,13 @@
<script> <script>
import { ActionButton, List, ListItem } from "@budibase/bbui" import { ActionButton, List, ListItem, Button } from "@budibase/bbui"
import DetailPopover from "components/common/DetailPopover.svelte" import DetailPopover from "components/common/DetailPopover.svelte"
import { screenStore, appStore } from "stores/builder" import { screenStore, appStore } from "stores/builder"
import { getContext } from "svelte" import { getContext, createEventDispatcher } from "svelte"
const { datasource } = getContext("grid") const { datasource } = getContext("grid")
const dispatch = createEventDispatcher()
let popover
$: ds = $datasource $: ds = $datasource
$: resourceId = ds?.type === "table" ? ds.tableId : ds?.id $: resourceId = ds?.type === "table" ? ds.tableId : ds?.id
@ -16,9 +19,14 @@
return JSON.stringify(screen).includes(`"${resourceId}"`) return JSON.stringify(screen).includes(`"${resourceId}"`)
}) })
} }
const generateScreen = () => {
popover?.hide()
dispatch("request-generate")
}
</script> </script>
<DetailPopover title="Screens" minWidth={400}> <DetailPopover title="Screens" minWidth={400} bind:this={popover}>
<svelte:fragment slot="anchor" let:open> <svelte:fragment slot="anchor" let:open>
<ActionButton <ActionButton
icon="WebPage" icon="WebPage"
@ -38,8 +46,14 @@
<ListItem <ListItem
title={screen.routing.route} title={screen.routing.route}
url={`/builder/app/${$appStore.appId}/design/${screen._id}`} url={`/builder/app/${$appStore.appId}/design/${screen._id}`}
showArrow
/> />
{/each} {/each}
</List> </List>
{/if} {/if}
<div>
<Button secondary icon="WebPage" on:click={generateScreen}>
Generate app screen
</Button>
</div>
</DetailPopover> </DetailPopover>

View File

@ -12,7 +12,8 @@
import GridGenerateButton from "components/backend/DataTable/buttons/grid/GridGenerateButton.svelte" import GridGenerateButton from "components/backend/DataTable/buttons/grid/GridGenerateButton.svelte"
import GridScreensButton from "components/backend/DataTable/buttons/grid/GridScreensButton.svelte" import GridScreensButton from "components/backend/DataTable/buttons/grid/GridScreensButton.svelte"
import GridRowActionsButton from "components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte" import GridRowActionsButton from "components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte"
import GridAutomationsButton from "components/backend/DataTable/buttons/grid/GridAutomationsButton.svelte"
let generateButton
$: id = $viewsV2.selected?.id $: id = $viewsV2.selected?.id
$: datasource = { $: datasource = {
@ -43,10 +44,10 @@
<GridColumnsSettingButton /> <GridColumnsSettingButton />
<GridManageAccessButton /> <GridManageAccessButton />
<GridRowActionsButton /> <GridRowActionsButton />
<GridScreensButton /> <GridScreensButton on:request-generate={() => generateButton?.show()} />
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="controls-right"> <svelte:fragment slot="controls-right">
<GridGenerateButton /> <GridGenerateButton bind:this={generateButton} />
</svelte:fragment> </svelte:fragment>
<GridCreateEditRowModal /> <GridCreateEditRowModal />
</Grid> </Grid>

View File

@ -120,9 +120,9 @@
<GridRowActionsButton /> <GridRowActionsButton />
{/if} {/if}
<GridAutomationsButton <GridAutomationsButton
on:generate-automation={() => generateButton?.show()} on:request-generate={() => generateButton?.show()}
/> />
<GridScreensButton /> <GridScreensButton on:request-generate={() => generateButton?.show()} />
{#if !isUsersTable} {#if !isUsersTable}
<GridImportButton /> <GridImportButton />
{/if} {/if}