<commit_before>import Ember from 'ember';
import loadAll from 'ember-osf/utils/load-relationship';
import Analytics from 'ember-osf/mixins/analytics';
import fileDownloadPath from '../utils/file-download-path';

/**
 * @module ember-preprints
 * @submodule components
 */

/**
 * Displays supplemental preprint files
 *
 * Sample usage:
 * ```handlebars
 * {{supplementary-file-browser
 *      preprint=model
 *      node=node
 *      projectURL=node.links.html
 *      chooseFile=(action 'chooseFile')
 * }}
 * ```
 * @class supplementary-file-browser
 */
export default Ember.Component.extend(Analytics, {
    theme: Ember.inject.service(),

    elementId: 'preprint-file-view',
    endIndex: 6,
    startIndex: 0,

    scrollAnim: '',
    selectedFile: null,
    allowCommenting: false,

    hasAdditionalFiles: function() {
        return this.get('files.length') > 1;
    }.property('files'),

    hasPrev: function() {
        return this.get('startIndex') > 0;
    }.property('files', 'endIndex', 'startIndex'),

    hasNext: function() {
        return this.get('endIndex') < this.get('files.length');
    }.property('files', 'endIndex', 'startIndex'),

    __files: function() {
        this.set('files', []);
        this.set('selectedFile', null);
        this.get('node').get('files')
            .then(providers => {
                this.set('provider', providers.findBy('name', 'osfstorage'));
                return loadAll(this.get('provider'), 'files', this.get('files'), {'page[size]': 50});
            })
            .then(() => this.get('preprint').get('primaryFile'))
            .then((pf) => {
                this.get('files').removeObject(pf);
                this.set('primaryFile', pf);
                this.set('selectedFile', this.get('primaryFile'));
                this.set('files', [this.get('primaryFile')].concat(this.get('files')));
                this.set('indexes', this.get('files').map(each => each.id));
            });
    }.observes('preprint'),

    selectedFileChanged: Ember.observer('selectedFile', function() {
        const eventData = {
            file_views: {
                preprint: {
                    type: 'preprint',
                    id: this.get('preprint.id')
                },
                file: {
                    id: this.get('selectedFile.id'),
                    primaryFile: this.get('preprint.primaryFile.id') === this.get('selectedFile.id'),
                    version: this.get('selectedFile.currentVersion')
                }
            }
        };
        Ember.get(this, 'metrics').invoke('trackSpecificCollection', 'Keen', {
            collection: 'preprint-file-views',
            eventData: eventData,
            node: this.get('node'),
        });
    }),

    _chosenFile: Ember.observer('chosenFile', 'indexes', function() {
        let fid = this.get('chosenFile');
        let index = this.get('indexes').indexOf(fid);
        if (fid && index !== -1) {
            this.set('selectedFile', this.get('files')[index]);
        }
    }),
    _moveIfNeeded: Ember.observer('selectedFile', function() {
        let index = this.get('files').indexOf(this.get('selectedFile'));
        if (index < 0) {
            return;
        }
        if (index >= this.get('endIndex') || index < this.get('startIndex')) {
            let max = this.get('files').length - 6;
            if (index > max) {
                this.set('startIndex', max);
                this.set('endIndex', this.get('files').length);
            } else {
                this.set('startIndex', index);
                this.set('endIndex', index + 6);
            }
        }
    }),
    fileDownloadURL: Ember.computed('selectedFile', function() {
        return fileDownloadPath(this.get('selectedFile'), this.get('node'));
    }),

    init() {
        this._super(...arguments);
        this.__files();
    },

    didReceiveAttrs() {
        this.get('theme.provider').then( provider => {
            this.set('allowCommenting', provider.get('allowCommenting'));
        });
    },

    actions: {
        next(direction) {
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'file browser',
                    action: 'click',
                    label: 'Content - Next'
                });

            if (this.get('endIndex') > this.get('files.length')) return;

            this.set('scrollAnim', `to${direction}`);
            this.set('endIndex', this.get('endIndex') + 5);
            this.set('startIndex', this.get('startIndex') + 5);
        },
        prev(direction) {
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'file browser',
                    action: 'click',
                    label: 'Content - Prev'
                });
            let start = this.get('startIndex');
            if (start <= 0) return;

            this.set('scrollAnim', `to${direction}`);
            if ((start - 5) < 0) {
                this.set('startIndex', 0);
                this.set('endIndex', 6);
            } else {
                this.set('startIndex', start - 5);
                this.set('endIndex', this.get('endIndex') - 5);
            }
        },
        changeFile(file) {
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'file browser',
                    action: 'select',
                    label: 'Content - File'
                });

            this.set('selectedFile', file);
            if (this.attrs.chooseFile) {
                this.sendAction('chooseFile', file);
            }
        },
    },
});
<commit_msg>[WIP][IN-343] Disallow hypothesis if node is private (#584)<commit_after>import Ember from 'ember';
import loadAll from 'ember-osf/utils/load-relationship';
import Analytics from 'ember-osf/mixins/analytics';
import fileDownloadPath from '../utils/file-download-path';

/**
 * @module ember-preprints
 * @submodule components
 */

/**
 * Displays supplemental preprint files
 *
 * Sample usage:
 * ```handlebars
 * {{supplementary-file-browser
 *      preprint=model
 *      node=node
 *      projectURL=node.links.html
 *      chooseFile=(action 'chooseFile')
 * }}
 * ```
 * @class supplementary-file-browser
 */
export default Ember.Component.extend(Analytics, {
    theme: Ember.inject.service(),

    elementId: 'preprint-file-view',
    endIndex: 6,
    startIndex: 0,

    scrollAnim: '',
    selectedFile: null,
    allowCommenting: false,

    hasAdditionalFiles: function() {
        return this.get('files.length') > 1;
    }.property('files'),

    hasPrev: function() {
        return this.get('startIndex') > 0;
    }.property('files', 'endIndex', 'startIndex'),

    hasNext: function() {
        return this.get('endIndex') < this.get('files.length');
    }.property('files', 'endIndex', 'startIndex'),

    __files: function() {
        this.set('files', []);
        this.set('selectedFile', null);
        this.get('node').get('files')
            .then(providers => {
                this.set('provider', providers.findBy('name', 'osfstorage'));
                return loadAll(this.get('provider'), 'files', this.get('files'), {'page[size]': 50});
            })
            .then(() => this.get('preprint').get('primaryFile'))
            .then((pf) => {
                this.get('files').removeObject(pf);
                this.set('primaryFile', pf);
                this.set('selectedFile', this.get('primaryFile'));
                this.set('files', [this.get('primaryFile')].concat(this.get('files')));
                this.set('indexes', this.get('files').map(each => each.id));
            });
    }.observes('preprint'),

    selectedFileChanged: Ember.observer('selectedFile', function() {
        const eventData = {
            file_views: {
                preprint: {
                    type: 'preprint',
                    id: this.get('preprint.id')
                },
                file: {
                    id: this.get('selectedFile.id'),
                    primaryFile: this.get('preprint.primaryFile.id') === this.get('selectedFile.id'),
                    version: this.get('selectedFile.currentVersion')
                }
            }
        };
        Ember.get(this, 'metrics').invoke('trackSpecificCollection', 'Keen', {
            collection: 'preprint-file-views',
            eventData: eventData,
            node: this.get('node'),
        });
    }),

    _chosenFile: Ember.observer('chosenFile', 'indexes', function() {
        let fid = this.get('chosenFile');
        let index = this.get('indexes').indexOf(fid);
        if (fid && index !== -1) {
            this.set('selectedFile', this.get('files')[index]);
        }
    }),
    _moveIfNeeded: Ember.observer('selectedFile', function() {
        let index = this.get('files').indexOf(this.get('selectedFile'));
        if (index < 0) {
            return;
        }
        if (index >= this.get('endIndex') || index < this.get('startIndex')) {
            let max = this.get('files').length - 6;
            if (index > max) {
                this.set('startIndex', max);
                this.set('endIndex', this.get('files').length);
            } else {
                this.set('startIndex', index);
                this.set('endIndex', index + 6);
            }
        }
    }),
    fileDownloadURL: Ember.computed('selectedFile', function() {
        return fileDownloadPath(this.get('selectedFile'), this.get('node'));
    }),

    init() {
        this._super(...arguments);
        this.__files();
    },

    didReceiveAttrs() {
        this.get('theme.provider').then( provider => {
            // NOTE: the public check will likely need to be removed after the node-preprint divorce
            const publishedAndPublic = this.get('preprint.isPublished') && this.get('node.public');
            this.set('allowCommenting', provider.get('allowCommenting') && publishedAndPublic);
        });
    },

    actions: {
        next(direction) {
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'file browser',
                    action: 'click',
                    label: 'Content - Next'
                });

            if (this.get('endIndex') > this.get('files.length')) return;

            this.set('scrollAnim', `to${direction}`);
            this.set('endIndex', this.get('endIndex') + 5);
            this.set('startIndex', this.get('startIndex') + 5);
        },
        prev(direction) {
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'file browser',
                    action: 'click',
                    label: 'Content - Prev'
                });
            let start = this.get('startIndex');
            if (start <= 0) return;

            this.set('scrollAnim', `to${direction}`);
            if ((start - 5) < 0) {
                this.set('startIndex', 0);
                this.set('endIndex', 6);
            } else {
                this.set('startIndex', start - 5);
                this.set('endIndex', this.get('endIndex') - 5);
            }
        },
        changeFile(file) {
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'file browser',
                    action: 'select',
                    label: 'Content - File'
                });

            this.set('selectedFile', file);
            if (this.attrs.chooseFile) {
                this.sendAction('chooseFile', file);
            }
        },
    },
});
<|endoftext|>


<commit_before>'use strict';

const Input=require('./input-classes.js');
const imports=require('crnx-base/option-classes');

const RangeInput=imports.RangeInput;
const Group=imports.Group;

class FixedLiveNumber {
	constructor(src,setToDefault) {
		if (!setToDefault) {
			this.value=src.value;
			this.min=src.min;
			this.max=src.max;
			this.input=Input.createFromString(src.input);
		} else {
			this.value=src.defaultValue
			this.min=src.availableMin;
			this.max=src.availableMax;
			this.input=Input.createFromString('constant');
		}
		// needed for formatting and to decide on clamp()/wrap():
		this.availableMin=src.availableMin;
		this.availableMax=src.availableMax;
		this.step=src.step;
	}
	valueOf() {
		return this.value;
	}
	toString() {
		return String(this.value);
	}
}

// abstract classes

class LiveNumber extends RangeInput {
	constructor(name,availableRange,defaultValue,data,fullName,isVisible,updateCallback) {
		let dataValue,dataMin,dataMax,dataInput;
		if (typeof data == 'object') {
			dataValue=data.value;
			dataMin  =data.min;
			dataMax  =data.max;
			dataInput=data.input;
		} else {
			dataValue=data;
		}
		super(name,availableRange,defaultValue,dataValue,fullName,isVisible,updateCallback);
		this._min=(dataMin!==undefined)?dataMin:this.availableMin;
		this._max=(dataMax!==undefined)?dataMax:this.availableMax;
		this._input=(dataInput!==undefined)?dataInput:'constant';
		this._$range=null;
	}
	updateInternalVisibility() {
		if (this._$range) this._$range.toggle(this._input!='constant');
	}
	get input() {
		return this._input;
	}
	set input(input) {
		this._input=input;
		this.updateInternalVisibility();
		this.updateCallback();
	}
	get min() {
		return this._min;
	}
	set min(min) {
		this._min=min;
		this.updateCallback();
	}
	get max() {
		return this._max;
	}
	set max(max) {
		this._max=max;
		this.updateCallback();
	}
	get $range() {
		return this._$range;
	}
	set $range($range) {
		this._$range=$range;
		this.updateInternalVisibility();
	}
	exportHelper(src) {
		const data={};
		if (src.value!=src.defaultValue) data.value=src.value;
		if (src.min!=src.availableMin) data.min=src.min;
		if (src.max!=src.availableMax) data.max=src.max;
		if (src.input!='constant') data.input=src.input;
		return data;
	}
	export() {
		return this.exportHelper(this);
	}
	fix() {
		const fixed=new FixedLiveNumber(this);
		fixed.name=this.name;
		return fixed;
	}
}

// concrete classes

class LiveInt extends LiveNumber {
	get step() {
		return 1;
	}
	get availableInputTypes() {
		return ['constant','slider','mousemovex','mousemovey'];
	}
}

class CanvasLiveInt extends LiveInt {
	get availableInputTypes() {
		return ['constant','slider'];
	}
}

class LiveFloat extends LiveNumber {
	constructor(name,availableRange,defaultValue,data,fullName,isVisible,updateCallback) {
		let dataSpeedValue,dataSpeedMin,dataSpeedMax,dataSpeedInput;
		if (typeof data == 'object') {
			if (typeof data.speed == 'object') {
				dataSpeedValue=data.speed.value;
				dataSpeedMin  =data.speed.min;
				dataSpeedMax  =data.speed.max;
				dataSpeedInput=data.speed.input;
			} else {
				dataSpeedValue=data.speed;
			}
		}
		super(...arguments);
		this._speedValue=(dataSpeedValue!==undefined)?dataSpeedValue:0;
		this._speedAvailableMin=availableRange[2]; this._speedMin=(dataSpeedMin!==undefined)?dataSpeedMin:this._speedAvailableMin;
		this._speedAvailableMax=availableRange[3]; this._speedMax=(dataSpeedMax!==undefined)?dataSpeedMax:this._speedAvailableMax;
		this._speedInput=(dataSpeedInput!==undefined)?dataSpeedInput:'constant';
		this._addSpeed=!(
			this._speedValue==0 &&
			this._speedMin==this._speedAvailableMin &&
			this._speedMax==this._speedAvailableMax &&
			this._speedInput=='constant'
		);
		this._speed$=null;
		this._$addSpeed=null;
	}
	updateInternalVisibility() {
		super.updateInternalVisibility();
		const notGamepad=['gamepad0','gamepad1','gamepad2','gamepad3'].indexOf(this._input)<0;
		if (this._speed$) this._speed$.toggle(
			this._addSpeed && notGamepad
		);
		if (this._$addSpeed) this._$addSpeed.toggle(notGamepad);
	}
	get addSpeed() {
		return this._addSpeed;
	}
	set addSpeed(addSpeed) {
		this._addSpeed=addSpeed;
		this.updateInternalVisibility();
		this.updateCallback();
	}
	get step() {
		if (this.availableMax>=100) {
			return '0.1';
		} else if (this.availableMax>=10) {
			return '0.01';
		} else {
			return '0.001';
		}
	}
	get availableInputTypes() {
		return ['constant','slider','mousemovex','mousemovey','gamepad0','gamepad1','gamepad2','gamepad3'];
	}
	get speed() {
		const option=this;
		return {
			get fullName() {
				return option.fullName+'.speed';
			},
			get defaultValue() {
				return 0;
			},
			get value() {
				return option._speedValue;
			},
			set value(value) {
				option._speedValue=value;
				option.updateCallback();
			},
			get input() {
				return option._speedInput;
			},
			set input(input) {
				option._speedInput=input;
				option.updateCallback();
			},
			get availableMin() {
				return option._speedAvailableMin;
			},
			get availableMax() {
				return option._speedAvailableMax;
			},
			get min() {
				return option._speedMin;
			},
			set min(min) {
				option._speedMin=min;
				option.updateCallback();
			},
			get max() {
				return option._speedMax;
			},
			set max(max) {
				option._speedMax=max;
				option.updateCallback();
			},
			get step() {
				return option.step;
			},
			get availableInputTypes() {
				return option.availableInputTypes;
			},
			get $() {
				return option._speed$;
			},
			set $($) {
				option._speed$=$;
				option.updateInternalVisibility();
			}
		};
	}
	get $addSpeed() {
		return this._$addSpeed;
	}
	set $addSpeed($addSpeed) {
		this._$addSpeed=$addSpeed;
		this.updateInternalVisibility();
	}
	export() {
		const notGamepad=['gamepad0','gamepad1','gamepad2','gamepad3'].indexOf(this.input)<0
		const data=this.exportHelper(this);
		if (notGamepad && this.addSpeed) {
			this.shortenExportAssign(this.exportHelper(this.speed),data,'speed');
		}
		return data;
	}
	fix() {
		const fixed=super.fix();
		const notGamepad=['gamepad0','gamepad1','gamepad2','gamepad3'].indexOf(this.input)<0
		if (notGamepad && this.addSpeed) {
			fixed.speed=new FixedLiveNumber(this.speed);
		} else {
			fixed.speed=new FixedLiveNumber(this.speed,true);
		}
		return fixed;
	}
}

class LiveColor extends Group {
	constructor(name,colorComponentDefaultValues,_,data,fullName,isVisible,updateCallback) {
		const cs='rgba';
		super(name,colorComponentDefaultValues.map((defaultValue,i)=>{
			const c=cs.charAt(i);
			let subData;
			if (typeof data == 'object') subData=data[c];
			return new LiveFloat(c,[0,1,-1,+1],defaultValue,subData,fullName+'.'+c,()=>true,updateCallback);
		}),undefined,undefined,fullName,isVisible,updateCallback);
	}
}

module.exports={};
for (let c in imports) {
	module.exports[c]=imports[c];
}
module.exports.LiveNumber=LiveNumber;
module.exports.LiveInt=LiveInt;
module.exports.CanvasLiveInt=CanvasLiveInt;
module.exports.LiveFloat=LiveFloat;
module.exports.LiveColor=LiveColor;
<commit_msg>updated option classes<commit_after>'use strict'

const Input=require('./input-classes')
const Option=Object.create(require('crnx-base/option-classes'))

class FixedLiveNumber {
	constructor(src,setToDefault) {
		if (!setToDefault) {
			this.value=src.value
			this.min=src.min
			this.max=src.max
			this.input=Input.createFromString(src.input)
		} else {
			this.value=src.defaultValue
			this.min=src.availableMin
			this.max=src.availableMax
			this.input=Input.createFromString('constant')
		}
		// needed for formatting and to decide on clamp()/wrap():
		this.availableMin=src.availableMin
		this.availableMax=src.availableMax
		this.step=src.step
	}
	valueOf() {
		return this.value
	}
	toString() {
		return String(this.value)
	}
}

// abstract classes

Option.LiveNumber = class extends Option.RangeInput {
	constructor(name,availableRange,defaultValue,data,fullName,isVisible,updateCallback) {
		let dataValue,dataMin,dataMax,dataInput
		if (typeof data == 'object') {
			dataValue=data.value
			dataMin  =data.min
			dataMax  =data.max
			dataInput=data.input
		} else {
			dataValue=data
		}
		super(name,availableRange,defaultValue,dataValue,fullName,isVisible,updateCallback)
		this._min=(dataMin!==undefined)?dataMin:this.availableMin
		this._max=(dataMax!==undefined)?dataMax:this.availableMax
		this._input=(dataInput!==undefined)?dataInput:'constant'
		this._$range=null
	}
	updateInternalVisibility() {
		if (this._$range) this._$range.toggle(this._input!='constant')
	}
	get input() {
		return this._input
	}
	set input(input) {
		this._input=input
		this.updateInternalVisibility()
		this.updateCallback()
	}
	get min() {
		return this._min
	}
	set min(min) {
		this._min=min
		this.updateCallback()
	}
	get max() {
		return this._max
	}
	set max(max) {
		this._max=max
		this.updateCallback()
	}
	get $range() {
		return this._$range
	}
	set $range($range) {
		this._$range=$range
		this.updateInternalVisibility()
	}
	exportHelper(src) {
		const data={}
		if (src.value!=src.defaultValue) data.value=src.value
		if (src.min!=src.availableMin) data.min=src.min
		if (src.max!=src.availableMax) data.max=src.max
		if (src.input!='constant') data.input=src.input
		return data
	}
	export() {
		return this.exportHelper(this)
	}
	fix() {
		const fixed=new FixedLiveNumber(this)
		fixed.name=this.name
		return fixed
	}
}

// concrete classes

Option.LiveInt = class extends Option.LiveNumber {
	get step() {
		return 1
	}
	get availableInputTypes() {
		return ['constant','slider','mousemovex','mousemovey']
	}
}

Option.CanvasLiveInt = class extends Option.LiveInt {
	get availableInputTypes() {
		return ['constant','slider']
	}
}

Option.LiveFloat = class extends Option.LiveNumber {
	constructor(name,availableRange,defaultValue,data,fullName,isVisible,updateCallback) {
		let dataSpeedValue,dataSpeedMin,dataSpeedMax,dataSpeedInput
		if (typeof data == 'object') {
			if (typeof data.speed == 'object') {
				dataSpeedValue=data.speed.value
				dataSpeedMin  =data.speed.min
				dataSpeedMax  =data.speed.max
				dataSpeedInput=data.speed.input
			} else {
				dataSpeedValue=data.speed
			}
		}
		super(...arguments)
		this._speedValue=(dataSpeedValue!==undefined)?dataSpeedValue:0
		this._speedAvailableMin=availableRange[2]; this._speedMin=(dataSpeedMin!==undefined)?dataSpeedMin:this._speedAvailableMin
		this._speedAvailableMax=availableRange[3]; this._speedMax=(dataSpeedMax!==undefined)?dataSpeedMax:this._speedAvailableMax
		this._speedInput=(dataSpeedInput!==undefined)?dataSpeedInput:'constant'
		this._addSpeed=!(
			this._speedValue==0 &&
			this._speedMin==this._speedAvailableMin &&
			this._speedMax==this._speedAvailableMax &&
			this._speedInput=='constant'
		)
		this._speed$=null
		this._$addSpeed=null
	}
	updateInternalVisibility() {
		super.updateInternalVisibility()
		const notGamepad=['gamepad0','gamepad1','gamepad2','gamepad3'].indexOf(this._input)<0
		if (this._speed$) this._speed$.toggle(
			this._addSpeed && notGamepad
		)
		if (this._$addSpeed) this._$addSpeed.toggle(notGamepad)
	}
	get addSpeed() {
		return this._addSpeed
	}
	set addSpeed(addSpeed) {
		this._addSpeed=addSpeed
		this.updateInternalVisibility()
		this.updateCallback()
	}
	get step() {
		if (this.availableMax>=100) {
			return '0.1'
		} else if (this.availableMax>=10) {
			return '0.01'
		} else {
			return '0.001'
		}
	}
	get availableInputTypes() {
		return ['constant','slider','mousemovex','mousemovey','gamepad0','gamepad1','gamepad2','gamepad3']
	}
	get speed() {
		const option=this
		return {
			get fullName() {
				return option.fullName+'.speed'
			},
			get defaultValue() {
				return 0
			},
			get value() {
				return option._speedValue
			},
			set value(value) {
				option._speedValue=value
				option.updateCallback()
			},
			get input() {
				return option._speedInput
			},
			set input(input) {
				option._speedInput=input
				option.updateCallback()
			},
			get availableMin() {
				return option._speedAvailableMin
			},
			get availableMax() {
				return option._speedAvailableMax
			},
			get min() {
				return option._speedMin
			},
			set min(min) {
				option._speedMin=min
				option.updateCallback()
			},
			get max() {
				return option._speedMax
			},
			set max(max) {
				option._speedMax=max
				option.updateCallback()
			},
			get step() {
				return option.step
			},
			get availableInputTypes() {
				return option.availableInputTypes
			},
			get $() {
				return option._speed$
			},
			set $($) {
				option._speed$=$
				option.updateInternalVisibility()
			}
		}
	}
	get $addSpeed() {
		return this._$addSpeed
	}
	set $addSpeed($addSpeed) {
		this._$addSpeed=$addSpeed
		this.updateInternalVisibility()
	}
	export() {
		const notGamepad=['gamepad0','gamepad1','gamepad2','gamepad3'].indexOf(this.input)<0
		const data=this.exportHelper(this)
		if (notGamepad && this.addSpeed) {
			this.shortenExportAssign(this.exportHelper(this.speed),data,'speed')
		}
		return data
	}
	fix() {
		const fixed=super.fix()
		const notGamepad=['gamepad0','gamepad1','gamepad2','gamepad3'].indexOf(this.input)<0
		if (notGamepad && this.addSpeed) {
			fixed.speed=new FixedLiveNumber(this.speed)
		} else {
			fixed.speed=new FixedLiveNumber(this.speed,true)
		}
		return fixed
	}
}

Option.LiveColor = class extends Option.Group {
	constructor(name,colorComponentDefaultValues,_,data,fullName,isVisible,updateCallback) {
		const cs='rgba'
		super(name,colorComponentDefaultValues.map((defaultValue,i)=>{
			const c=cs.charAt(i)
			let subData
			if (typeof data == 'object') subData=data[c]
			return new Option.LiveFloat(c,[0,1,-1,+1],defaultValue,subData,fullName+'.'+c,()=>true,updateCallback)
		}),undefined,undefined,fullName,isVisible,updateCallback)
	}
}

module.exports=Option
<|endoftext|>


<commit_before>module.exports = function(config) {
  config.set({
    browsers: ['PhantomJS2'],
    frameworks: ['jasmine', 'fixture'],
    reporters: ['spec'],
    plugins: [
        'karma-jasmine',
        'karma-fixture',
        'karma-html2js-preprocessor',
        'karma-phantomjs2-launcher',
        'karma-spec-reporter'
    ],
    preprocessors: {
      '**/*.html': ['html2js']
    },
    files: [
        'node_modules/promise-polyfill/Promise.js',
        'src/*.js',
        'test/spec/*',
        {pattern: 'test/fixture/*', included: false, served: true, nocache: false},
    ],
  });
};
<commit_msg>Fix casing of node_modules/promise-polyfill/promise.js<commit_after>module.exports = function(config) {
  config.set({
    browsers: ['PhantomJS2'],
    frameworks: ['jasmine', 'fixture'],
    reporters: ['spec'],
    plugins: [
        'karma-jasmine',
        'karma-fixture',
        'karma-html2js-preprocessor',
        'karma-phantomjs2-launcher',
        'karma-spec-reporter'
    ],
    preprocessors: {
      '**/*.html': ['html2js']
    },
    files: [
        'node_modules/promise-polyfill/promise.js',
        'src/*.js',
        'test/spec/*',
        {pattern: 'test/fixture/*', included: false, served: true, nocache: false},
    ],
  });
};
<|endoftext|>


<commit_before>if (!window.tm) window.tm = {};

tm.import = {

  importTabGroupsJson(json) {
    let data;
    try {
      data = JSON.parse(json);
      if (Array.isArray(data.windows)) {
        return data.windows.reduce((result, windowData) =>
          result.then(() => this.importWindows(windowData)),
          Promise.resolve());
      }
      return Promise.reject('Invalid JSON structure');
    } catch (e) {
      return Promise.reject('Unable to parse JSON', e);
    }
  },

  importWindows(data) {
    const groups = this.getGroupsData(data);
    const tabs = this.getTabsData(data);

    if (groups) {
      groups.forEach((group, i) => {
        groups[i].tabs = tabs.filter(t => t.groupId === group.id);
      });
      return this.importGroups(groups);
    }

    return Promise.resolve();
  },

  importGroups(groups) {
    return groups.reduce((result, group) =>
      result.then(() => tm.bookmarks.createFolder(group.title)
        .then(folder => this.importTabs(group.tabs, folder)),
              error => console.error(`Could not create folder for group "${group.title}"`, error)),
      Promise.resolve());
  },

  importTabs(tabs, folder) {
    return tabs.reduce((result, tab) =>
      result.then(() => tm.bookmarks.create(tab.title, tab.url, folder.id))
        .catch((error) => {
          console.error(`Could not create bookmark "${tab.url}" in group "${folder.id}"`, error);
        }),
      Promise.resolve());
  },

  getGroupsData(data) {
    if (data && data.extData && data.extData['tabview-group']) {
      try {
        const groups = JSON.parse(data.extData['tabview-group']);
        return Object.keys(groups).map(id => ({ id: parseInt(id, 10), title: groups[id].title }));
      } catch (e) {
        return null;
      }
    }
    return null;
  },

  getTabsData(data) {
    if (Array.isArray(data.tabs)) {
      return data.tabs
        .map(this.getTabData)
        .filter(t => t && t.url && t.url.indexOf('about:') !== 0);
    }
    return [];
  },

  getTabData(data) {
    if (Array.isArray(data.entries) && data.entries.length > 0) {
      const entry = data.entries[0];
      if (data && data.extData && data.extData['tabview-tab']) {
        try {
          const groupData = JSON.parse(data.extData['tabview-tab']);
          if (groupData && groupData.groupID != null) {
            return {
              title: entry.title,
              url: entry.url,
              groupId: parseInt(groupData.groupID, 10),
            };
          }
        } catch (e) {
          return null;
        }
      }
    }
    return null;
  },

};
<commit_msg>Fix linting issues<commit_after>if (!window.tm) window.tm = {};

tm.import = {

  importTabGroupsJson(json) {
    let data;
    try {
      data = JSON.parse(json);
      if (Array.isArray(data.windows)) {
        return data.windows.reduce((result, windowData) =>
          result.then(() => this.importWindows(windowData)),
        Promise.resolve());
      }
      return Promise.reject('Invalid JSON structure');
    } catch (e) {
      return Promise.reject('Unable to parse JSON', e);
    }
  },

  importWindows(data) {
    const groups = this.getGroupsData(data);
    const tabs = this.getTabsData(data);

    if (groups) {
      groups.forEach((group, i) => {
        groups[i].tabs = tabs.filter(t => t.groupId === group.id);
      });
      return this.importGroups(groups);
    }

    return Promise.resolve();
  },

  importGroups(groups) {
    return groups.reduce((result, group) =>
      result.then(() => tm.bookmarks.createFolder(group.title)
        .then(folder => this.importTabs(group.tabs, folder)),
      error => console.error(`Could not create folder for group "${group.title}"`, error)),
    Promise.resolve());
  },

  importTabs(tabs, folder) {
    return tabs.reduce((result, tab) =>
      result.then(() => tm.bookmarks.create(tab.title, tab.url, folder.id))
        .catch((error) => {
          console.error(`Could not create bookmark "${tab.url}" in group "${folder.id}"`, error);
        }),
    Promise.resolve());
  },

  getGroupsData(data) {
    if (data && data.extData && data.extData['tabview-group']) {
      try {
        const groups = JSON.parse(data.extData['tabview-group']);
        return Object.keys(groups).map(id => ({ id: parseInt(id, 10), title: groups[id].title }));
      } catch (e) {
        return null;
      }
    }
    return null;
  },

  getTabsData(data) {
    if (Array.isArray(data.tabs)) {
      return data.tabs
        .map(this.getTabData)
        .filter(t => t && t.url && t.url.indexOf('about:') !== 0);
    }
    return [];
  },

  getTabData(data) {
    if (Array.isArray(data.entries) && data.entries.length > 0) {
      const entry = data.entries[0];
      if (data && data.extData && data.extData['tabview-tab']) {
        try {
          const groupData = JSON.parse(data.extData['tabview-tab']);
          if (groupData && groupData.groupID != null) {
            return {
              title: entry.title,
              url: entry.url,
              groupId: parseInt(groupData.groupID, 10),
            };
          }
        } catch (e) {
          return null;
        }
      }
    }
    return null;
  },

};
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Tue Feb 09 2016 15:58:33 GMT-0700 (MST)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine', 'sinon-chrome'],

    // list of files / patterns to load in the browser
    files: [
      // 'app/**/*.js',
      'test/**/*-spec.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}
<commit_msg>Uncommented file that includes all JS files<commit_after>// Karma configuration
// Generated on Tue Feb 09 2016 15:58:33 GMT-0700 (MST)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine', 'sinon-chrome'],

    // list of files / patterns to load in the browser
    files: [
      'app/**/*.js',
      'test/**/*-spec.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}
<|endoftext|>


<commit_before>'use strict';

var cp = require('child_process');
var fs = require('fs.extra');
var _ = require('lodash');
var async = require('async');
var mongoose = require('mongoose');
var ncp = require('ncp');
var Simulation = mongoose.model('Simulation');
var swig = require('swig');

// translate from the db model for shocks into the string
// representations needed for the swig template
function writeShocks(shocks) {

    /// A shock has a name property that is used as a component of its variable name
    /// "name": "a",
    ///
    /// Shock ranges are specified as an array. For the time being there will not be more
    /// than two ranges specified. These shock ranges will be written as variables 1 and 2
    ///
    /// "ranges": [
    ///   {
    ///       "start": 0,
    ///       "end": 0,
    ///       "value": 0,
    ///   }
    /// ],
    ///
    /// Variable e_{{shock.name}}0 is represented by an array of valu
    /// "periods": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    ///

    /// return value used by swig template
    /// each object in return object array will have name, periods, and values string values
    var return_obj = { shocks: [] };

    /// bail if shocks is undefined, which should yield an octave error
    if (shocks === undefined) return return_obj;

    // iterate over shocks from simulation
    for (var i = 0; i < shocks.length; i++) {

        var shock = shocks[i];
        /// for each shock, create 6 return_obj entries needed for {{simulation.short_name}}_shocks.mod
        var pos = [], neg = [], periods = [];
        for (var j=0; i < shock.periods.length; i++){
            var value = shock.periods[j];
            periods.push(j+1);
            pos.push(value < 0 ? 0 : value);
            neg.push(value < 0 ? Math.abs(value) : 0);
        }
        periods = periods.join(' ');
        return_obj.shocks.push({ name: 'e_' + shock.name + '0', periods:periods, values:pos.join(' ') });
        return_obj.shocks.push({ name: 'e_' + shock.name + '0_neg', periods:periods, values:neg.join(' ') });

        for (var k=0; k < 2; k++){
            var start = 0, end = 0, range_value = 0;
            if (k < shock.ranges.length){
                var range = shock.ranges[k];
                start = range.start;
                end = range.end;
                range_value = range.value;
            }

            var r_variable_id = k + 1,
                r_periods = start + ':' + end,
                r_pos = range_value < 0 ? 0 : range_value,
                r_neg = range_value < 0 ? Math.abs(range_value) : 0;

            return_obj.shocks.push({ name: 'e_' + shock.name + r_variable_id, periods:r_periods, values:r_pos });
            return_obj.shocks.push({ name: 'e_' + shock.name + r_variable_id + '_neg', periods:r_periods, values:r_neg });
        }
    }

    return return_obj;
}

/**
 *
 * @param template_path
 * @param destination
 * @param obj
 * @param callback
 */
var writeVariableFile = function(template_path, destination, obj, callback){
    swig.renderFile(template_path, obj, function (error, output) {
        if (error) { callback(error, 'Failed to render template: ' + template_path); }
        else {
            fs.writeFile(destination, output, function (error) {
                callback(error, 'Writing variable file: ' + destination);
            });
        }
    });
};

/**
 *
 * @param model
 * @param simulation
 * @param cb
 */
var writeVariables = function (model, simulation, cb) {

    var model_definition_path = 'run/definitions/' + model.short_name;
    var simulation_path = 'run/simulations/' + simulation.id;
    var set_params_template_path = 'run/templates/set_params.m.html';
    var shocks_template_path = 'run/templates/shocks.mod.html';
    var set_macro_vars_template_path = 'run/templates/set_macro_vars.mod.html';
    var set_params_path = simulation_path + '/set_params_exp.m';
    var shocks_path = simulation_path + '/' + model.short_name + '_shocks.mod';
    var set_macro_vars_path = simulation_path + '/set_macro_vars.mod';

    console.log('-----' + simulation.dsf + '------');

    var set_macro_var_components = simulation.dsf.split(','); // this should really be cleaner!!
    var set_macro_vars = {
        exogenous: set_macro_var_components[0],
        endogenous_domestic : set_macro_var_components[1],
        endogenous_commercial : set_macro_var_components[2]
    };

    async.series([
        function (callback) {
            /// ensure that model definition directory exists
            fs.exists(model_definition_path, function (exists) {
                var error = exists ? null : new Error('Model definition path does not exist: ' + model_definition_path);
                callback(error, 'Verified model definition path.');
            });
        },
        function (callback) {
            /// ensure that simulation directory has been created
            /// from model definition directory
            fs.exists(simulation_path, function (exists) {
                if (exists) callback(null, 'Verified simulation path.');
                else {
                    ncp.ncp(model_definition_path, simulation_path, function (error) {
                        callback(error, 'Copied model definition to simulation path.');
                    });
                }
            });
        },
        function (callback) {
            /// write shocks.mod file
            var shocks = writeShocks(simulation.shocks);
            writeVariableFile(shocks_template_path, shocks_path, shocks, callback);
        },
        function (callback) {
            /// write set_macro_vars.mod file
            writeVariableFile(set_macro_vars_template_path, set_macro_vars_path, set_macro_vars, callback);
        },
        function (callback) {
            /// write set_params.m file
            writeVariableFile(set_params_template_path, set_params_path, simulation, callback);
        }
    ], cb);

};

exports.compute = function(req, res) {

    var socketio = req.app.get('socketio');
    var simulation = req.simulation;

    var simulation_path = 'run/simulations/' + simulation.id.toString();
    console.log('Begin to compute simulation: ' + simulation.id);

    writeVariables(simulation.model, simulation, function(error, results) {

        for (var i in results) console.log(results[i]);

        if (error) {
            console.log('Error: ', error);
            res.status(error.status).end();
        }
        else {
            // Production environment on Ubuntu does not require the
            // path to Dynare, but Mac OS X development machines do
            var octave;

            if (process.env.NODE_ENV === 'development') {
                var dynarePath = process.env.DYNARE_PATH || '';
                octave = cp.spawn(
                    'octave',
                    ['-p', dynarePath.toString(), '-q', 'run_model.m'],
                    {'cwd': simulation_path});
            } else {
                octave = cp.spawn(
                    'octave',
                    ['-q', 'run_model.m'],
                    {'cwd': simulation_path});
            }

            octave.on('error', function(err) {
                console.log('octave spawn error: ', err);
            });

            octave.stdout.on('data', function (data) {

                console.log('stdout: ' + data);
                socketio.sockets.emit('compute.' + req.simulation.id, data.toString());

            });

            octave.stderr.on('data', function (data) {

                socketio.sockets.emit('compute.' + req.simulation.id, data.toString());
                console.log('stderr: ' + data);

            });

            octave.on('close', function (code) {

                socketio.sockets.emit('compute.' + req.simulation.id, 'on:close:'+ code);
                console.log('child process exited with code ' + code);

            });

            res.send({message:'Started octave.'});

        }
    });
};
<commit_msg>Tested new writeShocks function and added _.isFinite validation defaulting to 0 when the value is NaN, Infinity or -Infinity.<commit_after>'use strict';

var cp = require('child_process');
var fs = require('fs.extra');
var _ = require('lodash');
var async = require('async');
var mongoose = require('mongoose');
var ncp = require('ncp');
var Simulation = mongoose.model('Simulation');
var swig = require('swig');

// translate from the db model for shocks into the string
// representations needed for the swig template
function writeShocks(shocks) {

    /// A shock has a name property that is used as a component of its variable name
    /// "name": "a",
    ///
    /// Shock ranges are specified as an array. For the time being there will not be more
    /// than two ranges specified. These shock ranges will be written as variables 1 and 2
    ///
    /// "ranges": [
    ///   {
    ///       "start": 0,
    ///       "end": 0,
    ///       "value": 0,
    ///   }
    /// ],
    ///
    /// Variable e_{{shock.name}}0 is represented by an array of valu
    /// "periods": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    ///

    /// return value used by swig template
    /// each object in return object array will have name, periods, and values string values
    var return_obj = { shocks: [] };

    console.log(shocks);

    /// bail if shocks is undefined, which should yield an octave error
    if (shocks === undefined) return return_obj;

    // iterate over shocks from simulation
    for (var i = 0; i < shocks.length; i++) {

        var shock = shocks[i];
        /// for each shock, create 6 return_obj entries needed for {{simulation.short_name}}_shocks.mod
        var pos = [], neg = [], periods = [];
        for (var j=0; j < shock.periods.length; j++){
            var value = shock.periods[j];
            value = _.isFinite(value) ? value : 0;
            periods.push(j+1);
            pos.push(value < 0 ? 0 : value);
            neg.push(value < 0 ? Math.abs(value) : 0);
        }
        periods = periods.join(' ');
        return_obj.shocks.push({ name: 'e_' + shock.name + '0', periods:periods, values:pos.join(' ') });
        return_obj.shocks.push({ name: 'e_' + shock.name + '0_neg', periods:periods, values:neg.join(' ') });

        for (var k=0; k < 2; k++){
            var start = 0, end = 0, range_value = 0;
            if (k < shock.ranges.length){
                var range = shock.ranges[k];
                start = _.isFinite(range.start) ? range.start : 0;
                end = _.isFinite(range.end) ? range.end : 0;
                range_value = range.value;
            }

            var r_variable_id = k + 1,
                r_periods = start + ':' + end,
                r_pos = range_value < 0 ? 0 : range_value,
                r_neg = range_value < 0 ? Math.abs(range_value) : 0;

            return_obj.shocks.push({ name: 'e_' + shock.name + r_variable_id, periods:r_periods, values:r_pos });
            return_obj.shocks.push({ name: 'e_' + shock.name + r_variable_id + '_neg', periods:r_periods, values:r_neg });
        }
    }

    console.log(return_obj);

    return return_obj;
}

/**
 *
 * @param template_path
 * @param destination
 * @param obj
 * @param callback
 */
var writeVariableFile = function(template_path, destination, obj, callback){
    swig.renderFile(template_path, obj, function (error, output) {
        if (error) { callback(error, 'Failed to render template: ' + template_path); }
        else {
            fs.writeFile(destination, output, function (error) {
                callback(error, 'Writing variable file: ' + destination);
            });
        }
    });
};

/**
 *
 * @param model
 * @param simulation
 * @param cb
 */
var writeVariables = function (model, simulation, cb) {

    var model_definition_path = 'run/definitions/' + model.short_name;
    var simulation_path = 'run/simulations/' + simulation.id;
    var set_params_template_path = 'run/templates/set_params.m.html';
    var shocks_template_path = 'run/templates/shocks.mod.html';
    var set_macro_vars_template_path = 'run/templates/set_macro_vars.mod.html';
    var set_params_path = simulation_path + '/set_params_exp.m';
    var shocks_path = simulation_path + '/' + model.short_name + '_shocks.mod';
    var set_macro_vars_path = simulation_path + '/set_macro_vars.mod';

    console.log('-----' + simulation.dsf + '------');

    var set_macro_var_components = simulation.dsf.split(','); // this should really be cleaner!!
    var set_macro_vars = {
        exogenous: set_macro_var_components[0],
        endogenous_domestic : set_macro_var_components[1],
        endogenous_commercial : set_macro_var_components[2]
    };

    async.series([
        function (callback) {
            /// ensure that model definition directory exists
            fs.exists(model_definition_path, function (exists) {
                var error = exists ? null : new Error('Model definition path does not exist: ' + model_definition_path);
                callback(error, 'Verified model definition path.');
            });
        },
        function (callback) {
            /// ensure that simulation directory has been created
            /// from model definition directory
            fs.exists(simulation_path, function (exists) {
                if (exists) callback(null, 'Verified simulation path.');
                else {
                    ncp.ncp(model_definition_path, simulation_path, function (error) {
                        callback(error, 'Copied model definition to simulation path.');
                    });
                }
            });
        },
        function (callback) {
            /// write shocks.mod file
            var shocks = writeShocks(simulation.shocks);
            writeVariableFile(shocks_template_path, shocks_path, shocks, callback);
        },
        function (callback) {
            /// write set_macro_vars.mod file
            writeVariableFile(set_macro_vars_template_path, set_macro_vars_path, set_macro_vars, callback);
        },
        function (callback) {
            /// write set_params.m file
            writeVariableFile(set_params_template_path, set_params_path, simulation, callback);
        }
    ], cb);

};

exports.compute = function(req, res) {

    var socketio = req.app.get('socketio');
    var simulation = req.simulation;

    var simulation_path = 'run/simulations/' + simulation.id.toString();
    console.log('Begin to compute simulation: ' + simulation.id);

    writeVariables(simulation.model, simulation, function(error, results) {

        for (var i in results) console.log(results[i]);

        if (error) {
            console.log('Error: ', error);
            res.status(error.status).end();
        }
        else {
            // Production environment on Ubuntu does not require the
            // path to Dynare, but Mac OS X development machines do
            var octave;

            if (process.env.NODE_ENV === 'development') {
                var dynarePath = process.env.DYNARE_PATH || '';
                octave = cp.spawn(
                    'octave',
                    ['-p', dynarePath.toString(), '-q', 'run_model.m'],
                    {'cwd': simulation_path});
            } else {
                octave = cp.spawn(
                    'octave',
                    ['-q', 'run_model.m'],
                    {'cwd': simulation_path});
            }

            octave.on('error', function(err) {
                console.log('octave spawn error: ', err);
            });

            octave.stdout.on('data', function (data) {

                console.log('stdout: ' + data);
                socketio.sockets.emit('compute.' + req.simulation.id, data.toString());

            });

            octave.stderr.on('data', function (data) {

                socketio.sockets.emit('compute.' + req.simulation.id, data.toString());
                console.log('stderr: ' + data);

            });

            octave.on('close', function (code) {

                socketio.sockets.emit('compute.' + req.simulation.id, 'on:close:'+ code);
                console.log('child process exited with code ' + code);

            });

            res.send({message:'Started octave.'});

        }
    });
};
<|endoftext|>


<commit_before>/**
    The MIT License (MIT)

    Copyright (c) 2015

    John Congote <jcongote@gmail.com>
    Felipe Calad
    Isabel Lozano
    Juan Diego Perez
    Joinner Ovalle

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

// var chatId = false;
var chatId = '111112';
var localStream, remoteStream, pc, ws;
$(document).ready(function() {
    ws = new WebSocket('ws://kladfelipe.koding.io:7000/ws/' + chatId);
    var configuration = {iceServers: [
        { url: 'stun:kladfelipe.koding.io:3478' },
        {
            url: 'turn:kladfelipe.koding.io:3978',
            username: 'turnserver',
            credential: 'hieKedq'
        }
    ]};
    var initiator;
    pc = new webkitRTCPeerConnection(configuration, {optional: [{RtpDataChannels: true}]});
    var channel;

    $(window).bind('beforeunload', function(){
        if (pc && pc.close) {
            pc.close();
        }
    });

    function initiatorCtrl(event) {
        console.log(event.data);
        if (event.data == "fullhouse") {
            alert("full house");
        }
        if (event.data == "initiator") {
            initiator = false;
            init();
        }
        if (event.data == "not initiator") {
            initiator = true;
            init();
        }
    }

    ws.onmessage = initiatorCtrl;

    function init() {
        if (initiator) {
            var channelOptions = { reliable: false };
            channel = pc.createDataChannel("chat"+chatId, channelOptions);
            channel.onmessage = function (evt) {
                console.info(evt);
                createMsg(false, evt.data);
            };

            channel.onopen = function (evt) {
                console.log("Channel " + channel.label + " is open");
                enableChatFields();
            };

            channel.onclose = function (evt) {
                console.log('RTCDataChannel closed.');
            };
        } else {
            pc.ondatachannel = function(evt){
                channel = evt.channel;
                channel.onopen = function () {
                    console.log("Channel " + channel.label + " is open");
                    enableChatFields();
                };
                channel.onmessage = function (evt) {
                    console.info(evt);
                    createMsg(false, evt.data);
                };
            };
        }
        connect();
    }

    function connect(stream) {
        pc.onaddstream = function(event) {
            console.log('REMOTE STREAM ADDED');
            remoteStream = event.stream;
            $('#remote').attachStream(event.stream);
            logStreaming(true);

            if (!localStream) {
                $('#video-btn').click();
            }
        };
        // pc.onremovestream = function(event) {
        //     $('#remote').removeStream(event.stream);
        //     logStreaming(false);
        // };

        pc.onicecandidate = function(event) {
            if (event.candidate) {
                ws.send(JSON.stringify(event.candidate));
            }
        };
        ws.onmessage = function (event) {
            var signal = JSON.parse(event.data);
            if (signal.sdp) {
                if (initiator) {
                    receiveAnswer(signal);
                } else {
                    receiveOffer(signal);
                }
            } else if (signal.candidate) {
                pc.addIceCandidate(new RTCIceCandidate(signal));
            }
        };

        if (initiator) {
            createOffer();
        } else {
            log('waiting for offer...');
        }
        logStreaming(false);
    }

    function enableVideo(stream) {
        if (stream) {
            localStream = stream;
            pc.addStream(stream);
            $('#local').attachStream(stream);
        }

        if (initiator) {
            createOffer();
        } else {
            ws.onmessage = function (event) {
                var signal = JSON.parse(event.data);
                if (signal.sdp) {
                        receiveOffer(signal);
                }
            };
            console.log("waiting for camera...");
        }

    }

    function createOffer() {
        log('creating offer...');
        pc.createOffer(function(offer) {
            log('created offer...');
            pc.setLocalDescription(offer, function() {
                log('sending to remote...');
                initiator = true;
                console.info(offer);
                ws.send(JSON.stringify(offer));
            }, fail);
        }, fail);
    }

    function receiveOffer(offer) {
        log('received offer...');
        pc.setRemoteDescription(new RTCSessionDescription(offer), function() {
            log('creating answer...');
            pc.createAnswer(function(answer) {
                log('created answer...');
                pc.setLocalDescription(answer, function() {
                    log('sent answer');
                    initiator = false;
                    console.info(answer);
                    ws.send(JSON.stringify(answer));
                }, fail);
            }, fail);
        }, fail);
    }

    function receiveAnswer(answer) {
        log('received answer');
        pc.setRemoteDescription(new RTCSessionDescription(answer));
    }

    function log() {
        $('#status').text(Array.prototype.join.call(arguments, ' '));
        console.log.apply(console, arguments);
    }

    function logStreaming(streaming) {
        $('#streaming').text(streaming ? '[streaming]' : '[..]');
    }

    function fail() {
        if (arguments[0].name == "PermissionDeniedError") {
            alert("No permitiste compartir multimedia");
        } else {
            $('#status').text(Array.prototype.join.call(arguments, ' '));
            $('#status').addClass('error');
            console.error.apply(console, arguments);
        }
    }

    function sendChatMessage() {
        channel.send($("#msg").val());
        createMsg(true, $("#msg").val());
        $("#msg").val("");
    }

    $("#sendChatBtn").on('click', function() {
        sendChatMessage();
    });

    jQuery.fn.attachStream = function(stream) {
        this.each(function() {
            this.src = URL.createObjectURL(stream);
            this.play();
        });
    };

    $('#video-btn').click(function(event) {
        if (!$(this).hasClass('active')) {
            MediaStreamTrack.getSources(function (media_sources) {
                var constraints = {};
                for (var i = 0; i < media_sources.length; i++) {
                    var media_source = media_sources[i];

                    // if audio device
                    if (media_source.kind == 'audio') {
                        constraints.audio = true;
                    }

                    // if video device
                    if (media_source.kind == 'video') {
                        constraints.video = true;
                    }
                }

                getUserMedia(constraints, enableVideo, fail);
            });
        } else {
            if (pc && pc.close) {
                pc.close();
            }
        }

        $('#videochat').slideToggle();
        $(this).toggleClass('active');
    });
});

function randomString() {
    var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
    var string_length = 8;
    var randomstring = '';
    for (var i=0; i<string_length; i++) {
        var rnum = Math.floor(Math.random() * chars.length);
        randomstring += chars.substring(rnum,rnum+1);
    }
    return randomstring;
}

function createMsg(localUser, msg) {
    var containerClass;
    if (!localUser) {
        containerClass = 'bubble-left';
    } else {
        containerClass = 'bubble-right';
    }

    $msgContainer = $("
").addClass('bubble').addClass(containerClass).html("

" + msg);

    $("#textchat").append($msgContainer);
}

function enableChatFields() {
    $("#msg").prop('disabled', false);
    $("#sendChatBtn").prop('disabled', false);
}<commit_msg>Corrección para que le salga el video de la otra persona al que no inicio la invitación de video<commit_after>/**
    The MIT License (MIT)

    Copyright (c) 2015

    John Congote <jcongote@gmail.com>
    Felipe Calad
    Isabel Lozano
    Juan Diego Perez
    Joinner Ovalle

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

// var chatId = false;
var chatId = '111112';
var localStream, remoteStream, pc, ws;
$(document).ready(function() {
    ws = new WebSocket('ws://kladfelipe.koding.io:7000/ws/' + chatId);
    var configuration = {iceServers: [
        { url: 'stun:kladfelipe.koding.io:3478' },
        {
            url: 'turn:kladfelipe.koding.io:3978',
            username: 'turnserver',
            credential: 'hieKedq'
        }
    ]};
    var initiator;
    pc = new webkitRTCPeerConnection(configuration, {optional: [{RtpDataChannels: true}]});
    var channel;

    $(window).bind('beforeunload', function(){
        if (pc && pc.close) {
            pc.close();
        }
    });

    function initiatorCtrl(event) {
        console.log(event.data);
        if (event.data == "fullhouse") {
            alert("full house");
        }
        if (event.data == "initiator") {
            initiator = false;
            init();
        }
        if (event.data == "not initiator") {
            initiator = true;
            init();
        }
    }

    ws.onmessage = initiatorCtrl;

    function init() {
        if (initiator) {
            var channelOptions = { reliable: false };
            channel = pc.createDataChannel("chat"+chatId, channelOptions);
            channel.onmessage = function (evt) {
                console.info(evt);
                createMsg(false, evt.data);
            };

            channel.onopen = function (evt) {
                console.log("Channel " + channel.label + " is open");
                enableChatFields();
            };

            channel.onclose = function (evt) {
                console.log('RTCDataChannel closed.');
            };
        } else {
            pc.ondatachannel = function(evt){
                channel = evt.channel;
                channel.onopen = function () {
                    console.log("Channel " + channel.label + " is open");
                    enableChatFields();
                };
                channel.onmessage = function (evt) {
                    console.info(evt);
                    createMsg(false, evt.data);
                };
            };
        }
        connect();
    }

    function connect(stream) {
        pc.onaddstream = function(event) {
            console.log('REMOTE STREAM ADDED');
            remoteStream = event.stream;
            $('#remote').attachStream(event.stream);
            logStreaming(true);

            if (!localStream) {
                $('#video-btn').click();
            }
        };
        // pc.onremovestream = function(event) {
        //     $('#remote').removeStream(event.stream);
        //     logStreaming(false);
        // };

        pc.onicecandidate = function(event) {
            if (event.candidate) {
                ws.send(JSON.stringify(event.candidate));
            }
        };
        ws.onmessage = function (event) {
            var signal = JSON.parse(event.data);
            if (signal.sdp) {
                if (initiator) {
                    receiveAnswer(signal);
                } else {
                    receiveOffer(signal);
                }
            } else if (signal.candidate) {
                pc.addIceCandidate(new RTCIceCandidate(signal));
            }
        };

        if (initiator) {
            createOffer();
        } else {
            log('waiting for offer...');
        }
        logStreaming(false);
    }

    function enableVideo(stream) {
        if (stream) {
            localStream = stream;
            pc.addStream(stream);
            $('#local').attachStream(stream);
        }

        createOffer();
    }

    function createOffer() {
        log('creating offer...');
        pc.createOffer(function(offer) {
            log('created offer...');
            pc.setLocalDescription(offer, function() {
                log('sending to remote...');
                initiator = true;
                console.info(offer);
                ws.send(JSON.stringify(offer));
            }, fail);
        }, fail);
    }

    function receiveOffer(offer) {
        log('received offer...');
        pc.setRemoteDescription(new RTCSessionDescription(offer), function() {
            log('creating answer...');
            pc.createAnswer(function(answer) {
                log('created answer...');
                pc.setLocalDescription(answer, function() {
                    log('sent answer');
                    initiator = false;
                    console.info(answer);
                    ws.send(JSON.stringify(answer));
                }, fail);
            }, fail);
        }, fail);
    }

    function receiveAnswer(answer) {
        log('received answer');
        pc.setRemoteDescription(new RTCSessionDescription(answer));
    }

    function log() {
        $('#status').text(Array.prototype.join.call(arguments, ' '));
        console.log.apply(console, arguments);
    }

    function logStreaming(streaming) {
        $('#streaming').text(streaming ? '[streaming]' : '[..]');
    }

    function fail() {
        if (arguments[0].name == "PermissionDeniedError") {
            alert("No permitiste compartir multimedia");
        } else {
            $('#status').text(Array.prototype.join.call(arguments, ' '));
            $('#status').addClass('error');
            console.error.apply(console, arguments);
        }
    }

    function sendChatMessage() {
        channel.send($("#msg").val());
        createMsg(true, $("#msg").val());
        $("#msg").val("");
    }

    $("#sendChatBtn").on('click', function() {
        sendChatMessage();
    });

    jQuery.fn.attachStream = function(stream) {
        this.each(function() {
            this.src = URL.createObjectURL(stream);
            this.play();
        });
    };

    $('#video-btn').click(function(event) {
        if (!$(this).hasClass('active')) {
            MediaStreamTrack.getSources(function (media_sources) {
                var constraints = {};
                for (var i = 0; i < media_sources.length; i++) {
                    var media_source = media_sources[i];

                    // if audio device
                    if (media_source.kind == 'audio') {
                        constraints.audio = true;
                    }

                    // if video device
                    if (media_source.kind == 'video') {
                        constraints.video = true;
                    }
                }

                getUserMedia(constraints, enableVideo, fail);
            });
        } else {
            if (pc && pc.close) {
                pc.close();
            }
        }

        $('#videochat').slideToggle();
        $(this).toggleClass('active');
    });
});

function randomString() {
    var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
    var string_length = 8;
    var randomstring = '';
    for (var i=0; i<string_length; i++) {
        var rnum = Math.floor(Math.random() * chars.length);
        randomstring += chars.substring(rnum,rnum+1);
    }
    return randomstring;
}

function createMsg(localUser, msg) {
    var containerClass;
    if (!localUser) {
        containerClass = 'bubble-left';
    } else {
        containerClass = 'bubble-right';
    }

    $msgContainer = $("
").addClass('bubble').addClass(containerClass).html("

" + msg);

    $("#textchat").append($msgContainer);
}

function enableChatFields() {
    $("#msg").prop('disabled', false);
    $("#sendChatBtn").prop('disabled', false);
}<|endoftext|>


<commit_before>var webpack = require('webpack');
// TODO: use BowerWebpackPlugin
// var BowerWebpackPlugin = require('bower-webpack-plugin');
var webpackCommon = require('./webpack.common.config.js');

// Put in separate file?
var webpackTestConfig = {
    devtool: 'inline-source-map',
    plugins: [
       new webpack.ResolverPlugin(
            new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin('bower.json', ['main'])
        ),

        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            'window.$': 'jquery'
        }),
    ],
    resolve: webpackCommon.resolve,
    externals: {'jquery': 'jQuery', 'jquery-ui': 'jQuery.ui'},
    module: {
        loaders: [
            // Assume test files are ES6
            {test: /\.test\.js$/, loader: 'babel-loader'},
        ]
    }
};

module.exports = function (config) {
    config.set({
        browsers: ['PhantomJS'],
        frameworks: ['mocha', 'sinon'],
        files: [
            'website/static/vendor/bower_components/jquery/dist/jquery.js',
            'website/static/vendor/bower_components/jquery-ui/ui/jquery-ui.js',
            // Only need to target one file, which will load all files in tests/ that
            // match *.test.js
            'website/static/js/tests/tests.webpack.js',
        ],
        reporters: ['spec'],
        preprocessors: {
            // add webpack as preprocessor
            'website/static/js/tests/tests.webpack.js': ['webpack', 'sourcemap'],
        },
        webpack: webpackTestConfig,
        webpackServer: {
            noInfo: true // don't spam the console
        }
    });
};
<commit_msg>Use the same loaders in tests as in webpack.common.config.js<commit_after>var webpack = require('webpack');
// TODO: use BowerWebpackPlugin
// var BowerWebpackPlugin = require('bower-webpack-plugin');
var webpackCommon = require('./webpack.common.config.js');

// Put in separate file?
var webpackTestConfig = {
    devtool: 'inline-source-map',
    plugins: [
       new webpack.ResolverPlugin(
            new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin('bower.json', ['main'])
        ),

        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            'window.$': 'jquery'
        }),
    ],
    resolve: webpackCommon.resolve,
    externals: {'jquery': 'jQuery', 'jquery-ui': 'jQuery.ui'},
    module: {
        loaders: webpackCommon.module.loaders.concat([
            // Assume test files are ES6
            {test: /\.test\.js$/, loader: 'babel-loader'},
        ])
    }
};

module.exports = function (config) {
    config.set({
        browsers: ['PhantomJS'],
        frameworks: ['mocha', 'sinon'],
        files: [
            'website/static/vendor/bower_components/jquery/dist/jquery.js',
            'website/static/vendor/bower_components/jquery-ui/ui/jquery-ui.js',
            // Only need to target one file, which will load all files in tests/ that
            // match *.test.js
            'website/static/js/tests/tests.webpack.js',
        ],
        reporters: ['spec'],
        preprocessors: {
            // add webpack as preprocessor
            'website/static/js/tests/tests.webpack.js': ['webpack', 'sourcemap'],
        },
        webpack: webpackTestConfig,
        webpackServer: {
            noInfo: true // don't spam the console
        }
    });
};
<|endoftext|>


<commit_before>/* eslint-env node */
"use strict";

//
// karma-typescript-preprocessor does not support loading a tsconfig.json. There
// is an old issue saying it can but probably the TS API changed and it no
// longer works properly.
//
// karma-typescript-preprocessor2 has issues with supporting recent TS:
//
// - The gulp-typescript it uses will load a local typescript. This local
//   typescript must be removed.
//
// - The gulp-typescript it uses does not support "extends".
//

module.exports = function configure(config) {
  const coverage = !config.debug ? ["coverage"] : [];
  config.set({
    basePath: "",
    frameworks: ["mocha", "chai"],
    client: {
      mocha: {
        grep: config.grep,
      },
    },
    files: [
      "node_modules/core-js/client/core.js",
      //
      // All the stuff after "zone" is needed to get Angular component tests to
      // run. Note that we flatten this with a reduce at the end of the top
      // array.
      //
      // And we map an array rather than rely on patterns because the matches
      // from a pattern are ordered alphabetically but the order here matters
      // (and is not alphabetical).
      //
      ["zone", "long-stack-trace-zone", "proxy", "sync-test",
       "async-test", "fake-async-test", "mocha-patch"].map(
                    (x) => `node_modules/zone.js/dist/${x}.js`),
      "build/standalone/lib/external/classList.js",
      "build/standalone/lib/wed/polyfills/contains.js",
      "build/standalone/lib/wed/polyfills/matches.js",
      "build/standalone/lib/wed/polyfills/innerHTML_for_XML.js",
      "node_modules/systemjs/dist/system.src.js",
      "build/standalone/lib/system.config.js",
      "web/test/karma-main.js",
      { pattern: "web/test/**/*.ts", included: false },
      { pattern: "build/standalone/lib/**/*.@(js|html|map|css)",
        included: false },
      { pattern: "node_modules/{*,*/*,*/*/*}/package.json",
        included: false },
      { pattern: "node_modules/bluebird/js/browser/bluebird.js",
        included: false },
      { pattern: "node_modules/chai-as-promised/lib/chai-as-promised.js",
        included: false },
      { pattern: "node_modules/check-error/check-error.js",
        included: false },
      { pattern: "node_modules/dexie/dist/dexie.js",
        included: false },
      { pattern: "node_modules/jquery/dist/jquery.js",
        included: false },
      { pattern: "node_modules/bootstrap/dist/js/bootstrap.js",
        included: false },
      { pattern: "node_modules/blueimp-md5/js/md5.js",
        included: false },
      { pattern: "node_modules/@angular/**/*.js",
        included: false },
      { pattern: "node_modules/rxjs/**/*.js",
        included: false },
      { pattern: "node_modules/rxjs/package.json",
        included: false },
      { pattern: "node_modules/bootbox/bootbox.js",
        included: false },
      { pattern: "node_modules/sinon/lib/**/*.js",
        included: false },
      { pattern: "node_modules/sinon-chai/lib/**/*.js",
        included: false },
    ].reduce((acc, x) => acc.concat(x), []),
    exclude: [],
    preprocessors: {
      "web/test/**/*.ts": ["typescript"],
      "build/standalone/lib/dashboard.js": coverage,
      "build/standalone/lib/dashboard/**/!(*.map).js": coverage,
    },
    typescriptPreprocessor: {
      tsconfigPath: "./web/test/tsconfig.json",
      compilerOptions: {
        typescript: require("typescript"),
        sourceMap: false,
        // We have to have them inline for the browser to find them.
        inlineSourceMap: true,
        inlineSources: true,
      },
      // transformPath: (path) => path.replace(/\.ts$/, ".js"),
    },
    reporters: ["progress", "coverage", "remap-coverage"],
    coverageReporter: {
      type: "in-memory",
    },
    remapCoverageReporter: {
      html: "coverage/karma",
    },
    remapOptions: {
      basePath: "web/dashboard/",
    },
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ["Chrome"],
    singleRun: false,
    concurrency: Infinity,
  });
};
<commit_msg>Use a middleware to serve from node_modules.<commit_after>/* eslint-env node */
"use strict";

const serveStatic = require("serve-static");

//
// karma-typescript-preprocessor does not support loading a tsconfig.json. There
// is an old issue saying it can but probably the TS API changed and it no
// longer works properly.
//
// karma-typescript-preprocessor2 has issues with supporting recent TS:
//
// - The gulp-typescript it uses will load a local typescript. This local
//   typescript must be removed.
//
// - The gulp-typescript it uses does not support "extends".
//

function makeServeMiddleware(config) {
  const serve = serveStatic("./node_modules", {
    index: false,
  });

  const baseURL = "/base/node_modules/";
  return function (req, resp, next) {
    if (req.url.lastIndexOf(baseURL, 0) === 0) {
      req.url = req.url.slice(baseURL.length);
      serve(req, resp, next);
    }
    else {
      next();
    }
  };
}

module.exports = function configure(config) {
  const coverage = !config.debug ? ["coverage"] : [];
  config.set({
    basePath: "",
    frameworks: ["mocha", "chai"],
    middleware: ["serve-node-modules"],
    plugins: [
      "karma-*", // This is the default, which we need to keep here.
      { "middleware:serve-node-modules": ["factory", makeServeMiddleware] },
    ],
    client: {
      mocha: {
        grep: config.grep,
      },
    },
    files: [
      "node_modules/core-js/client/core.js",
      //
      // All the stuff after "zone" is needed to get Angular component tests to
      // run. Note that we flatten this with a reduce at the end of the top
      // array.
      //
      // And we map an array rather than rely on patterns because the matches
      // from a pattern are ordered alphabetically but the order here matters
      // (and is not alphabetical).
      //
      ["zone", "long-stack-trace-zone", "proxy", "sync-test",
       "async-test", "fake-async-test", "mocha-patch"].map(
                    (x) => `node_modules/zone.js/dist/${x}.js`),
      "build/standalone/lib/external/classList.js",
      "build/standalone/lib/wed/polyfills/contains.js",
      "build/standalone/lib/wed/polyfills/matches.js",
      "build/standalone/lib/wed/polyfills/innerHTML_for_XML.js",
      "node_modules/systemjs/dist/system.src.js",
      "build/standalone/lib/system.config.js",
      "web/test/karma-main.js",
      { pattern: "web/test/**/*.ts", included: false },
      { pattern: "web/test/mmwp-data/**/*", included: false },
      { pattern: "build/standalone/lib/**/*.@(js|html|map|css)",
        included: false },
      // { pattern: "node_modules/{*,*/*,*/*/*}/package.json", included: false },
      // { pattern: "node_modules/bluebird/js/browser/bluebird.js",
      //   included: false },
      // { pattern: "node_modules/chai-as-promised/lib/chai-as-promised.js",
      //   included: false },
      // { pattern: "node_modules/check-error/check-error.js", included: false },
      // { pattern: "node_modules/dexie/dist/dexie.js", included: false },
      // { pattern: "node_modules/jquery/dist/jquery.js", included: false },
      // { pattern: "node_modules/bootstrap/dist/js/bootstrap.js", included: false },
      // { pattern: "node_modules/blueimp-md5/js/md5.js", included: false },
      // { pattern: "node_modules/@angular/**/*.js", included: false },
      // { pattern: "node_modules/rxjs/**/*.js", included: false },
      // { pattern: "node_modules/rxjs/package.json", included: false },
      // { pattern: "node_modules/bootbox/bootbox.js", included: false },
      // { pattern: "node_modules/sinon/lib/**/*.js", included: false },
      // { pattern: "node_modules/sinon-chai/lib/**/*.js", included: false },
      // { pattern: "node_modules/bluejax/index.js", included: false },
      // { pattern: "node_modules/bluejax.try/index.js", included: false },
      // { pattern: "node_modules/salve/salve.js", included: false },
      // { pattern: "node_modules/salve-dom/salve-dom.js", included: false },
      // { pattern: "node_modules/slug/slug.js", included: false },
      // { pattern: "node_modules/systemjs-plugin-json/json.js", included: false },
      // { pattern: "node_modules/rangy/lib/rangy-core.js", included: false },
    ].reduce((acc, x) => acc.concat(x), []),
    exclude: [],
    preprocessors: {
      "web/test/**/*.ts": ["typescript"],
      "build/standalone/lib/dashboard.js": coverage,
      "build/standalone/lib/dashboard/**/!(*.map).js": coverage,
    },
    typescriptPreprocessor: {
      tsconfigPath: "./web/test/tsconfig.json",
      compilerOptions: {
        typescript: require("typescript"),
        sourceMap: false,
        // We have to have them inline for the browser to find them.
        inlineSourceMap: true,
        inlineSources: true,
      },
      // transformPath: (path) => path.replace(/\.ts$/, ".js"),
    },
    reporters: ["progress", "coverage", "remap-coverage"],
    coverageReporter: {
      type: "in-memory",
    },
    remapCoverageReporter: {
      html: "coverage/karma",
    },
    remapOptions: {
      basePath: "web/dashboard/",
    },
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ["Chrome"],
    singleRun: false,
    concurrency: Infinity,
  });
};
<|endoftext|>


<commit_before>/*globals module */

/**
 * @license angular-bootstrap-datetimepicker
 * (c) 2013 Knight Rider Consulting, Inc. http://www.knightrider.com
 * License: MIT
 */

/**
 *
 *    @author        Dale "Ducky" Lotts
 *    @since        7/21/13
 */

module.exports = function (config) {
  'use strict';
  config.set({

    frameworks: ['jasmine'],

    files: [
      'bower_components/jquery/jquery.js',
      'bower_components/moment/moment.js',
      'bower_components/bootstrap/docs/assets/js/bootstrap.js',
      'bower_components/angular/angular.js',
      'bower_components/angular-mocks/angular-mocks.js',
      'src/js/datetimepicker.js',
      'test/*.spec.js'
    ],

    // list of files to exclude
    exclude: [

    ],

    preprocessors: {
      '**/src/js/*.js': ['coverage']
    },

    // test results reporter to use
    // possible values: 'dots', 'progress', 'junit'
    reporters: ['progress', 'coverage'],

    coverageReporter: {
      type : 'html',
      dir : 'coverage/'
    },

    // web server port
    port: 9876,

    // cli runner port
    runnerPort: 9100,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Chrome'],

    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: true
  });
};<commit_msg>Fix path to java script files in src<commit_after>/*globals module */

/**
 * @license angular-bootstrap-datetimepicker
 * (c) 2013 Knight Rider Consulting, Inc. http://www.knightrider.com
 * License: MIT
 */

/**
 *
 *    @author        Dale "Ducky" Lotts
 *    @since        7/21/13
 */

module.exports = function (config) {
  'use strict';
  config.set({

    frameworks: ['jasmine'],

    files: [
      'bower_components/jquery/jquery.js',
      'bower_components/moment/moment.js',
      'bower_components/bootstrap/docs/assets/js/bootstrap.js',
      'bower_components/angular/angular.js',
      'bower_components/angular-mocks/angular-mocks.js',
      'src/js/datetimepicker.js',
      'test/*.spec.js'
    ],

    // list of files to exclude
    exclude: [

    ],

    preprocessors: {
      'src/js/*.js': ['coverage']
    },

    // test results reporter to use
    // possible values: 'dots', 'progress', 'junit'
    reporters: ['progress', 'coverage'],

    coverageReporter: {
      type: 'html',
      dir: 'coverage/'
    },

    // web server port
    port: 9876,

    // cli runner port
    runnerPort: 9100,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Chrome'],

    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: true
  });
};<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Match = mongoose.model('Match'),
	User = mongoose.model('User'),
	Court = mongoose.model('Court'),
	_ = require('lodash');

/**
 * Create a Match
 */
exports.create = function(req, res) {
	var match = new Match();
	console.log(req.body.spieler[1].user);
	User.findOne(req.body.spieler[1].user, function(err, spieler){
		match.spieler.push({user: req.user});
		match.spieler.push({user: spieler});
		Court.findOne(req.body.court, function(err, court){
			match.court = court;
			match.proposedTimes = req.body.proposedTimes;
			match.sport = req.body.sport;
			match.state = req.body.state;
			match.propBy = req.user;
			match.save(function(err) {
				if (err) {
					return res.status(400).send({
						message: errorHandler.getErrorMessage(err)
					});
				} else {
					res.jsonp(match);
				}
			});
		});
	});

};

/**
 * Show the current Match
 */
exports.read = function(req, res) {
	res.jsonp(req.match);
};

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

	match = _.extend(match , req.body);
	if(req.body.state == 'r2c'){
		match.r2cBy = req.user;
	}else{
		match.propBy = req.user;
	}

	match.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(match);
		}
	});
};

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

	match.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(match);
		}
	});
};

/**
 * List of Matches
 */
exports.list = function(req, res) {

	Match.find({'spieler.user': req.user}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listNew = function(req, res) {
	Match.find({'spieler.user': req.user, state: 'new', propBy: { $ne: req.user}}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listChange = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'proposed', propBy: { $ne: req.user}}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listInProgress = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'progress'}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.rtwoc = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'r2c', r2cBy: { $ne: req.user}}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listOpen = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'open'}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listDone = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'done'}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
/**
 * Match middleware
 */
exports.matchByID = function(req, res, next, id) {
	Match.findById(id).populate('spieler court propsedTimes').exec(function(err, match) {
		User.populate(match, {path: 'spieler.user'}, function (err, user) {

			if (err) return next(err);
			if (!match) return next(new Error('Failed to load Match ' + id));
			req.match = match;
			next();
		});
	});
};

/**
 * Match authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.match.spieler.indexOf(req.user)>-1) {
		return res.status(403).send('User is not authorized');
	}
	next();
};
<commit_msg>restrict modification access by API<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Match = mongoose.model('Match'),
	User = mongoose.model('User'),
	Court = mongoose.model('Court'),
	_ = require('lodash');

/**
 * Create a Match
 */
exports.create = function(req, res) {
	var match = new Match();
	console.log(req.body.spieler[1].user);
	User.findOne(req.body.spieler[1].user, function(err, spieler){
		match.spieler.push({user: req.user});
		match.spieler.push({user: spieler});
		Court.findOne(req.body.court, function(err, court){
			match.court = court;
			match.proposedTimes = req.body.proposedTimes;
			match.sport = req.body.sport;
			match.state = req.body.state;
			match.propBy = req.user;
			match.save(function(err) {
				if (err) {
					return res.status(400).send({
						message: errorHandler.getErrorMessage(err)
					});
				} else {
					res.jsonp(match);
				}
			});
		});
	});

};

/**
 * Show the current Match
 */
exports.read = function(req, res) {
	res.jsonp(req.match);
};

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

	match = _.extend(match , req.body);
	if(req.body.state == 'r2c'){
		match.r2cBy = req.user;
	}else{
		match.propBy = req.user;
	}

	match.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(match);
		}
	});
};

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

	match.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(match);
		}
	});
};

/**
 * List of Matches
 */
exports.list = function(req, res) {

	Match.find({'spieler.user': req.user}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listNew = function(req, res) {
	Match.find({'spieler.user': req.user, state: 'new', propBy: { $ne: req.user}}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listChange = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'proposed', propBy: { $ne: req.user}}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listInProgress = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'progress'}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.rtwoc = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'r2c', r2cBy: { $ne: req.user}}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listOpen = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'open'}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
exports.listDone = function(req, res) {
	var user = req.user;
	Match.find({'spieler.user': req.user, state: 'done'}).sort('-created').populate('spieler court').exec(function(err, matches) {
		User.populate(matches, {path: 'spieler.user'}, function (err, user) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				res.jsonp(matches);
			}
		});
	});
};
/**
 * Match middleware
 */
exports.matchByID = function(req, res, next, id) {
	Match.findById(id).populate('spieler court propsedTimes').exec(function(err, match) {
		User.populate(match, {path: 'spieler.user'}, function (err, user) {

			if (err) return next(err);
			if (!match) return next(new Error('Failed to load Match ' + id));
			req.match = match;
			next();
		});
	});
};

/**
 * Match authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	Match.findById(req.match._id).populate('spieler court propsedTimes').exec(function(err, match) {
		User.populate(match, {path: 'spieler.user'}, function (err, user) {
			console.log(match.r2cBy + req.user._id);

			if (!match) return res.status(404).send('Match not valid');

			if (match.spieler.indexOf(req.user)>-1) {

				return res.status(403).send('User is not authorized');
			}
			if(match.state === 'r2c'&&req.user._id == match.r2cBy){

				return res.status(403).send('User is not authorized');
			}
			else if(req.user._id == match.propBy){
				return res.status(403).send('User is not authorized');
			}
			next()
		});
	});
	;
};
<|endoftext|>