<commit_before>var defaults = [
  'color',
  'emoji'
];

var color = require('./color.js');

function trigger(command, api, message) {
  var threadID = message.threadID;
  var option = command.substring(0, command.indexOf(' '));
  var setting = command.substring(command.indexOf(' ') + 1);
  if (option == '') {
    if (command == 'list') {
      var msg = {
        body: 'list defaults'
      };
      api.sendMessage(msg, threadID);
    } else {
      var msg = {
        body: 'pls use format "defaults <option> <setting>" or "defaults list"'
      };
      api.sendMessage(msg, threadID);
    }
  } else if (defaults.indexOf(option) != -1) {
    if (option == 'color') {
      color.trigger(setting, api, message);
    }
  } else {
    var msg = {
      body: 'not a valid default'
    };
    api.sendMessage(msg, threadID);
  }
}

module.exports = {
  trigger: trigger
}<commit_msg>Use firebase functionality in defaults module<commit_after>var color = require('./color.js');

var defaults = {
  color: {
    module: color
  }
};

var firebase = require('../firebase.js')

function trigger(command, api, message) {
  var threadID = message.threadID;
  var option = command.substring(0, command.indexOf(' '));
  var setting = command.substring(command.indexOf(' ') + 1);
  if (option == '') {
    if (command == 'list') {
      var msg = {
        body: 'list defaults'
      };
      api.sendMessage(msg, threadID);
    } else {
      var msg = {
        body: 'pls use format "defaults <option> <setting>" or "defaults list"'
      };
      api.sendMessage(msg, threadID);
    }
  } else if (option in defaults) {
    for (var key in defaults) {
      if (key == option) {
        defaults[key].module.trigger(setting, api, message);
        firebase(function(db) {
          var threadRef = db.ref(threadID);
          threadRef.set({
            option: setting
          });
        });
        return;
      }
    }
  } else {
    var msg = {
      body: 'not a valid default'
    };
    api.sendMessage(msg, threadID);
  }
}

module.exports = {
  trigger: trigger
}<|endoftext|>


<commit_before>import {Observable} from "rxjs";
import {PING, PLAY, PONG, STOP} from "./../constant/actions";
import * as tableStatus from "./../constant/tableStatus";
import {ROUND_DURATION} from "./../constant/game";

export function play() {
    console.log('Action<Play>()');
    return {
        type: PLAY,
    }
}

export function stop() {
    console.log('Action<Stop>()');
    return {
        type: STOP,
    }
}

export const playEpic = (action$, {getState}) =>
    action$.ofType(PLAY)
        .switchMap(() => {
            console.log('Epic<Play>.startGame()');

            return Observable.interval(ROUND_DURATION)
                .switchMap(() =>
                    getState().table.status === tableStatus.PING
                        ? Observable.of(1).map(pong)
                        : Observable.of(1).map(ping)
                );
        });

function ping() {
    console.log('Action<Ping>()');
    return {
        type: PING,
    }
}

function pong() {
    console.log('Action<Pong>()');
    return {
        type: PONG,
    }
}
<commit_msg>PingPong - stoping ping-ponging<commit_after>import {Observable} from "rxjs";
import {PING, PLAY, PONG, STOP} from "./../constant/actions";
import * as tableStatus from "./../constant/tableStatus";
import {ROUND_DURATION} from "./../constant/game";

export function play() {
    console.log('Action<Play>()');
    return {
        type: PLAY,
    }
}

export function stop() {
    console.log('Action<Stop>()');
    return {
        type: STOP,
    }
}

export const playEpic = (action$, {getState}) =>
    action$.ofType(PLAY)
        .switchMap(() => {
            console.log('Epic<Play>.startGame()');

            return Observable.interval(ROUND_DURATION)
                .switchMap(() =>
                    getState().table.status === tableStatus.PING
                        ? Observable.of(1).map(pong)
                        : Observable.of(1).map(ping)
                )
                .takeUntil(action$.ofType(STOP));
        });

function ping() {
    console.log('Action<Ping>()');
    return {
        type: PING,
    }
}

function pong() {
    console.log('Action<Pong>()');
    return {
        type: PONG,
    }
}
<|endoftext|>


<commit_before>/*
Name:           piwik
Description:    Access a Piwik API or track hits with node.js
Author:         Franklin van de Meent (http://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-piwik
Feedback:       https://github.com/fvdm/nodejs-piwik/issues
License:        Unlicense / Public Domain (see UNLICENSE file)
                (https://github.com/fvdm/nodejs-piwik/raw/develop/UNLICENSE)
*/

var urltool = require ('url');
var querystring = require ('querystring');
var http = null;

var app = {settings: {}};

// SETUP basics
app.setup = function (baseURL, token) {
  var url = urltool.parse (baseURL, true);

  if (url.protocol === 'https:') {
    http = require ('https');
    app.settings.apiprotocol = 'https:';
    app.settings.apiport = url.port || 443;
  } else {
    http = require ('http');
    app.settings.apiprotocol = 'http:';
    app.settings.apiport = url.port || 80;
  }

  // token in baseURL?
  if (url.query && url.query.token_auth) {
    app.settings.token = url.query.token_auth;
  }

  // override with custom token, if any
  if (token) {
    app.settings.token = token;
  }

  app.settings.apihost = url.hostname;
  app.settings.apipath = url.pathname;

  return app;
};

// API call
app.api = function (vars, cb) {
  vars = typeof vars === 'object' ? vars : {};
  vars.module = 'API';
  vars.format = 'JSON';
  vars.token_auth = app.settings.token;
  talk ({method: 'GET', query: vars}, cb);
  return app;
};

// Track
app.track = function (vars, cb) {
  var bulk = {requests: []};
  if (app.settings.token) { bulk.token_auth = app.settings.token; }

  if (vars instanceof Array && vars[0] instanceof Object) {
    // array with objects
    for (var i = 0; i < vars.length; i++) {
      var keys = Object.keys (vars [i]);
      for (var k = 0; k < keys.length; k++) {
        var val = vars [i] [keys [k]];
        vars [i] [keys [k]] = typeof val === 'object' ? JSON.stringify (val) : val;
      }
      vars [i].rec = 1;
      vars [i].apiv = 1;
      vars [i] = '?'+ querystring.stringify (vars [i]);
      bulk.requests.push (vars [i]);
      delete vars [i];
    }
  } else if (vars instanceof Object) {
    // object
    keys = Object.keys (vars);
    var i, val;
    for (i = 0; i < keys.length; i++) {
      val = vars [keys [i]];
      vars [keys [i]] = typeof val === 'object' ? JSON.stringify (val) : val;
    }
    vars.rec = 1;
    vars.apiv = 1;
    bulk.requests.push ('?'+ querystring.stringify (vars) );
  }

  talk(
    {
      method: 'POST',
      path: 'piwik.php',
      body: JSON.stringify (bulk)
    },
    function (err, data) {
      if (err) { return cb (err); }
      if (data.status === 'success') {
        cb (null, data);
      } else {
        var error = new Error ('track failed');
        error.data = data;
        cb (error);
      }
    }
  );

  return app;
};

// HTTP GET
function talk (props, cb) {
  // prevent multiple callbacks
  var complete = false;
  function callback (err, res) {
    if (!complete) {
      complete = true;
      cb (err, res || null);
    }
  }

  // build request
  var query = '';
  if (props.query instanceof Object) {
    var keys = Object.keys (props.query);
    for (var i = 0; i < keys.length; i++) {
      var key = keys [i];
      if (typeof props.query [key] === 'object') {
        props.query [key] = JSON.stringify (props.query [key]);
      }
    }
    query = '?'+ querystring.stringify (props.query);
  }

  var options = {
    protocol: app.settings.apiprotocol,
    host: app.settings.apihost,
    port: app.settings.apiport,
    path: app.settings.apipath + (props.path || '') + query,
    method: props.method || 'GET',
    headers: {}
  };

  if (props.method === 'POST' && typeof props.body === 'string') {
    options.headers ['Content-Type'] = 'application/json';
    options.headers ['Content-Length'] = props.body.length;
  }

  var request = http.request (options);

  // response
  request.on ('response', function (response) {
    var data = [];
    var size = 0;

    response.on ('close', function () {
      callback (new Error ('request dropped'));
    });

    response.on ('data', function (chunk) {
      data.push (chunk);
      size += chunk.length;
    });

    response.on ('end', function () {
      data = Buffer.concat (data, size) .toString () .trim ();

      if (response.statusCode >= 300) {
        var error = new Error ('http error');
        error.code = response.statusCode;
        error.body = data;
        callback (error);
        return;
      }

      try {
        data = JSON.parse (data);

        if (data.result && data.result === 'error') {
          error = new Error ('api error');
          error.text = data.message;
          callback (error);
          return;
        }

        callback (null, data);
      }
      catch (e) {
        var error = new Error ('response invalid');
        error.code = response.statusCode;
        error.body = data;
        callback (error);
      }
    });
  });

  // client error
  request.on ('error', function (error) {
    var err = new Error ('request failed');
    err.error = error;
    callback (err);
  });

  // run it
  request.end (props.body || null);
}

// module
module.exports = app;
<commit_msg>JSHint out of scope & already defined (#9)<commit_after>/*
Name:           piwik
Description:    Access a Piwik API or track hits with node.js
Author:         Franklin van de Meent (http://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-piwik
Feedback:       https://github.com/fvdm/nodejs-piwik/issues
License:        Unlicense / Public Domain (see UNLICENSE file)
                (https://github.com/fvdm/nodejs-piwik/raw/develop/UNLICENSE)
*/

var urltool = require ('url');
var querystring = require ('querystring');
var http = null;

var app = {settings: {}};

// SETUP basics
app.setup = function (baseURL, token) {
  var url = urltool.parse (baseURL, true);

  if (url.protocol === 'https:') {
    http = require ('https');
    app.settings.apiprotocol = 'https:';
    app.settings.apiport = url.port || 443;
  } else {
    http = require ('http');
    app.settings.apiprotocol = 'http:';
    app.settings.apiport = url.port || 80;
  }

  // token in baseURL?
  if (url.query && url.query.token_auth) {
    app.settings.token = url.query.token_auth;
  }

  // override with custom token, if any
  if (token) {
    app.settings.token = token;
  }

  app.settings.apihost = url.hostname;
  app.settings.apipath = url.pathname;

  return app;
};

// API call
app.api = function (vars, cb) {
  vars = typeof vars === 'object' ? vars : {};
  vars.module = 'API';
  vars.format = 'JSON';
  vars.token_auth = app.settings.token;
  talk ({method: 'GET', query: vars}, cb);
  return app;
};

// Track
app.track = function (vars, cb) {
  var bulk = {requests: []};
  var i, k, val;
  if (app.settings.token) { bulk.token_auth = app.settings.token; }

  if (vars instanceof Array && vars[0] instanceof Object) {
    // array with objects
    for (i = 0; i < vars.length; i++) {
      var keys = Object.keys (vars [i]);
      for (k = 0; k < keys.length; k++) {
        val = vars [i] [keys [k]];
        vars [i] [keys [k]] = typeof val === 'object' ? JSON.stringify (val) : val;
      }
      vars [i].rec = 1;
      vars [i].apiv = 1;
      vars [i] = '?'+ querystring.stringify (vars [i]);
      bulk.requests.push (vars [i]);
      delete vars [i];
    }
  } else if (vars instanceof Object) {
    // object
    var keys = Object.keys (vars);
    for (i = 0; i < keys.length; i++) {
      val = vars [keys [i]];
      vars [keys [i]] = typeof val === 'object' ? JSON.stringify (val) : val;
    }
    vars.rec = 1;
    vars.apiv = 1;
    bulk.requests.push ('?'+ querystring.stringify (vars) );
  }

  talk(
    {
      method: 'POST',
      path: 'piwik.php',
      body: JSON.stringify (bulk)
    },
    function (err, data) {
      if (err) { return cb (err); }
      if (data.status === 'success') {
        cb (null, data);
      } else {
        var error = new Error ('track failed');
        error.data = data;
        cb (error);
      }
    }
  );

  return app;
};

// HTTP GET
function talk (props, cb) {
  // prevent multiple callbacks
  var complete = false;
  function callback (err, res) {
    if (!complete) {
      complete = true;
      cb (err, res || null);
    }
  }

  // build request
  var query = '';
  if (props.query instanceof Object) {
    var keys = Object.keys (props.query);
    for (var i = 0; i < keys.length; i++) {
      var key = keys [i];
      if (typeof props.query [key] === 'object') {
        props.query [key] = JSON.stringify (props.query [key]);
      }
    }
    query = '?'+ querystring.stringify (props.query);
  }

  var options = {
    protocol: app.settings.apiprotocol,
    host: app.settings.apihost,
    port: app.settings.apiport,
    path: app.settings.apipath + (props.path || '') + query,
    method: props.method || 'GET',
    headers: {}
  };

  if (props.method === 'POST' && typeof props.body === 'string') {
    options.headers ['Content-Type'] = 'application/json';
    options.headers ['Content-Length'] = props.body.length;
  }

  var request = http.request (options);

  // response
  request.on ('response', function (response) {
    var data = [];
    var size = 0;

    response.on ('close', function () {
      callback (new Error ('request dropped'));
    });

    response.on ('data', function (chunk) {
      data.push (chunk);
      size += chunk.length;
    });

    response.on ('end', function () {
      var error = null;
      data = Buffer.concat (data, size) .toString () .trim ();

      if (response.statusCode >= 300) {
        error = new Error ('http error');
        error.code = response.statusCode;
        error.body = data;
        return;
      }

      try {
        data = JSON.parse (data);
        if (data.result && data.result === 'error') {
          error = new Error ('api error');
          error.text = data.message;
          return;
        }
      }
      catch (e) {
        error = new Error ('response invalid');
        error.code = response.statusCode;
        error.body = data;
      }

      callback (error, !error ? data : null);
    });
  });

  // client error
  request.on ('error', function (error) {
    var err = new Error ('request failed');
    err.error = error;
    callback (err);
  });

  // run it
  request.end (props.body || null);
}

// module
module.exports = app;
<|endoftext|>


<commit_before><commit_msg>Fixed resource log message.<commit_after><|endoftext|>


<commit_before>/**
 * This plugin will be used to transform Diva into a layering tool which will be used to provide
 * the ground truth data for the machine learning algorithm
 * that classifies and isolates the different components of old manuscripts and scores.
 *
 * {string} pluginName - Added to the class prototype. Defines the name for the plugin.
 *
 **/
export default class PixelPlugin
{
    constructor (core)
    {
        this.core = core;
        this.drawHighlights();
    }

    // Is called every time visible tiles are loaded to draw highlights on top of them
    drawHighlights()
    {
        let core = this.core;

        Diva.Events.subscribe('VisibleTilesDidLoad', function (pageIndex, zoomLevel)
        {
            let renderer = core.getSettings().renderer;
            let scaleRatio = Math.pow(2,zoomLevel);
            const viewportPaddingX = Math.max(0, (renderer._viewport.width - renderer.layout.dimensions.width) / 2);
            const viewportPaddingY = Math.max(0, (renderer._viewport.height - renderer.layout.dimensions.height) / 2);

            // Setup the rectangle to draw (These will be passed in an array afterwards)
            // The following absolute values are experimental values to highlight the square on the first page of Salzinnes, CDN-Hsmu M2149.L4
            var absoluteRectWidth = 24;
            var absoluteRectHeight = 24;
            var absoluteRectOriginX = 23;
            var absoluteRectOriginY = 42;

            // The relative values are used to scale the highlights according to the zoom level on the page itself
            var relativeRectWidth = absoluteRectWidth * scaleRatio;
            var relativeRectHeight = absoluteRectHeight * scaleRatio;
            var relativeRectOriginX = absoluteRectOriginX * scaleRatio;
            var relativeRectOriginY = absoluteRectOriginY * scaleRatio;

            // This indicates the page on top of which the highlights are supposed to be drawn
            var highlightPageIndex = 0;

            if (pageIndex === highlightPageIndex){
                // Calculates where the highlights should be drawn as a function of the whole webpage coordinates
                // (to make it look like it is on top of a page in Diva)
                var highlightXOffset = renderer._getImageOffset(pageIndex).left - renderer._viewport.left + viewportPaddingX + relativeRectOriginX;
                var highlightYOffset = renderer._getImageOffset(pageIndex).top - renderer._viewport.top + viewportPaddingY + relativeRectOriginY;

                //Draw the rectangle
                renderer._ctx.fillStyle = "rgba(255, 255, 0, 0.25)";
                renderer._ctx.fillRect(highlightXOffset, highlightYOffset,relativeRectWidth,relativeRectHeight);
            }
        });
    }
}

PixelPlugin.prototype.pluginName = "pixel";

/**
 * Make this plugin available in the global context
 * as part of the 'Diva' namespace.
 **/
(function (global)
{
    global.Diva.PixelPlugin = PixelPlugin;
})(window);
<commit_msg>Created svg icon that activates the pixel plugin on click<commit_after>/**
 * This plugin will be used to transform Diva into a layering tool which will be used to provide
 * the ground truth data for the machine learning algorithm
 * that classifies and isolates the different components of old manuscripts and scores.
 *
 * {string} pluginName - Added to the class prototype. Defines the name for the plugin.
 *
 * @method drawHighlights - Used to highlight pages after the tiles are visible
 *
 *
 **/
export default class PixelPlugin
{
    constructor (core)
    {
        this.core = core;
        this.pageToolsIcon = this.createIcon();
    }

    // Is called every time visible tiles are loaded to draw highlights on top of them
    drawHighlights()
    {
        //FIXME
        let core = this.core;

        Diva.Events.subscribe('VisibleTilesDidLoad', function (pageIndex, zoomLevel)
        {
            let renderer = core.getSettings().renderer;
            let scaleRatio = Math.pow(2,zoomLevel);
            const viewportPaddingX = Math.max(0, (renderer._viewport.width - renderer.layout.dimensions.width) / 2);
            const viewportPaddingY = Math.max(0, (renderer._viewport.height - renderer.layout.dimensions.height) / 2);

            // Setup the rectangle to draw (These will be passed in an array afterwards)
            // The following absolute values are experimental values to highlight the square on the first page of Salzinnes, CDN-Hsmu M2149.L4
            var absoluteRectWidth = 24;
            var absoluteRectHeight = 24;
            var absoluteRectOriginX = 23;
            var absoluteRectOriginY = 42;

            // The relative values are used to scale the highlights according to the zoom level on the page itself
            var relativeRectWidth = absoluteRectWidth * scaleRatio;
            var relativeRectHeight = absoluteRectHeight * scaleRatio;
            var relativeRectOriginX = absoluteRectOriginX * scaleRatio;
            var relativeRectOriginY = absoluteRectOriginY * scaleRatio;

            // This indicates the page on top of which the highlights are supposed to be drawn
            var highlightPageIndex = 0;

            if (pageIndex === highlightPageIndex)
            {
                // Calculates where the highlights should be drawn as a function of the whole webpage coordinates
                // (to make it look like it is on top of a page in Diva)
                var highlightXOffset = renderer._getImageOffset(pageIndex).left - renderer._viewport.left + viewportPaddingX + relativeRectOriginX;
                var highlightYOffset = renderer._getImageOffset(pageIndex).top - renderer._viewport.top + viewportPaddingY + relativeRectOriginY;

                //Draw the rectangle
                renderer._ctx.fillStyle = "rgba(255, 255, 0, 0.25)";
                renderer._ctx.fillRect(highlightXOffset, highlightYOffset,relativeRectWidth,relativeRectHeight);
            }
        });
    }
    /**
     * Will be enabling the layering plugin
     *
     **/
    handleClick (event, settings, publicInstance, pageIndex)
    {
        console.log("Entered Handle Click");
        this.drawHighlights();
    }

    createIcon ()
    {
        const pageToolsIcon = document.createElement('div');
        pageToolsIcon.classList.add('diva-pixel-icon');

        let root = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        root.setAttribute("x", "0px");
        root.setAttribute("y", "0px");
        root.setAttribute("viewBox", "0 0 25 25");
        root.id = `${this.core.settings.selector}pixel-icon`;

        let g = document.createElementNS("http://www.w3.org/2000/svg", "g");
        g.id = `${this.core.settings.selector}pixel-icon-glyph`;
        g.setAttribute("transform", "matrix(1, 0, 0, 1, -11.5, -11.5)");
        g.setAttribute("class", "diva-pagetool-icon");

        //Placeholder icon
        let rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
        rect.setAttribute('x', '15');
        rect.setAttribute('y', '10');
        rect.setAttribute('width', '25');
        rect.setAttribute('height', 25);

        g.appendChild(rect);
        root.appendChild(g);

        pageToolsIcon.appendChild(root);

        return pageToolsIcon;
    }
}

PixelPlugin.prototype.pluginName = "pixel";
PixelPlugin.prototype.isPageTool = true;

/**
 * Make this plugin available in the global context
 * as part of the 'Diva' namespace.
 **/
(function (global)
{
    global.Diva.PixelPlugin = PixelPlugin;
})(window);
<|endoftext|>


<commit_before>
/*

rest3d-server.js

The MIT License (MIT)

Copyright (c) 2013 Rémi Arnaud - Advanced Micro Devices, Inc.

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

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

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

'use strict';

if (process.env['NODETIME_KEY']) {
	console.log("+=+=+= Starting http://nodetime.com");
	console.log("Key = '"+process.env['NODETIME_KEY']+"'");
	require('nodetime').profile({
    accountKey: process.env['NODETIME_KEY'],
    appName: 'rest3d.fl4re.com node server'
  });
}

var restify = require('restify');
//var connect = require('connect');
var http = require('http');
var utils = require('./src/utils');
var childProcess = require('child_process');
var os= require('os');
require('shelljs/global');

var fs = require('fs');
var path = require('path');
var cache = require('./src/diskcache').Cache;
// fast html scrapping
var request = require('request');
// get content from zip files
var zip = require("zip");

var formidable = require('formidable');

var rmdirSync = require('./src/rmdir');
var copyFileSync = require('./src/cp');

var toJSON = require('./src/tojson');

var FileInfo = require('./src/fileinfo');
var sendFile = require('./src/sendfile');
var handler= require('./src/handler');

var platform = os.type().match(/^Win/) ? 'win' :
				(os.type().match(/^Dar/) ? 'mac' : 'unix');

console.log('host platform=',platform);
var staticPath = path.join(__dirname , '../static');

console.log('static folder=',staticPath);

var httpPort = process.env.OPENSHIFT_NODEJS_PORT ||
                   process.env.HTTP ||
                   8000;
var httpsPort = process.env.HTTPS || 443;
var ip_address = process.env.OPENSHIFT_NODEJS_IP || null;
var listenToPort = httpPort;

// see where collada2gltf is located
var openshift = process.env.OPENSHIFT_DATA_DIR;
var collada2gltf = 'collada2gltf';
if (openshift)
    collada2gltf = openshift + 'bin/collada2gltf-latest';
if (process.env.GLTF_BIN_PATH)
    collada2gltf = process.env.GLTF_BIN_PATH+'/collada2gltf';

// find out if we are running http or https
// if https, create two servers, the http server only does redirect to https

var params = {name: 'rest3d'};

if (fs.existsSync('./server.pem') && fs.existsSync('./server.key')){
	console.log('found https certficates');
	params.key = fs.readFileSync('./server.key');
	params.certificate = fs.readFileSync('./server.pem');
	listenToPort = httpsPort;
};

var server = module.exports.server = restify.createServer(params);

if (params.key) {
  var http_server = restify.createServer();
  http_server.get(/.*/,function(req,res,next) {
    // Assume https port is on the default port
    var redirect = "https://" + req.headers.host.replace (/(.*):.*/, '$1') +  req.url;
  	res.writeHead(302, {'Location': redirect});

    //console.log('**** https redirect to '+redirect)
    res.end();
    next();
	});
	http_server.listen( httpPort, ip_address);
}

rmdirSync('tmp');
rmdirSync('cache');
rmdirSync('upload');

fs.mkdirSync('tmp');
fs.mkdirSync('upload');
fs.mkdirSync('cache');

fs.chmodSync('tmp', '777');
fs.chmodSync('upload', '777');
fs.chmodSync('cache', '777');

//fs.mkdirSync('upload/thumbnail');

server.use(restify.acceptParser(server.acceptable));
//server.use(restify.authorizationParser());
server.use(restify.dateParser());
server.use(restify.queryParser());
//server.use(restify.bodyParser()); -> use formidable instead
server.use(restify.gzipResponse());
restify.defaultResponseHeaders = false;

var session=require('./src/session')();
server.sessionManager = session;
server.use(session.sessionManager);

// include routes
require('./src/warehouse')(server);
require('./src/3dvia')(server);
require('./src/upload')(server);

var database =  process.env.DATABASE ||
                process.argv[2] ||
                   'existdb';

console.log("loading database module ["+database+"]");

require('./src/'+database)(server);

// create diskcache (no mem caching, no gzip)
server.diskcache = new cache('cache',true,false,false);

function unknownMethodHandler(req, res) {
	console.log('unkownMethodHandler method='+req.method.toLowerCase());
  if (req.method.toLowerCase() === 'options') {
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version'];

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
    res.header('Access-Control-Allow-Methods', res.methods.join(', '));
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);
/*
server.use(restify.throttle({
  burst: 100,
  rate: 50,
  ip: true,
  overrides: {
    '192.168.1.1': {
      rate: 0,        // unlimited
      burst: 0
    }
  }
}));
*/
//server.use(restify.conditionalRequest());

// rest3d API

// convert

server.post(/^\/rest3d\/convert.*/,function(req,res,next){
	 console.log('post -> convert');

	 var form = new formidable.IncomingForm(),
         url = '',
         params = {};

   var h = new handler(req,res, next);

     form.on('field', function (name, data) {
     	params[name] = data;
     }).on('error', function (e) {
     	h.handleError(e);
     }).on('end', function(){//
     	console.log(params);
     	console.log('now converting collada');
     	if (!params.name && !params.path || !params.name.toLowerCase().endsWith('dae')) {
     		h.handleError({error: 'invalid file '+params.name+' in convert'});
     		return;
     	}
     	if(params.hasOwnProperty("path")){
     		// new API, path specified in the params of the request in order to convert the right file.
     		var output_dir = params.path.split('/');
     		output_dir[output_dir.length-2] = output_dir[output_dir.length-2] + '_gltf';
     		output_dir[output_dir.length-1] = output_dir[output_dir.length-1].replace('.dae','.json').replace('.DAE','.json');
     		var output_path=output_dir[0];
     		for(var i =1;i<output_dir.length;i++){
     			output_path = output_path + "/" +output_dir[i];
     			var list = fs.readdirSync("upload")
                list.forEach(function (name) {
                	console.log(name);
		        });
     			console.log(output_path,fs.existsSync(output_path+"/"));
     			if(!fs.existsSync(output_path)&&i!==output_dir.length-1){
     				console.log("create folder "+output_path)
     				fs.mkdirSync(output_path);
     			}
     		}
	     	console.log(collada2gltf+" -p -f \"" + params.path+"\" -o \""+output_path+"\"");
	     	var cmd = collada2gltf+" -p -f \"" + params.path+"\" -o \""+output_path+"\"";
	     	var input_dir = params.path.replace(/[^\/]*$/,'');
	     	output_dir = output_path.replace(/[^\/]*$/,'');
     	}
     	else{
     		// let's considered the model is stocked under rest3d/upload/ repository in case any path isn't specified
     		// the conversion will create a folder for stocking the gltf file
     		// CODE NOT TESTED, maybe get some conflicts for copying all textures to the gltf folder.
     		console.log("PART NOT TESTED YET")
	     	var output_dir = params.name.split('\.')[0]+'_gltf';
	     	var output_file = params.name.replace('.dae','.json');
	     	var output_path = 'upload/'+output_dir+'/'+output_file;
	     	var cmd = collada2gltf+" -p -f \"upload/" + params.name+"\" -o \""+output_path+"\"";
	     	 var input_dir = "upload/";
	     	output_dir = output_path.replace(/[^\/]*$/,'');
     }
     	console.log('exec '+cmd);
     	// todo -> manage progress !!!
		var outputC2J;
     	var codeC2J;
     	// todo -> manage progress !!!
		var ls = childProcess.exec(cmd, function (error, stdout, stderr) {
		   if (error) {
		     console.log(error.stack);
		     //console.log('Error code: '+error.code);
		     //console.log('Signal received: '+error.signal);

			 h.handleError({"code":error.code, "message": stderr});

		   }
		   console.log('Child Process STDOUT: '+stdout);
		   console.log('Child Process STDERR: '+stderr);
		 });
		 ls.on('exit', function (code, output) {
		  console.log('Child process exited with exit code '+code);
		  if (code !== 0) {
				h.handleError({errorCode:code, message:'ERROR, child process exited with exit code '});
				return;
			}
			codeC2J= code;
			outputC2J = output;

	  		console.log(input_dir)
			console.log('Exit code:', code);
	  		console.log('Program output:', output);

	  		console.log(input_dir)
			// // hack, copy all images in the output_dir, so the viewer will work
		    fs.readdir(input_dir, function (err, list) {
                list.forEach(function (name) {
                	var ext = name.match(/\.[^.]+$/);
                	if (ext[0]!=='.json'&&ext[0]!=='.dae'&&ext[0]!=='.glsl')
                	{
                		copyFileSync(input_dir+name, output_dir+name);
                		console.log(input_dir+name+'  TO  '+output_dir+name);
                	}
		        });
		    });
		    // end hack
			var files = [];
			fs.readdir(output_dir, function (err, list) {
                list.forEach(function (name) {
		            var stats = fs.statSync(output_dir+name),
		                fileInfo;
		            if (stats.isFile() && name[0] !== '.') {
		                fileInfo = new FileInfo({
		                    name: output_dir+name,
		                    size: stats.size
		                });
		                //fileInfo.initUrls(req);
		                files.push(fileInfo);
		            }
		        });
		        var timeout = function() {
                    	rmdirSync(output_dir);
                    	console.log('timeout !! '+output_dir+' was deleted');
                    }
                    setTimeout(function() { timeout()},5 * 60 * 1000);
		        h.handleResult({files: files, code:codeC2J, output:outputC2J});
		    });
	     });
	     });
    form.parse(req);
});

// static server
server.get(/^\/.*/, function (req, res, next) {

	// parse out parameters from url
	var filename = req.url.split('\?')[0];
	var p=path.resolve(staticPath + filename);

	console.log('http get path='+filename);

	sendFile(req,res,p);
	return next();
});

// clean exit
function sigterm_handler() {
    console.warn('Kaboom Baby!');
    process.exit(0);
}

process.on('SIGTERM', sigterm_handler);

// run server
server.listen( listenToPort, ip_address);
console.log ('rest3d server listening on port '+listenToPort);

<commit_msg>Touch<commit_after>
/*

rest3d-server.js

The MIT License (MIT)

Copyright (c) 2013 Rémi Arnaud - Advanced Micro Devices, Inc.

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

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

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

'use strict';

if (process.env['NODETIME_KEY']) {
	console.log("+=+=+= Starting http://nodetime.com");
	console.log("Key = '"+process.env['NODETIME_KEY']+"'");
	require('nodetime').profile({
    accountKey: process.env['NODETIME_KEY'],
    appName: 'rest3d.fl4re.com node server'
  });
}

var restify = require('restify');
//var connect = require('connect');
var http = require('http');
var utils = require('./src/utils');
var childProcess = require('child_process');
var os= require('os');
require('shelljs/global');

var fs = require('fs');
var path = require('path');
var cache = require('./src/diskcache').Cache;
// fast html scrapping
var request = require('request');
// get content from zip files
var zip = require("zip");

var formidable = require('formidable');

var rmdirSync = require('./src/rmdir');
var copyFileSync = require('./src/cp');

var toJSON = require('./src/tojson');

var FileInfo = require('./src/fileinfo');
var sendFile = require('./src/sendfile');
var handler= require('./src/handler');

var platform = os.type().match(/^Win/) ? 'win' :
				(os.type().match(/^Dar/) ? 'mac' : 'unix');

console.log('host platform=',platform);
var staticPath = path.join(__dirname , '../static');

console.log('static folder=',staticPath);

var httpPort = process.env.OPENSHIFT_NODEJS_PORT ||
                   process.env.HTTP ||
                   8000;
var httpsPort = process.env.HTTPS || 443;
var ip_address = process.env.OPENSHIFT_NODEJS_IP || null;
var listenToPort = httpPort;

// see where collada2gltf is located
var openshift = process.env.OPENSHIFT_DATA_DIR;
var collada2gltf = 'collada2gltf';
if (openshift)
    collada2gltf = openshift + 'bin/collada2gltf-latest';
if (process.env.GLTF_BIN_PATH)
    collada2gltf = process.env.GLTF_BIN_PATH+'/collada2gltf';

// find out if we are running http or https
// if https, create two servers, the http server only does redirect to https

var params = {name: 'rest3d'};

if (fs.existsSync('./server.pem') && fs.existsSync('./server.key')){
	console.log('found https certficates');
	params.key = fs.readFileSync('./server.key');
	params.certificate = fs.readFileSync('./server.pem');
	listenToPort = httpsPort;
};

var server = module.exports.server = restify.createServer(params);

if (params.key) {
  var http_server = restify.createServer();
  http_server.get(/.*/,function(req,res,next) {
    // Assume https port is on the default port
    var redirect = "https://" + req.headers.host.replace (/(.*):.*/, '$1') +  req.url;
  	res.writeHead(302, {'Location': redirect});

    //console.log('**** https redirect to '+redirect)
    res.end();
    next();
	});
	http_server.listen( httpPort, ip_address);
}

rmdirSync('tmp');
rmdirSync('cache');
rmdirSync('upload');

fs.mkdirSync('tmp');
fs.mkdirSync('upload');
fs.mkdirSync('cache');

fs.chmodSync('tmp', '777');
fs.chmodSync('upload', '777');
fs.chmodSync('cache', '777');

//fs.mkdirSync('upload/thumbnail');

server.use(restify.acceptParser(server.acceptable));
//server.use(restify.authorizationParser());
server.use(restify.dateParser());
server.use(restify.queryParser());
//server.use(restify.bodyParser()); -> use formidable instead
server.use(restify.gzipResponse());
restify.defaultResponseHeaders = false;

var session=require('./src/session')();
server.sessionManager = session;
server.use(session.sessionManager);

// include routes
require('./src/warehouse')(server);
require('./src/3dvia')(server);
require('./src/upload')(server);

var database =  process.env.DATABASE ||
                process.argv[2] ||
                   'existdb';

console.log("loading database module ["+database+"]");

require('./src/'+database)(server);

// create diskcache (no mem caching, no gzip)
server.diskcache = new cache('cache',true,false,false);

function unknownMethodHandler(req, res) {
	console.log('unkownMethodHandler method='+req.method.toLowerCase());
  if (req.method.toLowerCase() === 'options') {
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version'];

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
    res.header('Access-Control-Allow-Methods', res.methods.join(', '));
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);
/*
server.use(restify.throttle({
  burst: 100,
  rate: 50,
  ip: true,
  overrides: {
    '192.168.1.1': {
      rate: 0,        // unlimited
      burst: 0
    }
  }
}));
*/
//server.use(restify.conditionalRequest());

// rest3d API

// convert

server.post(/^\/rest3d\/convert.*/,function(req,res,next){
	 console.log('post -> convert');

	 var form = new formidable.IncomingForm(),
         url = '',
         params = {};

   var h = new handler(req,res, next);

     form.on('field', function (name, data) {
     	params[name] = data;
     }).on('error', function (e) {
     	h.handleError(e);
     }).on('end', function(){//
     	console.log(params);
     	console.log('now converting collada');
     	if (!params.name && !params.path || !params.name.toLowerCase().endsWith('dae')) {
     		h.handleError({error: 'invalid file '+params.name+' in convert'});
     		return;
     	}
     	if(params.hasOwnProperty("path")){
     		// new API, path specified in the params of the request in order to convert the right file.
     		var output_dir = params.path.split('/');
     		output_dir[output_dir.length-2] = output_dir[output_dir.length-2] + '_gltf';
     		output_dir[output_dir.length-1] = output_dir[output_dir.length-1].replace('.dae','.json').replace('.DAE','.json');
     		var output_path=output_dir[0];
     		for(var i =1;i<output_dir.length;i++){
     			output_path = output_path + "/" +output_dir[i];
     			var list = fs.readdirSync("upload")
                list.forEach(function (name) {
                	console.log(name);
		        });
     			console.log(output_path,fs.existsSync(output_path+"/"));
     			if(!fs.existsSync(output_path)&&i!==output_dir.length-1){
     				console.log("create folder "+output_path)
     				fs.mkdirSync(output_path);
     			}
     		}
	     	console.log(collada2gltf+" -p -f \"" + params.path+"\" -o \""+output_path+"\"");
	     	var cmd = collada2gltf+" -p -f \"" + params.path+"\" -o \""+output_path+"\"";
	     	var input_dir = params.path.replace(/[^\/]*$/,'');
	     	output_dir = output_path.replace(/[^\/]*$/,'');
     	}
     	else{
     		// let's considered the model is stocked under rest3d/upload/ repository in case any path isn't specified
     		// the conversion will create a folder for stocking the gltf file
     		// CODE NOT TESTED, maybe get some conflicts for copying all textures to the gltf folder.
     		console.log("PART NOT TESTED YET")
	     	var output_dir = params.name.split('\.')[0]+'_gltf';
	     	var output_file = params.name.replace('.dae','.json');
	     	var output_path = 'upload/'+output_dir+'/'+output_file;
	     	var cmd = collada2gltf+" -p -f \"upload/" + params.name+"\" -o \""+output_path+"\"";
	     	 var input_dir = "upload/";
	     	output_dir = output_path.replace(/[^\/]*$/,'');
     }
     	console.log('exec '+cmd);
     	// todo -> manage progress !!!
		var outputC2J;
     	var codeC2J;
     	// todo -> manage progress !!!
		var ls = childProcess.exec(cmd, function (error, stdout, stderr) {
		   if (error) {
		     console.log(error.stack);
		     //console.log('Error code: '+error.code);
		     //console.log('Signal received: '+error.signal);

			 h.handleError({"code":error.code, "message": stderr});

		   }
		   console.log('Child Process STDOUT: '+stdout);
		   console.log('Child Process STDERR: '+stderr);
		 });
		 ls.on('exit', function (code, output) {
		  console.log('Child process exited with exit code '+code);
		  if (code !== 0) {
				h.handleError({errorCode:code, message:'ERROR, child process exited with exit code '});
				return;
			}
			codeC2J= code;
			outputC2J = output;

	  		console.log(input_dir)
			console.log('Exit code:', code);
	  		console.log('Program output:', output);

	  		console.log(input_dir)
			// // hack, copy all images in the output_dir, so the viewer will work
		    fs.readdir(input_dir, function (err, list) {
                list.forEach(function (name) {
                	var ext = name.match(/\.[^.]+$/);
                	if (ext[0]!=='.json'&&ext[0]!=='.dae'&&ext[0]!=='.glsl'&&ext[0]!=='.bin')
                	{
                		copyFileSync(input_dir+name, output_dir+name);
                		console.log(input_dir+name+'  TO  '+output_dir+name);
                	}
		        });
		    });
		    // end hack
			var files = [];
			fs.readdir(output_dir, function (err, list) {
                list.forEach(function (name) {
		            var stats = fs.statSync(output_dir+name),
		                fileInfo;
		            if (stats.isFile() && name[0] !== '.') {
		                fileInfo = new FileInfo({
		                    name: output_dir+name,
		                    size: stats.size
		                });
		                //fileInfo.initUrls(req);
		                files.push(fileInfo);
		            }
		        });
		        var timeout = function() {
                    	rmdirSync(output_dir);
                    	console.log('timeout !! '+output_dir+' was deleted');
                    }
                    setTimeout(function() { timeout()},5 * 60 * 1000);
		        h.handleResult({files: files, code:codeC2J, output:outputC2J});
		    });
	     });
	     });
    form.parse(req);
});

// static server
server.get(/^\/.*/, function (req, res, next) {

	// parse out parameters from url
	var filename = req.url.split('\?')[0];
	var p=path.resolve(staticPath + filename);

	console.log('http get path='+filename);

	sendFile(req,res,p);
	return next();
});

// clean exit
function sigterm_handler() {
    console.warn('Kaboom Baby!');
    process.exit(0);
}

process.on('SIGTERM', sigterm_handler);

// run server
server.listen( listenToPort, ip_address);
console.log ('rest3d server listening on port '+listenToPort);

<|endoftext|>


<commit_before>iD.svg.Midpoints = function(projection) {
    return function drawMidpoints(surface, graph, entities, filter, extent) {
        var midpoints = {};

        if (!surface.select('.layer-hit g.vertex').node()) {
            return surface.selectAll('.layer-hit g.midpoint').remove();
        }

        for (var i = 0; i < entities.length; i++) {
            if (entities[i].type !== 'way') continue;

            var entity = entities[i],
                nodes = graph.childNodes(entity);

            // skip the last node because it is always repeated
            for (var j = 0; j < nodes.length - 1; j++) {

                var a = nodes[j],
                    b = nodes[j + 1],
                    id = [a.id, b.id].sort().join('-');

                // If neither of the nodes changed, no need to redraw midpoint
                if (!midpoints[id] && (filter(a) || filter(b))) {
                    var loc = iD.geo.interp(a.loc, b.loc, 0.5);
                    if (extent.intersects(loc) && iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) {
                        midpoints[id] = {
                            type: 'midpoint',
                            id: id,
                            loc: loc,
                            edge: [a.id, b.id]
                        };
                    }
                }
            }
        }

        var groups = surface.select('.layer-hit').selectAll('g.midpoint')
            .filter(filter)
            .data(_.values(midpoints), function(d) { return d.id; });

        var group = groups.enter()
            .insert('g', ':first-child')
            .attr('class', 'midpoint');

        group.append('circle')
            .attr('r', 7)
            .attr('class', 'shadow');

        group.append('circle')
            .attr('r', 3)
            .attr('class', 'fill');

        groups.attr('transform', iD.svg.PointTransform(projection));

        // Propagate data bindings.
        groups.select('circle.shadow');
        groups.select('circle.fill');

        groups.exit()
            .remove();
    };
};
<commit_msg>more careful about not drawing midpoints<commit_after>iD.svg.Midpoints = function(projection) {
    return function drawMidpoints(surface, graph, entities, filter, extent) {
        var midpoints = {};

        var vertices = 0;

        for (var i = 0; i < entities.length; i++) {

            if (entities[i].geometry(graph) === 'vertex' && vertices++ > 2000) {
                return surface.selectAll('.layer-hit g.midpoint').remove();
            }

            if (entities[i].type !== 'way') continue;

            var entity = entities[i],
                nodes = graph.childNodes(entity);

            // skip the last node because it is always repeated
            for (var j = 0; j < nodes.length - 1; j++) {

                var a = nodes[j],
                    b = nodes[j + 1],
                    id = [a.id, b.id].sort().join('-');

                // If neither of the nodes changed, no need to redraw midpoint
                if (!midpoints[id] && (filter(a) || filter(b))) {
                    var loc = iD.geo.interp(a.loc, b.loc, 0.5);
                    if (extent.intersects(loc) && iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) {
                        midpoints[id] = {
                            type: 'midpoint',
                            id: id,
                            loc: loc,
                            edge: [a.id, b.id]
                        };
                    }
                }
            }
        }

        var groups = surface.select('.layer-hit').selectAll('g.midpoint')
            .filter(filter)
            .data(_.values(midpoints), function(d) { return d.id; });

        var group = groups.enter()
            .insert('g', ':first-child')
            .attr('class', 'midpoint');

        group.append('circle')
            .attr('r', 7)
            .attr('class', 'shadow');

        group.append('circle')
            .attr('r', 3)
            .attr('class', 'fill');

        groups.attr('transform', iD.svg.PointTransform(projection));

        // Propagate data bindings.
        groups.select('circle.shadow');
        groups.select('circle.fill');

        groups.exit()
            .remove();
    };
};
<|endoftext|>


<commit_before>var express = require('express');

var app = express();

app.set('view engine', 'html');
app.use('/', express.static('./public'));

var bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

module.exports = app;

//require sequelize models
var models = require('./db/orm-model.js');
var models = models();
var User = models.User;
var Activity = models.Activity;

//Insert or update user information in database
app.post('/data/user', function(req, res) {
  'use strict';
  User.upsert({
    userId: req.body.user_id,
    email: req.body.email,
    picture: req.body.picture,
    name: req.body.name,
    nickname:req.body.nickname});
  res.sendStatus(200);
});

app.get('/data/user', function(req, res){
  'use strict';
  res.sendStatus(200);
});

app.post('/data/activities', function(req, res){
  'use strict';
  User.find({
    where: {
      userId : req.body.user_id
    }
  })
  .then(function(user){
    Activity.build({
      title: req.body.title,
      description: req.body.description,
      location: req.body.location,
      keywords: req.body.keywords
    })
    .save()
    .then(function(activity){
      if(user)
        user.addActivity(activity);
    });
  });
  res.redirect('/');
});

app.get('/data/activities', function(req, res){
  'use strict';

  Activity.findAll({})
  .then(function(activities){
    activities.reduce(function(list, activity){
      activity.getUsers({
        where : {
          userId : {
            ne : req.query.userID
          }//userId
        }//where
      })//getUsers
      .then(function(user){
        list.push({id: activity.id, avatar: user[0].picture,
          user: user[0].name, description: activity.description});

        if(list.length === activities.length)
          { res.send(list); }
      }); //then(function(user))
      return list;
    }, []); //reduce
  });//then(function(activities))
});//app.get
<commit_msg>Added an iteration count to determine end of activity/user cycle.<commit_after>var express = require('express');

var app = express();

app.set('view engine', 'html');
app.use('/', express.static('./public'));

var bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

module.exports = app;

//require sequelize models
var models = require('./db/orm-model.js');
var models = models();
var User = models.User;
var Activity = models.Activity;

//Insert or update user information in database
app.post('/data/user', function(req, res) {
  'use strict';
  User.upsert({
    userId: req.body.user_id,
    email: req.body.email,
    picture: req.body.picture,
    name: req.body.name,
    nickname:req.body.nickname});
  res.sendStatus(200);
});

app.get('/data/user', function(req, res){
  'use strict';
  res.sendStatus(200);
});

app.post('/data/activities', function(req, res){
  'use strict';
  User.find({
    where: {
      userId : req.body.user_id
    }
  })
  .then(function(user){
    Activity.build({
      title: req.body.title,
      description: req.body.description,
      location: req.body.location,
      keywords: req.body.keywords
    })
    .save()
    .then(function(activity){
      if(user)
        user.addActivity(activity);
    });
  });
  res.redirect('/');
});

app.get('/data/activities', function(req, res){
  'use strict';
  var iterations = 0;
  Activity.findAll({})
  .then(function(activities){
    activities.reduce(function(list, activity){
      activity.getUsers({
        where : {
          userId : {
            ne : req.query.userID
          }//userId
        }//where
      })//getUsers
      .then(function(user){
        if(user.length > 0){
          console.log('user data', user);
          list.push({id: activity.id, avatar: user[0].picture,
            user: user[0].name, description: activity.description});
          iterations++;
        }else{
          iterations++;
        }
        if(iterations === activities.length)
          { res.send(list); }
      }); //then(function(user))
      return list;
    }, []); //reduce
  });//then(function(activities))
});//app.get
<|endoftext|>


<commit_before>/*
 * inline-expanding.js
 * https://github.com/savetheinternet/Tinyboard/blob/master/js/inline-expanding.js
 *
 * Released under the MIT license
 * Copyright (c) 2012-2013 Michael Save <savetheinternet@tinyboard.org>
 *
 * Usage:
 *   // $config['additional_javascript'][] = 'js/jquery.min.js';
 *   $config['additional_javascript'][] = 'js/inline-expanding.js';
 *
 */

onready(function(){
	var inline_expand_post = function() {
		var link = this.getElementsByTagName('a');

		for (var i = 0; i < link.length; i++) {
			if (typeof link[i] == "object" && link[i].childNodes && typeof link[i].childNodes[0] !== 'undefined' && link[i].childNodes[0].src && link[i].childNodes[0].className.match(/post-image/) && !link[i].className.match(/file/)) {
				link[i].childNodes[0].style.maxWidth = '100%';

				link[i].onclick = function(e) {
					if (this.childNodes[0].className == 'hidden')
						return false;
					if (e.which == 2 || e.metaKey)
						return true;
					if (!this.dataset.src) {
						this.dataset.expanded = 'true';
						this.dataset.src= this.childNodes[0].src;
						this.dataset.width = this.childNodes[0].style.width;
						this.dataset.height = this.childNodes[0].style.height;
						this.childNodes[0].src = this.href;
						this.childNodes[0].style.opacity = '0.4';
						this.childNodes[0].style.filter = 'alpha(opacity=40)';
						this.childNodes[0].style.width = 'auto';
						this.childNodes[0].style.height = 'auto';
						this.childNodes[0].onload = function() {
							this.style.opacity = '';
							this.style.filter= '';
						}
					} else {
						this.childNodes[0].src = this.dataset.src;
						this.childNodes[0].style.width = this.dataset.width;
						this.childNodes[0].style.height = this.dataset.height;
						this.childNodes[0].style.opacity="";
						this.childNodes[0].style.filter="";
						this.childNodes[0].style.float = 'left';
						delete this.dataset.expanded;
						delete this.dataset.src;

					}
					return false;
				}
			}
		}
	}

	if (window.jQuery) {
		$('div[id^="thread_"]').each(inline_expand_post);

		// allow to work with auto-reload.js, etc.
		$(document).bind('new_post', function(e, post) {
			if (post.length){
				//post is a jQuery array
				post.each(inline_expand_post)
			}
			else
				inline_expand_post.call(post);
		});
	} else {
		inline_expand_post.call(document);
	}

});
<commit_msg>inline-expanding.js: fix for FS#222<commit_after>/**
 * inline-expanding.js
 * https://github.com/twiforce/fukuro/blob/master/js/inline-expanding.js
 *
 * Expands images inside div.post.
 *
 * Released under the MIT license
 * Copyright (c) 2012-2013 Michael Save <savetheinternet@tinyboard.org>
 *     			 2013-2015 Simon Twiforce <twiforce@syn-ch.ru>
 *               2015 GhostPerson <https://github.com/GhostPerson>
 *               2015 appleboom <appleboom@syn-ch.ru>
 *
 * Usage:
 *   // $config['additional_javascript'][] = 'js/jquery.min.js';
 *   $config['additional_javascript'][] = 'js/inline-expanding.js';
 *
 */

$(function(){
	var inline_expand_post = function() {
		var link = this.getElementsByTagName('a');

		for (var i = 0; i < link.length; i++) {
			if (typeof link[i] == "object" && link[i].childNodes && typeof link[i].childNodes[0] !== 'undefined' && link[i].childNodes[0].src && link[i].childNodes[0].className.match(/post-image/) && !link[i].className.match(/file/)) {
				link[i].childNodes[0].style.maxWidth = '100%';

				link[i].onclick = function(e) {
					if (this.childNodes[0].className == 'hidden')
						return false;
					if (e.which == 2 || e.metaKey)
						return true;
					if (!this.dataset.src) {
						this.dataset.expanded = 'true';
						this.dataset.src= this.childNodes[0].src;
						this.dataset.width = this.childNodes[0].style.width;
						this.dataset.height = this.childNodes[0].style.height;
						this.childNodes[0].src = this.href;
						this.childNodes[0].style.opacity = '0.4';
						this.childNodes[0].style.filter = 'alpha(opacity=40)';
						this.childNodes[0].style.width = 'auto';
						this.childNodes[0].style.height = 'auto';
						this.childNodes[0].onload = function() {
							this.style.opacity = '';
							this.style.filter= '';
						}
					} else {
						this.childNodes[0].src = this.dataset.src;
						this.childNodes[0].style.width = this.dataset.width;
						this.childNodes[0].style.height = this.dataset.height;
						this.childNodes[0].style.opacity="";
						this.childNodes[0].style.filter="";
						this.childNodes[0].style.float = 'left';
						delete this.dataset.expanded;
						delete this.dataset.src;

					}
					return false;
				}
			}
		}
	};

	if (window.jQuery) {
		$('div[id^="thread_"]').each(inline_expand_post);

		// allow to work with auto-reload.js, etc.
		$(document).bind('new_post', function(e, post) {
			if ('selector' in post){
				//post is a jQuery array
				post.each(inline_expand_post)
			}
			else
				inline_expand_post.call(post);
		});
	} else {
		inline_expand_post.call(document);
	}

});
<|endoftext|>


<commit_before>describe('idai field app', function() {

    function createObject() {

        return clickCreateObject()
                .then(selectTypeObject)
                .then(typeInIdentifier)
                .then(saveObject);
    }

    function clickCreateObject() {
        return element(by.id('object-overview-button-create-object')).click()
    }

    function selectTypeObject() {
        return element(by.id('create-object-option-0')).click();
    }

    function typeInIdentifier() {
        return element(by.id('object-edit-input-identifier')).clear().sendKeys('1').sendKeys('2');
    }

    function typeInIdentifierInSearchField() {
        return element(by.id('object-search')).clear().sendKeys('1').sendKeys('2');
    }

    function saveObject() {
        return element(by.id('object-edit-button-save-object')).click();
    }

    beforeEach(function(){
        browser.get('/');
    });

    it('should create a new object of first listed type ', function() {
        createObject()
            .then(function(){
                expect(element(by.id('object-overview-identifier-0')).getText()).toEqual("12");
            });
    });

    it('should warn if an existing id is used ', function() {
        createObject()
            .then(createObject)
            .then(function(){
                expect(element(by.id('message-0')).getText()).
                    toEqual("Objekt Identifier existiert bereits. Bei Klick auf ein anderes Objekt wird der ursprüngliche Zustand wiederhergestellt.");
            });
    });

    it('should find it by its identifier', function() {
        createObject()
            .then(typeInIdentifierInSearchField)
            .then(function(){
                expect(element(by.id('object-overview-identifier-0')).getText()).toEqual("12");
            });
    });
});
<commit_msg>Fix test.<commit_after>describe('idai field app', function() {

    function createObject() {

        return clickCreateObject()
                .then(selectTypeObject)
                .then(typeInIdentifier)
                .then(saveObject);
    }

    function clickCreateObject() {
        return element(by.id('object-overview-button-create-object')).click()
    }

    function selectTypeObject() {
        return element(by.id('create-object-option-0')).click();
    }

    function typeInIdentifier() {
        return element(by.id('object-edit-input-identifier')).clear().sendKeys('1').sendKeys('2');
    }

    function typeInIdentifierInSearchField() {
        return element(by.id('object-search')).clear().sendKeys('1').sendKeys('2');
    }

    function saveObject() {
        return element(by.id('object-edit-button-save-object')).click();
    }

    beforeEach(function(){
        browser.get('/');
    });

    it('should create a new object of first listed type ', function() {
        createObject()
            .then(function(){
                expect(element(by.id('object-overview-identifier-0')).getText()).toEqual("12");
            });
    });

    it('should warn if an existing id is used ', function() {
        createObject()
            .then(createObject)
            .then(function(){
                expect(element(by.id('message-0')).getText()).
                    toEqual("Objekt Identifier existiert bereits.");
            });
    });

    it('should find it by its identifier', function() {
        createObject()
            .then(typeInIdentifierInSearchField)
            .then(function(){
                expect(element(by.id('object-overview-identifier-0')).getText()).toEqual("12");
            });
    });
});
<|endoftext|>


<commit_before>define([], function() {
	Path.map("#!/reset").to(function(){
	}).enter(function() {
		require(['tpl!template/reset.html'], function(tpl){
			$('#main').append($(tpl.apply()));

			$('header').hide();
			$('#main').addClass('transparent-background');
			$('footer').hide();
		});
	}).exit(function() {
		// Exit from route
		$('header').show();
		$('#main').off().empty().removeClass('transparent-background');
		$('footer').show();
	});
});

<commit_msg>Add optional hash parameter to /reset route<commit_after>define([], function() {
	Path.map("#!/reset(/:hash)").to(function(){
	}).enter(function() {
		var hash = this.params['hash'];

		require(['tpl!template/reset.html'], function(tpl){
			$('#main').append($(tpl.apply()));

			$('header').hide();
			$('#main').addClass('transparent-background');
			$('footer').hide();
		});
	}).exit(function() {
		// Exit from route
		$('header').show();
		$('#main').off().empty().removeClass('transparent-background');
		$('footer').show();
	});
});

<|endoftext|>


<commit_before>// Functions for the jobs page.
$(function() {
    const fs = require('fs');
    const path = require('path');
    var kb = 1024;
    var mb = 1024 * kb;
    var gb = 1024 * mb;
    var tb = 1024 * gb;
    var alreadyAdded = {};
    var body = document.getElementsByTagName("body")[0];
    body.addEventListener('drop', function (e) {
	    e.preventDefault();
	    e.stopPropagation();
	    for (let f of e.dataTransfer.files) {
            addFile(f.path)
	    }
    });

    body.addEventListener('dragover', function (e) {
	    e.preventDefault();
	    e.stopPropagation();
    });

    function addFile(filepath) {
        var rowNumber = $("#filesTable > tbody tr").length
        var stat = fs.statSync(filepath)
        var row = getTableRow(filepath, rowNumber, stat.isDirectory())
        $(row).insertBefore('#fileTotals')
        alreadyAdded[filepath] = true
        fs.stat(filepath, function(err, stats) {
            statPath(err, stats, filepath, rowNumber)
        });
    };

    function deleteFile(filepath) {
        // TODO: Delete table row
        delete alreadyAdded[filepath]
    };

    function statPath(err, stats, filepath, rowNumber) {
        if (stats.isDirectory()) {
            fs.readdir(filepath, function(err, files) {
                if (err != null) {
                    console.log(err)
                    return
                }
                for (var i=0; i < files.length; i++) {
                    var fullpath = path.join(filepath, files[i])
                    fs.stat(fullpath, function(err, stats) {
                        statPath(err, stats, fullpath, rowNumber)
                    });
                }
            });
        }
        if (err != null) {
            console.log(err)
            return
        }
        var countCell = $('#fileCount' + rowNumber)
        var sizeCell = $('#fileSize' + rowNumber)
        var totalCountCell = $('#totalFileCount')
        var totalSizeCell = $('#totalFileSize')
        var prevCount = parseInt(totalCountCell.data('total'), 10)
        var prevSize = parseInt(totalSizeCell.data('total'), 10)
        console.log("Old Count: " + prevCount)
        console.log("Old Size: " + prevSize)
        var newCount = prevCount + 1
        var newSize = prevSize + stats.size
        countCell.text(newCount)
        totalCountCell.data('total', newCount)
        sizeCell.text(formatFileSize(newSize))
        totalSizeCell.data('total', newSize)
        console.log("Count: " + newCount)
        console.log("Size: " + newSize)
        // TODO: Totals in last row
    }

    function formatFileSize(size) {
        if (size > tb) {
            return (size / tb).toFixed(2) + " TB"
        }
        if (size > gb) {
            return (size / gb).toFixed(2) + " GB"
        }
        if (size > mb) {
            return (size / mb).toFixed(2) + " MB"
        }
        return (size / kb).toFixed(2) + " KB"
    }

    function getTableRow(filepath, rowNumber, isDir) {
        var icon = getIconForPath(filepath)
        return `

            ${icon} <input type="hidden" name="files" value="${filepath}"/>
            0
            0

`
    }

    function getIconForPath(filepath, isDir) {
        if (isDir) {
            return getFolderIcon(filepath)
        }
        return getFileIcon(filepath)
    }

    function getFileIcon(filepath) {
        return '' + filepath;
    }

    function getFolderIcon(filepath) {
        return '' + filepath;
    }

});
<commit_msg>Added some TODOs and removed some logging<commit_after>// Functions for the jobs page.
$(function() {
    const fs = require('fs');
    const path = require('path');
    var kb = 1024;
    var mb = 1024 * kb;
    var gb = 1024 * mb;
    var tb = 1024 * gb;
    var alreadyAdded = {};
    var body = document.getElementsByTagName("body")[0];
    body.addEventListener('drop', function (e) {
	    e.preventDefault();
	    e.stopPropagation();
	    for (let f of e.dataTransfer.files) {
            addFile(f.path)
	    }
    });

    body.addEventListener('dragover', function (e) {
	    e.preventDefault();
	    e.stopPropagation();
    });

    function addFile(filepath) {
        var rowNumber = $("#filesTable > tbody tr").length
        var stat = fs.statSync(filepath)
        var row = getTableRow(filepath, rowNumber, stat.isDirectory())
        $(row).insertBefore('#fileTotals')
        alreadyAdded[filepath] = true
        fs.stat(filepath, function(err, stats) {
            statPath(err, stats, filepath, rowNumber)
        });
    };

    function deleteFile(filepath) {
        // TODO: Delete table row
        delete alreadyAdded[filepath]
    };

    function statPath(err, stats, filepath, rowNumber) {
        // TODO: Recursion isn't working - bad filepaths.
        // TODO: Count directories separately.
        // TODO: Skip .DS_Store and other junk files.
        if (stats.isDirectory()) {
            fs.readdir(filepath, function(err, files) {
                if (err != null) {
                    console.log(err)
                    return
                }
                for (var i=0; i < files.length; i++) {
                    var fullpath = path.join(filepath, files[i])
                    fs.stat(fullpath, function(err, stats) {
                        statPath(err, stats, fullpath, rowNumber)
                    });
                }
            });
        }
        if (err != null) {
            console.log(err)
            return
        }
        var countCell = $('#fileCount' + rowNumber)
        var sizeCell = $('#fileSize' + rowNumber)
        var totalCountCell = $('#totalFileCount')
        var totalSizeCell = $('#totalFileSize')
        var prevCount = parseInt(totalCountCell.data('total'), 10)
        var prevSize = parseInt(totalSizeCell.data('total'), 10)
        var newCount = prevCount + 1
        var newSize = prevSize + stats.size
        countCell.text(newCount)
        totalCountCell.data('total', newCount)
        sizeCell.text(formatFileSize(newSize))
        totalSizeCell.data('total', newSize)
        console.log(filepath + " " + newCount + " " + stats.size)
        // TODO: Totals in last row
    }

    function formatFileSize(size) {
        if (size > tb) {
            return (size / tb).toFixed(2) + " TB"
        }
        if (size > gb) {
            return (size / gb).toFixed(2) + " GB"
        }
        if (size > mb) {
            return (size / mb).toFixed(2) + " MB"
        }
        return (size / kb).toFixed(2) + " KB"
    }

    function getTableRow(filepath, rowNumber, isDir) {
        var icon = getIconForPath(filepath)
        return `

            ${icon} <input type="hidden" name="files" value="${filepath}"/>
            0
            0

`
    }

    function getIconForPath(filepath, isDir) {
        if (isDir) {
            return getFolderIcon(filepath)
        }
        return getFileIcon(filepath)
    }

    function getFileIcon(filepath) {
        return '' + filepath;
    }

    function getFolderIcon(filepath) {
        return '' + filepath;
    }

});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { ReactDom } from 'react-dom';
import { List } from 'immutable';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { getAuth } from 'src/auth';

import { getSelectedTask } from 'src/tasks';
import { getCommentList } from 'src/comments';

import './task-view.css';
import Icon from '../icon';
import Textarea from 'react-textarea-autosize';

import Img from 'react-image'
import TagsInput from 'react-tagsinput';
import 'react-tagsinput/react-tagsinput.css';
import Select from 'react-select';
import Button from '../button';
import CommentList from '../comment-list';

export class TaskView extends Component {
  constructor() {
    super(...arguments);

    this.state = {
      title: '',
      description: '',
      circle: '',
      projectName: null,
      defaultCircle: [
        { value: 'אור', label: 'אור' },
        { value: 'אמיר', label: 'אמיר'},
        { value: 'מיכאל', label: 'מיכאל'}
      ],
      type: '',
      defaultType: [
        { value: 1, label: 'תכנון ארוע' },
        { value: 2, label: 'משמרות בארוע (בשביל אחראי משימות משמרות) - טרם נפתח', disabled: true},
        { value: 3, label: 'משימות של מחנות נושא - טרם נפתח', disabled: true},
        { value: 4, label: 'משימות של מיצבי אמנות - טרם נפתח', disabled: true},
        { value: 5, label: 'אחר'}
      ],
      label: [],
      relevantContacts: '',
      assigneePhone: '',
      status: ''
    }

    this.handleChange = this.handleChange.bind(this);
    this.handleLabelChange = this.handleLabelChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  static propTypes = {
    selectTask: PropTypes.func.isRequired,
    updateTask: PropTypes.func.isRequired,
    removeTask: PropTypes.func.isRequired,
    assignTask: PropTypes.func.isRequired,
    selectedTask: PropTypes.object,
    isAdmin: PropTypes.bool.isRequired,
    unloadComments: PropTypes.func.isRequired,
  };

  componentWillMount() {
  }

  componentWillReceiveProps(nextProps) {
    // TODO - check this maybe called several times now that we use comments

    // TODO: On mobile scroll to top - hackish -
    // TODO: should move this to a window resize event...
    if(window.innerWidth < 768) {
      window.scrollTo(0, 150);
    }

    let nextSelectedTask = nextProps.selectedTask || {};
    let { id, title, description, circle, type, projectName,
      label, relevantContacts,
      assigneePhone, status, dueDate, createdDate } = nextSelectedTask;

      // this checks if we got another task, or we're updating the same one
      if (id != this.state.id) {
        const labelAsArray = label ?
          (Object.keys(label).map( l => { return l })) : [];

        this.setState({
          id: id || '',
          title: title || '',
          description:description || '',
          circle:circle || '',
          label: labelAsArray || [],
          relevantContacts:relevantContacts || '',
          assigneePhone:assigneePhone || '',
          status: status || '',
          createdDate: createdDate || '',
          dueDate: dueDate || null,
          type: type || null,
          projectName: projectName || '',
        });
      }

    // if(nextProps.comments.length() != this.state.comments) {
    //   this.props.unloadComments(); //TODO - probably length is not such a good indicator
    //   // TODO - we should unload comments when we're start loading new comments
    // }
  }

  render() {
    //const { task } = this.props;

    const task = this.props.selectedTask;

    if(!task) {
      return(

      );
    }

    const isTaskEmpty = !task.description &&
        !task.circle && !task.status;

    const isUserCreator = task.creator && task.creator.id == this.props.auth.id;

    return (

        <Button className='button-no-border close-button' onClick={ () => this.props.selectTask() }><Icon name='close' className='close-icon grow' /></Button>

        {!task.assignee ? <Button
          className='button button-small action-button assign_task'
          onClick={()=>this.props.assignTask(task)}
          type='button'>קח אחריות על משימה זו</Button> :

            {task.assignee.name}

}

          { isTaskEmpty && isUserCreator ?
          <Button
            className='action-button delete_task'
            onClick={()=> { this.props.removeTask(task); this.props.selectTask(); }}
            type='button'>מחק משימה</Button> : '' }

          <form onSubmit={this.handleSubmit} noValidate>
            {this.renderInput(task, 'title', 'שם המשימה')}
            {this.renderInput(task, 'projectName', 'שם הפרוייקט')}
            {this.renderTextArea(task, 'description', 'תאור המשימה')}
            {this.props.isAdmin?
              this.renderSelect(task, 'circle', 'מעגל', this.state.defaultCircle): ''}

<Icon className='label' name='label_outline' /> {this.renderLabel()}

            { this.renderSelect(task, 'type', 'סוג המשימה', this.state.defaultType)}
            {this.renderTextArea(task, 'relevantContacts', 'אנשי קשר רלוונטיים')}
            {this.renderInput(task, 'assigneePhone', 'טלפון ממלא המשימה')}
            {this.renderTextArea(task, 'status', 'סטטוס המשימה')}
            <input className='button button-small button-save' type="submit" value="שמור" />
          </form>

        { this.props.comments ?
          <CommentList
          task={task}
          comments={this.props.comments}
          auth={this.props.auth}
          createComment={this.props.createComment}/> : ''}

    );
  }

  renderSelect(task, fieldName, placeholder, options) {
    return (
      <Select
      type='text'
      name={fieldName}
      value={this.state[fieldName]}
      placeholder={placeholder}
      ref={e => this[fieldName+'Input'] = e}
      onChange={(e) => { let val=null; if (e) { val = e.value };
                this.setState({ [fieldName]: val}) }}
      options={options}
      onBlur={this.handleSubmit}
      noResultsText={'לא נמצאו תוצאות'}
      searchable={ false } />
  );
  }

  renderInput(task, fieldName, placeholder) {
    return (
        <input
        className='changing-input'
        type = 'text'
        name = { fieldName }
        value = { this.state[fieldName] }
        placeholder = { placeholder }
        ref = { e => this[fieldName+'Input'] = e }
        onChange = { this.handleChange }
        onBlur = { this.handleSubmit } />
    );
  }

  renderTextArea(task, fieldName, placeholder) {
    return (
        <Textarea
        className='changing-input'
        name={fieldName}
        value={this.state[fieldName]}
        placeholder={placeholder}
        ref={e => this[fieldName+'Input'] = e}
        onChange={this.handleChange}
        onBlur={this.handleSubmit}/>
    );
  }

  renderLabel() {
    const showPlaceholder = !this.state.label || this.state.label.length == 0 ;
    return (
      <TagsInput className='react-tagsinput-changing'
      value={this.state.label}
      onChange={this.handleLabelChange}
      onlyUnique={true}
      addOnBlur={true}
      inputProps={{ placeholder: showPlaceholder ? 'הכנס תגיות. לחץ על Enter בין תגית לתגית' : ''}}
      />
    )
  }

  handleChange(e) {
    let fieldName = e.target.name;
    this.setState({
      [fieldName]: e.target.value
    });
  }

  handleLabelChange(label) {
    this.setState({label})
  }

  handleKeyUp(event) {
    if (event.keyCode === 13) {
      this.handleSubmit(event);
    }
  }

  handleSubmit(event) {
    event.preventDefault();
    let labelAsObject = this.arrayToObject(this.state.label);
    const fieldsToUpdate = {
      title: this.state.title,
      description: this.state.description,
      circle: this.state.circle,
      label: labelAsObject,
      relevantContacts: this.state.relevantContacts,
      assigneePhone: this.state.assigneePhone,
      status: this.state.status,
      type: this.state.type,
      projectName: this.state.projectName
    };
    fieldsToUpdate.dueDate = this.state.dueDate || null;

    this.props.updateTask(this.props.selectedTask, fieldsToUpdate);
  }

  arrayToObject(array) {
    var result = {};
    for (var i = 0; i < array.length; ++i)
      result[array[i]] = true;
    return result;
  }
}

//=====================================
//  CONNECT
//-------------------------------------

const mapStateToProps = createSelector(
  getCommentList,
  getAuth,
  (comments, auth) => ({
    comments,
    auth
  })
);

const mapDispatchToProps = Object.assign(
  {},
);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TaskView);

//export default TaskView;
<commit_msg>Removed unused func<commit_after>import React, { Component } from 'react';
import { ReactDom } from 'react-dom';
import { List } from 'immutable';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { getAuth } from 'src/auth';

import { getCommentList } from 'src/comments';

import './task-view.css';
import Icon from '../icon';
import Textarea from 'react-textarea-autosize';

import Img from 'react-image'
import TagsInput from 'react-tagsinput';
import 'react-tagsinput/react-tagsinput.css';
import Select from 'react-select';
import Button from '../button';
import CommentList from '../comment-list';

export class TaskView extends Component {
  constructor() {
    super(...arguments);

    this.state = {
      title: '',
      description: '',
      circle: '',
      projectName: null,
      defaultCircle: [
        { value: 'אור', label: 'אור' },
        { value: 'אמיר', label: 'אמיר'},
        { value: 'מיכאל', label: 'מיכאל'}
      ],
      type: '',
      defaultType: [
        { value: 1, label: 'תכנון ארוע' },
        { value: 2, label: 'משמרות בארוע (בשביל אחראי משימות משמרות) - טרם נפתח', disabled: true},
        { value: 3, label: 'משימות של מחנות נושא - טרם נפתח', disabled: true},
        { value: 4, label: 'משימות של מיצבי אמנות - טרם נפתח', disabled: true},
        { value: 5, label: 'אחר'}
      ],
      label: [],
      relevantContacts: '',
      assigneePhone: '',
      status: ''
    }

    this.handleChange = this.handleChange.bind(this);
    this.handleLabelChange = this.handleLabelChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  static propTypes = {
    selectTask: PropTypes.func.isRequired,
    updateTask: PropTypes.func.isRequired,
    removeTask: PropTypes.func.isRequired,
    assignTask: PropTypes.func.isRequired,
    selectedTask: PropTypes.object,
    isAdmin: PropTypes.bool.isRequired,
    unloadComments: PropTypes.func.isRequired,
  };

  componentWillMount() {
  }

  componentWillReceiveProps(nextProps) {
    // TODO - check this maybe called several times now that we use comments

    // TODO: On mobile scroll to top - hackish -
    // TODO: should move this to a window resize event...
    if(window.innerWidth < 768) {
      window.scrollTo(0, 150);
    }

    let nextSelectedTask = nextProps.selectedTask || {};
    let { id, title, description, circle, type, projectName,
      label, relevantContacts,
      assigneePhone, status, dueDate, createdDate } = nextSelectedTask;

      // this checks if we got another task, or we're updating the same one
      if (id != this.state.id) {
        const labelAsArray = label ?
          (Object.keys(label).map( l => { return l })) : [];

        this.setState({
          id: id || '',
          title: title || '',
          description:description || '',
          circle:circle || '',
          label: labelAsArray || [],
          relevantContacts:relevantContacts || '',
          assigneePhone:assigneePhone || '',
          status: status || '',
          createdDate: createdDate || '',
          dueDate: dueDate || null,
          type: type || null,
          projectName: projectName || '',
        });
      }

    // if(nextProps.comments.length() != this.state.comments) {
    //   this.props.unloadComments(); //TODO - probably length is not such a good indicator
    //   // TODO - we should unload comments when we're start loading new comments
    // }
  }

  render() {
    //const { task } = this.props;

    const task = this.props.selectedTask;

    if(!task) {
      return(

      );
    }

    const isTaskEmpty = !task.description &&
        !task.circle && !task.status;

    const isUserCreator = task.creator && task.creator.id == this.props.auth.id;

    return (

        <Button className='button-no-border close-button' onClick={ () => this.props.selectTask() }><Icon name='close' className='close-icon grow' /></Button>

        {!task.assignee ? <Button
          className='button button-small action-button assign_task'
          onClick={()=>this.props.assignTask(task)}
          type='button'>קח אחריות על משימה זו</Button> :

            {task.assignee.name}

}

          { isTaskEmpty && isUserCreator ?
          <Button
            className='action-button delete_task'
            onClick={()=> { this.props.removeTask(task); this.props.selectTask(); }}
            type='button'>מחק משימה</Button> : '' }

          <form onSubmit={this.handleSubmit} noValidate>
            {this.renderInput(task, 'title', 'שם המשימה')}
            {this.renderInput(task, 'projectName', 'שם הפרוייקט')}
            {this.renderTextArea(task, 'description', 'תאור המשימה')}
            {this.props.isAdmin?
              this.renderSelect(task, 'circle', 'מעגל', this.state.defaultCircle): ''}

<Icon className='label' name='label_outline' /> {this.renderLabel()}

            { this.renderSelect(task, 'type', 'סוג המשימה', this.state.defaultType)}
            {this.renderTextArea(task, 'relevantContacts', 'אנשי קשר רלוונטיים')}
            {this.renderInput(task, 'assigneePhone', 'טלפון ממלא המשימה')}
            {this.renderTextArea(task, 'status', 'סטטוס המשימה')}
            <input className='button button-small button-save' type="submit" value="שמור" />
          </form>

        { this.props.comments ?
          <CommentList
          task={task}
          comments={this.props.comments}
          auth={this.props.auth}
          createComment={this.props.createComment}/> : ''}

    );
  }

  renderSelect(task, fieldName, placeholder, options) {
    return (
      <Select
      type='text'
      name={fieldName}
      value={this.state[fieldName]}
      placeholder={placeholder}
      ref={e => this[fieldName+'Input'] = e}
      onChange={(e) => { let val=null; if (e) { val = e.value };
                this.setState({ [fieldName]: val}) }}
      options={options}
      onBlur={this.handleSubmit}
      noResultsText={'לא נמצאו תוצאות'}
      searchable={ false } />
  );
  }

  renderInput(task, fieldName, placeholder) {
    return (
        <input
        className='changing-input'
        type = 'text'
        name = { fieldName }
        value = { this.state[fieldName] }
        placeholder = { placeholder }
        ref = { e => this[fieldName+'Input'] = e }
        onChange = { this.handleChange }
        onBlur = { this.handleSubmit } />
    );
  }

  renderTextArea(task, fieldName, placeholder) {
    return (
        <Textarea
        className='changing-input'
        name={fieldName}
        value={this.state[fieldName]}
        placeholder={placeholder}
        ref={e => this[fieldName+'Input'] = e}
        onChange={this.handleChange}
        onBlur={this.handleSubmit}/>
    );
  }

  renderLabel() {
    const showPlaceholder = !this.state.label || this.state.label.length == 0 ;
    return (
      <TagsInput className='react-tagsinput-changing'
      value={this.state.label}
      onChange={this.handleLabelChange}
      onlyUnique={true}
      addOnBlur={true}
      inputProps={{ placeholder: showPlaceholder ? 'הכנס תגיות. לחץ על Enter בין תגית לתגית' : ''}}
      />
    )
  }

  handleChange(e) {
    let fieldName = e.target.name;
    this.setState({
      [fieldName]: e.target.value
    });
  }

  handleLabelChange(label) {
    this.setState({label})
  }

  handleKeyUp(event) {
    if (event.keyCode === 13) {
      this.handleSubmit(event);
    }
  }

  handleSubmit(event) {
    event.preventDefault();
    let labelAsObject = this.arrayToObject(this.state.label);
    const fieldsToUpdate = {
      title: this.state.title,
      description: this.state.description,
      circle: this.state.circle,
      label: labelAsObject,
      relevantContacts: this.state.relevantContacts,
      assigneePhone: this.state.assigneePhone,
      status: this.state.status,
      type: this.state.type,
      projectName: this.state.projectName
    };
    fieldsToUpdate.dueDate = this.state.dueDate || null;

    this.props.updateTask(this.props.selectedTask, fieldsToUpdate);
  }

  arrayToObject(array) {
    var result = {};
    for (var i = 0; i < array.length; ++i)
      result[array[i]] = true;
    return result;
  }
}

//=====================================
//  CONNECT
//-------------------------------------

const mapStateToProps = createSelector(
  getCommentList,
  getAuth,
  (comments, auth) => ({
    comments,
    auth
  })
);

const mapDispatchToProps = Object.assign(
  {},
);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TaskView);

//export default TaskView;
<|endoftext|>


<commit_before>// Copyright 2014 Endless Mobile, Inc.

const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;

const InfiniteScrolledWindow = imports.app.infiniteScrolledWindow;
const SectionPage = imports.app.sectionPage;
const StyleClasses = imports.app.styleClasses;

/**
 * Class: SectionPageA
 *
 * This class extends <SectionPage> and represents the section page for
 * template A of the knowledge apps.
 * It will also be used as the search results page.
 * In addition to the 'title' property published by <SectionPage>, it has
 * a set of articles to show. Articles are represented by cards. Cards are
 * grouped into sections call 'Segments'. A segment has a title, which is the
 * type of cards in its section, and a list of cards to display.
 *
 */
const SectionPageA = new Lang.Class({
    Name: 'SectionPageA',
    GTypeName: 'EknSectionPageA',
    Extends: SectionPage.SectionPage,

    LOADING_BOTTOM_BUFFER: 250,

    _init: function (props) {
        this.parent(props);

        this._segments = {};

        // We need the segment titles of all be right aligned with each other.
        // This gets tricky as they aren't all in the same container, so we
        // will keep them in a size group.
        this._right_column_size_group = new Gtk.SizeGroup({
            mode: Gtk.SizeGroupMode.HORIZONTAL
        });

        this.get_style_context().add_class(StyleClasses.SECTION_PAGE_A);
    },

    pack_title_banner: function (title_banner) {
        title_banner.halign = Gtk.Align.CENTER;
        this._scrolled_window = new InfiniteScrolledWindow.InfiniteScrolledWindow({
            hscrollbar_policy: Gtk.PolicyType.NEVER,
            bottom_buffer: this.LOADING_BOTTOM_BUFFER,
        });
        this._scrolled_window.connect('notify::need-more-content', Lang.bind(this, function () {
            if (this._scrolled_window.need_more_content) {
                this.emit('load-more-results');
            }
        }));

        this._content_grid = new Gtk.Grid({
            orientation: Gtk.Orientation.VERTICAL,
            expand: true,
            valign: Gtk.Align.START,
            row_spacing: 20,
            margin_start: 100,
            margin_end: 100
        });
        this._content_grid.add(title_banner);
        this._scrolled_window.add(this._content_grid);
        this.add(this._scrolled_window);
    },

    /*
     *  Method: append_to_segment
     *
     *  Appends a set of cards to the segment specified by segment_title
     *  If no segment with title of segment_title exists, this will create
     *  one.
     */
    append_to_segment: function (segment_title, cards) {
        if (segment_title in this._segments) {
            this._segments[segment_title].append_cards(cards);
        } else {
            let segment = new CardsSegment({
                title: segment_title
            });
            this._right_column_size_group.add_widget(segment.title_label);
            this._content_grid.add(segment);
            segment.show_all();
            segment.append_cards(cards);
            this._segments[segment_title] = segment;
        }
        this._scrolled_window.need_more_content = false;
    },

    /*
     *  Method: remove_segment
     *
     *  Removes the segment specified by segment_title
     */
    remove_segment: function (segment_title) {
        let segment = this._segments[segment_title];
        this._content_grid.remove(segment);
        this._right_column_size_group.remove_widget(segment.title_label);
        delete this._segments[segment_title];
    },

    remove_all_segments: function () {
        for (let segment_title in this._segments) {
            this.remove_segment(segment_title);
        }
    }
});

const CardsSegment = new Lang.Class({
    Name: 'CardsSegment',
    GTypeName: 'EknCardsSegment',
    Extends: Gtk.Grid,

    Properties: {
        // title property
        // A string with the title of the segment. Defaults to an empty string.
        'title': GObject.ParamSpec.string('title', 'Segment Title',
            'Title of the segment',
            GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE, '')

    },

    _init: function (props) {
        props = props || {};
        props.column_spacing = 20;
        props.row_spacing = 20;
        props.expand = true;

        this.title_label = new Gtk.Label({
            xalign: 1,
            valign: Gtk.Align.START,
            wrap: true,
            justify: Gtk.Justification.RIGHT,
            max_width_chars: 8 // TODO: change this after clarifying with design how resizing should work
        });
        let separator = new Gtk.Separator({
            expand: true,
            halign: Gtk.Align.FILL
        });

        this._flow_box = new Gtk.FlowBox({
            expand: true,
            halign: Gtk.Align.START,
            homogeneous: true
        });

        this._cards = null;

        this.parent(props);

        this.attach(separator, 0, 0, 2, 1);
        this.attach(this.title_label, 0, 1, 1, 1);
        this.attach(this._flow_box, 1, 1, 1, 1);

        this.title_label.get_style_context().add_class(StyleClasses.SECTION_PAGE_A_SEGMENT_TITLE);

    },

    get title () {
        if (this._title)
            return this._title;
        return '';
    },

    set title (v) {
        if (this._title === v) return;
        this._title = v;
        this.title_label.label = this._title.toUpperCase();
        this.notify('title');
    },

    append_cards: function (cards) {
        for (let card of cards) {
            this._flow_box.add(card);
        }
    }
});
<commit_msg>Style cleanup<commit_after>// Copyright 2014 Endless Mobile, Inc.

const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;

const InfiniteScrolledWindow = imports.app.infiniteScrolledWindow;
const SectionPage = imports.app.sectionPage;
const StyleClasses = imports.app.styleClasses;

/**
 * Class: SectionPageA
 *
 * This class extends <SectionPage> and represents the section page for
 * template A of the knowledge apps.
 * It will also be used as the search results page.
 * In addition to the 'title' property published by <SectionPage>, it has
 * a set of articles to show. Articles are represented by cards. Cards are
 * grouped into sections call 'Segments'. A segment has a title, which is the
 * type of cards in its section, and a list of cards to display.
 *
 */
const SectionPageA = new Lang.Class({
    Name: 'SectionPageA',
    GTypeName: 'EknSectionPageA',
    Extends: SectionPage.SectionPage,

    LOADING_BOTTOM_BUFFER: 250,

    _init: function (props) {
        this.parent(props);

        this._segments = {};

        // We need the segment titles of all be right aligned with each other.
        // This gets tricky as they aren't all in the same container, so we
        // will keep them in a size group.
        this._right_column_size_group = new Gtk.SizeGroup({
            mode: Gtk.SizeGroupMode.HORIZONTAL
        });

        this.get_style_context().add_class(StyleClasses.SECTION_PAGE_A);
    },

    pack_title_banner: function (title_banner) {
        title_banner.halign = Gtk.Align.CENTER;
        this._scrolled_window = new InfiniteScrolledWindow.InfiniteScrolledWindow({
            hscrollbar_policy: Gtk.PolicyType.NEVER,
            bottom_buffer: this.LOADING_BOTTOM_BUFFER,
        });
        this._scrolled_window.connect('notify::need-more-content', () => {
            if (this._scrolled_window.need_more_content) {
                this.emit('load-more-results');
            }
        });

        this._content_grid = new Gtk.Grid({
            orientation: Gtk.Orientation.VERTICAL,
            expand: true,
            valign: Gtk.Align.START,
            row_spacing: 20,
            margin_start: 100,
            margin_end: 100
        });
        this._content_grid.add(title_banner);
        this._scrolled_window.add(this._content_grid);
        this.add(this._scrolled_window);
    },

    /*
     *  Method: append_to_segment
     *
     *  Appends a set of cards to the segment specified by segment_title
     *  If no segment with title of segment_title exists, this will create
     *  one.
     */
    append_to_segment: function (segment_title, cards) {
        if (segment_title in this._segments) {
            this._segments[segment_title].append_cards(cards);
        } else {
            let segment = new CardsSegment({
                title: segment_title
            });
            this._right_column_size_group.add_widget(segment.title_label);
            this._content_grid.add(segment);
            segment.show_all();
            segment.append_cards(cards);
            this._segments[segment_title] = segment;
        }
        this._scrolled_window.need_more_content = false;
    },

    /*
     *  Method: remove_segment
     *
     *  Removes the segment specified by segment_title
     */
    remove_segment: function (segment_title) {
        let segment = this._segments[segment_title];
        this._content_grid.remove(segment);
        this._right_column_size_group.remove_widget(segment.title_label);
        delete this._segments[segment_title];
    },

    remove_all_segments: function () {
        for (let segment_title in this._segments) {
            this.remove_segment(segment_title);
        }
    }
});

const CardsSegment = new Lang.Class({
    Name: 'CardsSegment',
    GTypeName: 'EknCardsSegment',
    Extends: Gtk.Grid,

    Properties: {
        // title property
        // A string with the title of the segment. Defaults to an empty string.
        'title': GObject.ParamSpec.string('title', 'Segment Title',
            'Title of the segment',
            GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE, '')

    },

    _init: function (props) {
        props = props || {};
        props.column_spacing = 20;
        props.row_spacing = 20;
        props.expand = true;

        this.title_label = new Gtk.Label({
            xalign: 1,
            valign: Gtk.Align.START,
            wrap: true,
            justify: Gtk.Justification.RIGHT,
            max_width_chars: 8 // TODO: change this after clarifying with design how resizing should work
        });
        let separator = new Gtk.Separator({
            expand: true,
            halign: Gtk.Align.FILL
        });

        this._flow_box = new Gtk.FlowBox({
            expand: true,
            halign: Gtk.Align.START,
            homogeneous: true
        });

        this._cards = null;

        this.parent(props);

        this.attach(separator, 0, 0, 2, 1);
        this.attach(this.title_label, 0, 1, 1, 1);
        this.attach(this._flow_box, 1, 1, 1, 1);

        this.title_label.get_style_context().add_class(StyleClasses.SECTION_PAGE_A_SEGMENT_TITLE);

    },

    get title () {
        if (this._title)
            return this._title;
        return '';
    },

    set title (v) {
        if (this._title === v) return;
        this._title = v;
        this.title_label.label = this._title.toUpperCase();
        this.notify('title');
    },

    append_cards: function (cards) {
        for (let card of cards) {
            this._flow_box.add(card);
        }
    }
});
<|endoftext|>