<commit_before>export default class PlayerController {
	constructor($rootScope, $scope, $log, $uibModal, _, toastr, playersApi, playerModel, websocket) {
		'ngInject';

		this.$rootScope = $rootScope;
		this.$scope = $scope;
		this.$log = $log.getInstance(this.constructor.name);
		this.$uibModal = $uibModal;

		this._ = _;
		this.toastr = toastr;

		this.playerModel = playerModel; // Used in template
		this.playersApi = playersApi;
		this.ws = websocket;

		this.$log.debug('constructor()', this);
	}

	$onInit() {
		this.$log.debug('$onInit()', this);

		this.$rootScope.$on('deck:action:winter', () => {
			this.$log.debug('deck:action:winter');

			if (this.player.id === this.playerModel.model.player.id) {
				this.playerModel.showSpecialCards();
			}
		});
	}

	$onDestroy() {
		this.$log.debug('$onDestroy()', this);
	}

	canStoreCards(cardsSelected) {
		if (this.game.actionCard || !cardsSelected || cardsSelected.length !== 3) {
			return false;
		}

		let cardsMatch = this._.reduce(cardsSelected, (prev, current, index, array) => {
			let len = array.length,
				sameCard = prev.amount === current.amount;

			if (!prev) {
				// If the previous object is 'false', then cards don't match
				return false;
			} else if (sameCard && index === len - 1) {
				// Reached the end of the array and all values matched
				return true;
			}

			return sameCard ? current : false;
		});

		return cardsMatch;
	}

	getCurrentPlayer() {
		return this.playerModel.model.player;
	}

	onStorageClick(evt) {
		let cardsSelected = this.player.cardsSelected;

		this.$log.debug('onStorageClick()', evt, cardsSelected, this);

		evt.preventDefault();

		if (this.player.isActive && this.player.hasDrawnCard && this.canStoreCards(cardsSelected)) {
			this.storeCards(cardsSelected);
		} else {
			this.showStorage(this.player);
		}
	}

	onStorageAutoClick(evt) {
		evt.preventDefault();

		if (this.player.isActive && !this.player.isFirstTurn) {
			// Filter out sets of 3 that have the same 'amount'
			this.playerModel.getCards()
				.then(res => {
					let cards = this._.filter(res.data, (o) => {
							return o.cardType === 'number';
						}),
						numberCards = this._.groupBy(cards, (o) => {
							return o.amount;
						}),
						isStored = false;

					this.$log.debug('numberCards -> ', numberCards);

					this._.forEach(numberCards, (cardsGroup) => {
						let numGroups = Math.floor(cardsGroup.length / 3),
							numToStore = numGroups * 3;

						if (numToStore) {
							let cardsToStore = this._.sampleSize(cardsGroup, numToStore);
							this.$log.debug('cardsToStore -> ', cardsToStore);
							this.storeCards(cardsToStore);
							isStored = true;
						}
					});

					if (!isStored) {
						this.toastr.warning('No matching cards to store!');
					}
				}, (err) => {
					this.$log.error(err);
				});
		}
	}

	storeCards(cardsSelected) {
		let cardsInStorage = this.player.cardsInStorage,
			cardsInHand = this.player.cardsInHand,
			onSuccess = (res => {
				if (res.status == 200) {
					this.$log.debug(res);
				}
			}),
			onError = (err => {
				this.$log.error(err);
			}),
			cardIds = this._.map(cardsSelected, (obj) => {
				return obj.id;
			});

		cardsInStorage.push(cardIds[0]);
		this._.pullAll(cardsInHand, cardIds);

		let plData = {
			cardsInHand: cardsInHand,
			cardsInStorage: cardsInStorage,
			score: this.player.score + cardsSelected[0].amount
		};

		this.playersApi
			.update(this.player.id, plData)
			.then(onSuccess, onError);

		this.player.cardsSelected = [];
	}

	showStorage(pl) {
		let onClose = (data => {
				this.$log.debug('onClose()', data, this);
			}),
			onError = (err => {
				if (err !== 'backdrop click') {
					this.$log.error(err);
				}
			});

		this.$log.debug('showStorage()', pl, this);

		let modal = this.$uibModal.open({
			appendTo: angular.element(document).find('players'),
			component: 'storageModal',
			resolve: {
				player: () => {
					return this.player;
				}
			}
		});

		modal.result.then(onClose, onError);
	}
}
<commit_msg>Add timeout for storing cards<commit_after>export default class PlayerController {
	constructor($rootScope, $scope, $log, $timeout, $uibModal, _, toastr, playersApi, playerModel, websocket) {
		'ngInject';

		this.$rootScope = $rootScope;
		this.$scope = $scope;
		this.$log = $log.getInstance(this.constructor.name);
		this.$timeout = $timeout;
		this.$uibModal = $uibModal;

		this._ = _;
		this.toastr = toastr;

		this.playerModel = playerModel; // Used in template
		this.playersApi = playersApi;
		this.ws = websocket;

		this.$log.debug('constructor()', this);
	}

	$onInit() {
		this.$log.debug('$onInit()', this);

		this.$rootScope.$on('deck:action:winter', () => {
			this.$log.debug('deck:action:winter');

			if (this.player.id === this.playerModel.model.player.id) {
				this.playerModel.showSpecialCards();
			}
		});
	}

	$onDestroy() {
		this.$log.debug('$onDestroy()', this);
	}

	canStoreCards(cardsSelected) {
		if (this.game.actionCard || !cardsSelected || cardsSelected.length !== 3) {
			return false;
		}

		let cardsMatch = this._.reduce(cardsSelected, (prev, current, index, array) => {
			let len = array.length,
				sameCard = prev.amount === current.amount;

			if (!prev) {
				// If the previous object is 'false', then cards don't match
				return false;
			} else if (sameCard && index === len - 1) {
				// Reached the end of the array and all values matched
				return true;
			}

			return sameCard ? current : false;
		});

		return cardsMatch;
	}

	getCurrentPlayer() {
		return this.playerModel.model.player;
	}

	onStorageClick(evt) {
		let cardsSelected = this.player.cardsSelected;

		this.$log.debug('onStorageClick()', evt, cardsSelected, this);

		evt.preventDefault();

		if (this.player.isActive && this.player.hasDrawnCard && this.canStoreCards(cardsSelected)) {
			this.storeCards(cardsSelected);
		} else {
			this.showStorage(this.player);
		}
	}

	onStorageAutoClick(evt) {
		evt.preventDefault();

		if (this.player.isActive && !this.player.isFirstTurn) {
			// Filter out sets of 3 that have the same 'amount'
			this.playerModel.getCards()
				.then(res => {
					let cards = this._.filter(res.data, (o) => {
							return o.cardType === 'number';
						}),
						numberCards = this._.groupBy(cards, (o) => {
							return o.amount;
						}),
						isStored = false,
						timeout = 0;

					this.$log.debug('numberCards -> ', numberCards);

					this._.forEach(numberCards, (cardsGroup) => {
						let numGroups = Math.floor(cardsGroup.length / 3),
							numToStore = numGroups * 3;

						if (numToStore) {
							let cardsToStore = this._.sampleSize(cardsGroup, numToStore);
							this.$log.debug('cardsToStore -> ', cardsToStore);

							this.$timeout(() => {
								this.storeCards(cardsToStore);
							}, timeout);

							timeout += 250;
							isStored = true;
						}
					});

					if (!isStored) {
						this.toastr.warning('No matching cards to store!');
					}
				}, (err) => {
					this.$log.error(err);
				});
		}
	}

	storeCards(cardsSelected) {
		let cardsInStorage = this.player.cardsInStorage,
			cardsInHand = this.player.cardsInHand,
			onSuccess = (res => {
				if (res.status == 200) {
					this.$log.debug(res);
				}
			}),
			onError = (err => {
				this.$log.error(err);
			}),
			cardIds = this._.map(cardsSelected, (obj) => {
				return obj.id;
			});

		cardsInStorage.push(cardIds[0]);
		this._.pullAll(cardsInHand, cardIds);

		let plData = {
			cardsInHand: cardsInHand,
			cardsInStorage: cardsInStorage,
			score: this.player.score + cardsSelected[0].amount
		};

		this.playersApi
			.update(this.player.id, plData)
			.then(onSuccess, onError);

		this.player.cardsSelected = [];
	}

	showStorage(pl) {
		let onClose = (data => {
				this.$log.debug('onClose()', data, this);
			}),
			onError = (err => {
				if (err !== 'backdrop click') {
					this.$log.error(err);
				}
			});

		this.$log.debug('showStorage()', pl, this);

		let modal = this.$uibModal.open({
			appendTo: angular.element(document).find('players'),
			component: 'storageModal',
			resolve: {
				player: () => {
					return this.player;
				}
			}
		});

		modal.result.then(onClose, onError);
	}
}
<|endoftext|>


<commit_before>"use strict";

var $ = require('jquery'),
    _ = require('underscore'),
    Backbone = require('backbone'),
    Marionette = require('../../../../shim/backbone.marionette'),
    chart = require('../../../core/chart.js'),
    barChartTmpl = require('../../../core/templates/barChart.html'),
    resultTmpl = require('./templates/result.html'),
    AoiVolumeModel = require('../models').AoiVolumeModel,
    tableRowTmpl = require('./templates/tableRow.html'),
    tableTmpl = require('./templates/table.html');

var ResultView = Marionette.LayoutView.extend({
    className: 'tab-pane',

    template: resultTmpl,

    regions: {
        tableRegion: '.runoff-table-region',
        chartRegion: '.runoff-chart-region'
    },

    modelEvents: {
        'change': 'onShow'
    },

    initialize: function(options) {
        this.compareMode = options.compareMode;
        this.scenario = options.scenario;
        this.aoi = options.areaOfInterest;
    },

    onShow: function() {
        this.tableRegion.reset();
        this.chartRegion.reset();

        if (this.model.get('result')) {
            var aoiVolumeModel = new AoiVolumeModel({
                areaOfInterest: this.aoi
            });

            if (!this.compareMode) {
                this.tableRegion.show(new TableView({
                    model: this.model,
                    aoiVolumeModel: aoiVolumeModel
                }));
            }

            this.chartRegion.show(new ChartView({
                model: this.model,
                scenario: this.scenario,
                compareMode: this.compareMode
            }));
        }
    }
});

var ChartView = Marionette.ItemView.extend({
    template: barChartTmpl,
    className: 'chart-container runoff-chart-container',

    initialize: function(options) {
        this.scenario = options.scenario;
        this.compareMode = options.compareMode;
    },

    onAttach: function() {
        this.addChart();
    },

    addChart: function() {
        function getData(result, seriesNames, seriesDisplayNames,
                         labelNames, labelDisplayNames) {
            return _.map(seriesNames, function(seriesName, seriesInd) {
                var seriesDisplayName = seriesDisplayNames[seriesInd];
                return {
                    key: seriesDisplayName,
                    values: _.map(labelNames, function(labelName, labelInd) {
                        var labelDisplayName = labelDisplayNames[labelInd];
                        return {
                            x: labelDisplayName,
                            y: result[labelName][seriesName]
                        };
                    })
                };
            });
        }

        var chartEl = this.$el.find('.bar-chart').get(0),
            result = this.model.get('result'),
            seriesNames = ['inf', 'runoff', 'et'],
            seriesDisplayNames = ['Infiltration', 'Runoff', 'Evapotranspiration'],
            labelNames,
            labelDisplayNames,
            data,
            chartOptions;

        $(chartEl).empty();

        if (result) {
            if (this.compareMode) {
                var target_result = 'modified';
                if (this.scenario.get('is_current_conditions')) {
                    target_result = 'unmodified';
                }
                if (this.scenario.get('is_pre_columbian')) {
                    target_result = 'pc_unmodified';
                }
                labelNames = [target_result];
                labelDisplayNames = [''];
                this.$el.addClass('current-conditions');
            } else if (this.scenario.get('is_current_conditions')) {
                labelNames = ['pc_unmodified', 'unmodified'];
                labelDisplayNames = ['100% Forest', 'Current Conditions'];
            } else {
                labelNames = ['unmodified', 'modified'];
                labelDisplayNames = ['Current Conditions', 'Modified'];
            }

            data = getData(result, seriesNames, seriesDisplayNames,
                           labelNames, labelDisplayNames);
            chartOptions = {
                seriesColors: ['#F8AA00', '#CF4300', '#C2D33C'],
                yAxisLabel: 'Level (cm)',
                yAxisUnit: 'cm',
                reverseLegend: true,
                disableToggle: true,
                margin: this.compareMode ? {top: 20, right: 0, bottom: 40, left: 60} : undefined
            };

            chart.renderVerticalBarChart(chartEl, data, chartOptions);
        }
    }

});

var TableRowView = Marionette.ItemView.extend({
    tagName: 'tr',
    template: tableRowTmpl
});

var TableView = Marionette.CompositeView.extend({
    childView: TableRowView,
    childViewContainer: 'tbody',
    template: tableTmpl,

    runoffTypes: [
        { name: 'runoff', display: 'Runoff' },
        { name: 'et', display: 'Evapotranspiration' },
        { name: 'inf', display: 'Infiltration' }
    ],

    initialize: function() {
        this.aoiVolumeModel = this.options.aoiVolumeModel;
        this.tr55Results = this.model.get('result');

        this.collection = this.formatData();
    },

    onAttach: function() {
        $('[data-toggle="table"]').bootstrapTable();
    },

    formatData: function() {
        // The TR55 results should be broken down into:
        // Runoff Partition | Depth | Volume
        var collection = new Backbone.Collection();

        collection.add(this.makeRowsForScenario('modified'));

        return collection;
    },

    makeRowsForScenario: function(runoffKey) {
        var self = this,
            runoffPartition = this.tr55Results[runoffKey];

        return _.map(this.runoffTypes, function(runoffType) {
            return _.extend(self.getRunoffTypeValue(runoffPartition, runoffType));
        });
    },

    getRunoffTypeValue: function(runoffPartition, runoffType) {
        var depth = runoffPartition[runoffType.name];

        return {
            runoffType: runoffType.display,
            depth: depth,
            adjustedVolume: this.aoiVolumeModel.adjust(depth)
        };
    }
});

module.exports = {
    ResultView: ResultView
};
<commit_msg>Only show current runoff scenario in output<commit_after>"use strict";

var $ = require('jquery'),
    _ = require('underscore'),
    Backbone = require('backbone'),
    Marionette = require('../../../../shim/backbone.marionette'),
    chart = require('../../../core/chart.js'),
    barChartTmpl = require('../../../core/templates/barChart.html'),
    resultTmpl = require('./templates/result.html'),
    AoiVolumeModel = require('../models').AoiVolumeModel,
    tableRowTmpl = require('./templates/tableRow.html'),
    tableTmpl = require('./templates/table.html');

var ResultView = Marionette.LayoutView.extend({
    className: 'tab-pane',

    template: resultTmpl,

    regions: {
        tableRegion: '.runoff-table-region',
        chartRegion: '.runoff-chart-region'
    },

    modelEvents: {
        'change': 'onShow'
    },

    initialize: function(options) {
        this.compareMode = options.compareMode;
        this.scenario = options.scenario;
        this.aoi = options.areaOfInterest;
    },

    onShow: function() {
        this.tableRegion.reset();
        this.chartRegion.reset();

        if (this.model.get('result')) {
            var aoiVolumeModel = new AoiVolumeModel({
                areaOfInterest: this.aoi
            });

            if (!this.compareMode) {
                this.tableRegion.show(new TableView({
                    model: this.model,
                    aoiVolumeModel: aoiVolumeModel
                }));
            }

            this.chartRegion.show(new ChartView({
                model: this.model,
                scenario: this.scenario,
                compareMode: this.compareMode
            }));
        }
    }
});

var ChartView = Marionette.ItemView.extend({
    template: barChartTmpl,
    className: 'chart-container runoff-chart-container',

    initialize: function(options) {
        this.scenario = options.scenario;
        this.compareMode = options.compareMode;
    },

    onAttach: function() {
        this.addChart();
    },

    addChart: function() {
        function getData(result, seriesNames, seriesDisplayNames,
                         labelNames, labelDisplayNames) {
            return _.map(seriesNames, function(seriesName, seriesInd) {
                var seriesDisplayName = seriesDisplayNames[seriesInd];
                return {
                    key: seriesDisplayName,
                    values: _.map(labelNames, function(labelName, labelInd) {
                        var labelDisplayName = labelDisplayNames[labelInd];
                        return {
                            x: labelDisplayName,
                            y: result[labelName][seriesName]
                        };
                    })
                };
            });
        }

        var chartEl = this.$el.find('.bar-chart').get(0),
            result = this.model.get('result'),
            seriesNames = ['inf', 'runoff', 'et'],
            seriesDisplayNames = ['Infiltration', 'Runoff', 'Evapotranspiration'],
            labelNames,
            labelDisplayNames,
            data,
            chartOptions;

        $(chartEl).empty();

        if (result) {
            if (this.compareMode) {
                var target_result = 'modified';
                if (this.scenario.get('is_current_conditions')) {
                    target_result = 'unmodified';
                }
                if (this.scenario.get('is_pre_columbian')) {
                    target_result = 'pc_unmodified';
                }
                labelNames = [target_result];
                labelDisplayNames = [''];
                this.$el.addClass('current-conditions');
            } else if (this.scenario.get('is_current_conditions')) {
                labelNames = ['unmodified'];
                labelDisplayNames = ['Current Conditions'];
            } else {
                labelNames = ['modified'];
                labelDisplayNames = ['Modified'];
            }

            data = getData(result, seriesNames, seriesDisplayNames,
                           labelNames, labelDisplayNames);
            chartOptions = {
                seriesColors: ['#F8AA00', '#CF4300', '#C2D33C'],
                yAxisLabel: 'Level (cm)',
                yAxisUnit: 'cm',
                reverseLegend: true,
                disableToggle: true,
                margin: this.compareMode ? {top: 20, right: 0, bottom: 40, left: 60} : undefined
            };

            chart.renderVerticalBarChart(chartEl, data, chartOptions);
        }
    }

});

var TableRowView = Marionette.ItemView.extend({
    tagName: 'tr',
    template: tableRowTmpl
});

var TableView = Marionette.CompositeView.extend({
    childView: TableRowView,
    childViewContainer: 'tbody',
    template: tableTmpl,

    runoffTypes: [
        { name: 'runoff', display: 'Runoff' },
        { name: 'et', display: 'Evapotranspiration' },
        { name: 'inf', display: 'Infiltration' }
    ],

    initialize: function() {
        this.aoiVolumeModel = this.options.aoiVolumeModel;
        this.tr55Results = this.model.get('result');

        this.collection = this.formatData();
    },

    onAttach: function() {
        $('[data-toggle="table"]').bootstrapTable();
    },

    formatData: function() {
        // The TR55 results should be broken down into:
        // Runoff Partition | Depth | Volume
        var collection = new Backbone.Collection();

        collection.add(this.makeRowsForScenario('modified'));

        return collection;
    },

    makeRowsForScenario: function(runoffKey) {
        var self = this,
            runoffPartition = this.tr55Results[runoffKey];

        return _.map(this.runoffTypes, function(runoffType) {
            return _.extend(self.getRunoffTypeValue(runoffPartition, runoffType));
        });
    },

    getRunoffTypeValue: function(runoffPartition, runoffType) {
        var depth = runoffPartition[runoffType.name];

        return {
            runoffType: runoffType.display,
            depth: depth,
            adjustedVolume: this.aoiVolumeModel.adjust(depth)
        };
    }
});

module.exports = {
    ResultView: ResultView
};
<|endoftext|>


<commit_before>var Q = require('q');
var util = require('util');
var url = require('url');
var mout = require('mout');
var path = require('path');
var request = require('request');
var LRU = require('lru-cache');
var Config = require('bower-config');
var download = require('bower-poc').util.download;
var createError = require('bower-poc').util.createError;
var extract = require('bower-poc').util.extract;
var Resolver = require('bower-poc').resolverBase;
var semver = require('bower-poc').util.semver;

function ArtifactoryResolver(decEndpoint, config, logger) {
    var pair;
    Resolver.call(this, decEndpoint, config, logger);

    this._artifactoryRegistryAddress = ArtifactoryResolver.extractArtifactoryRegistry(this._config);

    pair = ArtifactoryResolver.getOrgRepoPair(this._source);
    if (!pair) {
        throw createError('Invalid Artifactory Registry', 'EINVEND', {
            details: this._source + ' does not seem to be a valid Artifactory registry response!'
        });
    }
    this._org = pair.org;
    this._repo = pair.repo;
}

util.inherits(ArtifactoryResolver, Resolver);
mout.object.mixIn(ArtifactoryResolver, Resolver);

// Abstract functions that must be implemented by concrete resolvers
ArtifactoryResolver.prototype._resolve = function () {
    var msg;
    var that = this;
    var requestUrl = this._artifactoryRegistryAddress + '/binaries/' + this._org + '/' + this._repo +
        '.git/' + this._target;

    requestUrl = url.format(requestUrl);
    var artifactoryRemote = url.parse(requestUrl);
    var tempDir = this._tempDir;
    var reqHeaders = {};
    var bowerConfig = this._config;
    var target = this._target;

    var resolve = ArtifactoryResolver.doArtifactoryHeadRequest(requestUrl, bowerConfig)
        .then(function (headResponse) {
            that._response = headResponse;
            var contentDisposition = ArtifactoryResolver.collectHeaderFileName(headResponse);
            var file = path.join(tempDir, contentDisposition);
            return download(requestUrl, file, {
                proxy: artifactoryRemote.protocol === 'https:' ? that._config.httpsProxy : that._config.proxy,
                strictSSL: that._config.strictSsl,
                timeout: that._config.timeout,
                headers: reqHeaders
            })
                .progress(function (state) {
                    // Retry?
                    if (state.retry) {
                        msg = 'Download of ' + requestUrl + ' failed with ' + state.error.code + ', ';
                        msg += 'retrying in ' + (state.delay / 1000).toFixed(1) + 's';
                        that._logger.debug('error', state.error.message, {error: state.error});
                        return that._logger.warn('retry', msg);
                    }

                    // Progress
                    msg = 'received ' + (state.received / 1024 / 1024).toFixed(1) + 'MB';
                    if (state.total) {
                        msg += ' of ' + (state.total / 1024 / 1024).toFixed(1) + 'MB downloaded, ';
                        msg += state.percent + '%';
                    }
                    that._logger.info('progress', msg);
                })
                .then(function () {
                    // Extract archive
                    that._logger.action('extract', path.basename(file), {
                        archive: file,
                        to: that._tempDir
                    });

                    return extract(file, that._tempDir)
                        // Fallback to standard git clone if extraction failed
                        .fail(function (err) {
                            msg = 'Decompression of ' + path.basename(file) + ' failed' + (err.code ? ' with ' + err.code : '') + ', ';
                            that._logger.debug('error', err.message, {error: err});
                            that._logger.warn('retry', msg);

                            return that._cleanTempDir();
                        });
                }, function (err) {
                    msg = 'Download of ' + requestUrl + ' failed' + (err.code ? ' with ' + err.code : '') + ', ';
                    that._logger.debug('error', err.message, {error: err});
                    that._logger.warn('retry', msg);

                    return that._cleanTempDir();
                });
        })
        .fail(function (response) {
            var status = response.statusCode;

            // In case we got 404, lets get the full error JSON, and show it to the user
            if (status === 404) {
                return ArtifactoryResolver.doArtifactoryRequest(requestUrl, bowerConfig)
                    .then(function (response) {
                        var jsonObject = JSON.parse(response);
                        if (jsonObject) {
                            var err = createError('Tag/branch ' + target + ' does not exist', 'ENORESTARGET');
                            err.details = response.message;
                            throw err;
                        }

                        return true;
                    })
                    .fail(function (response) {
                        var err = createError(response.message, 'ENORESTARGET');
                        err.details = response.message;
                        throw err;
                    });
            }

            if (status < 200 || status >= 300) {
                return createError('Request to ' + requestUrl + ' failed with ' + response.statusCode,
                    'EINVRES');
            }
        });

    return resolve;
};

ArtifactoryResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
    var requestUrl = this._artifactoryRegistryAddress + '/binaries/' + this._org + '/' + this._repo +
        '.git/' + this._target;

    var oldCacheHeaders = pkgMeta._cacheHeaders || {};
    var reqHeaders = {};

    // If the previous cache headers contain an ETag,
    // send the "If-None-Match" header with it
    if (oldCacheHeaders.ETag) {
        reqHeaders['If-None-Match'] = oldCacheHeaders.ETag;
    }

    var res = ArtifactoryResolver.doArtifactoryHeadRequest(requestUrl, this._config, reqHeaders)
        .then(function (response) {
            console.log("response" + response);
            return true;
        })
        .fail(function (response) {
            if (response.statusCode === 304) {
                return false;
            }

            return true;
        });

    return res;
}

ArtifactoryResolver.prototype._savePkgMeta = function (meta) {
    // Store collected headers in the package meta
    meta._cacheHeaders = this._collectCacheHeaders(this._response);

    // Store ETAG under _release
    if (meta._cacheHeaders.ETag) {
        meta._release = 'e-tag:' + mout.string.trim(meta._cacheHeaders.ETag.substr(0, 10), '"');
    }

    return Resolver.prototype._savePkgMeta.call(this, meta);
};

ArtifactoryResolver.prototype._collectCacheHeaders = function (res) {
    var headers = {};

    // Collect cache headers
    this.constructor._cacheHeaders.forEach(function (name) {
        var value = res.headers[name.toLowerCase()];

        if (value != null) {
            headers[name] = value;
        }
    });

    return headers;
};

ArtifactoryResolver.versions = function (source) {
    var value = this._cache.versions.get(source);
    if (value) {
        return Q.resolve(value)
            .then(function () {
                var versions = this._cache.versions.get(source);
                versions = versions.map(function (version) {
                    return version.version;
                });

                return versions;
            }.bind(this));
    }

    value = this.tags(source)
        .then(function (tags) {
            var tag;
            var version;
            var versions = [];

            // For each tag
            for (tag in tags) {
                version = semver.clean(tag);
                if (version) {
                    versions.push({version: version, tag: tag, commit: tags[tag]});
                }
            }

            // Sort them by DESC order
            versions.sort(function (a, b) {
                return semver.rcompare(a.version, b.version);
            });

            this._cache.versions.set(source, versions);

            // Call the function again to keep it DRY
            return this.versions(source);
        }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.versions.set(source, value);

    return value;
};

ArtifactoryResolver.tags = function (source) {
    var value = this._cache.tags.get(source);

    if (value) {
        return Q.resolve(value);
    }

    value = this.refs(source).then(function (refs) {
        var tags = {};

        // For each line in the refs, match only the tags
        refs.forEach(function (line) {
            var match = line.match(/^([a-f0-9]{44})\s+refs\/tags\/(\S+)/);

            if (match && !mout.string.endsWith(match[2], '^{}')) {
                tags[match[2]] = match[1];
            }
        });
        this._cache.tags.set(source, tags);

        return tags;
    }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.tags.set(source, value);

    return value;
}

ArtifactoryResolver.refs = function (source) {
    var config = require('bower-poc').config;
    var pair = ArtifactoryResolver.getOrgRepoPair(source);
    var value;

    value = this._cache.refs.get(source);
    if (value) {
        return Q.resolve(value);
    }

    var requestUrl = ArtifactoryResolver.extractArtifactoryRegistry(config) + '/' + pair.org +
        '/' + pair.repo + '.git/' + 'info/refs?service=git-upload-pack';

    value = ArtifactoryResolver.doArtifactoryRequest(requestUrl, config)
        .then(function (response) {
            var refs = response.toString()
                .trim()                         // Trim trailing and leading spaces
                .split(/[\r\n]+/);

            // Update the refs with the actual refs
            this._cache.refs.set(source, refs);

            return refs;
        }.bind(this))
        .fail(function (response) {
            var err = createError(response.message, 'ENORESTARGET');
            err.details = response.message;
            throw err;
        });

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.refs.set(source, value);

    return value;
}

ArtifactoryResolver.getOrgRepoPair = function (source) {
    var match;
    match = source.replace(ArtifactoryResolver.ARTIFACTORY_PREFIX, "").split("/")

    if (match.length < 2) {
        return null;
    }

    return {
        org: match[0],
        repo: match[1]
    };
};

ArtifactoryResolver.extractArtifactoryRegistry = function (config) {
    var registryUrl;
    registryUrl = config.registry.register;
    if (!registryUrl || registryUrl === Config.DEFAULT_REGISTRY) {
        config.registry.search.forEach(function (reg) {
            if (reg.indexOf("artifactory") > -1) {
                registryUrl = reg;
            }
        });
    }

    return registryUrl;
}

ArtifactoryResolver.doArtifactoryHeadRequest = function (requestUrl, config, customHeaders) {
    var headers = customHeaders || {};
    var remote = url.parse(requestUrl);
    var deferred = Q.defer();

    request.head(requestUrl, {
        proxy: remote.protocol === 'https:' ? config.httpsProxy : config.proxy,
        headers: headers,
        strictSSL: config.strictSsl,
        timeout: config.timeout
    })
    .on('error', function (error) {
        throw createError('Request to ' + requestUrl + ' failed: ' + error.message, error.code);
    })
    .on('response', function (response) {
        var status = response.statusCode;

        if (status < 200 || status >= 300) {
            return deferred.reject(response);
        }

        deferred.resolve(response);
    });

    return deferred.promise;
}

ArtifactoryResolver.doArtifactoryRequest = function (requestUrl, config) {
    var headers = {};
    var remote = url.parse(requestUrl);
    var deferred = Q.defer();

    request.get(requestUrl, {
        proxy: remote.protocol === 'https:' ? config.httpsProxy : config.proxy,
        headers: headers,
        strictSSL: config.strictSsl,
        timeout: config.timeout
    })
        .on('error', function (error) {
            deferred.reject(createError('Request to ' + requestUrl + ' failed: ' + error.message, error.code));
        })
        .on('data', function (data) {
            deferred.resolve(data);
        })
    /*.on('response', function(response) {
     var status = response.statusCode;

     if(status !== 404){
     deferred.resolve(response)
     }

     */
    /* if (status < 200 || status >= 300) {
     return deferred.reject(createError('Request to ' + requestUrl + ' failed with ' + response.statusCode,
     'EINVRES'));
     }

     deferred.resolve(response);*/
    /*
     });*/

    return deferred.promise;
}

ArtifactoryResolver.collectHeaderFileName = function (headResponse) {
    var contentDisposition = headResponse.headers['content-disposition'];
    contentDisposition = contentDisposition.replace("attachment; filename=", "");
    contentDisposition = contentDisposition.substring(1, contentDisposition.length - 1);

    return contentDisposition;
}

ArtifactoryResolver._cacheHeaders = [
    'Content-MD5',
    'ETag',
    'Last-Modified',
    'Content-Language',
    'Content-Length',
    'Content-Type',
    'Content-Disposition'
];

ArtifactoryResolver._cache = {
    branches: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
    tags: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
    versions: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
    refs: new LRU({ max: 50, maxAge: 5 * 60 * 1000 })
};

ArtifactoryResolver.ARTIFACTORY_PREFIX = "arti://";

module.exports = ArtifactoryResolver;
<commit_msg>compatible with tar.gz only<commit_after>var Q = require('q');
var util = require('util');
var url = require('url');
var mout = require('mout');
var path = require('path');
var request = require('request');
var LRU = require('lru-cache');
var Config = require('bower-config');
var download = require('bower-poc').util.download;
var createError = require('bower-poc').util.createError;
var extract = require('bower-poc').util.extract;
var Resolver = require('bower-poc').resolverBase;
var semver = require('bower-poc').util.semver;

function ArtifactoryResolver(decEndpoint, config, logger) {
    var pair;
    Resolver.call(this, decEndpoint, config, logger);

    this._artifactoryRegistryAddress = ArtifactoryResolver.extractArtifactoryRegistry(this._config);

    pair = ArtifactoryResolver.getOrgRepoPair(this._source);
    if (!pair) {
        throw createError('Invalid Artifactory Registry', 'EINVEND', {
            details: this._source + ' does not seem to be a valid Artifactory registry response!'
        });
    }
    this._org = pair.org;
    this._repo = pair.repo;
}

util.inherits(ArtifactoryResolver, Resolver);
mout.object.mixIn(ArtifactoryResolver, Resolver);

// Abstract functions that must be implemented by concrete resolvers
ArtifactoryResolver.prototype._resolve = function () {
    var msg;
    var that = this;
    var requestUrl = this._artifactoryRegistryAddress + '/binaries/' + this._org + '/' + this._repo +
        '.git/' + this._target;

    requestUrl = url.format(requestUrl);
    var artifactoryRemote = url.parse(requestUrl);
    var tempDir = this._tempDir;
    var reqHeaders = {};
    var file = path.join(tempDir, 'archive.tar.gz');

    return download(requestUrl, file, {
                proxy: artifactoryRemote.protocol === 'https:' ? that._config.httpsProxy : that._config.proxy,
                strictSSL: that._config.strictSsl,
                timeout: that._config.timeout,
                headers: reqHeaders
            })
            .progress(function (state) {
                // Retry?
                if (state.retry) {
                    msg = 'Download of ' + requestUrl + ' failed with ' + state.error.code + ', ';
                    msg += 'retrying in ' + (state.delay / 1000).toFixed(1) + 's';
                    that._logger.debug('error', state.error.message, {error: state.error});
                    return that._logger.warn('retry', msg);
                }

                // Progress
                msg = 'received ' + (state.received / 1024 / 1024).toFixed(1) + 'MB';
                if (state.total) {
                    msg += ' of ' + (state.total / 1024 / 1024).toFixed(1) + 'MB downloaded, ';
                    msg += state.percent + '%';
                }
                that._logger.info('progress', msg);
            })
            .then(function (response) {
                that._response = response;
                // Extract archive
                that._logger.action('extract', path.basename(file), {
                    archive: file,
                    to: that._tempDir
                });

                return extract(file, that._tempDir)
                    // Fallback to standard git clone if extraction failed
                    .fail(function (err) {
                        msg = 'Decompression of ' + path.basename(file) + ' failed' + (err.code ? ' with ' + err.code : '') + ', ';
                        that._logger.debug('error', err.message, {error: err});
                        that._logger.warn('retry', msg);

                        return that._cleanTempDir();
                    });
            }, function (err) {
                msg = 'Download of ' + requestUrl + ' failed' + (err.code ? ' with ' + err.code : '') + ', ';
                that._logger.debug('error', err.message, {error: err});
                that._logger.warn('retry', msg);

                return that._cleanTempDir();
            })
            .fail(function (response) {
                var status = response.statusCode;

                // In case we got 404, lets take the full error JSON, and show it to the user
                if (status === 404) {
                    return ArtifactoryResolver.doArtifactoryRequest(requestUrl, bowerConfig)
                        .then(function (response) {
                            var jsonObject = JSON.parse(response);
                            if (jsonObject) {
                                var err = createError('Tag/branch ' + target + ' does not exist', 'ENORESTARGET');
                                err.details = response.message;
                                throw err;
                            }

                            return true;
                        })
                        .fail(function (response) {
                            var err = createError(response.message, 'ENORESTARGET');
                            err.details = response.message;
                            throw err;
                        });
                }

                if (status < 200 || status >= 300) {
                    return createError('Request to ' + requestUrl + ' failed with ' + response.statusCode,
                        'EINVRES');
                }
            });
};

ArtifactoryResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
    var requestUrl = this._artifactoryRegistryAddress + '/binaries/' + this._org + '/' + this._repo +
        '.git/' + this._target;

    var oldCacheHeaders = pkgMeta._cacheHeaders || {};
    var reqHeaders = {};

    // If the previous cache headers contain an ETag,
    // send the "If-None-Match" header with it
    if (oldCacheHeaders.ETag) {
        reqHeaders['If-None-Match'] = oldCacheHeaders.ETag;
    }

    return ArtifactoryResolver.doArtifactoryHeadRequest(requestUrl, this._config, reqHeaders)
        .then(function () {
            return true;
        })
        .fail(function (response) {
            return response.statusCode !== 304;
        });
};

ArtifactoryResolver.prototype._savePkgMeta = function (meta) {
    if(this._response) {
        // Store collected headers in the package meta
        meta._cacheHeaders = this._collectCacheHeaders(this._response);

        // Store ETAG under _release
        if (meta._cacheHeaders.ETag) {
            meta._release = 'e-tag:' + mout.string.trim(meta._cacheHeaders.ETag.substr(0, 10), '"');
        }
    }
    return Resolver.prototype._savePkgMeta.call(this, meta);
};

ArtifactoryResolver.prototype._collectCacheHeaders = function (res) {
    var headers = {};

    // Collect cache headers
    this.constructor._cacheHeaders.forEach(function (name) {
        var value = res.headers[name.toLowerCase()];

        if (value != null) {
            headers[name] = value;
        }
    });

    return headers;
};

ArtifactoryResolver.versions = function (source) {
    var value = this._cache.versions.get(source);
    if (value) {
        return Q.resolve(value)
            .then(function () {
                var versions = this._cache.versions.get(source);
                versions = versions.map(function (version) {
                    return version.version;
                });

                return versions;
            }.bind(this));
    }

    value = this.tags(source)
        .then(function (tags) {
            var tag;
            var version;
            var versions = [];

            // For each tag
            for (tag in tags) {
                version = semver.clean(tag);
                if (version) {
                    versions.push({version: version, tag: tag, commit: tags[tag]});
                }
            }

            // Sort them by DESC order
            versions.sort(function (a, b) {
                return semver.rcompare(a.version, b.version);
            });

            this._cache.versions.set(source, versions);

            // Call the function again to keep it DRY
            return this.versions(source);
        }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.versions.set(source, value);

    return value;
};

ArtifactoryResolver.tags = function (source) {
    var value = this._cache.tags.get(source);

    if (value) {
        return Q.resolve(value);
    }

    value = this.refs(source).then(function (refs) {
        var tags = {};

        // For each line in the refs, match only the tags
        refs.forEach(function (line) {
            var match = line.match(/^([a-f0-9]{44})\s+refs\/tags\/(\S+)/);

            if (match && !mout.string.endsWith(match[2], '^{}')) {
                tags[match[2]] = match[1];
            }
        });
        this._cache.tags.set(source, tags);

        return tags;
    }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.tags.set(source, value);

    return value;
};

ArtifactoryResolver.refs = function (source) {
    var config = require('bower-poc').config;
    var pair = ArtifactoryResolver.getOrgRepoPair(source);
    var value;

    value = this._cache.refs.get(source);
    if (value) {
        return Q.resolve(value);
    }

    var requestUrl = ArtifactoryResolver.extractArtifactoryRegistry(config) + '/' + pair.org +
        '/' + pair.repo + '.git/' + 'info/refs?service=git-upload-pack';

    value = ArtifactoryResolver.doArtifactoryRequest(requestUrl, config)
        .then(function (response) {
            var refs = response.toString()
                .trim()                         // Trim trailing and leading spaces
                .split(/[\r\n]+/);

            // Update the refs with the actual refs
            this._cache.refs.set(source, refs);

            return refs;
        }.bind(this))
        .fail(function (response) {
            var err = createError(response.message, 'ENORESTARGET');
            err.details = response.message;
            throw err;
        });

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.refs.set(source, value);

    return value;
};

ArtifactoryResolver.getOrgRepoPair = function (source) {
    var match;
    match = source.replace(ArtifactoryResolver.ARTIFACTORY_PREFIX, "").split("/")

    if (match.length < 2) {
        return null;
    }

    return {
        org: match[0],
        repo: match[1]
    };
};

ArtifactoryResolver.extractArtifactoryRegistry = function (config) {
    var registryUrl;
    registryUrl = config.registry.register;
    if (!registryUrl || registryUrl === Config.DEFAULT_REGISTRY) {
        config.registry.search.forEach(function (reg) {
            if (reg.indexOf("artifactory") > -1) {
                registryUrl = reg;
            }
        });
    }

    return registryUrl;
};

ArtifactoryResolver.doArtifactoryHeadRequest = function (requestUrl, config, customHeaders) {
    var headers = customHeaders || {};
    var remote = url.parse(requestUrl);
    var deferred = Q.defer();

    request.head(requestUrl, {
        proxy: remote.protocol === 'https:' ? config.httpsProxy : config.proxy,
        headers: headers,
        strictSSL: config.strictSsl,
        timeout: config.timeout
    })
    .on('error', function (error) {
        throw createError('Request to ' + requestUrl + ' failed: ' + error.message, error.code);
    })
    .on('response', function (response) {
        var status = response.statusCode;

        if (status < 200 || status >= 300) {
            return deferred.reject(response);
        }

        deferred.resolve(response);
    });

    return deferred.promise;
};

ArtifactoryResolver.doArtifactoryRequest = function (requestUrl, config) {
    var headers = {};
    var remote = url.parse(requestUrl);
    var deferred = Q.defer();

    request.get(requestUrl, {
        proxy: remote.protocol === 'https:' ? config.httpsProxy : config.proxy,
        headers: headers,
        strictSSL: config.strictSsl,
        timeout: config.timeout
    })
        .on('error', function (error) {
            deferred.reject(createError('Request to ' + requestUrl + ' failed: ' + error.message, error.code));
        })
        .on('data', function (data) {
            deferred.resolve(data);
        });

    return deferred.promise;
};

ArtifactoryResolver.collectHeaderFileName = function (headResponse) {
    var contentDisposition = headResponse.headers['content-disposition'];
    contentDisposition = contentDisposition.replace("attachment; filename=", "");
    contentDisposition = contentDisposition.substring(1, contentDisposition.length - 1);

    return contentDisposition;
};

ArtifactoryResolver._cacheHeaders = [
    'Content-MD5',
    'ETag',
    'Last-Modified',
    'Content-Language',
    'Content-Length',
    'Content-Type',
    'Content-Disposition'
];

ArtifactoryResolver._cache = {
    branches: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
    tags: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
    versions: new LRU({ max: 50, maxAge: 5 * 60 * 1000 }),
    refs: new LRU({ max: 50, maxAge: 5 * 60 * 1000 })
};

ArtifactoryResolver.ARTIFACTORY_PREFIX = "arti://";

module.exports = ArtifactoryResolver;
<|endoftext|>


<commit_before>var Util         = require('util');
var BaseService = require('./BaseService');

module.exports = BizInfoCheckService;
Util.inherits(BizInfoCheckService,BaseService);

function BizInfoCheckService(configs) {
  BaseService.call(this,configs);
  this._scopes.push('171');
};

BaseService.addMethod(BizInfoCheckService.prototype, 'getChargeInfo', function(CorpNum, success, error){
  this.getChargeInfo(CorpNum, '', success, error);
});

BaseService.addMethod(BizInfoCheckService.prototype, 'getChargeInfo', function(CorpNum, UserID, success, error) {
  if(!CorpNum || 0 === CorpNum.length) {
    this._throwError(-99999999,'팝빌회원 사업자번호가 입력되지 않았습니다.',error);
    return;
  }
  this._executeAction({
    uri : '/BizInfo/ChargeInfo',
    CorpNum : CorpNum,
    UserID : UserID,
    success : function(response){
      if(success) success(response);
    },
    error : error
  });
});

BaseService.addMethod(BizInfoCheckService.prototype,'getUnitCost', function(CorpNum,success,error) {
  if(!CorpNum || 0 === CorpNum.length) {
    this._throwError(-99999999,'팝빌회원 사업자번호가 입력되지 않았습니다.',error);
    return;
  }
  this._executeAction({
    uri : '/BizInfo/UnitCost',
    CorpNum : CorpNum,
    success : function(response){
      if(success) success(response.unitCost);
    },
    error : error
  });
});

BaseService.addMethod(BizInfoCheckService.prototype,'checkBizInfo' , function(UserCorpNum, CheckCorpNum, success, error){
    this.checkBizInfo(UserCorpNum, CheckCorpNum, '', success, error)
});

BaseService.addMethod(BizInfoCheckService.prototype,'checkBizInfo', function(UserCorpNum, CheckCorpNum, UserID, success, error){
  if(!UserCorpNum || 0 === UserCorpNum.length) {
    this._throwError(-99999999,'팝빌회원 사업자번호가 입력되지 않았습니다.',error);
    return;
  }
  if(!CheckCorpNum || 0 === CheckCorpNum.length) {
    this._throwError(-99999999,'조회할 사업자번호가 입력되지 않았습니다.',error);
    return;
  }

  this._executeAction({
    uri : '/BizInfo/Check?CN=' + CheckCorpNum,
    CorpNum : UserCorpNum,
    UserID: UserID,
    Method : 'GET',
    success : function(response){
      if(success) success(response);
    },
    error : error
  });
});

<commit_msg>기업정보조회 typo<commit_after>var Util         = require('util');
var BaseService = require('./BaseService');

module.exports = BizInfoCheckService;
Util.inherits(BizInfoCheckService,BaseService);

function BizInfoCheckService(configs) {
  BaseService.call(this,configs);
  this._scopes.push('171');
};

BaseService.addMethod(BizInfoCheckService.prototype, 'getChargeInfo', function(CorpNum, success, error){
  this.getChargeInfo(CorpNum, '', success, error);
});

BaseService.addMethod(BizInfoCheckService.prototype, 'getChargeInfo', function(CorpNum, UserID, success, error) {
  if(!CorpNum || 0 === CorpNum.length) {
    this._throwError(-99999999,'팝빌회원 사업자번호가 입력되지 않았습니다.',error);
    return;
  }
  this._executeAction({
    uri : '/BizInfo/ChargeInfo',
    CorpNum : CorpNum,
    UserID : UserID,
    success : function(response){
      if(success) success(response);
    },
    error : error
  });
});

BaseService.addMethod(BizInfoCheckService.prototype,'getUnitCost', function(CorpNum,success,error) {
  if(!CorpNum || 0 === CorpNum.length) {
    this._throwError(-99999999,'팝빌회원 사업자번호가 입력되지 않았습니다.',error);
    return;
  }
  this._executeAction({
    uri : '/BizInfo/UnitCost',
    CorpNum : CorpNum,
    success : function(response){
      if(success) success(response.unitCost);
    },
    error : error
  });
});

BaseService.addMethod(BizInfoCheckService.prototype,'checkBizInfo' , function(MemberCorpNum, CheckCorpNum, success, error){
    this.checkBizInfo(MemberCorpNum, CheckCorpNum, '', success, error)
});

BaseService.addMethod(BizInfoCheckService.prototype,'checkBizInfo', function(MemberCorpNum, CheckCorpNum, UserID, success, error){
  if(!MemberCorpNum || 0 === MemberCorpNum.length) {
    this._throwError(-99999999,'팝빌회원 사업자번호가 입력되지 않았습니다.',error);
    return;
  }
  if(!CheckCorpNum || 0 === CheckCorpNum.length) {
    this._throwError(-99999999,'조회할 사업자번호가 입력되지 않았습니다.',error);
    return;
  }

  this._executeAction({
    uri : '/BizInfo/Check?CN=' + CheckCorpNum,
    CorpNum : MemberCorpNum,
    UserID: UserID,
    Method : 'GET',
    success : function(response){
      if(success) success(response);
    },
    error : error
  });
});

<|endoftext|>


<commit_before>$(document).ready(function () {
    "use strict";

    $(document).foundation();

    var $segments = $(".segments");
    var $svg = $("svg");
    $svg.attr("width", $segments.width());
    $svg.attr("height", $segments.height());

    $(".toolbox label input").each(function(){
        var $this = $(this);
        $this.parent().addClass("toolbox-option-{0}".format($this.val()));
    });

});

function QuestionsController($scope) {
    "use strict";

    // ### Attributes ###

    $scope.eo_selected = undefined; // Id of the selected occurrence

    // Publish into the scope the variables defined globally
    $scope.eos = window.eos;
    $scope.relations = window.relations;
    $scope.forms = window.forms;
    $scope.current_tool = window.initial_tool;
    $scope.arrows = {};

    $(document).ready(function(){
        $scope.svg = $("svg")[0];

        $scope.update_relations_arrows();
        $(window).resize($scope.update_relations_arrows);

        $(".eo-submenu").on("click", $scope.on_eo_submenu_click);
        $(".eo-submenu").mouseover($scope.highlight_eo_tokens);
        $(".eo-submenu").mouseout($scope.highlight_eo_tokens);
        $(".entity-occurrence").mouseover($scope.highlight_eo_tokens);
        $(".entity-occurrence").mouseout($scope.highlight_eo_tokens);
    });

    // ### Methods ###
    $scope.update_relations_arrows = function () {

        for (var form_id in $scope.forms) {
            if ($scope.forms.hasOwnProperty(form_id)) {
                var path = $scope.arrows[form_id];
                if (path) {
                    $scope.svg.removeChild(path);
                }
            }
        }

        for (var i in $scope.relations) {
            if ($scope.relations.hasOwnProperty(i)) {
                var rel_obj = $scope.relations[i];
                $scope.calculate_arrow_string(
                    rel_obj.relation[0],
                    rel_obj.relation[1],
                    rel_obj.form_id
                );
            }
        }
    };

    // Sets the value for selectable on all entity occurrences
    $scope.set_selectables = function (value) {
        for (var i in $scope.eos) {
            if ($scope.eos.hasOwnProperty(i)) {
                $scope.eos[i].selectable = value;
            }
        }
    };

    $scope.eo_click = function (ids) {
        // Handles only the case of 1 id, if it has
        // more than one, it shows the menu
        if (ids.length === 1) {
            var id = ids[0];
            $scope.handle_click_on_eo(id);
        }
    };

    $scope.on_eo_submenu_click = function (event) {
        event.preventDefault();

        var $this = $(this);
        var eo_id = $this.data("eo-id");
        $scope.handle_click_on_eo(eo_id);
        $scope.$apply();
    };

    $scope.handle_click_on_eo = function (id) {
        var eo = $scope.eos[id];

        // Not selectable
        if (!eo || !eo.selectable) { return; }

        if ($scope.eo_selected === undefined) {
            // Marking as selected
            $scope.eo_first_click(id);
        } else {
            $scope.eo_second_click(id);
        }
    };

    $scope.highlight_eo_tokens = function () {
        var $this = $(this);
        var eo_id = $this.data("eo-id");
        $(".eo-{0}".format(eo_id)).each(function () {
            var $this = $(this);
            $this.toggleClass("highlight");
        });
    };

    $scope.eo_first_click = function (id) {
        var eo = $scope.eos[id];
        $scope.eo_selected = id;

        $scope.set_selectables(false);
        eo.selectable = true;
        eo.selected = true;

        // Calculate wich ones must be selectable
        for (var i in $scope.relations) {
            if ($scope.relations.hasOwnProperty(i)) {
                var rel = $scope.relations[i];
                var rel_index = rel.relation.indexOf(id);
                if (rel_index >= 0) {
                    var eo_id = $scope.relations[i].relation[(rel_index + 1) % 2];
                    $scope.eos[eo_id].selectable = true;
                }
            }
        }
    };

    $scope.eo_second_click = function (id) {
        if ($scope.eo_selected === id) {
            // You're de-selecting the one you've just selected
            $scope.eos[id].selected = false;
        } else {
            var eo_id1 = $scope.eo_selected;
            var eo_id2 = id;

            for (var i in $scope.relations) {
                if ($scope.relations.hasOwnProperty(i)) {
                    var rel = $scope.relations[i];
                    var eo_rel_index1 = rel.relation.indexOf(eo_id1);
                    var eo_rel_index2 = rel.relation.indexOf(eo_id2);
                    if (eo_rel_index1 >= 0 && eo_rel_index2 >= 0) {
                        var form_value = $scope.forms[rel.form_id];
                        var new_value = form_value ? "": $scope.current_tool;
                        $scope.forms[rel.form_id] = new_value;

                        $scope.calculate_arrow_string(
                            rel.relation[0],
                            rel.relation[1],
                            rel.form_id
                        );

                        $scope.eos[eo_id1].selected = false;
                        $scope.eos[eo_id2].selected = false;
                    }
                }
            }
        }

        $scope.set_selectables(true);
        $scope.eo_selected = undefined;
    };

    $scope.calculate_arrow_string = function (eo_id1, eo_id2, form_id) {
        var path;

        if (!$scope.forms[form_id]) {
            // Remove the arrow
            path = $scope.arrows[form_id];
            $scope.svg.removeChild(path);
        } else {
            // Curve configuration
            var curve_distance = 25;
            var y_offset = $($scope.svg).position().top;
            var x_offset = -30;

            // Entity occurrences
            var $eo1 = $(".eo-" + eo_id1);
            var $eo2 = $(".eo-" + eo_id2);

            // Positions
            var eo1_pos = $eo1.position();
            var eo2_pos = $eo2.position();

            // Corrected positions
            var eo1_pos_left = eo1_pos.left - x_offset;
            var eo1_pos_top = eo1_pos.top - y_offset - 5;
            var eo2_pos_left = eo2_pos.left - x_offset;
            var eo2_pos_top = eo2_pos.top - y_offset - 10;

            // Form value
            var form_value = $scope.forms[form_id];

            // Format should be:
            // M<x1>,<y1> C<x1>,<y1 + distance> <x2>,<y2 + distance> <x2>,<y2>
            var curve_string = "M{0},{1} C{0},{4} {2},{5} {2},{3}".format(
                Math.round(eo1_pos_left), // {0}
                Math.round(eo1_pos_top),  // {1}
                Math.round(eo2_pos_left), // {2}
                Math.round(eo2_pos_top),  // {3}
                Math.round(eo1_pos_top - curve_distance), // {4}
                Math.round(eo2_pos_top - curve_distance)  // {5}
            );

            path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            path.innerHTML = 'createElementNS';
            path.setAttribute("class", 'arrow arrow_{0}'.format(form_value));
            path.setAttribute("style", 'marker-end: url(#arrow-point-{0});'.format(
                form_value
            ));
            path.setAttribute("d", curve_string);

            $scope.svg.appendChild(path);
            $scope.arrows[form_id] = path;
        }
    };
}

String.prototype.format = String.prototype.f = function() {
    var s = this;
    var i = arguments.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    }
    return s;
};
<commit_msg>updating svg width & height on window resize<commit_after>$(document).ready(function () {
    "use strict";

    $(document).foundation();

    $(".toolbox label input").each(function(){
        var $this = $(this);
        $this.parent().addClass("toolbox-option-{0}".format($this.val()));
    });

});

function QuestionsController($scope) {
    "use strict";

    // ### Attributes ###

    $scope.eo_selected = undefined; // Id of the selected occurrence

    // Publish into the scope the variables defined globally
    $scope.eos = window.eos;
    $scope.relations = window.relations;
    $scope.forms = window.forms;
    $scope.current_tool = window.initial_tool;
    $scope.arrows = {};

    $(document).ready(function(){
        $scope.$segments = $(".segments");
        $scope.$svg = $("svg");
        $scope.svg = $scope.$svg[0];

        $scope.update_relations_arrows();
        $(window).resize($scope.update_relations_arrows);

        $(".eo-submenu").on("click", $scope.on_eo_submenu_click);
        $(".eo-submenu").mouseover($scope.highlight_eo_tokens);
        $(".eo-submenu").mouseout($scope.highlight_eo_tokens);
        $(".entity-occurrence").mouseover($scope.highlight_eo_tokens);
        $(".entity-occurrence").mouseout($scope.highlight_eo_tokens);
    });

    // ### Methods ###
    $scope.update_relations_arrows = function () {
        // Update width and height of the svg element
        $scope.$svg.attr("width", $scope.$segments.width());
        $scope.$svg.attr("height", $scope.$segments.height());

        // Remove all arrows before re-drawing
        for (var form_id in $scope.forms) {
            if ($scope.forms.hasOwnProperty(form_id)) {
                var path = $scope.arrows[form_id];
                if (path) {
                    $scope.svg.removeChild(path);
                }
            }
        }

        // Re-draw all the arrows
        for (var i in $scope.relations) {
            if ($scope.relations.hasOwnProperty(i)) {
                var rel_obj = $scope.relations[i];
                $scope.calculate_arrow_string(
                    rel_obj.relation[0],
                    rel_obj.relation[1],
                    rel_obj.form_id
                );
            }
        }
    };

    // Sets the value for selectable on all entity occurrences
    $scope.set_selectables = function (value) {
        for (var i in $scope.eos) {
            if ($scope.eos.hasOwnProperty(i)) {
                $scope.eos[i].selectable = value;
            }
        }
    };

    $scope.eo_click = function (ids) {
        // Handles only the case of 1 id, if it has
        // more than one, it shows the menu
        if (ids.length === 1) {
            var id = ids[0];
            $scope.handle_click_on_eo(id);
        }
    };

    $scope.on_eo_submenu_click = function (event) {
        event.preventDefault();

        var $this = $(this);
        var eo_id = $this.data("eo-id");
        $scope.handle_click_on_eo(eo_id);
        $scope.$apply();
    };

    $scope.handle_click_on_eo = function (id) {
        var eo = $scope.eos[id];

        // Not selectable
        if (!eo || !eo.selectable) { return; }

        if ($scope.eo_selected === undefined) {
            // Marking as selected
            $scope.eo_first_click(id);
        } else {
            $scope.eo_second_click(id);
        }
    };

    $scope.highlight_eo_tokens = function () {
        var $this = $(this);
        var eo_id = $this.data("eo-id");
        $(".eo-{0}".format(eo_id)).each(function () {
            var $this = $(this);
            $this.toggleClass("highlight");
        });
    };

    $scope.eo_first_click = function (id) {
        var eo = $scope.eos[id];
        $scope.eo_selected = id;

        $scope.set_selectables(false);
        eo.selectable = true;
        eo.selected = true;

        // Calculate wich ones must be selectable
        for (var i in $scope.relations) {
            if ($scope.relations.hasOwnProperty(i)) {
                var rel = $scope.relations[i];
                var rel_index = rel.relation.indexOf(id);
                if (rel_index >= 0) {
                    var eo_id = $scope.relations[i].relation[(rel_index + 1) % 2];
                    $scope.eos[eo_id].selectable = true;
                }
            }
        }
    };

    $scope.eo_second_click = function (id) {
        if ($scope.eo_selected === id) {
            // You're de-selecting the one you've just selected
            $scope.eos[id].selected = false;
        } else {
            var eo_id1 = $scope.eo_selected;
            var eo_id2 = id;

            for (var i in $scope.relations) {
                if ($scope.relations.hasOwnProperty(i)) {
                    var rel = $scope.relations[i];
                    var eo_rel_index1 = rel.relation.indexOf(eo_id1);
                    var eo_rel_index2 = rel.relation.indexOf(eo_id2);
                    if (eo_rel_index1 >= 0 && eo_rel_index2 >= 0) {
                        var form_value = $scope.forms[rel.form_id];
                        var new_value = form_value ? "": $scope.current_tool;
                        $scope.forms[rel.form_id] = new_value;

                        $scope.calculate_arrow_string(
                            rel.relation[0],
                            rel.relation[1],
                            rel.form_id
                        );

                        $scope.eos[eo_id1].selected = false;
                        $scope.eos[eo_id2].selected = false;
                    }
                }
            }
        }

        $scope.set_selectables(true);
        $scope.eo_selected = undefined;
    };

    $scope.calculate_arrow_string = function (eo_id1, eo_id2, form_id) {
        var path;

        if (!$scope.forms[form_id]) {
            // Remove the arrow
            path = $scope.arrows[form_id];
            $scope.svg.removeChild(path);
        } else {
            // Curve configuration
            var curve_distance = 25;
            var y_offset = $($scope.svg).position().top;
            var x_offset = -30;

            // Entity occurrences
            var $eo1 = $(".eo-" + eo_id1);
            var $eo2 = $(".eo-" + eo_id2);

            // Positions
            var eo1_pos = $eo1.position();
            var eo2_pos = $eo2.position();

            // Corrected positions
            var eo1_pos_left = eo1_pos.left - x_offset;
            var eo1_pos_top = eo1_pos.top - y_offset - 5;
            var eo2_pos_left = eo2_pos.left - x_offset;
            var eo2_pos_top = eo2_pos.top - y_offset - 10;

            // Form value
            var form_value = $scope.forms[form_id];

            // Format should be:
            // M<x1>,<y1> C<x1>,<y1 + distance> <x2>,<y2 + distance> <x2>,<y2>
            var curve_string = "M{0},{1} C{0},{4} {2},{5} {2},{3}".format(
                Math.round(eo1_pos_left), // {0}
                Math.round(eo1_pos_top),  // {1}
                Math.round(eo2_pos_left), // {2}
                Math.round(eo2_pos_top),  // {3}
                Math.round(eo1_pos_top - curve_distance), // {4}
                Math.round(eo2_pos_top - curve_distance)  // {5}
            );

            path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            path.innerHTML = 'createElementNS';
            path.setAttribute("class", 'arrow arrow_{0}'.format(form_value));
            path.setAttribute("style", 'marker-end: url(#arrow-point-{0});'.format(
                form_value
            ));
            path.setAttribute("d", curve_string);

            $scope.svg.appendChild(path);
            $scope.arrows[form_id] = path;
        }
    };
}

String.prototype.format = String.prototype.f = function() {
    var s = this;
    var i = arguments.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    }
    return s;
};
<|endoftext|>


<commit_before>requirejs.config({
	shim: {
		'facebook': {
			export: 'FB'
		},
		'backbone': {
			deps: ["underscore", "jquery"],
			exports: "Backbone"
		},
		'underscore': {
			exports: "_"
		},
		'bootstrap': {
			deps: ["jquery"]
		},
		'jquery-ui': {
			deps: ["jquery"],
			exports: '$'
		}
	},
	"paths": {
		"jquery": "//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min",
		"jquery-ui": "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min",
		"facebook": "//connect.facebook.net/en_US/all",
		"underscore": "//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.1/underscore-min",
		"backbone": "//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min",
		"json": "//cdnjs.cloudflare.com/ajax/libs/json2/20121008/json2.min",
		"text": "//cdnjs.cloudflare.com/ajax/libs/require-text/2.0.10/text.min",
		'bootstrap': '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/js/bootstrap.min',

		'models': 'app/models/modelIndex',
		'model_want': 'app/models/want',
		'model_wants': 'app/models/wants',
		'model_search_item': 'app/models/searchItem',
		'model_search_results': 'app/models/searchResults',

		'views': 'app/views/viewIndex',
		'view_common': 'app/views/common',
		'view_main': 'app/views/main',
		'view_search': 'app/views/search',

		'utils': 'app/utils'
	}
});

requirejs(["jquery", "underscore", "backbone", "views", "utils", 'bootstrap'], function($, _, Backbone, Views, Utils) {

	// Create a loading indicator. Inspired by
	// http://tbranyen.com/post/how-to-indicate-backbone-fetch-progress
	_.each(["Model", "Collection"], function(name) {
		// Cache Backbone constructor.
		var ctor = Backbone[name];
		// Cache original fetch and set.
		var fetch = ctor.prototype.fetch;

		// Override the fetch method to emit a fetch event.
		ctor.prototype.fetch = function() {
			// Trigger the fetch event on the instance.
			this.trigger("fetch", this);

			// Pass through to original fetch.
			var result = fetch.apply(this, arguments);
			var that = this;
			result.success(function() {
				that.trigger("fetched", that);
			});
			return result;
		};
	});

	var App = _.extend({
		appId: '509825915758193',

		init: function() {
			FB.init({
				appId: this.appId,
				channelUrl: '//crowdbuy.sapuan.org/channel.html',
				oauth: true,
				xfbml: true
			});
			FB.login(function() {}, {
				scope: 'read_friendlists, user_about_me'
			});

			$('#loginbutton,#feedbutton').removeAttr('disabled');

			FB.getLoginStatus((function(that) {
				return function(response) {
					if (response.status === 'connected') {
						// Handle authentication here.
						Utils.logIn();

						FB.api('/me', function(response) {
							var welcomeString = that._randomWelcome();
							that.userId = response.id;
							$('#welcome').html(welcomeString + response.first_name + '!');

							if (that.view) {
								that.view.userId = response.id;
							}

							that._continueInit();
						});

					} else {
						alert("Whoa, something went wrong! Try refreshing this page.");
					}

				};
			})(this));

			$('#add-to-timeline').click(this.addToTimeline());
		},

		addToTimeline: function() {
			var that = this;
			return function() {
				var permissionsUrlPromise = Utils.getFacebookCustomSectionsLink(that.appId);
				permissionsUrlPromise.done(function(response) {
					location.href = response.profile_section_url;
				});
			};
		},

		loadHome: function() {
			this.changeView(Views.Main);
		},

		changeView: function(newView) {
			if (typeof this.view !== 'undefined') {
				this.stopListening(this.view);
			}
			this.view = Utils.loadView(newView, this.userId);
			this.listenTo(this.view, 'changeView', this.changeView);
			this.listenTo(this.view, 'goHome', this.loadHome);
		},

		_randomWelcome: function() {
			var welcomeMessages = ["Welcome, ", "Hey ", "Hello ", "Hi "];
			var rand = Math.floor(Math.random() * 4);
			return welcomeMessages[rand];
		},

		_continueInit: function() {
			this.loadHome();

			this.SearchPane = new Views.SearchForm({
				el: '#search-bar',
				id: 'search',
				userId: this.userId
			});

			this.listenTo(this.SearchPane, 'changeView', this.changeView);
			this.listenTo(this.SearchPane, 'goHome', this.loadHome);
			this.listenTo(this.view, 'changeView', this.changeView);
		}

	}, Backbone.Events);
	App.init();

});<commit_msg>Open graph collection in new window/tab.<commit_after>requirejs.config({
	shim: {
		'facebook': {
			export: 'FB'
		},
		'backbone': {
			deps: ["underscore", "jquery"],
			exports: "Backbone"
		},
		'underscore': {
			exports: "_"
		},
		'bootstrap': {
			deps: ["jquery"]
		},
		'jquery-ui': {
			deps: ["jquery"],
			exports: '$'
		}
	},
	"paths": {
		"jquery": "//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min",
		"jquery-ui": "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min",
		"facebook": "//connect.facebook.net/en_US/all",
		"underscore": "//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.1/underscore-min",
		"backbone": "//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min",
		"json": "//cdnjs.cloudflare.com/ajax/libs/json2/20121008/json2.min",
		"text": "//cdnjs.cloudflare.com/ajax/libs/require-text/2.0.10/text.min",
		'bootstrap': '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/js/bootstrap.min',

		'models': 'app/models/modelIndex',
		'model_want': 'app/models/want',
		'model_wants': 'app/models/wants',
		'model_search_item': 'app/models/searchItem',
		'model_search_results': 'app/models/searchResults',

		'views': 'app/views/viewIndex',
		'view_common': 'app/views/common',
		'view_main': 'app/views/main',
		'view_search': 'app/views/search',

		'utils': 'app/utils'
	}
});

requirejs(["jquery", "underscore", "backbone", "views", "utils", 'bootstrap'], function($, _, Backbone, Views, Utils) {

	// Create a loading indicator. Inspired by
	// http://tbranyen.com/post/how-to-indicate-backbone-fetch-progress
	_.each(["Model", "Collection"], function(name) {
		// Cache Backbone constructor.
		var ctor = Backbone[name];
		// Cache original fetch and set.
		var fetch = ctor.prototype.fetch;

		// Override the fetch method to emit a fetch event.
		ctor.prototype.fetch = function() {
			// Trigger the fetch event on the instance.
			this.trigger("fetch", this);

			// Pass through to original fetch.
			var result = fetch.apply(this, arguments);
			var that = this;
			result.success(function() {
				that.trigger("fetched", that);
			});
			return result;
		};
	});

	var App = _.extend({
		appId: '509825915758193',

		init: function() {
			FB.init({
				appId: this.appId,
				channelUrl: '//crowdbuy.sapuan.org/channel.html',
				oauth: true,
				xfbml: true
			});
			FB.login(function() {}, {
				scope: 'read_friendlists, user_about_me'
			});

			$('#loginbutton,#feedbutton').removeAttr('disabled');

			FB.getLoginStatus((function(that) {
				return function(response) {
					if (response.status === 'connected') {
						// Handle authentication here.
						Utils.logIn();

						FB.api('/me', function(response) {
							var welcomeString = that._randomWelcome();
							that.userId = response.id;
							$('#welcome').html(welcomeString + response.first_name + '!');

							if (that.view) {
								that.view.userId = response.id;
							}

							that._continueInit();
						});

					} else {
						alert("Whoa, something went wrong! Try refreshing this page.");
					}

				};
			})(this));

			$('#add-to-timeline').click(this.addToTimeline());
		},

		addToTimeline: function() {
			var that = this;
			return function() {
				var permissionsUrlPromise = Utils.getFacebookCustomSectionsLink(that.appId);
				permissionsUrlPromise.done(function(response) {
					window.open(response.profile_section_url, '_blank');
				});
			};
		},

		loadHome: function() {
			this.changeView(Views.Main);
		},

		changeView: function(newView) {
			if (typeof this.view !== 'undefined') {
				this.stopListening(this.view);
			}
			this.view = Utils.loadView(newView, this.userId);
			this.listenTo(this.view, 'changeView', this.changeView);
			this.listenTo(this.view, 'goHome', this.loadHome);
		},

		_randomWelcome: function() {
			var welcomeMessages = ["Welcome, ", "Hey ", "Hello ", "Hi "];
			var rand = Math.floor(Math.random() * 4);
			return welcomeMessages[rand];
		},

		_continueInit: function() {
			this.loadHome();

			this.SearchPane = new Views.SearchForm({
				el: '#search-bar',
				id: 'search',
				userId: this.userId
			});

			this.listenTo(this.SearchPane, 'changeView', this.changeView);
			this.listenTo(this.SearchPane, 'goHome', this.loadHome);
			this.listenTo(this.view, 'changeView', this.changeView);
		}

	}, Backbone.Events);
	App.init();

});<|endoftext|>


<commit_before>import React from 'react';
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';
import { Roles } from 'meteor/alanning:roles';
import { createContainer } from 'meteor/react-meteor-data';
import slugify from 'slugify';
import Cookies from 'js-cookie';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';

// components:
import Header from '/imports/ui/layouts/header/Header';
import FilterWidget from '/imports/ui/components/commentary/FilterWidget';
import Spinner from '/imports/ui/components/loading/Spinner';
import CommentLemmaSelect from '/imports/ui/components/editor/addComment/CommentLemmaSelect';
import AddComment from '/imports/ui/components/editor/addComment/AddComment';
import ContextPanel from '/imports/ui/layouts/commentary/ContextPanel';

// lib
import muiTheme from '/imports/lib/muiTheme';

// api
import Commenters from '/imports/api/collections/commenters';
import Keywords from '/imports/api/collections/keywords';
import ReferenceWorks from '/imports/api/collections/referenceWorks';

/*
 *	helpers
 */
const handlePermissions = () => {
	if (Roles.subscription.ready()) {
		if (!Roles.userIsInRole(Meteor.userId(), ['editor', 'admin', 'commenter'])) {
			FlowRouter.go('/');
		}
	}
};
const getReferenceWorks = (formData) => {
	let referenceWorks = null;
	if (formData.referenceWorksValue) {
		referenceWorks = ReferenceWorks.findOne({_id: formData.referenceWorksValue.value});
	}
	return referenceWorks;
};
const getCommenter = (formData) => {
	const commenter = Commenters.findOne({
		_id: formData.commenterValue.value,
	});
	return commenter;
};
const getKeywords = (formData) => {
	const keywords = [];

	formData.tagsValue.forEach((tag) => {
		const keyword = tag.keyword;
		keyword.isMentionedInLemma = tag.isMentionedInLemma;
		keywords.push(keyword);
	});
	return keywords;
};
const getFilterValues = (filters) => {
	const filterValues = {};

	filters.forEach((filter) => {
		if (filter.key === 'works') {
			filterValues.work = filter.values[0];
		} else if (filter.key === 'subworks') {
			filterValues.subwork = filter.values[0];
		} else if (filter.key === 'lineTo') {
			filterValues.lineTo = filter.values[0];
		} else if (filter.key === 'lineFrom') {
			filterValues.lineFrom = filter.values[0];
		}
	});

	return filterValues;
};

/*
 *	BEGIN AddCommentLayout
 */
class AddCommentLayout extends React.Component {
	static propTypes = {
		ready: React.PropTypes.bool,
		isTest: React.PropTypes.bool,
	};

	static defaultProps = {
		ready: false,
		isTest: false,
	};
	constructor(props) {
		super(props);

		this.state = {
			filters: [],
			selectedLineFrom: 0,
			selectedLineTo: 0,
			contextReaderOpen: true,
			loading: false,
			selectedWork: ''
		};

		// methods:
		this.updateSelectedLines = this.updateSelectedLines.bind(this);
		this.toggleSearchTerm = this.toggleSearchTerm.bind(this);

		this.addComment = this.addComment.bind(this);
		this.getWork = this.getWork.bind(this);
		this.getSubwork = this.getSubwork.bind(this);
		this.getLineLetter = this.getLineLetter.bind(this);
		this.getSelectedLineTo = this.getSelectedLineTo.bind(this);
		this.closeContextReader = this.closeContextReader.bind(this);
		this.openContextReader = this.openContextReader.bind(this);
		this.lineLetterUpdate = this.lineLetterUpdate.bind(this);
		this.handleChangeLineN = this.handleChangeLineN.bind(this);
	}

	componentWillUpdate() {
		handlePermissions();
	}

	// --- BEGNI LINE SELECTION --- //

	updateSelectedLines(selectedLineFrom, selectedLineTo) {
		if (selectedLineFrom === null) {
			this.setState({
				selectedLineTo,
			});
		} else if (selectedLineTo === null) {
			this.setState({
				selectedLineFrom,
			});
		} else if (selectedLineTo != null && selectedLineFrom != null) {
			this.setState({
				selectedLineFrom,
				selectedLineTo,
			});
		} else {
			// do nothing
		}
	}

	toggleSearchTerm(key, value) {
		const { filters } = this.state;

		let keyIsInFilter = false;
		let valueIsInFilter = false;
		let filterValueToRemove;
		let filterToRemove;

		filters.forEach((filter, i) => {
			if (filter.key === key) {
				keyIsInFilter = true;

				filter.values.forEach((filterValue, j) => {
					if (filterValue._id === value._id) {
						valueIsInFilter = true;
						filterValueToRemove = j;
					}
				});

				if (valueIsInFilter) {
					filter.values.splice(filterValueToRemove, 1);
					if (filter.values.length === 0) {
						filterToRemove = i;
					}
				} else if (key === 'works') {
					filters[i].values = [value];
				} else {
					filters[i].values.push(value);
				}
			}
		});

		if (typeof filterToRemove !== 'undefined') {
			filters.splice(filterToRemove, 1);
		}

		if (!keyIsInFilter) {
			filters.push({
				key,
				values: [value],
			});
		}

		this.setState({
			filters,
			skip: 0,
		});
	}

	// --- END LINE SELECTION --- //

	// --- BEGNI ADD COMMENT --- //

	addComment(formData, textValue, textRawValue) {
		this.setState({
			loading: true,
		});

		// get data for comment:
		const work = this.getWork();
		const subwork = this.getSubwork();
		const lineLetter = this.getLineLetter();
		const referenceWorks = formData.referenceWorks;
		const commenter = getCommenter(formData);
		const selectedLineTo = this.getSelectedLineTo();
		const token = Cookies.get('loginToken');

		// get keywords after they were created:
		const keywords = getKeywords(formData);
		const revisionId = new Meteor.Collection.ObjectID();

		// create comment object to be inserted:
		const comment = {
			work: {
				title: work.title,
				slug: work.slug,
				order: work.order,
			},
			subwork: {
				title: subwork.title,
				n: subwork.n,
			},
			lineFrom: this.state.selectedLineFrom,
			lineTo: selectedLineTo,
			lineLetter,
			nLines: (selectedLineTo - this.state.selectedLineFrom) + 1,
			revisions: [{
				_id: revisionId.valueOf(),
				title: formData.titleValue,
				text: textValue,
				textRaw: textRawValue,
				created: referenceWorks ? referenceWorks.date : new Date(),
				slug: slugify(formData.titleValue),
			}],
			commenters: commenter ? [{
				_id: commenter._id,
				name: commenter.name,
				slug: commenter.slug,
			}] : [{}],
			keywords: keywords || [{}],
			referenceWorks: referenceWorks,
			tenantId: Session.get('tenantId'),
			created: new Date(),
		};

		Meteor.call('comments.insert', token, comment, (error, commentId) => {
			FlowRouter.go('/commentary', {}, {_id: commentId});
		});
	}

	getWork() {
		let work = null;
		this.state.filters.forEach((filter) => {
			if (filter.key === 'works') {
				work = filter.values[0];
			}
		});
		if (!work) {
			work = {
				title: 'Iliad',
				slug: 'iliad',
				order: 1,
			};
		}
		return work;
	}

	getSubwork() {
		let subwork = null;
		this.state.filters.forEach((filter) => {
			if (filter.key === 'subworks') {
				subwork = filter.values[0];
			}
		});
		if (!subwork) {
			subwork = {
				title: '1',
				n: 1,
			};
		}
		return subwork;
	}

	getLineLetter() {

		const { selectedLineTo, selectedLineFrom } = this.state;

		let lineLetter = '';
		if (selectedLineTo === 0 && selectedLineFrom > 0) {
			lineLetter = this.commentLemmaSelect.state ? this.commentLemmaSelect.state.lineLetterValue : null;
		}
		return lineLetter;
	}

	getSelectedLineTo() {

		const { selectedLineTo, selectedLineFrom } = this.state;

		let newSelectedLineTo = 0;
		if (selectedLineTo === 0) {
			newSelectedLineTo = selectedLineFrom;
		} else {
			newSelectedLineTo = selectedLineTo;
		}
		return newSelectedLineTo;
	}

	// --- END ADD COMMENT --- //

	closeContextReader() {
		this.setState({
			contextReaderOpen: false,
		});
	}

	openContextReader() {
		this.setState({
			contextReaderOpen: true,
		});
	}

	lineLetterUpdate(value) {
		this.setState({
			lineLetter: value,
		});
	}

	handleChangeLineN(e) {
		const { filters } = this.state;

		if (e.from > 1) {
			let lineFromInFilters = false;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineFrom') {
					filters[i].values = [e.from];
					lineFromInFilters = true;
				}
			});

			if (!lineFromInFilters) {
				filters.push({
					key: 'lineFrom',
					values: [e.from],
				});
			}
		} else {
			let filterToRemove;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineFrom') {
					filterToRemove = i;
				}
			});

			if (typeof filterToRemove !== 'undefined') {
				filters.splice(filterToRemove, 1);
			}
		}

		if (e.to < 2100) {
			let lineToInFilters = false;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineTo') {
					filters[i].values = [e.to];
					lineToInFilters = true;
				}
			});

			if (!lineToInFilters) {
				filters.push({
					key: 'lineTo',
					values: [e.to],
				});
			}
		} else {
			let filterToRemove;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineTo') {
					filterToRemove = i;
				}
			});

			if (typeof filterToRemove !== 'undefined') {
				filters.splice(filterToRemove, 1);
			}
		}

		this.setState({
			filters,
		});
	}

	render() {

		const { isTest } = this.props;
		const { filters, loading, selectedLineFrom, selectedLineTo, contextReaderOpen } = this.state;

		const { work, subwork, lineFrom, lineTo } = getFilterValues(filters);

		return (
			<MuiThemeProvider muiTheme={getMuiTheme(muiTheme)}>
				{!loading ?

						{!isTest ?

										<CommentLemmaSelect
											ref={(component) => { this.commentLemmaSelect = component; }}
											selectedLineFrom={selectedLineFrom}
											selectedLineTo={selectedLineTo}
											workSlug={work ? work.slug : 'iliad'}
											subworkN={subwork ? subwork.n : 1}
										/>

										<AddComment
											selectedLineFrom={selectedLineFrom}
											selectedLineTo={selectedLineTo}
											submitForm={this.addComment}
										/>

										<ContextPanel
											open={contextReaderOpen}
											workSlug={work ? work.slug : 'iliad'}
											subworkN={subwork ? subwork.n : 1}
											lineFrom={lineFrom || 1}
											selectedLineFrom={selectedLineFrom}
											selectedLineTo={selectedLineTo}
											updateSelectedLines={this.updateSelectedLines}
											editor
										/>

								<FilterWidget
									filters={filters}
									toggleSearchTerm={this.toggleSearchTerm}
								/>

						: ''}

					:
					<Spinner fullPage />
				}
			</MuiThemeProvider>
		);
	}
}
/*
 *	END AddCommentLayout
 */

const AddCommentLayoutContainer = (() => {
	const ready = Roles.subscription.ready();
	return {
		ready,
	};
}, AddCommentLayout);

export default AddCommentLayoutContainer;
<commit_msg>fix adding comments to commentary publish status<commit_after>import React from 'react';
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';
import { Roles } from 'meteor/alanning:roles';
import { createContainer } from 'meteor/react-meteor-data';
import slugify from 'slugify';
import Cookies from 'js-cookie';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';

// components:
import Header from '/imports/ui/layouts/header/Header';
import FilterWidget from '/imports/ui/components/commentary/FilterWidget';
import Spinner from '/imports/ui/components/loading/Spinner';
import CommentLemmaSelect from '/imports/ui/components/editor/addComment/CommentLemmaSelect';
import AddComment from '/imports/ui/components/editor/addComment/AddComment';
import ContextPanel from '/imports/ui/layouts/commentary/ContextPanel';

// lib
import muiTheme from '/imports/lib/muiTheme';

// api
import Commenters from '/imports/api/collections/commenters';
import Keywords from '/imports/api/collections/keywords';
import ReferenceWorks from '/imports/api/collections/referenceWorks';

/*
 *	helpers
 */
const handlePermissions = () => {
	if (Roles.subscription.ready()) {
		if (!Roles.userIsInRole(Meteor.userId(), ['editor', 'admin', 'commenter'])) {
			FlowRouter.go('/');
		}
	}
};
const getReferenceWorks = (formData) => {
	let referenceWorks = null;
	if (formData.referenceWorksValue) {
		referenceWorks = ReferenceWorks.findOne({_id: formData.referenceWorksValue.value});
	}
	return referenceWorks;
};
const getCommenter = (formData) => {
	const commenter = Commenters.findOne({
		_id: formData.commenterValue.value,
	});
	return commenter;
};
const getKeywords = (formData) => {
	const keywords = [];

	formData.tagsValue.forEach((tag) => {
		const keyword = tag.keyword;
		keyword.isMentionedInLemma = tag.isMentionedInLemma;
		keywords.push(keyword);
	});
	return keywords;
};
const getFilterValues = (filters) => {
	const filterValues = {};

	filters.forEach((filter) => {
		if (filter.key === 'works') {
			filterValues.work = filter.values[0];
		} else if (filter.key === 'subworks') {
			filterValues.subwork = filter.values[0];
		} else if (filter.key === 'lineTo') {
			filterValues.lineTo = filter.values[0];
		} else if (filter.key === 'lineFrom') {
			filterValues.lineFrom = filter.values[0];
		}
	});

	return filterValues;
};

/*
 *	BEGIN AddCommentLayout
 */
class AddCommentLayout extends React.Component {
	static propTypes = {
		ready: React.PropTypes.bool,
		isTest: React.PropTypes.bool,
	};

	static defaultProps = {
		ready: false,
		isTest: false,
	};
	constructor(props) {
		super(props);

		this.state = {
			filters: [],
			selectedLineFrom: 0,
			selectedLineTo: 0,
			contextReaderOpen: true,
			loading: false,
			selectedWork: ''
		};

		// methods:
		this.updateSelectedLines = this.updateSelectedLines.bind(this);
		this.toggleSearchTerm = this.toggleSearchTerm.bind(this);

		this.addComment = this.addComment.bind(this);
		this.getWork = this.getWork.bind(this);
		this.getSubwork = this.getSubwork.bind(this);
		this.getLineLetter = this.getLineLetter.bind(this);
		this.getSelectedLineTo = this.getSelectedLineTo.bind(this);
		this.closeContextReader = this.closeContextReader.bind(this);
		this.openContextReader = this.openContextReader.bind(this);
		this.lineLetterUpdate = this.lineLetterUpdate.bind(this);
		this.handleChangeLineN = this.handleChangeLineN.bind(this);
	}

	componentWillUpdate() {
		handlePermissions();
	}

	// --- BEGNI LINE SELECTION --- //

	updateSelectedLines(selectedLineFrom, selectedLineTo) {
		if (selectedLineFrom === null) {
			this.setState({
				selectedLineTo,
			});
		} else if (selectedLineTo === null) {
			this.setState({
				selectedLineFrom,
			});
		} else if (selectedLineTo != null && selectedLineFrom != null) {
			this.setState({
				selectedLineFrom,
				selectedLineTo,
			});
		} else {
			// do nothing
		}
	}

	toggleSearchTerm(key, value) {
		const { filters } = this.state;

		let keyIsInFilter = false;
		let valueIsInFilter = false;
		let filterValueToRemove;
		let filterToRemove;

		filters.forEach((filter, i) => {
			if (filter.key === key) {
				keyIsInFilter = true;

				filter.values.forEach((filterValue, j) => {
					if (filterValue._id === value._id) {
						valueIsInFilter = true;
						filterValueToRemove = j;
					}
				});

				if (valueIsInFilter) {
					filter.values.splice(filterValueToRemove, 1);
					if (filter.values.length === 0) {
						filterToRemove = i;
					}
				} else if (key === 'works') {
					filters[i].values = [value];
				} else {
					filters[i].values.push(value);
				}
			}
		});

		if (typeof filterToRemove !== 'undefined') {
			filters.splice(filterToRemove, 1);
		}

		if (!keyIsInFilter) {
			filters.push({
				key,
				values: [value],
			});
		}

		this.setState({
			filters,
			skip: 0,
		});
	}

	// --- END LINE SELECTION --- //

	// --- BEGNI ADD COMMENT --- //

	addComment(formData, textValue, textRawValue) {
		this.setState({
			loading: true,
		});

		// get data for comment:
		const work = this.getWork();
		const subwork = this.getSubwork();
		const lineLetter = this.getLineLetter();
		const referenceWorks = formData.referenceWorks;
		const commenter = getCommenter(formData);
		const selectedLineTo = this.getSelectedLineTo();
		const token = Cookies.get('loginToken');

		// get keywords after they were created:
		const keywords = getKeywords(formData);
		const revisionId = new Meteor.Collection.ObjectID();

		// create comment object to be inserted:
		const comment = {
			work: {
				title: work.title,
				slug: work.slug,
				order: work.order,
			},
			subwork: {
				title: subwork.title,
				n: subwork.n,
			},
			lineFrom: this.state.selectedLineFrom,
			lineTo: selectedLineTo,
			lineLetter,
			nLines: (selectedLineTo - this.state.selectedLineFrom) + 1,
			revisions: [{
				_id: revisionId.valueOf(),
				title: formData.titleValue,
				text: textValue,
				textRaw: textRawValue,
				created: referenceWorks ? referenceWorks.date : new Date(),
				slug: slugify(formData.titleValue),
			}],
			commenters: commenter ? [{
				_id: commenter._id,
				name: commenter.name,
				slug: commenter.slug,
			}] : [{}],
			keywords: keywords || [{}],
			referenceWorks: referenceWorks,
			tenantId: Session.get('tenantId'),
			created: new Date(),
			status: 'publish',
		};

		Meteor.call('comments.insert', token, comment, (error, commentId) => {
			if (error) {
				console.error(error);
				return null;
			}

			FlowRouter.go('/commentary', {}, {_id: commentId});
		});
	}

	getWork() {
		let work = null;
		this.state.filters.forEach((filter) => {
			if (filter.key === 'works') {
				work = filter.values[0];
			}
		});
		if (!work) {
			work = {
				title: 'Iliad',
				slug: 'iliad',
				order: 1,
			};
		}
		return work;
	}

	getSubwork() {
		let subwork = null;
		this.state.filters.forEach((filter) => {
			if (filter.key === 'subworks') {
				subwork = filter.values[0];
			}
		});
		if (!subwork) {
			subwork = {
				title: '1',
				n: 1,
			};
		}
		return subwork;
	}

	getLineLetter() {

		const { selectedLineTo, selectedLineFrom } = this.state;

		let lineLetter = '';
		if (selectedLineTo === 0 && selectedLineFrom > 0) {
			lineLetter = this.commentLemmaSelect.state ? this.commentLemmaSelect.state.lineLetterValue : null;
		}
		return lineLetter;
	}

	getSelectedLineTo() {

		const { selectedLineTo, selectedLineFrom } = this.state;

		let newSelectedLineTo = 0;
		if (selectedLineTo === 0) {
			newSelectedLineTo = selectedLineFrom;
		} else {
			newSelectedLineTo = selectedLineTo;
		}
		return newSelectedLineTo;
	}

	// --- END ADD COMMENT --- //

	closeContextReader() {
		this.setState({
			contextReaderOpen: false,
		});
	}

	openContextReader() {
		this.setState({
			contextReaderOpen: true,
		});
	}

	lineLetterUpdate(value) {
		this.setState({
			lineLetter: value,
		});
	}

	handleChangeLineN(e) {
		const { filters } = this.state;

		if (e.from > 1) {
			let lineFromInFilters = false;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineFrom') {
					filters[i].values = [e.from];
					lineFromInFilters = true;
				}
			});

			if (!lineFromInFilters) {
				filters.push({
					key: 'lineFrom',
					values: [e.from],
				});
			}
		} else {
			let filterToRemove;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineFrom') {
					filterToRemove = i;
				}
			});

			if (typeof filterToRemove !== 'undefined') {
				filters.splice(filterToRemove, 1);
			}
		}

		if (e.to < 2100) {
			let lineToInFilters = false;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineTo') {
					filters[i].values = [e.to];
					lineToInFilters = true;
				}
			});

			if (!lineToInFilters) {
				filters.push({
					key: 'lineTo',
					values: [e.to],
				});
			}
		} else {
			let filterToRemove;

			filters.forEach((filter, i) => {
				if (filter.key === 'lineTo') {
					filterToRemove = i;
				}
			});

			if (typeof filterToRemove !== 'undefined') {
				filters.splice(filterToRemove, 1);
			}
		}

		this.setState({
			filters,
		});
	}

	render() {

		const { isTest } = this.props;
		const { filters, loading, selectedLineFrom, selectedLineTo, contextReaderOpen } = this.state;

		const { work, subwork, lineFrom, lineTo } = getFilterValues(filters);

		return (
			<MuiThemeProvider muiTheme={getMuiTheme(muiTheme)}>
				{!loading ?

						{!isTest ?

										<CommentLemmaSelect
											ref={(component) => { this.commentLemmaSelect = component; }}
											selectedLineFrom={selectedLineFrom}
											selectedLineTo={selectedLineTo}
											workSlug={work ? work.slug : 'iliad'}
											subworkN={subwork ? subwork.n : 1}
										/>

										<AddComment
											selectedLineFrom={selectedLineFrom}
											selectedLineTo={selectedLineTo}
											submitForm={this.addComment}
										/>

										<ContextPanel
											open={contextReaderOpen}
											workSlug={work ? work.slug : 'iliad'}
											subworkN={subwork ? subwork.n : 1}
											lineFrom={lineFrom || 1}
											selectedLineFrom={selectedLineFrom}
											selectedLineTo={selectedLineTo}
											updateSelectedLines={this.updateSelectedLines}
											editor
										/>

								<FilterWidget
									filters={filters}
									toggleSearchTerm={this.toggleSearchTerm}
								/>

						: ''}

					:
					<Spinner fullPage />
				}
			</MuiThemeProvider>
		);
	}
}
/*
 *	END AddCommentLayout
 */

const AddCommentLayoutContainer = (() => {
	const ready = Roles.subscription.ready();
	return {
		ready,
	};
}, AddCommentLayout);

export default AddCommentLayoutContainer;
<|endoftext|>