Enable uploading a CSV file as a datasource and fix edge cases
This commit is contained in:
parent
43c30d877b
commit
9667c954ef
|
@ -10,6 +10,10 @@
|
||||||
Drawer,
|
Drawer,
|
||||||
DrawerContent,
|
DrawerContent,
|
||||||
Icon,
|
Icon,
|
||||||
|
Modal,
|
||||||
|
ModalContent,
|
||||||
|
CoreDropzone,
|
||||||
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import { store, currentAsset } from "builderStore"
|
import { store, currentAsset } from "builderStore"
|
||||||
|
@ -24,6 +28,7 @@
|
||||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||||
import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte"
|
import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte"
|
||||||
|
import { API } from "api"
|
||||||
|
|
||||||
export let value = {}
|
export let value = {}
|
||||||
export let otherSources
|
export let otherSources
|
||||||
|
@ -39,6 +44,7 @@
|
||||||
let tmpQueryParams
|
let tmpQueryParams
|
||||||
let tmpCustomData
|
let tmpCustomData
|
||||||
let customDataValid = true
|
let customDataValid = true
|
||||||
|
let modal
|
||||||
|
|
||||||
$: text = value?.label ?? "Choose an option"
|
$: text = value?.label ?? "Choose an option"
|
||||||
$: tables = $tablesStore.list.map(m => ({
|
$: tables = $tablesStore.list.map(m => ({
|
||||||
|
@ -184,6 +190,26 @@
|
||||||
})
|
})
|
||||||
drawer.hide()
|
drawer.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const promptForCSV = () => {
|
||||||
|
drawer.hide()
|
||||||
|
modal.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCSV = async e => {
|
||||||
|
try {
|
||||||
|
const csv = await e.detail[0]?.text()
|
||||||
|
if (csv?.length) {
|
||||||
|
const js = await API.csvToJson(csv)
|
||||||
|
tmpCustomData = JSON.stringify(js)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
notifications.error("Failed to parse CSV")
|
||||||
|
}
|
||||||
|
modal.hide()
|
||||||
|
drawer.show()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container" bind:this={anchorRight}>
|
<div class="container" bind:this={anchorRight}>
|
||||||
|
@ -227,12 +253,12 @@
|
||||||
<Icon hoverable name="Settings" on:click={openCustomDrawer} />
|
<Icon hoverable name="Settings" on:click={openCustomDrawer} />
|
||||||
</div>
|
</div>
|
||||||
<Drawer title="Custom data" bind:this={drawer}>
|
<Drawer title="Custom data" bind:this={drawer}>
|
||||||
<Button
|
<div slot="buttons" style="display:contents">
|
||||||
slot="buttons"
|
<Button primary on:click={promptForCSV}>Load CSV</Button>
|
||||||
cta
|
<Button cta on:click={saveCustomData} disabled={!customDataValid}>
|
||||||
on:click={saveCustomData}
|
Save
|
||||||
disabled={!customDataValid}>Save</Button
|
</Button>
|
||||||
>
|
</div>
|
||||||
<div slot="description">
|
<div slot="description">
|
||||||
Provide a JavaScript or JSON array to use as data
|
Provide a JavaScript or JSON array to use as data
|
||||||
</div>
|
</div>
|
||||||
|
@ -349,6 +375,12 @@
|
||||||
</div>
|
</div>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<Modal bind:this={modal}>
|
||||||
|
<ModalContent title="Choose a CSV">
|
||||||
|
<CoreDropzone compact extensions=".csv" on:change={handleCSV} />
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -146,6 +146,11 @@ export const createActions = context => {
|
||||||
return getAPI()?.actions.canUseColumn(name)
|
return getAPI()?.actions.canUseColumn(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the default number of rows for a single page
|
||||||
|
const getFeatures = () => {
|
||||||
|
return getAPI()?.actions.getFeatures()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
datasource: {
|
datasource: {
|
||||||
...datasource,
|
...datasource,
|
||||||
|
@ -158,6 +163,7 @@ export const createActions = context => {
|
||||||
getRow,
|
getRow,
|
||||||
isDatasourceValid,
|
isDatasourceValid,
|
||||||
canUseColumn,
|
canUseColumn,
|
||||||
|
getFeatures,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
|
import QueryFetch from "../../../../fetch/QueryFetch"
|
||||||
|
|
||||||
|
export const RowPageSize = 100000
|
||||||
|
|
||||||
export const createActions = context => {
|
export const createActions = context => {
|
||||||
const { columns, stickyColumn, table, viewV2 } = context
|
const { columns, stickyColumn, table, viewV2 } = context
|
||||||
|
@ -35,6 +38,11 @@ export const createActions = context => {
|
||||||
return $columns.some(col => col.name === name) || $sticky?.name === name
|
return $columns.some(col => col.name === name) || $sticky?.name === name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getFeatures = () => {
|
||||||
|
// We don't support any features
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nonPlus: {
|
nonPlus: {
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -45,6 +53,7 @@ export const createActions = context => {
|
||||||
getRow,
|
getRow,
|
||||||
isDatasourceValid,
|
isDatasourceValid,
|
||||||
canUseColumn,
|
canUseColumn,
|
||||||
|
getFeatures,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
|
import TableFetch from "../../../../fetch/TableFetch"
|
||||||
|
|
||||||
const SuppressErrors = true
|
const SuppressErrors = true
|
||||||
|
|
||||||
|
export const RowPageSize = 100
|
||||||
|
|
||||||
export const createActions = context => {
|
export const createActions = context => {
|
||||||
const { API, datasource, columns, stickyColumn } = context
|
const { API, datasource, columns, stickyColumn } = context
|
||||||
|
|
||||||
|
@ -45,6 +48,10 @@ export const createActions = context => {
|
||||||
return $columns.some(col => col.name === name) || $sticky?.name === name
|
return $columns.some(col => col.name === name) || $sticky?.name === name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getFeatures = () => {
|
||||||
|
return new TableFetch(null).determineFeatureFlags()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
table: {
|
table: {
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -55,6 +62,7 @@ export const createActions = context => {
|
||||||
getRow,
|
getRow,
|
||||||
isDatasourceValid,
|
isDatasourceValid,
|
||||||
canUseColumn,
|
canUseColumn,
|
||||||
|
getFeatures,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
|
import ViewV2Fetch from "../../../../fetch/ViewV2Fetch"
|
||||||
|
|
||||||
const SuppressErrors = true
|
const SuppressErrors = true
|
||||||
|
|
||||||
|
export const RowPageSize = 100
|
||||||
|
|
||||||
export const createActions = context => {
|
export const createActions = context => {
|
||||||
const { API, datasource, columns, stickyColumn } = context
|
const { API, datasource, columns, stickyColumn } = context
|
||||||
|
|
||||||
|
@ -45,6 +48,10 @@ export const createActions = context => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getFeatures = () => {
|
||||||
|
return new ViewV2Fetch(null).determineFeatureFlags()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
viewV2: {
|
viewV2: {
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -55,6 +62,7 @@ export const createActions = context => {
|
||||||
getRow,
|
getRow,
|
||||||
isDatasourceValid,
|
isDatasourceValid,
|
||||||
canUseColumn,
|
canUseColumn,
|
||||||
|
getFeatures,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { writable, derived, get } from "svelte/store"
|
||||||
import { fetchData } from "../../../fetch"
|
import { fetchData } from "../../../fetch"
|
||||||
import { NewRowID, RowPageSize } from "../lib/constants"
|
import { NewRowID, RowPageSize } from "../lib/constants"
|
||||||
import { tick } from "svelte"
|
import { tick } from "svelte"
|
||||||
import { Helpers } from "@budibase/bbui"
|
|
||||||
|
|
||||||
export const createStores = () => {
|
export const createStores = () => {
|
||||||
const rows = writable([])
|
const rows = writable([])
|
||||||
|
@ -111,6 +110,10 @@ export const createActions = context => {
|
||||||
const $filter = get(filter)
|
const $filter = get(filter)
|
||||||
const $sort = get(sort)
|
const $sort = get(sort)
|
||||||
|
|
||||||
|
// Determine how many rows to fetch per page
|
||||||
|
const features = datasource.actions.getFeatures()
|
||||||
|
const limit = features?.supportsPagination ? RowPageSize : 100000
|
||||||
|
|
||||||
// Create new fetch model
|
// Create new fetch model
|
||||||
const newFetch = fetchData({
|
const newFetch = fetchData({
|
||||||
API,
|
API,
|
||||||
|
@ -119,7 +122,7 @@ export const createActions = context => {
|
||||||
filter: $filter,
|
filter: $filter,
|
||||||
sortColumn: $sort.column,
|
sortColumn: $sort.column,
|
||||||
sortOrder: $sort.order,
|
sortOrder: $sort.order,
|
||||||
limit: RowPageSize,
|
limit,
|
||||||
paginate: true,
|
paginate: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,9 +31,9 @@ export default class CustomFetch extends DataFetch {
|
||||||
if (typeof data === "string") {
|
if (typeof data === "string") {
|
||||||
// Try JSON parsing
|
// Try JSON parsing
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(data)
|
const js = JSON.parse(data)
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(js)) {
|
||||||
return data
|
return js
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Ignore
|
// Ignore
|
||||||
|
|
Loading…
Reference in New Issue