Manage States between Routes in Angular

I use ui-router (https://github.com/angular-ui/ui-router) to route the url to state. For each state, we can specify the controller and the view. When transitioning from one state to another, we need to pass some data.

The way to specify a state is

$stateProvider.state('StateName', {
    url: 'request url',
    templateUrl: 'html file path'
})

There are a few ways to pass data to the state.

  1. Set the parameter in the url. For example, "contacts/{contactId}".  And use $stateParams to get the value. For example, $stateParams.contactId.
  2. In some cases, we don't want to specify parameters in url. Then we still can specify parameters in the state. e.g.
$stateProvider.state('StateName', {
    url: 'request url',
    params: {
       param1: null,
       param2: null
    },
    templateUrl: 'html file path'

Then you still can use $stateParams.param1 or $stateParams.param2 to get the values.
The way to set the parameter is:

$state.go('StateName', {param1: 'params Value'});

That's it. We can pass various parameters to the same url and the state should be able to handle it.

My First Cordova Project

I developed a mobile app recently. VS is an excellent tool in managing the project and debugging. I would like to start from setting up the project in VS, followed by my experience in my mobile development journey.

The app is a bookkeeping of your investment. Your investment can be in the brokerage account, retirement account or HSA. Besides bookkeeping, it also calculates the rate of investment.

First of all, I use Visual Studio 2015 Community with Apache Cordova Tool. I chose to install Windows phone 10 SDK. You can install the Android emulator and the Android SDK. It's up to your target platform.

VS Installtion screenshot

Note that even though you just want to target Windows 10 and Windows Phone 10, you still need to install Windows Phone 8.1 Tools and SDKs. Otherwise you won't be able to debug it on your Windows 10 Phone. It complains that bin/arm/dbghelp.dll is not found and it comes with Windows Phone 8.1 Tools.

Framework can improve productivity and accelerate development. It provides the backbone of the application and glue all major parts together. I just need to follow the pattern and fill in the parts. I chose Ionic framework.

What UI is suitable for this app? Ionic provides some templates: simple, tabs and side menu. I think side menu provides the largest real estate on the screen, while flexible in navigation.

It's easy to create an Ionic project in VS. In the "New Project" dialog, search Ionic in the Online tab, then download the one you like.

VS search Ionic template screenshot

After the template is downloaded, you need to re-open "New Project" dialog, and Ionic project templates are in the Installed tab.

VS new Ionic project screenshot

Since it's bookkeeping, it needs to persist the data. Sqlite is suitable in the mobile application. I found a plugin at GitHub (https://github.com/litehelpers/cordova-sqlite-ext.git).

In VS, open config.xml (View Designer), then add a custom plugin. Use the git repository and install it. VS Cordova add plugin screenshot

So far, I've set up the project.  The journey has started.

Setting Up CSF on VPS

I recently noticed my VPS is slow. The blog takes a long time to show me any content. When I log in vis SSH, I usually don't see what I type in immediately. The command is echoed a few minutes later.

I started my investigation. I ran 'top'. CPU doesn't run crazily. Memory isn't loaded heavily. There's no suspicious process. Everything looks good. But the connection is still slow! I asked the VPS provider. Hey, why is my VPS slow to respond when CPU and memory aren't overloaded? The support team took a look and responded to me with one IP address 191.96.249.54 that established many connections to my VPS. I then searched the IP address online and found this StackOverflow question (http://serverfault.com/questions/778831/how-to-block-an-attack-on-wordpress-using-ufw-on-ubuntu-server). It's an attack! Somebody suggested to use ipsest to add a blacklist. Probably that's the way to go, because when I looked at Apache log, there's also connection from 191.96.249.53. They're from the same organization.

I found the solution. I installed ipset to find out that it didn't run. I got this error:

ipset v6.11: Cannot open session to kernel.

Some articles online say it needs kernel patching. But I don't control kernel on my VPS. So I contacted my VPS provider again. We couldn't just upgrade the kernel. But they suggested me an alternative solution: CSF (http://www.configserver.com/cp/csf.html).

CSF can do what ipset does. I just need to use the blacklist. Besides, it can monitor user log in and inform you when somebody tries to log in in a short time to figure out the password. There are other protections too. All are documented in the readme file. The configuration file contains explanation for all options. It is a lot of information to digest and you have to make your own choice. I'll just put down some basic points:

  1. Set TESTING to 1 first. The value 1 will have CSF stop itself 5 minutes  after it's started. So when you accidentally lock yourself out, you still can gain access to your VPS after at most 5 minutes.  Remember to set it back to 0 when you've tested your configuration file.
  2. TCP_IN and UDP_IN are the ports that incoming connections are allowed to connect to. At least, put your SSH port number in TCP_IN so that you still can access  to your VPS.
  3. On my system, CSF can't find /usr/bin/host. It's in its log file. Remember to check the log file for any errors and fix them.
  4. csf.deny contains a list of IPs from where the incoming connection are dropped. It supports CIDR notation (https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation). I put the suspicious IP addresses in this file.

After CSF starts to run. There is no connection from the suspicious IPs any more from Apache log file. The connection to my VPS is fast again.

Translate in AngularJS

I'm using angular-translate and angular-translate-loader-partial to translate an AngularJS application. angular-translate provides directives, filters and a service to get texts translated. It provides a few ways to load translation files. angular-translate-loader-partial is one loader that allows you to load the necessary translation files when you need them. This is what I'm using right now. The document from https://angular-translate.github.io/ covers all of them. But there's a gap in the end to end scenario. The translation fails.

Here's the summary of what need to be done from the document:

    1. Tell the translate provider to use the partial loader and the translation file path pattern.
      $translateProvider.useLoader('$translatePartialLoader', {
          urlTemplate: '/i18n/{part}/{lang}.json'
      });

      urlTemplate tells the loader how to find the translation file. In this example, it's in /i18n/ directory. {part} will be provided later. {lang} is the language you use. It's set later too.

    2. Set the preferred language and fall back languages in your module configuration function. e.g.
      $translateProvider.preferredLanguage('zh_CN').fallbackLanguage('en_US');

      That tells the translate provider to look for translation for Simplified Chinese, and fall back to English if it's not found. This will set the {lang} for the loader.

    3. Load the translation file and refresh translation tables. This is done by
      $translatePartialLoader.addPart('contact');
      $translate.refresh();

      The translation file for 'contact' will be loaded. It sets the {part} in urlTemplate. So the translation file path is /i18n/contact/zh_CN.json.

      $translate.refresh() must be called every time a part is added. The document also suggests to refresh translation tables in event $translatePartialLoaderStructureChanged.

      app.run(function ($rootScope, $translate) {
        $rootScope.$on('$translatePartialLoaderStructureChanged', function () {
          $translate.refresh();
        });
      });

That seems straightforward. Everyone can add those code and start to use directives, filters or the service to translate their own applications. But that won't just work.

Both $translatePartialLoader.addPart() and $translate.refresh() are asynchronous. When you use directives, filters or the service to ask for translation for a given id, the translation table may not be loaded! This is what happens in my application. The document doesn't warn it, and doesn't present a solution either. The solution is simple, however. Both loadPart() and refresh() return promises. You have to ask $translate to get the translation after the promise refresh() is resolved.  So you can do something similar to:

$translate.refresh().then(function() {
    $translate('TRANSLATE_ID').then(function(data) {
        $scope.SomeLabel = data;
    });
});

This is tedious. Every time when you try to translate something, you have to double check whether the translation table is ready. And you cannot use directives and filters. Because when the translation table becomes ready, it won't update the directives and filters. Here's an example to demonstrate the solution: http://plnkr.co/edit/MrliEBMed17f3yqeRqz3

angular-translate is flexible in loaders and how to do translation (directives, filters or services). But there are some undocumented limitations (or bugs). When you use partial loader, you cannot use directives and filters. But at least, there's always another way of doing it. angular-translate still doesn't fail at getting the work done.

C# Variant on Struct

In C#, covariant and contravariant allow implicit conversion for generic type arguments. But they're not applied to struct or other value types including primitive type (except string) and enum.

Only an interface declaration can contain covariant and contravariant generic parameters.

A covariant allows to assign an object that is instantiated with a more derived type argument to an object that is instantiated with a less derived type argument. It's declared with keyword out with the generic type parameter. For example, this declares an interface with a covariant generic parameter: interface ICovariantInterface<out T>.

A contravariant does the reversed. It allows to assign an object that is instantiated with a less derived type argument to an object that is instantiated with a more derived type argument. It's declared with keyword in with the generic type parameter. For example, this declares an interface with a contravariant generic parameter: interface IContravariantInterface<in T>.

There are some built-in covariant and contravariant generic interfaces in C#, such as IEnumerable, IComparable.

Usually I would think that covariant in analogy to class hierarchy. It's similar to that a derived class can be assigned to a base class/interface. For contravariant, it's done in the opposite direction.

But we cannot use struct or other value types in covariant and contravariant. Both covariant and contravariant are applied to reference types. And reference types and value types have different memory layout.

So this is not allowed: IEnumerable<object> baseGeneric = new List<int>();.