diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 99535e6b33..1b814be96d 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -84,7 +84,7 @@ "@spectrum-css/vars": "3.0.1", "dayjs": "^1.10.4", "easymde": "^2.16.1", - "svelte-flatpickr": "^3.2.3", + "svelte-flatpickr": "^3.3.2", "svelte-portal": "^1.0.0" }, "resolutions": { diff --git a/packages/bbui/src/ActionButton/ActionButton.svelte b/packages/bbui/src/ActionButton/ActionButton.svelte index 60c8bec80b..e9eb3b3471 100644 --- a/packages/bbui/src/ActionButton/ActionButton.svelte +++ b/packages/bbui/src/ActionButton/ActionButton.svelte @@ -71,7 +71,7 @@ {/if} {#if icon}
+
{#if selectedImage} {#if gallery} diff --git a/packages/bbui/src/Table/ArrayRenderer.svelte b/packages/bbui/src/Table/ArrayRenderer.svelte index 3755850666..637454dbca 100644 --- a/packages/bbui/src/Table/ArrayRenderer.svelte +++ b/packages/bbui/src/Table/ArrayRenderer.svelte @@ -5,8 +5,9 @@ const displayLimit = 5 - $: badges = Array.isArray(value) ? value.slice(0, displayLimit) : [] - $: leftover = (value?.length ?? 0) - badges.length + $: arrayValue = Array.isArray(value) ? value : [value].filter(x => !!x) + $: badges = arrayValue.slice(0, displayLimit) + $: leftover = arrayValue.length - badges.length {#each badges as badge} diff --git a/packages/bbui/src/Table/Table.svelte b/packages/bbui/src/Table/Table.svelte index 19d361c8b1..5bb4ed4523 100644 --- a/packages/bbui/src/Table/Table.svelte +++ b/packages/bbui/src/Table/Table.svelte @@ -143,7 +143,7 @@ } fields?.forEach(field => { const fieldSchema = schema[field] - if (fieldSchema.width) { + if (fieldSchema.width && typeof fieldSchema.width === "string") { style += ` ${fieldSchema.width}` } else { style += " minmax(auto, 1fr)" diff --git a/packages/bbui/src/bbui.css b/packages/bbui/src/bbui.css index ef3483d3df..343aa77b27 100644 --- a/packages/bbui/src/bbui.css +++ b/packages/bbui/src/bbui.css @@ -97,4 +97,22 @@ a { text-decoration: none; -} \ No newline at end of file +} + +/* Custom theme additions */ +.spectrum--darkest { + --drop-shadow: rgba(0, 0, 0, 0.6); + --spectrum-global-color-blue-100: rgb(28, 33, 43); +} +.spectrum--dark { + --drop-shadow: rgba(0, 0, 0, 0.3); + --spectrum-global-color-blue-100: rgb(42, 47, 57); +} +.spectrum--light { + --drop-shadow: rgba(0, 0, 0, 0.075); + --spectrum-global-color-blue-100: rgb(240, 245, 255); +} +.spectrum--lightest { + --drop-shadow: rgba(0, 0, 0, 0.05); + --spectrum-global-color-blue-100: rgb(240, 244, 255); +} diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 0c5adfc18c..acb3dacf93 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -1,286 +1,74 @@ -
- + { - selectedRows = e.detail - }} - customPlaceholder + allowAddRows={!isUsersTable} + allowDeleteRows={!isUsersTable} + schemaOverrides={isUsersTable ? userSchemaOverrides : null} + on:updatetable={e => tables.updateTable(e.detail)} > -
-
- - {#if !isUsersTable} - - {/if} - {#if isInternal} - - {/if} -
-
- - {#if isUsersTable} - - {/if} - {#if !isInternal} - - {/if} - - - - {#key id} - - {/key} -
-
-
- - {#if !hasCols} - Let's create some columns - - Start building out your table structure
- by adding some columns - - {:else} - Now let's add a row - - Add some data to your table
- by adding some rows - - {/if} -
-
-
- {#key id} -
- -
- {/key} + + {#if isInternal} + + {/if} + + {#if isUsersTable} + + {/if} + {#if !isInternal} + + {/if} + + + + + + {#if isUsersTable} + + {:else} + + {/if} + +
diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index a0e777c331..4df6e9a306 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -1,15 +1,10 @@ @@ -138,16 +97,6 @@ {/if}
- {#if !isUsersTable && selectedRows.length > 0} - { - await deleteRows(rows) - resetSelectedRows() - }} - /> - {/if}
{#key tableId} @@ -160,13 +109,7 @@ {rowCount} {disableSorting} {customPlaceholder} - bind:selectedRows - allowSelectRows={allowEditing && !isUsersTable} - allowEditRows={allowEditing} - allowEditColumns={allowEditing} showAutoColumns={!hideAutocolumns} - on:editcolumn={e => editColumn(e.detail)} - on:editrow={e => editRow(e.detail)} on:clickrelationship={e => selectRelationship(e.detail)} on:sort > @@ -176,42 +119,6 @@ {/key} - - { - confirmDelete.show() - }} - row={editableRow} - /> - - - { - if (editableRow) { - await deleteRows([editableRow]) - } - editableRow = undefined - }} - onCancel={async () => { - editRow(editableRow) - }} - title="Confirm Deletion" -> - Are you sure you want to delete this row? - - - - - - diff --git a/packages/builder/src/components/start/AppRow.svelte b/packages/builder/src/components/start/AppRow.svelte index 96c0e2154a..34d083a096 100644 --- a/packages/builder/src/components/start/AppRow.svelte +++ b/packages/builder/src/components/start/AppRow.svelte @@ -59,9 +59,7 @@
- +
diff --git a/packages/builder/src/global.css b/packages/builder/src/global.css index 5e9a35706e..bc1f55d9d3 100644 --- a/packages/builder/src/global.css +++ b/packages/builder/src/global.css @@ -70,7 +70,6 @@ a { background: var(--spectrum-alias-background-color-default); } html * { - scrollbar-width: thin; scrollbar-color: var(--spectrum-global-color-gray-400) var(--spectrum-alias-background-color-default); } diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json index 5da16d2b50..d35e7cd515 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json @@ -28,6 +28,7 @@ "dataprovider", "repeater", "table", + "spreadsheet", "dynamicfilter", "daterangepicker" ] diff --git a/packages/builder/src/stores/backend/tables.js b/packages/builder/src/stores/backend/tables.js index 3b7ce35dde..75679532f3 100644 --- a/packages/builder/src/stores/backend/tables.js +++ b/packages/builder/src/stores/backend/tables.js @@ -135,6 +135,24 @@ export function createTablesStore() { await save(draft) } + const updateTable = table => { + const index = get(store).list.findIndex(x => x._id === table._id) + if (index === -1) { + return + } + + // This function has to merge state as there discrepancies with the table + // API endpoints. The table list endpoint and get table endpoint use the + // "type" property to mean different things. + store.update(state => { + state.list[index] = { + ...table, + type: state.list[index].type, + } + return state + }) + } + return { subscribe: derivedStore.subscribe, fetch, @@ -145,6 +163,7 @@ export function createTablesStore() { delete: deleteTable, saveField, deleteField, + updateTable, } } diff --git a/packages/client/manifest.json b/packages/client/manifest.json index c4408b9202..f27d090617 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -5161,5 +5161,36 @@ "type": "schema", "suffix": "repeater" } + }, + "spreadsheet": { + "name": "Spreadsheet", + "icon": "ViewGrid", + "settings": [ + { + "key": "table", + "type": "table", + "label": "Table" + }, + { + "type": "filter", + "label": "Filtering", + "key": "filter" + }, + { + "type": "field/sortable", + "label": "Sort Column", + "key": "sortColumn" + }, + { + "type": "select", + "label": "Sort Order", + "key": "sortOrder", + "options": [ + "Ascending", + "Descending" + ], + "defaultValue": "Ascending" + } + ] } } diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index d69170702c..ce8722bb9b 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -95,7 +95,7 @@ {#if $builderStore.usedPlugins?.length} - {#each $builderStore.usedPlugins as plugin} + {#each $builderStore.usedPlugins as plugin (plugin.hash)} {/each} {/if} diff --git a/packages/client/src/sdk.js b/packages/client/src/sdk.js index 264cc85626..c9ff1eba36 100644 --- a/packages/client/src/sdk.js +++ b/packages/client/src/sdk.js @@ -12,6 +12,7 @@ import { environmentStore, sidePanelStore, dndIsDragging, + confirmationStore, } from "stores" import { styleable } from "utils/styleable" import { linkable } from "utils/linkable" @@ -35,6 +36,7 @@ export default { sidePanelStore, dndIsDragging, currentRole, + confirmationStore, styleable, linkable, getAction, diff --git a/packages/client/src/utils/domDebounce.js b/packages/client/src/utils/domDebounce.js index b7fc017247..b15d2698b4 100644 --- a/packages/client/src/utils/domDebounce.js +++ b/packages/client/src/utils/domDebounce.js @@ -1,12 +1,14 @@ -export const domDebounce = callback => { +export const domDebounce = (callback, extractParams = x => x) => { let active = false - return e => { + let lastParams + return (...params) => { + lastParams = extractParams(...params) if (!active) { - window.requestAnimationFrame(() => { - callback(e) + active = true + requestAnimationFrame(() => { + callback(lastParams) active = false }) - active = true } } } diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index 4f1cc2930d..48161defb8 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -8,7 +8,9 @@ "dependencies": { "@budibase/bbui": "2.5.6-alpha.6", "@budibase/shared-core": "2.5.6-alpha.6", + "dayjs": "^1.11.7", "lodash": "^4.17.21", + "socket.io-client": "^4.6.1", "svelte": "^3.46.2" } } diff --git a/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte b/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte new file mode 100644 index 0000000000..2eb191e113 --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte @@ -0,0 +1,153 @@ + + +
+ {#each value || [] as attachment} + {#if isImage(attachment.extension)} + {attachment.extension} + {:else} +
+ {attachment.extension} +
+ {/if} + {/each} +
+ +{#if isOpen} +
+ onChange(e.detail)} + {processFiles} + {deleteAttachments} + {handleFileTooLarge} + /> +
+{/if} + + diff --git a/packages/frontend-core/src/components/grid/cells/BooleanCell.svelte b/packages/frontend-core/src/components/grid/cells/BooleanCell.svelte new file mode 100644 index 0000000000..52aecb07a7 --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/BooleanCell.svelte @@ -0,0 +1,44 @@ + + +
+ +
+ + diff --git a/packages/frontend-core/src/components/grid/cells/DataCell.svelte b/packages/frontend-core/src/components/grid/cells/DataCell.svelte new file mode 100644 index 0000000000..d97edabc01 --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/DataCell.svelte @@ -0,0 +1,86 @@ + + + focusedCellId.set(cellId)} + on:contextmenu={e => menu.actions.open(cellId, e)} + width={column.width} +> + + diff --git a/packages/frontend-core/src/components/grid/cells/DateCell.svelte b/packages/frontend-core/src/components/grid/cells/DateCell.svelte new file mode 100644 index 0000000000..0112bcda15 --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/DateCell.svelte @@ -0,0 +1,77 @@ + + +
+
+ {#if value} + {dayjs(timeOnly ? time : value).format(format)} + {/if} +
+ {#if editable} + + {/if} +
+ +{#if editable} +
+ onChange(e.detail)} + appendTo={document.documentElement} + enableTime={!dateOnly} + {timeOnly} + time24hr + ignoreTimezones={schema.ignoreTimezones} + /> +
+{/if} + + diff --git a/packages/frontend-core/src/components/grid/cells/FormulaCell.svelte b/packages/frontend-core/src/components/grid/cells/FormulaCell.svelte new file mode 100644 index 0000000000..b4db795e44 --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/FormulaCell.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/frontend-core/src/components/grid/cells/GridCell.svelte b/packages/frontend-core/src/components/grid/cells/GridCell.svelte new file mode 100644 index 0000000000..52dbed641c --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/GridCell.svelte @@ -0,0 +1,159 @@ + + +
+ {#if error} +
+ {error} +
+ {/if} + + {#if selectedUser && !focused} +
+ {selectedUser.label} +
+ {/if} +
+ + diff --git a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte new file mode 100644 index 0000000000..890f314e2e --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte @@ -0,0 +1,237 @@ + + +
+ + +
+ {column.label} +
+ {#if sortedBy} +
+ +
+ {/if} +
(open = true)} + > + +
+
+
+ + + + + Edit column + + + Use as display column + + + Sort A-Z + + + Sort Z-A + + + Move left + + + Move right + + + + + diff --git a/packages/frontend-core/src/components/grid/cells/JSONCell.svelte b/packages/frontend-core/src/components/grid/cells/JSONCell.svelte new file mode 100644 index 0000000000..30803fd862 --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/JSONCell.svelte @@ -0,0 +1,36 @@ + + + diff --git a/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte b/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte new file mode 100644 index 0000000000..f41e206d1d --- /dev/null +++ b/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte @@ -0,0 +1,117 @@ + + +{#if isOpen} +