<commit_before>/* global process */
var Q          = require('q');
var fs         = require('q-io/fs');

var path       = require('path');
var bodyParser = require('body-parser');
var express    = require('express');
var tinylr     = require('tiny-lr');
var app        = express();

var util       = require('./lib/util.js');
var apiFactory = require('./lib/api.js').factory;
var render     = require('./lib/render.js');
var deps       = require('./lib/deps.js');

// Start a tiny-lr server as well.
tinylr().listen(35729, function() {
  console.log('... Listening on 35729 ...');
});

if (process.argv.length < 5) {
  console.log('Usage:\n     node diversity-server.js <webshopid> <themeid|settings.json> <auth>');
  process.exit();
}

var webshopUid = process.argv[2];
var themeUid = process.argv[3];
var auth = process.argv[4];

var api = apiFactory(webshopUid, 'sv', auth);

//ZGF2aWRAdGV4dGFsay5zZTsxNDEyMzIyNTIyO2EwOTJkOTJiNDlkNGYzN2I0ZmMxMjI2ZGI2NmU5MTg3

app.use(bodyParser.json());
app.use(express.static('.'));

// We need tws-compontselector and jsquery.jsonrpcclient
deps.updateDeps('tws-admin-schema-form').fail(function(err) {
  console.log(err);
});
deps.updateDeps({
  name: 'jquery.jsonrpcclient.js',
  url: 'https://github.com/Textalk/jquery.jsonrpcclient.js.git'
});

app.get('/reset', function(req, res) {
  // Reset skip list
  deps.reset();
  res.send('OK');
});

app.get('/', function(req, res) {

  var tid = parseInt(themeUid, 10);
  var settingsPromise;
  if (isNaN(tid)) {
    //Its not a number but a settings file!
    settingsPromise = fs.read(themeUid).then(deps.parseJSON).then(function(settings) {
      return {params: {settings:settings}};
    });
  } else {
    settingsPromise = api('Theme.get', [tid, true]);
  }

  // We update dependencies and load theme each time so we always pick up changes.
  // This is for development people!
  settingsPromise.then(function(theme) {
    var settings  = (theme.params && theme.params.settings) || {};
    var name      = (theme.params && theme.params.component) || 'tws-theme';

    // We want to load the supplied theme + any components in it's settins
    var promises = [];

    promises.push(deps.updateDeps(name));

    var settingsComponents = {};
    util.findComponentsInSettings(settings, function(c) {
      settingsComponents[c.component] = true;
    });

    Object.keys(settingsComponents).forEach(function(n) {
      promises.push(deps.updateDeps(n));
    });

    return Q.all(promises).then(function(result) {
      var defs = result.reduce(function(soFar, obj) {
        Object.keys(obj).forEach(function(k) {
          if (obj[k] !== undefined) {
            soFar[k] = obj[k];
          }
        });
        return soFar;
      }, {});

      var renderList = [];
      var templates = [];

      util.findComponentsInSettings(settings, function(obj) {
        // findComponentsInSettings goes depth first and applies children before parents
        var def = defs[obj.component];
        if (def.template) {
          // FIXME: alternative templates
          templates.push(fs.read(path.join(
            process.cwd(),
            deps.DEPS_FOLDER,
            def.name,
            def.template
          )));
          renderList.push(obj);
        }
      });
      //console.log('And the renderlist is: ', renderList.map(function(c) {
      //  return c.component;
      //}));

      // Load all templates
      return Q.all(templates).then(function(templateData) {

        // Render mustache templates for each in the list.
        renderList.forEach(function(obj, i) {

          var c = render.createContext();
          c.settings = obj.settings;
          c.settingsJSON = JSON.stringify(obj.settings).replace(/<\/script>/g,'<\\/script>')
          obj.componentHTML = render.renderMustache(templateData[i], c);
        });

        var context = render.createContext();
        var names = Object.keys(settingsComponents);
        names.unshift(name);

        var prefix = render.prefixFactory(deps.DEPS_FOLDER);

        util.traverseDeps(names, defs, function(comp) {
          if (typeof comp.style === 'string') {
            context.styles.push(prefix(comp.name, comp.style));
          } else if (typeof comp.style !== 'undefined') {
            context.styles = comp.style.map(function(u) {
              return prefix(comp.name, u);
            }).concat(context.styles);
          }

          if (typeof comp.script === 'string') {
            context.scripts.unshift(prefix(comp.name, comp.script));
          } else if (typeof comp.script !== 'undefined') {
            context.scripts = comp.script.map(function(u) {
              return prefix(comp.name, u);
            }).concat(context.scripts);
          }

          if (comp.angular) {
            context.modules[comp.angular] = true;
          }
        });

        context.settings = settings;

        // Since settingsJSON is going up to the server we need to clean out redundant code.
        util.findComponentsInSettings(settings, function(obj) {
          delete obj.settings;
        }, true);

        context.settingsJSON = JSON.stringify(settings).replace(/<\/script>/g,'<\\/script>');

        context.angularBootstrap = 'angular.module("tws",["' +
                                    Object.keys(context.modules).join('","') +
                                   '"])\n' + 'angular.bootstrap(document,["tws"])';

        // Lets render main mustache template;
        return fs.read(path.join(
          process.cwd(),
          deps.DEPS_FOLDER,
          name,
          defs[name].template
        )).then(function(template) {
          res.send(render.renderMustache(template, context));
        });

      });
    });
  }).fail(function(err) {
    if (!Array.isArray(err)) {
      err = [err];
    }
    console.log(err.join(err.join('\n')));
    err.map(function(e) { return e.stack || e; });
    res.status(500).send('An error occured: ' + err.join('
'));

  });

});

var server = app.listen(3000, function() {
  console.log('Listening on port %d', server.address().port);
});
<commit_msg>Handle sub paths, i.e. reload now works<commit_after>/* global process */
var Q          = require('q');
var fs         = require('q-io/fs');

var path       = require('path');
var bodyParser = require('body-parser');
var express    = require('express');
var tinylr     = require('tiny-lr');
var app        = express();

var util       = require('./lib/util.js');
var apiFactory = require('./lib/api.js').factory;
var render     = require('./lib/render.js');
var deps       = require('./lib/deps.js');

// Start a tiny-lr server as well.
tinylr().listen(35729, function() {
  console.log('... Listening on 35729 ...');
});

if (process.argv.length < 5) {
  console.log('Usage:\n     node diversity-server.js <webshopid> <themeid|settings.json> <auth>');
  process.exit();
}

var webshopUid = process.argv[2];
var themeUid = process.argv[3];
var auth = process.argv[4];

var api = apiFactory(webshopUid, 'sv', auth);

//ZGF2aWRAdGV4dGFsay5zZTsxNDEyMzIyNTIyO2EwOTJkOTJiNDlkNGYzN2I0ZmMxMjI2ZGI2NmU5MTg3

app.use(bodyParser.json());
app.use(express.static('.'));

// We need tws-compontselector and jsquery.jsonrpcclient
deps.updateDeps('tws-admin-schema-form').fail(function(err) {
  console.log(err);
});
deps.updateDeps({
  name: 'jquery.jsonrpcclient.js',
  url: 'https://github.com/Textalk/jquery.jsonrpcclient.js.git'
});

app.get('/reset', function(req, res) {
  // Reset skip list
  deps.reset();
  res.send('OK');
});

app.get('/*', function(req, res, next) {

  // Skip /deps, those are files
  if (req.url.indexOf('/deps') === 0) {
    return next();
  }

  var tid = parseInt(themeUid, 10);
  var settingsPromise;
  if (isNaN(tid)) {
    //Its not a number but a settings file!
    settingsPromise = fs.read(themeUid).then(deps.parseJSON).then(function(settings) {
      return {params: {settings:settings}};
    });
  } else {
    settingsPromise = api('Theme.get', [tid, true]);
  }

  // We update dependencies and load theme each time so we always pick up changes.
  // This is for development people!
  settingsPromise.then(function(theme) {
    var settings  = (theme.params && theme.params.settings) || {};
    var name      = (theme.params && theme.params.component) || 'tws-theme';

    // We want to load the supplied theme + any components in it's settins
    var promises = [];

    promises.push(deps.updateDeps(name));

    var settingsComponents = {};
    util.findComponentsInSettings(settings, function(c) {
      settingsComponents[c.component] = true;
    });

    Object.keys(settingsComponents).forEach(function(n) {
      promises.push(deps.updateDeps(n));
    });

    return Q.all(promises).then(function(result) {
      var defs = result.reduce(function(soFar, obj) {
        Object.keys(obj).forEach(function(k) {
          if (obj[k] !== undefined) {
            soFar[k] = obj[k];
          }
        });
        return soFar;
      }, {});

      var renderList = [];
      var templates = [];

      util.findComponentsInSettings(settings, function(obj) {
        // findComponentsInSettings goes depth first and applies children before parents
        var def = defs[obj.component];
        if (def.template) {
          // FIXME: alternative templates
          templates.push(fs.read(path.join(
            process.cwd(),
            deps.DEPS_FOLDER,
            def.name,
            def.template
          )));
          renderList.push(obj);
        }
      });
      //console.log('And the renderlist is: ', renderList.map(function(c) {
      //  return c.component;
      //}));

      // Load all templates
      return Q.all(templates).then(function(templateData) {

        // Render mustache templates for each in the list.
        renderList.forEach(function(obj, i) {

          var c = render.createContext();
          c.settings = obj.settings || {};
          c.settingsJSON = JSON.stringify(obj.settings).replace(/<\/script>/g,'<\\/script>')
          obj.componentHTML = render.renderMustache(templateData[i], c);
        });

        var context = render.createContext();
        var names = Object.keys(settingsComponents);
        names.unshift(name);

        var prefix = render.prefixFactory(deps.DEPS_FOLDER);

        util.traverseDeps(names, defs, function(comp) {
          if (typeof comp.style === 'string') {
            context.styles.push(prefix(comp.name, comp.style));
          } else if (typeof comp.style !== 'undefined') {
            context.styles = comp.style.map(function(u) {
              return prefix(comp.name, u);
            }).concat(context.styles);
          }

          if (typeof comp.script === 'string') {
            context.scripts.unshift(prefix(comp.name, comp.script));
          } else if (typeof comp.script !== 'undefined') {
            context.scripts = comp.script.map(function(u) {
              return prefix(comp.name, u);
            }).concat(context.scripts);
          }

          if (comp.angular) {
            context.modules[comp.angular] = true;
          }
        });

        context.settings = settings;

        // Since settingsJSON is going up to the server we need to clean out redundant code.
        util.findComponentsInSettings(settings, function(obj) {
          delete obj.settings;
        }, true);

        context.settingsJSON = JSON.stringify(settings).replace(/<\/script>/g,'<\\/script>');

        context.angularBootstrap = 'angular.module("tws",["' +
                                    Object.keys(context.modules).join('","') +
                                   '"])\n' + 'angular.bootstrap(document,["tws"])';

        // Lets render main mustache template;
        return fs.read(path.join(
          process.cwd(),
          deps.DEPS_FOLDER,
          name,
          defs[name].template
        )).then(function(template) {
          res.send(render.renderMustache(template, context));
        });

      });
    });
  }).fail(function(err) {
    if (!Array.isArray(err)) {
      err = [err];
    }
    console.log(err.join(err.join('\n')));
    err.map(function(e) { return e.stack || e; });
    res.status(500).send('An error occured: ' + err.join('
'));

  });
});

var server = app.listen(3000, function() {
  console.log('Listening on port %d', server.address().port);
});
<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import _ from 'underscore';
import { Button } from 'react-bootstrap';
import { console, object, Schemas, fileUtil, DateUtility } from './../util';
import { FormattedInfoBlock } from './components';
import DefaultItemView, { OverViewBodyItem } from './DefaultItemView';

export default class ProtocolView extends DefaultItemView {

    getTabViewContents(){

        var initTabs = [];

        initTabs.push(ProtocolViewOverview.getTabObject(this.props));

        return initTabs.concat(this.getCommonTabs()); // Add remainder of common tabs (Details, Attribution)
    }

}

class ProtocolViewOverview extends React.PureComponent {

    /**
     * Get overview tab object for tabpane.
     *
     * @param {{ context: Object, schemas: Object|null }} props - Object containing Protocol Item context/result and schemas.
     */
    static getTabObject(props){
        return {
            'tab' :  Overview,
            'key' : 'protocol-info',
            //'disabled' : !Array.isArray(context.experiments),
            'content' : (

                        Overview

                    <ProtocolViewOverview context={props.context} schemas={props.schemas} />

            )
        };
    }

    render(){
        const { context, schemas } = this.props;
        const tips = object.tipsFromSchema(schemas || Schemas.get(), context);
        const result = context;

        return (

                <OverViewBodyItem {...{ result, tips }} property='protocol_type' fallbackTitle="Protocol Type" wrapInColumn />

                <OverViewBodyItem {...{ result, tips }} property='protocol_classification' fallbackTitle="Protocol Classification" wrapInColumn />

                <ItemFileAttachment context={result} tips={tips} wrapInColumn includeTitle />

        );

    }

}

export class ItemFileAttachment extends React.PureComponent {

    static defaultProps = {
        'required' : false,
        'includeTitle' : false,
        'itemType' : 'Protocol',
        'property' : "attachment",
        'btnSize' : null
    };

    wrapInColumn(){
        var wrapInColumn = this.props.wrapInColumn;
        if (!wrapInColumn) return arguments;
        return (

                { Array.from(arguments) }

        );
    }

    attachmentTips(){
        var tips = this.props.tips;
        var fieldInfo = {};
        if (tips && tips.attachment && tips.attachment.properties){
            fieldInfo = tips.attachment.properties;
        }
        return fieldInfo;
    }

    size(){
        var attachment = (this.props.context && this.props.context.attachment) || null;
        if (!attachment || !attachment.size || typeof attachment.size !== 'number') return null;
        var tip = this.attachmentTips().size;
        return (

                  { Schemas.Term.bytesToLargerUnit(attachment.size) }

        );
    }

    md5sum(){
        var attachment = (this.props.context && this.props.context.attachment) || null;
        if (!attachment || !attachment.md5sum || typeof attachment.md5sum !== 'string') return null;
        return (

                <object.TooltipInfoIconContainerAuto tips={this.attachmentTips()} fallbackTitle="MD5" property="md5sum" className="text-500" result={attachment} elementType="span" /> : { attachment.md5sum }

        );
    }

    attachmentType(){
        var attachment = (this.props.context && this.props.context.attachment) || null;
        if (!attachment || !attachment.md5sum || typeof attachment.md5sum !== 'string') return null;
        return (

                <object.TooltipInfoIconContainerAuto tips={this.attachmentTips()} fallbackTitle="File Type" property="type" className="text-500" result={attachment} elementType="span" /> : { attachment.type }

        );
    }

    render(){
        var { context, tips, includeTitle, property, wrapInColumn, btnSize } = this.props;

        if ((this.props.hideIfNoValue) && (!context || !context.attachment)) return null;
        var attachment = (context && context.attachment) || null;

        var fieldInfo = {};
        if (tips && tips.attachment){
            fieldInfo = tips.attachment;
        }

        var title = !includeTitle ? null : (
            <object.TooltipInfoIconContainerAuto {..._.pick(this.props, 'tips', 'schemas')} fallbackTitle="Attachment"
                property={property} result={context} elementType="h5" />
        );

        var contents = null;
        if (attachment){
            contents = (

                        <fileUtil.ViewFileButton
                            size={btnSize}
                            filename={(attachment && attachment.download) || null}
                            href={object.itemUtil.atId(context) + attachment.href}
                            disabled={typeof attachment.href !== 'string' || attachment.href.length === 0}
                            className={fileUtil.ViewFileButton.defaultProps.className + ' btn-block'}
                        />

{ this.size() }{ this.md5sum() }{ this.attachmentType() }

            );
        } else {
            contents =
None
;
        }

        var elems = (

                { title } { contents }

        );

        return wrapInColumn ? this.wrapInColumn(elems) : elems;
    }

}
<commit_msg>Added url display to Protocol item page overview tab<commit_after>'use strict';

import React from 'react';
import _ from 'underscore';
import { Button } from 'react-bootstrap';
import { console, object, Schemas, fileUtil, DateUtility } from './../util';
import { FormattedInfoBlock } from './components';
import DefaultItemView, { OverViewBodyItem } from './DefaultItemView';

export default class ProtocolView extends DefaultItemView {

    getTabViewContents(){

        var initTabs = [];

        initTabs.push(ProtocolViewOverview.getTabObject(this.props));

        return initTabs.concat(this.getCommonTabs()); // Add remainder of common tabs (Details, Attribution)
    }

}

class ProtocolViewOverview extends React.PureComponent {

    /**
     * Get overview tab object for tabpane.
     *
     * @param {{ context: Object, schemas: Object|null }} props - Object containing Protocol Item context/result and schemas.
     */
    static getTabObject(props){
        return {
            'tab' :  Overview,
            'key' : 'protocol-info',
            //'disabled' : !Array.isArray(context.experiments),
            'content' : (

                        Overview

                    <ProtocolViewOverview context={props.context} schemas={props.schemas} />

            )
        };
    }

    render(){
        const { context, schemas } = this.props;
        const tips = object.tipsFromSchema(schemas || Schemas.get(), context);
        const result = context;

        return (

                    <OverViewBodyItem {...{ result, tips }} property='protocol_type' fallbackTitle="Protocol Type" wrapInColumn="col-xs-6 col-md-4 mb-3" />
                    <OverViewBodyItem {...{ result, tips }} property='protocol_classification' fallbackTitle="Protocol Classification" wrapInColumn />
                    <ItemFileAttachment context={result} tips={tips} wrapInColumn includeTitle />

                    <OverViewBodyItem {...{ result, tips }} property="url" fallbackTitle="External Link" wrapInColumn="col-md-6" titleRenderFxn={OverViewBodyItem.titleRenderPresets.url_string} hideIfNoValue />

        );

    }

}

export class ItemFileAttachment extends React.PureComponent {

    static defaultProps = {
        'required' : false,
        'includeTitle' : false,
        'itemType' : 'Protocol',
        'property' : "attachment",
        'btnSize' : null
    };

    wrapInColumn(){
        var wrapInColumn = this.props.wrapInColumn;
        if (!wrapInColumn) return arguments;
        return (

                { Array.from(arguments) }

        );
    }

    attachmentTips(){
        var tips = this.props.tips;
        var fieldInfo = {};
        if (tips && tips.attachment && tips.attachment.properties){
            fieldInfo = tips.attachment.properties;
        }
        return fieldInfo;
    }

    size(){
        var attachment = (this.props.context && this.props.context.attachment) || null;
        if (!attachment || !attachment.size || typeof attachment.size !== 'number') return null;
        var tip = this.attachmentTips().size;
        return (

                  { Schemas.Term.bytesToLargerUnit(attachment.size) }

        );
    }

    md5sum(){
        var attachment = (this.props.context && this.props.context.attachment) || null;
        if (!attachment || !attachment.md5sum || typeof attachment.md5sum !== 'string') return null;
        return (

                <object.TooltipInfoIconContainerAuto tips={this.attachmentTips()} fallbackTitle="MD5" property="md5sum" className="text-500" result={attachment} elementType="span" /> : { attachment.md5sum }

        );
    }

    attachmentType(){
        var attachment = (this.props.context && this.props.context.attachment) || null;
        if (!attachment || !attachment.md5sum || typeof attachment.md5sum !== 'string') return null;
        return (

                <object.TooltipInfoIconContainerAuto tips={this.attachmentTips()} fallbackTitle="File Type" property="type" className="text-500" result={attachment} elementType="span" /> : { attachment.type }

        );
    }

    render(){
        var { context, tips, includeTitle, property, wrapInColumn, btnSize } = this.props;

        if ((this.props.hideIfNoValue) && (!context || !context.attachment)) return null;
        var attachment = (context && context.attachment) || null;

        var fieldInfo = {};
        if (tips && tips.attachment){
            fieldInfo = tips.attachment;
        }

        var title = !includeTitle ? null : (
            <object.TooltipInfoIconContainerAuto {..._.pick(this.props, 'tips', 'schemas')} fallbackTitle="Attachment"
                property={property} result={context} elementType="h5" />
        );

        var contents = null;
        if (attachment){
            contents = (

                        <fileUtil.ViewFileButton
                            size={btnSize}
                            filename={(attachment && attachment.download) || null}
                            href={object.itemUtil.atId(context) + attachment.href}
                            disabled={typeof attachment.href !== 'string' || attachment.href.length === 0}
                            className={fileUtil.ViewFileButton.defaultProps.className + ' btn-block'}
                        />

{ this.size() }{ this.md5sum() }{ this.attachmentType() }

            );
        } else {
            contents =
None
;
        }

        var elems = (

                { title } { contents }

        );

        return wrapInColumn ? this.wrapInColumn(elems) : elems;
    }

}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Job = mongoose.model('Job'),
	Employer = mongoose.model('Employer'),
	Candidate = mongoose.model('Candidate'),
	_ = require('lodash');

/**
 * Get the error message from error object
 */
var getErrorMessage = function(err) {

	var message = '';
	if(err.message)
		message = err.message;

	if (err.code) {
		switch (err.code) {
			case 11000:
			case 11001:
				message = 'Job already exists';
				break;
			default:
				message = 'Something went wrong';
		}
	} else {
		for (var errName in err.errors) {
			if (err.errors[errName].message) message = err.errors[errName].message;
		}
	}

	return message;
};

/**
 * Create a Job
 */
exports.create = function(req, res) {
	console.log(req.user.candidate);
	if(req.user.userType === 'employer'){
		var job = new Job(req.body);
		job.user = req.user;
		console.log(req.user._id);

		var emp = Employer.find({user: req.user._id}).populate('company').exec(function(err, employers){
			console.log(employers[0]._id);
			job.employer = employers[0]._id;
			job.company = employers[0].company._id;
			employers[0].jobs.push(job);
			var company = employers[0].company;
			company.jobs.push(job);
			company.save();
			job.save(function(err) {
				if (err) {
					return res.send(400, {
						message: getErrorMessage(err)
					});
				} else {
					employers[0].save();
					res.jsonp(job);
				}
			});
		});
	}

};

/**
 * Show the current Job
 */
exports.read = function(req, res) {
		Job.findOne({_id: req.job._id}).populate('company').exec(function(err, job){
		res.jsonp(job);
	});
};

/**
 * Show the current Job
 */
exports.getJobCandidates = function(req, res) {
	Job.findOne({_id: req.job._id}).populate('candidates').exec(function(err, job){
		res.jsonp(job);
	});
};

/**
 * Show the current Job
 */
exports.getShortListedCandidates = function(req, res) {
	Job.findOne({_id: req.job._id}).populate('shortListedCandidates').exec(function(err, job){
		res.jsonp(job);
	});
};

exports.getRemoveShortListedCandidates = function(req, res) {
	Job.findOne({_id: req.job._id}).populate('shortListedCandidates').exec(function(err, job){
		res.jsonp(job);
	});
};

exports.apply = function(req, res, next)

{

	if(req.user.userType === 'candidate')

	{
		var job = req.job;

		Job.findOne({_id: req.job._id})
			.exec(function(err, doc)
				{
				job = doc;
				Candidate.findOne({user: req.user._id}).exec(function(err, candidate)
					{
					Job.findOne({_id: job._id})
					.where({candidates: candidate._id})
					.exec(function(err, doc)
						{
							if(!doc)
							{
								//doc.apply(candidate);
								job.apply(candidate);
								res.jsonp(req.job);
							}
						});
				});
		});

	}
};

/**
 * Update a Job
 */
exports.update = function(req, res) {
	var job = req.job ;

	job = _.extend(job , req.body);

	job.save(function(err) {
		if (err) {
			return res.send(400, {
				message: getErrorMessage(err)
			});
		} else {
			res.jsonp(job);
		}
	});
};

/**
 * Delete an Job
 */
exports.delete = function(req, res) {
	var job = req.job ;

	job.remove(function(err) {
		if (err) {
			return res.send(400, {
				message: getErrorMessage(err)
			});
		} else {
			res.jsonp(job);
		}
	});
};

/**
 * List of Jobs
 */
exports.list = function(req, res) {
	Job.find().sort('-created').populate('user', 'displayName').populate('company').exec(function(err, jobs) {
		if (err) {
			return res.send(400, {
				message: getErrorMessage(err)
			});
		} else {
			res.jsonp(jobs);
		}
	});
};

/**
 * Job middleware
 */
exports.jobByID = function(req, res, next, id) { Job.findById(id).populate('user', 'displayName').exec(function(err, job) {
		if (err) return next(err);
		if (! job) return next(new Error('Failed to load Job ' + id));
		req.job = job ;
		next();
	});
};

exports.addToShortList = function(req, res, next) {

	if(req.user.userType === 'employer'){

		var jobId = req.body.jobId;
		var candidateId = req.body.candidateId;

			Job.findOne({_id: jobId}).exec(function(err, job){
			Employer.findOne({user: req.user._id}).exec(function(err, employer){
				Candidate.findOne({_id: candidateId}).exec(function(err, candidate){
					job.addToShortList(candidate, employer);
					res.jsonp(job);
				});
			});
		});
	}
};

exports.removeFromShortList = function(req, res, next) {

	if(req.user.userType === 'employer'){
		var jobId = req.body.jobId;
		var candidateId = req.body.candidateId;

		Job.findByIdAndUpdate(jobId, {
		  $pull: {
		    shortListedCandidates: {candidate: candidateId}
		  }
		}, function(err, job){
			res.jsonp(job);
		});

	}
};

/**
 * Job authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.job.user.id !== req.user.id) {
		return res.send(403, 'User is not authorized');
	}
	next();
};<commit_msg>unique shortlist<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Job = mongoose.model('Job'),
	Employer = mongoose.model('Employer'),
	Candidate = mongoose.model('Candidate'),
	_ = require('lodash');

/**
 * Get the error message from error object
 */
var getErrorMessage = function(err) {

	var message = '';
	if(err.message)
		message = err.message;

	if (err.code) {
		switch (err.code) {
			case 11000:
			case 11001:
				message = 'Job already exists';
				break;
			default:
				message = 'Something went wrong';
		}
	} else {
		for (var errName in err.errors) {
			if (err.errors[errName].message) message = err.errors[errName].message;
		}
	}

	return message;
};

/**
 * Create a Job
 */
exports.create = function(req, res) {
	console.log(req.user.candidate);
	if(req.user.userType === 'employer'){
		var job = new Job(req.body);
		job.user = req.user;
		console.log(req.user._id);

		var emp = Employer.find({user: req.user._id}).populate('company').exec(function(err, employers){
			console.log(employers[0]._id);
			job.employer = employers[0]._id;
			job.company = employers[0].company._id;
			employers[0].jobs.push(job);
			var company = employers[0].company;
			company.jobs.push(job);
			company.save();
			job.save(function(err) {
				if (err) {
					return res.send(400, {
						message: getErrorMessage(err)
					});
				} else {
					employers[0].save();
					res.jsonp(job);
				}
			});
		});
	}

};

/**
 * Show the current Job
 */
exports.read = function(req, res) {
		Job.findOne({_id: req.job._id}).populate('company').exec(function(err, job){
		res.jsonp(job);
	});
};

/**
 * Show the current Job
 */
exports.getJobCandidates = function(req, res) {
	Job.findOne({_id: req.job._id}).populate('candidates').exec(function(err, job){
		res.jsonp(job);
	});
};

/**
 * Show the current Job
 */
exports.getShortListedCandidates = function(req, res) {
	Job.findOne({_id: req.job._id}).populate('shortListedCandidates').exec(function(err, job){
		res.jsonp(job);
	});
};

exports.getRemoveShortListedCandidates = function(req, res) {
	Job.findOne({_id: req.job._id}).populate('shortListedCandidates').exec(function(err, job){
		res.jsonp(job);
	});
};

exports.apply = function(req, res, next)

{

	if(req.user.userType === 'candidate')

	{
		var job = req.job;

		Job.findOne({_id: req.job._id})
			.exec(function(err, doc)
				{
				job = doc;
				Candidate.findOne({user: req.user._id}).exec(function(err, candidate)
					{
					Job.findOne({_id: job._id})
					.where({candidates: candidate._id})
					.exec(function(err, doc)
						{
							if(!doc)
							{
								//doc.apply(candidate);
								job.apply(candidate);
								res.jsonp(req.job);
							}
						});
				});
		});

	}
};

/**
 * Update a Job
 */
exports.update = function(req, res) {
	var job = req.job ;

	job = _.extend(job , req.body);

	job.save(function(err) {
		if (err) {
			return res.send(400, {
				message: getErrorMessage(err)
			});
		} else {
			res.jsonp(job);
		}
	});
};

/**
 * Delete an Job
 */
exports.delete = function(req, res) {
	var job = req.job ;

	job.remove(function(err) {
		if (err) {
			return res.send(400, {
				message: getErrorMessage(err)
			});
		} else {
			res.jsonp(job);
		}
	});
};

/**
 * List of Jobs
 */
exports.list = function(req, res) {
	Job.find().sort('-created').populate('user', 'displayName').populate('company').exec(function(err, jobs) {
		if (err) {
			return res.send(400, {
				message: getErrorMessage(err)
			});
		} else {
			res.jsonp(jobs);
		}
	});
};

/**
 * Job middleware
 */
exports.jobByID = function(req, res, next, id) { Job.findById(id).populate('user', 'displayName').exec(function(err, job) {
		if (err) return next(err);
		if (! job) return next(new Error('Failed to load Job ' + id));
		req.job = job ;
		next();
	});
};

exports.addToShortList = function(req, res, next) {

	if(req.user.userType === 'employer'){

		var jobId = req.body.jobId;
		var candidateId = req.body.candidateId;

			Job.findOne({_id: jobId}).exec(function(err, job){

				var exists = false;
				job.shortListedCandidates.forEach(function(slc){
					if(slc.candidate == candidateId)
					{
						exists = true;
					}
				});

				if(!exists){
					Employer.findOne({user: req.user._id}).exec(function(err, employer){
						Candidate.findOne({_id: candidateId}).exec(function(err, candidate)
							{
							job.addToShortList(candidate, employer);
							res.jsonp(job);
						});
					});
				}
		});

	}
};

exports.removeFromShortList = function(req, res, next) {

	if(req.user.userType === 'employer'){
		var jobId = req.body.jobId;
		var candidateId = req.body.candidateId;

		Job.findByIdAndUpdate(jobId, {
		  $pull: {
		    shortListedCandidates: {candidate: candidateId}
		  }
		}, function(err, job){
			res.jsonp(job);
		});

	}
};

/**
 * Job authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.job.user.id !== req.user.id) {
		return res.send(403, 'User is not authorized');
	}
	next();
};

<|endoftext|>


<commit_before>/*! Kernel CI Dashboard | Licensed under the GNU GPL v3 (or later) */
define(function() {
    'use strict';
    var html,
        htmlEntities;

    html = {};
    htmlEntities = {
        '"': '"',
        '#': '#',
        '$': '$',
        '%': '%',
        '&': '&',
        '\'': ''',
        '/': '/',
        '<': '<',
        '=': '=',
        '>': '>',
        '?': '?'
    };

    html.escape = function(toEscape) {
        return String(toEscape).replace(/[&<>"'\/]/g, function fromMap(s) {
            return htmlEntities[s];
        });
    };

    html.a = function() {
        return document.createElement('a');
    };

    html.i = function() {
        return document.createElement('i');
    };

    html.div = function() {
        return document.createElement('div');
    };

    html.span = function() {
        return document.createElement('span');
    };

    html.table = function() {
        return document.createElement('table');
    };

    html.strong = function() {
        return document.createElement('strong');
    };

    html.small = function() {
        return document.createElement('small');
    };

    html.h4 = function() {
        return document.createElement('h4');
    };

    html.h5 = function() {
        return document.createElement('h5');
    };

    html.dl = function() {
        return document.createElement('dl');
    };

    html.dt = function() {
        return document.createElement('dt');
    };

    html.dd = function() {
        return document.createElement('dd');
    };

    html.errorDiv = function(text) {
        var divNode,
            strongNode;

        divNode = document.createElement('div');
        divNode.className = 'pull-center';

        strongNode = document.createElement('strong');
        strongNode.appendChild(document.createTextNode(text));

        divNode.appendChild(strongNode);

        return divNode;
    };

    html.build = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-info';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-cogs';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.fail = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-danger';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-exclamation-triangle';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.success = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-success';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-check';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.unknown = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-warning';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-question';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.offline = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-info';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-power-off';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.tooltip = function() {
        var element;

        element = document.createElement('span');
        element.setAttribute('rel', 'tooltip');
        element.setAttribute('data-toggle', 'tooltip');

        return element;
    };

    html.time = function() {
        return document.createElement('time');
    };

    html.replaceAllBySelector = function(selector, content) {
        [].forEach.call(
            document.querySelectorAll(selector),
            function(element) {
                element.innerHTML = content;
            }
        );
    };

    html.replaceByClass = function(className, content) {
        [].forEach.call(
            document.getElementsByClassName(className),
            function(element) {
                element.innerHTML = content;
            }
        );
    };

    html.replaceByClassNode = function(className, node) {
        [].forEach.call(
            document.getElementsByClassName(className),
            function(element) {
                while (element.firstChild) {
                    element.removeChild(element.firstChild);
                }
                element.appendChild(child);
            }
        );
    };

    html.replaceContent = function(element, child) {
        if (element !== null) {
            while (element.firstChild) {
                element.removeChild(element.firstChild);
            }
            element.appendChild(child);
        }
    };

    html.removeChildren = function(element) {
        if (element !== null) {
            while (element.firstChild) {
                element.removeChild(element.firstChild);
            }
        }
    };

    html.unavailable = function() {
        var iNode,
            spanNode;

        iNode = document.createElement('i');
        iNode.className = 'fa fa-ban';
        spanNode = document.createElement('span');
        spanNode.setAttribute('rel', 'tooltip');
        spanNode.setAttribute('data-toggle', 'tooltip');
        spanNode.setAttribute('title', 'Not available');
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.addClass = function(element, newClass) {
        var classes;

        if (element !== null) {
            classes = element.className.split(' ');

            if (classes.indexOf(newClass) === -1) {
                element.className = classes.join(' ');
            }
        }
    };

    html.removeClass = function(element, className) {
        var classIdx,
            classes;

        if (element !== null) {
            classes = element.className.split(' ');
            classIdx = classes.indexOf(className);

            if (classIdx !== -1) {
                classes.splice(classIdx, 1);
            }

            element.className = classes.join(' ');
        }
    };

    html.attrBySelector = function(selector, attribute) {
        var element,
            value;

        element = document.querySelector(selector);
        value = null;
        if (element !== null) {
            value = element.getAttribute(attribute);
        }

        return value;
    };

    html.attrById = function(elementId, attribute) {
        var element,
            value;

        element = document.getElementById(elementId);
        value = null;
        if (element !== null) {
            value = element.getAttribute(attribute);
        }

        return value;
    };

    html.removeElement = function(element) {
        if (element !== null) {
            element.parentElement.removeChild(element);
        }
    };

    return html;
});
<commit_msg>Fix error in setting element classes.<commit_after>/*! Kernel CI Dashboard | Licensed under the GNU GPL v3 (or later) */
define(function() {
    'use strict';
    var html,
        htmlEntities;

    html = {};
    htmlEntities = {
        '"': '"',
        '#': '#',
        '$': '$',
        '%': '%',
        '&': '&',
        '\'': ''',
        '/': '/',
        '<': '<',
        '=': '=',
        '>': '>',
        '?': '?'
    };

    html.escape = function(toEscape) {
        return String(toEscape).replace(/[&<>"'\/]/g, function fromMap(s) {
            return htmlEntities[s];
        });
    };

    html.a = function() {
        return document.createElement('a');
    };

    html.i = function() {
        return document.createElement('i');
    };

    html.div = function() {
        return document.createElement('div');
    };

    html.span = function() {
        return document.createElement('span');
    };

    html.table = function() {
        return document.createElement('table');
    };

    html.strong = function() {
        return document.createElement('strong');
    };

    html.small = function() {
        return document.createElement('small');
    };

    html.h4 = function() {
        return document.createElement('h4');
    };

    html.h5 = function() {
        return document.createElement('h5');
    };

    html.dl = function() {
        return document.createElement('dl');
    };

    html.dt = function() {
        return document.createElement('dt');
    };

    html.dd = function() {
        return document.createElement('dd');
    };

    html.errorDiv = function(text) {
        var divNode,
            strongNode;

        divNode = document.createElement('div');
        divNode.className = 'pull-center';

        strongNode = document.createElement('strong');
        strongNode.appendChild(document.createTextNode(text));

        divNode.appendChild(strongNode);

        return divNode;
    };

    html.build = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-info';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-cogs';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.fail = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-danger';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-exclamation-triangle';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.success = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-success';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-check';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.unknown = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-warning';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-question';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.offline = function() {
        var spanNode,
            iNode;

        spanNode = document.createElement('span');
        spanNode.className = 'label label-info';
        iNode = document.createElement('i');
        iNode.className = 'fa fa-power-off';
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.tooltip = function() {
        var element;

        element = document.createElement('span');
        element.setAttribute('rel', 'tooltip');
        element.setAttribute('data-toggle', 'tooltip');

        return element;
    };

    html.time = function() {
        return document.createElement('time');
    };

    html.replaceAllBySelector = function(selector, content) {
        [].forEach.call(
            document.querySelectorAll(selector),
            function(element) {
                element.innerHTML = content;
            }
        );
    };

    html.replaceByClass = function(className, content) {
        [].forEach.call(
            document.getElementsByClassName(className),
            function(element) {
                element.innerHTML = content;
            }
        );
    };

    html.replaceByClassNode = function(className, node) {
        [].forEach.call(
            document.getElementsByClassName(className),
            function(element) {
                while (element.firstChild) {
                    element.removeChild(element.firstChild);
                }
                element.appendChild(child);
            }
        );
    };

    html.replaceContent = function(element, child) {
        if (element !== null) {
            while (element.firstChild) {
                element.removeChild(element.firstChild);
            }
            element.appendChild(child);
        }
    };

    html.removeChildren = function(element) {
        if (element !== null) {
            while (element.firstChild) {
                element.removeChild(element.firstChild);
            }
        }
    };

    html.unavailable = function() {
        var iNode,
            spanNode;

        iNode = document.createElement('i');
        iNode.className = 'fa fa-ban';
        spanNode = document.createElement('span');
        spanNode.setAttribute('rel', 'tooltip');
        spanNode.setAttribute('data-toggle', 'tooltip');
        spanNode.setAttribute('title', 'Not available');
        spanNode.appendChild(iNode);

        return spanNode;
    };

    html.addClass = function(element, newClass) {
        var classes;

        if (element !== null) {
            classes = element.className.split(' ');

            if (classes.indexOf(newClass) === -1) {
                classes.push(newClass);
                element.className = classes.join(' ');
            }
        }
    };

    html.removeClass = function(element, className) {
        var classIdx,
            classes;

        if (element !== null) {
            classes = element.className.split(' ');
            classIdx = classes.indexOf(className);

            if (classIdx !== -1) {
                classes.splice(classIdx, 1);
            }

            element.className = classes.join(' ');
        }
    };

    html.attrBySelector = function(selector, attribute) {
        var element,
            value;

        element = document.querySelector(selector);
        value = null;
        if (element !== null) {
            value = element.getAttribute(attribute);
        }

        return value;
    };

    html.attrById = function(elementId, attribute) {
        var element,
            value;

        element = document.getElementById(elementId);
        value = null;
        if (element !== null) {
            value = element.getAttribute(attribute);
        }

        return value;
    };

    html.removeElement = function(element) {
        if (element !== null) {
            element.parentElement.removeChild(element);
        }
    };

    return html;
});
<|endoftext|>


<commit_before>import logger from 'logger';
import { getPeruseAppObj } from '../network';
import { setWebFetchStatus } from '../../../actions/web_fetch_actions';

const safeRoute = ( store ) => ( {
    method  : 'GET',
    path    : '/safe/{link*}',
    handler : async ( request, reply ) =>
    {
        try
        {
            const link = `safe://${request.params.link}`;

            const app = getPeruseAppObj() || {};
            const headers = request.headers;
            let isRangeReq = false;
            const BYTES = 'bytes=';

            let start;
            let end;

            logger.verbose( `Handling SAFE req: ${link}` );

            if ( !app )
            {
                return reply( 'SAFE not connected yet' );
            }

            if ( headers.range )
            {
                const range = headers.range;
                const rangeArray =
                  range.substring( BYTES.length, range.length )
                      .replace( /['"]+/g, '' )
                      .split( '-' );

                start = rangeArray[0] ? parseInt( rangeArray[0], 10 ) : null;
                end = rangeArray[1] ? parseInt( rangeArray[1], 10 ) : null;

                // we need to separate out 0- length requests which are not partial content
                if ( start && start !== 0 )
                {
                    // should have a start !== 0
                    isRangeReq = true;
                }

                if ( start === 0 && end )
                {
                    isRangeReq = true;
                }
            }

            // setup opts object
            const options = { headers };

            if ( isRangeReq )
            {
                options.range = { start, end };
            }
            store.dispatch( setWebFetchStatus( {
                fetching : true,
                link,
                options  : JSON.stringify( options )
            } ) );
            let data = null;
            try
            {
                data = await app.webFetch( link, options );
            }
            catch ( error )
            {
                logger.error( error.code, error.message );
                store.dispatch( setWebFetchStatus( { fetching: false, error, options: '' } ) );
                return reply( error.message || error );
            }
            store.dispatch( setWebFetchStatus( { fetching: false, options: '' } ) );

            if ( isRangeReq )
            {
                return reply( data.body )
                    .code( 206 )
                    .type( data.headers['Content-Type'] )
                    .header( 'Content-Range', data.headers['Content-Range'] )
                    .header( 'Content-Length', data.headers['Content-Length'] );
            }

            return reply( data.body )
                .type( data.headers['Content-Type'] )
                .header( 'Transfer-Encoding', 'chunked' )
                .header( 'Accept-Ranges', 'bytes' );
        }
        catch ( e )
        {
            logger.error( e );

            if ( e.code && e.code === -302 )
            {
                return reply( 'Requested Range Not Satisfiable' )
                    .code( 416 );
            }
            return reply( e.message || e );
        }
    }
} );

export default safeRoute;
<commit_msg>MAID-2488 feat/webFetch: impl multipart range requests<commit_after>import logger from 'logger';
import { getPeruseAppObj } from '../network';
import { setWebFetchStatus } from '../../../actions/web_fetch_actions';

const safeRoute = ( store ) => ( {
    method  : 'GET',
    path    : '/safe/{link*}',
    handler : async ( request, reply ) =>
    {
        try
        {
            const link = `safe://${request.params.link}`;

            const app = getPeruseAppObj() || {};
            const headers = request.headers;
            let isRangeReq = false;
	    let multipartReq = false;
            const BYTES = 'bytes=';

            let start;
            let end;
	    let rangeArray;

            logger.verbose( `Handling SAFE req: ${link}` );

            if ( !app )
            {
                return reply( 'SAFE not connected yet' );
            }

            if ( headers.range )
            {
	        isRangeReq = true;
                const range = headers.range;
                rangeArray =
                  range.substring( BYTES.length, range.length )
                      .split( ',' )
		      .map(part =>
		      {
		          const partObj = {};
	                  part.split('-')
			      .forEach((int, i) =>
			      {
			          if (i === 0)
				  {
				    if ( Number.isInteger(parseInt(int, 10)) )
				    {
				      partObj.start = parseInt(int, 10);
				    }
				    else
				    {
				      partObj.start = null;
				    }
				  }
				  else if (i === 1)
				  {
				    if ( Number.isInteger(parseInt(int, 10)) )
				    {
				      partObj.end = parseInt(int, 10);
				    }
				    else
				    {
				      partObj.end = null;
				    }
				  }
  	                      });
			  return partObj;
	              });
		if (rangeArray.length > 1) {
	          multipartReq = true;
		}
            }

            // setup opts object
            const options = { headers };

            if ( isRangeReq )
            {
                options.range = rangeArray;
            }
            store.dispatch( setWebFetchStatus( {
                fetching : true,
                link,
                options  : JSON.stringify( options )
            } ) );
            let data = null;
            try
            {
                data = await app.webFetch( link, options );
            }
            catch ( error )
            {
                logger.error( error.code, error.message );
                store.dispatch( setWebFetchStatus( { fetching: false, error, options: '' } ) );
                return reply( error.message || error );
            }
            store.dispatch( setWebFetchStatus( { fetching: false, options: '' } ) );

            if ( isRangeReq && multipartReq )
            {
                return reply( data.parts )
                    .code( 206 )
                    .type( data.headers['Content-Type'] )
                    .header( 'Content-Length', data.headers['Content-Length'] );
            }
            else if ( isRangeReq )
            {
                return reply( data.body )
                    .code( 206 )
                    .type( data.headers['Content-Type'] )
                    .header( 'Content-Range', data.headers['Content-Range'] )
                    .header( 'Content-Length', data.headers['Content-Length'] );
            }
	    else
	    {
              return reply( data.body )
                  .type( data.headers['Content-Type'] )
                  .header( 'Transfer-Encoding', 'chunked' )
                  .header( 'Accept-Ranges', 'bytes' );
	    }
        }
        catch ( e )
        {
            logger.error( e );

            if ( e.code && e.code === -302 )
            {
                return reply( 'Requested Range Not Satisfiable' )
                    .code( 416 );
            }
            return reply( e.message || e );
        }
    }
} );

export default safeRoute;
<|endoftext|>


<commit_before>import * as Promise from 'bluebird'
import * as Immutable from 'immutable'
import {isUndefined} from 'lodash'
import findResults from 'helpers/findResults'
import findWordForProgress from 'helpers/findWordForProgress'

let areas = Immutable.Map({
	// Degrees
	'd-ba': require('../../mockups/bachelorOfArts.es6').default,
	// 'd-bm': require('../../mockups/bachelorOfMusic.es6').default,

	// Majors
	// 'm-csci':  require('../../mockups/computerScience.es6').default,
	// 'm-asian': require('../../mockups/asianStudies.es6').default,
	// 'm-chem':  require('../../mockups/chemistry.es6').default,
	// 'm-phys':  require('../../mockups/physics.es6').default,

	// Concentrations
	// 'c-asian': require('../../mockups/asianStudiesConcentration.es6').default,
	// 'c-stat':  require('../../mockups/statisticsConcentration.es6').default,
	// 'c-chin':  require('../../mockups/chineseStudiesConcentration.es6').default,
	// 'c-japan': require('../../mockups/japaneseStudiesConcentration.es6').default,

	// Emphases
})

let noResult = (type, title, id) => {
	return {
		id: id,
		title: title,
		result: false,
		progress: {at: 0, of: 1, word: 'zero'},
		type: type,
		details: {
			result: false,
			details: [{
				title: `${type} not found!`,
				description: `This ${type} could not be found.`,
			}],
		},
	}
}

let isTrue = (val) => val === true

function checkStudentAgainstArea(student, area) {
	let title = area.title
	let type = area.type
	let id = area.id

	let areaChecker = areas.get(area.id)

	if (!areaChecker)
		return Promise.resolve(noResult(type, title, id))

	return areaChecker(student)
		.then((studentResults) => {
			let listOfResults = findResults(studentResults.details)

			let currentProgress = Immutable.List.of(listOfResults).filterNot(isUndefined).filter(isTrue).size
			let maxProgress = listOfResults.length
			let progressName = findWordForProgress(maxProgress, currentProgress)

			let progress = {at: currentProgress, of: maxProgress, word: progressName}

			let result = studentResults.result
			let details = studentResults.details

			return {id, title, type, progress, result, details}
		})
}

function checkStudentGraduatability(student) {
	let areaResults = student.studies.map((area) => checkStudentAgainstArea(student, area)).toArray()
	// console.log('areaResults', student.studies.toArray(), areaResults)

	return Promise.all(areaResults).then((areas) => {
		areas = Immutable.List(areas)
		let graduatability = (areas.map(a => a.result).filter(isTrue).size - areas.size) >= 1
		return {graduatability: graduatability, areaDetails: areas}
	})
}

export default checkStudentGraduatability
<commit_msg>Only do List.of on something that isn't an array<commit_after>import * as Promise from 'bluebird'
import * as Immutable from 'immutable'
import {isUndefined} from 'lodash'
import findResults from 'helpers/findResults'
import findWordForProgress from 'helpers/findWordForProgress'

let areas = Immutable.Map({
	// Degrees
	'd-ba': require('../../mockups/bachelorOfArts.es6').default,
	// 'd-bm': require('../../mockups/bachelorOfMusic.es6').default,

	// Majors
	// 'm-csci':  require('../../mockups/computerScience.es6').default,
	// 'm-asian': require('../../mockups/asianStudies.es6').default,
	// 'm-chem':  require('../../mockups/chemistry.es6').default,
	// 'm-phys':  require('../../mockups/physics.es6').default,

	// Concentrations
	// 'c-asian': require('../../mockups/asianStudiesConcentration.es6').default,
	// 'c-stat':  require('../../mockups/statisticsConcentration.es6').default,
	// 'c-chin':  require('../../mockups/chineseStudiesConcentration.es6').default,
	// 'c-japan': require('../../mockups/japaneseStudiesConcentration.es6').default,

	// Emphases
})

let noResult = (type, title, id) => {
	return {
		id: id,
		title: title,
		result: false,
		progress: {at: 0, of: 1, word: 'zero'},
		type: type,
		details: {
			result: false,
			details: [{
				title: `${type} not found!`,
				description: `This ${type} could not be found.`,
			}],
		},
	}
}

let isTrue = (val) => val === true

function checkStudentAgainstArea(student, area) {
	let title = area.title
	let type = area.type
	let id = area.id

	let areaChecker = areas.get(area.id)

	if (!areaChecker)
		return Promise.resolve(noResult(type, title, id))

	return areaChecker(student)
		.then((studentResults) => {
			let listOfResults = findResults(studentResults.details)

			let currentProgress = Immutable.List(listOfResults).filterNot(isUndefined).filter(isTrue).size
			let maxProgress = listOfResults.length
			let progressName = findWordForProgress(maxProgress, currentProgress)

			let progress = {at: currentProgress, of: maxProgress, word: progressName}

			let result = studentResults.result
			let details = studentResults.details

			return {id, title, type, progress, result, details}
		})
}

function checkStudentGraduatability(student) {
	let areaResults = student.studies.map((area) => checkStudentAgainstArea(student, area)).toArray()
	// console.log('areaResults', student.studies.toArray(), areaResults)

	return Promise.all(areaResults).then((areas) => {
		areas = Immutable.List(areas)
		let graduatability = (areas.map(a => a.result).filter(isTrue).size - areas.size) >= 1
		return {graduatability: graduatability, areaDetails: areas}
	})
}

export default checkStudentGraduatability
<|endoftext|>


<commit_before>var http = require('q-io/http');
var redis = require('then-redis');
var _ = require('underscore');

var config = require('../config.js');
var Instance = require('./instance.js');
var DigitalOcean = require('./digital_ocean.js');
var DigitalOceanFake = require('./digital_ocean_fake.js');
var average = require('./average.js');

module.exports = function ResourceManager() {
    var self = this;

    // Redis database used for storage
    this.db = redis.createClient();

    // Client for our IaaS provider (DigitalOcean)
    if (config.useDigitalOcean) {
        this.digitalOcean = new DigitalOcean(config.digitalOcean);
    } else {
        this.digitalOcean = new DigitalOceanFake();
    }

    // List of application instances
    this.instances = [];

    this.systemLoad = 0;

    // Some ID that is guaranteed to be currently available
    this.availableId = 1;

    this.timestamp = function(date) {
        if(!date) {
            date = new Date;
        }

        var format = function(num) {
            return num < 10 ? "0" + num : num;
        }

        return format(date.getHours()) + ":"+ format(date.getMinutes()) + ":" + format(date.getSeconds());
    };

    this.allocateInstance = function() {
        var id = this.availableId;
        console.log("Allocating instance with ID: " + id);

        this.availableId += 1;
        return this.digitalOcean.allocate(id)
            .then(function(instance) {
                this.addInstance(instance);
                this.db.set("imgcloud-allocation-"+id+"-"+this.timestamp(), 1);
            }.bind(this));
    };

    this.deallocateInstance = function(instance) {
        console.log("Deallocating instance: " + instance);
        this.db.set("imgcloud-deallocation-"+instance.id+"-"+this.timestamp(), 1);
        return this.digitalOcean.deallocate(instance);
    };

    this.addInstance = function(instance) {
        this.instances.push(instance);
    };

    this.removeInstance = function(instance) {
        var index = this.instances.indexOf(instance);
        if (index != -1) {
            this.instances.splice(index, 1);
        }
    };

    this.markInstanceDead = function(instance) {
        console.log("markInstanceDead: marking %s", instance);
        instance.notifyDead();

        // Remove instance
        this.removeInstance(instance);

        this.deallocateInstance(instance)
            .then(function() {
                console.log("Succesfully deallocated: " + instance);
            })
            .fail(console.error);

        // Check if we need to allocate a new instance to make up for the deallocated one
        if (this.instances.length < config.MIN_INSTANCES) {
            this.allocateInstance();
        }
    };

    this.getInstances = function() {
        return this.instances;
    };

    this.getRunningInstances = function() {
        return this.instances.filter(function(instance) {
            return instance.isRunning();
        });
    };

    this.getInstance = function(id) {
        var instance = false;
        this.instances.forEach(function(inst) {
            if (inst.id == id) {
                instance = inst;
                return false; // Break
            }
        }, this);

        return instance;
    };

    this.pingInstance = function(instance) {
        return http.request("http://" + instance.host + ":" + instance.port + "/ping")
            .timeout(2 * config.POLL_FREQUENCY); // Cancel the ping after at most 2 polls
    };

    this.pollInstances = function() {
        // Store stats
        this.storeLoads();

        console.log("Polling... (%d instances)", this.instances.length);
        this.instances.forEach(function(instance) {
            this.pingInstance(instance)
                .then(function(data) {
                    console.log("pollInstances: %s is alive", instance);
                    instance.notifyAlive();
                })
                .fail(function(error) {
                    if (!instance.host) {
                        console.log("pollInstances: %s does not have an address yet", instance);

                        this.digitalOcean.getAddress(instance)
                            .then(function(address) {
                                instance.host = address;
                            });

                        return;
                    }

                    if (instance.isStarting()) {
                        // Fine, we'll forgive you for now
                        console.log("pollInstances: %s has not booted yet", instance);
                        return;
                    }

                    console.log("pollInstances: %s died", instance);
                    this.markInstanceDead(instance);
                }.bind(this));
        }, this);
    };

    // Calculate the average load over instances in the system
    this.calculateSystemLoad = function() {
        /*
        var instanceLoads = [];
        this.instances.forEach(function(instance) {
            instanceLoads.push(instance.load);
        }, this);

        return average(instanceLoads);
        */

        // Just use the most recently reported system load
        return this.systemLoad;
    };

    this.storeLoads = function() {
        var time = new Date;

        var data = {}
        data["imgcloud-systemload-0-"+this.timestamp(time)] = this.calculateSystemLoad();
        this.instances.forEach(function(instance) {
            data["imgcloud-instanceload-"+instance.id+"-"+self.timestamp(time)] = instance.load;
        });

        this.db.mset(data);
    }

    // Provision (allocate or deallocate) resources based on the system load
    this.provision = function() {
//        var systemLoad = 20 * Math.random();
        var systemLoad = this.calculateSystemLoad();
        var numInstances = this.instances.length;

        console.log("System load: %s, thresholds are %s and %s", systemLoad, config.DEALLOCATION_THRESHOLD, config.ALLOCATION_THRESHOLD);

        if (systemLoad > config.ALLOCATION_THRESHOLD) {
            console.log("provision: allocate");

            if(numInstances < config.MAX_INSTANCES) {
                this.allocateInstance().done(); // Throw any exceptions
            } else {
                console.log("provision: did not allocate due to MAX_INSTANCES");
            }
        } else if (systemLoad < config.DEALLOCATION_THRESHOLD) {
            console.log("provision: deallocate");

            // Enforce lower bound on the number of instances
            if(numInstances > config.MIN_INSTANCES) {
                var runningInstances = this.getRunningInstances();
                if (runningInstances.length <= 0) {
                    // Randomly kill some instance
                    var victim = runningInstances[0];
                    this.removeInstance(victim);
                    this.deallocateInstance(victim);
                }
            } else {
                console.log("provision: did not deallocate due to MIN_INSTANCES");
            }
        } else {
            console.log("provision: all is well");
        }
    };

    this.startProvisioning = function(freq) {
        freq = freq || config.PROVISION_FREQUENCY;

        // Check the load at regular intervals, and provision accordingly
        setInterval(this.provision.bind(this), freq);
    };

    // Bootstrap the resource manager, with an optional set of initial instances
    this.bootstrap = function(initialInstances) {
        initialInstances = initialInstances || [];

        this.instances = [];
        initialInstances.forEach(function(instInfo) {
            var inst = new Instance(instInfo.id, instInfo.host, instInfo.port);
            this.addInstance(inst);

            // Make sure our availableId is higher
            this.availableId = Math.max(this.availableId, instInfo.id + 1);
        }, this);

        // Fetch existing list from DigitalOcean
        this.digitalOcean.instances()
            .then(function(instances) {
                instances.forEach(function(instance) {
                    console.log("Re-adding existing instance: " + instance);
                    this.addInstance(instance);
                }.bind(this));
            }.bind(this))
            .then(function() {
                // If we still haven't reached it, allocate at least our minimum
                _.forEach(_.range(config.MIN_INSTANCES - this.instances.length), function() {
                    this.allocateInstance().done();
                }, this);
            }.bind(this));

        console.log("Initialized RM (with %d bootstrap instances)", this.instances.length);
    };

    this.destroyAll = function() {
        this.instances.forEach(function(instance) {
            this.markInstanceDead(instance);
        }, this);
    };

    this.saveRequestStats = function(instanceId, res) {
        var curTime = new Date;
        var keyBit = instanceId + "-"+this.timestamp(curTime);

        var values = {}

        // Store the LB and app response times
        values["imgcloud-response-" + keyBit] = +curTime - parseInt(res.getHeader('x-imgcloud-start-lb'), 10)

        // Store the instance load
        if(res.getHeader('x-imgcloud-osload')) {
            values["imgcloud-osload-" + keyBit] = res.getHeader('x-imgcloud-osload').split(",")[0];
        } else {
            console.log("saveRequestStats ERROR: no osload provided");
        }

        this.db.mset(values);
    };

    // Emit an event
    this.emit = function(eventName, req, res) {
        var instanceId = req.headers['x-imgcloud-host'];
        var instance = this.getInstance(instanceId);

        // Poller beat us to it?
        if (!instance) {
            return;
        }

        switch (eventName) {
            case "serverFailure":
                console.log("ServerFailure for " + instanceId);
                this.markInstanceDead(instance);
                break;

            case "requestEnd":
                if (req.url == "/images/upload") {
                    this.saveRequestStats(instanceId, res);
                }
                break;
        }
    };

    // Notify the resource manager of a newly calculated system load
    this.notifySystemLoad = function(systemLoad) {
        this.systemLoad = systemLoad;
    };
};
<commit_msg>Wrong operator.<commit_after>var http = require('q-io/http');
var redis = require('then-redis');
var _ = require('underscore');

var config = require('../config.js');
var Instance = require('./instance.js');
var DigitalOcean = require('./digital_ocean.js');
var DigitalOceanFake = require('./digital_ocean_fake.js');
var average = require('./average.js');

module.exports = function ResourceManager() {
    var self = this;

    // Redis database used for storage
    this.db = redis.createClient();

    // Client for our IaaS provider (DigitalOcean)
    if (config.useDigitalOcean) {
        this.digitalOcean = new DigitalOcean(config.digitalOcean);
    } else {
        this.digitalOcean = new DigitalOceanFake();
    }

    // List of application instances
    this.instances = [];

    this.systemLoad = 0;

    // Some ID that is guaranteed to be currently available
    this.availableId = 1;

    this.timestamp = function(date) {
        if(!date) {
            date = new Date;
        }

        var format = function(num) {
            return num < 10 ? "0" + num : num;
        }

        return format(date.getHours()) + ":"+ format(date.getMinutes()) + ":" + format(date.getSeconds());
    };

    this.allocateInstance = function() {
        var id = this.availableId;
        console.log("Allocating instance with ID: " + id);

        this.availableId += 1;
        return this.digitalOcean.allocate(id)
            .then(function(instance) {
                this.addInstance(instance);
                this.db.set("imgcloud-allocation-"+id+"-"+this.timestamp(), 1);
            }.bind(this));
    };

    this.deallocateInstance = function(instance) {
        console.log("Deallocating instance: " + instance);
        this.db.set("imgcloud-deallocation-"+instance.id+"-"+this.timestamp(), 1);
        return this.digitalOcean.deallocate(instance);
    };

    this.addInstance = function(instance) {
        this.instances.push(instance);
    };

    this.removeInstance = function(instance) {
        var index = this.instances.indexOf(instance);
        if (index != -1) {
            this.instances.splice(index, 1);
        }
    };

    this.markInstanceDead = function(instance) {
        console.log("markInstanceDead: marking %s", instance);
        instance.notifyDead();

        // Remove instance
        this.removeInstance(instance);

        this.deallocateInstance(instance)
            .then(function() {
                console.log("Succesfully deallocated: " + instance);
            })
            .fail(console.error);

        // Check if we need to allocate a new instance to make up for the deallocated one
        if (this.instances.length < config.MIN_INSTANCES) {
            this.allocateInstance();
        }
    };

    this.getInstances = function() {
        return this.instances;
    };

    this.getRunningInstances = function() {
        return this.instances.filter(function(instance) {
            return instance.isRunning();
        });
    };

    this.getInstance = function(id) {
        var instance = false;
        this.instances.forEach(function(inst) {
            if (inst.id == id) {
                instance = inst;
                return false; // Break
            }
        }, this);

        return instance;
    };

    this.pingInstance = function(instance) {
        return http.request("http://" + instance.host + ":" + instance.port + "/ping")
            .timeout(2 * config.POLL_FREQUENCY); // Cancel the ping after at most 2 polls
    };

    this.pollInstances = function() {
        // Store stats
        this.storeLoads();

        console.log("Polling... (%d instances)", this.instances.length);
        this.instances.forEach(function(instance) {
            this.pingInstance(instance)
                .then(function(data) {
                    console.log("pollInstances: %s is alive", instance);
                    instance.notifyAlive();
                })
                .fail(function(error) {
                    if (!instance.host) {
                        console.log("pollInstances: %s does not have an address yet", instance);

                        this.digitalOcean.getAddress(instance)
                            .then(function(address) {
                                instance.host = address;
                            });

                        return;
                    }

                    if (instance.isStarting()) {
                        // Fine, we'll forgive you for now
                        console.log("pollInstances: %s has not booted yet", instance);
                        return;
                    }

                    console.log("pollInstances: %s died", instance);
                    this.markInstanceDead(instance);
                }.bind(this));
        }, this);
    };

    // Calculate the average load over instances in the system
    this.calculateSystemLoad = function() {
        /*
        var instanceLoads = [];
        this.instances.forEach(function(instance) {
            instanceLoads.push(instance.load);
        }, this);

        return average(instanceLoads);
        */

        // Just use the most recently reported system load
        return this.systemLoad;
    };

    this.storeLoads = function() {
        var time = new Date;

        var data = {}
        data["imgcloud-systemload-0-"+this.timestamp(time)] = this.calculateSystemLoad();
        this.instances.forEach(function(instance) {
            data["imgcloud-instanceload-"+instance.id+"-"+self.timestamp(time)] = instance.load;
        });

        this.db.mset(data);
    }

    // Provision (allocate or deallocate) resources based on the system load
    this.provision = function() {
//        var systemLoad = 20 * Math.random();
        var systemLoad = this.calculateSystemLoad();
        var numInstances = this.instances.length;

        console.log("System load: %s, thresholds are %s and %s", systemLoad, config.DEALLOCATION_THRESHOLD, config.ALLOCATION_THRESHOLD);

        if (systemLoad > config.ALLOCATION_THRESHOLD) {
            console.log("provision: allocate");

            if(numInstances < config.MAX_INSTANCES) {
                this.allocateInstance().done(); // Throw any exceptions
            } else {
                console.log("provision: did not allocate due to MAX_INSTANCES");
            }
        } else if (systemLoad < config.DEALLOCATION_THRESHOLD) {
            console.log("provision: deallocate");

            // Enforce lower bound on the number of instances
            if(numInstances > config.MIN_INSTANCES) {
                var runningInstances = this.getRunningInstances();
                if (runningInstances.length > 0) {
                    // Randomly kill some instance
                    var victim = runningInstances[0];
                    this.removeInstance(victim);
                    this.deallocateInstance(victim);
                }
            } else {
                console.log("provision: did not deallocate due to MIN_INSTANCES");
            }
        } else {
            console.log("provision: all is well");
        }
    };

    this.startProvisioning = function(freq) {
        freq = freq || config.PROVISION_FREQUENCY;

        // Check the load at regular intervals, and provision accordingly
        setInterval(this.provision.bind(this), freq);
    };

    // Bootstrap the resource manager, with an optional set of initial instances
    this.bootstrap = function(initialInstances) {
        initialInstances = initialInstances || [];

        this.instances = [];
        initialInstances.forEach(function(instInfo) {
            var inst = new Instance(instInfo.id, instInfo.host, instInfo.port);
            this.addInstance(inst);

            // Make sure our availableId is higher
            this.availableId = Math.max(this.availableId, instInfo.id + 1);
        }, this);

        // Fetch existing list from DigitalOcean
        this.digitalOcean.instances()
            .then(function(instances) {
                instances.forEach(function(instance) {
                    console.log("Re-adding existing instance: " + instance);
                    this.addInstance(instance);
                }.bind(this));
            }.bind(this))
            .then(function() {
                // If we still haven't reached it, allocate at least our minimum
                _.forEach(_.range(config.MIN_INSTANCES - this.instances.length), function() {
                    this.allocateInstance().done();
                }, this);
            }.bind(this));

        console.log("Initialized RM (with %d bootstrap instances)", this.instances.length);
    };

    this.destroyAll = function() {
        this.instances.forEach(function(instance) {
            this.markInstanceDead(instance);
        }, this);
    };

    this.saveRequestStats = function(instanceId, res) {
        var curTime = new Date;
        var keyBit = instanceId + "-"+this.timestamp(curTime);

        var values = {}

        // Store the LB and app response times
        values["imgcloud-response-" + keyBit] = +curTime - parseInt(res.getHeader('x-imgcloud-start-lb'), 10)

        // Store the instance load
        if(res.getHeader('x-imgcloud-osload')) {
            values["imgcloud-osload-" + keyBit] = res.getHeader('x-imgcloud-osload').split(",")[0];
        } else {
            console.log("saveRequestStats ERROR: no osload provided");
        }

        this.db.mset(values);
    };

    // Emit an event
    this.emit = function(eventName, req, res) {
        var instanceId = req.headers['x-imgcloud-host'];
        var instance = this.getInstance(instanceId);

        // Poller beat us to it?
        if (!instance) {
            return;
        }

        switch (eventName) {
            case "serverFailure":
                console.log("ServerFailure for " + instanceId);
                this.markInstanceDead(instance);
                break;

            case "requestEnd":
                if (req.url == "/images/upload") {
                    this.saveRequestStats(instanceId, res);
                }
                break;
        }
    };

    // Notify the resource manager of a newly calculated system load
    this.notifySystemLoad = function(systemLoad) {
        this.systemLoad = systemLoad;
    };
};
<|endoftext|>