<commit_before>(function(dust){

/* make a safe version of console if it is not available
 * currently supporting:
 *   _console.log
 * */
var _console = (typeof console !== 'undefined')? console: {
  log: function(){
     /* a noop*/
   }
};

function isSelect(context) {
  var value = context.current();
  return typeof value === "object" && value.isSelect === true;
}

function filter(chunk, context, bodies, params, filter) {
  var params = params || {},
      actual, expected;

  if (params.key) {
    actual = context.get(params.key);
  } else if (isSelect(context)) {
    actual = context.current().value;
    if (context.current().isResolved) {
      filter = function() { return false; };
    }
  } else {
    throw "No key specified for filter and no key found in context from select statement";
  }

  expected = params.value;
  if (filter(expected, coerce(actual, params.type, context))) {
    if (isSelect(context)) {
      context.current().isResolved = true;
    }
    return chunk.render(bodies.block, context);
  } else if (bodies['else']) {
    return chunk.render(bodies['else'], context);
  }

  return chunk.write('');
}

function coerce (value, type, context) {
  if (value) {
    switch (type || typeof(value)) {
      case 'number': return +value;
      case 'string': return String(value);
      case 'boolean': return Boolean(value);
      case 'date': return new Date(value);
      case 'context': return context.get(value);
    }
  }

  return value;
}

var helpers = {

  sep: function(chunk, context, bodies) {
    if (context.stack.index === context.stack.of - 1) {
      return chunk;
    }
    return bodies.block(chunk, context);
  },

  idx: function(chunk, context, bodies) {
    return bodies.block(chunk, context.push(context.stack.index));
  },
  contextDump: function(chunk, context, bodies) {
    _console.log(JSON.stringify(context.stack));
    return chunk;
  },// Utility helping to resolve dust references in the given chunk
  tap: function( input, chunk, context ){
    // return given input if there is no dust reference to resolve
    var output = input;
    // dust compiles a string to function, if there are references
    if( typeof input === "function"){
      output = '';
      chunk.tap(function(data){
        output += data;
        return '';
      }).render(input, context).untap();
      if( output === '' ){
        output = false;
      }
    }
    return output;
  },

  "if": function( chunk, context, bodies, params ){
    if( params && params.cond ){
      var cond = params.cond;
      cond = this.tap(cond, chunk, context);
      // eval expressions with no dust references
      if( eval( cond ) ){
       return chunk.render( bodies.block, context );
      }
      if( bodies['else'] ){
       return chunk.render( bodies['else'], context );
      }
    }
    // no condition
    else {
      _console.log( "No expression given!" );
    }
    return chunk;
  },

  select: function(chunk, context, bodies, params) {
    return chunk.render(bodies.block, context.push({ isSelect: true, isResolved: false, value: context.get(params.key) }));
  },

  eq: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual === expected; });
  },

  lt: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual < expected; });
  },

  lte: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual <= expected; });
  },

  gt: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual > expected; });
  },

  gte: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual >= expected; });
  },

  "else": function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return true; });
  }
};

dust.helpers = helpers;

})(typeof exports !== 'undefined' ? exports : getGlobal());
<commit_msg>minor formatting<commit_after>(function(dust){

/* make a safe version of console if it is not available
 * currently supporting:
 *   _console.log
 * */
var _console = (typeof console !== 'undefined')? console: {
  log: function(){
     /* a noop*/
   }
};

function isSelect(context) {
  var value = context.current();
  return typeof value === "object" && value.isSelect === true;
}

function filter(chunk, context, bodies, params, filter) {
  var params = params || {},
      actual, expected;

  if (params.key) {
    actual = context.get(params.key);
  } else if (isSelect(context)) {
    actual = context.current().value;
    if (context.current().isResolved) {
      filter = function() { return false; };
    }
  } else {
    throw "No key specified for filter and no key found in context from select statement";
  }

  expected = params.value;
  if (filter(expected, coerce(actual, params.type, context))) {
    if (isSelect(context)) {
      context.current().isResolved = true;
    }
    return chunk.render(bodies.block, context);
  } else if (bodies['else']) {
    return chunk.render(bodies['else'], context);
  }

  return chunk.write('');
}

function coerce (value, type, context) {
  if (value) {
    switch (type || typeof(value)) {
      case 'number': return +value;
      case 'string': return String(value);
      case 'boolean': return Boolean(value);
      case 'date': return new Date(value);
      case 'context': return context.get(value);
    }
  }

  return value;
}

var helpers = {

  sep: function(chunk, context, bodies) {
    if (context.stack.index === context.stack.of - 1) {
      return chunk;
    }
    return bodies.block(chunk, context);
  },

  idx: function(chunk, context, bodies) {
    return bodies.block(chunk, context.push(context.stack.index));
  },
  contextDump: function(chunk, context, bodies) {
    _console.log(JSON.stringify(context.stack));
    return chunk;
  },

  // Utility helping to resolve dust references in the given chunk
  tap: function( input, chunk, context ){
    // return given input if there is no dust reference to resolve
    var output = input;
    // dust compiles a string to function, if there are references
    if( typeof input === "function"){
      output = '';
      chunk.tap(function(data){
        output += data;
        return '';
      }).render(input, context).untap();
      if( output === '' ){
        output = false;
      }
    }
    return output;
  },

  "if": function( chunk, context, bodies, params ){
    if( params && params.cond ){
      var cond = params.cond;
      cond = this.tap(cond, chunk, context);
      // eval expressions with no dust references
      if( eval( cond ) ){
       return chunk.render( bodies.block, context );
      }
      if( bodies['else'] ){
       return chunk.render( bodies['else'], context );
      }
    }
    // no condition
    else {
      _console.log( "No expression given!" );
    }
    return chunk;
  },

  select: function(chunk, context, bodies, params) {
    return chunk.render(bodies.block, context.push({ isSelect: true, isResolved: false, value: context.get(params.key) }));
  },

  eq: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual === expected; });
  },

  lt: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual < expected; });
  },

  lte: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual <= expected; });
  },

  gt: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual > expected; });
  },

  gte: function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return actual >= expected; });
  },

  "else": function(chunk, context, bodies, params) {
    return filter(chunk, context, bodies, params, function(expected, actual) { return true; });
  }
};

dust.helpers = helpers;

})(typeof exports !== 'undefined' ? exports : getGlobal());
<|endoftext|>


<commit_before>Ext.namespace('Gemma');
/**
 * @class Gemma.ExperimentPagingStore
 * @extends Ext.data.Store
 * @param {Object} config
 */
Gemma.ExperimentPagingStore = Ext.extend(Ext.data.Store, {
    constructor: function(config){
        Gemma.ExperimentPagingStore.superclass.constructor.call(this, config);
    },
    initComponent: function(){
        Gemma.ExperimentPagingStore.superclass.initComponent.call(this);
    },
    paramNames: {
        start: 'start', // default The parameter name which specifies the start row
        limit: 'limit', // default The parameter name which specifies number of rows to return
        sort: 'sort', // default The parameter name which specifies the column to sort on
        dir: 'dir' // default The parameter name which specifies the sort direction
    },
    remoteSort: true,
    proxy: new Ext.data.DWRProxy({
        apiActionToHandlerMap: {
            read: {
                dwrFunction: ExpressionExperimentController.browse,
                getDwrArgsFunction: function(request){
                    var params = request.params;
                    return [params];
                }
            }
        }
    }),

    reader: new Ext.data.JsonReader({
        root: 'records', // required.
        successProperty: 'success', // same as default.
        messageProperty: 'message', // optional
        totalProperty: 'totalRecords', // default is 'total'; optional unless
        // paging.
        idProperty: "id", // same as default,
        adjustedStart: 'adjustedStart',
        // used by store to set its sortInfo
        sortInfo: {
            field: "name",
            direction: "ASC"
        },
        fields: [{
            name: "id",
            type: "int"
        }, {
            name: "name",
            type: "string"
        }, {
            name: "shortName",
            type: "string"
        }, {
            name: "bioAssayCount",
            type: "int"
        }, {
            name: "taxon",
            type: "string"
        }, {
            name: "dateCreated",
            type: "date"
        }, {
            name: "troubled",
			sortDir: 'DESC'
        }, {
            name: "troubleDetails"
        }]
    }),

    writer: new Ext.data.JsonWriter({
        writeAllFields: true
    })

});
/**
 * @class Gemma.ExperimentPagingStoreSelectedIds
 * @extends Gemma.ExperimentPagingStore
 * @param {Object} config
 */
Gemma.ExperimentPagingStoreSelectedIds = Ext.extend(Gemma.ExperimentPagingStore, {

    initComponent: function(){
        Gemma.ExperimentPagingStoreSelectedIds.superclass.initComponent.call(this);
    },
    // overwrite proxy to use load instead of browse
    proxy: new Ext.data.DWRProxy({
        apiActionToHandlerMap: {
            read: {
                dwrFunction: ExpressionExperimentController.browseSpecificIds,
                getDwrArgsFunction: function(request){
                    var params = request.params;
                    var ids = params.ids;
                    // ids is not a field in the ListBatchCommand java object
                    delete params.ids;
                    return [params, ids];
                }
            }
        }
    })
});

/**
 * @class Gemma.ExperimentPagingStoreTaxon
 * @extends Gemma.ExperimentPagingStore
 * @param {Object} config
 */
Gemma.ExperimentPagingStoreTaxon = Ext.extend(Gemma.ExperimentPagingStore, {

    initComponent: function(){
        Gemma.ExperimentPagingStoreSelectedIds.superclass.initComponent.call(this);
    },
    // overwrite proxy to use load instead of browse
    proxy: new Ext.data.DWRProxy({
        apiActionToHandlerMap: {
            read: {
                dwrFunction: ExpressionExperimentController.browseByTaxon,
                getDwrArgsFunction: function(request){
                    var params = request.params;
                    var taxonId = params.taxonId;
                    // taxonId is not a field in the ListBatchCommand java object
                    delete params.taxonId;
                    return [params, taxonId];
                }
            }
        }
    })
});

/**
 * @class Gemma.ExperimentPagingGrid
 * @extends Ext.grid.GridPanel
 * @param {Object} config
 */
Gemma.ExperimentPagingGrid = Ext.extend(Ext.grid.GridPanel, {
    //width: 1000,
    loadMask: true,
    autoScroll: true,
    stripeRows: true,
    rowExpander: true,
    emptyText: Gemma.HelpText.WidgetDefaults.ExperimentPagingGrid.emptyText ,
    viewConfig: {
        forceFit: true
    },
    myPageSize: 20,
    title: 'Expression Experiments',

    columns: [    /*{ // for testing
     id:'id',
     header: "db id",
     dataIndex: 'id',
     sortable:true,
     width: 0.1 //viewConfig.forceFit resizes based on relative widths
     },*/
    {
        id: 'name',
        header: "Dataset Name",
        dataIndex: 'name',
        sortable: true,
        width: 0.5, //viewConfig.forceFit resizes based on relative widths,
        renderer: function(value, metaData, record, rowIndex, colIndex, store){
            return (value && record) ? '' + value + '' : '';
        }
    }, {
        header: "Status",
        dataIndex: 'troubled',
        sortable: true,
        width: 0.03,
        hidden: true,
        renderer: function(value, metaData, record, rowIndex, colIndex, store){
            return (value) ? '' : '';
        }
    }, {
        header: "Short Name",
        dataIndex: 'shortName',
        sortable: true,
        width: 0.1
    }, {
        header: "Assay Count",
        dataIndex: 'bioAssayCount',
        sortable: true,
        width: 0.1,
        tooltip: "View bioassays",
        renderer: function(value, metaData, record, rowIndex, colIndex, store){
            return (value && record) ? '' + value + '' : '';
        }
    }, {
        header: "Species",
        dataIndex: 'taxon',
        sortable: true,
        width: 0.1
    }],

	/**
	 * private
	 * @return a configured Gemma.ExperimentPagingStoreSelectedIds
	 */
	getIdsStore: function(ids){
		var pageSize = this.myPageSize;
		var pageStore = new Gemma.ExperimentPagingStoreSelectedIds({
                autoLoad: {
                    params: {
                        start: 0,
                        limit: pageSize
                    }
                },
                baseParams: {
                    ids: ids
                }
            });

        pageStore.setDefaultSort('name');

		return pageStore;
	},
	/**
	 * Show the experiments indicated by the array of ids passed in
	 *
	 * Steps:
	 * 1) create a store with the ids from the parameter pass in
	 * 2) unbind the current store from the paging toolbar and bind Gemma.ExperimentPagingStoreSelectedIds
	 * 3) reconfigure the grid with the new store
	 * @param {Object} eeIds
	 */
	loadExperimentsById: function(eeIds){

		// I tried being fancy and only creating a new store if the current one
		// wasn't an id store, but it caused problems on page changes
		// (the first page loaded fine, but when you navigated to the next page, it
		// was populated with entries from the previous query)
		// Always need to create new store for new queries, it seems.

		var idsStore = this.getIdsStore(eeIds);
		// bind new store to paging toolbar
        this.getBottomToolbar().bind(idsStore);
		// reconfigure grid to use new store
		this.reconfigure(idsStore, this.getColumnModel());
		this.nowSubset();
	},

	/**
	 * private
	 * @return a configured Gemma.ExperimentPagingStoreTaxon
	 */
	getTaxonStore: function(id){
		var pageSize = this.myPageSize;
		var pageStore = new Gemma.ExperimentPagingStoreTaxon({
                autoLoad: {
                    params: {
                        start: 0,
                        limit: pageSize
                    }
                },
                baseParams: {
                    taxonId: id
                }
            });

		this.setTitle("Expression Experiments For Taxon");
        pageStore.on('load', function(store, records, options){
			// problem for salmon because this will be child taxon, not parent
			// TODO use parent taxon, need to add it to object coming from back end
			if (records[0]) {
				this.setTitle("Expression Experiments For Taxon: " + records[0].get('taxon'));
			}
		}, this);

		return pageStore;
	},
	/**
	 * Show the experiments indicated by the array of ids passed in
	 *
	 * Steps:
	 * 1) if necessary, unbind the current store from the paging toolbar and bind Gemma.ExperimentPagingStoreSelectedIds
	 * 2) reconfigure the store with the new store (if necessary)
	 * 3) load the (new) store with the ids from the parameter pass in
	 * @param {Object} eeIds
	 */
	loadExperimentsByTaxon: function(taxonId){

		// I tried being fancy and only creating a new store if the current one
		// wasn't a taxon store, but it caused problems on page changes
		// (the first page loaded fine, but when you navigated to the next page, it
		// was populated with entries from the previous query)
		// Always need to create new store for new queries, it seems.

		var store = this.getTaxonStore(taxonId);
		// bind new store to paging toolbar
        this.getBottomToolbar().bind(store);
		// reconfigure grid to use new store
		this.reconfigure(store, this.getColumnModel());
		this.nowSubset();

	},
    initComponent: function(){

        this.showAll = !(document.URL.indexOf("?") > -1 && (document.URL.indexOf("id=") > -1 || document.URL.indexOf("taxonId=") > -1));
        this.idSubset = [];
        var myPageSize = this.myPageSize;
        var filterById = false;
        var filterByTaxon = false;
        if (!this.showAll) {
            var subsetDetails = document.URL.substr(document.URL.indexOf("?") + 1);
            var param = Ext.urlDecode(subsetDetails);
            if (param.id) {
                this.idSubset = param.id.split(',');
                filterById = true;
            }
            else
                if (param.taxonId) {
                    this.taxonId = param.taxonId;
                    filterByTaxon = true;
                }
                else {
                    this.showAll = true;
                }
        }
        var pageStore;
        if (filterById) {

			pageStore = this.getIdsStore(this.idSubset);

		} else if (filterByTaxon) {

			pageStore = this.getTaxonStore(this.taxonId);

		} else {
			this.setTitle("All Expression Experiments");
			pageStore = new Gemma.ExperimentPagingStore({
				autoLoad: {
					params: {
						start: 0,
						limit: myPageSize
					}
				}
			});
		}
        pageStore.setDefaultSort('name');

        pageStore.on('load', function(store, records, options){
            //console.log(records[0]);
        }, this);
        var eeCombo = new Gemma.ExperimentAndExperimentGroupCombo({
            width: 310,
            hideTrigger: true
        });
        eeCombo.on("recordSelected", function(selectedGroup){
            if (selectedGroup !== null) {

                this.showAll = false;
                filterById = true;
                // create a store that browses with selected ids
                var ids = selectedGroup.memberIds;
                this.loadExperimentsById(ids);
				// ids is not security filtered
				var totalCount = this.getStore().getTotalCount();
                this.setTitle("Displaying set: "" + selectedGroup.name + """);

                // problem: if the user reaches this grid with a URL like '[...]?taxonId=4' and then does a search, the taxon
                // clause will still be in the URL
                // so we need to refresh to clear the url, but if we do that, we lose the selected ids!
                // as a quick fix in this one case, we'll use this alternative way that is bookmarkable but limited by URL length
                //if(document.URL.indexOf("?") > 0){
                //	window.location = "/Gemma/expressionExperiment/showAllExpressionExperiments.html?id="+ids.join(',');
                //}
            }
        }, this);
        var editMine = new Ext.Button({
            text: 'Edit my datasets',
            cls: 'x-toolbar-standardbutton',
            handler: function(){
                window.location = "/Gemma/expressionExperiment/showAllExpressionExperimentLinkSummaries.html";
            },
            hidden: true
        });
        var subsetText = new Ext.BoxComponent({
            xtype: 'box',
            html: 'Viewing subset',
            border: false,
            style: 'padding-right:10px;padding-left:10px',
            hidden: this.showAll
        });
        var showAllButton = new Ext.Button({
            text: 'Show All Experiments',
            cls: 'x-toolbar-standardbutton',
            handler: function(){
                window.location = "/Gemma/expressionExperiment/showAllExpressionExperiments.html";
            },
            hidden: this.showAll
        });
        var QClinkButton = new Ext.Button({
            text: 'Experiment QC',
            cls: 'x-toolbar-standardbutton',
            handler: function(){
                window.location = "/Gemma/expressionExperimentsWithQC.html";
            }
        });
        this.nowSubset = function(){
            subsetText.show();
            showAllButton.show();
        };
        var mybbar = new Ext.PagingToolbar({
            store: pageStore, // grid and PagingToolbar using same
            // store
            displayInfo: true,
            pageSize: myPageSize,
        	plugins: [new Ext.ux.PageSizePlugin()]
        });
        Ext.apply(this, {
            store: pageStore,
            tbar: [eeCombo,'->', subsetText, showAllButton, '-', editMine, QClinkButton],
            bbar: mybbar
        });
        if (this.rowExpander) {
            Ext.apply(this, {
                rowExpander: new Gemma.EEGridRowExpander({
                    tpl: ""
                })
            });
            this.columns.unshift(this.rowExpander);
            Ext.apply(this, {
                plugins: this.rowExpander
            });
        }
        Gemma.ExperimentPagingGrid.superclass.initComponent.call(this);

        // when user changes the grid's sorting, bring them back to the first page
        // this makes sense if they're on the 4th page, but may be annoying if the user is on the last page
        // since the prior is more common than the latter, I think this is a good move
        //this.on('sortchange', function(grid, sortinfo){
        // THIS DOESN'T WORK WELL BECAUSE THE GRID RELOADS WITH NEW SORT FIRST, THEN RELOADS WITH FIRST PAGE
        //	grid.getBottomToolbar().moveFirst();
        //});

        // if the user is an admin, show the status column
        var isAdmin = (Ext.getDom('hasAdmin')) ? Ext.getDom('hasAdmin').getValue() : false;
        this.adjustForIsAdmin(isAdmin);

        Gemma.Application.currentUser.on("logIn", function(userName, isAdmin){
            this.adjustForIsAdmin(isAdmin);
            // when user logs in, reload the grid in case they can see more experiments now
            this.getStore().reload(this.getStore().lastOptions);

        }, this);
        Gemma.Application.currentUser.on("logOut", function(){

            // update the column model to hide the status column
            this.adjustForIsAdmin(false);

            // when user logs out, reload the grid in case they can see fewer experiments now
            this.getStore().reload(this.getStore().lastOptions);

        }, this);

    }, // end of initComponent
    // make changes based on whether user is admin or not
    adjustForIsAdmin: function(isAdmin){
        if (isAdmin) {
            // if user is admin, update the column model to show the status column
            var index = this.getColumnModel().findColumnIndex('troubled');
            this.getColumnModel().setHidden(index, !isAdmin);
        }

    }
});
<commit_msg>probably fixes 3019<commit_after>Ext.namespace('Gemma');
/**
 * @class Gemma.ExperimentPagingStore
 * @extends Ext.data.Store
 * @param {Object} config
 */
Gemma.ExperimentPagingStore = Ext.extend(Ext.data.Store, {
    constructor: function(config){
        Gemma.ExperimentPagingStore.superclass.constructor.call(this, config);
    },
    initComponent: function(){
        Gemma.ExperimentPagingStore.superclass.initComponent.call(this);
    },
    paramNames: {
        start: 'start', // default The parameter name which specifies the start row
        limit: 'limit', // default The parameter name which specifies number of rows to return
        sort: 'sort', // default The parameter name which specifies the column to sort on
        dir: 'dir' // default The parameter name which specifies the sort direction
    },
    remoteSort: true,
    proxy: new Ext.data.DWRProxy({
        apiActionToHandlerMap: {
            read: {
                dwrFunction: ExpressionExperimentController.browse,
                getDwrArgsFunction: function(request){
                    var params = request.params;
                    return [params];
                }
            }
        }
    }),

    reader: new Ext.data.JsonReader({
        root: 'records', // required.
        successProperty: 'success', // same as default.
        messageProperty: 'message', // optional
        totalProperty: 'totalRecords', // default is 'total'; optional unless
        // paging.
        idProperty: "id", // same as default,
        adjustedStart: 'adjustedStart',
        // used by store to set its sortInfo
        sortInfo: {
            field: "name",
            direction: "ASC"
        },
        fields: [{
            name: "id",
            type: "int"
        }, {
            name: "name",
            type: "string"
        }, {
            name: "shortName",
            type: "string"
        }, {
            name: "bioAssayCount",
            type: "int"
        }, {
            name: "taxon",
            type: "string"
        }, {
            name: "dateCreated",
            type: "date"
        }, {
            name: "troubled",
			sortDir: 'DESC'
        }, {
            name: "troubleDetails"
        }]
    }),

    writer: new Ext.data.JsonWriter({
        writeAllFields: true
    })

});
/**
 * @class Gemma.ExperimentPagingStoreSelectedIds
 * @extends Gemma.ExperimentPagingStore
 * @param {Object} config
 */
Gemma.ExperimentPagingStoreSelectedIds = Ext.extend(Gemma.ExperimentPagingStore, {

    initComponent: function(){
        Gemma.ExperimentPagingStoreSelectedIds.superclass.initComponent.call(this);
    },
    // overwrite proxy to use load instead of browse
    proxy: new Ext.data.DWRProxy({
        apiActionToHandlerMap: {
            read: {
                dwrFunction: ExpressionExperimentController.browseSpecificIds,
                getDwrArgsFunction: function(request){
                    var params = request.params;
                    var ids = params.ids;
                    // ids is not a field in the ListBatchCommand java object
                    delete params.ids;
                    return [params, ids];
                }
            }
        }
    })
});

/**
 * @class Gemma.ExperimentPagingStoreTaxon
 * @extends Gemma.ExperimentPagingStore
 * @param {Object} config
 */
Gemma.ExperimentPagingStoreTaxon = Ext.extend(Gemma.ExperimentPagingStore, {

    initComponent: function(){
        Gemma.ExperimentPagingStoreSelectedIds.superclass.initComponent.call(this);
    },
    // overwrite proxy to use load instead of browse
    proxy: new Ext.data.DWRProxy({
        apiActionToHandlerMap: {
            read: {
                dwrFunction: ExpressionExperimentController.browseByTaxon,
                getDwrArgsFunction: function(request){
                    var params = request.params;
                    var taxonId = params.taxonId;
                    // taxonId is not a field in the ListBatchCommand java object
                    delete params.taxonId;
                    return [params, taxonId];
                }
            }
        }
    })
});

/**
 * @class Gemma.ExperimentPagingGrid
 * @extends Ext.grid.GridPanel
 * @param {Object} config
 */
Gemma.ExperimentPagingGrid = Ext.extend(Ext.grid.GridPanel, {
    //width: 1000,
    loadMask: true,
    autoScroll: true,
    stripeRows: true,
    rowExpander: true,
    emptyText: Gemma.HelpText.WidgetDefaults.ExperimentPagingGrid.emptyText ,
    viewConfig: {
        forceFit: true
    },
    myPageSize: 20,
    title: 'Expression Experiments',

    columns: [    /*{ // for testing
     id:'id',
     header: "db id",
     dataIndex: 'id',
     sortable:true,
     width: 0.1 //viewConfig.forceFit resizes based on relative widths
     },*/
    {
        id: 'name',
        header: "Dataset Name",
        dataIndex: 'name',
        sortable: true,
        width: 0.5, //viewConfig.forceFit resizes based on relative widths,
        renderer: function(value, metaData, record, rowIndex, colIndex, store){
            return (value && record) ? '' + value + '' : '';
        }
    }, {
        header: "Status",
        dataIndex: 'troubled',
        sortable: true,
        width: 0.03,
        hidden: true,
        renderer: function(value, metaData, record, rowIndex, colIndex, store){
            return (value) ? '' : '';
        }
    }, {
        header: "Short Name",
        dataIndex: 'shortName',
        sortable: true,
        width: 0.1
    }, {
        header: "Assay Count",
        dataIndex: 'bioAssayCount',
        sortable: true,
        width: 0.1,
        tooltip: "View bioassays",
        renderer: function(value, metaData, record, rowIndex, colIndex, store){
            return (value && record) ? '' + value + '' : '';
        }
    }, {
        header: "Species",
        dataIndex: 'taxon',
        sortable: true,
        width: 0.1
    }],

	/**
	 * private
	 * @return a configured Gemma.ExperimentPagingStoreSelectedIds
	 */
	getIdsStore: function(ids){
		var pageSize = this.myPageSize;
		var pageStore = new Gemma.ExperimentPagingStoreSelectedIds({
                autoLoad: {
                    params: {
                        start: 0,
                        limit: pageSize
                    }
                },
                baseParams: {
                    ids: ids
                }
            });

        pageStore.setDefaultSort('name');

		return pageStore;
	},
	/**
	 * Show the experiments indicated by the array of ids passed in
	 *
	 * Steps:
	 * 1) create a store with the ids from the parameter pass in
	 * 2) unbind the current store from the paging toolbar and bind Gemma.ExperimentPagingStoreSelectedIds
	 * 3) reconfigure the grid with the new store
	 * @param {Object} eeIds
	 */
	loadExperimentsById: function(eeIds){

		// I tried being fancy and only creating a new store if the current one
		// wasn't an id store, but it caused problems on page changes
		// (the first page loaded fine, but when you navigated to the next page, it
		// was populated with entries from the previous query)
		// Always need to create new store for new queries, it seems.

		var idsStore = this.getIdsStore(eeIds);
		// bind new store to paging toolbar
        this.getBottomToolbar().bind(idsStore);
		// reconfigure grid to use new store
		this.reconfigure(idsStore, this.getColumnModel());
		this.nowSubset();
	},

	/**
	 * private
	 * @return a configured Gemma.ExperimentPagingStoreTaxon
	 */
	getTaxonStore: function(id){
		var pageSize = this.myPageSize;
		var pageStore = new Gemma.ExperimentPagingStoreTaxon({
                autoLoad: {
                    params: {
                        start: 0,
                        limit: pageSize
                    }
                },
                baseParams: {
                    taxonId: id
                }
            });

		this.setTitle("Expression Experiments For Taxon");
        pageStore.on('load', function(store, records, options){
			// problem for salmon because this will be child taxon, not parent
			// TODO use parent taxon, need to add it to object coming from back end
			if (records[0]) {
				this.setTitle("Expression Experiments For Taxon: " + records[0].get('taxon'));
			}
		}, this);

		return pageStore;
	},
	/**
	 * Show the experiments indicated by the array of ids passed in
	 *
	 * Steps:
	 * 1) if necessary, unbind the current store from the paging toolbar and bind Gemma.ExperimentPagingStoreSelectedIds
	 * 2) reconfigure the store with the new store (if necessary)
	 * 3) load the (new) store with the ids from the parameter pass in
	 * @param {Object} eeIds
	 */
	loadExperimentsByTaxon: function(taxonId){

		// I tried being fancy and only creating a new store if the current one
		// wasn't a taxon store, but it caused problems on page changes
		// (the first page loaded fine, but when you navigated to the next page, it
		// was populated with entries from the previous query)
		// Always need to create new store for new queries, it seems.

		var store = this.getTaxonStore(taxonId);
		// bind new store to paging toolbar
        this.getBottomToolbar().bind(store);
		// reconfigure grid to use new store
		this.reconfigure(store, this.getColumnModel());
		this.nowSubset();

	},
    initComponent: function(){

        this.showAll = !(document.URL.indexOf("?") > -1 && (document.URL.indexOf("id=") > -1 || document.URL.indexOf("taxonId=") > -1));
        this.idSubset = [];
        var myPageSize = this.myPageSize;
        var filterById = false;
        var filterByTaxon = false;
        if (!this.showAll) {
            var subsetDetails = document.URL.substr(document.URL.indexOf("?") + 1);
            var param = Ext.urlDecode(subsetDetails);
            if (param.id) {
                this.idSubset = param.id.split(',');
                filterById = true;
            }
            else
                if (param.taxonId) {
                    this.taxonId = param.taxonId;
                    filterByTaxon = true;
                }
                else {
                    this.showAll = true;
                }
        }
        var pageStore;
        if (filterById) {

			pageStore = this.getIdsStore(this.idSubset);

		} else if (filterByTaxon) {

			pageStore = this.getTaxonStore(this.taxonId);

		} else {
			this.setTitle("All Expression Experiments");
			pageStore = new Gemma.ExperimentPagingStore({
				autoLoad: {
					params: {
						start: 0,
						limit: myPageSize
					}
				}
			});
		}
        pageStore.setDefaultSort('name');

        pageStore.on('load', function(store, records, options){
            //console.log(records[0]);
        }, this);
        var eeCombo = new Gemma.ExperimentAndExperimentGroupCombo({
            width: 310,
            hideTrigger: true
        });
        eeCombo.on("recordSelected", function(selectedGroup){
            if (selectedGroup !== null) {

                this.showAll = false;
                filterById = true;
                // create a store that browses with selected ids
                var ids = selectedGroup.memberIds;
                this.loadExperimentsById(ids);
				// ids is not security filtered
				var totalCount = this.getStore().getTotalCount();
                this.setTitle("Displaying set: "" + selectedGroup.name + """);

                // problem: if the user reaches this grid with a URL like '[...]?taxonId=4' and then does a search, the taxon
                // clause will still be in the URL
                // so we need to refresh to clear the url, but if we do that, we lose the selected ids!
                // as a quick fix in this one case, we'll use this alternative way that is bookmarkable but limited by URL length
                //if(document.URL.indexOf("?") > 0){
                //	window.location = "/Gemma/expressionExperiment/showAllExpressionExperiments.html?id="+ids.join(',');
                //}
            }
        }, this);
        var editMine = new Ext.Button({
            text: 'Edit my datasets',
            cls: 'x-toolbar-standardbutton',
            handler: function(){
                window.location = "/Gemma/expressionExperiment/showAllExpressionExperimentLinkSummaries.html";
            },
            hidden: true
        });
        var subsetText = new Ext.BoxComponent({
            xtype: 'box',
            html: 'Viewing subset',
            border: false,
            style: 'padding-right:10px;padding-left:10px',
            hidden: this.showAll
        });
        var showAllButton = new Ext.Button({
            text: 'Show All Experiments',
            cls: 'x-toolbar-standardbutton',
            handler: function(){
                window.location = "/Gemma/expressionExperiment/showAllExpressionExperiments.html";
            },
            hidden: this.showAll
        });
        var QClinkButton = new Ext.Button({
            text: 'Experiment QC',
            cls: 'x-toolbar-standardbutton',
            handler: function(){
                window.location = "/Gemma/expressionExperimentsWithQC.html";
            }
        });
        this.nowSubset = function(){
            subsetText.show();
            showAllButton.show();
        };
        var mybbar = new Ext.PagingToolbar({
            store: pageStore, // grid and PagingToolbar using same
            // store
            displayInfo: true,
            pageSize: myPageSize,
        	plugins: [new Ext.ux.PageSizePlugin()]
        });
        Ext.apply(this, {
            store: pageStore,
            tbar: [eeCombo,'->', subsetText, showAllButton, '-', editMine, QClinkButton],
            bbar: mybbar
        });
        if (this.rowExpander) {
            Ext.apply(this, {
                rowExpander: new Gemma.EEGridRowExpander({
                    tpl: ""
                })
            });
            this.columns.unshift(this.rowExpander);
            Ext.apply(this, {
                plugins: this.rowExpander
            });
        }
        Gemma.ExperimentPagingGrid.superclass.initComponent.call(this);

        // when user changes the grid's sorting, bring them back to the first page
        // this makes sense if they're on the 4th page, but may be annoying if the user is on the last page
        // since the prior is more common than the latter, I think this is a good move
        //this.on('sortchange', function(grid, sortinfo){
        // THIS DOESN'T WORK WELL BECAUSE THE GRID RELOADS WITH NEW SORT FIRST, THEN RELOADS WITH FIRST PAGE
        //	grid.getBottomToolbar().moveFirst();
        //});

        // if the user is an admin, show the status column
        var isAdmin = (Ext.getDom('hasAdmin')) ? Ext.getDom('hasAdmin').getValue() : false;
        this.adjustForIsAdmin(isAdmin);

        Gemma.Application.currentUser.on("logIn", function(userName, isAdmin){
            this.adjustForIsAdmin(isAdmin);
            // when user logs in, reload the grid in case they can see more experiments now
            this.getStore().reload(this.getStore().lastOptions);

        }, this);
        Gemma.Application.currentUser.on("logOut", function(){

            // update the column model to hide the status column
            this.adjustForIsAdmin(false);

            // when user logs out, reload the grid in case they can see fewer experiments now
            this.getStore().reload(this.getStore().lastOptions);

        }, this);

    }, // end of initComponent
    // make changes based on whether user is admin or not
    adjustForIsAdmin: function(isAdmin){
        if (isAdmin) {
            // if user is admin, update the column model to show the status column
            var index = this.getColumnModel().findColumnIndex('troubled');
            this.getColumnModel().setHidden(index, !isAdmin);
        }

    }
});
<|endoftext|>


<commit_before>
describe("streamingHttp", function(){
   "use strict";

   describe("calls through to browser xhr", function(){

      it('gives xhr null when body is undefined', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', undefined);

         expect( xhr.send ).toHaveBeenCalledWith(null);
      })

      it('gives xhr null when body is null', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', null);

         expect( xhr.send ).toHaveBeenCalledWith(null);
      })

      it('give xhr string request body', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', 'my_data');

         expect( xhr.send ).toHaveBeenCalledWith('my_data');
      })

      it('gives xhr a json encoded request body when given an object', function(){
         var eventBus = pubSub(), xhr = xhrStub();
         var payload = {a:'A', b:'B'};

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', payload);

         expect( xhr.send ).toHaveBeenCalledWith(JSON.stringify( payload ) );
      });

      it('gives xhr the request headers', function(){
         var eventBus = pubSub(), xhr = xhrStub();
         var headers = {
            'X-FROODINESS':'frood',
            'X-HOOPINESS':'hoopy'
         };

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', undefined, headers);

         expect( xhr.setRequestHeader ).toHaveBeenCalledWith( 'X-FROODINESS', 'frood' );
         expect( xhr.setRequestHeader ).toHaveBeenCalledWith( 'X-HOOPINESS', 'hoopy' );
      });

      it('should be able to abort an xhr once started', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', 'my_data');

         eventBus.fire(ABORTING);

         expect( xhr.abort ).toHaveBeenCalled();
      });

      function xhrStub() {
         return {
            abort: jasmine.createSpy('abort'),
            open: jasmine.createSpy('open'),
            setRequestHeader: jasmine.createSpy('setRequestHeader'),
            send: jasmine.createSpy('send')
         };
      }
   });

});

<commit_msg>use jasmine streaming object - slighlty simpler<commit_after>
describe("streamingHttp", function(){
   "use strict";

   describe("calls through to browser xhr", function(){

      it('gives xhr null when body is undefined', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', undefined);

         expect( xhr.send ).toHaveBeenCalledWith(null);
      })

      it('gives xhr null when body is null', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', null);

         expect( xhr.send ).toHaveBeenCalledWith(null);
      })

      it('give xhr string request body', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', 'my_data');

         expect( xhr.send ).toHaveBeenCalledWith('my_data');
      })

      it('gives xhr a json encoded request body when given an object', function(){
         var eventBus = pubSub(), xhr = xhrStub();
         var payload = {a:'A', b:'B'};

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', payload);

         expect( xhr.send ).toHaveBeenCalledWith(JSON.stringify( payload ) );
      });

      it('gives xhr the request headers', function(){
         var eventBus = pubSub(), xhr = xhrStub();
         var headers = {
            'X-FROODINESS':'frood',
            'X-HOOPINESS':'hoopy'
         };

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', undefined, headers);

         expect( xhr.setRequestHeader ).toHaveBeenCalledWith( 'X-FROODINESS', 'frood' );
         expect( xhr.setRequestHeader ).toHaveBeenCalledWith( 'X-HOOPINESS', 'hoopy' );
      });

      it('should be able to abort an xhr once started', function(){
         var eventBus = pubSub(), xhr = xhrStub();

         streamingHttp(eventBus.fire, eventBus.on, xhr, 'GET', 'http://example.com', 'my_data');

         eventBus.fire(ABORTING);

         expect( xhr.abort ).toHaveBeenCalled();
      });

      function xhrStub() {
         return jasmine.createSpyObj('xhr', ['abort', 'open', 'setRequestHeader', 'send']);
      }
   });

});

<|endoftext|>


<commit_before>var port = 3000;

var http = require("http");
var path = require("path");
var url = require("url");
var fs = require("fs");

var request = require("request");

http.createServer( function(req, res) {

    var now = new Date();

    var filename = req.url || "index.html";
    var ext = path.extname(filename);
    var localPath = __dirname;
    var validExtensions = {
        ".html" : "text/html",
        ".js": "application/javascript",
        ".css": "text/css",
        ".txt": "text/plain",
        ".jpg": "image/jpeg",
        ".gif": "image/gif",
        ".png": "image/png",
        ".json": "application/json",
        ".map": "application/javascript",
        ".ico":"image/ico",
        "":"text/html"
    };
    var isValidExt = validExtensions[ext];

    if (isValidExt) {

        localPath += filename;
        path.exists(localPath, function(exists) {
            if(exists) {
                console.log("Serving file: " + localPath);
                getFile(localPath, res, isValidExt);
            } else {
                console.log("File not found: " + localPath);
                res.writeHead(404);
                res.end();
            }
        });

    } else {
        console.log("Invalid file extension detected: " + ext);
    }

    if(req.url == "/saveResults") {

        var postData = '';
        var filename = 'config/minimaxResults.json'
        req.on('data', function(datum) {
          postData += datum;
        });

        req.on('end', function() {
            fs.writeFile(filename, postData, function (err) {
              if (err) return console.log(err);
              console.log('File '+filename+' has been written to the folder.');
            });
        });

        var response = JSON.stringify({'success': filename});
        res.writeHead(200, { 'Content-Type': 'application/json' , 'Content-Length':response.length});
        res.write(response);
        res.end();
    }

}).listen(process.env.PORT || port);

function getFile(localPath, res, mimeType) {
    fs.readFile(localPath, function(err, contents) {
        if(!err) {
            res.setHeader("Content-Length", contents.length);
            res.setHeader("Content-Type", mimeType);
            res.statusCode = 200;
            res.end(contents);
        } else {
            res.writeHead(500);
            res.end();
        }
    });
}
<commit_msg>Node adds an app folder in front of the main directory<commit_after>var port = 3000;

var http = require("http");
var path = require("path");
var url = require("url");
var fs = require("fs");

var request = require("request");

http.createServer( function(req, res) {

    var now = new Date();

    var filename = req.url || "index.html";
    var ext = path.extname(filename);
    var localPath = __dirname;
    var validExtensions = {
        ".html" : "text/html",
        ".js": "application/javascript",
        ".css": "text/css",
        ".txt": "text/plain",
        ".jpg": "image/jpeg",
        ".gif": "image/gif",
        ".png": "image/png",
        ".json": "application/json",
        ".map": "application/javascript",
        ".ico":"image/ico",
        "":"text/html"
    };
    var isValidExt = validExtensions[ext];

    if (isValidExt) {

        localPath += filename;
        path.exists(localPath, function(exists) {
            if(exists) {
                console.log("Serving file: " + localPath);
                getFile(localPath, res, isValidExt);
            } else {
                console.log("File not found: " + localPath);
                res.writeHead(404);
                res.end();
            }
        });

    } else {
        console.log("Invalid file extension detected: " + ext);
    }

    if(req.url == "/saveResults" || req.url == "/app/saveResults") {

        var postData = '';
        var filename = 'config/minimaxResults.json'
        req.on('data', function(datum) {
          postData += datum;
        });

        req.on('end', function() {
            fs.writeFile(filename, postData, function (err) {
              if (err) return console.log(err);
              console.log('File '+filename+' has been written to the folder.');
            });
        });

        var response = JSON.stringify({'success': filename});
        res.writeHead(200, { 'Content-Type': 'application/json' , 'Content-Length':response.length});
        res.write(response);
        res.end();
    }

}).listen(process.env.PORT || port);

function getFile(localPath, res, mimeType) {
    fs.readFile(localPath, function(err, contents) {
        if(!err) {
            res.setHeader("Content-Length", contents.length);
            res.setHeader("Content-Type", mimeType);
            res.statusCode = 200;
            res.end(contents);
        } else {
            res.writeHead(500);
            res.end();
        }
    });
}
<|endoftext|>


<commit_before>function Teams() {
    this.teams = [
        {
            id: "Renaissance",
            name: "Renaissance",
            streams: ["StreamR1", "StreamR2", "StreamR3"],
            teamLead: "Aliaksandr Koush",
            qaTeamLead: "Aliaksandra Kutynka",
            developers: [
                "Andrei Osipau2",
                "Dzianis Arlouski",
                "Siarhei Tkachenka",
                "Iryna Kucharenka1",
                "Ivan Izmer",
                "Mark Varabyou",
                "Raman But-Husaim",
                "Siarhei Abrazhevich",
                "Artsiom Rusak",
                "Raman Ivanou",
                "Aliaksandr Koush",
                "Nicolay Kostroma",
                "Valentina Napolnova",
                "Aliaksey Rahatka",
                "Pavel Kastsiuk",
                "Juliana Stolnik",
		        "Volha Viktarava",
                "Artsiom Kazlou"
            ],
            testers: [
                "Pavel Vysotsky",
                "Viktoriya Harbatsenkava",
                "Hanna Prykhodzka",
                "Kseniya Kavalchuk",
                "Yuliya Tukaila",
		        "Aliaksei Huliayeu",
		        "Artsiom Yesis",
		        "Siarhei Shyshparonak",
                "Aliaksandra Kutynka"
            ]
        },
        {
            id: "Inspiration",
            name: "Inspiration",
            streams: ["StreamIn1", "StreamIn2", "StreamIn3"],
            teamLead: "Sergey Tischenko",
            qaTeamLead: "Denys Pugachov",
            developers: [
                "Borys Roshal",
                "Denys Poliakov",
                "Kostiantyn Lazurenko",
                "Oleksandr Stukalov",
                "Oleksii Bespalko",
                "Yevhenii Havryliuk",
                "Yuriy Shestyora",
                "Ihor Bershov",
                "Vladyslav Pilhui",
                "Oleksandr Zhyltsov",
                "Oleksii Suriadnyi",
                "Serhiy Haponenko",
                "Yevhenii Lomov",
                "Ihor Rudchenko",
                "Andrii Savinov",
                "Dmytro Petlia",
                "Olena Ostroverkhova",
		        "Volodymyr Osmak"
            ],
            testers: [
                "Mila Botnar",
                "Yuri Timchenko",
                "Anastasia Kotenyova",
                "Pavlo Golovashchenko",
                "Oleksii Milman",
		        "Svitlana Andrieieva",
                "Denys Pugachov"
            ]
        },
        {
            id: "Nova",
            name: "Nova",
            streams: ["StreamN1", "StreamN2", "StreamN3"],
            teamLead: "Heorhi Vilkitski",
            qaTeamLead: "Valiantsina Krautsevich",
            developers: [
                "Andrei Kandybovich",
                "Dzmitry Siamchonak",
                "Mikita Stalpinski",
                "Uladzimir Harabtsou",
                "Aliaksandr Nikulin",
                "Ilya Kazlou1",
                "Katsiaryna Kaliukhovich",
                "Vadzim Vysotski",
                "Edhar Liashok",
                "Raman Prakofyeu",
                "Ruslan Khilmanovich",
                "Anton Kratenok",
                "Siarhei Maksimau1",
                "Dzmitry Chapurok",
		        "Pavel Davidouski",
                "Evgeny Sinitsyn"
            ],
            testers: [
                "Aliaksei Burnosenka",
                "Viktar Mikalayenka",
                "Eugeny Okulik",
                "Yuliya Kalasouskaya",
                "Hanna Maskalenka",
		        "Kiryl Kozubouski",
		        "Mikhail Naskalau",
		        "Nataliya Shmakava",
                "Valiantsina Krautsevich"
            ]
        },
        {
            id: "Liberty",
            name: "Liberty",
            streams: ["StreamL1", "StreamL2", "StreamL3"],
            teamLead: "Dzmitry Tabolich",
            qaTeamLead: "Iryna Kutsko",
            developers: [
                "Pavel Naumenka",
                "Sergei Kulick",
                "Ilya Huchok",
                "Aliaksandr Rusak",
                "Andrei Kasak",
                "Andrei Krasnou",
                "Pavel Krakasevich",
                "Stepan Zelenin",
                "Dzmitry Isachenka",
                "Eugen Surovets",
                "Katsiaryna Tsalabanava",
                "Andrii Prykhodko",
                "Hleb Krotsik",
                "Uladzimir Vysotski"
            ],
            testers: [
                "Anna Novikova",
                "Anton Rapinchuk",
                "Igor Andros",
                "Maria Sobal",
                "Yuliya Karnatsevich",
                "Nastassia Dziadkova",
                "Iryna Kutsko",
                "Natalya Krestelyova"
            ]
        },
        {
            id: "Viva",
            name: "Viva",
            streams: ["StreamV1", "StreamV2", "StreamV3"],
            teamLead: "Valentine Zhuck",
            qaTeamLead: "Katsiaryna Kuchko",
            developers: [
                "Valentine Zhuck",
                "Viachaslau Anufryiuk",
                "Yury Yamoryk",
                "Aliaksandr Kladau",
                "Dzmitry Kavaliou",
                "Dzmitry Shynkarou",
                "Maksim Tsikhan",
                "Petr Falitarchyk",
                "Yuri Chupyrkin",
                "Aliaksandr Rykau",
                "Ivan Dziameshka",
                "Siarhei Bahdanovich",
                "Andrei Lysenka",
                "Aleh Dukel",
                "Ivan Yanchuk",
                "Kanstantsin Ldou",
                "Siarhei Nikitsin",
		        "Mikhail Kelbas",
                "Katsiaryna Zeliankova"
            ],
            testers: [
                "Iryna Malets",
                "Maryia Kireyeva",
                "Iryna Shuliak",
                "Liudmila Barshcheuskaya",
                "Iryna Razorionova",
		        "Volha Shymanovich",
                "Katsiaryna Kuchko"
            ]
        },
        {
            id: "Elfish",
            name: "Elfish",
            teamLead: "Roman Golovchenko",
            qaTeamLead: "",
            developers: [
                "Roman Golovchenko",
                "Allaberdi Hojayev",
                "Bohdan Sorokin",
		        "Ivan Manzhos",
		        "Oleh Vinnikov",
                "Yevhenii Koliesnik"
            ],
            testers: [
                "Ivan Nalyvaiko",
                "Oleksii Shchelkunov",
                "Valeriia Karabut"
            ]
        },
        {
            id: "TeamAutomation",
            name: "Automation",
            teamLead: "Aliaksandr Basau",
            developers: [
                "Viachaslau Naimovich",
                "Vitali Sonchyk",
                "Katsiaryna Kulbitskaya",
                "Maryia Kashtanava"
            ]
        }
    ]
}

exports.AllTeams = new Teams();

exports.OldDevelopers = function oldDevelopers(name) {
    if(name == 'Valentine Zhuck' ||
        name == 'Dzmitry Tabolich' ||
        name == 'Heorhi Vilkitski' ||
        name == "Hanna Kastsian" ||
        name == "Alena Charnova" ||
        name == "Aliaksei Astashkin" ||
        name == "yauheni_lohinau" ||
        name == "Dmytro Komar" ||
        name == "Aliaksei Labachou" ||
        name == "Mariya Babich" ||
        name == "Katsiaryna Sasina" ||
        name == "aliaksei_labachou aliaksei_labachou" ||
        name == "Maryna Furman" ||
 	    name == "Dzmitry Salodki" ||
	    name == "Volha Shandrokha" ||
 	    name == "Kate Tsalabanava" ||
 	    name == "Vitali Podobed" ||
 	    name == "Siarhei Zhalezka" ||
 	    name == "Maryna Furman" ||
        name == undefined) {
        return true;
    }
    return false;
};
<commit_msg>-- add mariya_babich mariya_babich in old developers list<commit_after>function Teams() {
    this.teams = [
        {
            id: "Renaissance",
            name: "Renaissance",
            streams: ["StreamR1", "StreamR2", "StreamR3"],
            teamLead: "Aliaksandr Koush",
            qaTeamLead: "Aliaksandra Kutynka",
            developers: [
                "Andrei Osipau2",
                "Dzianis Arlouski",
                "Siarhei Tkachenka",
                "Iryna Kucharenka1",
                "Ivan Izmer",
                "Mark Varabyou",
                "Raman But-Husaim",
                "Siarhei Abrazhevich",
                "Artsiom Rusak",
                "Raman Ivanou",
                "Aliaksandr Koush",
                "Nicolay Kostroma",
                "Valentina Napolnova",
                "Aliaksey Rahatka",
                "Pavel Kastsiuk",
                "Juliana Stolnik",
		        "Volha Viktarava",
                "Artsiom Kazlou"
            ],
            testers: [
                "Pavel Vysotsky",
                "Viktoriya Harbatsenkava",
                "Hanna Prykhodzka",
                "Kseniya Kavalchuk",
                "Yuliya Tukaila",
		        "Aliaksei Huliayeu",
		        "Artsiom Yesis",
		        "Siarhei Shyshparonak",
                "Aliaksandra Kutynka"
            ]
        },
        {
            id: "Inspiration",
            name: "Inspiration",
            streams: ["StreamIn1", "StreamIn2", "StreamIn3"],
            teamLead: "Sergey Tischenko",
            qaTeamLead: "Denys Pugachov",
            developers: [
                "Borys Roshal",
                "Denys Poliakov",
                "Kostiantyn Lazurenko",
                "Oleksandr Stukalov",
                "Oleksii Bespalko",
                "Yevhenii Havryliuk",
                "Yuriy Shestyora",
                "Ihor Bershov",
                "Vladyslav Pilhui",
                "Oleksandr Zhyltsov",
                "Oleksii Suriadnyi",
                "Serhiy Haponenko",
                "Yevhenii Lomov",
                "Ihor Rudchenko",
                "Andrii Savinov",
                "Dmytro Petlia",
                "Olena Ostroverkhova",
		        "Volodymyr Osmak"
            ],
            testers: [
                "Mila Botnar",
                "Yuri Timchenko",
                "Anastasia Kotenyova",
                "Pavlo Golovashchenko",
                "Oleksii Milman",
		        "Svitlana Andrieieva",
                "Denys Pugachov"
            ]
        },
        {
            id: "Nova",
            name: "Nova",
            streams: ["StreamN1", "StreamN2", "StreamN3"],
            teamLead: "Heorhi Vilkitski",
            qaTeamLead: "Valiantsina Krautsevich",
            developers: [
                "Andrei Kandybovich",
                "Dzmitry Siamchonak",
                "Mikita Stalpinski",
                "Uladzimir Harabtsou",
                "Aliaksandr Nikulin",
                "Ilya Kazlou1",
                "Katsiaryna Kaliukhovich",
                "Vadzim Vysotski",
                "Edhar Liashok",
                "Raman Prakofyeu",
                "Ruslan Khilmanovich",
                "Anton Kratenok",
                "Siarhei Maksimau1",
                "Dzmitry Chapurok",
		        "Pavel Davidouski",
                "Evgeny Sinitsyn"
            ],
            testers: [
                "Aliaksei Burnosenka",
                "Viktar Mikalayenka",
                "Eugeny Okulik",
                "Yuliya Kalasouskaya",
                "Hanna Maskalenka",
		        "Kiryl Kozubouski",
		        "Mikhail Naskalau",
		        "Nataliya Shmakava",
                "Valiantsina Krautsevich"
            ]
        },
        {
            id: "Liberty",
            name: "Liberty",
            streams: ["StreamL1", "StreamL2", "StreamL3"],
            teamLead: "Dzmitry Tabolich",
            qaTeamLead: "Iryna Kutsko",
            developers: [
                "Pavel Naumenka",
                "Sergei Kulick",
                "Ilya Huchok",
                "Aliaksandr Rusak",
                "Andrei Kasak",
                "Andrei Krasnou",
                "Pavel Krakasevich",
                "Stepan Zelenin",
                "Dzmitry Isachenka",
                "Eugen Surovets",
                "Katsiaryna Tsalabanava",
                "Andrii Prykhodko",
                "Hleb Krotsik",
                "Uladzimir Vysotski"
            ],
            testers: [
                "Anna Novikova",
                "Anton Rapinchuk",
                "Igor Andros",
                "Maria Sobal",
                "Yuliya Karnatsevich",
                "Nastassia Dziadkova",
                "Iryna Kutsko",
                "Natalya Krestelyova"
            ]
        },
        {
            id: "Viva",
            name: "Viva",
            streams: ["StreamV1", "StreamV2", "StreamV3"],
            teamLead: "Valentine Zhuck",
            qaTeamLead: "Katsiaryna Kuchko",
            developers: [
                "Valentine Zhuck",
                "Viachaslau Anufryiuk",
                "Yury Yamoryk",
                "Aliaksandr Kladau",
                "Dzmitry Kavaliou",
                "Dzmitry Shynkarou",
                "Maksim Tsikhan",
                "Petr Falitarchyk",
                "Yuri Chupyrkin",
                "Aliaksandr Rykau",
                "Ivan Dziameshka",
                "Siarhei Bahdanovich",
                "Andrei Lysenka",
                "Aleh Dukel",
                "Ivan Yanchuk",
                "Kanstantsin Ldou",
                "Siarhei Nikitsin",
		        "Mikhail Kelbas",
                "Katsiaryna Zeliankova"
            ],
            testers: [
                "Iryna Malets",
                "Maryia Kireyeva",
                "Iryna Shuliak",
                "Liudmila Barshcheuskaya",
                "Iryna Razorionova",
		        "Volha Shymanovich",
                "Katsiaryna Kuchko"
            ]
        },
        {
            id: "Elfish",
            name: "Elfish",
            teamLead: "Roman Golovchenko",
            qaTeamLead: "",
            developers: [
                "Roman Golovchenko",
                "Allaberdi Hojayev",
                "Bohdan Sorokin",
		        "Ivan Manzhos",
		        "Oleh Vinnikov",
                "Yevhenii Koliesnik"
            ],
            testers: [
                "Ivan Nalyvaiko",
                "Oleksii Shchelkunov",
                "Valeriia Karabut"
            ]
        },
        {
            id: "TeamAutomation",
            name: "Automation",
            teamLead: "Aliaksandr Basau",
            developers: [
                "Viachaslau Naimovich",
                "Vitali Sonchyk",
                "Katsiaryna Kulbitskaya",
                "Maryia Kashtanava"
            ]
        }
    ]
}

exports.AllTeams = new Teams();

exports.OldDevelopers = function oldDevelopers(name) {
    if(name == 'Valentine Zhuck' ||
        name == 'Dzmitry Tabolich' ||
        name == 'Heorhi Vilkitski' ||
        name == "Hanna Kastsian" ||
        name == "Alena Charnova" ||
        name == "Aliaksei Astashkin" ||
        name == "yauheni_lohinau" ||
        name == "Dmytro Komar" ||
        name == "Aliaksei Labachou" ||
        name == "Mariya Babich" ||
		name == "mariya_babich mariya_babich" ||
        name == "Katsiaryna Sasina" ||
        name == "aliaksei_labachou aliaksei_labachou" ||
        name == "Maryna Furman" ||
 	    name == "Dzmitry Salodki" ||
	    name == "Volha Shandrokha" ||
 	    name == "Kate Tsalabanava" ||
 	    name == "Vitali Podobed" ||
 	    name == "Siarhei Zhalezka" ||
 	    name == "Maryna Furman" ||
        name == undefined) {
        return true;
    }
    return false;
};
<|endoftext|>


<commit_before>/* global electron */
/* global angular */
/* global $ */
/* global io */
angular
.value('cnc',{
  arduino:false,
  working:false,
  pause:{
    line: 0,
    status: false,
    steps: [0,0,0]
  },
  file:{
    //gcode : [],
    name:'Sin Archivo.',
    line: {
      total : 0,
      run : 0,
      duration : 0,
      progress : 0
    },
    travel : 0
  },
  Progress: function  (trvl) {
	  // this = cnc
    this.file.line.run++;
    this.file.line.progress = ((trvl*100)/this.file.travel).toFixed(2);
    if(this.file.line.progress>16 || this.file.line.progress===0){
      let time = new Date().getTime() - this.time.start.getTime();
      let mileSecondsLeft =  this.file.travel * time / trvl;
      this.time.end = new Date( this.time.start.getTime() + mileSecondsLeft );
      console.log(mileSecondsLeft / trvl);
    }
  },
  time:{
    pause:'--:--',
    start:'--:--',
    end:'--:--'
  }
})
.value('lineTable', [])
.value('statusBar', {
  "message":"CNC-ino.",
  "type":"none",
  "time":3000
})
.value('config', {
    "motor": {
    "xy": {
      "time": 24,
      "steps": 4000,
      "advance": 29.37
    },
    "z": {
      "steps": 2000,
      "advance": 14
    }
  }
})
.directive('checkbox', function () {
  return {
    link: function (scope, element, attrs) {
        element.checkbox();
    }
  }
})
.directive('popupElement', function () {
  return {
    link: function (scope, element, attrs) {
      element.popup({
        title    : attrs.ngPopupTitle,
        content  : attrs.ngPopup,
        position : attrs.ngPopupPosition,
        variation : attrs.ngPopupVariatio,
        delay: {
          hide: 450
        }
      });
    }
  }
})
.directive('ngPopup', function () {
  return {
    link: function (scope, element, attrs) {
      element.popup({
        popup : $(attrs.id)
      });
    }
  }
})
;<commit_msg>delete consol lg<commit_after>/* global electron */
/* global angular */
/* global $ */
/* global io */
angular
.value('cnc',{
  arduino:false,
  working:false,
  pause:{
    line: 0,
    status: false,
    steps: [0,0,0]
  },
  file:{
    //gcode : [],
    name:'Sin Archivo.',
    line: {
      total : 0,
      run : 0,
      duration : 0,
      progress : 0
    },
    travel : 0
  },
  Progress: function  (trvl) {
	  // this = cnc
    this.file.line.run++;
    this.file.line.progress = ((trvl*100)/this.file.travel).toFixed(2);
    if(this.file.line.progress>16 || this.file.line.progress===0){
      let time = new Date().getTime() - this.time.start.getTime();
      let mileSecondsLeft =  this.file.travel * time / trvl;
      this.time.end = new Date( this.time.start.getTime() + mileSecondsLeft );
    }
  },
  time:{
    pause:'--:--',
    start:'--:--',
    end:'--:--'
  }
})
.value('lineTable', [])
.value('statusBar', {
  "message":"CNC-ino.",
  "type":"none",
  "time":3000
})
.value('config', {
    "motor": {
    "xy": {
      "time": 24,
      "steps": 4000,
      "advance": 29.37
    },
    "z": {
      "steps": 2000,
      "advance": 14
    }
  }
})
.directive('checkbox', function () {
  return {
    link: function (scope, element, attrs) {
        element.checkbox();
    }
  }
})
.directive('popupElement', function () {
  return {
    link: function (scope, element, attrs) {
      element.popup({
        title    : attrs.ngPopupTitle,
        content  : attrs.ngPopup,
        position : attrs.ngPopupPosition,
        variation : attrs.ngPopupVariatio,
        delay: {
          hide: 450
        }
      });
    }
  }
})
.directive('ngPopup', function () {
  return {
    link: function (scope, element, attrs) {
      element.popup({
        popup : $(attrs.id)
      });
    }
  }
})
;<|endoftext|>


<commit_before>import Ember from 'ember';

/**
  * @overview OAuth2 library for Emberjs that stores tokens in the browsers localStorage
  * @license   Licensed under MIT license
  *            See https://raw.github.com/amkirwan/ember-oauth2/master/LICENSE
  * @version   0.7.0
  *
  * @module ember-oauth2
  * @class ember-oauth2
  */
export default Ember.Object.extend(Ember.Evented, {
  /**
   * Initializes the Ember.OAuth2 object when using Ember.OAuth2.create({providerId: 'providerId'}). The following options are available for the configuring a provider: clientId, authBaseUri, redirectUri, scope, statePrefix and tokenPrefix. The clientId, authBaseUri and redirectUri are required. The statePrefix has a default value of 'state' and the tokenPrefix has a default value of 'token'.
   *
   * @method init
   */
  init: function() {
    this._super();
    /**
     * The configuration object for the given provider id.
     *  @property {Object} providerConfig
     *  @property {Object} providerConfig.providerId **Required**
     *  @property {String} providerConfig.providerId.clientId **Required**
     *  @property {String} providerConfig.providerId.authBaseUri **Required**
     *  @property {String} providerConfig.providerId.redirectUri **Required**
     *  @property {String} providerConfig.providerId.scope **Optional**
     *  @property {String} providerConfig.providerId.responseType **Default:** "token", **Optional**
     *  @property {String} providerConfig.providerId.statePrefix **Default:** "state", **Optional**
     *  @property {String} providerConfig.providerId.tokenPrefix **Default:** "prefix", **Optional**
     *  @example
     *    App.oauth = Ember.OAuth2.create({providerId: 'google'});
     */

    // if Ember.OAuth2.config has keys use it instead of window.ENV
    if (Ember.OAuth2 && Ember.OAuth2.config && Object.keys(Ember.OAuth2.config).length) {
      Ember.Logger.warn("Ember.OAuth2.config is deprecated and will be removed in future versions. Set the config using window.ENV['ember-oauth2']");
      this.set('config', Ember.OAuth2.config);
    } else if (window.EmberENV && window.EmberENV['ember-oauth2']) {
      this.set('config', window.EmberENV['ember-oauth2']);
    } else if (window.ENV && window.ENV['ember-oauth2']) {
      this.set('config', window.ENV['ember-oauth2']);
    } else {
      throw new Error('Cannot find the ember-oauth2 config.');
    }

    if (!this.get('config')[this.get('providerId')]) {
      throw new Error("Cannot find the providerId: '" + this.get('providerId') + "' in the config.");
    }

    this.set('providerConfig', this.get('config')[this.get('providerId')]);

    /**
     * The prefix name for the state key stored in the localStorage.
     *
     * @property statePrefix
     * @type String
     * @default "state"
     */
    this.set('statePrefix', 'state');
    /**
     * The prefix name for the token key stored in the localStorage.
     *
     * @property tokenPrefix
     * @type String
     * @default "token"
     */
    this.set('tokenPrefix', 'token');

    /**
     * The response type for the authorization request.
     *
     * @property responseType
     * @type String
     * @default "token"
     */
    this.set('responseType', 'token');

    /**
     * @property {String} clientId
     */
    /**
     * @property {String} authBaseUri
     */
    /**
     * @property {String} redirectUri
     */
    /**
     * @property {String} scope
     */
    // sets the properties from the providerConfig and overrides any default settings.
    this.setProperties(this.providerConfig);

    /**
     * @event redirect
     * @param {function} The function that handles the redirect.
     */
    this.on('redirect', this.handleRedirect);
  },

  /**
   * @method version
   * @return {String} The current version number of Ember.OAuth2
   */
  version: function() {
    return VERSION;
  },

  /**
   * @method uuid
   * @return {String} A pseudo random uuid
   */
  uuid: function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
          var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
              return v.toString(16);
    });
  },

  /**
   * @method now
   * @return {Number} The current time in seconds rounded
   */
  now: function() {
    return Math.round(new Date().getTime()/1000.0);
  },

  /**
   * Creates and returns the request object.
   *
   * @method requestObj
   * @return {Object} request object
   */
  requestObj: function() {
    var request = {};
    request.response_type = this.get('responseType');
    request.providerId = this.get('providerId');
    request.state = this.get('state');
    request.client_id = this.get('clientId');
    request.state = this.get('state');
    if (this.get('scope')) request.scope = this.get('scope');
    return request;
  },

  /**
   * @method authUri
   * @return {String} Authorization uri for generating an OAuth2 token
   */
  authUri: function() {
    if (!this.get('state')) { this.set('state', this.uuid()); }
    var uri = this.get('authBaseUri');
    uri += '?response_type=' + encodeURIComponent(this.get('responseType')) +
        '&redirect_uri=' + encodeURIComponent(this.get('redirectUri')) +
        '&client_id=' + encodeURIComponent(this.get('clientId')) +
        '&state=' + encodeURIComponent(this.get('state'));
    if (this.get('scope')) uri += '&scope=' + encodeURIComponent(this.get('.scope')).replace('%20', '+');
    return uri;
  },

  /**
   * Open authorize window if the configuration object is valid.
   *
   * @method authorize
   * @return {Promise}
   */
  authorize: function() {
    if (!this.get('providerId')) throw new Error('No provider id given.');
    if (!this.get('clientId')) throw new Error('No client id given.');
    if (!this.get('authBaseUri')) throw new Error('No auth base uri given.');
    if (!this.get('redirectUri')) throw new Error('No redirect uri given.');
    var authorizeUri = this.authUri();
    this.clearStates();
    this.saveState(this.get('state'), this.requestObj());
    return this.openWindow(authorizeUri);
  },

  /**
   * Isolated function responsible for opening windows, to make it
   * easier to override this part in some environments (e.g. Phonegap)

    @param {String} url
    @return {Object} On resolve returns reference to the opened window.
                    On reject returns Object with reference to dialog and error.
   */
  openWindow: function(url) {
    var dialog = window.open(url, 'Authorize', 'height=600, width=450');
    if (window.focus && dialog) { dialog.focus(); }
    return new Ember.RSVP.Promise(function(resolve, reject) {
      if (dialog) { resolve(dialog); }
      else { reject(new Error('Opening dialog login window failed.')); }
    });
  },

  /**
   @method authSuccess
    @param {Object} The params returned from the OAuth2 callback
    @return {String} the access_token from the params
  */
  authSuccess: function(params) {
    return (this.get('responseType') === 'token' && params.access_token) ||
            (this.get('responseType') === 'code' && params.code);
  },

  /**
   * Token properties
   * providerId
   * expiresIn
   * scope
   * token

    @method generateToken
    @return {Object} The access_token object with info about the token
   */
  generateToken: function(params) {
    var token = {};
    token.provider_id = this.get('providerId');
    token.expires_in = this.expiresIn(params.expires_in);
    token.scope = this.get('scope');
    token.access_token = params.access_token;
    return token;
  },

  /**
   * @method expiresIn
   * @param {String} expires Expires time string from params
   * @return {Number} When the token expires in seconds.
  */
  expiresIn: function(expires) {
    return this.now() + parseInt(expires, 10);
  },

  /**
   * proxy functions for old event handlers
   *
   * Check if the token returned is valid and if so trigger `success` event else trigger `error`
   *
   * @method handleRedirect
   * @param {Object} hash The window location hash callback url
   * @param {Function} callback Optional callback
   */
  handleRedirect: function(hash, callback) {
    var params = this.parseCallback(hash);

    if (this.authSuccess(params)) {
      var stateObj = this.getState(params.state);
      this.checkState(stateObj);

      if (this.get('responseType') === "token") {
        this.saveToken(this.generateToken(params));
        this.trigger('success', stateObj);
      }
      else {
        this.trigger('success', params.code);
      }
    } else {
      this.trigger('error', params);
    }

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

  /**
   * Checks if the State returned from the server matches the state that was generated in the original request and saved in the browsers localStorage.
   *
   * @method checkState
   * @param {Object} stateObj The object returned from localStorage
   */
  checkState: function(stateObj) {
    if (!stateObj) throw new Error("Could not find state.");
    if (stateObj.state !== this.get('state')) throw new Error("State returned from the server did not match the local saved state.");
  },

  /**
   * Parse the callback function from the OAuth2 provider
   *
   * callback should have the following params if authentication is successful
   * state
   * access_token
   * token_type
   * expires_in
   *
   * @method parseCalback
   * @param {String} locationHash
   * @return {Object} The params returned from the OAuth2 provider
   */
  parseCallback: function(locationHash) {
    var oauthParams = {};
    var queryString = locationHash.substring(locationHash.indexOf('?'));
    var regex = /([^#?&=]+)=([^&]*)/g;
    var match;
    while ((match = regex.exec(queryString)) !== null) {
      oauthParams[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
    }
    return oauthParams;
  },

  /**
   * @method saveState
   * @param {String} state The state uuid
   * @param {Object} requestObj Properties of the request state to save in localStorage
   */
  saveState: function(state, requestObj) {
    window.localStorage.setItem(this.stateKeyName(), JSON.stringify(requestObj));
  },

  /**
   * Return the saved state and remove it from the localStoage.
   *
   * @method getState
   * @param {String} state The state uuid to retreive from localStorage
   * @return {Object} Properties of the request state
   */
  getState: function(state) {
    var keyName = state || this.stateKeyName();
    var obj = JSON.parse(window.localStorage.getItem(keyName));
    this.removeState();

    return obj;
  },

  /**
    * Remove any states from localStorage if they exist
    * @method clearStates
    * @return {Array} Keys used to remove states from localStorage
    */
  clearStates: function() {
    var regex = new RegExp( '^' + this.get('statePrefix') + '-.*', 'g');

    var name;
    var toRemove = [];
    for(var i = 0, l = window.localStorage.length; i < l; i++) {
      name = window.localStorage.key(i);
      if (name.match(regex)) {
        toRemove.push(name);
      }
    }

    for(var j = 0, len = toRemove.length; j < len; j++) {
      name = toRemove[j];
      this.removeState(name);
    }
    return toRemove;
  },

  /**
   * The key name to use for saving state to localstorage
   *
   * @method stateKeyName
   */
  stateKeyName: function() {
    return this.get('statePrefix') + '-' + this.get('state');
  },

  /**
   * The key name to use for saving the token to localstorage
   *
   * @method tokenKeyName
   */
  tokenKeyName: function() {
    return this.get('tokenPrefix') + '-' + this.get('providerId');
  },

  /**
   * saveToken stores the token by the tokenPrefix and the providerId
   * access_token
   * expires : time that the token expires
   * providerId: the providerId
   * scopes: array of scopes
   *
   * @method saveToken
   * @param {Object} token Saves the params in the response from the OAuth2 server to localStorage with the key 'tokenPrefix-providerId
   */
  saveToken: function(token) {
    window.localStorage.setItem(this.tokenKeyName(), JSON.stringify(token));
  },

  /**
   * remove the state from localstorage
   */
  removeState: function(stateName) {
    if (stateName) {
      return window.localStorage.removeItem(stateName);
    } else {
      return window.localStorage.removeItem(this.stateKeyName());
    }
  },

  /**
   * remove the token from localstorage
   */
  removeToken: function() {
    return window.localStorage.removeItem(this.tokenKeyName());
  },

  /**
   * @method getToken
   * @return {Object} The params from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
   */
  getToken: function() {
    var token = JSON.parse(window.localStorage.getItem(this.tokenKeyName()));
    if (!token) return null;
    if (!token.access_token) return null;
    return token;
  },

  /**
   * @method getAccessToken
   * @return {Object} The access_token param from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
   */
  getAccessToken: function() {
    var token = this.getToken();
    if (!token) return null;
    return token.access_token;
  },

  /**
   * @method accessTokenIsExpired
   * @return {Boolean} Check if the access_token is expired.
   */
  accessTokenIsExpired: function() {
    var token = this.getToken();
    if (!token) return true;
    if (this.now() >= token.expires_in) {
      return true;
    } else {
      return false;
    }
  },

  /**
   * Sets the access token expires_in time to 0 and saves the token to localStorage
   * @method expireAccessToken
   */
  expireAccessToken: function() {
    var token = this.getToken();
    if (!token) return null;
    token.expires_in = 0;
    this.saveToken(token);
  }
});

/**
 * @property {String} VERSION
 * @final
*/
var VERSION = "0.7.0";

/**
 * @method version
 * @static
 */
if (Ember.OAuth2) {
 Ember.OAuth2.version = VERSION;
}
<commit_msg>additonal yuidoc<commit_after>import Ember from 'ember';

/**
  * @overview OAuth2 library for Emberjs that stores tokens in the browsers localStorage
  * @license   Licensed under MIT license
  *            See https://raw.github.com/amkirwan/ember-oauth2/master/LICENSE
  * @version   0.7.0
  *
  * @module ember-oauth2
  * @class ember-oauth2
  */
export default Ember.Object.extend(Ember.Evented, {
  /**
   * Initializes the Ember.OAuth2 object when using Ember.OAuth2.create({providerId: 'providerId'}). The following options are available for the configuring a provider: clientId, authBaseUri, redirectUri, scope, statePrefix and tokenPrefix. The clientId, authBaseUri and redirectUri are required. The statePrefix has a default value of 'state' and the tokenPrefix has a default value of 'token'.
   *
   * @method init
   */
  init: function() {
    this._super();
    /**
     * The configuration object for the given provider id.
     *  @property {Object} providerConfig
     *  @property {Object} providerConfig.providerId **Required**
     *  @property {String} providerConfig.providerId.clientId **Required**
     *  @property {String} providerConfig.providerId.authBaseUri **Required**
     *  @property {String} providerConfig.providerId.redirectUri **Required**
     *  @property {String} providerConfig.providerId.scope **Optional**
     *  @property {String} providerConfig.providerId.responseType **Default:** "token", **Optional**
     *  @property {String} providerConfig.providerId.statePrefix **Default:** "state", **Optional**
     *  @property {String} providerConfig.providerId.tokenPrefix **Default:** "prefix", **Optional**
     *  @example
     *    App.oauth = Ember.OAuth2.create({providerId: 'google'});
     */

    // if Ember.OAuth2.config has keys use it instead of window.ENV
    if (Ember.OAuth2 && Ember.OAuth2.config && Object.keys(Ember.OAuth2.config).length) {
      Ember.Logger.warn("Ember.OAuth2.config is deprecated and will be removed in future versions. Set the config using window.ENV['ember-oauth2']");
      this.set('config', Ember.OAuth2.config);
    } else if (window.EmberENV && window.EmberENV['ember-oauth2']) {
      this.set('config', window.EmberENV['ember-oauth2']);
    } else if (window.ENV && window.ENV['ember-oauth2']) {
      this.set('config', window.ENV['ember-oauth2']);
    } else {
      throw new Error('Cannot find the ember-oauth2 config.');
    }

    if (!this.get('config')[this.get('providerId')]) {
      throw new Error("Cannot find the providerId: '" + this.get('providerId') + "' in the config.");
    }

    this.set('providerConfig', this.get('config')[this.get('providerId')]);

    /**
     * The prefix name for the state key stored in the localStorage.
     *
     * @property statePrefix
     * @type String
     * @default "state"
     */
    this.set('statePrefix', 'state');
    /**
     * The prefix name for the token key stored in the localStorage.
     *
     * @property tokenPrefix
     * @type String
     * @default "token"
     */
    this.set('tokenPrefix', 'token');

    /**
     * The response type for the authorization request.
     *
     * @property responseType
     * @type String
     * @default "token"
     */
    this.set('responseType', 'token');

    /**
     * @property {String} clientId
     */
    /**
     * @property {String} authBaseUri
     */
    /**
     * @property {String} redirectUri
     */
    /**
     * @property {String} scope
     */
    // sets the properties from the providerConfig and overrides any default settings.
    this.setProperties(this.providerConfig);

    /**
     * @event redirect
     * @param {function} The function that handles the redirect.
     */
    this.on('redirect', this.handleRedirect);
  },

  /**
   * @method version
   * @return {String} The current version number of Ember.OAuth2
   */
  version: function() {
    return VERSION;
  },

  /**
   * @method uuid
   * @return {String} A pseudo random uuid
   */
  uuid: function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
          var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
              return v.toString(16);
    });
  },

  /**
   * @method now
   * @return {Number} The current time in seconds rounded
   */
  now: function() {
    return Math.round(new Date().getTime()/1000.0);
  },

  /**
   * Creates and returns the request object.
   *
   * @method requestObj
   * @return {Object} request object
   */
  requestObj: function() {
    var request = {};
    request.response_type = this.get('responseType');
    request.providerId = this.get('providerId');
    request.state = this.get('state');
    request.client_id = this.get('clientId');
    request.state = this.get('state');
    if (this.get('scope')) request.scope = this.get('scope');
    return request;
  },

  /**
   * @method authUri
   * @return {String} Authorization uri for generating an OAuth2 token
   */
  authUri: function() {
    if (!this.get('state')) { this.set('state', this.uuid()); }
    var uri = this.get('authBaseUri');
    uri += '?response_type=' + encodeURIComponent(this.get('responseType')) +
        '&redirect_uri=' + encodeURIComponent(this.get('redirectUri')) +
        '&client_id=' + encodeURIComponent(this.get('clientId')) +
        '&state=' + encodeURIComponent(this.get('state'));
    if (this.get('scope')) uri += '&scope=' + encodeURIComponent(this.get('.scope')).replace('%20', '+');
    return uri;
  },

  /**
   * Open authorize window if the configuration object is valid.
   *
   * @method authorize
   * @return {Promise}
   */
  authorize: function() {
    if (!this.get('providerId')) throw new Error('No provider id given.');
    if (!this.get('clientId')) throw new Error('No client id given.');
    if (!this.get('authBaseUri')) throw new Error('No auth base uri given.');
    if (!this.get('redirectUri')) throw new Error('No redirect uri given.');
    var authorizeUri = this.authUri();
    this.clearStates();
    this.saveState(this.get('state'), this.requestObj());
    return this.openWindow(authorizeUri);
  },

  /**
   * Isolated function responsible for opening windows, to make it
   * easier to override this part in some environments (e.g. Phonegap)

    @param {String} url
    @return {Object} On resolve returns reference to the opened window.
                    On reject returns Object with reference to dialog and error.
   */
  openWindow: function(url) {
    var dialog = window.open(url, 'Authorize', 'height=600, width=450');
    if (window.focus && dialog) { dialog.focus(); }
    return new Ember.RSVP.Promise(function(resolve, reject) {
      if (dialog) { resolve(dialog); }
      else { reject(new Error('Opening dialog login window failed.')); }
    });
  },

  /**
   @method authSuccess
    @param {Object} The params returned from the OAuth2 callback
    @return {String} the access_token from the params
  */
  authSuccess: function(params) {
    return (this.get('responseType') === 'token' && params.access_token) ||
            (this.get('responseType') === 'code' && params.code);
  },

  /**
   * Token properties
   * providerId
   * expiresIn
   * scope
   * token

    @method generateToken
    @return {Object} The access_token object with info about the token
   */
  generateToken: function(params) {
    var token = {};
    token.provider_id = this.get('providerId');
    token.expires_in = this.expiresIn(params.expires_in);
    token.scope = this.get('scope');
    token.access_token = params.access_token;
    return token;
  },

  /**
   * @method expiresIn
   * @param {String} expires Expires time string from params
   * @return {Number} When the token expires in seconds.
  */
  expiresIn: function(expires) {
    return this.now() + parseInt(expires, 10);
  },

  /**
   * proxy functions for old event handlers
   *
   * Check if the token returned is valid and if so trigger `success` event else trigger `error`
   *
   * @method handleRedirect
   * @param {Object} hash The window location hash callback url
   * @param {Function} callback Optional callback
   */
  handleRedirect: function(hash, callback) {
    var params = this.parseCallback(hash);

    if (this.authSuccess(params)) {
      var stateObj = this.getState(params.state);
      this.checkState(stateObj);

      if (this.get('responseType') === "token") {
        this.saveToken(this.generateToken(params));
        this.trigger('success', stateObj);
      }
      else {
        this.trigger('success', params.code);
      }
    } else {
      this.trigger('error', params);
    }

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

  /**
   * Checks if the State returned from the server matches the state that was generated in the original request and saved in the browsers localStorage.
   *
   * @method checkState
   * @param {Object} stateObj The object returned from localStorage
   */
  checkState: function(stateObj) {
    if (!stateObj) throw new Error("Could not find state.");
    if (stateObj.state !== this.get('state')) throw new Error("State returned from the server did not match the local saved state.");
  },

  /**
   * Parse the callback function from the OAuth2 provider
   *
   * callback should have the following params if authentication is successful
   * state
   * access_token
   * token_type
   * expires_in
   *
   * @method parseCalback
   * @param {String} locationHash
   * @return {Object} The params returned from the OAuth2 provider
   */
  parseCallback: function(locationHash) {
    var oauthParams = {};
    var queryString = locationHash.substring(locationHash.indexOf('?'));
    var regex = /([^#?&=]+)=([^&]*)/g;
    var match;
    while ((match = regex.exec(queryString)) !== null) {
      oauthParams[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
    }
    return oauthParams;
  },

  /**
   * @method saveState
   * @param {String} state The state uuid
   * @param {Object} requestObj Properties of the request state to save in localStorage
   */
  saveState: function(state, requestObj) {
    window.localStorage.setItem(this.stateKeyName(), JSON.stringify(requestObj));
  },

  /**
   * Return the saved state and remove it from the localStoage.
   *
   * @method getState
   * @param {String} state The state uuid to retreive from localStorage
   * @return {Object} Properties of the request state
   */
  getState: function(state) {
    var keyName = state || this.stateKeyName();
    var obj = JSON.parse(window.localStorage.getItem(keyName));
    this.removeState();

    return obj;
  },

  /**
    * Remove any states from localStorage if they exist
    * @method clearStates
    * @return {Array} Keys used to remove states from localStorage
    */
  clearStates: function() {
    var regex = new RegExp( '^' + this.get('statePrefix') + '-.*', 'g');

    var name;
    var toRemove = [];
    for(var i = 0, l = window.localStorage.length; i < l; i++) {
      name = window.localStorage.key(i);
      if (name.match(regex)) {
        toRemove.push(name);
      }
    }

    for(var j = 0, len = toRemove.length; j < len; j++) {
      name = toRemove[j];
      this.removeState(name);
    }
    return toRemove;
  },

  /**
   * The key name to use for saving state to localstorage
   *
   * @method stateKeyName
   * @return {String} The state key name used for localstorage
   */
  stateKeyName: function() {
    return this.get('statePrefix') + '-' + this.get('state');
  },

  /**
   * The key name to use for saving the token to localstorage
   *
   * @method tokenKeyName
   * @return {String} The token key name used for localstorage
   */
  tokenKeyName: function() {
    return this.get('tokenPrefix') + '-' + this.get('providerId');
  },

  /**
   * saveToken stores the token by the tokenPrefix and the providerId
   * access_token
   * expires : time that the token expires
   * providerId: the providerId
   * scopes: array of scopes
   *
   * @method saveToken
   * @param {Object} token Saves the params in the response from the OAuth2 server to localStorage with the key 'tokenPrefix-providerId
   */
  saveToken: function(token) {
    window.localStorage.setItem(this.tokenKeyName(), JSON.stringify(token));
  },

  /**
   * remove the state from localstorage
   *
   * @method removeState
   * @param {String} stateName The keyname of the state object in localstorage
   * @return {Object} The deleted state object from localstorage
   */
  removeState: function(stateName) {
    if (stateName) {
      return window.localStorage.removeItem(stateName);
    } else {
      return window.localStorage.removeItem(this.stateKeyName());
    }
  },

  /**
   * remove the token from localstorage
   *
   * @method removeToken
   * @return {Object} The token object in localstorage
   */
  removeToken: function() {
    return window.localStorage.removeItem(this.tokenKeyName());
  },

  /**
   * @method getToken
   * @return {Object} The params from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
   */
  getToken: function() {
    var token = JSON.parse(window.localStorage.getItem(this.tokenKeyName()));
    if (!token) return null;
    if (!token.access_token) return null;
    return token;
  },

  /**
   * @method getAccessToken
   * @return {Object} The access_token param from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
   */
  getAccessToken: function() {
    var token = this.getToken();
    if (!token) return null;
    return token.access_token;
  },

  /**
   * @method accessTokenIsExpired
   * @return {Boolean} Check if the access_token is expired.
   */
  accessTokenIsExpired: function() {
    var token = this.getToken();
    if (!token) return true;
    if (this.now() >= token.expires_in) {
      return true;
    } else {
      return false;
    }
  },

  /**
   * Sets the access token expires_in time to 0 and saves the token to localStorage
   * @method expireAccessToken
   */
  expireAccessToken: function() {
    var token = this.getToken();
    if (!token) return null;
    token.expires_in = 0;
    this.saveToken(token);
  }
});

/**
 * @property {String} VERSION
 * @final
*/
var VERSION = "0.7.0";

/**
 * @method version
 * @static
 */
if (Ember.OAuth2) {
 Ember.OAuth2.version = VERSION;
}
<|endoftext|>