Initial commit

This commit is contained in:
Dean 2023-10-11 10:09:14 +01:00
parent 088ed1139c
commit b4a8f22b2e
10 changed files with 412 additions and 111 deletions

View File

@ -23,6 +23,7 @@ import BasicColumnEditor from "./controls/ColumnEditor/BasicColumnEditor.svelte"
import GridColumnEditor from "./controls/ColumnEditor/GridColumnEditor.svelte"
import BarButtonList from "./controls/BarButtonList.svelte"
import FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration.svelte"
import ButtonConfiguration from "./controls/ButtonConfiguration/ButtonConfiguration.svelte"
import RelationshipFilterEditor from "./controls/RelationshipFilterEditor.svelte"
const componentMap = {
@ -48,6 +49,7 @@ const componentMap = {
"filter/relationship": RelationshipFilterEditor,
url: URLSelect,
fieldConfiguration: FieldConfiguration,
buttonConfiguration: ButtonConfiguration,
columns: ColumnEditor,
"columns/basic": BasicColumnEditor,
"columns/grid": GridColumnEditor,

View File

@ -0,0 +1,104 @@
<script>
import DraggableList from "../DraggableList.svelte"
import ButtonSetting from "./ButtonSetting.svelte"
import {
getBindableProperties,
getComponentBindableProperties,
} from "builderStore/dataBinding"
import { createEventDispatcher, onMount } from "svelte"
import { selectedScreen, store } from "builderStore"
import { isEqual, cloneDeep } from "lodash"
export let componentInstance
export let value
$: bindings = getBindableProperties($selectedScreen, componentInstance._id)
const dispatch = createEventDispatcher()
let buttonList
let mounted
let cachedValue
let componentBindings = []
$: componentBindings = getComponentBindableProperties(
$selectedScreen,
componentInstance._id
)
$: if (!isEqual(value, cachedValue) && mounted) {
cachedValue = value
? cloneDeep(value)
: [
buildPseudoInstance({ name: `Button 1`, type: "cta" }),
buildPseudoInstance({ name: `Button 2` }),
]
}
const updateState = value => {
buttonList = value
}
$: updateState(cachedValue)
const processItemUpdate = e => {
const updatedField = e.detail
const parentButtonsUpdated = buttonList ? cloneDeep(buttonList) : []
let parentFieldIdx = parentButtonsUpdated.findIndex(pSetting => {
return pSetting._id === updatedField?._id
})
if (parentFieldIdx == -1) {
parentButtonsUpdated.push(updatedField)
} else {
parentButtonsUpdated[parentFieldIdx] = updatedField
}
console.log("On value update ", parentButtonsUpdated)
dispatch("change", parentButtonsUpdated)
}
const listUpdated = e => {
dispatch("change", [...e.detail])
}
// May not be necessary without
const buildPseudoInstance = cfg => {
const pseudoComponentInstance = store.actions.components.createInstance(
`@budibase/standard-components/button`,
{
_instanceName: cfg.name,
text: cfg.name,
type: cfg.type || "primary",
},
{}
)
return pseudoComponentInstance
}
onMount(() => {
mounted = true
})
</script>
<div class="button-configuration">
{#if buttonList?.length}
<DraggableList
on:change={listUpdated}
on:itemChange={processItemUpdate}
items={buttonList}
listItemKey={"_id"}
listType={ButtonSetting}
listTypeProps={{
componentBindings,
bindings,
}}
/>
{/if}
</div>
<style>
.button-configuration :global(.spectrum-ActionButton) {
width: 100%;
}
</style>

View File

@ -0,0 +1,61 @@
<script>
import EditFieldPopover from "../FieldConfiguration/EditFieldPopover.svelte"
import { Icon } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
// import { cloneDeep } from "lodash/fp"
export let item
export let componentBindings
export let bindings
export let anchor
const dispatch = createEventDispatcher()
// const onToggle = item => {
// return e => {
// item.active = e.detail
// dispatch("change", { ...cloneDeep(item), active: e.detail })
// }
// }
</script>
<div class="list-item-body">
<div class="list-item-left">
<EditFieldPopover
{anchor}
field={item}
{componentBindings}
{bindings}
on:change
/>
<div class="field-label">{item.text}</div>
</div>
<div class="list-item-right">
<Icon size="S" name="Close" hoverable on:click={() => {console.log("REMOVE ME")}}
/>
</div>
</div>
<style>
.field-label {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.list-item-body,
.list-item-left {
display: flex;
align-items: center;
gap: var(--spacing-m);
min-width: 0;
}
.list-item-body {
margin-top: 8px;
margin-bottom: 8px;
}
.list-item-right :global(div.spectrum-Switch) {
margin: 0px;
}
.list-item-body {
justify-content: space-between;
}
</style>

View File

@ -1,91 +0,0 @@
<script>
import { Button, ActionButton, Drawer } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import ColumnDrawer from "./ColumnEditor/ColumnDrawer.svelte"
import { cloneDeep } from "lodash/fp"
import {
getDatasourceForProvider,
getSchemaForDatasource,
} from "builderStore/dataBinding"
import { currentAsset } from "builderStore"
import { getFields } from "helpers/searchFields"
export let componentInstance
export let value = []
export let allowCellEditing = true
export let subject = "Table"
const dispatch = createEventDispatcher()
let drawer
let boundValue
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
$: schema = getSchema($currentAsset, datasource)
$: options = allowCellEditing
? Object.keys(schema || {})
: enrichedSchemaFields?.map(field => field.name)
$: sanitisedValue = getValidColumns(value, options)
$: updateBoundValue(sanitisedValue)
$: enrichedSchemaFields = getFields(Object.values(schema || {}), {
allowLinks: true,
})
const getSchema = (asset, datasource) => {
const schema = getSchemaForDatasource(asset, datasource).schema
// Don't show ID and rev in tables
if (schema) {
delete schema._id
delete schema._rev
}
return schema
}
const updateBoundValue = value => {
boundValue = cloneDeep(value)
}
const getValidColumns = (columns, options) => {
if (!Array.isArray(columns) || !columns.length) {
return []
}
// We need to account for legacy configs which would just be an array
// of strings
if (typeof columns[0] === "string") {
columns = columns.map(col => ({
name: col,
displayName: col,
}))
}
return columns.filter(column => {
return options.includes(column.name)
})
}
const open = () => {
updateBoundValue(sanitisedValue)
drawer.show()
}
const save = () => {
dispatch("change", getValidColumns(boundValue, options))
drawer.hide()
}
</script>
<ActionButton on:click={open}>Configure columns</ActionButton>
<Drawer bind:this={drawer} title="{subject} Columns">
<svelte:fragment slot="description">
Configure the columns in your {subject.toLowerCase()}.
</svelte:fragment>
<Button cta slot="buttons" on:click={save}>Save</Button>
<ColumnDrawer
slot="body"
bind:columns={boundValue}
{options}
{schema}
{allowCellEditing}
/>
</Drawer>

View File

@ -61,6 +61,25 @@
dispatch("change", update)
}
const customPositionHandler = (anchorBounds, eleBounds, cfg) => {
let { left, top } = cfg
let percentageOffset = 30
// left-outside
left = anchorBounds.left - eleBounds.width - 18
// shift up from the anchor, if space allows
let offsetPos = Math.floor(eleBounds.height / 100) * percentageOffset
let defaultTop = anchorBounds.top - offsetPos
if (window.innerHeight - defaultTop < eleBounds.height) {
top = window.innerHeight - eleBounds.height - 5
} else {
top = anchorBounds.top - offsetPos
}
return { ...cfg, left, top }
}
</script>
<Icon
@ -92,24 +111,7 @@
showPopover={drawers.length == 0}
clickOutsideOverride={drawers.length > 0}
maxHeight={600}
handlePostionUpdate={(anchorBounds, eleBounds, cfg) => {
let { left, top } = cfg
let percentageOffset = 30
// left-outside
left = anchorBounds.left - eleBounds.width - 18
// shift up from the anchor, if space allows
let offsetPos = Math.floor(eleBounds.height / 100) * percentageOffset
let defaultTop = anchorBounds.top - offsetPos
if (window.innerHeight - defaultTop < eleBounds.height) {
top = window.innerHeight - eleBounds.height - 5
} else {
top = anchorBounds.top - offsetPos
}
return { ...cfg, left, top }
}}
handlePostionUpdate={customPositionHandler}
>
<span class="popover-wrap">
<Layout noPadding noGap>

View File

@ -50,7 +50,7 @@
updateSanitsedFields(sanitisedValue)
unconfigured = buildUnconfiguredOptions(schema, sanitisedFields)
fieldList = [...sanitisedFields, ...unconfigured]
.map(buildSudoInstance)
.map(buildPseudoInstance)
.filter(x => x != null)
}
@ -104,7 +104,7 @@
})
}
const buildSudoInstance = instance => {
const buildPseudoInstance = instance => {
if (instance._component) {
return instance
}

View File

@ -36,6 +36,7 @@
"heading",
"text",
"button",
"buttongroup",
"tag",
"spectrumcard",
"cardstat",

View File

@ -258,6 +258,189 @@
"description": "Contains your app screens",
"static": true
},
"buttongroup": {
"name": "Button group",
"icon": "Button",
"hasChildren": false,
"settings": [
{
"section": true,
"name": "Buttons",
"settings": [
{
"type": "buttonConfiguration",
"key": "buttons",
"nested": true,
"defaultValue" : [{
"component" : "button",
"props" : {
"type": "cta"
}
},{
"component" : "button",
"props" : {
"type" : "primary"
}
}]
}
]
},
{
"section": true,
"name": "Layout",
"settings": [
{
"type": "select",
"label": "Direction",
"key": "direction",
"showInBar": true,
"barStyle": "buttons",
"options": [
{
"label": "Column",
"value": "column",
"barIcon": "ViewColumn",
"barTitle": "Column layout"
},
{
"label": "Row",
"value": "row",
"barIcon": "ViewRow",
"barTitle": "Row layout"
}
],
"defaultValue": "column"
},
{
"type": "select",
"label": "Horiz. align",
"key": "hAlign",
"showInBar": true,
"barStyle": "buttons",
"options": [
{
"label": "Left",
"value": "left",
"barIcon": "AlignLeft",
"barTitle": "Align left"
},
{
"label": "Center",
"value": "center",
"barIcon": "AlignCenter",
"barTitle": "Align center"
},
{
"label": "Right",
"value": "right",
"barIcon": "AlignRight",
"barTitle": "Align right"
},
{
"label": "Stretch",
"value": "stretch",
"barIcon": "MoveLeftRight",
"barTitle": "Align stretched horizontally"
}
],
"defaultValue": "left"
},
{
"type": "select",
"label": "Vert. align",
"key": "vAlign",
"showInBar": true,
"barStyle": "buttons",
"options": [
{
"label": "Top",
"value": "top",
"barIcon": "AlignTop",
"barTitle": "Align top"
},
{
"label": "Middle",
"value": "middle",
"barIcon": "AlignMiddle",
"barTitle": "Align middle"
},
{
"label": "Bottom",
"value": "bottom",
"barIcon": "AlignBottom",
"barTitle": "Align bottom"
},
{
"label": "Stretch",
"value": "stretch",
"barIcon": "MoveUpDown",
"barTitle": "Align stretched vertically"
}
],
"defaultValue": "top"
},
{
"type": "select",
"label": "Size",
"key": "size",
"showInBar": true,
"barStyle": "buttons",
"options": [
{
"label": "Shrink",
"value": "shrink",
"barIcon": "Minimize",
"barTitle": "Shrink container"
},
{
"label": "Grow",
"value": "grow",
"barIcon": "Maximize",
"barTitle": "Grow container"
}
],
"defaultValue": "shrink"
},
{
"type": "select",
"label": "Gap",
"key": "gap",
"showInBar": true,
"barStyle": "picker",
"options": [
{
"label": "None",
"value": "N"
},
{
"label": "Small",
"value": "S"
},
{
"label": "Medium",
"value": "M"
},
{
"label": "Large",
"value": "L"
}
],
"defaultValue": "M"
},
{
"type": "boolean",
"label": "Wrap",
"key": "wrap",
"showInBar": true,
"barIcon": "ModernGridView",
"barTitle": "Wrap"
}
]
}
]
},
"button": {
"name": "Button",
"description": "A basic html button that is ready for styling",

View File

@ -0,0 +1,38 @@
<script>
import { getContext } from "svelte"
import Container from "components/app/Container.svelte"
import BlockComponent from "../../BlockComponent.svelte"
import Block from "../../Block.svelte"
const { styleable } = getContext("sdk")
const component = getContext("component")
export let buttons = []
export let direction
export let hAlign
export let vAlign
export let gap = "S"
export let wrap
$: console.log("client buttons/wrap", buttons, wrap)
</script>
<!-- <div use:styleable={$component.styles}> -->
<Block>
<Container {direction} {hAlign} {vAlign} {gap} {wrap}>
{#each buttons as { text, type, quiet, disabled, onClick, size }}
<BlockComponent
type="button"
props={{
text,
onClick,
type,
quiet,
disabled,
size
}}
/>
{/each}
</Container>
</Block>
<!-- </div> -->

View File

@ -16,3 +16,4 @@ export { default as jsonfield } from "./JSONField.svelte"
export { default as s3upload } from "./S3Upload.svelte"
export { default as codescanner } from "./CodeScannerField.svelte"
export { default as bbreferencefield } from "./BBReferenceField.svelte"
export { default as buttongroup } from "./ButtonGroup.svelte"