1
0
Fork 0
mirror of synced 2024-08-16 02:22:08 +12:00

Merge pull request #6676 from Budibase/feature/app-action-ui-updates

Feature/app action UI updates
This commit is contained in:
deanhannigan 2022-07-15 10:46:58 +01:00 committed by GitHub
commit 998f48e171
3 changed files with 146 additions and 17 deletions

View file

@ -6,8 +6,8 @@
Button, Button,
Layout, Layout,
DrawerContent, DrawerContent,
ActionMenu, ActionButton,
MenuItem, Search,
} from "@budibase/bbui" } from "@budibase/bbui"
import { getAvailableActions } from "./index" import { getAvailableActions } from "./index"
import { generate } from "shortid" import { generate } from "shortid"
@ -22,8 +22,24 @@
export let actions export let actions
export let bindings = [] export let bindings = []
$: showAvailableActions = !actions?.length
let actionQuery
$: parsedQuery =
typeof actionQuery === "string" ? actionQuery.toLowerCase().trim() : ""
let selectedAction = actions?.length ? actions[0] : null let selectedAction = actions?.length ? actions[0] : null
$: mappedActionTypes = actionTypes.reduce((acc, action) => {
let parsedName = action.name.toLowerCase().trim()
if (parsedQuery.length && parsedName.indexOf(parsedQuery) < 0) {
return acc
}
acc[action.type] = acc[action.type] || []
acc[action.type].push(action)
return acc
}, {})
// These are ephemeral bindings which only exist while executing actions // These are ephemeral bindings which only exist while executing actions
$: buttonContextBindings = getButtonContextBindings( $: buttonContextBindings = getButtonContextBindings(
$currentAsset, $currentAsset,
@ -61,7 +77,12 @@
actions = actions actions = actions
} }
const addAction = actionType => () => { const toggleActionList = () => {
actionQuery = null
showAvailableActions = !showAvailableActions
}
const addAction = actionType => {
const newAction = { const newAction = {
parameters: {}, parameters: {},
[EVENT_TYPE_KEY]: actionType.name, [EVENT_TYPE_KEY]: actionType.name,
@ -78,6 +99,11 @@
selectedAction = action selectedAction = action
} }
const onAddAction = actionType => {
addAction(actionType)
toggleActionList()
}
function handleDndConsider(e) { function handleDndConsider(e) {
actions = e.detail.items actions = e.detail.items
} }
@ -88,7 +114,39 @@
<DrawerContent> <DrawerContent>
<Layout noPadding gap="S" slot="sidebar"> <Layout noPadding gap="S" slot="sidebar">
{#if actions && actions.length > 0} {#if showAvailableActions || !actions?.length}
<div class="actions-list">
{#if actions?.length > 0}
<div>
<ActionButton
secondary
icon={"ArrowLeft"}
on:click={toggleActionList}
>
Back
</ActionButton>
</div>
{/if}
<div class="search-wrap">
<Search placeholder="Search" bind:value={actionQuery} />
</div>
{#each Object.entries(mappedActionTypes) as [categoryId, category], idx}
<div class="heading" class:top-entry={idx === 0}>{categoryId}</div>
<ul>
{#each category as actionType}
<li on:click={onAddAction(actionType)}>
<span class="action-name">{actionType.name}</span>
</li>
{/each}
</ul>
{/each}
</div>
{/if}
{#if actions && actions.length > 0 && !showAvailableActions}
<div>
<Button secondary on:click={toggleActionList}>Add Action</Button>
</div>
<div <div
class="actions" class="actions"
use:dndzone={{ use:dndzone={{
@ -120,17 +178,9 @@
{/each} {/each}
</div> </div>
{/if} {/if}
<ActionMenu>
<Button slot="control" secondary>Add Action</Button>
{#each actionTypes as actionType}
<MenuItem on:click={addAction(actionType)}>
{actionType.name}
</MenuItem>
{/each}
</ActionMenu>
</Layout> </Layout>
<Layout noPadding> <Layout noPadding>
{#if selectedActionComponent} {#if selectedActionComponent && !showAvailableActions}
{#key selectedAction.id} {#key selectedAction.id}
<div class="selected-action-container"> <div class="selected-action-container">
<svelte:component <svelte:component
@ -152,13 +202,10 @@
align-items: stretch; align-items: stretch;
gap: var(--spacing-s); gap: var(--spacing-s);
} }
.action-header { .action-header {
color: var(--spectrum-global-color-gray-700); color: var(--spectrum-global-color-gray-700);
flex: 1 1 auto; flex: 1 1 auto;
} }
.action-container { .action-container {
background-color: var(--background); background-color: var(--background);
padding: var(--spacing-s) var(--spacing-m); padding: var(--spacing-s) var(--spacing-m);
@ -182,4 +229,55 @@
.action-container.selected .action-header { .action-container.selected .action-header {
color: var(--spectrum-global-color-gray-900); color: var(--spectrum-global-color-gray-900);
} }
.actions-list > * {
padding-bottom: var(--spectrum-global-dimension-static-size-200);
}
.actions-list .heading {
padding-bottom: var(--spectrum-global-dimension-static-size-100);
padding-top: var(--spectrum-global-dimension-static-size-50);
}
.actions-list .heading.top-entry {
padding-top: 0px;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
font-size: var(--font-size-s);
padding: var(--spacing-m);
border-radius: 4px;
background-color: var(--spectrum-global-color-gray-200);
transition: background-color 130ms ease-in-out, color 130ms ease-in-out,
border-color 130ms ease-in-out;
word-wrap: break-word;
}
li:not(:last-of-type) {
margin-bottom: var(--spacing-s);
}
li :global(*) {
transition: color 130ms ease-in-out;
}
li:hover {
color: var(--spectrum-global-color-gray-900);
background-color: var(--spectrum-global-color-gray-50);
cursor: pointer;
}
.action-name {
font-weight: 600;
text-transform: capitalize;
}
.heading {
font-size: var(--font-size-s);
font-weight: 600;
text-transform: uppercase;
color: var(--spectrum-global-color-gray-600);
}
</style> </style>

View file

@ -69,9 +69,16 @@
notifications.error("Error creating automation") notifications.error("Error creating automation")
} }
} }
$: actionCount = value?.length
$: actionText = `${actionCount || "No"} action${
actionCount !== 1 ? "s" : ""
} set`
</script> </script>
<div class="action-count">{actionText}</div>
<ActionButton on:click={openDrawer}>Define actions</ActionButton> <ActionButton on:click={openDrawer}>Define actions</ActionButton>
<Drawer bind:this={drawer} title={"Actions"}> <Drawer bind:this={drawer} title={"Actions"}>
<svelte:fragment slot="description"> <svelte:fragment slot="description">
Define what actions to run. Define what actions to run.
@ -85,3 +92,10 @@
{key} {key}
/> />
</Drawer> </Drawer>
<style>
.action-count {
padding-bottom: var(--spacing-s);
font-weight: 600;
}
</style>

View file

@ -2,6 +2,7 @@
"actions": [ "actions": [
{ {
"name": "Save Row", "name": "Save Row",
"type": "data",
"component": "SaveRow", "component": "SaveRow",
"context": [ "context": [
{ {
@ -12,6 +13,7 @@
}, },
{ {
"name": "Duplicate Row", "name": "Duplicate Row",
"type": "data",
"component": "DuplicateRow", "component": "DuplicateRow",
"context": [ "context": [
{ {
@ -22,14 +24,17 @@
}, },
{ {
"name": "Delete Row", "name": "Delete Row",
"type": "data",
"component": "DeleteRow" "component": "DeleteRow"
}, },
{ {
"name": "Navigate To", "name": "Navigate To",
"type": "application",
"component": "NavigateTo" "component": "NavigateTo"
}, },
{ {
"name": "Execute Query", "name": "Execute Query",
"type": "data",
"component": "ExecuteQuery", "component": "ExecuteQuery",
"context": [ "context": [
{ {
@ -40,43 +45,53 @@
}, },
{ {
"name": "Trigger Automation", "name": "Trigger Automation",
"type": "application",
"component": "TriggerAutomation" "component": "TriggerAutomation"
}, },
{ {
"name": "Update Field Value", "name": "Update Field Value",
"type": "form",
"component": "UpdateFieldValue" "component": "UpdateFieldValue"
}, },
{ {
"name": "Validate Form", "name": "Validate Form",
"type": "form",
"component": "ValidateForm" "component": "ValidateForm"
}, },
{ {
"name": "Change Form Step", "name": "Change Form Step",
"type": "form",
"component": "ChangeFormStep" "component": "ChangeFormStep"
}, },
{ {
"name": "Clear Form", "name": "Clear Form",
"type": "form",
"component": "ClearForm" "component": "ClearForm"
}, },
{ {
"name": "Log Out", "name": "Log Out",
"type": "application",
"component": "LogOut" "component": "LogOut"
}, },
{ {
"name": "Close Screen Modal", "name": "Close Screen Modal",
"type": "application",
"component": "CloseScreenModal" "component": "CloseScreenModal"
}, },
{ {
"name": "Refresh Data Provider", "name": "Refresh Data Provider",
"type": "data",
"component": "RefreshDataProvider" "component": "RefreshDataProvider"
}, },
{ {
"name": "Update State", "name": "Update State",
"type": "data",
"component": "UpdateState", "component": "UpdateState",
"dependsOnFeature": "state" "dependsOnFeature": "state"
}, },
{ {
"name": "Upload File to S3", "name": "Upload File to S3",
"type": "data",
"component": "S3Upload", "component": "S3Upload",
"context": [ "context": [
{ {
@ -87,10 +102,12 @@
}, },
{ {
"name": "Export Data", "name": "Export Data",
"type": "data",
"component": "ExportData" "component": "ExportData"
}, },
{ {
"name": "Continue if / Stop if", "name": "Continue if / Stop if",
"type": "logic",
"component": "ContinueIf", "component": "ContinueIf",
"dependsOnFeature": "continueIfAction" "dependsOnFeature": "continueIfAction"
} }