diff --git a/packages/datalib/src/ChangeSet.ts b/packages/datalib/src/ChangeSet.ts index a063bb160..a46f5935e 100644 --- a/packages/datalib/src/ChangeSet.ts +++ b/packages/datalib/src/ChangeSet.ts @@ -390,6 +390,25 @@ export function changeSetInsertNewRow(changeSet: ChangeSet, name?: NamedObjectIn }; } +export function changeSetInsertDocuments( + changeSet: ChangeSet, + documents: any[], + name?: NamedObjectInfo +): ChangeSet { + const insertedRows = getChangeSetInsertedRows(changeSet, name); + return { + ...changeSet, + inserts: [ + ...changeSet.inserts, + ...documents.map((doc, index) => ({ + ...name, + insertedRowIndex: insertedRows.length + index, + fields: doc, + })), + ], + }; +} + export function changeSetContainsChanges(changeSet: ChangeSet) { if (!changeSet) return false; return changeSet.deletes.length > 0 || changeSet.updates.length > 0 || changeSet.inserts.length > 0; diff --git a/packages/datalib/src/CollectionGridDisplay.ts b/packages/datalib/src/CollectionGridDisplay.ts index 133490238..74dfe747d 100644 --- a/packages/datalib/src/CollectionGridDisplay.ts +++ b/packages/datalib/src/CollectionGridDisplay.ts @@ -98,8 +98,9 @@ export class CollectionGridDisplay extends GridDisplay { changeSet ) { super(config, setConfig, cache, setCache, driver); - const changedDocs = _.compact([...changeSet.inserts, ...changeSet.updates].map(chs => chs.document)); - this.columns = analyseCollectionDisplayColumns([...(loadedRows || []), ...changedDocs], this); + const changedDocs = _.compact(changeSet.updates.map(chs => chs.document)); + const insertedDocs = _.compact(changeSet.inserts.map(chs => chs.fields)); + this.columns = analyseCollectionDisplayColumns([...(loadedRows || []), ...changedDocs, ...insertedDocs], this); this.filterable = true; this.sortable = true; this.editable = true; diff --git a/packages/web/src/datagrid/ChangeSetGrider.ts b/packages/web/src/datagrid/ChangeSetGrider.ts index 591a9d984..b74b8d3f0 100644 --- a/packages/web/src/datagrid/ChangeSetGrider.ts +++ b/packages/web/src/datagrid/ChangeSetGrider.ts @@ -14,6 +14,7 @@ import { setChangeSetRowData, compileMacroFunction, runMacroOnValue, + changeSetInsertDocuments, } from 'dbgate-datalib'; import Grider, { GriderRowStatus } from './Grider'; @@ -181,6 +182,12 @@ export default class ChangeSetGrider extends Grider { return res; } + insertDocuments(documents: any[]): number { + const res = this.rowCountInUpdate; + this.applyModification(chs => changeSetInsertDocuments(chs, documents, this.display.baseTableOrCollection)); + return res; + } + beginUpdate() { this.batchChangeSet = this.changeSet; } diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index da193a886..6cbec73cc 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -1094,7 +1094,7 @@ return [row, col]; } - function handlePaste(event) { + async function handlePaste(event) { var pastedText = undefined; // @ts-ignore if (window.clipboardData && window.clipboardData.getData) { @@ -1105,41 +1105,62 @@ pastedText = event.clipboardData.getData('text/plain'); } event.preventDefault(); - grider.beginUpdate(); - const pasteRows = pastedText - .replace(/\r/g, '') - .split('\n') - .map(row => row.split('\t')); - const selectedRegular = cellsToRegularCells(selectedCells); - if (selectedRegular.length <= 1) { - const startRow = isRegularCell(currentCell) ? currentCell[0] : grider.rowCount; - const startCol = isRegularCell(currentCell) ? currentCell[1] : 0; - let rowIndex = startRow; - for (const rowData of pasteRows) { - if (rowIndex >= grider.rowCountInUpdate) { - grider.insertRow(); - } - let colIndex = startCol; - for (const cell of rowData) { - setCellValue([rowIndex, colIndex], cell == '(NULL)' ? null : cell); - colIndex += 1; - } - rowIndex += 1; + + let json = null; + if (grider.canInsert) { + try { + json = JSON.parse(pastedText); + } catch (e) { + json = null; } } - if (selectedRegular.length > 1) { - const startRow: number = _.min(selectedRegular.map(x => x[0])); - const startCol: number = _.min(selectedRegular.map(x => x[1])); - for (const cell of selectedRegular) { - const [rowIndex, colIndex] = cell; - const selectionRow = rowIndex - startRow; - const selectionCol = colIndex - startCol; - const pasteRow = pasteRows[selectionRow % pasteRows.length]; - const pasteCell = pasteRow[selectionCol % pasteRow.length]; - setCellValue(cell, pasteCell); + + if (json && (_.isArray(json) || _.isPlainObject(json))) { + const rowIndex = grider.insertDocuments(_.isArray(json) ? json : [json]); + const cell = [rowIndex, (currentCell && currentCell[1]) || 0]; + // @ts-ignore + currentCell = cell; + // @ts-ignore + selectedCells = [cell]; + await tick(); + scrollIntoView(cell); + } else { + grider.beginUpdate(); + const pasteRows = pastedText + .replace(/\r/g, '') + .split('\n') + .map(row => row.split('\t')); + const selectedRegular = cellsToRegularCells(selectedCells); + if (selectedRegular.length <= 1) { + const startRow = isRegularCell(currentCell) ? currentCell[0] : grider.rowCount; + const startCol = isRegularCell(currentCell) ? currentCell[1] : 0; + let rowIndex = startRow; + for (const rowData of pasteRows) { + if (rowIndex >= grider.rowCountInUpdate) { + grider.insertRow(); + } + let colIndex = startCol; + for (const cell of rowData) { + setCellValue([rowIndex, colIndex], cell == '(NULL)' ? null : cell); + colIndex += 1; + } + rowIndex += 1; + } } + if (selectedRegular.length > 1) { + const startRow: number = _.min(selectedRegular.map(x => x[0])); + const startCol: number = _.min(selectedRegular.map(x => x[1])); + for (const cell of selectedRegular) { + const [rowIndex, colIndex] = cell; + const selectionRow = rowIndex - startRow; + const selectionCol = colIndex - startCol; + const pasteRow = pasteRows[selectionRow % pasteRows.length]; + const pasteCell = pasteRow[selectionCol % pasteRow.length]; + setCellValue(cell, pasteCell); + } + } + grider.endUpdate(); } - grider.endUpdate(); } function cellsToRegularCells(cells) { @@ -1296,7 +1317,7 @@ {:else if isDynamicStructure && isLoadedAll && grider?.rowCount == 0}
- + {#if display.filterCount > 0} display.clearFilters()} /> {/if} diff --git a/packages/web/src/datagrid/Grider.ts b/packages/web/src/datagrid/Grider.ts index 0f24aeea4..698023b39 100644 --- a/packages/web/src/datagrid/Grider.ts +++ b/packages/web/src/datagrid/Grider.ts @@ -22,6 +22,9 @@ export default abstract class Grider { insertRow(): number { return null; } + insertDocuments(documents: any[]): number { + return null; + } revertRowChanges(index: number) {} revertAllChanges() {} undo() {} diff --git a/packages/web/src/freetable/FreeTableGrider.ts b/packages/web/src/freetable/FreeTableGrider.ts index 008112327..c005b678a 100644 --- a/packages/web/src/freetable/FreeTableGrider.ts +++ b/packages/web/src/freetable/FreeTableGrider.ts @@ -47,6 +47,15 @@ export default class FreeTableGrider extends Grider { }; return this.currentModel.rows.length - 1; } + insertDocuments(documents: any[]): number { + const model = this.currentModel; + this.currentModel = { + ...model, + rows: [...model.rows, ...documents], + }; + return this.currentModel.rows.length - documents.length; + } + deleteRow(index: number) { const model = this.currentModel; this.currentModel = { diff --git a/packages/web/src/tabs/CollectionDataTab.svelte b/packages/web/src/tabs/CollectionDataTab.svelte index 73dd2da66..3d04ad48f 100644 --- a/packages/web/src/tabs/CollectionDataTab.svelte +++ b/packages/web/src/tabs/CollectionDataTab.svelte @@ -56,6 +56,7 @@ import EditJsonModal from '../modals/EditJsonModal.svelte'; import ChangeSetGrider from '../datagrid/ChangeSetGrider'; import { setContext } from 'svelte'; + import _ from 'lodash'; export let tabid; export let conid; @@ -139,8 +140,7 @@ json: {}, onSave: value => { const grider = new ChangeSetGrider(loadedRows, $changeSetStore, dispatchChangeSet, display); - const newRowIndex = grider.insertRow(); - grider.setRowData(newRowIndex, value); + grider.insertDocuments(_.isArray(value) ? value : [value]); return true; }, });