mirror of https://github.com/Budibase/budibase.git
10 changed files with 313 additions and 4 deletions
@ -0,0 +1,59 @@ |
|||
<script> |
|||
import { createEventDispatcher } from "svelte" |
|||
|
|||
let dispatch = createEventDispatcher() |
|||
|
|||
export let type = "info" |
|||
export let icon = "Info" |
|||
export let size = "S" |
|||
export let extraButtonText |
|||
export let extraButtonAction |
|||
|
|||
let show = true |
|||
|
|||
function clear() { |
|||
show = false |
|||
dispatch("change") |
|||
} |
|||
</script> |
|||
|
|||
{#if show} |
|||
<div class="spectrum-Toast spectrum-Toast--{type}"> |
|||
<svg |
|||
class="spectrum-Icon spectrum-Icon--size{size} spectrum-Toast-typeIcon" |
|||
focusable="false" |
|||
aria-hidden="true" |
|||
> |
|||
<use xlink:href="#spectrum-icon-18-{icon}" /> |
|||
</svg> |
|||
<div class="spectrum-Toast-body"> |
|||
<div class="spectrum-Toast-content"> |
|||
<slot /> |
|||
</div> |
|||
{#if extraButtonText && extraButtonAction} |
|||
<button |
|||
class="spectrum-Button spectrum-Button--sizeM spectrum-Button--overBackground spectrum-Button--quiet" |
|||
on:click={extraButtonAction} |
|||
> |
|||
<span class="spectrum-Button-label">{extraButtonText}</span> |
|||
</button> |
|||
{/if} |
|||
</div> |
|||
<div class="spectrum-Toast-buttons"> |
|||
<button |
|||
class="spectrum-ClearButton spectrum-ClearButton--overBackground spectrum-ClearButton--size{size}" |
|||
on:click={clear} |
|||
> |
|||
<div class="spectrum-ClearButton-fill"> |
|||
<svg |
|||
class="spectrum-ClearButton-icon spectrum-Icon spectrum-UIIcon-Cross100" |
|||
focusable="false" |
|||
aria-hidden="true" |
|||
> |
|||
<use xlink:href="#spectrum-css-icon-Cross100" /> |
|||
</svg> |
|||
</div> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
{/if} |
|||
@ -0,0 +1,63 @@ |
|||
<script> |
|||
import { Heading, Icon, Input, Label, Body } from "@budibase/bbui" |
|||
import { createEventDispatcher } from "svelte" |
|||
|
|||
let dispatch = createEventDispatcher() |
|||
|
|||
export let defaultValue = "" |
|||
export let value |
|||
export let type = "label" |
|||
export let size = "M" |
|||
|
|||
let editing = false |
|||
|
|||
function setEditing(state) { |
|||
editing = state |
|||
if (editing) { |
|||
dispatch("change") |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<div class="parent"> |
|||
{#if !editing} |
|||
{#if type === "heading"} |
|||
<Heading {size}>{value || defaultValue}</Heading> |
|||
{:else if type === "body"} |
|||
<Body {size}>{value || defaultValue}</Body> |
|||
{:else} |
|||
<Label {size}>{value || defaultValue}</Label> |
|||
{/if} |
|||
<div class="hide"> |
|||
<Icon name="Edit" hoverable size="S" on:click={() => setEditing(true)} /> |
|||
</div> |
|||
{:else} |
|||
<div class="input"> |
|||
<Input placeholder={defaultValue} bind:value on:change /> |
|||
</div> |
|||
<Icon |
|||
name="SaveFloppy" |
|||
hoverable |
|||
size="S" |
|||
on:click={() => setEditing(false)} |
|||
/> |
|||
{/if} |
|||
</div> |
|||
|
|||
<style> |
|||
.parent { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: var(--spacing-m); |
|||
} |
|||
.hide { |
|||
display: none; |
|||
margin-top: 5px; |
|||
} |
|||
.parent:hover .hide { |
|||
display: block; |
|||
} |
|||
.input { |
|||
flex: 1; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,4 @@ |
|||
<script> |
|||
</script> |
|||
|
|||
<slot /> |
|||
@ -0,0 +1,173 @@ |
|||
<script> |
|||
import { params } from "@roxi/routify" |
|||
import { datasources, integrations, queries } from "stores/backend" |
|||
import { |
|||
Layout, |
|||
Input, |
|||
Select, |
|||
Tabs, |
|||
Tab, |
|||
Banner, |
|||
Divider, |
|||
Button, |
|||
Heading, |
|||
} from "@budibase/bbui" |
|||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte" |
|||
import EditableLabel from "components/common/inputs/EditableLabel.svelte" |
|||
import CodeMirrorEditor from "components/common/CodeMirrorEditor.svelte" |
|||
import { capitalise } from "helpers" |
|||
import { onMount } from "svelte" |
|||
|
|||
let query |
|||
let breakQs = {} |
|||
|
|||
$: datasource = $datasources.list.find(ds => ds._id === query?.datasourceId) |
|||
$: datasourceType = datasource?.source |
|||
$: integrationInfo = $integrations[datasourceType] |
|||
$: queryConfig = integrationInfo?.query |
|||
|
|||
function getSelectedQuery() { |
|||
return ( |
|||
$queries.list.find(q => q._id === $queries.selected) || { |
|||
datasourceId: $params.selectedDatasource, |
|||
parameters: [], |
|||
fields: {}, |
|||
queryVerb: "read", |
|||
} |
|||
) |
|||
} |
|||
|
|||
function breakQueryString(qs) { |
|||
if (!qs) { |
|||
return {} |
|||
} |
|||
const params = qs.split("&") |
|||
let paramObj = {} |
|||
for (let param of params) { |
|||
const [key, value] = param.split("=") |
|||
paramObj[key] = value |
|||
} |
|||
} |
|||
|
|||
// function buildQueryString(obj) { |
|||
// let str = "" |
|||
// for (let [key, value] of Object.entries(obj)) { |
|||
// if (str !== "") { |
|||
// str += "&" |
|||
// } |
|||
// str += `${key}=${value}` |
|||
// } |
|||
// return str |
|||
// } |
|||
|
|||
function checkQueryName(queryToCheck, url = null) { |
|||
if (queryToCheck && (!queryToCheck.name || queryToCheck.flags.urlName)) { |
|||
queryToCheck.flags.urlName = true |
|||
queryToCheck.name = url || queryToCheck.fields.path |
|||
} |
|||
} |
|||
|
|||
function learnMoreBanner() {} |
|||
|
|||
function saveQuery() {} |
|||
|
|||
onMount(() => { |
|||
query = getSelectedQuery() |
|||
breakQs = breakQueryString(query?.fields.queryString) |
|||
if (query && !query.transformer) { |
|||
query.transformer = "return data" |
|||
} |
|||
if (query && !query.flags) { |
|||
query.flags = { |
|||
urlName: false, |
|||
bannerCleared: false, |
|||
} |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
{#if query} |
|||
<div class="inner"> |
|||
<div class="top"> |
|||
<Layout gap="S"> |
|||
<EditableLabel |
|||
type="heading" |
|||
bind:value={query.name} |
|||
defaultValue="Untitled" |
|||
on:change={() => (query.flags.urlName = false)} |
|||
/> |
|||
<div class="url-block"> |
|||
<div class="verb"> |
|||
<Select |
|||
bind:value={query.queryVerb} |
|||
on:change={() => {}} |
|||
options={Object.keys(queryConfig)} |
|||
getOptionLabel={verb => |
|||
queryConfig[verb]?.displayName || capitalise(verb)} |
|||
/> |
|||
</div> |
|||
<div class="url"> |
|||
<Input |
|||
bind:value={query.fields.path} |
|||
on:change={({ detail }) => checkQueryName(query, detail)} |
|||
/> |
|||
</div> |
|||
<Button cta disabled={!query.fields.path} on:click={saveQuery} |
|||
>Send</Button |
|||
> |
|||
</div> |
|||
<Tabs selected="Params"> |
|||
<Tab title="Params"> |
|||
<KeyValueBuilder bind:object={breakQs} name="param" /> |
|||
</Tab> |
|||
<Tab title="Headers" /> |
|||
<Tab title="Body" /> |
|||
<Tab title="Transformer"> |
|||
<Layout noPadding> |
|||
{#if !query.flags.bannerCleared} |
|||
<Banner |
|||
extraButtonText="Learn more" |
|||
extraButtonAction={learnMoreBanner} |
|||
on:change={() => (query.flags.bannerCleared = true)} |
|||
> |
|||
Add a JavaScript function to transform the query result. |
|||
</Banner> |
|||
{/if} |
|||
<CodeMirrorEditor |
|||
height={200} |
|||
value={query.transformer} |
|||
resize="vertical" |
|||
on:change={e => (query.transformer = e.detail)} |
|||
/> |
|||
</Layout> |
|||
</Tab> |
|||
</Tabs> |
|||
</Layout> |
|||
</div> |
|||
<Layout paddingY="L"> |
|||
<Divider size="S" /> |
|||
<Heading size="M">Response</Heading> |
|||
</Layout> |
|||
</div> |
|||
{/if} |
|||
|
|||
<style> |
|||
.inner { |
|||
width: 840px; |
|||
margin: 0 auto; |
|||
height: 100%; |
|||
} |
|||
.url-block { |
|||
display: flex; |
|||
gap: var(--spacing-s); |
|||
} |
|||
.verb { |
|||
flex: 1; |
|||
} |
|||
.url { |
|||
flex: 4; |
|||
} |
|||
.top { |
|||
min-height: 50%; |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue