<commit_before>/* @flow  */
/**
 * @jsx React.DOM

 */
'use strict';

var React           = require('react');
var joinClasses      = require('classnames');
var Cell            = require('./Cell');
var cloneWithProps  = require('react/lib/cloneWithProps');
var ColumnMetrics   = require('./ColumnMetrics');
var ColumnUtilsMixin  = require('./ColumnUtils');

type RowPropsType = {
  height: number;
  idx: number;
  columns: any;
  row: any;
  cellRenderer: ?any;
  isSelected: ?boolean;
};

type cellProps = {
  props: {
    selected: {rowIdx: number};
    dragged: {complete: bool; rowIdx: number};
    copied: { rowIdx: number};
  }
};

var Row = React.createClass({

  propTypes: {
    height: React.PropTypes.number.isRequired,
    columns: React.PropTypes.oneOfType([React.PropTypes.object, React.PropTypes.array]).isRequired,
    row: React.PropTypes.object.isRequired,
    cellRenderer: React.PropTypes.func,
    isSelected: React.PropTypes.bool,
    idx : React.PropTypes.number.isRequired,
    expandedRows : React.PropTypes.arrayOf(React.PropTypes.object)
  },

  mixins: [ColumnUtilsMixin],

  render(): ?ReactElement {
    var className = joinClasses(
      'react-grid-Row',
      "react-grid-Row--${this.props.idx % 2 === 0 ? 'even' : 'odd'}"
    );

    var style = {
      height: this.getRowHeight(this.props),
      overflow: 'hidden'
    };

    var cells = this.getCells();
    return (
      <div {...this.props} className={className} style={style} onDragEnter={this.handleDragEnter}>
        {React.isValidElement(this.props.row) ?
          this.props.row : cells}
      </div>
    );
  },

  getCells(): Array<ReactElement> {
    var cells = [];
    var lockedCells = [];
    var selectedColumn = this.getSelectedColumn();

    this.props.columns.forEach((column, i) => {

      var CellRenderer = this.props.cellRenderer;
      var cell = <CellRenderer
                    ref={i}
                    key={i}
                    idx={i}
                    rowIdx={this.props.idx}
                    value={this.getCellValue(column.key || i)}
                    column={column}
                    height={this.getRowHeight()}
                    formatter={column.formatter}
                    cellMetaData={this.props.cellMetaData}
                    rowData={this.props.row}
                    selectedColumn={selectedColumn}
                    isRowSelected={this.props.isSelected} />
      if (column.locked) {
        lockedCells.push(cell);
      } else {
        cells.push(cell);
      }
    });

    return cells.concat(lockedCells);
  },

  getRowHeight(): number {
    var rows = this.props.expandedRows || null;
    if(rows && this.props.key) {
      var row = rows[this.props.key] || null;
      if(row) {
        return row.height;
      }
    }
    return this.props.height;
  },

  getCellValue(key: number | string): any {
    var val;
    if(key === 'select-row'){
      return this.props.isSelected;
    } else if (typeof this.props.row.get === 'function') {
      val = this.props.row.get(key);
    }
    else {
      var val = this.props.row[key];
    }
    return !val ? '' : val;
  },

  getRowData(){
    return this.props.row.toJSON ? this.props.row.toJSON() : this.props.row;
  },

  getDefaultProps(): {cellRenderer: Cell} {
    return {
      cellRenderer: Cell,
      isSelected: false,
      height : 35
    };
  },

  setScrollLeft(scrollLeft: number) {
    this.props.columns.forEach( (column, i) => {
      if (column.locked) {
        this.refs[i].setScrollLeft(scrollLeft);
      }
    });
  },

  doesRowContainSelectedCell(props: any): boolean{
    var selected = props.cellMetaData.selected;
    if(selected && selected.rowIdx === props.idx){
      return true;
    }else{
      return false;
    }
  },

  willRowBeDraggedOver(props: any): boolean{
    var dragged = props.cellMetaData.dragged;
    return  dragged != null && (dragged.rowIdx>=0 || dragged.complete === true);
  },

  hasRowBeenCopied(): boolean{
    var copied = this.props.cellMetaData.copied;
    return copied != null && copied.rowIdx === this.props.idx;
  },

  shouldComponentUpdate(nextProps: any, nextState: any): boolean {
    return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) ||
    this.doesRowContainSelectedCell(this.props)          ||
    this.doesRowContainSelectedCell(nextProps)           ||
    this.willRowBeDraggedOver(nextProps)                 ||
    nextProps.row !== this.props.row                     ||
    this.hasRowBeenCopied()                              ||
    this.props.isSelected !== nextProps.isSelected       ||
    nextProps.height !== this.props.height;
  },

  handleDragEnter(){
    var handleDragEnterRow = this.props.cellMetaData.handleDragEnterRow;
    if(handleDragEnterRow){
      handleDragEnterRow(this.props.idx);
    }
  },

  getSelectedColumn(){
    var selected = this.props.cellMetaData.selected;
    if(selected && selected.idx){
      return this.getColumn(this.props.columns, selected.idx);
    }
  }

});

module.exports = Row;
<commit_msg>Null check<commit_after>/* @flow  */
/**
 * @jsx React.DOM

 */
'use strict';

var React           = require('react');
var joinClasses      = require('classnames');
var Cell            = require('./Cell');
var cloneWithProps  = require('react/lib/cloneWithProps');
var ColumnMetrics   = require('./ColumnMetrics');
var ColumnUtilsMixin  = require('./ColumnUtils');

type RowPropsType = {
  height: number;
  idx: number;
  columns: any;
  row: any;
  cellRenderer: ?any;
  isSelected: ?boolean;
};

type cellProps = {
  props: {
    selected: {rowIdx: number};
    dragged: {complete: bool; rowIdx: number};
    copied: { rowIdx: number};
  }
};

var Row = React.createClass({

  propTypes: {
    height: React.PropTypes.number.isRequired,
    columns: React.PropTypes.oneOfType([React.PropTypes.object, React.PropTypes.array]).isRequired,
    row: React.PropTypes.object.isRequired,
    cellRenderer: React.PropTypes.func,
    isSelected: React.PropTypes.bool,
    idx : React.PropTypes.number.isRequired,
    expandedRows : React.PropTypes.arrayOf(React.PropTypes.object)
  },

  mixins: [ColumnUtilsMixin],

  render(): ?ReactElement {
    var className = joinClasses(
      'react-grid-Row',
      "react-grid-Row--${this.props.idx % 2 === 0 ? 'even' : 'odd'}"
    );

    var style = {
      height: this.getRowHeight(this.props),
      overflow: 'hidden'
    };

    var cells = this.getCells();
    return (
      <div {...this.props} className={className} style={style} onDragEnter={this.handleDragEnter}>
        {React.isValidElement(this.props.row) ?
          this.props.row : cells}
      </div>
    );
  },

  getCells(): Array<ReactElement> {
    var cells = [];
    var lockedCells = [];
    var selectedColumn = this.getSelectedColumn();

    this.props.columns.forEach((column, i) => {

      var CellRenderer = this.props.cellRenderer;
      var cell = <CellRenderer
                    ref={i}
                    key={i}
                    idx={i}
                    rowIdx={this.props.idx}
                    value={this.getCellValue(column.key || i)}
                    column={column}
                    height={this.getRowHeight()}
                    formatter={column.formatter}
                    cellMetaData={this.props.cellMetaData}
                    rowData={this.props.row}
                    selectedColumn={selectedColumn}
                    isRowSelected={this.props.isSelected} />
      if (column.locked) {
        lockedCells.push(cell);
      } else {
        cells.push(cell);
      }
    });

    return cells.concat(lockedCells);
  },

  getRowHeight(): number {
    var rows = this.props.expandedRows || null;
    if(rows && this.props.key) {
      var row = rows[this.props.key] || null;
      if(row) {
        return row.height;
      }
    }
    return this.props.height;
  },

  getCellValue(key: number | string): any {
    var val;
    if(key === 'select-row'){
      return this.props.isSelected;
    } else if (typeof this.props.row.get === 'function') {
      val = this.props.row.get(key);
    }
    else {
      var val = this.props.row[key];
    }
    return !val ? '' : val;
  },

  getRowData(){
    return this.props.row.toJSON ? this.props.row.toJSON() : this.props.row;
  },

  getDefaultProps(): {cellRenderer: Cell} {
    return {
      cellRenderer: Cell,
      isSelected: false,
      height : 35
    };
  },

  setScrollLeft(scrollLeft: number) {
    this.props.columns.forEach( (column, i) => {
      if (column.locked) {
        if(!this.refs[i]) return;
        this.refs[i].setScrollLeft(scrollLeft);
      }
    });
  },

  doesRowContainSelectedCell(props: any): boolean{
    var selected = props.cellMetaData.selected;
    if(selected && selected.rowIdx === props.idx){
      return true;
    }else{
      return false;
    }
  },

  willRowBeDraggedOver(props: any): boolean{
    var dragged = props.cellMetaData.dragged;
    return  dragged != null && (dragged.rowIdx>=0 || dragged.complete === true);
  },

  hasRowBeenCopied(): boolean{
    var copied = this.props.cellMetaData.copied;
    return copied != null && copied.rowIdx === this.props.idx;
  },

  shouldComponentUpdate(nextProps: any, nextState: any): boolean {
    return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) ||
    this.doesRowContainSelectedCell(this.props)          ||
    this.doesRowContainSelectedCell(nextProps)           ||
    this.willRowBeDraggedOver(nextProps)                 ||
    nextProps.row !== this.props.row                     ||
    this.hasRowBeenCopied()                              ||
    this.props.isSelected !== nextProps.isSelected       ||
    nextProps.height !== this.props.height;
  },

  handleDragEnter(){
    var handleDragEnterRow = this.props.cellMetaData.handleDragEnterRow;
    if(handleDragEnterRow){
      handleDragEnterRow(this.props.idx);
    }
  },

  getSelectedColumn(){
    var selected = this.props.cellMetaData.selected;
    if(selected && selected.idx){
      return this.getColumn(this.props.columns, selected.idx);
    }
  }

});

module.exports = Row;
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            html: {
                files: ['public/views/**'],
                options: {
                    livereload: true,
                },
            },
            js: {
                files: ['public/js/**'],
                options: {
                    livereload: true,
                },
            },
            css: {
                files: ['public/sass/**'],
                tasks: ['compass'],
                options: {
                    livereload: true,
                },
            }
        },
        jshint: {
            all: ['gruntfile.js']
        },
        compass: { // Task
            dist: { // Target
                options: { // Target options
                    sassDir: 'public/sass',
                    cssDir: 'public/css',
                    environment: 'production'
                }
            },
            dev: { // Another target
                options: {
                    sassDir: 'public/sass',
                    cssDir: 'public/css'
                }
            }
        },
        nodemon: {
            dev: {
                options: {
                    file: 'server.js',
                    args: [],
                    ignoredFiles: ['README.md', 'node_modules/**', '.DS_Store'],
                    watchedExtensions: ['js'],
                    watchedFolders: ['app', 'config'],
                    debug: true,
                    delayTime: 1,
                    env: {
                        PORT: 3000
                    },
                    cwd: __dirname
                }
            },
            exec: {
                options: {
                    exec: 'less'
                }
            }
        },
        concurrent: {
            target: {
                tasks: ['nodemon', 'watch'],
                options: {
                    logConcurrentOutput: true
                }
            }
        }
    });

    // Load NPM tasks
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-nodemon');
    grunt.loadNpmTasks('grunt-concurrent');

    // Default task(s).
    grunt.registerTask('default', ['jshint', 'compass', 'concurrent:target']);
};<commit_msg>Disabled compass until dependency issues are resolved<commit_after>module.exports = function(grunt) {
    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            html: {
                files: ['public/views/**'],
                options: {
                    livereload: true,
                },
            },
            js: {
                files: ['public/js/**'],
                options: {
                    livereload: true,
                },
            },
            css: {
                files: ['public/sass/**'],
                tasks: ['compass'],
                options: {
                    livereload: true,
                },
            }
        },
        jshint: {
            all: ['gruntfile.js']
        },
        compass: { // Task
            dist: { // Target
                options: { // Target options
                    sassDir: 'public/sass',
                    cssDir: 'public/css',
                    environment: 'production'
                }
            },
            dev: { // Another target
                options: {
                    sassDir: 'public/sass',
                    cssDir: 'public/css'
                }
            }
        },
        nodemon: {
            dev: {
                options: {
                    file: 'server.js',
                    args: [],
                    ignoredFiles: ['README.md', 'node_modules/**', '.DS_Store'],
                    watchedExtensions: ['js'],
                    watchedFolders: ['app', 'config'],
                    debug: true,
                    delayTime: 1,
                    env: {
                        PORT: 3000
                    },
                    cwd: __dirname
                }
            },
            exec: {
                options: {
                    exec: 'less'
                }
            }
        },
        concurrent: {
            target: {
                tasks: ['nodemon', 'watch'],
                options: {
                    logConcurrentOutput: true
                }
            }
        }
    });

    // Load NPM tasks
    // grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-nodemon');
    grunt.loadNpmTasks('grunt-concurrent');

    // Default task(s).
    grunt.registerTask('default', ['jshint', 'concurrent:target']);
};<|endoftext|>


<commit_before>/* global console, module, require */
module.exports = function(__grunt){
	//--show run time
	require('time-grunt')(__grunt);

	//--autoload grunt tasks package.json
	require('load-grunt-tasks')(__grunt);

	//--path configuration
	var __paths = {
		project: '.'
	};
	//--src
	__paths.src = __paths.project + '/src';
	__paths.build = __paths.src + '/build';
	__paths.lib = __paths.src + '/lib';
	__paths.webSrc = __paths.src + '/web';
	//---assets
	__paths.assets = __paths.src;
	__paths.stylesSrc = __paths.assets + '/styles';
	__paths.stylesBuildsSrc = __paths.stylesSrc + '/builds';
	__paths.scriptsSrc = __paths.assets + '/scripts';
	//--web
	__paths.webRoot = __paths.project + '/web';
	__paths.assetsTarget = __paths.webRoot + '/_';
	__paths.scriptsTarget = __paths.assetsTarget + '/scripts';
	__paths.scriptsDev = __paths.scriptsTarget + '/dev';
	__paths.scriptsProd = __paths.scriptsTarget + '/prod';
	__paths.stylesTarget = __paths.assetsTarget + '/styles';
	__paths.stylesDev = __paths.stylesTarget + '/dev';
	__paths.stylesProd = __paths.stylesTarget + '/prod';

	//-# for test
	__paths.views = __paths.src + '/views';

	//--grunt config
	__grunt.initConfig({
		autoprefixer: {
			dev: {
				options: {
					browsers: ['last 4 versions', '> 1%', 'ie >= 7', 'ff >= 3']
				}
				,src: __paths.stylesDev + '/**/*.css'
			}
			,prod: {
				options: {
					browsers: ['last 4 versions', '> 1%', 'ie >= 7', 'ff >= 3']
				}
				,src: __paths.stylesProd + '/**/*.css'
			}
		}
		,clean: {
			web: [__paths.webRoot]
		}
		,sass: {
			options: {
				require: ['sass-css-importer', 'sass-globbing']
				,unixNewlines: true
			}
			,dev: {
				files: [{
					cwd: __paths.stylesBuildsSrc
					,dest: __paths.stylesDev
					,expand: true
					,ext: '.css'
					,extDot: 'last'
					,src: ['**/*.scss']
				}]
				,options: {
					lineNumbers: true
					,style: 'nested'
				}
			}
			,prod: {
				files: [{
					cwd: __paths.stylesBuildsSrc
					,dest: __paths.stylesProd
					,expand: true
					,ext: '.css'
					,extDot: 'last'
					,src: ['**/*.scss']
				}]
				,options: {
					style: 'compressed'
				}
			}
		}
		,symlink: {
			options: {
				overwrite: true
			}
			,devJS: {
				dest: __paths.scriptsDev
				,overwrite: true
				,src: __paths.scriptsSrc
			}
			,libDev: {
				dest: __paths.assetsTarget + '/lib'
				,overwrite: true
				,src: __paths.lib
			}
			,libDevForRequire: {
				dest: __paths.scriptsTarget + '/lib'
				,overwrite: true
				,src: __paths.lib
			}
			,web: {
				cwd: __paths.webSrc
				,dest: __paths.webRoot
				,dot: true
				,expand: true
				,overwrite: true
				,src: '**/*'
			}
		}
		,jshint: {
			options: {
				jshintrc: './.jshintrc'
			}
			,all: [
				'Gruntfile.js'
				,__paths.scriptsSrc
			]
		}
		,requirejs: {
			require: {
				options: {
					baseUrl: __paths.scriptsSrc
					,optimize: 'uglify2'
					,include: ['../../node_modules/almond/almond', 'builds/main']
					,mainConfigFile: __paths.scriptsSrc + '/config/main.js'
					,out: __paths.scriptsProd + '/main.js'
					,wrap: {
						startFile: __paths.build + '/scripts/wrap.start.js'
						,endFile: __paths.build + '/scripts/wrap.end.js'
					}
					,wrapShim: true
				}
			}
		}
		,watch: {
			css: {
				files: [{
					extDot: 'last'
					,src: [__paths.stylesSrc + '/**/*.scss']
				}]
				,tasks: ['build:css:dev']
			}
			,js: {
				files: [{
					extDot: 'last'
					,src: [__paths.scriptsSrc + '/**/*.js']
				}]
				,tasks: ['lint', 'build:js']
			}
			,prod: {
				files: [{
					extDot: 'last'
					,src: [
						__paths.scriptsSrc
						,__paths.stylesSrc
					]
				}]
				,tasks: [
					'build:css:prod'
					,'build:js:prod'
				]
			}
		}
	});

	//--tasks
	/*---
	convenient configuration map of all tasks to register
	key is name of task
	value is either a map or an array of tasks or a function to run
		Map: can have two keys, 'value' and 'description'.  'description' is optional description of task.  'value' is either an array of tasks or a function to run
		Something Else: will be used as the 'value' equivalent of the map
	*/
	var __tasks = {
		'default': function(){
			console.log('available commands:\n', Object.keys(__tasks).toString().replace(/,/g, ', '));
		}
		,'all': {
			description: 'Run hinting and, if succesful, build css and js for production'
			,value: [
				'hint'
				,'build:prod'
			]
		}
		,'build:css': [
			'build:css:dev'
		]
		,'build:css:dev': [
			'build:web'
			,'sass:dev'
			,'autoprefixer:dev'
		]
		,'build:css:prod': [
			'build:web'
			,'sass:prod'
			,'autoprefixer:prod'
		]
		,'build:dev': [
			'build:css:dev'
			,'build:js:dev'
		]
		,'build:js': [
			'build:web'
			,'requirejs:require'
		]
		,'build:js:dev': [
			'build:web'
			,'symlink:devJS'
			,'symlink:libDev'
			,'symlink:libDevForRequire'
		]
		,'build:js:prod': [
			'lint'
			,'build:js'
		]
		,'build:prod': [
			'build:css:prod'
			,'build:js:prod'
		]
		,'build:web': [
			'symlink:web'
		]
		,'lint': [
			'jshint'
		]
		,'watch:dev': [
			'watch:css'
			,'watch:js'
		]

		//-# for test
		,'test:build': [
			'build:dev'
			,'build:prod'
			,'test:views'
		]
		,'test:views': function(){
			var fs = require('fs');
			var swig = require('swig');
			var _data = {
				app: {
					devName: 'Toby Mackenzie'
					,devUrl: 'http://www.tobymackenzie.com'
					,devYears: '2014'
					,environment: 'dev'
				}
				,doc: {
					aside: 'Sit amet lorem nonummy.'
					,charset: 'utf-8'
					,content: 'Lorem ipsum dolor sit amet.  Nonummy.  Nonummy nonummy nonummy.'
					,description: 'This is a test'
					,keywords: 'test,html,boilerplate'
					,lang: 'en'
					,name: 'test'
					,styles: undefined
					,title: 'Test'
				}
				,site: {
					isResponsive: true
					,name: 'Test'
					,nav: [
						{
							name: 'Dev'
							,subNav: [
								{
									name: 'html'
									,url: 'index.dev.html'
								}
								,{
									name: 'json'
									,url: 'index.dev.json'
								}
							]
						}
						,{
							name: 'Prod'
							,subNav: [
								{
									name: 'html'
									,url: 'index.html'
								}
								,{
									name: 'json'
									,url: 'index.json'
								}
							]
						}
						,
					]
					,title: 'Test Site'
				}
			};
			fs.writeFileSync(__paths.webRoot + '/index.dev.html', swig.renderFile(__paths.views + '/skeletons/site.html.twig', _data));
			fs.writeFileSync(__paths.webRoot + '/index.dev.json', swig.renderFile(__paths.views + '/skeletons/site.json.twig', _data));
			_data.app.environment = 'prod';
			fs.writeFileSync(__paths.webRoot + '/index.html', swig.renderFile(__paths.views + '/skeletons/site.html.twig', _data));
			fs.writeFileSync(__paths.webRoot + '/index.json', swig.renderFile(__paths.views + '/skeletons/site.json.twig', _data));
		}
	};
	//---loop through all tasks, registering each
	var _item;
	for(var _key in __tasks){
		if(__tasks.hasOwnProperty(_key)){
			//--items are objects or are converted to them
			_item = __tasks[_key];
			if(_item instanceof Array || typeof _item === 'function'){
				_item = {
					value: _item
				};
			}
			if(_item.description){
				__grunt.registerTask(_key, _item.description, _item.value);
			}else{
				__grunt.registerTask(_key, _item.value);
			}
		}
	}
};
<commit_msg>styles: support '.sass' files<commit_after>/* global console, module, require */
module.exports = function(__grunt){
	//--show run time
	require('time-grunt')(__grunt);

	//--autoload grunt tasks package.json
	require('load-grunt-tasks')(__grunt);

	//--path configuration
	var __paths = {
		project: '.'
	};
	//--src
	__paths.src = __paths.project + '/src';
	__paths.build = __paths.src + '/build';
	__paths.lib = __paths.src + '/lib';
	__paths.webSrc = __paths.src + '/web';
	//---assets
	__paths.assets = __paths.src;
	__paths.stylesSrc = __paths.assets + '/styles';
	__paths.stylesBuildsSrc = __paths.stylesSrc + '/builds';
	__paths.scriptsSrc = __paths.assets + '/scripts';
	//--web
	__paths.webRoot = __paths.project + '/web';
	__paths.assetsTarget = __paths.webRoot + '/_';
	__paths.scriptsTarget = __paths.assetsTarget + '/scripts';
	__paths.scriptsDev = __paths.scriptsTarget + '/dev';
	__paths.scriptsProd = __paths.scriptsTarget + '/prod';
	__paths.stylesTarget = __paths.assetsTarget + '/styles';
	__paths.stylesDev = __paths.stylesTarget + '/dev';
	__paths.stylesProd = __paths.stylesTarget + '/prod';

	//-# for test
	__paths.views = __paths.src + '/views';

	//--grunt config
	__grunt.initConfig({
		autoprefixer: {
			dev: {
				options: {
					browsers: ['last 4 versions', '> 1%', 'ie >= 7', 'ff >= 3']
				}
				,src: __paths.stylesDev + '/**/*.css'
			}
			,prod: {
				options: {
					browsers: ['last 4 versions', '> 1%', 'ie >= 7', 'ff >= 3']
				}
				,src: __paths.stylesProd + '/**/*.css'
			}
		}
		,clean: {
			web: [__paths.webRoot]
		}
		,sass: {
			options: {
				require: ['sass-css-importer', 'sass-globbing']
				,unixNewlines: true
			}
			,dev: {
				files: [{
					cwd: __paths.stylesBuildsSrc
					,dest: __paths.stylesDev
					,expand: true
					,ext: '.css'
					,extDot: 'last'
					,src: ['**/*.s{a,c}ss']
				}]
				,options: {
					lineNumbers: true
					,style: 'nested'
				}
			}
			,prod: {
				files: [{
					cwd: __paths.stylesBuildsSrc
					,dest: __paths.stylesProd
					,expand: true
					,ext: '.css'
					,extDot: 'last'
					,src: ['**/*.s{a,c}ss']
				}]
				,options: {
					style: 'compressed'
				}
			}
		}
		,symlink: {
			options: {
				overwrite: true
			}
			,devJS: {
				dest: __paths.scriptsDev
				,overwrite: true
				,src: __paths.scriptsSrc
			}
			,libDev: {
				dest: __paths.assetsTarget + '/lib'
				,overwrite: true
				,src: __paths.lib
			}
			,libDevForRequire: {
				dest: __paths.scriptsTarget + '/lib'
				,overwrite: true
				,src: __paths.lib
			}
			,web: {
				cwd: __paths.webSrc
				,dest: __paths.webRoot
				,dot: true
				,expand: true
				,overwrite: true
				,src: '**/*'
			}
		}
		,jshint: {
			options: {
				jshintrc: './.jshintrc'
			}
			,all: [
				'Gruntfile.js'
				,__paths.scriptsSrc
			]
		}
		,requirejs: {
			require: {
				options: {
					baseUrl: __paths.scriptsSrc
					,optimize: 'uglify2'
					,include: ['../../node_modules/almond/almond', 'builds/main']
					,mainConfigFile: __paths.scriptsSrc + '/config/main.js'
					,out: __paths.scriptsProd + '/main.js'
					,wrap: {
						startFile: __paths.build + '/scripts/wrap.start.js'
						,endFile: __paths.build + '/scripts/wrap.end.js'
					}
					,wrapShim: true
				}
			}
		}
		,watch: {
			css: {
				files: [{
					extDot: 'last'
					,src: [__paths.stylesSrc + '/**/*.s{a,c}ss']
				}]
				,tasks: ['build:css:dev']
			}
			,js: {
				files: [{
					extDot: 'last'
					,src: [__paths.scriptsSrc + '/**/*.js']
				}]
				,tasks: ['lint', 'build:js']
			}
			,prod: {
				files: [{
					extDot: 'last'
					,src: [
						__paths.scriptsSrc
						,__paths.stylesSrc
					]
				}]
				,tasks: [
					'build:css:prod'
					,'build:js:prod'
				]
			}
		}
	});

	//--tasks
	/*---
	convenient configuration map of all tasks to register
	key is name of task
	value is either a map or an array of tasks or a function to run
		Map: can have two keys, 'value' and 'description'.  'description' is optional description of task.  'value' is either an array of tasks or a function to run
		Something Else: will be used as the 'value' equivalent of the map
	*/
	var __tasks = {
		'default': function(){
			console.log('available commands:\n', Object.keys(__tasks).toString().replace(/,/g, ', '));
		}
		,'all': {
			description: 'Run hinting and, if succesful, build css and js for production'
			,value: [
				'hint'
				,'build:prod'
			]
		}
		,'build:css': [
			'build:css:dev'
		]
		,'build:css:dev': [
			'build:web'
			,'sass:dev'
			,'autoprefixer:dev'
		]
		,'build:css:prod': [
			'build:web'
			,'sass:prod'
			,'autoprefixer:prod'
		]
		,'build:dev': [
			'build:css:dev'
			,'build:js:dev'
		]
		,'build:js': [
			'build:web'
			,'requirejs:require'
		]
		,'build:js:dev': [
			'build:web'
			,'symlink:devJS'
			,'symlink:libDev'
			,'symlink:libDevForRequire'
		]
		,'build:js:prod': [
			'lint'
			,'build:js'
		]
		,'build:prod': [
			'build:css:prod'
			,'build:js:prod'
		]
		,'build:web': [
			'symlink:web'
		]
		,'lint': [
			'jshint'
		]
		,'watch:dev': [
			'watch:css'
			,'watch:js'
		]

		//-# for test
		,'test:build': [
			'build:dev'
			,'build:prod'
			,'test:views'
		]
		,'test:views': function(){
			var fs = require('fs');
			var swig = require('swig');
			var _data = {
				app: {
					devName: 'Toby Mackenzie'
					,devUrl: 'http://www.tobymackenzie.com'
					,devYears: '2014'
					,environment: 'dev'
				}
				,doc: {
					aside: 'Sit amet lorem nonummy.'
					,charset: 'utf-8'
					,content: 'Lorem ipsum dolor sit amet.  Nonummy.  Nonummy nonummy nonummy.'
					,description: 'This is a test'
					,keywords: 'test,html,boilerplate'
					,lang: 'en'
					,name: 'test'
					,styles: undefined
					,title: 'Test'
				}
				,site: {
					isResponsive: true
					,name: 'Test'
					,nav: [
						{
							name: 'Dev'
							,subNav: [
								{
									name: 'html'
									,url: 'index.dev.html'
								}
								,{
									name: 'json'
									,url: 'index.dev.json'
								}
							]
						}
						,{
							name: 'Prod'
							,subNav: [
								{
									name: 'html'
									,url: 'index.html'
								}
								,{
									name: 'json'
									,url: 'index.json'
								}
							]
						}
						,
					]
					,title: 'Test Site'
				}
			};
			fs.writeFileSync(__paths.webRoot + '/index.dev.html', swig.renderFile(__paths.views + '/skeletons/site.html.twig', _data));
			fs.writeFileSync(__paths.webRoot + '/index.dev.json', swig.renderFile(__paths.views + '/skeletons/site.json.twig', _data));
			_data.app.environment = 'prod';
			fs.writeFileSync(__paths.webRoot + '/index.html', swig.renderFile(__paths.views + '/skeletons/site.html.twig', _data));
			fs.writeFileSync(__paths.webRoot + '/index.json', swig.renderFile(__paths.views + '/skeletons/site.json.twig', _data));
		}
	};
	//---loop through all tasks, registering each
	var _item;
	for(var _key in __tasks){
		if(__tasks.hasOwnProperty(_key)){
			//--items are objects or are converted to them
			_item = __tasks[_key];
			if(_item instanceof Array || typeof _item === 'function'){
				_item = {
					value: _item
				};
			}
			if(_item.description){
				__grunt.registerTask(_key, _item.description, _item.value);
			}else{
				__grunt.registerTask(_key, _item.value);
			}
		}
	}
};
<|endoftext|>


<commit_before>/**
 * Copyright 2015 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import './polyfills';

import {historyFor} from './history';
import {viewerFor} from './viewer';

import {installAd} from '../builtins/amp-ad';
import {installImg} from '../builtins/amp-img';
import {installVideo} from '../builtins/amp-video';
import {installPixel} from '../builtins/amp-pixel';
import {installStyles} from './styles';
import {stubElements} from './custom-element';
import {adopt} from './runtime';
import {installExperimentalViewerIntegration} from './experimental-viewer-integration';
import {cssText} from '../build/css.js';
import {action} from './action';
import {maybeValidate} from './validator-integration';

historyFor(window);
viewerFor(window);

installAd(window);
installImg(window);
installPixel(window);
installVideo(window);

installStyles(document, cssText);
adopt(window);
stubElements(window);

action.addEvent('tap');

maybeValidate(window);

installExperimentalViewerIntegration();
<commit_msg>// Output a message to the console and add an attribute to the <html> // tag with version information that can be used in error reports. // (At least by sophisticated users).<commit_after>/**
 * Copyright 2015 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import './polyfills';

import {historyFor} from './history';
import {viewerFor} from './viewer';

import {installAd} from '../builtins/amp-ad';
import {installImg} from '../builtins/amp-img';
import {installVideo} from '../builtins/amp-video';
import {installPixel} from '../builtins/amp-pixel';
import {installStyles} from './styles';
import {stubElements} from './custom-element';
import {adopt} from './runtime';
import {installExperimentalViewerIntegration} from './experimental-viewer-integration';
import {cssText} from '../build/css.js';
import {action} from './action';
import {maybeValidate} from './validator-integration';

// Output a message to the console and add an attribute to the <html>
// tag to give some information that can be used in error reports.
// (At least by sophisticated users).
if (window.console) {
  (console.info || console.log).call(console,
      'Powered by AMP ⚡ HTML – Version $internalRuntimeVersion$');
  document.documentElement.setAttribute('amp-version',
      '$internalRuntimeVersion$');
}

historyFor(window);
viewerFor(window);

installAd(window);
installImg(window);
installPixel(window);
installVideo(window);

installStyles(document, cssText);
adopt(window);
stubElements(window);

action.addEvent('tap');

maybeValidate(window);

installExperimentalViewerIntegration();
<|endoftext|>


<commit_before>module.exports = function(grunt) { // Grunt wrapper - Do grunt-related things in here

  // Set a path for the development, staging and build folders.
  // The benifit of doing this is that when it comes time to start plugging in a cms we can just alter this to point to a new folder, for example the wordpress theme folder.
  var config = {
    src: 'src', // Devlopment files
    app: 'app', // Staging files
    dist: 'dist' // Build files
  };

  grunt.initConfig({ // Initialize our configuration object

    // Project settings
    config: config,

    pkg: grunt.file.readJSON('package.json'), // Read project settings from package.json

    // DANGER ZONE! BE CAREFUL!
    // This cleans the destination folder out completely.
    // This shouldn't matter if you are using the correct Bread and Butter workflow and only working in the src folder but only you and the lord above know if that is the case.
    clean: ['<%= config.app %>/**/*', '<%= config.app %>/.htaccess'],

    copy: {

      pages: {
        // This copies the pages from the src/pages folder to the app folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/pages/',
            src: ['*.php', '*.html', '.htaccess'],
            dest: '<%= config.app %>/'
          }
        ]
      },

      modules: {
        // This copies the modules from the src/modules folder to the app/modules folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/modules/',
            src: ['*.php'],
            dest: '<%= config.app %>/modules/'
          }
        ]
      },

      includes: {
        // This copies the includes from the src/includes folder to the app/includes folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/includes/',
            src: ['*.php'],
            dest: '<%= config.app %>/includes/'
          }
        ]
      },

      images: {
        // This copies the includes from the src/images folder to the app/images folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/images/',
            src: ['*.jpg', '*.png', '*.gif'],
            dest: '<%= config.app %>/images/'
          }
        ]
      },

      fontcopy:{
      // This task will find the relevant font files in the src/fonts folder and move them to the app/fonts folder.
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/fonts/',
            src: ['**/*.eot', '**/*.svg', '**/*.ttf', '**/*.woff'],
            dest: '<%= config.app %>/fonts/'
          }
        ]
      }
    },

    uglify: {

      // The base uglify task
      base: {
        options: {
          mangle: false,
          // If you want to add banners to your minified css uncomment the below. This currently is commented out in order to clean up commits in development.
          // banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: {
        '<%= config.app %>/js/custom.min.js': ['<%= config.src %>/js/custom.js']
        }
      },

    },

    jshint: {

      // The jshint task.
      files: [
      '<%= config.src %>/js/custom.js', // Just watch the src js file not the minified one
      ]
    },

    less: {

      // Configure the less task
      // The compilation of our css goes through three stages:
      // 1. We use this less task to compile the less to css in the src folder
      // 2. We use the auto-prefixer task to put prefixes for various browsers into our css file and move it to the app folder
      // 3. We use the cssmin task to minify that css file into a new file with the .min.css extension

      // So here we go...
      // 1. We use this less task to compile the less to css in the src folder
      development: {
        options: {
          paths: ["<%= config.src %>/less"],
        },
        files: {
          // target.css file: source.less file
          "<%= config.src %>/css/style.css": "<%= config.src %>/less/style.less"
        }
      }
    },

    autoprefixer: {

      // We use the auto-prefixer task to put prefixes for various browsers into our css file and move it to the app folder
      options: {
        browsers: ['last 3 versions'] // More options available for this see https://github.com/ai/autoprefixer#browsers
      },
      files: {
        src: '<%= config.src %>/css/style.css',
        dest: '<%= config.app %>/style.css' // Put the autoprefixed version right back over its original
      }
    },

    cssmin: {

      // We use the cssmin task to minify that css file into a new file with the .min.css extension
      minify: {
        options: {
          // If you want to add banners to your minified css uncomment the below. This currently is commented out in order to clean up commits in development.
          // banner: '/* <%= pkg.name %>.css minified <%= grunt.template.today("dd-mm-yyyy") %> */' // Give it a nice banner
        },
        files: {
          '<%= config.app %>/style.min.css': ['<%= config.app %>/style.css']
        }
      },

      // This task will find the stylesheet in the webkit folder, minify it and move it to the app folder
      fontmin: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/fonts/',
            src: ['**/*/stylesheet.css'],
            dest: '<%= config.app %>/fonts/',
            ext: '.min.css'
          }
        ]
      }
    },

    pixrem: {

      // We run pixrem on that file to create fallback for our use of rem units. We rewrite the result over itself.
      options: {
        rootvalue: '62.5%' // We set this so that the 1 rem unit equals 10px. Easier to understand.
      },
      dist: {
        src: '<%= config.app %>/style.min.css',
        dest: '<%= config.app %>/style.min.css'
      }
    },

    // This grabs all the listed bower dependancies and adds them to once vendor.js file
    bower_concat: {

      all: {
        dest: '<%= config.app %>/js/vendor.min.js'
      }
    },

    watch: {
    // Configure the watch task
    // You should adapt this to your specific needs on a per project basis
      pages: {
        files: ['src/pages/*.php'],
        tasks: ['copy:pages'],
      },
      modules: {
        files: ['src/modules/*.php'],
        tasks: ['copy:modules'],
      },
      includes: {
        files: ['src/includes/*.php'],
        tasks: ['copy:includes'],
      },
      images: {
        files: ['src/images/*'],
        tasks: ['copy:images'],
      },
      scripts: {
        files: ['<%= jshint.files %>'],
        tasks: ['jshint'],
      },
      uglify: {
        files: ['src/**/*.js'],
        tasks: ['uglify'],
      },
      css: {
        files: ['src/**/*.less'],
        tasks: ['less', 'autoprefixer', 'cssmin:minify'],
      },
      css: {
        files: ['src/**/*.less'],
        tasks: ['pixrem'],
      },
      livereload: {
        // Here we watch the files the watch task will change.
        // These files are then sent to the live reload server.
        options: { livereload: true },
        files: ['<%= config.app %>/**/*'],
      },
    }

  });

    // Auto load the grunt tasks
    require('load-grunt-tasks')(grunt);

    // Register a test task for jshint. This can be run just by typing "grunt test" on the command line
    grunt.registerTask('test', [
      'jshint'
    ]);

    //Register a task for setting up the webkit fonts when picking up the project
    grunt.registerTask('fontload', [
      'copy:fontcopy',
      'cssmin:fontmin'
    ]);

    grunt.registerTask('build', [
        'useminprepare',
        'concat',
        'uglify'
    ]);

    // And register the default task. This can be run just by typing "grunt" on the command line. This should be done before production.
    grunt.registerTask('default', [
      'copy:pages',
      'copy:modules',
      'copy:includes',
      'copy:images',
      'uglify',
      'less',
      'autoprefixer',
      'cssmin',
      //'pixrem'
    ]);

};<commit_msg>add uglify task to concat bower .js dependencies file<commit_after>module.exports = function(grunt) { // Grunt wrapper - Do grunt-related things in here

  // Set a path for the development, staging and build folders.
  // The benifit of doing this is that when it comes time to start plugging in a cms we can just alter this to point to a new folder, for example the wordpress theme folder.
  var config = {
    src: 'src', // Devlopment files
    app: 'app', // Staging files
    dist: 'dist' // Build files
  };

  grunt.initConfig({ // Initialize our configuration object

    // Project settings
    config: config,

    pkg: grunt.file.readJSON('package.json'), // Read project settings from package.json

    // DANGER ZONE! BE CAREFUL!
    // This cleans the destination folder out completely.
    // This shouldn't matter if you are using the correct Bread and Butter workflow and only working in the src folder but only you and the lord above know if that is the case.
    clean: ['<%= config.app %>/**/*', '<%= config.app %>/.htaccess'],

    copy: {

      pages: {
        // This copies the pages from the src/pages folder to the app folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/pages/',
            src: ['*.php', '*.html', '.htaccess'],
            dest: '<%= config.app %>/'
          }
        ]
      },

      modules: {
        // This copies the modules from the src/modules folder to the app/modules folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/modules/',
            src: ['*.php'],
            dest: '<%= config.app %>/modules/'
          }
        ]
      },

      includes: {
        // This copies the includes from the src/includes folder to the app/includes folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/includes/',
            src: ['*.php'],
            dest: '<%= config.app %>/includes/'
          }
        ]
      },

      images: {
        // This copies the includes from the src/images folder to the app/images folder
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/images/',
            src: ['*.jpg', '*.png', '*.gif'],
            dest: '<%= config.app %>/images/'
          }
        ]
      },

      fontcopy:{
      // This task will find the relevant font files in the src/fonts folder and move them to the app/fonts folder.
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/fonts/',
            src: ['**/*.eot', '**/*.svg', '**/*.ttf', '**/*.woff'],
            dest: '<%= config.app %>/fonts/'
          }
        ]
      }
    },

    uglify: {

      // The base uglify task
      base: {
        options: {
          mangle: false,
          // If you want to add banners to your minified css uncomment the below. This currently is commented out in order to clean up commits in development.
          // banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: {
        '<%= config.app %>/js/custom.min.js': ['<%= config.src %>/js/custom.js']
        }
      },

      bower: {
        options: {
          mangle: true,
          compress: true
        },
        files: {
          '<%= config.app %>/js/vendor.min.js': '<%= config.src %>/js/vendor.js'
        }
      }
    },

    jshint: {

      // The jshint task.
      files: [
      '<%= config.src %>/js/custom.js', // Just watch the src js file not the minified one
      ]
    },

    less: {

      // Configure the less task
      // The compilation of our css goes through three stages:
      // 1. We use this less task to compile the less to css in the src folder
      // 2. We use the auto-prefixer task to put prefixes for various browsers into our css file and move it to the app folder
      // 3. We use the cssmin task to minify that css file into a new file with the .min.css extension

      // So here we go...
      // 1. We use this less task to compile the less to css in the src folder
      development: {
        options: {
          paths: ["<%= config.src %>/less"],
        },
        files: {
          // target.css file: source.less file
          "<%= config.src %>/css/style.css": "<%= config.src %>/less/style.less"
        }
      }
    },

    autoprefixer: {

      // We use the auto-prefixer task to put prefixes for various browsers into our css file and move it to the app folder
      options: {
        browsers: ['last 3 versions'] // More options available for this see https://github.com/ai/autoprefixer#browsers
      },
      files: {
        src: '<%= config.src %>/css/style.css',
        dest: '<%= config.app %>/style.css' // Put the autoprefixed version right back over its original
      }
    },

    cssmin: {

      // We use the cssmin task to minify that css file into a new file with the .min.css extension
      minify: {
        options: {
          // If you want to add banners to your minified css uncomment the below. This currently is commented out in order to clean up commits in development.
          // banner: '/* <%= pkg.name %>.css minified <%= grunt.template.today("dd-mm-yyyy") %> */' // Give it a nice banner
        },
        files: {
          '<%= config.app %>/style.min.css': ['<%= config.app %>/style.css']
        }
      },

      // This task will find the stylesheet in the webkit folder, minify it and move it to the app folder
      fontmin: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/fonts/',
            src: ['**/*/stylesheet.css'],
            dest: '<%= config.app %>/fonts/',
            ext: '.min.css'
          }
        ]
      }
    },

    pixrem: {

      // We run pixrem on that file to create fallback for our use of rem units. We rewrite the result over itself.
      options: {
        rootvalue: '62.5%' // We set this so that the 1 rem unit equals 10px. Easier to understand.
      },
      dist: {
        src: '<%= config.app %>/style.min.css',
        dest: '<%= config.app %>/style.min.css'
      }
    },

    // This grabs all the listed bower dependancies and adds them to once vendor.js file
    bower_concat: {

      all: {
        dest: '<%= config.src %>/js/vendor.js'
      }
    },

    watch: {
    // Configure the watch task
    // You should adapt this to your specific needs on a per project basis
      pages: {
        files: ['src/pages/*.php'],
        tasks: ['copy:pages'],
      },
      modules: {
        files: ['src/modules/*.php'],
        tasks: ['copy:modules'],
      },
      includes: {
        files: ['src/includes/*.php'],
        tasks: ['copy:includes'],
      },
      images: {
        files: ['src/images/*'],
        tasks: ['copy:images'],
      },
      scripts: {
        files: ['<%= jshint.files %>'],
        tasks: ['jshint'],
      },
      uglify: {
        files: ['src/**/*.js'],
        tasks: ['uglify'],
      },
      css: {
        files: ['src/**/*.less'],
        tasks: ['less', 'autoprefixer', 'cssmin:minify'],
      },
      css: {
        files: ['src/**/*.less'],
        tasks: ['pixrem'],
      },
      livereload: {
        // Here we watch the files the watch task will change.
        // These files are then sent to the live reload server.
        options: { livereload: true },
        files: ['<%= config.app %>/**/*'],
      },
    }

  });

    // Auto load the grunt tasks
    require('load-grunt-tasks')(grunt);

    // Register a test task for jshint. This can be run just by typing "grunt test" on the command line
    grunt.registerTask('test', [
      'jshint'
    ]);

    // Register a task for setting up the webkit fonts when picking up the project
    grunt.registerTask('fontload', [
      'copy:fontcopy',
      'cssmin:fontmin'
    ]);

    // Registar a build task to concatenate all bower dependencies to one file and minify
    grunt.registerTask('build', [
      'bower_concat',
      'uglify:bower'
    ]);

    // And register the default task. This can be run just by typing "grunt" on the command line. This should be done before production.
    grunt.registerTask('default', [
      'copy:pages',
      'copy:modules',
      'copy:includes',
      'copy:images',
      'uglify',
      'less',
      'autoprefixer',
      'cssmin',
      //'pixrem'
    ]);

};<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';

const { Controller, computed, RSVP, inject, isPresent, isEmpty } = Ember;
const { sort, gt } = computed;
const { service } = inject;
const { PromiseArray } = DS;

export default Controller.extend({
  store: service(),
  flashMessages: service(),
  queryParams: ['offset', 'limit', 'filter', 'school'],
  offset: 0,
  limit: 25,
  filter: '',
  school: null,
  hasMoreThanOneSchool: gt('model.schools.length', 1),
  sortSchoolsBy:['title'],
  sortedSchools: sort('model.schools', 'sortSchoolsBy'),
  selectedSchool: computed('model.schools.[]', 'model.primarySchool', 'school', function(){
    let schools = this.get('model.schools');
    if(isPresent(this.get('school'))){
      let school =  schools.find(school => {
        return school.get('id') === this.get('school');
      });
      if(school){
        return school;
      }
    }
    return this.get('model.primarySchool');
  }),

  deletedUpdates: [],
  updatesBeingSaved: [],

  allUpdates: computed('selectedSchool', function(){
    let defer = RSVP.defer();
    let school = this.get('selectedSchool');
    this.get('store').query('pending-user-update', {
      limit: 1000,
      filters: {
        schools: [school.get('id')]
      }
    }).then(updates => {
      //preload user for each update
      RSVP.all(updates.mapBy('user')).then(() => {
        defer.resolve(updates);
      });
    });

    return PromiseArray.create({
      promise: defer.promise
    });
  }),

  displayedUpdates: computed('allUpdates.@each.user.fullName', 'filter', 'offset', 'limit', function(){
    const limit = this.get('limit');
    const offset = this.get('offset');
    const end = limit + offset;
    const filter = this.get('filter');
    const exp = new RegExp(filter, 'gi');

    return this.get('allUpdates')
      .sortBy('user.lastName', 'user.firstName')
      .slice(offset, end).filter(update => {
        return !this.get('deletedUpdates').contains(update) &&
        (isEmpty(update.get('user.fullName')) || update.get('user.fullName').match(exp));
      });
  }),
  actions: {
    changeSelectedSchool(schoolId){
      this.set('school', schoolId);
    },
    updateEmailAddress(update){
      this.get('updatesBeingSaved').pushObject(update);
      update.get('user').then(user => {
        user.set('email', update.get('value'));
        user.save().then(() => {
          update.deleteRecord();
          update.save().then(() => {
            this.get('deletedUpdates').pushObject(update);
            this.get('updatesBeingSaved').removeObject(update);
            this.get('flashMessages').success('general.savedSuccessfully');
          });
        });
      });
    },
    disableUser(update){
      this.get('updatesBeingSaved').pushObject(update);
      update.get('user').then(user => {
        user.set('enabled', false);
        user.save().then(() => {
          update.deleteRecord();
          update.save().then(() => {
            this.get('deletedUpdates').pushObject(update);
            this.get('updatesBeingSaved').removeObject(update);
            this.get('flashMessages').success('general.savedSuccessfully');

          });
        });
      });

    },
    excludeFromSync(update){
      this.get('updatesBeingSaved').pushObject(update);
      update.get('user').then(user => {
        user.set('userSyncIgnore', true);
        user.save().then(() => {
          update.deleteRecord();
          update.save().then(() => {
            this.get('deletedUpdates').pushObject(update);
            this.get('updatesBeingSaved').removeObject(update);
            this.get('flashMessages').success('general.savedSuccessfully');
          });
        });
      });

    }
  }
});
<commit_msg>Delete all update notices for a user when they are disabled<commit_after>import Ember from 'ember';
import DS from 'ember-data';

const { Controller, computed, RSVP, inject, isPresent, isEmpty } = Ember;
const { sort, gt } = computed;
const { service } = inject;
const { PromiseArray } = DS;

export default Controller.extend({
  store: service(),
  flashMessages: service(),
  queryParams: ['offset', 'limit', 'filter', 'school'],
  offset: 0,
  limit: 25,
  filter: '',
  school: null,
  hasMoreThanOneSchool: gt('model.schools.length', 1),
  sortSchoolsBy:['title'],
  sortedSchools: sort('model.schools', 'sortSchoolsBy'),
  selectedSchool: computed('model.schools.[]', 'model.primarySchool', 'school', function(){
    let schools = this.get('model.schools');
    if(isPresent(this.get('school'))){
      let school =  schools.find(school => {
        return school.get('id') === this.get('school');
      });
      if(school){
        return school;
      }
    }
    return this.get('model.primarySchool');
  }),

  deletedUpdates: [],
  updatesBeingSaved: [],

  allUpdates: computed('selectedSchool', function(){
    let defer = RSVP.defer();
    let school = this.get('selectedSchool');
    this.get('store').query('pending-user-update', {
      limit: 1000,
      filters: {
        schools: [school.get('id')]
      }
    }).then(updates => {
      //preload user for each update
      RSVP.all(updates.mapBy('user')).then(() => {
        defer.resolve(updates);
      });
    });

    return PromiseArray.create({
      promise: defer.promise
    });
  }),

  displayedUpdates: computed('allUpdates.@each.user.fullName', 'filter', 'offset', 'limit', function(){
    const limit = this.get('limit');
    const offset = this.get('offset');
    const end = limit + offset;
    const filter = this.get('filter');
    const exp = new RegExp(filter, 'gi');

    return this.get('allUpdates')
      .sortBy('user.lastName', 'user.firstName')
      .slice(offset, end).filter(update => {
        return !this.get('deletedUpdates').contains(update) &&
        (isEmpty(update.get('user.fullName')) || update.get('user.fullName').match(exp));
      });
  }),
  actions: {
    changeSelectedSchool(schoolId){
      this.set('school', schoolId);
    },
    updateEmailAddress(update){
      this.get('updatesBeingSaved').pushObject(update);
      update.get('user').then(user => {
        user.set('email', update.get('value'));
        user.save().then(() => {
          update.deleteRecord();
          update.save().then(() => {
            this.get('deletedUpdates').pushObject(update);
            this.get('updatesBeingSaved').removeObject(update);
            this.get('flashMessages').success('general.savedSuccessfully');
          });
        });
      });
    },
    disableUser(update){
      this.get('updatesBeingSaved').pushObject(update);
      update.get('user').then(user => {
        user.set('enabled', false);
        user.save().then(() => {
          user.get('pendingUserUpdates').then(updates => {
            updates.invoke('deleteRecord');
            RSVP.all(updates.invoke('save')).then(() => {
              this.get('deletedUpdates').pushObject(update);
              this.get('updatesBeingSaved').removeObject(update);
              this.get('flashMessages').success('general.savedSuccessfully');
            });
          });
        });
      });

    },
    excludeFromSync(update){
      this.get('updatesBeingSaved').pushObject(update);
      update.get('user').then(user => {
        user.set('userSyncIgnore', true);
        user.save().then(() => {
          user.get('pendingUserUpdates').then(updates => {
            updates.invoke('deleteRecord');
            RSVP.all(updates.invoke('save')).then(() => {
              this.get('deletedUpdates').pushObject(update);
              this.get('updatesBeingSaved').removeObject(update);
              this.get('flashMessages').success('general.savedSuccessfully');
            });
          });
        });
      });

    }
  }
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  /*
   * Include grunt configuration
   */
  var gruntConfig = require( './config/grunt.conf.js' );

  /*
   * Helpers (preparing for grunt util deprecation)
   */
  var glob = require('glob');

  /*
   * Time grunt execution
   */
  require('time-grunt')(grunt);

  /*
   * JIT Grunt will automatically load other npm tasks
   */
  require('jit-grunt')(grunt);
  grunt.loadNpmTasks('grunt-protractor-runner');

  /*
   * Configuration
   */
  var gruntTasks = {
    pkg: grunt.file.readJSON('package.json'),
    /*
     * Placed at the top of the compiled source files.
     * Use the 'banner' -> banner: '<%= meta.banner %>'
     *
     */
    meta: {
      banner:
        '/*\n' +
        ' * Compiled <%= grunt.template.today("yyyy-mm-dd") %>\n' +
        ' * Docs @ <%= pkg.repository.url %>\n' +
        ' */\n'
    },
    /*
     * The shell task can run handy shell commands.
     * To configure the dev/prod server check out the 'sh' files
     * in './server'.
     *
     */
    shell: {
      dev_server: {
        command: './server/build-server.sh'
      },
      prod_server: {
        command: './server/production-server.sh'
      },
      run_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager start'
      },
      update_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager update'
      }
    },
    /*
     * The copy task copies files for both build and compile
     * phases, as well as test files.
     *
     * 'build_index' will process the 'index.html' file and write
     * <script> tags for all files (modules or vendor scripts).
     *
     * 'compile_index' will process the 'index.html' file without
     * providing any scripts. In this case, a single script will
     * be included: 'app.min.js'.
     *
     * See './src/index.html' for more details.
     *
     */
    copy: {
      build_app_js: {
        src: [
          findModuleFilesIn('./src/app/'),
          findModuleFilesIn('./src/common/')
        ],
        dest: '<%= build_dir %>'
      },
      build_app_data: {
        src: ['./src/app/**/*.json'],
        dest: '<%= build_dir %>/data/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_unit: {
        src: ['./src/**/*.spec.js'],
        dest: '<%= build_dir %>'
      },
      build_vendor_js: {
        src: ['<%= build.vendor_js %>'],
        dest: '<%= build_dir %>'
      },
      build_views: {
        cwd: './src',
        src: ['app/**/*.html', '!app/shared/**/*.html'],
        dest: '<%= build_dir %>/views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_shared_views: {
        cwd: './src',
        src: ['app/shared/**/*.html'],
        dest: '<%= build_dir %>/shared-views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= build_dir %>',
        expand: true,
        options: {
          process: processBuildScripts
        }
      },
      build_assets: {
        cwd: './src/assets',
        src: [
          'img/**/*',
          'fonts/**/*',
          '!**/*.less',
          '!**/*.css'
        ],
        dest: '<%= build_dir %>src/assets/',
        expand: true
      },
      build_fonts: {
        src: ['<%= common.vendor_fonts %>'],
        dest: '<%= build_dir %>src/assets/fonts/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_karma: {
        src: ['./config/karma.conf.js'],
        dest: '<%= build_dir %>',
        options: {
          process: processBuildScripts
        }
      },
      build_protractor: {
        cwd: './src',
        src: ['**/*.protractor.js', '**/*.e2e.js'],
        dest: '<%= build_dir %>src/e2e/',
        expand: true,
        flatten: true
      },
      compile_app_data: {
        cwd: '<%= build_dir %>',
        src: ['data/*.json'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_views: {
        cwd: '<%= build_dir %>',
        src: ['views/**/*.html'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= compile_dir %>',
        expand: true,
        options: {
          process: function processCompileIndex(content){
            return grunt.template.process(content);
          }
        }
      },
      compile_app_assets: {
        cwd: '<%= build_dir %>',
        src: ['src/assets/**/*', '!src/assets/**/*.md'],
        dest: '<%= compile_dir %>',
        expand: true
      }
    },
    /*
     * The clean task is used to remove files / directories that
     * are used and not needed anymore.
     *
     * It's also used to remove the build directory before a new
     * compile, see 'build_clean' below.
     *
     */
    clean: {
      build_clean: ['<%= build_dir %>'],
      build_css_clean: ['<%= build_dir %>/src/assets/css/app.custom.css'],
      compile_js_clean: ['<%= compile_dir %>/src/app/modules.min.js'],
      compile_shared_views_clean: ['<%= compile_dir %>/shared-views/'],
      clean_samples: [
        './src/app/about/',
        './src/app/home/',
        './src/app/profile-feature/',
        './src/app//shared/profile-model'
      ]
    },
    /*
     * The less task compiles all less files.
     * They will be afterwards concatenated with vendor
     * stylesheet, see the 'cssmin' task.
     *
     */
    less: {
      build_less: {
        src: ['./src/assets/**/*.less'],
        dest: '<%= build_dir %>/src/assets/css/app.custom.css',
        options: {
          cleancss: true,
          compress: true
        }
      }
    },
    /*
     * The cssmin task minifies css files and merges them into a
     * single file (done during build).
     *
     */
    cssmin: {
      build_css: {
        src: [
          '<%= build.vendor_css %>',
          './src/assets/**/*.css',
          '<%= build_dir %>/src/assets/css/app.custom.css'
        ],
        dest: '<%= build_dir %>/src/assets/css/app.min.css',
        options: {
          keepSpecialComments: 0,
          banner: '<%= meta.banner %>'
        }
      }
    },
    /*
     * This task autoprefixes CSS
     * You won't have to ever add -webkit-, -moz-, etc
     * in your CSS files EVER!
     *
     */
    autoprefixer: {
      options: {
        browsers: ['> 1%']
      },
      build_autoprefix_css: {
        src: '<%= build_dir %>/src/assets/css/app.min.css',
        dest: '<%= build_dir %>/src/assets/css/app.min.css'
      }
    },
    /*
     * The uglify task mainly minifies and mangles module scripts.
     * After all scripts are concatenated, it minifies without
     * mangling to remove comments, line breaks, etc that come
     * from vendor scripts.
     *
     */
    uglify: {
      compile_module_js: {
        options: {
          wrap: 'moduleExports',
          mangle: {
            except: ['exceptionLoggingService']
          }
        },
        src: [
          '<%= compile.vendor_js %>',
          findModuleFilesIn('./build/src/app/'),
          findModuleFilesIn('./build/src/common/')
        ],
        dest: '<%= compile_dir %>/src/app/modules.min.js'
      },
      compile_soft_uglify: {
        options: {
          mangle: false,
          banner: '<%= meta.banner %>'
        },
        src: ['<%= compile_dir %>/src/app/app.min.js'],
        dest: '<%= compile_dir %>/src/app/app.min.js'
      }
    },
    /*
     * The concat task is used in the compile phase to merge all
     * scripts into one.
     *
     */
    concat: {
      compile_js: {
        src: [
          '<%= compile.vendor_min_js %>',
          '<%= compile_dir %>/src/app/modules.min.js',
          '<%= compile_dir %>/shared-views/views.min.js'
        ],
        dest: '<%= compile_dir %>/src/app/app.min.js',
        options: {
          banner: '<%= meta.banner %>'
        }
      }
    },
    /*
     * The html2js task is used to convert all shared views into a module
     * that adds them to $templateCache. It also minifies HTML
     * markup.
     *
     */
    html2js: {
      options: {
        htmlmin: {
          collapseBooleanAttributes: false,
          collapseWhitespace: true,
          removeAttributeQuotes: false,
          removeComments: true,
          removeEmptyAttributes: false,
          removeRedundantAttributes: true,
          removeScriptTypeAttributes: true,
          removeStyleLinkTypeAttributes: true
        }
      },
      compile_shared_views: {
        src: ['<%= build_dir %>/shared-views/**/*.html'],
        dest: '<%= compile_dir %>/shared-views/views.min.js',
        options: {
          module: 'sharedViewsModule',
          base: './build',
          singleModule: true
        }
      }
    },
    /*
     * The jshint task detects errors and potential problems in
     * the JavaScript source and grunt files.
     *
     */
    jshint: {
      options: {
        jshintrc: true
      },
      src_js: ['./src/**/*.js'],
      gruntfiles: ['./gruntfile.js', 'grunt.conf.js']
    },
    /*
     * Karma is used to run unit tests.
     * It can run continiously (similar to the watch task).
     *
     */
    karma: {
      options: {
        configFile: '<%= build_dir %>/config/karma.conf.js'
      },
      unit: {
        port: 9191,
        background: false
      },
      continuous: {
        singleRun: false,
        autoWatch: true
      }
    },
    /*
     * Protractor is used to run E2E tests. (need a running
     * selenium server).
     *
     * To run locally, 'grunt test', 'grunt test:e2e' and
     * 'grunt protractor:build' will do the job.
     *
     * It also contains configuration for Travis CI.
     * Both '/build' (development) and '/application' (
     * production) paths are covered.
     *
     */
    protractor: {
      options: {
        keepAlive: false, // the grunt process stops when the test fails.
        noColor: false,
        args: {}
      },
      build: {
        options: {
          keepAlive: true,
          configFile: './config/protractor.conf.js', //Local tests
        }
      },
      ci_dev: {
        options: {
          configFile: './config/protractor-ci.conf.js'
        }
      },
      ci_prod: {
        options: {
          configFile: './config/protractor-ci-prod.conf.js'
        }
      }
    },
    /*
     * The `watch` task builds JavaScript, HTML and all assets
     * (including tests and the gruntfiles themselves) when any
     * of them are changed.
     *
     */
    watch: {
      options: {
        livereload: true
      },
      src_js: {
        files: ['./src/**/*.js', './src/**/*.json'],
        tasks: ['newer:jshint:src_js', 'newer:copy:build_app_js', 'copy:build_app_data']
      },
      src_html: {
        files: ['./src/**/*.html', '!./src/index.html'],
        tasks: ['newer:copy:build_views', 'copy:build_shared_views']
      },
      src_index: {
        files: ['./src/index.html'],
        tasks: ['copy:build_index']
      },
      src_stylesheets: {
        files: ['./src/assets/**/*.less', './src/assets/**/*.css'],
        tasks: ['newer:less:build_less', 'cssmin:build_css', 'clean:build_css_clean', 'autoprefixer:build_autoprefix_css']
      },
      src_assets: {
        files: ['./src/assets/**/*', '!./src/assets/**/*.less', '!./src/assets/**/*.css'],
        tasks: ['newer:copy:build_assets']
      },
      gruntfiles: {
        files: ['./gruntfile.js', 'grunt.conf.js'],
        tasks: ['newer:jshint:gruntfiles'],
        options: {
          livereload: false
        }
      },
      tests: {
        files: ['src/**/*.spec.js', 'src/**/*.e2e.js', 'src/**/*.protractor.js'],
        tasks: ['newer:copy:build_karma', 'newer:copy:build_unit', 'newer:copy:build_protractor']
      }
    }
  };

  /*
   * When initializing Grunt, it needs to be extended with the
   * 'gruntConfig' object (imported from './config/grunt.conf.js')
   *
   */
  grunt.initConfig(
    grunt.util._.extend(gruntTasks, gruntConfig)
  );

  /*
   * Tasks.
   * Running 'grunt' should be enough for development.
   * When ready for production, 'grunt compile' will compile the
   * application into the './application' directory.
   *
   */
  grunt.registerTask('default', ['build', 'karma:unit', 'watch']);
  grunt.registerTask('build', [
    'clean:build_clean',
    'jshint',
    'copy:build_app_js',
    'copy:build_app_data',
    'copy:build_vendor_js',
    'copy:build_views',
    'copy:build_shared_views',
    'copy:build_fonts',
    'copy:build_index',
    'copy:build_unit',
    'copy:build_protractor',
    'copy:build_karma',
    'copy:build_assets',
    'less:build_less',
    'cssmin:build_css',
    'clean:build_css_clean',
    'autoprefixer:build_autoprefix_css'
  ]);
  grunt.registerTask('compile', [
    'jshint',
    'build',
    'copy:compile_views',
    'html2js:compile_shared_views',
    'uglify:compile_module_js',
    'concat:compile_js',
    'uglify:compile_soft_uglify',
    'clean:compile_js_clean',
    'clean:compile_shared_views_clean',
    'copy:compile_app_data',
    'copy:compile_app_assets',
    'copy:compile_index'
  ]);
  grunt.registerTask('test', ['karma:unit', 'protractor:build']);
  grunt.registerTask('test:unit', ['karma:unit']);
  grunt.registerTask('test:ci', ['karma:unit', 'protractor:ci_dev', 'protractor:ci_prod']);
  grunt.registerTask('test:e2e', ['protractor:build']);
  grunt.registerTask('dev', ['shell:dev_server']);
  grunt.registerTask('prod', ['shell:prod_server']);

  /*
   * Helper methods.
   * The methods below use the 'module_file_order' Array in
   * 'grunt.conf.js' to easily load modules in a consistent
   * manner, generate globbing patterns or process files.
   *
   * (i.e. the 'index.html' is processed in order to
   * automatically write <script> tags)
   *
   */

  /*
   * Generates a globbing pattern that matches the
   * 'module_file_order' Array in 'grunt.conf.js'.
   *
   * @param {String} modulePath - The module path
   * @returns {Array} output - An Array of globbing patterns
   *
   * (i.e. findModuleFilesIn('./src/app/') loads all module
   * files in './src/app' in the defined order)
   *
   */
  function findModuleFilesIn(modulePath){
    var output = [],
        i;

    for(i = 0; i <= gruntConfig.module_file_order.length-1; i++){
      output.push(modulePath + gruntConfig.module_file_order[i]);
    }

    return output;
  }

  /*
   * 'Manually globs (using 'node-glob')' for all JavaScript files
   * that should be included in the build phase, then stores them
   * into the 'buildScripts' Array. 'buildScripts' is then passed * as 'scripts' to the template.
   * The template is processed (usually loops through 'scripts').
   * (See 'index.html')
   *
   * @param {String} content - File content
   * @returns {String} - Processed content
   *
   */
  function processBuildScripts(content){
    var buildScripts = [],
        globFiles,
        customModules = gruntConfig.build.vendor_js
                        .concat(findModuleFilesIn('./src/app/'))
                        .concat(findModuleFilesIn('./src/common/'));

    customModules.forEach(function(module){
      globFiles = glob.sync(module);

      if(globFiles.length > 0){
        buildScripts = buildScripts.concat(globFiles);
      }
    });

    return grunt.template.process(content, {
      data: {
        scripts: buildScripts
      }
    });
  }
};<commit_msg>fix(gruntfile.js): corrected '//' typo (now /) on the clean_samples task<commit_after>module.exports = function(grunt) {
  /*
   * Include grunt configuration
   */
  var gruntConfig = require( './config/grunt.conf.js' );

  /*
   * Helpers (preparing for grunt util deprecation)
   */
  var glob = require('glob');

  /*
   * Time grunt execution
   */
  require('time-grunt')(grunt);

  /*
   * JIT Grunt will automatically load other npm tasks
   */
  require('jit-grunt')(grunt);
  grunt.loadNpmTasks('grunt-protractor-runner');

  /*
   * Configuration
   */
  var gruntTasks = {
    pkg: grunt.file.readJSON('package.json'),
    /*
     * Placed at the top of the compiled source files.
     * Use the 'banner' -> banner: '<%= meta.banner %>'
     *
     */
    meta: {
      banner:
        '/*\n' +
        ' * Compiled <%= grunt.template.today("yyyy-mm-dd") %>\n' +
        ' * Docs @ <%= pkg.repository.url %>\n' +
        ' */\n'
    },
    /*
     * The shell task can run handy shell commands.
     * To configure the dev/prod server check out the 'sh' files
     * in './server'.
     *
     */
    shell: {
      dev_server: {
        command: './server/build-server.sh'
      },
      prod_server: {
        command: './server/production-server.sh'
      },
      run_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager start'
      },
      update_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager update'
      }
    },
    /*
     * The copy task copies files for both build and compile
     * phases, as well as test files.
     *
     * 'build_index' will process the 'index.html' file and write
     * <script> tags for all files (modules or vendor scripts).
     *
     * 'compile_index' will process the 'index.html' file without
     * providing any scripts. In this case, a single script will
     * be included: 'app.min.js'.
     *
     * See './src/index.html' for more details.
     *
     */
    copy: {
      build_app_js: {
        src: [
          findModuleFilesIn('./src/app/'),
          findModuleFilesIn('./src/common/')
        ],
        dest: '<%= build_dir %>'
      },
      build_app_data: {
        src: ['./src/app/**/*.json'],
        dest: '<%= build_dir %>/data/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_unit: {
        src: ['./src/**/*.spec.js'],
        dest: '<%= build_dir %>'
      },
      build_vendor_js: {
        src: ['<%= build.vendor_js %>'],
        dest: '<%= build_dir %>'
      },
      build_views: {
        cwd: './src',
        src: ['app/**/*.html', '!app/shared/**/*.html'],
        dest: '<%= build_dir %>/views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_shared_views: {
        cwd: './src',
        src: ['app/shared/**/*.html'],
        dest: '<%= build_dir %>/shared-views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= build_dir %>',
        expand: true,
        options: {
          process: processBuildScripts
        }
      },
      build_assets: {
        cwd: './src/assets',
        src: [
          'img/**/*',
          'fonts/**/*',
          '!**/*.less',
          '!**/*.css'
        ],
        dest: '<%= build_dir %>src/assets/',
        expand: true
      },
      build_fonts: {
        src: ['<%= common.vendor_fonts %>'],
        dest: '<%= build_dir %>src/assets/fonts/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_karma: {
        src: ['./config/karma.conf.js'],
        dest: '<%= build_dir %>',
        options: {
          process: processBuildScripts
        }
      },
      build_protractor: {
        cwd: './src',
        src: ['**/*.protractor.js', '**/*.e2e.js'],
        dest: '<%= build_dir %>src/e2e/',
        expand: true,
        flatten: true
      },
      compile_app_data: {
        cwd: '<%= build_dir %>',
        src: ['data/*.json'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_views: {
        cwd: '<%= build_dir %>',
        src: ['views/**/*.html'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= compile_dir %>',
        expand: true,
        options: {
          process: function processCompileIndex(content){
            return grunt.template.process(content);
          }
        }
      },
      compile_app_assets: {
        cwd: '<%= build_dir %>',
        src: ['src/assets/**/*', '!src/assets/**/*.md'],
        dest: '<%= compile_dir %>',
        expand: true
      }
    },
    /*
     * The clean task is used to remove files / directories that
     * are used and not needed anymore.
     *
     * It's also used to remove the build directory before a new
     * compile, see 'build_clean' below.
     *
     */
    clean: {
      build_clean: ['<%= build_dir %>'],
      build_css_clean: ['<%= build_dir %>/src/assets/css/app.custom.css'],
      compile_js_clean: ['<%= compile_dir %>/src/app/modules.min.js'],
      compile_shared_views_clean: ['<%= compile_dir %>/shared-views/'],
      clean_samples: [
        './src/app/about/',
        './src/app/home/',
        './src/app/profile-feature/',
        './src/app/shared/profile-model'
      ]
    },
    /*
     * The less task compiles all less files.
     * They will be afterwards concatenated with vendor
     * stylesheet, see the 'cssmin' task.
     *
     */
    less: {
      build_less: {
        src: ['./src/assets/**/*.less'],
        dest: '<%= build_dir %>/src/assets/css/app.custom.css',
        options: {
          cleancss: true,
          compress: true
        }
      }
    },
    /*
     * The cssmin task minifies css files and merges them into a
     * single file (done during build).
     *
     */
    cssmin: {
      build_css: {
        src: [
          '<%= build.vendor_css %>',
          './src/assets/**/*.css',
          '<%= build_dir %>/src/assets/css/app.custom.css'
        ],
        dest: '<%= build_dir %>/src/assets/css/app.min.css',
        options: {
          keepSpecialComments: 0,
          banner: '<%= meta.banner %>'
        }
      }
    },
    /*
     * This task autoprefixes CSS
     * You won't have to ever add -webkit-, -moz-, etc
     * in your CSS files EVER!
     *
     */
    autoprefixer: {
      options: {
        browsers: ['> 1%']
      },
      build_autoprefix_css: {
        src: '<%= build_dir %>/src/assets/css/app.min.css',
        dest: '<%= build_dir %>/src/assets/css/app.min.css'
      }
    },
    /*
     * The uglify task mainly minifies and mangles module scripts.
     * After all scripts are concatenated, it minifies without
     * mangling to remove comments, line breaks, etc that come
     * from vendor scripts.
     *
     */
    uglify: {
      compile_module_js: {
        options: {
          wrap: 'moduleExports',
          mangle: {
            except: ['exceptionLoggingService']
          }
        },
        src: [
          '<%= compile.vendor_js %>',
          findModuleFilesIn('./build/src/app/'),
          findModuleFilesIn('./build/src/common/')
        ],
        dest: '<%= compile_dir %>/src/app/modules.min.js'
      },
      compile_soft_uglify: {
        options: {
          mangle: false,
          banner: '<%= meta.banner %>'
        },
        src: ['<%= compile_dir %>/src/app/app.min.js'],
        dest: '<%= compile_dir %>/src/app/app.min.js'
      }
    },
    /*
     * The concat task is used in the compile phase to merge all
     * scripts into one.
     *
     */
    concat: {
      compile_js: {
        src: [
          '<%= compile.vendor_min_js %>',
          '<%= compile_dir %>/src/app/modules.min.js',
          '<%= compile_dir %>/shared-views/views.min.js'
        ],
        dest: '<%= compile_dir %>/src/app/app.min.js',
        options: {
          banner: '<%= meta.banner %>'
        }
      }
    },
    /*
     * The html2js task is used to convert all shared views into a module
     * that adds them to $templateCache. It also minifies HTML
     * markup.
     *
     */
    html2js: {
      options: {
        htmlmin: {
          collapseBooleanAttributes: false,
          collapseWhitespace: true,
          removeAttributeQuotes: false,
          removeComments: true,
          removeEmptyAttributes: false,
          removeRedundantAttributes: true,
          removeScriptTypeAttributes: true,
          removeStyleLinkTypeAttributes: true
        }
      },
      compile_shared_views: {
        src: ['<%= build_dir %>/shared-views/**/*.html'],
        dest: '<%= compile_dir %>/shared-views/views.min.js',
        options: {
          module: 'sharedViewsModule',
          base: './build',
          singleModule: true
        }
      }
    },
    /*
     * The jshint task detects errors and potential problems in
     * the JavaScript source and grunt files.
     *
     */
    jshint: {
      options: {
        jshintrc: true
      },
      src_js: ['./src/**/*.js'],
      gruntfiles: ['./gruntfile.js', 'grunt.conf.js']
    },
    /*
     * Karma is used to run unit tests.
     * It can run continiously (similar to the watch task).
     *
     */
    karma: {
      options: {
        configFile: '<%= build_dir %>/config/karma.conf.js'
      },
      unit: {
        port: 9191,
        background: false
      },
      continuous: {
        singleRun: false,
        autoWatch: true
      }
    },
    /*
     * Protractor is used to run E2E tests. (need a running
     * selenium server).
     *
     * To run locally, 'grunt test', 'grunt test:e2e' and
     * 'grunt protractor:build' will do the job.
     *
     * It also contains configuration for Travis CI.
     * Both '/build' (development) and '/application' (
     * production) paths are covered.
     *
     */
    protractor: {
      options: {
        keepAlive: false, // the grunt process stops when the test fails.
        noColor: false,
        args: {}
      },
      build: {
        options: {
          keepAlive: true,
          configFile: './config/protractor.conf.js', //Local tests
        }
      },
      ci_dev: {
        options: {
          configFile: './config/protractor-ci.conf.js'
        }
      },
      ci_prod: {
        options: {
          configFile: './config/protractor-ci-prod.conf.js'
        }
      }
    },
    /*
     * The `watch` task builds JavaScript, HTML and all assets
     * (including tests and the gruntfiles themselves) when any
     * of them are changed.
     *
     */
    watch: {
      options: {
        livereload: true
      },
      src_js: {
        files: ['./src/**/*.js', './src/**/*.json'],
        tasks: ['newer:jshint:src_js', 'newer:copy:build_app_js', 'copy:build_app_data']
      },
      src_html: {
        files: ['./src/**/*.html', '!./src/index.html'],
        tasks: ['newer:copy:build_views', 'copy:build_shared_views']
      },
      src_index: {
        files: ['./src/index.html'],
        tasks: ['copy:build_index']
      },
      src_stylesheets: {
        files: ['./src/assets/**/*.less', './src/assets/**/*.css'],
        tasks: ['newer:less:build_less', 'cssmin:build_css', 'clean:build_css_clean', 'autoprefixer:build_autoprefix_css']
      },
      src_assets: {
        files: ['./src/assets/**/*', '!./src/assets/**/*.less', '!./src/assets/**/*.css'],
        tasks: ['newer:copy:build_assets']
      },
      gruntfiles: {
        files: ['./gruntfile.js', 'grunt.conf.js'],
        tasks: ['newer:jshint:gruntfiles'],
        options: {
          livereload: false
        }
      },
      tests: {
        files: ['src/**/*.spec.js', 'src/**/*.e2e.js', 'src/**/*.protractor.js'],
        tasks: ['newer:copy:build_karma', 'newer:copy:build_unit', 'newer:copy:build_protractor']
      }
    }
  };

  /*
   * When initializing Grunt, it needs to be extended with the
   * 'gruntConfig' object (imported from './config/grunt.conf.js')
   *
   */
  grunt.initConfig(
    grunt.util._.extend(gruntTasks, gruntConfig)
  );

  /*
   * Tasks.
   * Running 'grunt' should be enough for development.
   * When ready for production, 'grunt compile' will compile the
   * application into the './application' directory.
   *
   */
  grunt.registerTask('default', ['build', 'karma:unit', 'watch']);
  grunt.registerTask('build', [
    'clean:build_clean',
    'jshint',
    'copy:build_app_js',
    'copy:build_app_data',
    'copy:build_vendor_js',
    'copy:build_views',
    'copy:build_shared_views',
    'copy:build_fonts',
    'copy:build_index',
    'copy:build_unit',
    'copy:build_protractor',
    'copy:build_karma',
    'copy:build_assets',
    'less:build_less',
    'cssmin:build_css',
    'clean:build_css_clean',
    'autoprefixer:build_autoprefix_css'
  ]);
  grunt.registerTask('compile', [
    'jshint',
    'build',
    'copy:compile_views',
    'html2js:compile_shared_views',
    'uglify:compile_module_js',
    'concat:compile_js',
    'uglify:compile_soft_uglify',
    'clean:compile_js_clean',
    'clean:compile_shared_views_clean',
    'copy:compile_app_data',
    'copy:compile_app_assets',
    'copy:compile_index'
  ]);
  grunt.registerTask('test', ['karma:unit', 'protractor:build']);
  grunt.registerTask('test:unit', ['karma:unit']);
  grunt.registerTask('test:ci', ['karma:unit', 'protractor:ci_dev', 'protractor:ci_prod']);
  grunt.registerTask('test:e2e', ['protractor:build']);
  grunt.registerTask('dev', ['shell:dev_server']);
  grunt.registerTask('prod', ['shell:prod_server']);

  /*
   * Helper methods.
   * The methods below use the 'module_file_order' Array in
   * 'grunt.conf.js' to easily load modules in a consistent
   * manner, generate globbing patterns or process files.
   *
   * (i.e. the 'index.html' is processed in order to
   * automatically write <script> tags)
   *
   */

  /*
   * Generates a globbing pattern that matches the
   * 'module_file_order' Array in 'grunt.conf.js'.
   *
   * @param {String} modulePath - The module path
   * @returns {Array} output - An Array of globbing patterns
   *
   * (i.e. findModuleFilesIn('./src/app/') loads all module
   * files in './src/app' in the defined order)
   *
   */
  function findModuleFilesIn(modulePath){
    var output = [],
        i;

    for(i = 0; i <= gruntConfig.module_file_order.length-1; i++){
      output.push(modulePath + gruntConfig.module_file_order[i]);
    }

    return output;
  }

  /*
   * 'Manually globs (using 'node-glob')' for all JavaScript files
   * that should be included in the build phase, then stores them
   * into the 'buildScripts' Array. 'buildScripts' is then passed * as 'scripts' to the template.
   * The template is processed (usually loops through 'scripts').
   * (See 'index.html')
   *
   * @param {String} content - File content
   * @returns {String} - Processed content
   *
   */
  function processBuildScripts(content){
    var buildScripts = [],
        globFiles,
        customModules = gruntConfig.build.vendor_js
                        .concat(findModuleFilesIn('./src/app/'))
                        .concat(findModuleFilesIn('./src/common/'));

    customModules.forEach(function(module){
      globFiles = glob.sync(module);

      if(globFiles.length > 0){
        buildScripts = buildScripts.concat(globFiles);
      }
    });

    return grunt.template.process(content, {
      data: {
        scripts: buildScripts
      }
    });
  }
};<|endoftext|>


<commit_before>// Node modules
var https = require('https'),
  url = require('url');
  fs = require('fs');

// EdgeGrid Auth Module
var auth = require('./auth'),
  edgerc = require('./edgerc'),
  logger = require('./logger');

var EdgeGrid = function(client_token, client_secret, access_token, base_uri) {
  this.config = {};

  // accepting an object containing a path to .edgerc and a config group
  if (typeof arguments[0] === 'object') {
    var path = arguments[0].path;
    var group = arguments[0].group;
    if (path === undefined) {
      logger.error("No .edgerc path");
      return false;
    }

    this.config = edgerc(path, group);
  } else {
    if (client_token === undefined || client_token === null) {
      logger.error("No client token");
      return false;
    } else if (client_secret === undefined || client_secret === null) {
      logger.error("No client secret");
      return false;
    } else if (access_token === undefined || access_token === null) {
      logger.error("No access token");
      return false;
    } else if (base_uri === undefined || base_uri === null) {
      logger.error("No base uri");
      return false;
    }

    this.config = {
      client_token: client_token,
      client_secret: client_secret,
      access_token: access_token,
      base_uri: base_uri
    };
  }

  return this;
};

EdgeGrid.prototype.auth = function(request, callback) {
  _request = auth.generate_auth(request, this.config.client_token, this.config.client_secret, this.config.access_token, this.config.base_uri);

  if (callback && typeof callback == "function") {
    callback(this);
  }

  return this;
};

EdgeGrid.prototype.send = function(callback) {
  var request = _request,
    data = "";

  var parts = url.parse(request.url);
  request.hostname = parts.hostname;
  request.port = parts.port;
  request.path = parts.path;

  // headers are case-insensitive so this function returns the value of a header
  // no matter what its case is. Returns undefined if there's no header defined.
  request.getHeader = function(header) {
    var result = undefined;
    for (k in this.headers) {
      if (k.toLowerCase() === header) {
        result = this.headers[k];
        break;
      }
    }
    return result;
  }

  if (request.method == "POST" || request.method == "PUT" || request.method == "DELETE") {
    // Accept user-defined, case-insensitive content-type header -- or use default type
    request.headers['content-type'] = request.getHeader('content-type') || 'application/x-www-form-urlencoded';
    request.headers['content-length'] = request.body.length;
  }

  var req = https.request(request, function(res) {
    res.on('data', function(d) {
      data += d;
    });

    res.on('end', function() {
      if (callback && typeof callback == "function") {
        callback(data, res);
      }

    });
  });

  if (request.method == "POST" || request.method == "PUT" || request.method == "DELETE") {
    req.write(request.body);
  }

  req.end();
};

module.exports = EdgeGrid;
<commit_msg>request now stored on Edgegrid instance<commit_after>// Node modules
var https = require('https'),
  url = require('url');
  fs = require('fs');

// EdgeGrid Auth Module
var auth = require('./auth'),
  edgerc = require('./edgerc'),
  logger = require('./logger');

var EdgeGrid = function(client_token, client_secret, access_token, base_uri) {
  this.config = {};

  // accepting an object containing a path to .edgerc and a config group
  if (typeof arguments[0] === 'object') {
    var path = arguments[0].path;
    var group = arguments[0].group;
    if (path === undefined) {
      logger.error("No .edgerc path");
      return false;
    }

    this.config = edgerc(path, group);
  } else {
    if (client_token === undefined || client_token === null) {
      logger.error("No client token");
      return false;
    } else if (client_secret === undefined || client_secret === null) {
      logger.error("No client secret");
      return false;
    } else if (access_token === undefined || access_token === null) {
      logger.error("No access token");
      return false;
    } else if (base_uri === undefined || base_uri === null) {
      logger.error("No base uri");
      return false;
    }

    this.config = {
      client_token: client_token,
      client_secret: client_secret,
      access_token: access_token,
      base_uri: base_uri
    };
  }

  return this;
};

EdgeGrid.prototype.auth = function(request, callback) {
  this.request = auth.generate_auth(request, this.config.client_token, this.config.client_secret, this.config.access_token, this.config.base_uri);

  if (callback && typeof callback == "function") {
    callback(this);
  }

  return this;
};

EdgeGrid.prototype.send = function(callback) {
  var request = this.request,
    data = "";

  var parts = url.parse(request.url);
  request.hostname = parts.hostname;
  request.port = parts.port;
  request.path = parts.path;

  // headers are case-insensitive so this function returns the value of a header
  // no matter what its case is. Returns undefined if there's no header defined.
  request.getHeader = function(header) {
    var result = undefined;
    for (k in this.headers) {
      if (k.toLowerCase() === header) {
        result = this.headers[k];
        break;
      }
    }
    return result;
  }

  if (request.method == "POST" || request.method == "PUT" || request.method == "DELETE") {
    // Accept user-defined, case-insensitive content-type header -- or use default type
    request.headers['content-type'] = request.getHeader('content-type') || 'application/x-www-form-urlencoded';
    request.headers['content-length'] = request.body.length;
  }

  var req = https.request(request, function(res) {
    res.on('data', function(d) {
      data += d;
    });

    res.on('end', function() {
      if (callback && typeof callback == "function") {
        callback(data, res);
      }

    });
  });

  if (request.method == "POST" || request.method == "PUT" || request.method == "DELETE") {
    req.write(request.body);
  }

  req.end();
};

module.exports = EdgeGrid;
<|endoftext|>