Sunday, December 28, 2014

ui-grid / ng-grid 3.0 and double click row feature...

To my sad experience the comment that double click was not provided because of touch devices was a mistery. So after many hours with my limited knowledge found a way to add the double click with uiGrid v3.0.0. First your app.js file add the following directive:

directive('dblClickRow', [
    '$compile',
    function($compile, $parse, $log) {
      return {
        priority : -190, // run after default uiGridCell directive
        restrict : 'A',
        scope : false,
        link : function($scope, $elm, $attrs, $log) {
          if ($scope.grid.options.enableRowSelection && !$scope.grid.options.enableRowHeaderSelection) {
            $elm.addClass('ui-grid-disable-selection');
            registerRowSelectionEvents();
          }
          function registerRowSelectionEvents() {
            $elm.on('dblclick', function(evt) {
              $log.log("double click on row", evt);
            });
          }
        } };
    } ])    ;
Next you setup your grid with the following rowTemplate in your grid controller...
$templateCache.put('ui-grid/ui-grid-row',  
     + "<div " //
     + " ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\"" + " ui-grid-cell dbl-click-row></div>");
Next in your grid setup .... register the event and run with it ...
var selectedRow;
$scope.gridOptions.onRegisterApi = function(gridApi) {
  $scope.gridApi = gridApi;
  gridApi.selection.on.rowSelectionChanged($scope, function(row) {
    var msg = 'row selected ' + row.isSelected;
    if (row.isSelected) {
      selectedRow = row;
    }
    else {
      selectedRow = undefined;
    }
    $log.log(selectedRow);
  });
  gridApi.registerEvent('selection', 'dblClick');
  gridApi.selection.on.dblClick($scope, function() {
    if (selectedRow) {
      $scope.open(selectedRow.entity);
    }
  });
};

Wednesday, October 22, 2014

List All Perl Modules That Are Installed On My Current System

One liner:
perl -MFile::Find=find -MFile::Spec::Functions -Tlwe 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC'

Sunday, October 19, 2014

Refresh npm, bower, grunt and wiredep.

Somehow I feel that I messed up something in the course of development... so let's start over... :-)

Removal of NPM


rm -fr ~/.npm
sudo su - 
cd /usr/local/lib/node_modules
rm -fr *

Node Package Manager (npm)

http://nodejs.org/ Select the link to install npm and installation will commence based on your operating system.

Yeoman Scaffolding (yo)


$ sudo npm install --global yo
/usr/local/bin/yo -> /usr/local/lib/node_modules/yo/cli.js

> yo@1.3.2 postinstall /usr/local/lib/node_modules/yo
> yodoctor

[Yeoman Doctor] Everything looks all right!

npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/npm-package-arg requires semver@'4' but will load
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/semver,
npm WARN unmet dependency which is version 2.3.0
yo@1.3.2 /usr/local/lib/node_modules/yo
├── is-root@1.0.0
├── sudo-block@1.0.0
├── yeoman-doctor@1.0.0
├── fullname@1.0.0
├── opn@1.0.0
├── async@0.9.0
├── shelljs@0.3.0
├── underscore.string@2.3.3
├── lodash@2.4.1
├── string-length@1.0.0 (strip-ansi@2.0.0)
├── yeoman-character@1.0.0 (supports-color@1.2.0)
├── nopt@3.0.1 (abbrev@1.0.5)
├── findup@0.1.5 (colors@0.6.2, commander@2.1.0)
├── multiline@1.0.1 (strip-indent@1.0.0)
├── chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
├── yosay@1.0.0 (ansi-regex@1.1.0, ansi-styles@1.1.0, strip-ansi@2.0.0, pad-component@0.0.1, word-wrap@0.1.3, minimist@1.1.0, taketalk@0.1.1)
├── update-notifier@0.2.2 (is-npm@1.0.0, semver-diff@2.0.0, latest-version@1.0.0)
├── configstore@0.3.1 (object-assign@0.3.1, osenv@0.1.0, graceful-fs@3.0.4, uuid@1.4.2, mkdirp@0.5.0, js-yaml@3.0.2)
├── insight@0.4.3 (object-assign@1.0.0, tough-cookie@0.12.1, os-name@1.0.1, lodash.debounce@2.4.1, request@2.45.0, inquirer@0.6.0)
├── yeoman-generator@0.17.7 (dargs@2.0.3, diff@1.0.8, class-extend@0.1.1, rimraf@2.2.8, text-table@0.2.0, github-username@1.0.0, mime@1.2.11, debug@1.0.4, isbinaryfile@2.0.1, grouped-queue@0.3.0, cross-spawn@0.2.3, run-async@0.1.0, mkdirp@0.5.0, iconv-lite@0.4.4, findup-sync@0.1.3, request@2.45.0, file-utils@0.2.1, gruntfile-editor@0.2.0, glob@4.0.6, cheerio@0.17.0, download@1.0.7, inquirer@0.7.3)
└── yeoman-environment@1.0.2 (log-symbols@1.0.1, diff@1.0.8, text-table@0.2.0, debug@2.1.0, grouped-queue@0.3.0, untildify@1.0.0, glob@4.0.6, inquirer@0.8.0)

Installing the AngularJS generator

$ sudo npm install -g generator-angularjs
Password:
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/npm-package-arg requires semver@'4' but will load
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/semver,
npm WARN unmet dependency which is version 2.3.0
generator-angularjs@1.0.0 /usr/local/lib/node_modules/generator-angularjs
└── yeoman-generator@0.14.2 (dargs@0.1.0, diff@1.0.8, debug@0.7.4, rimraf@2.2.8, text-table@0.2.0, mime@1.2.11, async@0.2.10, mkdirp@0.3.5, isbinaryfile@0.1.9, shelljs@0.2.6, chalk@0.3.0, underscore.string@2.3.3, iconv-lite@0.2.11, lodash@2.2.1, findup-sync@0.1.3, glob@3.2.11, file-utils@0.1.5, request@2.27.0, cheerio@0.12.4, inquirer@0.3.5, download@0.1.19)

Installing Grunt

$ sudo npm install -g grunt-cli
Password:
/usr/local/bin/grunt -> /usr/local/lib/node_modules/grunt-cli/bin/grunt
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/npm-package-arg requires semver@'4' but will load
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/semver,
npm WARN unmet dependency which is version 2.3.0
grunt-cli@0.1.13 /usr/local/lib/node_modules/grunt-cli
├── resolve@0.3.1
├── nopt@1.0.10 (abbrev@1.0.5)
└── findup-sync@0.1.3 (lodash@2.4.1, glob@3.2.11)

Wiredep (Re)Install

$ sudo npm install -g wiredep
Password:
wiredep@1.8.6 node_modules/wiredep
├── propprop@0.3.0
├── minimist@1.1.0
├── lodash@2.4.1
├── through2@0.6.3 (xtend@4.0.0, readable-stream@1.0.33-1)
├── chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
├── glob@4.0.6 (inherits@2.0.1, graceful-fs@3.0.4, once@1.3.1, minimatch@1.0.0)
└── bower-config@0.5.2 (osenv@0.0.3, graceful-fs@2.0.3, optimist@0.6.1, mout@0.9.1)

Bower (Re)Install

http://bower.io/
$ sudo npm install -g bower
Password:
/usr/local/bin/bower -> /usr/local/lib/node_modules/bower/bin/bower
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/npm-package-arg requires semver@'4' but will load
npm WARN unmet dependency /usr/local/lib/node_modules/npm/node_modules/semver,
npm WARN unmet dependency which is version 2.3.0
bower@1.3.12 /usr/local/lib/node_modules/bower
├── is-root@1.0.0
├── junk@1.0.0
├── stringify-object@1.0.0
├── abbrev@1.0.5
├── which@1.0.5
├── chmodr@0.1.0
├── osenv@0.1.0
├── opn@1.0.0
├── archy@0.0.2
├── rimraf@2.2.8
├── lru-cache@2.5.0
├── bower-logger@0.2.2
├── bower-endpoint-parser@0.2.2
├── graceful-fs@3.0.4
├── lockfile@1.0.0
├── nopt@3.0.1
├── retry@0.6.0
├── tmp@0.0.23
├── q@1.0.1
├── semver@2.3.2
├── p-throttler@0.1.0 (q@0.9.7)
├── request-progress@0.3.0 (throttleit@0.0.2)
├── shell-quote@1.4.2 (array-filter@0.0.1, array-reduce@0.0.0, array-map@0.0.0, jsonify@0.0.0)
├── fstream@1.0.2 (inherits@2.0.1)
├── mkdirp@0.5.0 (minimist@0.0.8)
├── bower-json@0.4.0 (intersect@0.0.3, deep-extend@0.2.11, graceful-fs@2.0.3)
├── promptly@0.2.0 (read@1.0.5)
├── chalk@0.5.0 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
├── fstream-ignore@1.0.1 (inherits@2.0.1, minimatch@1.0.0)
├── glob@4.0.6 (inherits@2.0.1, once@1.3.1, minimatch@1.0.0)
├── bower-config@0.5.2 (osenv@0.0.3, graceful-fs@2.0.3, optimist@0.6.1)
├── tar-fs@0.5.2 (pump@0.3.5, tar-stream@0.4.7)
├── mout@0.9.1
├── cardinal@0.4.0 (redeyed@0.4.4)
├── decompress-zip@0.0.8 (nopt@2.2.1, mkpath@0.1.0, touch@0.0.2, readable-stream@1.1.13, binary@0.3.0)
├── request@2.42.0 (caseless@0.6.0, json-stringify-safe@5.0.0, aws-sign2@0.5.0, forever-agent@0.5.2, stringstream@0.0.4, oauth-sign@0.4.0, tunnel-agent@0.4.0, node-uuid@1.4.1, qs@1.2.2, mime-types@1.0.2, bl@0.9.3, form-data@0.1.4, http-signature@0.10.0, tough-cookie@0.12.1, hawk@1.1.1)
├── bower-registry-client@0.2.1 (request-replay@0.2.0, lru-cache@2.3.1, async@0.2.10, mkdirp@0.3.5, graceful-fs@2.0.3, request@2.27.0)
├── update-notifier@0.2.0 (semver-diff@0.1.0, string-length@0.1.2, configstore@0.3.1, latest-version@0.2.0)
├── handlebars@2.0.0 (optimist@0.3.7, uglify-js@2.3.6)
├── inquirer@0.7.1 (figures@1.3.3, mute-stream@0.0.4, through@2.3.6, readline2@0.1.0, lodash@2.4.1, cli-color@0.3.2, rx@2.3.13)
└── insight@0.4.3 (object-assign@1.0.0, async@0.9.0, chalk@0.5.1, os-name@1.0.1, lodash.debounce@2.4.1, tough-cookie@0.12.1, configstore@0.3.1, inquirer@0.6.0)

Sunday, August 3, 2014

Perl: Exporting Static Methods with Moose and Sub::Exporter

Simple how to on exporting static metods with Moose and Sub::Exporter.
package Utils;

=head
   UTILS
=cut

use Moose;
use Carp qw/carp/;
use Sub::Exporter -setup => {
  exports => [
    qw(normalize bounds min max)
  ]
};

sub max {
  my ($value, $compare) = @_;
}
sub min {
  my ($value, $compare) = @_;
}
sub normalize {
  my ($value, $compare) = @_;
}

Saturday, July 19, 2014

Dancer2 Session & Authentication and AngularJS

This took me too much to figure out from different sources hence jotting down my recipe. My application is called ADA ... here the main part with login / logout
package Ada;
use Dancer2;
use Dancer2::Session::Simple;
use Dancer2::Plugin::Auth::Tiny;

our $VERSION = '0.1';

# Authentication Requires Session, here the in memory
set session => "Simple";
#set session => 'YAML';

hook before => sub {
  printf "logged in? %s\n", session('user') ? session('user') : '-';
  if ( !session('user') && request->dispatch_path !~ m{^/login} ) {
    forward '/login', { requested_path => request->dispatch_path };
  }
};

get '/' => sub {
  template 'index';
};

get '/login' => sub {

  # Display a login page; the original URL they requested is available as
  # param('requested_path'), so could be put in a hidden field in the form
  template 'login', { path => param('requested_path') };
};

post '/login' => sub {
  if ( _is_valid( param('user'), param('pass') ) ) {
    print "logged on success!\n";
    session user => param('user');
    redirect param('path') || '/';
  }
  else {
    redirect '/login?failed=1';
  }
};

sub _is_valid {
  my ( $u, $p ) = @_;
  my $store = schema 'default';
  foreach my $r ( $store->resultset('PmiUser')->all ) {
    printf "%10s = %s\n", $r->fedex_id, $r->fedex_pw;
  }
  my $rec =
    $store->resultset('PmiUser')
    ->find( { 'id' => $u, 'pwd' => $p } );
  printf $rec->fedex_id;
  return $rec and $rec->fedex_id ? 0 : 1;
}

get '/logout' => sub {
  printf( "logging out %s\n", session('user') ? session('user') : '-' );
  context->destroy_session;
  redirect '/';
};

true;

project layout

.
├── Gruntfile.js
├── MANIFEST
├── MANIFEST.SKIP
├── Makefile.PL
├── app
│   ├── 404.html
│   ├── favicon.ico
│   ├── fonts
│   ├── images
│   │   └── yeoman.png
│   ├── index.html
│   ├── robots.txt
│   ├── scripts
│   │   ├── app.js
│   │   ├── controllers
│   │   │   ├── main.js
│   │   └── services
│   │       ├── lookups.js
│   ├── styles
│   │   └── main.css
│   ├── test
│   │   └── spec
│   │       └── services
│   │           └── lookups.js
│   └── views
│       └── main.html
├── bin
│   └── app.pl
├── bower.json
├── config.yml
├── environments
│   ├── development.yml
│   └── production.yml
├── karma-e2e.conf.js
├── karma.conf.js
├── lib
│   └── Ada.pm
├── out
├── package.json
├── run.sh
├── t
│   ├── 001_base.t
│   └── 002_index_route.t
├── test
│   ├── runner.html
│   └── spec
│       ├── controllers
│       │   ├── main.js
│       └── services
│           ├── lookups.js
│           └── wls-domain-service.js
└── views
    ├── index.tt -> ../app/index.html
    ├── layouts
    │   ├── main.tt -> ../../app/index.html
    │   └── navbar.tt
    └── login.tt

config.yml

# This is the main configuration file of your Dancer2 app
# env-related settings should go to environments/$env.yml
# all the settings in this file will be loaded at Dancer's startup.

# Your application's name
appname: "ada"

# when the charset is set to UTF-8 Dancer2 will handle for you
# all the magic of encoding and decoding. You should not care
# about unicode within your app when this setting is set (recommended).
charset: "UTF-8"

# template engine
# simple: default and very basic template engine
# template_toolkit: TT
serializer: JSON
session: YAML
session_dir: /tmp/dancer-sessions

template: "template_toolkit"
engines:
  JSON:
    allow_blessed:   '1'
    canonical:       '1'
    convert_blessed: '1' 
  template_toolkit:
    encoding:  'utf8'
    start_tag: '[%'
    end_tag:   '%]'
    WRAPPER: layouts/main.tt
    EVAL_PERL: '1'
  Auth::RBAC:
    credentials:
        class: Config
        options:
            accounts:
                  user01:
                      password: foobar
                      roles:
                          - guest
                          - user
                  weblogic:
                      password: wladmin1
                      roles:
                          - admin

angularjs - index.tt

Add the Logout function to your navigation pills.... make sure its a href.
  <!-- Add your site or application content here -->
  <div class="header">
    <ul class="nav nav-pills pull-right">
      <li class="active"><a ng-href="#">Home</a></li>
      <li><a href="./logout">Logout</a></li>
    </ul>
    <h3 class="text-muted">AD Assistant</h3>
  </div>

login.tt

A very simple ugly login screen.
<html>
      <head>
        <title>Session and logging in</title>
      </head>
      <body>
        <form action='/login' method='POST'>
            User Name : <input type='text' name='user'/>
            Password: <input type='password' name='pass' />

            <!-- Put the original path requested into a hidden
                       field so it's sent back in the POST and can be
                       used to redirect to the right page after login -->
            <input type='hidden' name='path' value='[% path %]'/>

            <input type='submit' value='Login' />
        </form>
      </body>
</html>

Friday, July 4, 2014

Angular ng-enter Directive

Just copied it from somewhere to keep for myself .. I mostly put it in the app.js at the bottom so everyone is able to use this function.
.directive('ngEnter', function() {
 return function(scope, element, attrs) {
  element.bind("keydown keypress", function(event) {
   if (event.which === 13) {
    scope.$apply(function() {
     scope.$eval(attrs.ngEnter, {
      'event' : event
     });
    });

    event.preventDefault();
   }
  });
 };
});

Thursday, July 3, 2014

Dancer2 and changing server port

Well the --port does not work... keeps it on 3000 also set port does not work...
#!/usr/bin/env perl
use Dancer2;
set port => '3010';
use lib './lib';
use Data::Dumper;
dance;
does not work... What to do ??? Here the magic environment variables...
sub _build_default_config {
    my $self = shift;

    $ENV{PLACK_ENV}
      and $ENV{DANCER_APPHANDLER} = 'PSGI';

    return {
        apphandler   => ( $ENV{DANCER_APPHANDLER}   || 'Standalone' ),
        content_type => ( $ENV{DANCER_CONTENT_TYPE} || 'text/html' ),
        charset      => ( $ENV{DANCER_CHARSET}      || '' ),
        warnings     => ( $ENV{DANCER_WARNINGS}     || 0 ),
        startup_info => ( $ENV{DANCER_STARTUP_INFO} || 1 ),
        traces       => ( $ENV{DANCER_TRACES}       || 0 ),
        logger       => ( $ENV{DANCER_LOGGER}       || 'console' ),
        host         => ( $ENV{DANCER_SERVER}       || '0.0.0.0' ),
        port         => ( $ENV{DANCER_PORT}         || '3000' ),
        views        => ( $ENV{DANCER_VIEWS}
              || path( $self->config_location, 'views' ) ),
        appdir        => $self->location,
    };
}
So specify your bin/app.pl like this
#!/usr/bin/env perl

BEGIN {
  $ENV{'DANCER_PUBLIC'}            = './app';
  $ENV{'DBIC_TRACE'}               = 1;
  $ENV{'DANCER_PORT'}              = 3010;
  $ENV{'DBIC_NULLABLE_KEY_NOWARN'} = 1; # allowing nulls in uniq constraints
}
use Dancer2;
set port => '3010';
use lib './lib';
use myapp;
dance;