Merge pull request #8219 from Budibase/feature/blocks-in-auto-screens

Component Blocks in CRUD Auto-screens
This commit is contained in:
deanhannigan 2022-10-13 17:18:53 +01:00 committed by GitHub
commit bebeccef12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 115 additions and 236 deletions

View File

@ -1,13 +1,8 @@
import sanitizeUrl from "./utils/sanitizeUrl" import sanitizeUrl from "./utils/sanitizeUrl"
import { Screen } from "./utils/Screen" import { Screen } from "./utils/Screen"
import { Component } from "./utils/Component" import { Component } from "./utils/Component"
import { import { makeBreadcrumbContainer } from "./utils/commonComponents"
makeBreadcrumbContainer, import { getSchemaForDatasource } from "../../dataBinding"
makeMainForm,
makeTitleContainer,
makeSaveButton,
makeDatasourceFormComponents,
} from "./utils/commonComponents"
export default function (tables) { export default function (tables) {
return tables.map(table => { return tables.map(table => {
@ -23,48 +18,55 @@ export default function (tables) {
export const newRowUrl = table => sanitizeUrl(`/${table.name}/new/row`) export const newRowUrl = table => sanitizeUrl(`/${table.name}/new/row`)
export const NEW_ROW_TEMPLATE = "NEW_ROW_TEMPLATE" export const NEW_ROW_TEMPLATE = "NEW_ROW_TEMPLATE"
function generateTitleContainer(table, formId) { const rowListUrl = table => sanitizeUrl(`/${table.name}`)
return makeTitleContainer("New Row").addChild(makeSaveButton(table, formId))
const getFields = schema => {
let columns = []
Object.entries(schema || {}).forEach(([field, fieldSchema]) => {
if (!field || !fieldSchema) {
return
}
if (!fieldSchema?.autocolumn) {
columns.push(field)
}
})
return columns
} }
const createScreen = table => { const generateFormBlock = table => {
const screen = new Screen() const datasource = { type: "table", tableId: table._id }
.instanceName(`${table.name} - New`) const { schema } = getSchemaForDatasource(null, datasource, {
.customProps({ formSchema: true,
hAlign: "center", })
}) const formBlock = new Component("@budibase/standard-components/formblock")
.route(newRowUrl(table)) formBlock
const form = makeMainForm()
.instanceName("Form")
.customProps({ .customProps({
title: "New row",
actionType: "Create", actionType: "Create",
actionUrl: rowListUrl(table),
showDeleteButton: false,
showSaveButton: true,
fields: getFields(schema),
dataSource: { dataSource: {
label: table.name, label: table.name,
tableId: table._id, tableId: table._id,
type: "table", type: "table",
}, },
labelPosition: "left",
size: "spectrum--medium", size: "spectrum--medium",
}) })
.instanceName(`${table.name} - Form block`)
const fieldGroup = new Component("@budibase/standard-components/fieldgroup") return formBlock
.instanceName("Field Group") }
.customProps({
labelPosition: "left", const createScreen = table => {
}) const formBlock = generateFormBlock(table)
const screen = new Screen()
// Add all form fields from this schema to the field group .instanceName(`${table.name} - New`)
const datasource = { type: "table", tableId: table._id } .route(newRowUrl(table))
makeDatasourceFormComponents(datasource).forEach(component => {
fieldGroup.addChild(component) return screen
}) .addChild(makeBreadcrumbContainer(table.name, "New row"))
.addChild(formBlock)
// Add all children to the form .json()
const formId = form._json._id
form
.addChild(makeBreadcrumbContainer(table.name, "New"))
.addChild(generateTitleContainer(table, formId))
.addChild(fieldGroup)
return screen.addChild(form).json()
} }

View File

@ -1,15 +1,8 @@
import sanitizeUrl from "./utils/sanitizeUrl" import sanitizeUrl from "./utils/sanitizeUrl"
import { rowListUrl } from "./rowListScreen"
import { Screen } from "./utils/Screen" import { Screen } from "./utils/Screen"
import { Component } from "./utils/Component" import { Component } from "./utils/Component"
import { makePropSafe } from "@budibase/string-templates" import { makeBreadcrumbContainer } from "./utils/commonComponents"
import { import { getSchemaForDatasource } from "../../dataBinding"
makeBreadcrumbContainer,
makeTitleContainer,
makeSaveButton,
makeMainForm,
makeDatasourceFormComponents,
} from "./utils/commonComponents"
export default function (tables) { export default function (tables) {
return tables.map(table => { return tables.map(table => {
@ -25,125 +18,53 @@ export default function (tables) {
export const ROW_DETAIL_TEMPLATE = "ROW_DETAIL_TEMPLATE" export const ROW_DETAIL_TEMPLATE = "ROW_DETAIL_TEMPLATE"
export const rowDetailUrl = table => sanitizeUrl(`/${table.name}/:id`) export const rowDetailUrl = table => sanitizeUrl(`/${table.name}/:id`)
function generateTitleContainer(table, title, formId, repeaterId) { const rowListUrl = table => sanitizeUrl(`/${table.name}`)
const saveButton = makeSaveButton(table, formId)
const deleteButton = new Component("@budibase/standard-components/button")
.text("Delete")
.customProps({
type: "secondary",
quiet: true,
size: "M",
onClick: [
{
parameters: {
tableId: table._id,
rowId: `{{ ${makePropSafe(repeaterId)}.${makePropSafe("_id")} }}`,
revId: `{{ ${makePropSafe(repeaterId)}.${makePropSafe("_rev")} }}`,
confirm: true,
},
"##eventHandlerType": "Delete Row",
},
{
parameters: {
url: rowListUrl(table),
},
"##eventHandlerType": "Navigate To",
},
],
})
.instanceName("Delete Button")
const buttons = new Component("@budibase/standard-components/container") const getFields = schema => {
.instanceName("Button Container") let columns = []
.customProps({ Object.entries(schema || {}).forEach(([field, fieldSchema]) => {
direction: "row", if (!field || !fieldSchema) {
hAlign: "right", return
vAlign: "middle", }
size: "shrink", if (!fieldSchema?.autocolumn) {
gap: "M", columns.push(field)
}) }
.addChild(deleteButton) })
.addChild(saveButton) return columns
}
return makeTitleContainer(title).addChild(buttons) const generateFormBlock = table => {
const datasource = { type: "table", tableId: table._id }
const { schema } = getSchemaForDatasource(null, datasource, {
formSchema: true,
})
const formBlock = new Component("@budibase/standard-components/formblock")
formBlock
.customProps({
title: "Edit row",
actionType: "Update",
actionUrl: rowListUrl(table),
showDeleteButton: true,
showSaveButton: true,
fields: getFields(schema),
dataSource: {
label: table.name,
tableId: table._id,
type: "table",
},
labelPosition: "left",
size: "spectrum--medium",
})
.instanceName(`${table.name} - Form block`)
return formBlock
} }
const createScreen = table => { const createScreen = table => {
const provider = new Component("@budibase/standard-components/dataprovider")
.instanceName(`Data Provider`)
.customProps({
dataSource: {
label: table.name,
name: table._id,
tableId: table._id,
type: "table",
},
filter: [
{
field: "_id",
operator: "equal",
type: "string",
value: `{{ ${makePropSafe("url")}.${makePropSafe("id")} }}`,
valueType: "Binding",
},
],
limit: 1,
paginate: false,
})
const repeater = new Component("@budibase/standard-components/repeater")
.instanceName("Repeater")
.customProps({
dataProvider: `{{ literal ${makePropSafe(provider._json._id)} }}`,
noRowsMessage: "We couldn't find a row to display",
})
const form = makeMainForm()
.instanceName("Form")
.customProps({
actionType: "Update",
size: "spectrum--medium",
dataSource: {
label: table.name,
tableId: table._id,
type: "table",
},
})
const fieldGroup = new Component("@budibase/standard-components/fieldgroup")
.instanceName("Field Group")
.customProps({
labelPosition: "left",
})
// Add all form fields from this schema to the field group
const datasource = { type: "table", tableId: table._id }
makeDatasourceFormComponents(datasource).forEach(component => {
fieldGroup.addChild(component)
})
// Add all children to the form
const formId = form._json._id
const repeaterId = repeater._json._id
const heading = table.primaryDisplay
? `{{ ${makePropSafe(repeaterId)}.${makePropSafe(table.primaryDisplay)} }}`
: null
form
.addChild(makeBreadcrumbContainer(table.name, heading || "Edit"))
.addChild(
generateTitleContainer(table, heading || "Edit Row", formId, repeaterId)
)
.addChild(fieldGroup)
repeater.addChild(form)
provider.addChild(repeater)
return new Screen() return new Screen()
.instanceName(`${table.name} - Detail`) .instanceName(`${table.name} - Detail`)
.route(rowDetailUrl(table)) .route(rowDetailUrl(table))
.customProps({ .addChild(makeBreadcrumbContainer(table.name, "Edit row"))
hAlign: "center", .addChild(generateFormBlock(table))
})
.addChild(provider)
.json() .json()
} }

View File

@ -2,7 +2,6 @@ import sanitizeUrl from "./utils/sanitizeUrl"
import { newRowUrl } from "./newRowScreen" import { newRowUrl } from "./newRowScreen"
import { Screen } from "./utils/Screen" import { Screen } from "./utils/Screen"
import { Component } from "./utils/Component" import { Component } from "./utils/Component"
import { makePropSafe } from "@budibase/string-templates"
export default function (tables) { export default function (tables) {
return tables.map(table => { return tables.map(table => {
@ -18,48 +17,17 @@ export default function (tables) {
export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE" export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE"
export const rowListUrl = table => sanitizeUrl(`/${table.name}`) export const rowListUrl = table => sanitizeUrl(`/${table.name}`)
function generateTitleContainer(table) { const generateTableBlock = table => {
const newButton = new Component("@budibase/standard-components/button") const tableBlock = new Component("@budibase/standard-components/tableblock")
.text("Create New") tableBlock
.customProps({
size: "M",
type: "primary",
onClick: [
{
parameters: {
url: newRowUrl(table),
},
"##eventHandlerType": "Navigate To",
},
],
})
.instanceName("New Button")
const heading = new Component("@budibase/standard-components/heading")
.instanceName("Title")
.text(table.name)
.customProps({
size: "M",
align: "left",
})
return new Component("@budibase/standard-components/container")
.customProps({
direction: "row",
hAlign: "stretch",
vAlign: "middle",
size: "shrink",
gap: "M",
})
.instanceName("Title Container")
.addChild(heading)
.addChild(newButton)
}
const createScreen = table => {
const provider = new Component("@budibase/standard-components/dataprovider")
.instanceName(`Data Provider`)
.customProps({ .customProps({
linkRows: true,
linkURL: `${rowListUrl(table)}/:id`,
showAutoColumns: false,
showTitleButton: true,
titleButtonText: "Create new",
titleButtonURL: newRowUrl(table),
title: table.name,
dataSource: { dataSource: {
label: table.name, label: table.name,
name: table._id, name: table._id,
@ -68,41 +36,16 @@ const createScreen = table => {
}, },
size: "spectrum--medium", size: "spectrum--medium",
paginate: true, paginate: true,
limit: 8,
})
const spectrumTable = new Component("@budibase/standard-components/table")
.customProps({
dataProvider: `{{ literal ${makePropSafe(provider._json._id)} }}`,
showAutoColumns: false,
quiet: false,
rowCount: 8, rowCount: 8,
}) })
.instanceName(`${table.name} Table`) .instanceName(`${table.name} - Table block`)
return tableBlock
const safeTableId = makePropSafe(spectrumTable._json._id) }
const safeRowId = makePropSafe("_id")
const viewLink = new Component("@budibase/standard-components/link")
.customProps({
text: "View",
url: `${rowListUrl(table)}/{{ ${safeTableId}.${safeRowId} }}`,
size: "S",
color: "var(--spectrum-global-color-gray-600)",
align: "left",
})
.normalStyle({
["margin-left"]: "16px",
["margin-right"]: "16px",
})
.instanceName("View Link")
spectrumTable.addChild(viewLink)
provider.addChild(spectrumTable)
const createScreen = table => {
return new Screen() return new Screen()
.route(rowListUrl(table)) .route(rowListUrl(table))
.instanceName(`${table.name} - List`) .instanceName(`${table.name} - List`)
.addChild(generateTitleContainer(table)) .addChild(generateTableBlock(table))
.addChild(provider)
.json() .json()
} }

View File

@ -65,6 +65,11 @@ export function makeBreadcrumbContainer(tableName, text) {
vAlign: "middle", vAlign: "middle",
size: "shrink", size: "shrink",
}) })
.normalStyle({
width: "600px",
"margin-right": "auto",
"margin-left": "auto",
})
.instanceName("Breadcrumbs") .instanceName("Breadcrumbs")
.addChild(link) .addChild(link)
.addChild(arrowText) .addChild(arrowText)

View File

@ -17,7 +17,7 @@
export let rowId export let rowId
export let actionUrl export let actionUrl
const { fetchDatasourceSchema, builderStore } = getContext("sdk") const { fetchDatasourceSchema } = getContext("sdk")
const FieldTypeToComponentMap = { const FieldTypeToComponentMap = {
string: "stringfield", string: "stringfield",
number: "numberfield", number: "numberfield",
@ -29,6 +29,7 @@
attachment: "attachmentfield", attachment: "attachmentfield",
link: "relationshipfield", link: "relationshipfield",
json: "jsonfield", json: "jsonfield",
barcodeqr: "codescanner",
} }
let schema let schema
@ -80,7 +81,7 @@
field: "_id", field: "_id",
operator: "equal", operator: "equal",
type: "string", type: "string",
value: rowId, value: !rowId ? `{{ ${safe("url")}.${safe("id")} }}` : rowId,
valueType: "Binding", valueType: "Binding",
}, },
] ]
@ -118,7 +119,7 @@
props={{ props={{
dataSource, dataSource,
filter, filter,
limit: rowId ? 1 : $builderStore.inBuilder ? 1 : 0, limit: 1,
paginate: false, paginate: false,
}} }}
> >
@ -129,6 +130,8 @@
props={{ props={{
dataProvider, dataProvider,
noRowsMessage: "We couldn't find a row to display", noRowsMessage: "We couldn't find a row to display",
direction: "column",
hAlign: "center",
}} }}
> >
<BlockComponent <BlockComponent
@ -139,6 +142,11 @@
size, size,
disabled: disabled || actionType === "View", disabled: disabled || actionType === "View",
}} }}
styles={{
normal: {
width: "600px",
},
}}
context="form" context="form"
bind:id={formId} bind:id={formId}
> >