<commit_before>define(function (require) {

  var React = require('react/addons'),
    Router = require('react-router'),
    Glyphicon = require('components/common/Glyphicon.react'),
    context = require('context');

  return React.createClass({

    renderRoute: function (name, linksTo, icon, requiresLogin) {
      if (requiresLogin && !context.profile) return null;

      return (

          <Router.Link to={linksTo}>
            <Glyphicon name={icon}/>
            {name}
          </Router.Link>

      )
    },

    render: function () {
      return (

                {this.renderRoute("Search", "search", "search", false)}
                {this.renderRoute("Favorites", "favorites", "bookmark", true)}
                {this.renderRoute("My Images", "authored", "user", true)}
                {this.renderRoute("Tags", "tags", "tags", false)}

      );
    }

  });

});
<commit_msg>Add 'My Image Requests' to secondary image navigation<commit_after>define(function (require) {

  var React = require('react/addons'),
    Router = require('react-router'),
    Glyphicon = require('components/common/Glyphicon.react'),
    context = require('context');

  return React.createClass({

    renderRoute: function (name, linksTo, icon, requiresLogin) {
      if (requiresLogin && !context.profile) return null;

      return (

          <Router.Link to={linksTo}>
            <Glyphicon name={icon}/>
            {name}
          </Router.Link>

      )
    },

    render: function () {

      return (

                {this.renderRoute("Search", "search", "search", false)}
                {this.renderRoute("Favorites", "favorites", "bookmark", true)}
                {this.renderRoute("My Images", "authored", "user", true)}
                {this.renderRoute("My Image Requests", "my-image-requests", "export", true)}
                {this.renderRoute("Tags", "tags", "tags", false)}

      );
    }

  });

});
<|endoftext|>


<commit_before>require('dotenv').config();

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  # Comments in GraphQL strings (such as this one) start with the hash (#) symbol.

  # This "Book" type defines the queryable fields for every book in our data source.
  type Book {
    title: String
    author: String
  }

  # The "Query" type is special: it lists all of the available queries that
  # clients can execute, along with the return type for each. In this
  # case, the "books" query returns an array of zero or more Books (defined above).
  type Query {
    books: [Book]
  }
`;

const books = [
      {
              title: 'Harry Potter and the Chamber of Secrets',
              author: 'J.K. Rowling',
            },
      {
              title: 'Jurassic Park',
              author: 'Michael Crichton',
            },
];

const resolvers = {
    Query: {
        books: () => books,
    },
};

var express = require('express');
var app = express();
var fs = require( 'fs' );
var auth = require('basic-auth');
var bodyParser = require('body-parser');

//parsing
app.use(bodyParser.json({
    type: '*/*'
}));

//authorization
app.use(function(req, res, next) {
    var credentials = auth(req);
    if (!credentials || credentials.name !== process.env.API_USER || credentials.pass !== process.env.API_PASS) {
        res.set({
            'WWW-Authenticate': 'Basic realm="simple-admin"'
        });
        res.sendStatus(401);
    } else {
        next();
    }
});

//pretty jsonresponses
app.use(function(req, res, next) {
    res.sendStatusJson = function (status) {
        res.status(status).send({status: status});
    };
    next();
});

//routes
routes = fs.readdirSync('./routes');
routes.forEach( function( routeFile ) {
    app.use('/api/' + routeFile, require('./routes/' + routeFile));
});

//errorhandling
app.use(function(err, req, res, next) {
    console.error(err.stack);
    res.status(500).send({
        error: "500"
    });
    next(err);
});

// hide h eaders
app.disable('x-powered-by');

var server = app.listen(process.env.RASPAPI_PORT, function() {

    var host = server.address().address;
    var port = server.address().port;

    console.log('raspapi listening at http://%s:%s', host, port);

});
<commit_msg>feat(graphql): add graphql endpoint with hello world data<commit_after>require('dotenv').config();

const express = require('express');
const app = express();
const fs = require( 'fs' );
const auth = require('basic-auth');
const bodyParser = require('body-parser');

const { ApolloServer, gql } = require('apollo-server-express');

const typeDefs = gql`
  # Comments in GraphQL strings (such as this one) start with the hash (#) symbol.

  # This "Book" type defines the queryable fields for every book in our data source.
  type Book {
    title: String
    author: String
  }

  # The "Query" type is special: it lists all of the available queries that
  # clients can execute, along with the return type for each. In this
  # case, the "books" query returns an array of zero or more Books (defined above).
    type Query {
        books: [Book]
        hello: String
    }
`;

const books = [
    {
        title: 'Harry Potter and the Chamber of Secrets',
        author: 'J.K. Rowling',
    },
    {
        title: 'Jurassic Park',
        author: 'Michael Crichton',
    },
];

const resolvers = {
    Query: {
            hello: () => 'world',
            books: () => books,
    },
};

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: async ({ req }) => {
        return {
            myProperty: true
        };
    },
});

//parsing
app.use(bodyParser.json({
    type: '*/*'
}));

//authorization
// app.use(function(req, res, next) {
//     var credentials = auth(req);
//     if (!credentials || credentials.name !== process.env.API_USER || credentials.pass !== process.env.API_PASS) {
//         res.set({
//             'WWW-Authenticate': 'Basic realm="simple-admin"'
//         });
//         res.sendStatus(401);
//     } else {
//         next();
//     }
// });
//
//pretty jsonresponses
app.use(function(req, res, next) {
    res.sendStatusJson = function (status) {
        res.status(status).send({status: status});
    };
    next();
});

//routes
routes = fs.readdirSync('./routes');
routes.forEach( function( routeFile ) {
    app.use('/api/' + routeFile, require('./routes/' + routeFile));
});

//graphql
server.applyMiddleware({ app });

//errorhandling
app.use(function(err, req, res, next) {
    console.error(err.stack);
    res.status(500).send({
        error: "500"
    });
    next(err);
});

// hide h eaders
app.disable('x-powered-by');

app.listen({
    port: process.env.RASPAPI_PORT
}, () => {
    console.log(`${new Date().toISOString()} raspapi listening at ${process.env.RASPAPI_PORT}`);
});
<|endoftext|>


<commit_before>define([
    'leaflet', 'leaflet.draw'
], function(L, leafletDraw){

    L.drawLocal.edit.toolbar.buttons.negate = 'Negate layers.';
    L.drawLocal.edit.toolbar.buttons.negateDisabled = 'No layers to negate.';
    L.drawLocal.edit.handlers.negate = {
        tooltip: {
            text: 'Click on a shape to negate'
        }
    }

    L.Draw.Event.NEGATESTART = 'draw:negatestart';
    L.Draw.Event.NEGATESTOP = 'draw:negatestop';

    /**
     * @class L.EditToolbar.Negate
     * @aka EditToolbar.Delete
     */
    L.EditToolbar.Negate = L.Handler.extend({
        statics: {
            TYPE: 'negate'
        },

        includes: L.Mixin.Events,

        // @method intialize(): void
        initialize: function (map, options) {
            L.Handler.prototype.initialize.call(this, map);

            L.Util.setOptions(this, options);

            // Store the selectable layer group for ease of access
            this._negatableLayers = this.options.featureGroup;

            if (!(this._negatableLayers instanceof L.FeatureGroup)) {
                throw new Error('options.featureGroup must be a L.FeatureGroup');
            }

            // Save the type so super can fire, need to do this as cannot do this.TYPE :(
            this.type = L.EditToolbar.Negate.TYPE;
        },

        // @method enable(): void
        // Enable the negate toolbar
        enable: function () {
            if (this._enabled || !this._hasAvailableLayers()) {
                return;
            }
            this.fire('enabled', { handler: this.type });

            this._map.fire(L.Draw.Event.NEGATESTART, { handler: this.type });

            L.Handler.prototype.enable.call(this);

            this._negatableLayers
                .on('layeradd', this._enableLayerNegate, this)
                .on('layerremove', this._disableLayerNegate, this);
        },

        // @method disable(): void
        // Disable the delete toolbar
        disable: function () {
            if (!this._enabled) {
                return;
            }

            this._negatableLayers
                .off('layeradd', this._enableLayerNegate, this)
                .off('layerremove', this._disableLayerNegate, this);

            L.Handler.prototype.disable.call(this);

            this._map.fire(L.Draw.Event.NEGATESTOP, { handler: this.type });

            this.fire('disabled', { handler: this.type });
        },

        // @method addHooks(): void
        // Add listener hooks to this handler
        addHooks: function () {
            var map = this._map;

            if (map) {
                map.getContainer().focus();

                this._negatableLayers.eachLayer(this._enableLayerNegate, this);

                this._tooltip = new L.Draw.Tooltip(this._map);
                this._tooltip.updateContent({ text: L.drawLocal.edit.handlers.negate.tooltip.text });

                this._map.on('mousemove', this._onMouseMove, this);
            }
        },

        // @method removeHooks(): void
        // Remove listener hooks from this handler
        removeHooks: function () {
            if (this._map) {
                this._negatableLayers.eachLayer(this._disableLayerNegate, this);

                this._tooltip.dispose();
                this._tooltip = null;

                this._map.off('mousemove', this._onMouseMove, this);
            }
        },

        // @method revertLayers(): void
        // Revert the negated layers back to their prior state.
        revertLayers: function () {
        },

        // @method save(): void
        // Save negated layers
        save: function () {
        },

        _enableLayerNegate: function (e) {
            var layer = e.layer || e.target || e;

            layer.on('click', this._negateLayer, this);
        },

        _disableLayerNegate: function (e) {
            var layer = e.layer || e.target || e;

            layer.off('click', this._negateLayer, this);
        },

        _negateLayer: function (e) {
            L.DomEvent.stopPropagation(e);
            L.DomEvent.preventDefault(e);
            var layer = e.layer || e.target || e;

            layer.negated = !layer.negated;

            const color = this.options.shapeOptions[layer.negated ? 'negatedColor' : 'color'];
            layer.setStyle({ color: color, fillColor: color })

            layer.fire('negated');
        },

        _onMouseMove: function (e) {
            this._tooltip.updatePosition(e.latlng);
        },

        _hasAvailableLayers: function () {
            return this._negatableLayers.getLayers().length !== 0;
        }
    });

    L.EditToolbar.prototype.options.negate = {
        shapeOptions: {
            color: '#3388ff',
            negatedColor: '#ff0000'
        }
    };

    const origGetModeHandlers = L.EditToolbar.prototype.getModeHandlers;
    L.EditToolbar.prototype.getModeHandlers = function(map){
        const handlers = origGetModeHandlers.apply(this, arguments);

        const featureGroup = this.options.featureGroup;

        handlers.unshift({
            enabled: this.options.negate,
            handler: new L.EditToolbar.Negate(map, {
                featureGroup: featureGroup,
                shapeOptions: this.options.negate.shapeOptions
            }),
            title: L.drawLocal.edit.toolbar.buttons.negate
        });

        return handlers;
    }

    const orig_checkDisabled = L.EditToolbar.prototype._checkDisabled;
    L.EditToolbar.prototype._checkDisabled = function(){
        const featureGroup = this.options.featureGroup,
            hasLayers = featureGroup.getLayers().length !== 0;

        if (this.options.negate) {
            const button = this._modes[L.EditToolbar.Negate.TYPE].button;

            if (hasLayers) {
                L.DomUtil.removeClass(button, 'leaflet-disabled');
            } else {
                L.DomUtil.addClass(button, 'leaflet-disabled');
            }

            button.setAttribute(
                'title',
                hasLayers ?
                    L.drawLocal.edit.toolbar.buttons.negate
                    : L.drawLocal.edit.toolbar.buttons.negateDisabled
            );
        }

        return orig_checkDisabled.apply(this, arguments);
    }

    const origGetActions = L.EditToolbar.prototype.getActions;
    L.EditToolbar.prototype.getActions = function(handler){
        if (handler instanceof L.EditToolbar.Negate) {
            return [];
        }

        return origGetActions.apply(this);
    }

    return leafletDraw;
})<commit_msg>Cleanup: correct comments<commit_after>define([
    'leaflet', 'leaflet.draw'
], function(L, leafletDraw){

    L.drawLocal.edit.toolbar.buttons.negate = 'Negate layers.';
    L.drawLocal.edit.toolbar.buttons.negateDisabled = 'No layers to negate.';
    L.drawLocal.edit.handlers.negate = {
        tooltip: {
            text: 'Click on a shape to negate'
        }
    }

    L.Draw.Event.NEGATESTART = 'draw:negatestart';
    L.Draw.Event.NEGATESTOP = 'draw:negatestop';

    /**
     * @class L.EditToolbar.Negate
     * @aka EditToolbar.Negate
     */
    L.EditToolbar.Negate = L.Handler.extend({
        statics: {
            TYPE: 'negate'
        },

        includes: L.Mixin.Events,

        // @method intialize(): void
        initialize: function (map, options) {
            L.Handler.prototype.initialize.call(this, map);

            L.Util.setOptions(this, options);

            // Store the selectable layer group for ease of access
            this._negatableLayers = this.options.featureGroup;

            if (!(this._negatableLayers instanceof L.FeatureGroup)) {
                throw new Error('options.featureGroup must be a L.FeatureGroup');
            }

            // Save the type so super can fire, need to do this as cannot do this.TYPE :(
            this.type = L.EditToolbar.Negate.TYPE;
        },

        // @method enable(): void
        // Enable the negate toolbar
        enable: function () {
            if (this._enabled || !this._hasAvailableLayers()) {
                return;
            }
            this.fire('enabled', { handler: this.type });

            this._map.fire(L.Draw.Event.NEGATESTART, { handler: this.type });

            L.Handler.prototype.enable.call(this);

            this._negatableLayers
                .on('layeradd', this._enableLayerNegate, this)
                .on('layerremove', this._disableLayerNegate, this);
        },

        // @method disable(): void
        // Disable the negation toolbar
        disable: function () {
            if (!this._enabled) {
                return;
            }

            this._negatableLayers
                .off('layeradd', this._enableLayerNegate, this)
                .off('layerremove', this._disableLayerNegate, this);

            L.Handler.prototype.disable.call(this);

            this._map.fire(L.Draw.Event.NEGATESTOP, { handler: this.type });

            this.fire('disabled', { handler: this.type });
        },

        // @method addHooks(): void
        // Add listener hooks to this handler
        addHooks: function () {
            var map = this._map;

            if (map) {
                map.getContainer().focus();

                this._negatableLayers.eachLayer(this._enableLayerNegate, this);

                this._tooltip = new L.Draw.Tooltip(this._map);
                this._tooltip.updateContent({ text: L.drawLocal.edit.handlers.negate.tooltip.text });

                this._map.on('mousemove', this._onMouseMove, this);
            }
        },

        // @method removeHooks(): void
        // Remove listener hooks from this handler
        removeHooks: function () {
            if (this._map) {
                this._negatableLayers.eachLayer(this._disableLayerNegate, this);

                this._tooltip.dispose();
                this._tooltip = null;

                this._map.off('mousemove', this._onMouseMove, this);
            }
        },

        // @method revertLayers(): void
        // Revert the negated layers back to their prior state.
        revertLayers: function () {
        },

        // @method save(): void
        // Save negated layers
        save: function () {
        },

        _enableLayerNegate: function (e) {
            var layer = e.layer || e.target || e;

            layer.on('click', this._negateLayer, this);
        },

        _disableLayerNegate: function (e) {
            var layer = e.layer || e.target || e;

            layer.off('click', this._negateLayer, this);
        },

        _negateLayer: function (e) {
            L.DomEvent.stopPropagation(e);
            L.DomEvent.preventDefault(e);
            var layer = e.layer || e.target || e;

            layer.negated = !layer.negated;

            const color = this.options.shapeOptions[layer.negated ? 'negatedColor' : 'color'];
            layer.setStyle({ color: color, fillColor: color })

            layer.fire('negated');
        },

        _onMouseMove: function (e) {
            this._tooltip.updatePosition(e.latlng);
        },

        _hasAvailableLayers: function () {
            return this._negatableLayers.getLayers().length !== 0;
        }
    });

    L.EditToolbar.prototype.options.negate = {
        shapeOptions: {
            color: '#3388ff',
            negatedColor: '#ff0000'
        }
    };

    const origGetModeHandlers = L.EditToolbar.prototype.getModeHandlers;
    L.EditToolbar.prototype.getModeHandlers = function(map){
        const handlers = origGetModeHandlers.apply(this, arguments);

        const featureGroup = this.options.featureGroup;

        handlers.unshift({
            enabled: this.options.negate,
            handler: new L.EditToolbar.Negate(map, {
                featureGroup: featureGroup,
                shapeOptions: this.options.negate.shapeOptions
            }),
            title: L.drawLocal.edit.toolbar.buttons.negate
        });

        return handlers;
    }

    const orig_checkDisabled = L.EditToolbar.prototype._checkDisabled;
    L.EditToolbar.prototype._checkDisabled = function(){
        const featureGroup = this.options.featureGroup,
            hasLayers = featureGroup.getLayers().length !== 0;

        if (this.options.negate) {
            const button = this._modes[L.EditToolbar.Negate.TYPE].button;

            if (hasLayers) {
                L.DomUtil.removeClass(button, 'leaflet-disabled');
            } else {
                L.DomUtil.addClass(button, 'leaflet-disabled');
            }

            button.setAttribute(
                'title',
                hasLayers ?
                    L.drawLocal.edit.toolbar.buttons.negate
                    : L.drawLocal.edit.toolbar.buttons.negateDisabled
            );
        }

        return orig_checkDisabled.apply(this, arguments);
    }

    const origGetActions = L.EditToolbar.prototype.getActions;
    L.EditToolbar.prototype.getActions = function(handler){
        if (handler instanceof L.EditToolbar.Negate) {
            return [];
        }

        return origGetActions.apply(this);
    }

    return leafletDraw;
})<|endoftext|>


<commit_before>load("wtf.js");
load("session.js");
var sesn = new session();

var conf_mail = {
    "address": "mail.io",
    "host": "localhost",
    "port": 25
};
container.deployModule("io.vertx~mod-mailer~2.0.0-final", conf_mail);

function mailer(){};

mailer.prototype.sendAuthMail = function(req){
    var owner = this;

    var code = null;
    var nk = null;
    var em = null;
    var uuid = sesn.getCookieUUID(req);

    wtf.heap([
        uuid
    ],
    [
        function(uuid, cb){
            eb.send(
                'redis.io',
                {
                    command: "get",
                    args: [uuid]
                },
                function(msg){
                    if(msg.value==null){
                        console.log("failed to get session(send_auth_mail()): ");
                    }else{
                        nk = msg.value;
                        cb(nk);
                    }
                }
            );
        },
        function(nk, cb){
            // remove user from database
            eb.send(
                'maria.io',
                {
                    action: 'select',
                    stmt: "select * from user where nickname=?",
                    values: [[nk]]
                },
                function(msg){
                    if(msg.status == 'ok'){
                        em = msg.result[0].email;
                        code = owner.generateCode();
                        cb();
                    }
                }
            );
        },
        function(cb){
            eb.send(
                'redis.io',
                {
                    command: "set",
                    args: [em, code]
                },
                function(msg){
                    if(msg.status == 'ok'){
                        cb();
                    }
                }
            );
        },
        function(cb){
            eb.send(
                'redis.io',
                {
                    command: "expire",
                    args: [em, server["sesn_lifetime"]]
                },
                function(msg){
                    console.log("email-code set in redis(sendAuthMail()): "+msg.status);
                    cb();
                }
            );
        },
        function(){
            eb.send(
                'mail.io',
                {
                    "from": "auth@ryunwake.com",
                    "to": em,
                    "subject": "Auth mail",
                    "body": code+""
                }
            );
        }
    ]);

    // eb.send(
    //     'redis.io',
    //     {
    //         command: "get",
    //         args: [uuid]
    //     },
    //     function(msg){
    //         if(msg.value==null){
    //             console.log("failed to get session(send_auth_mail()): ");
    //         }else{
    //             nk = msg.value;
    //             // remove user from database
    //             eb.send(
    //                 'maria.io',
    //                 {
    //                     action: 'select',
    //                     stmt: "select * from user where nickname=?",
    //                     values: [[nk]]
    //                 },
    //                 function(msg){
    //                     if(msg.status == 'ok'){
    //                         em = msg.result[0].email;
    //                         code = owner.generateCode();
    //                         eb.send(
    //                             'redis.io',
    //                             {
    //                                 command: "set",
    //                                 args: [em, code]
    //                             },
    //                             function(msg){
    //                                 if(msg.status == 'ok'){
    //                                     eb.send(
    //                                         'redis.io',
    //                                         {
    //                                             command: "expire",
    //                                             args: [em, server["sesn_lifetime"]]
    //                                         },
    //                                         function(msg){
    //                                             console.log("email-code set in redis(sendAuthMail()): "+msg.status);
    //                                             eb.send(
    //                                                 'mail.io',
    //                                                 {
    //                                                     "from": "auth@ryunwake.com",
    //                                                     "to": em,
    //                                                     "subject": "Auth mail",
    //                                                     "body": code+""
    //                                                 }
    //                                             );
    //                                         }
    //                                     );
    //                                 }
    //                             }
    //                         );
    //                     }
    //                 }
    //             );
    //         }
    //     }
    // );
};

mailer.prototype.checkMailCode = function(req){
    console.log("checkMailCode called -----------");
    req.expectMultiPart(true);
    req.endHandler(function(){
        var code = req.formAttributes().get("code");
        var em = null;
        var nk = null;
        var uuid = sesn.getCookieUUID(req);
        console.log("code(checkMailCode()): "+code);
        eb.send(
            'redis.io',
            {
                command: "get",
                args: [uuid]
            },
            function(msg){
                nk = msg.value;
                console.log("gotten nickname(checkMailCode()): "+ nk);
                if( nk!= null){
                    eb.send(
                        'maria.io',
                        {
                            action: 'select',
                            stmt: "select * from user where nickname=?",
                            values: [[nk]]
                        },
                        function(msg){
                            if(msg.status == 'ok'){
                                em = msg.result[0].email;
                                console.log("gotten email(checkMailCode()): "+em);
                                eb.send(
                                    'redis.io',
                                    {
                                        command: "get",
                                        args: [em]
                                    },
                                    function(msg){
                                        console.log("code value from redis(checkMailCode()): "+msg.value);
                                        if(msg.value == code){
                                            eb.send(
                                                'maria.io',
                                                {
                                                    action: 'update',
                                                    stmt: "update user set authed='true' where nickname=?",
                                                    values: [[nk]]
                                                },
                                                function(msg){
                                                    if(msg.status == 'ok'){
                                                        req.response.end("<script>location.href = '"+server['url']+"/main';</script>");
                                                    }
                                                }
                                            );
                                        }else{
                                            req.response.end("<script>location.href = '"+server['url']+"';</script>");
                                        }
                                    }
                                );
                            }
                        }
                    );
                } else{
                    req.response.end("<script>location.href = '"+server['url']+"';</script>");
                }
            }
        );
    });
};

mailer.prototype.generateCode = function(){
    var code = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ ){
        code += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    return code;
};
<commit_msg>classify mailauth<commit_after>load("wtf.js");
load("session.js");
var sesn = new session();

var conf_mail = {
    "address": "mail.io",
    "host": "localhost",
    "port": 25
};
container.deployModule("io.vertx~mod-mailer~2.0.0-final", conf_mail);

function mailer(){};

mailer.prototype.sendAuthMail = function(req){
    var owner = this;

    var code = null;
    var nk = null;
    var em = null;
    var uuid = sesn.getCookieUUID(req);

    wtf.heap([
        uuid
    ],
    [
        function(uuid, cb){
            eb.send(
                'redis.io',
                {
                    command: "get",
                    args: [uuid]
                },
                function(msg){
                    if(msg.value==null){
                        console.log("failed to get session(send_auth_mail()): ");
                    }else{
                        nk = msg.value;
                        cb(nk);
                    }
                }
            );
        },
        function(nk, cb){
            // remove user from database
            eb.send(
                'maria.io',
                {
                    action: 'select',
                    stmt: "select * from user where nickname=?",
                    values: [[nk]]
                },
                function(msg){
                    if(msg.status == 'ok'){
                        em = msg.result[0].email;
                        code = owner.generateCode();
                        cb();
                    }
                }
            );
        },
        function(cb){
            eb.send(
                'redis.io',
                {
                    command: "set",
                    args: [em, code]
                },
                function(msg){
                    if(msg.status == 'ok'){
                        cb();
                    }
                }
            );
        },
        function(cb){
            eb.send(
                'redis.io',
                {
                    command: "expire",
                    args: [em, server["sesn_lifetime"]]
                },
                function(msg){
                    console.log("email-code set in redis(sendAuthMail()): "+msg.status);
                    cb();
                }
            );
        },
        function(){
            eb.send(
                'mail.io',
                {
                    "from": "auth@ryunwake.com",
                    "to": em,
                    "subject": "Auth mail",
                    "body": code+""
                }
            );
        }
    ]);
};

mailer.prototype.checkMailCode = function(req){
    console.log("checkMailCode called -----------");
    req.expectMultiPart(true);
    req.endHandler(function(){
        var code = req.formAttributes().get("code");
        var em = null;
        var nk = null;
        var uuid = sesn.getCookieUUID(req);
        console.log("code(checkMailCode()): "+code);

        wtf.heap([
            uuid
        ],
        [
            function(uuid, cb){
                eb.send(
                    'redis.io',
                    {
                        command: "get",
                        args: [uuid]
                    },
                    function(msg){
                        nk = msg.value;
                        console.log("gotten nickname(checkMailCode()): "+ nk);
                        if( nk!= null){
                            cb(nk);
                        }else{
                            req.response.end("<script>location.href = '"+server['url']+"';</script>");
                        }
                    }
                );
            },
            function(nk, cb){
                eb.send(
                    'maria.io',
                    {
                        action: 'select',
                        stmt: "select * from user where nickname=?",
                        values: [[nk]]
                    },
                    function(msg){
                        if(msg.status == 'ok'){
                            em = msg.result[0].email;
                            console.log("gotten email(checkMailCode()): "+em);
                            cb(em);
                        }
                    }
                );
            },
            function(em, cb){
                eb.send(
                    'redis.io',
                    {
                        command: "get",
                        args: [em]
                    },
                    function(msg){
                        console.log("code value from redis(checkMailCode()): "+msg.value);
                        if(msg.value == code){
                            cb(nk);
                        }else{
                            req.response.end("<script>location.href = '"+server['url']+"';</script>");
                        }
                    }
                );
            },
            function(nk, cb){
                eb.send(
                    'maria.io',
                    {
                        action: 'update',
                        stmt: "update user set authed='true' where nickname=?",
                        values: [[nk]]
                    },
                    function(msg){
                        if(msg.status == 'ok'){
                            req.response.end("<script>location.href = '"+server['url']+"/main';</script>");
                        }
                    }
                );
            }
        ]);
    });
};

mailer.prototype.generateCode = function(){
    var code = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ ){
        code += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    return code;
};
<|endoftext|>


<commit_before>'use strict';

var SRW_EXAMPLES;

SIREPO.srlog = console.log.bind(console);
SIREPO.srdbg = console.log.bind(console);

var srlog = SIREPO.srlog;
var srdbg = SIREPO.srdbg;

SIREPO.IS_SRW_LANDING_PAGE = window.location.href.match(/\/light/);

angular.element(document).ready(function() {
    $.ajax({
        url: '/static/json/srw-examples.json?' + SIREPO.APP_VERSION,
        success: function(result) {
            SRW_EXAMPLES = result;
            angular.bootstrap(document, ['LandingPageApp']);
        },
        error: function(xhr, status, err) {
            if (! SRW_EXAMPLES)
                srlog("srw examples load failed: ", err);
        },
        method: 'GET',
        dataType: 'json',
    });
});

var app = angular.module('LandingPageApp', ['ngRoute']);

app.value('appRoutes', {
    'calculator': 'SR Calculator',
    'light-sources': 'Light Source Facilities',
    'wavefront': 'Wavefront Propagation',
});

app.config(function($routeProvider, appRoutesProvider) {
    // srw landing page
    if (SIREPO.IS_SRW_LANDING_PAGE) {
        var appRoutes = appRoutesProvider.$get();
        $routeProvider.when('/home', {
            templateUrl: '/static/html/landing-page-home.html?' + SIREPO.APP_VERSION,
        });
        Object.keys(appRoutes).forEach(function(key) {
            $routeProvider.when('/' + key, {
                template: '

',
            });
        });
        $routeProvider.otherwise({
            redirectTo: '/home',
        });
    }
    // root landing page
    else {
        $routeProvider.when('/about', {
            templateUrl: '/static/html/landing-page-about.html?' + SIREPO.APP_VERSION,
        });
        $routeProvider.otherwise({
            redirectTo: '/about',
        });
    }
});

app.controller('LandingPageController', function ($location, appRoutes) {
    var self = this;
    self.srwExamples = SRW_EXAMPLES;

    function pageCategory() {
        return $location.path().substring(1);
    }

    self.itemsForCategory = function() {
        for (var i = 0; i < self.srwExamples.length; i++) {
            if (self.srwExamples[i].category == pageCategory())
                return self.srwExamples[i].examples;
        }
    };

    self.itemUrl = function(item) {
        return '/find-by-name/srw/' + pageCategory() + '/' + encodeURIComponent(item.simulationName || item.name);
    };

    self.pageName = function() {
        return appRoutes[pageCategory()];
    };

    self.pageTitle = function() {
        var name = self.pageName();
        return (name ? (name + ' - ') : '') + 'Synchrotron Radiation Workshop - Radiasoft';
    };
});

app.directive('bigButton', function() {
    return {
        scope: {
            title: '@bigButton',
            image: '@',
            href: '@',
        },
        template: [
            '
',
              '
',
                '
{{ title }}
',
              '
',
            '
',
        ].join(''),
    };
});

app.directive('pageHeading', function() {
    function getTemplate() {
        if (SIREPO.IS_SRW_LANDING_PAGE) {
            return [
                '
Synchrotron Radiation Workshop',
                  ' - ',
                  '',
                '
',
            ].join('');
        }
        return [
            '
Sirepo
',
        ].join('');
    }
    return {
        scope: {
            landingPage: '=',
        },
        template: getTemplate(),
    };
});
<commit_msg>fixed page title for landing page<commit_after>'use strict';

var SRW_EXAMPLES;

SIREPO.srlog = console.log.bind(console);
SIREPO.srdbg = console.log.bind(console);

var srlog = SIREPO.srlog;
var srdbg = SIREPO.srdbg;

SIREPO.IS_SRW_LANDING_PAGE = window.location.href.match(/\/light/);

angular.element(document).ready(function() {
    $.ajax({
        url: '/static/json/srw-examples.json?' + SIREPO.APP_VERSION,
        success: function(result) {
            SRW_EXAMPLES = result;
            angular.bootstrap(document, ['LandingPageApp']);
        },
        error: function(xhr, status, err) {
            if (! SRW_EXAMPLES)
                srlog("srw examples load failed: ", err);
        },
        method: 'GET',
        dataType: 'json',
    });
});

var app = angular.module('LandingPageApp', ['ngRoute']);

app.value('appRoutes', {
    'calculator': 'SR Calculator',
    'light-sources': 'Light Source Facilities',
    'wavefront': 'Wavefront Propagation',
});

app.config(function($routeProvider, appRoutesProvider) {
    // srw landing page
    if (SIREPO.IS_SRW_LANDING_PAGE) {
        var appRoutes = appRoutesProvider.$get();
        $routeProvider.when('/home', {
            templateUrl: '/static/html/landing-page-home.html?' + SIREPO.APP_VERSION,
        });
        Object.keys(appRoutes).forEach(function(key) {
            $routeProvider.when('/' + key, {
                template: '

',
            });
        });
        $routeProvider.otherwise({
            redirectTo: '/home',
        });
    }
    // root landing page
    else {
        $routeProvider.when('/about', {
            templateUrl: '/static/html/landing-page-about.html?' + SIREPO.APP_VERSION,
        });
        $routeProvider.otherwise({
            redirectTo: '/about',
        });
    }
});

app.controller('LandingPageController', function ($location, appRoutes) {
    var self = this;
    self.srwExamples = SRW_EXAMPLES;

    function pageCategory() {
        return $location.path().substring(1);
    }

    self.itemsForCategory = function() {
        for (var i = 0; i < self.srwExamples.length; i++) {
            if (self.srwExamples[i].category == pageCategory())
                return self.srwExamples[i].examples;
        }
    };

    self.itemUrl = function(item) {
        return '/find-by-name/srw/' + pageCategory() + '/' + encodeURIComponent(item.simulationName || item.name);
    };

    self.pageName = function() {
        return appRoutes[pageCategory()];
    };

    self.pageTitle = function() {
        if (SIREPO.IS_SRW_LANDING_PAGE) {
            var name = self.pageName();
            return (name ? (name + ' - ') : '') + 'Synchrotron Radiation Workshop - Radiasoft';
        }
        return 'Sirepo - Radiasoft';
    };
});

app.directive('bigButton', function() {
    return {
        scope: {
            title: '@bigButton',
            image: '@',
            href: '@',
        },
        template: [
            '
',
              '
',
                '
{{ title }}
',
              '
',
            '
',
        ].join(''),
    };
});

app.directive('pageHeading', function() {
    function getTemplate() {
        if (SIREPO.IS_SRW_LANDING_PAGE) {
            return [
                '
Synchrotron Radiation Workshop',
                  ' - ',
                  '',
                '
',
            ].join('');
        }
        return [
            '
Sirepo
',
        ].join('');
    }
    return {
        scope: {
            landingPage: '=',
        },
        template: getTemplate(),
    };
});
<|endoftext|>


<commit_before>function init(){
    //init data
    var json = {
        id: "node02",
        name: "0.2",
        data: {},
        children: [{
            id: "node13",
            name: "1.3",
            data: {},
            children: [{
                id: "node24",
                name: "2.4",
                data: {},
                children: []
            }, {
                id: "node222",
                name: "2.22",
                data: {},
                children: []
            }]
        }, {
            id: "node125",
            name: "1.25",
            data: {},
            children: [{
                id: "node226",
                name: "2.26",
                data: {},
                children: []
            }, {
                id: "node237",
                name: "2.37",
                data: {},
                children: []
            }, {
                id: "node258",
                name: "2.58",
                data: {},
                children: []
            }]
        }, {
            id: "node165",
            name: "1.65",
            data: {},
            children: [{
                id: "node266",
                name: "2.66",
                data: {},
                children: []
            }, {
                id: "node283",
                name: "2.83",
                data: {},
                children: []
            }, {
                id: "node2104",
                name: "2.104",
                data: {},
                children: []
            }, {
                id: "node2109",
                name: "2.109",
                data: {},
                children: []
            }, {
                id: "node2125",
                name: "2.125",
                data: {},
                children: []
            }]
        }, {
            id: "node1130",
            name: "1.130",
            data: {},
            children: [{
                id: "node2131",
                name: "2.131",
                data: {},
                children: []
            }, {
                id: "node2138",
                name: "2.138",
                data: {},
                children: []
            }]
        }]
    };
    //end
    //init Node Types
    //Create a node rendering function that plots a fillRectangle and
    //a stroke rectangle for borders
    $jit.ST.Plot.NodeTypes.implement({
      'stroke-rect': {
        'render': function(node, canvas) {
          var width = node.getData('width'),
              height = node.getData('height'),
              pos = this.getAlignedPos(node.pos.getc(true), width, height),
              posX = pos.x + width/2,
              posY = pos.y + height/2;
          this.nodeHelper.rectangle.render('fill', {x: posX, y: posY}, width, height, canvas);
          this.nodeHelper.rectangle.render('stroke', {x: posX, y: posY}, width, height, canvas);
        }
      }
    });
    //init st
    //Create a new ST instance
    var st = new $jit.ST({
        //id of viz container element
        injectInto: 'infovis',
        //set distance between node and its children
        levelDistance: 50,
        //set an X offset
        offsetX: 130,
        //set node, edge and label styles
        //set overridable=true for styling individual
        //nodes or edges
        Node: {
            overridable: true,
            type: 'stroke-rect',
            height: 20,
            width: 60,
            //canvas specific styles
            CanvasStyles: {
              fillStyle: '#daa',
              strokeStyle: '#ffc',
              lineWidth: 2
            }
        },
        Edge: {
            overridable: true,
            type: 'line',
            color: '#ffc',
            lineWidth: 1
        },
        Label: {
            type: labelType,
            style: 'bold',
            size: 10,
            color: '#333'
        },
        //This method is called on DOM label creation.
        //Use this method to add event handlers and styles to
        //your node.
        onCreateLabel: function(label, node){
            label.innerHTML = node.name;
            //set label styles
            var style = label.style;
            style.width = 60 + 'px';
            style.height = 17 + 'px';
            style.color = '#333';
            style.fontSize = '0.8em';
            style.textAlign= 'center';
            style.paddingTop = '3px';
        },
        onPlaceLabel: function(label, node) {
          var style = label.style;
          style.width = node.getData('width') + 'px';
          style.height = node.getData('height') + 'px';
          style.color = node.getLabelData('color');
          style.fontSize = node.getLabelData('size') + 'px';
          style.textAlign= 'center';
          style.paddingTop = '3px';
        }
    });
    //load json data
    st.loadJSON(json);
    //compute node positions and layout
    st.compute();
    //emulate a click on the root node.
    st.onClick(st.root);
    //end

    //Add Select All/None actions
    var nodeAll = $jit.id('select-all-nodes'),
        nodeNone = $jit.id('select-none-nodes'),
        edgeAll = $jit.id('select-all-edges'),
        edgeNone = $jit.id('select-none-edges'),
        labelAll = $jit.id('select-all-labels'),
        labelNone = $jit.id('select-none-labels');
    $jit.util.each([nodeAll, edgeAll, labelAll], function(elem) {
      elem.onclick = function() {
        var pn = elem.parentNode.parentNode.parentNode; //table
        var inputs = pn.getElementsByTagName('input');
        for(var i=0, l=inputs.length; i<l; i++) {
          if(inputs[i].type == 'checkbox') {
            inputs[i].checked = true;
          }
        }
      };
    });
    $jit.util.each([nodeNone, edgeNone, labelNone], function(elem) {
      elem.onclick = function() {
        var pn = elem.parentNode.parentNode.parentNode; //table
        var inputs = pn.getElementsByTagName('input');
        for(var i=0, l=inputs.length; i<l; i++) {
          if(inputs[i].type == 'checkbox') {
            inputs[i].checked = false;
          }
        }
      };
    });
    //get checkboxes
    var nWidth = $jit.id('n-width'),
        nHeight = $jit.id('n-height'),
        nColor = $jit.id('n-color'),
        nBorderColor = $jit.id('n-border-color'),
        nBorderWidth = $jit.id('n-border-width'),
        eLineWidth = $jit.id('e-line-width'),
        eLineColor = $jit.id('e-line-color'),
        lFontSize = $jit.id('l-font-size'),
        lFontColor = $jit.id('l-font-color');

    //init Morphing Animations
    var button = $jit.id('update'),
        restore = $jit.id('restore'),
        rand = Math.random,
        floor = Math.floor,
        colors = ['#33a', '#55b', '#77c', '#99d', '#aae', '#bf0', '#cf5',
                  '#dfa', '#faccff', '#ffccff', '#CCC', '#C37'],
        colorLength = colors.length;
    //add click event for restore
    $jit.util.addEvent(restore, 'click', function() {
      if(init.busy) return;
      init.busy = true;

      st.graph.eachNode(function(n) {
        //restore width and height node styles
        n.setDataset('end', {
          width: 60,
          height: 20
        });
        //restore canvas specific styles
        n.setCanvasStyles('end', {
          fillStyle: '#daa',
          strokeStyle: '#ffc',
          lineWidth: 2
        });
        //restore font styles
        n.setLabelDataset('end', {
          size: 10,
          color: '#333'
        });
        //set adjacencies styles
        n.eachAdjacency(function(adj) {
          adj.setDataset('end', {
            lineWidth: 1,
            color: '#ffc'
          });
        });
      });
      st.compute('end');
      st.geom.translate({x:-130, y:0}, 'end');
      st.fx.animate({
        modes: ['linear',
                'node-property:width:height',
                'edge-property:lineWidth:color',
                'label-property:size:color',
                'node-style:fillStyle:strokeStyle:lineWidth'],
        duration: 1500,
        onComplete: function() {
          init.busy = false;
        }
      });
    });
    //add click event for updating styles
    $jit.util.addEvent(button, 'click', function() {
      if(init.busy) return;
      init.busy = true;

      st.graph.eachNode(function(n) {
        //set random width and height node styles
        nWidth.checked && n.setData('width', floor(rand() * 40 + 20), 'end');
        nHeight.checked && n.setData('height', floor(rand() * 40 + 20), 'end');
        //set random canvas specific styles
        nColor.checked && n.setCanvasStyle('fillStyle', colors[floor(colorLength * rand())], 'end');
        nBorderColor.checked && n.setCanvasStyle('strokeStyle', colors[floor(colorLength * rand())], 'end');
        nBorderWidth.checked && n.setCanvasStyle('lineWidth', 10 * rand() + 1, 'end');
        //set label styles
        lFontSize.checked && n.setLabelData('size', 20 * rand() + 1, 'end');
        lFontColor.checked && n.setLabelData('color', colors[floor(colorLength * rand())], 'end');
        //set adjacency styles
        n.eachAdjacency(function(adj) {
          eLineWidth.checked && adj.setData('lineWidth', 10 * rand() + 1, 'end');
          eLineColor.checked && adj.setData('color', colors[floor(colorLength * rand())], 'end');
        });
      });
      st.compute('end');
      st.geom.translate({x:-130, y:0}, 'end');
      st.fx.animate({
        modes: ['linear',
                'node-property:width:height',
                'edge-property:lineWidth:color',
                'label-property:size:color',
                'node-style:fillStyle:strokeStyle:lineWidth'],
        duration: 1500,
        onComplete: function() {
          init.busy = false;
        }
      });
    });
    //end
}
<commit_msg>Cleanup JSON data in spacetree test<commit_after>function init(){
    //init data
    var json = {
        id: "node02",
        name: "0.2",
        children: [{
            id: "node13",
            name: "1.3",
            children: [{
                id: "node24",
                name: "2.4"
              }, {
                id: "node222",
                name: "2.22"
              }]
        }, {
            id: "node125",
            name: "1.25",
            children: [{
                id: "node226",
                name: "2.26"
            }, {
                id: "node237",
                name: "2.37"
            }, {
                id: "node258",
                name: "2.58"
            }]
        }, {
            id: "node165",
            name: "1.65",
            children: [{
                id: "node266",
                name: "2.66"
            }, {
                id: "node283",
                name: "2.83"
            }, {
                id: "node2104",
                name: "2.104",
            }, {
                id: "node2109",
                name: "2.109"
            }, {
                id: "node2125",
                name: "2.125"
            }]
        }, {
            id: "node1130",
            name: "1.130",
            children: [{
                id: "node2131",
                name: "2.131"
            }, {
                id: "node2138",
                name: "2.138"
            }]
        }]
    };
    //end
    //init Node Types
    //Create a node rendering function that plots a fillRectangle and
    //a stroke rectangle for borders
    $jit.ST.Plot.NodeTypes.implement({
      'stroke-rect': {
        'render': function(node, canvas) {
          var width = node.getData('width'),
              height = node.getData('height'),
              pos = this.getAlignedPos(node.pos.getc(true), width, height),
              posX = pos.x + width/2,
              posY = pos.y + height/2;
          this.nodeHelper.rectangle.render('fill', {x: posX, y: posY}, width, height, canvas);
          this.nodeHelper.rectangle.render('stroke', {x: posX, y: posY}, width, height, canvas);
        }
      }
    });
    //init st
    //Create a new ST instance
    var st = new $jit.ST({
        //id of viz container element
        injectInto: 'infovis',
        //set distance between node and its children
        levelDistance: 50,
        //set an X offset
        offsetX: 130,
        //set node, edge and label styles
        //set overridable=true for styling individual
        //nodes or edges
        Node: {
            overridable: true,
            type: 'stroke-rect',
            height: 20,
            width: 60,
            //canvas specific styles
            CanvasStyles: {
              fillStyle: '#daa',
              strokeStyle: '#ffc',
              lineWidth: 2
            }
        },
        Edge: {
            overridable: true,
            type: 'line',
            color: '#ffc',
            lineWidth: 1
        },
        Label: {
            type: labelType,
            style: 'bold',
            size: 10,
            color: '#333'
        },
        //This method is called on DOM label creation.
        //Use this method to add event handlers and styles to
        //your node.
        onCreateLabel: function(label, node){
            label.innerHTML = node.name;
            //set label styles
            var style = label.style;
            style.width = 60 + 'px';
            style.height = 17 + 'px';
            style.color = '#333';
            style.fontSize = '0.8em';
            style.textAlign= 'center';
            style.paddingTop = '3px';
        },
        onPlaceLabel: function(label, node) {
          var style = label.style;
          style.width = node.getData('width') + 'px';
          style.height = node.getData('height') + 'px';
          style.color = node.getLabelData('color');
          style.fontSize = node.getLabelData('size') + 'px';
          style.textAlign= 'center';
          style.paddingTop = '3px';
        }
    });
    //load json data
    st.loadJSON(json);
    //compute node positions and layout
    st.compute();
    //emulate a click on the root node.
    st.onClick(st.root);
    //end

    //Add Select All/None actions
    var nodeAll = $jit.id('select-all-nodes'),
        nodeNone = $jit.id('select-none-nodes'),
        edgeAll = $jit.id('select-all-edges'),
        edgeNone = $jit.id('select-none-edges'),
        labelAll = $jit.id('select-all-labels'),
        labelNone = $jit.id('select-none-labels');
    $jit.util.each([nodeAll, edgeAll, labelAll], function(elem) {
      elem.onclick = function() {
        var pn = elem.parentNode.parentNode.parentNode; //table
        var inputs = pn.getElementsByTagName('input');
        for(var i=0, l=inputs.length; i<l; i++) {
          if(inputs[i].type == 'checkbox') {
            inputs[i].checked = true;
          }
        }
      };
    });
    $jit.util.each([nodeNone, edgeNone, labelNone], function(elem) {
      elem.onclick = function() {
        var pn = elem.parentNode.parentNode.parentNode; //table
        var inputs = pn.getElementsByTagName('input');
        for(var i=0, l=inputs.length; i<l; i++) {
          if(inputs[i].type == 'checkbox') {
            inputs[i].checked = false;
          }
        }
      };
    });
    //get checkboxes
    var nWidth = $jit.id('n-width'),
        nHeight = $jit.id('n-height'),
        nColor = $jit.id('n-color'),
        nBorderColor = $jit.id('n-border-color'),
        nBorderWidth = $jit.id('n-border-width'),
        eLineWidth = $jit.id('e-line-width'),
        eLineColor = $jit.id('e-line-color'),
        lFontSize = $jit.id('l-font-size'),
        lFontColor = $jit.id('l-font-color');

    //init Morphing Animations
    var button = $jit.id('update'),
        restore = $jit.id('restore'),
        rand = Math.random,
        floor = Math.floor,
        colors = ['#33a', '#55b', '#77c', '#99d', '#aae', '#bf0', '#cf5',
                  '#dfa', '#faccff', '#ffccff', '#CCC', '#C37'],
        colorLength = colors.length;
    //add click event for restore
    $jit.util.addEvent(restore, 'click', function() {
      if(init.busy) return;
      init.busy = true;

      st.graph.eachNode(function(n) {
        //restore width and height node styles
        n.setDataset('end', {
          width: 60,
          height: 20
        });
        //restore canvas specific styles
        n.setCanvasStyles('end', {
          fillStyle: '#daa',
          strokeStyle: '#ffc',
          lineWidth: 2
        });
        //restore font styles
        n.setLabelDataset('end', {
          size: 10,
          color: '#333'
        });
        //set adjacencies styles
        n.eachAdjacency(function(adj) {
          adj.setDataset('end', {
            lineWidth: 1,
            color: '#ffc'
          });
        });
      });
      st.compute('end');
      st.geom.translate({x:-130, y:0}, 'end');
      st.fx.animate({
        modes: ['linear',
                'node-property:width:height',
                'edge-property:lineWidth:color',
                'label-property:size:color',
                'node-style:fillStyle:strokeStyle:lineWidth'],
        duration: 1500,
        onComplete: function() {
          init.busy = false;
        }
      });
    });
    //add click event for updating styles
    $jit.util.addEvent(button, 'click', function() {
      if(init.busy) return;
      init.busy = true;

      st.graph.eachNode(function(n) {
        //set random width and height node styles
        nWidth.checked && n.setData('width', floor(rand() * 40 + 20), 'end');
        nHeight.checked && n.setData('height', floor(rand() * 40 + 20), 'end');
        //set random canvas specific styles
        nColor.checked && n.setCanvasStyle('fillStyle', colors[floor(colorLength * rand())], 'end');
        nBorderColor.checked && n.setCanvasStyle('strokeStyle', colors[floor(colorLength * rand())], 'end');
        nBorderWidth.checked && n.setCanvasStyle('lineWidth', 10 * rand() + 1, 'end');
        //set label styles
        lFontSize.checked && n.setLabelData('size', 20 * rand() + 1, 'end');
        lFontColor.checked && n.setLabelData('color', colors[floor(colorLength * rand())], 'end');
        //set adjacency styles
        n.eachAdjacency(function(adj) {
          eLineWidth.checked && adj.setData('lineWidth', 10 * rand() + 1, 'end');
          eLineColor.checked && adj.setData('color', colors[floor(colorLength * rand())], 'end');
        });
      });
      st.compute('end');
      st.geom.translate({x:-130, y:0}, 'end');
      st.fx.animate({
        modes: ['linear',
                'node-property:width:height',
                'edge-property:lineWidth:color',
                'label-property:size:color',
                'node-style:fillStyle:strokeStyle:lineWidth'],
        duration: 1500,
        onComplete: function() {
          init.busy = false;
        }
      });
    });
    //end
}
<|endoftext|>


<commit_before>
/* Dasca, an idle game by @CylonicRaider (github.com/CylonicRaider/dasca)
 * Abstract engine for JS-based idle games */

'use strict';

/* Construct a new clock
 * source is a function that, when called, returns the current time; scale
 * and offset modify source's output in a linear fashion: the reading of
 * source is multiplied by scale and offset is added to that to obtain the
 * current time. If scale is undefined or null, it defaults to 1; if offset
 * is null, it is computed such that the clock starts counting from zero. */
function Clock(source, scale, offset) {
  if (scale == null) scale = 1.0;
  if (offset == null) offset = -source() * scale;
  this.source = source;
  this.scale = scale;
  this.offset = offset;
}

Clock.prototype = {
  /* Sample the current time */
  now: function() {
    return this.source() * this.scale + this.offset;
  },

  /* Construct a new clock from this one, applying the given transformation
   * The new clock derives its time from the same (!) source as this one,
   * but its scale and offset are modified to simulate a clock constructed
   * like
   *     new Clock(this, scale, offset);
   */
  derive: function(scale, offset) {
    if (scale == null) scale = 1.0;
    if (offset != null) offset = this.offset * scale + offset;
    var ret = new Clock(this.source, this.scale * scale, offset);
    if (this._realTime) ret._realTime = true;
    return ret;
  },

  /* Serialization boilerplate */
  constructor: Clock
};

/* Construct a clock that returns (optionally scaled) real time
 * The clock counts from zero */
Clock.realTime = function(scale, start) {
  if (scale == null) scale = 1.0;
  scale *= 1e-3;
  var offset = (start == null) ? null : start - performance.now() * scale;
  var ret = new Clock(performance.now.bind(performance), scale, offset);
  ret._realTime = true;
  return ret;
};

/* Seralize a clock */
Clock.__save__ = function(clock) {
  if (! clock._realTime) throw new Error("Clock not serializable!");
  return {scale: clock.scale * 1e3, time: clock.now()};
};

/* Deserialize a clock */
Clock.__restore__ = function(clock) {
  return Clock.realTime(clock.scale, clock.time);
};

/* Serialize an object tree to JSON, storing type information */
function serialize(obj) {
  return JSON.stringify(obj, function(name, value) {
    /* Only transform object values */
    if (typeof value != "object" || Array.isArray(value)) return value;
    /* Get a meaningful constructor name */
    var cons = value.constructor.__sername__;
    if (! cons) cons = value.constructor.name;
    if (! cons) cons = Object.prototype.toString(value).slice(8, -1);
    if (cons == "Object") cons = undefined;
    /* Copy properties into new object, or let object serialize itself */
    var ret;
    if (value.constructor.__save__) {
      ret = value.constructor.__save__(value);
    } else {
      ret = {};
      for (var prop in value) ret[prop] = value[prop];
    }
    /* Add __type__ */
    ret.__type__ = cons;
    /* Done */
    return ret;
  });
}

/* Deserialize a JSON string into an object structure */
function deserialize(obj) {
  return JSON.parse(obj, function(name, value) {
    /* Ignore non-objects */
    if (typeof value != "object" || Array.isArray(value)) return value;
    /* Check for a __type__ */
    if (value.__type__) {
      /* Obtain type object */
      var type = window[value.__type__];
      if (type && type.__restore__) {
        /* Use restorer function */
        value = type.__restore__(value);
      } else if (type) {
        /* Assume an object is deserializable as-is */
        var newVal = Object.create(type.prototype);
        for (var k in value) if (! /^__.+__$/.test(k)) newVal[k] = value[k];
        value = newVal;
      } else {
        /* Nope */
        throw new Error("Object not deserializable (cannot find type): " +
                        JSON.stringify(value));
      }
    }
    return value;
  });
}
<commit_msg>Sanitize data to be serialized<commit_after>
/* Dasca, an idle game by @CylonicRaider (github.com/CylonicRaider/dasca)
 * Abstract engine for JS-based idle games */

'use strict';

/* Construct a new clock
 * source is a function that, when called, returns the current time; scale
 * and offset modify source's output in a linear fashion: the reading of
 * source is multiplied by scale and offset is added to that to obtain the
 * current time. If scale is undefined or null, it defaults to 1; if offset
 * is null, it is computed such that the clock starts counting from zero. */
function Clock(source, scale, offset) {
  if (scale == null) scale = 1.0;
  if (offset == null) offset = -source() * scale;
  this.source = source;
  this.scale = scale;
  this.offset = offset;
}

Clock.prototype = {
  /* Sample the current time */
  now: function() {
    return this.source() * this.scale + this.offset;
  },

  /* Construct a new clock from this one, applying the given transformation
   * The new clock derives its time from the same (!) source as this one,
   * but its scale and offset are modified to simulate a clock constructed
   * like
   *     new Clock(this, scale, offset);
   */
  derive: function(scale, offset) {
    if (scale == null) scale = 1.0;
    if (offset != null) offset = this.offset * scale + offset;
    var ret = new Clock(this.source, this.scale * scale, offset);
    if (this._realTime) ret._realTime = true;
    return ret;
  },

  /* Serialization boilerplate */
  constructor: Clock
};

/* Construct a clock that returns (optionally scaled) real time
 * The clock counts from zero */
Clock.realTime = function(scale, start) {
  if (scale == null) scale = 1.0;
  scale *= 1e-3;
  var offset = (start == null) ? null : start - performance.now() * scale;
  var ret = new Clock(performance.now.bind(performance), scale, offset);
  ret._realTime = true;
  return ret;
};

/* Seralize a clock */
Clock.__save__ = function(clock) {
  if (! clock._realTime) throw new Error("Clock not serializable!");
  return {scale: clock.scale * 1e3, time: clock.now()};
};

/* Deserialize a clock */
Clock.__restore__ = function(clock) {
  return Clock.realTime(clock.scale, clock.time);
};

/* Serialize an object tree to JSON, storing type information */
function serialize(obj) {
  return JSON.stringify(obj, function(name, value) {
    /* Fail verbosely */
    if (typeof value == "function")
      throw new Error("Cannot serialize function");
    /* Only transform object values */
    if (typeof value != "object" || Array.isArray(value)) return value;
    /* Get a meaningful constructor name */
    var cons = value.constructor.__sername__;
    if (! cons) cons = value.constructor.name;
    if (! cons) cons = Object.prototype.toString(value).slice(8, -1);
    if (cons == "Object") cons = undefined;
    /* Copy properties into new object, or let object serialize itself */
    var ret;
    if (value.constructor.__save__) {
      ret = value.constructor.__save__(value);
    } else {
      ret = {};
      for (var prop in value) ret[prop] = value[prop];
    }
    /* Add __type__ */
    ret.__type__ = cons;
    /* Done */
    return ret;
  });
}

/* Deserialize a JSON string into an object structure */
function deserialize(obj) {
  return JSON.parse(obj, function(name, value) {
    /* Ignore non-objects */
    if (typeof value != "object" || Array.isArray(value)) return value;
    /* Check for a __type__ */
    if (value.__type__) {
      /* Obtain type object */
      var type = window[value.__type__];
      if (type && type.__restore__) {
        /* Use restorer function */
        value = type.__restore__(value);
      } else if (type) {
        /* Assume an object is deserializable as-is */
        var newVal = Object.create(type.prototype);
        for (var k in value) if (! /^__.+__$/.test(k)) newVal[k] = value[k];
        value = newVal;
      } else {
        /* Nope */
        throw new Error("Object not deserializable (cannot find type): " +
                        JSON.stringify(value));
      }
    }
    return value;
  });
}
<|endoftext|>


<commit_before>import _arity from './internal/_arity';
import _concat from './internal/_concat';
import _curry2 from './internal/_curry2';

/**
 * `tryCatch` takes two functions, a `tryer` and a `catcher`. The returned
 * function evaluates the `tryer`; if it does not throw, it simply returns the
 * result. If the `tryer` *does* throw, the returned function evaluates the
 * `catcher` function and returns its result. Note that for effective
 * composition with this function, both the `tryer` and `catcher` functions
 * must return the same type of results.
 *
 * @func
 * @memberOf R
 * @since v0.20.0
 * @category Function
 * @sig (...x -> a) -> ((e, ...x) -> a) -> (...x -> a)
 * @param {Function} tryer The function that may throw.
 * @param {Function} catcher The function that will be evaluated if `tryer` throws.
 * @return {Function} A new function that will catch exceptions and send then to the catcher.
 * @example
 *
 *      R.tryCatch(R.prop('x'), R.F)({x: true}); //=> true
 *      R.tryCatch(JSON.parse, R.F)({});      //=> false
 */
var tryCatch = _curry2(function _tryCatch(tryer, catcher) {
  return _arity(tryer.length, function() {
    try {
      return tryer.apply(this, arguments);
    } catch (e) {
      return catcher.apply(this, _concat([e], arguments));
    }
  });
});
export default tryCatch;
<commit_msg>fix documentation on tryCatch method<commit_after>import _arity from './internal/_arity';
import _concat from './internal/_concat';
import _curry2 from './internal/_curry2';

/**
 * `tryCatch` takes two functions, a `tryer` and a `catcher`. The returned
 * function evaluates the `tryer`; if it does not throw, it simply returns the
 * result. If the `tryer` *does* throw, the returned function evaluates the
 * `catcher` function and returns its result. Note that for effective
 * composition with this function, both the `tryer` and `catcher` functions
 * must return the same type of results.
 *
 * @func
 * @memberOf R
 * @since v0.20.0
 * @category Function
 * @sig (...x -> a) -> ((e, ...x) -> a) -> (...x -> a)
 * @param {Function} tryer The function that may throw.
 * @param {Function} catcher The function that will be evaluated if `tryer` throws.
 * @return {Function} A new function that will catch exceptions and send then to the catcher.
 * @example
 *
 *      R.tryCatch(R.prop('x'), R.F)({x: true}); //=> true
 *      R.tryCatch(() => { throw 'foo'}, R.always('catched'))('bar') // => 'catched'
 *      R.tryCatch(R.times(R.identity), R.always([]))('s') // => []
 `` */
var tryCatch = _curry2(function _tryCatch(tryer, catcher) {
  return _arity(tryer.length, function() {
    try {
      return tryer.apply(this, arguments);
    } catch (e) {
      return catcher.apply(this, _concat([e], arguments));
    }
  });
});
export default tryCatch;
<|endoftext|>


<commit_before>import Screen from 'screen';
import Rect from 'rect';
import {GrayBrick, BlueBrick, RedBrick, YellowBrick, PurpleBrick, GreenBrick} from 'brick';

const canvas = document.querySelector('#screen');
const screen = Screen(canvas.getContext('2d'));

// screen.toggleSnap(true);
screen.size = {
	width: 224*2,
	height: 256*2
};

function createBricks(cols, rows) {
	const bricks = [];
	const colors = [GrayBrick, RedBrick, YellowBrick, BlueBrick, PurpleBrick, GreenBrick];
	for (let row = 0; row < rows; row++) {
		for (let col = 0; col < cols; col++) {
			bricks.push(colors[row]({x: col*2, y: row}, screen));
		}
	}
	return bricks;
}

const bricks = createBricks(13, 6);

function draw() {
	screen.save();

	screen.brush = '#222';
	screen.clear();

	screen.translate({x: (screen.width/14)/2, y: 4*(screen.width/14)/2});

	for (let brick of bricks) {
		brick.draw();
	}
	screen.restore();
	requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
<commit_msg>test ui<commit_after>import Screen from 'screen';
import Rect from 'rect';
import {GrayBrick, BlueBrick, RedBrick, YellowBrick, PurpleBrick, GreenBrick} from 'brick';
import ui from 'ui';

const canvas = document.querySelector('#screen');
const screen = Screen(canvas.getContext('2d'));

screen.size = {
	width: 224*2,
	height: 256*2
};

function createBricks(cols, rows) {
	const bricks = [];
	const colors = [GrayBrick, RedBrick, YellowBrick, BlueBrick, PurpleBrick, GreenBrick];
	for (let row = 0; row < rows; row++) {
		for (let col = 0; col < cols; col++) {
			bricks.push(colors[row]({x: col*2, y: row}, screen));
		}
	}
	return bricks;
}

ui.keyboard.on('direction-changed', direction => {
	console.log(`(${direction.x}, ${direction.y})`);
});

const bricks = createBricks(13, 6);

function draw() {
	screen.save();

	screen.brush = '#222';
	screen.clear();
	screen.translate({x: (screen.width/14)/2, y: 4*(screen.width/14)/2});

	for (let brick of bricks) {
		brick.draw();
	}
	screen.restore();
	requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
<|endoftext|>


<commit_before>lobby.transporter.module.create('transporter', function(thisModule) {

thisModule.addSlots(transporter.module, function(add) {

  add.method('name', function () { return this._name; }, {category: ['accessing']});

  add.method('toString', function () { return this.name(); }, {category: ['printing']});

  add.method('objectsThatMightContainSlotsInMe', function () {
    return lobby.transporter.module.cache[this.name()];
  }, {category: ['keeping track of changes']});

  add.method('mirrorsInOrderForFilingOut', function (f) {
    var alreadySeen = bloodyHashTable.copyRemoveAll(); // aaa - remember that mirrors don't hash well; this'll be slow for big modules unless we fix that
    this.objectsThatMightContainSlotsInMe().each(function(obj) {
      var mir = reflect(obj);
      if (! alreadySeen.containsKey(mir)) {
        alreadySeen.put(mir, mir);
      }
    }.bind(this));
    return alreadySeen.values().sort(function(a, b) { var an = a.name(); var bn = b.name(); return an === bn ? 0 : an < bn ? -1 : 1; });
  }, {category: ['transporting']});

  add.method('fileOut', function () {
    var buffer = stringBuffer.create("lobby.transporter.module.create('").append(this.name()).append("', function(thisModule) {\n\n\n");
    this.fileOutSlots(buffer);
    buffer.append("});");

    var doc = buffer.toString();

    // aaa - hack because I haven't managed to get WebDAV working on adamspitz.com yet
    if (URL.source.fullPath().startsWith("http://adamspitz.com")) {
      var uploadScriptURL = "http://adamspitz.com/cgi-bin/savefile.cgi";
      //alert(uploadScriptURL);
      new Ajax.Request(uploadScriptURL, {
        method: 'post',
        contentType: 'text/plain',
        parameters: {fileName: this.name() + ".js", fileContents: doc},
        asynchronous: true,
        onSuccess:   function(transport) { var urlToDownload = transport.responseText; window.open(urlToDownload, 'Download'); }.bind(this),
        onFailure:   function(         ) {alert("Failure. :(");}.bind(this),
        onException: function(r,      e) {alert("Exception. :(");}.bind(this),
      });
    } else {
      var url = this.urlForModuleName(this.name());
      var status = new Resource(Record.newPlainInstance({URL: url})).store(doc, true).getStatus();
      if (! status.isSuccess()) {
        throw "failed to file out " + this + ", status is " + status.code();
      }
    }
  }, {category: ['transporting']});

  add.method('fileOutSlots', function (buffer) {
    var mirs = this.mirrorsInOrderForFilingOut();
    mirs.each(function(mir) {
      buffer.append("thisModule.addSlots(").append(mir.creatorSlotChainExpression()).append(", function(add) {\n\n");
      mir.eachSlot(function(s) {
        if (s.module && s.module() === this) {
          s.fileOutTo(buffer);
        }
      }.bind(this));
      buffer.append("});\n\n\n");
    }.bind(this));
  }, {category: ['transporting']});

  add.method('urlForModuleDirectory', function () {
    return URL.source.getDirectory().withRelativePath("../jsdemo/");
  }, {category: ['saving to WebDAV']});

  add.method('urlForModuleName', function (name) {
    return this.urlForModuleDirectory().withFilename(name + ".js");
  }, {category: ['saving to WebDAV']});

  add.method('fileIn', function (name) {
    var url = this.urlForModuleName(name);
    var code = FileDirectory.getContent(url);
    eval(code);
  }, {category: ['transporting']});

  add.method('eachModule', function (f) {
    reflect(lobby.modules).eachNormalSlot(function(s) { f(s.contents().reflectee()); });
  }, {category: ['iterating']});

  add.method('existingOneNamed', function (n) {
    return lobby.modules[n];
  }, {category: ['accessing modules']});

});

});
<commit_msg>Fixed the script.<commit_after>lobby.transporter.module.create('transporter', function(thisModule) {

thisModule.addSlots(transporter.module, function(add) {

  add.method('name', function () { return this._name; }, {category: ['accessing']});

  add.method('toString', function () { return this.name(); }, {category: ['printing']});

  add.method('objectsThatMightContainSlotsInMe', function () {
    return lobby.transporter.module.cache[this.name()];
  }, {category: ['keeping track of changes']});

  add.method('mirrorsInOrderForFilingOut', function (f) {
    var alreadySeen = bloodyHashTable.copyRemoveAll(); // aaa - remember that mirrors don't hash well; this'll be slow for big modules unless we fix that
    this.objectsThatMightContainSlotsInMe().each(function(obj) {
      var mir = reflect(obj);
      if (! alreadySeen.containsKey(mir)) {
        alreadySeen.put(mir, mir);
      }
    }.bind(this));
    return alreadySeen.values().sort(function(a, b) { var an = a.name(); var bn = b.name(); return an === bn ? 0 : an < bn ? -1 : 1; });
  }, {category: ['transporting']});

  add.method('fileOut', function () {
    var buffer = stringBuffer.create("lobby.transporter.module.create('").append(this.name()).append("', function(thisModule) {\n\n\n");
    this.fileOutSlots(buffer);
    buffer.append("});");

    var doc = buffer.toString();

    // aaa - hack because I haven't managed to get WebDAV working on adamspitz.com yet
    if (URL.source.hostname.include("adamspitz.com")) {
      var uploadScriptURL = "http://adamspitz.com/cgi-bin/savefile.cgi";
      new Ajax.Request(uploadScriptURL, {
        method: 'post',
        contentType: 'text/plain',
        parameters: {fileName: this.name() + ".js", fileContents: doc},
        asynchronous: true,
        onSuccess:   function(transport) { var urlToDownload = transport.responseText; window.open(urlToDownload, 'Download'); }.bind(this),
        onFailure:   function(         ) {alert("Failure. :(");}.bind(this),
        onException: function(r,      e) {alert("Exception. :(");}.bind(this),
      });
    } else {
      var url = this.urlForModuleName(this.name());
      var status = new Resource(Record.newPlainInstance({URL: url})).store(doc, true).getStatus();
      if (! status.isSuccess()) {
        throw "failed to file out " + this + ", status is " + status.code();
      }
    }
  }, {category: ['transporting']});

  add.method('fileOutSlots', function (buffer) {
    var mirs = this.mirrorsInOrderForFilingOut();
    mirs.each(function(mir) {
      buffer.append("thisModule.addSlots(").append(mir.creatorSlotChainExpression()).append(", function(add) {\n\n");
      mir.eachSlot(function(s) {
        if (s.module && s.module() === this) {
          s.fileOutTo(buffer);
        }
      }.bind(this));
      buffer.append("});\n\n\n");
    }.bind(this));
  }, {category: ['transporting']});

  add.method('urlForModuleDirectory', function () {
    return URL.source.getDirectory().withRelativePath("../jsdemo/");
  }, {category: ['saving to WebDAV']});

  add.method('urlForModuleName', function (name) {
    return this.urlForModuleDirectory().withFilename(name + ".js");
  }, {category: ['saving to WebDAV']});

  add.method('fileIn', function (name) {
    var url = this.urlForModuleName(name);
    var code = FileDirectory.getContent(url);
    eval(code);
  }, {category: ['transporting']});

  add.method('eachModule', function (f) {
    reflect(lobby.modules).eachNormalSlot(function(s) { f(s.contents().reflectee()); });
  }, {category: ['iterating']});

  add.method('existingOneNamed', function (n) {
    return lobby.modules[n];
  }, {category: ['accessing modules']});

});

});
<|endoftext|>


<commit_before>angular.module('myApp')
  .service('EventService', ['$http', '$window', '$q', 'util', function($http, $window, $q, util) {
    var errorHandler = function(err) {
      console.error('Failed to save event ', err);
    };

    this.postSave = function(requestData, doRedirect) { // TODO redirect to different urls on edit and create
      console.log("req data: ", requestData);
      $http.post('/event/save', requestData).success(function(res){
        console.log('Event is saved successfully ', res);
        if (_.isUndefined(doRedirect)) {
          doRedirect = true;
        }
        if (doRedirect === true) {
          var redirectUrl = '/event/' + res.event._id;
          console.log('Redirecting to ', redirectUrl);
          $window.location = redirectUrl;
        }
      }).error(errorHandler);
    };
    /**
     * @param opts
     * @param opts.eventId
     * @param opts.imageId
     * @param cb
     */
    this.postRemoveImage = function(opts, cb) {
      $http.post('/event/' + opts.eventId + '/rm-image/' + opts.imageId).success(cb).error(errorHandler);
    };

    this.loadFriendsStream = function(currentUser, cb) {
      var deferred = $q.defer();
      if (currentUser) {
        var friends = currentUser.profile.friends;
        if (friends) {
          var fetchFriendsEvents = _.map(friends, function(friend) {
            return $http.get(util.apiUrl('/events/find'), {params: {participantId: friend._id}}).then(function(res) {
              return {events: res.data, friend: friend};
            });
          });
          $q.all(fetchFriendsEvents).then(function(ress) {
            // make {[events], friend} => {event: [friends]}
            var r = _.map(ress, function(res) {
              var r = _.map(res.events, function(event) {
                var friends = _.filter(_.map(ress, function(res) {
                  return _.contains(res.events, event) ? res.friend : undefined;
                }), function(friend) { return friend; });
                return {event: event, friends: friends};
              });
              return r;
            });
            r = _.reduce(_.flatten(r), function(memo, iter) {
              var existing = _.find(memo, function (v) {
                return v.event._id == iter.event._id
              });
              if (existing) {
                existing.friends = existing.friends.concat(iter.friends);
              } else {
                memo.push(iter);
              }
              return memo;
            }, []);
            deferred.resolve(r);
          }, function(err) { deferred.reject(err); });
        }
      } else {
        deferred.resolve();
      }
      return deferred.promise;
    };
  }]);<commit_msg>Refactor "event to friends" grouping algo<commit_after>'use strict';

angular.module('myApp')
  .service('EventService', ['$http', '$window', '$q', 'util', function($http, $window, $q, util) {
    var errorHandler = function(err) {
      console.error('Failed to save event ', err);
    };

    this.postSave = function(requestData, doRedirect) { // TODO redirect to different urls on edit and create
      console.log("req data: ", requestData);
      $http.post('/event/save', requestData).success(function(res){
        console.log('Event is saved successfully ', res);
        if (_.isUndefined(doRedirect)) {
          doRedirect = true;
        }
        if (doRedirect === true) {
          var redirectUrl = '/event/' + res.event._id;
          console.log('Redirecting to ', redirectUrl);
          $window.location = redirectUrl;
        }
      }).error(errorHandler);
    };

    /**
     * @param opts
     * @param opts.eventId
     * @param opts.imageId
     * @param cb
     */
    this.postRemoveImage = function(opts, cb) {
      $http.post('/event/' + opts.eventId + '/rm-image/' + opts.imageId).success(cb).error(errorHandler);
    };

    this.loadFriendsStream = function(currentUser, cb) {
      var deferred = $q.defer();
      if (currentUser) {
        var friends = currentUser.profile.friends;
        if (friends) {
          var fetchFriendsEvents = _.map(friends, function(friend) {
            return $http.get(util.apiUrl('/events/find'), {params: {participantId: friend._id}}).then(function(res) {
              return {events: res.data, friend: friend};
            });
          });
          $q.all(fetchFriendsEvents).then(function(ress) {
            // Transform structure: {[events], friend} => {event, [friends]}
            var eventIds = [];
            var eventIdToFriendsMap = {};
            _.each(ress, function(res) {
              _.each(res.events, function(event) {
                var eid = event._id;
                if (_.isUndefined(eventIdToFriendsMap[eid])) {
                  eventIds.push(eid);
                  eventIdToFriendsMap[eid] = { event: event, friends: [] };
                }
                eventIdToFriendsMap[eid].friends.push(res.friend);
              });
            });
            var r = _.map(eventIds, function(eid) {
              return eventIdToFriendsMap[eid];
            });
            deferred.resolve(r);
          }, function(err) { deferred.reject(err); });
        }
      } else {
        deferred.resolve();
      }
      return deferred.promise;
    };
  }]);<|endoftext|>


<commit_before>define(function(require) {

    'use strict';

    var _               = require('underscore')
      , Base            = require('app/views/Base')
      , Comments        = require('app/collections/Comments')
      , CommentItemView = require('app/views/Topic/CommentItem')
      , Post            = require('app/models/Post')
      , log             = require('bows.min')('Views:Topic:CommentList')
      require('jquery.scrollparent')

    return Base.extend({

      template: _.template(require('text!tpl/Topic/CommentList.html')),

      requiresLogin: true,

      className: 'posts',

      tagName: 'section',

      events: {
        'click .js-showMore': 'loadMoreComments'
      },

      initialize: function(options) {
        _.bindAll('render')
        this.options = options
        this.router = options.router
        this.collection = new Comments(null, {
          node: this.options.node,
          id: this.options.id,
          after: options.highlightPost
        })
        if (this.options.highlightPost) {
          this.collection.once('loaded:comments', this.loadHighlightedPost, this)
        }
        this.loadComments()
      },

      loadHighlightedPost: function() {
        var post = new Post({
          id: this.options.highlightPost,
          node: this.options.node
        })
        post.once('loaded:post', function() {
          this.collection.add(post, { silent: true })
          this.addComments(post, true)
          this.collection.lastItemId
        }, this)
        post.sync()
      },

      loadComments: function() {
        this.collection.on('all', function(event) { log('TopicList', event) })
        this.collection.on('loaded:comments', this.addComments, this)

        /* focus on newComment has to wait for this */
        this.collection.once('loaded:comments', function(){
          this.trigger('loaded:comments')
        }, this)

        this.collection.on('error', function() {
          this.renderComments()
          this.enableLoadMoreButton()
          this.showError('Oh no! Could not load the comments')
        }, this)

        if (0 !== this.collection.length) {
          return this.once('render', this.renderComments, this)
        }
        this.collection.on('add', this.pushedItem, this)
        this.collection.sync()
      },

      pushedItem: function(model) {
        this.addComments(model)
      },

      addComments: function(length, prepend) {
        var newComments =  null
        var addMethod = 'prepend'
        if (length instanceof Backbone.Model) {
          newComments = [ length ]
          if (!prepend) {
            addMethod = 'append'
          }
        } else {
          newComments = this.collection.models.slice(0, length)
          log(length + ' new comments')
        }
        var comments = document.createDocumentFragment()
        var self = this
        var scrollParent = this.$el.scrollParent()

        var scrollHeight = (scrollParent.get(0) == document ? $('body') : scrollParent).prop('scrollHeight')
        var viewHeight = (scrollParent.get(0) == document ? $(window) : scrollParent).outerHeight()
        var isScrolledToBottom = Math.abs(scrollHeight - scrollParent.scrollTop() - viewHeight) < 5

        newComments.forEach(function(newComment) {
          var comment = new CommentItemView({
            model: newComment,
            router: self.router
          })
          comments.appendChild(comment.render().el)
        }, this)

        if (addMethod == 'prepend') {
          this.$el.find('.js-showMore').after(comments)
        } else {
          this.$el.append(comments)
        }

        if (this.collection.allItemsLoaded()) {
          return this.$el.find('.js-showMore').remove()
        }

        this.isFetchingComments = false
        this.$el.find('.js-showMore').removeClass('is-loading')

        if(isScrolledToBottom){
          scrollParent.scrollTop(999999)
        }
      },

      loadMoreComments: function() {
        if (this.isFetchingComments) {
          return
        }

        this.isFetchingComments = true
        this.$el.find('.js-showMoreHolder').addClass('is-loading')
        this.collection.sync()
      }
    })

})
<commit_msg>fix comment loading-spinner<commit_after>define(function(require) {

    'use strict';

    var _               = require('underscore')
      , Base            = require('app/views/Base')
      , Comments        = require('app/collections/Comments')
      , CommentItemView = require('app/views/Topic/CommentItem')
      , Post            = require('app/models/Post')
      , log             = require('bows.min')('Views:Topic:CommentList')
      require('jquery.scrollparent')

    return Base.extend({

      template: _.template(require('text!tpl/Topic/CommentList.html')),

      requiresLogin: true,

      className: 'posts',

      tagName: 'section',

      events: {
        'click .js-showMore': 'loadMoreComments'
      },

      initialize: function(options) {
        _.bindAll('render')
        this.options = options
        this.router = options.router
        this.collection = new Comments(null, {
          node: this.options.node,
          id: this.options.id,
          after: options.highlightPost
        })
        if (this.options.highlightPost) {
          this.collection.once('loaded:comments', this.loadHighlightedPost, this)
        }
        this.loadComments()
      },

      loadHighlightedPost: function() {
        var post = new Post({
          id: this.options.highlightPost,
          node: this.options.node
        })
        post.once('loaded:post', function() {
          this.collection.add(post, { silent: true })
          this.addComments(post, true)
          this.collection.lastItemId
        }, this)
        post.sync()
      },

      loadComments: function() {
        this.collection.on('all', function(event) { log('TopicList', event) })
        this.collection.on('loaded:comments', this.addComments, this)

        /* focus on newComment has to wait for this */
        this.collection.once('loaded:comments', function(){
          this.trigger('loaded:comments')
        }, this)

        this.collection.on('error', function() {
          this.renderComments()
          this.enableLoadMoreButton()
          this.showError('Oh no! Could not load the comments')
        }, this)

        if (0 !== this.collection.length) {
          return this.once('render', this.renderComments, this)
        }
        this.collection.on('add', this.pushedItem, this)
        this.collection.sync()
      },

      pushedItem: function(model) {
        this.addComments(model)
      },

      addComments: function(length, prepend) {
        var newComments =  null
        var addMethod = 'prepend'
        if (length instanceof Backbone.Model) {
          newComments = [ length ]
          if (!prepend) {
            addMethod = 'append'
          }
        } else {
          newComments = this.collection.models.slice(0, length)
          log(length + ' new comments')
        }
        var comments = document.createDocumentFragment()
        var self = this
        var scrollParent = this.$el.scrollParent()

        var scrollHeight = (scrollParent.get(0) == document ? $('body') : scrollParent).prop('scrollHeight')
        var viewHeight = (scrollParent.get(0) == document ? $(window) : scrollParent).outerHeight()
        var isScrolledToBottom = Math.abs(scrollHeight - scrollParent.scrollTop() - viewHeight) < 5

        newComments.forEach(function(newComment) {
          var comment = new CommentItemView({
            model: newComment,
            router: self.router
          })
          comments.appendChild(comment.render().el)
        }, this)

        if (addMethod == 'prepend') {
          this.$el.find('.js-showMore').after(comments)
        } else {
          this.$el.append(comments)
        }

        if (this.collection.allItemsLoaded()) {
          return this.$el.find('.js-showMore').remove()
        }

        this.isFetchingComments = false
        this.$el.find('.js-showMore').removeClass('is-loading')

        if(isScrolledToBottom){
          scrollParent.scrollTop(999999)
        }
      },

      loadMoreComments: function() {
        if (this.isFetchingComments) {
          return
        }

        this.isFetchingComments = true
        this.$el.find('.js-showMore').addClass('is-loading')
        this.collection.sync()
      }
    })

})
<|endoftext|>