Add initial work on new S3 upload component and button action
This commit is contained in:
parent
4ccf3f9687
commit
8772dc342d
|
@ -44,7 +44,8 @@
|
||||||
"relationshipfield",
|
"relationshipfield",
|
||||||
"daterangepicker",
|
"daterangepicker",
|
||||||
"multifieldselect",
|
"multifieldselect",
|
||||||
"jsonfield"
|
"jsonfield",
|
||||||
|
"s3upload"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<script>
|
||||||
|
import { Select, Label } from "@budibase/bbui"
|
||||||
|
import { currentAsset } from "builderStore"
|
||||||
|
import { findAllMatchingComponents } from "builderStore/componentUtils"
|
||||||
|
|
||||||
|
export let parameters
|
||||||
|
|
||||||
|
$: components = findAllMatchingComponents($currentAsset.props, component =>
|
||||||
|
component._component.endsWith("s3upload")
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<Label small>S3 Upload Component</Label>
|
||||||
|
<Select
|
||||||
|
bind:value={parameters.componentId}
|
||||||
|
options={components}
|
||||||
|
getOptionLabel={x => x._instanceName}
|
||||||
|
getOptionValue={x => x._id}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
display: grid;
|
||||||
|
column-gap: var(--spacing-l);
|
||||||
|
row-gap: var(--spacing-s);
|
||||||
|
grid-template-columns: 120px 1fr;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -11,3 +11,4 @@ export { default as ChangeFormStep } from "./ChangeFormStep.svelte"
|
||||||
export { default as UpdateState } from "./UpdateState.svelte"
|
export { default as UpdateState } from "./UpdateState.svelte"
|
||||||
export { default as RefreshDataProvider } from "./RefreshDataProvider.svelte"
|
export { default as RefreshDataProvider } from "./RefreshDataProvider.svelte"
|
||||||
export { default as DuplicateRow } from "./DuplicateRow.svelte"
|
export { default as DuplicateRow } from "./DuplicateRow.svelte"
|
||||||
|
export { default as S3Upload } from "./S3Upload.svelte"
|
||||||
|
|
|
@ -70,6 +70,10 @@
|
||||||
"name": "Update State",
|
"name": "Update State",
|
||||||
"component": "UpdateState",
|
"component": "UpdateState",
|
||||||
"dependsOnFeature": "state"
|
"dependsOnFeature": "state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Upload File to S3",
|
||||||
|
"component": "S3Upload"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
import { Select } from "@budibase/bbui"
|
||||||
|
import { datasources } from "stores/backend"
|
||||||
|
|
||||||
|
export let value = null
|
||||||
|
|
||||||
|
$: dataSources = $datasources.list
|
||||||
|
.filter(ds => ds.source === "S3")
|
||||||
|
.map(ds => ({
|
||||||
|
label: ds.name,
|
||||||
|
value: ds._id,
|
||||||
|
}))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Select options={dataSources} {value} on:change />
|
|
@ -1,5 +1,6 @@
|
||||||
import { Checkbox, Select, Stepper } from "@budibase/bbui"
|
import { Checkbox, Select, Stepper } from "@budibase/bbui"
|
||||||
import DataSourceSelect from "./DataSourceSelect.svelte"
|
import DataSourceSelect from "./DataSourceSelect.svelte"
|
||||||
|
import S3DataSourceSelect from "./S3DataSourceSelect.svelte"
|
||||||
import DataProviderSelect from "./DataProviderSelect.svelte"
|
import DataProviderSelect from "./DataProviderSelect.svelte"
|
||||||
import ButtonActionEditor from "./ButtonActionEditor/ButtonActionEditor.svelte"
|
import ButtonActionEditor from "./ButtonActionEditor/ButtonActionEditor.svelte"
|
||||||
import TableSelect from "./TableSelect.svelte"
|
import TableSelect from "./TableSelect.svelte"
|
||||||
|
@ -21,6 +22,7 @@ const componentMap = {
|
||||||
text: DrawerBindableCombobox,
|
text: DrawerBindableCombobox,
|
||||||
select: Select,
|
select: Select,
|
||||||
dataSource: DataSourceSelect,
|
dataSource: DataSourceSelect,
|
||||||
|
"dataSource/s3": S3DataSourceSelect,
|
||||||
dataProvider: DataProviderSelect,
|
dataProvider: DataProviderSelect,
|
||||||
boolean: Checkbox,
|
boolean: Checkbox,
|
||||||
number: Stepper,
|
number: Stepper,
|
||||||
|
|
|
@ -3315,5 +3315,44 @@
|
||||||
"suffix": "repeater"
|
"suffix": "repeater"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"s3upload": {
|
||||||
|
"name": "S3 File Upload",
|
||||||
|
"icon": "UploadToCloud",
|
||||||
|
"styles": ["size"],
|
||||||
|
"editable": true,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "field/attachment",
|
||||||
|
"label": "Field",
|
||||||
|
"key": "field"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "Label",
|
||||||
|
"key": "label"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dataSource/s3",
|
||||||
|
"label": "S3 Datasource",
|
||||||
|
"key": "datasource"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "Bucket",
|
||||||
|
"key": "bucket"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Disabled",
|
||||||
|
"key": "disabled",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "validation/attachment",
|
||||||
|
"label": "Validation",
|
||||||
|
"key": "validation"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
<script>
|
||||||
|
import Field from "./Field.svelte"
|
||||||
|
import { CoreDropzone } from "@budibase/bbui"
|
||||||
|
import { getContext, onMount, onDestroy } from "svelte"
|
||||||
|
|
||||||
|
export let dataSource
|
||||||
|
export let bucket
|
||||||
|
export let field
|
||||||
|
export let label
|
||||||
|
export let disabled = false
|
||||||
|
export let validation
|
||||||
|
|
||||||
|
let fieldState
|
||||||
|
let fieldApi
|
||||||
|
|
||||||
|
const { API, notificationStore, uploadStore } = getContext("sdk")
|
||||||
|
const component = getContext("component")
|
||||||
|
const formContext = getContext("form")
|
||||||
|
|
||||||
|
// 5GB cap per item sent via S3 REST API
|
||||||
|
const MaxFileSize = 1000000000 * 5
|
||||||
|
|
||||||
|
let file
|
||||||
|
|
||||||
|
const handleFileTooLarge = () => {
|
||||||
|
notificationStore.actions.warning(
|
||||||
|
"Files cannot exceed 5GB. Please try again with a smaller file."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const processFiles = async fileList => {
|
||||||
|
// let data = new FormData()
|
||||||
|
// for (let i = 0; i < fileList.length; i++) {
|
||||||
|
// data.append("file", fileList[i])
|
||||||
|
// }
|
||||||
|
// return await API.uploadAttachment(data, formContext?.dataSource?.tableId)
|
||||||
|
file = fileList[0]
|
||||||
|
console.log("processing", fileList)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const upload = async () => {
|
||||||
|
console.log("UPLOADING!!!")
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
uploadStore.actions.registerFileUpload($component.id, upload)
|
||||||
|
})
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
uploadStore.actions.unregisterFileUpload($component.id)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
{label}
|
||||||
|
{field}
|
||||||
|
{disabled}
|
||||||
|
{validation}
|
||||||
|
type="s3upload"
|
||||||
|
bind:fieldState
|
||||||
|
bind:fieldApi
|
||||||
|
defaultValue={[]}
|
||||||
|
>
|
||||||
|
{#if fieldState}
|
||||||
|
<CoreDropzone
|
||||||
|
value={fieldState.value}
|
||||||
|
disabled={fieldState.disabled}
|
||||||
|
error={fieldState.error}
|
||||||
|
on:change={e => {
|
||||||
|
fieldApi.setValue(e.detail)
|
||||||
|
}}
|
||||||
|
{processFiles}
|
||||||
|
{handleFileTooLarge}
|
||||||
|
maximum={1}
|
||||||
|
fileSizeLimit={MaxFileSize}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</Field>
|
|
@ -12,3 +12,4 @@ export { default as relationshipfield } from "./RelationshipField.svelte"
|
||||||
export { default as passwordfield } from "./PasswordField.svelte"
|
export { default as passwordfield } from "./PasswordField.svelte"
|
||||||
export { default as formstep } from "./FormStep.svelte"
|
export { default as formstep } from "./FormStep.svelte"
|
||||||
export { default as jsonfield } from "./JSONField.svelte"
|
export { default as jsonfield } from "./JSONField.svelte"
|
||||||
|
export { default as s3upload } from "./S3Upload.svelte"
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
routeStore,
|
routeStore,
|
||||||
screenStore,
|
screenStore,
|
||||||
builderStore,
|
builderStore,
|
||||||
|
uploadStore,
|
||||||
} from "stores"
|
} from "stores"
|
||||||
import { styleable } from "utils/styleable"
|
import { styleable } from "utils/styleable"
|
||||||
import { linkable } from "utils/linkable"
|
import { linkable } from "utils/linkable"
|
||||||
|
@ -19,6 +20,7 @@ export default {
|
||||||
routeStore,
|
routeStore,
|
||||||
screenStore,
|
screenStore,
|
||||||
builderStore,
|
builderStore,
|
||||||
|
uploadStore,
|
||||||
styleable,
|
styleable,
|
||||||
linkable,
|
linkable,
|
||||||
getAction,
|
getAction,
|
||||||
|
|
|
@ -9,6 +9,7 @@ export { confirmationStore } from "./confirmation"
|
||||||
export { peekStore } from "./peek"
|
export { peekStore } from "./peek"
|
||||||
export { stateStore } from "./state"
|
export { stateStore } from "./state"
|
||||||
export { themeStore } from "./theme"
|
export { themeStore } from "./theme"
|
||||||
|
export { uploadStore } from "./uploads.js"
|
||||||
|
|
||||||
// Context stores are layered and duplicated, so it is not a singleton
|
// Context stores are layered and duplicated, so it is not a singleton
|
||||||
export { createContextStore } from "./context"
|
export { createContextStore } from "./context"
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
|
||||||
|
export const createUploadStore = () => {
|
||||||
|
const store = writable([])
|
||||||
|
|
||||||
|
// Registers a new file upload component
|
||||||
|
const registerFileUpload = (componentId, callback) => {
|
||||||
|
if (!componentId || !callback) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
store.update(state => {
|
||||||
|
state.push({
|
||||||
|
componentId,
|
||||||
|
callback,
|
||||||
|
})
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregisters a file upload component
|
||||||
|
const unregisterFileUpload = componentId => {
|
||||||
|
store.update(state => state.filter(c => c.componentId !== componentId))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processes a file upload for a given component ID
|
||||||
|
const processFileUpload = async componentId => {
|
||||||
|
if (!componentId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const component = get(store).find(c => c.componentId === componentId)
|
||||||
|
await component?.callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe: store.subscribe,
|
||||||
|
actions: { registerFileUpload, unregisterFileUpload, processFileUpload },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const uploadStore = createUploadStore()
|
|
@ -5,6 +5,7 @@ import {
|
||||||
confirmationStore,
|
confirmationStore,
|
||||||
authStore,
|
authStore,
|
||||||
stateStore,
|
stateStore,
|
||||||
|
uploadStore,
|
||||||
} from "stores"
|
} from "stores"
|
||||||
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "api"
|
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "api"
|
||||||
import { ActionTypes } from "constants"
|
import { ActionTypes } from "constants"
|
||||||
|
@ -157,6 +158,14 @@ const updateStateHandler = action => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const s3UploadHandler = async action => {
|
||||||
|
const { componentId } = action.parameters
|
||||||
|
if (!componentId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await uploadStore.actions.processFileUpload(componentId)
|
||||||
|
}
|
||||||
|
|
||||||
const handlerMap = {
|
const handlerMap = {
|
||||||
["Save Row"]: saveRowHandler,
|
["Save Row"]: saveRowHandler,
|
||||||
["Duplicate Row"]: duplicateRowHandler,
|
["Duplicate Row"]: duplicateRowHandler,
|
||||||
|
@ -171,6 +180,7 @@ const handlerMap = {
|
||||||
["Close Screen Modal"]: closeScreenModalHandler,
|
["Close Screen Modal"]: closeScreenModalHandler,
|
||||||
["Change Form Step"]: changeFormStepHandler,
|
["Change Form Step"]: changeFormStepHandler,
|
||||||
["Update State"]: updateStateHandler,
|
["Update State"]: updateStateHandler,
|
||||||
|
["Upload File to S3"]: s3UploadHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmTextMap = {
|
const confirmTextMap = {
|
||||||
|
|
Loading…
Reference in New Issue