mirror of https://github.com/Budibase/budibase.git
5 changed files with 221 additions and 64 deletions
@ -1,74 +1,159 @@ |
|||
<script> |
|||
import { goto } from "@roxi/routify" |
|||
import { datasources } from "stores/backend" |
|||
import { notifications } from "@budibase/bbui" |
|||
import { Input, Label, ModalContent, Modal, Context } from "@budibase/bbui" |
|||
import TableIntegrationMenu from "../TableIntegrationMenu/index.svelte" |
|||
import { ModalContent, Modal, Body, Layout, Label } from "@budibase/bbui" |
|||
import { onMount } from "svelte" |
|||
import ICONS from "../icons" |
|||
import api from "builderStore/api" |
|||
import { IntegrationNames } from "constants" |
|||
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte" |
|||
import analytics from "analytics" |
|||
import { getContext } from "svelte" |
|||
import DatasourceDetailsModal from "components/backend/DatasourceNavigator/modals/DatasourceDetailsModal.svelte" |
|||
|
|||
const modalContext = getContext(Context.Modal) |
|||
export let modal |
|||
let integrations = [] |
|||
let integration = {} |
|||
let internalTableModal |
|||
let externalDatasourceModal |
|||
|
|||
let tableModal |
|||
let name |
|||
let error = "" |
|||
let integration |
|||
const INTERNAL = "BUDIBASE" |
|||
|
|||
$: checkOpenModal(integration && integration.type === "BUDIBASE") |
|||
onMount(() => { |
|||
fetchIntegrations() |
|||
}) |
|||
|
|||
function checkValid(evt) { |
|||
const datasourceName = evt.target.value |
|||
if ( |
|||
$datasources?.list.some(datasource => datasource.name === datasourceName) |
|||
) { |
|||
error = `Datasource with name ${datasourceName} already exists. Please choose another name.` |
|||
return |
|||
function selectIntegration(integrationType) { |
|||
const selected = integrations[integrationType] |
|||
|
|||
// build the schema |
|||
const config = {} |
|||
for (let key of Object.keys(selected.datasource)) { |
|||
config[key] = selected.datasource[key].default |
|||
} |
|||
integration = { |
|||
type: integrationType, |
|||
plus: selected.plus, |
|||
config, |
|||
schema: selected.datasource, |
|||
} |
|||
error = "" |
|||
} |
|||
|
|||
function checkOpenModal(isInternal) { |
|||
if (isInternal) { |
|||
tableModal.show() |
|||
function chooseNextModal() { |
|||
if (integration.type === INTERNAL) { |
|||
externalDatasourceModal.hide() |
|||
internalTableModal.show() |
|||
} else { |
|||
externalDatasourceModal.show() |
|||
} |
|||
} |
|||
|
|||
async function saveDatasource() { |
|||
const { type, plus, ...config } = integration |
|||
|
|||
// Create datasource |
|||
const response = await datasources.save({ |
|||
name, |
|||
source: type, |
|||
config, |
|||
plus, |
|||
}) |
|||
notifications.success(`Datasource ${name} created successfully.`) |
|||
analytics.captureEvent("Datasource Created", { name, type }) |
|||
|
|||
// Navigate to new datasource |
|||
$goto(`./datasource/${response._id}`) |
|||
async function fetchIntegrations() { |
|||
const response = await api.get("/api/integrations") |
|||
const json = await response.json() |
|||
integrations = { |
|||
[INTERNAL]: { datasource: {}, name: "INTERNAL/CSV" }, |
|||
...json, |
|||
} |
|||
return json |
|||
} |
|||
</script> |
|||
|
|||
<Modal bind:this={tableModal} on:hide={modalContext.hide}> |
|||
<CreateTableModal bind:name /> |
|||
<Modal bind:this={internalTableModal}> |
|||
<CreateTableModal /> |
|||
</Modal> |
|||
|
|||
<Modal bind:this={externalDatasourceModal}> |
|||
<DatasourceDetailsModal {integration} /> |
|||
</Modal> |
|||
|
|||
<Modal bind:this={modal}> |
|||
<ModalContent |
|||
disabled={!Object.keys(integration).length} |
|||
title="Add Data" |
|||
confirmText="Continue" |
|||
cancelText="Start from scratch" |
|||
size="M" |
|||
onConfirm={() => { |
|||
chooseNextModal() |
|||
}} |
|||
> |
|||
<Body size="XS" |
|||
>All apps need data. You can connect to a data source below, or add data |
|||
to your app using Budibase's built-in database - it's simple! |
|||
</Body> |
|||
|
|||
<Layout noPadding> |
|||
<div |
|||
class:selected={integration.type === INTERNAL} |
|||
on:click={() => selectIntegration(INTERNAL)} |
|||
class="item hoverable" |
|||
> |
|||
<div class="item-body"> |
|||
<svelte:component this={ICONS.BUDIBASE} height="18" width="18" /> |
|||
<span class="icon-spacing"> |
|||
<Body size="S">Budibase DB (no prior data required)</Body></span |
|||
> |
|||
</div> |
|||
</div> |
|||
<Label size="S">Connect to data source</Label> |
|||
|
|||
<div class="item-list"> |
|||
{#each Object.entries(integrations).filter(([key]) => key !== INTERNAL) as [integrationType, schema]} |
|||
<div |
|||
class:selected={integration.type === integrationType} |
|||
on:click={() => selectIntegration(integrationType)} |
|||
class="item hoverable" |
|||
> |
|||
<div class="item-body"> |
|||
<svelte:component |
|||
this={ICONS[integrationType]} |
|||
height="18" |
|||
width="18" |
|||
/> |
|||
|
|||
<span class="icon-spacing"> |
|||
<Body size="S" |
|||
>{schema.name || IntegrationNames[integrationType]}</Body |
|||
></span |
|||
> |
|||
</div> |
|||
</div> |
|||
{/each} |
|||
</div> |
|||
</Layout> |
|||
</ModalContent> |
|||
</Modal> |
|||
<ModalContent |
|||
title="Create Datasource" |
|||
size="L" |
|||
confirmText="Create" |
|||
onConfirm={saveDatasource} |
|||
disabled={error || !name || !integration?.type} |
|||
> |
|||
<Input |
|||
data-cy="datasource-name-input" |
|||
label="Datasource Name" |
|||
on:input={checkValid} |
|||
bind:value={name} |
|||
{error} |
|||
/> |
|||
<Label>Datasource Type</Label> |
|||
<TableIntegrationMenu bind:integration /> |
|||
</ModalContent> |
|||
|
|||
<style> |
|||
.icon-spacing { |
|||
margin-left: var(--spacing-m); |
|||
} |
|||
.item-body { |
|||
display: flex; |
|||
margin-left: var(--spacing-m); |
|||
} |
|||
.item-list { |
|||
display: grid; |
|||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); |
|||
grid-gap: var(--spectrum-alias-grid-baseline); |
|||
} |
|||
|
|||
.item { |
|||
cursor: pointer; |
|||
display: grid; |
|||
grid-gap: var(--spectrum-alias-grid-margin-xsmall); |
|||
padding: var(--spectrum-alias-item-padding-s); |
|||
background: var(--spectrum-alias-background-color-secondary); |
|||
transition: 0.3s all; |
|||
border: solid var(--spectrum-alias-border-color); |
|||
border-radius: 5px; |
|||
box-sizing: border-box; |
|||
border-width: 2px; |
|||
} |
|||
|
|||
.selected { |
|||
background: var(--spectrum-alias-background-color-tertiary); |
|||
} |
|||
|
|||
.item:hover, |
|||
.selected { |
|||
background: var(--spectrum-alias-background-color-tertiary); |
|||
} |
|||
</style> |
|||
|
|||
@ -0,0 +1,51 @@ |
|||
<script> |
|||
import { ModalContent, notifications } from "@budibase/bbui" |
|||
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte" |
|||
import { datasources } from "stores/backend" |
|||
import { IntegrationNames } from "constants" |
|||
|
|||
export let integration |
|||
|
|||
function prepareData() { |
|||
let datasource = {} |
|||
let existingTypeCount = $datasources.list.filter( |
|||
ds => ds.type == integration.type |
|||
).length |
|||
|
|||
let baseName = IntegrationNames[integration.type] |
|||
let name = |
|||
existingTypeCount == 0 ? baseName : `${baseName}-${existingTypeCount + 1}` |
|||
|
|||
datasource.type = "datasource" |
|||
datasource.source = integration.type |
|||
datasource.config = integration.config |
|||
datasource.name = name |
|||
|
|||
return datasource |
|||
} |
|||
async function saveDatasource() { |
|||
try { |
|||
// Create datasource |
|||
await datasources.save(prepareData()) |
|||
notifications.success(`Datasource updated successfully.`) |
|||
} catch (err) { |
|||
notifications.error(`Error saving datasource: ${err}`) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<ModalContent |
|||
title="Add Data" |
|||
onConfirm={() => saveDatasource()} |
|||
confirmText="Continue" |
|||
cancelText="Start from scratch" |
|||
size="M" |
|||
> |
|||
<IntegrationConfigForm |
|||
schema={integration.schema} |
|||
bind:integration={integration.config} |
|||
/> |
|||
</ModalContent> |
|||
|
|||
<style> |
|||
</style> |
|||
@ -1,6 +1,13 @@ |
|||
<script> |
|||
import { goto } from "@roxi/routify" |
|||
$goto("./table") |
|||
import CreateDatasourceModal from "components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte" |
|||
import { datasources } from "stores/backend" |
|||
|
|||
$: setupComplete = |
|||
$datasources.list.find(x => (x._id = "bb_internal")).entities.length > 1 || |
|||
$datasources.list > 1 |
|||
</script> |
|||
|
|||
{#if !setupComplete} |
|||
<CreateDatasourceModal /> |
|||
{/if} |
|||
<!-- routify:options index=false --> |
|||
|
|||
Loading…
Reference in new issue