1
0
Fork 0
mirror of synced 2024-06-22 04:10:54 +12:00
This commit is contained in:
mike12345567 2021-01-14 17:02:05 +00:00
parent 0c66d9fca4
commit 29424e59c0
11 changed files with 84 additions and 60 deletions

View file

@ -1,5 +1,5 @@
import { writable } from "svelte/store" import { writable } from "svelte/store"
import api, {get} from "../api" import api, { get } from "../api"
const INITIAL_HOSTING_UI_STATE = { const INITIAL_HOSTING_UI_STATE = {
hostingInfo: {}, hostingInfo: {},
@ -45,7 +45,7 @@ export const getHostingStore = () => {
return state return state
}) })
return deployments return deployments
} },
} }
return store return store
} }

View file

@ -50,7 +50,10 @@
function addBlockToAutomation(stepId, blockDefinition) { function addBlockToAutomation(stepId, blockDefinition) {
const newBlock = $automationStore.selectedAutomation.constructBlock( const newBlock = $automationStore.selectedAutomation.constructBlock(
selectedTab, stepId, blockDefinition) selectedTab,
stepId,
blockDefinition
)
automationStore.actions.addBlockToAutomation(newBlock) automationStore.actions.addBlockToAutomation(newBlock)
closePopover() closePopover()
if (stepId === "WEBHOOK") { if (stepId === "WEBHOOK") {

View file

@ -36,9 +36,7 @@
</script> </script>
<div class="root"> <div class="root">
<div class="add-field"> <div class="add-field"><i class="ri-add-line" on:click={addField} /></div>
<i class="ri-add-line" on:click={addField} />
</div>
<div class="spacer" /> <div class="spacer" />
{#each fieldsArray as field} {#each fieldsArray as field}
<div class="field"> <div class="field">
@ -57,13 +55,11 @@
<option>datetime</option> <option>datetime</option>
</Select> </Select>
<i class="remove-field ri-delete-bin-line" <i
class="remove-field ri-delete-bin-line"
on:click={() => removeField(field.name)} /> on:click={() => removeField(field.name)} />
</div> </div>
{/each} {/each}
</div> </div>
<style> <style>
@ -105,7 +101,8 @@
} }
.field :global(input) { .field :global(input) {
padding: var(--spacing-m) var(--spacing-xl) var(--spacing-xs) var(--spacing-m); padding: var(--spacing-m) var(--spacing-xl) var(--spacing-xs)
var(--spacing-m);
font-size: var(--font-size-s); font-size: var(--font-size-s);
font-weight: bold; font-weight: bold;
} }
@ -129,5 +126,4 @@
.add-field > i { .add-field > i {
cursor: pointer; cursor: pointer;
} }
</style> </style>

View file

@ -36,7 +36,8 @@
let errorReason let errorReason
let poll let poll
let deployments = [] let deployments = []
let urlComponent = $hostingStore.hostingInfo.type === "self" ? $store.url : `/${appId}` let urlComponent =
$hostingStore.hostingInfo.type === "self" ? $store.url : `/${appId}`
let deploymentUrl = `${$hostingStore.appUrl}${urlComponent}` let deploymentUrl = `${$hostingStore.appUrl}${urlComponent}`
const formatDate = (date, format) => const formatDate = (date, format) =>

View file

@ -2,7 +2,7 @@
import { Input, TextArea } from "@budibase/bbui" import { Input, TextArea } from "@budibase/bbui"
import { store, hostingStore } from "builderStore" import { store, hostingStore } from "builderStore"
import api from "builderStore/api" import api from "builderStore/api"
import {object, string} from "yup" import { object, string } from "yup"
import { onMount } from "svelte" import { onMount } from "svelte"
import { get } from "svelte/store" import { get } from "svelte/store"
@ -47,7 +47,8 @@
} }
onMount(async () => { onMount(async () => {
const nameError = "Your application must have a name.", urlError = "Your application must have a URL." const nameError = "Your application must have a name.",
urlError = "Your application must have a URL."
let hostingInfo = await hostingStore.actions.fetch() let hostingInfo = await hostingStore.actions.fetch()
if (hostingInfo.type === "self") { if (hostingInfo.type === "self") {
await hostingStore.actions.fetchDeployedApps() await hostingStore.actions.fetchDeployedApps()
@ -55,8 +56,16 @@
const existingAppUrls = get(hostingStore).deployedAppUrls const existingAppUrls = get(hostingStore).deployedAppUrls
existingAppNames.splice(existingAppNames.indexOf(get(store).name), 1) existingAppNames.splice(existingAppNames.indexOf(get(store).name), 1)
existingAppUrls.splice(existingAppUrls.indexOf(get(store).url), 1) existingAppUrls.splice(existingAppUrls.indexOf(get(store).url), 1)
nameValidation = { name: string().required(nameError).notOneOf(existingAppNames) } nameValidation = {
urlValidation = { url: string().required(urlError).notOneOf(existingAppUrls) } name: string()
.required(nameError)
.notOneOf(existingAppNames),
}
urlValidation = {
url: string()
.required(urlError)
.notOneOf(existingAppUrls),
}
} else { } else {
nameValidation = { name: string.required(nameError) } nameValidation = { name: string.required(nameError) }
} }
@ -71,7 +80,7 @@
bind:value={$store.name} bind:value={$store.name}
bind:error={nameError} bind:error={nameError}
label="App Name" /> label="App Name" />
{#if $hostingStore.hostingInfo.type === "self"} {#if $hostingStore.hostingInfo.type === 'self'}
<Input <Input
on:save={e => updateApplication({ url: e.detail })} on:save={e => updateApplication({ url: e.detail })}
thin thin

View file

@ -84,7 +84,9 @@
if (hostingInfo.type === "self") { if (hostingInfo.type === "self") {
await hostingStore.actions.fetchDeployedApps() await hostingStore.actions.fetchDeployedApps()
const existingAppNames = svelteGet(hostingStore).deployedAppNames const existingAppNames = svelteGet(hostingStore).deployedAppNames
infoValidation.applicationName = string().required("Your application must have a name.").notOneOf(existingAppNames) infoValidation.applicationName = string()
.required("Your application must have a name.")
.notOneOf(existingAppNames)
isApiKeyValid = true isApiKeyValid = true
steps = [buildStep(Info), buildStep(User)] steps = [buildStep(Info), buildStep(User)]
validationSchemas = [infoValidation, userValidation] validationSchemas = [infoValidation, userValidation]

View file

@ -47,32 +47,36 @@
await createAutomation(action.parameters) await createAutomation(action.parameters)
} }
} }
dispatch("change", actions) dispatch("change", actions)
} }
// called by the parent modal when actions are saved // called by the parent modal when actions are saved
const createAutomation = async parameters => { const createAutomation = async parameters => {
if (parameters.automationId || !parameters.newAutomationName) return if (parameters.automationId || !parameters.newAutomationName) return
await automationStore.actions.create({name: parameters.newAutomationName}) await automationStore.actions.create({ name: parameters.newAutomationName })
const appActionDefinition = $automationStore.blockDefinitions.TRIGGER.APP const appActionDefinition = $automationStore.blockDefinitions.TRIGGER.APP
const newBlock = $automationStore.selectedAutomation.constructBlock( const newBlock = $automationStore.selectedAutomation.constructBlock(
"TRIGGER", "APP", appActionDefinition) "TRIGGER",
"APP",
appActionDefinition
)
newBlock.inputs = { newBlock.inputs = {
fields: Object.entries(parameters.fields).reduce((fields, [key, value]) => { fields: Object.entries(parameters.fields).reduce(
fields[key] = value.type (fields, [key, value]) => {
return fields fields[key] = value.type
}, {}) return fields
},
{}
),
} }
automationStore.actions.addBlockToAutomation(newBlock) automationStore.actions.addBlockToAutomation(newBlock)
await automationStore.actions.save( await automationStore.actions.save($automationStore.selectedAutomation)
$automationStore.selectedAutomation)
parameters.automationId = $automationStore.selectedAutomation.automation._id parameters.automationId = $automationStore.selectedAutomation.automation._id
delete parameters.newAutomationName delete parameters.newAutomationName

View file

@ -1,6 +1,13 @@
<script> <script>
// accepts an array of field names, and outputs an object of { FieldName: value } // accepts an array of field names, and outputs an object of { FieldName: value }
import { DataList, Label, TextButton, Spacer, Select, Input } from "@budibase/bbui" import {
DataList,
Label,
TextButton,
Spacer,
Select,
Input,
} from "@budibase/bbui"
import { store, backendUiStore, currentAsset } from "builderStore" import { store, backendUiStore, currentAsset } from "builderStore"
import fetchBindableProperties from "builderStore/fetchBindableProperties" import fetchBindableProperties from "builderStore/fetchBindableProperties"
import { CloseCircleIcon, AddIcon } from "components/common/Icons" import { CloseCircleIcon, AddIcon } from "components/common/Icons"
@ -14,7 +21,7 @@
export let parameterFields export let parameterFields
export let schemaFields export let schemaFields
export let fieldLabel="Column" export let fieldLabel = "Column"
const emptyField = () => ({ name: "", value: "" }) const emptyField = () => ({ name: "", value: "" })
@ -60,7 +67,9 @@
// value and type is needed by the client, so it can parse // value and type is needed by the client, so it can parse
// a string into a correct type // a string into a correct type
newParameterFields[field.name] = { newParameterFields[field.name] = {
type: schemaFields ? schemaFields.find(f => f.name === field.name).type : "string", type: schemaFields
? schemaFields.find(f => f.name === field.name).type
: "string",
value: readableToRuntimeBinding(bindableProperties, field.value), value: readableToRuntimeBinding(bindableProperties, field.value),
} }
} }
@ -83,7 +92,7 @@
{/each} {/each}
</Select> </Select>
{:else} {:else}
<Input secondary bind:value={field.name} on:blur={rebuildParameters}/> <Input secondary bind:value={field.name} on:blur={rebuildParameters} />
{/if} {/if}
<Label size="m" color="dark">Value</Label> <Label size="m" color="dark">Value</Label>
<DataList secondary bind:value={field.value} on:blur={rebuildParameters}> <DataList secondary bind:value={field.value} on:blur={rebuildParameters}>
@ -105,7 +114,8 @@
<Spacer small /> <Spacer small />
<TextButton text small blue on:click={addField}> <TextButton text small blue on:click={addField}>
Add {fieldLabel} Add
{fieldLabel}
<div style="height: 20px; width: 20px;"> <div style="height: 20px; width: 20px;">
<AddIcon /> <AddIcon />
</div> </div>

View file

@ -41,53 +41,53 @@
newOrExisting = "existing" newOrExisting = "existing"
parameters.newAutomationName = "" parameters.newAutomationName = ""
} }
</script> </script>
<div class="root"> <div class="root">
<div class="radio-container" on:click={setNew}> <div class="radio-container" on:click={setNew}>
<input <input
type="radio" type="radio"
value="new" value="new"
bind:group={newOrExisting} bind:group={newOrExisting}
disabled={!hasAutomations}> disabled={!hasAutomations} />
<Label disabled={!hasAutomations}>Create a new automation </Label>
<Label disabled={!hasAutomations}>Create a new automation</Label>
</div> </div>
<div class="radio-container" on:click={setExisting}> <div class="radio-container" on:click={setExisting}>
<input
<input type="radio"
type="radio" value="existing"
value="existing"
bind:group={newOrExisting} bind:group={newOrExisting}
disabled={!hasAutomations}> disabled={!hasAutomations} />
<Label disabled={!hasAutomations}>Use an existing automation </Label>
<Label disabled={!hasAutomations}>Use an existing automation</Label>
</div> </div>
<Label size="m" color="dark">Automation</Label> <Label size="m" color="dark">Automation</Label>
{#if newOrExisting=== "existing"} {#if newOrExisting === 'existing'}
<Select secondary bind:value={parameters.automationId} placeholder="Choose automation"> <Select
secondary
bind:value={parameters.automationId}
placeholder="Choose automation">
<option value="" /> <option value="" />
{#each automations as automation} {#each automations as automation}
<option value={automation._id}>{automation.name}</option> <option value={automation._id}>{automation.name}</option>
{/each} {/each}
</Select> </Select>
{:else} {:else}
<Input secondary bind:value={parameters.newAutomationName} placeholder="Enter automation name" /> <Input
secondary
bind:value={parameters.newAutomationName}
placeholder="Enter automation name" />
{/if} {/if}
<SaveFields <SaveFields
parameterFields={parameters.fields} parameterFields={parameters.fields}
schemaFields={newOrExisting === "existing" && selectedAutomation && selectedAutomation.schema} schemaFields={newOrExisting === 'existing' && selectedAutomation && selectedAutomation.schema}
fieldLabel="Field" fieldLabel="Field"
on:fieldschanged={onFieldsChanged} /> on:fieldschanged={onFieldsChanged} />
</div> </div>
<style> <style>
@ -127,5 +127,4 @@
.radio-container > input:focus { .radio-container > input:focus {
outline: none; outline: none;
} }
</style> </style>

View file

@ -5,7 +5,8 @@ const { join } = require("path")
const { homedir } = require("os") const { homedir } = require("os")
// level option is purely for testing (development) // level option is purely for testing (development)
const COUCH_DB_URL = env.COUCH_DB_URL || `leveldb://${join(homedir(), ".budibase")}/.data/` const COUCH_DB_URL =
env.COUCH_DB_URL || `leveldb://${join(homedir(), ".budibase")}/.data/`
const Pouch = PouchDB.defaults({ const Pouch = PouchDB.defaults({
prefix: COUCH_DB_URL, prefix: COUCH_DB_URL,
@ -13,4 +14,4 @@ const Pouch = PouchDB.defaults({
allDbs(Pouch) allDbs(Pouch)
module.exports = Pouch module.exports = Pouch

View file

@ -2,8 +2,7 @@ const env = require("../environment")
module.exports = async (ctx, next) => { module.exports = async (ctx, next) => {
const selfHostKey = const selfHostKey =
ctx.request.headers["x-budibase-auth"] || ctx.request.headers["x-budibase-auth"] || ctx.request.body.selfHostKey
ctx.request.body.selfHostKey
if (!selfHostKey || env.SELF_HOST_KEY !== selfHostKey) { if (!selfHostKey || env.SELF_HOST_KEY !== selfHostKey) {
ctx.throw(401, "Request unauthorised") ctx.throw(401, "Request unauthorised")
} else { } else {