Update screen templates to support full form generation. Fix issues with screen templates
This commit is contained in:
parent
3dd6769777
commit
e3b0de6805
|
@ -9,5 +9,6 @@ const createScreen = () => {
|
||||||
return new Screen()
|
return new Screen()
|
||||||
.mainType("div")
|
.mainType("div")
|
||||||
.component("@budibase/standard-components/container")
|
.component("@budibase/standard-components/container")
|
||||||
|
.instanceName("New Screen")
|
||||||
.json()
|
.json()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { Screen } from "./utils/Screen"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: `New Row (Empty)`,
|
|
||||||
create: () => createScreen(),
|
|
||||||
}
|
|
||||||
|
|
||||||
const createScreen = () => {
|
|
||||||
return new Screen()
|
|
||||||
.component("@budibase/standard-components/newrow")
|
|
||||||
.table("")
|
|
||||||
.json()
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { Screen } from "./utils/Screen"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: `Row Detail (Empty)`,
|
|
||||||
create: () => createScreen(),
|
|
||||||
}
|
|
||||||
|
|
||||||
const createScreen = () => {
|
|
||||||
return new Screen()
|
|
||||||
.component("@budibase/standard-components/rowdetail")
|
|
||||||
.table("")
|
|
||||||
.json()
|
|
||||||
}
|
|
|
@ -1,17 +1,12 @@
|
||||||
import newRowScreen from "./newRowScreen"
|
import newRowScreen from "./newRowScreen"
|
||||||
import rowDetailScreen from "./rowDetailScreen"
|
import rowDetailScreen from "./rowDetailScreen"
|
||||||
import rowListScreen from "./rowListScreen"
|
import rowListScreen from "./rowListScreen"
|
||||||
import emptyNewRowScreen from "./emptyNewRowScreen"
|
|
||||||
import createFromScratchScreen from "./createFromScratchScreen"
|
import createFromScratchScreen from "./createFromScratchScreen"
|
||||||
import emptyRowDetailScreen from "./emptyRowDetailScreen"
|
|
||||||
|
|
||||||
const allTemplates = tables => [
|
const allTemplates = tables => [
|
||||||
createFromScratchScreen,
|
|
||||||
...newRowScreen(tables),
|
...newRowScreen(tables),
|
||||||
...rowDetailScreen(tables),
|
...rowDetailScreen(tables),
|
||||||
...rowListScreen(tables),
|
...rowListScreen(tables),
|
||||||
emptyNewRowScreen,
|
|
||||||
emptyRowDetailScreen,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
// Allows us to apply common behaviour to all create() functions
|
// Allows us to apply common behaviour to all create() functions
|
||||||
|
@ -22,8 +17,18 @@ const createTemplateOverride = (frontendState, create) => () => {
|
||||||
return screen
|
return screen
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (frontendState, tables) =>
|
export default (frontendState, tables) => {
|
||||||
allTemplates(tables).map(template => ({
|
const enrichTemplate = template => ({
|
||||||
...template,
|
...template,
|
||||||
create: createTemplateOverride(frontendState, template.create),
|
create: createTemplateOverride(frontendState, template.create),
|
||||||
}))
|
})
|
||||||
|
|
||||||
|
const fromScratch = enrichTemplate(createFromScratchScreen)
|
||||||
|
const tableTemplates = allTemplates(tables).map(enrichTemplate)
|
||||||
|
return [
|
||||||
|
fromScratch,
|
||||||
|
...tableTemplates.sort((templateA, templateB) => {
|
||||||
|
return templateA.name > templateB.name ? 1 : -1
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import sanitizeUrl from "./utils/sanitizeUrl"
|
import sanitizeUrl from "./utils/sanitizeUrl"
|
||||||
import { Component } from "./utils/Component"
|
|
||||||
import { Screen } from "./utils/Screen"
|
import { Screen } from "./utils/Screen"
|
||||||
|
import { Component } from "./utils/Component"
|
||||||
import {
|
import {
|
||||||
makeBreadcrumbContainer,
|
makeBreadcrumbContainer,
|
||||||
makeMainContainer,
|
makeMainForm,
|
||||||
makeTitleContainer,
|
makeTitleContainer,
|
||||||
makeSaveButton,
|
makeSaveButton,
|
||||||
|
makeSchemaFormComponents,
|
||||||
} from "./utils/commonComponents"
|
} from "./utils/commonComponents"
|
||||||
|
|
||||||
export default function(tables) {
|
export default function(tables) {
|
||||||
|
@ -21,29 +22,45 @@ 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, providerId) {
|
function generateTitleContainer(table, formId) {
|
||||||
return makeTitleContainer("New Row").addChild(
|
return makeTitleContainer("New Row").addChild(makeSaveButton(table, formId))
|
||||||
makeSaveButton(table, providerId)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScreen = table => {
|
const createScreen = table => {
|
||||||
const screen = new Screen()
|
const screen = new Screen()
|
||||||
.component("@budibase/standard-components/newrow")
|
.component("@budibase/standard-components/container")
|
||||||
.table(table._id)
|
|
||||||
.route(newRowUrl(table))
|
|
||||||
.instanceName(`${table.name} - New`)
|
.instanceName(`${table.name} - New`)
|
||||||
.name("")
|
.route(newRowUrl(table))
|
||||||
|
|
||||||
const dataform = new Component(
|
const form = makeMainForm()
|
||||||
"@budibase/standard-components/dataformwide"
|
.instanceName("Form")
|
||||||
).instanceName("Form")
|
.customProps({
|
||||||
|
theme: "spectrum--light",
|
||||||
|
size: "spectrum--medium",
|
||||||
|
datasource: {
|
||||||
|
label: table.name,
|
||||||
|
tableId: table._id,
|
||||||
|
type: "table",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const providerId = screen._json.props._id
|
const fieldGroup = new Component("@budibase/standard-components/fieldgroup")
|
||||||
const container = makeMainContainer()
|
.instanceName("Field Group")
|
||||||
|
.customProps({
|
||||||
|
labelPosition: "left",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add all form fields from this schema to the field group
|
||||||
|
makeSchemaFormComponents(table._id).forEach(component => {
|
||||||
|
fieldGroup.addChild(component)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add all children to the form
|
||||||
|
const formId = form._json._id
|
||||||
|
form
|
||||||
.addChild(makeBreadcrumbContainer(table.name, "New"))
|
.addChild(makeBreadcrumbContainer(table.name, "New"))
|
||||||
.addChild(generateTitleContainer(table, providerId))
|
.addChild(generateTitleContainer(table, formId))
|
||||||
.addChild(dataform)
|
.addChild(fieldGroup)
|
||||||
|
|
||||||
return screen.addChild(container).json()
|
return screen.addChild(form).json()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,18 @@ 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 {
|
import {
|
||||||
makeMainContainer,
|
|
||||||
makeBreadcrumbContainer,
|
makeBreadcrumbContainer,
|
||||||
makeTitleContainer,
|
makeTitleContainer,
|
||||||
makeSaveButton,
|
makeSaveButton,
|
||||||
|
makeSchemaFormComponents,
|
||||||
|
makeMainForm,
|
||||||
} from "./utils/commonComponents"
|
} from "./utils/commonComponents"
|
||||||
|
|
||||||
export default function(tables) {
|
export default function(tables) {
|
||||||
return tables.map(table => {
|
return tables.map(table => {
|
||||||
const heading = table.primaryDisplay
|
|
||||||
? `{{ data.${table.primaryDisplay} }}`
|
|
||||||
: null
|
|
||||||
return {
|
return {
|
||||||
name: `${table.name} - Detail`,
|
name: `${table.name} - Detail`,
|
||||||
create: () => createScreen(table, heading),
|
create: () => createScreen(table),
|
||||||
id: ROW_DETAIL_TEMPLATE,
|
id: ROW_DETAIL_TEMPLATE,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -25,9 +23,9 @@ 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, providerId) {
|
function generateTitleContainer(table, title, formId) {
|
||||||
// have to override style for this, its missing margin
|
// have to override style for this, its missing margin
|
||||||
const saveButton = makeSaveButton(table, providerId).normalStyle({
|
const saveButton = makeSaveButton(table, formId).normalStyle({
|
||||||
background: "#000000",
|
background: "#000000",
|
||||||
"border-width": "0",
|
"border-width": "0",
|
||||||
"border-style": "None",
|
"border-style": "None",
|
||||||
|
@ -60,8 +58,8 @@ function generateTitleContainer(table, title, providerId) {
|
||||||
onClick: [
|
onClick: [
|
||||||
{
|
{
|
||||||
parameters: {
|
parameters: {
|
||||||
rowId: `{{ ${providerId}._id }}`,
|
rowId: `{{ ${formId}._id }}`,
|
||||||
revId: `{{ ${providerId}._rev }}`,
|
revId: `{{ ${formId}._rev }}`,
|
||||||
tableId: table._id,
|
tableId: table._id,
|
||||||
},
|
},
|
||||||
"##eventHandlerType": "Delete Row",
|
"##eventHandlerType": "Delete Row",
|
||||||
|
@ -81,23 +79,46 @@ function generateTitleContainer(table, title, providerId) {
|
||||||
.addChild(saveButton)
|
.addChild(saveButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScreen = (table, heading) => {
|
const createScreen = table => {
|
||||||
const screen = new Screen()
|
const screen = new Screen()
|
||||||
.component("@budibase/standard-components/rowdetail")
|
.component("@budibase/standard-components/rowdetail")
|
||||||
.table(table._id)
|
.table(table._id)
|
||||||
.instanceName(`${table.name} - Detail`)
|
.instanceName(`${table.name} - Detail`)
|
||||||
.route(rowDetailUrl(table))
|
.route(rowDetailUrl(table))
|
||||||
.name("")
|
|
||||||
|
|
||||||
const dataform = new Component(
|
const form = makeMainForm()
|
||||||
"@budibase/standard-components/dataformwide"
|
.instanceName("Form")
|
||||||
).instanceName("Form")
|
.customProps({
|
||||||
|
theme: "spectrum--light",
|
||||||
|
size: "spectrum--medium",
|
||||||
|
datasource: {
|
||||||
|
label: table.name,
|
||||||
|
tableId: table._id,
|
||||||
|
type: "table",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const providerId = screen._json.props._id
|
const fieldGroup = new Component("@budibase/standard-components/fieldgroup")
|
||||||
const container = makeMainContainer()
|
.instanceName("Field Group")
|
||||||
|
.customProps({
|
||||||
|
labelPosition: "left",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add all form fields from this schema to the field group
|
||||||
|
makeSchemaFormComponents(table._id).forEach(component => {
|
||||||
|
fieldGroup.addChild(component)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add all children to the form
|
||||||
|
const formId = form._json._id
|
||||||
|
const rowDetailId = screen._json.props._id
|
||||||
|
const heading = table.primaryDisplay
|
||||||
|
? `{{ ${rowDetailId}.${table.primaryDisplay} }}`
|
||||||
|
: null
|
||||||
|
form
|
||||||
.addChild(makeBreadcrumbContainer(table.name, heading || "Edit"))
|
.addChild(makeBreadcrumbContainer(table.name, heading || "Edit"))
|
||||||
.addChild(generateTitleContainer(table, heading || "Edit Row", providerId))
|
.addChild(generateTitleContainer(table, heading || "Edit Row", formId))
|
||||||
.addChild(dataform)
|
.addChild(fieldGroup)
|
||||||
|
|
||||||
return screen.addChild(container).json()
|
return screen.addChild(form).json()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,11 @@ export class Component extends BaseStructure {
|
||||||
active: {},
|
active: {},
|
||||||
selected: {},
|
selected: {},
|
||||||
},
|
},
|
||||||
type: "",
|
|
||||||
_instanceName: "",
|
_instanceName: "",
|
||||||
_children: [],
|
_children: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type(type) {
|
|
||||||
this._json.type = type
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
normalStyle(styling) {
|
normalStyle(styling) {
|
||||||
this._json._styles.normal = styling
|
this._json._styles.normal = styling
|
||||||
return this
|
return this
|
||||||
|
@ -35,14 +29,20 @@ export class Component extends BaseStructure {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
text(text) {
|
|
||||||
this._json.text = text
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: do we need this
|
|
||||||
instanceName(name) {
|
instanceName(name) {
|
||||||
this._json._instanceName = name
|
this._json._instanceName = name
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shorthand for custom props "type"
|
||||||
|
type(type) {
|
||||||
|
this._json.type = type
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shorthand for custom props "text"
|
||||||
|
text(text) {
|
||||||
|
this._json.text = text
|
||||||
|
return this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
import { Component } from "./Component"
|
import { Component } from "./Component"
|
||||||
import { rowListUrl } from "../rowListScreen"
|
import { rowListUrl } from "../rowListScreen"
|
||||||
|
import { backendUiStore } from "builderStore"
|
||||||
|
import StringFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/StringFieldSelect.svelte"
|
||||||
|
import NumberFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/NumberFieldSelect.svelte"
|
||||||
|
import OptionsFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/OptionsFieldSelect.svelte"
|
||||||
|
import BooleanFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/BooleanFieldSelect.svelte"
|
||||||
|
import LongFormFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/LongFormFieldSelect.svelte"
|
||||||
|
import DateTimeFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/DateTimeFieldSelect.svelte"
|
||||||
|
import AttachmentFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/AttachmentFieldSelect.svelte"
|
||||||
|
import RelationshipFieldSelect from "../../../../components/design/PropertiesPanel/PropertyControls/RelationshipFieldSelect.svelte"
|
||||||
|
|
||||||
export function makeLinkComponent(tableName) {
|
export function makeLinkComponent(tableName) {
|
||||||
return new Component("@budibase/standard-components/link")
|
return new Component("@budibase/standard-components/link")
|
||||||
|
@ -22,13 +32,12 @@ export function makeLinkComponent(tableName) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeMainContainer() {
|
export function makeMainForm() {
|
||||||
return new Component("@budibase/standard-components/container")
|
return new Component("@budibase/standard-components/form")
|
||||||
.type("div")
|
.type("div")
|
||||||
.normalStyle({
|
.normalStyle({
|
||||||
width: "700px",
|
width: "700px",
|
||||||
padding: "0px",
|
padding: "0px",
|
||||||
background: "white",
|
|
||||||
"border-radius": "0.5rem",
|
"border-radius": "0.5rem",
|
||||||
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
|
@ -39,7 +48,26 @@ export function makeMainContainer() {
|
||||||
"padding-left": "48px",
|
"padding-left": "48px",
|
||||||
"margin-bottom": "20px",
|
"margin-bottom": "20px",
|
||||||
})
|
})
|
||||||
.instanceName("Container")
|
.instanceName("Form")
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeMainContainer() {
|
||||||
|
return new Component("@budibase/standard-components/container")
|
||||||
|
.type("div")
|
||||||
|
.normalStyle({
|
||||||
|
width: "700px",
|
||||||
|
padding: "0px",
|
||||||
|
"border-radius": "0.5rem",
|
||||||
|
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||||||
|
margin: "auto",
|
||||||
|
"margin-top": "20px",
|
||||||
|
"padding-top": "48px",
|
||||||
|
"padding-bottom": "48px",
|
||||||
|
"padding-right": "48px",
|
||||||
|
"padding-left": "48px",
|
||||||
|
"margin-bottom": "20px",
|
||||||
|
})
|
||||||
|
.instanceName("Form")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
|
export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
|
||||||
|
@ -78,7 +106,7 @@ export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
|
||||||
.addChild(identifierText)
|
.addChild(identifierText)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeSaveButton(table, providerId) {
|
export function makeSaveButton(table, formId) {
|
||||||
return new Component("@budibase/standard-components/button")
|
return new Component("@budibase/standard-components/button")
|
||||||
.normalStyle({
|
.normalStyle({
|
||||||
background: "#000000",
|
background: "#000000",
|
||||||
|
@ -99,8 +127,14 @@ export function makeSaveButton(table, providerId) {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
onClick: [
|
onClick: [
|
||||||
{
|
{
|
||||||
|
"##eventHandlerType": "Validate Form",
|
||||||
parameters: {
|
parameters: {
|
||||||
providerId,
|
componentId: formId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters: {
|
||||||
|
providerId: formId,
|
||||||
},
|
},
|
||||||
"##eventHandlerType": "Save Row",
|
"##eventHandlerType": "Save Row",
|
||||||
},
|
},
|
||||||
|
@ -142,3 +176,43 @@ export function makeTitleContainer(title) {
|
||||||
.instanceName("Title Container")
|
.instanceName("Title Container")
|
||||||
.addChild(heading)
|
.addChild(heading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fieldTypeToComponentMap = {
|
||||||
|
string: "stringfield",
|
||||||
|
number: "numberfield",
|
||||||
|
options: "optionsfield",
|
||||||
|
boolean: "booleanfield",
|
||||||
|
longform: "longformfield",
|
||||||
|
datetime: "datetimefield",
|
||||||
|
attachment: "attachmentfield",
|
||||||
|
link: "relationshipfield",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeSchemaFormComponents(tableId) {
|
||||||
|
const tables = get(backendUiStore).tables
|
||||||
|
const schema = tables.find(table => table._id === tableId)?.schema ?? {}
|
||||||
|
let components = []
|
||||||
|
let fields = Object.keys(schema)
|
||||||
|
fields.forEach(field => {
|
||||||
|
const fieldSchema = schema[field]
|
||||||
|
const componentType = fieldTypeToComponentMap[fieldSchema.type]
|
||||||
|
const fullComponentType = `@budibase/standard-components/${componentType}`
|
||||||
|
if (componentType) {
|
||||||
|
const component = new Component(fullComponentType)
|
||||||
|
.instanceName(field)
|
||||||
|
.customProps({
|
||||||
|
field,
|
||||||
|
label: field,
|
||||||
|
placeholder: field,
|
||||||
|
})
|
||||||
|
if (fieldSchema.type === "options") {
|
||||||
|
component.customProps({ placeholder: "Choose an option " })
|
||||||
|
}
|
||||||
|
if (fieldSchema.type === "boolean") {
|
||||||
|
component.customProps({ text: field, label: "" })
|
||||||
|
}
|
||||||
|
components.push(component)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return components
|
||||||
|
}
|
||||||
|
|
|
@ -60,8 +60,7 @@
|
||||||
"screenslot",
|
"screenslot",
|
||||||
"navigation",
|
"navigation",
|
||||||
"login",
|
"login",
|
||||||
"rowdetail",
|
"rowdetail"
|
||||||
"newrow"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -9,7 +9,10 @@ export const createContextStore = existingContext => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
if (componentId) {
|
if (componentId) {
|
||||||
state[componentId] = data
|
state[componentId] = data
|
||||||
state[`${componentId}_draft`] = cloneDeep(data)
|
|
||||||
|
// Keep track of the closest component ID so we can later hydrate a "data" prop.
|
||||||
|
// This is only required for legacy bindings that used "data" rather than a
|
||||||
|
// component ID.
|
||||||
state.closestComponentId = componentId
|
state.closestComponentId = componentId
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { ActionTypes } from "../constants"
|
||||||
const saveRowHandler = async (action, context) => {
|
const saveRowHandler = async (action, context) => {
|
||||||
const { fields, providerId } = action.parameters
|
const { fields, providerId } = action.parameters
|
||||||
if (providerId) {
|
if (providerId) {
|
||||||
let draft = context[`${providerId}_draft`]
|
let draft = context[providerId]
|
||||||
if (fields) {
|
if (fields) {
|
||||||
for (let [key, entry] of Object.entries(fields)) {
|
for (let [key, entry] of Object.entries(fields)) {
|
||||||
draft[key] = await enrichDataBinding(entry.value, context)
|
draft[key] = await enrichDataBinding(entry.value, context)
|
||||||
|
|
|
@ -35,8 +35,10 @@ export const enrichProps = async (props, context, user) => {
|
||||||
const totalContext = {
|
const totalContext = {
|
||||||
...context,
|
...context,
|
||||||
user,
|
user,
|
||||||
|
|
||||||
|
// This is only required for legacy bindings that used "data" rather than a
|
||||||
|
// component ID.
|
||||||
data: context[context.closestComponentId],
|
data: context[context.closestComponentId],
|
||||||
data_draft: context[`${context.closestComponentId}_draft`],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enrich all data bindings in top level props
|
// Enrich all data bindings in top level props
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
<script>
|
|
||||||
import { getContext } from "svelte"
|
|
||||||
import {
|
|
||||||
Label,
|
|
||||||
DatePicker,
|
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
Toggle,
|
|
||||||
RichText,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import Dropzone from "./attachments/Dropzone.svelte"
|
|
||||||
import LinkedRowSelector from "./LinkedRowSelector.svelte"
|
|
||||||
import { capitalise } from "./helpers"
|
|
||||||
|
|
||||||
const { styleable, API } = getContext("sdk")
|
|
||||||
const component = getContext("component")
|
|
||||||
const context = getContext("context")
|
|
||||||
|
|
||||||
export let wide = false
|
|
||||||
|
|
||||||
let row
|
|
||||||
let schema
|
|
||||||
let fields = []
|
|
||||||
|
|
||||||
// Fetch info about the closest data context
|
|
||||||
$: getFormData($context[$context.closestComponentId])
|
|
||||||
|
|
||||||
const getFormData = async context => {
|
|
||||||
if (context) {
|
|
||||||
const tableDefinition = await API.fetchTableDefinition(context.tableId)
|
|
||||||
schema = tableDefinition?.schema
|
|
||||||
fields = Object.keys(schema ?? {})
|
|
||||||
|
|
||||||
// Use the draft version for editing
|
|
||||||
row = $context[`${$context.closestComponentId}_draft`]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="form-content" use:styleable={$component.styles}>
|
|
||||||
<!-- <ErrorsBox errors={$store.saveRowErrors || {}} />-->
|
|
||||||
{#each fields as field}
|
|
||||||
<div class="form-field" class:wide>
|
|
||||||
{#if !(schema[field].type === 'boolean' && !wide)}
|
|
||||||
<Label extraSmall={!wide} grey>{capitalise(schema[field].name)}</Label>
|
|
||||||
{/if}
|
|
||||||
{#if schema[field].type === 'options'}
|
|
||||||
<Select secondary bind:value={row[field]}>
|
|
||||||
<option value="">Choose an option</option>
|
|
||||||
{#each schema[field].constraints.inclusion as opt}
|
|
||||||
<option>{opt}</option>
|
|
||||||
{/each}
|
|
||||||
</Select>
|
|
||||||
{:else if schema[field].type === 'datetime'}
|
|
||||||
<DatePicker bind:value={row[field]} />
|
|
||||||
{:else if schema[field].type === 'boolean'}
|
|
||||||
<Toggle
|
|
||||||
text={wide ? null : capitalise(schema[field].name)}
|
|
||||||
bind:checked={row[field]} />
|
|
||||||
{:else if schema[field].type === 'number'}
|
|
||||||
<Input type="number" bind:value={row[field]} />
|
|
||||||
{:else if schema[field].type === 'string'}
|
|
||||||
<Input bind:value={row[field]} />
|
|
||||||
{:else if schema[field].type === 'longform'}
|
|
||||||
<RichText bind:value={row[field]} />
|
|
||||||
{:else if schema[field].type === 'attachment'}
|
|
||||||
<Dropzone bind:files={row[field]} />
|
|
||||||
{:else if schema[field].type === 'link'}
|
|
||||||
<LinkedRowSelector
|
|
||||||
secondary
|
|
||||||
showLabel={false}
|
|
||||||
bind:linkedRows={row[field]}
|
|
||||||
schema={schema[field]} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-content {
|
|
||||||
display: grid;
|
|
||||||
gap: var(--spacing-xl);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-field {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
.form-field.wide {
|
|
||||||
align-items: center;
|
|
||||||
grid-template-columns: 20% 1fr;
|
|
||||||
gap: var(--spacing-xl);
|
|
||||||
}
|
|
||||||
.form-field.wide :global(label) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<script>
|
|
||||||
import { getContext } from "svelte"
|
|
||||||
|
|
||||||
const { Provider, styleable } = getContext("sdk")
|
|
||||||
const component = getContext("component")
|
|
||||||
|
|
||||||
export let table
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div use:styleable={$component.styles}>
|
|
||||||
<Provider data={{ tableId: table }}>
|
|
||||||
<slot />
|
|
||||||
</Provider>
|
|
||||||
</div>
|
|
|
@ -28,7 +28,6 @@ export { default as image } from "./Image.svelte"
|
||||||
export { default as embed } from "./Embed.svelte"
|
export { default as embed } from "./Embed.svelte"
|
||||||
export { default as cardhorizontal } from "./CardHorizontal.svelte"
|
export { default as cardhorizontal } from "./CardHorizontal.svelte"
|
||||||
export { default as cardstat } from "./CardStat.svelte"
|
export { default as cardstat } from "./CardStat.svelte"
|
||||||
export { default as newrow } from "./NewRow.svelte"
|
|
||||||
export { default as icon } from "./Icon.svelte"
|
export { default as icon } from "./Icon.svelte"
|
||||||
export * from "./charts"
|
export * from "./charts"
|
||||||
export * from "./forms"
|
export * from "./forms"
|
||||||
|
|
Loading…
Reference in New Issue