<commit_before>// Revision view for single business process

'use strict';

var renderDocumentsAndData = require('./_business-process-documents-and-data')
, renderMainInfo = require('./_business-process-main-info')
, _       = require('mano').i18n.bind('Official: Revision');

exports._parent = require('./user-base');
exports._match = 'businessProcess';

exports['sub-main'] = {
	class: { content: true, 'user-forms': true },
	content: function () {
		var revisionStep = this.processingStep;

		renderMainInfo(this.businessProcess);

		section(dialog({ id: 'reject-reason', class: 'dialog-reject dialog-modal' },
			header(
				label({ for: 'revision-reject-reason' }, h3(_("Reason for rejection of the file")))
			),
			section({ class: 'dialog-body' },
				form({ method: 'post', action: '/revision/' + this.businessProcess.__id__ + '/reject/' },
					p({ class: 'input' }, input({ id: 'revision-reject-reason',
							dbjs: this.processingStep._rejectionReason })),
					p(input({ type: 'submit', value: _("Reject") })))),
			footer(p(a({ href: '' }, _("Cancel"))))));

		insert(_if(revisionStep._isPending, section({ class: 'official-submission-toolbar' },
			// show buttons only if step is pending

			_if(eq(revisionStep._revisionProgress, 1),
				// show "approve" or "sent back" buttons only, when revision was finalized
				_if(eq(revisionStep._approvalProgress, 1),
					postButton(
						{ action: url('revision', this.businessProcess.__id__, 'approve'),
							buttonClass: 'button-main button-main-success',
							'data-hint': _("Enables the processing of the application."),
							class: 'hint-optional hint-optional-bottom',
							value: _("Validate revision") }
					),
					postButton(
						{ action: url('revision', this.businessProcess.__id__, 'return'),
							buttonClass: 'button-main',
							class: 'hint-optional hint-optional-bottom',
							'data-hint': _("You can reject the registration when documents and/or " +
								"data that is sent can be determined as not real."),
							value: _("Return for corrections") }
					))),
					// show reject button at all times when revision is pending
			a({ href: '#reject-reason',
				class: 'button-main button-main-error hint-optional' +
				' hint-optional-right hint-optional-multiline',
				'data-hint': _("When returning the application for corrections, the user will receive" +
					" a notification with information on the changes that must be done in his form or" +
					" in the documents that your request.") },
				_("Reject application"))
			)));

		renderDocumentsAndData(this.businessProcess,
			{ urlPrefix: '/' + this.businessProcess.__id__ + '/' });
	}
};
<commit_msg>REfactored revision rejection modal display. #758<commit_after>// Revision view for single business process

'use strict';

var renderDocumentsAndData = require('./_business-process-documents-and-data')
, renderMainInfo = require('./_business-process-main-info')
, _       = require('mano').i18n.bind('Official: Revision');

exports._parent = require('./user-base');
exports._match = 'businessProcess';

exports['sub-main'] = {
	class: { content: true, 'user-forms': true },
	content: function () {
		var revisionStep = this.processingStep;

		renderMainInfo(this.businessProcess);

		insert(_if(revisionStep._isPending, section({ class: 'official-submission-toolbar' },
			// show buttons only if step is pending
			_if(eq(revisionStep._revisionProgress, 1),
				// show "approve" or "sent back" buttons only, when revision was finalized
				_if(eq(revisionStep._approvalProgress, 1),
					postButton(
						{ action: url('revision', this.businessProcess.__id__, 'approve'),
							buttonClass: 'button-main button-main-success',
							'data-hint': _("Enables the processing of the application."),
							class: 'hint-optional hint-optional-bottom',
							value: _("Validate revision") }
					),
					postButton(
						{ action: url('revision', this.businessProcess.__id__, 'return'),
							buttonClass: 'button-main',
							class: 'hint-optional hint-optional-bottom',
							'data-hint': _("You can reject the registration when documents and/or " +
								"data that is sent can be determined as not real."),
							value: _("Return for corrections") }
					))),
					// show reject button at all times when revision is pending
			dialog({ id: 'reject-reason', class: 'dialog-reject dialog-modal' },
				header(
					label({ for: 'revision-reject-reason' }, h3(_("Reason for rejection of the file")))
				),
				section({ class: 'dialog-body' },
					form({ method: 'post', action: '/revision/' + this.businessProcess.__id__ + '/reject/' },
						p({ class: 'input' }, input({ id: 'revision-reject-reason',
								dbjs: this.processingStep._rejectionReason })),
						p(input({ type: 'submit', value: _("Reject") })))),
				footer(p(a({ href: '' }, _("Cancel"))))),
			a({ href: '#reject-reason',
				class: 'button-main button-main-error hint-optional' +
				' hint-optional-right hint-optional-multiline',
				'data-hint': _("When returning the application for corrections, the user will receive" +
					" a notification with information on the changes that must be done in his form or" +
					" in the documents that your request.") },
				_("Reject application"))
			)));

		renderDocumentsAndData(this.businessProcess,
			{ urlPrefix: '/' + this.businessProcess.__id__ + '/' });
	}
};
<|endoftext|>


<commit_before>import { useMemo } from 'react'
import PropTypes from 'prop-types'

import { getBy, getFirstDefined, setBy } from '../utils'
import { addActions, actions } from '../actions'
import { defaultState } from './useTableState'

defaultState.expanded = {}

addActions({
  toggleExpanded: '__toggleExpanded__',
  useExpanded: '__useExpanded__',
})

const propTypes = {
  expandedKey: PropTypes.string,
  paginateSubRows: PropTypes.bool,
}

export const useExpanded = props => {
  PropTypes.checkPropTypes(propTypes, props, 'property', 'useExpanded')

  const {
    debug,
    rows,
    expandedKey = 'expanded',
    hooks,
    state: [{ expanded }, setState],
    paginateSubRows = true,
  } = props

  const toggleExpandedByPath = (path, set) => {
    return setState(old => {
      const { expanded } = old
      const existing = getBy(expanded, path)
      set = getFirstDefined(set, !existing)
      return {
        ...old,
        expanded: setBy(expanded, path, set),
      }
    }, actions.toggleExpanded)
  }

  hooks.row.push(row => {
    const { path } = row
    row.toggleExpanded = set => toggleExpandedByPath(path, set)
  })

  const expandedRows = useMemo(() => {
    if (debug) console.info('getExpandedRows')

    const expandedRows = []

    // Here we do some mutation, but it's the last stage in the
    // immutable process so this is safe
    const handleRow = (row, index, depth = 0, parentPath = []) => {
      // Compute some final state for the row
      const path = [...parentPath, index]

      row.path = path
      row.depth = depth

      row.isExpanded =
        (row.original && row.original[expandedKey]) || getBy(expanded, path)

      if (paginateSubRows || (!paginateSubRows && row.depth === 0)) {
        expandedRows.push(row)
      }

      if (row.isExpanded && row.subRows && row.subRows.length) {
        row.subRows.forEach((row, i) => handleRow(row, i, depth + 1, path))
      }

      return row
    }

    rows.forEach((row, i) => handleRow(row, i))

    return expandedRows
  }, [debug, rows, expandedKey, expanded, paginateSubRows])

  const expandedDepth = findExpandedDepth(expanded)

  return {
    ...props,
    toggleExpandedByPath,
    expandedDepth,
    rows: expandedRows,
  }
}

function findExpandedDepth(obj, depth = 1) {
  return Object.values(obj).reduce((prev, curr) => {
    if (typeof curr === 'object') {
      return Math.max(prev, findExpandedDepth(curr, depth + 1))
    }
    return depth
  }, 0)
}
<commit_msg>returned row inside row hook subscription (#1393)<commit_after>import { useMemo } from 'react'
import PropTypes from 'prop-types'

import { getBy, getFirstDefined, setBy } from '../utils'
import { addActions, actions } from '../actions'
import { defaultState } from './useTableState'

defaultState.expanded = {}

addActions({
  toggleExpanded: '__toggleExpanded__',
  useExpanded: '__useExpanded__',
})

const propTypes = {
  expandedKey: PropTypes.string,
  paginateSubRows: PropTypes.bool,
}

export const useExpanded = props => {
  PropTypes.checkPropTypes(propTypes, props, 'property', 'useExpanded')

  const {
    debug,
    rows,
    expandedKey = 'expanded',
    hooks,
    state: [{ expanded }, setState],
    paginateSubRows = true,
  } = props

  const toggleExpandedByPath = (path, set) => {
    return setState(old => {
      const { expanded } = old
      const existing = getBy(expanded, path)
      set = getFirstDefined(set, !existing)
      return {
        ...old,
        expanded: setBy(expanded, path, set),
      }
    }, actions.toggleExpanded)
  }

  hooks.row.push(row => {
    const { path } = row
    row.toggleExpanded = set => toggleExpandedByPath(path, set)
    return row;
  })

  const expandedRows = useMemo(() => {
    if (debug) console.info('getExpandedRows')

    const expandedRows = []

    // Here we do some mutation, but it's the last stage in the
    // immutable process so this is safe
    const handleRow = (row, index, depth = 0, parentPath = []) => {
      // Compute some final state for the row
      const path = [...parentPath, index]

      row.path = path
      row.depth = depth

      row.isExpanded =
        (row.original && row.original[expandedKey]) || getBy(expanded, path)

      if (paginateSubRows || (!paginateSubRows && row.depth === 0)) {
        expandedRows.push(row)
      }

      if (row.isExpanded && row.subRows && row.subRows.length) {
        row.subRows.forEach((row, i) => handleRow(row, i, depth + 1, path))
      }

      return row
    }

    rows.forEach((row, i) => handleRow(row, i))

    return expandedRows
  }, [debug, rows, expandedKey, expanded, paginateSubRows])

  const expandedDepth = findExpandedDepth(expanded)

  return {
    ...props,
    toggleExpandedByPath,
    expandedDepth,
    rows: expandedRows,
  }
}

function findExpandedDepth(obj, depth = 1) {
  return Object.values(obj).reduce((prev, curr) => {
    if (typeof curr === 'object') {
      return Math.max(prev, findExpandedDepth(curr, depth + 1))
    }
    return depth
  }, 0)
}
<|endoftext|>


<commit_before>/****************************************
 *     PENN STATE DIRECTORY API         *
 ****************************************/
(function() {

    var express = require('express');
    var app = express();
    var request = require('request');
    var querystring = require('querystring');
    var cheerio = require('cheerio');

    /**
     * psd-api namespace
     *
     */
    var getStudent = function(options) {
        var pub = {};
        var priv = {};

        priv.Student = {},
        priv.form = {},
        priv.desc = [],
        priv.data = [];

        /* Search configuration */
        priv.config = {
            year: "" // student year --> undergraduate
        };

        /* Selectors used for searching HTML */
        priv.selectors = {
            matches: "b", // the number of matches for each student
            desc: "th", // the descriptions of the student such as name, email, etc
            data: "td" // the data for the descriptions
        };

        /* Generates new query object for the form */
        priv.newQuery = function(firstName, lastName, userId, email) {
            return {
                'cn': firstName,
                'sn': lastName,
                'uid': userId, // name=uid in search page instead of id=userid
                'mail': email // name=mail in search page instead of id=email
            };
        };

        /* Validation object that contains the different validation methods */
        priv.validate = {
            /* Validates the passed in parameter options */
            options: function(str) {
                return /^[a-zA-Z]+$/.test(str);
            },

            /* Checks if passed in parameter is an email */
            email: function(str) {
                return str.endsWith("@psu.edu");
            },

            /* Checks if passed in parameter contains a number, which means it is an id */
            /* This validation happens AFTER checking if the string is an email */
            userId: function(str) {
                var isNumber, userId = str.match(/\d+/g);
                if (userId != null) {
                    isNumber = true;
                }
                else {
                    isNumber = false;
                }
                return isNumber;
            },

            /* Determines if the option parameter is an object */
            isobjectValid: function() {
                if (typeof options === "object") {
                    /* Checks every value in the options object and Incase the string contains non-alphabet characters */
                    for (var optKey in options) {
                        if ((typeof options[optKey] != "string") || (priv.validate.options(options[optKey]) === false)) {
                            throw new Error("Invalid Object format!");
                        }
                    }
                    return true;
                }
            }
        };

        /* Fills the student info object  */
        priv.fillStudentObj = function(firstName, lastName, userId, email) {
            priv.Student.firstName = firstName;
            priv.Student.lastName = lastName;
            priv.Student.userId = userId;
            priv.Student.email = email;
        };

        /* Initializes the Student object depending on the passed in string */
        priv.initStrStudent = function() {
            /* Checks if passed in parameter is an email */
            if (priv.validate.email(options)) {
                priv.fillStudentObj("", "", "", options);
            }

            /* Checks if passed in parameter is an id */
            else if (priv.validate.userId(options)) {
                priv.fillStudentObj("", "", options, "");
            }

            /* Passed in parameter is not an object, email, or id, so it must be a name */
            else {
                var input = options.split(" ");
                if (input.length === 2) {
                    priv.fillStudentObj(input[0], input[1]);
                }
                else {
                    priv.fillStudentObj(input[0], "", "", "");
                }
            }
        }

        /* Initializes the students information passed in as options */
        priv.initStudent = function() {
            /* Object is valid */
            if (priv.validate.isobjectValid()) {
                Object.assign(priv.Student, options);
            }

            /* Checks if the passed in parameter is a string */
            else if (typeof options === "string") {
                priv.initStrStudent();
            }
        }();

        /* Form object that will contain the form data that will be sent in the post request */
        priv.form.data = priv.newQuery(priv.Student.firstName, priv.Student.lastName, priv.Student.userId, priv.Student.email);
        priv.form.stringFormData = querystring.stringify(priv.form.data); /* Contains the stringified data */
        priv.form.contentLength = priv.form.stringFormData.length; /* Contains the size of the data that is sent over */
        priv.form.dirLink = 'http://www.work.psu.edu/cgi-bin/ldap/ldap_query.cgi';  /* Penn State Directory link for scraping */

        /* Request options that contain the appropriate request headers, url, body, and method for sending the post request */
        priv.form.reqOptions = {
            headers: {
                'Content-Length': priv.form.contentLength,
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            url: priv.form.dirLink,
            body: priv.form.stringFormData,
            method: 'POST'
        };

        /* Removes all line breaks in the data retrieved */
        priv.removeLinBr = function(arr) {
            for (var str in arr) {
                arr[str] = arr[str].replace(/\n+/g, '');
            }
        };

        /* Finds if there is a match */
        priv.isStudentFound = function($) {
            if ($(priv.selectors.matches).text().indexOf("0 matches", 0) == 0) {
                return false;
            }
            else {
                return true;
            }
        };

        /* Queries the student page for the table headers and table data */
        priv.queryPage = function($) {
            $(priv.selectors.desc).each(function() {
                priv.desc.push($(this).text());
            });

            $(priv.selectors.data).each(function() {
                priv.data.push($(this).text());
            });

            priv.desc.shift();
            priv.removeLinBr(priv.desc);
            priv.removeLinBr(priv.data);
            // console.log(priv.desc);
            console.log(priv.data);
        };

        /* Finds the students info on the given html page */
        priv.findStudent = function(htmlPage) {
            /* Library used to parse html  */
            var $ = cheerio.load(htmlPage);

            /* Checks if the student is found */
            if (priv.isStudentFound($)) {
                priv.queryPage($);
            }
            else {
                console.error("Student was not found!");
            }
        };

        /* Scrapes the students html page that is received from the server */
        priv.scrape = function(htmlPage) {
            priv.findStudent(htmlPage);
        };

        /* Callback that executes after the student information is returned */
        var callback = function(err, res, html) {
            if (err) throw new Error('Error in retrieving student informaton');
            priv.scrape(res.body);
        };

        /* Sends the request */
        request(priv.form.reqOptions, callback);
    };

    /* Allows you to pass in array of students for searching */
    var psd = function(input) {
        if (Array.isArray(input)) {
            for (var student in input) {
                console.log(input[student]);
                getStudent(input[student]);
            }
        }
        else {
            getStudent(input);
        }
    };

    /* Starts the psd-api */
    // psd([{
    //     firstName: "Hozaifa",
    //     lastName: "Abdalla"
    // }, {
    //     firstName: "Yehya",
    //     lastName: "Awad"
    // }, {
    //     firstName: "Kenneth",
    //     lastName: "Schnall"
    // }]);

    // psd("Nicholas Cecchetti");

    psd("Hozaifa Abdalla");

    app.listen(process.env.PORT, process.env.IP);
}).call(this);

/* OUTPUT BELOW!

{ firstName: 'Hozaifa', lastName: 'Abdalla' }
{ firstName: 'Yehya', lastName: 'Awad' }
{ firstName: 'Kenneth', lastName: 'Schnall' }
[ 'MANAN VIBHU PATEL',
  'mvp5542@psu.edu',
  'mvp5542@psu.edu',
  '2130 GLENDALE AVEERIE, PA 16510',
  '+1 412 801 1514',
  'UNDERGRAD STUDENT',
  'PENN STATE ERIE, THE BEHREND COLLEGE',
  'COMPUTER SCIENCE',
  'MANAN PATEL',
  'MANAN JIGNESHKUMAR PATEL' ]
[ 'KENNETH ALEXANDER SCHNALL',
  'kas6570@psu.edu',
  'kenneth.schnall@psu.edukensch@psu.edukas6570@psu.edu',
  ' https://kensch.com',
  'UNDERGRAD STUDENT',
  'PENN STATE ERIE, THE BEHREND COLLEGE',
  'ENGINEERING' ]
[ 'YEHYA HOSSAM SAID ABDALLA AWAD',
  'yha5009@psu.edu',
  'HackPSU@psu.eduyehya@psu.eduawad@psu.eduyha5009@psu.edu',
  ' http://www.personal.psu.edu/yha5009',
  '+1 717 460 6012',
  'UNDERGRAD STUDENT',
  'PENN STATE ERIE, THE BEHREND COLLEGE',
  'SOFTWARE ENGINEERING' ]
[ 'HOZAIFA ELHAFIZ ABDALLA',
  'hea113@psu.edu',
  'hea113@psu.edu',
  'UNDERGRAD STUDENT',
  'PENN STATE ERIE, THE BEHREND COLLEGE',
  'SOFTWARE ENGINEERING' ]
[ 'KENNETH ALEXANDER SCHNALL',
  'kas6570@psu.edu',
  'kenneth.schnall@psu.edukensch@psu.edukas6570@psu.edu',
  ' https://kensch.com',
  'UNDERGRAD STUDENT',
  'PENN STATE ERIE, THE BEHREND COLLEGE',
  'ENGINEERING' ]
[ 'KENNETH ALEXANDER SCHNALL',
  'kas6570@psu.edu',
  'kenneth.schnall@psu.edukensch@psu.edukas6570@psu.edu',
  ' https://kensch.com',
  'UNDERGRAD STUDENT',
  'PENN STATE ERIE, THE BEHREND COLLEGE',
  'ENGINEERING' ]

*/<commit_msg>Implement sample test cases<commit_after>/****************************************
 *     PENN STATE DIRECTORY API         *
 ****************************************/
(function() {

    var express = require('express');
    var app = express();
    var request = require('request');
    var querystring = require('querystring');
    var cheerio = require('cheerio');

    /**
     * psd-api namespace
     *
     */
    var getStudent = function(options) {
        var pub = {};
        var priv = {};

        priv.Student = {},
            priv.form = {},
            priv.desc = [],
            priv.data = [];

        /* Search configuration */
        priv.config = {
            year: "" // student year --> undergraduate
        };

        /* Selectors used for searching HTML */
        priv.selectors = {
            matches: "b", // the number of matches for each student
            desc: "th", // the descriptions of the student such as name, email, etc
            data: "td" // the data for the descriptions
        };

        /* Generates new query object for the form */
        priv.newQuery = function(firstName, lastName, userID, email) {
            return {
                'cn': firstName,
                'sn': lastName,
                'uid': userID, // name=uid in search page instead of id=userID
                'mail': email // name=mail in search page instead of id=email
            };
        };

        /* Validation object that contains the different validation methods */
        priv.validate = {
            /* Validates the passed in parameter options */
            options: function(str) {
                return /^[a-zA-Z]+$/.test(str);
            },

            /* Checks if passed in parameter is an email */
            email: function(str) {
                return str.endsWith("@psu.edu");
            },

            /* Checks if passed in parameter contains a number, which means it is an id */
            /* This validation happens AFTER checking if the string is an email */
            userID: function(str) {
                var isNumber, userID = str.match(/\d+/g);
                if (userID != null) {
                    isNumber = true;
                }
                else {
                    isNumber = false;
                }
                return isNumber;
            },

            /* Validates the userID so that the format can either be xxxDDD or xxxDDDD, x-> letter D-> digit */

            /* Determines if the option parameter is an object */
            isobjectValid: function() {
                if (typeof options === "object") {
                    /* Checks every value in the options object and Incase the string contains non-alphabet characters */
                    for (var optKey in options) {
                        /* Validates first and last name */
                        if (optKey === "firstName" || optKey === "lastName") {
                            if ((typeof options[optKey] != "string")) {
                                throw new Error("Invalid Object format!");
                            }
                        }

                        /* Validates the user id */
                        else if (optKey === "userID") {

                        }

                        /* Validates the email */
                        else if (optKey === "email") {
                            if ((priv.validate.email(options[optKey]) === false)) {
                                throw new Error("Invalid Object format!");
                            }
                        }
                        else {
                            throw new Error("Invalid Object format!");
                        }
                    }
                    return true;
                }
            }
        };

        /* Fills the student info object  */
        priv.fillStudentObj = function(firstName, lastName, userID, email) {
            priv.Student.firstName = firstName;
            priv.Student.lastName = lastName;
            priv.Student.userID = userID;
            priv.Student.email = email;
        };

        /* Initializes the Student object depending on the passed in string */
        priv.initStrStudent = function() {
            /* Checks if passed in parameter is an email */
            if (priv.validate.email(options)) {
                priv.fillStudentObj("", "", "", options);
            }

            /* Checks if passed in parameter is an id */
            else if (priv.validate.userID(options)) {
                priv.fillStudentObj("", "", options, "");
            }

            /* Passed in parameter is not an object, email, or id, so it must be a name */
            else {
                var input = options.split(" ");
                if (input.length === 2) {
                    priv.fillStudentObj(input[0], input[1]);
                }
                else {
                    priv.fillStudentObj(input[0], "", "", "");
                }
            }
        }

        /* Initializes the students information passed in as options */
        priv.initStudent = function() {
            /* Object is valid */
            if (priv.validate.isobjectValid()) {
                Object.assign(priv.Student, options);
            }

            /* Checks if the passed in parameter is a string */
            else if (typeof options === "string") {
                priv.initStrStudent();
            }
        }();

        /* Form object that will contain the form data that will be sent in the post request */
        priv.form.data = priv.newQuery(priv.Student.firstName, priv.Student.lastName, priv.Student.userID, priv.Student.email);
        priv.form.stringFormData = querystring.stringify(priv.form.data); /* Contains the stringified data */
        priv.form.contentLength = priv.form.stringFormData.length; /* Contains the size of the data that is sent over */
        priv.form.dirLink = 'http://www.work.psu.edu/cgi-bin/ldap/ldap_query.cgi'; /* Penn State Directory link for scraping */

        /* Request options that contain the appropriate request headers, url, body, and method for sending the post request */
        priv.form.reqOptions = {
            headers: {
                'Content-Length': priv.form.contentLength,
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            url: priv.form.dirLink,
            body: priv.form.stringFormData,
            method: 'POST'
        };

        /* Removes all line breaks in the data retrieved */
        priv.removeLinBr = function(arr) {
            for (var str in arr) {
                arr[str] = arr[str].replace(/\n+/g, '');
            }
        };

        /* Finds if there is a match */
        priv.isStudentFound = function($) {
            if ($(priv.selectors.matches).text().indexOf("0 matches", 0) == 0) {
                return false;
            }
            else {
                return true;
            }
        };

        /* Queries the student page for the table headers and table data */
        priv.queryPage = function($) {
            $(priv.selectors.desc).each(function() {
                priv.desc.push($(this).text());
            });

            $(priv.selectors.data).each(function() {
                priv.data.push($(this).text());
            });

            priv.desc.shift();
            priv.removeLinBr(priv.desc);
            priv.removeLinBr(priv.data);
            // console.log(priv.desc);
            console.log(priv.data);
        };

        /* Finds the students info on the given html page */
        priv.findStudent = function(htmlPage) {
            /* Library used to parse html  */
            var $ = cheerio.load(htmlPage);

            /* Checks if the student is found */
            if (priv.isStudentFound($)) {
                priv.queryPage($);
            }
            else {
                console.error("Student was not found!");
            }
        };

        /* Scrapes the students html page that is received from the server */
        priv.scrape = function(htmlPage) {
            priv.findStudent(htmlPage);
        };

        /* Callback that executes after the student information is returned */
        var callback = function(err, res, html) {
            if (err) throw new Error('Error in retrieving student informaton');
            priv.scrape(res.body);
        };

        /* Sends the request */
        request(priv.form.reqOptions, callback);
    };

    /* Allows you to pass in array of students for searching */
    var psd = function(input) {
        if (Array.isArray(input)) {
            for (var student in input) {
                console.log(input[student]);
                getStudent(input[student]);
            }
        }
        else {
            getStudent(input);
        }
    };

    /* Starts the psd-api below */

    /* SAMPLE OBJECT TESTCASES */
    psd({firstName: "Hozaifa"}); /* PASSED */
    // psd({lastName: "Abdalla"}); /* PASSED */
    // psd({email: "hea113"}); /* PASSED */
    // psd({userID: "hea113"}); /* PASSED */
    // psd({firstName: "Hozaifa", lastName: ""}); /* PASSED */
    // psd({firstName: "", lastName: "Abdalla"}); /* PASSED */
    // psd({firstName: "Hozaifa", lastName: "Abdalla"}); /* PASSED */
    // psd({firstName: "Hozaifa", lastName: "Abdalla" , userID: "hea113"}); /* PASSED */
    // psd({firstName: "Hozaifa", lastName: "Abdalla" , userID: ""}); /* PASSED */
    // psd({firstName: "Hozaifa", lastName: "Abdalla" , userID: "hea113", email: "hea113@psu.edu"}); /* PASSED */
    // psd({firstName: "Hozaifa", lastName: "Abdalla" , userID: "", email: "hea113@psu.edu"}); /* PASSED */

    app.listen(process.env.PORT, process.env.IP);
}).call(this);
<|endoftext|>


<commit_before>/**
 * @file Entry-point of the server that just delivers the web content for now
 */

/**
 * The server application
 *
 * @module server
 */

const fs          = require('fs');
const express     = require('express');
const transformJs = require('connect-static-transform');

const config = require('./get-config')();
const app    = express();

/* Inserts config into the front-end application */
var cachedJsMtime;
var cachedJsPromise;
const insertConfigIntoFrontendApp = mtime => {
    if (cachedJsMtime !== mtime) {
        cachedJsMtime   = mtime;
        cachedJsPromise = new Promise((resolve, reject) => (
            fs.readFile('./web/app.js', (error, contents) => {
                if (error) {
                    reject(error);
                } else {
                    resolve(contents.toString().replace(
                        '\'Client configuration insertion point\'',
                        `${JSON.stringify(config.client)}`
                    ))
                }
            })
        ))
    }

    return cachedJsPromise;
};

/* JS bundle request */
app.get('/app.js', (request, response) => (
    fs.stat('./web/app.js', (error, info) => (
        Promise[error ? 'reject' : 'resolve']()
        .then(() => insertConfigIntoFrontendApp(info.mtime))
        .then(js => response.send(js).end)
        .catch(error => response.status(500))
    ))
));

/* Static content service */
app.get('/', express.static('./web'));
app.use(express.static('./web'));

/* Starts the web server */
app.listen(config.server.port, function () {
    console.log(`Webserver started on port ${config.server.port}.`);
});
<commit_msg>Removed unused require()<commit_after>/**
 * @file Entry-point of the server that just delivers the web content for now
 */

/**
 * The server application
 *
 * @module server
 */

const fs      = require('fs');
const express = require('express');

const config = require('./get-config')();
const app    = express();

/* Inserts config into the front-end application */
var cachedJsMtime;
var cachedJsPromise;
const insertConfigIntoFrontendApp = mtime => {
    if (cachedJsMtime !== mtime) {
        cachedJsMtime   = mtime;
        cachedJsPromise = new Promise((resolve, reject) => (
            fs.readFile('./web/app.js', (error, contents) => {
                if (error) {
                    reject(error);
                } else {
                    resolve(contents.toString().replace(
                        '\'Client configuration insertion point\'',
                        `${JSON.stringify(config.client)}`
                    ))
                }
            })
        ))
    }

    return cachedJsPromise;
};

/* JS bundle request */
app.get('/app.js', (request, response) => (
    fs.stat('./web/app.js', (error, info) => (
        Promise[error ? 'reject' : 'resolve']()
        .then(() => insertConfigIntoFrontendApp(info.mtime))
        .then(js => response.send(js).end)
        .catch(error => response.status(500))
    ))
));

/* Static content service */
app.get('/', express.static('./web'));
app.use(express.static('./web'));

/* Starts the web server */
app.listen(config.server.port, function () {
    console.log(`Webserver started on port ${config.server.port}.`);
});
<|endoftext|>


<commit_before>import {
  useReducer,
  useRef,
  useEffect,
  useMemo,
  useLayoutEffect,
  useContext
} from 'react'
import invariant from 'invariant'
import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
import Subscription from '../utils/Subscription'
import { ReactReduxContext } from '../components/Context'

// React currently throws a warning when using useLayoutEffect on the server.
// To get around it, we can conditionally useEffect on the server (no-op) and
// useLayoutEffect in the browser. We need useLayoutEffect to ensure the store
// subscription callback always has the selector from the latest render commit
// available, otherwise a store update may happen between render and the effect,
// which may cause missed updates; we also must ensure the store subscription
// is created synchronously, otherwise a store update may occur before the
// subscription is created and an inconsistent state may be observed
const useIsomorphicLayoutEffect =
  typeof window !== 'undefined' ? useLayoutEffect : useEffect

const refEquality = (a, b) => a === b

function useSelectorWithStoreAndSubscription(
  selector,
  equalityFn,
  store,
  contextSub
) {
  const [, forceRender] = useReducer(s => s + 1, 0)

  const subscription = useMemo(() => new Subscription(store, contextSub), [
    store,
    contextSub
  ])

  const latestSubscriptionCallbackError = useRef()
  const latestSelector = useRef()
  const latestSelectedState = useRef()

  let selectedState

  try {
    if (
      selector !== latestSelector.current ||
      latestSubscriptionCallbackError.current
    ) {
      selectedState = selector(store.getState())
    } else {
      selectedState = latestSelectedState.current
    }
  } catch (err) {
    let errorMessage = `An error occured while selecting the store state: ${err.message}.`

    if (latestSubscriptionCallbackError.current) {
      errorMessage += `\nThe error may be correlated with this previous error:\n${latestSubscriptionCallbackError.current.stack}\n\nOriginal stack trace:`
    }

    throw new Error(errorMessage)
  }

  useIsomorphicLayoutEffect(() => {
    latestSelector.current = selector
    latestSelectedState.current = selectedState
    latestSubscriptionCallbackError.current = undefined
  })

  useIsomorphicLayoutEffect(() => {
    function checkForUpdates() {
      try {
        const newSelectedState = latestSelector.current(store.getState())

        if (equalityFn(newSelectedState, latestSelectedState.current)) {
          return
        }

        latestSelectedState.current = newSelectedState
      } catch (err) {
        // we ignore all errors here, since when the component
        // is re-rendered, the selectors are called again, and
        // will throw again, if neither props nor store state
        // changed
        latestSubscriptionCallbackError.current = err
      }

      forceRender({})
    }

    subscription.onStateChange = checkForUpdates
    subscription.trySubscribe()

    checkForUpdates()

    return () => subscription.tryUnsubscribe()
  }, [store, subscription])

  return selectedState
}

/**
 * Hook factory, which creates a `useSelector` hook bound to a given context.
 *
 * @param {Function} [context=ReactReduxContext] Context passed to your `<Provider>`.
 * @returns {Function} A `useSelector` hook bound to the specified context.
 */
export function createSelectorHook(context = ReactReduxContext) {
  const useReduxContext =
    context === ReactReduxContext
      ? useDefaultReduxContext
      : () => useContext(context)
  return function useSelector(selector, equalityFn = refEquality) {
    invariant(selector, `You must pass a selector to useSelectors`)

    const { store, subscription: contextSub } = useReduxContext()

    return useSelectorWithStoreAndSubscription(
      selector,
      equalityFn,
      store,
      contextSub
    )
  }
}

/**
 * A hook to access the redux store's state. This hook takes a selector function
 * as an argument. The selector is called with the store state.
 *
 * This hook takes an optional equality comparison function as the second parameter
 * that allows you to customize the way the selected state is compared to determine
 * whether the component needs to be re-rendered.
 *
 * @param {Function} selector the selector function
 * @param {Function=} equalityFn the function that will be used to determine equality
 *
 * @returns {any} the selected state
 *
 * @example
 *
 * import React from 'react'
 * import { useSelector } from 'react-redux'
 *
 * export const CounterComponent = () => {
 *   const counter = useSelector(state => state.counter)
 *   return
{counter}

 * }
 */
export const useSelector = createSelectorHook()
<commit_msg>Use the same condition for checking if SSR in useSelector.js as in connectAdvanced.js (#1419)<commit_after>import {
  useReducer,
  useRef,
  useEffect,
  useMemo,
  useLayoutEffect,
  useContext
} from 'react'
import invariant from 'invariant'
import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
import Subscription from '../utils/Subscription'
import { ReactReduxContext } from '../components/Context'

// React currently throws a warning when using useLayoutEffect on the server.
// To get around it, we can conditionally useEffect on the server (no-op) and
// useLayoutEffect in the browser. We need useLayoutEffect to ensure the store
// subscription callback always has the selector from the latest render commit
// available, otherwise a store update may happen between render and the effect,
// which may cause missed updates; we also must ensure the store subscription
// is created synchronously, otherwise a store update may occur before the
// subscription is created and an inconsistent state may be observed
const useIsomorphicLayoutEffect =
  typeof window !== 'undefined' &&
  typeof window.document !== 'undefined' &&
  typeof window.document.createElement !== 'undefined'
    ? useLayoutEffect
    : useEffect

const refEquality = (a, b) => a === b

function useSelectorWithStoreAndSubscription(
  selector,
  equalityFn,
  store,
  contextSub
) {
  const [, forceRender] = useReducer(s => s + 1, 0)

  const subscription = useMemo(() => new Subscription(store, contextSub), [
    store,
    contextSub
  ])

  const latestSubscriptionCallbackError = useRef()
  const latestSelector = useRef()
  const latestSelectedState = useRef()

  let selectedState

  try {
    if (
      selector !== latestSelector.current ||
      latestSubscriptionCallbackError.current
    ) {
      selectedState = selector(store.getState())
    } else {
      selectedState = latestSelectedState.current
    }
  } catch (err) {
    let errorMessage = `An error occured while selecting the store state: ${err.message}.`

    if (latestSubscriptionCallbackError.current) {
      errorMessage += `\nThe error may be correlated with this previous error:\n${latestSubscriptionCallbackError.current.stack}\n\nOriginal stack trace:`
    }

    throw new Error(errorMessage)
  }

  useIsomorphicLayoutEffect(() => {
    latestSelector.current = selector
    latestSelectedState.current = selectedState
    latestSubscriptionCallbackError.current = undefined
  })

  useIsomorphicLayoutEffect(() => {
    function checkForUpdates() {
      try {
        const newSelectedState = latestSelector.current(store.getState())

        if (equalityFn(newSelectedState, latestSelectedState.current)) {
          return
        }

        latestSelectedState.current = newSelectedState
      } catch (err) {
        // we ignore all errors here, since when the component
        // is re-rendered, the selectors are called again, and
        // will throw again, if neither props nor store state
        // changed
        latestSubscriptionCallbackError.current = err
      }

      forceRender({})
    }

    subscription.onStateChange = checkForUpdates
    subscription.trySubscribe()

    checkForUpdates()

    return () => subscription.tryUnsubscribe()
  }, [store, subscription])

  return selectedState
}

/**
 * Hook factory, which creates a `useSelector` hook bound to a given context.
 *
 * @param {Function} [context=ReactReduxContext] Context passed to your `<Provider>`.
 * @returns {Function} A `useSelector` hook bound to the specified context.
 */
export function createSelectorHook(context = ReactReduxContext) {
  const useReduxContext =
    context === ReactReduxContext
      ? useDefaultReduxContext
      : () => useContext(context)
  return function useSelector(selector, equalityFn = refEquality) {
    invariant(selector, `You must pass a selector to useSelectors`)

    const { store, subscription: contextSub } = useReduxContext()

    return useSelectorWithStoreAndSubscription(
      selector,
      equalityFn,
      store,
      contextSub
    )
  }
}

/**
 * A hook to access the redux store's state. This hook takes a selector function
 * as an argument. The selector is called with the store state.
 *
 * This hook takes an optional equality comparison function as the second parameter
 * that allows you to customize the way the selected state is compared to determine
 * whether the component needs to be re-rendered.
 *
 * @param {Function} selector the selector function
 * @param {Function=} equalityFn the function that will be used to determine equality
 *
 * @returns {any} the selected state
 *
 * @example
 *
 * import React from 'react'
 * import { useSelector } from 'react-redux'
 *
 * export const CounterComponent = () => {
 *   const counter = useSelector(state => state.counter)
 *   return
{counter}

 * }
 */
export const useSelector = createSelectorHook()
<|endoftext|>


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

'use strict';

var Realm = require('realm');
var TestCase = require('./asserts');

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

function createUsersWithTestRealms(count) {
  const createUserWithTestRealm = () => {
    return Realm.Sync.User.register('http://localhost:9080', uuid(), 'password')
      .then(user => {
        new Realm({sync: {user, url: 'realm://localhost:9080/~/test'}}).close();
        return user;
      });
  };

  return Promise.all(Array.from({length: count}, createUserWithTestRealm));
}

function wait(t) {
   return new Promise(resolve => setTimeout(resolve, t));
}

function repeatUntil(fn, predicate) {
    let retries = 0
    function check() {
        if (retries > 3) {
            return Promise.reject(new Error("operation timed out"));
        }
        ++retries;
        return fn().then(x => predicate(x) ? x : wait(100).then(check));
    }
    return check;
}

module.exports = {
    // testApplyAndGetGrantedPermissions() {
    //   return createUsersWithTestRealms(1)
    //     .then(([user]) => {
    //       return user.applyPermissions({ userId: '*' }, `/${user.identity}/test`, 'read')
    //         .then(repeatUntil(() => user.getGrantedPermissions('any'),
    //                           permissions => permissions.length > 1))
    //         .then(permissions => {
    //           TestCase.assertEqual(permissions[1].path, `/${user.identity}/test`);
    //           TestCase.assertEqual(permissions[1].mayRead, true);
    //           TestCase.assertEqual(permissions[1].mayWrite, false);
    //           TestCase.assertEqual(permissions[1].mayManage, false);
    //         });
    //     });
    // },

    testOfferPermissions() {
      return createUsersWithTestRealms(2)
        .then(([user1, user2]) => {
          return user1.offerPermissions(`/${user1.identity}/test`, 'read')
            .then(token => user2.acceptPermissionOffer(token))
            .then(realmUrl => {
              TestCase.assertEqual(realmUrl, `/${user1.identity}/test`);
              return realmUrl;
            })
            .then(repeatUntil(() => user2.getGrantedPermissions('any'),
                              permissions => permissions.length > 1))
            .then(permissions => {
              TestCase.assertEqual(permissions[1].path, `/${user1.identity}/test`);
              TestCase.assertEqual(permissions[1].mayRead, true);
              TestCase.assertEqual(permissions[1].mayWrite, false);
              TestCase.assertEqual(permissions[1].mayManage, false);
            });
        });
    },

    testInvalidatePermissionOffer() {
      let user1, user2, token;
      return createUsersWithTestRealms(2)
        .then(users => {
            user1 = users[0];
            user2 = users[1];
            return user1.offerPermissions(`/${user1.identity}/test`, 'read');
        })
        .then(t => { token = t; return user1.invalidatePermissionOffer(token); })
        // Since we don't yet support notification when the invalidation has gone through,
        // wait for a bit and hope the server is done processing.
        .then(wait(100))
        .then(() => user2.acceptPermissionOffer(token))
        // We want the call to fail, i.e. the catch() below should be called.
        .then(() => { throw new Error("User was able to accept an invalid permission offer token"); })
        .catch(error => {
          try {
            TestCase.assertEqual(error.message, 'The permission offer is expired.');
            TestCase.assertEqual(error.statusCode, 701);
          }
          catch (e) {
            throw new Error(e);
          }
        });
    },
}

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

'use strict';

var Realm = require('realm');
var TestCase = require('./asserts');

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

function createUsersWithTestRealms(count) {
  const createUserWithTestRealm = () => {
    return Realm.Sync.User.register('http://localhost:9080', uuid(), 'password')
      .then(user => {
        new Realm({sync: {user, url: 'realm://localhost:9080/~/test'}}).close();
        return user;
      });
  };

  return Promise.all(Array.from({length: count}, createUserWithTestRealm));
}

function wait(t) {
   return new Promise(resolve => setTimeout(resolve, t));
}

function repeatUntil(fn, predicate) {
    let retries = 0
    function check() {
        if (retries > 3) {
            return Promise.reject(new Error("operation timed out"));
        }
        ++retries;
        return fn().then(x => predicate(x) ? x : wait(100).then(check));
    }
    return check;
}

module.exports = {
    testApplyAndGetGrantedPermissions() {
      return createUsersWithTestRealms(1)
        .then(([user]) => {
          return user.applyPermissions({ userId: `${user.identity}` }, `/${user.identity}/test`, 'read')
            .then(repeatUntil(() => user.getGrantedPermissions('any'),
                              permissions => permissions.length > 1))
            .then(permissions => {
              TestCase.assertEqual(permissions[0].path, `/${user.identity}/test`);
              TestCase.assertEqual(permissions[0].mayRead, true);
              TestCase.assertEqual(permissions[0].mayWrite, false);
              TestCase.assertEqual(permissions[0].mayManage, false);
            });
        });
    },

    testOfferPermissions() {
      return createUsersWithTestRealms(2)
        .then(([user1, user2]) => {
          return user1.offerPermissions(`/${user1.identity}/test`, 'read')
            .then(token => user2.acceptPermissionOffer(token))
            .then(realmUrl => {
              TestCase.assertEqual(realmUrl, `/${user1.identity}/test`);
              return realmUrl;
            })
            .then(repeatUntil(() => user2.getGrantedPermissions('any'),
                              permissions => permissions.length > 1))
            .then(permissions => {
              TestCase.assertEqual(permissions[2].path, `/${user1.identity}/test`);
              TestCase.assertEqual(permissions[2].mayRead, true);
              TestCase.assertEqual(permissions[2].mayWrite, false);
              TestCase.assertEqual(permissions[2].mayManage, false);
            });
        });
    },

    testInvalidatePermissionOffer() {
      let user1, user2, token;
      return createUsersWithTestRealms(2)
        .then(users => {
            user1 = users[0];
            user2 = users[1];
            return user1.offerPermissions(`/${user1.identity}/test`, 'read');
        })
        .then(t => { token = t; return user1.invalidatePermissionOffer(token); })
        // Since we don't yet support notification when the invalidation has gone through,
        // wait for a bit and hope the server is done processing.
        .then(wait(100))
        .then(() => user2.acceptPermissionOffer(token))
        // We want the call to fail, i.e. the catch() below should be called.
        .then(() => { throw new Error("User was able to accept an invalid permission offer token"); })
        .catch(error => {
          try {
            TestCase.assertEqual(error.message, 'The permission offer is expired.');
            TestCase.assertEqual(error.statusCode, 701);
          }
          catch (e) {
            throw new Error(e);
          }
        });
    },
}

<|endoftext|>


<commit_before>var yify = "http://crossorigin.me/http://yify.is/index.php/api/v2/list_movies.json"
angular.module('myAppServices', ['ngResource']).

    factory('BreakinBadChar', function($resource){

  return $resource(yify, {}, {

    query: {method:'GET', isArray: true}

  });

});
<commit_msg>Update services.js<commit_after>var yify = "http://crossorigin.me/http://yify.is/index.php/api/v2/list_movies.json";
angular.module('myAppServices', ['ngResource']);

    factory('BreakinBadChar', function($resource){

  return $resource(yify, {}, {

    query: {method:'GET', isArray: true}

  });

});
    /*

function InstantSearchController($scope, $http){
 $scope.search = function() {
  $http.jsonp("http://something.com/lol?query="+ $scope.searchString + "?json_callback=JSON_CALLBACK").success(
                        function(data, status) {
                            console.log(data);
                        }
                );
 }

    */
<|endoftext|>


<commit_before>#!/usr/bin/env node

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var path = require('path'),
    fs = require('fs'),
    clean = require('./clean'),
    shjs = require('shelljs'),
    zip = require('adm-zip'),
    check_reqs = require('./check_reqs'),
    buildDirInMerge ='build--release';

function hasMergesCustomReleaseArtifactsDir() {
    return fs.existsSync('merges/firefoxos/'+buildDirInMerge);
}

function hasCustomReleaseArtifactsDir() {
    return fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge);
}

/**
 * hasAllMergesRequiredCustomReleaseArtifacts()
 * checks that merges/firefoxos/build--release is avialable and properly filled.
 *
 */
function hasAllMergesRequiredCustomReleaseArtifacts() {
    if(!fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/manifest.webapp')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/manifest.webapp');
    }

    if(!fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/index.html')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/index.html');
    }

    return (   fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/manifest.webapp')
            && fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/index.html') );
}

/**
 * hasAllRequiredCustomReleaseArtifacts()
 * checks that 'cordova prepare' has copied merges/firefoxos to platforms/firefoxos/www
 *
 */
function hasAllRequiredCustomReleaseArtifacts() {
    if(!fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/manifest.webapp')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/manifest.webapp');
    }

    if(!fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/index.html')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/index.html');
    }

    return (   fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/manifest.webapp')
            && fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/index.html') );
}

function moveWwwBuildReleaseToBuild() {
    hasAllRequiredCustomReleaseArtifacts();
    console.log('Move files at  provided at \'merges/firefoxos/'+buildDirInMerge+'/\' to platforms/firefoxos/build');
    shjs.mv('-f', 'platforms/firefoxos/www/'+buildDirInMerge+'/index.html', 'platforms/firefoxos/build/index.html');
    shjs.mv('-f' ,'platforms/firefoxos/www/'+buildDirInMerge+'/manifest.webapp', 'platforms/firefoxos/build/manifest.webapp');
}

// cordova merges merge/firefoxos to platforms/firefoxos/www
// this removes the 'build--release' directory from platforms/firefoxos/www
function removeWwwBuildRelease() {
    console.log('Remove '+buildDirInMerge+' from \'platforms/firefoxos/www\'');
    if(fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge)) {
        shjs.rm('-r', 'platforms/firefoxos/www/'+buildDirInMerge);
    }
}

/**
 * buildProject
 *   --debug (default):
 *
 *
 *   --release
 *
 *
 */
exports.buildProject = function(buildTarget){

    // Check that requirements are (stil) met
    if(!check_reqs.run()) {
        console.error('Please make sure you meet the software requirements in order to build a firefoxos cordova project');
        process.exit(2);
    }

    clean.cleanProject(); // remove old build result

    // if 'debug' (default), remove files we only need for 'release'
    if(buildTarget == 'debug') {
        if(hasCustomReleaseArtifactsDir()){
            removeWwwBuildRelease();
        }
        process.exit(0);
    }

    if(buildTarget == 'release') {
        console.log('Building Firefoxos project');

        if(!hasAllMergesRequiredCustomReleaseArtifacts()) {
               console.error('\nCheck \'https://developer.mozilla.org/en-US/Marketplace/Publishing/Packaged_apps\' for the required artifacts');
               console.error('\n');
               process.exit(2);
        }

        if(!hasAllRequiredCustomReleaseArtifacts()) {
               console.error('\nIf merges/firefoxos/build-release has proper content, make sure \'cordova prepare firefoxos\' is run.');
               console.error('\n');
               process.exit(2);
        }

        if(!fs.existsSync('platforms/firefoxos/build')) {
            fs.mkdir('platforms/firefoxos/build');
        }

        moveWwwBuildReleaseToBuild();
        removeWwwBuildRelease();

        // add the project in a zipfile
        var zipFile = zip();
        zipFile.addLocalFolder('platforms/firefoxos/www', '.');
        zipFile.writeZip("platforms/firefoxos/build/package.zip");

        process.exit(0);
    }

    // should never get here
    console.error('Illegal target to build a firefoxos cordova project ('+buildTarget+')');
    process.exit(2);

}

module.exports.help = function() {
    console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'build')) + ' [build_type]');
    console.log('Build Types : ');
    console.log('    \'--debug\': Default build.');
    console.log('    \'--release\': will build a zip-file of the project in \'platforms/firefoxos/build\'.');
    console.log('                  Please provide manifest.webapp and index.html in merges/firefoxos/'+buildDirInMerge);
}

<commit_msg>CB-5816 corrected some logging<commit_after>#!/usr/bin/env node

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var path = require('path'),
    fs = require('fs'),
    clean = require('./clean'),
    shjs = require('shelljs'),
    zip = require('adm-zip'),
    check_reqs = require('./check_reqs'),
    buildDirInMerge ='build--release';

function hasMergesCustomReleaseArtifactsDir() {
    return fs.existsSync('merges/firefoxos/'+buildDirInMerge);
}

function hasCustomReleaseArtifactsDir() {
    return fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge);
}

/**
 * hasAllMergesRequiredCustomReleaseArtifacts()
 * checks that merges/firefoxos/build--release is avialable and properly filled.
 *
 */
function hasAllMergesRequiredCustomReleaseArtifacts() {
    if(!fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/manifest.webapp')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/manifest.webapp');
    }

    if(!fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/index.html')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/index.html');
    }

    return (   fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/manifest.webapp')
            && fs.existsSync('merges/firefoxos/'+buildDirInMerge+'/index.html') );
}

/**
 * hasAllRequiredCustomReleaseArtifacts()
 * checks that 'cordova prepare' has copied merges/firefoxos to platforms/firefoxos/www
 *
 */
function hasAllRequiredCustomReleaseArtifacts() {
    if(!fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/manifest.webapp')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/manifest.webapp');
    }

    if(!fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/index.html')) {
        console.error('\nPlease provide <project>/merges/firefoxos/'+buildDirInMerge+'/index.html');
    }

    return (   fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/manifest.webapp')
            && fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge+'/index.html') );
}

function moveWwwBuildReleaseToBuild() {
    hasAllRequiredCustomReleaseArtifacts();
    console.log('Move index.html and manifest.webapp provided at \'merges/firefoxos/'+buildDirInMerge+'/\' to platforms/firefoxos/build');
    shjs.mv('-f', 'platforms/firefoxos/www/'+buildDirInMerge+'/index.html', 'platforms/firefoxos/build/index.html');
    shjs.mv('-f' ,'platforms/firefoxos/www/'+buildDirInMerge+'/manifest.webapp', 'platforms/firefoxos/build/manifest.webapp');
}

// cordova merges merge/firefoxos to platforms/firefoxos/www
// this removes the 'build--release' directory from platforms/firefoxos/www
function removeWwwBuildRelease() {
    console.log('Remove '+buildDirInMerge+' from \'platforms/firefoxos/www\'');
    if(fs.existsSync('platforms/firefoxos/www/'+buildDirInMerge)) {
        shjs.rm('-r', 'platforms/firefoxos/www/'+buildDirInMerge);
    }
}

/**
 * buildProject
 *   --debug (default):
 *
 *
 *   --release
 *
 *
 */
exports.buildProject = function(buildTarget){

    // Check that requirements are (stil) met
    if(!check_reqs.run()) {
        console.error('Please make sure you meet the software requirements in order to build a firefoxos cordova project');
        process.exit(2);
    }

    clean.cleanProject(); // remove old build result

    // if 'debug' (default), remove files we only need for 'release'
    if(buildTarget == 'debug') {
        if(hasCustomReleaseArtifactsDir()){
            removeWwwBuildRelease();
        }
        process.exit(0);
    }

    if(buildTarget == 'release') {
        console.log('Building Firefoxos project');

        if(!hasAllMergesRequiredCustomReleaseArtifacts()) {
               console.error('\nCheck \'https://developer.mozilla.org/en-US/Marketplace/Publishing/Packaged_apps\' for the required artifacts');
               console.error('\n');
               process.exit(2);
        }

        if(!hasAllRequiredCustomReleaseArtifacts()) {
               console.error('\nIf merges/firefoxos/build-release has proper content, make sure \'cordova prepare firefoxos\' is run.');
               console.error('\n');
               process.exit(2);
        }

        if(!fs.existsSync('platforms/firefoxos/build')) {
            fs.mkdir('platforms/firefoxos/build');
        }

        moveWwwBuildReleaseToBuild();
        removeWwwBuildRelease();

        // add the project in a zipfile
        var zipFile = zip();
        zipFile.addLocalFolder('platforms/firefoxos/www', '.');
        zipFile.writeZip("platforms/firefoxos/build/package.zip");

        process.exit(0);
    }

    // should never get here
    console.error('Illegal target to build a firefoxos cordova project ('+buildTarget+')');
    process.exit(2);

}

module.exports.help = function() {
    console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'build')) + ' [build_type]');
    console.log('Build Types : ');
    console.log('    \'--debug\': Default build.');
    console.log('    \'--release\': will build a zip-file of the project in \'platforms/firefoxos/build\'.');
    console.log('                  Please provide manifest.webapp and index.html in merges/firefoxos/'+buildDirInMerge);
}

<|endoftext|>


<commit_before>/* global Affiliation, Authorship, ResearchEntity, Document, TagLabel, SqlService, DocumentOrigins */
'use strict';

/**
 * ResearchEntity.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/#!documentation/models
 */

const exec = require('child_process').exec;
const Promise = require("bluebird");
const _ = require("lodash");
const BaseModel = require("./BaseModel.js");

module.exports = _.merge({}, BaseModel, {
    attributes: {},
    createDraft: function (ResearchEntityModel, researchEntityId, draftData) {
        const selectedDraftData = Document.selectData(draftData);
        selectedDraftData.kind = DocumentKinds.DRAFT;
        return Promise.all([
            ResearchEntityModel.findOneById(researchEntityId).populate('drafts'),
            Document.create(selectedDraftData)
        ])
            .spread(function (researchEntity, draft) {
                researchEntity.drafts.add(draft);
                return Promise.all([
                    draft.id,
                    researchEntity.savePromise()
                ]);
            })
            .spread(function (draftId) {
                return Promise.all([
                    draftId,
                    Authorship.createEmptyAuthorships(draftId, draftData)
                ]);
            })
            .spread(function (draftId) {
                return Document.findOneById(draftId)
                    .populate('authorships')
                    .populate('affiliations')
                    .populate('authors')
                    .populate('source');
            });
    },
    unverifyDocument: async function (ResearchEntityModel, researchEntityId, documentId) {
        await this.doUnverifyDocument(ResearchEntityModel, researchEntityId, documentId);
        const deletedDocument = await Document.deleteIfNotVerified(documentId);
        return deletedDocument;
    },
    doUnverifyDocument: async function (ResearchEntityModel, researchEntityId, documentId) {
        const authorshipModel = getAuthorshipModel(ResearchEntityModel);
        const authorship = await authorshipModel.findOne({researchEntity: researchEntityId, document: documentId});
        if (!authorship)
            return;
        return authorship.unverify();
    },
    createDrafts: function (Model, researchEntityId, documents) {
        return Promise.all(documents.map(function (document) {
            return Model.createDraft(Model, researchEntityId, document);
        }));
    },
    undiscardDocument: async function(Model, researchEntityId, documentId) {
        const DiscardedModel = getDiscardedModel(Model);
        await DiscardedModel.destroy({document: documentId, researchEntity: researchEntityId});
        const deletedDocument = await Document.deleteIfNotVerified(documentId);
        return deletedDocument;
    },
    discardDocument: async function (Model, researchEntityId, documentId) {
        const DiscardedModel = getDiscardedModel(Model);
        const AuthorshipModel = getAuthorshipModel(Model);
        const authorships = await AuthorshipModel.find({document:documentId, researchEntity: researchEntityId});
        if (authorships.length > 0)
            return null;
        const discarded = await DiscardedModel.findOrCreate({researchEntity: researchEntityId, document: documentId});
        return discarded;
    },
    discardDocuments: function (Model, researchEntityId, documentIds) {
        return Promise.all(documentIds.map(function (documentId) {
            return Model.discardDocument(Model, researchEntityId, documentId);
        }));
    },
    verifyDrafts: function (ResearchEntityModel, researchEntityId, draftIds) {
        return Promise.all(
            draftIds.map(draftId => ResearchEntityModel.verifyDraft(ResearchEntityModel, researchEntityId, draftId))
        );
    },
    verifyDraft: async function (ResearchEntityModel, researchEntityId, draftId, position, affiliationInstituteIds, corresponding) {
        const draft = await Document.findOneById(draftId)
            .populate('authorships')
            .populate('affiliations');

        if (!draft || draft.kind !== DocumentKinds.DRAFT)
            return {
                error: 'Draft not found',
                item: draftId
            };
        if (!draft.isValid())
            return {
                error: 'Draft not valid for verification',
                item: draft
            };

        const authorshipData = await ResearchEntityModel.getAuthorshipsData(draft, researchEntityId, position, affiliationInstituteIds, corresponding);

        if (!authorshipData.isVerifiable)
            return {
                error: authorshipData.error,
                item: authorshipData.document
            };

        const documentCopies = await Document.findCopies(draft, authorshipData.position);

        var n = documentCopies.length;
        let docToVerify;
        if (n === 0) {
            docToVerify = await draft.draftToDocument();
        }
        else {
            if (n > 1)
                sails.log.debug('Too many similar documents to ' + draft.id + ' ( ' + n + ')');
            docToVerify = documentCopies[0];

            if (docToVerify.isPositionVerified(authorshipData.position))
                return {
                    error: "The position is already verified",
                    item: documentCopy
                };

            sails.log.debug('Draft ' + draft.id + ' will be deleted and substituted by ' + docToVerify.id);
            await Document.destroy({id: draft.id});
        }

        const newDoc = await ResearchEntityModel.doVerifyDocument(docToVerify, researchEntityId, authorshipData);

        return newDoc;
    },
    verifyDocuments: function (Model, researchEntityId, documentIds) {
        return Promise.all(documentIds.map(documentId => Model.verifyDocument(Model, researchEntityId, documentId)));
    },
    verifyDocument: async function (Model, researchEntityId, documentId, position, affiliationInstituteIds, corresponding) {
        const DiscardedModel = getDiscardedModel(Model);
        await  DiscardedModel.destroy({document: documentId, researchEntity: researchEntityId});
        const document = await Document.findOneById(documentId)
            .populate('affiliations')
            .populate('authorships');
        if (!document || document.kind !== DocumentKinds.VERIFIED)
            return {
                error: 'Document not found',
                item: researchEntityId
            };
        const authorshipData = await Model.getAuthorshipsData(document, researchEntityId, position, affiliationInstituteIds, corresponding)
        if (!authorshipData.isVerifiable)
            return {
                error: authorshipData.error,
                item: authorshipData.document
            };

        if (authorshipData.document.isPositionVerified(authorshipData.position))
            return {
                error: "The position is already verified",
                item: authorshipData.document
            };
        const verifiedDocument = await Model.doVerifyDocument(authorshipData.document, researchEntityId, authorshipData);
        return verifiedDocument;
    },
    updateDraft: async function (ResearchEntityModel, draftId, draftData) {
        const documentFields = Document.getFields();
        const selectedDraftData = _.pick(draftData, documentFields);
        selectedDraftData.kind = DocumentKinds.DRAFT;
        selectedDraftData.editedAfterImport = true;
        const updatedDraft = await Document.update({id: draftId}, selectedDraftData);
        return updatedDraft[0];
    },
    deleteDrafts: function (Model, draftIds) {
        return Promise.all(draftIds.map(function (draftId) {
            return Document.destroy({id: draftId});
        }));
    },
    addTags: function (TagModel, userId, documentId, tags) {
        return TagModel.destroy({researchEntity: userId, document: documentId})
            .then(() =>
                tags.forEach(t =>
                    TagLabel
                        .findOrCreate({value: t})
                        .then(tl => TagModel.create({
                            document: documentId,
                            researchEntity: userId,
                            tagLabel: tl.id
                        }))
                )
            )
    },
    setAuthorships: async function (ResearchEntityModel, researchEntityId, draftId, authorshipsData) {
        authorshipsData.forEach(a => delete a.id);
        const deleteAuthorships = await Authorship.destroy({document: draftId});
        await Affiliation.destroy({authorship: deleteAuthorships.map(a => a.id)});
        return Authorship.create(authorshipsData);
    },
    updateProfile: async function (ResearchEntityModel, researchEntityId, researchEntityData) {
        const oldResearchEntity = await ResearchEntityModel.findOne({id: researchEntityId});
        const res = await ResearchEntityModel.update({id: researchEntityId}, researchEntityData);
        const newResearchEntity = res[0];
        const researchEntityType = newResearchEntity.getType();
        const command = 'grunt external:import:' + researchEntityType + ':' + newResearchEntity.id;
        if (newResearchEntity.scopusId !== oldResearchEntity.scopusId)
            exec(command + ':' + DocumentOrigins.SCOPUS);
        if (newResearchEntity.username !== oldResearchEntity.username
            || newResearchEntity.publicationsAcronym !== oldResearchEntity.publicationsAcronym)
            exec(command + ':' + DocumentOrigins.PUBLICATIONS);

        return newResearchEntity;
    },
    _config: {
        actions: false,
        shortcuts: false,
        rest: false
    }
});

function getThroughModel(ResearchEntityModel, fieldName) {
    const throughModelName = ResearchEntityModel._attributes[fieldName].through;
    return sails.models[throughModelName];
}

function getAuthorshipModel(ResearchEntityModel) {
    return getThroughModel(ResearchEntityModel, 'documents');
}

function getDiscardedModel(ResearchEntityModel) {
    return getThroughModel(ResearchEntityModel, 'discardedDocuments');
}<commit_msg>Fixed small error.<commit_after>/* global Affiliation, Authorship, ResearchEntity, Document, TagLabel, SqlService, DocumentOrigins */
'use strict';

/**
 * ResearchEntity.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/#!documentation/models
 */

const exec = require('child_process').exec;
const Promise = require("bluebird");
const _ = require("lodash");
const BaseModel = require("./BaseModel.js");

module.exports = _.merge({}, BaseModel, {
    attributes: {},
    createDraft: function (ResearchEntityModel, researchEntityId, draftData) {
        const selectedDraftData = Document.selectData(draftData);
        selectedDraftData.kind = DocumentKinds.DRAFT;
        return Promise.all([
            ResearchEntityModel.findOneById(researchEntityId).populate('drafts'),
            Document.create(selectedDraftData)
        ])
            .spread(function (researchEntity, draft) {
                researchEntity.drafts.add(draft);
                return Promise.all([
                    draft.id,
                    researchEntity.savePromise()
                ]);
            })
            .spread(function (draftId) {
                return Promise.all([
                    draftId,
                    Authorship.createEmptyAuthorships(draftId, draftData)
                ]);
            })
            .spread(function (draftId) {
                return Document.findOneById(draftId)
                    .populate('authorships')
                    .populate('affiliations')
                    .populate('authors')
                    .populate('source');
            });
    },
    unverifyDocument: async function (ResearchEntityModel, researchEntityId, documentId) {
        await this.doUnverifyDocument(ResearchEntityModel, researchEntityId, documentId);
        const deletedDocument = await Document.deleteIfNotVerified(documentId);
        return deletedDocument;
    },
    doUnverifyDocument: async function (ResearchEntityModel, researchEntityId, documentId) {
        const authorshipModel = getAuthorshipModel(ResearchEntityModel);
        const authorship = await authorshipModel.findOne({researchEntity: researchEntityId, document: documentId});
        if (!authorship)
            return;
        return authorship.unverify();
    },
    createDrafts: function (Model, researchEntityId, documents) {
        return Promise.all(documents.map(function (document) {
            return Model.createDraft(Model, researchEntityId, document);
        }));
    },
    undiscardDocument: async function(Model, researchEntityId, documentId) {
        const DiscardedModel = getDiscardedModel(Model);
        await DiscardedModel.destroy({document: documentId, researchEntity: researchEntityId});
        const deletedDocument = await Document.deleteIfNotVerified(documentId);
        return deletedDocument;
    },
    discardDocument: async function (Model, researchEntityId, documentId) {
        const DiscardedModel = getDiscardedModel(Model);
        const AuthorshipModel = getAuthorshipModel(Model);
        const authorships = await AuthorshipModel.find({document:documentId, researchEntity: researchEntityId});
        if (authorships.length > 0)
            return null;
        const discarded = await DiscardedModel.findOrCreate({researchEntity: researchEntityId, document: documentId});
        return discarded;
    },
    discardDocuments: function (Model, researchEntityId, documentIds) {
        return Promise.all(documentIds.map(function (documentId) {
            return Model.discardDocument(Model, researchEntityId, documentId);
        }));
    },
    verifyDrafts: function (ResearchEntityModel, researchEntityId, draftIds) {
        return Promise.all(
            draftIds.map(draftId => ResearchEntityModel.verifyDraft(ResearchEntityModel, researchEntityId, draftId))
        );
    },
    verifyDraft: async function (ResearchEntityModel, researchEntityId, draftId, position, affiliationInstituteIds, corresponding) {
        const draft = await Document.findOneById(draftId)
            .populate('authorships')
            .populate('affiliations');

        if (!draft || draft.kind !== DocumentKinds.DRAFT)
            return {
                error: 'Draft not found',
                item: draftId
            };
        if (!draft.isValid())
            return {
                error: 'Draft not valid for verification',
                item: draft
            };

        const authorshipData = await ResearchEntityModel.getAuthorshipsData(draft, researchEntityId, position, affiliationInstituteIds, corresponding);

        if (!authorshipData.isVerifiable)
            return {
                error: authorshipData.error,
                item: authorshipData.document
            };

        const documentCopies = await Document.findCopies(draft, authorshipData.position);

        var n = documentCopies.length;
        let docToVerify;
        if (n === 0) {
            docToVerify = await draft.draftToDocument();
        }
        else {
            if (n > 1)
                sails.log.debug('Too many similar documents to ' + draft.id + ' ( ' + n + ')');
            docToVerify = documentCopies[0];

            if (docToVerify.isPositionVerified(authorshipData.position))
                return {
                    error: "The position is already verified",
                    item: docToVerify
                };

            sails.log.debug('Draft ' + draft.id + ' will be deleted and substituted by ' + docToVerify.id);
            await Document.destroy({id: draft.id});
        }

        const newDoc = await ResearchEntityModel.doVerifyDocument(docToVerify, researchEntityId, authorshipData);

        return newDoc;
    },
    verifyDocuments: function (Model, researchEntityId, documentIds) {
        return Promise.all(documentIds.map(documentId => Model.verifyDocument(Model, researchEntityId, documentId)));
    },
    verifyDocument: async function (Model, researchEntityId, documentId, position, affiliationInstituteIds, corresponding) {
        const DiscardedModel = getDiscardedModel(Model);
        await  DiscardedModel.destroy({document: documentId, researchEntity: researchEntityId});
        const document = await Document.findOneById(documentId)
            .populate('affiliations')
            .populate('authorships');
        if (!document || document.kind !== DocumentKinds.VERIFIED)
            return {
                error: 'Document not found',
                item: researchEntityId
            };
        const authorshipData = await Model.getAuthorshipsData(document, researchEntityId, position, affiliationInstituteIds, corresponding)
        if (!authorshipData.isVerifiable)
            return {
                error: authorshipData.error,
                item: authorshipData.document
            };

        if (authorshipData.document.isPositionVerified(authorshipData.position))
            return {
                error: "The position is already verified",
                item: authorshipData.document
            };
        const verifiedDocument = await Model.doVerifyDocument(authorshipData.document, researchEntityId, authorshipData);
        return verifiedDocument;
    },
    updateDraft: async function (ResearchEntityModel, draftId, draftData) {
        const documentFields = Document.getFields();
        const selectedDraftData = _.pick(draftData, documentFields);
        selectedDraftData.kind = DocumentKinds.DRAFT;
        selectedDraftData.editedAfterImport = true;
        const updatedDraft = await Document.update({id: draftId}, selectedDraftData);
        return updatedDraft[0];
    },
    deleteDrafts: function (Model, draftIds) {
        return Promise.all(draftIds.map(function (draftId) {
            return Document.destroy({id: draftId});
        }));
    },
    addTags: function (TagModel, userId, documentId, tags) {
        return TagModel.destroy({researchEntity: userId, document: documentId})
            .then(() =>
                tags.forEach(t =>
                    TagLabel
                        .findOrCreate({value: t})
                        .then(tl => TagModel.create({
                            document: documentId,
                            researchEntity: userId,
                            tagLabel: tl.id
                        }))
                )
            )
    },
    setAuthorships: async function (ResearchEntityModel, researchEntityId, draftId, authorshipsData) {
        authorshipsData.forEach(a => delete a.id);
        const deleteAuthorships = await Authorship.destroy({document: draftId});
        await Affiliation.destroy({authorship: deleteAuthorships.map(a => a.id)});
        return Authorship.create(authorshipsData);
    },
    updateProfile: async function (ResearchEntityModel, researchEntityId, researchEntityData) {
        const oldResearchEntity = await ResearchEntityModel.findOne({id: researchEntityId});
        const res = await ResearchEntityModel.update({id: researchEntityId}, researchEntityData);
        const newResearchEntity = res[0];
        const researchEntityType = newResearchEntity.getType();
        const command = 'grunt external:import:' + researchEntityType + ':' + newResearchEntity.id;
        if (newResearchEntity.scopusId !== oldResearchEntity.scopusId)
            exec(command + ':' + DocumentOrigins.SCOPUS);
        if (newResearchEntity.username !== oldResearchEntity.username
            || newResearchEntity.publicationsAcronym !== oldResearchEntity.publicationsAcronym)
            exec(command + ':' + DocumentOrigins.PUBLICATIONS);

        return newResearchEntity;
    },
    _config: {
        actions: false,
        shortcuts: false,
        rest: false
    }
});

function getThroughModel(ResearchEntityModel, fieldName) {
    const throughModelName = ResearchEntityModel._attributes[fieldName].through;
    return sails.models[throughModelName];
}

function getAuthorshipModel(ResearchEntityModel) {
    return getThroughModel(ResearchEntityModel, 'documents');
}

function getDiscardedModel(ResearchEntityModel) {
    return getThroughModel(ResearchEntityModel, 'discardedDocuments');
}<|endoftext|>


<commit_before>/**
* GreatestHit.js
*
* @description :: Greatest Hit of Yacht Rock
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {

    "id": {
      type: "integer",
      autoIncrement: true
    },
    "name": {
      type: 'string'
    },
    "artist": {
      type: 'string'
    },
    "year": {
      type: 'integer'
    }
  }
};
<commit_msg>Remove 'id' attribute<commit_after>/**
* GreatestHit.js
*
* @description :: Greatest Hit of Yacht Rock
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {
    name": {
      type: 'string'
    },
    "artist": {
      type: 'string'
    },
    "year": {
      type: 'integer'
    }
  }
};
<|endoftext|>


<commit_before>$(function() {

    $( '.news-title' ).click(function( ev ) {

        document.location.hash = ev.target.parentElement.id;

    });

});
<commit_msg>Using vanilla JS.<commit_after>(function(body) {

    body.addEventListener( 'click', function( ev ) {

        var el = ev.target, cl;

        if (el && (cl=el.className) && cl.indexOf('news-title') >= 0) {

            document.location.hash = el.parentElement.id;

        }

    }, true );

})(document.getElementsByTagName( 'body' )[0]);
<|endoftext|>


<commit_before>import testUtils from './../test-utils';
import angular from 'angular';

describe('formlyMaterial - textarea type', () => {
  //
  // vars
  //

  let $compile;
  let $rootScope;
  let $scope;
  let form;
  let element;
  let field;

  //
  // helpers
  //

  function compile(options) {
    $scope = $rootScope.$new();
    $scope.fields = [angular.merge({}, {
      key: 'testField',
      type: 'textarea',
      templateOptions: {
        label: 'test field',
        rows: 5,
        cols: 6
      }
    }, options)];

    form = $compile(testUtils.getFormTemplate())($scope);
    $scope.$digest();
    field = $scope.fields[0];
    element = form.find('[ng-model]');
  }

  //
  // tests
  //

  beforeEach(() => {
    window.module('formlyMaterial');

    inject((_$compile_, _$rootScope_) => {
      $compile = _$compile_;
      $rootScope = _$rootScope_;
    });

    compile();
  });

  it('should be input element', () => {
    expect(element[0].nodeName).toBe('TEXTAREA');
  });

  it('should have messages wrapper', () => {
    expect(form.find('[ng-messages]').length).toBe(1);
  });

  it('should have label wrapper', () => {
    const label = form.find('label');

    expect(label.length).toBe(1);
    expect(label.html()).toContain(field.templateOptions.label);
  });

  it('should not auto grow', () => {
    expect(element.attr('md-no-autogrow')).toBeUndefined();
  });

  it('should be able to disable autogrowing', () => {
    compile({
      templateOptions: {
        grow: false
      }
    });
    expect(element.attr('md-no-autogrow')).toBeDefined();
  });

  it('should have inputContainer wrapper', () => {
    expect(form.find('md-input-container').length).toBe(1);
  });

  it('should be able to set rows', () => {
    expect(parseInt(element.attr('rows'), 10)).toEqual(field.templateOptions.rows);
  });

  it('should be able to set cols', () => {
    expect(parseInt(element.attr('cols'), 10)).toEqual(field.templateOptions.cols);
  });
});
<commit_msg>test(textarea): templateOptions.disabled<commit_after>import testUtils from './../test-utils';
import angular from 'angular';

describe('formlyMaterial - textarea type', () => {
  //
  // vars
  //

  let $compile;
  let $rootScope;
  let $scope;
  let form;
  let element;
  let elementScope;
  let field;

  //
  // helpers
  //

  function compile(options) {
    $scope = $rootScope.$new();
    $scope.fields = [angular.merge({}, {
      key: 'testField',
      type: 'textarea',
      templateOptions: {
        label: 'test field',
        disabled: true,
        rows: 5,
        cols: 6
      }
    }, options)];

    form = $compile(testUtils.getFormTemplate())($scope);
    $scope.$digest();
    field = $scope.fields[0];
    element = form.find('[ng-model]');
    elementScope = element.scope();
  }

  //
  // tests
  //

  beforeEach(() => {
    window.module('formlyMaterial');

    inject((_$compile_, _$rootScope_) => {
      $compile = _$compile_;
      $rootScope = _$rootScope_;
    });

    compile();
  });

  it('should be input element', () => {
    expect(element[0].nodeName).toBe('TEXTAREA');
  });

  it('should have messages wrapper', () => {
    expect(form.find('[ng-messages]').length).toBe(1);
  });

  it('should have label wrapper', () => {
    const label = form.find('label');

    expect(label.length).toBe(1);
    expect(label.html()).toContain(field.templateOptions.label);
  });

  it('should not auto grow', () => {
    expect(element.attr('md-no-autogrow')).toBeUndefined();
  });

  it('should be able to disable autogrowing', () => {
    compile({
      templateOptions: {
        grow: false
      }
    });
    expect(element.attr('md-no-autogrow')).toBeDefined();
  });

  it('should have inputContainer wrapper', () => {
    expect(form.find('md-input-container').length).toBe(1);
  });

  it('should be able to set rows', () => {
    expect(parseInt(element.attr('rows'), 10)).toEqual(field.templateOptions.rows);
  });

  it('should be able to set cols', () => {
    expect(parseInt(element.attr('cols'), 10)).toEqual(field.templateOptions.cols);
  });

  it('should be able to be disabled', () => {
    expect(element.attr('ng-disabled')).toBe(`options.templateOptions['disabled']`);
    expect(elementScope.options.templateOptions.disabled).toBe(true);
  });
});
<|endoftext|>


<commit_before>/**
 * # Authorization settings
 * Copyright(c) {YEAR} {AUTHOR} <{AUTHOR_EMAIL}>
 * MIT Licensed
 *
 * http://www.nodegame.org
 * ---
 */
module.exports = {

    /**
     * ## enabled
     *
     * If TRUE, authorization files will be imported and checked
     */
    enabled: false, // [true, false] Default: TRUE.

    /**
     * ## mode
     *
     * The mode for importing the authorization codes
     *
     * Available modes:
     *
     *   - 'dummy': creates dummy ids and passwords in sequential order.
     *   - 'auto': creates random 8-digit alphanumeric ids and passwords.
     *   - 'local': reads the authorization codes from a file. Defaults:
     *              codes.json, code.csv. A custom file can be specified
     *              in settings.file (available formats: json and csv).
     *   - 'remote': fetches the authorization codes from a remote URI.
     *               Available protocol: DeSciL protocol.
     *   - 'custom': The 'customCb' property of the settings object
     *               will be executed with settings and done callback
     *               as parameters.
     *
     */
    mode: 'local',

    /**
     * ## nCodes
     *
     * The number of codes to create
     *
     * Modes: 'dummy', 'auto'
     * Default: 100
     */
    // nCodes: 20,

    /**
     * ## addPwd
     *
     * If TRUE, a password field is added to each code
     *
     * Modes: 'dummy', 'auto'
     * Default: FALSE
     */
    // addPwd: true,

    /**
     * ## codesLength
     *
     * The length of generated codes
     *
     * Modes: 'auto'
     * Default: { id: 8, pwd: 8, AccessCode: 6, ExitCode: 6 }
     */
    // codesLength: { id: 8, pwd: 8, AccessCode: 6, ExitCode: 6 },

    /**
     * ## customCb
     *
     * The custom callback associated to mode 'custom'
     *
     * Modes: 'custom'
     */
    // customCb: function(settings, done) { return [ ... ] },

    /**
     * ## inFile
     *
     * The name of the codes file inside auth/ dir or a full path to it
     *
     * Available formats: .csv and .json.
     *
     * Modes: 'local'
     * Default: 'codes.json', 'codes.js', 'code.csv' (tried in sequence)
     */
    inFile: 'codes.imported.csv',

    /**
     * ## dumpCodes
     *
     * If TRUE, all imported codes will be dumped to file `outFile`
     *
     * Modes: 'dummy', 'auto', 'local', 'remote', 'custom'
     * Default: TRUE
     */
    // dumpCodes: false

    /**
     * ## outFile
     *
     * The name of the codes dump file inside auth/ dir or a full path to it
     *
     * Only used, if `dumpCodes` is TRUE. Available formats: .csv and .json.
     *
     * Modes: 'dummy', 'auto', 'local', 'remote', 'custom'
     * Default: 'codes.imported.csv'
     */
    // outFile: 'my.imported.codes.csv',

    /**
     * ## claimId
     *
     * If TRUE, remote clients will be able to claim an id via GET request
     *
     * Default: FALSE
     */
    // claimId: true,

    /**
     * ## claimIdValidateRequest
     *
     * Returns TRUE if a requester is authorized to claim an id
     *
     * Returns an error string describing the error otherwise.
     *
     * Default: undefined
     */
    // claimIdValidateRequest: function(query, headers) {
    //    // Check query and headers.
    //    return true;
    //},

    /**
     * ## claimIdPostProcess
     *
     * Manipulates the client object after the claim id process succeeded
     */
    //claimIdPostProcess: function(code, query, headers) {
    //    code.WorkerId = query.id;
    //},

    /**
     * ## codes
     *
     * Path to the code generator file
     *
     * The file must export a function that takes current settings
     * (e.g. mode, etc.) and returns synchronously or asynchronously
     * an array of valid authorization codes.
     */
    //codes: 'path/to/code/generator.js',

    // # Reserved words for future requirements settings.

    // page: 'login.htm'

};
<commit_msg>mods for v4<commit_after>/**
 * # Authorization settings
 * Copyright(c) {YEAR} {AUTHOR} <{AUTHOR_EMAIL}>
 * MIT Licensed
 *
 * http://www.nodegame.org
 * ---
 */
module.exports = {

    /**
     * ## enabled
     *
     * If TRUE, authorization files will be imported and checked
     */
    enabled: false, // [true, false] Default: TRUE.

    /**
     * ## mode
     *
     * The mode for importing the authorization codes
     *
     * Available modes:
     *
     *   - 'dummy': creates dummy ids and passwords in sequential order.
     *   - 'auto': creates random 8-digit alphanumeric ids and passwords.
     *   - 'local': reads the authorization codes from a file. Defaults:
     *              codes.json, code.csv. A custom file can be specified
     *              in settings.file (available formats: json and csv).
     *   - 'remote': fetches the authorization codes from a remote URI.
     *               Available protocol: DeSciL protocol.
     *   - 'custom': The 'customCb' property of the settings object
     *               will be executed with settings and done callback
     *               as parameters.
     *
     */
    mode: 'local',

    /**
     * ## nCodes
     *
     * The number of codes to create
     *
     * Modes: 'dummy', 'auto'
     * Default: 100
     */
    // nCodes: 20,

    /**
     * ## addPwd
     *
     * If TRUE, a password field is added to each code
     *
     * Modes: 'dummy', 'auto'
     * Default: FALSE
     */
    // addPwd: true,

    /**
     * ## codesLength
     *
     * The length of generated codes
     *
     * Modes: 'auto'
     * Default: { id: 8, pwd: 8, AccessCode: 6, ExitCode: 6 }
     */
    // codesLength: { id: 8, pwd: 8, AccessCode: 6, ExitCode: 6 },

    /**
     * ## customCb
     *
     * The custom callback associated to mode 'custom'
     *
     * Modes: 'custom'
     */
    // customCb: function(settings, done) { return [ ... ] },

    /**
     * ## inFile
     *
     * The name of the codes file inside auth/ dir or a full path to it
     *
     * Available formats: .csv and .json.
     *
     * Modes: 'local'
     * Default: 'codes.json', 'codes.js', 'code.csv' (tried in sequence)
     */
    inFile: 'codes.imported.csv',

    /**
     * ## dumpCodes
     *
     * If TRUE, all imported codes will be dumped to file `outFile`
     *
     * Modes: 'dummy', 'auto', 'local', 'remote', 'custom'
     * Default: TRUE
     */
    // dumpCodes: false

    /**
     * ## outFile
     *
     * The name of the codes dump file inside auth/ dir or a full path to it
     *
     * Only used, if `dumpCodes` is TRUE. Available formats: .csv and .json.
     *
     * Modes: 'dummy', 'auto', 'local', 'remote', 'custom'
     * Default: 'codes.imported.csv'
     */
    // outFile: 'my.imported.codes.csv',

    /**
     * ## claimId
     *
     * If TRUE, remote clients will be able to claim an id via GET request
     *
     * Default: FALSE
     */
    // claimId: true,

    /**
     * ## claimIdValidateRequest
     *
     * Returns TRUE if a requester is authorized to claim an id
     *
     * Returns an error string describing the error otherwise.
     *
     * Default: undefined
     */
    // claimIdValidateRequest: function(query, headers) {
    //    // Check query and headers.
    //    return true;
    //},

    /**
     * ## claimIdPostProcess
     *
     * Manipulates the client object after the claim id process succeeded
     */
    //claimIdPostProcess: function(clientObj, query, headers) {
    //    clientObj.WorkerId = query.id;
    //},

    /**
     * ## claimIdModifyReply
     *
     * Manipulates the object sent back to the client
     *
     * @experimental
     * @v4
     */
    //claimIdModifyReply: function(reply) {
    //    In case of success tell the client the name of the host
    //    where the game is. Default: same host.
    //    if (reply.code) reply.host = 'http://myhost.com';
    //},

    /**
     * ## codes
     *
     * Path to the code generator file
     *
     * The file must export a function that takes current settings
     * (e.g. mode, etc.) and returns synchronously or asynchronously
     * an array of valid authorization codes.
     */
    //codes: 'path/to/code/generator.js',

    // # Reserved words for future requirements settings.

    // page: 'login.htm'

};
<|endoftext|>