<commit_before>var path = require('path')
  , Matcher
  , rule
  , Rule;

// Define a helper object with some utility functions
Matcher = new (function () {

  // Split a task to two parts, name space and task name.
  // For example, given 'foo:bin/a%.c', return an object with
  // - 'ns'     : foo
  // - 'name'   : bin/a%.c
  this.split = function(task) {
    var parts = task.split(':')
    , name  = parts.pop()
    , ns    = Matcher.resolveNS( parts );
    return {
      'name' : name,
      'ns'   : ns
    };
  };

  // Return the namespace based on an array of names.
  // For example, given ['foo', 'baz' ], return the namespace
  //
  //   default -> foo -> baz
  //
  // where default is the global root namespace
  // and -> means child namespace.
  this.resolveNS = function(parts) {
    var  ns    = jake.defaultNamespace;
    for(var i = 0, l = parts.length; ns && i < l; i++) {
      ns = ns.childNamespaces[parts[i]];
    }
    return ns;
  };

  // Given a pattern p, say 'foo:bin/a%.c'
  // Return an object with
  // - 'ns'     : foo
  // - 'dir'    : bin
  // - 'prefix' : a
  // - 'suffix' : .c
  this.resolve = function(p) {
    var task = Matcher.split(p),
        name  = task.name,
        ns    = task.ns;
    var split = path.basename(name).split('%');
    return {
      ns: ns
    , dir: path.dirname(name)
    , prefix: split[0]
    , suffix: split[1]
    };
  };

  // Test whether string a is a suffix of string b
  this.stringEndWith = function (a,b) {
    var l;
    return (l = b.lastIndexOf(a)) == -1 ? false : l + a.length == b.length;
  };

  // Replace the suffix a of the string s with b.
  // Note that, it is assumed a is a suffix of s.
  this.stringReplaceSuffix = function (s,a,b) {
    return s.slice(0,s.lastIndexOf(a)) + b;
  };

  // Test wether the a prerequisite matchs the pattern.
  // The arg 'pattern' does not have namespace as prefix.
  // For example, the following tests are true
  //
  //   pattern      |    prereq
  //   bin/%.o      |    bin/main.o
  //   bin/%.o      |    foo:bin/main.o
  //
  // The following tests are false (trivally)
  //
  //   pattern      |    prereq
  //   bin/%.o      |    foobin/main.o
  //   bin/%.o      |    bin/main.oo
  this.match = function(pattern, prereq) {
    var p
      , task
      , name
      , ns
      , obj
      , filename;

    if (pattern.indexOf('%') == -1) {
      // No Pattern. No Folder. No Namespace.
      // A Simple Suffix Rule. Just test suffix
      return this.stringEndWith(pattern, prereq);
    }
    else {
      // Resolve the dir, prefix and suffix of pattern
      p = this.resolve(pattern);

      // Resolve the namespace and task name of prereq
      task = this.split(prereq);
      name = task.name;
      ns = task.ns;

      // Set the objective as the task name of prereq
      obj = name;

      // Namespace is already matched.

      // Check dir
      if (path.dirname(obj) != p.dir) {
        return false;
      }

      filename = path.basename(obj);

      // Check file name length.
      if ((p.prefix.length + p.suffix.length + 1) > filename.length) {
        // Length does not match.
        return false;
      }

      // Check prefix
      if (filename.indexOf(p.prefix) !== 0) {
        return false;
      }

      // Check suffix
      if (!this.stringEndWith(p.suffix, filename)) {
        return false;
      }

      // OK. Find a match.
      return true;
    }
  };

  // Generate the source based on
  //  - prereq   prerequisite
  //  - objP    pattern for the objective
  //  - srcP    pattern for the source
  //
  // Return the source with properties
  //  - dep      the prerequisite of source
  //             (with the namespace)
  //
  //  - file     the file name of source
  //             (without the namespace)
  //
  // For example, given
  //
  //  - prereq   foo:bin/main.o
  //  - objP    bin/%.o
  //  - srcP    src/%.c
  //
  // return {
  //    'dep' : 'foo:src/main.c',
  //    'file': 'src/main.c'
  //  };
  //
  this.source = function(prereq, objP, srcP) {
    var src
      , p
      , parts
      , obj
      , ns
      , filename
      , fill
      , dep;

    if (objP.indexOf('%') == -1) {
      // A Simple Suffix
      src = this.stringReplaceSuffix(prereq, objP, srcP);
      return {
        dep: src
      , file: src
      };
    }
    else {
      // Resolve the dir, prefix and suffix of pattern
      p = this.resolve(objP);

      // Resolve the namespace and task name
      parts = prereq.split(':');
      obj = parts.pop();
      ns = this.resolveNS( parts );

      filename = path.basename(obj);

      // Resolve the matching pattern for the symbol '%'
      fill = filename.slice(p.prefix.length,
          filename.length - p.suffix.length);

      // Replace the % with the mathcing pattern
      // found in last step
      src = srcP.replace('%', fill);

      // Construct the return object
      if (parts.length === 0) {
        // no name space
        return {
          dep: src
        , file: src
        };
      }
      else {
        // Add namespace to the prerequisite of source file
        dep = parts.join(':') + ':' + src;
        return {
          dep: dep
        , file: src
        };
      }
    }
  };

})();

Rule = function (opts) {
  this.args = opts.args;
  this.desc =  opts.desc;
  this.ns = opts.ns;
};

rule = new (function () {
  // The steps are
  // 1. Resolve the task name and namespace for the prerequisite.
  // 2. Fetch all the rules belonging to the namespace.
  // 3. Test each pattern.
  this.match = function(prereq, args) {
    // 1.
    var task = Matcher.split(prereq)
      , ns = task.ns
      , rules;

    if (!ns) {
      return null;
    }

    // 2.
    rules = ns.rules;

    // 3.
    for (var p in rules) {
      if (rules.hasOwnProperty(p) &&
          typeof rules[p] == 'object' &&
          Matcher.match(p, prereq)) {
        return p;
      }
    }
    return null;
  };

  // Create a file task based on the Rule.
  this.createTask = function(pattern, prereq, args) {
    var objP
    , srcP
    , prereqs = []
    , arg
    , action
    , opts
    , task
    , name
    , ns
    , rule
    , src
    , newAction
    , newArgs
    , tNs
    , createdTask;

    // 1. Resolve the task name and namespace for the prerequisite.
    task = Matcher.split(prereq);
    name = task.name;
    ns = task.ns;

    // 2. Obtain the matching rule.
    rule = ns.rules[pattern].args.slice(0);  // We need a copy.

    // 3. Obtain the pattern for the objective and source.
    objP = rule.shift();
    srcP = rule.shift();

    // 4. Resolve the prerequisite and file name representing the source
    src = Matcher.source( prereq, objP, srcP );
    // - src.dep  is the prerequisite with namespace.
    // - src.file is the source file name.

    // 5. Generate the prerequisite for the matching task.
    //    It is the original prerequisites plus the prerequisite
    //    representing source file, i.e.,
    //
    //      rule( '%.o', '%.c', ['some.h'] ...
    //
    //    If the objective is main.o, then new task should be
    //
    //      file( 'main.o', ['main.c', 'some.h' ] ...
    if (Array.isArray(rule[0])) {
      prereqs = rule.shift().slice(0); // again, a copy
    }
    prereqs.unshift( src.dep );

    // 6. Fetch the action and opts.
    while ((arg = rule.shift())) {
      if (typeof arg == 'function') {
        action = arg;
      }
      else {
        opts = arg;
      }
    }

    // 7. Create a new action with obj and src replaced.
    newAction = function() {
      action(name, src.file, args);
    };

    // 8. Now, create the file task.
    newArgs = [name, prereqs, newAction, opts];
    newArgs.unshift('file');

    // 9. Insert the file task into Jake
    //
    // Since createTask function stores the task as a child task
    // of currentNamespace. Here we temporariliy switch the namespace.
    tNs = jake.currentNamespace;
    jake.currentNamespace = ns;
    createdTask = jake.createTask.apply(global, newArgs);
    jake.currentNamespace = tNs;

    return createdTask;
  };

})();

rule.Rule = Rule;

module.exports = rule;
<commit_msg>A bit more linting<commit_after>var path = require('path')
  , Matcher
  , rule
  , Rule;

// Define a helper object with some utility functions
Matcher = new (function () {

  // Split a task to two parts, name space and task name.
  // For example, given 'foo:bin/a%.c', return an object with
  // - 'ns'     : foo
  // - 'name'   : bin/a%.c
  this.split = function(task) {
    var parts = task.split(':')
    , name  = parts.pop()
    , ns    = this.resolveNS( parts );
    return {
      'name' : name,
      'ns'   : ns
    };
  };

  // Return the namespace based on an array of names.
  // For example, given ['foo', 'baz' ], return the namespace
  //
  //   default -> foo -> baz
  //
  // where default is the global root namespace
  // and -> means child namespace.
  this.resolveNS = function(parts) {
    var  ns    = jake.defaultNamespace;
    for(var i = 0, l = parts.length; ns && i < l; i++) {
      ns = ns.childNamespaces[parts[i]];
    }
    return ns;
  };

  // Given a pattern p, say 'foo:bin/a%.c'
  // Return an object with
  // - 'ns'     : foo
  // - 'dir'    : bin
  // - 'prefix' : a
  // - 'suffix' : .c
  this.resolve = function(p) {
    var task = this.split(p),
        name  = task.name,
        ns    = task.ns;
    var split = path.basename(name).split('%');
    return {
      ns: ns
    , dir: path.dirname(name)
    , prefix: split[0]
    , suffix: split[1]
    };
  };

  // Test whether string a is a suffix of string b
  this.stringEndWith = function (a,b) {
    var l;
    return (l = b.lastIndexOf(a)) == -1 ? false : l + a.length == b.length;
  };

  // Replace the suffix a of the string s with b.
  // Note that, it is assumed a is a suffix of s.
  this.stringReplaceSuffix = function (s,a,b) {
    return s.slice(0,s.lastIndexOf(a)) + b;
  };

  // Test wether the a prerequisite matchs the pattern.
  // The arg 'pattern' does not have namespace as prefix.
  // For example, the following tests are true
  //
  //   pattern      |    prereq
  //   bin/%.o      |    bin/main.o
  //   bin/%.o      |    foo:bin/main.o
  //
  // The following tests are false (trivally)
  //
  //   pattern      |    prereq
  //   bin/%.o      |    foobin/main.o
  //   bin/%.o      |    bin/main.oo
  this.match = function(pattern, prereq) {
    var p
      , task
      , name
      , ns
      , obj
      , filename;

    if (pattern.indexOf('%') == -1) {
      // No Pattern. No Folder. No Namespace.
      // A Simple Suffix Rule. Just test suffix
      return this.stringEndWith(pattern, prereq);
    }
    else {
      // Resolve the dir, prefix and suffix of pattern
      p = this.resolve(pattern);

      // Resolve the namespace and task name of prereq
      task = this.split(prereq);
      name = task.name;
      ns = task.ns;

      // Set the objective as the task name of prereq
      obj = name;

      // Namespace is already matched.

      // Check dir
      if (path.dirname(obj) != p.dir) {
        return false;
      }

      filename = path.basename(obj);

      // Check file name length.
      if ((p.prefix.length + p.suffix.length + 1) > filename.length) {
        // Length does not match.
        return false;
      }

      // Check prefix
      if (filename.indexOf(p.prefix) !== 0) {
        return false;
      }

      // Check suffix
      if (!this.stringEndWith(p.suffix, filename)) {
        return false;
      }

      // OK. Find a match.
      return true;
    }
  };

  // Generate the source based on
  //  - prereq   prerequisite
  //  - objP    pattern for the objective
  //  - srcP    pattern for the source
  //
  // Return the source with properties
  //  - dep      the prerequisite of source
  //             (with the namespace)
  //
  //  - file     the file name of source
  //             (without the namespace)
  //
  // For example, given
  //
  //  - prereq   foo:bin/main.o
  //  - objP    bin/%.o
  //  - srcP    src/%.c
  //
  // return {
  //    'dep' : 'foo:src/main.c',
  //    'file': 'src/main.c'
  //  };
  //
  this.source = function(prereq, objP, srcP) {
    var src
      , p
      , parts
      , obj
      , ns
      , filename
      , fill
      , dep;

    if (objP.indexOf('%') == -1) {
      // A Simple Suffix
      src = this.stringReplaceSuffix(prereq, objP, srcP);
      return {
        dep: src
      , file: src
      };
    }
    else {
      // Resolve the dir, prefix and suffix of pattern
      p = this.resolve(objP);

      // Resolve the namespace and task name
      parts = prereq.split(':');
      obj = parts.pop();
      ns = this.resolveNS( parts );

      filename = path.basename(obj);

      // Resolve the matching pattern for the symbol '%'
      fill = filename.slice(p.prefix.length,
          filename.length - p.suffix.length);

      // Replace the % with the mathcing pattern
      // found in last step
      src = srcP.replace('%', fill);

      // Construct the return object
      if (parts.length === 0) {
        // no name space
        return {
          dep: src
        , file: src
        };
      }
      else {
        // Add namespace to the prerequisite of source file
        dep = parts.join(':') + ':' + src;
        return {
          dep: dep
        , file: src
        };
      }
    }
  };

})();

Rule = function (opts) {
  this.args = opts.args;
  this.desc =  opts.desc;
  this.ns = opts.ns;
};

rule = new (function () {
  // The steps are
  // 1. Resolve the task name and namespace for the prerequisite.
  // 2. Fetch all the rules belonging to the namespace.
  // 3. Test each pattern.
  this.match = function(prereq, args) {
    // 1.
    var task = Matcher.split(prereq)
      , ns = task.ns
      , rules;

    if (!ns) {
      return null;
    }

    // 2.
    rules = ns.rules;

    // 3.
    for (var p in rules) {
      if (rules.hasOwnProperty(p) &&
          typeof rules[p] == 'object' &&
          Matcher.match(p, prereq)) {
        return p;
      }
    }
    return null;
  };

  // Create a file task based on the Rule.
  this.createTask = function(pattern, prereq, args) {
    var objP
    , srcP
    , prereqs = []
    , arg
    , action
    , opts
    , task
    , name
    , ns
    , rule
    , src
    , newAction
    , newArgs
    , tNs
    , createdTask;

    // 1. Resolve the task name and namespace for the prerequisite.
    task = Matcher.split(prereq);
    name = task.name;
    ns = task.ns;

    // 2. Obtain the matching rule.
    rule = ns.rules[pattern].args.slice(0);  // We need a copy.

    // 3. Obtain the pattern for the objective and source.
    objP = rule.shift();
    srcP = rule.shift();

    // 4. Resolve the prerequisite and file name representing the source
    src = Matcher.source( prereq, objP, srcP );
    // - src.dep  is the prerequisite with namespace.
    // - src.file is the source file name.

    // 5. Generate the prerequisite for the matching task.
    //    It is the original prerequisites plus the prerequisite
    //    representing source file, i.e.,
    //
    //      rule( '%.o', '%.c', ['some.h'] ...
    //
    //    If the objective is main.o, then new task should be
    //
    //      file( 'main.o', ['main.c', 'some.h' ] ...
    if (Array.isArray(rule[0])) {
      prereqs = rule.shift().slice(0); // again, a copy
    }
    prereqs.unshift( src.dep );

    // 6. Fetch the action and opts.
    while ((arg = rule.shift())) {
      if (typeof arg == 'function') {
        action = arg;
      }
      else {
        opts = arg;
      }
    }

    // 7. Create a new action with obj and src replaced.
    newAction = function() {
      action(name, src.file, args);
    };

    // 8. Now, create the file task.
    newArgs = [name, prereqs, newAction, opts];
    newArgs.unshift('file');

    // 9. Insert the file task into Jake
    //
    // Since createTask function stores the task as a child task
    // of currentNamespace. Here we temporariliy switch the namespace.
    tNs = jake.currentNamespace;
    jake.currentNamespace = ns;
    createdTask = jake.createTask.apply(global, newArgs);
    jake.currentNamespace = tNs;

    return createdTask;
  };

})();

rule.Rule = Rule;

module.exports = rule;
<|endoftext|>


<commit_before>'use strict';

var exports = module.exports = function(callback) {

  var exec = require("child_process").exec;
  var path = require('path');

  var source = path.join(__dirname, 'Frontend/learn.json');
  var dist = path.join(__dirname, '../DeepNgRoot/Frontend');

  exec('cp ' + source + ' ' + dist, function(error, stdout, stderr) {
    if (error) {
      console.error('Error while copying learn.json', error);
      callback();
      return;
    }

    console.log('learn.json was successfully copied into DeepNgRoot');

    callback();
  })
};
<commit_msg>Update hook.init.js<commit_after>'use strict';

var exports = module.exports = function(callback) {
  if (!this.microservice.property.rootMicroservice) {
    console.error('Seems like there is no root microservice to copy learn.json to. Skipping...');
    callback();
    return;
  }

  var exec = require("child_process").exec;
  var path = require('path');

  var source = path.join(this.microservice.autoload.frontend, 'learn.json');
  var dist = this.microservice.property.rootMicroservice.autoload.frontend;

  exec('cp ' + source + ' ' + dist, function(error, stdout, stderr) {
    if (error) {
      console.error('Error while copying learn.json', error);
      callback();
      return;
    }

    console.log('learn.json was successfully copied into DeepNgRoot');

    callback();
  })
};
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var fs = require('fs');
var fsp = require('fs-promise');
var path = require('path');
var sass = require('node-sass');

var componentScraper = require('./component_scraper');

var CWD = process.cwd();

var PATH_BOWER_INCLUDES = path.join(CWD, 'bower_components/bourbon/app/assets/stylesheets');

var PATH_LEXICON_SCSS = path.join(CWD, 'node_modules/lexicon/src/scss');

module.exports = {
	clearCustomVariablesFile: function() {
		return fsp.writeFile(path.join(CWD, 'lexicon/_custom_variables.scss'), '');
	},

	render: function(options, filePath, cb) {
		options = _.defaults({
			file: filePath,
			includePaths: [PATH_BOWER_INCLUDES, PATH_LEXICON_SCSS]
		}, options);

		sass.render(options, cb);
	},

	renderLexiconBase: function(options, cb) {
		if (!cb) {
			cb = options;
			options = {};
		}

		var baseLexiconTheme = _.kebabCase(options.baseLexiconTheme || 'lexiconBase');

		options = _.omit(options, 'baseLexiconTheme');

		this.render(options, path.join(CWD, 'lexicon', baseLexiconTheme + '.scss'), function(err, result) {
			if (err) {
				console.log(err);
			}

			let filePath;

			if (!err) {
				var cssString = result.css.toString();

				filePath = path.join(CWD, 'lexicon/build', baseLexiconTheme + '.css');

				fs.writeFileSync(filePath, cssString);
			}

			cb(err, filePath);
		});
	},

	writeCustomVariablesFile: function(variables, themePath) {
		var variableMap = this._getUserVariables(variables);

		var variablesString = this._generateVariablesString(variableMap.bootstrap);

		variablesString.concat(this._generateVariablesString(variableMap.lexicon));

		return fsp.writeFile(path.join(CWD, 'lexicon/_custom_variables.scss'), variablesString);

		if (themePath) {
			fsp.writeFile(path.join(themePath, 'src/css/_aui_variables.scss'), variablesString);
		}
	},

	_getUniqueVariables: function(variables, baseVariables) {
		return _.reduce(variables, function(result, item, index) {
			var baseComponentVariables = baseVariables[index];

			var obj = _.omitBy(item, function(value, name) {
				return value == baseComponentVariables[name];
			});

			if (!_.isEmpty(obj)) {
				result[index] = obj;
			}

			return result;
		}, {});
	},

	_getUserVariables: function(variables) {
		var bootstrapBaseVariables = componentScraper.mapBootstrapVariables();
		var lexiconBaseVariables = componentScraper.mapLexiconVariables();

		return {
			bootstrap: this._getUniqueVariables(variables.bootstrap, bootstrapBaseVariables),
			lexicon: this._getUniqueVariables(variables.lexicon, lexiconBaseVariables)
		};
	},

	_generateVariablesString: function(variableMap) {
		var instance = this;

		return _.map(variableMap, function(item, index) {
			if (_.isObject(item)) {
				var header = '\n// ' + index + '\n\n';

				return header + instance._generateVariablesString(item);
			}
			else {
				return index + ': ' + item + ';\n'
			}
		}).join('');
	}
};
<commit_msg>Write to theme path first since we are returning promise<commit_after>'use strict';

var _ = require('lodash');
var fs = require('fs');
var fsp = require('fs-promise');
var path = require('path');
var sass = require('node-sass');

var componentScraper = require('./component_scraper');

var CWD = process.cwd();

var PATH_BOWER_INCLUDES = path.join(CWD, 'bower_components/bourbon/app/assets/stylesheets');

var PATH_LEXICON_SCSS = path.join(CWD, 'node_modules/lexicon/src/scss');

module.exports = {
	clearCustomVariablesFile: function() {
		return fsp.writeFile(path.join(CWD, 'lexicon/_custom_variables.scss'), '');
	},

	render: function(options, filePath, cb) {
		options = _.defaults({
			file: filePath,
			includePaths: [PATH_BOWER_INCLUDES, PATH_LEXICON_SCSS]
		}, options);

		sass.render(options, cb);
	},

	renderLexiconBase: function(options, cb) {
		if (!cb) {
			cb = options;
			options = {};
		}

		var baseLexiconTheme = _.kebabCase(options.baseLexiconTheme || 'lexiconBase');

		options = _.omit(options, 'baseLexiconTheme');

		this.render(options, path.join(CWD, 'lexicon', baseLexiconTheme + '.scss'), function(err, result) {
			if (err) {
				console.log(err);
			}

			let filePath;

			if (!err) {
				var cssString = result.css.toString();

				filePath = path.join(CWD, 'lexicon/build', baseLexiconTheme + '.css');

				fs.writeFileSync(filePath, cssString);
			}

			cb(err, filePath);
		});
	},

	writeCustomVariablesFile: function(variables, themePath) {
		var variableMap = this._getUserVariables(variables);

		var variablesString = this._generateVariablesString(variableMap.bootstrap);

		variablesString.concat(this._generateVariablesString(variableMap.lexicon));

		if (themePath) {
			fsp.writeFile(path.join(themePath, 'src/css/_aui_variables.scss'), variablesString);
		}

		return fsp.writeFile(path.join(CWD, 'lexicon/_custom_variables.scss'), variablesString);
	},

	_getUniqueVariables: function(variables, baseVariables) {
		return _.reduce(variables, function(result, item, index) {
			var baseComponentVariables = baseVariables[index];

			var obj = _.omitBy(item, function(value, name) {
				return value == baseComponentVariables[name];
			});

			if (!_.isEmpty(obj)) {
				result[index] = obj;
			}

			return result;
		}, {});
	},

	_getUserVariables: function(variables) {
		var bootstrapBaseVariables = componentScraper.mapBootstrapVariables();
		var lexiconBaseVariables = componentScraper.mapLexiconVariables();

		return {
			bootstrap: this._getUniqueVariables(variables.bootstrap, bootstrapBaseVariables),
			lexicon: this._getUniqueVariables(variables.lexicon, lexiconBaseVariables)
		};
	},

	_generateVariablesString: function(variableMap) {
		var instance = this;

		return _.map(variableMap, function(item, index) {
			if (_.isObject(item)) {
				var header = '\n// ' + index + '\n\n';

				return header + instance._generateVariablesString(item);
			}
			else {
				return index + ': ' + item + ';\n'
			}
		}).join('');
	}
};
<|endoftext|>


<commit_before>/**
 * Yobi, Project Hosting SW
 *
 * Copyright 2013 NAVER Corp.
 * http://yobi.io
 *
 * @Author JiHan Kim
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function(ns){
    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        /**
         * initialize
         */
        function _init(htOptions){
            _initVar(htOptions || {});
            _initElement(htOptions || {});
            _attachEvent();

            _initFileUploader();
        }

        /**
         * 변수 초기화
         * initialize variables
         */
        function _initVar() {
            htVar.sFormURL = htOptions.sFormURL;
            htVar.oFromProject = new yobi.ui.Dropdown({"elContainer": htOptions.welFromProject});
            htVar.oToProject = new yobi.ui.Dropdown({"elContainer": htOptions.welToProject});
            htVar.oFromBranch  = new yobi.ui.Dropdown({"elContainer": htOptions.welFromBranch});
            htVar.oToBranch  = new yobi.ui.Dropdown({"elContainer": htOptions.welToBranch});
            htVar.sUploaderId = null;
            htVar.oSpinner = null;

            htVar.htUserInput = {};
            htVar.sTplFileItem = $('#tplAttachedFile').text();
        }

        /**
         * 엘리먼트 변수 초기화
         * initialize element variables
         */
        function _initElement(htOptions){
            htElement.welForm = $("form.nm");
            htElement.welInputTitle = $('#title');
            htElement.welInputBody  = $('#body');

            htElement.welInputFromProject = $('input[name="fromProjectId"]');
            htElement.welInputToProject = $('input[name="toProjectId"]');
            htElement.welInputFromBranch = $('input[name="fromBranch"]');
            htElement.welInputToBranch = $('input[name="toBranch"]');

            htElement.welUploader = $("#upload");
            htElement.welContainer = $("#frmWrap");
        }

        /**
         * 이벤트 핸들러 설정
         * attach event handlers
         */
        function _attachEvent(){
            htElement.welForm.submit(_onSubmitForm);
            htElement.welInputTitle.on("keyup", _onKeyupInput);
            htElement.welInputBody.on("keyup", _onKeyupInput);

            htVar.oFromProject.onChange(_refreshNewPullRequestForm);
            htVar.oToProject.onChange(_refreshNewPullRequestForm);
            htVar.oFromBranch.onChange(_reloadNewPullRequestForm);
            htVar.oToBranch.onChange(_reloadNewPullRequestForm);

            $('#helpMessage').hide();
            $('#helpBtn').click(function(e){
                e.preventDefault();
                $('#helpMessage').toggle();
            });

            $('body').on('click','button.more',function(){
               $(this).next('pre').toggleClass("hidden");
            });
        }

        /**
         * 제목/내용에 키 입력이 발생할 때의 이벤트 핸들러
         *
         * @param {Wrapped Event} weEvt
         */
        function _onKeyupInput(weEvt){
            var welTarget = $(weEvt.target);
            var sInputId = welTarget.attr("id");
            htVar.htUserInput = htVar.htUserInput || {};
            htVar.htUserInput[sInputId] = true;
        }

        /**
         * 프로젝트 선택이 바뀌면 페이지를 새로고침
         *
         * @private
         */
        function _refreshNewPullRequestForm(){
            var htData = {};

            htData.fromProjectId = htVar.oFromProject.getValue();
            htData.toProjectId = htVar.oToProject.getValue();

            document.location.href = htVar.sFormURL + "?fromProjectId=" + htData.fromProjectId + "&toProjectId=" + htData.toProjectId;
        }

        /**
         * 브랜치 선택이 바뀌면 폼 내용을 변경한다
         * request to reload pullRequestForm
         */
        function _reloadNewPullRequestForm(){
            var htData = {};
            htData.fromBranch = htVar.oFromBranch.getValue();
            htData.toBranch = htVar.oToBranch.getValue();
            htData.fromProjectId = htVar.oFromProject.getValue();
            htData.toProjectId = htVar.oToProject.getValue();

            if(!(htData.fromBranch && htData.toBranch)) {
                return;
            }

            _startSpinner();

            $.ajax(htVar.sFormURL, {
                "method" : "get",
                "data"   : htData,
                "success": _onSuccessReloadForm,
                "error"  : _onErrorReloadForm
            });
        }

        /**
         * onSuccess to reloadForm
         */
        function _onSuccessReloadForm(sRes){
            var sTitle = htElement.welInputTitle.val();
            var sBody = htElement.welInputBody.val();

            htElement.welContainer.html(sRes);
            _reloadElement();

            // 만약 사용자가 입력한 제목이나 본문이 있으면 내용을 유지한다
            if(sTitle.length > 0 && htVar.htUserInput.title){
                htElement.welInputTitle.val(sTitle);
            }
            if(sBody.length > 0 && htVar.htUserInput.body){
                htElement.welInputBody.val(sBody);
            }

            _initFileUploader();
            _stopSpinner();
        }

        /**
         * pjax 영역 변화에 의해 다시 찾아야 하는 엘리먼트 레퍼런스
         * _onSuccessReloadForm 에서 호출
         */
        function _reloadElement(){
            htElement.welInputTitle = $('#title');
            htElement.welInputBody  = $('#body');
            htElement.welUploader = $("#upload");

            htElement.welInputTitle.on("keyup", _onKeyupInput);
            htElement.welInputBody.on("keyup", _onKeyupInput);
        }

        /**
         * onFailed to reloadForm
         */
        function _onErrorReloadForm(oRes){
            _stopSpinner();
            $yobi.alert(Messages("pullRequest.error.newPullRequestForm", oRes.status, oRes.statusText));
        }

        /**
         * Spinner 시작
         */
        function _startSpinner(){
            htVar.oSpinner = htVar.oSpinner || new Spinner();
            htVar.oSpinner.spin(document.getElementById('spin'));
        }

        /**
         * Spinner 종료
         */
        function _stopSpinner(){
            if(htVar.oSpinner){
                htVar.oSpinner.stop();
            }
            htVar.oSpinner = null;
        }

        /**
         * Event handler on submit form
         */
        function _onSubmitForm(weEvt){
            return _validateForm();
        }

        /**
         * 폼 유효성 검사
         * Validate form before submit
         */
        function _validateForm(){
            // these two fields should be loaded dynamically.
            htElement.welInputFromBranch = $('input[name="fromBranch"]');
            htElement.welInputToBranch = $('input[name="toBranch"]');
            htElement.welInputFromProject = $('input[name="fromProjectId"]');
            htElement.welInputToProject = $('input[name="toProjectId"]');

            // check whether required field is empty
            var htRequired = {
                "title"     : $.trim(htElement.welInputTitle.val()),
                "fromProject": $.trim(htElement.welInputFromProject.val()),
                "toProject" : $.trim(htElement.welInputToProject.val()),
                "fromBranch": $.trim(htElement.welInputFromBranch.val()),
                "toBranch"  : $.trim(htElement.welInputToBranch.val())
            };

            for(var sMessageKey in htRequired){
                if(htRequired[sMessageKey].length === 0){
                    $yobi.alert(Messages("pullRequest." + sMessageKey + ".required"));
                    return false;
                }
            }

            if(!htVar.sFormURL) {
                return true;
            }

            var bCommitNotChanged = $.trim($("#commitChanged").val()) != "true";

            if(bCommitNotChanged) {
                $yobi.alert(Messages("pullRequest.diff.noChanges"));
                return false;
            }
            return true;
        }

        /**
         * 파일업로더 초기화
         * initialize fileUploader
         */
        function _initFileUploader(){
            // 이미 설정된 업로더가 있으면 제거하고 재설정
            // reloadNewPullRequest 에서 브랜치 선택할 때 마다 입력 영역이 변하기 때문
            if(htVar.sUploaderId){
                htVar.oAttachments.destroy();
                yobi.Files.destroyUploader(htVar.sUploaderId);
                htVar.sUploaderId = null;
            }

            // 업로더 초기화
            var oUploader = yobi.Files.getUploader(htElement.welUploader, htElement.welInputBody);
            if(oUploader){
                htVar.sUploaderId = oUploader.attr("data-namespace");
                htVar.oAttachments = new yobi.Attachments({
                    "elContainer"  : htElement.welUploader,
                    "elTextarea"   : htElement.welInputBody,
                    "sTplFileItem" : htVar.sTplFileItem,
                    "sUploaderId"  : htVar.sUploaderId
                });
            }
        }

        _init(htOptions || {});
    };
})("yobi.git.Write");
<commit_msg>PullRequest: fix moreBtn for multiline commit msg<commit_after>/**
 * Yobi, Project Hosting SW
 *
 * Copyright 2013 NAVER Corp.
 * http://yobi.io
 *
 * @Author JiHan Kim
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function(ns){
    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        /**
         * initialize
         */
        function _init(htOptions){
            _initVar(htOptions || {});
            _initElement(htOptions || {});
            _attachEvent();

            _initFileUploader();
        }

        /**
         * 변수 초기화
         * initialize variables
         */
        function _initVar() {
            htVar.sFormURL = htOptions.sFormURL;
            htVar.oFromProject = new yobi.ui.Dropdown({"elContainer": htOptions.welFromProject});
            htVar.oToProject = new yobi.ui.Dropdown({"elContainer": htOptions.welToProject});
            htVar.oFromBranch  = new yobi.ui.Dropdown({"elContainer": htOptions.welFromBranch});
            htVar.oToBranch  = new yobi.ui.Dropdown({"elContainer": htOptions.welToBranch});
            htVar.sUploaderId = null;
            htVar.oSpinner = null;

            htVar.htUserInput = {};
            htVar.sTplFileItem = $('#tplAttachedFile').text();
        }

        /**
         * 엘리먼트 변수 초기화
         * initialize element variables
         */
        function _initElement(htOptions){
            htElement.welForm = $("form.nm");
            htElement.welInputTitle = $('#title');
            htElement.welInputBody  = $('#body');

            htElement.welInputFromProject = $('input[name="fromProjectId"]');
            htElement.welInputToProject = $('input[name="toProjectId"]');
            htElement.welInputFromBranch = $('input[name="fromBranch"]');
            htElement.welInputToBranch = $('input[name="toBranch"]');

            htElement.welUploader = $("#upload");
            htElement.welContainer = $("#frmWrap");
        }

        /**
         * 이벤트 핸들러 설정
         * attach event handlers
         */
        function _attachEvent(){
            htElement.welForm.submit(_onSubmitForm);
            htElement.welInputTitle.on("keyup", _onKeyupInput);
            htElement.welInputBody.on("keyup", _onKeyupInput);

            htVar.oFromProject.onChange(_refreshNewPullRequestForm);
            htVar.oToProject.onChange(_refreshNewPullRequestForm);
            htVar.oFromBranch.onChange(_reloadNewPullRequestForm);
            htVar.oToBranch.onChange(_reloadNewPullRequestForm);

            $('#helpMessage').hide();
            $('#helpBtn').click(function(e){
                e.preventDefault();
                $('#helpMessage').toggle();
            });

            $(document.body).on("click", "button.moreBtn", function(){
                $(this).next("pre.commitMsg.desc").toggleClass("hidden");
            });
        }

        /**
         * 제목/내용에 키 입력이 발생할 때의 이벤트 핸들러
         *
         * @param {Wrapped Event} weEvt
         */
        function _onKeyupInput(weEvt){
            var welTarget = $(weEvt.target);
            var sInputId = welTarget.attr("id");
            htVar.htUserInput = htVar.htUserInput || {};
            htVar.htUserInput[sInputId] = true;
        }

        /**
         * 프로젝트 선택이 바뀌면 페이지를 새로고침
         *
         * @private
         */
        function _refreshNewPullRequestForm(){
            var htData = {};

            htData.fromProjectId = htVar.oFromProject.getValue();
            htData.toProjectId = htVar.oToProject.getValue();

            document.location.href = htVar.sFormURL + "?fromProjectId=" + htData.fromProjectId + "&toProjectId=" + htData.toProjectId;
        }

        /**
         * 브랜치 선택이 바뀌면 폼 내용을 변경한다
         * request to reload pullRequestForm
         */
        function _reloadNewPullRequestForm(){
            var htData = {};
            htData.fromBranch = htVar.oFromBranch.getValue();
            htData.toBranch = htVar.oToBranch.getValue();
            htData.fromProjectId = htVar.oFromProject.getValue();
            htData.toProjectId = htVar.oToProject.getValue();

            if(!(htData.fromBranch && htData.toBranch)) {
                return;
            }

            _startSpinner();

            $.ajax(htVar.sFormURL, {
                "method" : "get",
                "data"   : htData,
                "success": _onSuccessReloadForm,
                "error"  : _onErrorReloadForm
            });
        }

        /**
         * onSuccess to reloadForm
         */
        function _onSuccessReloadForm(sRes){
            var sTitle = htElement.welInputTitle.val();
            var sBody = htElement.welInputBody.val();

            htElement.welContainer.html(sRes);
            _reloadElement();

            // 만약 사용자가 입력한 제목이나 본문이 있으면 내용을 유지한다
            if(sTitle.length > 0 && htVar.htUserInput.title){
                htElement.welInputTitle.val(sTitle);
            }
            if(sBody.length > 0 && htVar.htUserInput.body){
                htElement.welInputBody.val(sBody);
            }

            _initFileUploader();
            _stopSpinner();
        }

        /**
         * pjax 영역 변화에 의해 다시 찾아야 하는 엘리먼트 레퍼런스
         * _onSuccessReloadForm 에서 호출
         */
        function _reloadElement(){
            htElement.welInputTitle = $('#title');
            htElement.welInputBody  = $('#body');
            htElement.welUploader = $("#upload");

            htElement.welInputTitle.on("keyup", _onKeyupInput);
            htElement.welInputBody.on("keyup", _onKeyupInput);
        }

        /**
         * onFailed to reloadForm
         */
        function _onErrorReloadForm(oRes){
            _stopSpinner();
            $yobi.alert(Messages("pullRequest.error.newPullRequestForm", oRes.status, oRes.statusText));
        }

        /**
         * Spinner 시작
         */
        function _startSpinner(){
            htVar.oSpinner = htVar.oSpinner || new Spinner();
            htVar.oSpinner.spin(document.getElementById('spin'));
        }

        /**
         * Spinner 종료
         */
        function _stopSpinner(){
            if(htVar.oSpinner){
                htVar.oSpinner.stop();
            }
            htVar.oSpinner = null;
        }

        /**
         * Event handler on submit form
         */
        function _onSubmitForm(weEvt){
            return _validateForm();
        }

        /**
         * 폼 유효성 검사
         * Validate form before submit
         */
        function _validateForm(){
            // these two fields should be loaded dynamically.
            htElement.welInputFromBranch = $('input[name="fromBranch"]');
            htElement.welInputToBranch = $('input[name="toBranch"]');
            htElement.welInputFromProject = $('input[name="fromProjectId"]');
            htElement.welInputToProject = $('input[name="toProjectId"]');

            // check whether required field is empty
            var htRequired = {
                "title"     : $.trim(htElement.welInputTitle.val()),
                "fromProject": $.trim(htElement.welInputFromProject.val()),
                "toProject" : $.trim(htElement.welInputToProject.val()),
                "fromBranch": $.trim(htElement.welInputFromBranch.val()),
                "toBranch"  : $.trim(htElement.welInputToBranch.val())
            };

            for(var sMessageKey in htRequired){
                if(htRequired[sMessageKey].length === 0){
                    $yobi.alert(Messages("pullRequest." + sMessageKey + ".required"));
                    return false;
                }
            }

            if(!htVar.sFormURL) {
                return true;
            }

            var bCommitNotChanged = $.trim($("#commitChanged").val()) != "true";

            if(bCommitNotChanged) {
                $yobi.alert(Messages("pullRequest.diff.noChanges"));
                return false;
            }
            return true;
        }

        /**
         * 파일업로더 초기화
         * initialize fileUploader
         */
        function _initFileUploader(){
            // 이미 설정된 업로더가 있으면 제거하고 재설정
            // reloadNewPullRequest 에서 브랜치 선택할 때 마다 입력 영역이 변하기 때문
            if(htVar.sUploaderId){
                htVar.oAttachments.destroy();
                yobi.Files.destroyUploader(htVar.sUploaderId);
                htVar.sUploaderId = null;
            }

            // 업로더 초기화
            var oUploader = yobi.Files.getUploader(htElement.welUploader, htElement.welInputBody);
            if(oUploader){
                htVar.sUploaderId = oUploader.attr("data-namespace");
                htVar.oAttachments = new yobi.Attachments({
                    "elContainer"  : htElement.welUploader,
                    "elTextarea"   : htElement.welInputBody,
                    "sTplFileItem" : htVar.sTplFileItem,
                    "sUploaderId"  : htVar.sUploaderId
                });
            }
        }

        _init(htOptions || {});
    };
})("yobi.git.Write");
<|endoftext|>


<commit_before>/*!
 * AngularJS complaint controllers
 * Version: 1
 *
 * Copyright 2016 Janaagraha.
 *
 * Author: Jeeva D <jeevananthamcse@gmail.com>
 * Related to project of PM University
 */
app.controller('topicCtrl', function ($scope, Data, $uibModal) {
    $scope.topics = [];
    $scope.loading = false;

    /* pagination settings */
    $scope.totalItems = 0;
    $scope.currentPage = 1;
    $scope.itemsPerPage = 10;
    $scope.maxSize = 5;
    $scope.filterTitle = 'All Complaints';

    /* for sorting */
    $scope.state = 'DESC';
    $scope.orderby = 'id';
    getResultsPage();
    function getResultsPage() {
        $scope.loading = true;
        var url = '/api/v1/admin/1/topics?api_token=94D63B96-7A4F-175C-383A-32F9B628EBEC&locale=en&perPage='+$scope.itemsPerPage+'&page='+$scope.currentPage;
        //var url = '/api/v1/admin/1/topics?locale=en&perPage='+$scope.itemsPerPage+'&page='+$scope.currentPage;
        //Data.post('complaint/lists/' + $scope.itemsPerPage + '/' + $scope.currentPage + '/' + $scope.orderby + '/' + $scope.state,
        Data.get(url,{filters: ''}).then(function (response) {
            $scope.loading = false;
            $scope.topics = response.data.topics;
            //console.log(response.data.topics);
            $scope.totalItems = response.data.total;
        });
    }
});
app.controller('compListCtrl', function ($scope, Data, $uibModal, $filter) {
    $scope.complaints = [];
    $scope.loading = false;
    $scope.checkedAny = false;
    /* pagination settings */
    $scope.totalItems = 0;
    $scope.currentPage = 1;
    $scope.itemsPerPage = 10;
    $scope.maxSize = 5;
    $scope.filterTitle = 'All Complaints';
    /* Status defaults */
    $scope.statusOpen = 0;
    $scope.statusOnthejob = 0;
    $scope.statusResolved = 0;
    /* for sorting */
    $scope.state = 'DESC';
    $scope.orderby = 'id';
    $scope.filter = {city: '', status: '', category: '', ward: '', term: '', priority: ''};
    /*set page*/
    $scope.setPage = function (pageNo) {
        $scope.currentPage = pageNo;
    };
    /*on page change*/
    $scope.pageChanged = function () {
        getResultsPage();
    };
    /* pagination settings */
    /* Check all */
    $scope.toggleAll = function () {
        var toggleStatus = $scope.isAllSelected;
        angular.forEach($scope.complaints, function (itm) {
            itm.cChecked = toggleStatus;
            //$scope.checkedAny = toggleStatus;
        });
    };
    /* Check each check box */
    $scope.optionToggled = function () {
        $scope.isAllSelected = $scope.complaints.every(function (itm) {
            return itm.cChecked;
        });
    };

    $scope.$watch("complaints", function (n, o) {
        var trues = $filter("filter")(n, {cChecked: true});
        $scope.checkedAny = (trues.length) ? true : false;
    }, true);
    /***Date range***/
    $scope.day = 1;
    $scope.date = {
        startDate: moment().subtract($scope.day, "days"),
        endDate: moment()
    };
    $scope.setRange = function (day) {
        $scope.day = day;
        $scope.date = {
            startDate: moment().subtract(day, "days"),
            endDate: moment()
        };
    };

    //Watch for date changes
    $scope.$watch('date', function (newDate) {
        $scope.filter.startDate = newDate.startDate.format('YYYY-MM-DD');
        $scope.filter.endDate = newDate.endDate.format('YYYY-MM-DD');

        var days = Math.round((newDate.endDate - newDate.startDate) / 86400000);
        //console.log('days='+days);

        if ((newDate.endDate.format('YYYY-MM-DD') == moment().format('YYYY-MM-DD')) && (days == 7 || days == 30 || days == 1)) {
            $scope.day = days;
        } else {
            $scope.day = 0;
        }
        getResultsPage();
    }, false);
    /***Date range***/

    /* Filters */
    $scope.sortingList = function (filterColumn, order) {
        $scope.orderby = filterColumn;
        $scope.state = (order == 'DESC') ? 'ASC' : 'DESC';
        getResultsPage()
    }

    $scope.setStatus = function (key, name) {
        $scope.filter.priority = '';
        $scope.filter.status = key;
        $scope.filterTitle = name;
        getResultsPage();
    }
    $scope.setPriority = function (key, name) {
        $scope.filter.priority = key;
        $scope.filter.status = '';
        $scope.filterTitle = name;
        getResultsPage();
    }
    $scope.setCategory = function (key) {
        $scope.filter.category = key;
        getResultsPage();
    }
    $scope.setCity = function (key) {
        $scope.filter.city = key;
        getResultsPage();
    }
    $scope.setWard = function (key) {
        $scope.filter.ward = key;
        getResultsPage();
    }
    $scope.termSearch = function (term) {
        $scope.filter.term = term;
        getResultsPage();
    }
    /* Search */
    $scope.isSearch = false;

    $scope.openSearch = function () {
        $scope.isSearch = true;
    }

    $scope.closeSearch = function () {
        $scope.filter.term = '';
        getResultsPage();
        $scope.isSearch = false;
    }
    /* change priority */
    $scope.savePriority = function (complaintId, priority) {
        Data.put('complaint/changepriority', {complaintId: complaintId, priority: priority}).then(function (response) {
            Data.toast(response);
        });
    }

    function getResultsPage() {
        $scope.loading = true;
        //$scope.complaints = [];
        Data.post('complaint/lists/' + $scope.itemsPerPage + '/' + $scope.currentPage + '/' + $scope.orderby + '/' + $scope.state,
                {filters: $scope.filter}).then(function (response) {
            $scope.loading = false;
            $scope.complaints = response.result;
            $scope.totalItems = response.total_count;
            $scope.statusOpen = response.open;
            $scope.statusOnthejob = response.onthejob;
            $scope.statusResolved = response.resolved;
        });
    }
    $scope.engineers = [];
    Data.get('user/lists/0/' + $scope.currentPage + '/' + $scope.orderby).then(function (response) {
        $scope.engineers = response.result;
    });
    $scope.animationsEnabled = true;
    $scope.complaint_id = '';
    $scope.open = function (complaintId) {
        $scope.complaintId = complaintId;
        var modalInstance = $uibModal.open({
            animation: $scope.animationsEnabled,
            backdrop: 'static',
            templateUrl: 'assignComplaintModal.html',
            controller: 'ModalInstanceCtrl',
            resolve: {
                items: function () {
                    return $scope.engineers;
                },
                id: function () {
                    return $scope.complaintId;
                }
            }
        });
    };
    $scope.escengineers = [];
    Data.get('user/get_escengineers').then(function (response) {
        $scope.escengineers = response.result;
    });
    $scope.animationsEnabled = true;
    $scope.complaint_id = '';
    $scope.openEsc = function (complaintId) {
        $scope.complaintId = complaintId;
        var modalInstance = $uibModal.open({
            animation: $scope.animationsEnabled,
            backdrop: 'static',
            templateUrl: 'assingEscalationModal.html',
            controller: 'EscModalInstanceCtrl',
            resolve: {
                items: function () {
                    return $scope.escengineers;
                },
                id: function () {
                    return $scope.complaintId;
                }
            }
        });
    };
    /* for status popup */
    $scope.statusPopup = function (status, compId) {
        $scope.status = status;
        $scope.compId = compId;
        var modalInstance = $uibModal.open({
            animation: $scope.animationsEnabled,
            backdrop: 'static',
            templateUrl: 'commentForStatusModal.html',
            controller: 'StatusModalInstanceCtrl',
            resolve: {
                comment: function () {
                    return $scope.comment;
                },
                status: function () {
                    return $scope.status;
                },
                compId: function () {
                    return $scope.compId;
                }
            }
        });
    }
});
// Please note that $uibModalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.

app.controller('ModalInstanceCtrl', function ($scope, $rootScope, $location, $http, Data, $window, $uibModalInstance, items, id, Data) {
    $scope.items = items;
    $scope.compId = id;
    $scope.assignEngineer = function (compId, engiId) {
        Data.post('complaint/assign_engineer', {complaint_id: compId, engineer_id: engiId}).then(function (response) {
            if (response.status == 'success') {
                Data.toast(response);
                $uibModalInstance.dismiss('cancel');
            } else {
                $scope.error_complaint_assigned = response.message;
            }
        });
    };
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});
app.controller('EscModalInstanceCtrl', function ($scope, $rootScope, $location, $http, Data, $window, $uibModalInstance, items, id, Data) {
    $scope.items = items;
    $scope.compId = id;
    $scope.assignEscEngineer = function (compId, engiId) {
        Data.post('complaint/assign_escalation_eng', {complaint_id: compId, engineer_id: engiId}).then(function (response) {
            if (response.status == 'success') {
                Data.toast(response);
                $uibModalInstance.dismiss('cancel');
            } else {
                $scope.error_complaint_assigned = response.message;
            }
        });
    };
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});
app.controller('StatusModalInstanceCtrl', function ($scope, $rootScope, $location, $http, Data, $window, $uibModalInstance, comment, status, compId) {
    $scope.comment = comment;
    $scope.compId = compId;
    $scope.status = status;
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
    $scope.writeComment = function (compId, comment, status) {
        Data.put('complaint/changestatus', {complaintId: compId, comment: comment, status: status}).then(function (response) {
            Data.toast(response);
            $uibModalInstance.dismiss('cancel');
        });
    };
});

<commit_msg>Api token updated<commit_after>/*!
 * AngularJS complaint controllers
 * Version: 1
 *
 * Copyright 2016 Janaagraha.
 *
 * Author: Jeeva D <jeevananthamcse@gmail.com>
 * Related to project of PM University
 */
app.controller('topicCtrl', function ($scope, Data, $uibModal) {
    $scope.topics = [];
    $scope.loading = false;

    /* pagination settings */
    $scope.totalItems = 0;
    $scope.currentPage = 1;
    $scope.itemsPerPage = 10;
    $scope.maxSize = 5;
    $scope.filterTitle = 'All Complaints';

    /* for sorting */
    $scope.state = 'DESC';
    $scope.orderby = 'id';
    getResultsPage();
    function getResultsPage() {
        $scope.loading = true;
        var url = '/api/v1/admin/1/topics?api_token=032FF917-8F9F-7907-E9F9-5DCC1374E38A&locale=en&perPage='+$scope.itemsPerPage+'&page='+$scope.currentPage;
        //var url = '/api/v1/admin/1/topics?locale=en&perPage='+$scope.itemsPerPage+'&page='+$scope.currentPage;
        //Data.post('complaint/lists/' + $scope.itemsPerPage + '/' + $scope.currentPage + '/' + $scope.orderby + '/' + $scope.state,
        Data.get(url,{filters: ''}).then(function (response) {
            $scope.loading = false;
            $scope.topics = response.data.topics;
            //console.log(response.data.topics);
            $scope.totalItems = response.data.total;
        });
    }
});
app.controller('compListCtrl', function ($scope, Data, $uibModal, $filter) {
    $scope.complaints = [];
    $scope.loading = false;
    $scope.checkedAny = false;
    /* pagination settings */
    $scope.totalItems = 0;
    $scope.currentPage = 1;
    $scope.itemsPerPage = 10;
    $scope.maxSize = 5;
    $scope.filterTitle = 'All Complaints';
    /* Status defaults */
    $scope.statusOpen = 0;
    $scope.statusOnthejob = 0;
    $scope.statusResolved = 0;
    /* for sorting */
    $scope.state = 'DESC';
    $scope.orderby = 'id';
    $scope.filter = {city: '', status: '', category: '', ward: '', term: '', priority: ''};
    /*set page*/
    $scope.setPage = function (pageNo) {
        $scope.currentPage = pageNo;
    };
    /*on page change*/
    $scope.pageChanged = function () {
        getResultsPage();
    };
    /* pagination settings */
    /* Check all */
    $scope.toggleAll = function () {
        var toggleStatus = $scope.isAllSelected;
        angular.forEach($scope.complaints, function (itm) {
            itm.cChecked = toggleStatus;
            //$scope.checkedAny = toggleStatus;
        });
    };
    /* Check each check box */
    $scope.optionToggled = function () {
        $scope.isAllSelected = $scope.complaints.every(function (itm) {
            return itm.cChecked;
        });
    };

    $scope.$watch("complaints", function (n, o) {
        var trues = $filter("filter")(n, {cChecked: true});
        $scope.checkedAny = (trues.length) ? true : false;
    }, true);
    /***Date range***/
    $scope.day = 1;
    $scope.date = {
        startDate: moment().subtract($scope.day, "days"),
        endDate: moment()
    };
    $scope.setRange = function (day) {
        $scope.day = day;
        $scope.date = {
            startDate: moment().subtract(day, "days"),
            endDate: moment()
        };
    };

    //Watch for date changes
    $scope.$watch('date', function (newDate) {
        $scope.filter.startDate = newDate.startDate.format('YYYY-MM-DD');
        $scope.filter.endDate = newDate.endDate.format('YYYY-MM-DD');

        var days = Math.round((newDate.endDate - newDate.startDate) / 86400000);
        //console.log('days='+days);

        if ((newDate.endDate.format('YYYY-MM-DD') == moment().format('YYYY-MM-DD')) && (days == 7 || days == 30 || days == 1)) {
            $scope.day = days;
        } else {
            $scope.day = 0;
        }
        getResultsPage();
    }, false);
    /***Date range***/

    /* Filters */
    $scope.sortingList = function (filterColumn, order) {
        $scope.orderby = filterColumn;
        $scope.state = (order == 'DESC') ? 'ASC' : 'DESC';
        getResultsPage()
    }

    $scope.setStatus = function (key, name) {
        $scope.filter.priority = '';
        $scope.filter.status = key;
        $scope.filterTitle = name;
        getResultsPage();
    }
    $scope.setPriority = function (key, name) {
        $scope.filter.priority = key;
        $scope.filter.status = '';
        $scope.filterTitle = name;
        getResultsPage();
    }
    $scope.setCategory = function (key) {
        $scope.filter.category = key;
        getResultsPage();
    }
    $scope.setCity = function (key) {
        $scope.filter.city = key;
        getResultsPage();
    }
    $scope.setWard = function (key) {
        $scope.filter.ward = key;
        getResultsPage();
    }
    $scope.termSearch = function (term) {
        $scope.filter.term = term;
        getResultsPage();
    }
    /* Search */
    $scope.isSearch = false;

    $scope.openSearch = function () {
        $scope.isSearch = true;
    }

    $scope.closeSearch = function () {
        $scope.filter.term = '';
        getResultsPage();
        $scope.isSearch = false;
    }
    /* change priority */
    $scope.savePriority = function (complaintId, priority) {
        Data.put('complaint/changepriority', {complaintId: complaintId, priority: priority}).then(function (response) {
            Data.toast(response);
        });
    }

    function getResultsPage() {
        $scope.loading = true;
        //$scope.complaints = [];
        Data.post('complaint/lists/' + $scope.itemsPerPage + '/' + $scope.currentPage + '/' + $scope.orderby + '/' + $scope.state,
                {filters: $scope.filter}).then(function (response) {
            $scope.loading = false;
            $scope.complaints = response.result;
            $scope.totalItems = response.total_count;
            $scope.statusOpen = response.open;
            $scope.statusOnthejob = response.onthejob;
            $scope.statusResolved = response.resolved;
        });
    }
    $scope.engineers = [];
    Data.get('user/lists/0/' + $scope.currentPage + '/' + $scope.orderby).then(function (response) {
        $scope.engineers = response.result;
    });
    $scope.animationsEnabled = true;
    $scope.complaint_id = '';
    $scope.open = function (complaintId) {
        $scope.complaintId = complaintId;
        var modalInstance = $uibModal.open({
            animation: $scope.animationsEnabled,
            backdrop: 'static',
            templateUrl: 'assignComplaintModal.html',
            controller: 'ModalInstanceCtrl',
            resolve: {
                items: function () {
                    return $scope.engineers;
                },
                id: function () {
                    return $scope.complaintId;
                }
            }
        });
    };
    $scope.escengineers = [];
    Data.get('user/get_escengineers').then(function (response) {
        $scope.escengineers = response.result;
    });
    $scope.animationsEnabled = true;
    $scope.complaint_id = '';
    $scope.openEsc = function (complaintId) {
        $scope.complaintId = complaintId;
        var modalInstance = $uibModal.open({
            animation: $scope.animationsEnabled,
            backdrop: 'static',
            templateUrl: 'assingEscalationModal.html',
            controller: 'EscModalInstanceCtrl',
            resolve: {
                items: function () {
                    return $scope.escengineers;
                },
                id: function () {
                    return $scope.complaintId;
                }
            }
        });
    };
    /* for status popup */
    $scope.statusPopup = function (status, compId) {
        $scope.status = status;
        $scope.compId = compId;
        var modalInstance = $uibModal.open({
            animation: $scope.animationsEnabled,
            backdrop: 'static',
            templateUrl: 'commentForStatusModal.html',
            controller: 'StatusModalInstanceCtrl',
            resolve: {
                comment: function () {
                    return $scope.comment;
                },
                status: function () {
                    return $scope.status;
                },
                compId: function () {
                    return $scope.compId;
                }
            }
        });
    }
});
// Please note that $uibModalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.

app.controller('ModalInstanceCtrl', function ($scope, $rootScope, $location, $http, Data, $window, $uibModalInstance, items, id, Data) {
    $scope.items = items;
    $scope.compId = id;
    $scope.assignEngineer = function (compId, engiId) {
        Data.post('complaint/assign_engineer', {complaint_id: compId, engineer_id: engiId}).then(function (response) {
            if (response.status == 'success') {
                Data.toast(response);
                $uibModalInstance.dismiss('cancel');
            } else {
                $scope.error_complaint_assigned = response.message;
            }
        });
    };
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});
app.controller('EscModalInstanceCtrl', function ($scope, $rootScope, $location, $http, Data, $window, $uibModalInstance, items, id, Data) {
    $scope.items = items;
    $scope.compId = id;
    $scope.assignEscEngineer = function (compId, engiId) {
        Data.post('complaint/assign_escalation_eng', {complaint_id: compId, engineer_id: engiId}).then(function (response) {
            if (response.status == 'success') {
                Data.toast(response);
                $uibModalInstance.dismiss('cancel');
            } else {
                $scope.error_complaint_assigned = response.message;
            }
        });
    };
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});
app.controller('StatusModalInstanceCtrl', function ($scope, $rootScope, $location, $http, Data, $window, $uibModalInstance, comment, status, compId) {
    $scope.comment = comment;
    $scope.compId = compId;
    $scope.status = status;
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
    $scope.writeComment = function (compId, comment, status) {
        Data.put('complaint/changestatus', {complaintId: compId, comment: comment, status: status}).then(function (response) {
            Data.toast(response);
            $uibModalInstance.dismiss('cancel');
        });
    };
});

<|endoftext|>


<commit_before>var types = require('./types');

var _WHITESPACE = [];
var _ANYCHAR = [];
for (var i = 0; i < 65536; i++) {
  if (!/./.test(String.fromCharCode(i))) _ANYCHAR.push(i);
  if (/\w/.test(String.fromCharCode(i))) _WHITESPACE.push(i);
}

var INTS = function() {
 return [{ type: types.RANGE , from: 48, to: 57 }];
};

var WORDS = function() {
 return [
      { type: types.CHAR, value: 95 }
    , { type: types.RANGE, from: 97, to: 122 }
    , { type: types.RANGE, from: 65, to: 90 }
  ].concat(INTS());
};

var WHITESPACE = function() {
  return _WHITESPACE.map(function (value) {
    return {type: types.CHAR, value: value}
  });
};

var ANYCHAR = function() {
  return _ANYCHAR.map(function (value) {
    return {type: types.CHAR, value: value}
  });
};

// predefined class objects
exports.words = function() {
  return { type: types.SET, set: WORDS(), not: false };
};

exports.notWords = function() {
  return { type: types.SET, set: WORDS(), not: true };
};

exports.ints = function() {
  return { type: types.SET, set: INTS(), not: false };
};

exports.notInts = function() {
  return { type: types.SET, set: INTS(), not: true };
};

exports.whitespace = function() {
  return { type: types.SET, set: WHITESPACE(), not: false };
};

exports.notWhitespace = function() {
  return { type: types.SET, set: WHITESPACE(), not: true };
};

exports.anyChar = function() {
  return { type: types.SET, set: ANYCHAR(), not: false };
};
<commit_msg>whitespace is \s not \w and anychar is everything but .<commit_after>var types = require('./types');

var _WHITESPACE = [];
var _NOTANYCHAR = [];
for (var i = 0; i < 65536; i++) {
  if (!/./.test(String.fromCharCode(i))) _NOTANYCHAR.push(i);
  if (/\s/.test(String.fromCharCode(i))) _WHITESPACE.push(i);
}

var INTS = function() {
 return [{ type: types.RANGE , from: 48, to: 57 }];
};

var WORDS = function() {
 return [
      { type: types.CHAR, value: 95 }
    , { type: types.RANGE, from: 97, to: 122 }
    , { type: types.RANGE, from: 65, to: 90 }
  ].concat(INTS());
};

var WHITESPACE = function() {
  return _WHITESPACE.map(function (value) {
    return {type: types.CHAR, value: value}
  });
};

var NOTANYCHAR = function() {
  return _NOTANYCHAR.map(function (value) {
    return {type: types.CHAR, value: value}
  });
};

// predefined class objects
exports.words = function() {
  return { type: types.SET, set: WORDS(), not: false };
};

exports.notWords = function() {
  return { type: types.SET, set: WORDS(), not: true };
};

exports.ints = function() {
  return { type: types.SET, set: INTS(), not: false };
};

exports.notInts = function() {
  return { type: types.SET, set: INTS(), not: true };
};

exports.whitespace = function() {
  return { type: types.SET, set: WHITESPACE(), not: false };
};

exports.notWhitespace = function() {
  return { type: types.SET, set: WHITESPACE(), not: true };
};

exports.anyChar = function() {
  return { type: types.SET, set: NOTANYCHAR(), not: true };
};
<|endoftext|>


<commit_before>// Copyright 2012 The Obvious Corporation.

/*
 * An in-memory collector for data events.
 */

/*
 * Modules used
 */

"use strict";

var assert = require("assert");
var stream = require("stream");
var util = require("util");

var consts = require("./consts");
var Codec = require("./codec").Codec;
var sealer = require("./sealer");

/*
 * Module variables
 */

/**
 * special error value indicating that there was in fact no error. This
 * is used instead of `undefined` to disambiguate the no-error case from
 * the case of an error receieved but with an `undefined` payload.
 */
var NO_ERROR = [ "no-error" ];

/*
 * Helper functions
 */

/**
 * Construct a Sink state object.
 */
function State(emitter, source) {
    assert.ok(source !== undefined, "Missing source.");

    if (typeof source.on !== "function") {
        throw new Error("Source not an EventEmitter.");
    }

    this.emitter = emitter;
    this.source = source;
    this.decoder = new Codec(); // event emission encoding handler
    this.paused = false;
    this.buffers = []; // incrementally collected buffers
    this.data = undefined; // final combined data
    this.error = NO_ERROR; // error payload that terminated the stream
    this.ready = false; // ready to emit?
    this.ended = false;

    // We `bind()` the event listener callback methods, so that they
    // get an appropriate `this` when they're called during event
    // emission.
    this.onCloseOrEnd = this.onCloseOrEnd.bind(this);
    this.onData = this.onData.bind(this);
    this.onError = this.onError.bind(this);

    source.on(consts.CLOSE, this.onCloseOrEnd);
    source.on(consts.DATA, this.onData);
    source.on(consts.END, this.onCloseOrEnd);
    source.on(consts.ERROR, this.onError);
}

State.prototype.destroy = function destroy() {
    var source = this.source;

    source.removeListener(consts.CLOSE, this.onCloseOrEnd);
    source.removeListener(consts.DATA, this.onData);
    source.removeListener(consts.END, this.onCloseOrEnd);
    source.removeListener(consts.ERROR, this.onError);

    this.emitter = undefined;
    this.paused = false;
    this.buffers = undefined;
    this.data = undefined;
    this.error = undefined;
    this.ready = false;
    this.ended = true;
};

/**
 * Construct the final data value for this instance, and indicate that
 * the instance is ready to emit.
 */
State.prototype.makeData = function makeData() {
    var buffers = this.buffers;

    var totalLength = 0;
    for (var i = 0; i < buffers.length; i++) {
        totalLength += buffers[i].length;
    }

    // Only set this.data if there were any non-empty data events.
    var data = undefined;
    if (totalLength !== 0) {
        if (buffers.length === 1) {
            // Easy case!
            data = buffers[0];
        } else {
            // Hard case: We have to actually combine all the data.
            data = new Buffer(totalLength);
            var at = 0;
            for (var i = 0; i < buffers.length; i++) {
                var one = buffers[i];
	        one.copy(data, at);
	        at += one.length;
            }
        }
    }

    this.data = this.decoder.decode(data);
    this.buffers = undefined; // Prevents extra data events from messing us up.
    this.ready = true;
}

/**
 * Emit the end-of-stream events for this instance.
 */
State.prototype.emitAllEvents = function emitAllEvents() {
    // Capture these variables up-front, to guard against the instance
    // getting `destroy()`ed by one of the event callbacks.
    var emitter = this.emitter;
    var data = this.data;
    var error = this.error;

    if (!emitter) {
        return;
    }

    if (data) {
        emitter.emit(consts.DATA, data);
    }

    if (error === NO_ERROR) {
        emitter.emit(consts.END);
        emitter.emit(consts.CLOSE);
    } else {
        emitter.emit(consts.ERROR, error);
    }

    this.ended = true;
}

State.prototype.isReadable = function isReadable() {
    return !this.ended;
}

State.prototype.pause = function pause() {
    if (!this.ended) {
        this.paused = true;
    }
};

State.prototype.resume = function resume() {
    if (!this.paused) {
        return;
    }

    this.paused = false;
    if (this.ready) {
        this.emitAllEvents();
    }
};

State.prototype.onCloseOrEnd = function onCloseOrEnd() {
    if (this.ended || this.ready) {
        return;
    }

    this.makeData();

    if (!this.paused) {
        this.emitAllEvents();
    }
}

State.prototype.onData = function onData(data) {
    if (this.ended || this.ready) {
        return;
    }

    // TODO: Correctly handle incoming encoding.
    if (typeof data === "string") {
        data = new Buffer(data);
    }

    this.buffers.push(data);
}

State.prototype.onError = function onError(error) {
    if (this.ended || this.ready) {
        return;
    }

    this.error = error;
    this.makeData();

    if (!this.paused) {
        this.emitAllEvents();
    }
}

/*
 * Exported bindings
 */

/**
 * Construct a Sink instance, which collects data events coming from the
 * indicated source stream. Sink instances are in turn instances of
 * `stream.Stream`.
 */
function Sink(source) {
    stream.Stream.call(this);
    this.sink = sealer.seal(new State(this, source));
}

util.inherits(Sink, stream.Stream);

Sink.prototype.destroy = function destroy() {
    sealer.unseal(this.sink).destroy();
};

Sink.prototype.pause = function pause() {
    sealer.unseal(this.sink).pause();
};

Sink.prototype.resume = function resume() {
    sealer.unseal(this.sink).resume();
};

Sink.prototype.setEncoding = function setEncoding(name) {
    sealer.unseal(this.sink).decoder.setEncoding(name);
};

Object.defineProperty(
    Sink.prototype,
    "readable",
    {
        get: function() { return sealer.unseal(this.sink).isReadable(); },
        enumerable: true
    });

/**
 * Sets the incoming encoding. This is how to interpret strings that are
 * received as the payloads of `data` events.
 */
Sink.prototype.setIncomingEncoding = function setIncomingEncoding(name) {
    // FIXME: Handle encoding.
}

/**
 * Gets the final combined data of the instance, if available.
 */
Sink.prototype.getData = function getData() {
    return sealer.unseal(this.sink).data;
}

/**
 * Gets the error that ended the upstream data, if any.
 */
Sink.prototype.getError = function getError() {
    var error = sealer.unseal(this.sink).error;

    return (error === NO_ERROR) ? undefined : error;
}

/**
 * Gets whether or not the stream ended with an error.
 */
Sink.prototype.gotError = function gotError() {
    return sealer.unseal(this.sink).error !== NO_ERROR;
}

Object.freeze(Sink.prototype);

module.exports = {
    Sink: Sink
};
<commit_msg>Implement `setIncomingEncoding()`.<commit_after>// Copyright 2012 The Obvious Corporation.

/*
 * An in-memory collector for data events.
 */

/*
 * Modules used
 */

"use strict";

var assert = require("assert");
var stream = require("stream");
var util = require("util");

var consts = require("./consts");
var Codec = require("./codec").Codec;
var sealer = require("./sealer");

/*
 * Module variables
 */

/**
 * special error value indicating that there was in fact no error. This
 * is used instead of `undefined` to disambiguate the no-error case from
 * the case of an error receieved but with an `undefined` payload.
 */
var NO_ERROR = [ "no-error" ];

/*
 * Helper functions
 */

/**
 * Construct a Sink state object.
 */
function State(emitter, source) {
    assert.ok(source !== undefined, "Missing source.");

    if (typeof source.on !== "function") {
        throw new Error("Source not an EventEmitter.");
    }

    this.emitter = emitter;
    this.source = source;
    this.decoder = new Codec(); // event emission encoding handler
    this.encoder = new Codec(); // event receipt encoding handler
    this.paused = false;
    this.buffers = []; // incrementally collected buffers
    this.data = undefined; // final combined data
    this.error = NO_ERROR; // error payload that terminated the stream
    this.ready = false; // ready to emit?
    this.ended = false;

    // We `bind()` the event listener callback methods, so that they
    // get an appropriate `this` when they're called during event
    // emission.
    this.onCloseOrEnd = this.onCloseOrEnd.bind(this);
    this.onData = this.onData.bind(this);
    this.onError = this.onError.bind(this);

    source.on(consts.CLOSE, this.onCloseOrEnd);
    source.on(consts.DATA, this.onData);
    source.on(consts.END, this.onCloseOrEnd);
    source.on(consts.ERROR, this.onError);
}

State.prototype.destroy = function destroy() {
    var source = this.source;

    source.removeListener(consts.CLOSE, this.onCloseOrEnd);
    source.removeListener(consts.DATA, this.onData);
    source.removeListener(consts.END, this.onCloseOrEnd);
    source.removeListener(consts.ERROR, this.onError);

    this.emitter = undefined;
    this.paused = false;
    this.buffers = undefined;
    this.data = undefined;
    this.error = undefined;
    this.ready = false;
    this.ended = true;
};

/**
 * Construct the final data value for this instance, and indicate that
 * the instance is ready to emit.
 */
State.prototype.makeData = function makeData() {
    var buffers = this.buffers;

    var totalLength = 0;
    for (var i = 0; i < buffers.length; i++) {
        totalLength += buffers[i].length;
    }

    // Only set this.data if there were any non-empty data events.
    var data = undefined;
    if (totalLength !== 0) {
        if (buffers.length === 1) {
            // Easy case!
            data = buffers[0];
        } else {
            // Hard case: We have to actually combine all the data.
            data = new Buffer(totalLength);
            var at = 0;
            for (var i = 0; i < buffers.length; i++) {
                var one = buffers[i];
	        one.copy(data, at);
	        at += one.length;
            }
        }
    }

    this.data = this.decoder.decode(data);
    this.buffers = undefined; // Prevents extra data events from messing us up.
    this.ready = true;
}

/**
 * Emit the end-of-stream events for this instance.
 */
State.prototype.emitAllEvents = function emitAllEvents() {
    // Capture these variables up-front, to guard against the instance
    // getting `destroy()`ed by one of the event callbacks.
    var emitter = this.emitter;
    var data = this.data;
    var error = this.error;

    if (!emitter) {
        return;
    }

    if (data) {
        emitter.emit(consts.DATA, data);
    }

    if (error === NO_ERROR) {
        emitter.emit(consts.END);
        emitter.emit(consts.CLOSE);
    } else {
        emitter.emit(consts.ERROR, error);
    }

    this.ended = true;
}

State.prototype.isReadable = function isReadable() {
    return !this.ended;
}

State.prototype.pause = function pause() {
    if (!this.ended) {
        this.paused = true;
    }
};

State.prototype.resume = function resume() {
    if (!this.paused) {
        return;
    }

    this.paused = false;
    if (this.ready) {
        this.emitAllEvents();
    }
};

State.prototype.onCloseOrEnd = function onCloseOrEnd() {
    if (this.ended || this.ready) {
        return;
    }

    this.makeData();

    if (!this.paused) {
        this.emitAllEvents();
    }
}

State.prototype.onData = function onData(data) {
    if (this.ended || this.ready) {
        return;
    }

    this.buffers.push(this.encoder.encode(data));
}

State.prototype.onError = function onError(error) {
    if (this.ended || this.ready) {
        return;
    }

    this.error = error;
    this.makeData();

    if (!this.paused) {
        this.emitAllEvents();
    }
}

/*
 * Exported bindings
 */

/**
 * Construct a Sink instance, which collects data events coming from the
 * indicated source stream. Sink instances are in turn instances of
 * `stream.Stream`.
 */
function Sink(source) {
    stream.Stream.call(this);
    this.sink = sealer.seal(new State(this, source));
}

util.inherits(Sink, stream.Stream);

Sink.prototype.destroy = function destroy() {
    sealer.unseal(this.sink).destroy();
};

Sink.prototype.pause = function pause() {
    sealer.unseal(this.sink).pause();
};

Sink.prototype.resume = function resume() {
    sealer.unseal(this.sink).resume();
};

Sink.prototype.setEncoding = function setEncoding(name) {
    sealer.unseal(this.sink).decoder.setEncoding(name);
};

Object.defineProperty(
    Sink.prototype,
    "readable",
    {
        get: function() { return sealer.unseal(this.sink).isReadable(); },
        enumerable: true
    });

/**
 * Sets the incoming encoding. This is how to interpret strings that are
 * received as the payloads of `data` events.
 */
Sink.prototype.setIncomingEncoding = function setIncomingEncoding(name) {
    sealer.unseal(this.sink).encoder.setEncoding(name);
}

/**
 * Gets the final combined data of the instance, if available.
 */
Sink.prototype.getData = function getData() {
    return sealer.unseal(this.sink).data;
}

/**
 * Gets the error that ended the upstream data, if any.
 */
Sink.prototype.getError = function getError() {
    var error = sealer.unseal(this.sink).error;

    return (error === NO_ERROR) ? undefined : error;
}

/**
 * Gets whether or not the stream ended with an error.
 */
Sink.prototype.gotError = function gotError() {
    return sealer.unseal(this.sink).error !== NO_ERROR;
}

Object.freeze(Sink.prototype);

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


<commit_before>"use strict";

let events = require( 'events' );
let jsonGate = require( 'json-gate' );

let pem = require( './pem.js' );
let DefinitionSink = require( './definition-sink.js' );
let HormoneSink = require( './hormone-sink.js' );

// The hormone names must not start or end with '/' and must not be empty
let nameSchema = jsonGate.createSchema( {
	type: 'string',
	pattern: '^[^/]+.*$'
} );

let definitionRE = /^definition\/(.*)$/;
let hormoneRE = /^hormone\/(.*)$/;

class Sink extends events.EventEmitter {

	constructor( es, filter, certCheck ) {

		super();

		// TODO: Check es

		this._es = es;
		this._filter = filter;
		this._certCheck = certCheck;

		// Create some stores ...
		this._subscriptions = {}; // Received definitions and subscribed hormones
		this._hormones = {};      // Last received hormone by name

		// Subscribe to defintion messages
		es._subscribe( 'definition/' + filter, ( topic, payload ) => {
			this._receivedDefinition( topic, payload );
		} );

	}

	destroy() {

		// Unsubscribe definition topic
		this._es._unsubscribe( 'defintion/' + this._filter );

		// Unsubscribe all hormones
		for( let name in this._subscriptions ) {
			this._removeHormoneSource( name );
		}

	}

	_receivedDefinition( topic, payload ) {

		// Extract name
		let tmp = definitionRE.exec( topic );
		if( ! tmp ) {
			return this.emit( 'receiveError', new Error( "Received no definition" ) );
		}
		let name = tmp[ 1 ];

		// The payload decides what to do
		if( payload == '' ) {
			// Remove hormone source
			this._removeHormoneSource( name );
		} else {
			// Add hormone source
			this._addHormoneSource( name, payload );
		}

	}

	_addHormoneSource( name, payload ) {

		try {
			// Create new definition from payload
			// Makes sure the format and signature are vaild
			let definition = new DefinitionSink( payload );

			// Check the certificate
			let data = definition.data;
			Promise.all( [
				pem.verifySigningChain( data.cert, this._es._ca ),
				pem.readCertificateInfo( data.cert )
			] ).then( ( results ) => {

				// Is cert signed by CA?
				if( ! results[0] ) {
					throw new Error( "Certificate has not been signed by CA" );
				}

				// Is the cert still valid?
				// First get current time. If we have an ESdummy, read time from es.
				// Otherwise get the current time from the OS
				let now = this._es.trustMeImAnEngineer ? this._es._now : Date.now();
				if( results[1].validity.start > now ) {
					throw new Error( "Certificate is valid in the future" );
				}
				if( results[1].validity.end < now ) {
					throw new Error( "Certificate has been expired" );
				}

				// Own check function
				if( typeof this._certCheck == 'function' ) {
					// The check function my return a promise, a value (-> everything is
					// ok) or throws an error
					return this._certCheck( name, results[ 1 ] );
				}

			} ).then( () => {

				// If the hormone is known, remove the old one first
				if( this._subscriptions[ name ] ) this._removeHormoneSource( name );

				// Subscribe to hormone
				this._es._subscribe( 'hormone/' + name, ( topic, payload ) => {

					// Skip empty messages
					if( payload == '' ) return;

					// Hand over hormone to handler
					this._receivedHormone( topic, payload );

				} );

				// Store handle
				this._subscriptions[ name ] = definition;

				// Report that we started listening to hormones
				this.emit( 'subscribe', name, definition );

			} ).catch( ( err ) => {
				this.emit( 'receiveError', err );
			} );

		} catch( err ) {
			this.emit( 'receiveError', err );
		}

	}

	_removeHormoneSource( name ) {

		// Check if we know the hormone source that shall be removed
		if( ! this._subscriptions[ name ] ) return this.emit(
			'receiveError',
			new Error( "Received unkown definition removal" )
		);

		// Unsubscribe hormone
		this._es._unsubscribe( 'hormone/' + name );

		// Remove timeout if it is pending
		if( this._hormones[ name ].timeout ) {
			clearTimeout( this._hormones[ name ].timeout );
		}

		// Remove subscription and last hormone
		delete this._subscriptions[ name ];
		delete this._hormones[ name ];

	}

	_receivedHormone( topic, payload ) {
		try {

			// Extract name
			let tmp = hormoneRE.exec( topic );
			if( ! tmp ) throw new Error( "Received no hormone" );
			let name = tmp[ 1 ];

			// Check if we have a definition for the received hormone
			if( ! this._subscriptions[ name ] ) throw new Error( "Received unkown hormone" );

			// Interprete hormone
			let hormone = new HormoneSink( this._subscriptions[ name ], payload );

			// At this point the hormone is okay :) At least the signature

			// If this is the first hormone we recieved under this name, make sure we
			// have at least some dummy data to compare with
			let formerHormone = this._hormones[ name ] ? this._hormones[ name ] : {
				isFresh: true,
				err: 0,
				timeout: null
			} ;

			// Stop expiration timeout if present
			if( formerHormone.timeout ) clearTimeout( formerHormone.timeout );

			// Further checks:
			// - Freshness
			let isFresh = hormone.isFresh;
			if( isFresh && ! formerHormone.isFresh ) {
				// The expired hormone went fresh -> tell the good news!
				this.emit( 'hormoneRefresh', name, hormone );
			} else if( ! isFresh && formerHormone.isFresh ) {
				// The received hormone has expired!
				this.emit( 'hormoneExpired', name, hormone );
			}
			// - Error
			let err = hormone.error;
			if( err == 0 && formerHormone.err != err ) {
				// The hormone reported recovery
				this.emit( 'hormoneRecover', name, hormone );
			} else if( err > 0 && formerHormone.err != err ) {
				// Some error occured!
				this.emit( 'hormoneError', name, hormone );
			}

			// If the hormone is fresh, set an expire timeout
			let timeout = null;
			if( isFresh ) timeout = setTimeout( () => {
				// The hormone just expired!
				this._hormones[ name ].isFresh = false;
				this._hormones[ name ].timeout = null;
				this.emit( 'hormoneExpired', name, hormone );
			}, hormone.freshness * 1000 );

			// Store all hormone related data
			this._hormones[ name ] = {
				hormone: hormone,
				isFresh: isFresh,
				err: err,
				timeout: timeout
			};

		} catch( err ) {
			this.emit( 'receiveError', err );
		}

	}

}

module.exports = Sink;
<commit_msg>Changed subscribe / unsubscribe to promisis<commit_after>"use strict";

let events = require( 'events' );
let jsonGate = require( 'json-gate' );

let pem = require( './pem.js' );
let DefinitionSink = require( './definition-sink.js' );
let HormoneSink = require( './hormone-sink.js' );

// The hormone names must not start or end with '/' and must not be empty
let nameSchema = jsonGate.createSchema( {
	type: 'string',
	pattern: '^[^/]+.*$'
} );

let definitionRE = /^definition\/(.*)$/;
let hormoneRE = /^hormone\/(.*)$/;

class Sink extends events.EventEmitter {

	constructor( es, filter, certCheck ) {

		super();

		// TODO: Check es

		this._es = es;
		this._filter = filter;
		this._certCheck = certCheck;

		// Create some stores ...
		this._subscriptions = {}; // Received definitions and subscribed hormones
		this._hormones = {};      // Last received hormone by name

		// Subscribe to defintion messages
		es._subscribe( 'definition/' + filter, ( topic, payload ) => {
			this._receivedDefinition( topic, payload );
		} ).catch( ( err ) => {
			this.emit( 'error', err );
		} );

	}

	destroy() {

		// Unsubscribe definition topic
		return this._es._unsubscribe( 'defintion/' + this._filter ).then( () => {

			let unsubJobs = [];

			// Unsubscribe all hormones
			for( let name in this._subscriptions ) {
				unsubJobs.push( this._removeHormoneSource( name ) );
			}

			// Wait for all unsubscriptions to be done
			return Promise.all( unsubJobs );

		});

	}

	_receivedDefinition( topic, payload ) {

		// Extract name
		let tmp = definitionRE.exec( topic );
		if( ! tmp ) {
			return this.emit( 'receiveError', new Error( "Received no definition" ) );
		}
		let name = tmp[ 1 ];

		// The payload decides what to do
		if( payload == '' ) {
			// Remove hormone source
			this._removeHormoneSource( name ).catch( ( err ) => {
				this.emit( 'receiveError', err );
			} );
		} else {
			// Add hormone source
			this._addHormoneSource( name, payload ).catch( ( err ) => {
				this.emit( 'receiveError', err );
			} );
		}

	}

	_addHormoneSource( name, payload ) {

		// Store for definition data
		let definition;

		return new Promise( ( resolve ) => {

			// Create new definition from payload
			// Makes sure the format and signature are vaild
			definition = new DefinitionSink( payload );

			// At this point the payload was readable and okay
			resolve();

		} ).then( () => {

			// Check the certificate
			let data = definition.data;
			return Promise.all( [
				pem.verifySigningChain( data.cert, this._es._ca ),
				pem.readCertificateInfo( data.cert )
			] )

		} ).then( ( results ) => {

			// Is cert signed by CA?
			if( ! results[0] ) {
				throw new Error( "Certificate has not been signed by CA" );
			}

			// Is the cert still valid?
			// First get current time. If we have an ESdummy, read time from es.
			// Otherwise get the current time from the OS
			let now = this._es.trustMeImAnEngineer ? this._es._now : Date.now();
			if( results[1].validity.start > now ) {
				throw new Error( "Certificate is valid in the future" );
			}
			if( results[1].validity.end < now ) {
				throw new Error( "Certificate has been expired" );
			}

			// Own check function
			if( typeof this._certCheck == 'function' ) {
				// The check function my return a promise, a value (-> everything is
				// ok) or throws an error
				return this._certCheck( name, results[ 1 ] );
			}

		} ).then( () => {

			// If the hormone is known, remove the old one first
			if( this._subscriptions[ name ] ) this._removeHormoneSource( name );

			// Subscribe to hormone
			return this._es._subscribe( 'hormone/' + name, ( topic, payload ) => {

				// Skip empty messages
				if( payload == '' ) return;

				// Hand over hormone to handler
				this._receivedHormone( topic, payload );

			} );

		} ).then( () => {

			// Store handle
			this._subscriptions[ name ] = definition;

			// Report that we started listening to hormones
			this.emit( 'subscribe', name, definition );

		} );

	}

	_removeHormoneSource( name ) {

		// Check if we know the hormone source that shall be removed
		if( ! this._subscriptions[ name ] ) {
			return Promise.reject( new Error( "Received unkown definition removal" ) );
		}

		// Unsubscribe hormone
		return this._es._unsubscribe( 'hormone/' + name ).then( () => {

			// Remove timeout if it is pending
			if( this._hormones[ name ].timeout ) {
				clearTimeout( this._hormones[ name ].timeout );
			}

			// Remove subscription and last hormone
			delete this._subscriptions[ name ];
			delete this._hormones[ name ];

		} );

	}

	_receivedHormone( topic, payload ) {
		try {

			// Extract name
			let tmp = hormoneRE.exec( topic );
			if( ! tmp ) throw new Error( "Received no hormone" );
			let name = tmp[ 1 ];

			// Check if we have a definition for the received hormone
			if( ! this._subscriptions[ name ] ) throw new Error( "Received unkown hormone" );

			// Interprete hormone
			let hormone = new HormoneSink( this._subscriptions[ name ], payload );

			// At this point the hormone is okay :) At least the signature

			// If this is the first hormone we recieved under this name, make sure we
			// have at least some dummy data to compare with
			let formerHormone = this._hormones[ name ] ? this._hormones[ name ] : {
				isFresh: true,
				err: 0,
				timeout: null
			} ;

			// Stop expiration timeout if present
			if( formerHormone.timeout ) clearTimeout( formerHormone.timeout );

			// Further checks:
			// - Freshness
			let isFresh = hormone.isFresh;
			if( isFresh && ! formerHormone.isFresh ) {
				// The expired hormone went fresh -> tell the good news!
				this.emit( 'hormoneRefresh', name, hormone );
			} else if( ! isFresh && formerHormone.isFresh ) {
				// The received hormone has expired!
				this.emit( 'hormoneExpired', name, hormone );
			}
			// - Error
			let err = hormone.error;
			if( err == 0 && formerHormone.err != err ) {
				// The hormone reported recovery
				this.emit( 'hormoneRecover', name, hormone );
			} else if( err > 0 && formerHormone.err != err ) {
				// Some error occured!
				this.emit( 'hormoneError', name, hormone );
			}

			// If the hormone is fresh, set an expire timeout
			let timeout = null;
			if( isFresh ) timeout = setTimeout( () => {
				// The hormone just expired!
				this._hormones[ name ].isFresh = false;
				this._hormones[ name ].timeout = null;
				this.emit( 'hormoneExpired', name, hormone );
			}, hormone.freshness * 1000 );

			// Store all hormone related data
			this._hormones[ name ] = {
				hormone: hormone,
				isFresh: isFresh,
				err: err,
				timeout: timeout
			};

		} catch( err ) {
			this.emit( 'receiveError', err );
		}

	}

}

module.exports = Sink;
<|endoftext|>