update datasource config to allow env var selection
This commit is contained in:
parent
5ed038406a
commit
47663ca395
13 changed files with 331 additions and 11 deletions
241
packages/bbui/src/Form/Core/EnvDropdown.svelte
Normal file
241
packages/bbui/src/Form/Core/EnvDropdown.svelte
Normal file
|
@ -0,0 +1,241 @@
|
|||
<script>
|
||||
import "@spectrum-css/textfield/dist/index-vars.css"
|
||||
import { createEventDispatcher, onMount } from "svelte"
|
||||
import clickOutside from "../../Actions/click_outside"
|
||||
import Divider from "../../Divider/Divider.svelte"
|
||||
import Body from "../../Typography/Body.svelte"
|
||||
export let value = null
|
||||
export let placeholder = null
|
||||
export let type = "text"
|
||||
export let disabled = false
|
||||
export let id = null
|
||||
export let readonly = false
|
||||
export let updateOnChange = true
|
||||
export let dataCy
|
||||
export let align
|
||||
export let autofocus = false
|
||||
export let variables
|
||||
export let showModal
|
||||
$: console.log(showModal)
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let field
|
||||
let focus = false
|
||||
let open = false
|
||||
|
||||
const updateValue = newValue => {
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
if (type === "number") {
|
||||
const float = parseFloat(newValue)
|
||||
newValue = isNaN(float) ? null : float
|
||||
}
|
||||
dispatch("change", newValue)
|
||||
}
|
||||
|
||||
const onFocus = () => {
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
focus = true
|
||||
}
|
||||
|
||||
const onBlur = event => {
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
focus = false
|
||||
updateValue(event.target.value)
|
||||
}
|
||||
|
||||
const onInput = event => {
|
||||
if (readonly || !updateOnChange) {
|
||||
return
|
||||
}
|
||||
updateValue(event.target.value)
|
||||
}
|
||||
|
||||
const updateValueOnEnter = event => {
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
if (event.key === "Enter") {
|
||||
updateValue(event.target.value)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOutsideClick = event => {
|
||||
if (open) {
|
||||
event.stopPropagation()
|
||||
open = false
|
||||
dispatch("closed")
|
||||
}
|
||||
}
|
||||
|
||||
const handleVarSelect = variable => {
|
||||
console.log(variable)
|
||||
open = false
|
||||
updateValue(`{{ ${variable} }}`)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
focus = autofocus
|
||||
if (focus) field.focus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="spectrum-InputGroup">
|
||||
<div
|
||||
class:is-focused={focus}
|
||||
class="spectrum-Textfield spectrum-InputGroup-textfield "
|
||||
>
|
||||
<svg
|
||||
class="hoverable icon-position spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
|
||||
focusable="false"
|
||||
aria-hidden="true"
|
||||
on:click={() => (open = true)}
|
||||
>
|
||||
<use xlink:href="#spectrum-icon-18-Key" />
|
||||
</svg>
|
||||
|
||||
<input
|
||||
bind:this={field}
|
||||
{disabled}
|
||||
{readonly}
|
||||
{id}
|
||||
data-cy={dataCy}
|
||||
value={value || ""}
|
||||
placeholder={placeholder || ""}
|
||||
on:click
|
||||
on:blur
|
||||
on:focus
|
||||
on:input
|
||||
on:keyup
|
||||
on:blur={onBlur}
|
||||
on:focus={onFocus}
|
||||
on:input={onInput}
|
||||
on:keyup={updateValueOnEnter}
|
||||
{type}
|
||||
class="spectrum-Textfield-input"
|
||||
style={align ? `text-align: ${align};` : ""}
|
||||
inputmode={type === "number" ? "decimal" : "text"}
|
||||
/>
|
||||
</div>
|
||||
{#if open}
|
||||
<div
|
||||
use:clickOutside={handleOutsideClick}
|
||||
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
|
||||
>
|
||||
<ul class="spectrum-Menu" role="listbox">
|
||||
{#if variables.length}
|
||||
{#each variables as variable, idx}
|
||||
<li
|
||||
class="spectrum-Menu-item"
|
||||
role="option"
|
||||
aria-selected="true"
|
||||
tabindex="0"
|
||||
on:click={() => handleVarSelect(variable.name)}
|
||||
>
|
||||
<span class="spectrum-Menu-itemLabel">
|
||||
<div class="primary-text">
|
||||
{variable.name}
|
||||
<span />
|
||||
</div>
|
||||
<svg
|
||||
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
|
||||
focusable="false"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<use xlink:href="#spectrum-css-icon-Checkmark100" />
|
||||
</svg>
|
||||
</span>
|
||||
</li>
|
||||
{/each}
|
||||
{:else}
|
||||
<li class="spectrum-Menu-item" role="option" aria-selected="true">
|
||||
<span class="spectrum-Menu-itemLabel">
|
||||
<div class="primary-text">
|
||||
You don't have any environment variables yet
|
||||
</div>
|
||||
</span>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
<Divider noMargin />
|
||||
<div class="add-variable">
|
||||
<svg
|
||||
class="spectrum-Icon spectrum-Icon--sizeS "
|
||||
focusable="false"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<use xlink:href="#spectrum-icon-18-Add" />
|
||||
</svg>
|
||||
<div on:click={() => showModal()} class="primary-text">
|
||||
<Body size="S">Add Variable</Body>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.spectrum-Textfield {
|
||||
width: 100%;
|
||||
}
|
||||
input:disabled {
|
||||
color: var(--spectrum-global-color-gray-600) !important;
|
||||
-webkit-text-fill-color: var(--spectrum-global-color-gray-600) !important;
|
||||
}
|
||||
|
||||
.icon-position {
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
right: 2%;
|
||||
}
|
||||
|
||||
.hoverable:hover {
|
||||
cursor: pointer;
|
||||
color: var(--spectrum-global-color-blue-400);
|
||||
}
|
||||
|
||||
.primary-text {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.spectrum-InputGroup {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.spectrum-InputGroup :global(.spectrum-Search-input) {
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--spectrum-global-color-gray-300);
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.spectrum-Popover {
|
||||
max-height: 240px;
|
||||
z-index: 999;
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.spectrum-Popover.spectrum-Popover--bottom.spectrum-Picker-popover.is-open {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Fix focus borders to show only when opened */
|
||||
.spectrum-Textfield-input {
|
||||
border-color: var(--spectrum-global-color-gray-400) !important;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
.add-variable {
|
||||
display: flex;
|
||||
padding: var(--spacing-m) 0 var(--spacing-m) var(--spacing-m);
|
||||
align-items: center;
|
||||
gap: var(--spacing-s);
|
||||
}
|
||||
</style>
|
48
packages/bbui/src/Form/EnvDropdown.svelte
Normal file
48
packages/bbui/src/Form/EnvDropdown.svelte
Normal file
|
@ -0,0 +1,48 @@
|
|||
<script>
|
||||
import Field from "./Field.svelte"
|
||||
import EnvDropdown from "./Core/EnvDropdown.svelte"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
|
||||
export let value = null
|
||||
export let label = null
|
||||
export let labelPosition = "above"
|
||||
export let placeholder = null
|
||||
export let type = "text"
|
||||
export let disabled = false
|
||||
export let readonly = false
|
||||
export let error = null
|
||||
export let updateOnChange = true
|
||||
export let quiet = false
|
||||
export let dataCy
|
||||
export let autofocus
|
||||
export let variables
|
||||
export let showModal
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = e => {
|
||||
value = e.detail
|
||||
dispatch("change", e.detail)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Field {label} {labelPosition} {error}>
|
||||
<EnvDropdown
|
||||
{dataCy}
|
||||
{updateOnChange}
|
||||
{error}
|
||||
{disabled}
|
||||
{readonly}
|
||||
{value}
|
||||
{placeholder}
|
||||
{type}
|
||||
{quiet}
|
||||
{autofocus}
|
||||
{variables}
|
||||
{showModal}
|
||||
on:change={onChange}
|
||||
on:click
|
||||
on:input
|
||||
on:blur
|
||||
on:focus
|
||||
on:keyup
|
||||
/>
|
||||
</Field>
|
|
@ -27,6 +27,7 @@ export { default as RadioGroup } from "./Form/RadioGroup.svelte"
|
|||
export { default as Checkbox } from "./Form/Checkbox.svelte"
|
||||
export { default as InputDropdown } from "./Form/InputDropdown.svelte"
|
||||
export { default as PickerDropdown } from "./Form/PickerDropdown.svelte"
|
||||
export { default as EnvDropdown } from "./Form/EnvDropdown.svelte"
|
||||
export { default as DetailSummary } from "./DetailSummary/DetailSummary.svelte"
|
||||
export { default as Popover } from "./Popover/Popover.svelte"
|
||||
export { default as ProgressBar } from "./ProgressBar/ProgressBar.svelte"
|
||||
|
|
|
@ -6,16 +6,22 @@
|
|||
Toggle,
|
||||
Button,
|
||||
TextArea,
|
||||
Modal,
|
||||
EnvDropdown,
|
||||
} from "@budibase/bbui"
|
||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||
import { capitalise } from "helpers"
|
||||
import { IntegrationTypes } from "constants/backend"
|
||||
import { createValidationStore } from "helpers/validation/yup"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { createEventDispatcher, onMount } from "svelte"
|
||||
import { environment } from "stores/portal"
|
||||
import CreateEditVariableModal from "components/portal/environment/CreateEditVariableModal.svelte"
|
||||
|
||||
export let datasource
|
||||
export let schema
|
||||
export let creating
|
||||
|
||||
let createVariableModal
|
||||
const validation = createValidationStore()
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
@ -60,6 +66,18 @@
|
|||
}
|
||||
return capitalise(name)
|
||||
}
|
||||
|
||||
function save(data) {
|
||||
environment.createVariable(data)
|
||||
createVariableModal.hide()
|
||||
}
|
||||
|
||||
function showModal() {
|
||||
createVariableModal.show()
|
||||
}
|
||||
onMount(async () => {
|
||||
await environment.loadVariables()
|
||||
})
|
||||
</script>
|
||||
|
||||
<form>
|
||||
|
@ -103,7 +121,9 @@
|
|||
{:else}
|
||||
<div class="form-row">
|
||||
<Label>{getDisplayName(configKey)}</Label>
|
||||
<Input
|
||||
<EnvDropdown
|
||||
{showModal}
|
||||
variables={$environment.variables}
|
||||
type={schema[configKey].type}
|
||||
on:change
|
||||
bind:value={config[configKey]}
|
||||
|
@ -115,6 +135,10 @@
|
|||
</Layout>
|
||||
</form>
|
||||
|
||||
<Modal bind:this={createVariableModal}>
|
||||
<CreateEditVariableModal {save} />
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.form-row {
|
||||
display: grid;
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
|
||||
// Adds a data binding to the expression
|
||||
const addBinding = (binding, { forceJS } = {}) => {
|
||||
console.log(binding)
|
||||
if (usingJS || forceJS) {
|
||||
let js = decodeJSBinding(jsValue)
|
||||
js = addJSBinding(js, getCaretPosition(), binding.readableBinding)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
export let allowHelpers = true
|
||||
export let updateOnChange = true
|
||||
export let drawerLeft
|
||||
|
||||
$: console.log(bindings)
|
||||
const dispatch = createEventDispatcher()
|
||||
let bindingDrawer
|
||||
let valid = true
|
||||
|
@ -28,6 +28,7 @@
|
|||
|
||||
$: readableValue = runtimeToReadableBinding(bindings, value)
|
||||
$: tempValue = readableValue
|
||||
$: console.log(tempValue)
|
||||
$: isJS = isJSBinding(value)
|
||||
|
||||
const saveBinding = () => {
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
>
|
||||
{#each fields as field, idx}
|
||||
<Input
|
||||
placeholder={keyPlaceholder}
|
||||
placeholder={"hello"}
|
||||
readonly={readOnly}
|
||||
bind:value={field.name}
|
||||
on:blur={changed}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { ModalContent, Toggle, Body, InlineAlert } from "@budibase/bbui"
|
||||
import { licensing } from "stores/portal"
|
||||
|
||||
export let app
|
||||
export let published
|
||||
|
@ -16,9 +17,11 @@
|
|||
</script>
|
||||
|
||||
<ModalContent {title} {confirmText} onConfirm={exportApp}>
|
||||
<InlineAlert
|
||||
header="Do not share your budibase application exports publicly as they may contain sensitive information such as database credentials or secret keys."
|
||||
/>
|
||||
{#if licensing.environmentVariablesEnabled}
|
||||
<InlineAlert
|
||||
header="Do not share your budibase application exports publicly as they may contain sensitive information such as database credentials or secret keys."
|
||||
/>
|
||||
{/if}
|
||||
<Body
|
||||
>Apps can be exported with or without data that is within internal tables -
|
||||
select this below.</Body
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { ActionButton, Modal } from "@budibase/bbui"
|
||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||
import { environment } from "stores/portal"
|
||||
import CreateEditVariableModal from "./CreateEditVariableModal.svelte"
|
||||
import CreateEditVariableModal from "components/portal/environment/CreateEditVariableModal.svelte"
|
||||
|
||||
export let row
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
} from "@budibase/bbui"
|
||||
import { environment, licensing, auth, admin } from "stores/portal"
|
||||
import { onMount } from "svelte"
|
||||
import CreateEditVariableModal from "./_components/CreateEditVariableModal.svelte"
|
||||
import CreateEditVariableModal from "components/portal/environment/CreateEditVariableModal.svelte"
|
||||
import EditVariableColumn from "./_components/EditVariableColumn.svelte"
|
||||
|
||||
let modal
|
||||
|
@ -64,7 +64,7 @@
|
|||
>Add and manage environment variables for development and production</Body
|
||||
>
|
||||
</Layout>
|
||||
{#if !$licensing.environmentVariablesEnabled}
|
||||
{#if $licensing.environmentVariablesEnabled}
|
||||
{#if noEncryptionKey}
|
||||
<InlineAlert
|
||||
message="Your Budibase installation does not have a key for encryption, please update your app service's environment variables to contain an 'ENCRYPTION_KEY' value."
|
||||
|
|
|
@ -9,7 +9,6 @@ export function createEnvironmentStore() {
|
|||
|
||||
async function checkStatus() {
|
||||
const status = await API.checkEnvironmentVariableStatus()
|
||||
console.log(status)
|
||||
update(store => {
|
||||
store.status = status
|
||||
return store
|
||||
|
|
|
@ -63,6 +63,8 @@ export const createLicensingStore = () => {
|
|||
let environmentVariablesEnabled = license.features.includes(
|
||||
Constants.Features.ENVIRONMENT_VARIABLES
|
||||
)
|
||||
|
||||
environmentVariablesEnabled = true
|
||||
store.update(state => {
|
||||
return {
|
||||
...state,
|
||||
|
|
Loading…
Reference in a new issue