forked from tsai/budibase
18 changed files with 302 additions and 176 deletions
@ -0,0 +1,23 @@ |
|||
<script> |
|||
import { Select } from "@budibase/bbui" |
|||
import { currentAsset, store } from "builderStore" |
|||
import { findComponentPath } from "builderStore/storeUtils" |
|||
|
|||
export let value |
|||
|
|||
$: path = findComponentPath($currentAsset.props, $store.selectedComponentId) |
|||
$: console.log(path) |
|||
$: providers = path.filter( |
|||
component => |
|||
component._component === "@budibase/standard-components/dataprovider" |
|||
) |
|||
</script> |
|||
|
|||
<Select thin secondary {value} on:change> |
|||
<option value="">Choose option</option> |
|||
{#if providers} |
|||
{#each providers as component} |
|||
<option value={component._id}>{component._instanceName}</option> |
|||
{/each} |
|||
{/if} |
|||
</Select> |
|||
@ -1,7 +1,7 @@ |
|||
<script> |
|||
import DatasourceSelect from "./DatasourceSelect.svelte" |
|||
import DataSourceSelect from "./DataSourceSelect.svelte" |
|||
|
|||
const otherSources = [{ name: "Custom", label: "Custom" }] |
|||
</script> |
|||
|
|||
<DatasourceSelect on:change {...$$props} showAllQueries={true} {otherSources} /> |
|||
<DataSourceSelect on:change {...$$props} showAllQueries={true} {otherSources} /> |
|||
|
|||
@ -0,0 +1,84 @@ |
|||
import { writable, get } from "svelte/store" |
|||
import { notificationStore } from "./notification" |
|||
|
|||
export const createDataSourceStore = () => { |
|||
const store = writable([]) |
|||
|
|||
// Registers a new dataSource instance
|
|||
const registerDataSource = (dataSource, instanceId, refresh) => { |
|||
if (!dataSource || !instanceId || !refresh) { |
|||
return |
|||
} |
|||
|
|||
// Create a list of all relevant dataSource IDs which would require that
|
|||
// this dataSource is refreshed
|
|||
let dataSourceIds = [] |
|||
|
|||
// Extract table ID
|
|||
if (dataSource.type === "table" || dataSource.type === "view") { |
|||
if (dataSource.tableId) { |
|||
dataSourceIds.push(dataSource.tableId) |
|||
} |
|||
} |
|||
|
|||
// Extract both table IDs from both sides of the relationship
|
|||
else if (dataSource.type === "link") { |
|||
if (dataSource.rowTableId) { |
|||
dataSourceIds.push(dataSource.rowTableId) |
|||
} |
|||
if (dataSource.tableId) { |
|||
dataSourceIds.push(dataSource.tableId) |
|||
} |
|||
} |
|||
|
|||
// Extract the dataSource ID (not the query ID) for queries
|
|||
else if (dataSource.type === "query") { |
|||
if (dataSource.dataSourceId) { |
|||
dataSourceIds.push(dataSource.dataSourceId) |
|||
} |
|||
} |
|||
|
|||
// Store configs for each relevant dataSource ID
|
|||
if (dataSourceIds.length) { |
|||
store.update(state => { |
|||
dataSourceIds.forEach(id => { |
|||
state.push({ |
|||
dataSourceId: id, |
|||
instanceId, |
|||
refresh, |
|||
}) |
|||
}) |
|||
return state |
|||
}) |
|||
} |
|||
} |
|||
|
|||
// Removes all registered dataSource instances belonging to a particular
|
|||
// instance ID
|
|||
const unregisterInstance = instanceId => { |
|||
store.update(state => { |
|||
return state.filter(instance => instance.instanceId !== instanceId) |
|||
}) |
|||
} |
|||
|
|||
// Invalidates a specific dataSource ID by refreshing all instances
|
|||
// which depend on data from that dataSource
|
|||
const invalidateDataSource = dataSourceId => { |
|||
const relatedInstances = get(store).filter(instance => { |
|||
return instance.dataSourceId === dataSourceId |
|||
}) |
|||
if (relatedInstances?.length) { |
|||
notificationStore.blockNotifications(1000) |
|||
} |
|||
relatedInstances?.forEach(instance => { |
|||
instance.refresh() |
|||
}) |
|||
} |
|||
|
|||
return { |
|||
subscribe: store.subscribe, |
|||
actions: { registerDataSource, unregisterInstance, invalidateDataSource }, |
|||
} |
|||
} |
|||
|
|||
export const dataSourceStore = createDataSourceStore() |
|||
@ -1,84 +0,0 @@ |
|||
import { writable, get } from "svelte/store" |
|||
import { notificationStore } from "./notification" |
|||
|
|||
export const createDatasourceStore = () => { |
|||
const store = writable([]) |
|||
|
|||
// Registers a new datasource instance
|
|||
const registerDatasource = (datasource, instanceId, refresh) => { |
|||
if (!datasource || !instanceId || !refresh) { |
|||
return |
|||
} |
|||
|
|||
// Create a list of all relevant datasource IDs which would require that
|
|||
// this datasource is refreshed
|
|||
let datasourceIds = [] |
|||
|
|||
// Extract table ID
|
|||
if (datasource.type === "table" || datasource.type === "view") { |
|||
if (datasource.tableId) { |
|||
datasourceIds.push(datasource.tableId) |
|||
} |
|||
} |
|||
|
|||
// Extract both table IDs from both sides of the relationship
|
|||
else if (datasource.type === "link") { |
|||
if (datasource.rowTableId) { |
|||
datasourceIds.push(datasource.rowTableId) |
|||
} |
|||
if (datasource.tableId) { |
|||
datasourceIds.push(datasource.tableId) |
|||
} |
|||
} |
|||
|
|||
// Extract the datasource ID (not the query ID) for queries
|
|||
else if (datasource.type === "query") { |
|||
if (datasource.datasourceId) { |
|||
datasourceIds.push(datasource.datasourceId) |
|||
} |
|||
} |
|||
|
|||
// Store configs for each relevant datasource ID
|
|||
if (datasourceIds.length) { |
|||
store.update(state => { |
|||
datasourceIds.forEach(id => { |
|||
state.push({ |
|||
datasourceId: id, |
|||
instanceId, |
|||
refresh, |
|||
}) |
|||
}) |
|||
return state |
|||
}) |
|||
} |
|||
} |
|||
|
|||
// Removes all registered datasource instances belonging to a particular
|
|||
// instance ID
|
|||
const unregisterInstance = instanceId => { |
|||
store.update(state => { |
|||
return state.filter(instance => instance.instanceId !== instanceId) |
|||
}) |
|||
} |
|||
|
|||
// Invalidates a specific datasource ID by refreshing all instances
|
|||
// which depend on data from that datasource
|
|||
const invalidateDatasource = datasourceId => { |
|||
const relatedInstances = get(store).filter(instance => { |
|||
return instance.datasourceId === datasourceId |
|||
}) |
|||
if (relatedInstances?.length) { |
|||
notificationStore.blockNotifications(1000) |
|||
} |
|||
relatedInstances?.forEach(instance => { |
|||
instance.refresh() |
|||
}) |
|||
} |
|||
|
|||
return { |
|||
subscribe: store.subscribe, |
|||
actions: { registerDatasource, unregisterInstance, invalidateDatasource }, |
|||
} |
|||
} |
|||
|
|||
export const datasourceStore = createDatasourceStore() |
|||
@ -0,0 +1,93 @@ |
|||
<script> |
|||
import { getContext } from "svelte" |
|||
|
|||
export let dataSource |
|||
export let filter |
|||
export let sortColumn |
|||
export let sortOrder |
|||
export let limit |
|||
|
|||
const { API, styleable, Provider, ActionTypes } = getContext("sdk") |
|||
const component = getContext("component") |
|||
|
|||
// Loading flag every time data is being fetched |
|||
let loading = false |
|||
|
|||
// Loading flag for the initial load |
|||
let loaded = false |
|||
|
|||
let allRows = [] |
|||
$: fetchData(dataSource) |
|||
$: filteredRows = filterRows(allRows, filter) |
|||
$: sortedRows = sortRows(filteredRows, sortColumn, sortOrder) |
|||
$: rows = limitRows(sortedRows, limit) |
|||
$: { |
|||
console.log(allRows) |
|||
console.log(filteredRows) |
|||
console.log(sortedRows) |
|||
console.log(rows) |
|||
} |
|||
|
|||
$: actions = [ |
|||
{ |
|||
type: ActionTypes.RefreshDatasource, |
|||
callback: () => fetchData(dataSource), |
|||
metadata: { dataSource }, |
|||
}, |
|||
] |
|||
$: dataContext = { |
|||
rows, |
|||
rowsLength: rows.length, |
|||
loading, |
|||
loaded, |
|||
} |
|||
|
|||
const fetchData = async dataSource => { |
|||
loading = true |
|||
allRows = await API.fetchDatasource(dataSource) |
|||
loading = false |
|||
loaded = false |
|||
} |
|||
|
|||
const filterRows = (rows, filter) => { |
|||
if (!Object.keys(filter || {}).length) { |
|||
return rows |
|||
} |
|||
let filteredData = [...rows] |
|||
Object.entries(filter).forEach(([field, value]) => { |
|||
if (value != null && value !== "") { |
|||
filteredData = filteredData.filter(row => { |
|||
return row[field] === value |
|||
}) |
|||
} |
|||
}) |
|||
return filteredData |
|||
} |
|||
|
|||
const sortRows = (rows, sortColumn, sortOrder) => { |
|||
if (!sortColumn || !sortOrder) { |
|||
return rows |
|||
} |
|||
return rows.slice().sort((a, b) => { |
|||
const colA = a[sortColumn] |
|||
const colB = b[sortColumn] |
|||
if (sortOrder === "descending") { |
|||
return colA > colB ? -1 : 1 |
|||
} else { |
|||
return colA > colB ? 1 : -1 |
|||
} |
|||
}) |
|||
} |
|||
|
|||
const limitRows = (rows, limit) => { |
|||
const numLimit = parseFloat(limit) |
|||
if (isNaN(numLimit)) { |
|||
return rows |
|||
} |
|||
return rows.slice(0, numLimit) |
|||
} |
|||
</script> |
|||
|
|||
<Provider {actions} data={dataContext}> |
|||
<slot /> |
|||
</Provider> |
|||
Loading…
Reference in new issue