StackOverflow Sorting is Broken

StackOverflow sorting sucks.

  1. The accepted answer is always on top. This is a joke. The asker of the question usually accepts the first best thing and then heads off. Thousands of people to come will then see the first best answer on top. For example: https://stackoverflow.com/questions/16267339/s3-static-website-hosting-route-all-paths-to-index-html . How ridiculous is that?
  2. Below the accepted answer, it’s sorted by upvotes. That system is also broken, because new answers will have a very hard time of getting more upvotes.

The solution? A smart sorting algorithm, like on Quora or Reddit.

There’s an ongoing discussion on StackOverflow about this:

https://meta.stackoverflow.com/questions/326095/please-unpin-the-accepted-answer-from-the-top

https://meta.stackoverflow.com/questions/283456/order-highest-upvoted-answer-before-accepted-answer

So, StackOverflow, are you ever going to change this?

What’s up with Angular Universal?

I was excited when I heard Angular 2 would support server-side rendering since SEO was a huge PITA (pain in the ass) with Angular 1. It was said that server-side rendering would be possible through Angular Universal.

Yet, this Angular Universal thing, what’s up with that? Seems to have a really small team on that and there doesn’t really seem to be any documentation. Well at least there’s a getting started repo, so I thought. However, this repo (https://github.com/robwormald/ng-universal-demo) doesn’t even have a readme…

Also, when you check out some of those files, they don’t seem very professional. For example: https://github.com/robwormald/ng-universal-demo/blob/master/src/express-engine.ts

First line of code: //hacky express wrapper thingy.

Seriously?

Then of course, there’s also some confusion as to where to go and look for resources. You’ll find quite a few.

When you just google “Angular Universal” (as of September 2017) you’ll get to https://universal.angular.io/. However, this page is a bit out of date.

Just have a look at the date:

Or the actual site:

Angular 2 is now Angular 4 and --ambient is also not a thing anymore. So the only purpose of universal.angular.io is to confuse people with outdated material and to link to github (https://github.com/angular/universal).

Github, even though being the best resource on Angular Universal, isn’t really documented either. Meh.

Well, I guess switching to React isn’t such a bad idea after all?

PS: I wrote this article in May 2017, I’ve checked again in September and now, even though the docs are still a mess, there’s a working demo here: https://github.com/angular/universal-starter/tree/master/cli

5 Funny Computer Science Jokes

Why do Java programmers wear glasses?

Because they can’t C#.

SQL

A SQL query goes into a bar, walks up to two tables and asks, “Can I join you?”

3 guys

A physicist, an engineer and a programmer are on a steep mountain passage, when suddenly the breaks stop functioning. After some shouting and near death experiences, they finally manage to bring the car to a halt. The physicist says “Let’s check the temperature on the breaks and test the friction, maybe then we can figure out what went wrong.”. The engineer goes “Let me just get some straps, I can fix it”. The programmer just gently shakes his head. Then he goes “Guys that’s not how it works. Let’s first do it again and check if it’s reproducible!”.

OOP Joke

Q: What’s the object oriented way to become rich?
A: Inheritance

[“hip”, “hip”]

(hip hip, array!)

I can’t see my <hr> tag (horizontal line), where did it go?

If you can’t see your <hr> tag, your best bet might be that it somehow got display: flex . This will cause the hr to have width 0. Test it by giving it the style <hr style="width: 100%"> and see whether this solves your problem. For example, if you use an Angular Material Design Card md-card, they use display:flex for the card, so hr’s won’t show up.

Here’s a little code snippet to illustrate:

<!-- notice the red dot in the middle? it's the hr -->
<div style="display: flex; border: 1px solid red">
 <hr style="border: 1px solid red">
</div>

<br>

<!-- with width 100% it's normal again -->
<div style="display: flex; border: 1px solid blue">
 <hr style="width: 100%">
</div>

and here’s the corresponding fiddle: https://jsfiddle.net/f327rq20/

UIB (Bootstrap) Component Modals Made Easy

So UIB decided to support “component modals”. Unfortunately, the way I see it, the components need to be “dirtied” with the modal logic, meaning you will also need to include resolve and close in every component you want to display as a modal. Inside the components constructor or $onInit you then proceed to “resolve the resolve” (i.e. if(resolve){ this.myBinding = this.resolve.myBinding; ... }) which is quite annoying. Why isn’t it possible to JUST WRAP A COMPONENT IN A MODAL? So that’s what I set out to do: I created a wrapper-modal-component for my modal-components.

The idea behind was, to abstract away the modal logic from the component logic. Most of the component doesn’t need to know that it’s wrapped by a modal.

Untitled drawing (22)

Now in this sketch, the inner component functionality, doesn’t need to know ANYTHING about the modal. The only thing where it might be useful to be aware that it’s a component, is the UPDATE button, since you might want to close the modal after the update. But you can easily and beautifully do this by emitting an event.

But first things first. So I thought what’s the minimal information that a component-modal-opener requires? I.e. openModal, what does it need to know?

  1. It needs to know the name of the modal
  2. It needs to know the bindings, in case there are any

So an implementation of `openModal` could look something like this:

public openComponentModal (componentName: string, bindings?) {

  let resolve = {
    component: () => {
      return componentName;
    },
    bindings: () => {
      return bindings;
    }
  };

  return this.$uibModal.open({
    animation: true,
    component: 'modal',
    resolve: resolve
  });

}

Okay, so what happened here? Lets say this is in my Utils service, so from now on, I can always open modals just with e.g.

this.Utils.openComponentModal('my-component', {
  bindingOne: this.bindingOne,
  bindingTwo: this.bindingTwo
  ...
});

Handy, isn’t it? The modals will look consistent across your app, and the component isn’t spoiled with modal logic. But how is this achieved?

Notice how I DON’T open my-component directly, but instead I open the component modal. The component modal is where the magic happens and it looks like this:

Controller:

@Component('myApp', 'modal', {
  templateUrl: '/components/directives/modal/modal-component.html',
  bindings: {
    resolve: "<",
    close: "&"
  }
})
class ModalComponent {

  public resolve;
  public close;

  static $inject: string[] = ['Utils', '$compile', '$scope', '$log'];

  constructor(
    private Utils: Utils,
    private $compile,
    private $scope,
    private $log: ILogService
  ) {}

  public style;

  $onInit() {

    this.initModal();
    this.initCloseButton();

    this.$scope.$on(EmitEvents.MODAL_CLOSE, () => {
      this.close();
    });

  }

  private initModal() {
    if (this.resolve && this.resolve.component) {
      let bindingsString = (bindings): string => {
        let str = "";
        if (bindings) {
          for (var property in bindings) {
            if (bindings.hasOwnProperty(property)) {
              str += " " + this.Utils.camelCaseToDash(property) + "=\"$ctrl." + property + "\"";
              this[property] = bindings[property];
            }
          }
        }
        return str;
      };

      let completeString = `<${this.resolve.component}` + bindingsString(this.resolve.bindings) +`><${this.resolve.component}>`;
      let compiledHtml = this.$compile(completeString)(this.$scope);
      $('#tb-modal').html(compiledHtml);
    } else {
      this.$log.error("Modal not correctly initialized");
    }
  };

  private initCloseButton() {

    this.style = {
      position: 'absolute',
      top: '-20px',
      right: '8px',
      'font-size': 35 + 'px',
      'z-index': 1000,
      color: this.Utils.primaryColor
    };

  }

  public open

}

View:

<div class='modal-wrapper'>
  
  <div style="position: relative">
    <button ng-click="$ctrl.close()" ng-style="$ctrl.style">
      <span style="position: relative">
        <i class="fa fa-circle" aria-hidden="true" style="position: absolute; color: {{$ctrl.color}}"></i>
        <i class="fa fa-times" aria-hidden="true" style="position: absolute; color: white; font-size: 20px; top: 7px; left: 7px;"></i>
      </span>
    </button>
  </div>
  
  
  <div id="tb-modal"></div>
  
</div>

Uff, pretty crazy. But the beauty about it is, that the crazyness is abstracted away in an isolated component. All the other things left and right of it are left untouched. So the crazyness quickly explained:

  1. The view has simply a close button and a div which is replaced with the actual component by jquery
  2. The controller takes a resolve from uib.resolve, resolves it, and compiles the component.
  3. The controller binds to an emit event.

Now, if e.g. the UPDATE button in the component should close the modal, you simply make it run:

this.$scope.$emit(EmitEvents.MODAL_CLOSE);

Meaning the component is still coupled to a modal, but much more lightly than before.

I hope this gets you started with your modal-wrapper-component. 🙂

Bootstrapping an Angular 1.5 Component with Typescript

Angular 1.5 introduces the “Component” concept in order to get closer to Angular 2. By now you might have started to use typescript in your project, but upgrading to Angular 2 was too big of a step. However, you can start writing “Components” in an exact-angular2-style. Here’s what you’ve got to do.

First of all you’re going to need the following code to make annotations work:

//component.ts
function Component(moduleOrName: string | ng.IModule, selector: string, options: {
  controllerAs?: string,
  template?: string,
  templateUrl?: string,
  bindings?: any
}) {
  return (controller: Function) => {
    var module = typeof moduleOrName === "string"
        ? angular.module(moduleOrName)
        : moduleOrName;
    module.component(selector, angular.extend(options, { controller: controller }));
  }
}

This will allow you to use annotations to define components.

A ready-to-use component can then be generated with the following scripts:

#creates skeletton
#argument: name in any case e.g. bla-bla or blaBla or BlaBla

pascalcase="$(node changecase.js ${1} pascalCase)"
paramcase="$(node changecase.js ${1} paramCase)"
camelcase="$(node changecase.js ${1} camelCase)"

mkdir WebContent/components/directives/${paramcase}

echo "
@Component('taskbaseApp', '${camelcase}', {
  templateUrl: '/components/directives/${paramcase}/${paramcase}-directive.html',
  bindings: {
    somebinding: \"<\" // One Way Binding
  }
})
class ${pascalcase} {

  public somebinding: string;
  static \$inject: string[] = ['Utils'];

  constructor(private Utils) {}

  public sayHello() {
    console.log('hi')
  }

}
" >> WebContent/components/directives/${paramcase}/${paramcase}-directive.ts


echo "<div class='${paramcase}-wrapper'>

  <button class=\"btn btn-default\" ng-click=\"\$ctrl.sayHello()\">Hello {{\$ctrl.somebinding}}</button>

</div>" >> WebContent/components/directives/${paramcase}/${paramcase}-directive.html


# Compile
cd WebContent/components && tsc

echo "Usage:

<${paramcase} somebinding=\"'World'\" ></${paramcase}>

"

and

//changecase.js
var changeCase = require('change-case');

var caseType = process.argv[3];
var inpt = process.argv[2];
console.log(changeCase[caseType](inpt));

Note: You need to `npm install changecase –save` in order for the scripts to run first.

That’s all.

Long to Base64 and Base64 to Long in Java

The following code converts a base64 String to a long and vice versa.

private static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
public static String encodeBase64(long v) {
    char[] a = alphabet.toCharArray();
    v = Math.abs(v);
    String s = "";
    for (int i = 0; i < 11; i++) {
        long val = v & 63;
        s = a[(int) val] + s;
        v >>= 6;
    }
    while (s.startsWith("A") && s.length() > 1)
        s = s.substring(1, s.length());
    return s;
}
public static long decodeBase64(String s) {
    char[] a = alphabet.toCharArray();
    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0; i < a.length; i++)
        map.put(a[i], i);
    char[] chars = s.toCharArray();
    long v = 0;
    for (char c : chars) {
        v <<= 6;
        v = v | map.get(c);
    }
    return v;
}

Get an A+ rating in SSL Labs

Get Certificate from Letsencrypt

sudo apt-get -y install git bc
sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
./letsencrypt-auto certonly --standalone --email yourmail@gmail.com -d www.example.com

Strong Diffie-Hellman

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Link to SSL Certificate / Key

cd /etc/nginx
mkdir ssl
cd ssl
ln -s /etc/letsencrypt/live/www.example.com/privkey.pem nginx.key
ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem taskbaSe.crt

Use the following in your nginx conf

server {
 listen 80;
 server_name taskba.se;
 return 301 https://$host$request_uri;
}

server {
 listen 443 ssl;
 client_max_body_size 20M;
 server_name www.example.com;
 ssl_certificate /etc/nginx/ssl/nginx.crt;
 ssl_certificate_key /etc/nginx/ssl/nginx.key;
 
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_prefer_server_ciphers on;
 ssl_dhparam /etc/ssl/certs/dhparam.pem;
 ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
 ssl_session_timeout 1d;
 ssl_session_cache shared:SSL:50m;
 ssl_stapling on;
 ssl_stapling_verify on;
 add_header Strict-Transport-Security max-age=15768000;
}