From e26163e274bfb3e0080181e4ce91ad00668ee564 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 20 Feb 2023 19:04:22 +0000 Subject: [PATCH] Add support for multiselect type --- .../app/spreadsheet/MultiSelectCell.svelte | 5 ++ .../app/spreadsheet/OptionsCell.svelte | 68 +++++++++++++------ .../app/spreadsheet/Spreadsheet.svelte | 50 ++++++-------- 3 files changed, 74 insertions(+), 49 deletions(-) diff --git a/packages/client/src/components/app/spreadsheet/MultiSelectCell.svelte b/packages/client/src/components/app/spreadsheet/MultiSelectCell.svelte index e69de29bb2..77eb95c9e7 100644 --- a/packages/client/src/components/app/spreadsheet/MultiSelectCell.svelte +++ b/packages/client/src/components/app/spreadsheet/MultiSelectCell.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/client/src/components/app/spreadsheet/OptionsCell.svelte b/packages/client/src/components/app/spreadsheet/OptionsCell.svelte index a39556c140..08c7699f62 100644 --- a/packages/client/src/components/app/spreadsheet/OptionsCell.svelte +++ b/packages/client/src/components/app/spreadsheet/OptionsCell.svelte @@ -5,12 +5,14 @@ export let schema export let selected = false export let onChange + export let multi = false const options = schema?.constraints?.inclusion || [] let open = false - $: color = getColor(value) + $: values = Array.isArray(value) ? value : [value].filter(x => x != null) + $: unselectedOptions = options.filter(x => !values.includes(x)) $: { // Close when deselected if (!selected) { @@ -26,44 +28,59 @@ return `hsla(${((index + 1) * 222) % 360}, 90%, 75%, 0.3)` } - const toggle = () => { - open = !open + const toggleOption = option => { + if (!multi) { + onChange(option) + } else { + if (values.includes(option)) { + onChange(values.filter(x => x !== option)) + } else { + onChange([...values, option]) + } + } }
(open = true) : null} > - {#if color} -
- {value} -
- {:else} -
- {value || ""} -
- {/if} +
+ {#each values as val (val)} + {@const color = getColor(val)} + {#if color} +
+ {val} +
+ {:else} +
+ {val || ""} +
+ {/if} + {/each} +
{#if selected} {/if} {#if open}
- {#if value} -
+ {#each values as val (val)} + {@const color = getColor(val)} +
toggleOption(val)}>
- {value} + {val}
- {/if} - {#each options.filter(x => x !== value) as option} -
onChange(option)}> + {/each} + {#each unselectedOptions as option (option)} +
toggleOption(option)}>
{option}
@@ -87,11 +104,24 @@ .container.selected:hover { cursor: pointer; } + .values { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + flex: 1 1 auto; + width: 0; + gap: 4px; + overflow: hidden; + } .text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .multi .text { + flex: 0 0 auto; + } .badge { padding: 2px 8px; background: var(--color); diff --git a/packages/client/src/components/app/spreadsheet/Spreadsheet.svelte b/packages/client/src/components/app/spreadsheet/Spreadsheet.svelte index b4437bc8e9..e20e5879ff 100644 --- a/packages/client/src/components/app/spreadsheet/Spreadsheet.svelte +++ b/packages/client/src/components/app/spreadsheet/Spreadsheet.svelte @@ -5,6 +5,7 @@ import TextCell from "./TextCell.svelte" import OptionsCell from "./OptionsCell.svelte" import DateCell from "./DateCell.svelte" + import MultiSelectCell from "./MultiSelectCell.svelte" export let table export let filter @@ -15,7 +16,7 @@ getContext("sdk") const component = getContext("component") const limit = 100 - const defaultWidth = 200 + const defaultWidth = 160 const minWidth = 100 let widths @@ -36,7 +37,6 @@ }) $: fields = Object.keys($fetch.schema || {}) $: initWidths(fields) - $: sliderPositions = getSliderPositions(widths) $: gridStyles = getGridStyles(widths) $: schema = $fetch.schema $: rowCount = $fetch.rows?.length || 0 @@ -65,14 +65,7 @@ if (!widths?.length) { return "--grid: 1fr;" } - return `--grid: 50px ${widths.map(x => `${x}px`).join(" ")} 180px;` - } - - const getSliderPositions = widths => { - let offset = 50 - return widths.map(width => { - return (offset += width) - }) + return `--grid: 40px ${widths.map(x => `${x}px`).join(" ")} 180px;` } const handleScroll = e => { @@ -88,6 +81,8 @@ return OptionsCell } else if (type === "datetime") { return DateCell + } else if (type === "array") { + return MultiSelectCell } return TextCell } @@ -262,20 +257,12 @@ {field} +
startResizing(fieldIdx, e)} />
{/each}
- - {#each sliderPositions as left, idx} -
startResizing(idx, e)} - style="--left: {left}px" - /> - {/each} - {#each rows as row, rowIdx (row._id)} {@const rowSelected = !!selectedRows[row._id]} @@ -368,7 +355,7 @@ justify-content: flex-start; align-items: stretch; overflow: auto; - max-height: 800px; + max-height: 600px; position: relative; cursor: default; } @@ -444,7 +431,7 @@ } .cell.sticky { position: sticky; - left: 50px; + left: 40px; z-index: 2; } .cell.sticky.selected { @@ -479,25 +466,28 @@ /* Column resizing */ .slider { position: absolute; - z-index: 5; - left: var(--left); top: 0; + right: 0; width: 16px; - height: 32px; - transform: translateX(-50%); + height: 100%; } - .slider:hover:after { + .slider:after { + opacity: 0; content: " "; position: absolute; - width: 2px; - left: 50%; + width: 4px; + right: 0; + top: 0; height: 100%; - background: var(--spectrum-global-color-blue-400); - transform: translateX(-50%); + background: var(--spectrum-global-color-gray-600); + transition: opacity 130ms ease-out; } .slider:hover { cursor: col-resize; } + .slider:hover:after { + opacity: 1; + } .sticky.shadow:after { content: " ";