From 70999b176b21b675002285d173f7cd28247859c4 Mon Sep 17 00:00:00 2001 From: sadakchap Date: Wed, 5 May 2021 17:08:16 +0530 Subject: [PATCH 01/21] disabled clone rows option for standard classes --- src/dashboard/Data/Browser/BrowserToolbar.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js index 017ac7573b..5e134a0348 100644 --- a/src/dashboard/Data/Browser/BrowserToolbar.react.js +++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js @@ -122,7 +122,7 @@ let BrowserToolbar = ({ /> From 326b0e8ec727d3a58ca2f918aae8d2520b0e98ee Mon Sep 17 00:00:00 2001 From: sadakchap Date: Wed, 5 May 2021 17:09:02 +0530 Subject: [PATCH 02/21] providing a way to edit clone rows on error 137 --- src/dashboard/Data/Browser/Browser.react.js | 37 ++++++++++++-- .../Data/Browser/BrowserTable.react.js | 50 +++++++++++++++++++ 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index cc0b596d1f..de23cde5a9 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -71,6 +71,7 @@ class Browser extends DashboardView { data: null, lastMax: -1, newObject: null, + editCloneRows: null, lastError: null, lastNote: null, @@ -121,6 +122,7 @@ class Browser extends DashboardView { this.closeEditRowDialog = this.closeEditRowDialog.bind(this); this.handleShowAcl = this.handleShowAcl.bind(this); this.onDialogToggle = this.onDialogToggle.bind(this); + this.addEditCloneRows = this.addEditCloneRows.bind(this); } componentWillMount() { @@ -300,6 +302,12 @@ class Browser extends DashboardView { this.showEditRowDialog(); } + addEditCloneRows(cloneRows) { + this.setState({ + editCloneRows: cloneRows + }); + } + removeColumn(name) { let payload = { className: this.props.params.className, @@ -330,6 +338,7 @@ class Browser extends DashboardView { newObject: null, lastMax: -1, selection: {}, + editCloneRows: null, }; if (relation) { await this.setState(initialState); @@ -529,8 +538,12 @@ class Browser extends DashboardView { } updateRow(row, attr, value) { - const isNewObject = row < 0; - const obj = isNewObject ? this.state.newObject : this.state.data[row]; + let isNewObject = row === -1; + let isEditCloneObj = row < -1; + let obj = isNewObject ? this.state.newObject : this.state.data[row]; + if(isEditCloneObj){ + obj = this.state.editCloneRows[row + (this.state.editCloneRows.length + 1)]; + } if (!obj) { return; } @@ -544,11 +557,11 @@ class Browser extends DashboardView { obj.set(attr, value); } obj.save(null, { useMasterKey: true }).then((objectSaved) => { - const createdOrUpdated = isNewObject ? 'created' : 'updated'; + const createdOrUpdated = isNewObject || isEditCloneObj ? 'created' : 'updated'; let msg = objectSaved.className + ' with id \'' + objectSaved.id + '\' ' + createdOrUpdated; this.showNote(msg, false); - const state = { data: this.state.data }; + const state = { data: this.state.data, editCloneRows: this.state.editCloneRows }; if (isNewObject) { const relation = this.state.relation; @@ -587,13 +600,23 @@ class Browser extends DashboardView { this.state.counts[obj.className] += 1; } } + if (isEditCloneObj) { + state.editCloneRows = state.editCloneRows.filter( + cloneObj => cloneObj._localId !== obj._localId + ); + if (state.editCloneRows.length === 0) state.editCloneRows = null; + if (this.props.params.className === obj.className) { + this.state.data.unshift(obj); + } + this.state.counts[obj.className] += 1; + } this.setState(state); }, (error) => { let msg = typeof error === 'string' ? error : error.message; if (msg) { msg = msg[0].toUpperCase() + msg.substr(1); } - if (!isNewObject) { + if (!isNewObject && !isEditCloneObj) { obj.set(attr, prev); this.setState({ data: this.state.data }); } @@ -829,6 +852,9 @@ class Browser extends DashboardView { showCloneSelectedRowsDialog: false }); } catch (error) { + if(error.code === 137){ + this.addEditCloneRows(toClone); + } this.setState({ selection: {}, showCloneSelectedRowsDialog: false @@ -1023,6 +1049,7 @@ class Browser extends DashboardView { data={this.state.data} ordering={this.state.ordering} newObject={this.state.newObject} + editCloneRows={this.state.editCloneRows} relation={this.state.relation} disableKeyControls={this.hasExtras()} updateRow={this.updateRow} diff --git a/src/dashboard/Data/Browser/BrowserTable.react.js b/src/dashboard/Data/Browser/BrowserTable.react.js index dc1b5bef30..8415109e46 100644 --- a/src/dashboard/Data/Browser/BrowserTable.react.js +++ b/src/dashboard/Data/Browser/BrowserTable.react.js @@ -115,6 +115,46 @@ export default class BrowserTable extends React.Component { (rowWidth, { visible, width }) => visible ? rowWidth + width : rowWidth, this.props.onAddRow ? 210 : 0 ); + let editCloneRows = null; + if(this.props.editCloneRows){ + editCloneRows = ( +
+ {this.props.editCloneRows.map((cloneRow, idx) => { + let index = (this.props.editCloneRows.length + 1) * -1 + idx; + const currentCol = this.props.current && this.props.current.row === index ? this.props.current.col : undefined; + const isEditingRow = this.props.current && this.props.current.row === index && !!this.props.editing; + return ( + + ); + })} +
+ ) + } let newRow = null; if (this.props.newObject && this.state.offset <= 0) { const currentCol = this.props.current && this.props.current.row === -1 ? this.props.current.col : undefined; @@ -205,6 +245,9 @@ export default class BrowserTable extends React.Component { } let obj = this.props.current.row < 0 ? this.props.newObject : this.props.data[this.props.current.row]; let value = obj; + if(!obj && this.props.current.row < -1){ + obj = this.props.editCloneRows[this.props.current.row + this.props.editCloneRows.length + 1]; + } if (!this.props.isUnique) { if (type === 'Array' || type === 'Object') { // This is needed to avoid unwanted conversions of objects to Parse.Objects. @@ -226,9 +269,15 @@ export default class BrowserTable extends React.Component { value = ''; } let wrapTop = Math.max(0, this.props.current.row * ROW_HEIGHT); + if(this.props.current.row < -1 && this.props.editCloneRows){ + wrapTop = ROW_HEIGHT * (this.props.current.row + (this.props.editCloneRows.length + 1)); + } if (this.props.current.row > -1 && this.props.newObject) { wrapTop += 60; } + if (this.props.current.row >= -1 && this.props.editCloneRows) { + wrapTop += ROW_HEIGHT * (this.props.editCloneRows.length + 1); + } let wrapLeft = 30; for (let i = 0; i < this.props.current.col; i++) { const column = this.props.order[i]; @@ -297,6 +346,7 @@ export default class BrowserTable extends React.Component { table = (
+ {editCloneRows} {newRow} {rows}
From d97e896696eb0f804320eade0bdcc0e7ca651361 Mon Sep 17 00:00:00 2001 From: sadakchap Date: Thu, 6 May 2021 20:34:58 +0530 Subject: [PATCH 03/21] allowing user to clone rows for standard classes --- src/dashboard/Data/Browser/BrowserToolbar.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js index 5e134a0348..017ac7573b 100644 --- a/src/dashboard/Data/Browser/BrowserToolbar.react.js +++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js @@ -122,7 +122,7 @@ let BrowserToolbar = ({ /> From 59aeb63cf90401b6a11b5b4a81847b6e7012e949 Mon Sep 17 00:00:00 2001 From: sadakchap Date: Mon, 17 May 2021 22:52:53 +0530 Subject: [PATCH 04/21] checking dirty clone objects on failed clone --- src/dashboard/Data/Browser/Browser.react.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 53129b104c..1d64aa6b7e 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -954,8 +954,24 @@ class Browser extends DashboardView { } }); } catch (error) { - if(error.code === 137){ - this.addEditCloneRows(toClone); + if (error.code === 137) { + let failedSaveObj = []; + let savedObjects = []; + toClone.forEach(cloneObj => { + cloneObj.dirty() + ? failedSaveObj.push(cloneObj) + : savedObjects.push(cloneObj); + }); + if (savedObjects.length) { + this.setState({ + data: [...savedObjects, ...this.state.data], + counts: { + ...this.state.counts, + [className]: this.state.counts[className] + savedObjects.length + } + }); + } + this.addEditCloneRows(failedSaveObj); } this.setState({ selection: {}, From 9b3be18864ff689a584fe78222fe22082bed8c3c Mon Sep 17 00:00:00 2001 From: sadakchap Date: Mon, 17 May 2021 23:21:29 +0530 Subject: [PATCH 05/21] giving option to clone or cancel per row for failed clone rows --- src/dashboard/Data/Browser/Browser.react.js | 66 ++++++++++++++++ .../Data/Browser/BrowserTable.react.js | 79 ++++++++++++------- 2 files changed, 116 insertions(+), 29 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 1d64aa6b7e..f5a373e6f0 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -125,6 +125,8 @@ class Browser extends DashboardView { this.addEditCloneRows = this.addEditCloneRows.bind(this); this.abortAddRow = this.abortAddRow.bind(this); this.saveNewRow = this.saveNewRow.bind(this); + this.saveEditCloneRow = this.saveEditCloneRow.bind(this); + this.abortEditCloneRow = this.abortEditCloneRow.bind(this); } componentWillMount() { @@ -366,6 +368,58 @@ class Browser extends DashboardView { ); } + saveEditCloneRow(rowIndex) { + let obj; + if (rowIndex < -1) { + obj = this.state.editCloneRows[ + rowIndex + (this.state.editCloneRows.length + 1) + ]; + } + if (!obj) { + return; + } + obj.save(null, { useMasterKey: true }).then((objectSaved) => { + let msg = objectSaved.className + ' with id \'' + objectSaved.id + '\' ' + 'created'; + this.showNote(msg, false); + + const state = { data: this.state.data, editCloneRows: this.state.editCloneRows }; + state.editCloneRows = state.editCloneRows.filter( + cloneObj => cloneObj._localId !== obj._localId + ); + if (state.editCloneRows.length === 0) state.editCloneRows = null; + if (this.props.params.className === obj.className) { + this.state.data.unshift(obj); + } + this.state.counts[obj.className] += 1; + this.setState(state); + }, (error) => { + let msg = typeof error === 'string' ? error : error.message; + if (msg) { + msg = msg[0].toUpperCase() + msg.substr(1); + } + + this.showNote(msg, true); + }); + } + + abortEditCloneRow(rowIndex) { + let obj; + if (rowIndex < -1) { + obj = this.state.editCloneRows[ + rowIndex + (this.state.editCloneRows.length + 1) + ]; + } + if (!obj) { + return; + } + const state = { editCloneRows: this.state.editCloneRows }; + state.editCloneRows = state.editCloneRows.filter( + cloneObj => cloneObj._localId !== obj._localId + ); + if (state.editCloneRows.length === 0) state.editCloneRows = null; + this.setState(state); + } + addRowWithModal() { this.addRow(); this.selectRow(undefined, true); @@ -653,6 +707,16 @@ class Browser extends DashboardView { }); return; } + if (isEditCloneObj) { + const editObjIndex = row + (this.state.editCloneRows.length + 1); + let cloneRows = [...this.state.editCloneRows]; + cloneRows.splice(editObjIndex, 1, obj); + this.setState({ + editCloneRows: cloneRows + }); + return; + } + obj.save(null, { useMasterKey: true }).then((objectSaved) => { const createdOrUpdated = isNewObject || isEditCloneObj ? 'created' : 'updated'; let msg = objectSaved.className + ' with id \'' + objectSaved.id + '\' ' + createdOrUpdated; @@ -1159,6 +1223,8 @@ class Browser extends DashboardView { onEditPermissions={this.onDialogToggle} onSaveNewRow={this.saveNewRow} onAbortAddRow={this.abortAddRow} + onSaveEditCloneRow={this.saveEditCloneRow} + onAbortEditCloneRow={this.abortEditCloneRow} columns={columns} className={className} diff --git a/src/dashboard/Data/Browser/BrowserTable.react.js b/src/dashboard/Data/Browser/BrowserTable.react.js index a8c04e12d6..702ad1b304 100644 --- a/src/dashboard/Data/Browser/BrowserTable.react.js +++ b/src/dashboard/Data/Browser/BrowserTable.react.js @@ -118,38 +118,56 @@ export default class BrowserTable extends React.Component { let editCloneRows = null; if(this.props.editCloneRows){ editCloneRows = ( -
+
{this.props.editCloneRows.map((cloneRow, idx) => { let index = (this.props.editCloneRows.length + 1) * -1 + idx; const currentCol = this.props.current && this.props.current.row === index ? this.props.current.col : undefined; const isEditingRow = this.props.current && this.props.current.row === index && !!this.props.editing; return ( - +
+ +
); })}
@@ -287,13 +305,16 @@ export default class BrowserTable extends React.Component { } let wrapTop = Math.max(0, this.props.current.row * ROW_HEIGHT); if(this.props.current.row < -1 && this.props.editCloneRows){ - wrapTop = ROW_HEIGHT * (this.props.current.row + (this.props.editCloneRows.length + 1)); + //for edit clone rows + wrapTop = (2 * ROW_HEIGHT) * (this.props.current.row + (this.props.editCloneRows.length + 1)); } if (this.props.current.row > -1 && this.props.newObject) { + //for data rows when there's new row wrapTop += 60; } if (this.props.current.row >= -1 && this.props.editCloneRows) { - wrapTop += ROW_HEIGHT * (this.props.editCloneRows.length + 1); + //for data rows & new row when there are edit clone rows + wrapTop += (ROW_HEIGHT) * (this.props.editCloneRows.length + 1 + 1); } let wrapLeft = 30; for (let i = 0; i < this.props.current.col; i++) { From 97057137547867bd0a18d7f3dd4d51425ade111b Mon Sep 17 00:00:00 2001 From: sadakchap Date: Mon, 17 May 2021 23:42:26 +0530 Subject: [PATCH 06/21] fixed wrapTop for data rows when edit clone row --- src/dashboard/Data/Browser/BrowserTable.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/Data/Browser/BrowserTable.react.js b/src/dashboard/Data/Browser/BrowserTable.react.js index 702ad1b304..5f64afe899 100644 --- a/src/dashboard/Data/Browser/BrowserTable.react.js +++ b/src/dashboard/Data/Browser/BrowserTable.react.js @@ -314,7 +314,7 @@ export default class BrowserTable extends React.Component { } if (this.props.current.row >= -1 && this.props.editCloneRows) { //for data rows & new row when there are edit clone rows - wrapTop += (ROW_HEIGHT) * (this.props.editCloneRows.length + 1 + 1); + wrapTop += (2 * ROW_HEIGHT) * (this.props.editCloneRows.length); } let wrapLeft = 30; for (let i = 0; i < this.props.current.col; i++) { From b7b7b93ba322f86624416ee8e8735cbe38789ec2 Mon Sep 17 00:00:00 2001 From: sadakchap Date: Fri, 21 May 2021 20:38:45 +0530 Subject: [PATCH 07/21] showing modal Clone menu --- src/dashboard/Data/Browser/Browser.react.js | 8 ++++++++ .../Data/Browser/BrowserToolbar.react.js | 17 +++++++++++++++-- src/dashboard/Data/Browser/DataBrowser.react.js | 5 ++++- src/icons/clone-icon.svg | 4 ++++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/icons/clone-icon.svg diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index f5a373e6f0..e60639cb79 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -127,6 +127,7 @@ class Browser extends DashboardView { this.saveNewRow = this.saveNewRow.bind(this); this.saveEditCloneRow = this.saveEditCloneRow.bind(this); this.abortEditCloneRow = this.abortEditCloneRow.bind(this); + this.cancelPendingEditRows = this.cancelPendingEditRows.bind(this); } componentWillMount() { @@ -426,6 +427,12 @@ class Browser extends DashboardView { this.showEditRowDialog(); } + cancelPendingEditRows() { + this.setState({ + editCloneRows: null + }); + } + addEditCloneRows(cloneRows) { this.setState({ editCloneRows: cloneRows @@ -1225,6 +1232,7 @@ class Browser extends DashboardView { onAbortAddRow={this.abortAddRow} onSaveEditCloneRow={this.saveEditCloneRow} onAbortEditCloneRow={this.abortEditCloneRow} + onCancelPendingEditRows={this.cancelPendingEditRows} columns={columns} className={className} diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js index 017ac7573b..543f3d880e 100644 --- a/src/dashboard/Data/Browser/BrowserToolbar.react.js +++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js @@ -49,6 +49,8 @@ let BrowserToolbar = ({ uniqueField, handleColumnDragDrop, handleColumnsOrder, + editCloneRows, + onCancelPendingEditRows, order, enableDeleteAllRows, @@ -59,6 +61,7 @@ let BrowserToolbar = ({ enableClassManipulation, }) => { let selectionLength = Object.keys(selection).length; + let isPendingEditCloneRows = editCloneRows && editCloneRows.length > 0; let details = []; if (count !== undefined) { if (count === 1) { @@ -103,7 +106,7 @@ let BrowserToolbar = ({ ); } else if (onAddRow) { menu = ( - + {enableColumnManipulation ? :