Add majority of frontend implementation of row actions
This commit is contained in:
parent
1991610b47
commit
c7c6597424
|
@ -19,6 +19,7 @@
|
||||||
{disabled}
|
{disabled}
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
on:click
|
on:click
|
||||||
|
on:click|stopPropagation
|
||||||
{id}
|
{id}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="spectrum-Switch-input"
|
class="spectrum-Switch-input"
|
||||||
|
|
|
@ -1,55 +1,50 @@
|
||||||
<script>
|
<script>
|
||||||
import Body from "../Typography/Body.svelte"
|
import Icon from "../Icon/Icon.svelte"
|
||||||
import IconAvatar from "../Icon/IconAvatar.svelte"
|
|
||||||
import Label from "../Label/Label.svelte"
|
|
||||||
import Avatar from "../Avatar/Avatar.svelte"
|
|
||||||
|
|
||||||
export let icon = null
|
export let icon = null
|
||||||
export let iconBackground = null
|
|
||||||
export let iconColor = null
|
export let iconColor = null
|
||||||
export let avatar = false
|
|
||||||
export let title = null
|
export let title = null
|
||||||
export let subtitle = null
|
export let subtitle = null
|
||||||
export let hoverable = false
|
export let url = null
|
||||||
|
|
||||||
$: initials = avatar ? title?.[0] : null
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<div class="list-item" class:hoverable on:click>
|
<a href={url} class="list-item" class:hoverable={url != null} on:click>
|
||||||
<div class="left">
|
<div class="left">
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<IconAvatar {icon} color={iconColor} background={iconBackground} />
|
<Icon name={icon} color={iconColor} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if avatar}
|
<div class="list-item__text">
|
||||||
<Avatar {initials} />
|
{#if title}
|
||||||
{/if}
|
<div class="list-item__title">
|
||||||
{#if title}
|
{title}
|
||||||
<Body>{title}</Body>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if subtitle}
|
{#if subtitle}
|
||||||
<Label>{subtitle}</Label>
|
<div class="list-item__subtitle">
|
||||||
{/if}
|
{subtitle}
|
||||||
</div>
|
</div>
|
||||||
{#if $$slots.default}
|
{/if}
|
||||||
<div class="right">
|
|
||||||
<slot />
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
<div class="right">
|
||||||
|
<slot name="right" />
|
||||||
|
<Icon name="ChevronRight" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.list-item {
|
.list-item {
|
||||||
padding: 0 16px;
|
padding: var(--spacing-m);
|
||||||
height: 56px;
|
background: var(--spectrum-global-color-gray-75);
|
||||||
background: var(--spectrum-global-color-gray-50);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
transition: background 130ms ease-out;
|
transition: background 130ms ease-out;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-m);
|
||||||
|
color: var(--spectrum-global-color-gray-800);
|
||||||
}
|
}
|
||||||
.list-item:not(:first-child) {
|
.list-item:not(:first-child) {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
|
@ -64,14 +59,15 @@
|
||||||
}
|
}
|
||||||
.hoverable:hover {
|
.hoverable:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--spectrum-global-color-gray-75);
|
background: var(--spectrum-global-color-gray-200);
|
||||||
}
|
}
|
||||||
|
|
||||||
.left,
|
.left,
|
||||||
.right {
|
.right {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-xl);
|
gap: var(--spacing-l);
|
||||||
}
|
}
|
||||||
.left {
|
.left {
|
||||||
width: 0;
|
width: 0;
|
||||||
|
@ -79,17 +75,20 @@
|
||||||
}
|
}
|
||||||
.right {
|
.right {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
color: var(--spectrum-global-color-gray-600);
|
||||||
}
|
}
|
||||||
.list-item :global(.spectrum-Icon),
|
|
||||||
.list-item :global(.spectrum-Avatar) {
|
.list-item__text {
|
||||||
flex: 0 0 auto;
|
flex: 1 1 auto;
|
||||||
|
width: 0;
|
||||||
}
|
}
|
||||||
.list-item :global(.spectrum-Body) {
|
.list-item__title,
|
||||||
color: var(--spectrum-global-color-gray-900);
|
.list-item__subtitle {
|
||||||
}
|
|
||||||
.list-item :global(.spectrum-Body) {
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
.list-item__subtitle {
|
||||||
|
color: var(--spectrum-global-color-gray-600);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { ActionButton, Modal } from "@budibase/bbui"
|
import { ActionButton } from "@budibase/bbui"
|
||||||
import { permissions } from "stores/builder"
|
import { permissions } from "stores/builder"
|
||||||
import ManageAccessModal from "../modals/ManageAccessModal.svelte"
|
import ManageAccessModal from "../modals/ManageAccessModal.svelte"
|
||||||
import DetailPopover from "components/common/DetailPopover.svelte"
|
import DetailPopover from "components/common/DetailPopover.svelte"
|
||||||
|
@ -11,7 +11,6 @@
|
||||||
$: fetchPermissions(resourceId)
|
$: fetchPermissions(resourceId)
|
||||||
|
|
||||||
const fetchPermissions = async id => {
|
const fetchPermissions = async id => {
|
||||||
console.log("getting perms for", id)
|
|
||||||
resourcePermissions = await permissions.forResourceDetailed(id)
|
resourcePermissions = await permissions.forResourceDetailed(id)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,12 +1,68 @@
|
||||||
<script>
|
<script>
|
||||||
import { ActionButton } from "@budibase/bbui"
|
import { ActionButton, List, ListItem, Button } from "@budibase/bbui"
|
||||||
import DetailPopover from "components/common/DetailPopover.svelte"
|
import DetailPopover from "components/common/DetailPopover.svelte"
|
||||||
|
import { TriggerStepID } from "constants/backend/automations"
|
||||||
|
import { automationStore, appStore } from "stores/builder"
|
||||||
|
import { createEventDispatcher, getContext } from "svelte"
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
const { datasource } = getContext("grid")
|
||||||
|
const triggerTypes = [
|
||||||
|
TriggerStepID.ROW_SAVED,
|
||||||
|
TriggerStepID.ROW_UPDATED,
|
||||||
|
TriggerStepID.ROW_DELETED,
|
||||||
|
]
|
||||||
|
|
||||||
|
let popover
|
||||||
|
|
||||||
|
$: ds = $datasource
|
||||||
|
$: resourceId = ds?.type === "table" ? ds.tableId : ds?.id
|
||||||
|
$: connectedAutomations = findConnectedAutomations(
|
||||||
|
$automationStore.automations,
|
||||||
|
resourceId
|
||||||
|
)
|
||||||
|
|
||||||
|
const findConnectedAutomations = (automations, resourceId) => {
|
||||||
|
return automations.filter(automation => {
|
||||||
|
if (!triggerTypes.includes(automation.definition?.trigger?.stepId)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return automation.definition?.trigger?.inputs?.tableId === resourceId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateAutomation = () => {
|
||||||
|
popover?.hide()
|
||||||
|
dispatch("generate-automation")
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailPopover title="Automations">
|
<DetailPopover title="Automations" minWidth={400} bind:this={popover}>
|
||||||
<svelte:fragment slot="anchor" let:open>
|
<svelte:fragment slot="anchor" let:open>
|
||||||
<ActionButton icon="JourneyVoyager" selected={open} quiet>
|
<ActionButton icon="JourneyVoyager" selected={open} quiet
|
||||||
Automations
|
>Automations</ActionButton
|
||||||
</ActionButton>
|
>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
{#if !connectedAutomations.length}
|
||||||
|
There aren't any automations connected to this data.
|
||||||
|
{:else}
|
||||||
|
The following automations are connected to this data.
|
||||||
|
<List>
|
||||||
|
{#each connectedAutomations as automation}
|
||||||
|
<ListItem
|
||||||
|
icon={automation.disabled ? "PauseCircle" : "PlayCircle"}
|
||||||
|
iconColor={automation.disabled
|
||||||
|
? "var(--spectrum-global-color-gray-600)"
|
||||||
|
: "var(--spectrum-global-color-green-600)"}
|
||||||
|
title={automation.name}
|
||||||
|
url={`/builder/app/${$appStore.appId}/automation/${automation._id}`}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</List>
|
||||||
|
{/if}
|
||||||
|
<div>
|
||||||
|
<Button secondary icon="JourneyVoyager" on:click={generateAutomation}>
|
||||||
|
Generate new automation
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</DetailPopover>
|
</DetailPopover>
|
||||||
|
|
|
@ -8,9 +8,14 @@
|
||||||
|
|
||||||
const { datasource } = getContext("grid")
|
const { datasource } = getContext("grid")
|
||||||
|
|
||||||
|
let popover
|
||||||
|
|
||||||
$: triggers = $automationStore.blockDefinitions.CREATABLE_TRIGGER
|
$: triggers = $automationStore.blockDefinitions.CREATABLE_TRIGGER
|
||||||
$: table = $tables.list.find(table => table._id === $datasource.tableId)
|
$: table = $tables.list.find(table => table._id === $datasource.tableId)
|
||||||
|
|
||||||
|
export const show = () => popover?.show()
|
||||||
|
export const hide = () => popover?.hide()
|
||||||
|
|
||||||
async function createAutomation(type) {
|
async function createAutomation(type) {
|
||||||
const triggerType = triggers[type]
|
const triggerType = triggers[type]
|
||||||
if (!triggerType) {
|
if (!triggerType) {
|
||||||
|
@ -53,7 +58,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailPopover title="Generate">
|
<DetailPopover title="Generate" bind:this={popover}>
|
||||||
<svelte:fragment slot="anchor" let:open>
|
<svelte:fragment slot="anchor" let:open>
|
||||||
<ActionButton icon="MagicWand" selected={open}>Generate</ActionButton>
|
<ActionButton icon="MagicWand" selected={open}>Generate</ActionButton>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
|
@ -1,12 +1,110 @@
|
||||||
<script>
|
<script>
|
||||||
import { ActionButton } from "@budibase/bbui"
|
import {
|
||||||
|
ActionButton,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Button,
|
||||||
|
Toggle,
|
||||||
|
notifications,
|
||||||
|
} from "@budibase/bbui"
|
||||||
import DetailPopover from "components/common/DetailPopover.svelte"
|
import DetailPopover from "components/common/DetailPopover.svelte"
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import { appStore, automationStore } 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
|
||||||
|
$: isView = ds?.type === "viewV2"
|
||||||
|
$: fetchRowActions(tableId)
|
||||||
|
$: console.log(rowActions)
|
||||||
|
$: activeCount = 0
|
||||||
|
$: suffix = isView ? activeCount : rowActions.length
|
||||||
|
|
||||||
|
const rowActionUrl = derived([url, appStore], ([$url, $appStore]) => {
|
||||||
|
return ({ automationId }) => {
|
||||||
|
return $url(`/builder/app/${$appStore.appId}/automation/${automationId}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const fetchRowActions = async tableId => {
|
||||||
|
if (!tableId) {
|
||||||
|
rowActions = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const res = await API.rowActions.fetch(tableId)
|
||||||
|
rowActions = Object.values(res || {})
|
||||||
|
}
|
||||||
|
|
||||||
|
const createRowAction = async () => {
|
||||||
|
try {
|
||||||
|
const name = getSequentialName(rowActions, "New row action ", {
|
||||||
|
getName: x => x.name,
|
||||||
|
})
|
||||||
|
const res = await API.rowActions.create({
|
||||||
|
name,
|
||||||
|
tableId,
|
||||||
|
})
|
||||||
|
console.log(res)
|
||||||
|
await automationStore.actions.fetch()
|
||||||
|
notifications.success("Row action created successfully")
|
||||||
|
$goto($rowActionUrl(res))
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailPopover title="Row Actions">
|
<DetailPopover title="Row Actions" minWidth={400} maxWidth={400}>
|
||||||
<svelte:fragment slot="anchor" let:open>
|
<svelte:fragment slot="anchor" let:open>
|
||||||
<ActionButton icon="Engagement" selected={open} quiet>
|
<ActionButton icon="Engagement" selected={open} quiet>
|
||||||
Row Actions
|
Row Actions ({suffix})
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
A row action is a user-triggered automation for a chosen row.
|
||||||
|
{#if isView && rowActions.length}
|
||||||
|
<br />
|
||||||
|
Use the toggle to enable/disable row actions for this view.
|
||||||
|
<br />
|
||||||
|
{/if}
|
||||||
|
{#if !rowActions.length}
|
||||||
|
<br />
|
||||||
|
You haven't created any row actions.
|
||||||
|
{:else}
|
||||||
|
<List>
|
||||||
|
{#each rowActions as action}
|
||||||
|
<ListItem title={action.name} url={$rowActionUrl(action)}>
|
||||||
|
<svelte:fragment slot="right">
|
||||||
|
{#if isView}
|
||||||
|
<span>
|
||||||
|
<Toggle />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</svelte:fragment>
|
||||||
|
</ListItem>
|
||||||
|
{/each}
|
||||||
|
</List>
|
||||||
|
{/if}
|
||||||
|
<div>
|
||||||
|
<Button secondary icon="Engagement" on:click={createRowAction}>
|
||||||
|
Create row action
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</DetailPopover>
|
</DetailPopover>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
span :global(.spectrum-Switch) {
|
||||||
|
min-height: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
span :global(.spectrum-Switch-switch) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { ActionButton } from "@budibase/bbui"
|
import { ActionButton, List, ListItem } from "@budibase/bbui"
|
||||||
import DetailPopover from "components/common/DetailPopover.svelte"
|
import DetailPopover from "components/common/DetailPopover.svelte"
|
||||||
import { screenStore } from "stores/builder"
|
import { screenStore, appStore } from "stores/builder"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const { datasource } = getContext("grid")
|
const { datasource } = getContext("grid")
|
||||||
|
@ -20,10 +20,21 @@
|
||||||
$: console.log(connectedScreens)
|
$: console.log(connectedScreens)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailPopover title="Screens">
|
<DetailPopover title="Screens" minWidth={400}>
|
||||||
<svelte:fragment slot="anchor" let:open>
|
<svelte:fragment slot="anchor" let:open>
|
||||||
<ActionButton icon="WebPage" selected={open} quiet>Screens</ActionButton>
|
<ActionButton icon="WebPage" selected={open} quiet>Screens</ActionButton>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
The following screens are connected to this data:
|
{#if !connectedScreens.length}
|
||||||
{connectedScreens.map(screen => screen.routing.route)}
|
There aren't any screens connected to this data.
|
||||||
|
{:else}
|
||||||
|
The following screens are connected to this data.
|
||||||
|
<List>
|
||||||
|
{#each connectedScreens as screen}
|
||||||
|
<ListItem
|
||||||
|
title={screen.routing.route}
|
||||||
|
url={`/builder/app/${$appStore.appId}/design/${screen._id}`}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</List>
|
||||||
|
{/if}
|
||||||
</DetailPopover>
|
</DetailPopover>
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
export let title
|
export let title
|
||||||
export let align = "left"
|
export let align = "left"
|
||||||
|
export let minWidth
|
||||||
|
export let maxWidth
|
||||||
|
|
||||||
let popover
|
let popover
|
||||||
let anchor
|
let anchor
|
||||||
|
@ -18,7 +20,14 @@
|
||||||
<slot name="anchor" {open} />
|
<slot name="anchor" {open} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Popover bind:this={popover} bind:open {anchor} {align} minWidth={300}>
|
<Popover
|
||||||
|
bind:this={popover}
|
||||||
|
bind:open
|
||||||
|
{anchor}
|
||||||
|
{align}
|
||||||
|
minWidth={minWidth || 300}
|
||||||
|
{maxWidth}
|
||||||
|
>
|
||||||
<div class="detail-popover">
|
<div class="detail-popover">
|
||||||
<div class="detail-popover__header">
|
<div class="detail-popover__header">
|
||||||
<div class="detail-popover__title">
|
<div class="detail-popover__title">
|
||||||
|
@ -34,7 +43,6 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.detail-popover {
|
.detail-popover {
|
||||||
--padding: var(--spacing-l);
|
|
||||||
background-color: var(--spectrum-alias-background-color-primary);
|
background-color: var(--spectrum-alias-background-color-primary);
|
||||||
}
|
}
|
||||||
.detail-popover__header {
|
.detail-popover__header {
|
||||||
|
@ -43,17 +51,17 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid var(--spectrum-global-color-gray-300);
|
border-bottom: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
padding: var(--padding);
|
padding: var(--spacing-l) var(--spacing-xl);
|
||||||
}
|
}
|
||||||
.detail-popover__title {
|
.detail-popover__title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.detail-popover__body {
|
.detail-popover__body {
|
||||||
padding: var(--padding);
|
padding: var(--spacing-xl) var(--spacing-xl);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: var(--padding);
|
gap: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
<GridColumnsSettingButton />
|
<GridColumnsSettingButton />
|
||||||
<GridManageAccessButton />
|
<GridManageAccessButton />
|
||||||
<GridRowActionsButton />
|
<GridRowActionsButton />
|
||||||
<GridAutomationsButton />
|
|
||||||
<GridScreensButton />
|
<GridScreensButton />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="controls-right">
|
<svelte:fragment slot="controls-right">
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import GridUsersTableButton from "components/backend/DataTable/buttons/grid/GridUsersTableButton.svelte"
|
import GridUsersTableButton from "components/backend/DataTable/buttons/grid/GridUsersTableButton.svelte"
|
||||||
import GridGenerateButton from "components/backend/DataTable/buttons/grid/GridGenerateButton.svelte"
|
import GridGenerateButton from "components/backend/DataTable/buttons/grid/GridGenerateButton.svelte"
|
||||||
import GridScreensButton from "components/backend/DataTable/buttons/grid/GridScreensButton.svelte"
|
import GridScreensButton from "components/backend/DataTable/buttons/grid/GridScreensButton.svelte"
|
||||||
|
import GridAutomationsButton from "components/backend/DataTable/buttons/grid/GridAutomationsButton.svelte"
|
||||||
import GridRowActionsButton from "components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte"
|
import GridRowActionsButton from "components/backend/DataTable/buttons/grid/GridRowActionsButton.svelte"
|
||||||
import { DB_TYPE_EXTERNAL } from "constants/backend"
|
import { DB_TYPE_EXTERNAL } from "constants/backend"
|
||||||
|
|
||||||
|
@ -27,6 +28,8 @@
|
||||||
status: { displayName: "Status", disabled: true },
|
status: { displayName: "Status", disabled: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let generateButton
|
||||||
|
|
||||||
$: autoColumnStatus = verifyAutocolumns($tables?.selected)
|
$: autoColumnStatus = verifyAutocolumns($tables?.selected)
|
||||||
$: duplicates = Object.values(autoColumnStatus).reduce((acc, status) => {
|
$: duplicates = Object.values(autoColumnStatus).reduce((acc, status) => {
|
||||||
if (status.length > 1) {
|
if (status.length > 1) {
|
||||||
|
@ -113,7 +116,12 @@
|
||||||
{#if relationshipsEnabled}
|
{#if relationshipsEnabled}
|
||||||
<GridRelationshipButton />
|
<GridRelationshipButton />
|
||||||
{/if}
|
{/if}
|
||||||
<GridRowActionsButton />
|
{#if !isUsersTable}
|
||||||
|
<GridRowActionsButton />
|
||||||
|
{/if}
|
||||||
|
<GridAutomationsButton
|
||||||
|
on:generate-automation={() => generateButton?.show()}
|
||||||
|
/>
|
||||||
<GridScreensButton />
|
<GridScreensButton />
|
||||||
{#if !isUsersTable}
|
{#if !isUsersTable}
|
||||||
<GridImportButton />
|
<GridImportButton />
|
||||||
|
@ -122,7 +130,7 @@
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="controls-right">
|
<svelte:fragment slot="controls-right">
|
||||||
<GridGenerateButton />
|
<GridGenerateButton bind:this={generateButton} />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<!-- Content for editing columns -->
|
<!-- Content for editing columns -->
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { buildEventEndpoints } from "./events"
|
||||||
import { buildAuditLogsEndpoints } from "./auditLogs"
|
import { buildAuditLogsEndpoints } from "./auditLogs"
|
||||||
import { buildLogsEndpoints } from "./logs"
|
import { buildLogsEndpoints } from "./logs"
|
||||||
import { buildMigrationEndpoints } from "./migrations"
|
import { buildMigrationEndpoints } from "./migrations"
|
||||||
|
import { buildRowActionEndpoints } from "./rowActions"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Random identifier to uniquely identify a session in a tab. This is
|
* Random identifier to uniquely identify a session in a tab. This is
|
||||||
|
@ -301,5 +302,6 @@ export const createAPIClient = config => {
|
||||||
...buildLogsEndpoints(API),
|
...buildLogsEndpoints(API),
|
||||||
...buildMigrationEndpoints(API),
|
...buildMigrationEndpoints(API),
|
||||||
viewV2: buildViewV2Endpoints(API),
|
viewV2: buildViewV2Endpoints(API),
|
||||||
|
rowActions: buildRowActionEndpoints(API),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
export const buildRowActionEndpoints = API => ({
|
||||||
|
/**
|
||||||
|
* Gets the available row actions for a table.
|
||||||
|
* @param tableId the ID of the table
|
||||||
|
*/
|
||||||
|
fetch: async tableId => {
|
||||||
|
const res = await API.get({
|
||||||
|
url: `/api/tables/${tableId}/actions`,
|
||||||
|
})
|
||||||
|
return res?.actions || {}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a row action.
|
||||||
|
* @param name the name of the row action
|
||||||
|
* @param tableId the ID of the table
|
||||||
|
*/
|
||||||
|
create: async ({ name, tableId }) => {
|
||||||
|
return await API.post({
|
||||||
|
url: `/api/tables/${tableId}/actions`,
|
||||||
|
body: {
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a row action.
|
||||||
|
* @param name the new name of the row action
|
||||||
|
* @param tableId the ID of the table
|
||||||
|
* @param rowActionId the ID of the row action to update
|
||||||
|
*/
|
||||||
|
update: async ({ tableId, rowActionId, name }) => {
|
||||||
|
return await API.post({
|
||||||
|
url: `/api/tables/${tableId}/actions/${rowActionId}`,
|
||||||
|
body: {
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a row action.
|
||||||
|
* @param tableId the ID of the table
|
||||||
|
* @param rowActionId the ID of the row action to delete
|
||||||
|
*/
|
||||||
|
delete: async ({ tableId, rowActionId }) => {
|
||||||
|
return await API.delete({
|
||||||
|
url: `/api/tables/${tableId}/actions/${rowActionId}`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a row action.
|
||||||
|
* @param tableId the ID of the table
|
||||||
|
* @param rowActionId the ID of the row action to trigger
|
||||||
|
*/
|
||||||
|
trigger: async ({ tableId, rowActionid }) => {
|
||||||
|
return await API.post({
|
||||||
|
url: `/api/tables/${tableId}/actions/${rowActionId}/trigger`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
Loading…
Reference in New Issue