aouellets of Academic Technical Team Code Base
5/1/2018 - 2:27 PM

finder

Scroll and search in the json - coming from pvs2json.

.finderElement {
	display: block;
	height: 100%;
	width: 100%;
}

.finderWidget {
	margin: auto;
	width: 198px;
	height: 54px;
	border-radius: 5px;
	background-color: #DDDDDD;
	padding: 3px;
	opacity: 0.5;
}

.finderButton {
	border-style: none;
	margin: 0;
	padding: 0;
	width: 48px;
	height: 48px;
}

.finderButton[disabled] {
	opacity: 0.5;
}
function twxFinder() {
  return {
    elementTag: 'twx-finder',

    label: 'Finder',

    properties: [
      {
        name: 'class',
        label: 'Class',
        datatype: 'string',
        default: ''
      },
      {
        name: 'auto',
        label: 'Auto',
        datatype: 'boolean',
        isBindingSource: false,
        isBindingTarget: true,
        showInput: true
      },      
      {
        name: 'src',
        label: 'Src',
        datatype: 'resource_url',
        default: '',
        isBindingTarget: true,
        showInput: true
      },
      {
        name: 'name',
        label: 'Property',
        datatype: 'string',
        default: 'Name',
        isBindingTarget: true,
        showInput: true
      },
      {
        name: 'op',
        label: 'Op',
        datatype: 'select',
        default: 'like',
        isBindingTarget: true,
        editor: 'select',
        options: [
            {label: 'Like'        , value: "like"},
            {label: 'Unlike'      , value: "unlike"},
            {label: 'Same'        , value: "same"},
            {label: 'Not'         , value: "not"},
            {label: 'Starts with' , value: "starts"},
            {label: 'Equal to'    , value: "eq"},
            {label: 'Not equal to', value: "ne"},
            {label: 'Greater than', value: "gt"},
            {label: 'Less than'   , value: "lt"},
            {label: 'Before'      , value: "before"},
            {label: 'After'       , value: "after"},
        ],
      },
      {
        name: 'value',
        label: 'Value',
        datatype: 'number',
        isBindingSource: false,
        isBindingTarget: true,
        showInput: true
      },
      {
        name: 'results',
        label: 'Results',
        datatype: 'Infotable',
  isBindingSource: true,
  isBindingTarget: false,
        showInput: false
      },
      {
        name: 'count',
        label: 'Count',
        datatype: 'number',
  isBindingSource: true,
  isBindingTarget: false,
        showInput: false
      }
    ],

    events: [
        {
            name: 'start',
            label: 'Started'
        },
        {
            name: 'complete',
            label: 'Completed'
        },
    ],

    services: [
      {
        name: 'find',
        label: 'Find'
      }
    ],

    designTemplate: function () {
      return '<div class="finderWidget"></div>';
    },

    runtimeTemplate: function (props) {
      var tmpl = '<div ng-finder class="ng-hide finderWidget ' + props.class + '" results-field="me.results" count-field="me.count" auto-field={{me.auto}} src-field={{me.src}} name-field={{me.name}}  op-field={{me.op}}  value-field={{me.value}}  delegate-field="delegate"></div>';
      return tmpl;
    }
  }
}

twxAppBuilder.widget('twxFinder', twxFinder);
if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports) {
  module.exports = 'finder-ng';
}

var cmds = {
    "starts": function (a, b) { return a.search(b) === 0 },
    "not"  :  function (a, b) { return a != b },
    "same"  : function (a, b) { return a === b },
    "like"  : function (a, b) { return a.search(b) >= 0 },
    "unlike": function (a, b) { return a.search(b) < 0 },
    "eq"    : function (a, b) { return parseFloat(a) === parseFloat(b) },
    "ne"    : function (a, b) { return parseFloat(a) !=  parseFloat(b) },
    "lt"    : function (a, b) { return parseFloat(a)  <  parseFloat(b) },
    "gt"    : function (a, b) { return parseFloat(a)  >  parseFloat(b) },
    "in"    : function (a,b,c){ var pa = parseFloat(a); return  (pa >= parseFloat(b) && pa <= parseFloat(c)) },
    "out"   : function (a,b,c){ var pa = parseFloat(a); return !(pa >= parseFloat(b) && pa <= parseFloat(c)) },
    "before": function (a,b)  { var pa = Date.parse(a); var pb = Date.parse(b); return pa < pb; },
    "after" : function (a,b)  { var pa = Date.parse(a); var pb = Date.parse(b); return pa > pb; },
};

function pvmeta(pvs,linq) {
    this.pvp  = pvs;
    var linq = linq;
    this.properties = function() {
        var props = linq.from(this.pvp.components)
                        .where (function(cmp) { return cmp.properties != undefined })
                        .select(function(s) { 
                            var names = linq.from(s.properties)
                                            .select(function(n) { return n.key})
                                            .toArray();
            
                            var instances = linq.from(s.children)
                                                .where (function(c) { return c.properties != undefined; })
                                                .select(function(c) {
                                                    var inames = linq.from(c.properties)
                                                                     .select(function(n) { return n.key})
                                                                     .toArray();
                                                    return inames;
                                                })
                                                .toArray();
                
                            var result = linq.from(names)
                                             .union(instances)
                                             .toArray();
                            return result;;
                        })
                        .toArray();
    
        // now count these up    
        var unique=new Object();
        props.forEach(function (a) {
            if (a != undefined && a instanceof Array) a.forEach(function (b) {
                if (b instanceof Array) {
                    b.forEach(function(c){
                        if (unique[c] === undefined)
                             unique[c] = 1;
                        else
                            unique[c] += 1;
                    });
                }
                else {
                    if (unique[b] === undefined)
                        unique[b] = 1;
                    else
                        unique[b] += 1;
                }
            });
        });
        
        // unsorted list, but doesnt trip out the heap!
        var order = new Array();
        for (var key in unique) {
            if (unique.hasOwnProperty(key)) {
                order.push({name:key, count:unique[key]});
            }
        }
    
        // finally, sort by name (or value)
        var oot = linq.from(order)
                      .orderBy('$.name')
                    //.orderBy("$.value")
                      .select(function(n) { return n; }) //return {name:n.key, count:n.value};})
                      .toArray();
              
        // sorted list of property name:count          
        return oot;
    }

    this.byName = function(name, lval, op, kval) {
        // we have a property name  
        var pname = name.toLowerCase();
        var props = undefined;
  
        // do we have a property value?
        if (lval != undefined) {
            var pval, comparer, rval=undefined;
            if (op != undefined) {
                pval = lval.toLowerCase();

                //yes, so lets look for name < value  
                compstr  = op.toLowerCase();
                comparer = cmds[compstr];
                if (comparer == undefined)
                    return undefined;
            }
            else {
                pval = lval.toLowerCase();

                //yes, so lets look for name==value  
                comparer = cmds["eq"];
            }
            if (kval != undefined) 
                rval = kval.toLowerCase();
            
            var pps = linq.from(this.pvp.components)
                          .where(function (cmp) {
                              return (cmp.properties != undefined &&
                                      cmp.properties[pname] != undefined &&
                                      comparer(cmp.properties[pname],pval,rval)) })
                          .select(function (s) { return { cid: s.cid, key: pname, value: s.properties[pname] }; })
                          .toArray();
    
            var ips = new Array();
            this.pvp.components.forEach(function(cmp) {
                var kids = linq.from(cmp.children)
                               .where(function (c) {
                                   return c.properties != undefined &&
                                          c.properties[pname] != undefined &&
                                          comparer(c.properties[pname],pval,rval); })
                               .select(function(s) { 
                                   return { cid: s.cidref, key: pname, value: s.properties[pname] };})
                               .toArray();   
                kids.forEach(function(a) { ips.push(a)});
            });
            props = linq.from(pps).union(ips).toArray();
        }
        else { 
            var pps = linq.from(this.pvp.components)
                          .where(function(cmp) { return (cmp.properties != undefined && 
                                                         cmp.properties[pname] != undefined) })
                          .select(function(s) { return {cid:s.cid, key:pname, value:s.properties[pname]}; })
                          .toArray();
    
            var ips = new Array();
            this.pvp.components.forEach(function(cmp) {
                var kids = linq.from(cmp.children)
                               .where (function(c) { return c.properties != undefined &&
                                                            c.properties[pname] != undefined; })
                               .select(function(s) { 
                                   return {cid:s.cidref, key:pname, value:s.properties[pname]}; })
                               .toArray();   
                kids.forEach(function(a) { ips.push(a)});
            });
            props = linq.from(pps).union(ips).toArray();
        }
        //console.log(props);
        if (props != undefined) {  
            var inst = linq.from(this.pvp.idmap)
                           .join(props,"map=>map.value","id=>id.cid","outer,inner=>{path:outer.key,key:inner.key, value:inner.value}")
                           .select(function(s) { return s; })
                           .toArray();
            return inst;               
        }
        else {
            return [];
        }
    }
}


(function () {
  'use strict';

  var finderModule = angular.module('finder-ng', []);
  finderModule.directive('ngFinder', ['$timeout', '$http', ngFinder]);

  function ngFinder($timeout, $http) {

    return {
      restrict: 'EA',
      scope: {
        nameField    : '@',
        valueField   : '@',
        opField      : '@',
        srcField     : '@',
        autoField    : '@',
        resultsField : '=',
        countField   : '=',
        delegateField: '='
      },
      template: '<div></div>',
      link: function (scope, element, attr) {

        var lastUpdated = 'unknown';
        scope.data = { name: undefined, 
                      value: undefined, 
                         op: undefined, 
                        src: undefined, 
                        pvm: undefined, 
                    results: [], 
                       prev: undefined,
                    promise: undefined,
                       auto: true
                     };

        var executeFinder = function() {
          scope.data.prev = scope.data.results;

          scope.data.results = scope.data.pvm.byName(scope.nameField,scope.valueField,scope.opField);

          // output the output variables
          scope.$parent.view.wdg[scope.$parent.widgetId]['results'] = scope.data.results;
          scope.$parent.view.wdg[scope.$parent.widgetId]['count']   = scope.data.results.length;

          scope.$parent.fireEvent('complete');
        };

        var find = function(){
          scope.$parent.fireEvent('start');
          $timeout(function () {

            // has the source data changed?  
            if (scope.srcField != scope.data.src) {  // the input source data has changed
              scope.data.src = scope.srcField;

              $http.get(scope.data.src, {},
                        { headers: { Accept: "application/json", "Content-Type": "application/json" } }
              ).then(function (response) {
                if (scope.data.pvm === undefined)
                  scope.data.pvm = new pvmeta(response.data, Enumerable);
                else             
                  scope.data.pvm.pvp = response.data;
                executeFinder()
              }, function (response) {
                console.log('failed to get ' + data.src);    
              });
            }           
            // if not, run the query again
            else
              executeFinder();

          }, 1);

        };

        var updateFinder = function(){
          if (scope.data.promise === undefined)
            scope.data.promise = $timeout(function(){
              scope.data.promise = undefined;  
              if (scope.data.auto)
                executeFinder();
          },1000);
        };

        scope.$watch('nameField', function () {
          updateFinder();
        });

        scope.$watch('valueField', function () {
          updateFinder();
        });

        scope.$watch('opField', function () {
          updateFinder();
        });

        scope.$watch('srcField', function () {
          find();
        });

        scope.$watch('autoField', function () {
          scope.data.auto = (scope.autoField != undefined && scope.autoField === 'true') ? true :false ;
          updateFinder();
        });

        scope.$watch('delegateField', function (delegate) {
          if (delegate) {
            delegate.find = function () {
              find();
            };
          }
        });

      }
    };
  }

}());