forked from tsai/budibase
15 changed files with 255 additions and 342 deletions
@ -0,0 +1,50 @@ |
|||||
|
<script> |
||||
|
import { DetailSummary, ActionButton } from "@budibase/bbui" |
||||
|
import { currentAsset, store } from "builderStore" |
||||
|
import { findClosestMatchingComponent } from "builderStore/storeUtils" |
||||
|
import { makeDatasourceFormComponents } from "builderStore/store/screenTemplates/utils/commonComponents" |
||||
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte" |
||||
|
|
||||
|
export let openSection |
||||
|
export let componentDefinition |
||||
|
export let componentInstance |
||||
|
|
||||
|
let confirmResetFieldsDialog |
||||
|
|
||||
|
const resetFormFields = () => { |
||||
|
const form = findClosestMatchingComponent( |
||||
|
$currentAsset.props, |
||||
|
componentInstance._id, |
||||
|
component => component._component.endsWith("/form") |
||||
|
) |
||||
|
const dataSource = form?.dataSource |
||||
|
const fields = makeDatasourceFormComponents(dataSource) |
||||
|
store.actions.components.updateProp( |
||||
|
"_children", |
||||
|
fields.map(field => field.json()) |
||||
|
) |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<DetailSummary name="Actions" on:open show={openSection === "actions"}> |
||||
|
<ActionButton secondary wide on:click={store.actions.components.resetStyles}> |
||||
|
Reset styles |
||||
|
</ActionButton> |
||||
|
{#if componentDefinition?.component?.endsWith("/fieldgroup")} |
||||
|
<ActionButton |
||||
|
secondary |
||||
|
wide |
||||
|
on:click={() => confirmResetFieldsDialog?.show()} |
||||
|
> |
||||
|
Update form fields |
||||
|
</ActionButton> |
||||
|
{/if} |
||||
|
</DetailSummary> |
||||
|
|
||||
|
<ConfirmDialog |
||||
|
bind:this={confirmResetFieldsDialog} |
||||
|
body={`All components inside this group will be deleted and replaced with fields to match the schema. Are you sure you want to update this Field Group?`} |
||||
|
okText="Update" |
||||
|
onOk={resetFormFields} |
||||
|
title="Confirm Form Field Update" |
||||
|
/> |
||||
@ -1,40 +0,0 @@ |
|||||
<script> |
|
||||
export let categories = [] |
|
||||
export let selectedCategory = {} |
|
||||
export let onClick = () => {} |
|
||||
</script> |
|
||||
|
|
||||
<div class="tabs"> |
|
||||
{#each categories as category} |
|
||||
<li |
|
||||
data-cy={category.name} |
|
||||
on:click={() => onClick(category)} |
|
||||
class:active={selectedCategory === category} |
|
||||
> |
|
||||
{category.name} |
|
||||
</li> |
|
||||
{/each} |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.tabs { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: flex-start; |
|
||||
align-items: center; |
|
||||
list-style: none; |
|
||||
font-size: var(--font-size-m); |
|
||||
font-weight: 600; |
|
||||
height: 24px; |
|
||||
} |
|
||||
|
|
||||
li { |
|
||||
color: var(--grey-5); |
|
||||
cursor: pointer; |
|
||||
margin-right: 20px; |
|
||||
} |
|
||||
|
|
||||
.active { |
|
||||
color: var(--ink); |
|
||||
} |
|
||||
</style> |
|
||||
@ -0,0 +1,33 @@ |
|||||
|
<script> |
||||
|
import { TextArea, DetailSummary } from "@budibase/bbui" |
||||
|
import { store } from "builderStore" |
||||
|
|
||||
|
export let componentInstance |
||||
|
export let openSection |
||||
|
|
||||
|
function onChange(css) { |
||||
|
store.actions.components.updateCustomStyle(css) |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<DetailSummary |
||||
|
name={`Custom Styles${componentInstance?._styles?.custom ? " *" : ""}`} |
||||
|
on:open |
||||
|
show={openSection === "custom"} |
||||
|
> |
||||
|
<div class="custom-styles"> |
||||
|
<TextArea |
||||
|
value={componentInstance?._styles?.custom} |
||||
|
on:change={event => onChange(event.detail)} |
||||
|
placeholder="Enter some CSS..." |
||||
|
/> |
||||
|
</div> |
||||
|
</DetailSummary> |
||||
|
|
||||
|
<style> |
||||
|
.custom-styles :global(textarea) { |
||||
|
font-family: monospace; |
||||
|
min-height: 120px; |
||||
|
font-size: var(--font-size-xs); |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,42 @@ |
|||||
|
<script> |
||||
|
import { DetailSummary } from "@budibase/bbui" |
||||
|
import PropertyGroup from "./PropertyControls/PropertyGroup.svelte" |
||||
|
import { allStyles } from "./componentStyles" |
||||
|
import { store } from "builderStore" |
||||
|
|
||||
|
export let componentDefinition |
||||
|
export let componentInstance |
||||
|
export let openSection |
||||
|
|
||||
|
let selectedCategory = "normal" |
||||
|
let currentGroup |
||||
|
|
||||
|
$: groups = componentDefinition?.styleable ? Object.keys(allStyles) : [] |
||||
|
</script> |
||||
|
|
||||
|
<DetailSummary name="Design" show={openSection === "design"} on:open> |
||||
|
{#if groups.length > 0} |
||||
|
{#each groups as groupName} |
||||
|
<PropertyGroup |
||||
|
name={groupName} |
||||
|
properties={allStyles[groupName]} |
||||
|
styleCategory={selectedCategory} |
||||
|
onStyleChanged={store.actions.components.updateStyle} |
||||
|
{componentInstance} |
||||
|
open={currentGroup === groupName} |
||||
|
on:open={() => (currentGroup = groupName)} |
||||
|
/> |
||||
|
{/each} |
||||
|
{:else} |
||||
|
<div class="no-design"> |
||||
|
This component doesn't have any design properties. |
||||
|
</div> |
||||
|
{/if} |
||||
|
</DetailSummary> |
||||
|
|
||||
|
<style> |
||||
|
.no-design { |
||||
|
font-size: var(--spectrum-global-dimension-font-size-75); |
||||
|
color: var(--grey-6); |
||||
|
} |
||||
|
</style> |
||||
@ -1,111 +0,0 @@ |
|||||
<script> |
|
||||
import { TextArea, DetailSummary, Button } from "@budibase/bbui" |
|
||||
import PropertyGroup from "./PropertyControls/PropertyGroup.svelte" |
|
||||
import FlatButtonGroup from "./PropertyControls/FlatButtonGroup" |
|
||||
import { allStyles } from "./componentStyles" |
|
||||
|
|
||||
export let componentDefinition = {} |
|
||||
export let componentInstance = {} |
|
||||
export let onStyleChanged = () => {} |
|
||||
export let onCustomStyleChanged = () => {} |
|
||||
export let onResetStyles = () => {} |
|
||||
|
|
||||
let selectedCategory = "normal" |
|
||||
let currentGroup |
|
||||
|
|
||||
function onChange(category) { |
|
||||
selectedCategory = category |
|
||||
} |
|
||||
|
|
||||
const buttonProps = [ |
|
||||
{ value: "normal", text: "Normal" }, |
|
||||
{ value: "hover", text: "Hover" }, |
|
||||
{ value: "active", text: "Active" }, |
|
||||
] |
|
||||
|
|
||||
$: groups = componentDefinition?.styleable ? Object.keys(allStyles) : [] |
|
||||
</script> |
|
||||
|
|
||||
<div class="container"> |
|
||||
<div class="state-categories"> |
|
||||
<FlatButtonGroup value={selectedCategory} {buttonProps} {onChange} /> |
|
||||
</div> |
|
||||
|
|
||||
<div class="positioned-wrapper"> |
|
||||
<div class="property-groups"> |
|
||||
{#if groups.length > 0} |
|
||||
{#each groups as groupName} |
|
||||
<PropertyGroup |
|
||||
name={groupName} |
|
||||
properties={allStyles[groupName]} |
|
||||
styleCategory={selectedCategory} |
|
||||
{onStyleChanged} |
|
||||
{componentInstance} |
|
||||
open={currentGroup === groupName} |
|
||||
on:open={() => (currentGroup = groupName)} |
|
||||
/> |
|
||||
{/each} |
|
||||
<DetailSummary |
|
||||
name={`Custom Styles${componentInstance._styles.custom ? " *" : ""}`} |
|
||||
on:open={() => (currentGroup = "custom")} |
|
||||
show={currentGroup === "custom"} |
|
||||
thin |
|
||||
> |
|
||||
<div class="custom-styles"> |
|
||||
<TextArea |
|
||||
value={componentInstance._styles.custom} |
|
||||
on:change={event => onCustomStyleChanged(event.detail)} |
|
||||
placeholder="Enter some CSS..." |
|
||||
/> |
|
||||
</div> |
|
||||
</DetailSummary> |
|
||||
<Button secondary wide on:click={onResetStyles}>Reset Styles</Button> |
|
||||
{:else} |
|
||||
<div class="no-design"> |
|
||||
This component doesn't have any design properties. |
|
||||
</div> |
|
||||
{/if} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.container { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
gap: var(--spacing-l); |
|
||||
} |
|
||||
|
|
||||
.positioned-wrapper { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
min-height: 0; |
|
||||
flex: 1 1 auto; |
|
||||
} |
|
||||
|
|
||||
.property-groups { |
|
||||
flex: 1; |
|
||||
overflow-y: auto; |
|
||||
min-height: 0; |
|
||||
margin: 0 -20px; |
|
||||
padding: 0 20px; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: flex-start; |
|
||||
align-items: stretch; |
|
||||
gap: var(--spacing-m); |
|
||||
} |
|
||||
|
|
||||
.no-design { |
|
||||
font-size: var(--font-size-xs); |
|
||||
color: var(--grey-5); |
|
||||
} |
|
||||
|
|
||||
.custom-styles :global(textarea) { |
|
||||
font-family: monospace; |
|
||||
min-height: 120px; |
|
||||
font-size: var(--font-size-xs); |
|
||||
} |
|
||||
</style> |
|
||||
Loading…
Reference in new issue