cfpb/owning-a-home

View on GitHub
src/static/js/modules/prepare-worksheets/worksheet-model.js

Summary

Maintainability
A
1 hr
Test Coverage
'use strict';

var _config = require( './worksheet-config' );
var _uuid = require( './util/uuid' );
var $ = require( 'jquery' );

var _dataStore = {
  worksheets: {}
};

// CRUD operations for the worksheet as a whole.
this.setWorksheet = function( type, value ) {
  _dataStore.worksheets[type] = value;
};

this.getWorksheet = function( type ) {
  return _dataStore.worksheets[type];
};

this.deleteWorksheet = function( type ) {
  delete _dataStore.worksheets[type];
};

this.resetWorksheet = function( type ) {
  var worksheet = this.getDefaultWorksheet( type );
  this.setDefaultWorksheet( type, worksheet );
  return worksheet;
};

this.getDefaultWorksheet = function( type ) {
  return _config.worksheetDefaults[type]();
};

this.setDefaultWorksheet = function( type, worksheet ) {
  // Add ids to rows.
  worksheet = worksheet || [];
  var row;
  for ( var i = 0; i < worksheet.length; i++ ) {
    row = worksheet[i];
    row.uid = _uuid.generateIdentifier();
  }
  // Add blank input row.
  worksheet.push( _getDefaultRow() );
  // Set this worksheet on dataStore.
  this.setWorksheet( type, worksheet );

  return worksheet;
};

this.getDefaultData = function() {
  return _config.getAllWorksheetDefaults();
};

this.setDefaultData = function() {
  var worksheet;
  var data = this.getDefaultData();

  for ( worksheet in data ) {
    if ( data.hasOwnProperty( worksheet ) ) {
      this.setDefaultWorksheet( worksheet, data[worksheet] );
    }
  }
};

// CRUD operations for the worksheet rows.
this.deleteWorksheetRow = function( type, rowID ) {
  // TODO -- check that this row is deletable
  var worksheet = _dataStore.worksheets[type];
  var idx = findRowById( worksheet, rowID );
  if ( !isNaN( parseInt( idx, 10 ) ) ) {
    worksheet.splice( idx, 1 );
  }
};

this.getWorksheetRow = function( type, row ) {
  row = _dataStore.worksheets[type][row];
  if ( !row ) {
    throw new Error( 'Requested row out of worksheet bounds!' );
  }
  return row;
};

this.addWorksheetRow = function( type, opts ) {
  var row = _getDefaultRow();
  if ( opts ) {
    $.extend( row, opts );
  }
  row.uid = _uuid.generateIdentifier();
  _dataStore.worksheets[type].push( row );
  return row;
};

this.setWorksheetRow = function( type, row, data ) {
  for ( var key in data ) {
    if ( data.hasOwnProperty( key ) ) {
      this.setWorksheetProperty( type, row, key, data[key] );
    }
  }
};

// CRUD operations for the worksheet properties.
this.setWorksheetProperty = function( type, row, key, value ) {
  row[key] = value;
};

this.getWorksheetProperty = function( type, row, key ) {
  return this.getWorksheet( type )[row][key];
};

this.deleteWorksheetProperty = function( type, row, key ) {
  var value = '';
  if ( key === 'grade' ) {
    value = null;
  }
  this.setWorksheetProperty( type, row, key, value );
};

// Utility methods.
this.setData = function( data ) {
  _dataStore = data;
};

this.getData = function() {
  return _dataStore;
};

function findRowById( worksheetRows, rowID ) {
  var idx;
  for ( var i = 0; i < worksheetRows.length; i++ ) {
    if ( worksheetRows[i].uid === rowID ) {
      idx = i;
    }
  }
  return idx;
}

// Data manipulation.

this.combineGoals = function() {
  // TODO: when financial goals are added:
  return this.getWorksheet( 'personal' ).concat( this.getWorksheet( 'financial' ) ) || [];
};

this.filterEmptyRows = function( worksheet, opts ) {
  // Filters out worksheet rows without text values
  // opts.requireGrade = true will also filter out items without grades
  // opts.skipLast = true will allow blank values for last item
  // TODO: add delete option?
  var filteredWorksheet = [];
  var len = worksheet.length - 1;
  var i = 0;
  var item;
  opts = opts || {};

  function isEmpty( item, lastItem ) {
    if ( lastItem && opts.skipLast ) { return false; }
    if ( !item.text ) { return true; }
    if ( opts.requireGrade && ( !item.grade && item.grade !== 0 ) ) {
      return true;
    }

    return false;
  }

  for ( i; i <= len; i++ ) {
    item = worksheet[i];
    if ( !isEmpty( item, i === len ) ) {
      filteredWorksheet.push( item );
    }
  }

  return filteredWorksheet;
};

this.sortWorksheetByGrade = function( worksheet, type ) {
  var sorted = [];
  var labels = _config.gradeSummaryLabels[type];
  var lenLabels = labels.length;
  var lenWorksheet = worksheet.length;
  var i = 0;
  var l = 0;

  // Add an item to the 'sorted' array for each of the grade labels.
  for ( l; l < lenLabels; l++ ) {
    sorted[l] = { title: labels[l], items: [], type: type };
  }

  // Add each graded worksheet row to the appropriate grade bucket.
  for ( i; i < lenWorksheet; i++ ) {
    var item = worksheet[i];
    var grade = item.grade;
    // if there's an object for this grade, add this item to its items array
    ( ( sorted[grade] || {} ).items || [] ).push( item );
  }

  return sorted;
};

// Private methods.
function _getDefaultRow() {
  return _config.getWorksheetRowDefaults();
}