<commit_before>/*
 * Waltz - Enterprise Architecture
 * Copyright (C) 2016  Khartec Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import _ from "lodash";
import {initialiseData} from "../common/index";

const initialState = {
    editingQuestion: false,
    questionFieldTypes: [{
        name: 'Text',
        value: 'TEXT'
    },{
        name: 'Text Area',
        value: 'TEXTAREA'
    },{
        name: 'Number',
        value: 'NUMBER'
    },{
        name: 'Boolean',
        value: 'BOOLEAN'
    }],
    selectedQuestion: {},
    surveyQuestions: [],
    surveyTemplate: {},
    targetEntityKinds: [{
        name: 'Application',
        value: 'APPLICATION'
    },{
        name: 'Change Initiative',
        value: 'CHANGE_INITIATIVE'
    }]
};

function controller($stateParams,
                    notification,
                    surveyQuestionStore,
                    surveyTemplateStore) {

    const vm = initialiseData(this, initialState);
    vm.id = $stateParams.id;

    surveyTemplateStore
        .getById(vm.id)
        .then(template => vm.surveyTemplate = template);

    surveyQuestionStore
        .findForTemplate(vm.id)
        .then(questions => vm.surveyQuestions = questions);

    vm.updateTemplate = () => {
        surveyTemplateStore
            .update({
                id: vm.surveyTemplate.id,
                name: vm.surveyTemplate.name,
                description: vm.surveyTemplate.description,
                targetEntityKind: vm.surveyTemplate.targetEntityKind
            })
            .then(updateCount => notification.success('Survey template updated successfully'));
    };

    vm.showAddQuestionForm = () => {
        vm.editingQuestion = true;
        const currentMaxPos = _.chain(vm.surveyQuestions)
            .map(q => q.position)
            .max()
            .value();

        vm.selectedQuestion = {
            surveyTemplateId: vm.id,
            isMandatory: false,
            allowComment: false,
            position: (currentMaxPos || 0) + 10
        };
    };

    vm.showEditQuestionForm = (q) => {
        vm.editingQuestion = true;
        vm.selectedQuestion = q;
    };

    vm.cancelQuestionForm = () => {
        vm.editingQuestion = false;
        vm.selectedQuestion = null;
    };

    vm.createQuestion = (q) => {
        surveyQuestionStore
            .create(q)
            .then(questionId => {
                notification.success('Survey question created successfully');
                q.id = questionId;
                vm.surveyQuestions.push(q);
                vm.cancelQuestionForm();
            });
    };

    vm.updateQuestion = (q) => {
        surveyQuestionStore
            .update(q)
            .then(updateCount => {
                notification.success('Survey question updated successfully');
                vm.cancelQuestionForm();
            });
    };

    vm.deleteQuestion = (q) => {
        if (confirm("Are you sure you want to delete this question?")) {
            surveyQuestionStore
                .deleteQuestion(q.id)
                .then(deleteCount => {
                    notification.success('Survey question deleted successfully');
                    _.remove(vm.surveyQuestions, que => que.id === q.id);
                    vm.cancelQuestionForm();
                });
        }
    };

}

controller.$inject = [
    '$stateParams',
    'Notification',
    'SurveyQuestionStore',
    'SurveyTemplateStore'
];

const page = {
    controller,
    controllerAs: 'ctrl',
    template: require('./survey-template-edit.html')
};

export default page;<commit_msg>Survey: Template edit/create form improvements<commit_after>/*
 * Waltz - Enterprise Architecture
 * Copyright (C) 2016  Khartec Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import _ from "lodash";
import {initialiseData} from "../common/index";

const initialState = {
    editingQuestion: false,
    questionFieldTypes: [{
        name: 'Text',
        value: 'TEXT'
    },{
        name: 'Text Area',
        value: 'TEXTAREA'
    },{
        name: 'Number',
        value: 'NUMBER'
    },{
        name: 'Boolean',
        value: 'BOOLEAN'
    }],
    selectedQuestion: {},
    surveyQuestions: [],
    surveyTemplate: {},
    targetEntityKinds: [{
        name: 'Application',
        value: 'APPLICATION'
    },{
        name: 'Change Initiative',
        value: 'CHANGE_INITIATIVE'
    }]
};

function controller($stateParams,
                    notification,
                    surveyQuestionStore,
                    surveyTemplateStore) {

    const vm = initialiseData(this, initialState);
    vm.id = $stateParams.id;

    surveyTemplateStore
        .getById(vm.id)
        .then(template => vm.surveyTemplate = template);

    const loadQuestions = () =>
        surveyQuestionStore
            .findForTemplate(vm.id)
            .then(questions => vm.surveyQuestions = questions);

    vm.updateTemplate = () => {
        surveyTemplateStore
            .update({
                id: vm.surveyTemplate.id,
                name: vm.surveyTemplate.name,
                description: vm.surveyTemplate.description,
                targetEntityKind: vm.surveyTemplate.targetEntityKind
            })
            .then(updateCount => notification.success('Survey template updated successfully'));
    };

    vm.showAddQuestionForm = () => {
        vm.editingQuestion = true;
        const currentMaxPos = _.chain(vm.surveyQuestions)
            .map(q => q.position)
            .max()
            .value();

        vm.selectedQuestion = {
            surveyTemplateId: vm.id,
            isMandatory: false,
            allowComment: false,
            position: (currentMaxPos || 0) + 10
        };
    };

    vm.showEditQuestionForm = (q) => {
        vm.editingQuestion = true;
        vm.selectedQuestion = _.cloneDeep(q);
    };

    vm.cancelQuestionForm = () => {
        vm.editingQuestion = false;
        vm.selectedQuestion = null;
    };

    vm.createQuestion = (q) => {
        surveyQuestionStore
            .create(q)
            .then(questionId => {
                notification.success('Survey question created successfully');
                loadQuestions();
                vm.cancelQuestionForm();
            });
    };

    vm.updateQuestion = (q) => {
        surveyQuestionStore
            .update(q)
            .then(updateCount => {
                notification.success('Survey question updated successfully');
                loadQuestions();
                vm.cancelQuestionForm();
            });
    };

    vm.deleteQuestion = (q) => {
        if (confirm("Are you sure you want to delete this question?")) {
            surveyQuestionStore
                .deleteQuestion(q.id)
                .then(deleteCount => {
                    notification.success('Survey question deleted successfully');
                    loadQuestions();
                    vm.cancelQuestionForm();
                });
        }
    };

    loadQuestions();
}

controller.$inject = [
    '$stateParams',
    'Notification',
    'SurveyQuestionStore',
    'SurveyTemplateStore'
];

const page = {
    controller,
    controllerAs: 'ctrl',
    template: require('./survey-template-edit.html')
};

export default page;<|endoftext|>


<commit_before>/**
 * Copyright 2014 Ian Davies
 *
 * 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.
 */
define([], function() {

	return ["$compile", "RecursionHelper", "$sce", function($compile, RecursionHelper, $sce) {

		return {

			scope: true,

			restrict: 'A',

			templateUrl: '/partials/content/ValueOrChildren.html',

			compile: function(element) {
	            return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn){

	            	scope.value = undefined;
	            	scope.children = undefined;
	            	scope.encoding = undefined;

	            	// scope.$parent.$watch(iAttrs.value, function(newValue) {
	            	// 	scope.value = newValue;
	            	// 	update();
	            	// });

	            	// scope.$parent.$watch(iAttrs.children, function(newChildren) {
	            	// 	scope.children = newChildren;
	            	// 	update();
	            	// });

	            	// scope.$parent.$watch(iAttrs.encoding, function(newEncoding) {
	            	// 	scope.encoding = newEncoding;
	            	// 	update();
	            	// });

					// Replace three watchers which always get called one after another with one watcher:
					scope.$parent.$watchGroup([iAttrs.value, iAttrs.children, iAttrs.encoding], function(newValues) {
						scope.value = newValues[0];
						scope.children = newValues[1];
						scope.encoding = newValues[2];
						update();
					});

	            	var update = function updateFn() {

	            		scope.safeValue = $sce.trustAsHtml(scope.value);

						if (scope.value != "" && scope.value != null && scope.children != null && scope.children.length > 0) {
							throw new Error("Cannot render both value and children:\n\tVALUE:\n" +  JSON.stringify(scope.value, null, 2) + "\n\n\tCHILDREN:\n" + JSON.stringify(scope.children, null, 2));
						}

						scope.contentChunks = []; // One of these for each chunk of content, where accordions may only appear on their own in a chunk.
			            var breakOnTypeChange = false;
			            var lastType = "";
						var currentChunk = [];
						for (var i in scope.children) {
							var c = scope.children[i];
							c.contentChildIndex = scope.$root.padIndex(i);

							if ((breakOnTypeChange && c.type != lastType) || (!breakOnTypeChange && c.type == "isaacFeaturedProfile")) {
								// Split profiles into a separate content chunk
								// This means the index when iterating over the profiles starts from 0
								// and allows the multicolumn design to be more simply implemented
								breakOnTypeChange = !breakOnTypeChange; // toggle

								if (currentChunk.length > 0) {
									scope.contentChunks.push(currentChunk);
								}

								currentChunk = [c];
							} else if (c.layout == "accordion" || c.layout == "tabs") {
								if (currentChunk.length > 0)
									scope.contentChunks.push(currentChunk);
								var accordionChunk = [c];
								accordionChunk.isAccordion = true;
								accordionChunk.isFirstChunk = scope.contentChunks.length == 0;
								scope.contentChunks.push(accordionChunk);
								currentChunk = [];
							} else {
								currentChunk.push(c);
							}

							lastType = c.type;
						}

						if (currentChunk.length > 0)
							scope.contentChunks.push(currentChunk);

					}

	            });
	        }
		};
	}];
});<commit_msg>Revert changes to watch cycle, hopefully this will fix the digest loop/growth problems.<commit_after>/**
 * Copyright 2014 Ian Davies
 *
 * 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.
 */
define([], function() {

	return ["$compile", "RecursionHelper", "$sce", function($compile, RecursionHelper, $sce) {

		return {

			scope: true,

			restrict: 'A',

			templateUrl: '/partials/content/ValueOrChildren.html',

			compile: function(element) {
	            return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn){

	            	scope.value = undefined;
	            	scope.children = undefined;
	            	scope.encoding = undefined;

	            	scope.$parent.$watch(iAttrs.value, function(newValue) {
	            		scope.value = newValue;
	            		update();
	            	});

	            	scope.$parent.$watch(iAttrs.children, function(newChildren) {
	            		scope.children = newChildren;
	            		update();
	            	});

	            	scope.$parent.$watch(iAttrs.encoding, function(newEncoding) {
	            		scope.encoding = newEncoding;
	            		update();
	            	});

					// Replace three watchers which always get called one after another with one watcher:
					// TODO: work out why this didn't work. Also, work out why removing only enmcoding from it
					// and having that watcher separately *did* work just fine . . .

					// scope.$parent.$watchGroup([iAttrs.value, iAttrs.children, iAttrs.encoding], function(newValues) {
					// 	scope.value = newValues[0];
					// 	scope.children = newValues[1];
					// 	scope.encoding = newValues[2];
					// 	update();
					// });

	            	var update = function updateFn() {

	            		scope.safeValue = $sce.trustAsHtml(scope.value);

						if (scope.value != "" && scope.value != null && scope.children != null && scope.children.length > 0) {
							throw new Error("Cannot render both value and children:\n\tVALUE:\n" +  JSON.stringify(scope.value, null, 2) + "\n\n\tCHILDREN:\n" + JSON.stringify(scope.children, null, 2));
						}

						scope.contentChunks = []; // One of these for each chunk of content, where accordions may only appear on their own in a chunk.
			            var breakOnTypeChange = false;
			            var lastType = "";
						var currentChunk = [];
						for (var i in scope.children) {
							var c = scope.children[i];
							c.contentChildIndex = scope.$root.padIndex(i);

							if ((breakOnTypeChange && c.type != lastType) || (!breakOnTypeChange && c.type == "isaacFeaturedProfile")) {
								// Split profiles into a separate content chunk
								// This means the index when iterating over the profiles starts from 0
								// and allows the multicolumn design to be more simply implemented
								breakOnTypeChange = !breakOnTypeChange; // toggle

								if (currentChunk.length > 0) {
									scope.contentChunks.push(currentChunk);
								}

								currentChunk = [c];
							} else if (c.layout == "accordion" || c.layout == "tabs") {
								if (currentChunk.length > 0)
									scope.contentChunks.push(currentChunk);
								var accordionChunk = [c];
								accordionChunk.isAccordion = true;
								accordionChunk.isFirstChunk = scope.contentChunks.length == 0;
								scope.contentChunks.push(accordionChunk);
								currentChunk = [];
							} else {
								currentChunk.push(c);
							}

							lastType = c.type;
						}

						if (currentChunk.length > 0)
							scope.contentChunks.push(currentChunk);

					}

	            });
	        }
		};
	}];
});<|endoftext|>


<commit_before>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var is = require('is');
var css = require('css');
var path = require('path');
var join = path.join;
var rename = require('./rename');
var cdeps = require('./css-deps');
var util = require('./util');
var debug = util.debug;
var colors = util.colors;

/**
 * Get rename options
 * @param transform
 * @returns {*}
 */

function initRenameOptions(transform){
  if (is.fn(transform)) {
    return transform;
  }

  transform = transform || {};

  if (transform.min) {
    transform.suffix = '-min';
  }

  if (transform.debug) {
    transform.suffix = '-debug';
  }

  return transform;
}

/**
 * Init options
 * @param options
 * @returns {object}
 */

function initOptions(options){
  var defaults = {
    prefix: null, // css prefix
    onpath: null, // css resource path callback
    cache: true, // use memory file cahe
    wwwroot: '', // web root
    rename: null, // { debug: boolean, min: boolean }
    compress: false // compress css code
  };

  // mix
  util.extend(true, defaults, options);

  if (defaults.wwwroot && !is.string(defaults.wwwroot)) {
    util.throwError('options.wwwroot\'s value should be string.');
  }

  // init wwwroot
  defaults.wwwroot = join(util.cwd, defaults.wwwroot);
  // init rename
  defaults.rename = initRenameOptions(defaults.rename);

  return defaults;
}

/**
 * Transport css dependencies.
 * - vinyl: vinyl object
 */

function transportCssDeps(vinyl, options){
  var deps = [];
  var remote = [];
  var include = [];
  var pkg = vinyl.package || {};
  var onpath = options.onpath;
  var prefix = options.prefix;

  // init css settings
  onpath = is.fn(onpath) ? function (path, property){
    return options.onpath(path, property, pkg.id || null, vinyl.path);
  } : null;
  prefix = is.fn(prefix) ? prefix(pkg.id || null, vinyl.path) : prefix;

  // replace imports and collect dependencies
  vinyl.contents = new Buffer(cdeps(vinyl.contents, function (id){
    var path;

    // id is not a local file
    if (!util.isLocal(id)) {
      // cache dependencie id
      remote.push(id);

      // delete import
      return false;
    }

    // normalize id
    id = util.normalize(id);

    // if end with /, find index file
    if (id.substring(id.length - 1) === '/') {
      id += 'index.css';
    }

    // set path
    path = id;
    // rename id
    id = rename(path, options.rename);

    // normalize id
    id = util.normalize(id);

    // debug
    debug('transport deps: %s', colors.magenta(id));

    // get absolute path
    path = util.resolve(path, vinyl, options.wwwroot);

    // cache dependencie id
    deps.push(id);
    // cache dependencie absolute path
    include.push(path);

    // delete all import
    return false;
  }, {
    prefix: prefix,
    onpath: onpath,
    compress: options.compress
  }));

  // Cache file dependencies
  vinyl.package = util.extend(pkg, {
    remote: remote,
    include: include,
    dependencies: deps
  });

  return deps;
}

/**
 * Exports module.
 */

exports.initOptions = initOptions;
exports.transportCssDeps = transportCssDeps;
<commit_msg>bug fixed<commit_after>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var is = require('is');
var css = require('css');
var path = require('path');
var join = path.join;
var rename = require('./rename');
var cdeps = require('./css-deps');
var util = require('./util');
var debug = util.debug;
var colors = util.colors;

/**
 * Get rename options
 * @param transform
 * @returns {*}
 */

function initRenameOptions(transform){
  if (is.fn(transform)) {
    return transform;
  }

  transform = transform || {};

  if (transform.min) {
    transform.suffix = '-min';
  }

  if (transform.debug) {
    transform.suffix = '-debug';
  }

  return transform;
}

/**
 * Init options
 * @param options
 * @returns {object}
 */

function initOptions(options){
  var defaults = {
    prefix: null, // css prefix
    onpath: null, // css resource path callback
    cache: true, // use memory file cahe
    wwwroot: '', // web root
    rename: null, // { debug: boolean, min: boolean }
    compress: false // compress css code
  };

  // mix
  util.extend(true, defaults, options);

  if (defaults.wwwroot && !is.string(defaults.wwwroot)) {
    util.throwError('options.wwwroot\'s value should be string.');
  }

  // init wwwroot
  defaults.wwwroot = join(util.cwd, defaults.wwwroot);
  // init rename
  defaults.rename = initRenameOptions(defaults.rename);

  return defaults;
}

/**
 * Transport css dependencies.
 * - vinyl: vinyl object
 */

function transportCssDeps(vinyl, options){
  var deps = [];
  var remote = [];
  var include = [];
  var pkg = vinyl.package || {};
  var onpath = options.onpath;
  var prefix = options.prefix;

  // init css settings
  onpath = is.fn(onpath) ? function (path, property){
    return options.onpath(path, property, pkg.id || null, vinyl.path);
  } : null;
  prefix = is.fn(prefix) ? prefix(pkg.id || null, vinyl.path) : prefix;

  // replace imports and collect dependencies
  vinyl.contents = new Buffer(cdeps(vinyl.contents, function (id){
    var path;

    // id is not a local file
    if (!util.isLocal(id)) {
      // cache dependencie id
      deps.push(id);
      remote.push(id);

      // delete import
      return false;
    }

    // normalize id
    id = util.normalize(id);

    // if end with /, find index file
    if (id.substring(id.length - 1) === '/') {
      id += 'index.css';
    }

    // set path
    path = id;
    // rename id
    id = rename(path, options.rename);

    // normalize id
    id = util.normalize(id);

    // debug
    debug('transport deps: %s', colors.magenta(id));

    // get absolute path
    path = util.resolve(path, vinyl, options.wwwroot);

    // cache dependencie id
    deps.push(id);
    // cache dependencie absolute path
    include.push(path);

    // delete all import
    return false;
  }, {
    prefix: prefix,
    onpath: onpath,
    compress: options.compress
  }));

  // Cache file dependencies
  vinyl.package = util.extend(pkg, {
    remote: remote,
    include: include,
    dependencies: deps
  });

  return deps;
}

/**
 * Exports module.
 */

exports.initOptions = initOptions;
exports.transportCssDeps = transportCssDeps;
<|endoftext|>


<commit_before>var BasicMenu = function(app, endpoint, config) {
  this._app = app;
  this._endpoint = endpoint;
  this.config = config;
}

BasicMenu.prototype.init = function() {
  // Write the template specified in the config to the buffer
  this._endpoint.sock.write(this._app.templates[config.template]);
  // Implement hooks on the endpoint socket
}
<commit_msg>export the basic menu<commit_after>var BasicMenu = function(app, endpoint, config) {
  this._app = app;
  this._endpoint = endpoint;
  this.config = config;
}

BasicMenu.prototype.init = function() {
  // Write the template specified in the config to the buffer
  this._endpoint.sock.write(this._app.templates[config.template]);
  // Implement hooks on the endpoint socket
}

module.exports = BasicMenu;
<|endoftext|>


<commit_before>/*
 * L.LineUtil contains different utility functions for line segments
 * and polylines (clipping, simplification, distances, etc.)
 */

L.LineUtil = {
	/*
	 * Simplify polyline with vertex reduction and Douglas-Peucker simplification.
	 * Improves rendering performance dramatically by lessening the number of points to draw.
	 */
	simplify: function(/*Point[]*/ points, /*Number*/ tolerance) {
		if (!tolerance || !points.length) return points.slice();

		// stage 1: vertex reduction
		points = this.reducePoints(points, tolerance);

		// stage 2: Douglas-Peucker simplification
		points = this.simplifyDP(points, tolerance);

		return points;
	},

	// distance from a point to a segment between two points
	pointToSegmentDistance:  function(/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
		return Math.sqrt(this._sqPointToSegmentDist(p, p1, p2));
	},

	closestPointOnSegment: function(/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
		var point = this._sqClosestPointOnSegment(p, p1, p2);
		point.distance = Math.sqrt(point._sqDist);
		return point;
	},

	// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
	simplifyDP: function(points, tol) {
		var maxDist2 = 0,
			index = 0,
			t2 = tol * tol;

		for (var i = 1, len = points.length, dist2; i < len - 1; i++) {
			dist2 = this._sqPointToSegmentDist(points[i], points[0], points[len - 1]);
			if (dist2 > maxDist2) {
				index = i;
				maxDist2 = dist2;
			}
		}

		if (maxDist2 >= t2) {
			var part1 = points.slice(0, index),
				part2 = points.slice(index),
				simplifiedPart1 = this.simplifyDP(part1, tol).slice(0, len - 2),
				simplifiedPart2 = this.simplifyDP(part2, tol);

			return simplifiedPart1.concat(simplifiedPart2);
		} else {
			return [points[0], points[len - 1]];
		}
	},

	// reduce points that are too close to each other to a single point
	reducePoints: function(points, tol) {
		var reducedPoints = [points[0]],
			t2 = tol * tol;

		for (var i = 1, prev = 0, len = points.length; i < len; i++) {
			if (this._sqDist(points[i], points[prev]) < t2) continue;
			reducedPoints.push(points[i]);
			prev = i;
		}
		if (prev < len - 1) {
			reducedPoints.push(points[len - 1]);
		}
		return reducedPoints;
	},

	/*
	 * Cohen-Sutherland line clipping algorithm.
	 * Used to avoid rendering parts of a polyline that are not currently visible.
	 */
	clipSegment: function(a, b, bounds, useLastCode) {
		var min = bounds.min,
			max = bounds.max;

		var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds),
			codeB = this._getBitCode(b, bounds);

		// save 2nd code to avoid calculating it on the next segment
		this._lastCode = codeB;

		while (true) {
			// if a,b is inside the clip window (trivial accept)
			if (!(codeA | codeB)) {
				return [a, b];
			// if a,b is outside the clip window (trivial reject)
			} else if (codeA & codeB) {
				return false;
			// other cases
			} else {
				var codeOut = codeA || codeB,
					p = this._getEdgeIntersection(a, b, codeOut, bounds),
					newCode = this._getBitCode(p, bounds);

				if (codeOut == codeA) {
					a = p;
					codeA = newCode;
				} else {
					b = p;
					codeB = newCode;
				}
			}
		}
	},

	_getEdgeIntersection: function(a, b, code, bounds) {
		var dx = b.x - a.x,
			dy = b.y - a.y,
			min = bounds.min,
			max = bounds.max;

		if (code & 8) { // top
			return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y);
		} else if (code & 4) { // bottom
			return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y);
		} else if (code & 2){ // right
			return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx);
		} else if (code & 1) { // left
			return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx);
		}
	},

	_getBitCode: function(/*Point*/ p, bounds) {
		var code = 0;

		if (p.x < bounds.min.x) code |= 1; // left
		else if (p.x > bounds.max.x) code |= 2; // right
		if (p.y < bounds.min.y) code |= 4; // bottom
		else if (p.y > bounds.max.y) code |= 8; // top

		return code;
	},

	// square distance (to avoid unnecessary Math.sqrt calls)
	_sqDist: function(p1, p2) {
		var dx = p2.x - p1.x,
			dy = p2.y - p1.y;
		return dx * dx + dy * dy;
	},

	/**
	 * @return L.Point point on segment with attribute _sqDist - square distance to segment
	 */
	_sqClosestPointOnSegment: function(p, p1, p2) {
		var x2 = p2.x - p1.x,
			y2 = p2.y - p1.y;

		if (!x2 && !y2) return this._sqDist(p, p1);

		var dot = (p.x - p1.x) * x2 + (p.y - p1.y) * y2,
			t = dot / this._sqDist(p1, p2);

		var apoint = p1;
		if (t > 1) {
			apoint = p2;
		} else if (t > 0) {
			apoint = new L.Point(p1.x + x2 * t, p1.y + y2 * t);
		}
		apoint._sqDist = this._sqDist(p, apoint);
		return apoint;
	},

	// distance from a point to a segment between two points
	_sqPointToSegmentDist: function(p, p1, p2) {
		return this._sqClosestPointOnSegment(p, p1, p2)._sqDist;
	}
};<commit_msg>Fix method L.LineUtil._sqClosestPointOnSegment<commit_after>/*
 * L.LineUtil contains different utility functions for line segments
 * and polylines (clipping, simplification, distances, etc.)
 */

L.LineUtil = {
	/*
	 * Simplify polyline with vertex reduction and Douglas-Peucker simplification.
	 * Improves rendering performance dramatically by lessening the number of points to draw.
	 */
	simplify: function(/*Point[]*/ points, /*Number*/ tolerance) {
		if (!tolerance || !points.length) return points.slice();

		// stage 1: vertex reduction
		points = this.reducePoints(points, tolerance);

		// stage 2: Douglas-Peucker simplification
		points = this.simplifyDP(points, tolerance);

		return points;
	},

	// distance from a point to a segment between two points
	pointToSegmentDistance:  function(/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
		return Math.sqrt(this._sqPointToSegmentDist(p, p1, p2));
	},

	closestPointOnSegment: function(/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
		var point = this._sqClosestPointOnSegment(p, p1, p2);
		point.distance = Math.sqrt(point._sqDist);
		return point;
	},

	// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
	simplifyDP: function(points, tol) {
		var maxDist2 = 0,
			index = 0,
			t2 = tol * tol;

		for (var i = 1, len = points.length, dist2; i < len - 1; i++) {
			dist2 = this._sqPointToSegmentDist(points[i], points[0], points[len - 1]);
			if (dist2 > maxDist2) {
				index = i;
				maxDist2 = dist2;
			}
		}

		if (maxDist2 >= t2) {
			var part1 = points.slice(0, index),
				part2 = points.slice(index),
				simplifiedPart1 = this.simplifyDP(part1, tol).slice(0, len - 2),
				simplifiedPart2 = this.simplifyDP(part2, tol);

			return simplifiedPart1.concat(simplifiedPart2);
		} else {
			return [points[0], points[len - 1]];
		}
	},

	// reduce points that are too close to each other to a single point
	reducePoints: function(points, tol) {
		var reducedPoints = [points[0]],
			t2 = tol * tol;

		for (var i = 1, prev = 0, len = points.length; i < len; i++) {
			if (this._sqDist(points[i], points[prev]) < t2) continue;
			reducedPoints.push(points[i]);
			prev = i;
		}
		if (prev < len - 1) {
			reducedPoints.push(points[len - 1]);
		}
		return reducedPoints;
	},

	/*
	 * Cohen-Sutherland line clipping algorithm.
	 * Used to avoid rendering parts of a polyline that are not currently visible.
	 */
	clipSegment: function(a, b, bounds, useLastCode) {
		var min = bounds.min,
			max = bounds.max;

		var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds),
			codeB = this._getBitCode(b, bounds);

		// save 2nd code to avoid calculating it on the next segment
		this._lastCode = codeB;

		while (true) {
			// if a,b is inside the clip window (trivial accept)
			if (!(codeA | codeB)) {
				return [a, b];
			// if a,b is outside the clip window (trivial reject)
			} else if (codeA & codeB) {
				return false;
			// other cases
			} else {
				var codeOut = codeA || codeB,
					p = this._getEdgeIntersection(a, b, codeOut, bounds),
					newCode = this._getBitCode(p, bounds);

				if (codeOut == codeA) {
					a = p;
					codeA = newCode;
				} else {
					b = p;
					codeB = newCode;
				}
			}
		}
	},

	_getEdgeIntersection: function(a, b, code, bounds) {
		var dx = b.x - a.x,
			dy = b.y - a.y,
			min = bounds.min,
			max = bounds.max;

		if (code & 8) { // top
			return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y);
		} else if (code & 4) { // bottom
			return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y);
		} else if (code & 2){ // right
			return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx);
		} else if (code & 1) { // left
			return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx);
		}
	},

	_getBitCode: function(/*Point*/ p, bounds) {
		var code = 0;

		if (p.x < bounds.min.x) code |= 1; // left
		else if (p.x > bounds.max.x) code |= 2; // right
		if (p.y < bounds.min.y) code |= 4; // bottom
		else if (p.y > bounds.max.y) code |= 8; // top

		return code;
	},

	// square distance (to avoid unnecessary Math.sqrt calls)
	_sqDist: function(p1, p2) {
		var dx = p2.x - p1.x,
			dy = p2.y - p1.y;
		return dx * dx + dy * dy;
	},

	/**
	 * @return L.Point point on segment with attribute _sqDist - square distance to segment
	 */
	_sqClosestPointOnSegment: function(p, p1, p2) {
		var x2 = p2.x - p1.x,
			y2 = p2.y - p1.y,
			apoint = p1;
		if (x2 || y2) {
			var dot = (p.x - p1.x) * x2 + (p.y - p1.y) * y2,
				t = dot / this._sqDist(p1, p2);

			if (t > 1) {
				apoint = p2;
			} else if (t > 0) {
				apoint = new L.Point(p1.x + x2 * t, p1.y + y2 * t);
			}
		}
		apoint._sqDist = this._sqDist(p, apoint);
		return apoint;
	},

	// distance from a point to a segment between two points
	_sqPointToSegmentDist: function(p, p1, p2) {
		return this._sqClosestPointOnSegment(p, p1, p2)._sqDist;
	}
};<|endoftext|>


<commit_before>define(['directives/directives'], function(directives){
	directives.directive('myFocus', ['$rootScope', function($rootScope){
		return {
			restrict: 'A',
			scope: false,
			link: function(scope, element, attrs){
				element[0].focus();
			}
		}
	}])
});<commit_msg>Update myFocus.js<commit_after>define(['directives/directives'], function(directives){
	directives.directive('myFocus', [function(){
		return {
			restrict: 'A',
			scope: false,
			link: function(scope, element, attrs){
				element[0].focus();
			}
		}
	}])
});
<|endoftext|>


<commit_before>function Graph( canvas_name, width, height ) {
	this.svg = "http://www.w3.org/2000/svg";
	this.canvas = document.getElementById(canvas_name);
	this.width = width;
	this.height = height;
	this.canvas.style.width = width + "px";
	this.canvas.style.height = height + "px";
	this.vertices = {};
	this.forcex = {};
	this.forcey = {};
	this.stepsize = 0.0005;
	this.iteration = 0;
	this.task = null;

	// tunables to adjust the layout
	this.repulsion = 200000; // repulsion constant, adjust for wider/narrower spacing
	this.spring_length = 20; // base resting length of springs
}

Graph.prototype.createVertex = function( name, color ) { // XXX -- should support separate id and name
	// create an SVG rectangle, attach additional attributed to it
	var vertex = document.createElementNS(this.svg, "rect");
	if( color === undefined ) {
		color = "#222";
	}
	vertex.setAttribute("style", "fill: "+color+"; stroke-width: 1px;");
	vertex.setAttribute("rx", "10px"); // round the edges
	// random placement with a 10% margin at the edges
	vertex.posx = Math.random() * (this.width * 0.8) + (this.width * 0.1);
	vertex.posy = (Math.random() * (this.height * 0.8)) + (this.height * 0.1);
	vertex.setAttribute("x", vertex.posx );
	vertex.setAttribute("y", vertex.posy );
	vertex.edges = new Array();
	this.canvas.appendChild(vertex);

	// text label
	vertex.name = name;
	vertex.textLabel = document.createElementNS(this.svg, "text");
	vertex.textLabel.setAttribute("style", "fill: #fff; stroke-width: 1px;");
	vertex.textLabel.appendChild( document.createTextNode( name ) );
	this.canvas.appendChild( vertex.textLabel );

	// get the size of the rectangle from the text label's bounding box
	vertex.h = vertex.textLabel.getBBox().height + 10;
	vertex.w = vertex.textLabel.getBBox().width + 10;
	vertex.setAttribute("height", vertex.h + "px");
	vertex.setAttribute("width", vertex.w + "px");

	this.vertices[name] = vertex;
}

Graph.prototype.createEdge = function( a, b, style ) {
	var line = document.createElementNS(this.svg, "path");
	if( style === undefined ) {
		style = "stroke: #444; stroke-width: 3px;";
	}
	line.setAttribute("style", style);
	this.canvas.insertBefore(line, this.canvas.firstChild);
	this.vertices[a].edges[b] = { "dest" : b, "line": line };
	this.vertices[b].edges[a] = { "dest" : a, "line": line };
}

Graph.prototype.updateLayout = function() {
	for (i in this.vertices) {
		this.forcex[i] = 0;
		this.forcey[i] = 0;
		for (j in this.vertices) {
			if( i !== j ) {
				// using rectangle's center, bounding box would be better
				var deltax = this.vertices[j].posx - this.vertices[i].posx;
				var deltay = this.vertices[j].posy - this.vertices[i].posy;
				var distance = Math.sqrt(deltax * deltax + deltay * deltay);

				// Coulomb's law -- repulsion varies inversely with distance
				this.forcex[i] -= (this.repulsion / Math.pow( distance, 2 )) * deltax;
				this.forcey[i] -= (this.repulsion / Math.pow( distance, 2 )) * deltay;

				// spring force along edges, follows Hooke's law
				if( this.vertices[i].edges[j] ) {
					this.forcex[i] += (distance - this.spring_length) * deltax;
					this.forcey[i] += (distance - this.spring_length) * deltay;
				}
			}
		}
	}
	for (i in this.vertices) {
		// update rectangles
		this.vertices[i].posx += this.forcex[i] * this.stepsize;
		this.vertices[i].posy += this.forcey[i] * this.stepsize;
		this.vertices[i].setAttribute("x", this.vertices[i].posx );
		this.vertices[i].setAttribute("y", this.vertices[i].posy );
		// update labels
		this.vertices[i].textLabel.setAttribute("x", this.vertices[i].posx + 5 + "px");
		this.vertices[i].textLabel.setAttribute("y", this.vertices[i].posy + (2*this.vertices[i].h/3 )+ "px");
		// update edges
		for (j in this.vertices[i].edges) {
			this.vertices[i].edges[j].line.setAttribute("d", "M"+(this.vertices[i].posx+(this.vertices[i].w/2))+","+(this.vertices[i].posy+(this.vertices[i].h/2))+" L"+(this.vertices[this.vertices[i].edges[j].dest].posx+(this.vertices[this.vertices[i].edges[j].dest].w/2))+" "+(this.vertices[this.vertices[i].edges[j].dest].posy+(this.vertices[this.vertices[i].edges[j].dest].h/2)));
		}
	}
	this.iteration++;
	if( this.iteration > 300 ) // XXX -- should watch for rest state, not just quit after N iterations
		this.quit();
}
Graph.prototype.go = function() {
	// already running
	if (this.task) {
		return;
	}
	obj = this;
	this.iteration = 0;
	this.task = window.setInterval(function(){ obj.updateLayout(); }, 1);
}
Graph.prototype.quit = function() {
	window.clearInterval(this.task);
	this.task = null;
}<commit_msg>improve clarity of layout<commit_after>function Graph( canvas_name, width, height ) {
	this.svg = "http://www.w3.org/2000/svg";
	this.canvas = document.getElementById(canvas_name);
	this.width = width;
	this.height = height;
	this.canvas.style.width = width + "px";
	this.canvas.style.height = height + "px";
	this.vertices = {};
	this.forcex = {};
	this.forcey = {};
	this.stepsize = 0.0005;
	this.iteration = 0;
	this.task = null;

	// tunables to adjust the layout
	this.repulsion = 200000; // repulsion constant, adjust for wider/narrower spacing
	this.spring_length = 20; // base resting length of springs
}

Graph.prototype.createVertex = function( name, color ) { // XXX -- should support separate id and name
	// create an SVG rectangle, attach additional attributed to it
	var vertex = document.createElementNS(this.svg, "rect");
	if( color === undefined ) {
		color = "#222";
	}
	vertex.setAttribute("style", "fill: "+color+"; stroke-width: 1px;");
	vertex.setAttribute("rx", "10px"); // round the edges
	// random placement with a 10% margin at the edges
	vertex.posx = Math.random() * (this.width * 0.8) + (this.width * 0.1);
	vertex.posy = (Math.random() * (this.height * 0.8)) + (this.height * 0.1);
	vertex.setAttribute("x", vertex.posx );
	vertex.setAttribute("y", vertex.posy );
	vertex.edges = new Array();
	this.canvas.appendChild(vertex);

	// text label
	vertex.name = name;
	vertex.textLabel = document.createElementNS(this.svg, "text");
	vertex.textLabel.setAttribute("style", "fill: #fff; stroke-width: 1px;");
	vertex.textLabel.appendChild( document.createTextNode( name ) );
	this.canvas.appendChild( vertex.textLabel );

	// get the size of the rectangle from the text label's bounding box
	vertex.h = vertex.textLabel.getBBox().height + 10;
	vertex.w = vertex.textLabel.getBBox().width + 10;
	vertex.setAttribute("height", vertex.h + "px");
	vertex.setAttribute("width", vertex.w + "px");

	this.vertices[name] = vertex;
}

Graph.prototype.createEdge = function( a, b, style ) {
	var line = document.createElementNS(this.svg, "path");
	if( style === undefined ) {
		style = "stroke: #444; stroke-width: 3px;";
	}
	line.setAttribute("style", style);
	this.canvas.insertBefore(line, this.canvas.firstChild);
	this.vertices[a].edges[b] = { "dest" : b, "line": line };
	this.vertices[b].edges[a] = { "dest" : a, "line": line };
}

Graph.prototype.updateLayout = function() {
	for (i in this.vertices) {
		this.forcex[i] = 0;
		this.forcey[i] = 0;
		for (j in this.vertices) {
			if( i !== j ) {
				// using rectangle's center, bounding box would be better
				var deltax = this.vertices[j].posx - this.vertices[i].posx;
				var deltay = this.vertices[j].posy - this.vertices[i].posy;

				// Coulomb's law -- repulsion varies inversely with square of distance
				var d2 = deltax * deltax + deltay * deltay;
				this.forcex[i] -= (this.repulsion / d2) * deltax;
				this.forcey[i] -= (this.repulsion / d2) * deltay;

				// spring force along edges, follows Hooke's law
				if( this.vertices[i].edges[j] ) {
					var distance = Math.sqrt(d2);
					this.forcex[i] += (distance - this.spring_length) * deltax;
					this.forcey[i] += (distance - this.spring_length) * deltay;
				}
			}
		}
	}
	for (i in this.vertices) {
		// update rectangles
		this.vertices[i].posx += this.forcex[i] * this.stepsize;
		this.vertices[i].posy += this.forcey[i] * this.stepsize;
		this.vertices[i].setAttribute("x", this.vertices[i].posx );
		this.vertices[i].setAttribute("y", this.vertices[i].posy );
		// update labels
		this.vertices[i].textLabel.setAttribute("x", this.vertices[i].posx + 5 + "px");
		this.vertices[i].textLabel.setAttribute("y", this.vertices[i].posy + (2*this.vertices[i].h/3 )+ "px");
		// update edges
		for (j in this.vertices[i].edges) {
			this.vertices[i].edges[j].line.setAttribute("d", "M"+(this.vertices[i].posx+(this.vertices[i].w/2))+","+(this.vertices[i].posy+(this.vertices[i].h/2))+" L"+(this.vertices[this.vertices[i].edges[j].dest].posx+(this.vertices[this.vertices[i].edges[j].dest].w/2))+" "+(this.vertices[this.vertices[i].edges[j].dest].posy+(this.vertices[this.vertices[i].edges[j].dest].h/2)));
		}
	}
	this.iteration++;
	if( this.iteration > 300 ) // XXX -- should watch for rest state, not just quit after N iterations
		this.quit();
}
Graph.prototype.go = function() {
	// already running
	if (this.task) {
		return;
	}
	obj = this;
	this.iteration = 0;
	this.task = window.setInterval(function(){ obj.updateLayout(); }, 1);
}
Graph.prototype.quit = function() {
	window.clearInterval(this.task);
	this.task = null;
}<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const util = require('util');

const log = require('debug')('nodejs-team:drive-sequelize');
const error = require('debug')('nodejs-team:error');

var models = require('../models/index');
var Drive = require('../models/drive');

exports.create = function(id,name, path, type, size) {
  return new Promise((resolve, reject) => {
    models.Drive.create({
      parent_id:id,
      name: name,
      path: path,
      fileType: type,
      size: size
    }).then(function(drive) {
      if (drive)
        resolve(drive);
      else {
        reject(`Error while creating a Drive model`);
      }
    });
  });
};

exports.list = function(parentId) {
  return new Promise((resolve, reject) => {
    models.Drive.findAll({
      where: {
         parent_id: parentId
      }
    }).then(function(drives) {
      if (drives)
        resolve(drives);
      else {
        reject(`Error while listing all drives`);
      }
    });
  });
};

exports.get_parent = function(id) {
  return new Promise((resolve, reject) => {
    models.Drive.find({
      where: {
         parent_id: id , fileType :1
      }
    }).then(function(drive) {
      if (drive)
        resolve(drive);
      else {
        reject(`Error while find a parent Drive model`);
      }
    });
  });
};

exports.multiple  = function (id , isFile) {
   console.log("delete multiple");
   console.log("id"+id);
    id = '8';
    var x= getFile(id);
    if(isFile) {
    /*  return new Promise ((resolve, reject ) => {
        models.Drive.destroy({ where: { id: id }}).then(function(drive)  {
        if(drive == 0) {
          reject(`Not Deleted Successfully`);
        }
        else  {
          resolve("Deleted successfully");
        }
      });
    });*/
    } else {

     p = getFile(id);
   }

}

var getFile = function (id) {
  var array = [];
  console.log("get folders");
  console.log('id' +id);
  var drive = -1;
do{
     return new Promise ((resolve, reject ) => {
      models.Drive.findAll({ where: { parent_id: id }}).then(function(drive)  {
      console.log(drive);
      console.log('drivvvess' + drive.dataValues.id);
      array.push(drive.id);
      id = drive.id;
      console.log('id' + id);
    });
      });
  } while(drive !=0);

}

exports.delete = function (id) {
  console.log("delete");
  var id = '2';
  console.log('id'+id);
  return new Promise ((resolve, reject ) => {
  models.Drive.destroy({ where: { id: id }}).then(function(drive)  {
  console.log(drive);
  if(drive == 0) {
    reject (`Not Deleted Successfully`);
  }
  else  {
    resolve(drive);
  }
  });
});
}

exports.move = function (sourceId, destParentId) {
    console.log(`sourceId:${sourceId}  parentId:${destParentId}`)
    return new Promise((resolve, reject) => {
        models.Drive.update({
            parent_id: destParentId
        }, {
            where: {
                id: sourceId
            }
        }).then(function (moved) {
            console.log(`"moved" callback param value is: ${moved}`);
            if (moved != 0)
                resolve(`Moved id:${sourceId} to new parent:${destParentId}`);
            else {
                reject(`Failed to move id:${sourceId} to new parent:${destParentId}`);
            }
        });
    });
};
<commit_msg>Fix 'move' method to also update the path of the file being moved. Note that moving folders currently does not update the path of all sub files and folders.<commit_after>'use strict';

const path = require('path');
const util = require('util');

const log = require('debug')('nodejs-team:drive-sequelize');
const error = require('debug')('nodejs-team:error');

var models = require('../models/index');
var Drive = require('../models/drive');

exports.create = function(id,name, path, type, size) {
  return new Promise((resolve, reject) => {
    models.Drive.create({
      parent_id:id,
      name: name,
      path: path,
      fileType: type,
      size: size
    }).then(function(drive) {
      if (drive)
        resolve(drive);
      else {
        reject(`Error while creating a Drive model`);
      }
    });
  });
};

exports.list = function(parentId) {
  return new Promise((resolve, reject) => {
    models.Drive.findAll({
      where: {
         parent_id: parentId
      }
    }).then(function(drives) {
      if (drives)
        resolve(drives);
      else {
        reject(`Error while listing all drives`);
      }
    });
  });
};

exports.get_parent = function(id) {
  return new Promise((resolve, reject) => {
    models.Drive.find({
      where: {
         parent_id: id , fileType :1
      }
    }).then(function(drive) {
      if (drive)
        resolve(drive);
      else {
        reject(`Error while find a parent Drive model`);
      }
    });
  });
};

exports.multiple  = function (id , isFile) {
   console.log("delete multiple");
   console.log("id"+id);
    id = '8';
    var x= getFile(id);
    if(isFile) {
    /*  return new Promise ((resolve, reject ) => {
        models.Drive.destroy({ where: { id: id }}).then(function(drive)  {
        if(drive == 0) {
          reject(`Not Deleted Successfully`);
        }
        else  {
          resolve("Deleted successfully");
        }
      });
    });*/
    } else {

     p = getFile(id);
   }

}

var getFile = function (id) {
  var array = [];
  console.log("get folders");
  console.log('id' +id);
  var drive = -1;
do{
     return new Promise ((resolve, reject ) => {
      models.Drive.findAll({ where: { parent_id: id }}).then(function(drive)  {
      console.log(drive);
      console.log('drivvvess' + drive.dataValues.id);
      array.push(drive.id);
      id = drive.id;
      console.log('id' + id);
    });
      });
  } while(drive !=0);

}

exports.delete = function (id) {
  console.log("delete");
  var id = '2';
  console.log('id'+id);
  return new Promise ((resolve, reject ) => {
  models.Drive.destroy({ where: { id: id }}).then(function(drive)  {
  console.log(drive);
  if(drive == 0) {
    reject (`Not Deleted Successfully`);
  }
  else  {
    resolve(drive);
  }
  });
});
}

exports.move = function (sourceId, destParentId) {
    console.log(`sourceId:${sourceId}  parentId:${destParentId}`)

    return new Promise((resolve, reject) => {

        var destRootPath = path.join(__dirname, '../public/cloud/');
        var destFullPath;
        var destFileName;

        // Find the name of the file/folder that we're moving
        models.Drive.findById(sourceId).then(function (sourceRow) {
            if (sourceRow) {
                destFileName = sourceRow.name;
            }
            else {
                var msg = `Failed to find "name" data for sourceId:${sourceId}`;
                console.log(msg);
                reject(msg);
            }

            // Find the path of the destination folder
            models.Drive.findById(destParentId).then(function (destRow) {
                if (destRow) {
                    // Build the path from the parent row
                    destFullPath = path.join(destRow.path, destFileName);
                }
                else if (destParentId == 0) {
                    // Use the default root path
                    destFullPath = path.join(destRootPath, destFileName)
                }
                else {
                    var msg = `Failed to find "path" data for id (destParentId):${destParentId}`;
                    console.log(msg);
                    reject(msg);
                }

                console.log(`destParentId full path: '${destFullPath}'`);

                // Update the database with the new path for the sourceId
                models.Drive.update(
                    {
                        parent_id: destParentId,
                        path: destPath
                    },
                    {
                        where: { id: sourceId }
                    }
                ).then(function (moved) {
                    if (moved != 0) {
                        var msg = `Moved id:${sourceId} to new parent:${destParentId}`;
                        console.log(msg);
                        resolve(msg);
                    }
                    else {
                        var msg = `Failed to move id:${sourceId} to new parent:${destParentId}`;
                        console.log(msg);
                        reject(msg);
                    }
                });
            });
        });
    });
};
<|endoftext|>


<commit_before>$(function() {
$('.mask').css({
  'position':'relative',
  'display':'inline-block',
  'flex-grow':'1',
  'overflow':'hidden'
});

$('.mask').children().css({
  '-webkit-transform':'translate(150%, 150%)',
  '-moz-transform':'translate(150%, 150%)',
  '-o-transform':'translate(150%, 150%)',
  '-ms-transform':'translate(150%, 150%)',
  'transform':'translate(150%, 150%)'
});
});

function maskIt() {
  var $mask = $('.mask'),
      $masked = $mask.children();

  $mask.each(function() {
  var maskTransition = $(this).data('mask-transition');
  switch(maskTransition) {
    case 'fromLeft':
      $(this).children().css({
        '-webkit-transform': 'translate(-150%, 0)',
        '-moz-transform': 'translate(-150%, 0)',
        '-o-transform': 'translate(-150%, 0)',
        '-ms-transform': 'translate(-150%, 0)',
        'transform': 'translate(-150%, 0)'
      });
      break;
    case 'fromRight':
      $(this).children().css({
        '-webkit-transform': 'translate(150%, 0)',
        '-moz-transform': 'translate(150%, 0)',
        '-o-transform': 'translate(150%, 0)',
        '-ms-transform': 'translate(150%, 0)',
        'transform': 'translate(150%, 0)'
      });
      break;
    case 'fromTop':
      $(this).children().css({
        '-webkit-transform': 'translate(0, -150%)',
        '-moz-transform': 'translate(0, -150%)',
        '-o-transform': 'translate(0, -150%)',
        '-ms-transform': 'translate(0, -150%)',
        'transform': 'translate(0, -150%)'
      });
      break;
    case 'fromBottom':
      $(this).children().css({
        '-webkit-transform': 'translate(0, 150%)',
        '-moz-transform': 'translate(0, 150%)',
        '-o-transform': 'translate(0, 150%)',
        '-ms-transform': 'translate(0, 150%)',
        'transform': 'translate(0, 150%)'
      });
      break;
  }
    });

  $.each($mask, function(h) {
    $(this).children().delay(h * 150).queue(function() {
      $(this).css({
        '-webkit-transition': '.5s ease',
        '-moz-transition': '.5s ease',
        '-o-transition': '.5s ease',
        'transition': '.5s ease',
        '-webkit-transform': 'translate(0,0)',
        '-moz-transform': 'translate(0,0)',
        '-o-transform': 'translate(0,0)',
        '-ms-transform': 'translate(0,0)',
        'transform': 'translate(0,0)'
      });
    });
  });

}

$(window).load(function() {
    maskIt();
});<commit_msg>Delete masked.js<commit_after><|endoftext|>


<commit_before>/* globals Api Meteor Restivus logger processWebhookMessage*/
// TODO: remove globals

import _ from 'underscore';
import s from 'underscore.string';
import vm from 'vm';
import moment from 'moment';

const compiledScripts = {};
function buildSandbox(store = {}) {
	const sandbox = {
		_,
		s,
		console,
		moment,
		Livechat: RocketChat.Livechat,
		Store: {
			set(key, val) {
				return store[key] = val;
			},
			get(key) {
				return store[key];
			}
		},
		HTTP(method, url, options) {
			try {
				return {
					result: HTTP.call(method, url, options)
				};
			} catch (error) {
				return {
					error
				};
			}
		}
	};

	Object.keys(RocketChat.models).filter((k) => !k.startsWith('_')).forEach((k) => sandbox[k] = RocketChat.models[k]);
	return { store, sandbox	};
}

function getIntegrationScript(integration) {
	const compiledScript = compiledScripts[integration._id];
	if ((compiledScript != null) && +compiledScript._updatedAt === +integration._updatedAt) {
		return compiledScript.script;
	}
	const script = integration.scriptCompiled;
	const {sandbox, store} = buildSandbox();
	try {
		logger.incoming.info('Will evaluate script of Trigger', integration.name);
		logger.incoming.debug(script);
		const vmScript = vm.createScript(script, 'script.js');
		vmScript.runInNewContext(sandbox);
		if (sandbox.Script != null) {
			compiledScripts[integration._id] = {
				script: new sandbox.Script(),
				store,
				_updatedAt: integration._updatedAt
			};
			return compiledScripts[integration._id].script;
		}
	} catch ({stack}) {
		logger.incoming.error('[Error evaluating Script in Trigger', integration.name, ':]');
		logger.incoming.error(script.replace(/^/gm, '  '));
		logger.incoming.error('[Stack:]');
		logger.incoming.error(stack.replace(/^/gm, '  '));
		throw RocketChat.API.v1.failure('error-evaluating-script');
	}
	if (sandbox.Script == null) {
		logger.incoming.error('[Class "Script" not in Trigger', integration.name, ']');
		throw RocketChat.API.v1.failure('class-script-not-found');
	}
}

Api = new Restivus({
	enableCors: true,
	apiPath: 'hooks/',
	auth: {
		user() {
			const payloadKeys = Object.keys(this.bodyParams);
			const payloadIsWrapped = (this.bodyParams && this.bodyParams.payload) && payloadKeys.length === 1;
			if (payloadIsWrapped && this.request.headers['content-type'] === 'application/x-www-form-urlencoded') {
				try {
					this.bodyParams = JSON.parse(this.bodyParams.payload);
				} catch ({message}) {
					return {
						error: {
							statusCode: 400,
							body: {
								success: false,
								error: message
							}
						}
					};
				}
			}
			this.integration = RocketChat.models.Integrations.findOne({
				_id: this.request.params.integrationId,
				token: decodeURIComponent(this.request.params.token)
			});
			if (this.integration == null) {
				logger.incoming.info('Invalid integration id', this.request.params.integrationId, 'or token', this.request.params.token);
				return;
			}
			const user = RocketChat.models.Users.findOne({
				_id: this.integration.userId
			});
			return {user};
		}
	}
});

function createIntegration(options, user) {
	logger.incoming.info('Add integration', options.name);
	logger.incoming.debug(options);
	Meteor.runAsUser(user._id, function() {
		switch (options['event']) {
			case 'newMessageOnChannel':
				if (options.data == null) {
					options.data = {};
				}
				if ((options.data.channel_name != null) && options.data.channel_name.indexOf('#') === -1) {
					options.data.channel_name = `#${ options.data.channel_name }`;
				}
				return Meteor.call('addOutgoingIntegration', {
					username: 'rocket.cat',
					urls: [options.target_url],
					name: options.name,
					channel: options.data.channel_name,
					triggerWords: options.data.trigger_words
				});
			case 'newMessageToUser':
				if (options.data.username.indexOf('@') === -1) {
					options.data.username = `@${ options.data.username }`;
				}
				return Meteor.call('addOutgoingIntegration', {
					username: 'rocket.cat',
					urls: [options.target_url],
					name: options.name,
					channel: options.data.username,
					triggerWords: options.data.trigger_words
				});
		}
	});
	return RocketChat.API.v1.success();
}

function removeIntegration(options, user) {
	logger.incoming.info('Remove integration');
	logger.incoming.debug(options);
	const integrationToRemove = RocketChat.models.Integrations.findOne({
		urls: options.target_url
	});
	Meteor.runAsUser(user._id, () => {
		return Meteor.call('deleteOutgoingIntegration', integrationToRemove._id);
	});
	return RocketChat.API.v1.success();
}

function executeIntegrationRest() {
	logger.incoming.info('Post integration:', this.integration.name);
	logger.incoming.debug('@urlParams:', this.urlParams);
	logger.incoming.debug('@bodyParams:', this.bodyParams);

	if (this.integration.enabled !== true) {
		return {
			statusCode: 503,
			body: 'Service Unavailable'
		};
	}

	const defaultValues = {
		channel: this.integration.channel,
		alias: this.integration.alias,
		avatar: this.integration.avatar,
		emoji: this.integration.emoji
	};

	if (this.integration.scriptEnabled === true && this.integration.scriptCompiled && this.integration.scriptCompiled.trim() !== '') {
		let script;
		try {
			script = getIntegrationScript(this.integration);
		} catch (e) {
			logger.incoming.warn(e);
			return RocketChat.API.v1.failure(e.message);
		}

		const request = {
			url: {
				hash: this.request._parsedUrl.hash,
				search: this.request._parsedUrl.search,
				query: this.queryParams,
				pathname: this.request._parsedUrl.pathname,
				path: this.request._parsedUrl.path
			},
			url_raw: this.request.url,
			url_params: this.urlParams,
			content: this.bodyParams,
			content_raw: this.request._readableState && this.request._readableState.buffer && this.request._readableState.buffer.toString(),
			headers: this.request.headers,
			user: {
				_id: this.user._id,
				name: this.user.name,
				username: this.user.username
			}
		};

		try {
			const { sandbox } = buildSandbox(compiledScripts[this.integration._id].store);
			sandbox.script = script;
			sandbox.request = request;

			const result = vm.runInNewContext('script.process_incoming_request({ request: request })', sandbox, {
				timeout: 3000
			});

			if (!result) {
				logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':] No data');
				return RocketChat.API.v1.success();
			} else if (result && result.error) {
				return RocketChat.API.v1.failure(result.error);
			}

			this.bodyParams = result && result.content;
			this.scriptResponse = result.response;
			if (result.user) {
				this.user = result.user;
			}

			logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':]');
			logger.incoming.debug('result', this.bodyParams);
		} catch ({stack}) {
			logger.incoming.error('[Error running Script in Trigger', this.integration.name, ':]');
			logger.incoming.error(this.integration.scriptCompiled.replace(/^/gm, '  '));
			logger.incoming.error('[Stack:]');
			logger.incoming.error(stack.replace(/^/gm, '  '));
			return RocketChat.API.v1.failure('error-running-script');
		}
	}

	// TODO: Turn this into an option on the integrations - no body means a success
	// TODO: Temporary fix for https://github.com/RocketChat/Rocket.Chat/issues/7770 until the above is implemented
	if (!this.bodyParams) {
		// return RocketChat.API.v1.failure('body-empty');
		return RocketChat.API.v1.success();
	}

	this.bodyParams.bot = { i: this.integration._id };

	try {
		const message = processWebhookMessage(this.bodyParams, this.user, defaultValues);
		if (_.isEmpty(message)) {
			return RocketChat.API.v1.failure('unknown-error');
		}

		if (this.scriptResponse) {
			logger.incoming.debug('response', this.scriptResponse);
		}

		return RocketChat.API.v1.success(this.scriptResponse);
	} catch ({ error }) {
		return RocketChat.API.v1.failure(error);
	}
}

function addIntegrationRest() {
	return createIntegration(this.bodyParams, this.user);
}

function removeIntegrationRest() {
	return removeIntegration(this.bodyParams, this.user);
}

function integrationSampleRest() {
	logger.incoming.info('Sample Integration');
	return {
		statusCode: 200,
		body: [
			{
				token: Random.id(24),
				channel_id: Random.id(),
				channel_name: 'general',
				timestamp: new Date,
				user_id: Random.id(),
				user_name: 'rocket.cat',
				text: 'Sample text 1',
				trigger_word: 'Sample'
			}, {
				token: Random.id(24),
				channel_id: Random.id(),
				channel_name: 'general',
				timestamp: new Date,
				user_id: Random.id(),
				user_name: 'rocket.cat',
				text: 'Sample text 2',
				trigger_word: 'Sample'
			}, {
				token: Random.id(24),
				channel_id: Random.id(),
				channel_name: 'general',
				timestamp: new Date,
				user_id: Random.id(),
				user_name: 'rocket.cat',
				text: 'Sample text 3',
				trigger_word: 'Sample'
			}
		]
	};
}

function integrationInfoRest() {
	logger.incoming.info('Info integration');
	return {
		statusCode: 200,
		body: {
			success: true
		}
	};
}

Api.addRoute(':integrationId/:userId/:token', { authRequired: true }, {
	post: executeIntegrationRest,
	get: executeIntegrationRest
});

Api.addRoute(':integrationId/:token', { authRequired: true }, {
	post: executeIntegrationRest,
	get: executeIntegrationRest
});

Api.addRoute('sample/:integrationId/:userId/:token', { authRequired: true }, {
	get: integrationSampleRest
});

Api.addRoute('sample/:integrationId/:token', { authRequired: true }, {
	get: integrationSampleRest
});

Api.addRoute('info/:integrationId/:userId/:token', { authRequired: true }, {
	get: integrationInfoRest
});

Api.addRoute('info/:integrationId/:token', { authRequired: true }, {
	get: integrationInfoRest
});

Api.addRoute('add/:integrationId/:userId/:token', { authRequired: true }, {
	post: addIntegrationRest
});

Api.addRoute('add/:integrationId/:token', { authRequired: true }, {
	post: addIntegrationRest
});

Api.addRoute('remove/:integrationId/:userId/:token', { authRequired: true }, {
	post: removeIntegrationRest
});

Api.addRoute('remove/:integrationId/:token', { authRequired: true }, {
	post: removeIntegrationRest
});
<commit_msg>Fixed issue on incoming webhooks that caused the content raw to not be available (#10258)<commit_after>/* globals Api Meteor Restivus logger processWebhookMessage*/
// TODO: remove globals

import _ from 'underscore';
import s from 'underscore.string';
import vm from 'vm';
import moment from 'moment';

const compiledScripts = {};
function buildSandbox(store = {}) {
	const sandbox = {
		_,
		s,
		console,
		moment,
		Livechat: RocketChat.Livechat,
		Store: {
			set(key, val) {
				return store[key] = val;
			},
			get(key) {
				return store[key];
			}
		},
		HTTP(method, url, options) {
			try {
				return {
					result: HTTP.call(method, url, options)
				};
			} catch (error) {
				return {
					error
				};
			}
		}
	};

	Object.keys(RocketChat.models).filter((k) => !k.startsWith('_')).forEach((k) => sandbox[k] = RocketChat.models[k]);
	return { store, sandbox	};
}

function getIntegrationScript(integration) {
	const compiledScript = compiledScripts[integration._id];
	if ((compiledScript != null) && +compiledScript._updatedAt === +integration._updatedAt) {
		return compiledScript.script;
	}
	const script = integration.scriptCompiled;
	const {sandbox, store} = buildSandbox();
	try {
		logger.incoming.info('Will evaluate script of Trigger', integration.name);
		logger.incoming.debug(script);
		const vmScript = vm.createScript(script, 'script.js');
		vmScript.runInNewContext(sandbox);
		if (sandbox.Script != null) {
			compiledScripts[integration._id] = {
				script: new sandbox.Script(),
				store,
				_updatedAt: integration._updatedAt
			};
			return compiledScripts[integration._id].script;
		}
	} catch ({stack}) {
		logger.incoming.error('[Error evaluating Script in Trigger', integration.name, ':]');
		logger.incoming.error(script.replace(/^/gm, '  '));
		logger.incoming.error('[Stack:]');
		logger.incoming.error(stack.replace(/^/gm, '  '));
		throw RocketChat.API.v1.failure('error-evaluating-script');
	}
	if (sandbox.Script == null) {
		logger.incoming.error('[Class "Script" not in Trigger', integration.name, ']');
		throw RocketChat.API.v1.failure('class-script-not-found');
	}
}

Api = new Restivus({
	enableCors: true,
	apiPath: 'hooks/',
	auth: {
		user() {
			const payloadKeys = Object.keys(this.bodyParams);
			const payloadIsWrapped = (this.bodyParams && this.bodyParams.payload) && payloadKeys.length === 1;
			if (payloadIsWrapped && this.request.headers['content-type'] === 'application/x-www-form-urlencoded') {
				try {
					this.bodyParams = JSON.parse(this.bodyParams.payload);
				} catch ({message}) {
					return {
						error: {
							statusCode: 400,
							body: {
								success: false,
								error: message
							}
						}
					};
				}
			}
			this.integration = RocketChat.models.Integrations.findOne({
				_id: this.request.params.integrationId,
				token: decodeURIComponent(this.request.params.token)
			});
			if (this.integration == null) {
				logger.incoming.info('Invalid integration id', this.request.params.integrationId, 'or token', this.request.params.token);
				return;
			}
			const user = RocketChat.models.Users.findOne({
				_id: this.integration.userId
			});
			return {user};
		}
	}
});

function createIntegration(options, user) {
	logger.incoming.info('Add integration', options.name);
	logger.incoming.debug(options);
	Meteor.runAsUser(user._id, function() {
		switch (options['event']) {
			case 'newMessageOnChannel':
				if (options.data == null) {
					options.data = {};
				}
				if ((options.data.channel_name != null) && options.data.channel_name.indexOf('#') === -1) {
					options.data.channel_name = `#${ options.data.channel_name }`;
				}
				return Meteor.call('addOutgoingIntegration', {
					username: 'rocket.cat',
					urls: [options.target_url],
					name: options.name,
					channel: options.data.channel_name,
					triggerWords: options.data.trigger_words
				});
			case 'newMessageToUser':
				if (options.data.username.indexOf('@') === -1) {
					options.data.username = `@${ options.data.username }`;
				}
				return Meteor.call('addOutgoingIntegration', {
					username: 'rocket.cat',
					urls: [options.target_url],
					name: options.name,
					channel: options.data.username,
					triggerWords: options.data.trigger_words
				});
		}
	});
	return RocketChat.API.v1.success();
}

function removeIntegration(options, user) {
	logger.incoming.info('Remove integration');
	logger.incoming.debug(options);
	const integrationToRemove = RocketChat.models.Integrations.findOne({
		urls: options.target_url
	});
	Meteor.runAsUser(user._id, () => {
		return Meteor.call('deleteOutgoingIntegration', integrationToRemove._id);
	});
	return RocketChat.API.v1.success();
}

function executeIntegrationRest() {
	logger.incoming.info('Post integration:', this.integration.name);
	logger.incoming.debug('@urlParams:', this.urlParams);
	logger.incoming.debug('@bodyParams:', this.bodyParams);

	if (this.integration.enabled !== true) {
		return {
			statusCode: 503,
			body: 'Service Unavailable'
		};
	}

	const defaultValues = {
		channel: this.integration.channel,
		alias: this.integration.alias,
		avatar: this.integration.avatar,
		emoji: this.integration.emoji
	};

	if (this.integration.scriptEnabled === true && this.integration.scriptCompiled && this.integration.scriptCompiled.trim() !== '') {
		let script;
		try {
			script = getIntegrationScript(this.integration);
		} catch (e) {
			logger.incoming.warn(e);
			return RocketChat.API.v1.failure(e.message);
		}

		this.request.setEncoding('utf8');
		const content_raw = this.request.read();

		const request = {
			url: {
				hash: this.request._parsedUrl.hash,
				search: this.request._parsedUrl.search,
				query: this.queryParams,
				pathname: this.request._parsedUrl.pathname,
				path: this.request._parsedUrl.path
			},
			url_raw: this.request.url,
			url_params: this.urlParams,
			content: this.bodyParams,
			content_raw,
			headers: this.request.headers,
			user: {
				_id: this.user._id,
				name: this.user.name,
				username: this.user.username
			}
		};

		try {
			const { sandbox } = buildSandbox(compiledScripts[this.integration._id].store);
			sandbox.script = script;
			sandbox.request = request;

			const result = vm.runInNewContext('script.process_incoming_request({ request: request })', sandbox, {
				timeout: 3000
			});

			if (!result) {
				logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':] No data');
				return RocketChat.API.v1.success();
			} else if (result && result.error) {
				return RocketChat.API.v1.failure(result.error);
			}

			this.bodyParams = result && result.content;
			this.scriptResponse = result.response;
			if (result.user) {
				this.user = result.user;
			}

			logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':]');
			logger.incoming.debug('result', this.bodyParams);
		} catch ({stack}) {
			logger.incoming.error('[Error running Script in Trigger', this.integration.name, ':]');
			logger.incoming.error(this.integration.scriptCompiled.replace(/^/gm, '  '));
			logger.incoming.error('[Stack:]');
			logger.incoming.error(stack.replace(/^/gm, '  '));
			return RocketChat.API.v1.failure('error-running-script');
		}
	}

	// TODO: Turn this into an option on the integrations - no body means a success
	// TODO: Temporary fix for https://github.com/RocketChat/Rocket.Chat/issues/7770 until the above is implemented
	if (!this.bodyParams) {
		// return RocketChat.API.v1.failure('body-empty');
		return RocketChat.API.v1.success();
	}

	this.bodyParams.bot = { i: this.integration._id };

	try {
		const message = processWebhookMessage(this.bodyParams, this.user, defaultValues);
		if (_.isEmpty(message)) {
			return RocketChat.API.v1.failure('unknown-error');
		}

		if (this.scriptResponse) {
			logger.incoming.debug('response', this.scriptResponse);
		}

		return RocketChat.API.v1.success(this.scriptResponse);
	} catch ({ error }) {
		return RocketChat.API.v1.failure(error);
	}
}

function addIntegrationRest() {
	return createIntegration(this.bodyParams, this.user);
}

function removeIntegrationRest() {
	return removeIntegration(this.bodyParams, this.user);
}

function integrationSampleRest() {
	logger.incoming.info('Sample Integration');
	return {
		statusCode: 200,
		body: [
			{
				token: Random.id(24),
				channel_id: Random.id(),
				channel_name: 'general',
				timestamp: new Date,
				user_id: Random.id(),
				user_name: 'rocket.cat',
				text: 'Sample text 1',
				trigger_word: 'Sample'
			}, {
				token: Random.id(24),
				channel_id: Random.id(),
				channel_name: 'general',
				timestamp: new Date,
				user_id: Random.id(),
				user_name: 'rocket.cat',
				text: 'Sample text 2',
				trigger_word: 'Sample'
			}, {
				token: Random.id(24),
				channel_id: Random.id(),
				channel_name: 'general',
				timestamp: new Date,
				user_id: Random.id(),
				user_name: 'rocket.cat',
				text: 'Sample text 3',
				trigger_word: 'Sample'
			}
		]
	};
}

function integrationInfoRest() {
	logger.incoming.info('Info integration');
	return {
		statusCode: 200,
		body: {
			success: true
		}
	};
}

Api.addRoute(':integrationId/:userId/:token', { authRequired: true }, {
	post: executeIntegrationRest,
	get: executeIntegrationRest
});

Api.addRoute(':integrationId/:token', { authRequired: true }, {
	post: executeIntegrationRest,
	get: executeIntegrationRest
});

Api.addRoute('sample/:integrationId/:userId/:token', { authRequired: true }, {
	get: integrationSampleRest
});

Api.addRoute('sample/:integrationId/:token', { authRequired: true }, {
	get: integrationSampleRest
});

Api.addRoute('info/:integrationId/:userId/:token', { authRequired: true }, {
	get: integrationInfoRest
});

Api.addRoute('info/:integrationId/:token', { authRequired: true }, {
	get: integrationInfoRest
});

Api.addRoute('add/:integrationId/:userId/:token', { authRequired: true }, {
	post: addIntegrationRest
});

Api.addRoute('add/:integrationId/:token', { authRequired: true }, {
	post: addIntegrationRest
});

Api.addRoute('remove/:integrationId/:userId/:token', { authRequired: true }, {
	post: removeIntegrationRest
});

Api.addRoute('remove/:integrationId/:token', { authRequired: true }, {
	post: removeIntegrationRest
});
<|endoftext|>