mirror of
				https://github.com/gristlabs/grist-core.git
				synced 2025-06-13 20:53:59 +00:00 
			
		
		
		
	(core) Convert CopySelection and tableUtil to typescript
Summary: - This should make these easier to work with and make changes to. - Removes one unused method. Test Plan: No changes of behavior, existing tests should pass. Reviewers: alexmojaki Reviewed By: alexmojaki Differential Revision: https://phab.getgrist.com/D3091
This commit is contained in:
		
							parent
							
								
									f7c9919120
								
							
						
					
					
						commit
						65e743931b
					
				@ -1,45 +0,0 @@
 | 
			
		||||
var ValueFormatter = require('app/common/ValueFormatter');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The CopySelection class is an abstraction for a subset of currently selected cells.
 | 
			
		||||
 * @param {Array} rowIds - row ids of the rows selected
 | 
			
		||||
 * @param {Array} fields - MetaRowModels of the selected view fields
 | 
			
		||||
 * @param {Object} options.rowStyle - an object that maps rowId to an object containing
 | 
			
		||||
 * style options. i.e. { 1: { height: 20px } }
 | 
			
		||||
 * @param {Object} options.colStyle - an object that maps colId to an object containing
 | 
			
		||||
 * style options.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function CopySelection(tableData, rowIds, fields, options) {
 | 
			
		||||
  this.fields = fields;
 | 
			
		||||
  this.rowIds = rowIds || [];
 | 
			
		||||
  this.colIds = fields.map(f => f.colId());
 | 
			
		||||
  this.displayColIds = fields.map(f => f.displayColModel().colId());
 | 
			
		||||
  this.rowStyle = options.rowStyle;
 | 
			
		||||
  this.colStyle = options.colStyle;
 | 
			
		||||
  this.columns = fields.map((f, i) => {
 | 
			
		||||
    let formatter = ValueFormatter.createFormatter(
 | 
			
		||||
      f.displayColModel().type(),
 | 
			
		||||
      f.widgetOptionsJson(),
 | 
			
		||||
      f.documentSettings()
 | 
			
		||||
    );
 | 
			
		||||
    let _fmtGetter = tableData.getRowPropFunc(this.displayColIds[i]);
 | 
			
		||||
    let _rawGetter = tableData.getRowPropFunc(this.colIds[i]);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      colId: this.colIds[i],
 | 
			
		||||
      fmtGetter: rowId => formatter.formatAny(_fmtGetter(rowId)),
 | 
			
		||||
      rawGetter: rowId => _rawGetter(rowId)
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CopySelection.prototype.isCellSelected = function(rowId, colId) {
 | 
			
		||||
  return this.rowIds.includes(rowId) && this.colIds.includes(colId);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CopySelection.prototype.onlyAddRowSelected = function() {
 | 
			
		||||
  return this.rowIds.length === 1 && this.rowIds[0] === "new";
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = CopySelection;
 | 
			
		||||
							
								
								
									
										60
									
								
								app/client/components/CopySelection.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								app/client/components/CopySelection.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
			
		||||
import type {CellValue} from 'app/common/DocActions';
 | 
			
		||||
import type {TableData} from 'app/common/TableData';
 | 
			
		||||
import type {UIRowId} from 'app/common/UIRowId';
 | 
			
		||||
import {createFormatter} from 'app/common/ValueFormatter';
 | 
			
		||||
import type {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The CopySelection class is an abstraction for a subset of currently selected cells.
 | 
			
		||||
 * @param {Array} rowIds - row ids of the rows selected
 | 
			
		||||
 * @param {Array} fields - MetaRowModels of the selected view fields
 | 
			
		||||
 * @param {Object} options.rowStyle - an object that maps rowId to an object containing
 | 
			
		||||
 * style options. i.e. { 1: { height: 20px } }
 | 
			
		||||
 * @param {Object} options.colStyle - an object that maps colId to an object containing
 | 
			
		||||
 * style options.
 | 
			
		||||
 */
 | 
			
		||||
export class CopySelection {
 | 
			
		||||
  public readonly colIds = this.fields.map(f => f.colId());
 | 
			
		||||
  public readonly displayColIds = this.fields.map(f => f.displayColModel().colId());
 | 
			
		||||
  public readonly rowStyle: {[r: number]: object}|undefined;
 | 
			
		||||
  public readonly colStyle: {[c: string]: object}|undefined;
 | 
			
		||||
 | 
			
		||||
  public readonly columns: Array<{
 | 
			
		||||
    colId: string,
 | 
			
		||||
    fmtGetter: (rowId: UIRowId) => string,
 | 
			
		||||
    rawGetter: (rowId: UIRowId) => CellValue|undefined,
 | 
			
		||||
  }>;
 | 
			
		||||
 | 
			
		||||
  constructor(tableData: TableData, public readonly rowIds: UIRowId[], public readonly fields: ViewFieldRec[],
 | 
			
		||||
              options: {
 | 
			
		||||
                rowStyle?: {[r: number]: object},
 | 
			
		||||
                colStyle?: {[c: string]: object},
 | 
			
		||||
              }
 | 
			
		||||
  ) {
 | 
			
		||||
    this.rowStyle = options.rowStyle;
 | 
			
		||||
    this.colStyle = options.colStyle;
 | 
			
		||||
    this.columns = fields.map((f, i) => {
 | 
			
		||||
      const formatter = createFormatter(
 | 
			
		||||
        f.displayColModel().type(),
 | 
			
		||||
        f.widgetOptionsJson(),
 | 
			
		||||
        f.documentSettings()
 | 
			
		||||
      );
 | 
			
		||||
      const _fmtGetter = tableData.getRowPropFunc(this.displayColIds[i])!;
 | 
			
		||||
      const _rawGetter = tableData.getRowPropFunc(this.colIds[i])!;
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        colId: this.colIds[i],
 | 
			
		||||
        fmtGetter: rowId => formatter.formatAny(_fmtGetter(rowId)),
 | 
			
		||||
        rawGetter: rowId => _rawGetter(rowId)
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public isCellSelected(rowId: UIRowId, colId: string): boolean {
 | 
			
		||||
    return this.rowIds.includes(rowId) && this.colIds.includes(colId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onlyAddRowSelected(): boolean {
 | 
			
		||||
    return this.rowIds.length === 1 && this.rowIds[0] === "new";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -10,7 +10,7 @@ require('app/client/lib/koUtil'); // Needed for subscribeInit.
 | 
			
		||||
 | 
			
		||||
var Base          = require('./Base');
 | 
			
		||||
var BaseView      = require('./BaseView');
 | 
			
		||||
var CopySelection = require('./CopySelection');
 | 
			
		||||
var {CopySelection} = require('./CopySelection');
 | 
			
		||||
var RecordLayout  = require('./RecordLayout');
 | 
			
		||||
var commands      = require('./commands');
 | 
			
		||||
const {RowContextMenu} = require('../ui/RowContextMenu');
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ var viewCommon    = require('./viewCommon');
 | 
			
		||||
var Base          = require('./Base');
 | 
			
		||||
var BaseView      = require('./BaseView');
 | 
			
		||||
var selector      = require('./Selector');
 | 
			
		||||
var CopySelection = require('./CopySelection');
 | 
			
		||||
var {CopySelection} = require('./CopySelection');
 | 
			
		||||
 | 
			
		||||
const {renderAllRows} = require('app/client/components/Printing');
 | 
			
		||||
const {reportError} = require('app/client/models/AppModel');
 | 
			
		||||
@ -502,11 +502,6 @@ GridView.prototype.clearSelection = function() {
 | 
			
		||||
 * @param {CopySelection} selection
 | 
			
		||||
 */
 | 
			
		||||
GridView.prototype.clearValues = function(selection) {
 | 
			
		||||
  console.debug('GridView.clearValues', selection);
 | 
			
		||||
  selection.rowIds = _.without(selection.rowIds, 'new');
 | 
			
		||||
  // If only the addRow was selected, don't send an action.
 | 
			
		||||
  if (selection.rowIds.length === 0) { return; }
 | 
			
		||||
 | 
			
		||||
  const options = this._getColumnMenuOptions(selection);
 | 
			
		||||
  if (options.isFormula === true) {
 | 
			
		||||
    this.activateEditorAtCursor({ init: ''});
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								app/client/declarations.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								app/client/declarations.d.ts
									
									
									
									
										vendored
									
									
								
							@ -145,15 +145,6 @@ declare module "app/client/components/commands" {
 | 
			
		||||
  export const createGroup: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module "app/client/lib/tableUtil" {
 | 
			
		||||
 | 
			
		||||
  import {KoArray} from 'app/client/lib/koArray';
 | 
			
		||||
  import {ViewFieldRec} from 'app/client/models/DocModel';
 | 
			
		||||
 | 
			
		||||
  function insertPositions(lowerPos: number|null, upperPos: number|null, numInserts: number): number[];
 | 
			
		||||
  function fieldInsertPositions(viewFields: KoArray<ViewFieldRec>, index: number, numInserts: number): number[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module "app/client/models/BaseRowModel" {
 | 
			
		||||
  import {Disposable} from 'app/client/lib/dispose';
 | 
			
		||||
  import * as TableModel from 'app/client/models/TableModel';
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,16 @@
 | 
			
		||||
var _         = require('underscore');
 | 
			
		||||
import type {CopySelection} from 'app/client/components/CopySelection';
 | 
			
		||||
import {get as getBrowserGlobals} from 'app/client/lib/browserGlobals';
 | 
			
		||||
import type {KoArray} from 'app/client/lib/koArray';
 | 
			
		||||
import type {ViewFieldRec} from 'app/client/models/DocModel';
 | 
			
		||||
import type {BulkUpdateRecord} from 'app/common/DocActions';
 | 
			
		||||
import {safeJsonParse} from 'app/common/gutil';
 | 
			
		||||
import type {TableData} from 'app/common/TableData';
 | 
			
		||||
import {tsvEncode} from 'app/common/tsvFormat';
 | 
			
		||||
import {dom} from 'grainjs';
 | 
			
		||||
import map = require('lodash/map');
 | 
			
		||||
import zipObject = require('lodash/zipObject');
 | 
			
		||||
 | 
			
		||||
var dom             = require('./dom');
 | 
			
		||||
var gutil           = require('app/common/gutil');
 | 
			
		||||
var {tsvEncode}     = require('app/common/tsvFormat');
 | 
			
		||||
 | 
			
		||||
const G = require('../lib/browserGlobals').get('document', 'DOMParser');
 | 
			
		||||
const G = getBrowserGlobals('document', 'DOMParser');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Returns unique positions given upper and lower position. This function returns a suitable
 | 
			
		||||
@ -23,16 +29,16 @@ const G = require('../lib/browserGlobals').get('document', 'DOMParser');
 | 
			
		||||
 *      insertPositions(0, null, 4) = [1, 2, 3, 4]
 | 
			
		||||
 *      insertPositions(0, 1, 4) = [0.2, 0.4, 0.6, 0.8]
 | 
			
		||||
 */
 | 
			
		||||
function insertPositions(lowerPos, upperPos, numInserts) {
 | 
			
		||||
export function insertPositions(lowerPos: number|null, upperPos: number|null, numInserts: number): number[] {
 | 
			
		||||
  numInserts = (typeof numInserts === 'undefined') ? 1 : numInserts;
 | 
			
		||||
  var start;
 | 
			
		||||
  var step = 1;
 | 
			
		||||
  var positions = [];
 | 
			
		||||
  let start = 0;
 | 
			
		||||
  let step = 1;
 | 
			
		||||
  const positions = [];
 | 
			
		||||
 | 
			
		||||
  if (typeof lowerPos !== 'number' && typeof upperPos !== 'number') {
 | 
			
		||||
    start = 0;
 | 
			
		||||
  } else if (typeof lowerPos !== 'number') {
 | 
			
		||||
    start = upperPos - numInserts;
 | 
			
		||||
    start = upperPos! - numInserts;
 | 
			
		||||
  } else if (typeof upperPos !== 'number') {
 | 
			
		||||
    start = lowerPos + 1;
 | 
			
		||||
  } else {
 | 
			
		||||
@ -40,12 +46,11 @@ function insertPositions(lowerPos, upperPos, numInserts) {
 | 
			
		||||
    start = lowerPos + step;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for(var i = 0; i < numInserts; i++ ){
 | 
			
		||||
  for(let i = 0; i < numInserts; i++ ){
 | 
			
		||||
    positions.push(start + step*i);
 | 
			
		||||
  }
 | 
			
		||||
  return positions;
 | 
			
		||||
}
 | 
			
		||||
exports.insertPositions = insertPositions;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a sorted array of parentPos values between the parentPos of the viewField at index-1 and index.
 | 
			
		||||
@ -53,12 +58,11 @@ exports.insertPositions = insertPositions;
 | 
			
		||||
 * @{param} {number} index - index to insert the viewFields into
 | 
			
		||||
 * @{param} {number} numInserts - number of new fields to insert
 | 
			
		||||
 */
 | 
			
		||||
function fieldInsertPositions(viewFields, index, numInserts) {
 | 
			
		||||
  var leftPos = (index > 0) ? viewFields.at(index-1).parentPos() : null;
 | 
			
		||||
  var rightPos = (index < viewFields.peekLength) ? viewFields.at(index).parentPos() : null;
 | 
			
		||||
export function fieldInsertPositions(viewFields: KoArray<ViewFieldRec>, index: number, numInserts: number): number[] {
 | 
			
		||||
  const leftPos = (index > 0) ? viewFields.at(index - 1)!.parentPos() : null;
 | 
			
		||||
  const rightPos = (index < viewFields.peekLength) ? viewFields.at(index)!.parentPos() : null;
 | 
			
		||||
  return insertPositions(leftPos, rightPos, numInserts);
 | 
			
		||||
}
 | 
			
		||||
exports.fieldInsertPositions = fieldInsertPositions;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns tsv formatted values from TableData at the given rowIDs and columnIds.
 | 
			
		||||
@ -66,14 +70,13 @@ exports.fieldInsertPositions = fieldInsertPositions;
 | 
			
		||||
 * @param {CopySelection} selection - a CopySelection instance
 | 
			
		||||
 * @return {String}
 | 
			
		||||
 **/
 | 
			
		||||
function makePasteText(tableData, selection) {
 | 
			
		||||
export function makePasteText(tableData: TableData, selection: CopySelection) {
 | 
			
		||||
  // tsvEncode expects data as a 2-d array with each a array representing a row
 | 
			
		||||
  // i.e. [["1-1", "1-2", "1-3"],["2-1", "2-2", "2-3"]]
 | 
			
		||||
  const values = selection.rowIds.map(rowId =>
 | 
			
		||||
    selection.columns.map(col => col.fmtGetter(rowId)));
 | 
			
		||||
  return tsvEncode(values);
 | 
			
		||||
}
 | 
			
		||||
exports.makePasteText = makePasteText;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns an html table of containing the cells denoted by the cross product of
 | 
			
		||||
@ -83,11 +86,11 @@ exports.makePasteText = makePasteText;
 | 
			
		||||
 * @param {Boolean} showColHeader - whether to include a column header row
 | 
			
		||||
 * @return {String} The html for a table containing the given data.
 | 
			
		||||
 **/
 | 
			
		||||
function makePasteHtml(tableData, selection, includeColHeaders) {
 | 
			
		||||
  let rowStyle = selection.rowStyle || {};    // Maps rowId to style object.
 | 
			
		||||
  let colStyle = selection.colStyle || {};    // Maps colId to style object.
 | 
			
		||||
export function makePasteHtml(tableData: TableData, selection: CopySelection, includeColHeaders: boolean) {
 | 
			
		||||
  const rowStyle = selection.rowStyle || {};    // Maps rowId to style object.
 | 
			
		||||
  const colStyle = selection.colStyle || {};    // Maps colId to style object.
 | 
			
		||||
 | 
			
		||||
  let elem = dom('table', {border: '1', cellspacing: '0', style: 'white-space: pre'},
 | 
			
		||||
  const elem = dom('table', {border: '1', cellspacing: '0', style: 'white-space: pre'},
 | 
			
		||||
    dom('colgroup', selection.colIds.map(colId =>
 | 
			
		||||
      dom('col', {
 | 
			
		||||
        style: _styleAttr(colStyle[colId]),
 | 
			
		||||
@ -102,14 +105,12 @@ function makePasteHtml(tableData, selection, includeColHeaders) {
 | 
			
		||||
    // Fill with table cells.
 | 
			
		||||
    selection.rowIds.map(rowId =>
 | 
			
		||||
      dom('tr',
 | 
			
		||||
        {style: _styleAttr(rowStyle[rowId])},
 | 
			
		||||
        {style: _styleAttr(rowStyle[rowId as number])},
 | 
			
		||||
        selection.columns.map(col => {
 | 
			
		||||
          let rawValue = col.rawGetter(rowId);
 | 
			
		||||
          let fmtValue = col.fmtGetter(rowId);
 | 
			
		||||
          let dataOptions = {};
 | 
			
		||||
          if (rawValue !== fmtValue) {
 | 
			
		||||
            dataOptions['data-grist-raw-value'] = JSON.stringify(rawValue);
 | 
			
		||||
          }
 | 
			
		||||
          const rawValue = col.rawGetter(rowId);
 | 
			
		||||
          const fmtValue = col.fmtGetter(rowId);
 | 
			
		||||
          const dataOptions = (rawValue === fmtValue) ? {} :
 | 
			
		||||
            {'data-grist-raw-value': JSON.stringify(rawValue)};
 | 
			
		||||
          return dom('td', dataOptions, fmtValue);
 | 
			
		||||
        })
 | 
			
		||||
      )
 | 
			
		||||
@ -117,33 +118,29 @@ function makePasteHtml(tableData, selection, includeColHeaders) {
 | 
			
		||||
  );
 | 
			
		||||
  return elem.outerHTML;
 | 
			
		||||
}
 | 
			
		||||
exports.makePasteHtml = makePasteHtml;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef RichPasteObject
 | 
			
		||||
 * @type {object}
 | 
			
		||||
 * @property {string} displayValue
 | 
			
		||||
 * @property {string} [rawValue] - Optional rawValue that should be used if colType matches
 | 
			
		||||
 *    destination.
 | 
			
		||||
 * @property {string} [colType] - Column type of the source column.
 | 
			
		||||
 */
 | 
			
		||||
export interface RichPasteObject {
 | 
			
		||||
  displayValue: string;
 | 
			
		||||
  colType?: string|null;  // Column type of the source column.
 | 
			
		||||
  rawValue?: unknown;     // Optional rawValue that should be used if colType matches destination.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Parses a 2-d array of objects from a text string containing an HTML table.
 | 
			
		||||
 * @param {string} data - String of an HTML table.
 | 
			
		||||
 * @return {Array<Array<RichPasteObj>>} - 2-d array of objects containing details of copied cells.
 | 
			
		||||
 */
 | 
			
		||||
function parsePasteHtml(data) {
 | 
			
		||||
  let parser = new G.DOMParser();
 | 
			
		||||
  let doc = parser.parseFromString(data, 'text/html');
 | 
			
		||||
  let table = doc.querySelector('table');
 | 
			
		||||
export function parsePasteHtml(data: string): RichPasteObject[][] {
 | 
			
		||||
  const parser = new G.DOMParser() as DOMParser;
 | 
			
		||||
  const doc = parser.parseFromString(data, 'text/html');
 | 
			
		||||
  const table = doc.querySelector('table');
 | 
			
		||||
 | 
			
		||||
  let colTypes = Array.from(table.querySelectorAll('col'), col =>
 | 
			
		||||
  const colTypes = Array.from(table!.querySelectorAll('col'), col =>
 | 
			
		||||
    col.getAttribute('data-grist-col-type'));
 | 
			
		||||
 | 
			
		||||
  let result = Array.from(table.querySelectorAll('tr'), (row, rowIdx) =>
 | 
			
		||||
  const result = Array.from(table!.querySelectorAll('tr'), (row, rowIdx) =>
 | 
			
		||||
    Array.from(row.querySelectorAll('td, th'), (cell, colIdx) => {
 | 
			
		||||
      let o = { displayValue: cell.textContent };
 | 
			
		||||
      const o: RichPasteObject = { displayValue: cell.textContent! };
 | 
			
		||||
 | 
			
		||||
      // If there's a column type, add it to the object
 | 
			
		||||
      if (colTypes[colIdx]) {
 | 
			
		||||
@ -151,7 +148,7 @@ function parsePasteHtml(data) {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (cell.hasAttribute('data-grist-raw-value')) {
 | 
			
		||||
        o.rawValue = gutil.safeJsonParse(cell.getAttribute('data-grist-raw-value'),
 | 
			
		||||
        o.rawValue = safeJsonParse(cell.getAttribute('data-grist-raw-value')!,
 | 
			
		||||
          o.displayValue);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -163,35 +160,12 @@ function parsePasteHtml(data) {
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
exports.parsePasteHtml = parsePasteHtml;
 | 
			
		||||
 | 
			
		||||
// Helper function to add css style properties to an html tag
 | 
			
		||||
function _styleAttr(style) {
 | 
			
		||||
  return _.map(style, (value, prop) => `${prop}: ${value};`).join(' ');
 | 
			
		||||
function _styleAttr(style: object) {
 | 
			
		||||
  return map(style, (value, prop) => `${prop}: ${value};`).join(' ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * groupBy takes in tableData and colId and returns an array of objects of unique values and counts.
 | 
			
		||||
 *
 | 
			
		||||
 * @param tableData
 | 
			
		||||
 * @param colId
 | 
			
		||||
 * @param {number} =optSort - Optional sort flag to return array sorted by count; 1 for asc, -1 for desc.
 | 
			
		||||
 */
 | 
			
		||||
function groupBy(tableData, colId, optSort) {
 | 
			
		||||
  var groups = _.map(
 | 
			
		||||
    _.countBy(tableData.getColValues(colId)),
 | 
			
		||||
    function(value, key) {
 | 
			
		||||
      return {
 | 
			
		||||
        key: key,
 | 
			
		||||
        count: value,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
  groups = _.sortBy(groups, 'key'); // first sort by key, then by count
 | 
			
		||||
  return optSort ? _.sortBy(groups, function(el) { return optSort * el.count; }) : groups;
 | 
			
		||||
}
 | 
			
		||||
exports.groupBy = groupBy;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* Given a selection object, creates a action to set all references in the object to the empty string.
 | 
			
		||||
* @param {Object} selection - an object with a list of selected row Ids, selected column Ids, a list of
 | 
			
		||||
@ -199,19 +173,24 @@ exports.groupBy = groupBy;
 | 
			
		||||
* See GridView.js getSelection and DetailView.js getSelection.
 | 
			
		||||
* @returns {Object} BulkUpdateRecord action
 | 
			
		||||
*/
 | 
			
		||||
export function makeDeleteAction(selection: CopySelection): BulkUpdateRecord|null {
 | 
			
		||||
  // If the selection includes the "new" row, ignore that one.
 | 
			
		||||
  const rowIds = selection.rowIds.filter((r): r is number => (typeof r === 'number'));
 | 
			
		||||
  if (rowIds.length === 0) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  const blankRow = rowIds.map(() => '');
 | 
			
		||||
 | 
			
		||||
function makeDeleteAction(selection) {
 | 
			
		||||
  let blankRow = selection.rowIds.map(() => '');
 | 
			
		||||
 | 
			
		||||
  let colIds = selection.fields
 | 
			
		||||
  const colIds = selection.fields
 | 
			
		||||
    .filter(field => !field.column().isRealFormula() && !field.disableEditData())
 | 
			
		||||
    .map(field => field.colId());
 | 
			
		||||
 | 
			
		||||
  // Get the tableId from the first selected column.
 | 
			
		||||
  let tableId = selection.fields[0].column().table().tableId();
 | 
			
		||||
  const tableId = selection.fields[0].column().table().tableId();
 | 
			
		||||
 | 
			
		||||
  return colIds.length === 0 ? null :
 | 
			
		||||
    ['BulkUpdateRecord', tableId, selection.rowIds, _.object(colIds, colIds.map(() => blankRow))];
 | 
			
		||||
  if (colIds.length === 0) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  return ['BulkUpdateRecord', tableId, rowIds,
 | 
			
		||||
    zipObject(colIds, colIds.map(() => blankRow))];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.makeDeleteAction = makeDeleteAction;
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user