1
0
Fork 0
mirror of synced 2024-09-09 06:01:08 +12:00

Allow expanding rows using existing edit row modal

This commit is contained in:
Andrew Kingston 2023-03-30 16:12:28 +01:00
parent 5640b2fa89
commit 7570c52879
8 changed files with 109 additions and 71 deletions

View file

@ -23,9 +23,9 @@
async function saveRow() { async function saveRow() {
errors = [] errors = []
try { try {
await API.saveRow({ ...row, tableId: table._id }) const res = await API.saveRow({ ...row, tableId: table._id })
notifications.success("Row saved successfully") notifications.success("Row saved successfully")
dispatch("updaterows") dispatch("updaterows", res._id)
} catch (error) { } catch (error) {
if (error.handled) { if (error.handled) {
const response = error.json const response = error.json

View file

@ -2,13 +2,27 @@
import CreateEditRow from "../../modals/CreateEditRow.svelte" import CreateEditRow from "../../modals/CreateEditRow.svelte"
import { getContext, onMount } from "svelte" import { getContext, onMount } from "svelte"
import { Modal } from "@budibase/bbui" import { Modal } from "@budibase/bbui"
import { cloneDeep } from "lodash/fp"
const { subscribe } = getContext("sheet") const { subscribe, rows } = getContext("sheet")
let modal let modal
onMount(() => subscribe("add-row", modal.show)) let row
onMount(() =>
subscribe("add-row", () => {
row = {}
modal.show()
})
)
onMount(() =>
subscribe("edit-row", rowToEdit => {
row = cloneDeep(rowToEdit)
modal.show()
})
)
</script> </script>
<Modal bind:this={modal}> <Modal bind:this={modal}>
<CreateEditRow /> <CreateEditRow {row} on:updaterows={e => rows.actions.refreshRow(e.detail)} />
</Modal> </Modal>

View file

@ -27,7 +27,6 @@
import { clickOutside } from "@budibase/bbui" import { clickOutside } from "@budibase/bbui"
import AddRowButton from "../controls/AddRowButton.svelte" import AddRowButton from "../controls/AddRowButton.svelte"
import SheetControls from "./SheetControls.svelte" import SheetControls from "./SheetControls.svelte"
import SidePanel from "./SidePanel.svelte"
export let API export let API
export let tableId export let tableId
@ -35,19 +34,21 @@
export let allowSelectRows = true export let allowSelectRows = true
export let allowAddColumns = true export let allowAddColumns = true
export let allowEditColumns = true export let allowEditColumns = true
export let allowExpandRows = true
// Sheet constants // Sheet constants
const cellHeight = 36 const cellHeight = 36
const gutterWidth = 80 const gutterWidth = 72
const rand = Math.random() const rand = Math.random()
// State stores // State stores
const tableIdStore = writable(tableId)
const config = writable({ const config = writable({
tableId,
allowAddRows, allowAddRows,
allowSelectRows, allowSelectRows,
allowAddColumns, allowAddColumns,
allowEditColumns, allowEditColumns,
allowExpandRows,
}) })
// Build up spreadsheet context // Build up spreadsheet context
@ -58,6 +59,7 @@
cellHeight, cellHeight,
gutterWidth, gutterWidth,
config, config,
tableId: tableIdStore,
} }
context = { ...context, ...createEventManagers() } context = { ...context, ...createEventManagers() }
context = { ...context, ...createBoundsStores(context) } context = { ...context, ...createBoundsStores(context) }
@ -76,13 +78,14 @@
// Reference some stores for local use // Reference some stores for local use
const { isResizing, isReordering, ui, loaded } = context const { isResizing, isReordering, ui, loaded } = context
// Keep config store up to date // Keep stores up to date
$: tableIdStore.set(tableId)
$: config.set({ $: config.set({
tableId,
allowAddRows, allowAddRows,
allowSelectRows, allowSelectRows,
allowAddColumns, allowAddColumns,
allowEditColumns, allowEditColumns,
allowExpandRows,
}) })
// Set context for children to consume // Set context for children to consume
@ -127,7 +130,6 @@
{/if} {/if}
</div> </div>
{/if} {/if}
<SidePanel />
<KeyboardManager /> <KeyboardManager />
</div> </div>

View file

@ -1,20 +0,0 @@
<script>
import { getContext } from "svelte"
const { sidePanelRowId } = getContext("sheet")
$: visible = $sidePanelRowId != null
</script>
<div class="side-panel" class:visible>some content</div>
<style>
.side-panel {
width: 320px;
transform: translateX(100%);
transition: transform 130ms ease-out;
}
.side-panel.visible {
transform: translateX(0);
}
</style>

View file

@ -1,6 +1,6 @@
<script> <script>
import { getContext } from "svelte" import { getContext } from "svelte"
import { Checkbox } from "@budibase/bbui" import { Checkbox, Icon } from "@budibase/bbui"
import SheetCell from "../cells/SheetCell.svelte" import SheetCell from "../cells/SheetCell.svelte"
import DataCell from "../cells/DataCell.svelte" import DataCell from "../cells/DataCell.svelte"
import SheetScrollWrapper from "./SheetScrollWrapper.svelte" import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
@ -19,6 +19,7 @@
selectedCellMap, selectedCellMap,
selectedCellRow, selectedCellRow,
gutterWidth, gutterWidth,
dispatch,
} = getContext("sheet") } = getContext("sheet")
$: scrollLeft = $scroll.left $: scrollLeft = $scroll.left
@ -59,17 +60,24 @@
class:scrolled={scrollLeft > 0} class:scrolled={scrollLeft > 0}
> >
<div class="header row"> <div class="header row">
<SheetCell <SheetCell width={gutterWidth}>
width={gutterWidth} <div class="gutter">
on:click={$config.allowSelectRows && selectAll} <div class="checkbox visible">
center {#if $config.allowSelectRows}
> <div on:click={$config.allowSelectRows && selectAll}>
{#if $config.allowSelectRows} <Checkbox
<Checkbox value={rowCount && selectedRowCount === rowCount}
value={rowCount && selectedRowCount === rowCount} disabled={!$renderedRows.length}
disabled={!$renderedRows.length} />
/> </div>
{/if} {/if}
</div>
{#if $config.allowExpandRows}
<div class="expand">
<Icon name="Maximize" size="S" />
</div>
{/if}
</div>
</SheetCell> </SheetCell>
{#if $stickyColumn} {#if $stickyColumn}
@ -89,25 +97,41 @@
on:mouseleave={() => ($hoveredRowId = null)} on:mouseleave={() => ($hoveredRowId = null)}
> >
<SheetCell <SheetCell
width={gutterWidth}
rowSelected={rowSelected || containsSelectedRow} rowSelected={rowSelected || containsSelectedRow}
{rowHovered} {rowHovered}
width={gutterWidth}
center
> >
<div <div class="gutter">
on:click={() => selectRow(row._id)} <div
class="checkbox" on:click={() => selectRow(row._id)}
class:visible={$config.allowSelectRows && class="checkbox"
(rowSelected || rowHovered)} class:visible={$config.allowSelectRows &&
> (rowSelected || rowHovered || containsSelectedRow)}
<Checkbox value={rowSelected} /> >
</div> <Checkbox value={rowSelected} />
<div </div>
class="number" <div
class:visible={!$config.allowSelectRows || class="number"
!(rowSelected || rowHovered)} class:visible={!$config.allowSelectRows ||
> !(rowSelected || rowHovered || containsSelectedRow)}
{row.__idx + 1} >
{row.__idx + 1}
</div>
{#if $config.allowExpandRows}
<div
class="expand"
class:visible={containsSelectedRow || rowHovered}
>
<Icon
name="Maximize"
hoverable
size="S"
on:click={() => {
dispatch("edit-row", row)
}}
/>
</div>
{/if}
</div> </div>
</SheetCell> </SheetCell>
@ -172,20 +196,35 @@
flex: 1 1 auto; flex: 1 1 auto;
} }
/* Styles for label cell */ /* Styles for gutter */
.gutter {
flex: 1 1 auto;
display: grid;
align-items: center;
padding: var(--cell-padding);
grid-template-columns: 1fr auto;
gap: var(--cell-spacing);
}
.checkbox, .checkbox,
.number { .number {
padding: 0 var(--cell-padding);
}
.checkbox {
display: none; display: none;
flex-direction: row;
justify-content: center;
align-items: center;
} }
.number { .number {
display: none;
color: var(--spectrum-global-color-gray-500); color: var(--spectrum-global-color-gray-500);
} }
.checkbox.visible, .checkbox.visible,
.number.visible { .number.visible {
display: flex; display: flex;
} }
.expand {
opacity: 0;
pointer-events: none;
}
.expand.visible {
opacity: 1;
pointer-events: all;
}
</style> </style>

View file

@ -1,9 +1,8 @@
import { derived, get } from "svelte/store" import { get } from "svelte/store"
import { io } from "socket.io-client" import { io } from "socket.io-client"
export const createWebsocket = context => { export const createWebsocket = context => {
const { rows, config, users, userId, selectedCellId } = context const { rows, tableId, users, userId, selectedCellId } = context
const tableId = derived(config, $config => $config.tableId)
// Determine connection info // Determine connection info
const tls = location.protocol === "https:" const tls = location.protocol === "https:"

View file

@ -3,8 +3,7 @@ import { fetchData } from "../../../fetch/fetchData"
import { notifications } from "@budibase/bbui" import { notifications } from "@budibase/bbui"
export const createRowsStore = context => { export const createRowsStore = context => {
const { config, API, scroll } = context const { tableId, API, scroll } = context
const tableId = derived(config, $config => $config.tableId)
const rows = writable([]) const rows = writable([])
const table = writable(null) const table = writable(null)
const filter = writable([]) const filter = writable([])
@ -115,6 +114,12 @@ export const createRowsStore = context => {
}) })
}) })
// Gets a row by ID
const getRow = id => {
const index = get(rowLookupMap)[id]
return index >= 0 ? get(enrichedRows)[index] : null
}
// Adds a new empty row // Adds a new empty row
const addRow = async (row, idx) => { const addRow = async (row, idx) => {
try { try {
@ -281,6 +286,7 @@ export const createRowsStore = context => {
subscribe: enrichedRows.subscribe, subscribe: enrichedRows.subscribe,
actions: { actions: {
addRow, addRow,
getRow,
updateRow, updateRow,
deleteRows, deleteRows,
hasRow, hasRow,

View file

@ -6,7 +6,6 @@ export const createUIStores = context => {
const selectedRows = writable({}) const selectedRows = writable({})
const hoveredRowId = writable(null) const hoveredRowId = writable(null)
const selectedCellAPI = writable(null) const selectedCellAPI = writable(null)
const sidePanelRowId = writable(null)
// Derive the row that contains the selected cell. // Derive the row that contains the selected cell.
const selectedCellRow = derived( const selectedCellRow = derived(
@ -93,7 +92,6 @@ export const createUIStores = context => {
hoveredRowId, hoveredRowId,
selectedCellRow, selectedCellRow,
selectedCellAPI, selectedCellAPI,
sidePanelRowId,
ui: { ui: {
actions: { actions: {
blur, blur,