1
0
Fork 0
mirror of synced 2024-09-15 08:47:37 +12:00

Add inline editing of options fields

This commit is contained in:
Andrew Kingston 2022-11-24 19:28:55 +00:00
parent b19a2a3d3a
commit 6471464971
2 changed files with 115 additions and 14 deletions

View file

@ -1,7 +1,12 @@
<script>
import { Icon } from "@budibase/bbui"
export let value
export let schema
export let selected = false
export let onChange
const options = schema?.constraints?.inclusion || []
const colors = [
"rgb(207, 223, 255)",
"rgb(208, 240, 253)",
@ -14,26 +19,116 @@
"rgb(237, 226, 254)",
]
$: idx = schema?.constraints?.inclusion?.indexOf(value)
$: color = value && idx === -1 ? null : colors[idx % colors.length]
let open = false
$: color = getColor(value)
$: {
// Close when deselected
if (!selected) {
open = false
}
}
const getColor = value => {
const index = options.indexOf(value)
if (!value || index === -1) {
return null
}
return colors[index % colors.length]
}
const toggle = () => {
open = !open
}
</script>
<div style="--color: {color}" class:valid={!!color}>
{value || ""}
<div
class="container"
class:selected
class:open
on:click={selected ? toggle : null}
>
{#if color}
<div class="badge text" style="--color: {color}">
{value}
</div>
{:else if value}
<div class="text">
{value}
</div>
{/if}
{#if selected}
<Icon name="ChevronDown" />
{/if}
{#if open}
<div class="options">
<div class="option">
<div class="badge text" style="--color: {color}">
{value}
</div>
<Icon name="Checkmark" color="var(--spectrum-global-color-blue-400)" />
</div>
{#each options.filter(x => x !== value) as option}
<div class="option" on:click={() => onChange(option)}>
<div class="badge text" style="--color: {getColor(option)}">
{option}
</div>
</div>
{/each}
</div>
{/if}
</div>
<style>
div {
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 0 8px;
flex: 1 1 auto;
overflow: hidden;
gap: 4px;
}
.container.selected:hover {
cursor: pointer;
}
.text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div.valid {
margin: 0 8px;
.badge {
padding: 2px 8px;
background: var(--color);
border-radius: 8px;
color: #333;
color: #2c2c2c;
user-select: none;
}
.options {
min-width: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.15);
border-radius: 4px;
max-height: 192px;
overflow-y: auto;
}
.option {
flex: 0 0 32px;
padding: 0 8px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
background-color: var(--spectrum-global-color-gray-50);
}
.option:hover {
background-color: var(--spectrum-global-color-gray-100);
}
</style>

View file

@ -106,17 +106,18 @@
}
const handleChange = async (rowId, field, value) => {
selectedCell = null
let row = $fetch.rows.find(x => x._id === rowId)
if (!row) {
return
}
const newRow = {
...row,
[field]: value,
if (row[field] === value) {
return
}
changeCache[rowId] = { [field]: value }
await API.saveRow(newRow)
await API.saveRow({
...row,
...changeCache[rowId],
})
await fetch.refresh()
delete changeCache[rowId]
}
@ -237,6 +238,7 @@
justify-content: flex-start;
align-items: stretch;
border: 1px solid var(--spectrum-global-color-gray-400);
border-radius: 4px;
}
.spreadsheet {
display: grid;
@ -294,12 +296,13 @@
font-size: 14px;
gap: 4px;
background: var(--spectrum-global-color-gray-50);
position: relative;
}
.cell.hovered {
background: var(--spectrum-global-color-gray-100);
}
.cell.selected {
box-shadow: inset 0 0 0 2px rgb(89, 167, 246);
box-shadow: inset 0 0 0 2px var(--spectrum-global-color-blue-400);
z-index: 1;
}
.cell:hover {
@ -310,6 +313,9 @@
left: 50px;
z-index: 2;
}
.cell.sticky.selected {
z-index: 3;
}
.cell.row-selected {
background-color: rgb(224, 242, 255);
}