Last active
October 24, 2018 10:18
-
-
Save janakprajapati2112/1425202b5a1141a24cf96b62fbbce67c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Subject | |
} from 'rxjs'; | |
import { | |
Component, | |
OnInit, | |
ViewEncapsulation, | |
AfterViewInit, | |
Input, | |
Output, | |
ComponentFactoryResolver, | |
ViewChild, | |
ViewContainerRef, | |
Directive, | |
Inject, | |
QueryList, | |
ViewChildren, | |
Injectable, | |
ChangeDetectionStrategy, | |
ChangeDetectorRef | |
} from '@angular/core'; | |
import { | |
Http, | |
RequestMethod, | |
RequestOptions, | |
Response, | |
ResponseOptions, | |
XHRBackend, | |
Headers | |
} from "@angular/http"; | |
import { | |
Observable | |
} from 'rxjs'; | |
import { | |
delay, | |
map | |
} from 'rxjs/operators'; | |
import 'rxjs/Rx'; | |
import { | |
ApplicationApiService | |
} from '../_services/api.service'; | |
@Injectable() | |
@Component({ | |
selector: 'dynamic-component', | |
template: ` | |
<div class="snippet" *ngIf="reportLoading === true"> | |
<div class="stage"> | |
<div class="dot-typing"></div> | |
</div> | |
</div> | |
<ng-container *ngFor="let rData of splitByData; let i = index; last as isLast"> | |
<div class="row report-row" > | |
<div class="col-4" [ngStyle]="{'padding-left': calculateTextPadding(nextSplit.id) }"> | |
<button | |
class="btn btn-sm" | |
*ngIf="checkIfHaveMoreSplits(nextSplit.id,splitOptions) !== 0 && rData.isCollapsed == true" | |
(click)="splitData(rowWiseFilterObj(rData,nextSplit.id,selectedRow),nextSplit.id,selectedFilters,splitOptions,i,rData,selectedDate)">+</button> | |
<button | |
class="btn btn-sm" | |
*ngIf="checkIfHaveMoreSplits(nextSplit.id,splitOptions) !== 0 && rData.isCollapsed == false" | |
(click)="removeDynamicComponent(rData,i)" | |
>-</button> | |
<span *ngIf="nextSplit.id !== '__time'">{{rData[nextSplit.id]}}</span> | |
<span *ngIf="nextSplit.id === '__time'">{{ rData[nextSplit.id] | date:'dd-MM-yyyy HH:mm:ss Z'}}</span> | |
</div> | |
<div class="col-2">{{convertToDecimals(rData.wins,2)}}</div> | |
<div class="col-2">{{convertToDecimals(rData.conversions,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.cost,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.bids,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.impressions,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.rev_payout,2)}}</div> | |
</div> | |
<div *ngIf="isLast">{{altrows("#ffffff","#f5f5f5")}}</div> | |
<ng-template #dynamic ></ng-template> | |
</ng-container> | |
` | |
}) | |
export class DynamicComponent implements OnInit, AfterViewInit { | |
@Input() selectedRow: any; | |
@Input() nextSplit: any; | |
@Input() selectedFilters: any; | |
@Input() splitOptions: any; | |
@Input() splitByData: any; | |
@Input() rowData: any; | |
@Input() reportLoading: any; | |
@Input() selectedDate: any; | |
factoryResolver; | |
rootViewContainer; | |
@ViewChildren('dynamic', { | |
read: ViewContainerRef | |
}) viewContainerRef: QueryList<ViewContainerRef> | |
constructor( | |
@Inject(ComponentFactoryResolver) factoryResolver, | |
private _apis: ApplicationApiService, | |
private cd: ChangeDetectorRef | |
) { | |
this.factoryResolver = factoryResolver | |
} | |
ngOnInit() { | |
} | |
ngAfterViewInit() { | |
} | |
setRootViewContainerRef(viewContainerRef) { | |
this.rootViewContainer = viewContainerRef | |
} | |
addDynamicComponent(selectedRow, nextSplit, selectedFilters, splitOptions, sRow, selectedDate) { | |
const factory = this.factoryResolver | |
.resolveComponentFactory(DynamicComponent) | |
const component = factory | |
.create(this.rootViewContainer.parentInjector) | |
component.instance.selectedRow = selectedRow; | |
component.instance.nextSplit = nextSplit; | |
component.instance.selectedFilters = selectedFilters; | |
component.instance.splitOptions = splitOptions; | |
component.instance.selectedDate = selectedDate; | |
var a = JSON.parse(JSON.stringify(selectedFilters)); | |
var b = JSON.parse(JSON.stringify(selectedRow)); | |
a.filter(function(o1) { | |
return b.some(function(o2) { | |
if (o1.id === o2.id) { | |
o1.values = o2.values; | |
} | |
}); | |
}); | |
//Find values that are in result1 but not in result2 | |
var uniqueResultOne = a.filter(function(obj) { | |
return !b.some(function(obj2) { | |
return obj.id == obj2.id; | |
}); | |
}); | |
//Find values that are in result2 but not in result1 | |
var uniqueResultTwo = b.filter(function(obj) { | |
return !a.some(function(obj2) { | |
return obj.id == obj2.id; | |
}); | |
}); | |
//Combine the two arrays of unique entries | |
var result = a.concat(uniqueResultOne.concat(uniqueResultTwo)); | |
result = result.filter((s1, pos, arr) => arr.findIndex((s2) => s2.id === s1.id) === pos); | |
this.reportLoading = true; | |
this._apis.getReportData(nextSplit.id, this.getApiFilters(result), selectedDate).subscribe(response => { | |
if (response.status == 1200) { | |
response.data.split_by_data.map(function(obj) { | |
obj.isCollapsed = true; | |
return obj; | |
}); | |
sRow.isCollapsed = false; | |
component.instance.splitByData = response.data.split_by_data; | |
this.reportLoading = false; | |
} | |
}) | |
this.rootViewContainer.insert(component.hostView) | |
} | |
getApiFilters(selectedFilters) { | |
var apiFilters: any = [{}]; | |
for (var i = 0; i < selectedFilters.length; i++) { | |
if (selectedFilters[i].values.length > 0) { | |
var k; | |
k = selectedFilters[i].id | |
apiFilters[0][k] = selectedFilters[i].values | |
} | |
} | |
return apiFilters[0]; | |
} | |
checkIfHaveMoreSplits(c, splitOptions) { | |
if (splitOptions.length > 0) { | |
var index = splitOptions.findIndex(function(v) { | |
return v.id == c | |
}) | |
if (typeof (splitOptions[index + 1]) != "undefined") { | |
return splitOptions[index + 1]; | |
} else { | |
return 0; | |
} | |
} | |
} | |
splitData(obj, cSplit, sFilters, splitOptions, index, sRow, selectedDate) { | |
var nextSplit = this.checkIfHaveMoreSplits(cSplit, splitOptions); | |
this.setRootViewContainerRef(this.viewContainerRef.toArray()[index]); | |
this.addDynamicComponent(obj, nextSplit, sFilters, splitOptions, sRow, selectedDate); | |
} | |
rowWiseFilterObj(row, split, prev) { | |
if (prev.length == 0) { | |
var arr = []; | |
var obj = { | |
id: split, | |
label: split, | |
values: [row[split]] | |
} | |
arr.push(obj); | |
return arr; | |
} else { | |
var obj = { | |
id: split, | |
label: split, | |
values: [row[split]] | |
} | |
prev.push(obj); | |
return prev | |
} | |
} | |
removeDynamicComponent(rowData, index) { | |
this.viewContainerRef.toArray()[index].clear(); | |
rowData.isCollapsed = true; | |
this.altrows("#ffffff", "#f5f5f5"); | |
} | |
convertToDecimals(input, decimals) { | |
var exp, rounded, | |
suffixes = ['K', 'M', 'B', 'T', 'P', 'E']; | |
if (input < 1000) { | |
return parseFloat(input).toFixed(2);; | |
} | |
exp = Math.floor(Math.log(input) / Math.log(1000)); | |
return (input / Math.pow(1000, exp)).toFixed(decimals) + suffixes[exp - 1]; | |
} | |
calculateTextPadding(id) { | |
var index = this.splitOptions.findIndex(function(v) { | |
return v.id == id | |
}) | |
if (typeof (index) != "undefined") { | |
return index * 40 + "px" | |
} else { | |
return "0px"; | |
} | |
} | |
altrows(firstcolor, secondcolor) { | |
var tableElements = document.getElementsByClassName("report-row"); | |
for (var j = 0; j < tableElements.length; j++) { | |
if (j % 2 == 0) { | |
(tableElements[j]).className = "row report-row odd"; | |
} | |
else { | |
(tableElements[j]).className = "row report-row even"; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--<input type="text" ngxDaterangepickerMd | |
[locale]="{applyLabel: 'ok', format: 'DD-MM-YYYY'}" | |
startKey="start" | |
endKey="end" | |
[(ngModel)]="selected" [ranges]="ranges"/> --> | |
<div class="row text-right" style="margin-top: 10px;"> | |
<div class="col-md-6"></div> | |
<div class="col-md-6 text-right" style="padding-right: 0px;"> | |
<input type="hidden" | |
ngxDaterangepickerMd | |
[(ngModel)]="selectedDate" | |
[showCustomRangeLabel]="true" | |
[alwaysShowCalendars]="true" | |
[ranges]="ranges" | |
[linkedCalendars]="false" | |
[isInvalidDate] = "isInvalidDate" | |
placeholder="Select please..." | |
[keepCalendarOpeningWithRange]="keepCalendarOpeningWithRange" | |
[showRangeLabelOnInput]="showRangeLabelOnInput" | |
(rangeClicked)="datesUpdated($event)" | |
(datesUpdated)="datesUpdated($event)"/> | |
<a href="javascript:;" class="ngx-daterangepicker-action waves-effect waves-light btn btn-sm btn-primary text-right" (click)="openDatePicker($event)" style="font-size: 14px;"> | |
{{ selectedDate.startDate | date:'dd/MM/yyyy'}} to {{ selectedDate.endDate | date:'dd/MM/yyyy'}}<i class="fa fa-calendar" style=" | |
margin: 10px 7px; | |
"></i> </a> | |
</div> | |
</div> | |
<div class="snippet" *ngIf="reportLoading === true"> | |
<div class="stage"> | |
<div class="dot-typing"></div> | |
</div> | |
</div> | |
<div class="row filter-row" style="border-bottom: 1px solid #ccc; margin-top: 20px;"> | |
<div class="general-selected-filters"> | |
Filter by: | |
<div class="filter-item" *ngFor="let filter of sFilters"> | |
<div class="clause" *ngIf="filter.values.length > 0"> | |
<span class="attribute" (click)="getFilterValues(filter,$event)">{{ filter.label }} :</span> | |
<span class="value" *ngIf="filter.values.length < 3" (click)="getFilterValues(filter,$event)">{{ arrToString(filter.values) | |
}}</span> | |
<span class="value" *ngIf="filter.values.length >= 3" (click)="getFilterValues(filter,$event)">{{ filter.values | slice:0:2 }} +{{ filter.values.length-2 }}</span> | |
<span class="remove-icon" ><i class="fa fa-times-circle" (click)="updateFilters(filter,'d')"></i></span> | |
</div> | |
</div> | |
</div> | |
<div class="addfilter btn btn-sm" (click)="openFilterSelection($event)" style="margin: -2px 0px; | |
text-align: right; | |
right: 10px; | |
position: absolute;"> | |
<i class="fa fa-plus"></i> | |
</div> | |
</div> | |
<div class="row split-row"> | |
<div class="general-selected-filters"> | |
Split by: | |
<div class="filter-item" *ngFor="let filter of splitOpt"> | |
<div class="clause"> | |
<span class="attribute">{{ filter.text }}</span> | |
<span class="remove-icon"><i class="fa fa-times-circle" (click)="updateFilters(filter,'s')"></i></span> | |
</div> | |
</div> | |
</div> | |
<div class="addfilter btn btn-sm" (click)="openSplitSelection($event)" style="margin: 1px 0px; | |
text-align: right; | |
right: 10px; | |
position: absolute;"> | |
<i class="fa fa-plus"></i> | |
</div> | |
</div> | |
<div class="popover-overlay-container" *ngIf="filterSelection || splitSelection " > | |
<div class="popover-overlay" (click)="hidePopup()"></div> | |
<div></div> | |
</div> | |
<div class="add-filter-menu" *ngIf="filterSelection" [ngStyle]="{'top': posY, 'left': posX}" > | |
<div class="add-filter-menu-results-container" > | |
<div class="attribute-selector" *ngIf="dimentionSelection"> | |
<div class="clearable-input" placeholder="Search"> | |
<input placeholder="Search" type="text" [(ngModel)]="query"> | |
<div class="delete-button"></div> | |
</div> | |
<ul class="menu-options attribute-choices" > | |
<li *ngFor="let dimention of filterDimentions | searchfilter: query" class="" (click)="getFilterValues(dimention)">{{ dimention.text }}</li> | |
</ul> | |
</div> | |
<div class="value-selector" *ngIf="dValueSelection"> | |
<div class="clearable-input" > | |
<input placeholder="Search" type="text" name="searchText" [(ngModel)]="q" (input)="onSearchChange()"> | |
<div class="delete-button" ></div> | |
</div> | |
<div class="list-cont"> | |
<div class="dvalue-loading" *ngIf="appLoading==true"> | |
<div class="m-loader m-loader--primary" style="width: 30px; display: inline-block;"></div> | |
</div> | |
<ul class="menu-options attribute-values" > | |
<li *ngFor="let dimention of filterDimentionsValues" class="" (click)="selectFilters(dimention);"> | |
<label class="m-checkbox app-checkbox" *ngIf="currentSelectedDimension !== '__time'"> | |
<input type="checkbox" (click)="selectFilters(dimention)" [checked]="((-1 !== checkIfDimvalueExists(dimention)) ? 'checked' : '')"/> | |
{{ dimention[currentSelectedDimension]}} | |
<span></span> | |
</label> | |
<label class="m-checkbox app-checkbox" *ngIf="currentSelectedDimension === '__time'"> | |
<input type="checkbox" (click)="selectFilters(dimention)" [checked]="((-1 !== checkIfDimvalueExists(dimention)) ? 'checked' : '')"/> | |
{{ dimention[currentSelectedDimension] | date:'dd-MM-yyyy HH:mm:ss Z'}} | |
<span></span> | |
</label> | |
</li> | |
</ul> | |
<!-- <div class="no-results">No results</div> --> | |
</div> | |
<div class="bottom-bar text-right" > | |
<button class="apply-button btn btn-sm btn-danger " (click)="goBackToDimensions()" style="position: absolute; | |
top: 6px; | |
right: 77px; | |
height: 28px; | |
font-size: 13px;">Back</button> | |
<button class="apply-button btn btn-sm btn-primary" (click)="getReport()">Apply</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="add-filter-menu" *ngIf="splitSelection" [ngStyle]="{'top': posY, 'left': posX}" > | |
<div class="add-filter-menu-results-container" > | |
<div class="attribute-selector" *ngIf="dimentionSelection"> | |
<div class="clearable-input" placeholder="Search"> | |
<input placeholder="Search" type="text" [(ngModel)]="query"> | |
<div class="delete-button"></div> | |
</div> | |
<ul class="menu-options attribute-choices" > | |
<li *ngFor="let dimention of filterDimentions | searchfilter: query" class="" (click)="selectSplitDimention(dimention)" >{{ dimention.text }}</li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
<div class="chart-container" > | |
<div class="report-nav" style="margin-top: 30px; margin-bottom: 30px;"> | |
<ul class="nav nav-pills nav-justified"> | |
<li class="reporting_nav"><a href="javascript:void(0)" class="plotgraph" data-label="Clicks" data-yparam="totalClicks">3.88M<span>Clicks</span></a></li> | |
<li class="reporting_nav active"><a href="javascript:void(0)" class="plotgraph" data-label="Conversions" data-yparam="totalConversions">742<span>Conversions</span></a></li> | |
<li class="reporting_nav"><a href="javascript:void(0)" class="plotgraph" data-label="Revenue" data-yparam="totalRevenueOg">$ 1.16k <span>Revenue</span></a></li> | |
<li class="reporting_nav"><a href="javascript:void(0)" class="plotgraph" data-label="Payout" data-yparam="totalRevenue">$ 823.43 <span>Payout</span></a></li> | |
<li class="reporting_nav"><a href="javascript:void(0)" class="plotgraph" data-label="CR" data-yparam="conversionRatio">0.02%<span>CR</span></a></li> | |
<li class="reporting_nav"><a href="javascript:void(0)" class="plotgraph" data-label="RPM" data-yparam="epc">$ 0.30<span>RPM</span></a></li> | |
<li class="reporting_nav" style="border-right:1px solid #eaeaea;"><a href="javascript:void(0)" class="plotgraph" data-label="Profit" data-yparam="profit">$ 341.15<span>Profit</span></a></li> | |
</ul> | |
</div> | |
<highcharts-chart | |
[Highcharts]="Highcharts" | |
[constructorType]="chartConstructor" | |
[options]="chartOptions" | |
[callbackFunction]="chartCallback" | |
[(update)]="updateFlag" | |
[oneToOne]="oneToOneFlag" | |
[runOutsideAngular]="runOutsideAngularFlag" | |
style="width: 100%; height: 350px; display: block;" | |
></highcharts-chart> | |
</div> | |
<div class="report-table-header" style="margin-top: 30px;" *ngIf="reportData.length > 0"> | |
<div class="row report-row-header" > | |
<div class="col-4" style="padding-left: 5px;">#</div> | |
<div class="col-2">Impressions</div> | |
<div class="col-2">Conversion</div> | |
<div class="col-1">Bids</div> | |
<div class="col-1">Wins</div> | |
<div class="col-1">Cost</div> | |
<div class="col-1">Rev Payout</div> | |
</div> | |
</div> | |
<div class="report-table-container" > | |
<ng-container *ngFor="let rData of reportData; let i = index; last as isLast" > | |
<div class="row report-row" > | |
<div class="col-4" style="padding-left: 5px;"> | |
<button | |
class="btn btn-sm" | |
*ngIf="checkIfHaveMoreSplits(this.splitOpt[0].id) !== 0 && rData.isCollapsed == true" | |
(click)="splitData(rowWiseFilterObj(rData,this.splitOpt[0].id),this.splitOpt[0].id,sFilters,splitOpt,i,rData,selectedDate)" | |
row="rData">+</button> | |
<button | |
class="btn btn-sm" | |
*ngIf="checkIfHaveMoreSplits(this.splitOpt[0].id) !== 0 && rData.isCollapsed == false" | |
(click)="removeDynamicComponent(rData,i)" | |
>-</button> | |
<span *ngIf="this.splitOpt[0].id !== '__time'">{{rData[this.splitOpt[0].id]}}</span> | |
<span *ngIf="this.splitOpt[0].id === '__time'">{{ rData[this.splitOpt[0].id] | date:'dd-MM-yyyy HH:mm:ss Z'}}</span> | |
</div> | |
<div class="col-2">{{convertToDecimals(rData.impressions,2)}}</div> | |
<div class="col-2">{{convertToDecimals(rData.conversions,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.bids,2)}}</div> | |
<div class="col-1" >{{convertToDecimals(rData.wins,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.cost,2)}}</div> | |
<div class="col-1">{{convertToDecimals(rData.rev_payout,2)}}</div> | |
</div> | |
<div *ngIf="isLast">{{altrows("#ffffff","#f5f5f5")}}</div> | |
<ng-template #dynamic ></ng-template> | |
</ng-container> | |
</div> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Injectable, | |
ChangeDetectionStrategy, | |
ChangeDetectorRef, | |
Renderer2, | |
Inject, | |
QueryList, | |
ViewChildren, | |
} from '@angular/core'; | |
import { | |
Subject | |
} from 'rxjs'; | |
import { | |
Component, | |
OnInit, | |
ViewEncapsulation, | |
AfterViewInit, | |
Input, | |
Output, | |
ComponentFactoryResolver, | |
ViewChild, | |
ViewContainerRef, | |
Directive | |
} from '@angular/core'; | |
import { | |
ModalDismissReasons, | |
NgbDateStruct, | |
NgbModal, | |
NgbRatingConfig | |
} from "@ng-bootstrap/ng-bootstrap"; | |
import { | |
distinctUntilChanged, | |
debounceTime, | |
switchMap, | |
tap | |
} from 'rxjs/operators' | |
import { | |
Http, | |
RequestMethod, | |
RequestOptions, | |
Response, | |
ResponseOptions, | |
XHRBackend, | |
Headers | |
} from "@angular/http"; | |
import { | |
ActivatedRoute | |
} from '@angular/router'; | |
import { | |
ScriptLoaderService | |
} from '../_services/script-loader.service'; | |
import { | |
ConfigService | |
} from '../_services/config.service'; | |
import { | |
ApplicationApiService | |
} from '../_services/api.service'; | |
import { | |
ToastrService | |
} from 'ngx-toastr'; | |
import { | |
Helpers | |
} from '../helpers'; | |
import swal from 'sweetalert2'; | |
import { | |
Service | |
} from './service'; | |
import * as moment from 'moment'; | |
import { DaterangepickerComponent, DaterangepickerDirective } from 'ngx-daterangepicker-material'; | |
import * as Highcharts from 'highcharts'; | |
@Component({ | |
selector: 'app-reports', | |
templateUrl: './template/reports.component.html', | |
encapsulation: ViewEncapsulation.None, | |
// changeDetection: ChangeDetectionStrategy.OnPush | |
}) | |
@Injectable() | |
export class ReportsComponent implements OnInit, AfterViewInit { | |
filterSelection: any = false; | |
dimentionSelection: any = false; | |
splitSelection: any = false; | |
dValueSelection: any = false; | |
filterDimentions: any = []; | |
selectedDimentions: any = []; | |
filterDimentionsValues: any = []; | |
currentSelectedDimension: any = []; | |
appLoading: any = false; | |
query: any = ''; | |
q: any = ''; | |
sFilters: any = []; | |
splitOpt: any = []; | |
posX: any = 100; | |
posY: any = 100; | |
reportData: any = []; | |
service: any; | |
reportLoading:boolean = false; | |
selectedDate: any = { | |
startDate:moment(), | |
endDate:moment() | |
}; | |
showRangeLabelOnInput: boolean = true; | |
alwaysShowCalendars: boolean = true; | |
keepCalendarOpeningWithRange: boolean = true; | |
ranges: any = { | |
'Today': [moment(), moment()], | |
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')], | |
'Last 7 Days': [moment().subtract(6, 'days'), moment()], | |
'Last 30 Days': [moment().subtract(29, 'days'), moment()], | |
'This Month': [moment().startOf('month'), moment().endOf('month')], | |
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')] | |
} | |
invalidDates: moment.Moment[] = []; | |
isInvalidDate = (m: moment.Moment) => { | |
return this.invalidDates.some(d => d.isSame(m, 'day') ) | |
} | |
// chart | |
Highcharts = Highcharts; // required | |
chartConstructor = 'chart'; // optional string, defaults to 'chart' | |
chartOptions = { | |
chart: { | |
type: "area" | |
}, | |
title: { | |
text: "Impressions" | |
}, | |
plotOptions: { | |
area: { | |
fillColor: "rgba(92, 205, 222,0.2)", | |
lineColor: "#5ccdde", | |
}, | |
series: { | |
marker: { | |
fillColor: '#FFFFFF', | |
lineWidth: 1, | |
lineColor: null // inherit from series | |
}, | |
fillOpacity: 0.5 | |
} | |
}, | |
xAxis: { | |
categories: ["2018-10-16", "2018-10-17", "2018-10-18", "2018-10-19", "2018-10-20", "2018-10-21", "2018-10-22"], | |
}, | |
yAxis: { | |
title: { | |
text: "Y" | |
}, | |
}, | |
tooltip: { | |
enabled: false | |
}, | |
series: [{ | |
name: "Impressions", | |
data: [21526628, 27342813, 15790662, 20631074, 20898211, 27230549, 3769183], | |
type: "area" | |
}] | |
}; | |
@ViewChild(DaterangepickerDirective) pickerDirective: DaterangepickerDirective; | |
picker: DaterangepickerComponent; | |
@ViewChildren('dynamic', { | |
read: ViewContainerRef | |
}) viewContainerRef: QueryList < ViewContainerRef > | |
constructor( | |
private _script: ScriptLoaderService, | |
private _apis: ApplicationApiService, | |
private modalService: NgbModal, | |
private cfr: ComponentFactoryResolver, | |
private toastr: ToastrService, | |
private _configService: ConfigService, | |
private http: Http, | |
private cd: ChangeDetectorRef, | |
private activatedRoute: ActivatedRoute, | |
@Inject(Service) service, | |
) { | |
this.service = service | |
} | |
ngOnInit() { | |
this.picker = this.pickerDirective.picker; | |
} | |
ngAfterViewInit() { | |
Helpers.bodyClass('m-page--wide m-header--fixed m-header--fixed-mobile m-footer--push m-aside--offcanvas-default reports-page'); | |
this._apis.getReportDimensions().subscribe(response => { | |
if (response.status == 1200) { | |
this.filterDimentions = response.data; | |
} | |
}); | |
// this.cd.detach(); | |
} | |
openFilterSelection(e) { | |
var xPos; | |
if (e.clientX > 1024) { | |
xPos = e.clientX - 250; | |
} else { | |
xPos = e.clientX | |
} | |
this.posX = xPos - 10 + "px"; | |
this.posY = e.clientY + 10 + "px"; | |
this.filterSelection = true | |
this.dimentionSelection = true; | |
this.dValueSelection = false; | |
} | |
openSplitSelection(e) { | |
var xPos; | |
if (e.clientX > 1024) { | |
xPos = e.clientX - 250; | |
} else { | |
xPos = e.clientX | |
} | |
this.posX = xPos - 10 + "px"; | |
this.posY = e.clientY + 10 + "px"; | |
this.splitSelection = true | |
this.dimentionSelection = true; | |
this.dValueSelection = false; | |
} | |
getFilterValues(d, e) { | |
if (e) { | |
var xPos; | |
if (e.clientX > 1024) { | |
xPos = e.clientX - 250; | |
} else { | |
xPos = e.clientX | |
} | |
this.posX = xPos - 10 + "px"; | |
this.posY = e.clientY + 10 + "px"; | |
} | |
this.filterDimentionsValues = []; | |
this.appLoading = true; | |
this.currentSelectedDimension = d.id; | |
var apiFilters: any = [{}]; | |
var index = this.sFilters.findIndex(function(v) { | |
return v.id == d.id | |
}); | |
if (index === -1) { | |
for (var i = 0; i < this.sFilters.length; i++) { | |
if (this.sFilters[i].values.length > 0) { | |
var k; | |
k = this.sFilters[i].id | |
apiFilters[0][k] = this.sFilters[i].values; | |
} | |
} | |
} else { | |
for (var i = 0; i < index; i++) { | |
if (this.sFilters[i].values.length > 0) { | |
var k; | |
k = this.sFilters[i].id | |
apiFilters[0][k] = this.sFilters[i].values; | |
} | |
} | |
} | |
delete apiFilters[0][d.id] | |
this._apis.getFilterDimentionValues(d.id, this.q, apiFilters[0],this.selectedDate).subscribe(response => { | |
if (response.status == 1200) { | |
this.filterDimentionsValues = response.data.split_by_data; | |
this.appLoading = false; | |
} | |
}) | |
this.filterSelection = true | |
this.dValueSelection = true; | |
this.dimentionSelection = false; | |
} | |
onSearchChange() { | |
var apiFilters: any = [{}]; | |
for (var i = 0; i < this.sFilters.length; i++) { | |
if (this.sFilters[i][0].values.length > 0) { | |
var k; | |
k = this.sFilters[i][0].id | |
apiFilters[0][k] = this.sFilters[i][0].values; | |
} | |
} | |
this._apis.getFilterDimentionValues(this.currentSelectedDimension, this.q, apiFilters[0],this.selectedDate).subscribe(response => { | |
if (response.status == 1200) { | |
this.filterDimentionsValues = response.data.split_by_data; | |
this.appLoading = false; | |
} | |
}) | |
} | |
hidePopup() { | |
this.filterSelection = false | |
this.dValueSelection = false; | |
this.dimentionSelection = false; | |
this.splitSelection = false; | |
} | |
goBackToDimensions() { | |
this.filterSelection = true | |
this.dimentionSelection = true; | |
this.dValueSelection = false; | |
} | |
selectFilters(d) { | |
var a = this.currentSelectedDimension; | |
if (this.sFilters.filter(e => e.id === a).length > 0) { | |
this.sFilters.filter(function(v) { | |
if (v.id == a) { | |
if (!v.values.includes(d[a])) { | |
v.values.push(d[a]) | |
} else { | |
var index = v.values.indexOf(d[a]); | |
if (index > -1) { | |
v.values.splice(index, 1); | |
} | |
} | |
} | |
}); | |
} else { | |
let labelText; | |
for(var i=0; i<this.filterDimentions.length; i++) { | |
if(this.filterDimentions[i].id == this.currentSelectedDimension) { | |
labelText = this.filterDimentions[i].text; | |
} | |
} | |
var obj = { | |
id: this.currentSelectedDimension, | |
label: labelText, | |
values: [d[a]], | |
} | |
this.sFilters.push(obj) | |
} | |
this.sFilters = this.sFilters.filter(function(v) { | |
return v.values.length > 0; | |
}); | |
} | |
checkIfDimvalueExists(d) { | |
var a = this.currentSelectedDimension; | |
if (this.sFilters.length > 0) { | |
var sel = this.sFilters.filter(function(v) { | |
if (v.id == a) { | |
return v | |
} | |
}); | |
if (sel.length > 0) { | |
var index = sel[0]["values"].indexOf(d[a]); | |
return index; | |
} else { | |
return -1; | |
} | |
} else { | |
return -1; | |
} | |
} | |
arrToString(d) { | |
return d.toString() | |
} | |
selectSplitDimention(d) { | |
if (this.splitOpt.filter(e => e.id === d.id).length == 0) { | |
this.splitOpt.push(d); | |
if(this.splitOpt.length === 1){ | |
this.getReport(); | |
} if(this.splitOpt.length === 0){ | |
this.reportData = []; | |
} else{ | |
// do nothing | |
} | |
} else { | |
this.splitOpt = this.splitOpt.filter(function(obj) { | |
return obj.id !== d.id; | |
}); | |
if(this.splitOpt.length === 0) { | |
this.reportData = []; | |
} else { | |
this.reportData = []; | |
this.getReport(); | |
} | |
} | |
this.hidePopup(); | |
} | |
getReport() { | |
this.hidePopup(); | |
if(this.splitOpt.length === 0) { | |
return false; | |
} | |
var apiFilters: any = [{}]; | |
for (var i = 0; i < this.sFilters.length; i++) { | |
if (this.sFilters[i].values.length > 0) { | |
var k; | |
k = this.sFilters[i].id | |
apiFilters[0][k] = this.sFilters[i].values | |
} | |
} | |
var split = this.splitOpt[0].id; | |
this.reportData=[]; | |
this.reportLoading = true; | |
this._apis.getReportData(split, apiFilters[0],this.selectedDate).subscribe(response => { | |
if (response.status == 1200) { | |
this.reportData = response.data.split_by_data; | |
this.reportData.map(function(obj) { | |
obj.isCollapsed = true; | |
return obj; | |
}); | |
this.reportLoading = false; | |
//this.cd.detectChanges(); | |
} | |
}); | |
} | |
checkIfHaveMoreSplits(c) { | |
if (this.splitOpt.length > 0) { | |
var index = this.splitOpt.findIndex(function(v) { | |
return v.id == c | |
}) | |
if (typeof(this.splitOpt[index + 1]) != "undefined") { | |
return this.splitOpt[index + 1]; | |
} else { | |
return 0; | |
} | |
} | |
} | |
splitData(obj, cSplit, sF, splitOptions, index,rowData,selectedDate) { | |
var nextSplit = this.checkIfHaveMoreSplits(cSplit); | |
this.service.setRootViewContainerRef(this.viewContainerRef.toArray()[index]); | |
this.service.addDynamicComponent(obj, nextSplit, sF, splitOptions,rowData,selectedDate); | |
} | |
removeDynamicComponent(rowData,index) { | |
this.viewContainerRef.toArray()[index].clear(); | |
rowData.isCollapsed = true; | |
} | |
rowWiseFilterObj(row, split) { | |
var arr = []; | |
var obj = { | |
id: split, | |
label: split, | |
values: [row[split]] | |
} | |
arr.push(obj); | |
return arr; | |
} | |
convertToDecimals(input, decimals) { | |
var exp, rounded, | |
suffixes = ['K', 'M', 'B', 'T', 'P', 'E']; | |
if (input < 1000) { | |
return parseFloat(input).toFixed(2);; | |
} | |
exp = Math.floor(Math.log(input) / Math.log(1000)); | |
return (input / Math.pow(1000, exp)).toFixed(decimals) + suffixes[exp - 1]; | |
} | |
altrows(firstcolor,secondcolor) | |
{ | |
var tableElements = document.getElementsByClassName("report-row") ; | |
for(var j = 0; j < tableElements.length; j++) | |
{ | |
if(j%2==0){ | |
(<any>tableElements[j]).style.backgroundColor = firstcolor ; | |
} | |
else{ | |
(<any>tableElements[j]).style.backgroundColor = secondcolor ; | |
} | |
} | |
} | |
updateFilters(d,o) { | |
if(o === "s") { | |
this.splitOpt = this.splitOpt.filter(function(obj) { | |
return obj.id !== d.id; | |
}); | |
if(this.splitOpt.length > 0){ | |
this.getReport(); | |
} else{ | |
this.reportData = []; | |
} | |
} | |
if(o === "d") { | |
this.sFilters = this.sFilters.filter(function(obj) { | |
return obj.id !== d.id; | |
}); | |
if(this.sFilters.length > 0){ | |
this.getReport(); | |
} else{ | |
//this.reportData = []; | |
} | |
} | |
} | |
openDatePicker(e) { | |
this.pickerDirective.open(e); | |
} | |
datesUpdated(e) { | |
if(e.startDate != null && e.endDate != null) { | |
this.getReport(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
ComponentFactoryResolver, | |
Injectable, | |
Inject, | |
ReflectiveInjector | |
} from '@angular/core' | |
import { | |
Http, | |
RequestMethod, | |
RequestOptions, | |
Response, | |
ResponseOptions, | |
XHRBackend, | |
Headers | |
} from "@angular/http"; | |
import { | |
Observable | |
} from 'rxjs'; | |
import { | |
delay, | |
map | |
} from 'rxjs/operators'; | |
import 'rxjs/Rx'; | |
import { | |
ApplicationApiService | |
} from '../_services/api.service'; | |
import { | |
DynamicComponent | |
} from './dynamic.component' | |
@Injectable() | |
export class Service { | |
factoryResolver; | |
rootViewContainer; | |
reportLoading: boolean = false; | |
constructor( | |
@Inject(ComponentFactoryResolver) factoryResolver, | |
private _apis: ApplicationApiService, | |
) { | |
this.factoryResolver = factoryResolver | |
} | |
setRootViewContainerRef(viewContainerRef) { | |
this.rootViewContainer = viewContainerRef | |
} | |
addDynamicComponent(selectedRow, nextSplit, selectedFilters, splitOptions, rowData, selectedDate) { | |
const factory = this.factoryResolver | |
.resolveComponentFactory(DynamicComponent) | |
const component = factory | |
.create(this.rootViewContainer.parentInjector) | |
component.instance.selectedRow = selectedRow; | |
component.instance.nextSplit = nextSplit; | |
component.instance.selectedFilters = selectedFilters; | |
component.instance.splitOptions = splitOptions; | |
component.instance.rowData = rowData; | |
component.instance.reportLoading = true; | |
component.instance.selectedDate = selectedDate; | |
var a = JSON.parse(JSON.stringify(selectedFilters)); | |
var b = JSON.parse(JSON.stringify(selectedRow)); | |
a.filter(function(o1) { | |
return b.some(function(o2) { | |
if (o1.id === o2.id) { | |
o1.values = o2.values; | |
} | |
}); | |
}); | |
//Find values that are in result1 but not in result2 | |
var uniqueResultOne = a.filter(function(obj) { | |
return !b.some(function(obj2) { | |
return obj.id == obj2.id; | |
}); | |
}); | |
//Find values that are in result2 but not in result1 | |
var uniqueResultTwo = b.filter(function(obj) { | |
return !a.some(function(obj2) { | |
return obj.id == obj2.id; | |
}); | |
}); | |
//Combine the two arrays of unique entries | |
var result = a.concat(uniqueResultOne.concat(uniqueResultTwo)); | |
result = result.filter((s1, pos, arr) => arr.findIndex((s2) => s2.id === s1.id) === pos); | |
this.reportLoading = true; | |
this._apis.getReportData(nextSplit.id, this.getApiFilters(result), selectedDate).subscribe(response => { | |
if (response.status == 1200) { | |
response.data.split_by_data.map(function(obj) { | |
obj.isCollapsed = true; | |
return obj; | |
}) | |
component.instance.splitByData = response.data.split_by_data; | |
component.instance.selectedDate = selectedDate; | |
component.instance.reportLoading = false; | |
rowData.isCollapsed = false; | |
} | |
}) | |
this.rootViewContainer.insert(component.hostView) | |
} | |
getApiFilters(selectedFilters) { | |
var apiFilters: any = [{}]; | |
for (var i = 0; i < selectedFilters.length; i++) { | |
if (selectedFilters[i].values.length > 0) { | |
var k; | |
k = selectedFilters[i].id | |
apiFilters[0][k] = selectedFilters[i].values | |
} | |
} | |
return apiFilters[0]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment