Expose refresh datasource action from form blocks and add row action button templates
This commit is contained in:
parent
61b82b8817
commit
5de81c624f
|
@ -6,6 +6,7 @@
|
||||||
import { componentStore } from "stores/builder"
|
import { componentStore } from "stores/builder"
|
||||||
import { getEventContextBindings } from "dataBinding"
|
import { getEventContextBindings } from "dataBinding"
|
||||||
import { cloneDeep, isEqual } from "lodash/fp"
|
import { cloneDeep, isEqual } from "lodash/fp"
|
||||||
|
import { getRowActionButtonTemplates } from "templates/rowActions"
|
||||||
|
|
||||||
export let componentInstance
|
export let componentInstance
|
||||||
export let componentBindings
|
export let componentBindings
|
||||||
|
@ -19,11 +20,14 @@
|
||||||
|
|
||||||
let focusItem
|
let focusItem
|
||||||
let cachedValue
|
let cachedValue
|
||||||
|
let rowActionTemplates = []
|
||||||
|
|
||||||
|
$: console.log(rowActionTemplates)
|
||||||
|
|
||||||
|
$: getRowActionTemplates(componentInstance)
|
||||||
$: if (!isEqual(value, cachedValue)) {
|
$: if (!isEqual(value, cachedValue)) {
|
||||||
cachedValue = cloneDeep(value)
|
cachedValue = cloneDeep(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: buttonList = sanitizeValue(cachedValue) || []
|
$: buttonList = sanitizeValue(cachedValue) || []
|
||||||
$: buttonCount = buttonList.length
|
$: buttonCount = buttonList.length
|
||||||
$: eventContextBindings = getEventContextBindings({
|
$: eventContextBindings = getEventContextBindings({
|
||||||
|
@ -39,6 +43,11 @@
|
||||||
}
|
}
|
||||||
$: canAddButtons = max == null || buttonList.length < max
|
$: canAddButtons = max == null || buttonList.length < max
|
||||||
|
|
||||||
|
const getRowActionTemplates = async instance => {
|
||||||
|
const templates = await getRowActionButtonTemplates({ component: instance })
|
||||||
|
rowActionTemplates = templates
|
||||||
|
}
|
||||||
|
|
||||||
const sanitizeValue = val => {
|
const sanitizeValue = val => {
|
||||||
if (!Array.isArray(val)) {
|
if (!Array.isArray(val)) {
|
||||||
return null
|
return null
|
||||||
|
@ -79,9 +88,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const addButton = () => {
|
const addButton = () => {
|
||||||
const newButton = buildPseudoInstance({
|
// const newButton = buildPseudoInstance({
|
||||||
text: `Button ${buttonCount + 1}`,
|
// text: `Button ${buttonCount + 1}`,
|
||||||
})
|
// })
|
||||||
|
const newButton = rowActionTemplates[0]
|
||||||
|
if (!newButton) {
|
||||||
|
return
|
||||||
|
}
|
||||||
dispatch("change", [...buttonList, newButton])
|
dispatch("change", [...buttonList, newButton])
|
||||||
focusItem = newButton._id
|
focusItem = newButton._id
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import InfoDisplay from "./InfoDisplay.svelte"
|
import InfoDisplay from "./InfoDisplay.svelte"
|
||||||
import analytics, { Events } from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import { shouldDisplaySetting } from "@budibase/frontend-core"
|
import { shouldDisplaySetting } from "@budibase/frontend-core"
|
||||||
|
import { getContext, setContext } from "svelte"
|
||||||
|
|
||||||
export let componentDefinition
|
export let componentDefinition
|
||||||
export let componentInstance
|
export let componentInstance
|
||||||
|
@ -19,6 +20,16 @@
|
||||||
export let includeHidden = false
|
export let includeHidden = false
|
||||||
export let tag
|
export let tag
|
||||||
|
|
||||||
|
// Sometimes we render component settings using a complicated nested
|
||||||
|
// component instance technique. This results in instances with IDs that
|
||||||
|
// don't exist anywhere in the tree. Therefore we need to keep track of
|
||||||
|
// what the real component tree ID is so we can always find it.
|
||||||
|
const rootId = getContext("rootId")
|
||||||
|
if (!rootId) {
|
||||||
|
setContext("rootId", componentInstance._id)
|
||||||
|
}
|
||||||
|
componentInstance._rootId = rootId || componentInstance._id
|
||||||
|
|
||||||
$: sections = getSections(
|
$: sections = getSections(
|
||||||
componentInstance,
|
componentInstance,
|
||||||
componentDefinition,
|
componentDefinition,
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
import { getDatasourceForProvider } from "dataBinding"
|
||||||
|
import { rowActions, selectedScreen, componentStore } from "stores/builder"
|
||||||
|
import { Helpers } from "@budibase/bbui"
|
||||||
|
import { findComponent } from "helpers/components"
|
||||||
|
|
||||||
|
export const getRowActionButtonTemplates = async ({ screen, component }) => {
|
||||||
|
if (!component) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if (!screen) {
|
||||||
|
screen = get(selectedScreen)
|
||||||
|
}
|
||||||
|
const id = component._rootId
|
||||||
|
const instance = findComponent(screen?.props, id)
|
||||||
|
if (!instance) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// The row ID binding depends on what component this is.
|
||||||
|
// Therefore we need to whitelist this to only function for certain components.
|
||||||
|
const type = instance?._component
|
||||||
|
const isGridBlock = type?.endsWith("/gridblock")
|
||||||
|
const isFormBlock =
|
||||||
|
type?.endsWith("/formblock") || type?.endsWith("/multistepformblock")
|
||||||
|
if (!isGridBlock && !isFormBlock) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check we have a valid datasource that can contain row actions
|
||||||
|
const ds = getDatasourceForProvider(get(selectedScreen), instance)
|
||||||
|
if (ds?.type !== "table" && ds?.type !== "viewV2") {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const resourceId = ds.id || ds.tableId
|
||||||
|
if (!resourceId) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
await rowActions.refreshRowActions(resourceId)
|
||||||
|
const enabledActions = get(rowActions)[resourceId] || []
|
||||||
|
|
||||||
|
// Generate the row ID binding depending on the component
|
||||||
|
let rowIdBinding
|
||||||
|
if (isGridBlock) {
|
||||||
|
rowIdBinding = `{{ [${instance._id}].[_id] }}`
|
||||||
|
} else if (isFormBlock) {
|
||||||
|
rowIdBinding = `{{ [${instance._id}-repeater].[_id] }}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create templates
|
||||||
|
return enabledActions.map(action => {
|
||||||
|
// Create a button instance
|
||||||
|
const button = componentStore.createInstance(
|
||||||
|
`@budibase/standard-components/button`,
|
||||||
|
{
|
||||||
|
_instanceName: Helpers.uuid(),
|
||||||
|
text: action.name,
|
||||||
|
type: "primary",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Row action button action
|
||||||
|
const onClick = [
|
||||||
|
{
|
||||||
|
parameters: {
|
||||||
|
rowActionId: action.id,
|
||||||
|
resourceId,
|
||||||
|
rowId: rowIdBinding,
|
||||||
|
},
|
||||||
|
"##eventHandlerType": "Row Action",
|
||||||
|
id: Helpers.uuid(),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// For form blocks we need to manually refresh the form after running the action
|
||||||
|
if (isFormBlock) {
|
||||||
|
onClick.push({
|
||||||
|
parameters: {
|
||||||
|
componentId: `${instance._id}-provider`,
|
||||||
|
},
|
||||||
|
"##eventHandlerType": "Refresh Data Provider",
|
||||||
|
id: Helpers.uuid(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...button,
|
||||||
|
onClick,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -6998,6 +6998,10 @@
|
||||||
{
|
{
|
||||||
"type": "ChangeFormStep",
|
"type": "ChangeFormStep",
|
||||||
"suffix": "form"
|
"suffix": "form"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "RefreshDatasource",
|
||||||
|
"suffix": "provider"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"context": [
|
"context": [
|
||||||
|
@ -7241,6 +7245,10 @@
|
||||||
{
|
{
|
||||||
"type": "ScrollTo",
|
"type": "ScrollTo",
|
||||||
"suffix": "form"
|
"suffix": "form"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "RefreshDatasource",
|
||||||
|
"suffix": "provider"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"context": [
|
"context": [
|
||||||
|
|
Loading…
Reference in New Issue