<commit_before>import _ from 'lodash';
import { compactQuery } from '../../../utils';
import { DBConnector, HISTORY_TO_TABLE_MAP, consolidateByTrendColumns } from '../dbConnector';

const consolidateByFunc = {
  'avg': 'MEAN',
  'min': 'MIN',
  'max': 'MAX',
  'sum': 'SUM',
  'count': 'COUNT'
};

export class InfluxDBConnector extends DBConnector {
  constructor(options) {
    super(options);
    this.retentionPolicy = options.retentionPolicy;
    super.loadDBDataSource().then(ds => {
      this.influxDS = ds;
      return ds;
    });
  }

  /**
   * Try to invoke test query for one of Zabbix database tables.
   */
  testDataSource() {
    return this.influxDS.testDatasource();
  }

  getHistory(items, timeFrom, timeTill, options) {
    let { intervalMs, consolidateBy, retentionPolicy } = options;
    const intervalSec = Math.ceil(intervalMs / 1000);

    const range = { timeFrom, timeTill };
    consolidateBy = consolidateBy || 'avg';

    // Group items by value type and perform request for each value type
    const grouped_items = _.groupBy(items, 'value_type');
    const promises = _.map(grouped_items, (items, value_type) => {
      const itemids = _.map(items, 'itemid');
      const table = HISTORY_TO_TABLE_MAP[value_type];
      const query = this.buildHistoryQuery(itemids, table, range, intervalSec, consolidateBy, retentionPolicy);
      return this.invokeInfluxDBQuery(query);
    });

    return Promise.all(promises)
    .then(_.flatten)
    .then(results => {
      return handleInfluxHistoryResponse(results);
    });
  }

  getTrends(items, timeFrom, timeTill, options) {
    options.retentionPolicy = this.retentionPolicy;
    return this.getHistory(items, timeFrom, timeTill, options);
  }

  buildHistoryQuery(itemids, table, range, intervalSec, aggFunction, retentionPolicy) {
    const { timeFrom, timeTill } = range;
    const measurement = retentionPolicy ? `"${retentionPolicy}"."${table}"` : `"${table}"`;
    let value = 'value';
    if (retentionPolicy) {
      value = consolidateByTrendColumns[aggFunction] || 'value_avg';
    }
    const aggregation = consolidateByFunc[aggFunction] || aggFunction;
    const where_clause = this.buildWhereClause(itemids);
    const query = `SELECT ${aggregation}("${value}") FROM ${measurement}
      WHERE ${where_clause} AND "time" >= ${timeFrom}s AND "time" <= ${timeTill}s
      GROUP BY time(${intervalSec}s), "itemid" fill(none)`;
    return compactQuery(query);
  }

  buildWhereClause(itemids) {
    const itemidsWhere = itemids.map(itemid => `"itemid" = '${itemid}'`).join(' OR ');
    return `(${itemidsWhere})`;
  }

  invokeInfluxDBQuery(query) {
    return this.influxDS._seriesQuery(query)
    .then(data => data && data.results ? data.results : []);
  }
}

///////////////////////////////////////////////////////////////////////////////

function handleInfluxHistoryResponse(results) {
  if (!results) {
    return [];
  }

  const seriesList = [];
  for (let i = 0; i < results.length; i++) {
    const result = results[i];

    if (result.error) {
      const error = `InfluxDB error: ${result.error}`;
      return Promise.reject(new Error(error));
    }

    if (!result || !result.series) {
      continue;
    }

    const influxSeriesList = results[i].series;

    for (let y = 0; y < influxSeriesList.length; y++) {
      const influxSeries = influxSeriesList[y];
      const datapoints = [];
      if (influxSeries.values) {
        for (i = 0; i < influxSeries.values.length; i++) {
          datapoints[i] = [influxSeries.values[i][1], influxSeries.values[i][0]];
        }
      }
      const timeSeries = {
        name: influxSeries.tags.itemid,
        points: datapoints
      };
      seriesList.push(timeSeries);
    }
  }

  return seriesList;
}
<commit_msg>DB Connection: return detailed connection error for InfluxDB<commit_after>import _ from 'lodash';
import { compactQuery } from '../../../utils';
import { DBConnector, HISTORY_TO_TABLE_MAP, consolidateByTrendColumns } from '../dbConnector';

const consolidateByFunc = {
  'avg': 'MEAN',
  'min': 'MIN',
  'max': 'MAX',
  'sum': 'SUM',
  'count': 'COUNT'
};

export class InfluxDBConnector extends DBConnector {
  constructor(options) {
    super(options);
    this.retentionPolicy = options.retentionPolicy;
    super.loadDBDataSource().then(ds => {
      this.influxDS = ds;
      return ds;
    });
  }

  /**
   * Try to invoke test query for one of Zabbix database tables.
   */
  testDataSource() {
    return this.influxDS.testDatasource().then(result => {
      if (result.status && result.status === 'error') {
        return Promise.reject({ data: {
          message: `InfluxDB connection error: ${result.message}`
        }});
      }
      return result;
    });
  }

  getHistory(items, timeFrom, timeTill, options) {
    let { intervalMs, consolidateBy, retentionPolicy } = options;
    const intervalSec = Math.ceil(intervalMs / 1000);

    const range = { timeFrom, timeTill };
    consolidateBy = consolidateBy || 'avg';

    // Group items by value type and perform request for each value type
    const grouped_items = _.groupBy(items, 'value_type');
    const promises = _.map(grouped_items, (items, value_type) => {
      const itemids = _.map(items, 'itemid');
      const table = HISTORY_TO_TABLE_MAP[value_type];
      const query = this.buildHistoryQuery(itemids, table, range, intervalSec, consolidateBy, retentionPolicy);
      return this.invokeInfluxDBQuery(query);
    });

    return Promise.all(promises)
    .then(_.flatten)
    .then(results => {
      return handleInfluxHistoryResponse(results);
    });
  }

  getTrends(items, timeFrom, timeTill, options) {
    options.retentionPolicy = this.retentionPolicy;
    return this.getHistory(items, timeFrom, timeTill, options);
  }

  buildHistoryQuery(itemids, table, range, intervalSec, aggFunction, retentionPolicy) {
    const { timeFrom, timeTill } = range;
    const measurement = retentionPolicy ? `"${retentionPolicy}"."${table}"` : `"${table}"`;
    let value = 'value';
    if (retentionPolicy) {
      value = consolidateByTrendColumns[aggFunction] || 'value_avg';
    }
    const aggregation = consolidateByFunc[aggFunction] || aggFunction;
    const where_clause = this.buildWhereClause(itemids);
    const query = `SELECT ${aggregation}("${value}") FROM ${measurement}
      WHERE ${where_clause} AND "time" >= ${timeFrom}s AND "time" <= ${timeTill}s
      GROUP BY time(${intervalSec}s), "itemid" fill(none)`;
    return compactQuery(query);
  }

  buildWhereClause(itemids) {
    const itemidsWhere = itemids.map(itemid => `"itemid" = '${itemid}'`).join(' OR ');
    return `(${itemidsWhere})`;
  }

  invokeInfluxDBQuery(query) {
    return this.influxDS._seriesQuery(query)
    .then(data => data && data.results ? data.results : []);
  }
}

///////////////////////////////////////////////////////////////////////////////

function handleInfluxHistoryResponse(results) {
  if (!results) {
    return [];
  }

  const seriesList = [];
  for (let i = 0; i < results.length; i++) {
    const result = results[i];

    if (result.error) {
      const error = `InfluxDB error: ${result.error}`;
      return Promise.reject(new Error(error));
    }

    if (!result || !result.series) {
      continue;
    }

    const influxSeriesList = results[i].series;

    for (let y = 0; y < influxSeriesList.length; y++) {
      const influxSeries = influxSeriesList[y];
      const datapoints = [];
      if (influxSeries.values) {
        for (i = 0; i < influxSeries.values.length; i++) {
          datapoints[i] = [influxSeries.values[i][1], influxSeries.values[i][0]];
        }
      }
      const timeSeries = {
        name: influxSeries.tags.itemid,
        points: datapoints
      };
      seriesList.push(timeSeries);
    }
  }

  return seriesList;
}
<|endoftext|>


<commit_before>/* Exports a function which returns an object that overrides the default &
 *   plugin grunt configuration object.
 *
 * You can familiarize yourself with Lineman's defaults by checking out:
 *
 *   - https://github.com/linemanjs/lineman/blob/master/config/application.coffee
 *   - https://github.com/linemanjs/lineman/blob/master/config/plugins
 *
 * You can also ask Lineman's about config from the command line:
 *
 *   $ lineman config #=> to print the entire config
 *   $ lineman config concat.js #=> to see the JS config for the concat task.
 */
module.exports = function(lineman) {
  //Override application configuration here. Common examples follow in the comments.
  return {
    // grunt-angular-templates assumes your module is named "app", but
    // you can override it like so:
    //
    // ngtemplates: {
    //   options: {
    //     module: "myModuleName"
    //   }
    // }

    server: {
      pushState: true
      // API Proxying
      //
      // During development, you'll likely want to make XHR (AJAX) requests to an API on the same
      // port as your lineman development server. By enabling the API proxy and setting the port, all
      // requests for paths that don't match a static asset in ./generated will be forwarded to
      // whatever service might be running on the specified port.
      //
      // apiProxy: {
      //   enabled: true,
      //   host: 'localhost',
      //   port: 3000
      // }
    }

    // Sass
    //
    // Lineman supports Sass via grunt-contrib-sass, which requires you first
    // have Ruby installed as well as the `sass` gem. To enable it, comment out the
    // following line:
    //
    // enableSass: true

    // Asset Fingerprints
    //
    // Lineman can fingerprint your static assets by appending a hash to the filename
    // and logging a manifest of logical-to-hashed filenames in dist/assets.json
    // via grunt-asset-fingerprint
    //
    // enableAssetFingerprint: true

  };
};<commit_msg>v0.0.4 Removed necessary tasks - I was not able to remove then in the lineman-angular2 plugin.<commit_after>/* Exports a function which returns an object that overrides the default &
 *   plugin grunt configuration object.
 *
 * You can familiarize yourself with Lineman's defaults by checking out:
 *
 *   - https://github.com/linemanjs/lineman/blob/master/config/application.coffee
 *   - https://github.com/linemanjs/lineman/blob/master/config/plugins
 *
 * You can also ask Lineman's about config from the command line:
 *
 *   $ lineman config #=> to print the entire config
 *   $ lineman config concat.js #=> to see the JS config for the concat task.
 */
module.exports = function(lineman) {
  //Override application configuration here. Common examples follow in the comments.
  return {
    // grunt-angular-templates assumes your module is named "app", but
    // you can override it like so:
    //
    // ngtemplates: {
    //   options: {
    //     module: "myModuleName"
    //   }
    // }

    server: {
      pushState: true
      // API Proxying
      //
      // During development, you'll likely want to make XHR (AJAX) requests to an API on the same
      // port as your lineman development server. By enabling the API proxy and setting the port, all
      // requests for paths that don't match a static asset in ./generated will be forwarded to
      // whatever service might be running on the specified port.
      //
      // apiProxy: {
      //   enabled: true,
      //   host: 'localhost',
      //   port: 3000
      // }
    },

    removeTasks: {
      common: ["coffee","less", "jshint", "handlebars", "jst", "concat_sourcemap", "copy:dev", "webfonts:dev", "pages:dev"],
      dist: ["uglify", "cssmin", "copy:dist", "images:dist", "webfonts:dist", "pages:dist"]
    }

    // Sass
    //
    // Lineman supports Sass via grunt-contrib-sass, which requires you first
    // have Ruby installed as well as the `sass` gem. To enable it, comment out the
    // following line:
    //
    // enableSass: true

    // Asset Fingerprints
    //
    // Lineman can fingerprint your static assets by appending a hash to the filename
    // and logging a manifest of logical-to-hashed filenames in dist/assets.json
    // via grunt-asset-fingerprint
    //
    // enableAssetFingerprint: true

  };
};<|endoftext|>


<commit_before>function Map() {
	var walls;
	var mobileAgents = [];
	var mobileAgentsPositions = [];
	var mobileAgentPerSquare = [];

	function getMobileAgentPerSquareIndex(id) {
		return (mobileAgentsPositions[id].y * 9) + mobileAgentsPositions[id].x;
	}

    this.getWallIds = function () {
        return Object.keys(walls);
    }

    /**
     * Add a mobile agent knowing its id, direction and position.
     * @param id the mobileAgent id
     * @param position the position (object with the properties x and y)
     * @param direction the direction (object with the properties deltaX and deltaY)
     */
    this.addMobileAgent = function (id, position, direction) {
        mobileAgents[id] = new MobileAgent(id, direction);
        mobileAgentsPositions[id] = position;
    };

    /**
     * Method call when on interaction with mobileAgent (click for instance).
     * @param id the mobileAgentId
     */
	this.onMobileAgentInteraction = function(id){
		return mobileAgents[id].onInteraction();
	};

    /**
     * The nextStep function compute all the new positions of mobileAgents, and detect the collisions with walls and mobileAgents.
     */
	this.nextStep = function () {
		var state = new State();

        mobileAgents.forEach(
			function (e, i, a) {
				var wallsInCollisionWith = [];

				var westSiteCollision = false;
				var northSiteCollision = false;
				var eastSiteCollision = false;
				var southSiteCollision = false;

				var mobileAgentsInSquare = mobileAgentPerSquare[getMobileAgentPerSquareIndex(e.id)];
				mobileAgentsInSquare.splice(mobileAgentsInSquare.indexOf(e) - 1,1);

				var x = mobileAgentsPositions[e.id].x + (e.direction.deltaX * e.increment);
				var y = mobileAgentsPositions[e.id].y + (e.direction.deltaY * e.increment);

                mobileAgentsPositions[e.id].x = x;
				mobileAgentsPositions[e.id].y = y;

				if (x < 1) {
					westSiteCollision = true;
					mobileAgentsPositions[e.id].x = 0;
				}

				if (y < 1) {
					northSiteCollision = true;
					mobileAgentsPositions[e.id].y = 0;
				}

				if (x >= 8) {
					eastSiteCollision = true;
					mobileAgentsPositions[e.id].x = 8;
				}

				if (y >= 8) {
					southSiteCollision = true;
					mobileAgentsPositions[e.id].y = 8;
				}

				if (westSiteCollision) {
					state.wallsInCollision.push("W" + mobileAgentsPositions[e.id].y);
					wallsInCollisionWith.push(walls["W" + mobileAgentsPositions[e.id].y]);
				}

				if (northSiteCollision) {
					state.wallsInCollision.push("N" + mobileAgentsPositions[e.id].x);
					wallsInCollisionWith.push(walls["N" + mobileAgentsPositions[e.id].x]);
				}

				if (eastSiteCollision) {
					state.wallsInCollision.push("E" + mobileAgentsPositions[e.id].y);
					wallsInCollisionWith.push(walls["E" + mobileAgentsPositions[e.id].y]);
				}

				if (southSiteCollision) {
					state.wallsInCollision.push("S" + mobileAgentsPositions[e.id].x);
					wallsInCollisionWith.push(walls["S" + mobileAgentsPositions[e.id].x]);
				}

				if (wallsInCollisionWith.length > 0) {
					state.mobileAgentsInWallCollision.push(e.id);
					e.onWallsCollision(wallsInCollisionWith);
				}

				mobileAgentPerSquare[getMobileAgentPerSquareIndex(e.id)].push(e);
			}
		);

		mobileAgentPerSquare.forEach(
			function (e, i, a) {
				if (mobileAgentPerSquare[i].length > 1) {
					mobileAgentPerSquare[i].forEach(
						function (e, j, a) {
							mobileAgentPerSquare[i][j].onMobileAgentsCollision(
								mobileAgentPerSquare[i].slice(mobileAgentPerSquare[i].indexOf(e) - 1, 1));

							state.mobileAgentsInMobileAgentCollision.push(e.id);
						}
					);
				}
			}
		);

        mobileAgents.forEach(
			function (e, i, a) {
                state.positions.push({id:e.id, position:mobileAgentsPositions[e.id], direction:e.direction});
            }
        );

		return state;
	};

	(function() {
		 var i;

		 for(i = 0; i<9*9 ; i++){
		    mobileAgentPerSquare[i] = [];
		 }

		 walls = new Object();

		 for (var i = 0 ; i < 9 ; i++) {
			walls["W" + i] = new Wall(i, 'W');
			walls["N" + i] = new Wall(i + 9, 'N');
			walls["E" + i] = new Wall(i + 18, 'E');
			walls["S" + i] = new Wall(i + 27, 'S');
		 }

	}).call(this);
}
<commit_msg>Fix bug in detection of wall collisions<commit_after>function Map() {
	var walls;
	var mobileAgents = [];
	var mobileAgentsPositions = [];
	var mobileAgentPerSquare = [];

	function getMobileAgentPerSquareIndex(id) {
		return (mobileAgentsPositions[id].y * 9) + mobileAgentsPositions[id].x;
	}

    this.getWallIds = function () {
        return Object.keys(walls);
    }

    /**
     * Add a mobile agent knowing its id, direction and position.
     * @param id the mobileAgent id
     * @param position the position (object with the properties x and y)
     * @param direction the direction (object with the properties deltaX and deltaY)
     */
    this.addMobileAgent = function (id, position, direction) {
        mobileAgents[id] = new MobileAgent(id, direction);
        mobileAgentsPositions[id] = position;
    };

    /**
     * Method call when on interaction with mobileAgent (click for instance).
     * @param id the mobileAgentId
     */
	this.onMobileAgentInteraction = function(id){
		return mobileAgents[id].onInteraction();
	};

    /**
     * The nextStep function compute all the new positions of mobileAgents, and detect the collisions with walls and mobileAgents.
     */
	this.nextStep = function () {
		var state = new State();

        mobileAgents.forEach(
			function (e, i, a) {
				var wallsInCollisionWith = [];

				var westSiteCollision = false;
				var northSiteCollision = false;
				var eastSiteCollision = false;
				var southSiteCollision = false;

				var mobileAgentsInSquare = mobileAgentPerSquare[getMobileAgentPerSquareIndex(e.id)];
				mobileAgentsInSquare.splice(mobileAgentsInSquare.indexOf(e) - 1,1);

				var x = mobileAgentsPositions[e.id].x + (e.direction.deltaX * e.increment);
				var y = mobileAgentsPositions[e.id].y + (e.direction.deltaY * e.increment);

                mobileAgentsPositions[e.id].x = x;
				mobileAgentsPositions[e.id].y = y;

				if (x < 1 && e.direction.deltaX < 0) {
					westSiteCollision = true;
					mobileAgentsPositions[e.id].x = 0;
				}

				if (y < 1 && e.direction.deltaY < 0) {
					northSiteCollision = true;
					mobileAgentsPositions[e.id].y = 0;
				}

				if (x >= 8 && e.direction.deltaX > 0) {
					eastSiteCollision = true;
					mobileAgentsPositions[e.id].x = 8;
				}

				if (y >= 8 && e.direction.deltaY > 0) {
					southSiteCollision = true;
					mobileAgentsPositions[e.id].y = 8;
				}

				if (westSiteCollision) {
					state.wallsInCollision.push("W" + mobileAgentsPositions[e.id].y);
					wallsInCollisionWith.push(walls["W" + mobileAgentsPositions[e.id].y]);
				}

				if (northSiteCollision) {
					state.wallsInCollision.push("N" + mobileAgentsPositions[e.id].x);
					wallsInCollisionWith.push(walls["N" + mobileAgentsPositions[e.id].x]);
				}

				if (eastSiteCollision) {
					state.wallsInCollision.push("E" + mobileAgentsPositions[e.id].y);
					wallsInCollisionWith.push(walls["E" + mobileAgentsPositions[e.id].y]);
				}

				if (southSiteCollision) {
					state.wallsInCollision.push("S" + mobileAgentsPositions[e.id].x);
					wallsInCollisionWith.push(walls["S" + mobileAgentsPositions[e.id].x]);
				}

				if (wallsInCollisionWith.length > 0) {
					state.mobileAgentsInWallCollision.push(e.id);
					e.onWallsCollision(wallsInCollisionWith);
				}

				mobileAgentPerSquare[getMobileAgentPerSquareIndex(e.id)].push(e);
			}
		);

		mobileAgentPerSquare.forEach(
			function (e, i, a) {
				if (mobileAgentPerSquare[i].length > 1) {
					mobileAgentPerSquare[i].forEach(
						function (e, j, a) {
							mobileAgentPerSquare[i][j].onMobileAgentsCollision(
								mobileAgentPerSquare[i].slice(mobileAgentPerSquare[i].indexOf(e) - 1, 1));

							state.mobileAgentsInMobileAgentCollision.push(e.id);
						}
					);
				}
			}
		);

        mobileAgents.forEach(
			function (e, i, a) {
                state.positions.push({id:e.id, position:mobileAgentsPositions[e.id], direction:e.direction});
            }
        );

		return state;
	};

	(function() {
		 var i;

		 for(i = 0; i<9*9 ; i++){
		    mobileAgentPerSquare[i] = [];
		 }

		 walls = new Object();

		 for (var i = 0 ; i < 9 ; i++) {
			walls["W" + i] = new Wall(i, 'W');
			walls["N" + i] = new Wall(i + 9, 'N');
			walls["E" + i] = new Wall(i + 18, 'E');
			walls["S" + i] = new Wall(i + 27, 'S');
		 }

	}).call(this);
}
<|endoftext|>


<commit_before>class SelectItemsService {
    /*@ngInject*/
    constructor($mdDialog, projectsAPI, experimentsAPI, projectFileTreeAPI, mcStateStore) {
        this.$mdDialog = $mdDialog;
        this.projectsAPI = projectsAPI;
        this.experimentsAPI = experimentsAPI;
        this.projectFileTreeAPI = projectFileTreeAPI;
        this.mcStateStore = mcStateStore;
    }

    dialog(locals, controller) {
        return this.$mdDialog.show({
            templateUrl: 'app/modals/select-items-dialog.html',
            controller: controller,
            controllerAs: '$ctrl',
            bindToController: true,
            clickOutsideToClose: true,
            multiple: true,
            locals: locals
        });
    }

    fileTree(uploadFiles = false) {
        let project = this.mcStateStore.getState('project');
        return this.projectFileTreeAPI.getProjectRoot(project.id).then(
            files => {
                project.files = files;
                return this.dialog({
                    showFileTree: true,
                    showFileTable: false,
                    uploadFiles,
                    project
                }, SelectItemsFilesServiceModalController);
            });
    }

    fileTreeForProject(projectId, uploadFiles = false) {
        return this.projectFileTreeAPI.getProjectRoot(projectId).then(
            files => {
                let project = {};
                project.files = files;
                return this.dialog({
                    showFileTree: true,
                    showFileTable: false,
                    uploadFiles,
                    project
                }, SelectItemsFilesServiceModalController);
            });
    }

    fileTable(files = [], uploadFiles = false) {
        return this.dialog({
            showFileTable: true,
            showFileTree: false,
            uploadFiles,
            files
        }, SelectItemsFilesServiceModalController);
    }

    samples(samples = [], singleSelection = false) {
        return this.dialog({samples, singleSelection}, SelectItemsSamplesServiceModalController);
    }

    samplesFromProject(projectId, showAllSamples = false, singleSelection = false) {
        let options = {
            singleSelection,
            showAllSamples
        };
        return this.projectsAPI.getProjectSamples(projectId).then(
            (samples) => this.dialog({samples, options}, SelectItemsSamplesServiceModalController)
        );
    }

    samplesFromExperiment(projectId, experimentId, singleSelection = false) {
        return this.experimentsAPI.getSamplesForExperiment(projectId, experimentId).then(
            (samples) => this.dialog({samples, singleSelection}, SelectItemsSamplesServiceModalController)
        );
    }

    processes(processes = []) {
        return this.dialog({processes}, SelectItemsProcessesServiceModalController);
    }

    processesFromProject(projectId) {
        return this.projectsAPI.getProjectProcesses(projectId).then(
            (processes) => this.dialog({processes}, SelectItemsProcessesServiceModalController)
        );
    }
}

class SelectItemsBase {
    constructor($mdDialog) {
        this.activeTab = 0;
        this.currentTab = '';
        this.tabs = [];
        this.$mdDialog = $mdDialog;
    }

    isActive(tab) {
        return this.activeTab === tab;
    }

    setActive(tabName) {
        this.activeTab = tabName;
    }

    addTab(name, icon) {
        this.tabs.push({name, icon});
        if (this.tabs.length === 1) {
            this.activeTab = this.tabs[0].name;
        }
    }

    cancel() {
        this.$mdDialog.cancel();
    }
}

class SelectItemsState {
    constructor() {
        this.uploadedFiles = [];
    }

    reset() {
        this.uploadedFiles = [];
    }
}

const selectItemsState = new SelectItemsState();

class SelectItemsSamplesServiceModalController extends SelectItemsBase {
    /*@ngInject*/
    constructor($mdDialog) {
        super($mdDialog);
        this.$onInit();
    }

    $onInit() {
        this.addTab('samples', 'fa-cubes');
    }

    ok() {
        let selectedSamples = this.samples.filter(s => {
            for (let i = 0; i < s.versions.length; i++) {
                if (s.versions[i].selected) {
                    return true;
                }
            }
            return false;
        });
        this.$mdDialog.hide({samples: selectedSamples});
    }
}

class SelectItemsProcessesServiceModalController extends SelectItemsBase {
    /*@ngInject*/
    constructor($mdDialog) {
        super($mdDialog);
        this.$onInit();
    }

    $onInit() {
        this.addTab('processes', 'fa-code-fork');
    }

    ok() {
        let selectedProcesses = this.processes.filter(p => p.input || p.output);
        this.$mdDialog.hide({processes: selectedProcesses});
    }
}

class SelectItemsFilesServiceModalController extends SelectItemsBase {
    /*@ngInject*/
    constructor($mdDialog) {
        super($mdDialog);
        this.$onInit();
    }

    $onInit() {
        selectItemsState.reset();
        if (this.showFileTable) {
            this.addTab('file table', 'fa-files-o');
        }

        if (this.showFileTree) {
            this.addTab('file tree', 'fa-files-o');
        }

        if (this.uploadFiles) {
            this.addTab('Upload Files', 'fa-upload');
        }
    }

    uploadComplete(files) {
        selectItemsState.uploadedFiles = files;
    }

    ok() {
        let selectedFiles = [];
        let selectedDirs = [];
        if (this.showFileTree) {
            let {files, dirs} = this.getFilesFromTree();
            selectedFiles = selectedFiles.concat(files);
            selectedDirs = selectedDirs.concat(dirs);
        }

        if (this.showFileTable) {
            selectedFiles = selectedFiles.concat(this.files.filter(f => f.selected));
        }

        if (this.uploadFiles) {
            selectedFiles = selectedFiles.concat(selectItemsState.uploadedFiles);
        }

        this.$mdDialog.hide({files: selectedFiles, dirs: selectedDirs});
    }

    getFilesFromTree() {
        let filesFromTree = [];
        let dirsFromTree = [];
        let projectFiles = this.project.files;
        if (projectFiles && projectFiles.length) {
            let treeModel = new TreeModel(),
                root = treeModel.parse(this.project.files[0]);
            // Walk the tree looking for selected files and adding them to the
            // list of files. Also reset the selected flag so the next time
            // the popup for files is used it doesn't show previously selected
            // items.
            root.walk({strategy: 'pre'}, function(node) {
                if (node.model.data.selected) {
                    node.model.data.selected = false;
                    console.log('node.model.data', node.model.data);
                    if (node.model.data.otype === 'file') {
                        filesFromTree.push(node.model.data);
                    } else if (node.model.data.otype === 'directory') {
                        dirsFromTree.push(node.model.data);
                    }
                }
            });
        }

        return {files: filesFromTree, dirs: dirsFromTree};
    }
}

angular.module('materialscommons').service('selectItems', SelectItemsService);
<commit_msg>Return both selected and selected files and dirs<commit_after>class SelectItemsService {
    /*@ngInject*/
    constructor($mdDialog, projectsAPI, experimentsAPI, projectFileTreeAPI, mcStateStore) {
        this.$mdDialog = $mdDialog;
        this.projectsAPI = projectsAPI;
        this.experimentsAPI = experimentsAPI;
        this.projectFileTreeAPI = projectFileTreeAPI;
        this.mcStateStore = mcStateStore;
    }

    dialog(locals, controller) {
        return this.$mdDialog.show({
            templateUrl: 'app/modals/select-items-dialog.html',
            controller: controller,
            controllerAs: '$ctrl',
            bindToController: true,
            clickOutsideToClose: true,
            multiple: true,
            locals: locals
        });
    }

    fileTree(uploadFiles = false) {
        let project = this.mcStateStore.getState('project');
        return this.projectFileTreeAPI.getProjectRoot(project.id).then(
            files => {
                project.files = files;
                return this.dialog({
                    showFileTree: true,
                    showFileTable: false,
                    uploadFiles,
                    project
                }, SelectItemsFilesServiceModalController);
            });
    }

    fileTreeForProject(projectId, uploadFiles = false) {
        return this.projectFileTreeAPI.getProjectRoot(projectId).then(
            files => {
                let project = {};
                project.files = files;
                return this.dialog({
                    showFileTree: true,
                    showFileTable: false,
                    uploadFiles,
                    project
                }, SelectItemsFilesServiceModalController);
            });
    }

    fileTable(files = [], uploadFiles = false) {
        return this.dialog({
            showFileTable: true,
            showFileTree: false,
            uploadFiles,
            files
        }, SelectItemsFilesServiceModalController);
    }

    samples(samples = [], singleSelection = false) {
        return this.dialog({samples, singleSelection}, SelectItemsSamplesServiceModalController);
    }

    samplesFromProject(projectId, showAllSamples = false, singleSelection = false) {
        let options = {
            singleSelection,
            showAllSamples
        };
        return this.projectsAPI.getProjectSamples(projectId).then(
            (samples) => this.dialog({samples, options}, SelectItemsSamplesServiceModalController)
        );
    }

    samplesFromExperiment(projectId, experimentId, singleSelection = false) {
        return this.experimentsAPI.getSamplesForExperiment(projectId, experimentId).then(
            (samples) => this.dialog({samples, singleSelection}, SelectItemsSamplesServiceModalController)
        );
    }

    processes(processes = []) {
        return this.dialog({processes}, SelectItemsProcessesServiceModalController);
    }

    processesFromProject(projectId) {
        return this.projectsAPI.getProjectProcesses(projectId).then(
            (processes) => this.dialog({processes}, SelectItemsProcessesServiceModalController)
        );
    }
}

class SelectItemsBase {
    constructor($mdDialog) {
        this.activeTab = 0;
        this.currentTab = '';
        this.tabs = [];
        this.$mdDialog = $mdDialog;
    }

    isActive(tab) {
        return this.activeTab === tab;
    }

    setActive(tabName) {
        this.activeTab = tabName;
    }

    addTab(name, icon) {
        this.tabs.push({name, icon});
        if (this.tabs.length === 1) {
            this.activeTab = this.tabs[0].name;
        }
    }

    cancel() {
        this.$mdDialog.cancel();
    }
}

class SelectItemsState {
    constructor() {
        this.uploadedFiles = [];
    }

    reset() {
        this.uploadedFiles = [];
    }
}

const selectItemsState = new SelectItemsState();

class SelectItemsSamplesServiceModalController extends SelectItemsBase {
    /*@ngInject*/
    constructor($mdDialog) {
        super($mdDialog);
        this.$onInit();
    }

    $onInit() {
        this.addTab('samples', 'fa-cubes');
    }

    ok() {
        let selectedSamples = this.samples.filter(s => {
            for (let i = 0; i < s.versions.length; i++) {
                if (s.versions[i].selected) {
                    return true;
                }
            }
            return false;
        });
        this.$mdDialog.hide({samples: selectedSamples});
    }
}

class SelectItemsProcessesServiceModalController extends SelectItemsBase {
    /*@ngInject*/
    constructor($mdDialog) {
        super($mdDialog);
        this.$onInit();
    }

    $onInit() {
        this.addTab('processes', 'fa-code-fork');
    }

    ok() {
        let selectedProcesses = this.processes.filter(p => p.input || p.output);
        this.$mdDialog.hide({processes: selectedProcesses});
    }
}

class SelectItemsFilesServiceModalController extends SelectItemsBase {
    /*@ngInject*/
    constructor($mdDialog) {
        super($mdDialog);
        this.$onInit();
    }

    $onInit() {
        selectItemsState.reset();
        if (this.showFileTable) {
            this.addTab('file table', 'fa-files-o');
        }

        if (this.showFileTree) {
            this.addTab('file tree', 'fa-files-o');
        }

        if (this.uploadFiles) {
            this.addTab('Upload Files', 'fa-upload');
        }
    }

    uploadComplete(files) {
        selectItemsState.uploadedFiles = files;
    }

    ok() {
        let selectedFiles = [];
        let selectedDirs = [];
        if (this.showFileTree) {
            let {files, dirs} = this.getFilesFromTree();
            selectedFiles = selectedFiles.concat(files);
            selectedDirs = selectedDirs.concat(dirs);
        }

        if (this.showFileTable) {
            selectedFiles = selectedFiles.concat(this.files.filter(f => f.selected));
        }

        if (this.uploadFiles) {
            selectedFiles = selectedFiles.concat(selectItemsState.uploadedFiles);
        }

        this.$mdDialog.hide({files: selectedFiles, dirs: selectedDirs});
    }

    getFilesFromTree() {
        let selectedFilesFromTree = [];
        let selectedDirsFromTree = [];
        let unselectedFilesFromTree = [];
        let unselectedDirsFromTree = [];
        let projectFiles = this.project.files;
        if (projectFiles && projectFiles.length) {
            let treeModel = new TreeModel(),
                root = treeModel.parse(this.project.files[0]);
            // Walk the tree looking for selected files and adding them to the
            // list of files. Also reset the selected flag so the next time
            // the popup for files is used it doesn't show previously selected
            // items.
            root.walk({strategy: 'pre'}, function(node) {
                if (node.model.data.selected) {
                    node.model.data.selected = false;
                    if (node.model.data.otype === 'file') {
                        selectedFilesFromTree.push(node.model.data);
                    } else if (node.model.data.otype === 'directory') {
                        selectedDirsFromTree.push(node.model.data);
                    }
                } else {
                    if (node.model.data.otype === 'file') {
                        unselectedFilesFromTree.push(node.model.data);
                    } else if (node.model.data.otype === 'directory') {
                        unselectedDirsFromTree.push(node.model.data);
                    }
                }
            });
        }

        return {
            files: selectedFilesFromTree,
            dirs: selectedDirsFromTree,
            unselected_files: unselectedFilesFromTree,
            unselected_dirs: unselectedDirsFromTree
        };
    }
}

angular.module('materialscommons').service('selectItems', SelectItemsService);
<|endoftext|>


<commit_before>/**
 * @fileOverview area.js traverse throught DOM and assign ARIA labels to all area elements with href.
 *
 * @author Gagandeep Singh <robi_osahan@yahoo.com>
 * @version 1.0.0
 */

(function(window, $, undefined){

    aria._h4 = function(options){

        var ele = $("h4"),
            labeller = {

                init: function(){

                    this.setOptions();

                    if(options.role){

                        this.defineRole();

                    }

                    if(options.label){

                        this.assignLabels();

                    }

                },

                setOptions: function(){

                    options.role = options.role || aria.options.role;
                    options.label = options.label || aria.options.label;

                },

                defineRole: function(){

                    $.each(ele, function( index, value ) {

                        if( typeof $(value).prop("role") === "undefined"){

                            $(value).attr("role", "heading");

                        }

                    });

                },

                assignLabels: function(){

                },

                uiStates: function(){

                }
            };

        labeller.init();

    };

})(this, jQuery);<commit_msg>updating scope of selector<commit_after>/**
 * @fileOverview area.js traverse throught DOM and assign ARIA labels to all area elements with href.
 *
 * @author Gagandeep Singh <robi_osahan@yahoo.com>
 * @version 1.0.0
 */

(function(window, $, undefined){

    aria._h4 = function(options){

        var ele = aria.currentSelector.find("h4"),
            labeller = {

                init: function(){

                    this.setOptions();

                    if(options.role){

                        this.defineRole();

                    }

                    if(options.label){

                        this.assignLabels();

                    }

                },

                setOptions: function(){

                    options.role = options.role || aria.options.role;
                    options.label = options.label || aria.options.label;

                },

                defineRole: function(){

                    $.each(ele, function( index, value ) {

                        if( typeof $(value).prop("role") === "undefined"){

                            $(value).attr("role", "heading");

                        }

                    });

                },

                assignLabels: function(){

                },

                uiStates: function(){

                }
            };

        labeller.init();

    };

})(this, jQuery);<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Google Inc., authors, and contributors <see AUTHORS file>
 * Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
 * Created By: dan@reciprocitylabs.com
 * Maintained By: dan@reciprocitylabs.com
 */

(function($, CMS, GGRC) {
  var RiskAssessmentsExtension = {},
      _risk_assessments_object_types = ["Program"];
  GGRC.extensions.push(RiskAssessmentsExtension);

  RiskAssessmentsExtension.name = "risk_assessments";

  // Register RA models for use with `infer_object_type`
  RiskAssessmentsExtension.object_type_decision_tree = function() {
    return {
      "risk_assessment": CMS.Models.RiskAssessment
    };
  };

  // Configure mapping extensions for ggrc_risk_assessments
  RiskAssessmentsExtension.init_mappings = function init_mappings() {
    var Proxy = GGRC.MapperHelpers.Proxy,
        Direct = GGRC.MapperHelpers.Direct,
        Cross = GGRC.MapperHelpers.Cross,
        Multi = GGRC.MapperHelpers.Multi,
        CustomFilter = GGRC.MapperHelpers.CustomFilter,
        Reify = GGRC.MapperHelpers.Reify,
        Search = GGRC.MapperHelpers.Search;

        var mappings = {
          Program: {
            _canonical: {
              risk_assessments: "RiskAssessment"
            },
            risk_assessments: Direct(
              "RiskAssessment", "program", "risk_assessments"),
          },
        };
        new GGRC.Mappings("ggrc_risk_assessments", mappings);
  };

  // Override GGRC.extra_widget_descriptors and GGRC.extra_default_widgets
  // Initialize widgets for risk assessment page
  RiskAssessmentsExtension.init_widgets = function init_widgets() {
    var descriptor = {},
        page_instance = GGRC.page_instance();

    if (page_instance && ~can.inArray(page_instance.constructor.shortName, _risk_assessments_object_types)) {
      descriptor[page_instance.constructor.shortName] = {
        risk_assessments: {
          widget_id: "risk_assessments",
          widget_name: "Assessments",
          content_controller: GGRC.Controllers.TreeView,
          content_controller_options: {
            mapping: "risk_assessments",
            parent_instance: page_instance,
            model: CMS.Models.RiskAssessment,
            show_view: GGRC.mustache_path + "/risk_assessments/tree.mustache",
            footer_view: GGRC.mustache_path + "/risk_assessments/tree_footer.mustache"
          }
        }
      };
    }
    new GGRC.WidgetList("ggrc_risk_assessments", descriptor);
  }

  // Initialize controller -- probably this should go in a separate
  // initialization area
  // $(function() {
    //$(document.body).ggrc_controllers_risk_assessment_page();
  // });

  // GGRC.register_hook("LHN.Sections", GGRC.mustache_path + "/dashboard/lhn_risk_assessments");
  // GGRC.register_hook(
  //     "ObjectNav.Actions",
  //     GGRC.mustache_path + "/dashboard/object_nav_actions");

  RiskAssessmentsExtension.init_mappings();
  RiskAssessmentsExtension.init_widgets();

})(this.can.$, this.CMS, this.GGRC);
<commit_msg>Change widget name to Risk Assessments.<commit_after>/*
 * Copyright (C) 2013 Google Inc., authors, and contributors <see AUTHORS file>
 * Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
 * Created By: dan@reciprocitylabs.com
 * Maintained By: dan@reciprocitylabs.com
 */

(function($, CMS, GGRC) {
  var RiskAssessmentsExtension = {},
      _risk_assessments_object_types = ["Program"];
  GGRC.extensions.push(RiskAssessmentsExtension);

  RiskAssessmentsExtension.name = "risk_assessments";

  // Register RA models for use with `infer_object_type`
  RiskAssessmentsExtension.object_type_decision_tree = function() {
    return {
      "risk_assessment": CMS.Models.RiskAssessment
    };
  };

  // Configure mapping extensions for ggrc_risk_assessments
  RiskAssessmentsExtension.init_mappings = function init_mappings() {
    var Proxy = GGRC.MapperHelpers.Proxy,
        Direct = GGRC.MapperHelpers.Direct,
        Cross = GGRC.MapperHelpers.Cross,
        Multi = GGRC.MapperHelpers.Multi,
        CustomFilter = GGRC.MapperHelpers.CustomFilter,
        Reify = GGRC.MapperHelpers.Reify,
        Search = GGRC.MapperHelpers.Search;

        var mappings = {
          Program: {
            _canonical: {
              risk_assessments: "RiskAssessment"
            },
            risk_assessments: Direct(
              "RiskAssessment", "program", "risk_assessments"),
          },
        };
        new GGRC.Mappings("ggrc_risk_assessments", mappings);
  };

  // Override GGRC.extra_widget_descriptors and GGRC.extra_default_widgets
  // Initialize widgets for risk assessment page
  RiskAssessmentsExtension.init_widgets = function init_widgets() {
    var descriptor = {},
        page_instance = GGRC.page_instance();

    if (page_instance && ~can.inArray(page_instance.constructor.shortName, _risk_assessments_object_types)) {
      descriptor[page_instance.constructor.shortName] = {
        risk_assessments: {
          widget_id: "risk_assessments",
          widget_name: "Risk Assessments",
          content_controller: GGRC.Controllers.TreeView,
          content_controller_options: {
            mapping: "risk_assessments",
            parent_instance: page_instance,
            model: CMS.Models.RiskAssessment,
            show_view: GGRC.mustache_path + "/risk_assessments/tree.mustache",
            footer_view: GGRC.mustache_path + "/risk_assessments/tree_footer.mustache"
          }
        }
      };
    }
    new GGRC.WidgetList("ggrc_risk_assessments", descriptor);
  }

  // Initialize controller -- probably this should go in a separate
  // initialization area
  // $(function() {
    //$(document.body).ggrc_controllers_risk_assessment_page();
  // });

  // GGRC.register_hook("LHN.Sections", GGRC.mustache_path + "/dashboard/lhn_risk_assessments");
  // GGRC.register_hook(
  //     "ObjectNav.Actions",
  //     GGRC.mustache_path + "/dashboard/object_nav_actions");

  RiskAssessmentsExtension.init_mappings();
  RiskAssessmentsExtension.init_widgets();

})(this.can.$, this.CMS, this.GGRC);
<|endoftext|>


<commit_before>import React, {Component} from 'react'
import AppBar from '@material-ui/core/AppBar'
import grey from '@material-ui/core/colors/grey'
import { withStyles } from '@material-ui/core/styles'
import PropTypes from 'prop-types'
import ServiceObject from './Objects/ServiceObjectContainer'
import HostObject from './Objects/HostObjectContainer'
import PollerObject from './Objects/PollerObjectContainer'
import UserProfile from './User/UserProfileContainer'
import Logo from './Logo/LogoContainer'
import Clock from './Clock/ClockContainer'

const styles = theme => ({
  root: {
    flexGrow: 1,
    zIndex: 1,
    fontFamily: theme.font.openSans,
    overflow: 'hidden'
  },
  container: {
    display: 'grid',
    gridTemplateColumns: 'repeat(12, 1fr)',
    gridGap: `${theme.spacing.unit * 3}px`,
  },
  clockUserContainer: {
    display: 'flex',
    justifyContent: 'flex-end',
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
    color: '#fff',
    backgroundColor: '#E7E7E8',
  },
  objectContainer: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
  },
  avatar: {
    margin: 10,
    color: '#fff',
    backgroundColor: grey[200],
  },
  indicatorContainer: {
    display: 'flex',
    alignItems: 'center',
    flexWrap: 'nowrap',
    justifyContent: 'flex-end'
  },
})

class TopHeader extends Component {
  render () {
    const {classes} = this.props
    return (

        <AppBar position="static" className={classes.appBar}>

              <Logo />

              <PollerObject />
              <HostObject />
              <ServiceObject />

                <Clock />
                <UserProfile />

        </AppBar>

    )
  }
}

TopHeader.propTypes = {
  classes: PropTypes.object.isRequired,
}

export default withStyles(styles)(TopHeader)
<commit_msg>fix(nav): fix nav display<commit_after>import React, {Component} from 'react'
import AppBar from '@material-ui/core/AppBar'
import grey from '@material-ui/core/colors/grey'
import { withStyles } from '@material-ui/core/styles'
import PropTypes from 'prop-types'
import ServiceObject from './Objects/ServiceObjectContainer'
import HostObject from './Objects/HostObjectContainer'
import PollerObject from './Objects/PollerObjectContainer'
import UserProfile from './User/UserProfileContainer'
import Logo from './Logo/LogoContainer'
import Clock from './Clock/ClockContainer'
import Nav from './Nav/NavContainer'

const styles = theme => ({
  root: {
    flexGrow: 1,
    zIndex: 1,
    fontFamily: theme.font.openSans,
    overflow: 'hidden'
  },
  container: {
    display: 'grid',
    gridTemplateColumns: 'repeat(12, 1fr)',
    gridGap: `${theme.spacing.unit * 3}px`,
  },
  clockUserContainer: {
    display: 'flex',
    justifyContent: 'flex-end',
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
    color: '#fff',
    backgroundColor: '#E7E7E8',
  },
  objectContainer: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
  },
  avatar: {
    margin: 10,
    color: '#fff',
    backgroundColor: grey[200],
  },
  indicatorContainer: {
    display: 'flex',
    alignItems: 'center',
    flexWrap: 'nowrap',
    justifyContent: 'flex-end'
  },
})

class TopHeader extends Component {
  render () {
    const {classes} = this.props
    return (

        <AppBar position="static" className={classes.appBar}>

              <Logo />

              <PollerObject />
              <HostObject />
              <ServiceObject />

                <Clock />
                <UserProfile />

        </AppBar>

    )
  }
}

TopHeader.propTypes = {
  classes: PropTypes.object.isRequired,
}

export default withStyles(styles)(TopHeader)
<|endoftext|>


<commit_before>/*
Copyright 2009 University of Toronto

Licensed under the Educational Community License (ECL), Version 2.0.
ou may not use this file except in compliance with this License.

You may obtain a copy of the ECL 2.0 License at
https://source.collectionspace.org/collection-space/LICENSE.txt
*/

/*global jQuery, fluid_1_1*/

var cspace = cspace || {};

(function ($, fluid) {

    var defaultSearchUrlBuilder = function (recordType, query) {
// CSPACE-701
// Up to 0.4, there's a bug in which the recordType for 'object' needs to be
// plural
        if (recordType === "object") {
            recordType = "objects";
        }
// end of fudge for CSPACE-701
        return "../../chain/" + recordType + "/search?query=" + query;
    };

    var colDefsGenerated = function (columnList, recordType) {
        return fluid.transform(columnList, function (object, index) {
            var key = "col:";
            var comp;

            if (object === "number") {
                key = "number";
                comp = {
                    target: recordType + ".html?csid=${*.csid}",
                    linktext: fluid.VALUE
                };
            } else if (object === "csid") {
                key = "csid";
            } else {
                comp = {value: "${*." + object + "}"};
            }
            return {
                key: key,
                valuebinding: "*." + object,
                components: comp,
                sortable: true
            };
        });
    };

    var displaySearchResults = function (that, recordType) {
        var colList = [];
        var results = that.model.results;
        for (var key in results[0]) {
            if (results[0].hasOwnProperty(key)) {
                colList.push(key);
            }
        }
        var pagerArguments = [
            that.options.selectors.resultsContainer,
            {
                dataModel: results,
                columnDefs: colDefsGenerated(colList, recordType),
                bodyRenderer: {
                    type: "fluid.pager.selfRender",
                    options: {
                        renderOptions: {
                            cutpoints: [
                                {id: "header:", selector: that.options.selectors.resultsHeader},
                                {id: "row:", selector: that.options.selectors.resultsRow},
                                {id: "number", selector: that.options.selectors.columns.number},
                                {id: "col:", selector: that.options.selectors.columns.col}
                            ]
                        }
                    }
                },
                pagerBar: {
                    type: "fluid.pager.pagerBar",
                    options: {
                        pageList: {
                            type: "fluid.pager.renderedPageList"
                        }
                    }
                }
            }
        ];
        var resultsPager = fluid.initSubcomponent(that, "resultsPager", pagerArguments);
        that.locate("resultsContainer").show();
        that.locate("resultsCount").text(resultsPager.model.totalRange);
    };

    var submitSearchRequest = function (that) {
        return function () {
            that.locate("errorMessage").hide();
            var recordType = that.locate("recordType").val();
            var query = that.locate("keywords").val();
            jQuery.ajax({
                url: that.options.searchUrlBuilder(recordType, query),
                type: "GET",
                dataType: "json",
                success: function (data, textStatus) {
                    that.model = data;
                    that.events.modelChanged.fire();
                },
                error: function (xhr, textStatus, errorThrown) {
                    that.events.onError.fire("search", textStatus);
                }
            });
        };
    };

    var bindEventHandlers = function (that) {
        that.locate("searchButton").click(submitSearchRequest(that));

        that.events.modelChanged.addListener(function () {
            displaySearchResults(that, that.locate("recordType").val());
        });

        that.events.onError.addListener(function (action, status) {
            that.locate("resultsContainer").hide();
            that.locate("errorMessage").show();
        });
    };

    cspace.search = function (container, options) {
        var that = fluid.initView("cspace.search", container, options);
        that.locate("resultsContainer").hide();
        that.model = {};

        bindEventHandlers(that);

        var keywords = cspace.util.getUrlParameter("keywords");
        var recordType = cspace.util.getUrlParameter("recordtype");
        if (keywords) {
            that.locate("keywords").val(keywords);
            that.locate("recordType").val(recordType);
            submitSearchRequest(that)();
        }
        return that;
    };

    fluid.defaults("cspace.search", {
        selectors: {
            keywords: ".csc-search-keywords",
            recordType: ".csc-search-record-type",
            errorMessage: ".csc-search-error-message",
            searchButton: ".csc-search-submit",
            resultsContainer: ".csc-search-results",
            resultsCount: ".csc-search-results-count",
            resultsHeader: ".csc-header",
            resultsRow: ".csc-row",
            columns: {
                number: ".csc-number",
                col: ".csc-col"
            }
        },

        events: {
            modelChanged: null,
            onError: null
        },

        searchUrlBuilder: defaultSearchUrlBuilder,

        resultsPager: {
            type: "fluid.pager"
        }
    });
})(jQuery, fluid_1_1);
<commit_msg>CSPACE-700: Reuse the same Pager for subsequent search results. Need to update the dataModel, the pager's model and the columnDefs according to the new search results.<commit_after>/*
Copyright 2009 University of Toronto

Licensed under the Educational Community License (ECL), Version 2.0.
ou may not use this file except in compliance with this License.

You may obtain a copy of the ECL 2.0 License at
https://source.collectionspace.org/collection-space/LICENSE.txt
*/

/*global jQuery, fluid_1_1*/

var cspace = cspace || {};

(function ($, fluid) {

    var resultsPager;

    var defaultSearchUrlBuilder = function (recordType, query) {
// CSPACE-701
// Up to 0.4, there's a bug in which the recordType for 'object' needs to be
// plural
        if (recordType === "object") {
            recordType = "objects";
        }
// end of fudge for CSPACE-701
        return "../../chain/" + recordType + "/search?query=" + query;
    };

    var colDefsGenerated = function (columnList, recordType) {
        return fluid.transform(columnList, function (object, index) {
            var key = "col:";
            var comp;

            if (object === "number") {
                key = "number";
                comp = {
                    target: recordType + ".html?csid=${*.csid}",
                    linktext: fluid.VALUE
                };
            } else if (object === "csid") {
                key = "csid";
            } else {
                comp = {value: "${*." + object + "}"};
            }
            return {
                key: key,
                valuebinding: "*." + object,
                components: comp,
                sortable: true
            };
        });
    };

    var displaySearchResults = function (that, recordType) {
        var colList = [];
        var results = that.model.results;
        for (var key in results[0]) {
            if (results[0].hasOwnProperty(key)) {
                colList.push(key);
            }
        }
        var pagerArguments = [
            that.options.selectors.resultsContainer,
            {
                dataModel: results,
                columnDefs: colDefsGenerated(colList, recordType),
                bodyRenderer: {
                    type: "fluid.pager.selfRender",
                    options: {
                        renderOptions: {
                            cutpoints: [
                                {id: "header:", selector: that.options.selectors.resultsHeader},
                                {id: "row:", selector: that.options.selectors.resultsRow},
                                {id: "number", selector: that.options.selectors.columns.number},
                                {id: "col:", selector: that.options.selectors.columns.col}
                            ]
                        }
                    }
                },
                pagerBar: {
                    type: "fluid.pager.pagerBar",
                    options: {
                        pageList: {
                            type: "fluid.pager.renderedPageList"
                        }
                    }
                }
            }
        ];
        if (resultsPager) {
            fluid.model.copyModel(resultsPager.options.dataModel, results);
            resultsPager.options.columnDefs = colDefsGenerated(colList, recordType),
            // you're not supposed to touch the pager's model, but there's a bug in this version, so...
            resultsPager.model.totalRange = results.length;
            resultsPager.events.initiatePageChange.fire({pageIndex: 0, forceUpdate: true});
        } else {
            resultsPager = fluid.initSubcomponent(that, "resultsPager", pagerArguments);
        }
        that.locate("resultsContainer").show();
        that.locate("resultsCount").text(resultsPager.model.totalRange);
    };

    var submitSearchRequest = function (that) {
        return function () {
            that.locate("errorMessage").hide();
            var recordType = that.locate("recordType").val();
            var query = that.locate("keywords").val();
            jQuery.ajax({
                url: that.options.searchUrlBuilder(recordType, query),
                type: "GET",
                dataType: "json",
                success: function (data, textStatus) {
                    that.model = data;
                    that.events.modelChanged.fire();
                },
                error: function (xhr, textStatus, errorThrown) {
                    that.events.onError.fire("search", textStatus);
                }
            });
        };
    };

    var bindEventHandlers = function (that) {
        that.locate("searchButton").click(submitSearchRequest(that));

        that.events.modelChanged.addListener(function () {
            displaySearchResults(that, that.locate("recordType").val());
        });

        that.events.onError.addListener(function (action, status) {
            that.locate("resultsContainer").hide();
            that.locate("errorMessage").show();
        });
    };

    cspace.search = function (container, options) {
        var that = fluid.initView("cspace.search", container, options);
        that.locate("resultsContainer").hide();
        that.model = {};

        bindEventHandlers(that);

        var keywords = cspace.util.getUrlParameter("keywords");
        var recordType = cspace.util.getUrlParameter("recordtype");
        if (keywords) {
            that.locate("keywords").val(keywords);
            that.locate("recordType").val(recordType);
            submitSearchRequest(that)();
        }
        return that;
    };

    fluid.defaults("cspace.search", {
        selectors: {
            keywords: ".csc-search-keywords",
            recordType: ".csc-search-record-type",
            errorMessage: ".csc-search-error-message",
            searchButton: ".csc-search-submit",
            resultsContainer: ".csc-search-results",
            resultsCount: ".csc-search-results-count",
            resultsHeader: ".csc-header",
            resultsRow: ".csc-row",
            columns: {
                number: ".csc-number",
                col: ".csc-col"
            }
        },

        events: {
            modelChanged: null,
            onError: null
        },

        searchUrlBuilder: defaultSearchUrlBuilder,

        resultsPager: {
            type: "fluid.pager"
        }
    });
})(jQuery, fluid_1_1);
<|endoftext|>


<commit_before>gf.PhysicsSystem = function(options) {
    options = options || {};

    this.space = new cp.Space();
    this.space.gravity = gf.utils.ensureVector(options.gravity !== undefined ? options.gravity : 9.87);

    //Time a body must remain idle to fall asleep
    //see: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_space.html#a928d74741904aae266a9efff5b5f68f7
    this.space.sleepTimeThreshold = options.sleepTimeThreshold || 0.2;

    //Amount of encouraged penetration between colliding shapes.
    //see: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_space.html#af1bec644a24e12bfc642a942a88520f7
    this.space.collisionSlop = options.collisionSlop || 0.1;

    //These two collision scenarios are separate because we don't
    //want tiles to collide with tiles all the time

    //sprite - sprite collisions
    this.space.addCollisionHandler(
        gf.PhysicsSystem.COLLISION_TYPE.SPRITE,
        gf.PhysicsSystem.COLLISION_TYPE.SPRITE,
        this.onCollisionBegin.bind(this), //begin
        null, //preSolve
        null, //postSolve
        null //separate
    );

    //sprite - tile collisions
    this.space.addCollisionHandler(
        gf.PhysicsSystem.COLLISION_TYPE.SPRITE,
        gf.PhysicsSystem.COLLISION_TYPE.TILE,
        this.onCollisionBegin.bind(this), //begin
        null, //preSolve
        null, //postSolve
        null //separate
    );
};

gf.inherits(gf.PhysicsSystem, Object, {
    _createBody: function(spr) {
        var body = new cp.Body(
            spr.mass || 1,
            spr.inertia || cp.momentForBox(spr.mass || 1, spr.width, spr.height) || Infinity
        );

        if(spr.mass === Infinity) {
            //inifinite mass means it is static, so make it static
            //and do not add it to the world (no need to simulate it)
            body.nodeIdleTime = Infinity;
        } else {
            this.space.addBody(body);
        }

        return body;
    },
    _createShape: function(spr, body) {
        var shape,
            hit = spr.hitArea;

        //specified shape
        if(hit) {
            if(hit instanceof gf.Rectangle) {
                //convert the top-left anchored rectangle to left,right,bottom,top values
                //for chipmunk space that will corospond to our own
                var l = hit.x,
                    r = hit.x + hit.width,
                    b = hit.y - spr.height,
                    t = b + hit.height,
                    a = spr.anchor ? spr.anchor.y : 0,
                    bias = hit.height - (hit.height * a);

                b += bias;
                t += bias;

                if(spr.type === 'zone' || spr.type === 'player') {
                    window.console.log(spr.anchor, l, r, t, b, spr);
                }

                shape = new cp.BoxShape2(body, new cp.BB(l, b, r, t));
            }
            else if(hit instanceof gf.Circle) {
                //the offset needs to move the circle to the sprite center based on the sprite's anchor (bottom-left)
                var offset = new gf.Vector(
                    spr.width / 4,
                    -spr.height / 4
                );

                shape = new cp.CircleShape(body, hit.radius, offset);
            }
            else if(hit instanceof gf.Polygon) {
                //cp shapes anchors are 0.5,0.5, but a polygon uses 0,0 as the topleft
                //of the bounding rect so we have to convert
                var points = [],
                    ps = hit.points;//.slice().reverse();

                for(var i = 0; i < ps.length; ++i) {
                    var p = ps[i];

                    points.push(p.x);
                    points.push(p.y - spr.height);
                }

                shape = new cp.PolyShape(body, cp.convexHull(points, null, 0), cp.vzero);
            }
        }

        //default box shape
        if(!shape) {
            shape = new cp.BoxShape2(body, new cp.BB(0, -spr.height, spr.width, 0));
        }

        this.space.addShape(shape);

        shape.width = spr.width;
        shape.height = spr.height;
        shape.sprite = spr;
        shape.setElasticity(0);
        shape.setSensor(spr.sensor);
        shape.setCollisionType(this.getCollisionType(spr));
        shape.setFriction(spr.friction !== undefined ? spr.friction : 0.1);

        return shape;
    },
    invalidCollisions: function() {
        this.space.reindexStatic();
    },
    getCollisionType: function(spr) {
        if(spr instanceof gf.Tile) {
            return gf.PhysicsSystem.COLLISION_TYPE.TILE;
        } else {
            return gf.PhysicsSystem.COLLISION_TYPE.SPRITE;
        }
    },
    add: function(spr) {
        if(!spr._phys)
            spr._phys = {};

        //already in system
        if(spr._phys.body)
            return;

        var body = this._createBody(spr),
            shape = this._createShape(spr, body);

        spr._phys.body = body;
        spr._phys.shape = shape;

        //add control body and constraints
        if(body.m !== Infinity) {
            var cbody = new cp.Body(Infinity, Infinity), //control body
                cpivot = this.space.addConstraint(new cp.PivotJoint(cbody, body, cp.vzero, cp.vzero)),
                cgear = this.space.addConstraint(new cp.GearJoint(cbody, body, 0, 1));

            cpivot.maxBias = 0; //disable join correction
            cpivot.maxForce = 10000; //emulate linear friction

            cgear.errorBias = 0; //attempt to fully correct the joint each step
            cgear.maxBias = 1.2; //but limit the angular correction
            cgear.maxForce = 50000; //emulate angular friction

            if(!spr._phys.control)
                spr._phys.control = {};

            spr._phys.control.body = cbody;
            spr._phys.control.pivot = cpivot;
            spr._phys.control.gear = cgear;
        }
    },
    remove: function(spr) {
        if(!spr || !spr._phys || !spr._phys.body || !spr._phys.shape)
            return;

        if(spr._phys.body.space)
            this.space.removeBody(spr._phys.body);

        if(spr._phys.shape.space)
            this.space.removeShape(spr._phys.shape);

        spr._phys.shape.sprite = null;

        //remove references
        spr._phys.body = null;
        spr._phys.shape = null;
    },
    setMass: function(spr, mass) {
        if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setMass(mass);
    },
    setVelocity: function(spr, vel) {
        //update control body velocity (and pivot contraint makes regular follow)
        if(spr && spr._phys && spr._phys.control && spr._phys.control.body)
            spr._phys.control.body.setVel(vel);

        //if no control body then update real body
        else if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setVel(vel);
    },
    setPosition: function(spr, pos) {
        //update body position
        if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setPos(pos);

        //update control body position
        if(spr && spr._phys && spr._phys.control && spr._phys.control.body)
            spr._phys.control.body.setPos(pos);
    },
    setRotation: function(spr, rads) {
        //update control body rotation (and gear contraint makes regular follow)
        if(spr && spr._phys && spr._phys.control && spr._phys.control.body)
            spr._phys.control.body.setAngle(rads);

        //if no control body then update real body
        else if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setAngle(rads);

    },
    update: function(dt) {
        //execute the physics step
        this.space.step(dt);

        //go through each changed shape
        this.space.activeShapes.each(function(shape) {
            //since the anchor for a cp shape is 0.5 0.5, we have to modify the pos a bit
            //to make it match the sprite's anchor point
            var spr = shape.sprite;
            spr.position.x = shape.body.p.x;// + ((spr.anchor.x * shape.width) - (shape.width / 2));
            spr.position.y = shape.body.p.y;// + ((spr.anchor.y * shape.height) - (shape.height / 2));
            spr.rotation = shape.body.a;

            if(spr._showHit) {
                spr.showPhysics();
            }
        });
    },
    onCollisionBegin: function(arbiter) {//, space) {
        var shapes = arbiter.getShapes(),
            spr1 = shapes[0].sprite,
            spr2 = shapes[1].sprite;

        spr1.onCollision(spr2);
        spr2.onCollision(spr1);

        //maintain the colliding state
        return true;
    }
});

gf.PhysicsSystem.COLLISION_TYPE = {
    SPRITE: 0,
    TILE: 1
};<commit_msg>remove debug<commit_after>gf.PhysicsSystem = function(options) {
    options = options || {};

    this.space = new cp.Space();
    this.space.gravity = gf.utils.ensureVector(options.gravity !== undefined ? options.gravity : 9.87);

    //Time a body must remain idle to fall asleep
    //see: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_space.html#a928d74741904aae266a9efff5b5f68f7
    this.space.sleepTimeThreshold = options.sleepTimeThreshold || 0.2;

    //Amount of encouraged penetration between colliding shapes.
    //see: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_space.html#af1bec644a24e12bfc642a942a88520f7
    this.space.collisionSlop = options.collisionSlop || 0.1;

    //These two collision scenarios are separate because we don't
    //want tiles to collide with tiles all the time

    //sprite - sprite collisions
    this.space.addCollisionHandler(
        gf.PhysicsSystem.COLLISION_TYPE.SPRITE,
        gf.PhysicsSystem.COLLISION_TYPE.SPRITE,
        this.onCollisionBegin.bind(this), //begin
        null, //preSolve
        null, //postSolve
        null //separate
    );

    //sprite - tile collisions
    this.space.addCollisionHandler(
        gf.PhysicsSystem.COLLISION_TYPE.SPRITE,
        gf.PhysicsSystem.COLLISION_TYPE.TILE,
        this.onCollisionBegin.bind(this), //begin
        null, //preSolve
        null, //postSolve
        null //separate
    );
};

gf.inherits(gf.PhysicsSystem, Object, {
    _createBody: function(spr) {
        var body = new cp.Body(
            spr.mass || 1,
            spr.inertia || cp.momentForBox(spr.mass || 1, spr.width, spr.height) || Infinity
        );

        if(spr.mass === Infinity) {
            //inifinite mass means it is static, so make it static
            //and do not add it to the world (no need to simulate it)
            body.nodeIdleTime = Infinity;
        } else {
            this.space.addBody(body);
        }

        return body;
    },
    _createShape: function(spr, body) {
        var shape,
            hit = spr.hitArea;

        //specified shape
        if(hit) {
            if(hit instanceof gf.Rectangle) {
                //convert the top-left anchored rectangle to left,right,bottom,top values
                //for chipmunk space that will corospond to our own
                var l = hit.x,
                    r = hit.x + hit.width,
                    b = hit.y - spr.height,
                    t = b + hit.height,
                    a = spr.anchor ? spr.anchor.y : 0,
                    bias = hit.height - (hit.height * a);

                b += bias;
                t += bias;

                shape = new cp.BoxShape2(body, new cp.BB(l, b, r, t));
            }
            else if(hit instanceof gf.Circle) {
                //the offset needs to move the circle to the sprite center based on the sprite's anchor (bottom-left)
                var offset = new gf.Vector(
                    spr.width / 4,
                    -spr.height / 4
                );

                shape = new cp.CircleShape(body, hit.radius, offset);
            }
            else if(hit instanceof gf.Polygon) {
                //cp shapes anchors are 0.5,0.5, but a polygon uses 0,0 as the topleft
                //of the bounding rect so we have to convert
                var points = [],
                    ps = hit.points;//.slice().reverse();

                for(var i = 0; i < ps.length; ++i) {
                    var p = ps[i];

                    points.push(p.x);
                    points.push(p.y - spr.height);
                }

                shape = new cp.PolyShape(body, cp.convexHull(points, null, 0), cp.vzero);
            }
        }

        //default box shape
        if(!shape) {
            shape = new cp.BoxShape2(body, new cp.BB(0, -spr.height, spr.width, 0));
        }

        this.space.addShape(shape);

        shape.width = spr.width;
        shape.height = spr.height;
        shape.sprite = spr;
        shape.setElasticity(0);
        shape.setSensor(spr.sensor);
        shape.setCollisionType(this.getCollisionType(spr));
        shape.setFriction(spr.friction !== undefined ? spr.friction : 0.1);

        return shape;
    },
    invalidCollisions: function() {
        this.space.reindexStatic();
    },
    getCollisionType: function(spr) {
        if(spr instanceof gf.Tile) {
            return gf.PhysicsSystem.COLLISION_TYPE.TILE;
        } else {
            return gf.PhysicsSystem.COLLISION_TYPE.SPRITE;
        }
    },
    add: function(spr) {
        if(!spr._phys)
            spr._phys = {};

        //already in system
        if(spr._phys.body)
            return;

        var body = this._createBody(spr),
            shape = this._createShape(spr, body);

        spr._phys.body = body;
        spr._phys.shape = shape;

        //add control body and constraints
        if(body.m !== Infinity) {
            var cbody = new cp.Body(Infinity, Infinity), //control body
                cpivot = this.space.addConstraint(new cp.PivotJoint(cbody, body, cp.vzero, cp.vzero)),
                cgear = this.space.addConstraint(new cp.GearJoint(cbody, body, 0, 1));

            cpivot.maxBias = 0; //disable join correction
            cpivot.maxForce = 10000; //emulate linear friction

            cgear.errorBias = 0; //attempt to fully correct the joint each step
            cgear.maxBias = 1.2; //but limit the angular correction
            cgear.maxForce = 50000; //emulate angular friction

            if(!spr._phys.control)
                spr._phys.control = {};

            spr._phys.control.body = cbody;
            spr._phys.control.pivot = cpivot;
            spr._phys.control.gear = cgear;
        }
    },
    remove: function(spr) {
        if(!spr || !spr._phys || !spr._phys.body || !spr._phys.shape)
            return;

        if(spr._phys.body.space)
            this.space.removeBody(spr._phys.body);

        if(spr._phys.shape.space)
            this.space.removeShape(spr._phys.shape);

        spr._phys.shape.sprite = null;

        //remove references
        spr._phys.body = null;
        spr._phys.shape = null;
    },
    setMass: function(spr, mass) {
        if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setMass(mass);
    },
    setVelocity: function(spr, vel) {
        //update control body velocity (and pivot contraint makes regular follow)
        if(spr && spr._phys && spr._phys.control && spr._phys.control.body)
            spr._phys.control.body.setVel(vel);

        //if no control body then update real body
        else if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setVel(vel);
    },
    setPosition: function(spr, pos) {
        //update body position
        if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setPos(pos);

        //update control body position
        if(spr && spr._phys && spr._phys.control && spr._phys.control.body)
            spr._phys.control.body.setPos(pos);
    },
    setRotation: function(spr, rads) {
        //update control body rotation (and gear contraint makes regular follow)
        if(spr && spr._phys && spr._phys.control && spr._phys.control.body)
            spr._phys.control.body.setAngle(rads);

        //if no control body then update real body
        else if(spr && spr._phys && spr._phys.body)
            spr._phys.body.setAngle(rads);

    },
    update: function(dt) {
        //execute the physics step
        this.space.step(dt);

        //go through each changed shape
        this.space.activeShapes.each(function(shape) {
            //since the anchor for a cp shape is 0.5 0.5, we have to modify the pos a bit
            //to make it match the sprite's anchor point
            var spr = shape.sprite;
            spr.position.x = shape.body.p.x;// + ((spr.anchor.x * shape.width) - (shape.width / 2));
            spr.position.y = shape.body.p.y;// + ((spr.anchor.y * shape.height) - (shape.height / 2));
            spr.rotation = shape.body.a;

            if(spr._showHit) {
                spr.showPhysics();
            }
        });
    },
    onCollisionBegin: function(arbiter) {//, space) {
        var shapes = arbiter.getShapes(),
            spr1 = shapes[0].sprite,
            spr2 = shapes[1].sprite;

        spr1.onCollision(spr2);
        spr2.onCollision(spr1);

        //maintain the colliding state
        return true;
    }
});

gf.PhysicsSystem.COLLISION_TYPE = {
    SPRITE: 0,
    TILE: 1
};<|endoftext|>


<commit_before>
var express = require('express'),
  bodyParser = require('body-parser'),
  multipart = require('connect-multiparty'),
  cookieParser = require('cookie-parser'),
  session = require('express-session'),
  favicon = require('serve-favicon')

var request = require('request')
var qs = require('qs')

var config = require('./config')
var flows = {
  1: require('./lib/oauth1'),
  2: require('./lib/oauth2'),
  getpocket: require('./lib/getpocket')
}

function Grant (_config) {
  var app = express()
    .use(favicon(__dirname+'/favicon.ico'))
    // body parser
    .use(bodyParser.json())
    .use(bodyParser.urlencoded({extended: true}))
    .use(multipart())
    // session
    .use(cookieParser())
    .use(session({
      name: 'grant', secret: 'very secret',
      saveUninitialized: true, resave: true
    }))
  app.config = config.init(_config)

  function p (provider, override) {
    var provider = app.config.app[provider]
    if (override && provider.overrides) {
      var override = provider.overrides[override]
      if (override) return override
    }
    return provider
  }
  function d (provider, params) {
    var options = {}
    for (var key in params) {
      if (!params[key]) continue
      options[key] = params[key]
    }
    if (Object.keys(options).length) {
      provider = config.override(provider, options)
      config.transform(provider, options)
    }
    return provider
  }

  app.get('/connect/:provider/:override?', function (req, res, next) {
    if (req.params.override == 'callback') return next()

    var provider = p(req.params.provider, req.params.override)
    req.session.provider = provider

    if (req.query.test) return res.end(JSON.stringify(provider))
    connect(req, res)
  })

  app.post('/connect/:provider/:override?', function (req, res) {
    var provider = p(req.params.provider, req.params.override)
    provider = d(provider, req.body)
    req.session.provider = provider

    if (req.body.test) return res.end(JSON.stringify(provider))
    connect(req, res)
  })

  function connect (req, res) {
    var provider = req.session.provider
    var flow = flows[provider.oauth]

    if (provider.oauth == 1) {
      flow.step1(provider, function (err, data) {
        if (err) return res.redirect(provider.callback + '?' + err)

        req.session.payload = data

        var url = flow.step2(provider, data)
        res.redirect(url)
      })
    }

    else if (provider.oauth == 2) {
      var url = flow.step1(provider)
      res.redirect(url)
    }

    else if (provider.custom) {
      flow = flows[provider.name]
      flow.step1(provider, function (err, data) {
        if (err) return res.redirect(provider.callback + '?' + err)

        req.session.payload = data

        var url = flow.step2(provider, data)
        res.redirect(url)
      })
    }
  }

  app.get('/connect/:provider/callback', function (req, res) {
    var provider = req.session.provider
    var flow = flows[provider.oauth]

    if (provider.oauth == 1) {
      var data = req.session.payload
      delete req.session.payload

      flow.step3(provider, data, req.query, function (err, url) {
        if (err) return res.redirect(provider.callback + '?' + err)
        res.redirect(url)
      })
    }

    else if (provider.oauth == 2) {
      flow.step2(provider, req.query, function (err, data) {
        if (err) return res.redirect(provider.callback + '?' + err)
        var url = flow.step3(provider, data)
        res.redirect(url)
      })
    }

    else if (provider.custom) {
      flow = flows[provider.name]

      var data = req.session.payload
      delete req.session.payload

      flow.step3(provider, data, function (err, url) {
        if (err) return res.redirect(provider.callback + '?' + err)
        res.redirect(url)
      })
    }
  })

  return app
}

exports = module.exports = Grant
<commit_msg>Improve route config logic<commit_after>
var express = require('express'),
  bodyParser = require('body-parser'),
  multipart = require('connect-multiparty'),
  cookieParser = require('cookie-parser'),
  session = require('express-session'),
  favicon = require('serve-favicon')

var request = require('request')
var qs = require('qs')

var config = require('./config')
var flows = {
  1: require('./lib/oauth1'),
  2: require('./lib/oauth2'),
  getpocket: require('./lib/getpocket')
}

function Grant (_config) {
  var app = express()
    .use(favicon(__dirname+'/favicon.ico'))
    // body parser
    .use(bodyParser.json())
    .use(bodyParser.urlencoded({extended: true}))
    .use(multipart())
    // session
    .use(cookieParser())
    .use(session({
      name: 'grant', secret: 'very secret',
      saveUninitialized: true, resave: true
    }))

  app.config = config.init(_config)

  function p (provider, override) {
    if (override && provider.overrides) {
      var override = provider.overrides[override]
      if (override) return override
    }
    return provider
  }
  function d (provider, params) {
    var options = {}
    for (var key in params) {
      if (!params[key]) continue
      options[key] = params[key]
    }
    if (Object.keys(options).length) {
      var dynamic = config.override(provider, options)
      config.transform(dynamic, options)
      return dynamic
    }
    return provider
  }

  app.get('/connect/:provider/:override?', function (req, res, next) {
    if (req.params.override == 'callback') return next()

    var provider = app.config.app[req.params.provider]
    if (req.params.override) {
      provider = p(provider, req.params.override)
    }

    req.session.provider = provider

    if (req.query.test) return res.end(JSON.stringify(provider))
    connect(req, res)
  })

  app.post('/connect/:provider/:override?', function (req, res) {
    var provider = app.config.app[req.params.provider]
    if (req.params.override) {
      provider = p(provider, req.params.override)
    }
    provider = d(provider, req.body)

    req.session.provider = provider

    if (req.body.test) return res.end(JSON.stringify(provider))
    connect(req, res)
  })

  function connect (req, res) {
    var provider = req.session.provider
    var flow = flows[provider.oauth]

    if (provider.oauth == 1) {
      flow.step1(provider, function (err, data) {
        if (err) return res.redirect(provider.callback + '?' + err)

        req.session.payload = data

        var url = flow.step2(provider, data)
        res.redirect(url)
      })
    }

    else if (provider.oauth == 2) {
      var url = flow.step1(provider)
      res.redirect(url)
    }

    else if (provider.custom) {
      flow = flows[provider.name]
      flow.step1(provider, function (err, data) {
        if (err) return res.redirect(provider.callback + '?' + err)

        req.session.payload = data

        var url = flow.step2(provider, data)
        res.redirect(url)
      })
    }
  }

  app.get('/connect/:provider/callback', function (req, res) {
    var provider = req.session.provider
    var flow = flows[provider.oauth]

    if (provider.oauth == 1) {
      var data = req.session.payload
      delete req.session.payload

      flow.step3(provider, data, req.query, function (err, url) {
        if (err) return res.redirect(provider.callback + '?' + err)
        res.redirect(url)
      })
    }

    else if (provider.oauth == 2) {
      flow.step2(provider, req.query, function (err, data) {
        if (err) return res.redirect(provider.callback + '?' + err)
        var url = flow.step3(provider, data)
        res.redirect(url)
      })
    }

    else if (provider.custom) {
      flow = flows[provider.name]

      var data = req.session.payload
      delete req.session.payload

      flow.step3(provider, data, function (err, url) {
        if (err) return res.redirect(provider.callback + '?' + err)
        res.redirect(url)
      })
    }
  })

  return app
}

exports = module.exports = Grant
<|endoftext|>