From 28b03dccb2c09f51241cc174e73968bead3b749d Mon Sep 17 00:00:00 2001 From: abe33 Date: Thu, 26 Nov 2015 21:56:45 +0100 Subject: [PATCH] Implement applying sort to the table for save Closes #14 --- lib/display-table.coffee | 23 ++++++++++- lib/table-editor.coffee | 2 +- lib/table-element.coffee | 7 ++++ lib/table.coffee | 24 +++++++++++ spec/display-table-spec.coffee | 74 ++++++++++++++++++++++++++++++++++ spec/table-element-spec.coffee | 22 +++++++++- 6 files changed, 149 insertions(+), 3 deletions(-) diff --git a/lib/display-table.coffee b/lib/display-table.coffee index c31b417..f26d488 100644 --- a/lib/display-table.coffee +++ b/lib/display-table.coffee @@ -13,7 +13,7 @@ class DisplayTable displayTable = new DisplayTable(state) @delegatesMethods( - 'changeColumnName', 'undo', 'redo', 'getRows', 'getColumns','getColumnCount', 'getColumnIndex', 'getRowCount', 'clearUndoStack', 'clearRedoStack', 'getValueAtPosition', 'setValueAtPosition', 'setValuesAtPositions', 'setValuesInRange', 'rowRangeFrom', 'swapRows', + 'changeColumnName', 'undo', 'redo', 'getRows', 'getColumns','getColumnCount', 'getColumnIndex', 'getRowCount', 'clearUndoStack', 'clearRedoStack', 'getValueAtPosition', 'setValueAtPosition', 'setValuesAtPositions', 'setValuesInRange', 'rowRangeFrom', 'swapRows', 'getRow', toProperty: 'table' ) @@ -604,6 +604,27 @@ class DisplayTable newScreenRange: {start: 0, end: @getRowCount()} } + applySort: -> + if @order? + if typeof @order is 'function' + orderFunction = @order + else + orderFunction = @compareRows(@order, @direction) + + order = @order + + @table.sortRows(orderFunction) + @table.ammendLastTransaction + undo: (commit) => + commit.undo() + @sortBy(order) + + redo: (commit) => + commit.redo() + @resetSort() + + @resetSort() + toggleSortDirection: -> @direction *= -1 @updateScreenRows() diff --git a/lib/table-editor.coffee b/lib/table-editor.coffee index 8a9e4ea..05524c1 100644 --- a/lib/table-editor.coffee +++ b/lib/table-editor.coffee @@ -37,7 +37,7 @@ class TableEditor 'onDidAddColumn','onDidRemoveColumn', 'onDidChangeColumnOption', 'onDidRenameColumn', 'onDidChangeLayout', 'getScreenCellRect', 'getScreenCellPosition', 'onDidChangeCellValue', - 'sortBy', 'toggleSortDirection', 'resetSort', + 'sortBy', 'toggleSortDirection', 'resetSort', 'applySort', 'undo', 'redo', 'clearUndoStack', 'clearRedoStack', toProperty: 'displayTable' ) diff --git a/lib/table-element.coffee b/lib/table-element.coffee index 4751435..413983f 100644 --- a/lib/table-element.coffee +++ b/lib/table-element.coffee @@ -113,6 +113,10 @@ class TableElement extends HTMLElement headerCell = e.target.parentNode.parentNode @fitColumnToContent(Number(headerCell.dataset.column)) + @subscriptions.add @subscribeTo @head, 'tablr-header-cell .column-apply-sort-action', + 'mousedown': stopPropagationAndDefault (e) => + 'click': stopPropagationAndDefault (e) => @applySort() + @subscriptions.add @subscribeTo @head, 'tablr-header-cell .column-resize-handle', 'mousedown': stopPropagationAndDefault (e) => @startColumnResizeDrag(e) 'click': stopPropagationAndDefault() @@ -788,6 +792,8 @@ class TableElement extends HTMLElement goToLineElement.attach() goToLineElement + applySort: -> @tableEditor.applySort() + # ######## ######## #### ######## # ## ## ## ## ## # ## ## ## ## ## @@ -1623,6 +1629,7 @@ TableElement.registerCommands = -> 'tablr:go-to-line': -> @openGoToLineModal() 'tablr:move-line-down': -> @moveLineDown() 'tablr:move-line-up': -> @moveLineUp() + 'tablr:apply-sort': -> @applySort() 'tablr:fit-column-to-content': -> column = @tableEditor.getCursorPosition().column @fitColumnToContent(column) diff --git a/lib/table.coffee b/lib/table.coffee index f8924b0..4a6e469 100644 --- a/lib/table.coffee +++ b/lib/table.coffee @@ -420,6 +420,30 @@ class Table @emitModifiedStatusChange() @emitter.emit 'did-change', {rowIndices: [rowA, rowB]} + sortRows: (sortFunction, transaction=true) -> + originalRows = @rows.slice() + sortedRows = @rows.slice().sort(sortFunction) + + @rows = sortedRows.slice() + + emitEvents = => + @emitModifiedStatusChange() + @emitter.emit 'did-change', { + oldRange: {start: 0, end: originalRows.length} + newRange: {start: 0, end: originalRows.length} + } + + if transaction + @transaction + undo: -> + @rows = originalRows + emitEvents() + redo: -> + @rows = sortedRows + emitEvents() + + emitEvents() + extendExistingRows: (column, index) -> row.splice index, 0, undefined for row in @rows diff --git a/spec/display-table-spec.coffee b/spec/display-table-spec.coffee index 904f38d..fa4ce0f 100644 --- a/spec/display-table-spec.coffee +++ b/spec/display-table-spec.coffee @@ -509,6 +509,32 @@ describe 'DisplayTable', -> expect(displayTable.getScreenRowHeightAt(1)).toEqual(20) expect(displayTable.getScreenRowHeightAt(2)).toEqual(100) + describe '::applySort', -> + describe 'when no sort is applied', -> + it 'does nothing', -> + displayTable.applySort() + + expect(displayTable.getRow(0)).toEqual(['name', 'Jane Doe']) + expect(displayTable.getRow(1)).toEqual(['age', 30]) + expect(displayTable.getRow(2)).toEqual(['gender', 'female']) + + describe 'when a sort is applied', -> + beforeEach -> + displayTable.sortBy('key') + displayTable.applySort() + + it 'modifies the table to match the sort', -> + expect(displayTable.getRow(0)).toEqual(['age', 30]) + expect(displayTable.getRow(1)).toEqual(['gender', 'female']) + expect(displayTable.getRow(2)).toEqual(['name', 'Jane Doe']) + + expect(displayTable.getScreenRow(0)).toEqual(['age', 30]) + expect(displayTable.getScreenRow(1)).toEqual(['gender', 'female']) + expect(displayTable.getScreenRow(2)).toEqual(['name', 'Jane Doe']) + + it 'removes the current sort', -> + expect(displayTable.order).toBeNull() + ## ###### ######## ## ## ###### ## ## ## ## ## ## ## ## ## ## ## ## ## ## @@ -947,3 +973,51 @@ describe 'DisplayTable', -> expect(displayTable.getScreenRow(1)).toEqual(['age', 20]) expect(table.undoStack.length).toEqual(1) expect(table.redoStack.length).toEqual(0) + + it 'rolls back a sort applied to the underlying table', -> + displayTable.addColumn 'key' + displayTable.addColumn 'value' + + displayTable.addRow ['name', 'Jane Doe'], height: 200 + displayTable.addRow ['age', 30], height: 50 + displayTable.addRow ['gender', 'female'], height: 100 + displayTable.addRow ['blood type', 'ab-'], height: 50 + + displayTable.clearUndoStack() + + displayTable.sortBy('key') + displayTable.applySort() + + displayTable.undo() + + expect(table.getRow(0)).toEqual(['name', 'Jane Doe']) + expect(table.getRow(1)).toEqual(['age', 30]) + expect(table.getRow(2)).toEqual(['gender', 'female']) + expect(table.getRow(3)).toEqual(['blood type', 'ab-']) + + expect(displayTable.getScreenRow(0)).toEqual(['age', 30]) + expect(displayTable.getScreenRow(1)).toEqual(['blood type', 'ab-']) + expect(displayTable.getScreenRow(2)).toEqual(['gender', 'female']) + expect(displayTable.getScreenRow(3)).toEqual(['name', 'Jane Doe']) + + expect(table.undoStack.length).toEqual(0) + expect(table.redoStack.length).toEqual(1) + + expect(displayTable.order).toEqual(0) + + displayTable.redo() + + expect(table.getRow(0)).toEqual(['age', 30]) + expect(table.getRow(1)).toEqual(['blood type', 'ab-']) + expect(table.getRow(2)).toEqual(['gender', 'female']) + expect(table.getRow(3)).toEqual(['name', 'Jane Doe']) + + expect(displayTable.getScreenRow(0)).toEqual(['age', 30]) + expect(displayTable.getScreenRow(1)).toEqual(['blood type', 'ab-']) + expect(displayTable.getScreenRow(2)).toEqual(['gender', 'female']) + expect(displayTable.getScreenRow(3)).toEqual(['name', 'Jane Doe']) + + expect(table.undoStack.length).toEqual(1) + expect(table.redoStack.length).toEqual(0) + + expect(displayTable.order).toBeNull() diff --git a/spec/table-element-spec.coffee b/spec/table-element-spec.coffee index 0a32d44..a0a088b 100644 --- a/spec/table-element-spec.coffee +++ b/spec/table-element-spec.coffee @@ -607,6 +607,19 @@ describe 'tableElement', -> expect(tableEditor.order).toEqual(1) expect(tableEditor.direction).toEqual(1) + describe 'clicking on a header cell apply sort action', -> + [cell] = [] + + beforeEach -> + cell = header.querySelector('tablr-header-cell .column-apply-sort-action') + + spyOn(tableElement, 'applySort') + + click(cell) + + it 'invokes the applySort method', -> + expect(tableElement.applySort).toHaveBeenCalled() + describe 'dragging a resize handle', -> beforeEach -> tableElement.absoluteColumnsWidths = true @@ -666,7 +679,6 @@ describe 'tableElement', -> expect(tableEditor.getScreenColumnWidthAt(2)).toEqual(atom.config.get('tablr.minimumColumnWidth')) - describe 'clicking on a header cell fit column action', -> [cell] = [] @@ -1573,6 +1585,14 @@ describe 'tableElement', -> expect(tableEditor.moveLineUp).toHaveBeenCalled() + describe 'tablr:apply-sort', -> + it 'calls tableEditor::applySort', -> + spyOn(tableEditor, 'applySort') + + atom.commands.dispatch(tableElement, 'tablr:apply-sort') + + expect(tableEditor.applySort).toHaveBeenCalled() + describe 'tablr:fit-column-to-content', -> [dummyCell] = [] beforeEach ->