added svcapi ui and camunda code
[it/otf.git] / otf-frontend / client / src / app / layout / components / stats / stats.service.ts
diff --git a/otf-frontend/client/src/app/layout/components/stats/stats.service.ts b/otf-frontend/client/src/app/layout/components/stats/stats.service.ts
new file mode 100644 (file)
index 0000000..31d872c
--- /dev/null
@@ -0,0 +1,765 @@
+/*  Copyright (c) 2019 AT&T Intellectual Property.                             #\r
+#                                                                              #\r
+#   Licensed under the Apache License, Version 2.0 (the "License");            #\r
+#   you may not use this file except in compliance with the License.           #\r
+#   You may obtain a copy of the License at                                    #\r
+#                                                                              #\r
+#       http://www.apache.org/licenses/LICENSE-2.0                             #\r
+#                                                                              #\r
+#   Unless required by applicable law or agreed to in writing, software        #\r
+#   distributed under the License is distributed on an "AS IS" BASIS,          #\r
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #\r
+#   See the License for the specific language governing permissions and        #\r
+#   limitations under the License.                                             #\r
+##############################################################################*/\r
+\r
+\r
+import { Injectable } from '@angular/core';\r
+import { FeathersService } from 'app/shared/services/feathers.service';\r
+import { TestExecutionService } from 'app/shared/services/test-execution.service';\r
+import { Observable, Subject, from } from 'rxjs';\r
+import { MatDialog } from '@angular/material';\r
+import { GroupService } from 'app/shared/services/group.service';\r
+import * as moment from 'moment';\r
+import { SchedulingService } from 'app/shared/services/scheduling.service';\r
+import { TestInstanceService } from 'app/shared/services/test-instance.service';\r
+import { string, number } from '@amcharts/amcharts4/core';\r
+import { group } from '@angular/animations';\r
+export interface StatsFilter {\r
+  startDate?: Date,\r
+  endDate?: Date,\r
+  selectedTestDefinitions?: Array<any>,\r
+  selectedTestInstances?: Array<any>\r
+}\r
+\r
+@Injectable({\r
+  providedIn: 'root'\r
+})\r
+\r
+//this service serves as the controller between the dashboard's data management and the components' UI.\r
+export class StatsService {\r
+\r
+  //set default filters\r
+  public filters: StatsFilter = {\r
+    startDate: moment().subtract(1, 'weeks').toDate(),\r
+    endDate: moment().toDate()\r
+  }\r
+\r
+  public executionList: Array<any> = [];\r
+\r
+  public testDefinitionData = {\r
+    //Executions Array thats made of objects with date, test definition name, and count\r
+    "Executions": [],\r
+    //Array of Results for the Pie Chart\r
+    "Results": [],\r
+  }\r
+  public testInstanceData = {\r
+    //Executions for Each Test Instance\r
+    "Executions": [],\r
+    //For multilinechart, objects made of test instance names, and execution count for each one.\r
+    "Individual_Exec": []\r
+  };\r
+\r
+  //list if test instance names\r
+  public testInstances = [];\r
+  //list of scheduled tests gotten from agenda in db.\r
+  public scheduledTests = [];\r
+\r
+  //these are filter objects attached to stats service that are updated whenever user confirms from filter modal. \r
+  //They are updated in the filter functions below.\r
+  // public tdFilters = {\r
+  //   startDate: {},\r
+  //   endDate: {},\r
+  //   selected: [],\r
+  // }\r
+  // public tiFilters = {\r
+  //   startDate: {},\r
+  //   endDate: {},\r
+  //   selectedTDs: [],\r
+  //   selectedTIs: [],\r
+  //   //this limit is for the amount of multiple series being displayed on the multiline chart according to default/filters.\r
+  //   multiLineLimit: 5,\r
+  // }\r
+  // public scheduleFilters = {\r
+  //   startDate: {},\r
+  //   endDate: {},\r
+  //   timeRangeStart: {},\r
+  //   timeRangeEnd: {},\r
+  //   selectedInstances: [],\r
+  // }\r
+\r
+  //these are for triggering the listeners located in the chart components.\r
+  //executionsChange subjects are triggered when user filters.\r
+  public tdExecutionsChange: Subject<Object> = new Subject<Object>();\r
+  public tiExecutionsChange: Subject<Object> = new Subject<Object>();\r
+  public scheduleChange: Subject<Object> = new Subject<Object>();\r
+  public finishedDefaultData: Subject<Object> = new Subject<Object>();\r
+  public startDefaultData: Subject<Object> = new Subject<Object>();\r
+  public startTDExecutionCall: Subject<Object> = new Subject<Object>();\r
+  public startTIExecutionCall: Subject<Object> = new Subject<Object>();\r
+  public windowResized: Subject<Object> = new Subject<Object>();\r
+  public startScheduleCall: Subject<Object> = new Subject<Object>();\r
+\r
+  constructor(public feathers: FeathersService, public testExecution: TestExecutionService,\r
+    public _groups: GroupService, public testInstanceService: TestInstanceService, public schedService: SchedulingService) {\r
+\r
+    //listening for whether user changes group, if so, variables are reset (rest are inside defaultData, we can work on consistency).\r
+    //and we get default data for the new group passed in.\r
+    // this.getDefaultData(this._groups.getGroup());\r
+    // this._groups.groupChange().subscribe(group => {\r
+    //   this.getDefaultData(group);\r
+    // });\r
+\r
+  }\r
+\r
+  \r
+\r
+  //these are trigger functions that we call in the data manipulating functions below.\r
+  //the purpose of these functions is to let the listeners set up in the chart components know that the data has been updated.\r
+  //then the chart components recall the data using getData().\r
+  checkWindow() {\r
+    return this.windowResized;\r
+  }\r
+\r
+  onDefaultDataCallStarted() {\r
+    return this.startDefaultData;\r
+  }\r
+\r
+  onTDExecutionChangeStarted() {\r
+    return this.startTDExecutionCall;\r
+  }\r
+\r
+  onTIExecutionChangeStarted() {\r
+    return this.startTIExecutionCall;\r
+  }\r
+\r
+  onScheduleChangeStarted() {\r
+    return this.startScheduleCall;\r
+  }\r
+\r
+  onDefaultDataCallFinished() {\r
+    return this.finishedDefaultData;\r
+  }\r
+\r
+  onTDExecutionChangeFinished() {\r
+    return this.tdExecutionsChange;\r
+  }\r
+\r
+  onTIExecutionChangeFinished() {\r
+    return this.tiExecutionsChange;\r
+  }\r
+\r
+  onScheduleChangeFinished() {\r
+    return this.scheduleChange;\r
+  }\r
+\r
+  //one giant getter where we pass in the name of what we want and switch case it.\r
+\r
+  //This function is called in the components and returns the relavent array for the component.\r
+  getData(name: string) {\r
+    let outputData = {};\r
+\r
+    switch (name) {\r
+      case "TD_Executions":\r
+        return this.testDefinitionData.Executions;\r
+      case "TD_Results":\r
+        return this.testDefinitionData.Results;\r
+      case "testInstances":\r
+        return this.testInstanceData.Executions;\r
+      case "Schedule":\r
+        return this.scheduledTests;\r
+      // case "multiLineData":\r
+      //   //limitting the series being displayed.\r
+      //   return this.testInstanceData.Individual_Exec.slice(0, this.tiFilters.multiLineLimit);\r
+    }\r
+    //console.log(outputData);\r
+    return outputData;\r
+  }\r
+\r
+  //this gets called from the filter modal when the user confirms their filters.\r
+  filterData(allFilters, tdFilters, tiFilters, schedFilters) {\r
+    //this.filterAll(allFilters);\r
+    this.filterTDs(tdFilters);\r
+    this.filterTIs(tiFilters);\r
+    this.filterSchedule(schedFilters)\r
+  }\r
+\r
+  //this is still under the works, the purpose of this is to filter ALL the components of the dashboard if they have common filtering grounds.\r
+  filterAll(allFilters) {\r
+    //console.log('Filtering everything')\r
+    //console.log(allFilters);\r
+    if (allFilters.startDate != "" || allFilters.endDate != "") {\r
+      if (allFilters.endDate == "") {\r
+        this.testDefinitionData.Executions = this.testDefinitionData.Executions.filter(execution => (\r
+          execution.startTime >= allFilters.startDate\r
+        ))\r
+      } else if (allFilters.startDate == "") {\r
+        this.testDefinitionData.Executions = this.testDefinitionData.Executions.filter(execution => (\r
+          execution.startTime <= allFilters.endDate\r
+        ))\r
+      } else {\r
+        this.testDefinitionData.Executions = this.testDefinitionData.Executions.filter(execution => (\r
+          execution.startTime >= allFilters.startDate &&\r
+          execution.date <= allFilters.endDate\r
+        ))\r
+      }\r
+    }\r
+  }\r
+\r
+  /*\r
+    this function takes in test definition filters and queries data accordingly.\r
+    improvement needed: if the filters provided do not require querying at all, the function should narrow the currently existing data. This\r
+    will be faster than requerying in those cases and improve loading times.\r
+  */\r
+  async filterTDs(tdFilters) {\r
+\r
+    /*\r
+      checking if the filters passed in are empty, if so do nothing, if not, trigger a start call that lets the components know querying is going to begin.\r
+      these start..Call() functions are so chart components can turn on their loading indicators.\r
+    */\r
+    // if (tdFilters.startDate == "" && tdFilters.endDate == "" && tdFilters.selected.length == 0) return;\r
+    // else this.startTDExecutionCall.next(tdFilters);\r
+\r
+    // //updating filter objects attached to stats service so we can use the service getters to get them where we want in the charts component code.\r
+    // this.tdFilters = tdFilters;\r
+\r
+    // //if no range is passed in we use the default range of past 2 months.\r
+    // let startDate = tdFilters.startDate == "" ? new Date(moment().subtract(2, 'weeks').format('L')) : new Date(tdFilters.startDate);\r
+    // let endDate = tdFilters.endDate == "" ? moment().toDate() : new Date(tdFilters.endDate);\r
+    // //update service filters accordingly. \r
+    // this.tdFilters.startDate = startDate;\r
+    // this.tdFilters.endDate = endDate;\r
+    //variable of id's of the test definitions selected in the filters.\r
+    let selectedIDs = this.filters.selectedTestDefinitions.map(item => item.id);\r
+\r
+    //Promise that queries the data according the filters. We use a promise so we wait for the data to query before the components render.\r
+    await new Promise((resolve, reject) => {\r
+\r
+      //feathers query time.\r
+      this.testExecution.find({\r
+        //get the data relevant to the group.\r
+        groupId: this._groups.getGroup()["_id"],\r
+        //thse are gonna go in the data objects.\r
+        $select: [\r
+          'historicTestDefinition.testName',\r
+          'startTime',\r
+          'testResult'\r
+        ],\r
+        //UNLIMITED DATA BABY.\r
+        $limit: -1,\r
+        //sort according to ascending dates.\r
+        $sort: {\r
+          startTime: 1,\r
+        },\r
+        //select the start and end dates from the filter dates.\r
+        startTime: {\r
+          $gte: this.filters.startDate,\r
+          $lte: this.filters.endDate,\r
+        },\r
+        //select the test definitions according to the selected ones in the filters.\r
+        'historicTestDefinition._id': {\r
+          $in: selectedIDs\r
+        }\r
+      }).subscribe(result => {\r
+\r
+        //console.log(result)\r
+\r
+        //resetting real quick cuz why not.\r
+        this.testDefinitionData = {\r
+          "Executions": [],\r
+          "Results": [],\r
+        }\r
+\r
+        //pretty self explanitory.\r
+        let fetchedData = result as Array<any>;\r
+        let currentExecutionsData = this.testDefinitionData.Executions;\r
+\r
+        /*\r
+          for each new fetched json we got with the selected stuff we specified in the feathers query,\r
+          we need to organize and distribute them accordingly to our service's data objects. For example, the json objects consist of\r
+          'historicTestDefinition.testName',\r
+          'startTime',\r
+          'testResult',\r
+          test results belong in the results array, the rest needs to be organzied in the executions array,\r
+          thats what the populate methods are for.\r
+        */\r
+        for (let index in fetchedData) {\r
+          let newItem = fetchedData[index];\r
+\r
+          //for consistency we're supposed to pass current data to both we'll fix that later, but for now the piechart one just calls the current results data\r
+          //inside itself.\r
+          this.populateLineChartData(newItem, currentExecutionsData);\r
+          this.populatePieChartData(newItem);\r
+        }\r
+        resolve();\r
+      })\r
+    }).then(res => {\r
+      //console.log(res);\r
+\r
+      //trigger that querying is done and the test definition executions data has been changed. Line chart and pie chart listen for this.\r
+      this.tdExecutionsChange.next(res);\r
+    })\r
+  }\r
+\r
+  //similar stuffies. just small differences.\r
+  async filterTIs(tiFilters) {\r
+\r
+    // if (tiFilters.startDate == "" && tiFilters.endDate == "" && tiFilters.selectedTDs.length == 0 && tiFilters.selectedTIs.length == 0) return;\r
+    // else this.startTIExecutionCall.next(tiFilters);\r
+\r
+    // this.tiFilters = tiFilters;\r
+    // if (tiFilters.selectedTIs.length > 0 && tiFilters.selectedTDs.length > 0) this.tiFilters.multiLineLimit = tiFilters.selectedTIs.length + tiFilters.selectedTDs.length;\r
+    // else if (tiFilters.selectedTIs.length > 0) this.tiFilters.multiLineLimit = tiFilters.selectedTIs.length;\r
+    // else if (tiFilters.selectedTDs.length > 0) this.tiFilters.multiLineLimit = tiFilters.selectedTDs.length;\r
+    // else this.tiFilters.multiLineLimit = 5;\r
+\r
+    // let startDate = tiFilters.startDate == "" ? new Date(moment().subtract(2, 'weeks').format('L')) : new Date(tiFilters.startDate);\r
+    // let endDate = tiFilters.endDate == "" ? moment().toDate() : new Date(tiFilters.endDate);\r
+\r
+    // this.tiFilters.startDate = startDate;\r
+    // this.tiFilters.endDate = endDate;\r
+    // console.log(tiFilters.selectedTDs)\r
+\r
+    await new Promise((resolve, reject) => {\r
+      this.testExecution.find({\r
+        groupId: this._groups.getGroup()["_id"],\r
+        $limit: -1,\r
+        startTime: {\r
+          $gte: this.filters.startDate,\r
+          $lte: this.filters.endDate,\r
+        },\r
+        $select: [\r
+          'startTime',\r
+          'endTime',\r
+          'historicTestDefinition.testName',\r
+          'historicTestInstance.testInstanceName',\r
+        ],\r
+        $or: [\r
+          {\r
+            'historicTestDefinition._id': {\r
+              $in: tiFilters.selectedTDs\r
+            }\r
+          },\r
+          {\r
+            'historicTestInstance._id': {\r
+              $in: tiFilters.selectedTIs\r
+            }\r
+          }\r
+        ]\r
+\r
+      }).subscribe(result => {\r
+        this.testInstanceData = {\r
+          "Executions": [],\r
+          "Individual_Exec": []\r
+        }\r
+        //console.log(result)\r
+        let fetchedData = result as Array<any>;\r
+        for (let index in fetchedData) {\r
+          let newItem = fetchedData[index];\r
+          this.populateBarChartData(newItem);\r
+          this.populateMultiLineChartData(newItem);\r
+        }\r
+        this.testInstanceData.Executions.sort((a, b) => b.Count - a.Count);\r
+        this.testInstanceData.Individual_Exec.sort((a, b) => b.total - a.total);\r
+\r
+        resolve();\r
+      })\r
+    }).then(res => {\r
+      this.tiExecutionsChange.next(res);\r
+      //console.log(this.testInstanceData.Executions);\r
+    })\r
+\r
+  }\r
+\r
+  //similar stuffies just smol differneces.\r
+  async filterSchedule(schedFilters) {\r
+\r
+    //console.log(schedFilters);\r
+    // this.scheduleFilters = schedFilters;\r
+    // //console.log(schedFilters.selectedInstances);\r
+\r
+    // if (schedFilters.startDate == "" &&\r
+    //   schedFilters.endDate == "" &&\r
+    //   schedFilters.selectedInstances.length == 0) {\r
+    //   return;\r
+    // } else this.startScheduleCall.next(schedFilters);\r
+\r
+    // let startDate = schedFilters.startDate == "" ? new Date(moment().toDate()) : new Date(schedFilters.startDate);\r
+    // let endDate = schedFilters.endDate == "" ? new Date(moment().add(2, 'weeks').format('L')) : new Date(schedFilters.endDate);\r
+\r
+    // this.scheduleFilters.startDate = startDate;\r
+    // this.scheduleFilters.endDate = endDate;\r
+\r
+    \r
+    this.schedService.find({\r
+      $select: ["data.testSchedule._testInstanceId", 'nextRunAt'],\r
+      $limit: -1,\r
+    }).subscribe(result => {\r
+      this.scheduledTests = [];\r
+      //console.log(result);\r
+      let fetchedData = result as Array<any>;\r
+      let resultingData: Array<any> = fetchedData;\r
+      if (schedFilters.selectedInstances.length !== 0) {\r
+        resultingData = fetchedData.filter(el => {\r
+          let fetchedID = el.data.testSchedule._testInstanceId;\r
+          let selectedIDs = schedFilters.selectedInstances as Array<any>;\r
+          let condition = selectedIDs.includes(fetchedID.toString());\r
+          //console.log(condition);\r
+          return condition;\r
+        })\r
+      }\r
+\r
+      resultingData = resultingData.filter(el => {\r
+        let schedDate = new Date(el.nextRunAt);\r
+        return schedDate >= this.filters.startDate && schedDate <= this.filters.endDate;\r
+      })\r
+\r
+      for (let index in resultingData) {\r
+        let checkIfTestBelongsToUserGroup = this.testInstances.findIndex(testInstances => testInstances.id === resultingData[index].data.testSchedule._testInstanceId);\r
+        if (checkIfTestBelongsToUserGroup >= 0) {\r
+          if (resultingData[index].nextRunAt) {\r
+            let d1 = new Date(resultingData[index].nextRunAt);\r
+            this.scheduledTests.push({\r
+              id: resultingData[index].data.testSchedule._testInstanceId,\r
+              name: this.testInstances[checkIfTestBelongsToUserGroup].name,\r
+              dateExec: d1.toDateString(),\r
+              timeExec: d1.toLocaleTimeString()\r
+            })\r
+          }\r
+        }\r
+      }\r
+      this.scheduleChange.next();\r
+    });\r
+    \r
+\r
+\r
+  }\r
+\r
+  //getters for the filter objects.\r
+  // getTDFilters() {\r
+  //   return this.tdFilters;\r
+  // }\r
+\r
+  // getTIFilters() {\r
+  //   return this.tiFilters;\r
+  // }\r
+\r
+  // getSchedFilters() {\r
+  //   return this.scheduleFilters;\r
+  // }\r
+\r
+  calcTime(execution) {\r
+    var end = new Date(execution.endTime);\r
+    var start = new Date(execution.startTime);\r
+    var executionTime = (end.getTime() - start.getTime()) / 1000;\r
+    return executionTime;\r
+  }\r
+\r
+  //This function takes an execution that was retrieved from the Database and takes the data it needs for the line chart. \r
+  populateLineChartData(execution, currentData) {\r
+    let executionDate = new Date(execution.startTime)\r
+\r
+    // Looks to see if the date already has an execution./\r
+    let indexOfItemFound = currentData.findIndex((element) => {\r
+\r
+      return (\r
+        executionDate.getFullYear() === element.date.getFullYear() &&\r
+        executionDate.getMonth() === element.date.getMonth() &&\r
+        executionDate.getDate() === element.date.getDate()\r
+      )\r
+    })\r
+\r
+    //If the date is not found. Push a new date into the array with a count of one\r
+    if (currentData[indexOfItemFound] == undefined) {\r
+      currentData.push({\r
+        date: new Date(executionDate.getFullYear(), executionDate.getMonth(), executionDate.getDate()),\r
+        count: 1\r
+      })\r
+    // else update the count\r
+    } else currentData[indexOfItemFound].count += 1;\r
+  }\r
+\r
+\r
+  //Takes an execution and  pushes the result/count or updates the count. For the Pie Chart\r
+  populatePieChartData(execution) {\r
+\r
+    //Check if result is already present in the array. \r
+    var checkIfPresent = this.testDefinitionData.Results.find(Results => Results.Name === execution.testResult);\r
+   \r
+    //If not present, add it to TOPSTATs with a default count of 1.    \r
+    if (!checkIfPresent) {\r
+      \r
+      var color;\r
+      //Set the color for the pie chart.\r
+      if (execution.testResult == "COMPLETED"){\r
+        color = "#0D47A1";\r
+      }else if (execution.testResult == "FAILED")\r
+        color = "#DD2C00";\r
+      else if (execution.testResult == "UNKNOWN")\r
+        color = "#C4CBD4";\r
+      else if (execution.testResult == "SUCCESS")\r
+        color = "#42d660";\r
+      else if (execution.testResult == "success")\r
+        color = "#42d660";\r
+      else if (execution.testResult == "STARTED")\r
+        color = "#29E3E8";\r
+      else if (execution.testResult == "FAILURE")\r
+        color = "#FC9100";\r
+      else if (execution.testResult == "STOPPED")\r
+        color = "#900C3F";\r
+      else if (execution.testResult == "TERMINATED")\r
+        color = "#AC00FC";\r
+      else if (execution.testResult == "UNAUTHORIZED")\r
+        color = "#7A6E6E";\r
+      else if (execution.testResult == "DOES_NOT_EXIST")\r
+        color = "#000000";\r
+      else if (execution.testResult == "ERROR")\r
+        color = "#eb2acd"\r
+      else if (execution.testResult == "WORKFLOW_ERROR")\r
+        color = "#194f24"\r
+      else\r
+        color = "#000000".replace(/0/g, function () { return (~~(Math.random() * 16)).toString(16); });\r
+\r
+      //Push the execution with the count and color.\r
+      this.testDefinitionData.Results.push({ Name: execution.testResult, Count: 1, color: color });\r
+    } else {\r
+\r
+      //Find index of the testResult and update the count by 1.\r
+      var position = this.testDefinitionData.Results.findIndex(Results => Results.Name === execution.testResult);\r
+      this.testDefinitionData.Results[position].Count += 1;\r
+    }\r
+  }\r
+\r
+  //Takes an execution and pushes result into the barchart. \r
+  populateBarChartData(execution) {\r
+\r
+    //check if test instance is present in the array. \r
+    var checkIfPresent = this.testInstanceData.Executions.find(Instances => Instances.id === execution.historicTestInstance._id);\r
+\r
+    //calculates the time it took for the execution/\r
+    var executionTime = this.calcTime(execution);\r
+    \r
+    //If execution is not present, push the test instance with a count of 1.\r
+    if (!checkIfPresent) {\r
+      //If not present, add it to testInstanceData with a default count of 1. \r
+\r
+      this.testInstanceData.Executions.push({\r
+        Name: execution.historicTestInstance.testInstanceName,\r
+        id: execution.historicTestInstance._id,\r
+        testResult: execution.testResult,\r
+        executionTime: executionTime,\r
+        Count: 1,\r
+        Average: executionTime\r
+      });\r
+    } else {\r
+      // If Present update count and execution time. \r
+      var position = this.testInstanceData.Executions.findIndex(Instances => Instances.id === execution.historicTestInstance._id);\r
+      this.testInstanceData.Executions[position].Count += 1;\r
+      this.testInstanceData.Executions[position].executionTime += executionTime;\r
+      this.testInstanceData.Executions[position].Average = this.testInstanceData.Executions[position].executionTime / this.testInstanceData.Executions[position].Count;\r
+    }\r
+\r
+  }\r
+\r
+  //queries data for the scheduled tests. \r
+  getScheduledTests(groupId) {\r
+\r
+    //Queries a list of test instances by group ID\r
+    this.testInstanceService.find({\r
+      groupId: groupId['_id'],\r
+      $select: ["_id", "testInstanceName", "groupId"],\r
+      $limit: -1\r
+    }).subscribe(result => {\r
+\r
+      //Iterate through the list and add the test instances to the list. \r
+      for (var index in result) {\r
+        var checkIfPresent = this.testInstances.find(id => id === result[index]._id);\r
+        if (!checkIfPresent)\r
+          this.testInstances.push({ id: result[index]._id, name: result[index].testInstanceName });\r
+      }\r
+    });\r
+\r
+    //Queries all of the scheduled tests. \r
+    this.schedService.find({\r
+\r
+      $select: ["data.testSchedule._testInstanceId", 'nextRunAt'],\r
+      $limit: -1,\r
+      $sort: {\r
+        startTime: 1\r
+      },\r
+\r
+    }).subscribe(result => {\r
+\r
+      this.scheduledTests = [];\r
+      for (var index in result) {\r
+\r
+        //If the scheduled testinstance is owned by the group, push the result. \r
+        var checkIfTestBelongsToUserGroup = this.testInstances.findIndex(testInstances => testInstances.id === result[index].data.testSchedule._testInstanceId);\r
+        if (checkIfTestBelongsToUserGroup >= 0) {\r
+\r
+          //If the next run at is valid, the test is scheduled.\r
+          if (result[index].nextRunAt) {\r
+            let d1 = new Date(result[index].nextRunAt);\r
+            this.scheduledTests.push({\r
+              id: result[index].data.testSchedule._testInstanceId,\r
+              name: this.testInstances[checkIfTestBelongsToUserGroup].name,\r
+              dateExec: d1.toDateString(),\r
+              timeExec: d1.toLocaleTimeString()\r
+            });\r
+          }\r
+        }\r
+      }\r
+    });\r
+  }\r
+\r
+  //populate multi line chart\r
+  populateMultiLineChartData(execution) {\r
+\r
+    let executionDate = new Date(execution.startTime)\r
+    let currentData = this.testInstanceData.Individual_Exec;\r
+    let count = 1;\r
+    //find if Instance is already present in the array. \r
+    let position = this.testInstanceData.Individual_Exec.findIndex(Instances => Instances.id === execution.historicTestInstance._id);\r
+\r
+    //First execution for this instance\r
+    if (currentData[position] == undefined) {\r
+      currentData.push({\r
+        testInstanceName: execution.historicTestInstance.testInstanceName,\r
+        testDefinitionName: execution.historicTestDefinition.testDefintionName,\r
+        id: execution.historicTestInstance._id,\r
+        dateData: [{ date: executionDate, count: count, name: execution.historicTestInstance.testInstanceName }],\r
+        total: 1\r
+      })\r
+      //execution already present\r
+    } else {\r
+      //find index of Date\r
+      let indexOfDate = currentData[position].dateData.findIndex((element) => {\r
+        return (\r
+          executionDate.getFullYear() === element.date.getFullYear() &&\r
+          executionDate.getMonth() === element.date.getMonth() &&\r
+          executionDate.getDate() === element.date.getDate()\r
+        )\r
+      });\r
+\r
+      //Check if the exeuction date is valid for this instance. If it is not present, push a new date and count. \r
+      if (currentData[position].dateData[indexOfDate] == undefined) {\r
+        let count = 1;\r
+        //Push the new Date\r
+        currentData[position].dateData.push({ date: executionDate, count: count, name: execution.historicTestInstance.testInstanceName, id: execution.historicTestInstance._id});\r
+        currentData[position].total++;\r
+      } else {\r
+        //date is already present\r
+        currentData[position].dateData[indexOfDate].count++;\r
+        currentData[position].total++;\r
+      }\r
+    }\r
+  }\r
+  //Gets the initial data for the default page. \r
+  async getDefaultData(group, query?) { \r
+    if(!group){\r
+      return;\r
+    }\r
+    \r
+    this.scheduledTests = [];\r
+\r
+    this.startDefaultData.next(group);\r
+    let groupId = group;\r
+    //let startDate = moment().subtract(2, 'weeks').toDate();\r
+    \r
+    //query sheduled tests\r
+    //this.getScheduledTests(group);\r
+\r
+    if(!query){\r
+      query = {\r
+        groupId: groupId['_id'],\r
+        $select: [\r
+          'startTime',\r
+          'endTime',\r
+          "historicTestDefinition._id",\r
+          "historicTestDefinition.testName",\r
+          "historicTestInstance._id",\r
+          "historicTestInstance.testInstanceName",\r
+          "testHeadResults.startTime",\r
+          "testHeadResults.endTime",\r
+          "testHeadResults.testHeadName",\r
+          "testHeadResults.testHeadId",\r
+          "testHeadResults.testHeadGroupId",\r
+          "testHeadResults.statusCode",\r
+          'testResult'\r
+        ],\r
+        $limit: -1,\r
+        $sort: {\r
+          startTime: 1\r
+        },\r
+        startTime: {\r
+          $gte: this.filters.startDate,\r
+          $lte: this.filters.endDate\r
+        }\r
+      }\r
+    }\r
+\r
+    //Query test Executions\r
+    await new Promise((resolve, reject) => {\r
+      this.testExecution.find(query).subscribe(result => {\r
+\r
+        //reset arrays\r
+        this.testDefinitionData = {\r
+          //Executions Array thats made of objects with date, tdName, result\r
+          "Executions": [],\r
+          "Results": [],\r
+        }\r
+        this.testInstanceData = {\r
+          "Executions": [],\r
+          "Individual_Exec": []\r
+        };\r
+\r
+        this.executionList = result as Array<any>;\r
+        let currentData = this.testDefinitionData.Executions;\r
+\r
+        \r
+\r
+        //iterate through the results and populate the appropriate arrays. \r
+        for (let index in this.executionList) {\r
+\r
+          let newItem = this.executionList[index];\r
+\r
+          //get default line chart Data\r
+          this.populateLineChartData(newItem, currentData);\r
+\r
+          //get pie chart data. \r
+          this.populatePieChartData(newItem);\r
+\r
+          //Get BarChart Data\r
+          //this.populateBarChartData(newItem);\r
+\r
+          //get multi line chart data\r
+          //this.populateMultiLineChartData(newItem);\r
+        }\r
+\r
+        //sort the two arrays descending.\r
+        this.testInstanceData.Executions.sort((a, b) => b.Count - a.Count);\r
+        this.testInstanceData.Individual_Exec.sort((a, b) => b.total - a.total);\r
+        resolve();\r
+      }, err => {\r
+        reject(err);\r
+      });\r
+    }).then(res => {\r
+\r
+      // this.tdFilters = {\r
+      //   startDate: moment().subtract(2, 'weeks').toDate(),\r
+      //   endDate: moment().toDate(),\r
+      //   selected: [],\r
+      // };\r
+      // this.tiFilters = {\r
+      //   startDate: moment().subtract(2, 'weeks').toDate(),\r
+      //   endDate: moment().toDate(),\r
+      //   selectedTDs: [],\r
+      //   selectedTIs: [],\r
+      //   multiLineLimit: 5,\r
+      // }\r
+      this.finishedDefaultData.next(res);\r
+    })\r
+  }\r
+\r
+\r
+}\r