Adding all response capabilities.
This commit is contained in:
parent
65d6ca9249
commit
ba9854d121
|
@ -8,6 +8,7 @@
|
|||
export let error = null
|
||||
export let id = null
|
||||
export let height = null
|
||||
export let minHeight = null
|
||||
export const getCaretPosition = () => ({
|
||||
start: textarea.selectionStart,
|
||||
end: textarea.selectionEnd,
|
||||
|
@ -23,7 +24,8 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
style={height ? `height: ${height}px;` : ""}
|
||||
style={(height ? `height: ${height}px;` : "") +
|
||||
(minHeight ? `min-height: ${minHeight}px` : "")}
|
||||
class="spectrum-Textfield spectrum-Textfield--multiline"
|
||||
class:is-invalid={!!error}
|
||||
class:is-disabled={disabled}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
export let error = null
|
||||
export let getCaretPosition = null
|
||||
export let height = null
|
||||
export let minHeight = null
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = e => {
|
||||
|
@ -27,6 +28,7 @@
|
|||
{value}
|
||||
{placeholder}
|
||||
{height}
|
||||
{minHeight}
|
||||
on:change={onChange}
|
||||
/>
|
||||
</Field>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { datasources, tables } from "../stores/backend"
|
||||
import { IntegrationNames } from "../constants"
|
||||
import { IntegrationNames } from "../constants/backend"
|
||||
import analytics, { Events } from "../analytics"
|
||||
import { get } from "svelte/store"
|
||||
import cloneDeep from "lodash/cloneDeepWith"
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
$: editRowComponent = isUsersTable ? CreateEditUser : CreateEditRow
|
||||
$: {
|
||||
UNSORTABLE_TYPES.forEach(type => {
|
||||
Object.values(schema).forEach(col => {
|
||||
Object.values(schema || {}).forEach(col => {
|
||||
if (col.type === type) {
|
||||
col.sortable = false
|
||||
}
|
||||
|
@ -113,16 +113,16 @@
|
|||
|
||||
<Layout noPadding gap="S">
|
||||
<div>
|
||||
<div class="table-title">
|
||||
{#if title}
|
||||
{#if title}
|
||||
<div class="table-title">
|
||||
<Heading size="S">{title}</Heading>
|
||||
{/if}
|
||||
{#if loading}
|
||||
<div transition:fade|local>
|
||||
<Spinner size="10" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if loading}
|
||||
<div transition:fade|local>
|
||||
<Spinner size="10" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="popovers">
|
||||
<slot />
|
||||
{#if !isUsersTable && selectedRows.length > 0}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
} from "@budibase/bbui"
|
||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||
import { capitalise } from "helpers"
|
||||
import { IntegrationTypes } from "constants"
|
||||
import { IntegrationTypes } from "constants/backend"
|
||||
|
||||
export let datasource
|
||||
export let schema
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import { onMount } from "svelte"
|
||||
import ICONS from "../icons"
|
||||
import api from "builderStore/api"
|
||||
import { IntegrationNames, IntegrationTypes } from "constants"
|
||||
import { IntegrationNames, IntegrationTypes } from "constants/backend"
|
||||
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte"
|
||||
import DatasourceConfigModal from "components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte"
|
||||
import { createRestDatasource } from "builderStore/datasource"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { goto } from "@roxi/routify"
|
||||
import { ModalContent, notifications, Body, Layout } from "@budibase/bbui"
|
||||
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
|
||||
import { IntegrationNames } from "constants"
|
||||
import { IntegrationNames } from "constants/backend"
|
||||
import cloneDeep from "lodash/cloneDeepWith"
|
||||
import { saveDatasource as save } from "builderStore/datasource"
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<script>
|
||||
import { TextArea } from "@budibase/bbui"
|
||||
|
||||
export let data
|
||||
export let height
|
||||
export let minHeight = "120"
|
||||
|
||||
$: string = JSON.stringify(data || {}, null, 2)
|
||||
</script>
|
||||
|
||||
<TextArea disabled value={string} {height} {minHeight} />
|
|
@ -1,5 +1,12 @@
|
|||
<script>
|
||||
import { Icon, ActionButton, Input, Label, Toggle } from "@budibase/bbui"
|
||||
import {
|
||||
Icon,
|
||||
ActionButton,
|
||||
Input,
|
||||
Label,
|
||||
Toggle,
|
||||
Select,
|
||||
} from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { lowercase } from "helpers"
|
||||
|
||||
|
@ -12,6 +19,7 @@
|
|||
export let name
|
||||
export let headings = false
|
||||
export let activity = false
|
||||
export let options
|
||||
|
||||
let fields = Object.entries(object).map(([name, value]) => ({ name, value }))
|
||||
|
||||
|
@ -50,7 +58,15 @@
|
|||
<div class="container" class:container-active={activity} class:readOnly>
|
||||
{#each fields as field, idx}
|
||||
<Input placeholder="Key" bind:value={field.name} on:change={changed} />
|
||||
<Input placeholder="Value" bind:value={field.value} on:change={changed} />
|
||||
{#if options}
|
||||
<Select bind:value={field.value} on:change={changed} {options} />
|
||||
{:else}
|
||||
<Input
|
||||
placeholder="Value"
|
||||
bind:value={field.value}
|
||||
on:change={changed}
|
||||
/>
|
||||
{/if}
|
||||
{#if activity}
|
||||
<Toggle />
|
||||
{/if}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
Tab,
|
||||
} from "@budibase/bbui"
|
||||
import { notifications, Divider } from "@budibase/bbui"
|
||||
import api from "builderStore/api"
|
||||
import ExtraQueryConfig from "./ExtraQueryConfig.svelte"
|
||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||
import ExternalDataSourceTable from "components/backend/DataTable/ExternalDataSourceTable.svelte"
|
||||
|
@ -28,23 +27,20 @@
|
|||
} from "stores/backend"
|
||||
import { capitalise } from "../../helpers"
|
||||
import CodeMirrorEditor from "components/common/CodeMirrorEditor.svelte"
|
||||
import { Roles } from "constants/backend"
|
||||
import JSONPreview from "./JSONPreview.svelte"
|
||||
import { Roles, SchemaTypeOptions } from "constants/backend"
|
||||
import { onMount } from "svelte"
|
||||
import KeyValueBuilder from "./KeyValueBuilder.svelte"
|
||||
import { fieldsToSchema, schemaToFields } from "helpers/data/utils"
|
||||
|
||||
export let query
|
||||
|
||||
let fields = query.schema ? schemaToFields(query.schema) : []
|
||||
let fields = query?.schema ? schemaToFields(query.schema) : []
|
||||
let parameters
|
||||
let data = []
|
||||
let roleId
|
||||
const transformerDocs =
|
||||
"https://docs.budibase.com/building-apps/data/transformers"
|
||||
const typeOptions = [
|
||||
{ label: "Text", value: "string" },
|
||||
{ label: "Number", value: "number" },
|
||||
{ label: "Boolean", value: "boolean" },
|
||||
{ label: "Datetime", value: "datetime" },
|
||||
]
|
||||
|
||||
$: datasource = $datasources.list.find(ds => ds._id === query.datasourceId)
|
||||
$: query.schema = fieldsToSchema(fields)
|
||||
|
@ -60,15 +56,6 @@
|
|||
query.transformer = "return data"
|
||||
}
|
||||
|
||||
function newField() {
|
||||
fields = [...fields, {}]
|
||||
}
|
||||
|
||||
function deleteField(idx) {
|
||||
fields.splice(idx, 1)
|
||||
fields = fields
|
||||
}
|
||||
|
||||
function resetDependentFields() {
|
||||
if (query.fields.extra) {
|
||||
query.fields.extra = {}
|
||||
|
@ -94,43 +81,18 @@
|
|||
|
||||
async function previewQuery() {
|
||||
try {
|
||||
const response = await api.post(`/api/queries/preview`, {
|
||||
fields: query.fields,
|
||||
queryVerb: query.queryVerb,
|
||||
transformer: query.transformer,
|
||||
parameters: query.parameters.reduce(
|
||||
(acc, next) => ({
|
||||
...acc,
|
||||
[next.name]: next.default,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
datasourceId: datasource._id,
|
||||
})
|
||||
const json = await response.json()
|
||||
|
||||
if (response.status !== 200) throw new Error(json.message)
|
||||
|
||||
data = json.rows || []
|
||||
|
||||
if (data.length === 0) {
|
||||
const response = await queries.preview(query)
|
||||
if (response.rows.length === 0) {
|
||||
notifications.info(
|
||||
"Query results empty. Please execute a query with results to create your schema."
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
data = response.rows
|
||||
fields = response.schema
|
||||
notifications.success("Query executed successfully.")
|
||||
|
||||
// Assume all the fields are strings and create a basic schema from the
|
||||
// unique fields returned by the server
|
||||
fields = json.schemaFields.map(field => ({
|
||||
name: field,
|
||||
type: "string",
|
||||
}))
|
||||
} catch (err) {
|
||||
notifications.error(`Query Error: ${err.message}`)
|
||||
console.error(err)
|
||||
notifications.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,26 +108,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
function schemaToFields(schema) {
|
||||
return Object.keys(schema).map(key => ({
|
||||
name: key,
|
||||
type: query.schema[key].type,
|
||||
}))
|
||||
}
|
||||
|
||||
function fieldsToSchema(fieldsToConvert) {
|
||||
return fieldsToConvert.reduce(
|
||||
(acc, next) => ({
|
||||
...acc,
|
||||
[next.name]: {
|
||||
name: next.name,
|
||||
type: next.type,
|
||||
},
|
||||
}),
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (!query || !query._id) {
|
||||
roleId = Roles.BASIC
|
||||
|
@ -271,29 +213,15 @@
|
|||
{#if data}
|
||||
<Tabs selected="JSON">
|
||||
<Tab title="JSON">
|
||||
<pre
|
||||
class="preview">
|
||||
<!-- prettier-ignore -->
|
||||
{#if !data[0]}
|
||||
Please run your query to fetch some data.
|
||||
{:else}
|
||||
{JSON.stringify(data[0], undefined, 2)}
|
||||
{/if}
|
||||
</pre>
|
||||
<JSONPreview data={data[0]} minHeight="120" />
|
||||
</Tab>
|
||||
<Tab title="Schema">
|
||||
<Layout gap="S">
|
||||
{#each fields as field, idx}
|
||||
<div class="field">
|
||||
<Input placeholder="Field Name" bind:value={field.name} />
|
||||
<Select bind:value={field.type} options={typeOptions} />
|
||||
<Icon name="bleClose" on:click={() => deleteField(idx)} />
|
||||
</div>
|
||||
{/each}
|
||||
<div>
|
||||
<Button secondary on:click={newField}>Add Field</Button>
|
||||
</div>
|
||||
</Layout>
|
||||
<KeyValueBuilder
|
||||
bind:object={fields}
|
||||
name="field"
|
||||
headings
|
||||
options={SchemaTypeOptions}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab title="Preview">
|
||||
<ExternalDataSourceTable {query} {data} />
|
||||
|
@ -322,29 +250,11 @@
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 5%;
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
|
||||
.viewer {
|
||||
min-height: 200px;
|
||||
width: 640px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
height: 100%;
|
||||
min-height: 120px;
|
||||
overflow-y: auto;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
background-color: var(--grey-2);
|
||||
padding: var(--spacing-m);
|
||||
border-radius: 8px;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.viewer-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
|
|
@ -154,3 +154,58 @@ export const ALLOWABLE_NUMBER_TYPES = ALLOWABLE_NUMBER_OPTIONS.map(
|
|||
export const SWITCHABLE_TYPES = ALLOWABLE_NUMBER_TYPES.concat(
|
||||
ALLOWABLE_STRING_TYPES
|
||||
)
|
||||
|
||||
export const IntegrationTypes = {
|
||||
POSTGRES: "POSTGRES",
|
||||
MONGODB: "MONGODB",
|
||||
COUCHDB: "COUCHDB",
|
||||
S3: "S3",
|
||||
MYSQL: "MYSQL",
|
||||
REST: "REST",
|
||||
DYNAMODB: "DYNAMODB",
|
||||
ELASTICSEARCH: "ELASTICSEARCH",
|
||||
SQL_SERVER: "SQL_SERVER",
|
||||
AIRTABLE: "AIRTABLE",
|
||||
ARANGODB: "ARANGODB",
|
||||
ORACLE: "ORACLE",
|
||||
INTERNAL: "INTERNAL",
|
||||
}
|
||||
|
||||
export const IntegrationNames = {
|
||||
[IntegrationTypes.POSTGRES]: "PostgreSQL",
|
||||
[IntegrationTypes.MONGODB]: "MongoDB",
|
||||
[IntegrationTypes.COUCHDB]: "CouchDB",
|
||||
[IntegrationTypes.S3]: "S3",
|
||||
[IntegrationTypes.MYSQL]: "MySQL",
|
||||
[IntegrationTypes.REST]: "REST",
|
||||
[IntegrationTypes.DYNAMODB]: "DynamoDB",
|
||||
[IntegrationTypes.ELASTICSEARCH]: "ElasticSearch",
|
||||
[IntegrationTypes.SQL_SERVER]: "SQL Server",
|
||||
[IntegrationTypes.AIRTABLE]: "Airtable",
|
||||
[IntegrationTypes.ARANGODB]: "ArangoDB",
|
||||
[IntegrationTypes.ORACLE]: "Oracle",
|
||||
[IntegrationTypes.INTERNAL]: "Internal",
|
||||
}
|
||||
|
||||
export const SchemaTypeOptions = [
|
||||
{ label: "Text", value: "string" },
|
||||
{ label: "Number", value: "number" },
|
||||
{ label: "Boolean", value: "boolean" },
|
||||
{ label: "Datetime", value: "datetime" },
|
||||
]
|
||||
|
||||
export const RawRestBodyTypes = {
|
||||
NONE: "none",
|
||||
FORM: "form",
|
||||
ENCODED: "encoded",
|
||||
JSON: "json",
|
||||
TEXT: "text",
|
||||
}
|
||||
|
||||
export const RestBodyTypes = [
|
||||
{ name: "none", value: "none" },
|
||||
{ name: "form-data", value: "form" },
|
||||
{ name: "x-www-form-encoded", value: "encoded" },
|
||||
{ name: "raw (JSON)", value: "json" },
|
||||
{ name: "raw (Text)", value: "text" },
|
||||
]
|
||||
|
|
|
@ -15,38 +15,6 @@ export const AppStatus = {
|
|||
DEPLOYED: "published",
|
||||
}
|
||||
|
||||
export const IntegrationTypes = {
|
||||
POSTGRES: "POSTGRES",
|
||||
MONGODB: "MONGODB",
|
||||
COUCHDB: "COUCHDB",
|
||||
S3: "S3",
|
||||
MYSQL: "MYSQL",
|
||||
REST: "REST",
|
||||
DYNAMODB: "DYNAMODB",
|
||||
ELASTICSEARCH: "ELASTICSEARCH",
|
||||
SQL_SERVER: "SQL_SERVER",
|
||||
AIRTABLE: "AIRTABLE",
|
||||
ARANGODB: "ARANGODB",
|
||||
ORACLE: "ORACLE",
|
||||
INTERNAL: "INTERNAL",
|
||||
}
|
||||
|
||||
export const IntegrationNames = {
|
||||
[IntegrationTypes.POSTGRES]: "PostgreSQL",
|
||||
[IntegrationTypes.MONGODB]: "MongoDB",
|
||||
[IntegrationTypes.COUCHDB]: "CouchDB",
|
||||
[IntegrationTypes.S3]: "S3",
|
||||
[IntegrationTypes.MYSQL]: "MySQL",
|
||||
[IntegrationTypes.REST]: "REST",
|
||||
[IntegrationTypes.DYNAMODB]: "DynamoDB",
|
||||
[IntegrationTypes.ELASTICSEARCH]: "ElasticSearch",
|
||||
[IntegrationTypes.SQL_SERVER]: "SQL Server",
|
||||
[IntegrationTypes.AIRTABLE]: "Airtable",
|
||||
[IntegrationTypes.ARANGODB]: "ArangoDB",
|
||||
[IntegrationTypes.ORACLE]: "Oracle",
|
||||
[IntegrationTypes.INTERNAL]: "Internal",
|
||||
}
|
||||
|
||||
// fields on the user table that cannot be edited
|
||||
export const UNEDITABLE_USER_FIELDS = [
|
||||
"email",
|
||||
|
@ -66,22 +34,6 @@ export const LAYOUT_NAMES = {
|
|||
},
|
||||
}
|
||||
|
||||
export const RawRestBodyTypes = {
|
||||
NONE: "none",
|
||||
FORM: "form",
|
||||
ENCODED: "encoded",
|
||||
JSON: "json",
|
||||
TEXT: "text",
|
||||
}
|
||||
|
||||
export const RestBodyTypes = [
|
||||
{ name: "none", value: "none" },
|
||||
{ name: "form-data", value: "form" },
|
||||
{ name: "x-www-form-encoded", value: "encoded" },
|
||||
{ name: "raw (JSON)", value: "json" },
|
||||
{ name: "raw (Text)", value: "text" },
|
||||
]
|
||||
|
||||
export const BUDIBASE_INTERNAL_DB = "bb_internal"
|
||||
|
||||
export const APP_NAME_REGEX = /^[\w\s]+$/
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
export function schemaToFields(schema) {
|
||||
const response = {}
|
||||
if (schema && typeof schema === "object") {
|
||||
for (let [field, value] of Object.entries(schema)) {
|
||||
response[field] = value?.type || "string"
|
||||
}
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
export function fieldsToSchema(fields) {
|
||||
const response = {}
|
||||
if (fields && typeof fields === "object") {
|
||||
for (let [name, type] of Object.entries(fields)) {
|
||||
response[name] = { name, type }
|
||||
}
|
||||
}
|
||||
return response
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { params } from "@roxi/routify"
|
||||
import { queries, datasources } from "stores/backend"
|
||||
import { IntegrationTypes } from "constants"
|
||||
import { IntegrationTypes } from "constants/backend"
|
||||
import { goto } from "@roxi/routify"
|
||||
|
||||
if ($params.query) {
|
||||
|
@ -13,7 +13,7 @@
|
|||
const datasource = $datasources.list.find(
|
||||
ds => ds._id === $datasources.selected
|
||||
)
|
||||
if (datasource.source === IntegrationTypes.REST) {
|
||||
if (datasource?.source === IntegrationTypes.REST) {
|
||||
$goto("../rest")
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { Body } from "@budibase/bbui"
|
||||
import { RawRestBodyTypes } from "constants"
|
||||
import { RawRestBodyTypes } from "constants/backend"
|
||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||
import CodeMirrorEditor, {
|
||||
EditorModes,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import PlusConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte"
|
||||
import ICONS from "components/backend/DatasourceNavigator/icons"
|
||||
import VerbRenderer from "./_components/VerbRenderer.svelte"
|
||||
import { IntegrationTypes } from "constants"
|
||||
import { IntegrationTypes } from "constants/backend"
|
||||
import { isEqual } from "lodash"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
Label,
|
||||
TextArea,
|
||||
Table,
|
||||
notifications,
|
||||
} from "@budibase/bbui"
|
||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||
import EditableLabel from "components/common/inputs/EditableLabel.svelte"
|
||||
|
@ -24,13 +25,19 @@
|
|||
import RestBodyInput from "../_components/RestBodyInput.svelte"
|
||||
import { capitalise } from "helpers"
|
||||
import { onMount } from "svelte"
|
||||
import { RestBodyTypes as bodyTypes } from "constants"
|
||||
import { fieldsToSchema, schemaToFields } from "helpers/data/utils"
|
||||
import {
|
||||
RestBodyTypes as bodyTypes,
|
||||
SchemaTypeOptions,
|
||||
} from "constants/backend"
|
||||
import JSONPreview from "components/integration/JSONPreview.svelte"
|
||||
|
||||
let query
|
||||
let breakQs = {}
|
||||
let url = ""
|
||||
// test - { info: { code: 500, time: "455ms", size: "2.09KB" }}
|
||||
let response
|
||||
let schema
|
||||
|
||||
$: datasource = $datasources.list.find(ds => ds._id === query?.datasourceId)
|
||||
$: datasourceType = datasource?.source
|
||||
|
@ -102,15 +109,38 @@
|
|||
|
||||
function learnMoreBanner() {}
|
||||
|
||||
function saveQuery() {}
|
||||
function buildQuery() {
|
||||
const newQuery = { ...query }
|
||||
const queryString = buildQueryString(breakQs)
|
||||
newQuery.fields.path = url.split("?")[0]
|
||||
newQuery.fields.queryString = queryString
|
||||
return newQuery
|
||||
}
|
||||
|
||||
function sendQuery() {}
|
||||
function saveQuery() {
|
||||
query.schema = fieldsToSchema(schema)
|
||||
}
|
||||
|
||||
async function runQuery() {
|
||||
try {
|
||||
response = await queries.preview(buildQuery(query))
|
||||
if (response.rows.length === 0) {
|
||||
notifications.info("Request did not return any data.")
|
||||
} else {
|
||||
response.info = response.info || { code: 200 }
|
||||
notifications.success("Request sent successfully.")
|
||||
}
|
||||
} catch (err) {
|
||||
notifications.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
query = getSelectedQuery()
|
||||
const qs = query?.fields.queryString
|
||||
breakQs = breakQueryString(qs)
|
||||
url = buildUrl(query.fields.path, qs)
|
||||
schema = schemaToFields(query.schema)
|
||||
if (query && !query.transformer) {
|
||||
query.transformer = "return data"
|
||||
}
|
||||
|
@ -149,7 +179,7 @@
|
|||
<div class="url">
|
||||
<Input bind:value={url} />
|
||||
</div>
|
||||
<Button cta disabled={!url} on:click={sendQuery}>Send</Button>
|
||||
<Button cta disabled={!url} on:click={runQuery}>Send</Button>
|
||||
</div>
|
||||
<Tabs selected="Params" quiet noPadding noHorizPadding>
|
||||
<Tab title="Params">
|
||||
|
@ -203,20 +233,17 @@
|
|||
{:else}
|
||||
<Tabs selected="JSON" quiet noPadding noHorizPadding>
|
||||
<Tab title="JSON">
|
||||
<CodeMirrorEditor
|
||||
height={300}
|
||||
value={response.text}
|
||||
resize="vertical"
|
||||
readonly
|
||||
on:change={e => (query.transformer = e.detail)}
|
||||
/>
|
||||
<div>
|
||||
<JSONPreview height="300" data={response.rows[0]} />
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab title="Schema">
|
||||
<KeyValueBuilder
|
||||
bind:object={response.schemaFields}
|
||||
bind:object={response.schema}
|
||||
name="header"
|
||||
headings
|
||||
activity
|
||||
options={SchemaTypeOptions}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab title="Raw">
|
||||
|
@ -225,7 +252,7 @@
|
|||
<Tab title="Preview">
|
||||
{#if response}
|
||||
<Table
|
||||
schema={response?.schemaFields}
|
||||
schema={response?.schema}
|
||||
data={response?.rows}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
|
|
|
@ -62,6 +62,35 @@ export function createQueriesStore() {
|
|||
unselect: () => {
|
||||
update(state => ({ ...state, selected: null }))
|
||||
},
|
||||
preview: async query => {
|
||||
const response = await api.post("/api/queries/preview", {
|
||||
fields: query.fields,
|
||||
queryVerb: query.queryVerb,
|
||||
transformer: query.transformer,
|
||||
parameters: query.parameters.reduce(
|
||||
(acc, next) => ({
|
||||
...acc,
|
||||
[next.name]: next.default,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
datasourceId: query.datasourceId,
|
||||
})
|
||||
|
||||
if (response.status !== 200) {
|
||||
const error = await response.text()
|
||||
throw `Query error: ${error}`
|
||||
}
|
||||
|
||||
const json = await response.json()
|
||||
// Assume all the fields are strings and create a basic schema from the
|
||||
// unique fields returned by the server
|
||||
const schema = {}
|
||||
for (let field of json.schemaFields) {
|
||||
schema[field] = "string"
|
||||
}
|
||||
return { ...json, schema, rows: json.rows || [] }
|
||||
},
|
||||
delete: async query => {
|
||||
const response = await api.delete(
|
||||
`/api/queries/${query._id}/${query._rev}`
|
||||
|
|
Loading…
Reference in New Issue