Allow generating screens from the data section

This commit is contained in:
Andrew Kingston 2024-08-23 11:19:56 +01:00
parent a29cd7fefc
commit 495c01c1a2
No known key found for this signature in database
6 changed files with 103 additions and 41 deletions

View File

@ -1,15 +1,24 @@
<script> <script>
import { ActionButton, Menu, MenuItem, notifications } from "@budibase/bbui" import { ActionButton, Menu, MenuItem, notifications } from "@budibase/bbui"
import { getContext } from "svelte" import { getContext } from "svelte"
import { automationStore, tables, builderStore } from "stores/builder" import {
automationStore,
tables,
builderStore,
viewsV2,
} from "stores/builder"
import { TriggerStepID } from "constants/backend/automations" import { TriggerStepID } from "constants/backend/automations"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import DetailPopover from "components/common/DetailPopover.svelte" import DetailPopover from "components/common/DetailPopover.svelte"
import MagicWand from "./magic-wand.svg" import MagicWand from "./magic-wand.svg"
import { AutoScreenTypes } from "constants"
import CreateScreenModal from "pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte"
const { datasource } = getContext("grid") const { datasource } = getContext("grid")
let popover let popover
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)
@ -57,6 +66,17 @@
notifications.error("Error creating automation") notifications.error("Error creating automation")
} }
} }
const startScreenWizard = autoScreenType => {
popover.hide()
let preSelected
if ($datasource.type === "table") {
preSelected = $tables.list.find(x => x._id === $datasource.tableId)
} else {
preSelected = $viewsV2.list.find(x => x.id === $datasource.id)
}
createScreenModal.show(autoScreenType, preSelected)
}
</script> </script>
<DetailPopover title="Generate" bind:this={popover}> <DetailPopover title="Generate" bind:this={popover}>
@ -88,10 +108,30 @@
> >
Automation: when row is updated Automation: when row is updated
</MenuItem> </MenuItem>
<MenuItem
icon="WebPage"
on:click={() => {
open = false
startScreenWizard(AutoScreenTypes.TABLE)
}}
>
CRUD app
</MenuItem>
<MenuItem
icon="WebPage"
on:click={() => {
open = false
startScreenWizard(AutoScreenTypes.FORM)
}}
>
Form
</MenuItem>
</Menu> </Menu>
</div> </div>
</DetailPopover> </DetailPopover>
<CreateScreenModal bind:this={createScreenModal} />
<style> <style>
.menu { .menu {
margin: 0 calc(-1 * var(--spacing-xl)); margin: 0 calc(-1 * var(--spacing-xl));

View File

@ -72,3 +72,9 @@ export const PlanModel = {
} }
export const ChangelogURL = "https://docs.budibase.com/changelog" export const ChangelogURL = "https://docs.budibase.com/changelog"
export const AutoScreenTypes = {
BLANK: "blank",
TABLE: "table",
FORM: "form",
}

View File

@ -10,12 +10,16 @@
navigationStore, navigationStore,
permissions as permissionsStore, permissions as permissionsStore,
builderStore, builderStore,
datasources,
appStore,
} from "stores/builder" } from "stores/builder"
import { auth } from "stores/portal" import { auth } from "stores/portal"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import { TOUR_KEYS } from "components/portal/onboarding/tours.js" import { TOUR_KEYS } from "components/portal/onboarding/tours.js"
import * as screenTemplating from "templates/screenTemplating" import * as screenTemplating from "templates/screenTemplating"
import { Roles } from "constants/backend" import { Roles } from "constants/backend"
import { AutoScreenTypes } from "constants"
import { makeTableOption, makeViewOption } from "./utils"
let mode let mode
@ -23,20 +27,33 @@
let datasourceModal let datasourceModal
let formTypeModal let formTypeModal
let tableTypeModal let tableTypeModal
let selectedTablesAndViews = [] let selectedTablesAndViews = []
let permissions = {} let permissions = {}
let hasPreselectedDatasource = false
$: screens = $screenStore.screens $: screens = $screenStore.screens
export const show = newMode => { export const show = (newMode, preselectedDatasource) => {
mode = newMode mode = newMode
selectedTablesAndViews = [] selectedTablesAndViews = []
permissions = {} permissions = {}
hasPreselectedDatasource = preselectedDatasource != null
if (mode === "table" || mode === "form") { if (mode === AutoScreenTypes.TABLE || mode === AutoScreenTypes.FORM) {
datasourceModal.show() if (preselectedDatasource) {
} else if (mode === "blank") { // If preselecting a datasource, skip a step
const isTable = preselectedDatasource.type === "table"
const tableOrView = isTable
? makeTableOption(preselectedDatasource, $datasources.list)
: makeViewOption(preselectedDatasource)
fetchPermission(tableOrView.id)
selectedTablesAndViews.push(tableOrView)
onSelectDatasources()
} else {
// Otherwise choose a datasource
datasourceModal.show()
}
} else if (mode === AutoScreenTypes.BLANK) {
screenDetailsModal.show() screenDetailsModal.show()
} else { } else {
throw new Error("Invalid mode provided") throw new Error("Invalid mode provided")
@ -77,9 +94,9 @@
} }
const onSelectDatasources = async () => { const onSelectDatasources = async () => {
if (mode === "form") { if (mode === AutoScreenTypes.FORM) {
formTypeModal.show() formTypeModal.show()
} else if (mode === "table") { } else if (mode === AutoScreenTypes.TABLE) {
tableTypeModal.show() tableTypeModal.show()
} }
} }
@ -136,9 +153,11 @@
if (screen?.props?._children.length) { if (screen?.props?._children.length) {
// Focus on the main component for the screen type // Focus on the main component for the screen type
const mainComponent = screen?.props?._children?.[0]._id const mainComponent = screen?.props?._children?.[0]._id
$goto(`./${screen._id}/${mainComponent}`) $goto(
`/builder/app/${$appStore.appId}/design/${screen._id}/${mainComponent}`
)
} else { } else {
$goto(`./${screen._id}`) $goto(`/builder/app/${$appStore.appId}/design/${screen._id}`)
} }
screenStore.select(screen._id) screenStore.select(screen._id)
@ -214,6 +233,7 @@
tableTypeModal.hide() tableTypeModal.hide()
datasourceModal.show() datasourceModal.show()
}} }}
showCancelButton={!hasPreselectedDatasource}
/> />
</Modal> </Modal>
@ -230,5 +250,6 @@
formTypeModal.hide() formTypeModal.hide()
datasourceModal.show() datasourceModal.show()
}} }}
showCancelButton={!hasPreselectedDatasource}
/> />
</Modal> </Modal>

View File

@ -1,11 +1,11 @@
<script> <script>
import { Body, ModalContent, Layout, notifications } from "@budibase/bbui" import { Body, ModalContent, Layout } from "@budibase/bbui"
import { datasources as datasourcesStore } from "stores/builder" import { datasources as datasourcesStore } from "stores/builder"
import ICONS from "components/backend/DatasourceNavigator/icons" import ICONS from "components/backend/DatasourceNavigator/icons"
import { IntegrationNames } from "constants" import { IntegrationNames } from "constants"
import { createEventDispatcher, onMount } from "svelte" import { createEventDispatcher } from "svelte"
import TableOrViewOption from "./TableOrViewOption.svelte" import TableOrViewOption from "./TableOrViewOption.svelte"
import * as format from "helpers/data/format" import { makeTableOption, makeViewOption } from "./utils"
export let onConfirm export let onConfirm
export let selectedTablesAndViews export let selectedTablesAndViews
@ -16,17 +16,10 @@
const views = Object.values(table.views || {}).filter( const views = Object.values(table.views || {}).filter(
view => view.version === 2 view => view.version === 2
) )
return views.map(makeViewOption)
return views.map(view => ({
icon: "Remove",
name: view.name,
id: view.id,
tableSelectFormat: format.tableSelect.viewV2(view),
datasourceSelectFormat: format.datasourceSelect.viewV2(view),
}))
} }
const getTablesAndViews = datasource => { const getTablesAndViews = (datasource, datasources) => {
let tablesAndViews = [] let tablesAndViews = []
const tables = Array.isArray(datasource.entities) const tables = Array.isArray(datasource.entities)
? datasource.entities ? datasource.entities
@ -37,16 +30,7 @@
continue continue
} }
const formattedTable = { const formattedTable = makeTableOption(table, datasources)
icon: "Table",
name: table.name,
id: table._id,
tableSelectFormat: format.tableSelect.table(table),
datasourceSelectFormat: format.datasourceSelect.table(
table,
$datasourcesStore.list
),
}
tablesAndViews = tablesAndViews.concat([ tablesAndViews = tablesAndViews.concat([
formattedTable, formattedTable,
@ -71,7 +55,7 @@
const datasource = { const datasource = {
name: rawDatasource.name, name: rawDatasource.name,
iconComponent: ICONS[rawDatasource.source], iconComponent: ICONS[rawDatasource.source],
tablesAndViews: getTablesAndViews(rawDatasource), tablesAndViews: getTablesAndViews(rawDatasource, rawDatasources),
} }
datasources.push(datasource) datasources.push(datasource)
@ -85,14 +69,6 @@
const toggleSelection = tableOrView => { const toggleSelection = tableOrView => {
dispatch("toggle", tableOrView) dispatch("toggle", tableOrView)
} }
onMount(async () => {
try {
await datasourcesStore.fetch()
} catch (error) {
notifications.error("Error fetching datasources")
}
})
</script> </script>
<ModalContent <ModalContent

View File

@ -7,6 +7,7 @@
export let types export let types
export let onCancel = () => {} export let onCancel = () => {}
export let onConfirm = () => {} export let onConfirm = () => {}
export let showCancelButton = true
</script> </script>
<ModalContent <ModalContent
@ -17,6 +18,7 @@
{onCancel} {onCancel}
disabled={!selectedType} disabled={!selectedType}
size="L" size="L"
{showCancelButton}
> >
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->

View File

@ -0,0 +1,17 @@
import * as format from "helpers/data/format"
export const makeViewOption = view => ({
icon: "Remove",
name: view.name,
id: view.id,
tableSelectFormat: format.tableSelect.viewV2(view),
datasourceSelectFormat: format.datasourceSelect.viewV2(view),
})
export const makeTableOption = (table, datasources) => ({
icon: "Table",
name: table.name,
id: table._id,
tableSelectFormat: format.tableSelect.table(table),
datasourceSelectFormat: format.datasourceSelect.table(table, datasources),
})