<commit_before>define(["dojo/_base/lang", "dojo/_base/config", "dojo/ready", "dojo/_base/unload",
        "dojo/_base/sniff", "dojo/request", "dojo/json", "dojo/io-query", "dojo/request/script"
], function(lang, config, ready, unload, has, request, JSON, ioQuery, script){

	var Analytics = function(){
		// summary:
		//		where we store data until we're ready to send it off.

		// the data queue;
		this._data = [];

		// id of messages for this session/page
		this._id = 1;

		// some default values
		this.sendInterval = config["sendInterval"] || 5000;
		this.inTransitRetry = config["inTransitRetry"] || 200;
		this.dataUrl = config["analyticsUrl"] || require.toUrl("dojox/analytics/logger/dojoxAnalytics.php");
		this.sendMethod = config["sendMethod"] || "xhrPost";
		this.maxRequestSize = has("ie") ? 2000 : config["maxRequestSize"] || 4000;

		// while we can go ahead and being logging as soon as this constructor is completed
		// we're not going to schedule pushing data to the server until after the page
		// has completed loading
		ready(this, "schedulePusher");
		unload.addOnUnload(this, "pushData", true);
	};

	lang.extend(Analytics, {
		schedulePusher: function(/* Int */interval){
			// summary:
			//		Schedule the data pushing routines to happen in interval ms
			setTimeout(lang.hitch(this, "checkData"), interval || this.sendInterval);
		},

		addData: function(dataType, data){
			// summary:
			//		add data to the queue. Will be pusshed to the server on the next
			//		data push

			if(arguments.length > 2){
				// FIXME: var c = dojo._toArray(arguments) ?
				data = Array.prototype.slice.call(arguments,1);
			}

			this._data.push({ plugin: dataType, data: data });
		},

		checkData: function(){
			// summary:
			//		TODOC?
			if(this._inTransit){
				this.schedulePusher(this.inTransitRetry);
				return;
			}

			if(this.pushData()){ return; }
			this.schedulePusher();
		},

		pushData: function(){
			// summary:
			//		pushes data to the server if any exists.  If a push is done, return
			//		the deferred after hooking up completion callbacks.  If there is no data
			//		to be pushed, return false;
			if(this._data.length){
				// clear the queue
				this._inTransit = this._data;
				this._data = [];
				var promise;
				switch(this.sendMethod){
					case "script":
						promise = script.get(this.getQueryPacket(), {
							preventCache: 1,
							callbackParamName: "callback"
						});
						break;
					case "xhrPost":
					default:
						promise = request.post(this.dataUrl, {
							data:{
								id: this._id++,
								data: JSON.stringify(this._inTransit)
							}
						});
						break;
				}
				promise.then(function(response){
					this.onPushComplete();
				});
				return promise;
			}
			return false;
		},

		getQueryPacket: function(){
			// TODOC
			while(true){
				var content = {
					id: this._id++,
					data: JSON.stringify(this._inTransit)
				};

				// FIXME would like a much better way to get the query down to length
				var query = this.dataUrl + '?' + ioQuery.objectToQuery(content);
				if(query.length > this.maxRequestSize){
					this._data.unshift(this._inTransit.pop());
					this._split = 1;
				}else{
					return query;
				}
			}
		},

		onPushComplete: function(results){
			// summary:
			//		If our data push was successfully, remove the _inTransit data and schedule the next
			//		parser run.
			if(this._inTransit){
				delete this._inTransit;
			}

			if(this._data.length > 0){
				this.schedulePusher(this.inTransitRetry);
			}else{
				this.schedulePusher();
			}
		}
	});

	// create the analytics singleton
	return lang.setObject("dojox.analytics",new Analytics());
});
<commit_msg>fixes #16229, dojox/analytics should use dojo/request<commit_after>define(["dojo/_base/lang", "dojo/_base/config", "dojo/ready", "dojo/_base/unload",
        "dojo/_base/sniff", "dojo/request", "dojo/json", "dojo/io-query", "dojo/request/script"
], function(lang, config, ready, unload, has, request, JSON, ioQuery, script){

	var Analytics = function(){
		// summary:
		//		where we store data until we're ready to send it off.

		// the data queue;
		this._data = [];

		// id of messages for this session/page
		this._id = 1;

		// some default values
		this.sendInterval = config["sendInterval"] || 5000;
		this.inTransitRetry = config["inTransitRetry"] || 200;
		this.dataUrl = config["analyticsUrl"] || require.toUrl("dojox/analytics/logger/dojoxAnalytics.php");
		this.sendMethod = config["sendMethod"] || "xhrPost";
		this.maxRequestSize = has("ie") ? 2000 : config["maxRequestSize"] || 4000;

		// while we can go ahead and being logging as soon as this constructor is completed
		// we're not going to schedule pushing data to the server until after the page
		// has completed loading
		ready(this, "schedulePusher");
		unload.addOnUnload(this, "pushData", true);
	};

	lang.extend(Analytics, {
		schedulePusher: function(/* Int */interval){
			// summary:
			//		Schedule the data pushing routines to happen in interval ms
			setTimeout(lang.hitch(this, "checkData"), interval || this.sendInterval);
		},

		addData: function(dataType, data){
			// summary:
			//		add data to the queue. Will be pusshed to the server on the next
			//		data push

			if(arguments.length > 2){
				// FIXME: var c = dojo._toArray(arguments) ?
				data = Array.prototype.slice.call(arguments,1);
			}

			this._data.push({ plugin: dataType, data: data });
		},

		checkData: function(){
			// summary:
			//		TODOC?
			if(this._inTransit){
				this.schedulePusher(this.inTransitRetry);
				return;
			}

			if(this.pushData()){ return; }
			this.schedulePusher();
		},

		pushData: function(){
			// summary:
			//		pushes data to the server if any exists.  If a push is done, return
			//		the deferred after hooking up completion callbacks.  If there is no data
			//		to be pushed, return false;
			if(this._data.length){
				// clear the queue
				this._inTransit = this._data;
				this._data = [];
				var promise;
				switch(this.sendMethod){
					case "script":
						promise = script.get(this.getQueryPacket(), {
							preventCache: 1,
							callbackParamName: "callback"
						});
						break;
					case "xhrPost":
					default:
						promise = request.post(this.dataUrl, {
							data:{
								id: this._id++,
								data: JSON.stringify(this._inTransit)
							}
						});
						break;
				}
				promise.then(function(response){
					lang.hitch(this, this.onPushComplete);
				});
				return promise;
			}
			return false;
		},

		getQueryPacket: function(){
			// TODOC
			while(true){
				var content = {
					id: this._id++,
					data: JSON.stringify(this._inTransit)
				};

				// FIXME would like a much better way to get the query down to length
				var query = this.dataUrl + '?' + ioQuery.objectToQuery(content);
				if(query.length > this.maxRequestSize){
					this._data.unshift(this._inTransit.pop());
					this._split = 1;
				}else{
					return query;
				}
			}
		},

		onPushComplete: function(results){
			// summary:
			//		If our data push was successfully, remove the _inTransit data and schedule the next
			//		parser run.
			if(this._inTransit){
				delete this._inTransit;
			}

			if(this._data.length > 0){
				this.schedulePusher(this.inTransitRetry);
			}else{
				this.schedulePusher();
			}
		}
	});

	// create the analytics singleton
	return lang.setObject("dojox.analytics",new Analytics());
});
<|endoftext|>


<commit_before>'use strict';
var boom = require('boom');
var fs = require('fs');
var os = require('os');
var path = require('path');
var _ = require('lodash');
var geojsonhint = require('geojsonhint');
var randomString = require('random-string');
var d3 = require('d3-queue');
var readline = require('readline');
var config = require('./../configs/config');
var format = require('./../utils/formatGeojson');
var client = require('./../utils/connection.js');
var folder = os.tmpDir();

module.exports.listTasks = function(request, reply) {
  client.search({
    index: 'tofix',
    type: 'tasks',
    body: {
      query: {
        match_all: {}
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var tasks = resp.hits.hits.map(function(v) {
      v._source.value.stats = v._source.value.stats[v._source.value.stats.length - 1];
      return v._source;
    });
    reply({
      tasks: tasks
    });
  });
};

module.exports.listTasksById = function(request, reply) {
  var idtask = request.params.idtask;
  client.get({
    index: 'tofix',
    type: 'tasks',
    id: idtask
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    reply(resp._source);
  });
};

module.exports.createTasks = function(request, reply) {
  var data = request.payload;
  if (data.password === config.password) {
    var task = {
      idtask: data.name.concat(randomString({
        length: 5
      })).replace(/[^a-zA-Z]+/g, '').toLowerCase(),
      isCompleted: false,
      value: {
        name: data.name,
        description: data.description,
        updated: Math.round((new Date()).getTime() / 1000),
        changesetComment: data.changesetComment,
        stats: [{
          edit: 0,
          fixed: 0,
          noterror: 0,
          skip: 0
        }]
      }
    };
    var bulk = [];
    var name = data.file.hapi.filename;
    var geojsonFile = path.join(folder, name);
    var file = fs.createWriteStream(geojsonFile);
    file.on('error', function(err) {
      if (err) return reply(boom.badRequest(err));
    });
    data.file.pipe(file);
    data.file.on('end', function(err) {
      if (err) return reply(boom.badRequest(err));
      if (geojsonhint.hint(file) && path.extname(geojsonFile) === '.geojson') { //check  more detail the data
        var q = d3.queue(1);
        q.defer(function(cb) {
          //format geojson file
          format.formatGeojson(geojsonFile, task, function(currentTask) {
            task = currentTask;
            cb();
          });
        });

        q.defer(function(cb) {
          if (!indexExists()) {
            client.indices.create({
              index: 'tofix'
            }, function(err) {
              if (err) return reply(boom.badRequest(err));
              cb();
            });
          } else {
            cb();
          }

        });

        q.defer(function(cb) {
          //set all features in a array to insert massive features  on my type
          var rd = readline.createInterface({
            input: fs.createReadStream(path.join(folder, task.idtask)),
            output: process.stdout,
            terminal: false
          });
          rd.on('line', function(line) {
            var obj = JSON.parse(line);
            bulk.push({
                index: {
                  _index: 'tofix',
                  _type: task.idtask,
                  _id: obj.properties._key
                }
              },
              obj
            );
          }).on('close', function() {
            cb();
          });
        });

        q.defer(function(cb) {
          // save data on type
          var bulkChunks = _.chunk(bulk, config.arrayChunks);
          var counter = 0;
          var errorsCounter = 0;

          function saveData(bulkChunk) {
            client.bulk({
              maxRetries: 5,
              index: 'tofix',
              id: task.idtask,
              type: task.idtask,
              body: bulkChunk
            }, function(err) {
              if (err) {
                //try 3 times to save the chunk
                errorsCounter++;
                if (errorsCounter === 3) {
                  return reply(boom.badRequest(err));
                } else {
                  saveData(bulkChunks[counter]);
                }
              } else {
                counter++;
                if (bulkChunks.length > counter) {
                  saveData(bulkChunks[counter]);
                } else {
                  cb();
                }
              }
            });
          }
          saveData(bulkChunks[0]);
        });
        q.defer(function(cb) {
          // create stats document for each task
          client.create({
            index: 'tofix',
            type: task.idtask + '_stats'
          }, function() {
            cb();
          });
        });

        q.defer(function(cb) {
          // save the task on document
          client.create({
            index: 'tofix',
            id: task.idtask,
            type: 'tasks',
            body: task
          }, function(err) {
            if (err) return reply(boom.badRequest(err));
            cb();
          });
        });
        q.await(function(error) {
          if (error) throw error;
          reply(task);
        });
      } else {
        reply(boom.badData(config.messages.badData));
      }
    });
  } else {
    return reply(boom.badRequest('password does not match'));
  }
};

module.exports.updateTasks = function(request, reply) {
  var data = request.payload;
  var idtask = data.idtask;
  if (data.password === config.password) {
    client.get({
      index: 'tofix',
      type: 'tasks',
      id: idtask
    }, function(err, resp) {
      if (err) return reply(boom.badRequest(err));
      var result = resp._source;
      var task = {
        idtask: idtask,
        isCompleted: (data.isCompleted === "false") ? false : true,
        value: {
          name: data.name,
          description: data.description,
          updated: Math.round((new Date()).getTime() / 1000),
          changesetComment: data.changesetComment,
          stats: result.value.stats
        }
      };
      var bulk = [];
      var bulkToRemove = [];

      if (data.file) {
        task.value.stats.push({
          edit: 0,
          fixed: 0,
          noterror: 0,
          skip: 0
        });
        var name = data.file.hapi.filename;
        var geojsonFile = path.join(folder, name);
        var file = fs.createWriteStream(geojsonFile);
        file.on('error', function(err) {
          if (err) return reply(boom.badRequest(err));
        });
        data.file.pipe(file);
        data.file.on('end', function(err) {
          if (err) return reply(boom.badRequest(err));
          if (geojsonhint.hint(file) && path.extname(geojsonFile) === '.geojson') {
            var q = d3.queue(1);
            q.defer(function(cb) {
              //format geojson file
              format.formatGeojson(geojsonFile, task, function(currentTask) {
                task = currentTask;
                cb();
              });
            });
            q.defer(function(cb) {
              var numItems = 0;
              client.search({
                index: 'tofix',
                type: idtask,
                scroll: '15s'
              }, function getMore(err, resp) {
                if (err) return reply(boom.badRequest(err));
                resp.hits.hits.forEach(function(v) {
                  bulkToRemove.push({
                    delete: {
                      _index: 'tofix',
                      _type: idtask,
                      _id: v._id
                    }
                  });
                  numItems++;
                });
                if (resp.hits.total !== numItems) {
                  client.scroll({
                    scrollId: resp._scroll_id,
                    scroll: '15s'
                  }, getMore);
                } else {
                  cb();
                }
              });
            });

            q.defer(function(cb) {
              //remove items
              client.bulk({
                index: 'tofix',
                id: task.idtask,
                type: task.idtask,
                body: bulkToRemove
              }, function(err) {
                if (err) return reply(boom.badRequest(err));
                cb();
              });
            });

            q.defer(function(cb) {
              //set all features in a array to insert massive features  on my type
              var rd = readline.createInterface({
                input: fs.createReadStream(path.join(folder, task.idtask)),
                output: process.stdout,
                terminal: false
              });
              rd.on('line', function(line) {
                var obj = JSON.parse(line);
                bulk.push({
                    index: {
                      _index: 'tofix',
                      _type: task.idtask,
                      _id: obj.properties._key
                    }
                  },
                  obj
                );
              }).on('close', function() {
                cb();
              });
            });

            q.defer(function(cb) {
              // update data on type
              var bulkChunks = _.chunk(bulk, config.arrayChunks);
              var counter = 0;
              var errorsCounter = 0;

              function saveData(bulkChunk) {
                client.bulk({
                  maxRetries: 5,
                  index: 'tofix',
                  id: task.idtask,
                  type: task.idtask,
                  body: bulkChunk
                }, function(err) {
                  if (err) {
                    //try 3 times to save the chunk
                    errorsCounter++;
                    if (errorsCounter === 3) {
                      return reply(boom.badRequest(err));
                    } else {
                      saveData(bulkChunks[counter]);
                    }
                  } else {
                    counter++;
                    if (bulkChunks.length > counter) {
                      saveData(bulkChunks[counter]);
                    } else {
                      cb();
                    }
                  }
                });
              }
              saveData(bulkChunks[0]);
            });

            q.defer(function(cb) {
              // update the task
              client.update({
                index: 'tofix',
                type: 'tasks',
                id: task.idtask,
                body: {
                  doc: task
                }
              }, function(err) {
                if (err) return reply(boom.badRequest(err));
                cb();
              });
            });

            q.await(function(error) {
              if (error) return reply(boom.badRequest(err));
              reply(task);
            });
          }
        });
      } else {
        client.update({
          index: 'tofix',
          type: 'tasks',
          id: task.idtask,
          body: {
            doc: task
          }
        }, function(err) {
          if (err) return reply(boom.badRequest(err));
          reply(task);
        });
      }
    });
  } else {
    return reply(boom.badRequest('password does not match'));
  }
};

module.exports.deleteTasks = function(request, reply) {
  var data = request.payload;
  var idtask = data.idtask;
  if (data.password === config.password) {
    client.delete({
      index: 'tofix',
      type: 'tasks',
      id: idtask
    }, function(err, resp) {
      if (err) return reply(boom.badRequest(err));
      reply(resp);
    });
  } else {
    return reply(boom.badRequest(config.messages.wrongPassword));
  }
};

module.exports.listTasksActivity = function(request, reply) {
  var idtask = request.params.idtask;
  var from = Math.round(+new Date(request.params.from.split(':')[1]) / 1000);
  var to = Math.round(+new Date(request.params.to.split(':')[1]) / 1000) + 24 * 60 * 60;
  if (from === to) to = to + 86400;
  client.search({
    index: 'tofix',
    type: idtask + '_stats',
    body: {
      sort: {
        'time': {
          order: 'desc'
        }
      },
      query: {
        bool: {
          must: [{
            range: {
              time: {
                gte: from,
                lte: to
              }
            }
          }]
        }
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var activity = resp.hits.hits.map(function(v) {
      return v._source;
    });
    return reply({
      updated: Math.round((new Date()).getTime() / 1000),
      data: activity
    });
  });
};

module.exports.listTasksActivityByUser = function(request, reply) {
  var idtask = request.params.idtask;
  var user = request.params.user;
  var from = Math.round(+new Date(request.params.from.split(':')[1]) / 1000);
  var to = Math.round(+new Date(request.params.to.split(':')[1]) / 1000) + 24 * 60 * 60;
  if (from === to) to = to + 86400;
  client.search({
    index: 'tofix',
    type: idtask + '_stats',
    body: {
      sort: {
        'time': {
          order: 'desc'
        }
      },
      query: {
        bool: {
          must: [{
            range: {
              time: {
                gte: from,
                lte: to
              }
            }
          }]
        }
      },
      filter: {
        term: {
          user: user
        }
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var activity = resp.hits.hits.map(function(v) {
      return v._source;
    });
    return reply({
      updated: Math.round((new Date()).getTime() / 1000),
      data: activity
    });
  });
};

module.exports.trackStats = function(request, reply) {
  var idtask = request.params.idtask;
  var from = Math.round(+new Date(request.params.from.split(':')[1]) / 1000);
  var to = Math.round(+new Date(request.params.to.split(':')[1]) / 1000) + 24 * 60 * 60;
  if (from === to) to = to + 86400;
  client.search({
    index: 'tofix',
    type: idtask + '_stats',
    body: {
      sort: {
        'time': {
          order: 'desc'
        }
      },
      query: {
        bool: {
          must: [{
            range: {
              time: {
                gte: from,
                lte: to
              }
            }
          }]
        }
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var activity = resp.hits.hits;
    var data = {};
    activity.forEach(function(v) {
      v = v._source;
      if (!data[v.user]) {
        data[v.user] = {
          edit: 0,
          fixed: 0,
          noterror: 0,
          skip: 0,
          user: v.user
        };
        data[v.user][v.action] = data[v.user][v.action] + 1;
      } else {
        data[v.user][v.action] = data[v.user][v.action] + 1;
      }
    });

    reply({
      updated: Math.round((new Date()).getTime() / 1000),
      stats: _.values(data)
    });
  });
};

function indexExists() {
  return client.indices.exists({
    index: 'tofix'
  });
}
<commit_msg>update<commit_after>'use strict';
var boom = require('boom');
var fs = require('fs');
var os = require('os');
var path = require('path');
var _ = require('lodash');
var geojsonhint = require('geojsonhint');
var randomString = require('random-string');
var d3 = require('d3-queue');
var readline = require('readline');
var config = require('./../configs/config');
var format = require('./../utils/formatGeojson');
var client = require('./../utils/connection.js');
var folder = os.tmpDir();

module.exports.listTasks = function(request, reply) {
  client.search({
    index: 'tofix',
    type: 'tasks',
    body: {
      query: {
        match_all: {}
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var tasks = resp.hits.hits.map(function(v) {
      v._source.value.stats = v._source.value.stats[v._source.value.stats.length - 1];
      return v._source;
    });
    reply({
      tasks: tasks
    });
  });
};

module.exports.listTasksById = function(request, reply) {
  var idtask = request.params.idtask;
  client.get({
    index: 'tofix',
    type: 'tasks',
    id: idtask
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    reply(resp._source);
  });
};

module.exports.createTasks = function(request, reply) {
  var data = request.payload;
  if (data.password === config.password) {
    var task = {
      idtask: data.name.concat(randomString({
        length: 5
      })).replace(/[^a-zA-Z]+/g, '').toLowerCase(),
      isCompleted: false,
      value: {
        name: data.name,
        description: data.description,
        updated: Math.round((new Date()).getTime() / 1000),
        changesetComment: data.changesetComment,
        stats: [{
          edit: 0,
          fixed: 0,
          noterror: 0,
          skip: 0
        }]
      }
    };
    var bulk = [];
    var name = data.file.hapi.filename;
    var geojsonFile = path.join(folder, name);
    var file = fs.createWriteStream(geojsonFile);
    file.on('error', function(err) {
      if (err) return reply(boom.badRequest(err));
    });
    data.file.pipe(file);
    data.file.on('end', function(err) {
      if (err) return reply(boom.badRequest(err));
      if (geojsonhint.hint(file) && path.extname(geojsonFile) === '.geojson') { //check  more detail the data
        var q = d3.queue(1);
        q.defer(function(cb) {
          //format geojson file
          format.formatGeojson(geojsonFile, task, function(currentTask) {
            task = currentTask;
            cb();
          });
        });

        q.defer(function(cb) {
          if (!indexExists()) {
            client.indices.create({
              index: 'tofix'
            }, function(err) {
              if (err) return reply(boom.badRequest(err));
              cb();
            });
          } else {
            cb();
          }

        });

        q.defer(function(cb) {
          //set all features in a array to insert massive features  on my type
          var rd = readline.createInterface({
            input: fs.createReadStream(path.join(folder, task.idtask)),
            output: process.stdout,
            terminal: false
          });
          rd.on('line', function(line) {
            var obj = JSON.parse(line);
            bulk.push({
                index: {
                  _index: 'tofix',
                  _type: task.idtask,
                  _id: obj.properties._key
                }
              },
              obj
            );
          }).on('close', function() {
            cb();
          });
        });

        q.defer(function(cb) {
          // save data on type
          var bulkChunks = _.chunk(bulk, config.arrayChunks);
          var counter = 0;
          var errorsCounter = 0;

          function saveData(bulkChunk) {
            client.bulk({
              maxRetries: 5,
              index: 'tofix',
              id: task.idtask,
              type: task.idtask,
              body: bulkChunk
            }, function(err) {
              if (err) {
                //try 3 times to save the chunk
                errorsCounter++;
                if (errorsCounter === 3) {
                  return reply(boom.badRequest(err));
                } else {
                  saveData(bulkChunks[counter]);
                }
              } else {
                counter++;
                if (bulkChunks.length > counter) {
                  saveData(bulkChunks[counter]);
                } else {
                  cb();
                }
              }
            });
          }
          saveData(bulkChunks[0]);
        });
        q.defer(function(cb) {
          // create stats document for each task
          client.create({
            index: 'tofix',
            type: task.idtask + '_stats'
          }, function() {
            cb();
          });
        });

        q.defer(function(cb) {
          // save the task on document
          client.create({
            index: 'tofix',
            id: task.idtask,
            type: 'tasks',
            body: task
          }, function(err) {
            if (err) return reply(boom.badRequest(err));
            cb();
          });
        });
        q.await(function(error) {
          if (error) throw error;
          reply(task);
        });
      } else {
        reply(boom.badData(config.messages.badData));
      }
    });
  } else {
    return reply(boom.badRequest('password does not match'));
  }
};

module.exports.updateTasks = function(request, reply) {
  var data = request.payload;
  var idtask = data.idtask;
  if (data.password === config.password) {
    client.get({
      index: 'tofix',
      type: 'tasks',
      id: idtask
    }, function(err, resp) {
      if (err) return reply(boom.badRequest(err));
      var result = resp._source;
      var task = {
        idtask: idtask,
        isCompleted: (data.isCompleted === 'false') ? false : true,
        value: {
          name: data.name,
          description: data.description,
          updated: Math.round((new Date()).getTime() / 1000),
          changesetComment: data.changesetComment,
          stats: result.value.stats
        }
      };
      var bulk = [];
      var bulkToRemove = [];

      if (data.file) {
        task.value.stats.push({
          edit: 0,
          fixed: 0,
          noterror: 0,
          skip: 0
        });
        var name = data.file.hapi.filename;
        var geojsonFile = path.join(folder, name);
        var file = fs.createWriteStream(geojsonFile);
        file.on('error', function(err) {
          if (err) return reply(boom.badRequest(err));
        });
        data.file.pipe(file);
        data.file.on('end', function(err) {
          if (err) return reply(boom.badRequest(err));
          if (geojsonhint.hint(file) && path.extname(geojsonFile) === '.geojson') {
            var q = d3.queue(1);
            q.defer(function(cb) {
              //format geojson file
              format.formatGeojson(geojsonFile, task, function(currentTask) {
                task = currentTask;
                cb();
              });
            });
            q.defer(function(cb) {
              var numItems = 0;
              client.search({
                index: 'tofix',
                type: idtask,
                scroll: '15s'
              }, function getMore(err, resp) {
                if (err) return reply(boom.badRequest(err));
                resp.hits.hits.forEach(function(v) {
                  bulkToRemove.push({
                    delete: {
                      _index: 'tofix',
                      _type: idtask,
                      _id: v._id
                    }
                  });
                  numItems++;
                });
                if (resp.hits.total !== numItems) {
                  client.scroll({
                    scrollId: resp._scroll_id,
                    scroll: '15s'
                  }, getMore);
                } else {
                  cb();
                }
              });
            });

            q.defer(function(cb) {
              //remove items
              client.bulk({
                index: 'tofix',
                id: task.idtask,
                type: task.idtask,
                body: bulkToRemove
              }, function(err) {
                if (err) return reply(boom.badRequest(err));
                cb();
              });
            });

            q.defer(function(cb) {
              //set all features in a array to insert massive features  on my type
              var rd = readline.createInterface({
                input: fs.createReadStream(path.join(folder, task.idtask)),
                output: process.stdout,
                terminal: false
              });
              rd.on('line', function(line) {
                var obj = JSON.parse(line);
                bulk.push({
                    index: {
                      _index: 'tofix',
                      _type: task.idtask,
                      _id: obj.properties._key
                    }
                  },
                  obj
                );
              }).on('close', function() {
                cb();
              });
            });

            q.defer(function(cb) {
              // update data on type
              var bulkChunks = _.chunk(bulk, config.arrayChunks);
              var counter = 0;
              var errorsCounter = 0;

              function saveData(bulkChunk) {
                client.bulk({
                  maxRetries: 5,
                  index: 'tofix',
                  id: task.idtask,
                  type: task.idtask,
                  body: bulkChunk
                }, function(err) {
                  if (err) {
                    //try 3 times to save the chunk
                    errorsCounter++;
                    if (errorsCounter === 3) {
                      return reply(boom.badRequest(err));
                    } else {
                      saveData(bulkChunks[counter]);
                    }
                  } else {
                    counter++;
                    if (bulkChunks.length > counter) {
                      saveData(bulkChunks[counter]);
                    } else {
                      cb();
                    }
                  }
                });
              }
              saveData(bulkChunks[0]);
            });

            q.defer(function(cb) {
              // update the task
              client.update({
                index: 'tofix',
                type: 'tasks',
                id: task.idtask,
                body: {
                  doc: task
                }
              }, function(err) {
                if (err) return reply(boom.badRequest(err));
                cb();
              });
            });

            q.await(function(error) {
              if (error) return reply(boom.badRequest(err));
              reply(task);
            });
          }
        });
      } else {
        client.update({
          index: 'tofix',
          type: 'tasks',
          id: task.idtask,
          body: {
            doc: task
          }
        }, function(err) {
          if (err) return reply(boom.badRequest(err));
          reply(task);
        });
      }
    });
  } else {
    return reply(boom.badRequest('password does not match'));
  }
};

module.exports.deleteTasks = function(request, reply) {
  var data = request.payload;
  var idtask = data.idtask;
  if (data.password === config.password) {
    client.delete({
      index: 'tofix',
      type: 'tasks',
      id: idtask
    }, function(err, resp) {
      if (err) return reply(boom.badRequest(err));
      reply(resp);
    });
  } else {
    return reply(boom.badRequest(config.messages.wrongPassword));
  }
};

module.exports.listTasksActivity = function(request, reply) {
  var idtask = request.params.idtask;
  var from = Math.round(+new Date(request.params.from.split(':')[1]) / 1000);
  var to = Math.round(+new Date(request.params.to.split(':')[1]) / 1000) + 24 * 60 * 60;
  if (from === to) to = to + 86400;
  client.search({
    index: 'tofix',
    type: idtask + '_stats',
    body: {
      sort: {
        'time': {
          order: 'desc'
        }
      },
      query: {
        bool: {
          must: [{
            range: {
              time: {
                gte: from,
                lte: to
              }
            }
          }]
        }
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var activity = resp.hits.hits.map(function(v) {
      return v._source;
    });
    return reply({
      updated: Math.round((new Date()).getTime() / 1000),
      data: activity
    });
  });
};

module.exports.listTasksActivityByUser = function(request, reply) {
  var idtask = request.params.idtask;
  var user = request.params.user;
  var from = Math.round(+new Date(request.params.from.split(':')[1]) / 1000);
  var to = Math.round(+new Date(request.params.to.split(':')[1]) / 1000) + 24 * 60 * 60;
  if (from === to) to = to + 86400;
  client.search({
    index: 'tofix',
    type: idtask + '_stats',
    body: {
      sort: {
        'time': {
          order: 'desc'
        }
      },
      query: {
        bool: {
          must: [{
            range: {
              time: {
                gte: from,
                lte: to
              }
            }
          }]
        }
      },
      filter: {
        term: {
          user: user
        }
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var activity = resp.hits.hits.map(function(v) {
      return v._source;
    });
    return reply({
      updated: Math.round((new Date()).getTime() / 1000),
      data: activity
    });
  });
};

module.exports.trackStats = function(request, reply) {
  var idtask = request.params.idtask;
  var from = Math.round(+new Date(request.params.from.split(':')[1]) / 1000);
  var to = Math.round(+new Date(request.params.to.split(':')[1]) / 1000) + 24 * 60 * 60;
  if (from === to) to = to + 86400;
  client.search({
    index: 'tofix',
    type: idtask + '_stats',
    body: {
      sort: {
        'time': {
          order: 'desc'
        }
      },
      query: {
        bool: {
          must: [{
            range: {
              time: {
                gte: from,
                lte: to
              }
            }
          }]
        }
      }
    }
  }, function(err, resp) {
    if (err) return reply(boom.badRequest(err));
    var activity = resp.hits.hits;
    var data = {};
    activity.forEach(function(v) {
      v = v._source;
      if (!data[v.user]) {
        data[v.user] = {
          edit: 0,
          fixed: 0,
          noterror: 0,
          skip: 0,
          user: v.user
        };
        data[v.user][v.action] = data[v.user][v.action] + 1;
      } else {
        data[v.user][v.action] = data[v.user][v.action] + 1;
      }
    });

    reply({
      updated: Math.round((new Date()).getTime() / 1000),
      stats: _.values(data)
    });
  });
};

function indexExists() {
  return client.indices.exists({
    index: 'tofix'
  });
}
<|endoftext|>


<commit_before>import React from 'react';
import {connect} from 'react-redux';
import Immutable from 'immutable';

import {CONFIG} from 'dashboard/config';
import {Input, Textarea} from 'views';

class Config extends React.Component {
  render(){
    return

      Hello World!

;
  }
}

export {Config};
<commit_msg>config page<commit_after>import React from 'react';
import {connect} from 'react-redux';
import Immutable from 'immutable';

import {CONFIG} from 'dashboard/config';
import {fetchConfigAction} from 'dashboard/reducers/actions';
import {makeGetConfig, getConfigRequest, getLogin, getLoginExpiresAt, getLoginValid} from 'dashboard/reducers/selectors';
import {Input, Textarea} from 'views';

class Config extends React.Component {
  componentWillMount(){
    this.props.fetchConfig('navigation');
  }
  render(){
    return

      {(!this.props.config.loading && !this.props.config.failed) && this.props.config.content &&
        JSON.stringify(this.props.config.content)
      }

;
  }
}

const makeMapStateToProps = ()=>{
  const getConfig = makeGetConfig();
  return (state)=>{
    return {
      config: getConfig(state),
      request: getConfigRequest(state),
      logininfo: getLogin(state),
      loginExpiresAt: getLoginExpiresAt(state)
    };
  };
};

const mapDispatchToProps = (dispatch)=>{
  return {
    fetchConfig: (configid, method=false, body=false)=>{
      dispatch(fetchConfigAction(CONFIG.retrieve('baseConfigUrl'), configid, method, body));
    },
    loginValid: (time)=>{
      return getLoginValid(time);
    }
  };
};

Config = connect(
  makeMapStateToProps,
  mapDispatchToProps
)(Config);

export {Config};
<|endoftext|>


<commit_before>/**
 * Sustainable Solutions (NZ) Ltd. 2020
 * mSupply Mobile
 */

import Realm from 'realm';

export class Location extends Realm.Object {
  get mostRecentTemperatureLog() {
    return this.temperatureLogs.sorted('timestamp', true)[0];
  }

  get mostRecentTemperatureBreach() {
    return this.breaches.sorted('startTimestamp', true)[0];
  }

  get leastRecentTemperatureLog() {
    return this.temperatureLogs.sorted('timestamp', false)[0];
  }

  /**
   * This location is currently experiencing a temperature breach
   * if the most recent breach for the location has no end timestamp.
   */
  get hasBreached() {
    const mostRecentBreach = this.mostRecentTemperatureBreach;
    return mostRecentBreach && !mostRecentBreach.endTimestamp;
  }

  get currentTemperature() {
    const { temperature } = this.mostRecentTemperatureLog ?? {};
    return temperature;
  }

  get numberOfBreaches() {
    return this.breaches.length;
  }

  get temperatureExposure() {
    const minimumTemperature = this.temperatureLogs.min('temperature') ?? Infinity;
    const maximumTemperature = this.temperatureLogs.max('temperature') ?? -Infinity;

    return { minimumTemperature, maximumTemperature };
  }

  batchesDuringTime(database, startTimestamp, endTimestamp) {
    const locationMovements = this.locationMovements.filtered(
      '(enterTimestamp <= $0 && (exitTimestamp > $0 || exitTimestamp == null)) ||' +
        '(enterTimestamp >= $0 && enterTimestamp <= $1)',
      startTimestamp ?? new Date(),
      endTimestamp ?? new Date()
    );

    return locationMovements.map(({ itemBatch }) => itemBatch);
  }

  totalStock() {
    return this.batches.sum('numberOfPacks') ?? 0;
  }

  get hotCumulativeBreachConfig() {
    return this.breachConfigs.filtered("type == 'HOT_CUMULATIVE'")[0];
  }

  get coldCumulativeBreachConfig() {
    return this.breachConfigs.filtered("type == 'COLD_CUMULATIVE'")[0];
  }

  get hotConsecutiveBreachConfig() {
    return this.breachConfigs.filtered("type == 'HOT_CONSECUTIVE'")[0];
  }

  get coldConsecutiveBreachConfig() {
    return this.breachConfigs.filtered("type == 'COLD_CONSECUTIVE'")[0];
  }

  get isInHotBreach() {
    return !!this.breaches.filtered('type == "HOT_CONSECUTIVE" && endTimestamp == null')[0];
  }

  get isInColdBreach() {
    return !!this.breaches.filtered('type == "COLD_CONSECUTIVE" && endTimestamp == null')[0];
  }

  // Sensor to location should be a one to one relationship at all times. Pick the first and
  // make the assumption it is the correct one.
  get sensor() {
    return this.sensors[0];
  }

  get batteryLevel() {
    return this.sensor?.batteryLevel ?? 0;
  }
}

Location.schema = {
  name: 'Location',
  primaryKey: 'id',
  properties: {
    id: 'string',
    description: { type: 'string', default: '' },
    code: { type: 'string', default: '' },
    locationType: { type: 'LocationType', optional: true },
    locationMovements: {
      type: 'linkingObjects',
      objectType: 'LocationMovement',
      property: 'location',
    },
    sensors: {
      type: 'linkingObjects',
      objectType: 'Sensor',
      property: 'location',
    },
    temperatureLogs: {
      type: 'linkingObjects',
      objectType: 'TemperatureLog',
      property: 'location',
    },
    breaches: {
      type: 'linkingObjects',
      objectType: 'TemperatureBreach',
      property: 'location',
    },
    batches: {
      type: 'linkingObjects',
      objectType: 'ItemBatch',
      property: 'location',
    },
    breachConfigs: {
      type: 'linkingObjects',
      objectType: 'TemperatureBreachConfiguration',
      property: 'location',
    },
  },
};

export default Location;
<commit_msg>Add change up of getters to use a currentBreach getter<commit_after>/**
 * Sustainable Solutions (NZ) Ltd. 2020
 * mSupply Mobile
 */

import Realm from 'realm';

export class Location extends Realm.Object {
  get mostRecentTemperatureLog() {
    return this.temperatureLogs.sorted('timestamp', true)[0];
  }

  get mostRecentTemperatureBreach() {
    return this.breaches.sorted('startTimestamp', true)[0];
  }

  get leastRecentTemperatureLog() {
    return this.temperatureLogs.sorted('timestamp', false)[0];
  }

  /**
   * This location is currently experiencing a temperature breach
   * if the most recent breach for the location has no end timestamp.
   */
  get hasBreached() {
    const mostRecentBreach = this.mostRecentTemperatureBreach;
    return mostRecentBreach && !mostRecentBreach.endTimestamp;
  }

  get currentTemperature() {
    const { temperature } = this.mostRecentTemperatureLog ?? {};
    return temperature;
  }

  get numberOfBreaches() {
    return this.breaches.length;
  }

  get temperatureExposure() {
    const minimumTemperature = this.temperatureLogs.min('temperature') ?? Infinity;
    const maximumTemperature = this.temperatureLogs.max('temperature') ?? -Infinity;

    return { minimumTemperature, maximumTemperature };
  }

  batchesDuringTime(database, startTimestamp, endTimestamp) {
    const locationMovements = this.locationMovements.filtered(
      '(enterTimestamp <= $0 && (exitTimestamp > $0 || exitTimestamp == null)) ||' +
        '(enterTimestamp >= $0 && enterTimestamp <= $1)',
      startTimestamp ?? new Date(),
      endTimestamp ?? new Date()
    );

    return locationMovements.map(({ itemBatch }) => itemBatch);
  }

  totalStock() {
    return this.batches.sum('numberOfPacks') ?? 0;
  }

  get hotCumulativeBreachConfig() {
    return this.breachConfigs.filtered("type == 'HOT_CUMULATIVE'")[0];
  }

  get coldCumulativeBreachConfig() {
    return this.breachConfigs.filtered("type == 'COLD_CUMULATIVE'")[0];
  }

  get hotConsecutiveBreachConfig() {
    return this.breachConfigs.filtered("type == 'HOT_CONSECUTIVE'")[0];
  }

  get coldConsecutiveBreachConfig() {
    return this.breachConfigs.filtered("type == 'COLD_CONSECUTIVE'")[0];
  }

  get currentBreach() {
    return this.breaches.filtered('endTimestamp == null')[0];
  }

  get isInHotBreach() {
    return !!this.currentBreach?.type === 'HOT_CONSECUTIVE';
  }

  get isInColdBreach() {
    return !!this.currentBreach?.type === 'COLD_CONSECUTIVE';
  }

  // Sensor to location should be a one to one relationship at all times. Pick the first and
  // make the assumption it is the correct one.
  get sensor() {
    return this.sensors[0];
  }

  get batteryLevel() {
    return this.sensor?.batteryLevel ?? 0;
  }
}

Location.schema = {
  name: 'Location',
  primaryKey: 'id',
  properties: {
    id: 'string',
    description: { type: 'string', default: '' },
    code: { type: 'string', default: '' },
    locationType: { type: 'LocationType', optional: true },
    locationMovements: {
      type: 'linkingObjects',
      objectType: 'LocationMovement',
      property: 'location',
    },
    sensors: {
      type: 'linkingObjects',
      objectType: 'Sensor',
      property: 'location',
    },
    temperatureLogs: {
      type: 'linkingObjects',
      objectType: 'TemperatureLog',
      property: 'location',
    },
    breaches: {
      type: 'linkingObjects',
      objectType: 'TemperatureBreach',
      property: 'location',
    },
    batches: {
      type: 'linkingObjects',
      objectType: 'ItemBatch',
      property: 'location',
    },
    breachConfigs: {
      type: 'linkingObjects',
      objectType: 'TemperatureBreachConfiguration',
      property: 'location',
    },
  },
};

export default Location;
<|endoftext|>


<commit_before>import Realm from 'realm';

export class NameNote extends Realm.Object {
  get data() {
    try {
      return JSON.parse(this._data);
    } catch {
      // swallow error, return a default
      return null;
    }
  }

  // Will throw if newValue is unable to be stringified
  set data(newValue) {
    this._data = JSON.stringify(newValue);
  }

  get patientEventID() {
    return this.patientEvent?.id;
  }

  toObject() {
    return {
      id: this.id,
      entryDate: this.entryDate.getTime(),
      data: this.data,
      nameID: this.name.id,
      patientEventID: this.patientEvent.id,
    };
  }
}

NameNote.schema = {
  name: 'NameNote',
  primaryKey: 'id',
  properties: {
    id: 'string',
    entryDate: { type: 'date', default: new Date() },
    _data: { type: 'string', optional: true },
    name: 'Name',
    patientEvent: 'PatientEvent',
  },
};

export default NameNote;
<commit_msg>Add crash prevention when a name not does not have a patient event<commit_after>import Realm from 'realm';

export class NameNote extends Realm.Object {
  get data() {
    try {
      return JSON.parse(this._data);
    } catch {
      // swallow error, return a default
      return null;
    }
  }

  // Will throw if newValue is unable to be stringified
  set data(newValue) {
    this._data = JSON.stringify(newValue);
  }

  get patientEventID() {
    return this.patientEvent?.id;
  }

  toObject() {
    return {
      id: this.id,
      entryDate: this.entryDate.getTime(),
      data: this.data,
      nameID: this.name.id,
      patientEventID: this.patientEvent?.id,
    };
  }
}

NameNote.schema = {
  name: 'NameNote',
  primaryKey: 'id',
  properties: {
    id: 'string',
    entryDate: { type: 'date', default: new Date() },
    _data: { type: 'string', optional: true },
    name: 'Name',
    patientEvent: 'PatientEvent',
  },
};

export default NameNote;
<|endoftext|>


<commit_before>
CPM.treemap = function(data, at) {

	var roots = [];
	$.each(data, function(idx, cls) {
		var p = cls.package;
		while(p.parent) {
			p = p.parent;
		}
		// this will be inefficient if there are many roots
		if (roots.indexOf(p) < 0) {
			roots.push(p);
		}
	})
	var root = (roots.length == 1) ? roots[0] : { name: "", children: roots };

	var fscale = d3.scale.linear()
    .domain([0, d3.max(data, function(d) { return CPM.getv(d, at.shade) })])
    .range([100, 20]);

	var layout = d3.layout.treemap()
		.size([699, 699])
		.padding(3)
		.mode("squarify")
		.round(true)
		.value(function(d) { return CPM.getv(d, at.order) });

	var nodes = layout.nodes(root);

	d3.selectAll("svg").remove();
	var chart = d3.select("#chart-wrapper").append("svg")
    .attr("class", "chart")
    .attr("width", 700)
    .attr("height", 700);

	chart.selectAll("rect")
	  .data(nodes)
	  .enter()
	  .append("rect")
		.attr("x", function(d) { return d.x })
		.attr("y", function(d) { return d.y + 1 })
		.attr("width", function(d) { return d.dx })
		.attr("height", function(d) { return d.dy })
		.attr("shape-rendering", "crispEdges")
		.style("fill", function(d) {
			switch(d.type) {
			case "Class": return "hsl(200, 80%, " + fscale(CPM.getv(d, at.shade)) + "%)";
			case "Package": return "#CCC";
			default: return "white";
			}
		})
		.call(tooltip());

}

<commit_msg>Reverse order.<commit_after>
CPM.treemap = function(data, at) {

	var roots = [];
	$.each(data, function(idx, cls) {
		var p = cls.package;
		while(p.parent) {
			p = p.parent;
		}
		// this will be inefficient if there are many roots
		if (roots.indexOf(p) < 0) {
			roots.push(p);
		}
	})
	var root = (roots.length == 1) ? roots[0] : { name: "", children: roots };

	var fscale = d3.scale.linear()
    .domain([0, d3.max(data, function(d) { return CPM.getv(d, at.shade) })])
    .range([100, 20]);

	var layout = d3.layout.treemap()
		.size([699, 699])
		.padding(3)
		.mode("squarify")
		.round(true)
		.sort(function(da, db) { return CPM.getv(da, at.order) - CPM.getv(db, at.order) })
		.value(function(d) { return CPM.getv(d, at.order) });

	var nodes = layout.nodes(root);

	d3.selectAll("svg").remove();
	var chart = d3.select("#chart-wrapper").append("svg")
    .attr("class", "chart")
    .attr("width", 700)
    .attr("height", 700);

	chart.selectAll("rect")
	  .data(nodes)
	  .enter()
	  .append("rect")
		.attr("x", function(d) { return d.x })
		.attr("y", function(d) { return d.y + 1 })
		.attr("width", function(d) { return d.dx })
		.attr("height", function(d) { return d.dy })
		.attr("shape-rendering", "crispEdges")
		.style("fill", function(d) {
			switch(d.type) {
			case "Class": return "hsl(200, 80%, " + fscale(CPM.getv(d, at.shade)) + "%)";
			case "Package": return "#CCC";
			default: return "white";
			}
		})
		.call(tooltip());

}

<|endoftext|>


<commit_before>
angular.module('dd.ui.dd-timepicker', [])
    .directive('ddTimepicker', TimepickerDirective)
    .service('timeparserService', timeparserService);

var KEY_ENTER = 13, KEY_UP = 38, KEY_DOWN = 40;

TimepickerDirective.$inject = ['dateFilter', 'timeparserService'];
function TimepickerDirective(dateFilter, timeparserService) {

    var directive = {
        restrict: 'A',
        require: 'ngModel',
        replace: true,
        scope: {
            ngModel: '=',
            minuteStep: '=?',
            isDateType: '=?'
        },
        link: function (scope, element, attrs, ctrl) {

            var dateTime = scope.isDateType && scope.ngModel instanceof Date ? scope.ngModel : new Date();
            scope.minuteStep = scope.minuteStep || 1;

            ctrl.$viewChangeListeners.push(function () {
                scope.$eval(attrs.onChange);
            });

            //(view to model)
            ctrl.$parsers.push(function (value) {
                return timeparserService.toModel(value, scope.isDateType, dateTime);
            });

            //(model to view)
            ctrl.$formatters.push(function (value) {
                return timeparserService.toView(value);
            });

            element.on('keydown keypress', function (event) {
                if (event.which === KEY_ENTER && !ctrl.$modelValue) {
                    updateViewValue(timeparserService.getFormattedTime());
                    event.preventDefault();
                } else if (event.which === KEY_UP) {
                    updateViewValue(timeparserService.changeTime(scope.ngModel, scope.minuteStep));
                    event.preventDefault();
                } else if (event.which === KEY_DOWN) {
                    updateViewValue(timeparserService.changeTime(scope.ngModel, -scope.minuteStep));
                    event.preventDefault();
                }
            });

            element.on('blur', function toModelTime() {
                updateViewValue(timeparserService.toView(scope.ngModel));
            });

            function updateViewValue(value) {
                ctrl.$setViewValue(value);
                ctrl.$render();
                applyNgChange();
            }

            function applyNgChange() {
                if (scope.ngChange) {
                    scope.ngChange();
                }
            }
        }
    };

    return directive;

}

timeparserService.$inject = ['dateFilter'];
function timeparserService(dateFilter) {
    var self = this;

    var amPmPattern = /^(\d+)(a|p)$/,
        normalTimePattern = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[.:][0-5][0-9]$/,
        digitsPattern = /^[0-9]+$/;

    self.toModel = toModel;
    self.toView = toView;
    self.changeTime = changeTime;
    self.getFormattedTime = getFormattedTime;

    function toModel(input, isDateModel, dateTime) {

        var parsedTime = null;

        if (!input) {
            return null;
        }

        if (normalTimePattern.test(input)) {
            parsedTime = parseNormalTime(input);
            return parsedTimeToModel(parsedTime, isDateModel, dateTime);
        }

        input = prepareInput(input);

        if (amPmPattern.test(input)) {
            parsedTime = parseAmPmTime(input, amPmPattern);
            return parsedTimeToModel(parsedTime, isDateModel, dateTime);
        }

        if (digitsPattern.test(input)) {
            parsedTime = parseDigitsTime(input, digitsPattern);
            return parsedTimeToModel(parsedTime, isDateModel, dateTime);
        }

        return null;
    }

    function toView(input) {
        if (input instanceof Date) {
            return getFormattedTime(input);
        }
        return input;
    }

    function changeTime(modelValue, delta) {
        var timeInfo = getTimeInfoFromString(prepareInput(modelValue));

        var date = new Date();
        date.setHours(timeInfo.hours);
        date.setMinutes(timeInfo.minutes + delta);

        return dateFilter(date, 'HH:mm');
    }

    function getFormattedTime(dateInstance) {
        var date = dateInstance || new Date();
        return dateFilter(date, 'HH:mm');
    }

    //private

    function parsedTimeToModel(parsedTime, isDateModel, dateTime) {

        if (!parsedTime) {
            return null;
        }

        if (isDateModel) {
            var tokens = parsedTime.split(':');
            dateTime.setHours(parseInt(tokens[0]));
            dateTime.setMinutes(parseInt(tokens[1]));
            return new Date(dateTime);
        }

        return parsedTime;
    }

    function parseAmPmTime(input, pattern) {
        var tokens = tokenize(input, pattern),
            timeInfo = getTimeInfoFromString(tokens[1], tokens[2]);

        return validateParsedTime(timeInfoToString(timeInfo));
    }

    function parseDigitsTime(input) {
        var timeInfo = getTimeInfoFromString(input, null);
        return validateParsedTime(timeInfoToString(timeInfo));
    }

    function parseNormalTime(input) {
        input = prepareInput(input);
        var timeInfo = getTimeInfoFromString(input, null);
        return timeInfoToString(timeInfo);
    }

    function tokenize(input, pattern) {
        return pattern.exec(input);
    }

    function getTimeInfoFromString(inputTime, mode) {

        if (inputTime[0] === '0') {
            inputTime = inputTime.replace(/^0/, '');
        }

        var val = parseInt(inputTime),
            hours = 0,
            minutes = 0;

        //user enter only minutes (mm)
        if (inputTime[0] === '0') {
            minutes = parseInt(inputTime);
        }
        //user enter only hour (H)
        else if (val <= 24 && inputTime.length <= 2) {
            hours = val;
        }
        // user enter hour and minutes (H:mm)
        else if (val > 24 && val <= 999) {
            hours = parseInt(inputTime[0]);
            minutes = parseInt(inputTime.substr(1, 3));
        }
        // user enter hours and minutes (HH:mm)
        else if (val > 24 && val <= 9999) {
            hours = parseInt(inputTime.substr(0, 2));
            minutes = parseInt(inputTime.substr(2, 4));
        }

        if (mode === 'p') {
            hours += 12;
        }

        return {
            hours: hours,
            minutes: minutes
        };
    }

    function validateParsedTime(input) {
        if (normalTimePattern.test(input)) {
            return input;
        }
        return null;
    }

    function prepareInput(input) {
        if (input instanceof Date) {
            input = dateFilter(input, 'HH:mm');
        }
        return input.trim().toLowerCase().replace('.', '').replace(':', '');
    }

    function hourToString(hour) {
        return hour < 10 ? '0' + hour : hour.toString();
    }

    function minutesToString(minutes) {
        return minutes < 10 ? '0' + minutes : minutes.toString();
    }

    function timeInfoToString(timeInfo) {
        return hourToString(timeInfo.hours) + ':' + minutesToString(timeInfo.minutes);
    }
}
<commit_msg>fix(timepicker): add default value if not exsist<commit_after>
angular.module('dd.ui.dd-timepicker', [])
    .directive('ddTimepicker', TimepickerDirective)
    .service('timeparserService', timeparserService);

var KEY_ENTER = 13, KEY_UP = 38, KEY_DOWN = 40;

TimepickerDirective.$inject = ['dateFilter', 'timeparserService'];
function TimepickerDirective(dateFilter, timeparserService) {

    var directive = {
        restrict: 'A',
        require: 'ngModel',
        replace: true,
        scope: {
            ngModel: '=',
            minuteStep: '=?',
            isDateType: '=?'
        },
        link: function (scope, element, attrs, ctrl) {

            var dateTime = scope.isDateType && scope.ngModel instanceof Date ? scope.ngModel : new Date();
            scope.minuteStep = scope.minuteStep || 1;

            ctrl.$viewChangeListeners.push(function () {
                scope.$eval(attrs.onChange);
            });

            //(view to model)
            ctrl.$parsers.push(function (value) {
                return timeparserService.toModel(value, scope.isDateType, dateTime);
            });

            //(model to view)
            ctrl.$formatters.push(function (value) {
                return timeparserService.toView(value);
            });

            element.on('keydown keypress', function (event) {
                if (event.which === KEY_ENTER && !ctrl.$modelValue) {
                    updateViewValue(timeparserService.getFormattedTime());
                    event.preventDefault();
                } else if (event.which === KEY_UP) {
                    updateViewValue(timeparserService.changeTime(scope.ngModel, scope.minuteStep));
                    event.preventDefault();
                } else if (event.which === KEY_DOWN) {
                    updateViewValue(timeparserService.changeTime(scope.ngModel, -scope.minuteStep));
                    event.preventDefault();
                }
            });

            element.on('blur', function toModelTime() {
                updateViewValue(timeparserService.toView(scope.ngModel));
            });

            function updateViewValue(value) {
                ctrl.$setViewValue(value);
                ctrl.$render();
                applyNgChange();
            }

            function applyNgChange() {
                if (scope.ngChange) {
                    scope.ngChange();
                }
            }
        }
    };

    return directive;

}

timeparserService.$inject = ['dateFilter'];
function timeparserService(dateFilter) {
    var self = this;

    var amPmPattern = /^(\d+)(a|p)$/,
        normalTimePattern = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[.:][0-5][0-9]$/,
        digitsPattern = /^[0-9]+$/;

    self.toModel = toModel;
    self.toView = toView;
    self.changeTime = changeTime;
    self.getFormattedTime = getFormattedTime;

    function toModel(input, isDateModel, dateTime) {

        var parsedTime = null;

        if (!input) {
            return null;
        }

        if (normalTimePattern.test(input)) {
            parsedTime = parseNormalTime(input);
            return parsedTimeToModel(parsedTime, isDateModel, dateTime);
        }

        input = prepareInput(input);

        if (amPmPattern.test(input)) {
            parsedTime = parseAmPmTime(input, amPmPattern);
            return parsedTimeToModel(parsedTime, isDateModel, dateTime);
        }

        if (digitsPattern.test(input)) {
            parsedTime = parseDigitsTime(input, digitsPattern);
            return parsedTimeToModel(parsedTime, isDateModel, dateTime);
        }

        return null;
    }

    function toView(input) {
        if (input instanceof Date) {
            return getFormattedTime(input);
        }
        return input;
    }

    function changeTime(modelValue, delta) {
        var timeInfo = getTimeInfoFromString(prepareInput(modelValue));

        var date = new Date();
        date.setHours(timeInfo.hours);
        date.setMinutes(timeInfo.minutes + delta);

        return dateFilter(date, 'HH:mm');
    }

    function getFormattedTime(dateInstance) {
        var date = dateInstance || new Date();
        return dateFilter(date, 'HH:mm');
    }

    //private

    function parsedTimeToModel(parsedTime, isDateModel, dateTime) {

        if (!parsedTime) {
            return null;
        }

        if (isDateModel) {
            var tokens = parsedTime.split(':');
            dateTime.setHours(parseInt(tokens[0]));
            dateTime.setMinutes(parseInt(tokens[1]));
            return new Date(dateTime);
        }

        return parsedTime;
    }

    function parseAmPmTime(input, pattern) {
        var tokens = tokenize(input, pattern),
            timeInfo = getTimeInfoFromString(tokens[1], tokens[2]);

        return validateParsedTime(timeInfoToString(timeInfo));
    }

    function parseDigitsTime(input) {
        var timeInfo = getTimeInfoFromString(input, null);
        return validateParsedTime(timeInfoToString(timeInfo));
    }

    function parseNormalTime(input) {
        input = prepareInput(input);
        var timeInfo = getTimeInfoFromString(input, null);
        return timeInfoToString(timeInfo);
    }

    function tokenize(input, pattern) {
        return pattern.exec(input);
    }

    function getTimeInfoFromString(inputTime, mode) {

        if (inputTime[0] === '0') {
            inputTime = inputTime.replace(/^0/, '');
        }

        var val = parseInt(inputTime),
            hours = 0,
            minutes = 0;

        //user enter only minutes (mm)
        if (inputTime[0] === '0') {
            minutes = parseInt(inputTime);
        }
        //user enter only hour (H)
        else if (val <= 24 && inputTime.length <= 2) {
            hours = val;
        }
        // user enter hour and minutes (H:mm)
        else if (val > 24 && val <= 999) {
            hours = parseInt(inputTime[0]);
            minutes = parseInt(inputTime.substr(1, 3));
        }
        // user enter hours and minutes (HH:mm)
        else if (val > 24 && val <= 9999) {
            hours = parseInt(inputTime.substr(0, 2));
            minutes = parseInt(inputTime.substr(2, 4));
        }

        if (mode === 'p') {
            hours += 12;
        }

        return {
            hours: hours,
            minutes: minutes
        };
    }

    function validateParsedTime(input) {
        if (normalTimePattern.test(input)) {
            return input;
        }
        return null;
    }

    function prepareInput(input) {
        if (input instanceof Date) {
            input = dateFilter(input, 'HH:mm');
        }
        if (!input) {
            input = '00:00';
        }
        return input.trim().toLowerCase().replace('.', '').replace(':', '');
    }

    function hourToString(hour) {
        return hour < 10 ? '0' + hour : hour.toString();
    }

    function minutesToString(minutes) {
        return minutes < 10 ? '0' + minutes : minutes.toString();
    }

    function timeInfoToString(timeInfo) {
        return hourToString(timeInfo.hours) + ':' + minutesToString(timeInfo.minutes);
    }
}
<|endoftext|>


<commit_before>/*
 * stan.js
 *
 * Copyright (C) 2015 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

define("mode/stan", function(require, exports, module) {

var oop = require("ace/lib/oop");
var TextMode = require("ace/mode/text").Mode;
var Tokenizer = require("ace/tokenizer").Tokenizer;
var StanHighlightRules = require("mode/stan_highlight_rules").StanHighlightRules;

var Mode = function() {
   this.$tokenizer = new Tokenizer(new StanHighlightRules().getRules());
};
oop.inherits(Mode, TextMode);

(function() {
    this.getNextLineIndent = function(state, line, tab) {
        return this.$getIndent(line);
    };
}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>add simple auto-indenter to stan mode<commit_after>/*
 * stan.js
 *
 * Copyright (C) 2015 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

define("mode/stan", function(require, exports, module) {

var oop = require("ace/lib/oop");
var TextMode = require("ace/mode/text").Mode;
var Tokenizer = require("ace/tokenizer").Tokenizer;
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
var StanHighlightRules = require("mode/stan_highlight_rules").StanHighlightRules;

var Mode = function() {
   this.$tokenizer = new Tokenizer(new StanHighlightRules().getRules());
   this.$outdent = new MatchingBraceOutdent();
};
oop.inherits(Mode, TextMode);

(function() {

    this.lineCommentStart = ["//"];
    this.blockComment = {start: "/*", end: "*/"};

    this.getNextLineIndent = function(state, line, tab) {
        var indent = this.$getIndent(line);

        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
        var tokens = tokenizedLine.tokens;
        var endState = tokenizedLine.state;

        if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
        }

        if (state == "start") {
            var match = line.match(/^.*(?:[\{\(\[])\s*$/);
            if (match) {
                indent += tab;
            }
        }

        return indent;
    };

    this.checkOutdent = function(state, line, input) {
        return this.$outdent.checkOutdent(line, input);
    };

    this.autoOutdent = function(state, doc, row) {
        this.$outdent.autoOutdent(doc, row);
    };

}).call(Mode.prototype);

exports.Mode = Mode;
});
<|endoftext|>


<commit_before>/**
 * @author kennethjiang / https://github.com/kennethjiang
 *
 */

import * as THREE from 'three'

// objects: Array of object3D that you want to be selectable by mouse clicks or touch guesture
// domElement: DomElement of the render
// camera: camera of the scene
//
function PointerInteractions( objects, domElement, camera ) {

    var scope = this;
    scope.objects = objects;

    //
    // public attributes and methods
    //

    domElement.addEventListener( "mousedown", onPointerDown, false );
    domElement.addEventListener( "touchstart", onPointerDown, false );

    domElement.addEventListener( "mousemove", onPointerMove, false );
    domElement.addEventListener( "touchmove", onPointerMove, false );

    domElement.addEventListener( "mouseup", onPointerUp, false );
    domElement.addEventListener( "touchend", onPointerUp, false );
    domElement.addEventListener( "touchcancel", onPointerUp, false );

    domElement.addEventListener( "mouseout", onPointerOut, false );
    domElement.addEventListener( "touchleave", onPointerOut, false );

    this.dispose = function () {

        domElement.removeEventListener( "mousedown", onPointerDown );
        domElement.removeEventListener( "touchstart", onPointerDown );

        domElement.removeEventListener( "mousemove", onPointerMove );
        domElement.removeEventListener( "touchmove", onPointerMove );

        domElement.removeEventListener( "mouseup", onPointerUp );
        domElement.removeEventListener( "touchend", onPointerUp );
        domElement.removeEventListener( "touchcancel", onPointerUp );

        domElement.removeEventListener( "mouseout", onPointerOut );
        domElement.removeEventListener( "touchleave", onPointerOut );

    };

    //
    // internals
    //

    var pointerVector = new THREE.Vector2();
    var ray = new THREE.Raycaster();
    ray.linePrecision = 0.01;

    var pointerDepressed = false;
    var lastPointerEvent;

    function onPointerDown( event ) {

        lastPointerEvent = "pointerdown";

        pointerDepressed = true;

    }

    function onPointerMove( event ) {

        lastPointerEvent = "pointermove";

        if (pointerDepressed) return ;

        if (! objectHovered ) return;

        var obj = insertedObject(event);
        if ( scope.hoveredObject != obj ) {
            scope.dispatchEvent( { type: 'hover', previous: scope.hoveredObject, current: obj } );
            scope.hoveredObject = obj;
        }

    }

    function onPointerUp( event ) {

        if (!pointerDepressed) return ;
        pointerDepressed = false;

        if (lastPointerEvent != "pointerdown") return ; // A click is a pointerdown followed immediately by a pointerup
        lastPointerEvent = "pointerup";

        if (! objectClicked ) return ;

        var obj = insertedObject(event);
        if ( scope.clickedObject != obj ) {
            scope.dispatchEvent( { type: 'click', previous: scope.clickedObject, current: obj } );
            scope.clickedObject = obj;
        }

    }

    function onPointerOut( event ) {

        lastPointerEvent = "pointerout";

        if (pointerDepressed) return ;

        if (! objectHovered ) return;

        scope.dispatchEvent( { type: 'hover', previous: scope.hoveredObject, current: null } );

        scope.hoveredObject = null;

    }

    function insertedObject( event ) {

        if ( event.button !== undefined && event.button !== 0 ) return;

        var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
        var rect = domElement.getBoundingClientRect();
        var x = ( pointer.clientX - rect.left ) / rect.width;
        var y = ( pointer.clientY - rect.top ) / rect.height;
        pointerVector.set( ( x * 2 ) - 1, - ( y * 2 ) + 1 );

        ray.setFromCamera( pointerVector, camera );

        var intersections = ray.intersectObjects( objects, false );
        return intersections[ 0 ] ? intersections[ 0 ].object : null;

    }

}

PointerInteractions.prototype = Object.create( THREE.EventDispatcher.prototype );
PointerInteractions.prototype.constructor = PointerInteractions;

export { PointerInteractions }
<commit_msg>Remove pre-mature optimization<commit_after>/**
 * @author kennethjiang / https://github.com/kennethjiang
 *
 */

import * as THREE from 'three'

// objects: Array of object3D that you want to be selectable by mouse clicks or touch guesture
// domElement: DomElement of the render
// camera: camera of the scene
//
function PointerInteractions( objects, domElement, camera ) {

    var scope = this;
    scope.objects = objects;

    //
    // public attributes and methods
    //

    domElement.addEventListener( "mousedown", onPointerDown, false );
    domElement.addEventListener( "touchstart", onPointerDown, false );

    domElement.addEventListener( "mousemove", onPointerMove, false );
    domElement.addEventListener( "touchmove", onPointerMove, false );

    domElement.addEventListener( "mouseup", onPointerUp, false );
    domElement.addEventListener( "touchend", onPointerUp, false );
    domElement.addEventListener( "touchcancel", onPointerUp, false );

    domElement.addEventListener( "mouseout", onPointerOut, false );
    domElement.addEventListener( "touchleave", onPointerOut, false );

    this.dispose = function () {

        domElement.removeEventListener( "mousedown", onPointerDown );
        domElement.removeEventListener( "touchstart", onPointerDown );

        domElement.removeEventListener( "mousemove", onPointerMove );
        domElement.removeEventListener( "touchmove", onPointerMove );

        domElement.removeEventListener( "mouseup", onPointerUp );
        domElement.removeEventListener( "touchend", onPointerUp );
        domElement.removeEventListener( "touchcancel", onPointerUp );

        domElement.removeEventListener( "mouseout", onPointerOut );
        domElement.removeEventListener( "touchleave", onPointerOut );

    };

    //
    // internals
    //

    var pointerVector = new THREE.Vector2();
    var ray = new THREE.Raycaster();
    ray.linePrecision = 0.01;

    var pointerDepressed = false;
    var lastPointerEvent;

    function onPointerDown( event ) {

        lastPointerEvent = "pointerdown";

        pointerDepressed = true;

    }

    function onPointerMove( event ) {

        lastPointerEvent = "pointermove";

        if (pointerDepressed) return ;

        var obj = insertedObject(event);
        if ( scope.hoveredObject != obj ) {
            scope.dispatchEvent( { type: 'hover', previous: scope.hoveredObject, current: obj } );
            scope.hoveredObject = obj;
        }

    }

    function onPointerUp( event ) {

        if (!pointerDepressed) return ;
        pointerDepressed = false;

        if (lastPointerEvent != "pointerdown") return ; // A click is a pointerdown followed immediately by a pointerup
        lastPointerEvent = "pointerup";

        var obj = insertedObject(event);
        if ( scope.clickedObject != obj ) {
            scope.dispatchEvent( { type: 'click', previous: scope.clickedObject, current: obj } );
            scope.clickedObject = obj;
        }

    }

    function onPointerOut( event ) {

        lastPointerEvent = "pointerout";

        if (pointerDepressed) return ;

        scope.dispatchEvent( { type: 'hover', previous: scope.hoveredObject, current: null } );

        scope.hoveredObject = null;

    }

    function insertedObject( event ) {

        if ( event.button !== undefined && event.button !== 0 ) return;

        var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
        var rect = domElement.getBoundingClientRect();
        var x = ( pointer.clientX - rect.left ) / rect.width;
        var y = ( pointer.clientY - rect.top ) / rect.height;
        pointerVector.set( ( x * 2 ) - 1, - ( y * 2 ) + 1 );

        ray.setFromCamera( pointerVector, camera );

        var intersections = ray.intersectObjects( objects, false );
        return intersections[ 0 ] ? intersections[ 0 ].object : null;

    }

}

PointerInteractions.prototype = Object.create( THREE.EventDispatcher.prototype );
PointerInteractions.prototype.constructor = PointerInteractions;

export { PointerInteractions }
<|endoftext|>


<commit_before>;(function () {
    // bootstrap modal 封装
    function createModal(size, title, href) {
    	var template;
    	var $this = $(this);
        size = (size != undefined ? size : '');
        template = [
                        '
',
                        '
',
                        '
',
                        '
',
                        '
',
                        '
'
                    ].join("");
        var titleFlag = (title != undefined && title.trim() != ''),
            $modal = $(template),
            $modalContent = $modal.find('.modal-content')

        if (titleFlag) {
            $modalContent.html(
                ['
',
                '<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>',
                '
', title, '
', // modal title
                '
'].join('')
            )
        }

        $.get(href, function(data) { // get modal content from server

            if (titleFlag) {
                $(data).insertAfter($modal.find('.modal-header'))
            } else {
                $modalContent.html(data)
            }

            // show modal
            $modal.modal()

            // Actually I mean to on show.bs.modal event
            // but it doesn't trigger
            $modal.on('shown.bs.modal', function () {
                $this.trigger('shown.fr.modal', $modal) // btn trigger shown.fr.modal event
            })
        })

        $modal.on('hidden.bs.modal', function () { // when the modal close remove it
            $modal.remove()
        })

        return $modal;
    }

    // modal api
    $('body').on('click', 'a[data-toggle="front-modal"]', function (e) {
        e.preventDefault();
        createModal.call(this, $(this).data('size'), $(this).data('title'), $(this).data('href'));
    });

    // jquery common
    $.frontModal = function (option) {
        var preSetParams = {
            size: '',
            title: '',
            href: ''
        };

        var params = $.extend(preSetParams, option);

        return createModal(params.size, params.title, params.href);
    };

    // 选择浮层
    // when [data-toggle="front-modal"] show then we can catch the shown.fr.modal event
    // to do some bind operation
    $('[data-toggle="front-modal-select"]')
        .on('click', createModal)
        .on('shown.fr.modal', selectModalInit)

    function selectModalInit() {
        var $this = $(this),
            $selectedArea = $('#front-selected-item')

        // search btn
        $('#front-search-btn').click(function() {
            $this.trigger('search.fr.modal.select')
        })

        // search input enter
        $('#front-search-input').keyup(function () {
            if (window.event.keyCode == 13) {
                $('#front-search-btn').click()
            }
        })

        // add up operation
        $('#front-tab-content').on('click', '.front-select-item>span', function (e) {
            var $span = $(e.target),
                $selectedItem = $selectedArea.children('.front-select-item'),
                i = 0,
                exist = false;

            for (;!exist && i < $selectedItem.length; ++i) {
                if ($selectedItem.eq(i).children('span').text() === $span.text()) {
                    exist = true;
                }
            }

            if (!exist) {
                $selectedArea.append([
                    '
',
                    '', $span.text(), '',
                    '删除',
                    '
'
                ].join(""))

                calSelectedNumber()
            }
        })

        // delete event on
        $selectedArea.on('click', 'a[data-toggle="delete"]', function(e) {
            var $this = $(this)
            e.preventDefault()
            $this.parent().remove()

            calSelectedNumber()
        })

        // clear selected item
        $('#fr-clear-item').click(function() {
            $selectedArea.html('')
            calSelectedNumber()

            return false
        })

        // update selected number
        function calSelectedNumber() {
            $('#front-item-num>span').text($selectedArea.children('.front-select-item').length)
        }
    }
})();
<commit_msg>DEL：delete useless code<commit_after>;(function () {
    // bootstrap modal 封装
    function createModal(size, title, href) {
    	var template;
    	var $this = $(this);
        size = (size != undefined ? size : '');
        template = [
                        '
',
                        '
',
                        '
',
                        '
',
                        '
',
                        '
'
                    ].join("");
        var titleFlag = (title != undefined && title.trim() != ''),
            $modal = $(template),
            $modalContent = $modal.find('.modal-content')

        if (titleFlag) {
            $modalContent.html(
                ['
',
                '<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>',
                '
', title, '
', // modal title
                '
'].join('')
            )
        }

        $.get(href, function(data) { // get modal content from server

            if (titleFlag) {
                $(data).insertAfter($modal.find('.modal-header'))
            } else {
                $modalContent.html(data)
            }

            // show modal
            $modal.modal()

            // Actually I mean to on show.bs.modal event
            // but it doesn't trigger
            $modal.on('shown.bs.modal', function () {
                $this.trigger('shown.fr.modal', $modal) // btn trigger shown.fr.modal event
            })
        })

        $modal.on('hidden.bs.modal', function () { // when the modal close remove it
            $modal.remove()
        })

        return $modal;
    }

    // modal api
    $('body').on('click', 'a[data-toggle="front-modal"]', function (e) {
        e.preventDefault();
        createModal.call(this, $(this).data('size'), $(this).data('title'), $(this).data('href'));
    });

    // jquery common
    $.frontModal = function (option) {
        var preSetParams = {
            size: '',
            title: '',
            href: ''
        };

        var params = $.extend(preSetParams, option);

        return createModal(params.size, params.title, params.href);
    };
})();
<|endoftext|>


<commit_before>var outlinesOrNot = true;

var coolChart = function (whereToDrawIt) {
  var bandSize = 5; // maybe have this constant band size instead of setting the number of bands.

  var height = 50;
  var width = document.documentElement.clientWidth - 20;
  var zeroPoint = 0;

  var numOfPositiveBands = (d3.max(data) > zeroPoint) ? Math.ceil(Math.abs(d3.max(data) - zeroPoint) / bandSize) : 0; // the closest to mod bandSize, rounded up.
  var numOfNegativeBands = (d3.min(data) < zeroPoint) ? Math.ceil(Math.abs(zeroPoint - d3.min(data)) / bandSize) : 0;
  var numOfMostBands = d3.max([numOfPositiveBands, numOfNegativeBands]);

  console.log("numPos: " + numOfPositiveBands); //TODO: test these with all types of input data. Maybe make test cases which use this as a module and render a bunch of different graphs. :D
  console.log("numNeg: " + numOfNegativeBands);

  var xScale = d3.scale.linear()
    .domain([0, data.length])
    .range([0, width + (width / (data.length - 1))]); // So that the furthest-right point is at the right edge of the plot

  var yScale = d3.scale.linear()
    .domain([zeroPoint, d3.max([zeroPoint, d3.max(data)])])
    .range([height * numOfPositiveBands, 0]);

  var fillScale = d3.scale.linear()
    .domain([0, numOfMostBands])
    .rangeRound([255, 0]);

  var chart;

  var d3area1 = d3.svg.area()
    .x(function (d, i) { return xScale(i); })
    .y1(function (d, i) { return yScale(d); }) // height - (d * 10); })
    .y0(height * numOfPositiveBands) //TODO: change this to both Pos and Neg or something ???
    .interpolate("cardinal");

  var my = function (selection) {
    selection.each(function (d, i) {
      //Our canvas, where the curves will be rendered, and which will be clipped.
      chart = whereToDrawIt.append("svg");

      //Set the chart's dimensions
      chart
        .attr("width", width)
        .attr("height", height * 5);

      //Draw the background for the chart
      chart
        .insert("svg:rect")
          .attr("width", width)
          .attr("height", height)
          .style("fill", "#FFF");

      //Make the clipPath (for cropping the paths)
      chart.insert("defs")
        .append("clipPath")
          .attr("id", "clip")
        .append("rect")
          .attr("width", width)
          .attr("height", height); //height / 4 - 20);

//      chart.attr("clip-path", "url(#clip)");

      //Make and render the Positive curves.
      chart.selectAll("posPath")
          .data(d3.range(numOfMostBands))
        .enter().append("path")
          .attr("class", "posPath")
          .attr("fill", function (d, i) { return "rgba(255, " + fillScale(i + 1) + ", " + fillScale(i + 1) + ", 1)"; })
          .style("stroke-width", function () { return outlinesOrNot ? 1 : 0; })
          .style("cursor", "help")
          .style("stroke", "#000")
          .attr("d", d3area1(d))
          .attr("transform", function (d, i) {return "translate(0, " + (i - numOfMostBands + 1) * height + ")"; });

      //Make and render the Negative curves.
      chart.selectAll("negPath")
          .data(d3.range(numOfMostBands, 0, -1))
        .enter().append("path")
          .attr("class", "negPath")
          .attr("fill", function (d, i) { return "rgba(" + fillScale(i + 1) + ", " + fillScale(i + 1) + ", 255, 1)"; })
          .style("stroke-width", function () { return outlinesOrNot ? 1 : 0; })
          .style("stroke", "#000")
          .style("cursor", "help")
          .attr("d", d3area1(d))
          .attr("transform", function (d, i) {return "translate(0, " + (d - numOfMostBands - 2) * height + ")"; });

      //Draw the outline for the chart
      chart
        .append("svg:rect")
          .attr("width", width)
          .attr("height", height)
          .style("fill", "rgba(0,0,0,0)")
          .style("stroke-width", 3)
          .style("stroke", "#000");
    });
  }

  my.width = function (value) {
    if (!arguments.length) return width;
    width = value;
    chart.attr("width", width); //TODO: fix this so that it redraws the plot
    return my;
  }

  my.height = function (value) {
    if (!arguments.length) return height;
    height = value;
    chart.attr("height", height); //TODO: fix this so that it redraws the plot
    return my;
  }

  return my;

  //TODO:
  //      Make the graph dynamic so that it sizes according to the screen
  //      - this might just mean setting it statically each time the screen is loaded or rotated.
  //      Either use transparency for the colours, or find a sweet way to make it an equation.
  //      Make sure it works for any number of bands >= 1
  //      Test with only negative values; only positive values.
  //      Test with different zero levels of all possibilities.
}

//var data = [0, 5, 10, 7, 10, 0, 7, 8, 6, 3, 0, 1, 2, 7, 8, 2];
//var data = [1, 2, 5, 4, 7, 6, 9, 8, 10, 0, 1];
var data = [0, -5, 10, -7, 10, -1, 7, 8, 2.5];
//var data = [-1, 0, 1, 0];
//var data = [0, 1, 0];

//var coolChart1 = coolChart().width(50).height(50);
var coolChart1 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data)
  .call(coolChart1);

//coolChart1.width(100).height(70);

var data2 = [2, 3, 2, 2, 3, 1, -1, 0, 1];
var coolChart2 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data2)
  .call(coolChart2);

var data3 = [0, 1, -3, 10, 0, 5, -4, -10, 2.5];
var coolChart3 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data3)
  .call(coolChart3);

var data4 = [10, 8, 9, 5, 3, 7, 4, 8, 9, 6, 10];
var coolChart4 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data4)
  .call(coolChart4);
<commit_msg>Horizon is now very usable. Not all test cases have been done yet.<commit_after>var outlinesOrNot = true;

var coolChart = function (whereToDrawIt) {
  var bandSize = 3; // maybe have this constant band size instead of setting the number of bands.

  var height = 50;
  var width = document.documentElement.clientWidth - 20;
  var zeroPoint = 0;

  var numOfPositiveBands = (d3.max(data) > zeroPoint) ? Math.ceil(Math.abs(d3.max(data) - zeroPoint) / bandSize) : 0; // the closest to mod bandSize, rounded up.
  var numOfNegativeBands = (d3.min(data) < zeroPoint) ? Math.ceil(Math.abs(zeroPoint - d3.min(data)) / bandSize) : 0;
  var numOfMostBands = d3.max([numOfPositiveBands, numOfNegativeBands]);

  console.log("numPos: " + numOfPositiveBands); //TODO: test these with all types of input data. Maybe make test cases which use this as a module and render a bunch of different graphs. :D
  console.log("numNeg: " + numOfNegativeBands);

  var xScale = d3.scale.linear()
    .domain([0, data.length])
    .range([0, width + (width / (data.length - 1))]); // So that the furthest-right point is at the right edge of the plot

  var yScale = d3.scale.linear()
    .domain([zeroPoint, d3.max([zeroPoint, numOfMostBands * bandSize])])
    .range([height * numOfPositiveBands, 0]);

  var fillScale = d3.scale.linear()
    .domain([0, numOfMostBands])
    .rangeRound([255, 0]);

  var chart;

  var d3area1 = d3.svg.area()
    .x(function (d, i) { return xScale(i); })
    .y1(function (d, i) { return yScale(d); }) // height - (d * 10); })
    .y0(height * numOfPositiveBands) //TODO: change this to both Pos and Neg or something ???
    .interpolate("cardinal");

  var my = function (selection) {
    selection.each(function (d, i) {
      //Our canvas, where the curves will be rendered, and which will be clipped.
      chart = whereToDrawIt.append("svg");

      //Set the chart's dimensions
      chart
        .attr("width", width)
        .attr("height", height);

      //Draw the background for the chart
      chart
        .insert("svg:rect")
          .attr("width", width)
          .attr("height", height)
          .style("fill", "#FFF");

      //Make the clipPath (for cropping the paths)
      chart.insert("defs")
        .append("clipPath")
          .attr("id", "clip")
        .append("rect")
          .attr("width", width)
          .attr("height", height); //height / 4 - 20);

      chart.attr("clip-path", "url(#clip)");

      //Make and render the Positive curves.
      chart.selectAll("posPath")
          .data(d3.range(numOfMostBands))
        .enter().append("path")
          .attr("class", "posPath")
          .attr("fill", function (d, i) { return "rgba(255, " + fillScale(i + 1) + ", " + fillScale(i + 1) + ", 1)"; })
          .style("stroke-width", function () { return outlinesOrNot ? 1 : 0; })
          .style("cursor", "help")
          .style("stroke", "#000")
          .attr("d", d3area1(d))
          .attr("transform", function (d, i) {return "translate(0, " + (i - numOfMostBands + 1) * height + ")"; });

      //Make and render the Negative curves.
      chart.selectAll("negPath")
          .data(d3.range(numOfMostBands, 0, -1))
        .enter().append("path")
          .attr("class", "negPath")
          .attr("fill", function (d, i) { return "rgba(" + fillScale(i + 1) + ", " + fillScale(i + 1) + ", 255, 1)"; })
          .style("stroke-width", function () { return outlinesOrNot ? 1 : 0; })
          .style("stroke", "#000")
          .style("cursor", "help")
          .attr("d", d3area1(d))
          .attr("transform", function (d, i) {return "translate(0, " + (d - (numOfMostBands * 2)) * height + ")"; });

      //Draw the outline for the chart
      chart
        .append("svg:rect")
          .attr("width", width)
          .attr("height", height)
          .style("fill", "rgba(0,0,0,0)")
          .style("stroke-width", 3)
          .style("stroke", "#000");
    });
  }

  my.width = function (value) {
    if (!arguments.length) return width;
    width = value;
    chart.attr("width", width); //TODO: fix this so that it redraws the plot
    return my;
  }

  my.height = function (value) {
    if (!arguments.length) return height;
    height = value;
    chart.attr("height", height); //TODO: fix this so that it redraws the plot
    return my;
  }

  return my;

  //TODO:
  //      Make the graph dynamic so that it sizes according to the screen
  //      - this might just mean setting it statically each time the screen is loaded or rotated.
  //      Either use transparency for the colours, or find a sweet way to make it an equation.
  //      Make sure it works for any number of bands >= 1
  //      Test with only negative values; only positive values.
  //      Test with different zero levels of all possibilities.
}

//var data = [0, 5, 10, 7, 10, 0, 7, 8, 6, 3, 0, 1, 2, 7, 8, 2];
//var data = [1, 2, 5, 4, 7, 6, 9, 8, 10, 0, 1];
var data = [0, -5, 10, -7, 10, -1, 7, 8, 2.5];
//var data = [-1, 0, 1, 0];
//var data = [0, 1, 0];

//var coolChart1 = coolChart().width(50).height(50);
var coolChart1 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data)
  .call(coolChart1);

//coolChart1.width(100).height(70);

var data2 = [2, 3, 2, 2, 3, 1, -1, 0, 1];
var coolChart2 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data2)
  .call(coolChart2);

var data3 = [0, 1, -3, 10, 0, 5, -4, -10, 2.5];
var coolChart3 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data3)
  .call(coolChart3);

var data4 = [10, 8, 9, 5, 3, 7, 4, 8, 9, 6, 10];
var coolChart4 = coolChart(d3.select("#charts"));
d3.select("#charts")
  .datum(data4)
  .call(coolChart4);
<|endoftext|>


<commit_before>/* istanbul ignore next */
import mkdirp from 'mkdirp'
import {dirname} from '../utils/path'

/**
 * Synchronous version of {link #makeDirectories}. Delegates to [mkdirp](http://npmjs.org/package/mkdirp) module
 *
 * @function makeDirectoriesSync
 * @param {String} outPath The path to a file
 *
 * @example
 * io.makeDirectories('path/to/create/to/data.tsv')
 *
 */
export default function makeDirectoriesSync (outPath) {
  mkdirp.sync(dirname(outPath))
}
<commit_msg>fix example<commit_after>/* istanbul ignore next */
import mkdirp from 'mkdirp'
import {dirname} from '../utils/path'

/**
 * Synchronous version of {@link makeDirectories}. Delegates to [mkdirp](http://npmjs.org/package/mkdirp) module.
 *
 * @function makeDirectoriesSync
 * @param {String} outPath The path to a file
 *
 * @example
 * io.makeDirectoriesSync('path/to/create/to/data.tsv')
 *
 */
export default function makeDirectoriesSync (outPath) {
  mkdirp.sync(dirname(outPath))
}
<|endoftext|>