<commit_before>/*
  ~  Copyright 2017 Ripple Foundation C.I.C. Ltd
  ~
  ~  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.
*/

let templateClinicalnotesDetail = require('./clinicalnotes-detail.html');

class ClinicalnotesDetailController {
  constructor($scope, $state, $stateParams, $ngRedux, clinicalnotesActions, serviceRequests, usSpinnerService) {

    this.setCurrentPageData = function (data) {
      /* istanbul ignore if  */
      if (data.patientsGet.data) {
        this.currentPatient = data.patientsGet.data;
      }
      if (data.clinicalnotes.dataGet) {
        this.clinicalNote = data.clinicalnotes.dataGet;
        this.dateCreated = moment(this.clinicalNote.dateCreated).format('DD-MMM-YYYY');
        usSpinnerService.stop("clinicalNoteDetail-spinner");
      }
    };

    let unsubscribe = $ngRedux.connect(state => ({
      getStoreData: this.setCurrentPageData(state)
    }))(this);

    $scope.$on('$destroy', unsubscribe);

    this.clinicalnotesLoad = clinicalnotesActions.get;
    this.clinicalnotesLoad($stateParams.patientId, $stateParams.detailsIndex, $stateParams.source);

    //Edit Clinical Note

    $scope.isEdit = false;

    /* istanbul ignore next  */
    this.edit = function () {
      $scope.isEdit = true;

      $scope.currentUser = this.currentUser;
      $scope.clinicalNoteEdit = Object.assign({}, this.clinicalNote);
      $scope.patient = this.currentPatient;

      $scope.clinicalNoteEdit.dateCreated = new Date(this.clinicalNote.dateCreated).toISOString().slice(0, 10);
    };
    this.cancelEdit = function () {
      $scope.isEdit = false;
    };

    $scope.confirmEdit = function (clinicalNoteForm, clinicalNote) {
      $scope.formSubmitted = true;
      /* istanbul ignore if  */
      if (clinicalNoteForm.$valid) {
        let toUpdate = {
          noteType: clinicalNote.clinicalNotesType,
          notes: clinicalNote.note,
          author: clinicalNote.author,
          source: clinicalNote.source,
          sourceId: clinicalNote.sourceId
        };

        this.clinicalNote = Object.assign(clinicalNote, $scope.clinicalNoteEdit);
        $scope.isEdit = false;
        clinicalnotesActions.update($scope.patient.id, toUpdate);
        setTimeout(function () {
          $state.go('clinicalNotes-detail', {
            patientId: $scope.patient.id,
            clinicalNoteIndex: clinicalNote.sourceId
          });
        }, 1000);
      }
    };
  }
}

const ClinicalnotesDetailComponent = {
  template: templateClinicalnotesDetail,
  controller: ClinicalnotesDetailController
};

ClinicalnotesDetailController.$inject = ['$scope', '$state', '$stateParams', '$ngRedux', 'clinicalnotesActions', 'serviceRequests', 'usSpinnerService'];
export default ClinicalnotesDetailComponent;<commit_msg>Change field for Clinical Notes Pages<commit_after>/*
  ~  Copyright 2017 Ripple Foundation C.I.C. Ltd
  ~
  ~  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.
*/

let templateClinicalnotesDetail = require('./clinicalnotes-detail.html');

class ClinicalnotesDetailController {
  constructor($scope, $state, $stateParams, $ngRedux, clinicalnotesActions, serviceRequests, usSpinnerService) {

    this.setCurrentPageData = function (data) {
      /* istanbul ignore if  */
      if (data.patientsGet.data) {
        this.currentPatient = data.patientsGet.data;
      }
      if (data.clinicalnotes.dataGet) {
        this.clinicalNote = data.clinicalnotes.dataGet;
        this.dateCreated = moment(this.clinicalNote.dateCreated).format('DD-MMM-YYYY');
        usSpinnerService.stop("clinicalNoteDetail-spinner");
      }
    };

    let unsubscribe = $ngRedux.connect(state => ({
      getStoreData: this.setCurrentPageData(state)
    }))(this);

    $scope.$on('$destroy', unsubscribe);

    this.clinicalnotesLoad = clinicalnotesActions.get;
    this.clinicalnotesLoad($stateParams.patientId, $stateParams.detailsIndex, $stateParams.source);

    //Edit Clinical Note

    $scope.isEdit = false;

    /* istanbul ignore next  */
    this.edit = function () {
      $scope.isEdit = true;

      $scope.currentUser = this.currentUser;
      $scope.clinicalNoteEdit = Object.assign({}, this.clinicalNote);
      $scope.patient = this.currentPatient;

      $scope.clinicalNoteEdit.dateCreated = new Date(this.clinicalNote.dateCreated).toISOString().slice(0, 10);
    };
    this.cancelEdit = function () {
      $scope.isEdit = false;
    };

    $scope.confirmEdit = function (clinicalNoteForm, clinicalNote) {
      $scope.formSubmitted = true;
      /* istanbul ignore if  */
      if (clinicalNoteForm.$valid) {
        let toUpdate = {
          clinicalNotesType: clinicalNote.clinicalNotesType,
          notes: clinicalNote.note,
          author: clinicalNote.author,
          source: clinicalNote.source,
          sourceId: clinicalNote.sourceId
        };

        this.clinicalNote = Object.assign(clinicalNote, $scope.clinicalNoteEdit);
        $scope.isEdit = false;
        clinicalnotesActions.update($scope.patient.id, toUpdate);
        setTimeout(function () {
          $state.go('clinicalNotes-detail', {
            patientId: $scope.patient.id,
            clinicalNoteIndex: clinicalNote.sourceId
          });
        }, 1000);
      }
    };
  }
}

const ClinicalnotesDetailComponent = {
  template: templateClinicalnotesDetail,
  controller: ClinicalnotesDetailController
};

ClinicalnotesDetailController.$inject = ['$scope', '$state', '$stateParams', '$ngRedux', 'clinicalnotesActions', 'serviceRequests', 'usSpinnerService'];
export default ClinicalnotesDetailComponent;<|endoftext|>


<commit_before>/************************************************************
 *
 * Mosaic Instagram Admin
 *
 ***********************************************************/

var MosaicInstagramAdmin = Class.extend({

  options: {
    http: {
      host: 'localhost'
      ,port: '3333'
    }
  }

  ,messageType: ''

  // Constructor
  // --------------------------------------------------------
  ,init: function(msgType) {

    var self = this;

    this.messageType = msgType;

    $('#instagram-images-overlay').fadeOut(0);
    $('#controls').hide();

    this.getQueuedImages(this.messageType, 1, function() {

      // Approve / decline buttons events
      $('div#approved-btn').click(function(e) {
        if(!self.locked) {
          $(this).addClass('highlight');
          self.updateImage($('#instagram-images li:first-child'), true);
        }
      });

      $('div#declined-btn').click(function(e) {
        if(!self.locked) {
          $(this).addClass('highlight');
          self.updateImage($('#instagram-images li:first-child'), false);
        }
      });

      $(document).keyup(function(e) {

        // Approve (arrow up)
        if(e.keyCode == 38) {
          if(!self.locked) {
            $('div#approved-btn').addClass('highlight');
            self.updateImage($('#instagram-images li:first-child'), true);
          }
        }

        // Decline (arrow down)
        if(e.keyCode == 40) {
          if(!self.locked) {
            $('div#declined-btn').addClass('highlight');
            self.updateImage($('#instagram-images li:first-child'), false);
          }
        }
      });

    });
  }

  //
  // --------------------------------------------------------
  ,getQueuedImages: function(type, limit, callback) {

    var self = this;

    // Get queued images json
    $.getJSON(
      'http://'
      + this.options.http.host
      + ':'
      + this.options.http.port
      + '/images/queued/'
      + type
      + '/0/0/'
      + limit

      ,function(images) {

        // Check for images
        if(images.length == 0) {

          $('#controls').hide();
          $('#instagram-images').fadeOut(100, function() {
            $('#instagram-images').empty();
            self.retryRequest(type, limit, function() {

              $('#instagram-images-overlay').fadeOut(100);
              $('#instagram-images').fadeIn(100);
              callback();
            });
          });

          return;
        }

        $('#controls').show();

        // Add images
        self.addImages(images, callback);
      }
    );
  }

  //
  // --------------------------------------------------------
  ,retryRequest: function(type, limit, callback) {

    var self = this;

    $('#instagram-images-overlay div.inner-update').hide();
    $('#instagram-images-overlay div.inner-error').show();
    $('#instagram-images-overlay').fadeIn(100, function() {

      var update_seconds = function(secondsLeft) {

        if(secondsLeft == 0) {
          self.getQueuedImages(type, limit, callback);
          return;
        }

        $('#error-timeout').text(secondsLeft);
        secondsLeft--;

        setTimeout(function() {
          update_seconds(secondsLeft);
        }, 1000);
      }

      update_seconds(5);
    });
  }

  //
  // --------------------------------------------------------
  ,addImages: function(images, callback) {

    var check_img = function(queue, cb) {

      if(queue.length == 0) {
        cb();
        return;
      }

      var image = queue.pop();
      var url = image.images.low_resolution.url;

      var img = new Image();

      img.onload = function() {

        var li = $('<li/>');
        var info = $('<div/>');
        info.addClass('instagram-image-info');

        info.html(image.user.username);

        li.append(info);

        li.attr({
          'id': 'instagram-image-' + image.media_id
        });

        li.data('media-id', image.media_id);
        li.data('item-id', image._id);

        li.css({
          'background-image': 'url(' + url + ')'
        });

        $('#instagram-images').append(li);

        check_img(queue, cb);

      };

      img.onerror = function() {

        check_img(queue, cb);

      };

      img.src = url;
    };

    check_img($.merge(images, []), callback);
  }

  //
  // --------------------------------------------------------
  ,updateImage: function(el, approved) {

    this.locked = true;

    var self = this;

    $('#instagram-images-overlay div.inner-error').hide();
    $('#instagram-images-overlay div.inner-update').show();
    $('#instagram-images-overlay').fadeIn(100);

    // Post new data to server
    $.post(
      'http://'
      + this.options.http.host
      + ':'
      + this.options.http.port
      + '/images/update/'
      ,{
        id: el.data('item-id')
        ,approved: approved
      }).done(function() {

      $('#instagram-images-result').empty();

      if(approved) {
        $('#instagram-images-result').css('background', 'green');
        $('#instagram-images-result').text('Approved');
      } else {
        $('#instagram-images-result').css('background', 'red');
        $('#instagram-images-result').text('Declined');
      }

      self.getQueuedImages(self.messageType, 1, function() {

        $('#instagram-images').fadeOut(100, function() {
          el.remove();
          $('#instagram-images-overlay').fadeOut(100);
          $('#instagram-images').fadeIn(100, function() {
            self.locked = false;
            $('.control-btn').removeClass('highlight');
          });
        });
      });
    })
  }
});<commit_msg>fxied image error<commit_after>/************************************************************
 *
 * Mosaic Instagram Admin
 *
 ***********************************************************/

var MosaicInstagramAdmin = Class.extend({

  options: {
    http: {
      host: 'localhost'
      ,port: '3333'
    }
  }

  ,messageType: ''

  // Constructor
  // --------------------------------------------------------
  ,init: function(msgType) {

    var self = this;

    this.messageType = msgType;

    $('#instagram-images-overlay').fadeOut(0);
    $('#controls').hide();

    this.getQueuedImages(this.messageType, 1, function() {

      // Approve / decline buttons events
      $('div#approved-btn').click(function(e) {
        if(!self.locked) {
          $(this).addClass('highlight');
          self.updateImage($('#instagram-images li:first-child'), true);
        }
      });

      $('div#declined-btn').click(function(e) {
        if(!self.locked) {
          $(this).addClass('highlight');
          self.updateImage($('#instagram-images li:first-child'), false);
        }
      });

      $(document).keyup(function(e) {

        // Approve (arrow up)
        if(e.keyCode == 38) {
          if(!self.locked) {
            $('div#approved-btn').addClass('highlight');
            self.updateImage($('#instagram-images li:first-child'), true);
          }
        }

        // Decline (arrow down)
        if(e.keyCode == 40) {
          if(!self.locked) {
            $('div#declined-btn').addClass('highlight');
            self.updateImage($('#instagram-images li:first-child'), false);
          }
        }
      });

    });
  }

  //
  // --------------------------------------------------------
  ,getQueuedImages: function(type, limit, callback) {

    var self = this;

    // Get queued images json
    $.getJSON(
      'http://'
      + this.options.http.host
      + ':'
      + this.options.http.port
      + '/images/queued/'
      + type
      + '/0/0/'
      + limit

      ,function(images) {

        // Check for images
        if(images.length == 0) {

          $('#controls').hide();
          $('#instagram-images').fadeOut(100, function() {
            $('#instagram-images').empty();
            self.retryRequest(type, limit, function() {

              $('#instagram-images-overlay').fadeOut(100);
              $('#instagram-images').fadeIn(100);
              callback();
            });
          });

          return;
        }

        $('#controls').show();

        // Add images
        self.addImages(images, callback);
      }
    );
  }

  //
  // --------------------------------------------------------
  ,retryRequest: function(type, limit, callback) {

    var self = this;

    $('#instagram-images-overlay div.inner-update').hide();
    $('#instagram-images-overlay div.inner-error').show();
    $('#instagram-images-overlay').fadeIn(100, function() {

      var update_seconds = function(secondsLeft) {

        if(secondsLeft == 0) {
          self.getQueuedImages(type, limit, callback);
          return;
        }

        $('#error-timeout').text(secondsLeft);
        secondsLeft--;

        setTimeout(function() {
          update_seconds(secondsLeft);
        }, 1000);
      }

      update_seconds(5);
    });
  }

  //
  // --------------------------------------------------------
  ,addImages: function(images, callback) {

    var self = this;

    var check_img = function(queue, cb) {

      if(queue.length == 0) {
        cb();
        return;
      }

      var image = queue.pop();
      var url = image.images.low_resolution.url;

      var img = new Image();

      img.onload = function() {

        var li = $('<li/>');
        var info = $('<div/>');
        info.addClass('instagram-image-info');

        info.html(image.user.username);

        li.append(info);

        li.attr({
          'id': 'instagram-image-' + image.media_id
        });

        li.data('media-id', image.media_id);
        li.data('item-id', image._id);

        li.css({
          'background-image': 'url(' + url + ')'
        });

        $('#instagram-images').append(li);

        check_img(queue, cb);

      };

      img.onerror = function() {

        self.retryRequest(self.messageType, 1, function() {

          $('#instagram-images').fadeOut(100, function() {
            el.remove();
            $('#instagram-images-overlay').fadeOut(100);
            $('#instagram-images').fadeIn(100, function() {
              self.locked = false;
              $('.control-btn').removeClass('highlight');
            });
          });
        });

      };

      img.src = url;
    };

    check_img($.merge(images, []), callback);
  }

  //
  // --------------------------------------------------------
  ,updateImage: function(el, approved) {

    this.locked = true;

    var self = this;

    $('#instagram-images-overlay div.inner-error').hide();
    $('#instagram-images-overlay div.inner-update').show();
    $('#instagram-images-overlay').fadeIn(100);

    // Post new data to server
    $.post(
      'http://'
      + this.options.http.host
      + ':'
      + this.options.http.port
      + '/images/update/'
      ,{
        id: el.data('item-id')
        ,approved: approved
      }).done(function() {

      $('#instagram-images-result').empty();

      if(approved) {
        $('#instagram-images-result').css('background', 'green');
        $('#instagram-images-result').text('Approved');
      } else {
        $('#instagram-images-result').css('background', 'red');
        $('#instagram-images-result').text('Declined');
      }

      self.getQueuedImages(self.messageType, 1, function() {

        $('#instagram-images').fadeOut(100, function() {
          el.remove();
          $('#instagram-images-overlay').fadeOut(100);
          $('#instagram-images').fadeIn(100, function() {
            self.locked = false;
            $('.control-btn').removeClass('highlight');
          });
        });
      });
    })
  }
});<|endoftext|>


<commit_before>L.scenograph.director.character_test = function() {
	// scene shit here
	console.log('Character test started')

	L.scenograph.director.camera_state.zoom = 500;
	L.scenograph.director.camera.position.set(
		0,
		0,
		L.scenograph.director.camera_state.zoom
	);
	var character = L.scenograph.director.make_character();
	character.position.y = -35;
	this.scene.add(character);
	this.animation_queue.push(character.animation)

	// direction (normalized), origin, length, color(hex)
	var origin = new THREE.Vector3(0,-130,0);
	var arrow = new THREE.ArrowHelper(new THREE.Vector3(0,0,1), origin,100, 0xFFCC00);
	this.scene.add(arrow);

	var gridXZ = new THREE.GridHelper(1000, 80);
	gridXZ.setColors( new THREE.Color(0x006600), new THREE.Color(0x006600) );
	gridXZ.position.set( 0,-150,0 );
	this.scene.add(gridXZ);
	var gridXY = new THREE.GridHelper(1000, 80);
	gridXY.setColors( new THREE.Color(0x006600), new THREE.Color(0x006600) );
	gridXY.rotation.z = Math.PI/2;
	gridXY.position.set( 1000,850,0 );
	this.scene.add(gridXY);
	var gridZY = new THREE.GridHelper(1000, 80);
	gridZY.setColors( new THREE.Color(0x006600), new THREE.Color(0x006600) );
	gridZY.rotation.x = Math.PI/2;
	gridZY.position.set( 0,850,1000 );
	this.scene.add(gridZY);

	var wireframeMaterial = new THREE.MeshBasicMaterial( { color: 0x666600, wireframe: true, transparent: true } );
	var box1 = new THREE.Mesh(new THREE.BoxGeometry(150, 75, 75), wireframeMaterial);
	box1.position.set(300,-110,300);
	this.scene.add(box1);
	var box2 = new THREE.Mesh(new THREE.BoxGeometry(150, 75, 75), wireframeMaterial);
	box2.position.set(300,-110,400);
	this.scene.add(box2);
	var box3 = new THREE.Mesh(new THREE.BoxGeometry(150, 75, 75), wireframeMaterial);
	box3.position.set(300,-35,300);
	this.scene.add(box3);
};

L.scenograph.director.make_character = function() {
	var texture = new THREE.ImageUtils.loadTexture( '/assets/exordium-male.png' );

	var material = new THREE.SpriteMaterial( { map: texture} );

	var new_character = new THREE.Sprite(material);
	new_character.world_rotation = 0;
	new_character.animation = new L.scenograph.director.make_animation( new_character, texture, 34, 1, 34, 3400 ); // texture, #horiz, #vert, #total, duration.
	new_character.scale.set(128,256,10);

	return new_character;
}

L.scenograph.director.move_character = function(character) {
	character.animation.moving = false;
	var rY = 0, tZ = 0, radian = (Math.PI / 180);
	if (L.scenograph.keyboard.pressed("W")) {
		tZ += 1.25;
		character.animation.moving = true;
	}
	if (L.scenograph.keyboard.pressed("S")) {
		tZ -= 1.25;
		character.animation.moving = true;
	}
	if (L.scenograph.keyboard.pressed("A")) {
		rY += radian;
		character.animation.moving = true;
	}
	if (L.scenograph.keyboard.pressed("D")) {
		rY -= radian;
		character.animation.moving = true;
	}
	if (rY != 0) {
		character.world_rotation += rY;
	}
	if (tZ != 0) {
		character.position.x += tZ * Math.sin(character.world_rotation);
		character.position.z += tZ * Math.cos(character.world_rotation);

		//L.scenograph.director.camera.position.x += tZ * Math.sin(character.world_rotation);
		//L.scenograph.director.camera.position.z += tZ * Math.cos(character.world_rotation);
		L.scenograph.director.camera.lookAt(character.position);

	}
}

L.scenograph.director.make_animation = function( character, texture, tilesHoriz, tilesVert, numTiles, tileDispDuration) {
	this.face = 'front';
	this.last_face = 'front';
	this.moving = true;
	// take in some variables to create a sprite object
	this.tilesHorizontal = tilesHoriz;
	this.tilesVertical = tilesVert;
	// how many images does this spritesheet contain?
	//  usually equals tilesHoriz * tilesVert, but not necessarily,
	//  if there at blank tiles at the bottom of the spritesheet.
	this.numberOfTiles = numTiles;
	texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
	texture.repeat.set( 1 / this.tilesHorizontal, 1 / this.tilesVertical );

	// how long should each image be displayed?
	this.tileDisplayDuration = tileDispDuration;

	// how long has the current image been displayed?
	this.currentDisplayTime = 0;

	// which image is currently being displayed?
	this.currentTile = 0;

	this.animate = function(delta) {
		L.scenograph.director.move_character(character);
		var tile_start = 0, tile_end = 7;
		switch(this.face) {
			case 'front':
				tile_start = 0;
				tile_end = 6;
				break;
			case 'back':
				tile_start = 8;
				tile_end = 14;
				break;
			case 'left':
				tile_start = 25;
				tile_end = 32;
				break;
			case 'right':
				tile_start = 16;
				tile_end = 23;
				break;
		}
		if (this.face != this.last_face) {
			this.currentTile = tile_start;
			this.last_face = this.face;
		}

		var axis = new THREE.Vector3( 0, -1, 0 );
		var angle = character.world_rotation;
		var matrix = new THREE.Matrix4().makeRotationAxis( axis, angle );
		var vector = character.position.clone();

		var camera_vector = new THREE.Vector3();
		camera_vector.setFromMatrixPosition( L.scenograph.director.camera.matrixWorld );

		var diff = new THREE.Vector3().subVectors(character.position, camera_vector).normalize();
		diff.applyMatrix4(matrix);

		if (diff.x < 0.6  && diff.x > -0.6 && diff.z <= 0.0) {
			this.face = 'front';
		}
		if (diff.x > 0.5 && diff.x < 0.8) {
			this.face = 'right';
		}
		if (diff.x < -0.5 && diff.x > -0.8) {
			this.face = 'left';
		}
		if (diff.z > 0.8) {
			this.face = 'back'
		}
		if (this.moving == true) {
			this.currentDisplayTime += delta * 25;
			while (this.currentDisplayTime > this.tileDisplayDuration)
			{
				this.currentDisplayTime -= this.tileDisplayDuration;

				if (this.currentTile >= tile_end) {
					this.currentTile = tile_start;
				}
				else {
					this.currentTile++;
				}
				var currentColumn = this.currentTile % this.tilesHorizontal;
				texture.offset.x = currentColumn / this.tilesHorizontal;
				var currentRow = Math.floor( this.currentTile / this.tilesHorizontal );
				texture.offset.y = currentRow / this.tilesVertical;
			}
		}
		else {
			this.currentTile = tile_start + 1;
			var currentColumn = this.currentTile % this.tilesHorizontal;
				texture.offset.x = currentColumn / this.tilesHorizontal;
				var currentRow = Math.floor( this.currentTile / this.tilesHorizontal );
				texture.offset.y = currentRow / this.tilesVertical;
		}

	}
}

L.scenograph.director.animate_character = function(delta) {

}<commit_msg>- Camera is now always looking at character<commit_after>L.scenograph.director.character_test = function() {
	// scene shit here
	console.log('Character test started')

	L.scenograph.director.camera_state.zoom = 500;
	L.scenograph.director.camera.position.set(
		0,
		0,
		L.scenograph.director.camera_state.zoom
	);
	var character = L.scenograph.director.make_character();
	character.position.y = -35;
	this.scene.add(character);
	this.animation_queue.push(character.animation)

	// direction (normalized), origin, length, color(hex)
	var origin = new THREE.Vector3(0,-130,0);
	var arrow = new THREE.ArrowHelper(new THREE.Vector3(0,0,1), origin,100, 0xFFCC00);
	this.scene.add(arrow);

	var gridXZ = new THREE.GridHelper(1000, 80);
	gridXZ.setColors( new THREE.Color(0x006600), new THREE.Color(0x006600) );
	gridXZ.position.set( 0,-150,0 );
	this.scene.add(gridXZ);
	var gridXY = new THREE.GridHelper(1000, 80);
	gridXY.setColors( new THREE.Color(0x006600), new THREE.Color(0x006600) );
	gridXY.rotation.z = Math.PI/2;
	gridXY.position.set( 1000,850,0 );
	this.scene.add(gridXY);
	var gridZY = new THREE.GridHelper(1000, 80);
	gridZY.setColors( new THREE.Color(0x006600), new THREE.Color(0x006600) );
	gridZY.rotation.x = Math.PI/2;
	gridZY.position.set( 0,850,1000 );
	this.scene.add(gridZY);

	var wireframeMaterial = new THREE.MeshBasicMaterial( { color: 0x666600, wireframe: true, transparent: true } );
	var box1 = new THREE.Mesh(new THREE.BoxGeometry(150, 75, 75), wireframeMaterial);
	box1.position.set(300,-110,300);
	this.scene.add(box1);
	var box2 = new THREE.Mesh(new THREE.BoxGeometry(150, 75, 75), wireframeMaterial);
	box2.position.set(300,-110,400);
	this.scene.add(box2);
	var box3 = new THREE.Mesh(new THREE.BoxGeometry(150, 75, 75), wireframeMaterial);
	box3.position.set(300,-35,300);
	this.scene.add(box3);
};

L.scenograph.director.make_character = function() {
	var texture = new THREE.ImageUtils.loadTexture( '/assets/exordium-male.png' );

	var material = new THREE.SpriteMaterial( { map: texture} );

	var new_character = new THREE.Sprite(material);
	new_character.world_rotation = 0;
	new_character.animation = new L.scenograph.director.make_animation( new_character, texture, 34, 1, 34, 3400 ); // texture, #horiz, #vert, #total, duration.
	new_character.scale.set(128,256,10);

	return new_character;
}

L.scenograph.director.move_character = function(character) {
	character.animation.moving = false;
	var rY = 0, tZ = 0, radian = (Math.PI / 180);
	if (L.scenograph.keyboard.pressed("W")) {
		tZ += 1.25;
		character.animation.moving = true;
	}
	if (L.scenograph.keyboard.pressed("S")) {
		tZ -= 1.25;
		character.animation.moving = true;
	}
	if (L.scenograph.keyboard.pressed("A")) {
		rY += radian;
		character.animation.moving = true;
	}
	if (L.scenograph.keyboard.pressed("D")) {
		rY -= radian;
		character.animation.moving = true;
	}
	if (rY != 0) {
		character.world_rotation += rY;
	}
	if (tZ != 0) {
		character.position.x += tZ * Math.sin(character.world_rotation);
		character.position.z += tZ * Math.cos(character.world_rotation);
	}
	L.scenograph.director.camera.lookAt(character.position);
}

L.scenograph.director.make_animation = function( character, texture, tilesHoriz, tilesVert, numTiles, tileDispDuration) {
	this.face = 'front';
	this.last_face = 'front';
	this.moving = true;
	// take in some variables to create a sprite object
	this.tilesHorizontal = tilesHoriz;
	this.tilesVertical = tilesVert;
	// how many images does this spritesheet contain?
	//  usually equals tilesHoriz * tilesVert, but not necessarily,
	//  if there at blank tiles at the bottom of the spritesheet.
	this.numberOfTiles = numTiles;
	texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
	texture.repeat.set( 1 / this.tilesHorizontal, 1 / this.tilesVertical );

	// how long should each image be displayed?
	this.tileDisplayDuration = tileDispDuration;

	// how long has the current image been displayed?
	this.currentDisplayTime = 0;

	// which image is currently being displayed?
	this.currentTile = 0;

	this.animate = function(delta) {
		L.scenograph.director.move_character(character);
		var tile_start = 0, tile_end = 7;
		switch(this.face) {
			case 'front':
				tile_start = 0;
				tile_end = 6;
				break;
			case 'back':
				tile_start = 8;
				tile_end = 14;
				break;
			case 'left':
				tile_start = 25;
				tile_end = 32;
				break;
			case 'right':
				tile_start = 16;
				tile_end = 23;
				break;
		}
		if (this.face != this.last_face) {
			this.currentTile = tile_start;
			this.last_face = this.face;
		}

		var axis = new THREE.Vector3( 0, -1, 0 );
		var angle = character.world_rotation;
		var matrix = new THREE.Matrix4().makeRotationAxis( axis, angle );
		var vector = character.position.clone();

		var camera_vector = new THREE.Vector3();
		camera_vector.setFromMatrixPosition( L.scenograph.director.camera.matrixWorld );

		var diff = new THREE.Vector3().subVectors(character.position, camera_vector).normalize();
		diff.applyMatrix4(matrix);

		if (diff.x < 0.6  && diff.x > -0.6 && diff.z <= 0.0) {
			this.face = 'front';
		}
		if (diff.x > 0.5 && diff.x < 0.8) {
			this.face = 'right';
		}
		if (diff.x < -0.5 && diff.x > -0.8) {
			this.face = 'left';
		}
		if (diff.z > 0.8) {
			this.face = 'back'
		}
		if (this.moving == true) {
			this.currentDisplayTime += delta * 25;
			while (this.currentDisplayTime > this.tileDisplayDuration)
			{
				this.currentDisplayTime -= this.tileDisplayDuration;

				if (this.currentTile >= tile_end) {
					this.currentTile = tile_start;
				}
				else {
					this.currentTile++;
				}
				var currentColumn = this.currentTile % this.tilesHorizontal;
				texture.offset.x = currentColumn / this.tilesHorizontal;
				var currentRow = Math.floor( this.currentTile / this.tilesHorizontal );
				texture.offset.y = currentRow / this.tilesVertical;
			}
		}
		else {
			this.currentTile = tile_start + 1;
			var currentColumn = this.currentTile % this.tilesHorizontal;
				texture.offset.x = currentColumn / this.tilesHorizontal;
				var currentRow = Math.floor( this.currentTile / this.tilesHorizontal );
				texture.offset.y = currentRow / this.tilesVertical;
		}

	}
}

L.scenograph.director.animate_character = function(delta) {

}<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', '{views}');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());{css}
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;
<commit_msg>gen: fix response code in error handlers<commit_after>var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', '{views}');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());{css}
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;
<|endoftext|>


<commit_before>// ==UserScript==
// @name         rails-i18n-translation-missing-highlighter
// @namespace    http://www.betterplace.org/
// @version      0.1
// @description  See https://github.com/tordans/rails-i18n-translation-missing-highlighter
// @match        http://www.betterplace.dev/*, https://www.bp42.com/*, https://www.betterplace.org/*
// @copyright    2012+, Tobias Jordans
// ==/UserScript==

var $translation_missing_elements = $("[title*='translation missing:']");
var $quickinfo_element = $('.quickinfo.generic-admin-box.for-platform-admins');

if($translation_missing_elements.length > 0) {
	$translation_missing_elements.each( function() {
		$quickinfo_element.append("
" + $(this).attr('title') + "
");
	});
} else {
    $quickinfo_element.append(" / no translations missing");
}
<commit_msg>Fix @match<commit_after>// ==UserScript==
// @name         rails-i18n-translation-missing-highlighter
// @namespace    http://www.betterplace.org/
// @version      0.1
// @description  See https://github.com/tordans/rails-i18n-translation-missing-highlighter
// @match        http://www.betterplace.org/*
// @copyright    2012+, Tobias Jordans
// ==/UserScript==

var $translation_missing_elements = $("[title*='translation missing:']");
var $quickinfo_element = $('.quickinfo.generic-admin-box.for-platform-admins');

if($translation_missing_elements.length > 0) {
	$translation_missing_elements.each( function() {
		$quickinfo_element.append("
" + $(this).attr('title') + "
");
	});
} else {
    $quickinfo_element.append(" / no translations missing");
}
<|endoftext|>


<commit_before>LazyLoad.js([
      '/Umbraco/lib/jquery/jquery-2.0.3.min.js',
      '/Umbraco/lib/jquery/jquery-ui-1.10.4.custom.min.js',
      '/Umbraco/lib/Less/less-1.7.0.min.js',
      '/Umbraco/lib/angular/1.1.5/angular.min.js',
      '/Umbraco/lib/angular-bootstrap/ui-bootstrap-tpls-0.10.0.min.js',
      '/Umbraco/lib/spectrum/spectrum.js',
      'http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js',
      '/umbraco/js/umbraco.uSkyTuning.js'
], function () {
    jQuery(document).ready(function () {
        angular.bootstrap(document, ['umbraco.uSkyTuning']);
    });
}
);<commit_msg>uSkyTuning.loader.js deleted<commit_after><|endoftext|>


<commit_before>import React from 'react';
import { map, isEmpty } from 'lodash';
import { displayUserInfo, displayCityState } from '../../helpers';

const UserInformation = (props) => (

    {!isEmpty(props.user) ?

        {props.linkSignup ?

<a href={`/signups/${props.linkSignup}`}>{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        :

{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        }

          {props.user.email ? {props.user.email}
: null}
          {props.user.mobile ? {props.user.mobile}
 : null }
          {displayCityState(props.user.addr_city, props.user.addr_state) ? {displayCityState(props.user.addr_city, props.user.addr_state) }
 : null }

    : null}

    {props.children}

);

export default UserInformation;
<commit_msg>Clean up UserInformation component<commit_after>import React from 'react';
import { isEmpty } from 'lodash';
import PropTypes from 'prop-types';
import { displayUserInfo, displayCityState } from '../../helpers';

const UserInformation = props => (

    {! isEmpty(props.user) ?

        {props.linkSignup ?

<a href={`/signups/${props.linkSignup}`}>{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

          :

{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        }

          {props.user.email ? {props.user.email}
 : null}
          {props.user.mobile ? {props.user.mobile}
 : null }
          {displayCityState(props.user.addr_city, props.user.addr_state) ?
            {displayCityState(props.user.addr_city, props.user.addr_state) }

            :
            null
          }

      : null
    }

    {props.children}

);

UserInformation.propTypes = {
  user: PropTypes.shape({
    first_name: PropTypes.string,
    last_name: PropTypes.string,
    birthdate: PropTypes.string,
    email: PropTypes.string,
    mobile: PropTypes.string,
    addr_city: PropTypes.string,
    addr_state: PropTypes.string,
  }).isRequired,
  children: PropTypes.string,
  linkSignup: PropTypes.int,
};

UserInformation.defaultProps = {
  children: null,
  linkSignup: null,
};

export default UserInformation;
<|endoftext|>


<commit_before>module.exports = (function($)
{

    var notificationCount = 0;
    var notifications     = new NotificationList();

    var handlerList = [];

    return {
        log             : _log,
        info            : _info,
        warn            : _warn,
        error           : _error,
        success         : _success,
        getNotifications: getNotifications,
        listen          : _listen
    };

    function _listen(handler)
    {
        handlerList.push(handler);
    }

    function trigger()
    {
        for (var i = 0; i < handlerList.length; i++)
        {
            handlerList[i].call({}, notifications.all());
        }
    }

    function _log(message, prefix)
    {
        var notification = new Notification(message);

        if (App.config.logMessages)
        {
            console.log((prefix || "") + "[" + notification.code + "] " + notification.message);

            for (var i = 0; i < notification.stackTrace.length; i++)
            {
                _log(notification.stackTrace[i], " + ");
            }
        }

        return notification;
    }

    function _info(message)
    {
        var notification = new Notification(message, "info");

        if (App.config.printInfos)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function _warn(message)
    {
        var notification = new Notification(message, "warning");

        if (App.config.printWarnings)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function _error(message)
    {
        var notification = new Notification(message, "danger");

        if (App.config.printErrors)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function _success(message)
    {
        var notification = new Notification(message, "success");

        if (App.config.printSuccess)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function getNotifications()
    {
        return notifications;
    }

    function _printNotification(notification)
    {
        notifications.add(notification);
        _log(notification);

        trigger();

        return notification;
    }

    function Notification(data, context)
    {
        if (!App.config.printStackTrace && data.stackTrace)
        {
            data.stackTrace = [];
        }
        var id   = notificationCount++;
        var self = {
            id        : id,
            code      : data.code || 0,
            message   : data.message || data || "",
            context   : context || "info",
            stackTrace: data.stackTrace || [],
            close     : close,
            closeAfter: closeAfter,
            trace     : trace
        };

        return self;

        function close()
        {
            notifications.remove(self);
            trigger();
        }

        function closeAfter(timeout)
        {
            setTimeout(function()
            {
                notifications.remove(self);
                trigger();
            }, timeout);
        }

        function trace(message, code)
        {
            if (App.config.printStackTrace)
            {
                self.stackTrace.push({
                    code   : code || 0,
                    message: message
                });
            }
        }
    }

    function NotificationList()
    {
        var elements = [];

        return {
            all   : all,
            add   : add,
            remove: remove
        };

        function all()
        {
            return elements;
        }

        function add(notification)
        {
            elements.push(notification);
        }

        function remove(notification)
        {
            for (var i = 0; i < elements.length; i++)
            {
                if (elements[i].id === notification.id)
                {
                    elements.splice(i, 1);
                    break;
                }
            }
        }
    }

})(jQuery);
<commit_msg>CHANGE type check for notification<commit_after>module.exports = (function($)
{

    var notificationCount = 0;
    var notifications     = new NotificationList();

    var handlerList = [];

    return {
        log             : _log,
        info            : _info,
        warn            : _warn,
        error           : _error,
        success         : _success,
        getNotifications: getNotifications,
        listen          : _listen
    };

    function _listen(handler)
    {
        handlerList.push(handler);
    }

    function trigger()
    {
        for (var i = 0; i < handlerList.length; i++)
        {
            handlerList[i].call({}, notifications.all());
        }
    }

    function _log(message, prefix)
    {
        var notification = new Notification(message);

        if (App.config.logMessages)
        {
            console.log((prefix || "") + "[" + notification.code + "] " + notification.message);

            for (var i = 0; i < notification.stackTrace.length; i++)
            {
                _log(notification.stackTrace[i], " + ");
            }
        }

        return notification;
    }

    function _info(message)
    {
        var notification = new Notification(message, "info");

        if (App.config.printInfos)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function _warn(message)
    {
        var notification = new Notification(message, "warning");

        if (App.config.printWarnings)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function _error(message)
    {
        var notification = new Notification(message, "danger");

        if (App.config.printErrors)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function _success(message)
    {
        var notification = new Notification(message, "success");

        if (App.config.printSuccess)
        {
            _printNotification(notification);
        }

        return notification;
    }

    function getNotifications()
    {
        return notifications;
    }

    function _printNotification(notification)
    {
        notifications.add(notification);
        _log(notification);

        trigger();

        return notification;
    }

    function Notification(data, context)
    {
        if (!App.config.printStackTrace && typeof (data) === "object")
        {
            data.stackTrace = [];
        }
        var id   = notificationCount++;
        var self = {
            id        : id,
            code      : data.code || 0,
            message   : data.message || data || "",
            context   : context || "info",
            stackTrace: data.stackTrace || [],
            close     : close,
            closeAfter: closeAfter,
            trace     : trace
        };

        return self;

        function close()
        {
            notifications.remove(self);
            trigger();
        }

        function closeAfter(timeout)
        {
            setTimeout(function()
            {
                notifications.remove(self);
                trigger();
            }, timeout);
        }

        function trace(message, code)
        {
            if (App.config.printStackTrace)
            {
                self.stackTrace.push({
                    code   : code || 0,
                    message: message
                });
            }
        }
    }

    function NotificationList()
    {
        var elements = [];

        return {
            all   : all,
            add   : add,
            remove: remove
        };

        function all()
        {
            return elements;
        }

        function add(notification)
        {
            elements.push(notification);
        }

        function remove(notification)
        {
            for (var i = 0; i < elements.length; i++)
            {
                if (elements[i].id === notification.id)
                {
                    elements.splice(i, 1);
                    break;
                }
            }
        }
    }

})(jQuery);
<|endoftext|>


<commit_before>

/*
 * Reference Technique library tree
 */
var buildReferenceTechniqueTree = function(id,  initially_select) {
  $(id).bind("loaded.jstree", function (event, data) {
    data.inst.open_all(-1);
  }).jstree({
    "core" : {
    "animation" : 0,
    "html_titles" : true
    },
    "ui" : {
      "initially_select" : [initially_select],
      "select_limit" : 1
    },
    "types" : {
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "valid_children" : [ "category" ],
        "types" : {
          "category" : {
            "icon" : {
              "image" : "images/tree/folder_16x16.png"
            },
            "valid_children" : [ "category", "template" ],
            "hover_node" : false,
            "select_node" : false,
            "start_drag" : false
          },
          "template" : {
            "icon" : {
              "image" : "images/tree/technique_16x16.png"
            },
            "valid_children" : "none"
          },
          "default" : {
            "valid_children" : "none"
          }
        }
      },
      "search" : {
          "case_insensitive" : true,
          "show_only_matches": true
        },
      "crrm" : {
        "move" : {
          "check_move" : function () { return false; }
        }
      },
      "dnd" : {
        "drop_target" : false,
        "drag_target" : false
      },
      "themes" : {
    	  "theme" : "rudder",
    	  "url" : "javascript/jstree/themes/rudder/style.css"
      },
      "plugins" : [ "themes", "html_data", "ui", "types", "dnd", "crrm", "search" ]
    })
}

/*
 * Active Techniques library tree
 */
var buildActiveTechniqueTree = function(id, foreignTreeId) {
  $(id).bind("loaded.jstree", function (event, data) {
	  data.inst.open_all(-1);
  }).jstree({
    "core" : {
    "animation" : 0,
    "html_titles" : true
    },
    "ui" : {
      "select_limit" : 1
    },
    "types" : {
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "valid_children" : [ "root-category" ],
      "types" : {
        "root-category" : {
          "icon" : {
            "image" : "images/tree/folder_16x16.png"
          },
          "valid_children" : [ "category", "template" ],
          "start_drag" : false
        },
        "category" : {
          "icon" : {
            "image" : "images/tree/folder_16x16.png"
          },
          "valid_children" : [ "category", "template" ]
        },
        "template" : {
          "icon" : {
            "image" : "images/tree/technique_16x16.png"
          },
          "valid_children" : "none"
        },
        "default" : {
          "valid_children" : "none"
        }
      }
    },
    "crrm" : {
      "move" : {
        "always_copy" : "multitree",
        "check_move" : function (m) {
          //only accept to move a node from the reference tree if it does not exists in that tree
           var checkNotAlreadyBound = function() {
	          var res = true;
	          var originTree = m.ot.get_container().prop("id");
	          var activetechniqueid = "";
	          for(i = 0 ; i < m.o[0].attributes.length; i++) {
	        	  if(m.o[0].attributes[i].name == "activetechniqueid") {
	        		  activetechniqueid = m.o[0].attributes[i].nodeValue;
	        		  break;
	        	  }
	          }
	          var list = $(id + " [activeTechniqueid=" + activetechniqueid + "]");
	          if(foreignTreeId == originTree) {
	            //look if there is an li with attr activeTechniqueId == moved object activeTechniqueId
	            res =  list.size() < 1 ;
	          }
	          return res;
          };
          //only accept "inside" node move (yes, comparing m.p == "inside" does not work)
          //and into a new parent node.
          var checkInside = (m.p != "before" && m.p != "after" && this._get_parent(m.o)[0] !== m.np[0]);

          return checkNotAlreadyBound() && checkInside;
        }
      }
    },
    "search" : {
        "case_insensitive" : true,
        "show_only_matches": true
      },
    "dnd" : {
      "drop_target" : false,
      "drag_target" : false
    },
    "themes" : {
  	  "theme" : "rudder",
  	  "url" : "javascript/jstree/themes/rudder/style.css"
    },
    "plugins" : [ "themes", "html_data", "ui", "types", "dnd", "crrm", "search" ]
  })
}

/*
 * Directive management
 */
var buildDirectiveTree = function(id, initially_select) {
  jQuery(id).jstree({
      "core" : {
      "animation" : 0,
      "html_titles" : true,
      "initially_open" : [ "jstn_0" ]
      },
     "ui" : {
        "select_limit" : 1,
        "initially_select" : [initially_select]
      },
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "types" : {
        "valid_children" : [ "category" ],
          "types" : {
            "category" : {
              "icon" : {
                "image" : "images/tree/folder_16x16.png"
              },
              "valid_children" : [ "category", "template" ],
              "select_node" : false
            },
            "template" : {
              "icon" : {
                "image" : "images/tree/technique_16x16.png"
              },
              "valid_children" : [ "directive" ]
            },
            "directive" : {
              "icon" : {
                "image" : "images/tree/directive_16x16.gif"
              },
              "valid_children" : "none"
            },
            "default" : {
              "valid_children" : "none"
            }
          }
      },
      "search" : {
        "case_insensitive" : true,
        "show_only_matches": true
      },
      "themes" : {
    	  "theme" : "rudder",
    	  "url" : "javascript/jstree/themes/rudder/style.css"
      },
      "plugins" : [ "themes", "html_data", "ui", "types", "search" ]
  })
}

/*
 * Group tree
 */
var buildGroupTree = function(id, initially_select, select_multiple_modifier) {
  if(select_multiple_modifier !== 'undefined') {
    select_limit = -1;
  } else {
    select_multiple_modifier = "";
    select_limit = 1;
  }
  $(id).bind("loaded.jstree", function (event, data) {
    data.inst.open_all(-1);
  }).jstree({
    "core" : {
      "animation" : 0,
      "html_titles" : true
    },
    "ui" : {
      "initially_select" : initially_select,
      "select_limit" : select_limit,
      "select_multiple_modifier" : select_multiple_modifier
    },
    "types" : {
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "valid_children" : [ "root-category" ],
      "types" : {
        "root-category" : {
          "icon" : { "image" : "images/tree/folder_16x16.png" },
          "valid_children" : [ "category", "group" , "special_target" ],
          "start_drag" : false
        },
        "category" : {
          "icon" : { "image" : "images/tree/folder_16x16.png" },
          "valid_children" : [ "category", "group" , "special_target" ],
          "select_node" : false
        },
        "group" : {
          "icon" : { "image" : "images/tree/server_group_16x16.gif" },
          "valid_children" : "none"
        },
        "special_target" : {
          "icon" : { "image" : "images/tree/special_target_16x16.gif" },
          "valid_children" : "none"
        },
        "default" : {
          "valid_children" : "none"
        }
      }
    },
    "crrm" : {
      "move" : {
        "check_move" : function (m) {
          //only accept "inside" node move (yes, comparing m.p == "inside" does not work)
          //and into a new parent node.
          return (m.p != "before" && m.p != "after" && this._get_parent(m.o)[0] !== m.np[0]);
        }
      }
    },
    "dnd" : {
      "drop_target" : false,
      "drag_target" : false
    },
    "themes" : {
  	  "theme" : "rudder",
  	  "url" : "javascript/jstree/themes/rudder/style.css"
    },
    "plugins" : [ "themes", "html_data", "ui", "types", "dnd", "crrm" ]
    });
}

/*
 * Directive management
 * NOTE: all children are set to none because
 *       we don't want/have to allow node move -
 *       that tree is read only.
 */
var buildTechniqueDependencyTree = function(id, initially_select) {
  jQuery(id).
    bind("loaded.jstree", function (event, data) {
      data.inst.open_all(-1);
    }).jstree({
      "core" : {
      "animation" : 0,
      "html_titles" : true
      },
     "ui" : {
        "initially_select" : [initially_select],
        "select_limit" : 1
      },
      "types" : {
        // I set both options to -2, as I do not need depth and children count checking
        // Those two checks may slow jstree a lot, so use only when needed
        "max_depth" : -2,
        "max_children" : -2,
        "valid_children" : [ "category" ],
          "types" : {
            "category" : {
              "icon" : {
                "image" : "images/tree/folder_16x16.png"
              },
              "valid_children" : [ "category", "template" ]
            },
            "template" : {
              "icon" : {
                "image" : "images/tree/technique_16x16.png"
              },
              "valid_children" : [ "directive" ]
            },
            "directive" : {
              "icon" : {
                "image" : "images/tree/directive_16x16.gif"
              },
              "valid_children" : [ "rule" ]
            },
            "rule" : {
                "icon" : {
                  "image" : "images/tree/configuration_rule_16x16.png"
                },
                "valid_children" : "none"
             },
            "default" : {
              "valid_children" : "none"
            }
          }
        },
        "themes" : {
      	  "theme" : "rudder",
      	  "url" : "javascript/jstree/themes/rudder/style.css"
        },
      "plugins" : [ "themes", "html_data", "ui", "types"]
    })
}

var buildRulePIdepTree = function(id, initially_select) {
  jQuery(id).
    bind("loaded.jstree", function (event, data) {
      data.inst.open_all(-1);
    }).jstree({
      "core" : {
        "animation" : 0,
        "html_titles" : true
      },
      "ui" : {
        "select_limit" : -1,
        "select_multiple_modifier" : "on",
        "selected_parent_close" : false,
        "initially_select" : initially_select
      },
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "types" : {
        "valid_children" : [ "category" ],
        "types" : {
          "category" : {
            "icon" : {
              "image" : "images/tree/folder_16x16.png"
            },
            "valid_children" : [ "category", "template" ],
            "select_node" : false
          },
          "template" : {
            "icon" : {
              "image" : "images/tree/technique_16x16.png"
            },
            "valid_children" : [ "directive" ],
            "select_node" : false
          },
          "directive" : {
            "icon" : {
              "image" : "images/tree/directive_16x16.gif"
            },
            "valid_children" : "none"
          },
          "default" : {
            "valid_children" : "none"
          }
        }
      },
      "themes" : {
    	  "theme" : "rudder",
    	  "url" : "javascript/jstree/themes/rudder/style.css"
      },
      "plugins" : [ "themes", "html_data", "ui", "types"]
    })
}

<commit_msg>Fixes #2674 Change the selection behavior in Group Tree<commit_after>

/*
 * Reference Technique library tree
 */
var buildReferenceTechniqueTree = function(id,  initially_select) {
  $(id).bind("loaded.jstree", function (event, data) {
    data.inst.open_all(-1);
  }).jstree({
    "core" : {
    "animation" : 0,
    "html_titles" : true
    },
    "ui" : {
      "initially_select" : [initially_select],
      "select_limit" : 1
    },
    "types" : {
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "valid_children" : [ "category" ],
        "types" : {
          "category" : {
            "icon" : {
              "image" : "images/tree/folder_16x16.png"
            },
            "valid_children" : [ "category", "template" ],
            "hover_node" : false,
            "select_node" : false,
            "start_drag" : false
          },
          "template" : {
            "icon" : {
              "image" : "images/tree/technique_16x16.png"
            },
            "valid_children" : "none"
          },
          "default" : {
            "valid_children" : "none"
          }
        }
      },
      "search" : {
          "case_insensitive" : true,
          "show_only_matches": true
        },
      "crrm" : {
        "move" : {
          "check_move" : function () { return false; }
        }
      },
      "dnd" : {
        "drop_target" : false,
        "drag_target" : false
      },
      "themes" : {
    	  "theme" : "rudder",
    	  "url" : "javascript/jstree/themes/rudder/style.css"
      },
      "plugins" : [ "themes", "html_data", "ui", "types", "dnd", "crrm", "search" ]
    })
}

/*
 * Active Techniques library tree
 */
var buildActiveTechniqueTree = function(id, foreignTreeId) {
  $(id).bind("loaded.jstree", function (event, data) {
	  data.inst.open_all(-1);
  }).jstree({
    "core" : {
    "animation" : 0,
    "html_titles" : true
    },
    "ui" : {
      "select_limit" : 1
    },
    "types" : {
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "valid_children" : [ "root-category" ],
      "types" : {
        "root-category" : {
          "icon" : {
            "image" : "images/tree/folder_16x16.png"
          },
          "valid_children" : [ "category", "template" ],
          "start_drag" : false
        },
        "category" : {
          "icon" : {
            "image" : "images/tree/folder_16x16.png"
          },
          "valid_children" : [ "category", "template" ]
        },
        "template" : {
          "icon" : {
            "image" : "images/tree/technique_16x16.png"
          },
          "valid_children" : "none"
        },
        "default" : {
          "valid_children" : "none"
        }
      }
    },
    "crrm" : {
      "move" : {
        "always_copy" : "multitree",
        "check_move" : function (m) {
          //only accept to move a node from the reference tree if it does not exists in that tree
           var checkNotAlreadyBound = function() {
	          var res = true;
	          var originTree = m.ot.get_container().prop("id");
	          var activetechniqueid = "";
	          for(i = 0 ; i < m.o[0].attributes.length; i++) {
	        	  if(m.o[0].attributes[i].name == "activetechniqueid") {
	        		  activetechniqueid = m.o[0].attributes[i].nodeValue;
	        		  break;
	        	  }
	          }
	          var list = $(id + " [activeTechniqueid=" + activetechniqueid + "]");
	          if(foreignTreeId == originTree) {
	            //look if there is an li with attr activeTechniqueId == moved object activeTechniqueId
	            res =  list.size() < 1 ;
	          }
	          return res;
          };
          //only accept "inside" node move (yes, comparing m.p == "inside" does not work)
          //and into a new parent node.
          var checkInside = (m.p != "before" && m.p != "after" && this._get_parent(m.o)[0] !== m.np[0]);

          return checkNotAlreadyBound() && checkInside;
        }
      }
    },
    "search" : {
        "case_insensitive" : true,
        "show_only_matches": true
      },
    "dnd" : {
      "drop_target" : false,
      "drag_target" : false
    },
    "themes" : {
  	  "theme" : "rudder",
  	  "url" : "javascript/jstree/themes/rudder/style.css"
    },
    "plugins" : [ "themes", "html_data", "ui", "types", "dnd", "crrm", "search" ]
  })
}

/*
 * Directive management
 */
var buildDirectiveTree = function(id, initially_select) {
  jQuery(id).jstree({
      "core" : {
      "animation" : 0,
      "html_titles" : true,
      "initially_open" : [ "jstn_0" ]
      },
     "ui" : {
        "select_limit" : 1,
        "initially_select" : [initially_select]
      },
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "types" : {
        "valid_children" : [ "category" ],
          "types" : {
            "category" : {
              "icon" : {
                "image" : "images/tree/folder_16x16.png"
              },
              "valid_children" : [ "category", "template" ],
              "select_node" : false
            },
            "template" : {
              "icon" : {
                "image" : "images/tree/technique_16x16.png"
              },
              "valid_children" : [ "directive" ]
            },
            "directive" : {
              "icon" : {
                "image" : "images/tree/directive_16x16.gif"
              },
              "valid_children" : "none"
            },
            "default" : {
              "valid_children" : "none"
            }
          }
      },
      "search" : {
        "case_insensitive" : true,
        "show_only_matches": true
      },
      "themes" : {
    	  "theme" : "rudder",
    	  "url" : "javascript/jstree/themes/rudder/style.css"
      },
      "plugins" : [ "themes", "html_data", "ui", "types", "search" ]
  })
}

/*
 * Group tree
 */
var buildGroupTree = function(id, initially_select, select_multiple_modifier) {
  if(select_multiple_modifier !== 'undefined') {
    select_limit = -1;
  } else {
    select_multiple_modifier = "";
    select_limit = 1;
  }
  $(id).bind("loaded.jstree", function (event, data) {
    data.inst.open_all(-1);
  }).jstree({
    "core" : {
      "animation" : 0,
      "html_titles" : true
    },
    "ui" : {
      "initially_select" : initially_select,
      "select_limit" : select_limit,
      "select_multiple_modifier" : select_multiple_modifier
    },
    "types" : {
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "valid_children" : [ "root-category" ],
      "types" : {
        "root-category" : {
          "icon" : { "image" : "images/tree/folder_16x16.png" },
          "valid_children" : [ "category", "group" , "special_target" ],
          "start_drag" : false,
          "select_node" : false
        },
        "category" : {
          "icon" : { "image" : "images/tree/folder_16x16.png" },
          "valid_children" : [ "category", "group" , "special_target" ],
          "select_node" : false
        },
        "group" : {
          "icon" : { "image" : "images/tree/server_group_16x16.gif" },
          "valid_children" : "none"
        },
        "special_target" : {
          "icon" : { "image" : "images/tree/special_target_16x16.gif" },
          "valid_children" : "none"
        },
        "default" : {
          "valid_children" : "none"
        }
      }
    },
    "crrm" : {
      "move" : {
        "check_move" : function (m) {
          //only accept "inside" node move (yes, comparing m.p == "inside" does not work)
          //and into a new parent node.
          return (m.p != "before" && m.p != "after" && this._get_parent(m.o)[0] !== m.np[0]);
        }
      }
    },
    "dnd" : {
      "drop_target" : false,
      "drag_target" : false
    },
    "themes" : {
  	  "theme" : "rudder",
  	  "url" : "javascript/jstree/themes/rudder/style.css"
    },
    "plugins" : [ "themes", "html_data", "ui", "types", "dnd", "crrm" ]
    });
}

/*
 * Directive management
 * NOTE: all children are set to none because
 *       we don't want/have to allow node move -
 *       that tree is read only.
 */
var buildTechniqueDependencyTree = function(id, initially_select) {
  jQuery(id).
    bind("loaded.jstree", function (event, data) {
      data.inst.open_all(-1);
    }).jstree({
      "core" : {
      "animation" : 0,
      "html_titles" : true
      },
     "ui" : {
        "initially_select" : [initially_select],
        "select_limit" : 1
      },
      "types" : {
        // I set both options to -2, as I do not need depth and children count checking
        // Those two checks may slow jstree a lot, so use only when needed
        "max_depth" : -2,
        "max_children" : -2,
        "valid_children" : [ "category" ],
          "types" : {
            "category" : {
              "icon" : {
                "image" : "images/tree/folder_16x16.png"
              },
              "valid_children" : [ "category", "template" ]
            },
            "template" : {
              "icon" : {
                "image" : "images/tree/technique_16x16.png"
              },
              "valid_children" : [ "directive" ]
            },
            "directive" : {
              "icon" : {
                "image" : "images/tree/directive_16x16.gif"
              },
              "valid_children" : [ "rule" ]
            },
            "rule" : {
                "icon" : {
                  "image" : "images/tree/configuration_rule_16x16.png"
                },
                "valid_children" : "none"
             },
            "default" : {
              "valid_children" : "none"
            }
          }
        },
        "themes" : {
      	  "theme" : "rudder",
      	  "url" : "javascript/jstree/themes/rudder/style.css"
        },
      "plugins" : [ "themes", "html_data", "ui", "types"]
    })
}

var buildRulePIdepTree = function(id, initially_select) {
  jQuery(id).
    bind("loaded.jstree", function (event, data) {
      data.inst.open_all(-1);
    }).jstree({
      "core" : {
        "animation" : 0,
        "html_titles" : true
      },
      "ui" : {
        "select_limit" : -1,
        "select_multiple_modifier" : "on",
        "selected_parent_close" : false,
        "initially_select" : initially_select
      },
      // I set both options to -2, as I do not need depth and children count checking
      // Those two checks may slow jstree a lot, so use only when needed
      "max_depth" : -2,
      "max_children" : -2,
      "types" : {
        "valid_children" : [ "category" ],
        "types" : {
          "category" : {
            "icon" : {
              "image" : "images/tree/folder_16x16.png"
            },
            "valid_children" : [ "category", "template" ],
            "select_node" : false
          },
          "template" : {
            "icon" : {
              "image" : "images/tree/technique_16x16.png"
            },
            "valid_children" : [ "directive" ],
            "select_node" : false
          },
          "directive" : {
            "icon" : {
              "image" : "images/tree/directive_16x16.gif"
            },
            "valid_children" : "none"
          },
          "default" : {
            "valid_children" : "none"
          }
        }
      },
      "themes" : {
    	  "theme" : "rudder",
    	  "url" : "javascript/jstree/themes/rudder/style.css"
      },
      "plugins" : [ "themes", "html_data", "ui", "types"]
    })
}

<|endoftext|>


<commit_before>import { Feature } from 'toolkit/core/feature';
import * as toolkitHelper from 'toolkit/helpers/toolkit';

export class CheckCreditBalances extends Feature {
  budgetView = null;

  injectCSS() {
    return require('./index.css');
  }

  shouldInvoke() {
    return toolkitHelper.getCurrentRouteName().indexOf('budget') !== -1;
  }

  invoke() {
    if (this.currentYear === 0 || this.currentMonth === 0) {
      this.onMonthChanged(toolkitHelper.getCurrentBudgetMonth());
    }

    if (this.inCurrentMonth()) {
      let debtAccounts = this.getDebtAccounts();

      if (debtAccounts !== null) {
        this.processDebtAccounts(debtAccounts);
      }
    } else {
      $('.toolkit-rectify-difference').remove();
    }
  }

  observe(changedNodes) {
    if (!this.shouldInvoke()) return;

    if (changedNodes.has('navlink-budget active') ||
        changedNodes.has('budget-table-cell-available-div user-data') ||
        changedNodes.has('budget-inspector') ||
        changedNodes.has('budget-table-row is-sub-category is-debt-payment-category is-checked') ||
        changedNodes.has('budget-header-totals-cell-value user-data')) {
      this.invoke();
    }
  }

  onBudgetChanged() {
    this.budgetView = null;
  }

  onRouteChanged() {
    if (!this.shouldInvoke()) return;

    this.invoke();
  }

  inCurrentMonth() { // check for current month or future month
    let today = new Date();
    let budgetDate = toolkitHelper.getCurrentBudgetDate();

    // check for current month or future month
    // must subtract 1 from budget month because the Date object is zero based.
    return budgetDate.month - 1 >= today.getMonth() && budgetDate.year >= today.getYear();
  }

  getDebtAccounts() {
    // After using Budget Quick Switch, budgetView needs to be reset to the new budget. The try catch construct is necessary
    // because this function can be called several times during the budget switch process.
    if (this.budgetView === null || this.budgetView.categoriesViewModel === null) {
      try {
        this.budgetView = toolkitHelper.getAllBudgetMonthsViewModelResult();
      } catch (e) {
        return null;
      }
    }

    let categoryEntityId = this.budgetView
      .categoriesViewModel.debtPaymentMasterCategory.entityId;

    let debtAccounts = this.budgetView
      .categoriesViewModel.subCategoriesCollection
      .findItemsByMasterCategoryId(categoryEntityId);

    return debtAccounts || [];
  }

  processDebtAccounts(debtAccounts) {
    let foundButton = false;
    let _this = this;
    debtAccounts.forEach(function (a) {
      // Not sure why but sometimes on a reload (F5 or CTRL-R) of YNAB, the accountId field is null which if not handled
      // throws an error and kills the feature.
      if (a.accountId !== null) {
        let account = _this.budgetView
          .sidebarViewModel.accountCalculationsCollection
          .findItemByAccountId(a.accountId);
        let currentMonth = moment(ynabToolKit.shared.parseSelectedMonth()).format('YYYY-MM');
        let balance = account.clearedBalance + account.unclearedBalance;
        let monthlyBudget = _this.budgetView
          .monthlySubCategoryBudgetCalculationsCollection
          .findItemByEntityId('mcbc/' + currentMonth + '/' + a.entityId);

        let available = 0;
        if (monthlyBudget) {
          available = monthlyBudget.balance;
        }

        // ensure that available is >= zero, otherwise don't update
        if (available >= 0) {
          // If cleared balance is positive, bring available to 0, otherwise
          // offset by the correct amount
          let difference = 0;
          if (balance > 0) {
            difference = (available * -1);
          } else {
            difference = ((available + balance) * -1);
          }

          foundButton |= _this.updateInspectorButton(a.name, difference);

          if (available !== (balance * -1)) {
            _this.updateRow(a.name);
            _this.updateInspectorStyle(a.name);
          }
        }
      }
    });

    if (!foundButton) {
      $('.toolkit-rectify-difference').remove();
    }
  }

  updateRow(name) {
    let rows = $('.is-sub-category.is-debt-payment-category');
    rows.each(function () {
      let accountName = $(this).find('.budget-table-cell-name div.button-truncate')
                               .prop('title')
                               .match(/.[^\n]*/)[0]; // strip the Note string

      if (name === accountName) {
        let categoryBalance = $(this).find('.budget-table-cell-available-div .user-data.currency');
        categoryBalance.removeClass('positive zero');
        if (!categoryBalance.hasClass('negative')) {
          $(this).find('.budget-table-cell-available-div .user-data.currency').addClass('cautious toolkit-pif-cautious');
        }
      }
    });
  }

  updateInspectorStyle(name) {
    let inspectorName = $('.inspector-category-name.user-data').text().trim();
    if (name === inspectorName) {
      let inspectorBalance = $('.inspector-overview-available .user-data .user-data.currency');
      inspectorBalance.removeClass('positive zero');
      if (!inspectorBalance.hasClass('negative')) {
        $('.inspector-overview-available .user-data .user-data.currency, .inspector-overview-available dt').addClass('cautious toolkit-pif-cautious');
      }
    }
  }

  updateInspectorButton(name, difference) {
    let inspectorName = $('.inspector-category-name.user-data').text().trim();

    if (name && name === inspectorName) {
      let fDifference = ynabToolKit.shared.formatCurrency(difference);
      let positive = '';
      if (ynab.unformat(difference) >= 0) {
        positive = '+';
      }

      let button = $('.toolkit-rectify-difference');
      if (!button.length) {
        button = $('<a>', {
          class: 'budget-inspector-button toolkit-rectify-difference'
        })
          .css({
            'text-align': 'center',
            'line-height': '30px',
            display: 'block',
            cursor: 'pointer'
          })
          .click(function () {
            this.updateCreditBalances($(this).data('name'), $(this).data('difference'));
          });

        $('.inspector-quick-budget').append(button);
      }

      button
        .data('name', name)
        .data('difference', difference)
        .empty()
        .append(((ynabToolKit.l10nData && ynabToolKit.l10nData['toolkit.checkCreditBalances']) || 'Rectify Difference:'))
        .append(' ' + positive)
        .append($('<strong>', { class: 'user-data', title: fDifference })
          .append(ynabToolKit.shared.appendFormattedCurrencyHtml($('<span>', { class: 'user-data currency zero' }), difference)));

      if (difference !== 0) {
        button.removeAttr('disabled');
      } else {
        button.attr('disabled', true);
      }

      return true;
    }
    return false;
  }

  updateCreditBalances(name, difference) {
    // eslint-disable-next-line no-alert
    if (ynabToolKit.options.QuickBudgetWarning && (!confirm('Are you sure you want to do this?'))) {
      return;
    }

    let debtPaymentCategories = $('.is-debt-payment-category.is-sub-category');

    $(debtPaymentCategories).each(function () {
      let accountName = $(this).find('.budget-table-cell-name div.button-truncate')
                               .prop('title')
                               .match(/.[^\n]*/)[0];
      if (accountName === name) {
        let input = $(this).find('.budget-table-cell-budgeted div.currency-input').click()
                           .find('input');

        let oldValue = input.val();

        // If nothing is budgeted, the input will be empty
        oldValue = oldValue || 0;

        // YNAB stores values *1000 for decimal places, so just
        // multiple by 1000 to get the actual amount.
        let newValue = (ynab.unformat(oldValue) * 1000 + difference);

        // format the calculated value back to selected number format
        input.val(ynab.formatCurrency(newValue));

        if (ynabToolKit.options.warnOnQuickBudget === 0) {
          // only seems to work if the confirmation doesn't pop up?
          // haven't figured out a way to properly blur otherwise
          input.blur();
        }
      }
    });
  }
}
<commit_msg>Fixed Rectify button for feature check-credit-balances<commit_after>import { Feature } from 'toolkit/core/feature';
import * as toolkitHelper from 'toolkit/helpers/toolkit';

export class CheckCreditBalances extends Feature {
  budgetView = null;

  injectCSS() {
    return require('./index.css');
  }

  shouldInvoke() {
    return toolkitHelper.getCurrentRouteName().indexOf('budget') !== -1;
  }

  invoke() {
    if (this.currentYear === 0 || this.currentMonth === 0) {
      this.onMonthChanged(toolkitHelper.getCurrentBudgetMonth());
    }

    if (this.inCurrentMonth()) {
      let debtAccounts = this.getDebtAccounts();

      if (debtAccounts !== null) {
        this.processDebtAccounts(debtAccounts);
      }
    } else {
      $('.toolkit-rectify-difference').remove();
    }
  }

  observe(changedNodes) {
    if (!this.shouldInvoke()) return;

    if (changedNodes.has('navlink-budget active') ||
        changedNodes.has('budget-table-cell-available-div user-data') ||
        changedNodes.has('budget-inspector') ||
        changedNodes.has('budget-table-row is-sub-category is-debt-payment-category is-checked') ||
        changedNodes.has('budget-header-totals-cell-value user-data')) {
      this.invoke();
    }
  }

  onBudgetChanged() {
    this.budgetView = null;
  }

  onRouteChanged() {
    if (!this.shouldInvoke()) return;

    this.invoke();
  }

  inCurrentMonth() { // check for current month or future month
    let today = new Date();
    let budgetDate = toolkitHelper.getCurrentBudgetDate();

    // check for current month or future month
    // must subtract 1 from budget month because the Date object is zero based.
    return budgetDate.month - 1 >= today.getMonth() && budgetDate.year >= today.getYear();
  }

  getDebtAccounts() {
    // After using Budget Quick Switch, budgetView needs to be reset to the new budget. The try catch construct is necessary
    // because this function can be called several times during the budget switch process.
    if (this.budgetView === null || this.budgetView.categoriesViewModel === null) {
      try {
        this.budgetView = toolkitHelper.getAllBudgetMonthsViewModelResult();
      } catch (e) {
        return null;
      }
    }

    let categoryEntityId = this.budgetView
      .categoriesViewModel.debtPaymentMasterCategory.entityId;

    let debtAccounts = this.budgetView
      .categoriesViewModel.subCategoriesCollection
      .findItemsByMasterCategoryId(categoryEntityId);

    return debtAccounts || [];
  }

  processDebtAccounts(debtAccounts) {
    let foundButton = false;
    let _this = this;
    debtAccounts.forEach(function (a) {
      // Not sure why but sometimes on a reload (F5 or CTRL-R) of YNAB, the accountId field is null which if not handled
      // throws an error and kills the feature.
      if (a.accountId !== null) {
        let account = _this.budgetView
          .sidebarViewModel.accountCalculationsCollection
          .findItemByAccountId(a.accountId);
        let currentMonth = moment(ynabToolKit.shared.parseSelectedMonth()).format('YYYY-MM');
        let balance = account.clearedBalance + account.unclearedBalance;
        let monthlyBudget = _this.budgetView
          .monthlySubCategoryBudgetCalculationsCollection
          .findItemByEntityId('mcbc/' + currentMonth + '/' + a.entityId);

        let available = 0;
        if (monthlyBudget) {
          available = monthlyBudget.balance;
        }

        // ensure that available is >= zero, otherwise don't update
        if (available >= 0) {
          // If cleared balance is positive, bring available to 0, otherwise
          // offset by the correct amount
          let difference = 0;
          if (balance > 0) {
            difference = (available * -1);
          } else {
            difference = ((available + balance) * -1);
          }

          foundButton |= _this.updateInspectorButton(a.name, difference);

          if (available !== (balance * -1)) {
            _this.updateRow(a.name);
            _this.updateInspectorStyle(a.name);
          }
        }
      }
    });

    if (!foundButton) {
      $('.toolkit-rectify-difference').remove();
    }
  }

  updateRow(name) {
    let rows = $('.is-sub-category.is-debt-payment-category');
    rows.each(function () {
      let accountName = $(this).find('.budget-table-cell-name div.button-truncate')
                               .prop('title')
                               .match(/.[^\n]*/)[0]; // strip the Note string

      if (name === accountName) {
        let categoryBalance = $(this).find('.budget-table-cell-available-div .user-data.currency');
        categoryBalance.removeClass('positive zero');
        if (!categoryBalance.hasClass('negative')) {
          $(this).find('.budget-table-cell-available-div .user-data.currency').addClass('cautious toolkit-pif-cautious');
        }
      }
    });
  }

  updateInspectorStyle(name) {
    let inspectorName = $('.inspector-category-name.user-data').text().trim();
    if (name === inspectorName) {
      let inspectorBalance = $('.inspector-overview-available .user-data .user-data.currency');
      inspectorBalance.removeClass('positive zero');
      if (!inspectorBalance.hasClass('negative')) {
        $('.inspector-overview-available .user-data .user-data.currency, .inspector-overview-available dt').addClass('cautious toolkit-pif-cautious');
      }
    }
  }

  updateInspectorButton(name, difference) {
    let inspectorName = $('.inspector-category-name.user-data').text().trim();

    if (name && name === inspectorName) {
      let fDifference = ynabToolKit.shared.formatCurrency(difference);
      let positive = '';
      if (ynab.unformat(difference) >= 0) {
        positive = '+';
      }

      let button = $('.toolkit-rectify-difference');
      if (!button.length) {
        button = $('<a>', {
          class: 'budget-inspector-button toolkit-rectify-difference'
        })
          .css({
            'text-align': 'center',
            'line-height': '30px',
            display: 'block',
            cursor: 'pointer'
          })
          .click(this.updateCreditBalances);

        $('.inspector-quick-budget').append(button);
      }

      button
        .data('name', name)
        .data('difference', difference)
        .empty()
        .append(((ynabToolKit.l10nData && ynabToolKit.l10nData['toolkit.checkCreditBalances']) || 'Rectify Difference:'))
        .append(' ' + positive)
        .append($('<strong>', { class: 'user-data', title: fDifference })
          .append(ynabToolKit.shared.appendFormattedCurrencyHtml($('<span>', { class: 'user-data currency zero' }), difference)));

      if (difference !== 0) {
        button.removeAttr('disabled');
      } else {
        button.attr('disabled', true);
      }

      return true;
    }
    return false;
  }

  updateCreditBalances() {
    // eslint-disable-next-line no-alert
    if (ynabToolKit.options.QuickBudgetWarning && (!confirm('Are you sure you want to do this?'))) {
      return;
    }

    let name = $(this).data('name');
    let difference = $(this).data('difference');
    let debtPaymentCategories = $('.is-debt-payment-category.is-sub-category');

    $(debtPaymentCategories).each(function () {
      let accountName = $(this).find('.budget-table-cell-name div.button-truncate')
                               .prop('title')
                               .match(/.[^\n]*/)[0];
      if (accountName === name) {
        let input = $(this).find('.budget-table-cell-budgeted div.currency-input').click()
                           .find('input');

        let oldValue = input.val();

        // If nothing is budgeted, the input will be empty
        oldValue = oldValue || 0;

        // YNAB stores values *1000 for decimal places, so just
        // multiple by 1000 to get the actual amount.
        let newValue = (ynab.unformat(oldValue) * 1000 + difference);

        // format the calculated value back to selected number format
        input.val(ynab.formatCurrency(newValue));

        if (ynabToolKit.options.warnOnQuickBudget === 0) {
          // only seems to work if the confirmation doesn't pop up?
          // haven't figured out a way to properly blur otherwise
          input.blur();
        }
      }
    });
  }
}
<|endoftext|>


<commit_before>import { ListPackage } from 'substance'
import InternalArticleSchema from '../InternalArticleSchema'

const ToggleListCommand = ListPackage.ToggleListCommand

export default class SchemaAwareToggleListCommand extends ToggleListCommand {
  getCommandState (params) {
    let commandState = super.getCommandState(params)
    // Note: in addition to the regular ListToggleCommand
    // this one checks the schema if it is ok to insert a <list> at the current position
    if (commandState.action === 'switchTextType') {
      let editorSession = params.editorSession
      let sel = params.selection
      let doc = editorSession.getDocument()
      let path = sel.path
      let node = doc.get(path[0])
      let parentNode = node.parentNode
      if (parentNode) {
        let elementSchema = InternalArticleSchema.getElementSchema(parentNode.type)
        if (elementSchema.isAllowed('list')) {
          return commandState
        }
      }
    } else {
      return commandState
    }
    // otherwise
    return { disabled: true }
  }
}
<commit_msg>Fix regression in SchemaAwareToggleListCommand.<commit_after>import { ListPackage } from 'substance'

const ToggleListCommand = ListPackage.ToggleListCommand

export default class SchemaAwareToggleListCommand extends ToggleListCommand {
  getCommandState (params) {
    let commandState = super.getCommandState(params)
    // Note: in addition to the regular ListToggleCommand
    // this one checks the schema if it is ok to insert a <list> at the current position
    if (commandState.action === 'switchTextType') {
      let editorSession = params.editorSession
      let sel = params.selection
      let doc = editorSession.getDocument()
      let path = sel.path
      let node = doc.get(path[0])
      let parentNode = node.parentNode
      if (parentNode) {
        let elementSchema = parentNode.constructor._elementSchema
        if (elementSchema) {
          if (elementSchema.isAllowed('list')) {
            return commandState
          }
        }
      }
    } else {
      return commandState
    }
    // otherwise
    return { disabled: true }
  }
}
<|endoftext|>