Merge branch 'feat/store-tests' of github.com:Budibase/budibase into spectrum-bbui
This commit is contained in:
commit
8619db57b4
|
@ -29,7 +29,9 @@
|
||||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/internals/mocks/fileMock.js",
|
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/internals/mocks/fileMock.js",
|
||||||
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
|
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
|
||||||
"components(.*)$": "<rootDir>/src/components$1",
|
"components(.*)$": "<rootDir>/src/components$1",
|
||||||
"builderStore(.*)$": "<rootDir>/src/builderStore$1"
|
"builderStore(.*)$": "<rootDir>/src/builderStore$1",
|
||||||
|
"stores(.*)$": "<rootDir>/src/stores$1",
|
||||||
|
"analytics(.*)$": "<rootDir>/src/analytics$1"
|
||||||
},
|
},
|
||||||
"moduleFileExtensions": [
|
"moduleFileExtensions": [
|
||||||
"js",
|
"js",
|
||||||
|
@ -90,7 +92,8 @@
|
||||||
"@rollup/plugin-replace": "^2.4.2",
|
"@rollup/plugin-replace": "^2.4.2",
|
||||||
"@roxi/routify": "2.15.1",
|
"@roxi/routify": "2.15.1",
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.5",
|
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.5",
|
||||||
"@testing-library/jest-dom": "^5.11.0",
|
"@babel/runtime": "^7.5.5",
|
||||||
|
"@testing-library/jest-dom": "^5.11.10",
|
||||||
"@testing-library/svelte": "^3.0.0",
|
"@testing-library/svelte": "^3.0.0",
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^26.6.3",
|
||||||
"cypress": "^5.1.0",
|
"cypress": "^5.1.0",
|
||||||
|
@ -98,7 +101,7 @@
|
||||||
"eslint": "^7.23.0",
|
"eslint": "^7.23.0",
|
||||||
"eslint-plugin-cypress": "^2.11.2",
|
"eslint-plugin-cypress": "^2.11.2",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^24.8.0",
|
"jest": "^26.6.3",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup": "^2.44.0",
|
"rollup": "^2.44.0",
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { backendUiStore, store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
import { findComponent, findComponentPath } from "./storeUtils"
|
import {
|
||||||
|
tables as tablesStore,
|
||||||
|
queries as queriesStores,
|
||||||
|
} from "stores/backend/"
|
||||||
|
import { findComponentPath } from "./storeUtils"
|
||||||
import { makePropSafe } from "@budibase/string-templates"
|
import { makePropSafe } from "@budibase/string-templates"
|
||||||
import { TableNames } from "../constants"
|
import { TableNames } from "../constants"
|
||||||
|
|
||||||
|
@ -190,10 +194,13 @@ const getContextBindings = (asset, componentId) => {
|
||||||
*/
|
*/
|
||||||
const getUserBindings = () => {
|
const getUserBindings = () => {
|
||||||
let bindings = []
|
let bindings = []
|
||||||
const { schema } = getSchemaForDatasource({
|
const tables = get(tablesStore).list
|
||||||
type: "table",
|
const userTable = tables.find(table => table._id === TableNames.USERS)
|
||||||
tableId: TableNames.USERS,
|
const schema = {
|
||||||
})
|
...userTable.schema,
|
||||||
|
_id: { type: "string" },
|
||||||
|
_rev: { type: "string" },
|
||||||
|
}
|
||||||
const keys = Object.keys(schema).sort()
|
const keys = Object.keys(schema).sort()
|
||||||
const safeUser = makePropSafe("user")
|
const safeUser = makePropSafe("user")
|
||||||
keys.forEach(key => {
|
keys.forEach(key => {
|
||||||
|
@ -248,10 +255,10 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
|
||||||
if (datasource) {
|
if (datasource) {
|
||||||
const { type } = datasource
|
const { type } = datasource
|
||||||
if (type === "query") {
|
if (type === "query") {
|
||||||
const queries = get(backendUiStore).queries
|
const queries = get(queriesStores).queries
|
||||||
table = queries.find(query => query._id === datasource._id)
|
table = queries.find(query => query._id === datasource._id)
|
||||||
} else {
|
} else {
|
||||||
const tables = get(backendUiStore).tables
|
const tables = get(tablesStore).list
|
||||||
table = tables.find(table => table._id === datasource.tableId)
|
table = tables.find(table => table._id === datasource.tableId)
|
||||||
}
|
}
|
||||||
if (table) {
|
if (table) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { getFrontendStore } from "./store/frontend"
|
import { getFrontendStore } from "./store/frontend"
|
||||||
import { getBackendUiStore } from "./store/backend"
|
|
||||||
import { getAutomationStore } from "./store/automation"
|
import { getAutomationStore } from "./store/automation"
|
||||||
import { getHostingStore } from "./store/hosting"
|
import { getHostingStore } from "./store/hosting"
|
||||||
import { getThemeStore } from "./store/theme"
|
import { getThemeStore } from "./store/theme"
|
||||||
|
@ -9,7 +8,6 @@ import { FrontendTypes, LAYOUT_NAMES } from "../constants"
|
||||||
import { findComponent } from "./storeUtils"
|
import { findComponent } from "./storeUtils"
|
||||||
|
|
||||||
export const store = getFrontendStore()
|
export const store = getFrontendStore()
|
||||||
export const backendUiStore = getBackendUiStore()
|
|
||||||
export const automationStore = getAutomationStore()
|
export const automationStore = getAutomationStore()
|
||||||
export const themeStore = getThemeStore()
|
export const themeStore = getThemeStore()
|
||||||
export const hostingStore = getHostingStore()
|
export const hostingStore = getHostingStore()
|
||||||
|
|
|
@ -2,13 +2,21 @@ import { get, writable } from "svelte/store"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import {
|
import {
|
||||||
allScreens,
|
allScreens,
|
||||||
backendUiStore,
|
|
||||||
hostingStore,
|
hostingStore,
|
||||||
currentAsset,
|
currentAsset,
|
||||||
mainLayout,
|
mainLayout,
|
||||||
selectedComponent,
|
selectedComponent,
|
||||||
selectedAccessRole,
|
selectedAccessRole,
|
||||||
} from "builderStore"
|
} from "builderStore"
|
||||||
|
// Backendstores
|
||||||
|
import {
|
||||||
|
datasources,
|
||||||
|
integrations,
|
||||||
|
queries,
|
||||||
|
database,
|
||||||
|
tables,
|
||||||
|
} from "stores/backend/"
|
||||||
|
|
||||||
import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
|
import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
|
||||||
import api from "../api"
|
import api from "../api"
|
||||||
import { FrontendTypes } from "constants"
|
import { FrontendTypes } from "constants"
|
||||||
|
@ -57,7 +65,16 @@ export const getFrontendStore = () => {
|
||||||
appInstance: application.instance,
|
appInstance: application.instance,
|
||||||
}))
|
}))
|
||||||
await hostingStore.actions.fetch()
|
await hostingStore.actions.fetch()
|
||||||
await backendUiStore.actions.database.select(application.instance)
|
|
||||||
|
// Initialise backend stores
|
||||||
|
const [_integrations] = await Promise.all([
|
||||||
|
api.get("/api/integrations").then(r => r.json()),
|
||||||
|
])
|
||||||
|
datasources.init()
|
||||||
|
integrations.set(_integrations)
|
||||||
|
queries.init()
|
||||||
|
database.set(application.instance)
|
||||||
|
tables.init()
|
||||||
},
|
},
|
||||||
routing: {
|
routing: {
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { processStringSync } from "@budibase/string-templates"
|
import { processStringSync } from "@budibase/string-templates"
|
||||||
import { get } from "lodash/fp"
|
import { get } from "lodash/fp"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
|
|
||||||
export let block
|
export let block
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
let enrichedInputs = { ...inputs, enriched: {} }
|
let enrichedInputs = { ...inputs, enriched: {} }
|
||||||
const tableId = inputs.tableId || inputs.row?.tableId
|
const tableId = inputs.tableId || inputs.row?.tableId
|
||||||
if (tableId) {
|
if (tableId) {
|
||||||
enrichedInputs.enriched.table = $backendUiStore.tables.find(
|
enrichedInputs.enriched.table = $tables.list.find(
|
||||||
table => table._id === tableId
|
table => table._id === tableId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { backendUiStore, automationStore } from "builderStore"
|
import { backendUiStore, automationStore } from "builderStore"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
|
=======
|
||||||
|
import { automationStore } from "builderStore"
|
||||||
|
import { database } from 'stores/backend/'
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { Input, ModalContent } from "@budibase/bbui"
|
import { Input, ModalContent } from "@budibase/bbui"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
@ -8,7 +14,7 @@
|
||||||
let name
|
let name
|
||||||
|
|
||||||
$: valid = !!name
|
$: valid = !!name
|
||||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
$: instanceId = $database._id
|
||||||
|
|
||||||
async function createAutomation() {
|
async function createAutomation() {
|
||||||
await automationStore.actions.create({
|
await automationStore.actions.create({
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { automationStore, backendUiStore } from "builderStore"
|
import { automationStore, backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { automationStore } from "builderStore"
|
||||||
|
import { database } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { DropdownMenu } from "@budibase/bbui"
|
import { DropdownMenu } from "@budibase/bbui"
|
||||||
import { DropdownContainer, DropdownItem } from "components/common/Dropdowns"
|
import { DropdownContainer, DropdownItem } from "components/common/Dropdowns"
|
||||||
|
@ -11,7 +17,7 @@
|
||||||
let anchor
|
let anchor
|
||||||
let dropdown
|
let dropdown
|
||||||
let confirmDeleteDialog
|
let confirmDeleteDialog
|
||||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
$: instanceId = $database._id
|
||||||
|
|
||||||
function showModal() {
|
function showModal() {
|
||||||
dropdown.hide()
|
dropdown.hide()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select } from "@budibase/bbui"
|
||||||
import DrawerBindableInput from "../../common/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "../../common/DrawerBindableInput.svelte"
|
||||||
import AutomationBindingPanel from "./AutomationBindingPanel.svelte"
|
import AutomationBindingPanel from "./AutomationBindingPanel.svelte"
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
export let value
|
export let value
|
||||||
export let bindings
|
export let bindings
|
||||||
|
|
||||||
$: table = $backendUiStore.tables.find(table => table._id === value?.tableId)
|
$: table = $tables.list.find(table => table._id === value?.tableId)
|
||||||
$: schemaFields = Object.entries(table?.schema ?? {})
|
$: schemaFields = Object.entries(table?.schema ?? {})
|
||||||
|
|
||||||
// Ensure any nullish tableId values get set to empty string so
|
// Ensure any nullish tableId values get set to empty string so
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<div class="block-field">
|
<div class="block-field">
|
||||||
<Select bind:value={value.tableId} extraThin secondary>
|
<Select bind:value={value.tableId} extraThin secondary>
|
||||||
<option value="">Choose an option</option>
|
<option value="">Choose an option</option>
|
||||||
{#each $backendUiStore.tables as table}
|
{#each $tables.list as table}
|
||||||
<option value={table._id}>{table.name}</option>
|
<option value={table._id}>{table.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore, automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
|
import { database } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import AutomationBlockSetup from "./AutomationBlockSetup.svelte"
|
import AutomationBlockSetup from "./AutomationBlockSetup.svelte"
|
||||||
import { Button, Modal } from "@budibase/bbui"
|
import { Button, Modal } from "@budibase/bbui"
|
||||||
|
@ -7,7 +8,7 @@
|
||||||
|
|
||||||
let webhookModal
|
let webhookModal
|
||||||
|
|
||||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
$: instanceId = $database._id
|
||||||
$: automation = $automationStore.selectedAutomation?.automation
|
$: automation = $automationStore.selectedAutomation?.automation
|
||||||
$: automationLive = automation?.live
|
$: automationLive = automation?.live
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select } from "@budibase/bbui"
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
<div class="block-field">
|
<div class="block-field">
|
||||||
<Select bind:value secondary extraThin>
|
<Select bind:value secondary extraThin>
|
||||||
<option value="">Choose an option</option>
|
<option value="">Choose an option</option>
|
||||||
{#each $backendUiStore.tables as table}
|
{#each $tables.list as table}
|
||||||
<option value={table._id}>{table.name}</option>
|
<option value={table._id}>{table.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { store, backendUiStore, automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
|
import { database } from 'stores/backend/'
|
||||||
import WebhookDisplay from "./WebhookDisplay.svelte"
|
import WebhookDisplay from "./WebhookDisplay.svelte"
|
||||||
import { ModalContent } from "@budibase/bbui"
|
import { ModalContent } from "@budibase/bbui"
|
||||||
import { onMount, onDestroy } from "svelte"
|
import { onMount, onDestroy } from "svelte"
|
||||||
|
@ -10,8 +11,7 @@
|
||||||
let schemaURL
|
let schemaURL
|
||||||
let propCount = 0
|
let propCount = 0
|
||||||
|
|
||||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
$: instanceId = $database._id
|
||||||
$: appId = $store.appId
|
|
||||||
$: automation = $automationStore.selectedAutomation?.automation
|
$: automation = $automationStore.selectedAutomation?.automation
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables, views } from 'stores/backend/'
|
||||||
|
|
||||||
import CreateRowButton from "./buttons/CreateRowButton.svelte"
|
import CreateRowButton from "./buttons/CreateRowButton.svelte"
|
||||||
import CreateColumnButton from "./buttons/CreateColumnButton.svelte"
|
import CreateColumnButton from "./buttons/CreateColumnButton.svelte"
|
||||||
import CreateViewButton from "./buttons/CreateViewButton.svelte"
|
import CreateViewButton from "./buttons/CreateViewButton.svelte"
|
||||||
|
@ -16,19 +17,19 @@
|
||||||
let hideAutocolumns = true
|
let hideAutocolumns = true
|
||||||
let data = []
|
let data = []
|
||||||
let loading = false
|
let loading = false
|
||||||
$: isUsersTable = $backendUiStore.selectedTable?._id === TableNames.USERS
|
$: isUsersTable = $tables.selected?._id === TableNames.USERS
|
||||||
$: title = $backendUiStore.selectedTable.name
|
$: title = $tables.selected.name
|
||||||
$: schema = $backendUiStore.selectedTable.schema
|
$: schema = $tables.selected.schema
|
||||||
$: tableView = {
|
$: tableView = {
|
||||||
schema,
|
schema,
|
||||||
name: $backendUiStore.selectedView.name,
|
name: $views.selected?.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch rows for specified table
|
// Fetch rows for specified table
|
||||||
$: {
|
$: {
|
||||||
if ($backendUiStore.selectedView?.name?.startsWith("all_")) {
|
if ($views.selected?.name?.startsWith("all_")) {
|
||||||
loading = true
|
loading = true
|
||||||
api.fetchDataForView($backendUiStore.selectedView).then(rows => {
|
api.fetchDataForView($views.selected).then(rows => {
|
||||||
data = rows || []
|
data = rows || []
|
||||||
loading = false
|
loading = false
|
||||||
})
|
})
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
<Table
|
<Table
|
||||||
{title}
|
{title}
|
||||||
{schema}
|
{schema}
|
||||||
tableId={$backendUiStore.selectedTable?._id}
|
tableId={$tables.selected?._id}
|
||||||
{data}
|
{data}
|
||||||
allowEditing={true}
|
allowEditing={true}
|
||||||
bind:hideAutocolumns
|
bind:hideAutocolumns
|
||||||
|
@ -50,7 +51,7 @@
|
||||||
title={isUsersTable ? 'Create New User' : 'Create New Row'}
|
title={isUsersTable ? 'Create New User' : 'Create New Row'}
|
||||||
modalContentComponent={isUsersTable ? CreateEditUser : CreateEditRow} />
|
modalContentComponent={isUsersTable ? CreateEditUser : CreateEditRow} />
|
||||||
<CreateViewButton />
|
<CreateViewButton />
|
||||||
<ManageAccessButton resourceId={$backendUiStore.selectedTable?._id} />
|
<ManageAccessButton resourceId={$tables.selected?._id} />
|
||||||
{#if isUsersTable}
|
{#if isUsersTable}
|
||||||
<EditRolesButton />
|
<EditRolesButton />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { params } from "@roxi/routify"
|
import { params } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import * as api from "./api"
|
import * as api from "./api"
|
||||||
|
=======
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import Table from "./Table.svelte"
|
import Table from "./Table.svelte"
|
||||||
|
|
||||||
export let query = {}
|
export let query = {}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import Table from "./Table.svelte"
|
import Table from "./Table.svelte"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
|
|
||||||
export let tableId
|
export let tableId
|
||||||
export let rowId
|
export let rowId
|
||||||
|
@ -12,11 +12,11 @@
|
||||||
|
|
||||||
$: data = row?.[fieldName] ?? []
|
$: data = row?.[fieldName] ?? []
|
||||||
$: linkedTableId = data?.length ? data[0].tableId : null
|
$: linkedTableId = data?.length ? data[0].tableId : null
|
||||||
$: linkedTable = $backendUiStore.tables.find(
|
$: linkedTable = $tables.list.find(
|
||||||
table => table._id === linkedTableId
|
table => table._id === linkedTableId
|
||||||
)
|
)
|
||||||
$: schema = linkedTable?.schema
|
$: schema = linkedTable?.schema
|
||||||
$: table = $backendUiStore.tables.find(table => table._id === tableId)
|
$: table = $tables.list.find(table => table._id === tableId)
|
||||||
$: fetchData(tableId, rowId)
|
$: fetchData(tableId, rowId)
|
||||||
$: {
|
$: {
|
||||||
let rowLabel = row?.[table?.primaryDisplay]
|
let rowLabel = row?.[table?.primaryDisplay]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
|
|
||||||
import Table from "./Table.svelte"
|
import Table from "./Table.svelte"
|
||||||
import CalculateButton from "./buttons/CalculateButton.svelte"
|
import CalculateButton from "./buttons/CalculateButton.svelte"
|
||||||
import GroupByButton from "./buttons/GroupByButton.svelte"
|
import GroupByButton from "./buttons/GroupByButton.svelte"
|
||||||
|
@ -26,8 +27,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchViewData(name, field, groupBy, calculation) {
|
async function fetchViewData(name, field, groupBy, calculation) {
|
||||||
const tables = $backendUiStore.tables
|
const _tables = $tables.list
|
||||||
const allTableViews = tables.map(table => table.views)
|
const allTableViews = _tables.map(table => table.views)
|
||||||
const thisView = allTableViews.filter(
|
const thisView = allTableViews.filter(
|
||||||
views => views != null && views[name] != null
|
views => views != null && views[name] != null
|
||||||
)[0]
|
)[0]
|
||||||
|
|
|
@ -1,22 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
import { TextButton, Icon, Popover } from "@budibase/bbui"
|
import { TextButton, Popover } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
import { permissions } from 'stores/backend/'
|
||||||
import { Roles } from "constants/backend"
|
|
||||||
import api from "builderStore/api"
|
|
||||||
import ManageAccessPopover from "../popovers/ManageAccessPopover.svelte"
|
import ManageAccessPopover from "../popovers/ManageAccessPopover.svelte"
|
||||||
|
|
||||||
export let resourceId
|
export let resourceId
|
||||||
|
|
||||||
let anchor
|
let anchor
|
||||||
let dropdown
|
let dropdown
|
||||||
let levels
|
let resourcePermissions
|
||||||
let permissions
|
|
||||||
|
|
||||||
async function openDropdown() {
|
async function openDropdown() {
|
||||||
permissions = await backendUiStore.actions.permissions.forResource(
|
resourcePermissions = await permissions.forResource(
|
||||||
resourceId
|
resourceId
|
||||||
)
|
)
|
||||||
levels = await backendUiStore.actions.permissions.fetchLevels()
|
|
||||||
dropdown.show()
|
dropdown.show()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -30,8 +26,8 @@
|
||||||
<Popover bind:this={dropdown} {anchor} align="left">
|
<Popover bind:this={dropdown} {anchor} align="left">
|
||||||
<ManageAccessPopover
|
<ManageAccessPopover
|
||||||
{resourceId}
|
{resourceId}
|
||||||
{levels}
|
levels={$permissions}
|
||||||
{permissions}
|
permissions={resourcePermissions}
|
||||||
onClosed={dropdown.hide} />
|
onClosed={dropdown.hide} />
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { roles } from 'stores/backend/'
|
||||||
|
|
||||||
export let roleId
|
export let roleId
|
||||||
|
|
||||||
$: role = $backendUiStore.roles.find(role => role._id === roleId)
|
$: role = $roles.find(role => role._id === roleId)
|
||||||
$: roleName = role?.name ?? "Unknown role"
|
$: roleName = role?.name ?? "Unknown role"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
Radio,
|
Radio,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
|
|
||||||
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
||||||
import {
|
import {
|
||||||
FIELDS,
|
FIELDS,
|
||||||
|
@ -33,29 +34,29 @@
|
||||||
constraints: fieldDefinitions.STRING.constraints,
|
constraints: fieldDefinitions.STRING.constraints,
|
||||||
|
|
||||||
// Initial value for column name in other table for linked records
|
// Initial value for column name in other table for linked records
|
||||||
fieldName: $backendUiStore.selectedTable.name,
|
fieldName: $tables.selected.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
let originalName = field.name
|
let originalName = field.name
|
||||||
let primaryDisplay =
|
let primaryDisplay =
|
||||||
$backendUiStore.selectedTable.primaryDisplay == null ||
|
$tables.selected.primaryDisplay == null ||
|
||||||
$backendUiStore.selectedTable.primaryDisplay === field.name
|
$tables.selected.primaryDisplay === field.name
|
||||||
|
|
||||||
let table = $backendUiStore.selectedTable
|
let table = $tables.selected
|
||||||
let indexes = [...($backendUiStore.selectedTable.indexes || [])]
|
let indexes = [...($tables.selected.indexes || [])]
|
||||||
let confirmDeleteDialog
|
let confirmDeleteDialog
|
||||||
let deletion
|
let deletion
|
||||||
|
|
||||||
$: tableOptions = $backendUiStore.tables.filter(
|
$: tableOptions = $tables.list.filter(
|
||||||
table => table._id !== $backendUiStore.draftTable._id
|
table => table._id !== $tables.draft._id
|
||||||
)
|
)
|
||||||
$: required = !!field?.constraints?.presence || primaryDisplay
|
$: required = !!field?.constraints?.presence || primaryDisplay
|
||||||
$: uneditable =
|
$: uneditable =
|
||||||
$backendUiStore.selectedTable?._id === TableNames.USERS &&
|
$tables.selected?._id === TableNames.USERS &&
|
||||||
UNEDITABLE_USER_FIELDS.includes(field.name)
|
UNEDITABLE_USER_FIELDS.includes(field.name)
|
||||||
$: invalid =
|
$: invalid =
|
||||||
(field.type === LINK_TYPE && !field.tableId) ||
|
(field.type === LINK_TYPE && !field.tableId) ||
|
||||||
Object.keys($backendUiStore.draftTable.schema).some(
|
Object.keys($tables.draft.schema).some(
|
||||||
key => key === field.name
|
key => key === field.name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,28 +73,25 @@
|
||||||
async function saveColumn() {
|
async function saveColumn() {
|
||||||
if (field.type === AUTO_COL) {
|
if (field.type === AUTO_COL) {
|
||||||
field = buildAutoColumn(
|
field = buildAutoColumn(
|
||||||
$backendUiStore.draftTable.name,
|
$tables.draft.name,
|
||||||
field.name,
|
field.name,
|
||||||
field.subtype
|
field.subtype
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
backendUiStore.update(state => {
|
tables.saveField({
|
||||||
backendUiStore.actions.tables.saveField({
|
|
||||||
originalName,
|
originalName,
|
||||||
field,
|
field,
|
||||||
primaryDisplay,
|
primaryDisplay,
|
||||||
indexes,
|
indexes,
|
||||||
})
|
})
|
||||||
return state
|
|
||||||
})
|
|
||||||
onClosed()
|
onClosed()
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteColumn() {
|
function deleteColumn() {
|
||||||
if (field.name === $backendUiStore.selectedTable.primaryDisplay) {
|
if (field.name === $tables.selected.primaryDisplay) {
|
||||||
notifier.danger("You cannot delete the display column")
|
notifier.danger("You cannot delete the display column")
|
||||||
} else {
|
} else {
|
||||||
backendUiStore.actions.tables.deleteField(field)
|
tables.deleteField(field)
|
||||||
notifier.success(`Column ${field.name} deleted.`)
|
notifier.success(`Column ${field.name} deleted.`)
|
||||||
onClosed()
|
onClosed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables, rows } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import RowFieldControl from "../RowFieldControl.svelte"
|
import RowFieldControl from "../RowFieldControl.svelte"
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
$: creating = row?._id == null
|
$: creating = row?._id == null
|
||||||
$: table = row.tableId
|
$: table = row.tableId
|
||||||
? $backendUiStore.tables.find(table => table._id === row?.tableId)
|
? $tables.list.find(table => table._id === row?.tableId)
|
||||||
: $backendUiStore.selectedTable
|
: $tables.selected
|
||||||
$: tableSchema = Object.entries(table?.schema ?? {})
|
$: tableSchema = Object.entries(table?.schema ?? {})
|
||||||
|
|
||||||
async function saveRow() {
|
async function saveRow() {
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier.success("Row saved successfully.")
|
notifier.success("Row saved successfully.")
|
||||||
backendUiStore.actions.rows.save(rowResponse)
|
rows.save(rowResponse)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables, rows } from 'stores/backend/'
|
||||||
|
import { roles } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import RowFieldControl from "../RowFieldControl.svelte"
|
import RowFieldControl from "../RowFieldControl.svelte"
|
||||||
import * as backendApi from "../api"
|
import * as backendApi from "../api"
|
||||||
|
@ -12,8 +13,8 @@
|
||||||
|
|
||||||
$: creating = row?._id == null
|
$: creating = row?._id == null
|
||||||
$: table = row.tableId
|
$: table = row.tableId
|
||||||
? $backendUiStore.tables.find(table => table._id === row?.tableId)
|
? $tables.list.find(table => table._id === row?.tableId)
|
||||||
: $backendUiStore.selectedTable
|
: $tables.selected
|
||||||
$: tableSchema = getUserSchema(table)
|
$: tableSchema = getUserSchema(table)
|
||||||
$: customSchemaKeys = getCustomSchemaKeys(tableSchema)
|
$: customSchemaKeys = getCustomSchemaKeys(tableSchema)
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier.success("User saved successfully.")
|
notifier.success("User saved successfully.")
|
||||||
backendUiStore.actions.rows.save(rowResponse)
|
rows.save(rowResponse)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@
|
||||||
data-cy="roleId-select"
|
data-cy="roleId-select"
|
||||||
bind:value={row.roleId}>
|
bind:value={row.roleId}>
|
||||||
<option value="">Choose an option</option>
|
<option value="">Choose an option</option>
|
||||||
{#each $backendUiStore.roles as role}
|
{#each $roles as role}
|
||||||
<option value={role._id}>{role.name}</option>
|
<option value={role._id}>{role.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { rows } from 'stores/backend/'
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
async function deleteRow() {
|
async function deleteRow() {
|
||||||
await api.deleteRow(row)
|
await api.deleteRow(row)
|
||||||
notifier.success("Row deleted")
|
notifier.success("Row deleted")
|
||||||
backendUiStore.actions.rows.delete(row)
|
rows.delete(row)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||||
import { backendUiStore } from "builderStore"
|
import { roles } from 'stores/backend/'
|
||||||
|
|
||||||
let basePermissions = []
|
let basePermissions = []
|
||||||
let selectedRole = {}
|
let selectedRole = {}
|
||||||
let errors = []
|
let errors = []
|
||||||
let builtInRoles = ["Admin", "Power", "Basic", "Public"]
|
let builtInRoles = ["Admin", "Power", "Basic", "Public"]
|
||||||
$: selectedRoleId = selectedRole._id
|
$: selectedRoleId = selectedRole._id
|
||||||
$: otherRoles = $backendUiStore.roles.filter(
|
$: otherRoles = $roles.filter(
|
||||||
role => role._id !== selectedRoleId
|
role => role._id !== selectedRoleId
|
||||||
)
|
)
|
||||||
$: isCreating = selectedRoleId == null || selectedRoleId === ""
|
$: isCreating = selectedRoleId == null || selectedRoleId === ""
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
// Changes the selected role
|
// Changes the selected role
|
||||||
const changeRole = event => {
|
const changeRole = event => {
|
||||||
const id = event?.target?.value
|
const id = event?.target?.value
|
||||||
const role = $backendUiStore.roles.find(role => role._id === id)
|
const role = $roles.find(role => role._id === id)
|
||||||
if (role) {
|
if (role) {
|
||||||
selectedRole = {
|
selectedRole = {
|
||||||
...role,
|
...role,
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save/create the role
|
// Save/create the role
|
||||||
const response = await backendUiStore.actions.roles.save(selectedRole)
|
const response = await roles.save(selectedRole)
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
notifier.success("Role saved successfully.")
|
notifier.success("Role saved successfully.")
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
// Deletes the selected role
|
// Deletes the selected role
|
||||||
const deleteRole = async () => {
|
const deleteRole = async () => {
|
||||||
const response = await backendUiStore.actions.roles.delete(selectedRole)
|
const response = await roles.delete(selectedRole)
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
changeRole()
|
changeRole()
|
||||||
notifier.success("Role deleted successfully.")
|
notifier.success("Role deleted successfully.")
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
value={selectedRoleId}
|
value={selectedRoleId}
|
||||||
on:change={changeRole}>
|
on:change={changeRole}>
|
||||||
<option value="">Create new role</option>
|
<option value="">Create new role</option>
|
||||||
{#each $backendUiStore.roles as role}
|
{#each $roles as role}
|
||||||
<option value={role._id}>{role.name}</option>
|
<option value={role._id}>{role.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Select } from "@budibase/bbui"
|
import { Button, Select } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
|
||||||
|
import { tables, views } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@
|
||||||
export let view = {}
|
export let view = {}
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
$: viewTable = $backendUiStore.tables.find(
|
$: viewTable = $tables.list.find(
|
||||||
({ _id }) => _id === $backendUiStore.selectedView.tableId
|
({ _id }) => _id === $views.selected.tableId
|
||||||
)
|
)
|
||||||
$: fields =
|
$: fields =
|
||||||
viewTable &&
|
viewTable &&
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
function saveView() {
|
function saveView() {
|
||||||
backendUiStore.actions.views.save(view)
|
views.save(view)
|
||||||
notifier.success(`View ${view.name} saved.`)
|
notifier.success(`View ${view.name} saved.`)
|
||||||
onClosed()
|
onClosed()
|
||||||
analytics.captureEvent("Added View Calculate", { field: view.field })
|
analytics.captureEvent("Added View Calculate", { field: view.field })
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Input } from "@budibase/bbui"
|
import { Button, Input } from "@budibase/bbui"
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { views as viewsStore } from 'stores/backend/'
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
|
||||||
|
@ -10,10 +16,7 @@
|
||||||
let name
|
let name
|
||||||
let field
|
let field
|
||||||
|
|
||||||
$: fields = Object.keys($backendUiStore.selectedTable.schema).filter(key => {
|
$: views = $tables.list.flatMap(table =>
|
||||||
return $backendUiStore.selectedTable.schema[key].type === "number"
|
|
||||||
})
|
|
||||||
$: views = $backendUiStore.tables.flatMap(table =>
|
|
||||||
Object.keys(table.views || {})
|
Object.keys(table.views || {})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,9 +25,9 @@
|
||||||
notifier.danger(`View exists with name ${name}.`)
|
notifier.danger(`View exists with name ${name}.`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
backendUiStore.actions.views.save({
|
viewsStore.save({
|
||||||
name,
|
name,
|
||||||
tableId: $backendUiStore.selectedTable._id,
|
tableId: $tables.selected._id,
|
||||||
field,
|
field,
|
||||||
})
|
})
|
||||||
notifier.success(`View ${name} created`)
|
notifier.success(`View ${name} created`)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Input, Select, DatePicker } from "@budibase/bbui"
|
import { Button, Input, Select, DatePicker } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables, views } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@
|
||||||
export let view = {}
|
export let view = {}
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
$: viewTable = $backendUiStore.tables.find(
|
$: viewTable = $tables.list.find(
|
||||||
({ _id }) => _id === $backendUiStore.selectedView.tableId
|
({ _id }) => _id === $views.selected.tableId
|
||||||
)
|
)
|
||||||
$: fields = viewTable && Object.keys(viewTable.schema)
|
$: fields = viewTable && Object.keys(viewTable.schema)
|
||||||
|
|
||||||
function saveView() {
|
function saveView() {
|
||||||
backendUiStore.actions.views.save(view)
|
views.save(view)
|
||||||
notifier.success(`View ${view.name} saved.`)
|
notifier.success(`View ${view.name} saved.`)
|
||||||
onClosed()
|
onClosed()
|
||||||
analytics.captureEvent("Added View Filter", {
|
analytics.captureEvent("Added View Filter", {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Select } from "@budibase/bbui"
|
import { Button, Select } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables, views } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { FIELDS } from "constants/backend"
|
import { FIELDS } from "constants/backend"
|
||||||
|
|
||||||
export let view = {}
|
export let view = {}
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
$: viewTable = $backendUiStore.tables.find(
|
$: viewTable = $tables.list.find(
|
||||||
({ _id }) => _id === $backendUiStore.selectedView.tableId
|
({ _id }) => _id === $views.selected.tableId
|
||||||
)
|
)
|
||||||
$: fields =
|
$: fields =
|
||||||
viewTable &&
|
viewTable &&
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
.map(([key]) => key)
|
.map(([key]) => key)
|
||||||
|
|
||||||
function saveView() {
|
function saveView() {
|
||||||
backendUiStore.actions.views.save(view)
|
views.save(view)
|
||||||
notifier.success(`View ${view.name} saved.`)
|
notifier.success(`View ${view.name} saved.`)
|
||||||
onClosed()
|
onClosed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { roles, permissions as permissionsStore } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { Button, Label, Input, Select, Spacer } from "@budibase/bbui"
|
import { Button, Label, Input, Select, Spacer } from "@budibase/bbui"
|
||||||
|
|
||||||
|
@ -8,14 +8,14 @@
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
async function changePermission(level, role) {
|
async function changePermission(level, role) {
|
||||||
await backendUiStore.actions.permissions.save({
|
await permissionsStore.save({
|
||||||
level,
|
level,
|
||||||
role,
|
role,
|
||||||
resource: resourceId,
|
resource: resourceId,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Show updated permissions in UI: REMOVE
|
// Show updated permissions in UI: REMOVE
|
||||||
permissions = await backendUiStore.actions.permissions.forResource(
|
permissions = await permissionsStore.forResource(
|
||||||
resourceId
|
resourceId
|
||||||
)
|
)
|
||||||
notifier.success("Updated permissions.")
|
notifier.success("Updated permissions.")
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
thin
|
thin
|
||||||
value={permissions[level]}
|
value={permissions[level]}
|
||||||
on:change={e => changePermission(level, e.target.value)}>
|
on:change={e => changePermission(level, e.target.value)}>
|
||||||
{#each $backendUiStore.roles as role}
|
{#each $roles as role}
|
||||||
<option value={role._id}>{role.name}</option>
|
<option value={role._id}>{role.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
@ -67,10 +67,6 @@
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: var(--spacing-s) 0 var(--spacing-m) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
|
@ -1,38 +1,43 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { database, datasources, queries } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import EditDatasourcePopover from "./popovers/EditDatasourcePopover.svelte"
|
import EditDatasourcePopover from "./popovers/EditDatasourcePopover.svelte"
|
||||||
import EditQueryPopover from "./popovers/EditQueryPopover.svelte"
|
import EditQueryPopover from "./popovers/EditQueryPopover.svelte"
|
||||||
import NavItem from "components/common/NavItem.svelte"
|
import NavItem from "components/common/NavItem.svelte"
|
||||||
import ICONS from "./icons"
|
import ICONS from "./icons"
|
||||||
|
|
||||||
function selectDatasource(datasource) {
|
function selectDatasource(datasource) {
|
||||||
backendUiStore.actions.datasources.select(datasource._id)
|
datasources.select(datasource._id)
|
||||||
$goto(`./datasource/${datasource._id}`)
|
$goto(`./datasource/${datasource._id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClickQuery(query) {
|
function onClickQuery(query) {
|
||||||
if ($backendUiStore.selectedQueryId === query._id) {
|
if ($queries.selected === query._id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
backendUiStore.actions.queries.select(query)
|
queries.select(query)
|
||||||
$goto(`./datasource/${query.datasourceId}/${query._id}`)
|
$goto(`./datasource/${query.datasourceId}/${query._id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
backendUiStore.actions.datasources.fetch()
|
datasources.fetch()
|
||||||
backendUiStore.actions.queries.fetch()
|
queries.fetch()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $backendUiStore.selectedDatabase && $backendUiStore.selectedDatabase._id}
|
{#if $database?._id}
|
||||||
<div class="hierarchy-items-container">
|
<div class="hierarchy-items-container">
|
||||||
{#each $backendUiStore.datasources as datasource, idx}
|
{#each $datasources.list as datasource, idx}
|
||||||
<NavItem
|
<NavItem
|
||||||
border={idx > 0}
|
border={idx > 0}
|
||||||
text={datasource.name}
|
text={datasource.name}
|
||||||
selected={$backendUiStore.selectedDatasourceId === datasource._id}
|
selected={$datasources.selected === datasource._id}
|
||||||
on:click={() => selectDatasource(datasource)}>
|
on:click={() => selectDatasource(datasource)}>
|
||||||
<div class="datasource-icon" slot="icon">
|
<div class="datasource-icon" slot="icon">
|
||||||
<svelte:component
|
<svelte:component
|
||||||
|
@ -42,12 +47,12 @@
|
||||||
</div>
|
</div>
|
||||||
<EditDatasourcePopover {datasource} />
|
<EditDatasourcePopover {datasource} />
|
||||||
</NavItem>
|
</NavItem>
|
||||||
{#each $backendUiStore.queries.filter(query => query.datasourceId === datasource._id) as query}
|
{#each $queries.list.filter(query => query.datasourceId === datasource._id) as query}
|
||||||
<NavItem
|
<NavItem
|
||||||
indentLevel={1}
|
indentLevel={1}
|
||||||
icon="ri-eye-line"
|
icon="ri-eye-line"
|
||||||
text={query.name}
|
text={query.name}
|
||||||
selected={$backendUiStore.selectedQueryId === query._id}
|
selected={$queries.selected === query._id}
|
||||||
on:click={() => onClickQuery(query)}>
|
on:click={() => onClickQuery(query)}>
|
||||||
<EditQueryPopover {query} />
|
<EditQueryPopover {query} />
|
||||||
</NavItem>
|
</NavItem>
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto, params } from "@roxi/routify"
|
import { goto, params } from "@roxi/routify"
|
||||||
import { backendUiStore, store } from "builderStore"
|
import { backendUiStore, store } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { datasources } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { Input, Label, ModalContent, Button, Spacer } from "@budibase/bbui"
|
import { Input, Label, ModalContent } from "@budibase/bbui"
|
||||||
import TableIntegrationMenu from "../TableIntegrationMenu/index.svelte"
|
import TableIntegrationMenu from "../TableIntegrationMenu/index.svelte"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
|
||||||
|
@ -14,7 +19,7 @@
|
||||||
function checkValid(evt) {
|
function checkValid(evt) {
|
||||||
const datasourceName = evt.target.value
|
const datasourceName = evt.target.value
|
||||||
if (
|
if (
|
||||||
$backendUiStore.datasources?.some(
|
$datasources?.list.some(
|
||||||
datasource => datasource.name === datasourceName
|
datasource => datasource.name === datasourceName
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -28,7 +33,7 @@
|
||||||
const { type, ...config } = integration
|
const { type, ...config } = integration
|
||||||
|
|
||||||
// Create datasource
|
// Create datasource
|
||||||
const response = await backendUiStore.actions.datasources.save({
|
const response = await datasources.save({
|
||||||
name,
|
name,
|
||||||
source: type,
|
source: type,
|
||||||
config,
|
config,
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { datasources } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { DropdownMenu } from "@budibase/bbui"
|
import { DropdownMenu } from "@budibase/bbui"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
|
@ -22,8 +27,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteDatasource() {
|
async function deleteDatasource() {
|
||||||
const wasSelectedSource = $backendUiStore.selectedDatasourceId
|
const wasSelectedSource = $datasources.selected
|
||||||
await backendUiStore.actions.datasources.delete(datasource)
|
console.log(wasSelectedSource)
|
||||||
|
console.log(datasource)
|
||||||
|
await datasources.delete(datasource)
|
||||||
notifier.success("Datasource deleted")
|
notifier.success("Datasource deleted")
|
||||||
// navigate to first index page if the source you are deleting is selected
|
// navigate to first index page if the source you are deleting is selected
|
||||||
if (wasSelectedSource === datasource._id) {
|
if (wasSelectedSource === datasource._id) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore, store, allScreens } from "builderStore"
|
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
import { DropdownMenu } from "@budibase/bbui"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import { DropdownContainer, DropdownItem } from "components/common/Dropdowns"
|
import { DropdownContainer, DropdownItem } from "components/common/Dropdowns"
|
||||||
|
|
||||||
|
@ -10,8 +9,6 @@
|
||||||
let anchor
|
let anchor
|
||||||
let dropdown
|
let dropdown
|
||||||
let confirmDeleteDialog
|
let confirmDeleteDialog
|
||||||
let error = ""
|
|
||||||
let willBeDeleted
|
|
||||||
|
|
||||||
function hideEditor() {
|
function hideEditor() {
|
||||||
dropdown?.hide()
|
dropdown?.hide()
|
||||||
|
@ -23,7 +20,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteQuery() {
|
async function deleteQuery() {
|
||||||
await backendUiStore.actions.queries.delete(query)
|
await queries.delete(query)
|
||||||
notifier.success("Query deleted")
|
notifier.success("Query deleted")
|
||||||
hideEditor()
|
hideEditor()
|
||||||
}
|
}
|
||||||
|
@ -62,22 +59,4 @@
|
||||||
div.icon i {
|
div.icon i {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
|
||||||
padding: var(--spacing-xl);
|
|
||||||
display: grid;
|
|
||||||
grid-gap: var(--spacing-xl);
|
|
||||||
min-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: var(--spacing-m);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { tables, views, database } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { TableNames } from "constants"
|
import { TableNames } from "constants"
|
||||||
import EditTablePopover from "./popovers/EditTablePopover.svelte"
|
import EditTablePopover from "./popovers/EditTablePopover.svelte"
|
||||||
import EditViewPopover from "./popovers/EditViewPopover.svelte"
|
import EditViewPopover from "./popovers/EditViewPopover.svelte"
|
||||||
import NavItem from "components/common/NavItem.svelte"
|
import NavItem from "components/common/NavItem.svelte"
|
||||||
|
|
||||||
$: selectedView =
|
$: selectedView =
|
||||||
$backendUiStore.selectedView && $backendUiStore.selectedView.name
|
$views.selected && $views.selected.name
|
||||||
|
|
||||||
function selectTable(table) {
|
function selectTable(table) {
|
||||||
backendUiStore.actions.tables.select(table)
|
tables.select(table)
|
||||||
$goto(`./table/${table._id}`)
|
$goto(`./table/${table._id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectView(view) {
|
function selectView(view) {
|
||||||
backendUiStore.actions.views.select(view)
|
views.select(view)
|
||||||
$goto(`./view/${view.name}`)
|
$goto(`./view/${view.name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +33,12 @@
|
||||||
...table.views[viewName],
|
...table.views[viewName],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $backendUiStore.selectedDatabase && $backendUiStore.selectedDatabase._id}
|
{#if $database?._id}
|
||||||
<div class="hierarchy-items-container">
|
<div class="hierarchy-items-container">
|
||||||
{#each $backendUiStore.tables as table, idx}
|
{#each $tables.list as table, idx}
|
||||||
<NavItem
|
<NavItem
|
||||||
border={idx > 0}
|
border={idx > 0}
|
||||||
icon={`ri-${table._id === TableNames.USERS ? 'user' : 'table'}-line`}
|
icon={`ri-${table._id === TableNames.USERS ? 'user' : 'table'}-line`}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore, store } from "builderStore"
|
import { backendUiStore, store } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { Input, Label, ModalContent, Toggle } from "@budibase/bbui"
|
import { Input, Label, ModalContent, Toggle } from "@budibase/bbui"
|
||||||
import TableDataImport from "../TableDataImport.svelte"
|
import TableDataImport from "../TableDataImport.svelte"
|
||||||
|
@ -17,7 +23,7 @@
|
||||||
ROW_LIST_TEMPLATE,
|
ROW_LIST_TEMPLATE,
|
||||||
]
|
]
|
||||||
|
|
||||||
$: tableNames = $backendUiStore.tables.map(table => table.name)
|
$: tableNames = $tables.list.map(table => table.name)
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
let name
|
let name
|
||||||
|
@ -58,7 +64,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create table
|
// Create table
|
||||||
const table = await backendUiStore.actions.tables.save(newTable)
|
const table = await tables.save(newTable)
|
||||||
notifier.success(`Table ${name} created successfully.`)
|
notifier.success(`Table ${name} created successfully.`)
|
||||||
analytics.captureEvent("Table Created", { name })
|
analytics.captureEvent("Table Created", { name })
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore, store, allScreens } from "builderStore"
|
import { backendUiStore, store, allScreens } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from '@sveltech/routify'
|
||||||
|
import { store, allScreens } from "builderStore"
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
|
@ -37,10 +43,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteTable() {
|
async function deleteTable() {
|
||||||
const wasSelectedTable = $backendUiStore.selectedTable
|
const wasSelectedTable = $tables.selected
|
||||||
await backendUiStore.actions.tables.delete(table)
|
await tables.delete(table)
|
||||||
store.actions.screens.delete(templateScreens)
|
store.actions.screens.delete(templateScreens)
|
||||||
await backendUiStore.actions.tables.fetch()
|
await tables.fetch()
|
||||||
notifier.success("Table deleted")
|
notifier.success("Table deleted")
|
||||||
if (wasSelectedTable._id === table._id) {
|
if (wasSelectedTable._id === table._id) {
|
||||||
$goto("./table")
|
$goto("./table")
|
||||||
|
@ -49,21 +55,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
await backendUiStore.actions.tables.save(table)
|
await tables.save(table)
|
||||||
notifier.success("Table renamed successfully")
|
notifier.success("Table renamed successfully")
|
||||||
hideEditor()
|
hideEditor()
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkValid(evt) {
|
function checkValid(evt) {
|
||||||
const tableName = evt.target.value
|
const tableName = evt.target.value
|
||||||
if (
|
error = originalName !== tableName
|
||||||
originalName !== tableName &&
|
? `Table with name ${tableName} already exists. Please choose another name.`
|
||||||
$backendUiStore.models?.some(model => model.name === tableName)
|
: ""
|
||||||
) {
|
|
||||||
error = `Table with name ${tableName} already exists. Please choose another name.`
|
|
||||||
return
|
|
||||||
}
|
|
||||||
error = ""
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { views } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
|
@ -29,7 +34,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
await backendUiStore.actions.views.save({
|
await views.save({
|
||||||
originalName,
|
originalName,
|
||||||
...view,
|
...view,
|
||||||
})
|
})
|
||||||
|
@ -40,7 +45,7 @@
|
||||||
async function deleteView() {
|
async function deleteView() {
|
||||||
const name = view.name
|
const name = view.name
|
||||||
const id = view.tableId
|
const id = view.tableId
|
||||||
await backendUiStore.actions.views.delete(name)
|
await views.delete(name)
|
||||||
notifier.success("View deleted")
|
notifier.success("View deleted")
|
||||||
$goto(`./table/${id}`)
|
$goto(`./table/${id}`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { Select, Label, Multiselect } from "@budibase/bbui"
|
import { Select, Label, Multiselect } from "@budibase/bbui"
|
||||||
import { capitalise } from "../../helpers"
|
import { capitalise } from "../../helpers"
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
$: linkedRows = linkedIds
|
$: linkedRows = linkedIds
|
||||||
$: label = capitalise(schema.name)
|
$: label = capitalise(schema.name)
|
||||||
$: linkedTableId = schema.tableId
|
$: linkedTableId = schema.tableId
|
||||||
$: linkedTable = $backendUiStore.tables.find(
|
$: linkedTable = $tables.list.find(
|
||||||
table => table._id === linkedTableId
|
table => table._id === linkedTableId
|
||||||
)
|
)
|
||||||
$: fetchRows(linkedTableId)
|
$: fetchRows(linkedTableId)
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
import {
|
import {
|
||||||
store,
|
store,
|
||||||
allScreens,
|
allScreens,
|
||||||
backendUiStore,
|
|
||||||
selectedAccessRole,
|
selectedAccessRole,
|
||||||
screenSearchString,
|
screenSearchString,
|
||||||
} from "builderStore"
|
} from "builderStore"
|
||||||
|
import { roles } from 'stores/backend/'
|
||||||
import { FrontendTypes } from "constants"
|
import { FrontendTypes } from "constants"
|
||||||
import ComponentNavigationTree from "components/design/NavigationPanel/ComponentNavigationTree/index.svelte"
|
import ComponentNavigationTree from "components/design/NavigationPanel/ComponentNavigationTree/index.svelte"
|
||||||
import Layout from "components/design/NavigationPanel/Layout.svelte"
|
import Layout from "components/design/NavigationPanel/Layout.svelte"
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
on:change={updateAccessRole}
|
on:change={updateAccessRole}
|
||||||
value={$selectedAccessRole}
|
value={$selectedAccessRole}
|
||||||
label="Filter by Access">
|
label="Filter by Access">
|
||||||
{#each $backendUiStore.roles as role}
|
{#each $roles as role}
|
||||||
<option value={role._id}>{role.name}</option>
|
<option value={role._id}>{role.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { store, backendUiStore, allScreens } from "builderStore"
|
import { store, allScreens } from "builderStore"
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
import { roles } from 'stores/backend/'
|
||||||
import { Input, Select, ModalContent, Toggle } from "@budibase/bbui"
|
import { Input, Select, ModalContent, Toggle } from "@budibase/bbui"
|
||||||
import getTemplates from "builderStore/store/screenTemplates"
|
import getTemplates from "builderStore/store/screenTemplates"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
@ -14,7 +16,7 @@
|
||||||
let createLink = true
|
let createLink = true
|
||||||
let roleId = "BASIC"
|
let roleId = "BASIC"
|
||||||
|
|
||||||
$: templates = getTemplates($store, $backendUiStore.tables)
|
$: templates = getTemplates($store, $tables.list)
|
||||||
$: route = !route && $allScreens.length === 0 ? "*" : route
|
$: route = !route && $allScreens.length === 0 ? "*" : route
|
||||||
$: {
|
$: {
|
||||||
if (templates && templateIndex === undefined) {
|
if (templates && templateIndex === undefined) {
|
||||||
|
@ -105,7 +107,7 @@
|
||||||
bind:value={route}
|
bind:value={route}
|
||||||
on:change={routeChanged} />
|
on:change={routeChanged} />
|
||||||
<Select label="Access" bind:value={roleId} secondary>
|
<Select label="Access" bind:value={roleId} secondary>
|
||||||
{#each $backendUiStore.roles as role}
|
{#each $roles as role}
|
||||||
<option value={role._id}>{role.name}</option>
|
<option value={role._id}>{role.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
Drawer,
|
Drawer,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
import { store, currentAsset } from "builderStore"
|
||||||
|
import { tables as tablesStore, queries as queriesStore } from 'stores/backend/'
|
||||||
|
import { datasources, integrations } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||||
|
@ -22,12 +24,12 @@
|
||||||
export let otherSources
|
export let otherSources
|
||||||
export let showAllQueries
|
export let showAllQueries
|
||||||
|
|
||||||
$: tables = $backendUiStore.tables.map(m => ({
|
$: tables = $tablesStore.list.map(m => ({
|
||||||
label: m.name,
|
label: m.name,
|
||||||
tableId: m._id,
|
tableId: m._id,
|
||||||
type: "table",
|
type: "table",
|
||||||
}))
|
}))
|
||||||
$: views = $backendUiStore.tables.reduce((acc, cur) => {
|
$: views = $tablesStore.list.reduce((acc, cur) => {
|
||||||
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
||||||
label: key,
|
label: key,
|
||||||
name: key,
|
name: key,
|
||||||
|
@ -36,7 +38,7 @@
|
||||||
}))
|
}))
|
||||||
return [...acc, ...viewsArr]
|
return [...acc, ...viewsArr]
|
||||||
}, [])
|
}, [])
|
||||||
$: queries = $backendUiStore.queries
|
$: queries = $queriesStore.list
|
||||||
.filter(
|
.filter(
|
||||||
query => showAllQueries || query.queryVerb === "read" || query.readable
|
query => showAllQueries || query.queryVerb === "read" || query.readable
|
||||||
)
|
)
|
||||||
|
@ -81,10 +83,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchQueryDefinition(query) {
|
function fetchQueryDefinition(query) {
|
||||||
const source = $backendUiStore.datasources.find(
|
const source = $datasources.list.find(
|
||||||
ds => ds._id === query.datasourceId
|
ds => ds._id === query.datasourceId
|
||||||
).source
|
).source
|
||||||
return $backendUiStore.integrations[source].query[query.queryVerb]
|
return $integrations[source].query[query.queryVerb]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -123,7 +125,7 @@
|
||||||
height={200}
|
height={200}
|
||||||
query={value}
|
query={value}
|
||||||
schema={fetchQueryDefinition(value)}
|
schema={fetchQueryDefinition(value)}
|
||||||
datasource={$backendUiStore.datasources.find(ds => ds._id === value.datasourceId)}
|
datasource={$datasources.list.find(ds => ds._id === value.datasourceId)}
|
||||||
editable={false} />
|
editable={false} />
|
||||||
<Spacer large />
|
<Spacer large />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select, Label, Spacer } from "@budibase/bbui"
|
import { Select, Label, Spacer } from "@budibase/bbui"
|
||||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
import { store, currentAsset } from "builderStore"
|
||||||
|
import { datasources, integrations, queries } from 'stores/backend/'
|
||||||
import { getBindableProperties } from "builderStore/dataBinding"
|
import { getBindableProperties } from "builderStore/dataBinding"
|
||||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||||
|
|
||||||
export let parameters
|
export let parameters
|
||||||
|
|
||||||
$: query = $backendUiStore.queries.find(q => q._id === parameters.queryId)
|
$: query = $queries.list.find(q => q._id === parameters.queryId)
|
||||||
$: datasource = $backendUiStore.datasources.find(
|
$: datasource = $datasources.list.find(
|
||||||
ds => ds._id === parameters.datasourceId
|
ds => ds._id === parameters.datasourceId
|
||||||
)
|
)
|
||||||
$: bindableProperties = getBindableProperties(
|
$: bindableProperties = getBindableProperties(
|
||||||
|
@ -17,19 +18,38 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
function fetchQueryDefinition(query) {
|
function fetchQueryDefinition(query) {
|
||||||
const source = $backendUiStore.datasources.find(
|
const source = $datasources.list.find(
|
||||||
ds => ds._id === query.datasourceId
|
ds => ds._id === query.datasourceId
|
||||||
).source
|
).source
|
||||||
return $backendUiStore.integrations[source].query[query.queryVerb]
|
return $integrations[source].query[query.queryVerb]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<Label small>Datasource</Label>
|
<Label small>Datasource</Label>
|
||||||
<Select thin secondary bind:value={parameters.datasourceId}>
|
<Select thin secondary bind:value={parameters.datasourceId}>
|
||||||
<option value="" />
|
<option value="" />
|
||||||
{#each $backendUiStore.datasources as datasource}
|
{#each $backendUiStore.datasources as datasource}
|
||||||
<option value={datasource._id}>{datasource.name}</option>
|
<option value={datasource._id}>{datasource.name}</option>
|
||||||
|
=======
|
||||||
|
<Label small>Datasource</Label>
|
||||||
|
<Select thin secondary bind:value={parameters.datasourceId}>
|
||||||
|
<option value="" />
|
||||||
|
{#each $datasources.list as datasource}
|
||||||
|
<option value={datasource._id}>{datasource.name}</option>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<Spacer medium />
|
||||||
|
|
||||||
|
{#if parameters.datasourceId}
|
||||||
|
<Label small>Query</Label>
|
||||||
|
<Select thin secondary bind:value={parameters.queryId}>
|
||||||
|
<option value="" />
|
||||||
|
{#each $queries.list.filter(query => query.datasourceId === datasource._id) as query}
|
||||||
|
<option value={query._id}>{query.name}</option>
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
import { roles } from 'stores/backend/'
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Select bind:value extraThin secondary on:change>
|
<Select bind:value extraThin secondary on:change>
|
||||||
<option value="">Choose an option</option>
|
<option value="">Choose an option</option>
|
||||||
{#each $backendUiStore.roles as role}
|
{#each $roles as role}
|
||||||
<option value={role._id}>{role.name}</option>
|
<option value={role._id}>{role.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables } from 'stores/backend/'
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
<div>
|
<div>
|
||||||
<Select extraThin secondary wide on:change {value}>
|
<Select extraThin secondary wide on:change {value}>
|
||||||
<option value="">Choose a table</option>
|
<option value="">Choose a table</option>
|
||||||
{#each $backendUiStore.tables as table}
|
{#each $tables.list as table}
|
||||||
<option value={table._id}>{table.name}</option>
|
<option value={table._id}>{table.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||||
import ExternalDataSourceTable from "components/backend/DataTable/ExternalDataSourceTable.svelte"
|
import ExternalDataSourceTable from "components/backend/DataTable/ExternalDataSourceTable.svelte"
|
||||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||||
import { backendUiStore } from "builderStore"
|
import { datasources, integrations, queries } from 'stores/backend/'
|
||||||
|
|
||||||
const PREVIEW_HEADINGS = [
|
const PREVIEW_HEADINGS = [
|
||||||
{
|
{
|
||||||
|
@ -35,13 +35,11 @@
|
||||||
export let query
|
export let query
|
||||||
export let fields = []
|
export let fields = []
|
||||||
|
|
||||||
let config
|
|
||||||
let tab = "JSON"
|
let tab = "JSON"
|
||||||
let parameters
|
let parameters
|
||||||
let data = []
|
let data = []
|
||||||
let popover
|
|
||||||
|
|
||||||
$: datasource = $backendUiStore.datasources.find(
|
$: datasource = $datasources.list.find(
|
||||||
ds => ds._id === query.datasourceId
|
ds => ds._id === query.datasourceId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -58,7 +56,7 @@
|
||||||
|
|
||||||
$: datasourceType = datasource?.source
|
$: datasourceType = datasource?.source
|
||||||
|
|
||||||
$: integrationInfo = $backendUiStore.integrations[datasourceType]
|
$: integrationInfo = $integrations[datasourceType]
|
||||||
$: queryConfig = integrationInfo?.query
|
$: queryConfig = integrationInfo?.query
|
||||||
|
|
||||||
$: shouldShowQueryConfig = queryConfig && query.queryVerb
|
$: shouldShowQueryConfig = queryConfig && query.queryVerb
|
||||||
|
@ -115,7 +113,7 @@
|
||||||
|
|
||||||
async function saveQuery() {
|
async function saveQuery() {
|
||||||
try {
|
try {
|
||||||
const { _id } = await backendUiStore.actions.queries.save(
|
const { _id } = await queries.save(
|
||||||
query.datasourceId,
|
query.datasourceId,
|
||||||
query
|
query
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { Input, Label, TextButton } from "@budibase/bbui"
|
import { Input, Label, TextButton } from "@budibase/bbui"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import { backendUiStore } from "builderStore"
|
import { database } from 'stores/backend/'
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
|
||||||
let keys = { budibase: "" }
|
let keys = { budibase: "" }
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
</TextButton>
|
</TextButton>
|
||||||
<div>
|
<div>
|
||||||
<Label extraSmall grey>Instance ID (Webhooks)</Label>
|
<Label extraSmall grey>Instance ID (Webhooks)</Label>
|
||||||
<span>{$backendUiStore.selectedDatabase._id}</span>
|
<span>{$database._id}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,13 @@
|
||||||
import {
|
import {
|
||||||
store,
|
store,
|
||||||
automationStore,
|
automationStore,
|
||||||
backendUiStore,
|
|
||||||
hostingStore,
|
hostingStore,
|
||||||
} from "builderStore"
|
} from "builderStore"
|
||||||
import { string, object } from "yup"
|
import { string, object } from "yup"
|
||||||
import api, { get } from "builderStore/api"
|
import api, { get } from "builderStore/api"
|
||||||
import Form from "@svelteschool/svelte-forms"
|
import Form from "@svelteschool/svelte-forms"
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
import Spinner from "components/common/Spinner.svelte"
|
||||||
import { API, Info, User } from "./Steps"
|
import { Info, User } from "./Steps"
|
||||||
import Indicator from "./Indicator.svelte"
|
import Indicator from "./Indicator.svelte"
|
||||||
import { Button } from "@budibase/bbui"
|
import { Button } from "@budibase/bbui"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
|
@ -26,8 +25,6 @@
|
||||||
|
|
||||||
export let template
|
export let template
|
||||||
|
|
||||||
let lastApiKey
|
|
||||||
let fetchApiKeyPromise
|
|
||||||
|
|
||||||
const infoValidation = {
|
const infoValidation = {
|
||||||
applicationName: string().required("Your application must have a name."),
|
applicationName: string().required("Your application must have a name."),
|
||||||
|
@ -153,7 +150,7 @@
|
||||||
)
|
)
|
||||||
const pkg = await applicationPkg.json()
|
const pkg = await applicationPkg.json()
|
||||||
if (applicationPkg.ok) {
|
if (applicationPkg.ok) {
|
||||||
backendUiStore.actions.reset()
|
// backendUiStore.actions.reset()
|
||||||
await store.actions.initialise(pkg)
|
await store.actions.initialise(pkg)
|
||||||
await automationStore.actions.fetch()
|
await automationStore.actions.fetch()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { store, automationStore, backendUiStore } from "builderStore"
|
import { store, automationStore } from "builderStore"
|
||||||
|
import { roles } from 'stores/backend/'
|
||||||
import { Button } from "@budibase/bbui"
|
import { Button } from "@budibase/bbui"
|
||||||
import SettingsLink from "components/settings/Link.svelte"
|
import SettingsLink from "components/settings/Link.svelte"
|
||||||
import ThemeEditorDropdown from "components/settings/ThemeEditorDropdown.svelte"
|
import ThemeEditorDropdown from "components/settings/ThemeEditorDropdown.svelte"
|
||||||
|
@ -18,10 +19,10 @@
|
||||||
const pkg = await res.json()
|
const pkg = await res.json()
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
backendUiStore.actions.reset()
|
// backendUiStore.actions.reset()
|
||||||
await store.actions.initialise(pkg)
|
await store.actions.initialise(pkg)
|
||||||
await automationStore.actions.fetch()
|
await automationStore.actions.fetch()
|
||||||
await backendUiStore.actions.roles.fetch()
|
await roles.fetch()
|
||||||
return pkg
|
return pkg
|
||||||
} else {
|
} else {
|
||||||
throw new Error(pkg)
|
throw new Error(pkg)
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/datasource/[selectedDatasource]/[query]/_layout.svelte
|
||||||
import { params } from "@roxi/routify"
|
import { params } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { params } from "@sveltech/routify"
|
||||||
|
import { queries } from "stores/backend/"
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/[query]/_layout.svelte
|
||||||
|
|
||||||
if ($params.query) {
|
if ($params.query) {
|
||||||
const query = $backendUiStore.queries.find(m => m._id === $params.query)
|
const query = $queries.list.find(
|
||||||
|
m => m._id === $params.query
|
||||||
|
)
|
||||||
if (query) {
|
if (query) {
|
||||||
backendUiStore.actions.queries.select(query)
|
queries.select(query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/datasource/[selectedDatasource]/[query]/index.svelte
|
||||||
import { params } from "@roxi/routify"
|
import { params } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { params } from "@sveltech/routify"
|
||||||
|
import { database, queries } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/[query]/index.svelte
|
||||||
import QueryInterface from "components/integration/QueryViewer.svelte"
|
import QueryInterface from "components/integration/QueryViewer.svelte"
|
||||||
|
|
||||||
async function fetchQueryConfig() {
|
async function fetchQueryConfig() {
|
||||||
|
@ -14,8 +19,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: selectedQuery = $backendUiStore.queries.find(
|
$: selectedQuery = $queries.list.find(
|
||||||
query => query._id === $backendUiStore.selectedQueryId
|
query => query._id === $queries.selected
|
||||||
) || {
|
) || {
|
||||||
datasourceId: $params.selectedDatasource,
|
datasourceId: $params.selectedDatasource,
|
||||||
parameters: [],
|
parameters: [],
|
||||||
|
@ -26,7 +31,7 @@
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
{#if $backendUiStore.selectedDatabase._id && selectedQuery}
|
{#if $database._id && selectedQuery}
|
||||||
<QueryInterface query={selectedQuery} />
|
<QueryInterface query={selectedQuery} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/datasource/[selectedDatasource]/_layout.svelte
|
||||||
import { params } from "@roxi/routify"
|
import { params } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { params } from "@sveltech/routify"
|
||||||
|
import { datasources } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/_layout.svelte
|
||||||
|
|
||||||
if ($params.selectedDatasource) {
|
if ($params.selectedDatasource) {
|
||||||
const datasource = $backendUiStore.datasources.find(
|
const datasource = $datasources.list.find(
|
||||||
m => m._id === $params.selectedDatasource
|
m => m._id === $params.selectedDatasource
|
||||||
)
|
)
|
||||||
if (datasource) {
|
if (datasource) {
|
||||||
backendUiStore.actions.datasources.select(datasource._id)
|
datasources.select(datasource._id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
<script>
|
<script>
|
||||||
import { goto, beforeUrlChange } from "@roxi/routify"
|
import { goto, beforeUrlChange } from "@roxi/routify"
|
||||||
import { Button, Heading, Body, Spacer } from "@budibase/bbui"
|
import { Button, Heading, Body, Spacer } from "@budibase/bbui"
|
||||||
import { backendUiStore } from "builderStore"
|
import { datasources, integrations, queries } from 'stores/backend/'
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
|
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
|
||||||
import ICONS from "components/backend/DatasourceNavigator/icons"
|
import ICONS from "components/backend/DatasourceNavigator/icons"
|
||||||
|
|
||||||
let unsaved = false
|
let unsaved = false
|
||||||
|
|
||||||
$: datasource = $backendUiStore.datasources.find(
|
$: datasource = $datasources.list.find(
|
||||||
ds => ds._id === $backendUiStore.selectedDatasourceId
|
ds => ds._id === $datasources.selected
|
||||||
)
|
)
|
||||||
$: integration = datasource && $backendUiStore.integrations[datasource.source]
|
$: integration = datasource && $integrations[datasource.source]
|
||||||
|
|
||||||
async function saveDatasource() {
|
async function saveDatasource() {
|
||||||
// Create datasource
|
// Create datasource
|
||||||
await backendUiStore.actions.datasources.save(datasource)
|
await datasources.save(datasource)
|
||||||
notifier.success(`Datasource ${name} saved successfully.`)
|
notifier.success(`Datasource ${name} saved successfully.`)
|
||||||
unsaved = false
|
unsaved = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClickQuery(query) {
|
function onClickQuery(query) {
|
||||||
if ($backendUiStore.selectedQueryId === query._id) {
|
if ($queries.selected === query._id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
backendUiStore.actions.queries.select(query)
|
queries.select(query)
|
||||||
$goto(`../${query._id}`)
|
$goto(`../${query._id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
</div>
|
</div>
|
||||||
<Spacer extraLarge />
|
<Spacer extraLarge />
|
||||||
<div class="query-list">
|
<div class="query-list">
|
||||||
{#each $backendUiStore.queries.filter(query => query.datasourceId === datasource._id) as query}
|
{#each $queries.list.filter(query => query.datasourceId === datasource._id) as query}
|
||||||
<div class="query-list-item" on:click={() => onClickQuery(query)}>
|
<div class="query-list-item" on:click={() => onClickQuery(query)}>
|
||||||
<p class="query-name">{query.name}</p>
|
<p class="query-name">{query.name}</p>
|
||||||
<p>{query.queryVerb}</p>
|
<p>{query.queryVerb}</p>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<script>
|
||||||
|
import { datasources } from 'stores/backend/'
|
||||||
|
import { goto, leftover } from "@sveltech/routify"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// navigate to first datasource in list, if not already selected
|
||||||
|
if (
|
||||||
|
!$leftover &&
|
||||||
|
$datasources.list.length > 0 &&
|
||||||
|
!$datasources.selected
|
||||||
|
) {
|
||||||
|
$goto(`./${$datasources.list[0]._id}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<slot />
|
|
@ -1,4 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/datasource/index.svelte
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
@ -21,3 +22,26 @@
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
=======
|
||||||
|
import { datasources, tables } from 'stores/backend/'
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// navigate to first table in list, if not already selected
|
||||||
|
$datasources.list.length > 0 && $goto(`../${$datasources.list[0]._id}`)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $tables.list.length === 0}
|
||||||
|
<i>Connect your first datasource to start building.</i>
|
||||||
|
{:else}<i>Select a datasource to edit</i>{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
i {
|
||||||
|
font-size: var(--font-size-m);
|
||||||
|
color: var(--grey-5);
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/datasource/index.svelte
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/table/[selectedTable]/_layout.svelte
|
||||||
import { params } from "@roxi/routify"
|
import { params } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { params } from "@sveltech/routify"
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/table/[selectedTable]/_layout.svelte
|
||||||
|
|
||||||
if ($params.selectedTable) {
|
if ($params.selectedTable) {
|
||||||
const table = $backendUiStore.tables.find(
|
const table = $tables.list.find(
|
||||||
m => m._id === $params.selectedTable
|
m => m._id === $params.selectedTable
|
||||||
)
|
)
|
||||||
if (table) {
|
if (table) {
|
||||||
backendUiStore.actions.tables.select(table)
|
tables.select(table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import TableDataTable from "components/backend/DataTable/DataTable.svelte"
|
import TableDataTable from "components/backend/DataTable/DataTable.svelte"
|
||||||
import { backendUiStore } from "builderStore"
|
import { tables, database } from 'stores/backend/'
|
||||||
|
|
||||||
$: selectedTable = $backendUiStore.selectedTable
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $backendUiStore.selectedDatabase._id && selectedTable.name}
|
{#if $database?._id && $tables?.selected?.name}
|
||||||
<TableDataTable />
|
<TableDataTable />
|
||||||
{:else}<i>Create your first table to start building</i>{/if}
|
{:else}<i>Create your first table to start building</i>{/if}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<script>
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
import { goto, leftover } from "@sveltech/routify"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// navigate to first table in list, if not already selected
|
||||||
|
// and this is the final url (i.e. no selectedTable)
|
||||||
|
if (
|
||||||
|
!$leftover &&
|
||||||
|
$tables.list.length > 0 &&
|
||||||
|
(!$tables.selected || !$tables.selected._id)
|
||||||
|
) {
|
||||||
|
$goto(`./${$tables.list[0]._id}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<slot />
|
|
@ -1,4 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/table/index.svelte
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
@ -6,10 +7,18 @@
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
$backendUiStore.tables.length > 0 &&
|
$backendUiStore.tables.length > 0 &&
|
||||||
$goto(`./${$backendUiStore.tables[0]._id}`)
|
$goto(`./${$backendUiStore.tables[0]._id}`)
|
||||||
|
=======
|
||||||
|
import { tables } from 'stores/backend/'
|
||||||
|
import { goto } from "@sveltech/routify"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
$tables.list.length > 0 && $goto(`../${$tables.list[0]._id}`)
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/table/index.svelte
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $backendUiStore.tables.length === 0}
|
{#if $tables.list.length === 0}
|
||||||
<i>Create your first table to start building</i>
|
<i>Create your first table to start building</i>
|
||||||
{:else}<i>Select a table to edit</i>{/if}
|
{:else}<i>Select a table to edit</i>{/if}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/view/[selectedView]/_layout.svelte
|
||||||
import { params } from "@roxi/routify"
|
import { params } from "@roxi/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import { params } from "@sveltech/routify"
|
||||||
|
import { tables, views } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/view/[selectedView]/_layout.svelte
|
||||||
|
|
||||||
if ($params.selectedView) {
|
if ($params.selectedView) {
|
||||||
let view
|
let view
|
||||||
const viewName = decodeURI($params.selectedView)
|
const viewName = decodeURI($params.selectedView)
|
||||||
for (let table of $backendUiStore.tables) {
|
for (let table of $tables.list) {
|
||||||
if (table.views && table.views[viewName]) {
|
if (table.views && table.views[viewName]) {
|
||||||
view = table.views[viewName]
|
view = table.views[viewName]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (view) {
|
if (view) {
|
||||||
backendUiStore.actions.views.select({
|
views.select({
|
||||||
name: viewName,
|
name: viewName,
|
||||||
...view,
|
...view,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
|
<<<<<<< HEAD:packages/builder/src/pages/builder/[application]/data/view/[selectedView]/index.svelte
|
||||||
import ViewDataTable from "components/backend/DataTable/ViewDataTable.svelte"
|
import ViewDataTable from "components/backend/DataTable/ViewDataTable.svelte"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
=======
|
||||||
|
import ViewDataTable from "components/backend/DataTable/ViewDataTable"
|
||||||
|
import { views, database } from 'stores/backend/'
|
||||||
|
>>>>>>> d803aa0bd7a74220e432f4a1b338abdd7fbe9b7d:packages/builder/src/pages/[application]/data/view/[selectedView]/index.svelte
|
||||||
|
|
||||||
$: selectedView = $backendUiStore.selectedView
|
$: selectedView = $views.selected
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $backendUiStore.selectedDatabase._id && selectedView}
|
{#if $database._id && selectedView}
|
||||||
<ViewDataTable view={selectedView} />
|
<ViewDataTable view={selectedView} />
|
||||||
{:else}<i>Create your first table to start building</i>{/if}
|
{:else}<i>Create your first table to start building</i>{/if}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
|
export const database = writable({})
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import { queries } from "./"
|
||||||
|
import api from "../../builderStore/api"
|
||||||
|
|
||||||
|
export const INITIAL_DATASOURCE_VALUES = {
|
||||||
|
list: [],
|
||||||
|
selected: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDatasourcesStore() {
|
||||||
|
const { subscribe, update, set } = writable(INITIAL_DATASOURCE_VALUES)
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
update,
|
||||||
|
init: async () => {
|
||||||
|
const response = await api.get(`/api/datasources`)
|
||||||
|
const json = await response.json()
|
||||||
|
set({ list: json, selected: null })
|
||||||
|
},
|
||||||
|
fetch: async () => {
|
||||||
|
const response = await api.get(`/api/datasources`)
|
||||||
|
const json = await response.json()
|
||||||
|
update(state => ({ ...state, list: json }))
|
||||||
|
return json
|
||||||
|
},
|
||||||
|
select: async datasourceId => {
|
||||||
|
update(state => ({ ...state, selected: datasourceId }))
|
||||||
|
queries.update(state => ({ ...state, selected: null }))
|
||||||
|
},
|
||||||
|
save: async datasource => {
|
||||||
|
const response = await api.post("/api/datasources", datasource)
|
||||||
|
const json = await response.json()
|
||||||
|
|
||||||
|
update(state => {
|
||||||
|
const currentIdx = state.list.findIndex(ds => ds._id === json._id)
|
||||||
|
|
||||||
|
const sources = state.list
|
||||||
|
|
||||||
|
if (currentIdx >= 0) {
|
||||||
|
sources.splice(currentIdx, 1, json)
|
||||||
|
} else {
|
||||||
|
sources.push(json)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { list: sources, selected: json._id }
|
||||||
|
})
|
||||||
|
return json
|
||||||
|
},
|
||||||
|
delete: async datasource => {
|
||||||
|
const response = await api.delete(
|
||||||
|
`/api/datasources/${datasource._id}/${datasource._rev}`
|
||||||
|
)
|
||||||
|
update(state => {
|
||||||
|
const sources = state.list.filter(
|
||||||
|
existing => existing._id !== datasource._id
|
||||||
|
)
|
||||||
|
return { list: sources, selected: null }
|
||||||
|
})
|
||||||
|
|
||||||
|
return response
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const datasources = createDatasourcesStore()
|
|
@ -0,0 +1,9 @@
|
||||||
|
export { database } from "./database"
|
||||||
|
export { tables } from "./tables"
|
||||||
|
export { views } from "./views"
|
||||||
|
export { rows } from "./rows"
|
||||||
|
export { permissions } from "./permissions"
|
||||||
|
export { roles } from "./roles"
|
||||||
|
export { datasources } from "./datasources"
|
||||||
|
export { integrations } from "./integrations"
|
||||||
|
export { queries } from "./queries"
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
|
export const integrations = writable({})
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
|
||||||
|
export function createPermissionStore() {
|
||||||
|
const { subscribe } = writable([])
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
forResource: async resourceId => {
|
||||||
|
const response = await api.get(`/api/permission/${resourceId}`)
|
||||||
|
const json = await response.json()
|
||||||
|
return json
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const permissions = createPermissionStore()
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
import { datasources, integrations } from "./"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
|
||||||
|
export function createQueriesStore() {
|
||||||
|
const { subscribe, set, update } = writable({ list: [], selected: null })
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
set,
|
||||||
|
update,
|
||||||
|
init: async () => {
|
||||||
|
const response = await api.get(`/api/queries`)
|
||||||
|
const json = await response.json()
|
||||||
|
set({ list: json, selected: null })
|
||||||
|
},
|
||||||
|
fetch: async () => {
|
||||||
|
const response = await api.get(`/api/queries`)
|
||||||
|
const json = await response.json()
|
||||||
|
update(state => ({ ...state, list: json }))
|
||||||
|
return json
|
||||||
|
},
|
||||||
|
save: async (datasourceId, query) => {
|
||||||
|
const _integrations = get(integrations)
|
||||||
|
const dataSource = get(datasources).list.filter(
|
||||||
|
ds => ds._id === datasourceId
|
||||||
|
)
|
||||||
|
// check if readable attribute is found
|
||||||
|
if (dataSource.length !== 0) {
|
||||||
|
const integration = _integrations[dataSource[0].source]
|
||||||
|
const readable = integration.query[query.queryVerb].readable
|
||||||
|
if (readable) {
|
||||||
|
query.readable = readable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
query.datasourceId = datasourceId
|
||||||
|
const response = await api.post(`/api/queries`, query)
|
||||||
|
if (response.status !== 200) {
|
||||||
|
throw new Error("Failed saving query.")
|
||||||
|
}
|
||||||
|
const json = await response.json()
|
||||||
|
update(state => {
|
||||||
|
const currentIdx = state.list.findIndex(query => query._id === json._id)
|
||||||
|
|
||||||
|
const queries = state.list
|
||||||
|
|
||||||
|
if (currentIdx >= 0) {
|
||||||
|
queries.splice(currentIdx, 1, json)
|
||||||
|
} else {
|
||||||
|
queries.push(json)
|
||||||
|
}
|
||||||
|
return { list: queries, selected: json._id }
|
||||||
|
})
|
||||||
|
return json
|
||||||
|
},
|
||||||
|
select: query => {
|
||||||
|
update(state => ({ ...state, selected: query._id }))
|
||||||
|
datasources.update(state => ({ ...state, selected: query.datasourceId }))
|
||||||
|
},
|
||||||
|
delete: async query => {
|
||||||
|
const response = await api.delete(
|
||||||
|
`/api/queries/${query._id}/${query._rev}`
|
||||||
|
)
|
||||||
|
update(state => {
|
||||||
|
state.list = state.list.filter(existing => existing._id !== query._id)
|
||||||
|
if (state.selected === query._id) {
|
||||||
|
state.selected = null
|
||||||
|
}
|
||||||
|
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const queries = createQueriesStore()
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
|
||||||
|
export function createRolesStore() {
|
||||||
|
const { subscribe, update, set } = writable([])
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
fetch: async () => {
|
||||||
|
set(await getRoles())
|
||||||
|
},
|
||||||
|
delete: async role => {
|
||||||
|
const response = await api.delete(`/api/roles/${role._id}/${role._rev}`)
|
||||||
|
update(state => state.filter(existing => existing._id !== role._id))
|
||||||
|
return response
|
||||||
|
},
|
||||||
|
save: async role => {
|
||||||
|
const response = await api.post("/api/roles", role)
|
||||||
|
set(await getRoles())
|
||||||
|
return response
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRoles() {
|
||||||
|
const response = await api.get("/api/roles")
|
||||||
|
return await response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const roles = createRolesStore()
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
import { views } from "./"
|
||||||
|
|
||||||
|
export function createRowsStore() {
|
||||||
|
const { subscribe } = writable([])
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
save: () => views.select(get(views).selected),
|
||||||
|
delete: () => views.select(get(views).selected),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const rows = createRowsStore()
|
|
@ -0,0 +1,125 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
import { views } from "./"
|
||||||
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
|
||||||
|
export function createTablesStore() {
|
||||||
|
const store = writable({})
|
||||||
|
const { subscribe, update, set } = store
|
||||||
|
|
||||||
|
async function fetch() {
|
||||||
|
const tablesResponse = await api.get(`/api/tables`)
|
||||||
|
const tables = await tablesResponse.json()
|
||||||
|
update(state => ({ ...state, list: tables }))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function select(table) {
|
||||||
|
if (!table) {
|
||||||
|
update(state => ({
|
||||||
|
...state,
|
||||||
|
selected: {},
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
update(state => ({
|
||||||
|
...state,
|
||||||
|
selected: table,
|
||||||
|
draft: cloneDeep(table),
|
||||||
|
}))
|
||||||
|
views.select({ name: `all_${table._id}` })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save(table) {
|
||||||
|
const updatedTable = cloneDeep(table)
|
||||||
|
const oldTable = get(store).list.filter(t => t._id === table._id)[0]
|
||||||
|
|
||||||
|
const fieldNames = []
|
||||||
|
// update any renamed schema keys to reflect their names
|
||||||
|
for (let key of Object.keys(updatedTable.schema)) {
|
||||||
|
// if field name has been seen before remove it
|
||||||
|
if (fieldNames.indexOf(key.toLowerCase()) !== -1) {
|
||||||
|
delete updatedTable.schema[key]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const field = updatedTable.schema[key]
|
||||||
|
const oldField = oldTable?.schema[key]
|
||||||
|
// if the type has changed then revert back to the old field
|
||||||
|
if (oldField != null && oldField?.type !== field.type) {
|
||||||
|
updatedTable.schema[key] = oldField
|
||||||
|
}
|
||||||
|
// field has been renamed
|
||||||
|
if (field.name && field.name !== key) {
|
||||||
|
updatedTable.schema[field.name] = field
|
||||||
|
updatedTable._rename = { old: key, updated: field.name }
|
||||||
|
delete updatedTable.schema[key]
|
||||||
|
}
|
||||||
|
// finally record this field has been used
|
||||||
|
fieldNames.push(key.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api.post(`/api/tables`, updatedTable)
|
||||||
|
const savedTable = await response.json()
|
||||||
|
await fetch()
|
||||||
|
await select(savedTable)
|
||||||
|
return savedTable
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
fetch,
|
||||||
|
select,
|
||||||
|
save,
|
||||||
|
init: async () => {
|
||||||
|
const response = await api.get("/api/tables")
|
||||||
|
const json = await response.json()
|
||||||
|
set({
|
||||||
|
list: json,
|
||||||
|
selected: {},
|
||||||
|
draft: {},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
delete: async table => {
|
||||||
|
await api.delete(`/api/tables/${table._id}/${table._rev}`)
|
||||||
|
update(state => ({
|
||||||
|
...state,
|
||||||
|
list: state.list.filter(existing => existing._id !== table._id),
|
||||||
|
selected: {},
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
saveField: ({ originalName, field, primaryDisplay = false, indexes }) => {
|
||||||
|
update(state => {
|
||||||
|
// delete the original if renaming
|
||||||
|
// need to handle if the column had no name, empty string
|
||||||
|
if (originalName || originalName === "") {
|
||||||
|
delete state.draft.schema[originalName]
|
||||||
|
state.draft._rename = {
|
||||||
|
old: originalName,
|
||||||
|
updated: field.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally set display column
|
||||||
|
if (primaryDisplay) {
|
||||||
|
state.draft.primaryDisplay = field.name
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexes) {
|
||||||
|
state.draft.indexes = indexes
|
||||||
|
}
|
||||||
|
|
||||||
|
state.draft.schema[field.name] = cloneDeep(field)
|
||||||
|
save(state.draft)
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteField: field => {
|
||||||
|
update(state => {
|
||||||
|
delete state.draft.schema[field.name]
|
||||||
|
save(state.draft)
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tables = createTablesStore()
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
import api from 'builderStore/api'
|
||||||
|
|
||||||
|
jest.mock('builderStore/api');
|
||||||
|
|
||||||
|
import { SOME_DATASOURCE, SAVE_DATASOURCE} from './fixtures/datasources'
|
||||||
|
|
||||||
|
import { createDatasourcesStore } from "../datasources"
|
||||||
|
import { queries } from '../queries'
|
||||||
|
|
||||||
|
describe("Datasources Store", () => {
|
||||||
|
let store = createDatasourcesStore()
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => [SOME_DATASOURCE]})
|
||||||
|
await store.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Initialises correctly", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => [SOME_DATASOURCE]})
|
||||||
|
|
||||||
|
await store.init()
|
||||||
|
expect(get(store)).toEqual({ list: [SOME_DATASOURCE], selected: null})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fetches all the datasources and updates the store", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => [SOME_DATASOURCE]})
|
||||||
|
|
||||||
|
await store.fetch()
|
||||||
|
expect(get(store)).toEqual({ list: [SOME_DATASOURCE], selected: null})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("selects a datasource", async () => {
|
||||||
|
store.select(SOME_DATASOURCE._id)
|
||||||
|
|
||||||
|
expect(get(store).select).toEqual(SOME_DATASOURCE._id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("resets the queries store when new datasource is selected", async () => {
|
||||||
|
|
||||||
|
await store.select(SOME_DATASOURCE._id)
|
||||||
|
const queriesValue = get(queries)
|
||||||
|
expect(queriesValue.selected).toEqual(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("saves the datasource, updates the store and returns status message", async () => {
|
||||||
|
api.post.mockReturnValue({ json: () => SAVE_DATASOURCE})
|
||||||
|
|
||||||
|
await store.save({
|
||||||
|
name: 'CoolDB',
|
||||||
|
source: 'REST',
|
||||||
|
config: SOME_DATASOURCE[0].config
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(get(store).list).toEqual(expect.arrayContaining([SAVE_DATASOURCE]))
|
||||||
|
})
|
||||||
|
it("deletes a datasource, updates the store and returns status message", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => SOME_DATASOURCE})
|
||||||
|
|
||||||
|
await store.fetch()
|
||||||
|
|
||||||
|
api.delete.mockReturnValue({status: 200, message: 'Datasource deleted.'})
|
||||||
|
|
||||||
|
await store.delete(SOME_DATASOURCE[0])
|
||||||
|
expect(get(store)).toEqual({ list: [], selected: null})
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,25 @@
|
||||||
|
export const SOME_DATASOURCE = [
|
||||||
|
{
|
||||||
|
type: "datasource",
|
||||||
|
name: "erterter",
|
||||||
|
source: "REST",
|
||||||
|
config: {
|
||||||
|
url: "localhost",
|
||||||
|
defaultHeaders: {},
|
||||||
|
},
|
||||||
|
_id: "datasource_04b003a7b4a8428eadd3bb2f7eae0255",
|
||||||
|
_rev: "1-4e72002f1011e9392e655948469b7908",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const SAVE_DATASOURCE = {
|
||||||
|
type: "datasource",
|
||||||
|
name: "CoolDB",
|
||||||
|
source: "REST",
|
||||||
|
config: {
|
||||||
|
url: "localhost",
|
||||||
|
defaultHeaders: {},
|
||||||
|
},
|
||||||
|
_id: "datasource_04b003a7b4a8428eadd3bb2f7eae0255",
|
||||||
|
_rev: "1-4e72002f1011e9392e655948469b7908",
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
export const SOME_QUERY = {
|
||||||
|
datasourceId: "datasource_04b003a7b4a8428eadd3bb2f7eae0255",
|
||||||
|
parameters: [],
|
||||||
|
fields: {
|
||||||
|
headers: {},
|
||||||
|
queryString: "",
|
||||||
|
path: "Speakers",
|
||||||
|
},
|
||||||
|
queryVerb: "read",
|
||||||
|
schema: {},
|
||||||
|
name: "Speakers",
|
||||||
|
_id:
|
||||||
|
"query_datasource_04b003a7b4a8428eadd3bb2f7eae0255_bcb8ffc6fcbc484e8d63121fc0bf986f",
|
||||||
|
_rev: "2-941f8699eb0adf995f8bd59c99203b26",
|
||||||
|
readable: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SAVE_QUERY_RESPONSE = {
|
||||||
|
datasourceId: "datasource_04b003a7b4a8428eadd3bb2f7eae0255",
|
||||||
|
parameters: [],
|
||||||
|
fields: {
|
||||||
|
headers: {},
|
||||||
|
queryString: "",
|
||||||
|
path: "Speakers",
|
||||||
|
},
|
||||||
|
queryVerb: "read",
|
||||||
|
schema: {
|
||||||
|
id: {
|
||||||
|
name: "id",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
firstName: {
|
||||||
|
name: "firstName",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
name: "lastName",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
fullName: {
|
||||||
|
name: "fullName",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
bio: {
|
||||||
|
name: "bio",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
tagLine: {
|
||||||
|
name: "tagLine",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
profilePicture: {
|
||||||
|
name: "profilePicture",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
sessions: {
|
||||||
|
name: "sessions",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
isTopSpeaker: {
|
||||||
|
name: "isTopSpeaker",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
name: "links",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
questionAnswers: {
|
||||||
|
name: "questionAnswers",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
categories: {
|
||||||
|
name: "categories",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: "Speakers",
|
||||||
|
_id:
|
||||||
|
"query_datasource_04b003a7b4a8428eadd3bb2f7eae0255_bcb8ffc6fcbc484e8d63121fc0bf986f",
|
||||||
|
_rev: "3-5a64adef494b1e9c793dc91b51ce73c6",
|
||||||
|
readable: true,
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
export const ROLES = [
|
||||||
|
{
|
||||||
|
name: "Test",
|
||||||
|
permissionId: "admin",
|
||||||
|
inherits: "ADMIN",
|
||||||
|
_id: "role_04681b7e71914a0aa53e09a5bea3584f",
|
||||||
|
_rev: "1-179c71ea61d7fd987306b84b6d64b00e",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: "ADMIN",
|
||||||
|
name: "Admin",
|
||||||
|
permissionId: "admin",
|
||||||
|
inherits: "POWER",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: "POWER",
|
||||||
|
name: "Power",
|
||||||
|
permissionId: "power",
|
||||||
|
inherits: "BASIC",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: "BASIC",
|
||||||
|
name: "Basic",
|
||||||
|
permissionId: "write",
|
||||||
|
inherits: "PUBLIC",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: "PUBLIC",
|
||||||
|
name: "Public",
|
||||||
|
permissionId: "public",
|
||||||
|
},
|
||||||
|
]
|
|
@ -0,0 +1,717 @@
|
||||||
|
export const SOME_TABLES = [
|
||||||
|
{
|
||||||
|
type: "table",
|
||||||
|
views: {},
|
||||||
|
name: "Guest",
|
||||||
|
schema: {
|
||||||
|
"Auto ID": {
|
||||||
|
name: "Auto ID",
|
||||||
|
type: "number",
|
||||||
|
subtype: "autoID",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastID: 1,
|
||||||
|
},
|
||||||
|
"Created By": {
|
||||||
|
name: "Created By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "createdBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Created At": {
|
||||||
|
name: "Created At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "createdAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Updated By": {
|
||||||
|
name: "Updated By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "updatedBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Updated At": {
|
||||||
|
name: "Updated At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "updatedAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Name: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Guest",
|
||||||
|
name: "Name",
|
||||||
|
},
|
||||||
|
Episode: {
|
||||||
|
name: "Episode",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Guest",
|
||||||
|
relationshipType: "one-to-many",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
primaryDisplay: "Name",
|
||||||
|
indexes: [],
|
||||||
|
_id: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
_rev: "10-27f034bf50ec3e2f180d8f96db1f0f31",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "table",
|
||||||
|
views: {},
|
||||||
|
name: "Sponsors",
|
||||||
|
schema: {
|
||||||
|
"Auto ID": {
|
||||||
|
name: "Auto ID",
|
||||||
|
type: "number",
|
||||||
|
subtype: "autoID",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastID: 1,
|
||||||
|
},
|
||||||
|
"Created By": {
|
||||||
|
name: "Created By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "createdBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Sponsors-Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Created At": {
|
||||||
|
name: "Created At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "createdAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Updated By": {
|
||||||
|
name: "Updated By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "updatedBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Sponsors-Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Updated At": {
|
||||||
|
name: "Updated At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "updatedAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Name: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Sponsors",
|
||||||
|
name: "Name",
|
||||||
|
},
|
||||||
|
Spot: {
|
||||||
|
type: "longform",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Sponsors",
|
||||||
|
name: "Spot",
|
||||||
|
},
|
||||||
|
Episode: {
|
||||||
|
name: "Episode",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Sponsors",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
primaryDisplay: "Name",
|
||||||
|
indexes: [],
|
||||||
|
_id: "ta_7fd0fa15edd54e0f91a47f50b7577281",
|
||||||
|
_rev: "7-de89b81e21ae4b3f65a6b655144fe097",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "table",
|
||||||
|
views: {},
|
||||||
|
name: "Episode",
|
||||||
|
schema: {
|
||||||
|
"Auto ID": {
|
||||||
|
name: "Auto ID",
|
||||||
|
type: "number",
|
||||||
|
subtype: "autoID",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastID: 1,
|
||||||
|
},
|
||||||
|
"Created By": {
|
||||||
|
name: "Created By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "createdBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Episode-Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Created At": {
|
||||||
|
name: "Created At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "createdAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Updated By": {
|
||||||
|
name: "Updated By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "updatedBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Episode-Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Updated At": {
|
||||||
|
name: "Updated At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "updatedAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Summary: {
|
||||||
|
type: "longform",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Summary",
|
||||||
|
},
|
||||||
|
Author: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Author",
|
||||||
|
},
|
||||||
|
Published: {
|
||||||
|
type: "boolean",
|
||||||
|
constraints: {
|
||||||
|
type: "boolean",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Published",
|
||||||
|
},
|
||||||
|
Guest: {
|
||||||
|
type: "link",
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Guest",
|
||||||
|
relationshipType: "many-to-one",
|
||||||
|
tableId: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
},
|
||||||
|
Title: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Title",
|
||||||
|
},
|
||||||
|
"Show Notes": {
|
||||||
|
type: "longform",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Show Notes",
|
||||||
|
},
|
||||||
|
Sponsors: {
|
||||||
|
type: "link",
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Sponsors",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
tableId: "ta_7fd0fa15edd54e0f91a47f50b7577281",
|
||||||
|
},
|
||||||
|
Number: {
|
||||||
|
type: "number",
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Number",
|
||||||
|
},
|
||||||
|
Audio: {
|
||||||
|
type: "attachment",
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Episode",
|
||||||
|
name: "Audio",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
indexes: [],
|
||||||
|
primaryDisplay: "Author",
|
||||||
|
_id: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
_rev: "13-9d70dee825154a9df5c22e1d39bf269c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "table",
|
||||||
|
views: {},
|
||||||
|
name: "Users",
|
||||||
|
schema: {
|
||||||
|
email: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
email: true,
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
fieldName: "email",
|
||||||
|
name: "email",
|
||||||
|
},
|
||||||
|
roleId: {
|
||||||
|
fieldName: "roleId",
|
||||||
|
name: "roleId",
|
||||||
|
type: "options",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
presence: false,
|
||||||
|
inclusion: ["ADMIN", "POWER", "BASIC", "PUBLIC", "BUILDER"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
fieldName: "status",
|
||||||
|
name: "status",
|
||||||
|
type: "options",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
presence: false,
|
||||||
|
inclusion: ["active", "inactive"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Episode-Created By": {
|
||||||
|
name: "Episode-Created By",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
autocolumn: true,
|
||||||
|
},
|
||||||
|
"Episode-Updated By": {
|
||||||
|
name: "Episode-Updated By",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
autocolumn: true,
|
||||||
|
},
|
||||||
|
"Guest-Created By": {
|
||||||
|
name: "Guest-Created By",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
fieldName: "Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
autocolumn: true,
|
||||||
|
},
|
||||||
|
"Guest-Updated By": {
|
||||||
|
name: "Guest-Updated By",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
fieldName: "Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
autocolumn: true,
|
||||||
|
},
|
||||||
|
"Sponsors-Created By": {
|
||||||
|
name: "Sponsors-Created By",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_7fd0fa15edd54e0f91a47f50b7577281",
|
||||||
|
fieldName: "Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
autocolumn: true,
|
||||||
|
},
|
||||||
|
"Sponsors-Updated By": {
|
||||||
|
name: "Sponsors-Updated By",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_7fd0fa15edd54e0f91a47f50b7577281",
|
||||||
|
fieldName: "Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
autocolumn: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
primaryDisplay: "email",
|
||||||
|
_id: "ta_users",
|
||||||
|
_rev: "67-1833e6a0028c100633e31788fe958a62",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const SAVE_TABLES_RESPONSE = {
|
||||||
|
type: "table",
|
||||||
|
_id: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
views: {},
|
||||||
|
name: "Guest",
|
||||||
|
schema: {
|
||||||
|
"Auto ID": {
|
||||||
|
name: "Auto ID",
|
||||||
|
type: "number",
|
||||||
|
subtype: "autoID",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastID: 1,
|
||||||
|
},
|
||||||
|
"Created By": {
|
||||||
|
name: "Created By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "createdBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Created At": {
|
||||||
|
name: "Created At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "createdAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Updated By": {
|
||||||
|
name: "Updated By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "updatedBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Updated At": {
|
||||||
|
name: "Updated At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "updatedAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Episode: {
|
||||||
|
name: "Episode",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Guest",
|
||||||
|
relationshipType: "one-to-many",
|
||||||
|
},
|
||||||
|
Names: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Guest",
|
||||||
|
name: "Names",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
primaryDisplay: "Names",
|
||||||
|
indexes: [],
|
||||||
|
_rev: "11-7c153edbc6d7c43821cfd5ed526266cf",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const A_TABLE = {
|
||||||
|
type: "table",
|
||||||
|
views: {},
|
||||||
|
name: "Guest",
|
||||||
|
schema: {
|
||||||
|
"Auto ID": {
|
||||||
|
name: "Auto ID",
|
||||||
|
type: "number",
|
||||||
|
subtype: "autoID",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastID: 1,
|
||||||
|
},
|
||||||
|
"Created By": {
|
||||||
|
name: "Created By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "createdBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Created At": {
|
||||||
|
name: "Created At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "createdAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Updated By": {
|
||||||
|
name: "Updated By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "updatedBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Updated At": {
|
||||||
|
name: "Updated At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "updatedAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Episode: {
|
||||||
|
name: "Episode",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Guest",
|
||||||
|
relationshipType: "one-to-many",
|
||||||
|
},
|
||||||
|
Names: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Guest",
|
||||||
|
name: "Names",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
primaryDisplay: "Names",
|
||||||
|
indexes: [],
|
||||||
|
_id: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
_rev: "10-27f034bf50ec3e2f180d8f96db1f0f31",
|
||||||
|
_rename: {
|
||||||
|
old: "Name",
|
||||||
|
updated: "Names",
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
export const A_VIEW = {
|
||||||
|
name: "Published",
|
||||||
|
tableId: "ta_3c78cffe33664ca9bfb6b2b6cb3ee55a",
|
||||||
|
filters: [],
|
||||||
|
schema: {
|
||||||
|
"Auto ID": {
|
||||||
|
name: "Auto ID",
|
||||||
|
type: "number",
|
||||||
|
subtype: "autoID",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
numericality: {
|
||||||
|
greaterThanOrEqualTo: "",
|
||||||
|
lessThanOrEqualTo: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastID: 2,
|
||||||
|
},
|
||||||
|
"Created By": {
|
||||||
|
name: "Created By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "createdBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Created By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Created At": {
|
||||||
|
name: "Created At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "createdAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Updated By": {
|
||||||
|
name: "Updated By",
|
||||||
|
type: "link",
|
||||||
|
subtype: "updatedBy",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "array",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
tableId: "ta_users",
|
||||||
|
fieldName: "Guest-Updated By",
|
||||||
|
relationshipType: "many-to-many",
|
||||||
|
},
|
||||||
|
"Updated At": {
|
||||||
|
name: "Updated At",
|
||||||
|
type: "datetime",
|
||||||
|
subtype: "updatedAt",
|
||||||
|
icon: "ri-magic-line",
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {},
|
||||||
|
presence: false,
|
||||||
|
datetime: {
|
||||||
|
latest: "",
|
||||||
|
earliest: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Episode: {
|
||||||
|
name: "Episode",
|
||||||
|
type: "link",
|
||||||
|
tableId: "ta_d4bf541ce0d84b16a1a8e0a060e5f7f7",
|
||||||
|
fieldName: "Guest",
|
||||||
|
relationshipType: "one-to-many",
|
||||||
|
},
|
||||||
|
Names: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
length: {
|
||||||
|
maximum: "",
|
||||||
|
},
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
fieldName: "Guest",
|
||||||
|
name: "Names",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import api from 'builderStore/api'
|
||||||
|
|
||||||
|
jest.mock('builderStore/api');
|
||||||
|
|
||||||
|
const PERMISSIONS_FOR_RESOURCE = {
|
||||||
|
"write": "BASIC",
|
||||||
|
"read": "BASIC"
|
||||||
|
}
|
||||||
|
|
||||||
|
import { createPermissionStore } from "../permissions"
|
||||||
|
|
||||||
|
describe("Permissions Store", () => {
|
||||||
|
const store = createPermissionStore()
|
||||||
|
|
||||||
|
it("fetches permissions for specific resource", async () => {
|
||||||
|
api.get.mockReturnValueOnce({ json: () => PERMISSIONS_FOR_RESOURCE})
|
||||||
|
|
||||||
|
const resourceId = "ta_013657543b4043b89dbb17e9d3a4723a"
|
||||||
|
|
||||||
|
const permissions = await store.forResource(resourceId)
|
||||||
|
|
||||||
|
expect(api.get).toBeCalledWith(`/api/permission/${resourceId}`)
|
||||||
|
expect(permissions).toEqual(PERMISSIONS_FOR_RESOURCE)
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
import api from 'builderStore/api'
|
||||||
|
|
||||||
|
jest.mock('builderStore/api');
|
||||||
|
|
||||||
|
import { SOME_QUERY, SAVE_QUERY_RESPONSE } from './fixtures/queries'
|
||||||
|
|
||||||
|
import { createQueriesStore } from "../queries"
|
||||||
|
import { datasources } from '../datasources'
|
||||||
|
|
||||||
|
describe("Queries Store", () => {
|
||||||
|
let store = createQueriesStore()
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => [SOME_QUERY]})
|
||||||
|
await store.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Initialises correctly", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => [SOME_QUERY]})
|
||||||
|
|
||||||
|
await store.init()
|
||||||
|
expect(get(store)).toEqual({ list: [SOME_QUERY], selected: null})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fetches all the queries", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => [SOME_QUERY]})
|
||||||
|
|
||||||
|
await store.fetch()
|
||||||
|
expect(get(store)).toEqual({ list: [SOME_QUERY], selected: null})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("selects a query and updates selected datasource", async () => {
|
||||||
|
await store.select(SOME_QUERY)
|
||||||
|
|
||||||
|
expect(get(store).selected).toEqual(SOME_QUERY._id)
|
||||||
|
expect(get(datasources).selected).toEqual(SOME_QUERY.datasourceId)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("saves the query, updates the store and returns status message", async () => {
|
||||||
|
api.post.mockReturnValue({ json: () => SAVE_QUERY_RESPONSE})
|
||||||
|
|
||||||
|
await store.select(SOME_QUERY.datasourceId, SOME_QUERY)
|
||||||
|
|
||||||
|
expect(get(store).list).toEqual(expect.arrayContaining([SOME_QUERY]))
|
||||||
|
})
|
||||||
|
it("deletes a query, updates the store and returns status message", async () => {
|
||||||
|
|
||||||
|
api.delete.mockReturnValue({status: 200, message: `Query deleted.`})
|
||||||
|
|
||||||
|
await store.delete(SOME_QUERY)
|
||||||
|
expect(get(store)).toEqual({ list: [], selected: null})
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
import api from 'builderStore/api'
|
||||||
|
|
||||||
|
jest.mock('builderStore/api');
|
||||||
|
|
||||||
|
import { createRolesStore } from "../roles"
|
||||||
|
import { ROLES } from './fixtures/roles'
|
||||||
|
|
||||||
|
describe("Roles Store", () => {
|
||||||
|
let store = createRolesStore()
|
||||||
|
|
||||||
|
beforeEach( async() => {
|
||||||
|
store = createRolesStore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fetches roles from backend", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => ROLES})
|
||||||
|
await store.fetch()
|
||||||
|
|
||||||
|
expect(api.get).toBeCalledWith("/api/roles")
|
||||||
|
expect(get(store)).toEqual(ROLES)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("deletes a role", async () => {
|
||||||
|
api.get.mockReturnValueOnce({ json: () => ROLES})
|
||||||
|
await store.fetch()
|
||||||
|
|
||||||
|
api.delete.mockReturnValue({status: 200, message: `Role deleted.`})
|
||||||
|
|
||||||
|
const updatedRoles = [...ROLES.slice(1)]
|
||||||
|
await store.delete(ROLES[0])
|
||||||
|
|
||||||
|
expect(get(store)).toEqual(updatedRoles)
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
import api from 'builderStore/api'
|
||||||
|
|
||||||
|
jest.mock('builderStore/api');
|
||||||
|
|
||||||
|
import { SOME_TABLES, SAVE_TABLES_RESPONSE, A_TABLE } from './fixtures/tables'
|
||||||
|
|
||||||
|
import { createTablesStore } from "../tables"
|
||||||
|
import { views } from '../views'
|
||||||
|
|
||||||
|
describe("Tables Store", () => {
|
||||||
|
let store = createTablesStore()
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => SOME_TABLES})
|
||||||
|
await store.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Initialises correctly", async () => {
|
||||||
|
expect(get(store)).toEqual({ list: SOME_TABLES, selected: {}, draft: {}})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fetches all the tables", async () => {
|
||||||
|
api.get.mockReturnValue({ json: () => SOME_TABLES})
|
||||||
|
|
||||||
|
await store.fetch()
|
||||||
|
expect(get(store)).toEqual({ list: SOME_TABLES, selected: {}, draft: {}})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("selects a table", async () => {
|
||||||
|
const tableToSelect = SOME_TABLES[0]
|
||||||
|
await store.select(tableToSelect)
|
||||||
|
|
||||||
|
expect(get(store).selected).toEqual(tableToSelect)
|
||||||
|
expect(get(store).draft).toEqual(tableToSelect)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("selecting without a param resets the selected property", async () => {
|
||||||
|
await store.select()
|
||||||
|
|
||||||
|
expect(get(store).draft).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("selecting a table updates the view store", async () => {
|
||||||
|
const tableToSelect = SOME_TABLES[0]
|
||||||
|
await store.select(tableToSelect)
|
||||||
|
|
||||||
|
expect(get(store).selected).toEqual(tableToSelect)
|
||||||
|
expect(get(views).selected).toEqual({ name: `all_${tableToSelect._id}` })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("saving a table also selects it", async () => {
|
||||||
|
api.post.mockReturnValue({ json: () => SAVE_TABLES_RESPONSE})
|
||||||
|
|
||||||
|
await store.save(A_TABLE)
|
||||||
|
|
||||||
|
expect(get(store).selected).toEqual(SAVE_TABLES_RESPONSE)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("saving the table returns a response", async () => {
|
||||||
|
api.post.mockReturnValue({ json: () => SAVE_TABLES_RESPONSE})
|
||||||
|
|
||||||
|
const response = await store.save(A_TABLE)
|
||||||
|
|
||||||
|
expect(response).toEqual(SAVE_TABLES_RESPONSE)
|
||||||
|
})
|
||||||
|
it("deleting a table removes it from the store", async () => {
|
||||||
|
api.delete.mockReturnValue({status: 200, message: `Table deleted.`})
|
||||||
|
|
||||||
|
await store.delete(A_TABLE)
|
||||||
|
expect(get(store).list).toEqual(expect.not.arrayContaining([A_TABLE]))
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: Write tests for saving and deleting fields
|
||||||
|
})
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
import { tables } from "./"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
|
||||||
|
export function createViewsStore() {
|
||||||
|
const { subscribe, update } = writable({
|
||||||
|
list: [],
|
||||||
|
selected: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
select: view => {
|
||||||
|
update(state => ({
|
||||||
|
...state,
|
||||||
|
selected: view,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
delete: async view => {
|
||||||
|
await api.delete(`/api/views/${view}`)
|
||||||
|
await tables.fetch()
|
||||||
|
},
|
||||||
|
save: async view => {
|
||||||
|
const response = await api.post(`/api/views`, view)
|
||||||
|
const json = await response.json()
|
||||||
|
|
||||||
|
const viewMeta = {
|
||||||
|
name: view.name,
|
||||||
|
...json,
|
||||||
|
}
|
||||||
|
|
||||||
|
update(state => {
|
||||||
|
const viewTable = get(tables).list.find(
|
||||||
|
table => table._id === view.tableId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (view.originalName) delete viewTable.views[view.originalName]
|
||||||
|
viewTable.views[view.name] = viewMeta
|
||||||
|
|
||||||
|
state.tables = state.tables
|
||||||
|
state.selectedView = viewMeta
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const views = createViewsStore()
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue