hackedteam/rcs-console

View on GitHub
src/it/ht/rcs/console/entities/view/LinkView.mxml

Summary

Maintainability
Test Coverage
<?xml version="1.0" encoding="utf-8"?>

<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
                    xmlns:s="library://ns.adobe.com/flex/spark"
                    xmlns:mx="library://ns.adobe.com/flex/mx"
                    xmlns:maps="com.google.maps.*"
                    xmlns:graph="it.ht.rcs.console.entities.view.graph.*"
                    xmlns:entities="it.ht.rcs.console.entities.view.*"
          xmlns:renderers="it.ht.rcs.console.entities.view.renderers.*"
                    xmlns:components="it.ht.rcs.console.entities.view.components.*"
                    xmlns:filters="it.ht.rcs.console.entities.view.filters.*"
                    xmlns:utils="it.ht.rcs.console.utils.*"
                    height="100%"
                    width="100%"
                    creationComplete="onCreationComplete()" 
          addedToStage="onAddedToStage(event)" 
          removedFromStage="onRemovedFromStage(event)" >
    <fx:Script>
        <![CDATA[
      import fr.kapit.layouts.model.Edge;
      
      import it.ht.rcs.console.entities.controller.EntityManager;
      import it.ht.rcs.console.entities.model.Entity;
      import it.ht.rcs.console.entities.model.Flow;
      import it.ht.rcs.console.entities.model.Flows;
      import it.ht.rcs.console.entities.view.components.advanced.timeline.TimelineUtils;
      import it.ht.rcs.console.entities.view.renderers.CustomLink;
      import it.ht.rcs.console.events.FilterEvent;
      import it.ht.rcs.console.search.controller.SearchManager;
      
      import locale.R;
      
      import mx.collections.ArrayCollection;
      import mx.collections.ListCollectionView;
      import mx.core.FlexGlobals;
      import mx.rpc.events.FaultEvent;
      import mx.rpc.events.ResultEvent;
      
      import spark.collections.Sort;

            [Bindable]
            public var entities:ListCollectionView;

            [Bindable]
            public var section:EntitiesSection;

            [Bindable]
            public var entitiesToShow:ArrayCollection;

            private var numEntitiesToShow:int=0;


            private var currentIndex:int=0;

            private var roots:ArrayCollection;

            [Bindable]
            public var selectedNodes:ArrayCollection;

            [Bindable]
            public var selectedEdge:Object

            [Bindable]
            public var linkEnabled:Boolean;

            [Bindable]
            public var mergeEnabled:Boolean;

            [Bindable]
            public var jumpEnabled:Boolean;

            [Bindable]
            public var exportEnabled:Boolean;
      
      [Bindable]
      public var groupEnabled:Boolean;
      
      [Bindable]
      public var ungroupEnabled:Boolean;


            private var sort:Sort;
            private var xmlData:XML;


            [Bindable]
            private var startDate:Date;

            [Bindable]
            private var endDate:Date;

            [Bindable]
            public var actionbar:EntitiesActionBar;
      
            private var flows:ArrayCollection;

            public var inited:Boolean; //??

            private var drawing:Boolean

            [Embed(source='/img/NEW/dottedLine.png')]
            public static const dottedLine:Class;

            [Embed(source='/img/NEW/dashedLine.png')]
            public static const dashedLine:Class;

            [Embed(source='/img/NEW/fullLine.png')]
            public static const fullLine:Class;
      
      [Bindable]
      public var filterCriteria:Object=
        {
          type:[], 
          relevance:[], 
          time:"time", 
          from:"lastMonth", 
          to:0,
          programs:[]
        };
      
      


            private function onCreationComplete():void
            {
                //trace("LINK MAP: CREATION COMPLETE")
        startDate=new Date();
        startDate.time=startDate.time - (1000 * 60 * 60 * 24 * 30);
        endDate=new Date();
            }


            

            public function draw():void
            { 
            
        graph.visible=false;
        graph.zoom(1)
        zoomSlider.value=1
        if(!entitiesToShow) 
          entitiesToShow=new ArrayCollection()
        entitiesToShow.removeAll()
        
        for (var i:int=0; i < entities.length; i++)
        {
          var entity:Entity=entities.getItemAt(i) as Entity; //TODO : ADD FILTERS
          if(meetsCriteria(entity))
            
            entitiesToShow.addItem(entity)
        }
        graph.draw(entitiesToShow, filterCriteria)
          
         
          graph.visible=true; //event listener?
          
            
       // trace("Drawing Graph > Entities to show: "+entitiesToShow.length)
        
        getFlows(entitiesToShow) //TODO 
            }
      
      
      private function meetsCriteria(entity:Entity):Boolean
      {
        if(!entity)
          return false;
        if(entity.type=="group")
          return true;
        if(filterCriteria.type)
        {
          if(filterCriteria.type.length >0 && filterCriteria.type.indexOf(entity.type)==-1)
            return false;
        }
        
        return true;
      }
      
      protected function onAddedToStage(event:Event):void
      {
       // trace("LINK MAP: ADDED TO STAGE")
       filterCriteria={ type:[], 
        relevance:[], 
        time:"time", 
        from:"lastMonth", 
        to:0,
        programs:[]
       }
         FlexGlobals.topLevelApplication.dispatchEvent(new FilterEvent(FilterEvent.ENTITIES_FILTER_RESET))
          
      }
      
      protected function onRemovedFromStage(event:Event):void
      {
        trace("LINK MAP: REMOVED FROM STAGE")
      }
      
      public function addListeners():void
      {
        //trace("LINK MAP: ADD LISTENERS")
        FlexGlobals.topLevelApplication.addEventListener(FilterEvent.ENTITIES_FILTER_CHANGED, onFilterChange)
      }
      
      public function removeListeners():void
      {
        //trace("LINK MAP: REMOVE LISTENERS")
        FlexGlobals.topLevelApplication.removeEventListener(FilterEvent.ENTITIES_FILTER_CHANGED, onFilterChange)
      }
      
      
      protected function onElementDoubleClick():void
      {
        
        if(graph.vis.selection[graph.vis.selection.length - 1] is CustomLink)
        {
          
          var entity1:Entity=EntityManager.instance.getItem(graph.vis.selection[graph.vis.selection.length - 1].data.source) as Entity
          var entity2:Entity=EntityManager.instance.getItem(graph.vis.selection[graph.vis.selection.length - 1].data.target) as Entity
            
          if (graph.vis.selection[graph.vis.selection.length - 1].data.info && graph.vis.selection[graph.vis.selection.length - 1].data.level=="automatic" && (entity1.type=="target" || entity2.type=="target"))
            actionbar.jumpToEvidence()
          return;
        }
        
        var item:*=EntityManager.instance.getItem(graph.vis.selection[graph.vis.selection.length - 1].data._id) //last selected
        
        if (item)
        {
          var hasPermission:Boolean=SearchManager.instance.getItem(item.stand_for)
          if(item.type=="group") // && !hasPermission) uncomment to jump to other operation graph (update the EntitiesSectionStateManager)
            return;
          section.stateManager.manageItemSelection(item);
          
        }
        
      }
      
      public function onSelectionChange():void
      {
        //trace("VIS SELECTION CHANGED")
        
        
        actionbar.selectedObject=null
        actionbar.selectedObjects=null;
        info.selectedItem=null;
        info.selectedItems=null;
        
        linkEnabled=actionbar.linkEnabled=false;
        mergeEnabled=actionbar.mergeEnabled=false;
        jumpEnabled=actionbar.jumpEnabled=false;
        exportEnabled=actionbar.exportEnabled=true;
        groupEnabled=actionbar.groupEnabled=false;
        ungroupEnabled=actionbar.ungroupEnabled=false;
        
        if(!graph.selection)
          return
        
        //Only 1 node 
        if (graph.selection.length == 1 && graph.selection[0].data.name)
        {
          info.selectedItem=EntityManager.instance.getItem(String(graph.selection[0].data._id)) || new Entity(graph.selection[0].data)
          info.selectedItems=new <Object>[info.selectedItem];
          actionbar.selectedObject=info.selectedItem;
          actionbar.selectedObjects=new <Object>[actionbar.selectedObject];
          actionbar.selectedObjects.push(actionbar.selectedObject)
        }
          //Only 1 edge 
        else if (graph.selection.length == 1 && graph.selection[0].data.versus != null)
        {
          info.selectedItem=graph.selection[0].data
          info.selectedItems=new <Object>[info.selectedItem];
          actionbar.selectedObject=info.selectedItem;
          actionbar.selectedObjects=new <Object>[actionbar.selectedObject];
          actionbar.selectedObjects.push(actionbar.selectedObject)
            
            var entity1:Entity=EntityManager.instance.getItem(graph.selection[0].data.source) as Entity
            var entity2:Entity=EntityManager.instance.getItem(graph.selection[0].data.target) as Entity
          
          if (graph.selection[0].data.info && (graph.selection[0].data.type == "peer" || graph.selection[0].data.type == "know" || graph.selection[0].data.type == "position") && graph.selection[0].data.level == "automatic" && (entity1.type=="target" || entity2.type=="target"))//TODO!!!!!!!!!!!
        
            jumpEnabled=actionbar.jumpEnabled=true;

        }
          //merging enabled?
        else if (graph.selection.length == 2)
        {
          trace("linked: " + areLinked(graph.selection[0].data._id, graph.selection[1].data._id))
          actionbar.selectedObjects=new Vector.<Object>
          actionbar.selectedObjects.push(graph.selection[0].data)
          actionbar.selectedObjects.push(graph.selection[1].data)
          if (graph.selection[0].data.name && graph.selection[1].data.name)
            linkEnabled=actionbar.linkEnabled=true;
          
          if ((graph.selection[0].data.type == "person" && graph.selection[1].data.type == "person") || (graph.selection[0].data.type == "target" && graph.selection[1].data.type == "person") || (graph.selection[0].data.type == "person" && graph.selection[1].data.type == "target"))
          {
            mergeEnabled=actionbar.mergeEnabled=true;
          }
        }
        //grouping
        var i:int
        if (graph.selection.length > 1)
        {
          
          groupEnabled=actionbar.groupEnabled=true;
          for(i=0;i<graph.selection.length;i++)
          {
            if(!graph.selection[i].data.name || (graph.selection[i].data.name && graph.selection[i].data.type=="group") || (graph.selection[i].data.name && isGrouped(graph.selection[i].data._id)))
            {
              groupEnabled=actionbar.groupEnabled=false;
              break;
            }
            
          }
        }
        if (graph.selection.length == 1 && graph.selection[0].data.type=="group" && !graph.selection[0].data.stand_for)
        {
          ungroupEnabled=actionbar.ungroupEnabled=true;
        }
        //no selection do not enable export
        if (graph.selection.length < 1)
          exportEnabled=actionbar.exportEnabled=false;
        else
        { //check if there is a link object in  selection
          for ( i=0; i < graph.selection.length; i++)
          {
            if (!graph.selection[i].data.name || (graph.selection[i].data.type=="group" && !SearchManager.instance.getItem(graph.selection[i].data.stand_for))) //link has no name
              exportEnabled=actionbar.exportEnabled=false; //link in selection do not enable export
          }
        }
        
      }

      private function onFilterChange(e:FilterEvent):void
      { 
        /* 
        trace("==============================")
        trace("FILTER HAS CHANGED")
        trace("==============================")
        trace("time: "+filterCriteria.time)
        trace("from: "+filterCriteria.from)
        trace("to: "+filterCriteria.to)
        trace("type: "+filterCriteria.type)
        trace("tag: "+filterCriteria.relevance) 
        */
        
        
        if(filterCriteria.from=="lastMonth")
        {
          startDate=new Date();
          startDate.time=startDate.time - (1000 * 60 * 60 * 24 * 30);
          endDate=new Date();
        }
          
        else if(filterCriteria.from=="last3Months")
        {
          startDate=new Date();
          startDate.time=startDate.time - (1000 * 60 * 60 * 24 * 90);
          endDate=new Date();
        }
          
        else if(filterCriteria.from=="last6Months")
        {
          startDate=new Date();
          startDate.time=startDate.time - (1000 * 60 * 60 * 24 * 180);
          endDate=new Date();
        }
          
        else if(filterCriteria.from && filterCriteria.to)
        {
          startDate=new Date(filterCriteria.from*1000)
          endDate=new Date(filterCriteria.from*1000);
        }
        
      //  trace("from: "+startDate)
       // trace("to: "+endDate)
        if(timeline.initialized)
        {
          timeline.stop()
          timeline.startDate=startDate
          timeline.endDate=endDate
          timeline.update()
          //onAddedToStage(null);
        }
        draw()
      }
      
      private function isGrouped(entityId:String):Boolean
      {
        for(var i:int=0;i<entities.length;i++)
        {
          var entity:Entity=entities.getItemAt(i) as Entity
          if(entity.type=="group" && entity.children.source.indexOf(entityId)!=-1)
            return true;
        }
        return false;
      }
      
      private function areLinked(source:String, target:String):Boolean
      {
        var edge:Edge;
        var renderer:CustomLink
        for (var i:int=0; i < graph.vis.graph.edges.length; i++)
        {
          edge=graph.vis.graph.edges[i] as Edge
          renderer=edge.visualEdge as CustomLink
          if ((renderer.data.source == source && renderer.data.target == target) || (renderer.data.source == target && renderer.data.target == source))
            return true;
        }
        
        return false;
      }
      
      private function getFlows(entities:ListCollectionView):void
      {
        timeline.visible=false;
        trace("get flows")
        if (!entities)
          return;
        
        var ids:Array=new Array();
        flows=new ArrayCollection
        
        for (var i:int=0; i < entities.length; i++)
        {
          var e:Entity=entities.getItemAt(i) as Entity;
          ids.push(e._id)
        }
        EntityManager.instance.flow(ids, formatDate(startDate), formatDate(endDate), onFlowResult, onFlowFault)
      }
      
      private function formatDate(d:Date):String
      {
        if (!d)
          return "";
        return String(d.fullYear) + TimelineUtils.doubleDigits(d.month + 1) + TimelineUtils.doubleDigits(d.date);
      }
      
      
      private function onFlowResult(e:ResultEvent):void
      {
        //trace("flow result")
        timeline.visible=true;
        flows=e.result as ArrayCollection;
        timeline.highlight(flows);
        graph.visible=true;
        if(section.linkToHighLight)
        {
          graph.highlightLink(section.linkToHighLight.from, section.linkToHighLight.to)
         
        }
        
        if(section.nodeToHighLight)
        {
          graph.highlightNode(section.nodeToHighLight.id)

        }
      }
      
      private function onFlowFault(e:FaultEvent):void
      {
        timeline.visible=true;
        graph.visible=true;
        //trace("flow fault")
      }
      
      private function onTimelineChange():void
      {
        // trace("LINK MAP: TIMELINE CHANGE")
        var d:Date=new Date();
        d.time=timeline.slider.value;
        var formattedDate:String=String(d.fullYear) + TimelineUtils.doubleDigits(d.month + 1) + TimelineUtils.doubleDigits(d.date);
        var currentEdge:Edge;
        var currentRenderer:CustomLink;
        
        if (graph.vis)
        {
          for (var r:int=0; r < graph.vis.graph.edges.length; r++)
          {
            currentEdge=graph.vis.graph.edges[r] as Edge;
            currentRenderer=currentEdge.visualEdge as CustomLink
            currentRenderer.reset()
            
          }
        }
        
        if (flows)
        {
          for (var i:int=0; i < flows.length; i++)
          {
            var flow:Flow=flows[i] as Flow;
            if (flow.date == formattedDate)
            {
              for (var j:int=0; j < flow.flows.length; j++)
              {
                var f:Flows=flow.flows.getItemAt(j) as Flows;
                if (graph.vis)
                {
                  for (var k:int=0; k < graph.vis.graph.edges.length; k++)
                  {
                    currentEdge=graph.vis.graph.edges[k] as Edge;
                    currentRenderer=currentEdge.visualEdge as CustomLink
                    
                    if (currentRenderer.data.source == f.from && currentRenderer.data.target == f.rcpt || currentRenderer.data.source == f.rcpt && currentRenderer.data.target == f.from)
                    {   
                      currentRenderer.showFlow(f.from, f.rcpt, f.count);
                    }
                  }
                }
              }
            }
          }
        }
      }
      
      private function onZoom(e:Event):void
      {
        graph.zoom(e.currentTarget.value)
      }

    ]]>
    </fx:Script>

    <s:HGroup width="100%"
                        height="100%"
                        gap="5">
    
    
        <s:VGroup width="100%"
                            height="100%">

            <s:HGroup verticalAlign="middle"
                                horizontalAlign="right"
                                width="100%"
                                paddingTop="6" gap="-1">
        

          
          <renderers:FilterRenderer label="{R.get('TIMEFRAME')}" filter="{filterCriteria}" property="time"
                                    popupFactory="it.ht.rcs.console.entities.view.filters.DateFilterPopup"
                                    width="150" />
        
          <renderers:FilterRenderer label="{R.get('TYPE_ENTITY')}"  filter="{filterCriteria}" property="type"
                                    popupFactory="it.ht.rcs.console.entities.view.filters.TypeFilterPopup"
                                    width="150"/>
        
          <renderers:FilterRenderer label="{R.get('TYPE_LINK')}" property="programs" filter="{filterCriteria}"
                                    popupFactory="it.ht.rcs.console.entities.view.filters.LinkTypeFilterPopup"
                                    width="150"/>
        
          <renderers:FilterRenderer label="{R.get('RELEVANCE')}" property="relevance" filter="{filterCriteria}"
                                    popupFactory="it.ht.rcs.console.entities.view.filters.TagFilterPopup"
                                    width="150"/>
      

                <s:Spacer width="100%"/>
        
        <s:Label text="zoom: " fontWeight="bold"/>
        <s:Spacer width="10"/>
        <s:HSlider  id="zoomSlider"
                    maximum="10" minimum="0.1"
                    showDataTip="false"
                    value="1"
                    stepSize="0.1" change="onZoom(event)"/>
            
            </s:HGroup>
            <s:Line width="100%">
                <s:stroke>
                    <s:SolidColorStroke color="0xCCCCCC"/>
                </s:stroke>
            </s:Line>
            <s:BorderContainer id="graphCnvs"
                                                 borderColor="#CCCCCC"
                                                 backgroundColor="#FFFFFF"
                                                 width="100%"
                                                 height="100%">

                <graph:LinkGraph id="graph"
                                                 selectionChange="onSelectionChange()" 
                                                 elementDoubleClick="onElementDoubleClick()"/>

            </s:BorderContainer>
            <s:Line width="100%">
                <s:stroke>
                    <s:SolidColorStroke color="0xCCCCCC"/>
                </s:stroke>
            </s:Line>
            <components:Timeline width="100%"
                                                     id="timeline"
                                                     step="{Timeline.DAY}"
                                                     startDate="{startDate}"
                                                     endDate="{endDate}"
                                                     change="onTimelineChange()"/>

        </s:VGroup>
        <entities:EntityInfoPanel id="info"/>
    </s:HGroup>

</s:VGroup>