diff --git a/packages/builder/src/components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte index 9adbca7603..5bd2b757e4 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte @@ -9,21 +9,20 @@ } from "@budibase/bbui" import DetailPopover from "components/common/DetailPopover.svelte" import { getContext } from "svelte" - import { appStore, automationStore } from "stores/builder" + import { appStore, rowActions } from "stores/builder" import { API } from "api" import { goto, url } from "@roxi/routify" import { derived } from "svelte/store" - import { getSequentialName } from "helpers/duplicate" const { datasource } = getContext("grid") - let rowActions = [] - $: ds = $datasource $: tableId = ds?.tableId + $: viewId = ds?.id $: isView = ds?.type === "viewV2" - $: fetchRowActions(ds) - $: actionCount = rowActions.filter(action => !isView || action.enabled).length + $: tableRowActions = $rowActions[tableId] || [] + $: viewRowActions = $rowActions[viewId] || [] + $: actionCount = isView ? viewRowActions.length : tableRowActions.length const rowActionUrl = derived([url, appStore], ([$url, $appStore]) => { return ({ automationId }) => { @@ -31,30 +30,11 @@ } }) - const fetchRowActions = async datasource => { - if (!datasource?.tableId) { - rowActions = [] - return - } - const res = await API.rowActions.fetch(datasource.tableId) - rowActions = Object.values(res || {}).map(action => ({ - ...action, - enabled: !isView || action.allowedViews?.includes(ds.id), - })) - } - const createRowAction = async () => { try { - const name = getSequentialName(rowActions, "New row action ", { - getName: x => x.name, - }) - const res = await API.rowActions.create({ - name, - tableId, - }) - await automationStore.actions.fetch() + const newRowAction = await rowActions.createRowAction(tableId, viewId) notifications.success("Row action created successfully") - $goto($rowActionUrl(res)) + // $goto($rowActionUrl(newRowAction)) } catch (error) { console.error(error) notifications.error("Error creating row action") @@ -62,19 +42,10 @@ } const toggleAction = async (action, enabled) => { - console.log(action, enabled) if (enabled) { - await API.rowActions.enableView({ - tableId, - rowActionId: action.id, - viewId: ds.id, - }) + await rowActions.enableView(tableId, viewId, action.id) } else { - await API.rowActions.disableView({ - tableId, - rowActionId: action.id, - viewId: ds.id, - }) + await rowActions.disableView(tableId, viewId, action.id) } } @@ -96,18 +67,18 @@ Use the toggle to enable/disable row actions for this view.
{/if} - {#if !rowActions.length} + {#if !tableRowActions.length}
You haven't created any row actions. {:else} - {#each rowActions as action} + {#each tableRowActions as action} {#if isView} toggleAction(action, e.detail)} /> diff --git a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/[viewId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/[viewId]/index.svelte index e3020394df..3596f1b832 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/[viewId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/[viewId]/index.svelte @@ -1,5 +1,5 @@ {#if $tables?.selected?.name} diff --git a/packages/builder/src/stores/BudiStore.js b/packages/builder/src/stores/BudiStore.js index 1acf299921..e7be02f283 100644 --- a/packages/builder/src/stores/BudiStore.js +++ b/packages/builder/src/stores/BudiStore.js @@ -2,9 +2,8 @@ import { writable } from "svelte/store" export default class BudiStore { constructor(init, opts) { - const store = writable({ - ...init, - }) + this.initialState = init + const store = writable({ ...init }) /** * Internal Svelte store @@ -23,6 +22,7 @@ export default class BudiStore { * *Store modification should be kept to a minimum */ this.update = this.store.update + this.set = this.store.set /** * Optional debug mode to output the store updates to console @@ -33,4 +33,8 @@ export default class BudiStore { }) } } + + reset = () => { + this.store.set({ ...this.initialState }) + } } diff --git a/packages/builder/src/stores/builder/index.js b/packages/builder/src/stores/builder/index.js index aa0062dd7d..dbde739951 100644 --- a/packages/builder/src/stores/builder/index.js +++ b/packages/builder/src/stores/builder/index.js @@ -29,6 +29,7 @@ import { integrations } from "./integrations" import { sortedIntegrations } from "./sortedIntegrations" import { queries } from "./queries" import { flags } from "./flags" +import { rowActions } from "./rowActions" import componentTreeNodesStore from "./componentTreeNodes" export { @@ -65,6 +66,7 @@ export { flags, hoverStore, snippets, + rowActions, } export const reset = () => { @@ -74,6 +76,7 @@ export const reset = () => { componentStore.reset() layoutStore.reset() navigationStore.reset() + rowActions.reset() } const refreshBuilderData = async () => { diff --git a/packages/builder/src/stores/builder/rowActions.js b/packages/builder/src/stores/builder/rowActions.js new file mode 100644 index 0000000000..0255e4726c --- /dev/null +++ b/packages/builder/src/stores/builder/rowActions.js @@ -0,0 +1,114 @@ +import { get, derived } from "svelte/store" +import BudiStore from "stores/BudiStore" +import { tables } from "./tables" +import { viewsV2 } from "./viewsV2" +import { automationStore } from "./automations" +import { API } from "api" +import { getSequentialName } from "helpers/duplicate" + +const initialState = {} + +export class RowActionStore extends BudiStore { + constructor() { + super(initialState) + } + + refreshRowActions = async sourceId => { + if (!sourceId) { + return + } + + // Get the underlying table ID for this source ID + let tableId = get(tables).list.find(table => table._id === sourceId)?._id + if (!tableId) { + const view = get(viewsV2).list.find(view => view.id === sourceId) + tableId = view?.tableId + } + if (!tableId) { + return + } + + // Fetch row actions for this table + const res = await API.rowActions.fetch(tableId) + const actions = Object.values(res || {}) + this.update(state => ({ + ...state, + [tableId]: actions, + })) + } + + createRowAction = async (tableId, viewId) => { + if (!tableId) { + return + } + + // Get a unique name for this action + const existingRowActions = get(this.store)[tableId] || [] + const name = getSequentialName(existingRowActions, "New row action ", { + getName: x => x.name, + }) + + // Create the action and update state + const res = await API.rowActions.create({ + name, + tableId, + }) + this.update(state => ({ + ...state, + [tableId]: [...(state[tableId] || []), res], + })) + + // If adding to a view, enable on this view + if (viewId) { + await this.enableView(tableId, viewId, res.id) + } + + // Refresh automations so we have this new row action automation + await automationStore.actions.fetch() + + return res + } + + enableView = async (tableId, viewId, rowActionId) => { + await API.rowActions.enableView({ + tableId, + viewId, + rowActionId, + }) + await this.refreshRowActions(tableId) + } + + disableView = async (tableId, viewId, rowActionId) => { + await API.rowActions.disableView({ + tableId, + viewId, + rowActionId, + }) + await this.refreshRowActions(tableId) + } +} + +const store = new RowActionStore() +const derivedStore = derived(store, $store => { + let map = {} + + // Generate an entry for every view as well + Object.keys($store || {}).forEach(tableId => { + map[tableId] = $store[tableId] + for (let action of $store[tableId]) { + for (let viewId of action.allowedViews || []) { + if (!map[viewId]) { + map[viewId] = [] + } + map[viewId].push(action) + } + } + }) + + return map +}) + +export const rowActions = { + ...store, + subscribe: derivedStore.subscribe, +} diff --git a/packages/builder/src/stores/portal/licensing.js b/packages/builder/src/stores/portal/licensing.js index dd9747aa09..0e44650479 100644 --- a/packages/builder/src/stores/portal/licensing.js +++ b/packages/builder/src/stores/portal/licensing.js @@ -104,7 +104,6 @@ export const createLicensingStore = () => { const isBusinessPlan = planType === Constants.PlanType.BUSINESS const isEnterpriseTrial = planType === Constants.PlanType.ENTERPRISE_BASIC_TRIAL - console.log(license) const groupsEnabled = license.features.includes( Constants.Features.USER_GROUPS ) @@ -143,8 +142,6 @@ export const createLicensingStore = () => { Constants.Features.VIEW_READONLY_COLUMNS ) - console.log(isViewReadonlyColumnsEnabled) - store.update(state => { return { ...state, diff --git a/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte b/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte index a086972941..03f5f4644e 100644 --- a/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte +++ b/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte @@ -25,7 +25,7 @@ let container - $: buttons = $props.buttons?.slice(0, 3) || [] + $: buttons = getButtons($props) $: columnsWidth = $scrollableColumns.reduce( (total, col) => (total += col.width), 0 @@ -34,6 +34,14 @@ $: gridEnd = $width - $buttonColumnWidth - 1 $: left = Math.min(columnEnd, gridEnd) + const getButtons = ({ buttons, buttonsCollapsed }) => { + let gridButtons = buttons || [] + if (!buttonsCollapsed) { + return gridButtons.slice(0, 3) + } + return gridButtons + } + const handleClick = async (button, row) => { await button.onClick?.(rows.actions.cleanRow(row)) await rows.actions.refreshRow(row._id)