mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-03 12:53:58 +00:00
Add multi-row selection support with bulk editing
- Show "(Multiple values)" when selected rows have different values - Allow bulk editing: changes apply to all selected rows - Rename format to "Table - Row" for clarity
This commit is contained in:
@@ -23,17 +23,38 @@
|
|||||||
$: realColumnUniqueNames = selection?.realColumnUniqueNames || [];
|
$: realColumnUniqueNames = selection?.realColumnUniqueNames || [];
|
||||||
$: setCellValue = selection?.setCellValue;
|
$: setCellValue = selection?.setCellValue;
|
||||||
|
|
||||||
|
$: uniqueRows = _.uniqBy(selection || [], 'row');
|
||||||
|
$: isMultipleRows = uniqueRows.length > 1;
|
||||||
|
|
||||||
|
function areValuesEqual(val1, val2) {
|
||||||
|
if (val1 === val2) return true;
|
||||||
|
if (val1 == null && val2 == null) return true;
|
||||||
|
if (val1 == null || val2 == null) return false;
|
||||||
|
return _.isEqual(val1, val2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFieldValue(colName) {
|
||||||
|
if (!isMultipleRows) return { value: rowData?.[colName], hasMultipleValues: false };
|
||||||
|
|
||||||
|
const values = uniqueRows.map(sel => sel.rowData?.[colName]);
|
||||||
|
const firstValue = values[0];
|
||||||
|
const allSame = values.every(v => areValuesEqual(v, firstValue));
|
||||||
|
|
||||||
|
return allSame ? { value: firstValue, hasMultipleValues: false } : { value: null, hasMultipleValues: true };
|
||||||
|
}
|
||||||
|
|
||||||
let filter = '';
|
let filter = '';
|
||||||
|
|
||||||
$: orderedFields = realColumnUniqueNames
|
$: orderedFields = realColumnUniqueNames
|
||||||
.map(colName => {
|
.map(colName => {
|
||||||
const col = columns.find(c => c.uniqueName === colName);
|
const col = columns.find(c => c.uniqueName === colName);
|
||||||
if (!col) return null;
|
if (!col) return null;
|
||||||
const value = rowData?.[colName];
|
const { value, hasMultipleValues } = getFieldValue(colName);
|
||||||
return {
|
return {
|
||||||
columnName: col.columnName || colName,
|
columnName: col.columnName || colName,
|
||||||
uniqueName: colName,
|
uniqueName: colName,
|
||||||
value,
|
value,
|
||||||
|
hasMultipleValues,
|
||||||
col,
|
col,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
@@ -73,7 +94,7 @@
|
|||||||
|
|
||||||
function handleDoubleClick(field) {
|
function handleDoubleClick(field) {
|
||||||
if (!editable || !setCellValue) return;
|
if (!editable || !setCellValue) return;
|
||||||
if (isJsonValue(field.value)) {
|
if (isJsonValue(field.value) && !field.hasMultipleValues) {
|
||||||
openEditModal(field);
|
openEditModal(field);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -83,12 +104,12 @@
|
|||||||
function startEditing(field) {
|
function startEditing(field) {
|
||||||
if (!editable || !setCellValue) return;
|
if (!editable || !setCellValue) return;
|
||||||
editingColumn = field.uniqueName;
|
editingColumn = field.uniqueName;
|
||||||
editValue = stringifyCellValue(field.value, 'inlineEditorIntent', editorTypes).value;
|
editValue = field.hasMultipleValues ? '' : stringifyCellValue(field.value, 'inlineEditorIntent', editorTypes).value;
|
||||||
isChangedRef.set(false);
|
isChangedRef.set(false);
|
||||||
tick().then(() => {
|
tick().then(() => {
|
||||||
if (!domEditor) return;
|
if (!domEditor) return;
|
||||||
domEditor.focus();
|
domEditor.focus();
|
||||||
domEditor.select();
|
if (!field.hasMultipleValues) domEditor.select();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +227,7 @@
|
|||||||
on:blur={() => handleBlur(field)}
|
on:blur={() => handleBlur(field)}
|
||||||
class="inline-editor"
|
class="inline-editor"
|
||||||
/>
|
/>
|
||||||
{#if editable}
|
{#if editable && !field.hasMultipleValues}
|
||||||
<ShowFormButton
|
<ShowFormButton
|
||||||
icon="icon edit"
|
icon="icon edit"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
@@ -216,6 +237,8 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{:else if field.hasMultipleValues}
|
||||||
|
<span class="multiple-values">(Multiple values)</span>
|
||||||
{:else}
|
{:else}
|
||||||
<CellValue
|
<CellValue
|
||||||
{rowData}
|
{rowData}
|
||||||
@@ -313,4 +336,9 @@
|
|||||||
.inline-editor:focus {
|
.inline-editor:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.multiple-values {
|
||||||
|
color: var(--theme-font-3);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1269,8 +1269,14 @@
|
|||||||
res.realColumnUniqueNames = realColumnUniqueNames;
|
res.realColumnUniqueNames = realColumnUniqueNames;
|
||||||
|
|
||||||
if (res.length > 0) {
|
if (res.length > 0) {
|
||||||
const firstRow = res[0].row;
|
const uniqueRowIndices = _.uniq(res.map(x => x.row));
|
||||||
res.setCellValue = (columnName, value) => grider.setCellValue(firstRow, columnName, value);
|
res.setCellValue = (columnName, value) => {
|
||||||
|
grider.beginUpdate();
|
||||||
|
for (const row of uniqueRowIndices) {
|
||||||
|
grider.setCellValue(row, columnName, value);
|
||||||
|
}
|
||||||
|
grider.endUpdate();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'table',
|
type: 'table',
|
||||||
title: 'Table',
|
title: 'Table - Row',
|
||||||
component: TableCellView,
|
component: TableCellView,
|
||||||
single: false,
|
single: false,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user