forked from tsai/budibase
committed by
GitHub
27 changed files with 67 additions and 748 deletions
@ -1,62 +0,0 @@ |
|||||
<script> |
|
||||
import { onMount } from "svelte" |
|
||||
import { buildStyle } from "../../helpers.js" |
|
||||
export let value = "" |
|
||||
export let name = "" |
|
||||
export let textAlign = "left" |
|
||||
export let width = "160px" |
|
||||
export let placeholder = "" |
|
||||
export let suffix = "" |
|
||||
export let onChange = val => {} |
|
||||
|
|
||||
let centerPlaceholder = textAlign === "center" |
|
||||
|
|
||||
let style = buildStyle({ width, textAlign }) |
|
||||
|
|
||||
function handleChange(val) { |
|
||||
value = val |
|
||||
let _value = value !== "auto" ? value + suffix : value |
|
||||
onChange(_value) |
|
||||
} |
|
||||
|
|
||||
$: displayValue = |
|
||||
suffix && value && value.endsWith(suffix) |
|
||||
? value.replace(new RegExp(`${suffix}$`), "") |
|
||||
: value || "" |
|
||||
</script> |
|
||||
|
|
||||
<input |
|
||||
{name} |
|
||||
class:centerPlaceholder |
|
||||
type="text" |
|
||||
value={displayValue} |
|
||||
{placeholder} |
|
||||
{style} |
|
||||
on:change={e => handleChange(e.target.value)} /> |
|
||||
|
|
||||
<style> |
|
||||
input { |
|
||||
/* width: 32px; */ |
|
||||
height: 36px; |
|
||||
font-size: 14px; |
|
||||
font-weight: 400; |
|
||||
margin: 0px 0px 0px 2px; |
|
||||
color: var(--ink); |
|
||||
padding: 0px 8px; |
|
||||
font-family: inter; |
|
||||
width: 164px; |
|
||||
box-sizing: border-box; |
|
||||
background-color: var(--grey-2); |
|
||||
border-radius: 4px; |
|
||||
border: 1px solid var(--grey-2); |
|
||||
outline: none; |
|
||||
} |
|
||||
|
|
||||
input::placeholder { |
|
||||
text-align: left; |
|
||||
} |
|
||||
|
|
||||
.centerPlaceholder::placeholder { |
|
||||
text-align: center; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,50 +0,0 @@ |
|||||
<script> |
|
||||
import { onMount } from "svelte" |
|
||||
import Input from "../Input.svelte" |
|
||||
|
|
||||
export let meta = [] |
|
||||
export let label = "" |
|
||||
export let value = ["0", "0", "0", "0"] |
|
||||
export let suffix = "" |
|
||||
|
|
||||
export let onChange = () => {} |
|
||||
|
|
||||
function handleChange(val, idx) { |
|
||||
value.splice(idx, 1, val !== "auto" && suffix ? val + suffix : val) |
|
||||
|
|
||||
value = value |
|
||||
let _value = value.map(v => |
|
||||
suffix && !v.endsWith(suffix) && v !== "auto" ? v + suffix : v |
|
||||
) |
|
||||
onChange(_value) |
|
||||
} |
|
||||
|
|
||||
$: displayValues = |
|
||||
value && suffix |
|
||||
? value.map(v => v.replace(new RegExp(`${suffix}$`), "")) |
|
||||
: value || [] |
|
||||
</script> |
|
||||
|
|
||||
<div class="input-container"> |
|
||||
<div class="label">{label}</div> |
|
||||
<div class="inputs-group"> |
|
||||
{#each meta as m, i} |
|
||||
<Input |
|
||||
width="37px" |
|
||||
textAlign="center" |
|
||||
placeholder={m.placeholder || ''} |
|
||||
value={!displayValues || displayValues[i] === '0' ? '' : displayValues[i]} |
|
||||
onChange={value => handleChange(value || 0, i)} /> |
|
||||
{/each} |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.label { |
|
||||
flex: 0; |
|
||||
} |
|
||||
|
|
||||
.inputs-group { |
|
||||
flex: 1; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,65 +0,0 @@ |
|||||
<script> |
|
||||
import getIcon from "./icon" |
|
||||
|
|
||||
export let icon |
|
||||
export let value |
|
||||
</script> |
|
||||
|
|
||||
<div class="select-container"> |
|
||||
{#if icon} |
|
||||
<i class={icon} /> |
|
||||
{/if} |
|
||||
<select class:adjusted={icon} on:change bind:value> |
|
||||
<slot /> |
|
||||
</select> |
|
||||
<span class="arrow"> |
|
||||
{@html getIcon('chevron-down', '24')} |
|
||||
</span> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.select-container { |
|
||||
font-size: 14px; |
|
||||
position: relative; |
|
||||
border: var(--grey-4) 1px solid; |
|
||||
} |
|
||||
|
|
||||
.adjusted { |
|
||||
padding-left: 30px; |
|
||||
} |
|
||||
|
|
||||
i { |
|
||||
position: absolute; |
|
||||
left: 10px; |
|
||||
top: 10px; |
|
||||
} |
|
||||
|
|
||||
select { |
|
||||
height: 40px; |
|
||||
display: block; |
|
||||
font-family: sans-serif; |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: var(--ink); |
|
||||
padding: 0 40px 0px 20px; |
|
||||
width: 100%; |
|
||||
max-width: 100%; |
|
||||
box-sizing: border-box; |
|
||||
margin: 0; |
|
||||
-moz-appearance: none; |
|
||||
-webkit-appearance: none; |
|
||||
appearance: none; |
|
||||
background: var(--white); |
|
||||
} |
|
||||
|
|
||||
.arrow { |
|
||||
position: absolute; |
|
||||
right: 10px; |
|
||||
bottom: 0; |
|
||||
margin: auto; |
|
||||
width: 30px; |
|
||||
height: 30px; |
|
||||
pointer-events: none; |
|
||||
color: var(--ink); |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,94 +0,0 @@ |
|||||
<script> |
|
||||
import { store, backendUiStore } from "builderStore" |
|
||||
import ActionButton from "components/common/ActionButton.svelte" |
|
||||
import * as api from "../api" |
|
||||
|
|
||||
export let onClosed |
|
||||
|
|
||||
let username |
|
||||
let password |
|
||||
let accessLevelId |
|
||||
|
|
||||
$: valid = username && password && accessLevelId |
|
||||
$: appId = $store.appId |
|
||||
|
|
||||
async function createUser() { |
|
||||
const user = { name: username, username, password, accessLevelId } |
|
||||
const response = await api.createUser(user) |
|
||||
backendUiStore.actions.users.create(response) |
|
||||
onClosed() |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<form on:submit|preventDefault class="uk-form-stacked"> |
|
||||
<div class="main"> |
|
||||
<div class="heading"> |
|
||||
<i class="ri-list-settings-line button--toggled" /> |
|
||||
<div class="title">Create User</div> |
|
||||
</div> |
|
||||
<div class="uk-margin"> |
|
||||
<label class="uk-form-label" for="form-stacked-text">Username</label> |
|
||||
<input |
|
||||
data-cy="username" |
|
||||
class="uk-input" |
|
||||
type="text" |
|
||||
bind:value={username} /> |
|
||||
</div> |
|
||||
<div class="uk-margin"> |
|
||||
<label class="uk-form-label" for="form-stacked-text">Password</label> |
|
||||
<input |
|
||||
data-cy="password" |
|
||||
class="uk-input" |
|
||||
type="password" |
|
||||
bind:value={password} /> |
|
||||
</div> |
|
||||
<div class="uk-margin"> |
|
||||
<label class="uk-form-label" for="form-stacked-text">Access Level</label> |
|
||||
<select |
|
||||
data-cy="accessLevel" |
|
||||
class="uk-select" |
|
||||
bind:value={accessLevelId}> |
|
||||
<option value="" /> |
|
||||
<option value="POWER_USER">Power User</option> |
|
||||
<option value="ADMIN">Admin</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
</div> |
|
||||
<footer> |
|
||||
<div class="button"> |
|
||||
<ActionButton secondary on:click={onClosed}>Cancel</ActionButton> |
|
||||
</div> |
|
||||
<ActionButton disabled={!valid} on:click={createUser}>Save</ActionButton> |
|
||||
</footer> |
|
||||
</form> |
|
||||
|
|
||||
<style> |
|
||||
.main { |
|
||||
padding: 40px 40px 20px 40px; |
|
||||
} |
|
||||
|
|
||||
.title { |
|
||||
font-size: 24px; |
|
||||
font-weight: 600; |
|
||||
color: var(--ink); |
|
||||
margin-left: 12px; |
|
||||
} |
|
||||
|
|
||||
.heading { |
|
||||
display: flex; |
|
||||
align-items: baseline; |
|
||||
} |
|
||||
|
|
||||
footer { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: flex-end; |
|
||||
padding: 20px; |
|
||||
background: var(--grey-1); |
|
||||
border-radius: 0 0 5px 5px; |
|
||||
} |
|
||||
|
|
||||
.button { |
|
||||
margin-right: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,170 +0,0 @@ |
|||||
<script> |
|
||||
import InputGroup from "../common/Inputs/InputGroup.svelte" |
|
||||
import LayoutTemplateControls from "./LayoutTemplateControls.svelte" |
|
||||
|
|
||||
export let onStyleChanged = () => {} |
|
||||
export let component |
|
||||
|
|
||||
const tbrl = [ |
|
||||
{ placeholder: "T" }, |
|
||||
{ placeholder: "R" }, |
|
||||
{ placeholder: "B" }, |
|
||||
{ placeholder: "L" }, |
|
||||
] |
|
||||
|
|
||||
const se = [{ placeholder: "START" }, { placeholder: "END" }] |
|
||||
|
|
||||
const single = [{ placeholder: "" }] |
|
||||
|
|
||||
$: layout = { |
|
||||
...component._styles.position, |
|
||||
...component._styles.layout, |
|
||||
} |
|
||||
|
|
||||
$: layouts = { |
|
||||
templaterows: ["Grid Rows", single], |
|
||||
templatecolumns: ["Grid Columns", single], |
|
||||
} |
|
||||
|
|
||||
$: display = { |
|
||||
direction: ["Direction", single], |
|
||||
align: ["Align", single], |
|
||||
justify: ["Justify", single], |
|
||||
} |
|
||||
|
|
||||
$: positions = { |
|
||||
column: ["Column", se], |
|
||||
row: ["Row", se], |
|
||||
} |
|
||||
|
|
||||
$: spacing = { |
|
||||
margin: ["Margin", tbrl, "small"], |
|
||||
padding: ["Padding", tbrl, "small"], |
|
||||
} |
|
||||
|
|
||||
$: size = { |
|
||||
height: ["Height", single], |
|
||||
width: ["Width", single], |
|
||||
} |
|
||||
|
|
||||
$: zindex = { |
|
||||
zindex: ["Z-Index", single], |
|
||||
} |
|
||||
|
|
||||
const newValue = n => Array(n).fill("") |
|
||||
</script> |
|
||||
|
|
||||
<h3>Layout</h3> |
|
||||
<div class="layout-pos"> |
|
||||
{#each Object.entries(display) as [key, [name, meta, size]] (component._id + key)} |
|
||||
<div class="grid"> |
|
||||
<h5>{name}:</h5> |
|
||||
<LayoutTemplateControls |
|
||||
onStyleChanged={_value => onStyleChanged('layout', key, _value)} |
|
||||
values={layout[key] || newValue(meta.length)} |
|
||||
propertyName={name} |
|
||||
{meta} |
|
||||
{size} |
|
||||
type="text" /> |
|
||||
</div> |
|
||||
{/each} |
|
||||
</div> |
|
||||
|
|
||||
<!-- <h4>Positioning</h4> |
|
||||
<div class="layout-pos"> |
|
||||
{#each Object.entries(positions) as [key, [name, meta, size]] (component._id + key)} |
|
||||
<div class="grid"> |
|
||||
<h5>{name}:</h5> |
|
||||
<InputGroup |
|
||||
onStyleChanged={_value => onStyleChanged('position', key, _value)} |
|
||||
values={layout[key] || newValue(meta.length)} |
|
||||
{meta} |
|
||||
{size} /> |
|
||||
</div> |
|
||||
{/each} |
|
||||
</div> --> |
|
||||
|
|
||||
<h3>Spacing</h3> |
|
||||
<div class="layout-spacing"> |
|
||||
{#each Object.entries(spacing) as [key, [name, meta, size]] (component._id + key)} |
|
||||
<div class="grid"> |
|
||||
<h5>{name}:</h5> |
|
||||
<InputGroup |
|
||||
onStyleChanged={_value => onStyleChanged('position', key, _value)} |
|
||||
values={layout[key] || newValue(meta.length)} |
|
||||
{meta} |
|
||||
{size} |
|
||||
type="text" /> |
|
||||
</div> |
|
||||
{/each} |
|
||||
</div> |
|
||||
|
|
||||
<h3>Size</h3> |
|
||||
<div class="layout-layer"> |
|
||||
{#each Object.entries(size) as [key, [name, meta, size]] (component._id + key)} |
|
||||
<div class="grid"> |
|
||||
<h5>{name}:</h5> |
|
||||
<InputGroup |
|
||||
onStyleChanged={_value => onStyleChanged('position', key, _value)} |
|
||||
values={layout[key] || newValue(meta.length)} |
|
||||
type="text" |
|
||||
{meta} |
|
||||
{size} /> |
|
||||
</div> |
|
||||
{/each} |
|
||||
</div> |
|
||||
|
|
||||
<h3>Order</h3> |
|
||||
<div class="layout-layer"> |
|
||||
{#each Object.entries(zindex) as [key, [name, meta, size]] (component._id + key)} |
|
||||
<div class="grid"> |
|
||||
<h5>{name}:</h5> |
|
||||
<InputGroup |
|
||||
onStyleChanged={_value => onStyleChanged('position', key, _value)} |
|
||||
values={layout[key] || newValue(meta.length)} |
|
||||
{meta} |
|
||||
{size} /> |
|
||||
</div> |
|
||||
{/each} |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
h3 { |
|
||||
text-transform: uppercase; |
|
||||
font-size: 13px; |
|
||||
font-weight: 600; |
|
||||
color: var(--ink); |
|
||||
opacity: 0.6; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
text-transform: uppercase; |
|
||||
font-size: 10px; |
|
||||
font-weight: 600; |
|
||||
color: var(--ink); |
|
||||
opacity: 0.4; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
|
|
||||
h5 { |
|
||||
font-size: 13px; |
|
||||
font-weight: 400; |
|
||||
color: var(--ink); |
|
||||
opacity: 0.8; |
|
||||
padding-top: 13px; |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
|
|
||||
div > div { |
|
||||
display: grid; |
|
||||
grid-template-rows: 1fr; |
|
||||
grid-gap: 10px; |
|
||||
height: 40px; |
|
||||
margin-bottom: 15px; |
|
||||
} |
|
||||
|
|
||||
.grid { |
|
||||
grid-template-columns: 70px 2fr; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,44 +0,0 @@ |
|||||
<script> |
|
||||
import { store } from "builderStore" |
|
||||
import Checkbox from "../common/Checkbox.svelte" |
|
||||
import StateBindingControl from "./StateBindingControl.svelte" |
|
||||
|
|
||||
export let index |
|
||||
export let prop_name |
|
||||
export let prop_value |
|
||||
export let prop_definition = {} |
|
||||
</script> |
|
||||
|
|
||||
<div class="root"> |
|
||||
{#if prop_definition.type !== 'event'} |
|
||||
<h5>{prop_name}</h5> |
|
||||
<StateBindingControl |
|
||||
value={prop_value} |
|
||||
type={prop_definition.type || prop_definition} |
|
||||
options={prop_definition.options} |
|
||||
styleBindingProperty={prop_definition.styleBindingProperty} |
|
||||
onChanged={v => store.setComponentProp(prop_name, v)} /> |
|
||||
{/if} |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.root { |
|
||||
height: 40px; |
|
||||
margin-bottom: 15px; |
|
||||
display: grid; |
|
||||
grid-template-rows: 1fr; |
|
||||
grid-template-columns: 70px 1fr; |
|
||||
grid-gap: 10px; |
|
||||
align-items: baseline; |
|
||||
} |
|
||||
|
|
||||
h5 { |
|
||||
word-wrap: break-word; |
|
||||
font-size: 13px; |
|
||||
font-weight: 400; |
|
||||
color: var(--ink); |
|
||||
opacity: 0.8; |
|
||||
padding-top: 13px; |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
</style> |
|
||||
@ -0,0 +1,11 @@ |
|||||
|
<script> |
||||
|
/* |
||||
|
This file exists because of how we pass this control to the |
||||
|
properties panel - via a JS reference, not using svelte tags |
||||
|
... checkout the use of Input in propertyCategories to see what i mean |
||||
|
*/ |
||||
|
import { Input } from "@budibase/bbui" |
||||
|
export let name, value, placeholder, type |
||||
|
</script> |
||||
|
|
||||
|
<Input {name} {value} {placeholder} {type} thin on:change /> |
||||
@ -1,52 +0,0 @@ |
|||||
<script> |
|
||||
import { some, includes, filter } from "lodash/fp" |
|
||||
import PropControl from "./PropControl.svelte" |
|
||||
import IconButton from "../common/IconButton.svelte" |
|
||||
|
|
||||
export let component |
|
||||
export let components |
|
||||
|
|
||||
let errors = [] |
|
||||
const props_to_ignore = ["_component", "_children", "_styles", "_code", "_id"] |
|
||||
|
|
||||
$: componentDef = components[component._component] |
|
||||
</script> |
|
||||
|
|
||||
<div class="root"> |
|
||||
|
|
||||
<form on:submit|preventDefault class="uk-form-stacked form-root"> |
|
||||
{#if componentDef} |
|
||||
{#each Object.entries(componentDef.props) as [prop_name, prop_def], index} |
|
||||
{#if prop_def !== 'event'} |
|
||||
<div class="prop-container"> |
|
||||
<PropControl |
|
||||
{prop_name} |
|
||||
prop_value={component[prop_name]} |
|
||||
prop_definition={prop_def} |
|
||||
{index} |
|
||||
disabled={false} /> |
|
||||
|
|
||||
</div> |
|
||||
{/if} |
|
||||
{/each} |
|
||||
{/if} |
|
||||
</form> |
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.root { |
|
||||
font-size: 10pt; |
|
||||
width: 100%; |
|
||||
} |
|
||||
|
|
||||
.form-root { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
} |
|
||||
|
|
||||
.prop-container { |
|
||||
flex: 1 1 auto; |
|
||||
min-width: 250px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,63 +0,0 @@ |
|||||
<script> |
|
||||
import { backendUiStore } from "builderStore" |
|
||||
import IconButton from "../common/IconButton.svelte" |
|
||||
import Input from "../common/Input.svelte" |
|
||||
|
|
||||
export let value = "" |
|
||||
export let onChanged = () => {} |
|
||||
export let type = "" |
|
||||
export let options = [] |
|
||||
export let styleBindingProperty = "" |
|
||||
|
|
||||
$: bindOptionToStyle = !!styleBindingProperty |
|
||||
</script> |
|
||||
|
|
||||
<div class="unbound-container"> |
|
||||
{#if type === 'bool'} |
|
||||
<div> |
|
||||
<IconButton |
|
||||
icon={value == true ? 'check-square' : 'square'} |
|
||||
size="19" |
|
||||
on:click={() => onChanged(!value)} /> |
|
||||
</div> |
|
||||
{:else if type === 'models'} |
|
||||
<select |
|
||||
class="uk-select uk-form-small" |
|
||||
bind:value |
|
||||
on:change={() => { |
|
||||
onChanged(value) |
|
||||
}}> |
|
||||
{#each $backendUiStore.models || [] as option} |
|
||||
<option value={option}>{option.name}</option> |
|
||||
{/each} |
|
||||
</select> |
|
||||
{:else if type === 'options' || type === 'models'} |
|
||||
<select |
|
||||
class="uk-select uk-form-small" |
|
||||
{value} |
|
||||
on:change={ev => onChanged(ev.target.value)}> |
|
||||
{#each options || [] as option} |
|
||||
{#if bindOptionToStyle} |
|
||||
<option style={`${styleBindingProperty}: ${option};`} value={option}> |
|
||||
{option} |
|
||||
</option> |
|
||||
{:else} |
|
||||
<option value={option}>{option}</option> |
|
||||
{/if} |
|
||||
{/each} |
|
||||
</select> |
|
||||
{/if} |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.unbound-container { |
|
||||
display: flex; |
|
||||
} |
|
||||
|
|
||||
.bound-header > div:nth-child(1) { |
|
||||
flex: 1 0 auto; |
|
||||
width: 30px; |
|
||||
color: var(--secondary50); |
|
||||
padding-left: 5px; |
|
||||
} |
|
||||
</style> |
|
||||
Loading…
Reference in new issue