philip { proplesch }

Atlassian Stash: Add Pull Request reviewers automatically

Though there are solutions to configure predefined Pull Request reviewers for a project in Stash, this might become handy for people without the permissions to configure such a thing.

// ==UserScript==
// @name       Set reviewers for a pull request in Stash
// @namespace  http://foo.bar/
// @version    0.1
// @description  
// @match      */projects/*/repos/*/pull-requests?create
// @copyright
// ==/UserScript==

document.getElementById('reviewers').value = 'johndoe|!|maxmustermann';    
alert('Reviewers added...');

You just have to add the user names of the reviewers separated by |!|.

This will also work as a bookmarklet.

AngularJS: Observe multiple variables with $watch()

If you want to observe a variable this can be done easily by using the $watch function.

$scope.$watch('foo', function(value) {
  // will be triggered when $scope.foo will be changed
});

In order to observe multiple properties all you need to do is concatenate them with a +.

$scope.$watch('foo + bar', function(value) {
  //  do something if $scope.foo or $scope.bar changes
});

ngRepeat without parent element

I'm working on an AngularJS-driven Single Page Application for a couple of months now and have to admit that it's a framework I really enjoy working with. That does not occur very often ;)

Enough warm words for now.


Imagine you want to repeat a list of a certain type (posts, comments, whatever).

With AngularJS you usually make use of the built-in ngRepeat directive as in the following example:

<article ng-repeat="post in posts">
  <h1 ng-bind="post.title" />
  <!-- ... -->
</article>

The ouput will look similar to this:

<article>
  <h1>Hello world!</h1>
  <!-- ... -->
</article>

<article>
  <h1>AngularJS is awesome!</h1>
  <!-- ... -->
</article>

<article>
  <h1>I see dead people :/</h1>
  <!-- ... -->
</article>

<!-- and so on... -->

As you might noticed the ngRepeat directive sits on the <article /> element which is great in most cases, but could be a problem if you don't have a parent element.

Let's take a definition list with the following markup:

<dl>
  <dt>Foo</dt>
  <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</dd>
  <dt>Bar</dt>
  <dd>Iste aperiam nesciunt enim dolorum dolores labore necessitatibus dolor?</dd>
</dl>

<dt /> and <dd /> are the elements that should be repeated now, but putting the ngRepeat on the <dl /> wouldn't make much sense because it will generate n separate lists (n = length of array).

Fortunately there's an app a solution for this in the framework :)

<dl>
  <dt ng-repeat-start="definition in definitions" ng-bind="definition.title"></dt>
  <dd ng-repeat-end="" ng-bind="definition.text"></dd>
</dl>

Et voilĂ ! See it in action on JSFiddle.

Use IIS pickup directory with Nodemailer

In the ASP.NET ecosystem I often make use of the IIS pickup directory. It's easy, it's free. Period.

When installing Ghost you will always get bothered by a message on the login screen saying something like mimimi... no smtp server configured.

Unfortunately Nodemailer, the mailing library used by Ghost, does not support my beloved pickup directory and a 3rd party service was not very satisfying. It's just a simple blog!

Well... I forked the repository and introduced a new transport object which stores the generated mail in a directory of your choice :)

Update

As of version 0.6.0 it is part of Nodemailer. Have a look at the README for details.

var transport = nodemailer.createTransport('PICKUP', {
  directory: 'path/to/mails'
});

// or

var transport = nodemailer.createTransport('PICKUP', 'path/to/mails');

Configure Ghost to use the pickup directory

After creating a backup and applying the necassary changes, this is how Ghosts's config.js looks on my machine:

production: {
  url: 'http://philipproplesch.de',
  mail: {
    transport: 'PICKUP',
    options: {                
      directory: 'path/to/mails'
    }
  },
  ...

Here is a mail that has been sent via the pickup directory after requesting a new password:

Password reset mail

Let Grunt install your dependencies

I am currently working on a Single Page Application and use Grunt for build and task automation. Since new dependencies are added from time to time (either through npm or bower), we also have to make sure that these are present on the CI server.

I am not a huge fan of configuring the build in multiple places (build script, CI server, here and there), therefore I have created the following tasks which make use of the exec method.

// http://gruntjs.com/creating-tasks#why-doesn-t-my-asynchronous-task-complete
var executeCommand = function(command, callback) {      
  var exec = require('child_process').exec;

  exec(command, function(error, stdout, stderr) {
    console.log(stdout);
    callback();
  });
};

grunt.registerTask('install-npm-dependencies', function() {
  var done = this.async();
  executeCommand('npm install', done);
});

grunt.registerTask('install-bower-dependencies', function() {
  var done = this.async();
  executeCommand('bower install', done);
});

Afterwards your can add them your actual build task.

grunt.registerTask('continous-build', [
  'install-npm-dependencies',
  'install-bower-dependencies',
  'build'
]);