Add common collapsed button group and use it for row actions and client button groups. Add collapsed settings to grids and form blocks
This commit is contained in:
parent
d8b6d10dce
commit
51cbced119
|
@ -0,0 +1,39 @@
|
|||
<script>
|
||||
import Button from "../Button/Button.svelte"
|
||||
import Popover from "../Popover/Popover.svelte"
|
||||
import Menu from "../Menu/Menu.svelte"
|
||||
import MenuItem from "../Menu/Item.svelte"
|
||||
|
||||
export let buttons
|
||||
export let text = "Action"
|
||||
export let size = "M"
|
||||
export let align = "left"
|
||||
export let offset
|
||||
|
||||
let anchor
|
||||
let popover
|
||||
|
||||
const handleClick = async button => {
|
||||
popover.hide()
|
||||
await button.onClick?.()
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button
|
||||
bind:ref={anchor}
|
||||
{size}
|
||||
icon="ChevronDown"
|
||||
cta
|
||||
on:click={() => popover?.show()}
|
||||
>
|
||||
{text || "Action"}
|
||||
</Button>
|
||||
<Popover bind:this={popover} {align} {anchor} {offset}>
|
||||
<Menu>
|
||||
{#each buttons as button}
|
||||
<MenuItem on:click={() => handleClick(button)} disabled={button.disabled}>
|
||||
{button.text || "Button"}
|
||||
</MenuItem>
|
||||
{/each}
|
||||
</Menu>
|
||||
</Popover>
|
|
@ -39,6 +39,7 @@ export { default as ActionGroup } from "./ActionGroup/ActionGroup.svelte"
|
|||
export { default as ActionMenu } from "./ActionMenu/ActionMenu.svelte"
|
||||
export { default as Button } from "./Button/Button.svelte"
|
||||
export { default as ButtonGroup } from "./ButtonGroup/ButtonGroup.svelte"
|
||||
export { default as CollapsedButtonGroup } from "./ButtonGroup/CollapsedButtonGroup.svelte"
|
||||
export { default as ClearButton } from "./ClearButton/ClearButton.svelte"
|
||||
export { default as Icon } from "./Icon/Icon.svelte"
|
||||
export { default as IconAvatar } from "./Icon/IconAvatar.svelte"
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
|
||||
let rowActions = []
|
||||
let generateButton
|
||||
let rowActionPopover
|
||||
let rowActionRow
|
||||
let rowActionAnchor
|
||||
let refreshRow
|
||||
|
||||
$: autoColumnStatus = verifyAutocolumns($tables?.selected)
|
||||
$: duplicates = Object.values(autoColumnStatus).reduce((acc, status) => {
|
||||
|
@ -58,21 +54,22 @@
|
|||
$: relationshipsEnabled = relationshipSupport(tableDatasource)
|
||||
$: currentTheme = $themeStore?.theme
|
||||
$: darkMode = !currentTheme.includes("light")
|
||||
$: buttons = [
|
||||
{
|
||||
text: "Action",
|
||||
type: "cta",
|
||||
icon: "ChevronDown",
|
||||
onClick: async (e, row, refresh) => {
|
||||
rowActionRow = row
|
||||
rowActionAnchor = e.currentTarget
|
||||
rowActionPopover.show()
|
||||
refreshRow = refresh
|
||||
},
|
||||
},
|
||||
]
|
||||
$: buttons = makeRowActionButtons(rowActions)
|
||||
$: fetchRowActions(id)
|
||||
|
||||
const makeRowActionButtons = rowActions => {
|
||||
return rowActions.map(action => ({
|
||||
text: action.name,
|
||||
onClick: async row => {
|
||||
await API.rowActions.trigger({
|
||||
rowActionId: action.id,
|
||||
tableId: id,
|
||||
rowId: row._id,
|
||||
})
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
const relationshipSupport = datasource => {
|
||||
const integration = $integrations[datasource?.source]
|
||||
return !isInternal && integration?.relationships !== false
|
||||
|
@ -110,16 +107,6 @@
|
|||
const res = await API.rowActions.fetch(tableId)
|
||||
rowActions = Object.values(res || {})
|
||||
}
|
||||
|
||||
const runRowAction = async action => {
|
||||
await API.rowActions.trigger({
|
||||
rowActionId: action.id,
|
||||
tableId: id,
|
||||
rowId: rowActionRow._id,
|
||||
})
|
||||
await refreshRow()
|
||||
rowActionPopover.hide()
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $tables?.selected?.name}
|
||||
|
@ -143,7 +130,8 @@
|
|||
schemaOverrides={isUsersTable ? userSchemaOverrides : null}
|
||||
showAvatars={false}
|
||||
isCloud={$admin.cloud}
|
||||
buttons={rowActions.length ? buttons : null}
|
||||
{buttons}
|
||||
buttonsCollapsed
|
||||
on:updatedatasource={handleGridTableUpdate}
|
||||
>
|
||||
<!-- Controls -->
|
||||
|
@ -192,19 +180,6 @@
|
|||
<i>Create your first table to start building</i>
|
||||
{/if}
|
||||
|
||||
<Popover
|
||||
bind:this={rowActionPopover}
|
||||
align="right"
|
||||
anchor={rowActionAnchor}
|
||||
offset={5}
|
||||
>
|
||||
<Menu>
|
||||
{#each rowActions as action}
|
||||
<MenuItem on:click={() => runRowAction(action)}>{action.name}</MenuItem>
|
||||
{/each}
|
||||
</Menu>
|
||||
</Popover>
|
||||
|
||||
<style>
|
||||
i {
|
||||
font-size: var(--font-size-m);
|
||||
|
|
|
@ -7591,6 +7591,18 @@
|
|||
"key": "row"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Collapse",
|
||||
"key": "buttonsCollapsed"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"label": "Collapsed text",
|
||||
"key": "buttonsCollapsedText",
|
||||
"dependsOn": "buttonsCollapsed",
|
||||
"placeholder": "Action"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
<script>
|
||||
import BlockComponent from "../BlockComponent.svelte"
|
||||
import Block from "../Block.svelte"
|
||||
import { Button, Popover, Menu, MenuItem } from "@budibase/bbui"
|
||||
import {
|
||||
Button,
|
||||
Popover,
|
||||
Menu,
|
||||
MenuItem,
|
||||
CollapsedButtonGroup,
|
||||
} from "@budibase/bbui"
|
||||
import { getContext } from "svelte"
|
||||
|
||||
export let buttons = []
|
||||
|
@ -16,39 +22,26 @@
|
|||
const component = getContext("component")
|
||||
const context = getContext("context")
|
||||
|
||||
let popover
|
||||
let anchor
|
||||
$: collapsedButtons = collapsed ? makeCollapsed(buttons) : null
|
||||
|
||||
const handleCollapsedClick = async button => {
|
||||
const makeCollapsed = buttons => {
|
||||
return buttons.map(button => ({
|
||||
...button,
|
||||
onClick: async () => {
|
||||
const fn = enrichButtonActions(button.onClick, $context)
|
||||
await fn?.()
|
||||
popover.hide()
|
||||
},
|
||||
}))
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if collapsed}
|
||||
<div use:styleable={$component.styles}>
|
||||
<Button
|
||||
bind:ref={anchor}
|
||||
on:click={() => popover?.show()}
|
||||
icon="ChevronDown"
|
||||
cta
|
||||
>
|
||||
{collapsedText || "Action"}
|
||||
</Button>
|
||||
<CollapsedButtonGroup
|
||||
text={collapsedText || "Action"}
|
||||
buttons={collapsedButtons}
|
||||
/>
|
||||
</div>
|
||||
<Popover bind:this={popover} align="left" {anchor}>
|
||||
<Menu>
|
||||
{#each buttons as button}
|
||||
<MenuItem
|
||||
on:click={() => handleCollapsedClick(button)}
|
||||
disabled={button.disabled}
|
||||
>
|
||||
{button.text || "Button"}
|
||||
</MenuItem>
|
||||
{/each}
|
||||
</Menu>
|
||||
</Popover>
|
||||
{:else}
|
||||
<Block>
|
||||
<BlockComponent
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
export let columns = null
|
||||
export let onRowClick = null
|
||||
export let buttons = null
|
||||
export let buttonsCollapsed = false
|
||||
export let buttonsCollapsedText = null
|
||||
|
||||
const context = getContext("context")
|
||||
const component = getContext("component")
|
||||
|
@ -115,15 +117,13 @@
|
|||
text: settings.text,
|
||||
type: settings.type,
|
||||
icon: settings.icon,
|
||||
onClick: async (_, row, refresh) => {
|
||||
onClick: async row => {
|
||||
// Create a fake, ephemeral context to run the buttons actions with
|
||||
const id = get(component).id
|
||||
const gridContext = createContextStore(context)
|
||||
gridContext.actions.provideData(id, row)
|
||||
const fn = enrichButtonActions(settings.onClick, get(gridContext))
|
||||
const res = await fn?.({ row })
|
||||
await refresh()
|
||||
return res
|
||||
return await fn?.({ row })
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
@ -183,6 +183,8 @@
|
|||
notifySuccess={notificationStore.actions.success}
|
||||
notifyError={notificationStore.actions.error}
|
||||
buttons={enrichedButtons}
|
||||
{buttonsCollapsed}
|
||||
{buttonsCollapsedText}
|
||||
isCloud={$environmentStore.cloud}
|
||||
on:rowclick={e => onRowClick?.({ row: e.detail })}
|
||||
/>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import GridCell from "../cells/GridCell.svelte"
|
||||
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
||||
import { BlankRowID } from "../lib/constants"
|
||||
import CollapsedButtonGroup from "../../../../../bbui/src/ButtonGroup/CollapsedButtonGroup.svelte"
|
||||
|
||||
const {
|
||||
renderedRows,
|
||||
|
@ -34,12 +35,16 @@
|
|||
$: gridEnd = $width - $buttonColumnWidth - 1
|
||||
$: left = Math.min(columnEnd, gridEnd)
|
||||
|
||||
const handleClick = async (e, button, row) => {
|
||||
await button.onClick?.(
|
||||
e,
|
||||
rows.actions.cleanRow(row),
|
||||
async () => await rows.actions.refreshRow(row._id)
|
||||
)
|
||||
const handleClick = async (button, row) => {
|
||||
await button.onClick?.(rows.actions.cleanRow(row))
|
||||
await rows.actions.refreshRow(row._id)
|
||||
}
|
||||
|
||||
const makeCollapsedButtons = (buttons, row) => {
|
||||
return buttons.map(button => ({
|
||||
...button,
|
||||
onClick: () => handleClick(button, row),
|
||||
}))
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
@ -80,26 +85,33 @@
|
|||
class="buttons"
|
||||
class:offset={$showVScrollbar && $showHScrollbar}
|
||||
>
|
||||
{#if $props.buttonsCollapsed}
|
||||
<CollapsedButtonGroup
|
||||
buttons={makeCollapsedButtons(buttons, row)}
|
||||
text={$props.buttonsCollapsedText || "Action"}
|
||||
align="right"
|
||||
offset={5}
|
||||
size="S"
|
||||
/>
|
||||
{:else}
|
||||
{#each buttons as button}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<span on:click={e => handleClick(e, button, row)}>
|
||||
<Button
|
||||
newStyles
|
||||
size="S"
|
||||
icon={button.icon}
|
||||
cta={button.type === "cta"}
|
||||
primary={button.type === "primary"}
|
||||
secondary={button.type === "secondary"}
|
||||
warning={button.type === "warning"}
|
||||
overBackground={button.type === "overBackground"}
|
||||
on:click={() => handleClick(button, row)}
|
||||
>
|
||||
{#if button.icon}
|
||||
<i class="{button.icon} S" />
|
||||
{/if}
|
||||
{button.text || "Button"}
|
||||
</Button>
|
||||
</span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</GridCell>
|
||||
</div>
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
export let notifySuccess = null
|
||||
export let notifyError = null
|
||||
export let buttons = null
|
||||
export let darkMode
|
||||
export let buttonsCollapsed = false
|
||||
export let buttonsCollapsedText = null
|
||||
export let darkMode = false
|
||||
export let isCloud = null
|
||||
export let rowConditions = null
|
||||
|
||||
|
@ -98,6 +100,8 @@
|
|||
notifySuccess,
|
||||
notifyError,
|
||||
buttons,
|
||||
buttonsCollapsed,
|
||||
buttonsCollapsedText,
|
||||
darkMode,
|
||||
isCloud,
|
||||
rowConditions,
|
||||
|
|
Loading…
Reference in New Issue