datasource selection logic - unselect other entities when choosing datasource

This commit is contained in:
Martin McKeaveney 2021-06-16 23:27:38 +01:00
parent 6e00919851
commit 9841a74e39
25 changed files with 91 additions and 184 deletions

View File

@ -23,6 +23,7 @@
schema,
name: $views.selected?.name,
}
$: isInternal = $tables.selected.type === "internal"
// Fetch rows for specified table
$: {
@ -60,12 +61,16 @@
modalContentComponent={CreateEditRow}
/>
{/if}
<CreateViewButton />
{#if isInternal}
<CreateViewButton />
{/if}
<ManageAccessButton resourceId={$tables.selected?._id} />
{#if isUsersTable}
<EditRolesButton />
{/if}
<HideAutocolumnButton bind:hideAutocolumns />
{#if isInternal}
<HideAutocolumnButton bind:hideAutocolumns />
{/if}
<!-- always have the export last -->
<ExportButton view={tableView} />
{/if}

View File

@ -11,8 +11,8 @@
import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte"
export let view = {}
let hideAutocolumns = true
let hideAutocolumns = true
let data = []
let loading = false
@ -27,7 +27,7 @@
async function fetchViewData(name, field, groupBy, calculation) {
const _tables = $tables.list
const allTableViews = _tables.map(table => table.views)
const thisView = allTableViews.filter(
const thisView = $allTableViews..filter(
views => views != null && views[name] != null
)[0]

View File

@ -1,6 +1,6 @@
<script>
import { goto } from "@roxi/routify"
import { tables, views, database } from "stores/backend"
import { entities, tables, views, database } from "stores/backend"
import { TableNames } from "constants"
import EditTablePopover from "./popovers/EditTablePopover.svelte"
import EditViewPopover from "./popovers/EditViewPopover.svelte"
@ -39,7 +39,7 @@
border={idx > 0}
icon={table._id === TableNames.USERS ? "UserGroup" : "Table"}
text={table.name}
selected={selectedView === table._id}
selected={$tables.selected?._id === table._id}
on:click={() => selectTable(table)}
>
{#if table._id !== TableNames.USERS}

View File

@ -1,18 +1,22 @@
<script>
import { isActive, goto } from "@roxi/routify"
import { isActive, goto, params } from "@roxi/routify"
import { Icon, Modal, Tabs, Tab } from "@budibase/bbui"
import { BUDIBASE_INTERNAL_DB } from "constants"
import TableNavigator from "components/backend/TableNavigator/TableNavigator.svelte"
import DatasourceNavigator from "components/backend/DatasourceNavigator/DatasourceNavigator.svelte"
import CreateDatasourceModal from "components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte"
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte"
let selected = "Sources"
let modal
$: isExternal =
$params.selectedDatasource &&
$params.selectedDatasource !== BUDIBASE_INTERNAL_DB
function selectFirstDatasource({ detail }) {
$goto("./datasource")
}
let modal
</script>
<!-- routify:options index=0 -->
@ -23,14 +27,18 @@
<div class="tab-content-padding">
<DatasourceNavigator />
<Modal bind:this={modal}>
<CreateDatasourceModal />
{#if isExternal}
<CreateDatasourceModal />
{:else}
<CreateTableModal />
{/if}
</Modal>
</div>
</Tab>
</Tabs>
<div
class="add-button"
data-cy={`new-${selected === "External" ? "datasource" : "table"}`}
data-cy={`new-${isExternal ? "datasource" : "table"}`}
>
<Icon hoverable name="AddCircle" on:click={modal.show} />
</div>

View File

@ -1,13 +1 @@
<script>
import { params } from "@roxi/routify"
import { queries } from "stores/backend"
// if ($params.query) {
// const query = $queries.list.find(m => m._id === $params.query)
// if (query) {
// queries.select(query)
// }
// }
</script>
<slot />

View File

@ -1,6 +1,6 @@
<script>
import { params } from "@roxi/routify"
import { database, queries } from "stores/backend"
import { database, queries, entities } from "stores/backend"
import QueryInterface from "components/integration/QueryViewer.svelte"
$: selectedQuery = $queries.list.find(

View File

@ -1,6 +1,6 @@
<script>
import { params } from "@roxi/routify"
import { datasources } from "stores/backend"
import { datasources, entities } from "stores/backend"
if ($params.selectedDatasource) {
const datasource = $datasources.list.find(

View File

@ -1,7 +1,13 @@
<script>
import { goto, beforeUrlChange } from "@roxi/routify"
import { Button, Heading, Body, Divider, Layout } from "@budibase/bbui"
import { datasources, integrations, queries, tables } from "stores/backend"
import {
datasources,
entities,
integrations,
queries,
tables,
} from "stores/backend"
import { notifications } from "@budibase/bbui"
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
import ICONS from "components/backend/DatasourceNavigator/icons"
@ -96,9 +102,13 @@
{/each}
</div>
{#if datasource.plus}
<Button cta on:click={updateDatasourceSchema}
>Fetch Tables From Database</Button
>
<Divider />
<div class="query-header">
<Heading size="S">Queries</Heading>
<Button cta on:click={updateDatasourceSchema}
>Fetch Tables From Database</Button
>
</div>
{/if}
</Layout>
</section>

View File

@ -1,5 +1,5 @@
<script>
import { tables } from "stores/backend"
import { tables, entities } from "stores/backend"
import { goto, leftover } from "@roxi/routify"
import { onMount } from "svelte"
@ -8,8 +8,8 @@
// and this is the final url (i.e. no selectedTable)
if (
!$leftover &&
$tables.list.length > 0 &&
(!$tables.selected || !$tables.selected._id)
$tables.list.length > 0
// (!$tables.selected || !$tables.selected._id)
) {
$goto(`./${$tables.list[0]._id}`)
}

View File

@ -8,8 +8,8 @@
// and this is the final url (i.e. no selectedTable)
if (
!$leftover &&
$tables.list.length > 0 &&
(!$tables.selected || !$tables.selected._id)
$tables.list.length > 0
// (!$tables.selected || !$tables.selected._id)
) {
$goto(`./${$tables.list[0]._id}`)
}

View File

@ -1,4 +1,5 @@
<script>
import { onMount } from "svelte"
import {
Layout,
Heading,
@ -7,9 +8,12 @@
Divider,
notifications,
} from "@budibase/bbui"
import api from "builderStore/api"
import { auth } from "stores/portal"
import { redirect } from "@roxi/routify"
let version
// Only admins allowed here
$: {
if (!$auth.isAdmin) {
@ -26,10 +30,20 @@
},
})
notifications.success("Your budibase installation is up to date.")
getVersion()
} catch (err) {
notifications.error(`Error installing budibase update ${err}`)
}
}
async function getVersion() {
const response = await api.get("/api/dev/version")
version = await response.text()
}
onMount(() => {
getVersion()
})
</script>
{#if $auth.isAdmin}
@ -43,6 +57,11 @@
</Layout>
<Divider size="S" />
<div class="fields">
<div class="field">
{#if version}
Current Version: {version}
{/if}
</div>
<div class="field">
<Button cta on:click={updateBudibase}>Check For Updates</Button>
</div>

View File

@ -16,7 +16,7 @@ export function createDatasourcesStore() {
init: async () => {
const response = await api.get(`/api/datasources`)
const json = await response.json()
set({ list: json, selected: null })
set({ list: json })
},
fetch: async () => {
const response = await api.get(`/api/datasources`)

View File

@ -1,5 +1,5 @@
import { writable, get } from "svelte/store"
import { datasources, integrations } from "./"
import { datasources, integrations, tables } from "./"
import api from "builderStore/api"
export function createQueriesStore() {
@ -59,6 +59,17 @@ export function createQueriesStore() {
...state,
selected: query.datasourceId,
}))
tables.update(state => ({
...state,
selected: null,
}))
},
unselect: () => {
update(state => ({ ...state, selected: null }))
datasources.update(state => ({
...state,
selected: null,
}))
},
delete: async query => {
const response = await api.delete(

View File

@ -1,5 +1,5 @@
import { writable, get } from "svelte/store"
import { views } from "./"
import { views, queries } from "./"
import { cloneDeep } from "lodash/fp"
import api from "builderStore/api"
@ -26,6 +26,7 @@ export function createTablesStore() {
draft: cloneDeep(table),
}))
views.select({ name: table._id })
queries.unselect()
}
}
@ -66,6 +67,7 @@ export function createTablesStore() {
return {
subscribe,
update,
fetch,
select,
save,

View File

@ -93,3 +93,7 @@ exports.revert = async ctx => {
ctx.throw(400, `Unable to revert. ${err}`)
}
}
exports.getBudibaseVersion = async ctx => {
ctx.body = require("../../../package.json").version
}

View File

@ -210,7 +210,7 @@ exports.validate = async () => {
return { valid: true }
}
exports.fetchEnrichedRow = async ctx => {
exports.fetchEnrichedRow = async () => {
// TODO: How does this work
throw "Not Implemented"
}

View File

@ -26,6 +26,7 @@ exports.fetch = async function (ctx) {
const internal = internalTables.rows.map(row => ({
...row.doc,
type: "internal",
sourceId: BudibaseInternalDB._id,
}))
@ -38,6 +39,7 @@ exports.fetch = async function (ctx) {
const external = externalTables.rows.flatMap(row => {
return Object.values(row.doc.entities || {}).map(entity => ({
...entity,
type: "external",
sourceId: row.doc._id,
}))
})

View File

@ -14,6 +14,7 @@ if (env.isDev() || env.isTest()) {
}
router
.get("/api/dev/version", authorized(BUILDER), controller.getBudibaseVersion)
.delete("/api/dev/:appId/lock", authorized(BUILDER), controller.clearLock)
.post("/api/dev/:appId/revert", authorized(BUILDER), controller.revert)

View File

@ -55,7 +55,7 @@ function addFilters(query, filters) {
return query
}
function buildRelationships() {}
// function buildRelationships() {}
function buildCreate(knex, json) {
const { endpoint, body } = json

View File

@ -9,8 +9,6 @@ const airtable = require("./airtable")
const mysql = require("./mysql")
const arangodb = require("./arangodb")
const rest = require("./rest")
// Plus
const postgresPlus = require("../integrations/plus/postgres")
const DEFINITIONS = {
POSTGRES: postgres.schema,

View File

@ -1,5 +0,0 @@
const postgres = require("./postgres")
module.exports = {
POSTGRES_PLUS: postgres,
}

View File

@ -1,135 +0,0 @@
// const Sql = require("../base/sql")
// const { Pool } = require("pg")
// const { FieldTypes } = require("../../constants")
// const { FIELD_TYPES } = require("../Integration")
// const { SEPARATOR } = require("@budibase/auth/db")
// const TYPE_MAP = {
// text: FieldTypes.LONGFORM,
// varchar: FieldTypes.STRING,
// integer: FieldTypes.NUMBER,
// bigint: FieldTypes.NUMBER,
// decimal: FieldTypes.NUMBER,
// smallint: FieldTypes.NUMBER,
// timestamp: FieldTypes.DATETIME,
// time: FieldTypes.DATETIME,
// boolean: FieldTypes.BOOLEAN,
// json: FIELD_TYPES.JSON,
// }
// const SCHEMA = {
// friendlyName: "PostgreSQL",
// description:
// "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.",
// plus: true,
// datasource: {
// host: {
// type: FIELD_TYPES.STRING,
// default: "localhost",
// required: true,
// },
// port: {
// type: FIELD_TYPES.NUMBER,
// required: true,
// default: 5432,
// },
// database: {
// type: FIELD_TYPES.STRING,
// default: "postgres",
// required: true,
// },
// user: {
// type: FIELD_TYPES.STRING,
// default: "root",
// required: true,
// },
// password: {
// type: FIELD_TYPES.PASSWORD,
// default: "root",
// required: true,
// },
// ssl: {
// type: FIELD_TYPES.BOOLEAN,
// default: false,
// required: false,
// },
// },
// }
// class PostgresPlus extends Sql {
// static pool
// COLUMNS_SQL =
// "select * from information_schema.columns where table_schema = 'public'"
// PRIMARY_KEYS_SQL = `
// select tc.table_schema, tc.table_name, kc.column_name as primary_key
// from information_schema.table_constraints tc
// join
// information_schema.key_column_usage kc on kc.table_name = tc.table_name
// and kc.table_schema = tc.table_schema
// and kc.constraint_name = tc.constraint_name
// where tc.constraint_type = 'PRIMARY KEY';
// `
// constructor(config, datasource) {
// super("pg")
// this.config = config
// this.datasource = datasource
// if (!this.pool) {
// this.pool = new Pool(this.config)
// }
// this.client = this.pool
// }
// async init(datasourceId) {
// let keys = []
// try {
// const primaryKeysResponse = await this.client.query(this.PRIMARY_KEYS_SQL)
// for (let table of primaryKeysResponse.rows) {
// keys.push(table.column_name || table.primary_key)
// }
// } catch (err) {
// // TODO: this try catch method isn't right
// keys = ["id"]
// }
// const columnsResponse = await this.client.query(this.COLUMNS_SQL)
// const tables = {}
// for (let column of columnsResponse.rows) {
// const tableName = column.table_name
// const columnName = column.column_name
// // table key doesn't exist yet
// if (!tables[tableName]) {
// tables[tableName] = {
// _id: `${datasourceId}${SEPARATOR}${tableName}`,
// // TODO: this needs to accommodate composite keys
// primary: keys,
// name: tableName,
// schema: {},
// }
// }
// tables[tableName].schema[columnName] = {
// name: columnName,
// type: TYPE_MAP[column.data_type] || FIELD_TYPES.STRING,
// }
// }
// this.tables = tables
// }
// async query(json) {
// const operation = this._operation(json).toLowerCase()
// const sql = this._query(json)
// const response = await this.client.query(sql.sql, sql.bindings)
// return response.rows.length ? response.rows : [{ [operation]: true }]
// }
// }
// module.exports = {
// schema: SCHEMA,
// integration: PostgresPlus,
// }

View File

@ -2,7 +2,6 @@ const { Pool } = require("pg")
const { FIELD_TYPES } = require("./Integration")
const Sql = require("./base/sql")
const { FieldTypes } = require("../constants")
const { SEPARATOR } = require("@budibase/auth/db")
const { buildExternalTableId } = require("./utils")
const SCHEMA = {