<commit_before>var env, store, User, Message, NotMessage, Video;
var run = Ember.run;

var attr = DS.attr;
var hasMany = DS.hasMany;
var belongsTo = DS.belongsTo;

function stringify(string) {
  return function() { return string; };
}

module('integration/relationships/polymorphic_mixins_has_many_test - Polymorphic hasMany relationships with mixins', {
  setup: function() {
    User = DS.Model.extend({
      name: attr('string'),
      messages: hasMany('message', { async: true, polymorphic: true })
    });
    User.toString = stringify('User');

    Message = Ember.Mixin.create({
      title: attr('string'),
      user: belongsTo('user', { async: true })
    });
    Message.toString = stringify('Message');

    Video = DS.Model.extend(Message, {
      video: attr()
    });

    NotMessage = DS.Model.extend({
      video: attr()
    });

    env = setupStore({
      user: User,
      video: Video,
      notMessage: NotMessage
    });

    env.registry.register('mixin:message', Message);
    store = env.store;
  },

  teardown: function() {
    run(env.container, 'destroy');
  }
});

/*
  Server loading tests
*/

test("Relationship is available from the belongsTo side even if only loaded from the hasMany side - async", function () {
  var user, video;
  run(function() {
    user = store.push('user', { id: 1, name: 'Stanley', messages: [{ id: 2, type: 'video' }] });
    video = store.push('video', { id: 2, video: 'Here comes Youtube' });
  });
  run(function() {
    user.get('messages').then(function(messages) {
      equal(messages.objectAt(0), video, 'The hasMany has loaded correctly');
      messages.objectAt(0).get('user').then(function(fetchedUser) {
        equal(fetchedUser, user, 'The inverse was setup correctly');
      });
    });
  });
});

/*
  Local edits
*/
test("Pushing to the hasMany reflects the change on the belongsTo side - async", function () {
  var user, video;
  run(function() {
    user = store.push('user', { id: 1, name: 'Stanley', messages: [] });
    video = store.push('video', { id: 2, video: 'Here comes Youtube' });
  });

  run(function() {
    user.get('messages').then(function(fetchedMessages) {
      fetchedMessages.pushObject(video);
      video.get('user').then(function(fetchedUser) {
        equal(fetchedUser, user, "user got set correctly");
      });
    });
  });
});

/*
  Local edits
*/
test("Pushing a an object that does not implement the mixin to the mixin accepting array errors out", function () {
  var user,notMessage;
  run(function() {
    user = store.push('user', { id: 1, name: 'Stanley', messages: [] });
    notMessage = store.push('not-message', { id: 2, video: 'Here comes Youtube' });
  });

  run(function() {
    user.get('messages').then(function(fetchedMessages) {
      expectAssertion(function() {
        fetchedMessages.pushObject(notMessage);
      }, /You cannot add a record of type 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/);
    });
  });
});

test("Pushing to the hasMany reflects the change on the belongsTo side - model injections true", function () {
  var injectionValue = Ember.MODEL_FACTORY_INJECTIONS;
  Ember.MODEL_FACTORY_INJECTIONS = true;

  try {
    var user, video;
    run(function() {
      user = store.push('user', { id: 1, name: 'Stanley', messages: [] });
      video = store.push('video', { id: 2, video: 'Here comes Youtube' });
    });

    run(function() {
      user.get('messages').then(function(fetchedMessages) {
        fetchedMessages.pushObject(video);
        video.get('user').then(function(fetchedUser) {
          equal(fetchedUser, user, "user got set correctly");
        });
      });
    });
  } finally {
    Ember.MODEL_FACTORY_INJECTIONS = injectionValue;
  }
});

/*
  Local edits
*/
test("Pushing a an object that does not implement the mixin to the mixin accepting array errors out - model injections true", function () {
  var injectionValue = Ember.MODEL_FACTORY_INJECTIONS;
  Ember.MODEL_FACTORY_INJECTIONS = true;

  try {
    var user,notMessage;
    run(function() {
      user = store.push('user', { id: 1, name: 'Stanley', messages: [] });
      notMessage = store.push('not-message', { id: 2, video: 'Here comes Youtube' });
    });

    run(function() {
      user.get('messages').then(function(fetchedMessages) {
        expectAssertion(function() {
          fetchedMessages.pushObject(notMessage);
        }, /You cannot add a record of type 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/);
      });
    });
  } finally {
    Ember.MODEL_FACTORY_INJECTIONS = injectionValue;
  }
});

<commit_msg>polymorphic changes store.push<commit_after>var env, store, User, Message, NotMessage, Video;
var run = Ember.run;

var attr = DS.attr;
var hasMany = DS.hasMany;
var belongsTo = DS.belongsTo;

function stringify(string) {
  return function() { return string; };
}

module('integration/relationships/polymorphic_mixins_has_many_test - Polymorphic hasMany relationships with mixins', {
  setup: function() {
    User = DS.Model.extend({
      name: attr('string'),
      messages: hasMany('message', { async: true, polymorphic: true })
    });
    User.toString = stringify('User');

    Message = Ember.Mixin.create({
      title: attr('string'),
      user: belongsTo('user', { async: true })
    });
    Message.toString = stringify('Message');

    Video = DS.Model.extend(Message, {
      video: attr()
    });

    NotMessage = DS.Model.extend({
      video: attr()
    });

    env = setupStore({
      user: User,
      video: Video,
      notMessage: NotMessage
    });

    env.registry.register('mixin:message', Message);
    store = env.store;
  },

  teardown: function() {
    run(env.container, 'destroy');
  }
});

/*
  Server loading tests
*/

test("Relationship is available from the belongsTo side even if only loaded from the hasMany side - async", function () {
  var user, video;
  run(function() {
    user = store.push({
        data: {
            id: '1',
            type: 'user',
            attributes: {
                name: 'Stanley'
            },
            relationships: {
                messages: {
                    data: [{
                        id: '2',
                        type: 'video'
                    }]
                }
            }
        }
    });
    video = store.push({
        data: {
            id: '2',
            type: 'video',
            attributes: {
                video: 'Here comes Youtube'
            }
        }
    });

  });
  run(function() {
    user.get('messages').then(function(messages) {
      equal(messages.objectAt(0), video, 'The hasMany has loaded correctly');
      messages.objectAt(0).get('user').then(function(fetchedUser) {
        equal(fetchedUser, user, 'The inverse was setup correctly');
      });
    });
  });
});

/*
  Local edits
*/
test("Pushing to the hasMany reflects the change on the belongsTo side - async", function () {
  var user, video;
  run(function() {
    user = store.push({
        data: {
            id: '1',
            type: 'user',
            attributes: {
                name: 'Stanley'
            },
            relationships: {
                messages: {
                    data: []
                }
            }
        }
    });
    video = store.push({
        data: {
            id: '2',
            type: 'video',
            attributes: {
                video: 'Here comes Youtube'
            }
        }
    });

  });

  run(function() {
    user.get('messages').then(function(fetchedMessages) {
      fetchedMessages.pushObject(video);
      video.get('user').then(function(fetchedUser) {
        equal(fetchedUser, user, "user got set correctly");
      });
    });
  });
});

/*
  Local edits
*/
test("Pushing a an object that does not implement the mixin to the mixin accepting array errors out", function () {
  var user,notMessage;
  run(function() {
    user = store.push('user', { id: '1', name: 'Stanley', messages: [] });
    notMessage = store.push('not-message', { id: '2', video: 'Here comes Youtube' });
  });

  run(function() {
    user.get('messages').then(function(fetchedMessages) {
      expectAssertion(function() {
        fetchedMessages.pushObject(notMessage);
      }, /You cannot add a record of type 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/);
    });
  });
});

test("Pushing to the hasMany reflects the change on the belongsTo side - model injections true", function () {
  var injectionValue = Ember.MODEL_FACTORY_INJECTIONS;
  Ember.MODEL_FACTORY_INJECTIONS = true;

  try {
    var user, video;
    run(function() {
      user = store.push('user', { id: '1', name: 'Stanley', messages: [] });
      video = store.push('video', { id: '2', video: 'Here comes Youtube' });
    });

    run(function() {
      user.get('messages').then(function(fetchedMessages) {
        fetchedMessages.pushObject(video);
        video.get('user').then(function(fetchedUser) {
          equal(fetchedUser, user, "user got set correctly");
        });
      });
    });
  } finally {
    Ember.MODEL_FACTORY_INJECTIONS = injectionValue;
  }
});

/*
  Local edits
*/
test("Pushing a an object that does not implement the mixin to the mixin accepting array errors out - model injections true", function () {
  var injectionValue = Ember.MODEL_FACTORY_INJECTIONS;
  Ember.MODEL_FACTORY_INJECTIONS = true;

  try {
    var user,notMessage;
    run(function() {
      user = store.push('user', { id: '1', name: 'Stanley', messages: [] });
      notMessage = store.push('not-message', { id: '2', video: 'Here comes Youtube' });
    });

    run(function() {
      user.get('messages').then(function(fetchedMessages) {
        expectAssertion(function() {
          fetchedMessages.pushObject(notMessage);
        }, /You cannot add a record of type 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/);
      });
    });
  } finally {
    Ember.MODEL_FACTORY_INJECTIONS = injectionValue;
  }
});

<|endoftext|>


<commit_before>
var through = require('through')
var stringify = require('json-stable-stringify')
var Binomial = require('./')
var createHash = require('crypto').createHash

module.exports = function (opts) {
  opts = opts || {}

  var ranges = Binomial(opts.start, opts.size)
  var alg = opts.alg || 'sha256'

  if(opts.reverse)
    ranges = ranges.reverse()

  var _ts = opts.ts, getTs = _ts

  if(!_ts)
    throw new Error('a ts function or property name must be provided')

  if('string' === typeof _ts)
    getTs = function (data) {
      return new Date(data[_ts])
    }

  var current = ranges.shift()
  var hash = createHash(alg)
  var count = 0

  function next () {
    if(count > 0) {
      current.hash = hash.digest('hex')
      current.count = count
      count = 0
      hash = createHash(alg)
      this.queue(current)
    }
    current = ranges.shift()
    if(!current) return this.queue(null)
  }

  return through(function (data) {
    var ts = getTs(data)

    //this should never happen
    if(ts < current.gte)
      return this.emit('error',
        new Error('timestamps out of order:'+ts+'>='+current.gte))

    //if we are now in the next group, continue.
    while(ts >= current.lt)
      next.call(this)

    count ++

    var enc = (
        Buffer.isBuffer(data) ? null
      : 'string' === typeof data ? 'utf8'
      : data=stringify(data), 'ascii'
    )

    hash.update(data, enc)
  }, function () {
    next.call(this)
    this.queue(null)
  })

}
<commit_msg>fail gracefully<commit_after>
var through = require('through')
var stringify = require('json-stable-stringify')
var Binomial = require('./')
var createHash = require('crypto').createHash

module.exports = function (opts) {
  opts = opts || {}

  var ranges = Binomial(opts.start, opts.size)
  var alg = opts.alg || 'sha256'

  if(opts.reverse)
    ranges = ranges.reverse()

  var _ts = opts.ts, getTs = _ts

  if(!_ts)
    throw new Error('a ts function or property name must be provided')

  if('string' === typeof _ts)
    getTs = function (data) {
      return new Date(data[_ts])
    }

  var current = ranges.shift()
  var hash = createHash(alg)
  var count = 0

  function next () {
    if(count > 0) {
      current.hash = hash.digest('hex')
      current.count = count
      count = 0
      hash = createHash(alg)
      this.queue(current)
    }
    current = ranges.shift()
    if(!current) return this.queue(null)
  }

  return through(function (data) {
    var ts = getTs(data)

    //this should never happen
    if(ts < current.gte)
      return this.emit('error',
        new Error('timestamps out of order:'+ts+'>='+current.gte))

    //if we are now in the next group, continue.
    while(current && ts >= current.lt) {
      next.call(this)
    }

    count ++

    var enc = (
        Buffer.isBuffer(data) ? null
      : 'string' === typeof data ? 'utf8'
      : data=stringify(data), 'ascii'
    )

    hash.update(data, enc)
  }, function () {
    next.call(this)
    this.queue(null)
  })

}
<|endoftext|>


<commit_before>import { operationDelete } from '../operations/index';
import { osmIsInterestingTag } from '../osm/tags';
import { t } from '../util/locale';
import { utilDisplayLabel } from '../util';
import { validationIssue, validationIssueFix } from '../core/validator';

export function validationMissingTag() {
    var type = 'missing_tag';

    function hasDescriptiveTags(entity) {
        var keys = Object.keys(entity.tags)
            .filter(function(k) {
                if (k === 'area' || k === 'name') {
                    return false;
                } else {
                    return osmIsInterestingTag(k);
                }
            });

        if (entity.type === 'relation' && keys.length === 1) {
            return entity.tags.type !== 'multipolygon';
        }
        return keys.length > 0;
    }

    var validation = function checkMissingTag(entity, context) {
        var graph = context.graph();

        // ignore vertex features and relation members
        if (entity.geometry(graph) === 'vertex' || entity.hasParentRelations(graph)) {
            return [];
        }

        var messageObj = {};
        var missingTagType;

        if (Object.keys(entity.tags).length === 0) {
            missingTagType = 'any';
        } else if (!hasDescriptiveTags(entity)) {
            missingTagType = 'descriptive';
        } else if (entity.type === 'relation' && !entity.tags.type) {
            missingTagType = 'specific';
            messageObj.tag = 'type';
        }

        if (!missingTagType) {
            return [];
        }

        messageObj.feature = utilDisplayLabel(entity, context);

        var fixes = [
            new validationIssueFix({
                icon: 'iD-icon-search',
                title: t('issues.fix.select_preset.title'),
                onClick: function() {
                    context.ui().sidebar.showPresetList();
                }
            })
        ];

        var canDelete = false;
        if (!operationDelete([entity.id], context).disabled()) {
            canDelete = true;
            fixes.push(
                new validationIssueFix({
                    icon: 'iD-operation-delete',
                    title: t('issues.fix.delete_feature.title'),
                    onClick: function() {
                        var id = this.issue.entities[0].id;
                        var operation = operationDelete([id], context);
                        if (!operation.disabled()) {
                            operation();
                        }
                    }
                })
            );
        }

        // error if created or modified and is deletable, else warning
        var isError = (entity.version === undefined || entity.v !== undefined) && canDelete;

        return [new validationIssue({
            type: type,
            severity: isError ? 'error' : 'warning',
            message: t('issues.missing_tag.' + missingTagType + '.message', messageObj),
            reference: showReference,
            entities: [entity],
            fixes: fixes
        })];

        function showReference(selection) {
            selection.selectAll('.issue-reference')
                .data([0])
                .enter()
                .append('div')
                .attr('class', 'issue-reference')
                .text(t('issues.missing_tag.tip'));
        }
    };

    validation.type = type;

    return validation;
}
<commit_msg>Better test for whether untagged entities can be deleted<commit_after>import { operationDelete } from '../operations/index';
import { osmIsInterestingTag } from '../osm/tags';
import { t } from '../util/locale';
import { utilDisplayLabel } from '../util';
import { validationIssue, validationIssueFix } from '../core/validator';

export function validationMissingTag() {
    var type = 'missing_tag';

    function hasDescriptiveTags(entity) {
        var keys = Object.keys(entity.tags)
            .filter(function(k) {
                if (k === 'area' || k === 'name') {
                    return false;
                } else {
                    return osmIsInterestingTag(k);
                }
            });

        if (entity.type === 'relation' && keys.length === 1) {
            return entity.tags.type !== 'multipolygon';
        }
        return keys.length > 0;
    }

    var validation = function checkMissingTag(entity, context) {
        var graph = context.graph();

        // ignore vertex features and relation members
        if (entity.geometry(graph) === 'vertex' || entity.hasParentRelations(graph)) {
            return [];
        }

        var messageObj = {};
        var missingTagType;

        if (Object.keys(entity.tags).length === 0) {
            missingTagType = 'any';
        } else if (!hasDescriptiveTags(entity)) {
            missingTagType = 'descriptive';
        } else if (entity.type === 'relation' && !entity.tags.type) {
            missingTagType = 'specific';
            messageObj.tag = 'type';
        }

        if (!missingTagType) {
            return [];
        }

        messageObj.feature = utilDisplayLabel(entity, context);

        var fixes = [
            new validationIssueFix({
                icon: 'iD-icon-search',
                title: t('issues.fix.select_preset.title'),
                onClick: function() {
                    context.ui().sidebar.showPresetList();
                }
            })
        ];

        // can always delete if the user created it in the first place..
        var canDelete = (entity.version === undefined || entity.v !== undefined);

        // otherwise check with operationDelete whether we can delete this entity
        if (!canDelete) {
            canDelete = !operationDelete([entity.id], context).disabled();
        }

        if (canDelete) {
            fixes.push(
                new validationIssueFix({
                    icon: 'iD-operation-delete',
                    title: t('issues.fix.delete_feature.title'),
                    onClick: function() {
                        var id = this.issue.entities[0].id;
                        var operation = operationDelete([id], context);
                        if (!operation.disabled()) {
                            operation();
                        }
                    }
                })
            );
        }

        return [new validationIssue({
            type: type,
            severity: canDelete ? 'error' : 'warning',
            message: t('issues.missing_tag.' + missingTagType + '.message', messageObj),
            reference: showReference,
            entities: [entity],
            fixes: fixes
        })];

        function showReference(selection) {
            selection.selectAll('.issue-reference')
                .data([0])
                .enter()
                .append('div')
                .attr('class', 'issue-reference')
                .text(t('issues.missing_tag.tip'));
        }
    };

    validation.type = type;

    return validation;
}
<|endoftext|>


<commit_before>/**
 * Javascript client for STREST protocol.
 *
 * Assumes a websocket is available to a server supporting STREST requests.
 *
 *
 *
 * @param url
 * @param onopen
 * @param onclose
 * @return
 */

function Strest(url, onopen, onclose) {
	//callbacks keyed by transactionId
	this.callbacks = {};

	var self = this;
	var _onmessage = function(event) {
		//console.log(event.data);
		var response = new StrestResponse(event.data);
		var txnId = response.getHeader('txn.id');
		var cb = self.callbacks[txnId];
		if (!cb) {
			console.log("ERROR: No callback registered for : " + response);
			return;
		}
		if (cb['onmessage']) {
			cb.onmessage(response);
		}
		if ('complete' == response.getHeader('txn.status')) {
			if (cb['ontxncomplete']) {
				cb.ontxncomplete(txnId);
			}
			delete self.callbacks[txnId];
		}
	};

	var _onclose = function(event) {
		//iterate over all the waiting callbacks and send the error
		for (var k in self.callbacks) {
			var cb = self.callbacks[k];
			if (cb.onerror) {
				cb.onerror('Connection closed');
			}
		}
		self.callbacks = {};
		if (onclose) {
			onclose(event);
		}
	};

	var _onopen = function(event) {
		if (onopen) {
			onopen(event);
		}
	};

	var _onerror = function(event) {
		self.close();
	};

	//initialize the websocket
	if (window.WebSocket) {
		this.socket = new WebSocket(url);
		this.socket.onmessage = _onmessage;
		this.socket.onopen = _onopen;
		this.socket.onclose = _onclose;
	} else {
	  alert("Your browser does not support Web Socket.");
	}

}

/*
 * Globals
 *
 */
Strest._txnId = 0;
Strest.userAgent = "JsStrest 2.0";
Strest.protocol = "2";
Strest.txnId = function() {
	return Strest._txnId++;
};

/**
 * Sends a request.
 *
 *
 *
 * @param request
 * @param message_callback
 * @param txn_end_callback
 * @param error_callback
 * @return
 */
Strest.prototype.sendRequest = function(request, message_callback, txn_complete_callback, error_callback) {
	if (!this.connected()) {
		throw "Not yet connected!";
	}
	//set up the headers.
	if (!(request instanceof StrestRequest)) {
		request = new StrestRequest(request);
	}

	request.setHeaderIfAbsent('method', 'GET');
	request.setHeaderIfAbsent('user-agent', Strest.userAgent);
	request.setHeaderIfAbsent('txn.id', Strest.txnId());
	request.setHeaderIfAbsent('txn.accept', 'multi');
	console.log(request)
	//register the callbacks
	this.callbacks[request.getHeader('txn.id')] = {
			'onmessage' : message_callback,
			'ontxncomplete' : txn_complete_callback,
			'onerror' : error_callback
	};

	var msg = request.toString();
	this.socket.send(msg);
	return request;
};

Strest.prototype.close = function() {
	if (this.connected()) {
		this.socket.close();
	}
};

Strest.prototype.connected = function() {
	if (!this.socket) {
		return false;
	}
	return this.socket.readyState == WebSocket.OPEN;
};

function StrestMessage() {
	this.strest = {};
	this.strest.txn = {};
};

/**
 * Set a field in the request.  honors the dot operator

 * @param key
 * @param value
 * @return
 */
StrestMessage.prototype.setHeader = function(key, value) {
	var keys = key.split('.')
	var d = this['strest'];
	for (var i = 0, len = keys.length; i < len; i++) {
		var k = keys[i];
		if (i == keys.length-1) {
			d[k] = value;
		} else {
			if (!d[k]) {
				d[k] = {};
			}
			d = d[k];
		}
	}
};

StrestMessage.prototype.setHeaderIfAbsent = function(key, value) {
	var v = this.getHeader(key);
	if (v != null) {
		return v;
	}
	this.setHeader(key, value);
};

StrestMessage.prototype.getHeader = function(key) {
	var keys = key.split('.');
	var d = this['strest'];
	for (var i = 0, len = keys.length; i < len; i++) {
		var k = keys[i];
		d = d[k];
		if (i == keys.length-1) {
			return d;
		}
	}
	return null;
};

StrestRequest.prototype = new StrestMessage;
StrestRequest.prototype.constructor = StrestRequest;
/**
 * A strest request.
 *
 * example:
 * var request = new StrestRequest({ method : 'GET', uri : '/firehose'})
 *
 *
 *
 * @param options
 * uri
 * method : one of 'GET', 'POST', 'PUT', 'DELETE'
 * params : these will get added to the uri
 *
 */
function StrestRequest(options) {
	StrestMessage.call(this);
	// console.log(options);
	this.setHeader('method', options['method']);
	this.setHeader('v', Strest.protocol);
	this.setHeader('user-agent', Strest.userAgent);
	this.setHeader('uri', options['uri']);
	this.setHeader('params', options['params']);

	// console.log(this);
};

StrestRequest.prototype.setUri = function(uri) {
	this.setHeader('uri', uri);
};
StrestRequest.prototype.setMethod = function(method) {
	this.setHeader('method', method);
};

StrestRequest.prototype.toString = function() {
	return JSON.stringify(this);
};

StrestResponse.prototype = new StrestMessage;
StrestResponse.prototype.constructor = StrestResponse;
/**
 * A strest response.
 *
 * @param options
 */
function StrestResponse(msg) {
	StrestMessage.call(this);
	this.originalText = msg;
	var tmp = JSON.parse(msg)
	for (key in tmp) {
		this[key] = tmp[key]
	}
};

StrestResponse.prototype.toString = function() {
	return this.originalText;
};

Strest.isString= function(obj) {
	if (!obj) {
		return false;
	}
	if (obj instanceof String) {
		return true;
	}
	if (typeof(obj) == 'string') {
		return true;
	}
	return false;
};

Strest.trim = function(str) {
	if (!Strest.isString(str)) {
		return str;
	}
//	http://forum.jquery.com/topic/faster-jquery-trimjavascript to
	str = str.replace(/^\s+/, '');
	for (var i = str.length - 1; i >= 0; i--) {
		if (/\S/.test(str.charAt(i))) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return str;
};<commit_msg>update to automatically handle reconnects and keepalive pings<commit_after>/**
 * Javascript client for STREST protocol.
 *
 * Assumes a websocket is available to a server supporting STREST requests.
 *
 *
 *
 * @return
 */

function Strest(config) {

	this.config = $.extend({
		//The url to connect to
		url : "Connectionurl",
		//called when the connection is closed
		onclose : function(event) {

		},
		//called when the connection is opened
		onopen : function(event) {

		},
		//will attempt to keep the connection live
		//will attempt to reconnect if the connection
		// is broken.  onclose, onopen will still be
		// called on reconnect
		keepalive : true,
		//the endpoint to use for keep alives
		//endpoint only needs to return a 200 strest packet
		ping : "/ping"
	}, config)

	//callbacks keyed by transactionId
	this.callbacks = {};

	this.pingTimer = null
	this.reconnectTimer = null

	var self = this;
	this._onmessage = function(event) {
		//console.log(event.data);
		var response = new StrestResponse(event.data);
		var txnId = response.getHeader('txn.id');
		var cb = self.callbacks[txnId];
		if (!cb) {
			console.log("ERROR: No callback registered for : " + response);
			return;
		}
		if (cb['onmessage']) {
			cb.onmessage(response);
		}
		if ('complete' == response.getHeader('txn.status')) {
			if (cb['ontxncomplete']) {
				cb.ontxncomplete(txnId);
			}
			delete self.callbacks[txnId];
		}
	};

	this._onclose = function(event) {
		//iterate over all the waiting callbacks and send the error
		for (var k in self.callbacks) {
			var cb = self.callbacks[k];
			if (cb.onerror) {
				cb.onerror('Connection closed');
			}
		}
		self.callbacks = {};
		if (self.pingTimer) {
			clearInterval(self.pingTimer)
			self.pingTimer = null
		}
		if (self.config.onclose) {
			self.config.onclose(event);
		}

		if (self.config.keepalive) {
			if (self.reconnectTimer) {
				clearInterval(self.reconnectTimer)
			}
			self.reconnectTimer = setInterval(function() {
				console.log("reconnect attempt");
				self.connect();
			}, 4000)
		}
	};

	this._onopen = function(event) {
		//clear the reconnect timer
		if (self.reconnectTimer) {
			clearInterval(self.reconnectTimer)
		}

		//start ping timer.
		if (self.config.keepalive && self.config.ping) {
			//this should never be, but best to be extra safe
			if (self.pingTimer) {
				clearInterval(self.pingTimer)
				self.pingTimer = null
			}
			self.pingTimer = setInterval(function() {
				self.sendRequest({
                    uri : self.config.ping
                  },
                  function(response) {},
                  function(txnId) {},
                  function(error) {
                  	//ping error
                  	console.log("Ping error!", error)
                  	self.close()
                  }
                );
			}, 20000)
		}

		if (self.config.onopen) {
			self.config.onopen(event);
		}
	};

	this._onerror = function(event) {
		self.close();
	};

}

/*
 * Globals
 *
 */
Strest._txnId = 0;
Strest.userAgent = "JsStrest 2.0";
Strest.protocol = "2";
Strest.txnId = function() {
	return Strest._txnId++;
};

Strest.prototype.close = function() {
	if (this.connected()) {
		this.socket.close();
	}
};

//connect to the websocket
Strest.prototype.connect = function() {
	if (this.connected()) {
		console.log("already connected")
		return;
	}
	//initialize the websocket
	if (window.WebSocket) {
		this.socket = new WebSocket(this.config.url);
		this.socket.onmessage = this._onmessage;
		this.socket.onopen = this._onopen;
		this.socket.onclose = this._onclose;
	} else {
	  alert("Your browser does not support Web Socket.");
	}
};

Strest.prototype.connected = function() {
	if (!this.socket) {
		return false;
	}
	return this.socket.readyState == WebSocket.OPEN;
};

/**
 * Sends a request.
 *
 *
 *
 * @param request
 * @param message_callback(response)
 * @param txn_end_callback(txnId)
 * @param error_callback(error)
 * @return
 */
Strest.prototype.sendRequest = function(request, message_callback, txn_complete_callback, error_callback) {
	if (!this.connected()) {
		throw "Not yet connected!";
	}
	//set up the headers.
	if (!(request instanceof StrestRequest)) {
		request = new StrestRequest(request);
	}

	request.setHeaderIfAbsent('method', 'GET');
	request.setHeaderIfAbsent('user-agent', Strest.userAgent);
	request.setHeaderIfAbsent('txn.id', Strest.txnId());
	request.setHeaderIfAbsent('txn.accept', 'multi');
	//register the callbacks
	this.callbacks[request.getHeader('txn.id')] = {
			'onmessage' : message_callback,
			'ontxncomplete' : txn_complete_callback,
			'onerror' : error_callback
	};

	var msg = request.toString();
	this.socket.send(msg);
	return request;
};

function StrestMessage() {
	this.strest = {};
	this.strest.txn = {};
};

/**
 * Set a field in the request.  honors the dot operator

 * @param key
 * @param value
 * @return
 */
StrestMessage.prototype.setHeader = function(key, value) {
	var keys = key.split('.')
	var d = this['strest'];
	for (var i = 0, len = keys.length; i < len; i++) {
		var k = keys[i];
		if (i == keys.length-1) {
			d[k] = value;
		} else {
			if (!d[k]) {
				d[k] = {};
			}
			d = d[k];
		}
	}
};

StrestMessage.prototype.setHeaderIfAbsent = function(key, value) {
	var v = this.getHeader(key);
	if (v != null) {
		return v;
	}
	this.setHeader(key, value);
};

StrestMessage.prototype.getHeader = function(key) {
	var keys = key.split('.');
	var d = this['strest'];
	for (var i = 0, len = keys.length; i < len; i++) {
		var k = keys[i];
		d = d[k];
		if (i == keys.length-1) {
			return d;
		}
	}
	return null;
};

StrestRequest.prototype = new StrestMessage;
StrestRequest.prototype.constructor = StrestRequest;
/**
 * A strest request.
 *
 * example:
 * var request = new StrestRequest({ method : 'GET', uri : '/firehose'})
 *
 *
 *
 * @param options
 * uri
 * method : one of 'GET', 'POST', 'PUT', 'DELETE'
 * params : these will get added to the uri
 *
 */
function StrestRequest(options) {
	StrestMessage.call(this);
	// console.log(options);
	this.setHeader('method', options['method']);
	this.setHeader('v', Strest.protocol);
	this.setHeader('user-agent', Strest.userAgent);
	this.setHeader('uri', options['uri']);
	this.setHeader('params', options['params']);

	// console.log(this);
};

StrestRequest.prototype.setUri = function(uri) {
	this.setHeader('uri', uri);
};
StrestRequest.prototype.setMethod = function(method) {
	this.setHeader('method', method);
};

StrestRequest.prototype.toString = function() {
	return JSON.stringify(this);
};

StrestResponse.prototype = new StrestMessage;
StrestResponse.prototype.constructor = StrestResponse;
/**
 * A strest response.
 *
 * @param options
 */
function StrestResponse(msg) {
	StrestMessage.call(this);
	this.originalText = msg;
	var tmp = JSON.parse(msg)
	for (key in tmp) {
		this[key] = tmp[key]
	}
};

StrestResponse.prototype.toString = function() {
	return this.originalText;
};

Strest.isString= function(obj) {
	if (!obj) {
		return false;
	}
	if (obj instanceof String) {
		return true;
	}
	if (typeof(obj) == 'string') {
		return true;
	}
	return false;
};

Strest.trim = function(str) {
	if (!Strest.isString(str)) {
		return str;
	}
//	http://forum.jquery.com/topic/faster-jquery-trimjavascript to
	str = str.replace(/^\s+/, '');
	for (var i = str.length - 1; i >= 0; i--) {
		if (/\S/.test(str.charAt(i))) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return str;
};<|endoftext|>


<commit_before>(function () {
    // "use strict";
    var $win = $(window),
        $chart = $('#head-chart'),
        $btnZoom = $('#chart-zoomout'),
        baseConfig = {
            chart: {
                renderTo: 'head-chart',
                zoomType: 'x',
                events: {
                    selection: function() {
                        $btnZoom.removeClass('inactive')
                                .click(_pd(function(e) {
                                    $(this).trigger('zoomout');
                                }));
                    }
                }
            },
            credits: { enabled: false },
            title: {
                text: null
            },
            xAxis: {
                type: 'datetime',
                maxZoom: 7 * 24 * 3600000, // seven days
                title: {
                    text: null
                }
            },
            yAxis: {
                title: {
                    text: null
                },
                labels: {
                    formatter: function() {
                        return Highcharts.numberFormat(this.value, 0);
                    }
                },
                min: 0,
                startOnTick: false,
                showFirstLabel: false
            },
            legend: {
                enabled: true
            },
            tooltip: { },
            plotOptions: {
                line: {
                    lineWidth: 1,
                    animation: false,
                    shadow: false,
                    marker: {
                        enabled: true,
                        radius: 0,
                        states: {
                           hover: {
                              enabled: true,
                              radius: 5
                           }
                        }
                    },
                    states: {
                        hover: {
                        lineWidth: 2
                    }
                 }
              }
           }
        };
    Highcharts.setOptions({ lang: { resetZoom: '' } });
    var chart;
    // which unit do we use for a given metric?
    var metricTypes = {
        "usage"              : "users",
        "apps"               : "users",
        "locales"            : "users",
        "os"                 : "users",
        "versions"           : "users",
        "statuses"           : "users",
        "users_created"      : "users",
        "downloads"          : "downloads",
        "sources"            : "downloads",
        "contributions"      : "currency",
        "reviews_created"    : "reviews",
        "addons_in_use"      : "addons",
        "addons_created"     : "addons",
        "addons_updated"     : "addons",
        "addons_downloaded"  : "addons",
        "collections_created" : "collections",
        "subscribers"        : "collections",
        "ratings"            : "collections"
    };

    var acceptedGroups = {
        'day'   : true,
        'week'  : true,
        'month' : true
    };

    function showNoDataOverlay() {
        $chart.parent().addClass('nodata');
        $chart.parent().removeClass('loading');
        if (chart && chart.destroy) chart.destroy();
    }

    $win.bind("changeview", function() {
        $chart.parent().removeClass('nodata');
        $chart.addClass('loading');
    });

    $win.bind("dataready", function(e, obj) {
        var view    = obj.view,
            metric  = view.metric,
            group   = view.group,
            data    = obj.data,
            range   = normalizeRange(view.range),
            start   = range.start,
            end     = range.end,
            fields  = obj.fields ? obj.fields.slice(0,5) : ['count'],
            series  = {},
            events  = obj.events,
            chartRange = {},
            t, row, i, field, val;

        if (!(group in acceptedGroups)) {
            group = 'day';
        }
        if (obj.data.empty || !data.firstIndex) {
            showNoDataOverlay();
            $chart.removeClass('loading');
            return;
        }

        // Initialize the empty series object.
        _.each(fields, function(f) { series[f] = []; });

        // Transmute the data into something Highcharts understands.
        start = Date.iso(data.firstIndex);
        z.data = data;
        var step = '1 ' + group,
            point;
        forEachISODate({start: start, end: end}, '1 '+group, data, function(row, d) {
            for (i = 0; i < fields.length; i++) {
                field = fields[i];
                val = parseFloat(z.StatsManager.getField(row, field));
                if (val != val) val = null;
                point = {
                    'x' : d.getTime(),
                    'y' : val
                };
                series[field].push(point);
            }
        }, this);

        // Populate the chart config object.
        var chartData = [], id;
        for (i = 0; i < fields.length; i++) {
            field = fields[i];
            id = field.split("|").slice(-1)[0];
            chartData.push({
                'type'  : 'line',
                'name'  : z.StatsManager.getPrettyName(view.metric, id),
                'id'    : id,
                'data'  : series[field],
                'visible' : !(metric == 'contributions' && id !='total')
            });
        }

        // Generate the tooltip function for this chart.
        // both x and y axis can be displayed differently.
        var tooltipFormatter = (function(){
            var xFormatter,
                yFormatter;
            function dayFormatter(d) { return Highcharts.dateFormat('%a, %b %e, %Y', new Date(d)); }
            function weekFormatter(d) { return "Week of " + Highcharts.dateFormat('%b %e, %Y', new Date(d)); }
            function monthFormatter(d) { return Highcharts.dateFormat('%B %Y', new Date(d)); }
            function downloadFormatter(n) { return Highcharts.numberFormat(n, 0) + ' downloads'; }
            function userFormatter(n) { return Highcharts.numberFormat(n, 0) + ' users'; }
            function addonsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' addons'; }
            function collectionsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' collections'; }
            function reviewsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' reviews'; }
            function currencyFormatter(n) { return '$' + Highcharts.numberFormat(n, 2); }
            function addEventData(s, date) {
                var e = events[date];
                if (e) {
                    s += format('

{type_pretty}', e);
                }
                return s;
            }

            // Determine x-axis formatter.
            if (group == "week") {
                xFormatter = weekFormatter;
            } else if (group == "month") {
                xFormatter = monthFormatter;
            } else {
                xFormatter = dayFormatter;
            }

            if (metric == 'overview') {
                return function() {
                    var ret = "" + xFormatter(this.x) + "",
                        p;
                    for (var i=0; i < this.points.length; i++) {
                        p = this.points[i];
                        ret += '
' + p.series.name + ': ';
                        ret += Highcharts.numberFormat(p.y, 0);
                    }
                    return addEventData(ret, this.x);
                };
            } else if (metric == 'contributions') {
                return function() {
                    var ret = "" + xFormatter(this.x) + "",
                        p;
                    for (var i=0; i < this.points.length; i++) {
                        p = this.points[i];
                        ret += '
' + p.series.name + ': ';
                        if (p.series.options.yAxis > 0) {
                            ret += Highcharts.numberFormat(p.y, 0);
                        } else {
                            ret += currencyFormatter(p.y);
                        }
                    }
                    return addEventData(ret, this.x);
                };
            } else {
                // Determine y-axis formatter.
                switch (metricTypes[metric]) {
                    case "users":
                        yFormatter = userFormatter;
                        break;
                    case "downloads":
                        yFormatter = downloadFormatter;
                        break;
                    case "currency":
                        yFormatter = currencyFormatter;
                        break;
                    case "collections":
                        yFormatter = collectionsFormatter;
                        break;
                    case "reviews":
                        yFormatter = reviewsFormatter;
                        break;
                    case "addons":
                        yFormatter = addonsFormatter;
                        break;
                }
                return function() {
                    var ret = "" + this.series.name + "
" +
                              xFormatter(this.x) + "
" +
                              yFormatter(this.y);
                    return addEventData(ret, this.x);
                };
            }
        })();

        // Set up the new chart's configuration.
        var newConfig = $.extend(baseConfig, { series: chartData });
        // set up dual-axes for the overview chart.
        if (metric == "overview" && newConfig.series.length) {
            _.extend(newConfig, {
                yAxis : [
                    { // Downloads
                        title: {
                           text: gettext('Downloads')
                        },
                        min: 0,
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        }
                    }, { // Daily Users
                        title: {
                            text: gettext('Daily Users')
                        },
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        },
                        min: 0,
                        opposite: true
                    }
                ],
                tooltip: {
                    shared : true,
                    crosshairs : true
                }
            });
            // set Daily Users series to use the right yAxis.
            _.find(newConfig.series,
                   function(s) { return s.id == 'updates'; }).yAxis = 1;
        }
        if (metric == "contributions" && newConfig.series.length) {
            _.extend(newConfig, {
                yAxis : [
                    { // Amount
                        title: {
                            text: gettext('Amount, in USD')
                        },
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 2);
                            }
                        },
                        min: 0
                    },
                    { // Number of Contributions
                        title: {
                           text: gettext('Number of Contributions')
                        },
                        min: 0,
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        },
                        opposite: true
                    }
                ],
                tooltip: {
                    shared : true,
                    crosshairs : true
                }
            });
            // set Daily Users series to use the right yAxis.
            newConfig.series[0].yAxis = 1;
        }
        newConfig.tooltip.formatter = tooltipFormatter;

        function makeSiteEventHandler(e) {
            return function() {
                var s = format('
{type_pretty}

{description}
', e);
                if (e.url) {
                    s += format('
{1}
', [e.url, gettext('More Info...')]);
                }
                $('#exception-note h2').html(format(
                    // L10n: {0} is an ISO-formatted date.
                    gettext('Details for {0}'),
                    e.start
                ));
                $('#exception-note div').html(s);
                $chart.trigger('explain-exception');
            };
        }

        var pb = [], pl = [];
        eventColors = ['#DDD','#DDD','#FDFFD0','#D0FFD8'];
        _.forEach(events, function(e) {
            pb.push({
                color: eventColors[e.type],
                from: Date.iso(e.start).backward('12h'),
                to: Date.iso(e.end || e.start).forward('12h'),
                events: {
                    click: makeSiteEventHandler(e)
                }
            });
        });
        newConfig.xAxis.plotBands = pb;
        newConfig.xAxis.plotLines = pl;

        if (fields.length == 1) {
            newConfig.legend.enabled = false;
        }

        // Generate a pretty title for the chart.
        var title;
        if (typeof obj.view.range == 'string') {
            var numDays = parseInt(obj.view.range, 10);
            title = format(csv_keys.chartTitle[metric][0], numDays);
        } else {
            title = format(csv_keys.chartTitle[metric][1], [start.iso(), end.iso()]);
        }
        newConfig.title = {
            text: title
        };
        if (chart && chart.destroy) chart.destroy();
        chart = new Highcharts.Chart(newConfig);

        chartRange = chart.xAxis[0].getExtremes();

        $win.bind('zoomout', function() {
            chart.xAxis[0].setExtremes(chartRange.min, chartRange.max);
            $btnZoom.addClass('inactive').click(_pd);
        });

        $chart.removeClass('loading');
    });
})();<commit_msg>fixed time offset issue with x-axis (bug 735730)<commit_after>(function () {
    // "use strict";
    var $win = $(window),
        $chart = $('#head-chart'),
        $btnZoom = $('#chart-zoomout'),
        baseConfig = {
            chart: {
                renderTo: 'head-chart',
                zoomType: 'x',
                events: {
                    selection: function() {
                        $btnZoom.removeClass('inactive')
                                .click(_pd(function(e) {
                                    $(this).trigger('zoomout');
                                }));
                    }
                }
            },
            credits: { enabled: false },
            title: {
                text: null
            },
            xAxis: {
                type: 'datetime',
                maxZoom: 7 * 24 * 3600000, // seven days
                title: {
                    text: null
                },
                tickmarkPlacement: 'on'
            },
            yAxis: {
                title: {
                    text: null
                },
                labels: {
                    formatter: function() {
                        return Highcharts.numberFormat(this.value, 0);
                    }
                },
                min: 0,
                startOnTick: false,
                showFirstLabel: false
            },
            legend: {
                enabled: true
            },
            tooltip: { },
            plotOptions: {
                line: {
                    lineWidth: 1,
                    animation: false,
                    shadow: false,
                    marker: {
                        enabled: true,
                        radius: 0,
                        states: {
                           hover: {
                              enabled: true,
                              radius: 5
                           }
                        }
                    },
                    states: {
                        hover: {
                            lineWidth: 2
                        }
                    }
                }
            }
        };
    Highcharts.setOptions({ lang: { resetZoom: '' } });
    var chart;
    // which unit do we use for a given metric?
    var metricTypes = {
        "usage"              : "users",
        "apps"               : "users",
        "locales"            : "users",
        "os"                 : "users",
        "versions"           : "users",
        "statuses"           : "users",
        "users_created"      : "users",
        "downloads"          : "downloads",
        "sources"            : "downloads",
        "contributions"      : "currency",
        "reviews_created"    : "reviews",
        "addons_in_use"      : "addons",
        "addons_created"     : "addons",
        "addons_updated"     : "addons",
        "addons_downloaded"  : "addons",
        "collections_created" : "collections",
        "subscribers"        : "collections",
        "ratings"            : "collections"
    };

    var acceptedGroups = {
        'day'   : true,
        'week'  : true,
        'month' : true
    };

    function showNoDataOverlay() {
        $chart.parent().addClass('nodata');
        $chart.parent().removeClass('loading');
        if (chart && chart.destroy) chart.destroy();
    }

    $win.bind("changeview", function() {
        $chart.parent().removeClass('nodata');
        $chart.addClass('loading');
    });

    $win.bind("dataready", function(e, obj) {
        var view    = obj.view,
            metric  = view.metric,
            group   = view.group,
            data    = obj.data,
            range   = normalizeRange(view.range),
            start   = range.start,
            end     = range.end,
            fields  = obj.fields ? obj.fields.slice(0,5) : ['count'],
            series  = {},
            events  = obj.events,
            chartRange = {},
            t, row, i, field, val;

        if (!(group in acceptedGroups)) {
            group = 'day';
        }
        if (obj.data.empty || !data.firstIndex) {
            showNoDataOverlay();
            $chart.removeClass('loading');
            return;
        }

        // Initialize the empty series object.
        _.each(fields, function(f) { series[f] = []; });

        // Transmute the data into something Highcharts understands.
        start = Date.iso(data.firstIndex);
        z.data = data;
        var step = '1 ' + group,
            point;
        forEachISODate({start: start, end: end}, '1 '+group, data, function(row, d) {
            for (i = 0; i < fields.length; i++) {
                field = fields[i];
                val = parseFloat(z.StatsManager.getField(row, field));
                if (val != val) val = null;
                series[field].push(val);
            }
        }, this);

        // Populate the chart config object.
        var chartData = [], id;
        for (i = 0; i < fields.length; i++) {
            field = fields[i];
            id = field.split("|").slice(-1)[0];
            chartData.push({
                'type'  : 'line',
                'name'  : z.StatsManager.getPrettyName(view.metric, id),
                'id'    : id,
                'pointInterval' : 1000 * 3600 * 24,
                // compensate for timezone offsets from UTC.
                'pointStart' : start.getTime() - start.getTimezoneOffset() * 60000,
                'data'  : series[field],
                'visible' : !(metric == 'contributions' && id !='total')
            });
        }

        // Generate the tooltip function for this chart.
        // both x and y axis can be displayed differently.
        var tooltipFormatter = (function(){
            var xFormatter,
                yFormatter;
            function dayFormatter(d) { return Highcharts.dateFormat('%a, %b %e, %Y', new Date(d)); }
            function weekFormatter(d) { return "Week of " + Highcharts.dateFormat('%b %e, %Y', new Date(d)); }
            function monthFormatter(d) { return Highcharts.dateFormat('%B %Y', new Date(d)); }
            function downloadFormatter(n) { return Highcharts.numberFormat(n, 0) + ' downloads'; }
            function userFormatter(n) { return Highcharts.numberFormat(n, 0) + ' users'; }
            function addonsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' addons'; }
            function collectionsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' collections'; }
            function reviewsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' reviews'; }
            function currencyFormatter(n) { return '$' + Highcharts.numberFormat(n, 2); }
            function addEventData(s, date) {
                var e = events[date];
                if (e) {
                    s += format('

{type_pretty}', e);
                }
                return s;
            }

            // Determine x-axis formatter.
            if (group == "week") {
                xFormatter = weekFormatter;
            } else if (group == "month") {
                xFormatter = monthFormatter;
            } else {
                xFormatter = dayFormatter;
            }

            if (metric == 'overview') {
                return function() {
                    var ret = "" + xFormatter(this.x) + "",
                        p;
                    for (var i=0; i < this.points.length; i++) {
                        p = this.points[i];
                        ret += '
' + p.series.name + ': ';
                        ret += Highcharts.numberFormat(p.y, 0);
                    }
                    return addEventData(ret, this.x);
                };
            } else if (metric == 'contributions') {
                return function() {
                    var ret = "" + xFormatter(this.x) + "",
                        p;
                    for (var i=0; i < this.points.length; i++) {
                        p = this.points[i];
                        ret += '
' + p.series.name + ': ';
                        if (p.series.options.yAxis > 0) {
                            ret += Highcharts.numberFormat(p.y, 0);
                        } else {
                            ret += currencyFormatter(p.y);
                        }
                    }
                    return addEventData(ret, this.x);
                };
            } else {
                // Determine y-axis formatter.
                switch (metricTypes[metric]) {
                    case "users":
                        yFormatter = userFormatter;
                        break;
                    case "downloads":
                        yFormatter = downloadFormatter;
                        break;
                    case "currency":
                        yFormatter = currencyFormatter;
                        break;
                    case "collections":
                        yFormatter = collectionsFormatter;
                        break;
                    case "reviews":
                        yFormatter = reviewsFormatter;
                        break;
                    case "addons":
                        yFormatter = addonsFormatter;
                        break;
                }
                return function() {
                    var ret = "" + this.series.name + "
" +
                              xFormatter(this.x) + "
" +
                              yFormatter(this.y);
                    return addEventData(ret, this.x);
                };
            }
        })();

        // Set up the new chart's configuration.
        var newConfig = $.extend(baseConfig, { series: chartData });
        // set up dual-axes for the overview chart.
        if (metric == "overview" && newConfig.series.length) {
            _.extend(newConfig, {
                yAxis : [
                    { // Downloads
                        title: {
                           text: gettext('Downloads')
                        },
                        min: 0,
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        }
                    }, { // Daily Users
                        title: {
                            text: gettext('Daily Users')
                        },
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        },
                        min: 0,
                        opposite: true
                    }
                ],
                tooltip: {
                    shared : true,
                    crosshairs : true
                }
            });
            // set Daily Users series to use the right yAxis.
            _.find(newConfig.series,
                   function(s) { return s.id == 'updates'; }).yAxis = 1;
        }
        if (metric == "contributions" && newConfig.series.length) {
            _.extend(newConfig, {
                yAxis : [
                    { // Amount
                        title: {
                            text: gettext('Amount, in USD')
                        },
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 2);
                            }
                        },
                        min: 0
                    },
                    { // Number of Contributions
                        title: {
                           text: gettext('Number of Contributions')
                        },
                        min: 0,
                        labels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        },
                        opposite: true
                    }
                ],
                tooltip: {
                    shared : true,
                    crosshairs : true
                }
            });
            // set Daily Users series to use the right yAxis.
            newConfig.series[0].yAxis = 1;
        }
        newConfig.tooltip.formatter = tooltipFormatter;

        function makeSiteEventHandler(e) {
            return function() {
                var s = format('
{type_pretty}

{description}
', e);
                if (e.url) {
                    s += format('
{1}
', [e.url, gettext('More Info...')]);
                }
                $('#exception-note h2').html(format(
                    // L10n: {0} is an ISO-formatted date.
                    gettext('Details for {0}'),
                    e.start
                ));
                $('#exception-note div').html(s);
                $chart.trigger('explain-exception');
            };
        }

        var pb = [], pl = [];
        eventColors = ['#DDD','#DDD','#FDFFD0','#D0FFD8'];
        _.forEach(events, function(e) {
            pb.push({
                color: eventColors[e.type],
                from: Date.iso(e.start).backward('12h'),
                to: Date.iso(e.end || e.start).forward('12h'),
                events: {
                    click: makeSiteEventHandler(e)
                }
            });
        });
        newConfig.xAxis.plotBands = pb;
        newConfig.xAxis.plotLines = pl;

        if (fields.length == 1) {
            newConfig.legend.enabled = false;
        }

        // Generate a pretty title for the chart.
        var title;
        if (typeof obj.view.range == 'string') {
            var numDays = parseInt(obj.view.range, 10);
            title = format(csv_keys.chartTitle[metric][0], numDays);
        } else {
            title = format(csv_keys.chartTitle[metric][1], [start.iso(), end.iso()]);
        }
        newConfig.title = {
            text: title
        };
        if (chart && chart.destroy) chart.destroy();
        chart = new Highcharts.Chart(newConfig);

        chartRange = chart.xAxis[0].getExtremes();

        $win.bind('zoomout', function() {
            chart.xAxis[0].setExtremes(chartRange.min, chartRange.max);
            $btnZoom.addClass('inactive').click(_pd);
        });

        $chart.removeClass('loading');
    });
})();<|endoftext|>


<commit_before>require('core/object');
require('core/array');
include('core/json');
include('helma/engine');
include('helma/file');
include('helma/functional');
include('./storeutils');
include('./querysupport');

export("Store", "Transaction");

module.shared = true;
var log = require('helma/logging').getLogger(module.id);
addHostObject(org.helma.wrappers.Storable);

/**
 * File Store class
 * @param path the database directory
 */
function Store(path) {

    // map of type to current id tip
    var idMap = {};
    var self = this;
    var registry = {};

    var proxy = {
        all: all,
        get: get,
        query: query,
        create: create,
        save: save,
        remove: remove,
        getEntity: getEntity,
        getKey: getKey,
        getProps: getProps,
        getId: getId,
        equalKeys: equalKeys
    };

    this.defineClass = function(type) {
        var ctor = registry[type];
        if (!ctor) {
            ctor = registry[type] = Storable.defineClass(proxy, type);
            ctor.all = bindArguments(all, type);
            ctor.get = bindArguments(get, type);
            ctor.query = bindArguments(query, type);
        }
        return ctor;
    }

    function create(type, key, entity) {
        var ctor = registry[type];
        return ctor.createInstance(key, entity);
    }

    function all(type) {
        return retrieveAll(type);
    }

    function get(type, id) {
        return retrieve(type, id);
    }

    function save(props, entity, txn) {
        var wrapTransaction = false;
        if (!txn) {
            txn = new Transaction();
            wrapTransaction = true;
        }

        if (updateEntity(props, entity, txn)) {
            store(entity, txn);
            if (wrapTransaction) {
                txn.commit();
            }
        }
    }

    function remove(key, txn) {
        var wrapTransaction = !txn;
        if (wrapTransaction) {
            txn = new Transaction();
        }

        removeImpl(key, txn);

        if (wrapTransaction) {
            txn.commit();
        }
    }

    function query(type) {
        return new BaseQuery(bindArguments(all, type));
    }

    function getEntity(type, arg) {
        if (isKey(arg)) {
            var [type, id] = arg.$ref.split(":");
            return load(type, id);
        } else if (isEntity(arg)) {
            return arg;
        } else if (arg instanceof Object) {
            var entity = arg.clone({});
            Object.defineProperty(entity, "_key", {
                value: createKey(type, generateId(type))
            });
            return entity;
        }
        return null;
    }

    function store(entity, txn) {
        var [type, id] = entity._key.$ref.split(":");

        var dir = new File(base, type);
        if (!dir.exists()) {
            if (!dir.makeDirectory()) {
                throw new Error("Can't create directory for type " + type);
            }
        }

        var file = new File(dir, id);
        if (file.exists() && !file.canWrite()) {
            throw new Error("No write permission for " + file);
        }

        var tempFileName = type + id + ".";
        var tempfile = base.createTempFile(tempFileName, ".tmp");

        if(log.isDebugEnabled())
            log.debug("Storing object: " + object.toSource());

        tempfile.open({ append: true });
        tempfile.write(JSON.stringify(entity));
        tempfile.close();
        txn.updateResource({ file: file, tempfile: tempfile });
    };

    function load(type, id) {
        var file = new File(new File(base, type), id);

        if (!file.exists()) {
            return null;
        } else if (!file.isFile()) {
            throw new Error("Is not a regular file: " + file);
        }

        var content = file.readAll();
        var entity = JSON.parse(content);
        Object.defineProperty(entity, "_key", {
            value: createKey(type, id)
        });
        return entity;
    };

    function retrieve(type, id) {
        var entity = load(type, id);
        if (entity) {
            return create(type, createKey(type, id), entity);
        }
        return null;
    };

    function retrieveAll(type) {
        var dir = new File(base, type);
        if (!dir.exists() || !dir.isDirectory()) {
            return [];
        }
        var files = dir.listFiles();
        var list = [];

        for each (var file in files) {
            if (!file.isFile() || file.isHidden()) {
                continue;
            }
            list.push(create(type, createKey(type, file.getName())));
        }
        return list;
    };

    function removeImpl(key, txn) {
        if (!isKey(key)) {
            throw new Error("Invalid key object: " + key);
        }
        var [type, id] = key.$ref.split(":");
        var file = new File(new File(base, type), id);
        txn.deleteResource({ file: file });
    };

    function generateId(type) {
        var dir = new File(base, type);
        var id = idMap[type] || 1;
        var file = new File(dir, id.toString(36));
        while(file.exists()) {
            id += 1;
            file = new File(dir, id.toString(36));
        }

        idMap[type] = id + 1;
        return file.getName();
    };

    var base = new File(path);
    log.debug("Set up new store: " + base);

};

function Transaction() {

    var updateList = [];
    var deleteList = [];

    var tx = new BaseTransaction();

    tx.deleteResource = function(res) {
        deleteList.push(res);
    }

    tx.updateResource = function(res) {
        updateList.push(res);
    }

    tx.commit = function() {
        for each (var res in updateList) {
            // because of a Java/Windows quirk, we have to delete
            // the existing file before trying to overwrite it
            if (res.file.exists()) {
                res.file.remove();
            }
            // move temporary file to permanent name
            if (res.tempfile.renameTo(res.file)) {
                // success - delete tmp file
                res.tempfile.remove();
            } else {
                // error - leave tmp file and print a message
                log.error("Couldn't move file, committed version is in " + res.tempfile);
            }
        }

        for each (var res in deleteList) {
            res.file.remove();
        }

        updateList = [];
        deleteList = [];
    }

    tx.abort = function() {
        for each (var res in updateList) {
            res.tempfile.remove();
        }
    }

    return tx;
}
<commit_msg>Fix typo in filestore<commit_after>require('core/object');
require('core/array');
include('core/json');
include('helma/engine');
include('helma/file');
include('helma/functional');
include('./storeutils');
include('./querysupport');

export("Store", "Transaction");

module.shared = true;
var log = require('helma/logging').getLogger(module.id);
addHostObject(org.helma.wrappers.Storable);

/**
 * File Store class
 * @param path the database directory
 */
function Store(path) {

    // map of type to current id tip
    var idMap = {};
    var self = this;
    var registry = {};

    var proxy = {
        all: all,
        get: get,
        query: query,
        create: create,
        save: save,
        remove: remove,
        getEntity: getEntity,
        getKey: getKey,
        getProps: getProps,
        getId: getId,
        equalKeys: equalKeys
    };

    this.defineClass = function(type) {
        var ctor = registry[type];
        if (!ctor) {
            ctor = registry[type] = Storable.defineClass(proxy, type);
            ctor.all = bindArguments(all, type);
            ctor.get = bindArguments(get, type);
            ctor.query = bindArguments(query, type);
        }
        return ctor;
    }

    function create(type, key, entity) {
        var ctor = registry[type];
        return ctor.createInstance(key, entity);
    }

    function all(type) {
        return retrieveAll(type);
    }

    function get(type, id) {
        return retrieve(type, id);
    }

    function save(props, entity, txn) {
        var wrapTransaction = false;
        if (!txn) {
            txn = new Transaction();
            wrapTransaction = true;
        }

        if (updateEntity(props, entity, txn)) {
            store(entity, txn);
            if (wrapTransaction) {
                txn.commit();
            }
        }
    }

    function remove(key, txn) {
        var wrapTransaction = !txn;
        if (wrapTransaction) {
            txn = new Transaction();
        }

        removeImpl(key, txn);

        if (wrapTransaction) {
            txn.commit();
        }
    }

    function query(type) {
        return new BaseQuery(bindArguments(all, type));
    }

    function getEntity(type, arg) {
        if (isKey(arg)) {
            var [type, id] = arg.$ref.split(":");
            return load(type, id);
        } else if (isEntity(arg)) {
            return arg;
        } else if (arg instanceof Object) {
            var entity = arg.clone({});
            Object.defineProperty(entity, "_key", {
                value: createKey(type, generateId(type))
            });
            return entity;
        }
        return null;
    }

    function store(entity, txn) {
        var [type, id] = entity._key.$ref.split(":");

        var dir = new File(base, type);
        if (!dir.exists()) {
            if (!dir.makeDirectory()) {
                throw new Error("Can't create directory for type " + type);
            }
        }

        var file = new File(dir, id);
        if (file.exists() && !file.canWrite()) {
            throw new Error("No write permission for " + file);
        }

        var tempFileName = type + id + ".";
        var tempfile = base.createTempFile(tempFileName, ".tmp");

        if(log.isDebugEnabled())
            log.debug("Storing object: " + entity.toSource());

        tempfile.open({ append: true });
        tempfile.write(JSON.stringify(entity));
        tempfile.close();
        txn.updateResource({ file: file, tempfile: tempfile });
    };

    function load(type, id) {
        var file = new File(new File(base, type), id);

        if (!file.exists()) {
            return null;
        } else if (!file.isFile()) {
            throw new Error("Is not a regular file: " + file);
        }

        var content = file.readAll();
        var entity = JSON.parse(content);
        Object.defineProperty(entity, "_key", {
            value: createKey(type, id)
        });
        return entity;
    };

    function retrieve(type, id) {
        var entity = load(type, id);
        if (entity) {
            return create(type, createKey(type, id), entity);
        }
        return null;
    };

    function retrieveAll(type) {
        var dir = new File(base, type);
        if (!dir.exists() || !dir.isDirectory()) {
            return [];
        }
        var files = dir.listFiles();
        var list = [];

        for each (var file in files) {
            if (!file.isFile() || file.isHidden()) {
                continue;
            }
            list.push(create(type, createKey(type, file.getName())));
        }
        return list;
    };

    function removeImpl(key, txn) {
        if (!isKey(key)) {
            throw new Error("Invalid key object: " + key);
        }
        var [type, id] = key.$ref.split(":");
        var file = new File(new File(base, type), id);
        txn.deleteResource({ file: file });
    };

    function generateId(type) {
        var dir = new File(base, type);
        var id = idMap[type] || 1;
        var file = new File(dir, id.toString(36));
        while(file.exists()) {
            id += 1;
            file = new File(dir, id.toString(36));
        }

        idMap[type] = id + 1;
        return file.getName();
    };

    var base = new File(path);
    log.debug("Set up new store: " + base);

};

function Transaction() {

    var updateList = [];
    var deleteList = [];

    var tx = new BaseTransaction();

    tx.deleteResource = function(res) {
        deleteList.push(res);
    }

    tx.updateResource = function(res) {
        updateList.push(res);
    }

    tx.commit = function() {
        for each (var res in updateList) {
            // because of a Java/Windows quirk, we have to delete
            // the existing file before trying to overwrite it
            if (res.file.exists()) {
                res.file.remove();
            }
            // move temporary file to permanent name
            if (res.tempfile.renameTo(res.file)) {
                // success - delete tmp file
                res.tempfile.remove();
            } else {
                // error - leave tmp file and print a message
                log.error("Couldn't move file, committed version is in " + res.tempfile);
            }
        }

        for each (var res in deleteList) {
            res.file.remove();
        }

        updateList = [];
        deleteList = [];
    }

    tx.abort = function() {
        for each (var res in updateList) {
            res.tempfile.remove();
        }
    }

    return tx;
}
<|endoftext|>


<commit_before>var extend = require('xtend')
var getFormData = require('form-data-set/element')

var ENTER = 13

module.exports = SubmitSinkHandler

function SubmitSinkHandler(sink, data) {
    if (!(this instanceof SubmitSinkHandler)) {
        return new SubmitSinkHandler(sink, data)
    }

    this.sink = sink
    this.data = data
    this.id = sink.id
    this.type = 'submit'

    if (this.data && typeof this.data === 'object' &&
        'preventDefault' in this.data
    ) {
        this.preventDefault = this.data.preventDefault;
        delete this.data.preventDefault;
    } else {
        this.preventDefault = true;
    }
}

SubmitSinkHandler.prototype.handleEvent = handleEvent

function handleEvent(ev) {
    var target = ev.target

    var isValid =
        (ev.type === 'click' && target.tagName === 'BUTTON') ||
        (ev.type === 'click' && target.type === 'submit') ||
        (
            (target.type === 'text') &&
            (ev.keyCode === ENTER && ev.type === 'keydown')
        )

    // prevent forms form refreshing page
    if (ev.type === 'submit') {
        ev.preventDefualt();
    }

    if (!isValid) {
        return
    }

    var value = getFormData(ev.currentTarget)
    var data = extend(value, this.data)

    if (typeof this.sink === 'function') {
        this.sink(data)
    } else {
        this.sink.write(data)
    }

    if (this.preventDefault && ev.preventDefault) {
        ev.preventDefault()
    }
}
<commit_msg>Typos<commit_after>var extend = require('xtend')
var getFormData = require('form-data-set/element')

var ENTER = 13

module.exports = SubmitSinkHandler

function SubmitSinkHandler(sink, data) {
    if (!(this instanceof SubmitSinkHandler)) {
        return new SubmitSinkHandler(sink, data)
    }

    this.sink = sink
    this.data = data
    this.id = sink.id
    this.type = 'submit'

    if (this.data && typeof this.data === 'object' &&
        'preventDefault' in this.data
    ) {
        this.preventDefault = this.data.preventDefault;
        delete this.data.preventDefault;
    } else {
        this.preventDefault = true;
    }
}

SubmitSinkHandler.prototype.handleEvent = handleEvent

function handleEvent(ev) {
    var target = ev.target

    var isValid =
        (ev.type === 'click' && target.tagName === 'BUTTON') ||
        (ev.type === 'click' && target.type === 'submit') ||
        (
            (target.type === 'text') &&
            (ev.keyCode === ENTER && ev.type === 'keydown')
        )

    // prevent forms from refreshing page
    if (ev.type === 'submit') {
        ev.preventDefault();
    }

    if (!isValid) {
        return
    }

    var value = getFormData(ev.currentTarget)
    var data = extend(value, this.data)

    if (typeof this.sink === 'function') {
        this.sink(data)
    } else {
        this.sink.write(data)
    }

    if (this.preventDefault && ev.preventDefault) {
        ev.preventDefault()
    }
}
<|endoftext|>


<commit_before>
var Metadata = require('../../../models/metadata');
var readdir = Metadata.readdir;

var stat = require('./stat');
var dirname = require('path').dirname;

var helper = require('../../../helper');
var forEach = helper.forEach;

var stat = require('./stat');

function dir (blog, dir, callback) {

  var blogID = blog.id;
  var files = [];

  readdir(blogID, dir, function(err, contents, dir){

    if (err && err.code === 'ENOTDIR') {

      return stat(blog, dir, function(err, stat){

        if (err) return callback(err);

        readdir(blogID, dirname(dir), function(err, contents, dir){

          callback(err, [], dir, stat);
        });
      });
    }

    if (err) return callback(err);

    forEach(contents, function(item, nextName){

      stat(blog, item.path, function(err, stat){

        if (err) console.log(err);

        if (err) return nextName();

        stat.name = item.name;
        stat.path = item.path;

        files.push(stat);
        nextName();
      });

    }, function(){

      callback(null, files, dir);
    });
  });
}

module.exports = dir;<commit_msg>put folders at the top<commit_after>
var Metadata = require('../../../models/metadata');
var readdir = Metadata.readdir;

var stat = require('./stat');
var dirname = require('path').dirname;

var helper = require('../../../helper');
var forEach = helper.forEach;

var stat = require('./stat');

function dir (blog, dir, callback) {

  var blogID = blog.id;
  var files = [];
  var folders = [];

  readdir(blogID, dir, function(err, contents, dir){

    if (err && err.code === 'ENOTDIR') {

      return stat(blog, dir, function(err, stat){

        if (err) return callback(err);

        readdir(blogID, dirname(dir), function(err, contents, dir){

          callback(err, [], dir, stat);
        });
      });
    }

    if (err) return callback(err);

    forEach(contents, function(item, nextName){

      stat(blog, item.path, function(err, stat){

        if (err) console.log(err);

        if (err) return nextName();

        stat.name = item.name;
        stat.path = item.path;

        if (stat.directory)
          folders.push(stat);
        else
          files.push(stat);

        nextName();
      });

    }, function(){

      callback(null, folders.concat(files), dir);
    });
  });
}

module.exports = dir;<|endoftext|>


<commit_before>module.exports = function(app) {

	var request = require('request');
	var http = require('http');

	app.post('/api/proxy/:server/*', isAuthorized, function(req, res) {

		var server = req.params.server;
		var path = req.params[0];
		var post_data = req.body;

		var hosts = {
			'nlpserver': 'http://nlp.scasefp7.eu:8010',
			'assetregistry': 'http://109.231.121.125:8080/s-case',
			'SCServer': 'http://109.231.127.61:8080',
			'ontologies': 'http://109.231.126.165:8080',
			'UMLServer': 'http://109.231.126.105:8080'
		};

		var querystring = '',
		i = 0;
		for (var key in req.query) {
			if (i === 0) {
				querystring = '?' + key + '=' + req.query[key];
			} else {
				querystring += '&' + key + '=' + req.query[key];
			}

			i++;
		}

		var options = {
			uri: hosts[server] + '/' + server + '/' + path + querystring,
			method: 'POST',
		};

		if( Object.keys(post_data).length !== 0 ) {
			options.json = post_data;
		}

		if(req.headers['content-type'].indexOf('multipart') !== -1) {

			req.pipe(request(options, function(error, response, body) {

					if (!error && response.statusCode == 200) {
						console.log(response.statusCode);
						res.send(response.body);
					}
					else {
						console.log(response.statusCode);
						res.send(response.statusCode);
					}

				}));

		} else {

			request(options, function(error, response, body) {

					if (!error && response.statusCode == 200) {
						console.log(response.statusCode);
						res.send(response.body);
					}
					else {
						console.log(response.statusCode);
						res.send(response.statusCode);
					}

				});

		}

	});

};

var isAuthorized = function(req, res, next) {

	var mysql = require('mysql');
	var dbconfig = require('../../config/database');
	var connConstant = require('../../config/ConnectConstant');
	var jwt = require('jsonwebtoken');

	var auth = req.headers['authorization'];

	if(!auth) { // No Authorization header was passed in
		res.send(401);
	}
	else if(auth) { // The Authorization was passed in so now we validate it

		var authParts = auth.split(' ');
		var buffer = new Buffer(authParts[1]).toString();
		var creds = buffer.split(':');
	        var token = creds[0];
	        var signature = creds[1];

		connection = connConstant.connection;
		connection.query('USE ' + dbconfig.database);

		// Query to get the secret of the user
		var getSecretQuery = "SELECT " + dbconfig.users_table + ".`scase_secret` AS scaseSecret, " + dbconfig.users_table + ".`scase_token` AS scaseToken FROM "+ dbconfig.users_table + " WHERE " + dbconfig.users_table + ".`scase_token`= '"+ token + "'";

		connection.query(getSecretQuery, function(error, rows) {
			if (error || rows.length < 1) { // Authorization failed
				res.send(401);
			}

			if(rows.length > 0) {
				var decoded = jwt.verify(signature, rows[0].scaseSecret);
				if(decoded.token == rows[0].scaseToken) { // Authorization succeeded
					next();
				}
				else { // Authorization failed
					res.send(401);
				}
			}
		});
	}
}
<commit_msg>Bug Fixes<commit_after>module.exports = function(app) {

	var request = require('request');
	var http = require('http');

	app.post('/api/proxy/:server/*', isAuthorized, function(req, res) {

		var server = req.params.server;
		var path = req.params[0];
		var post_data = req.body;

		var hosts = {
			'nlpserver': 'http://nlp.scasefp7.eu:8010',
			'assetregistry': 'http://109.231.121.125:8080/s-case',
			'SCServer': 'http://109.231.127.61:8080',
			'ontologies': 'http://109.231.126.165:8080',
			'UMLServer': 'http://109.231.126.105:8080'
		};

		var querystring = '',
		i = 0;
		for (var key in req.query) {
			if (i === 0) {
				querystring = '?' + key + '=' + req.query[key];
			} else {
				querystring += '&' + key + '=' + req.query[key];
			}

			i++;
		}

		var options = {
			uri: hosts[server] + '/' + server + '/' + path + querystring,
			method: 'POST',
		};

		if( Object.keys(post_data).length !== 0 ) {
			options.json = post_data;
		}

		if(req.headers['content-type'].indexOf('multipart') !== -1) {

			req.pipe(request(options, function(error, response, body) {

					if (!error) {
						console.log(response.statusCode);
						res.send(response.body);
					}
					else {
						console.log(response.statusCode);
						res.send(response.statusCode);
					}

				}));

		} else {

			request(options, function(error, response, body) {

					if (!error) {
						console.log(response.statusCode);
						res.send(response.body);
					}
					else {
						console.log(response.statusCode);
						res.send(response.statusCode);
					}

				});

		}

	});

};

var isAuthorized = function(req, res, next) {

	var mysql = require('mysql');
	var dbconfig = require('../../config/database');
	var connConstant = require('../../config/ConnectConstant');
	var jwt = require('jsonwebtoken');

	var auth = req.headers['authorization'];

	if(!auth) { // No Authorization header was passed in
		res.send(401);
	}
	else if(auth) { // The Authorization was passed in so now we validate it

		var authParts = auth.split(' ');
		var buffer = new Buffer(authParts[1]).toString();
		var creds = buffer.split(':');
	        var token = creds[0];
	        var signature = creds[1];

		connection = connConstant.connection;
		connection.query('USE ' + dbconfig.database);

		// Query to get the secret of the user
		var getSecretQuery = "SELECT " + dbconfig.users_table + ".`scase_secret` AS scaseSecret, " + dbconfig.users_table + ".`scase_token` AS scaseToken FROM "+ dbconfig.users_table + " WHERE " + dbconfig.users_table + ".`scase_token`= '"+ token + "'";

		connection.query(getSecretQuery, function(error, rows) {
			if (error || rows.length < 1) { // Authorization failed
				res.send(401);
			}

			if(rows.length > 0) {
				var decoded = jwt.verify(signature, rows[0].scaseSecret);
				if(decoded.token == rows[0].scaseToken) { // Authorization succeeded
					next();
				}
				else { // Authorization failed
					res.send(401);
				}
			}
		});
	}
}
<|endoftext|>


<commit_before>// @flow

import { compose } from 'redux';
import { connect } from 'react-redux';
import UserProfile from './components/UserProfile';
import {
  fetchUser,
  addPenalty,
  deletePenalty,
  changeGrade,
} from 'app/actions/UserActions';
import { fetchAllWithType } from 'app/actions/GroupActions';
import { fetchPrevious, fetchUpcoming } from 'app/actions/EventActions';
import { fetchUserFeed } from 'app/actions/FeedActions';
import { selectUserWithGroups } from 'app/reducers/users';
import {
  selectPreviousEvents,
  selectUpcomingEvents,
} from 'app/reducers/events';
import { selectGroupsWithType } from 'app/reducers/groups';
import { selectPenaltyByUserId } from 'app/reducers/penalties';
import loadingIndicator from 'app/utils/loadingIndicator';
import replaceUnlessLoggedIn from 'app/utils/replaceUnlessLoggedIn';
import prepare from 'app/utils/prepare';
import { LoginPage } from 'app/components/LoginForm';

const loadData = (
  {
    match: {
      params: { username },
    },
  },
  dispatch
) => {
  return dispatch(fetchUser(username)).then((action) =>
    Promise.all([
      dispatch(fetchPrevious()),
      dispatch(fetchUpcoming()),
      dispatch(fetchAllWithType('klasse')),
    ])
  );
  // TODO: re-enable when the user feed is fixed:
  // .then(action =>
  //   dispatch(fetchUserFeed(action.payload.result))
  //  );
};

const mapStateToProps = (state, props) => {
  const {
    match: { params },
  } = props;
  const username =
    params.username === 'me' ? state.auth.username : params.username;

  const user = selectUserWithGroups(state, { username });
  let feed;
  let feedItems;
  const previousEvents = selectPreviousEvents(state);
  const upcomingEvents = selectUpcomingEvents(state);
  let penalties;
  if (user) {
    feed = { type: 'user', activities: [] };
    feedItems = [];
    // TODO: re-enable! see above.
    // feed = selectFeedById(state, { feedId: feedIdByUserId(user.id) });
    // feedItems = selectFeedActivitesByFeedId(state, {
    //   feedId: feedIdByUserId(user.id)
    // });
    penalties = selectPenaltyByUserId(state, { userId: user.id });
  }

  const isMe =
    params.username === 'me' || params.username === state.auth.username;
  const actionGrant = (user && user.actionGrant) || [];
  const showSettings = isMe || actionGrant.includes('edit');
  const canChangeGrade = state.allowed.groups;
  const canDeletePenalties = state.allowed.penalties;
  const groups = selectGroupsWithType(state, { groupType: 'klasse' });
  return {
    username,
    auth: state.auth,
    loggedIn: props.loggedIn,
    user,
    previousEvents,
    upcomingEvents,
    feed,
    feedItems,
    showSettings,
    isMe,
    loading: state.events.fetching,
    penalties,
    canDeletePenalties,
    groups,
    canChangeGrade,
  };
};

const mapDispatchToProps = {
  fetchUser,
  fetchUpcoming,
  fetchUserFeed,
  addPenalty,
  deletePenalty,
  changeGrade,
};

export default compose(
  replaceUnlessLoggedIn(LoginPage),
  prepare(loadData, ['match.params.username']),
  connect(mapStateToProps, mapDispatchToProps),
  loadingIndicator(['user'])
)(UserProfile);
<commit_msg>Comment more on user profle<commit_after>// @flow

import { compose } from 'redux';
import { connect } from 'react-redux';
import UserProfile from './components/UserProfile';
import {
  fetchUser,
  addPenalty,
  deletePenalty,
  changeGrade,
} from 'app/actions/UserActions';
import { fetchAllWithType } from 'app/actions/GroupActions';
import { fetchPrevious, fetchUpcoming } from 'app/actions/EventActions';
//import { fetchUserFeed } from 'app/actions/FeedActions';
import { selectUserWithGroups } from 'app/reducers/users';
import {
  selectPreviousEvents,
  selectUpcomingEvents,
} from 'app/reducers/events';
import { selectGroupsWithType } from 'app/reducers/groups';
import { selectPenaltyByUserId } from 'app/reducers/penalties';
import loadingIndicator from 'app/utils/loadingIndicator';
import replaceUnlessLoggedIn from 'app/utils/replaceUnlessLoggedIn';
import prepare from 'app/utils/prepare';
import { LoginPage } from 'app/components/LoginForm';

const loadData = (
  {
    match: {
      params: { username },
    },
  },
  dispatch
) => {
  return dispatch(fetchUser(username)).then((action) =>
    Promise.all([
      dispatch(fetchPrevious()),
      dispatch(fetchUpcoming()),
      dispatch(fetchAllWithType('klasse')),
    ])
  );
  // TODO: re-enable when the user feed is fixed:
  // .then(action =>
  //   dispatch(fetchUserFeed(action.payload.result))
  //  );
};

const mapStateToProps = (state, props) => {
  const {
    match: { params },
  } = props;
  const username =
    params.username === 'me' ? state.auth.username : params.username;

  const user = selectUserWithGroups(state, { username });
  //let feed;
  //let feedItems;
  const previousEvents = selectPreviousEvents(state);
  const upcomingEvents = selectUpcomingEvents(state);
  let penalties;
  if (user) {
    //  feed = { type: 'user', activities: [] };
    //  feedItems = [];
    // TODO: re-enable! see above.
    // feed = selectFeedById(state, { feedId: feedIdByUserId(user.id) });
    // feedItems = selectFeedActivitesByFeedId(state, {
    //   feedId: feedIdByUserId(user.id)
    // });
    penalties = selectPenaltyByUserId(state, { userId: user.id });
  }

  const isMe =
    params.username === 'me' || params.username === state.auth.username;
  const actionGrant = (user && user.actionGrant) || [];
  const showSettings = isMe || actionGrant.includes('edit');
  const canChangeGrade = state.allowed.groups;
  const canDeletePenalties = state.allowed.penalties;
  const groups = selectGroupsWithType(state, { groupType: 'klasse' });
  return {
    username,
    auth: state.auth,
    loggedIn: props.loggedIn,
    user,
    previousEvents,
    upcomingEvents,
    //feed,
    //feedItems,
    showSettings,
    isMe,
    loading: state.events.fetching,
    penalties,
    canDeletePenalties,
    groups,
    canChangeGrade,
  };
};

const mapDispatchToProps = {
  fetchUser,
  fetchUpcoming,
  //fetchUserFeed,
  addPenalty,
  deletePenalty,
  changeGrade,
};

export default compose(
  replaceUnlessLoggedIn(LoginPage),
  prepare(loadData, ['match.params.username']),
  connect(mapStateToProps, mapDispatchToProps),
  loadingIndicator(['user'])
)(UserProfile);
<|endoftext|>


<commit_before>'use strict';

/* global _ */

/* Stage Controller */

angular.module('septWebRadioControllers')
  .controller('StageCtrl', ['$scope', 'soundcloudSearch', 'utilities', '$modal', '$log', 'Page',
    function ($scope, soundcloudSearch, utilities, $modal, $log, Page) {
      $scope.title = 'Stage';

      $scope.isSearching = false;
      $scope.searchedTerm = undefined;
      $scope.searchedItems = [];
      $scope.playlists = [
        {id: 1, title: 'Playlist 1'},
        {id: 2, title: 'Playlist 2'},
        {id: 3, title: 'Playlist 3'}
      ];

      $scope.selectedPlaylists = [];

      $scope.list1 = [];
      Page.setTitle('Stage');

      $scope.search = function () {
        // If there is a term to search
        if ($scope.searchedTerm && $scope.searchedTerm !== '' && $scope.searchedTerm.length >= 2) {
          $scope.isSearching = true;

          // Search the terms
          soundcloudSearch.autoCompleteSearch($scope.searchedTerm)
            .then(function (response) {
              $scope.searchedItems = utilities.unionWithId($scope.searchedItems, response);
              $scope.isSearching = false;
            });
        } else {
          // There is nothing to search
          $scope.isSearching = false;
          $scope.searchedItems.splice(0, $scope.searchedItems.length);
        }
      };

      $scope.dropped = function (droppedItems) {
        var scopeItems = [];

        angular.forEach(droppedItems, function (valueId) {
          valueId = parseInt(valueId);
          var item = _.find($scope.searchedItems, function (listItem) {
            return valueId === parseInt(listItem.id);
          });

          this.push(item);
        }, scopeItems);

        $scope.open(scopeItems);
      };

      $scope.togglePlaylist = function (playlistId) {
        // If the playlist is not here, wee add it
        if (_.indexOf($scope.selectedPlaylists, playlistId) === -1) {
          $scope.selectedPlaylists.push(playlistId);
        } else {
          // Else, we remove it
          $scope.selectedPlaylists = _.without($scope.selectedPlaylists, playlistId);
        }
        console.log($scope.selectedPlaylists);
      };

      $scope.open = function (items) {
        var modalInstance = $modal.open({
          templateUrl: 'myModalContent.html',
          controller: ModalInstanceCtrl,
          resolve: {
            items: function () {
              return items;
            }
          }
        });

        modalInstance.result.then(function (selectedItem) {
          $scope.selected = selectedItem;
        }, function () {
          $log.info('Modal dismissed at: ' + new Date());
        });
      };

      var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
        $scope.items = items;
        $scope.ok = function () {
          $modalInstance.close($scope.items);
        };
        $scope.cancel = function () {
          $modalInstance.dismiss('cancel');
        };
      };
    }]
  );<commit_msg>Correct and add playlist<commit_after>'use strict';

/* global _ */

/* Stage Controller */

angular.module('septWebRadioControllers')
  .controller('StageCtrl', ['$scope', 'soundcloudSearch', 'utilities', '$modal', '$log', 'Page',
    function ($scope, soundcloudSearch, utilities, $modal, $log, Page) {
      $scope.title = 'Stage';

      $scope.isSearching = false;
      $scope.searchedTerm = undefined;
      $scope.searchedItems = [];
      $scope.playlists = [
        {id: 1, title: 'Playlist 1'},
        {id: 2, title: 'Playlist 2'},
        {id: 3, title: 'Playlist 3'},
        {id: 4, title: 'Playlist 4'}
      ];

      $scope.selectedPlaylists = [];

      $scope.list1 = [];
      Page.setTitle('Stage');

      $scope.search = function () {
        // If there is a term to search
        if ($scope.searchedTerm && $scope.searchedTerm !== '' && $scope.searchedTerm.length >= 2) {
          $scope.isSearching = true;

          // Search the terms
          soundcloudSearch.autoCompleteSearch($scope.searchedTerm)
            .then(function (response) {
              $scope.searchedItems = utilities.unionWithId($scope.searchedItems, response);
              $scope.isSearching = false;
            });
        } else {
          // There is nothing to search
          $scope.isSearching = false;
          $scope.searchedItems.splice(0, $scope.searchedItems.length);
        }
      };

      $scope.dropped = function (droppedItems) {
        var scopeItems = [];

        angular.forEach(droppedItems, function (valueId) {
          valueId = parseInt(valueId);
          var item = _.find($scope.searchedItems, function (listItem) {
            return valueId === parseInt(listItem.id);
          });

          this.push(item);
        }, scopeItems);

        $scope.open(scopeItems);
      };

      $scope.togglePlaylist = function (playlistId) {
        // If the playlist is not here, wee add it
        if (_.indexOf($scope.selectedPlaylists, playlistId) === -1) {
          $scope.selectedPlaylists.push(playlistId);
        } else {
          // Else, we remove it
          $scope.selectedPlaylists = _.without($scope.selectedPlaylists, playlistId);
        }
      };

      $scope.open = function (items) {
        var modalInstance = $modal.open({
          templateUrl: 'myModalContent.html',
          controller: ModalInstanceCtrl,
          resolve: {
            items: function () {
              return items;
            }
          }
        });

        modalInstance.result.then(function (selectedItem) {
          $scope.selected = selectedItem;
        }, function () {
          $log.info('Modal dismissed at: ' + new Date());
        });
      };

      var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
        $scope.items = items;
        $scope.ok = function () {
          $modalInstance.close($scope.items);
        };
        $scope.cancel = function () {
          $modalInstance.dismiss('cancel');
        };
      };
    }]
  );<|endoftext|>