Skip to content

Commit

Permalink
Merge pull request #54 from metrico/feat/export
Browse files Browse the repository at this point in the history
Export as .pcap, .png and .txt
  • Loading branch information
lmangani authored Mar 20, 2024
2 parents a01da5b + 340d40c commit 00d77b4
Show file tree
Hide file tree
Showing 8 changed files with 2,874 additions and 381 deletions.
1 change: 1 addition & 0 deletions ngx-flow/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@angular/platform-browser": "~12.2.0",
"@angular/platform-browser-dynamic": "~12.2.0",
"@angular/router": "~12.2.0",
"html2canvas": "^1.4.1",
"document-register-element": "^1.7.2",
"is-in-subnet": "^4.0.1",
"moment": "^2.29.4",
Expand Down
24 changes: 20 additions & 4 deletions ngx-flow/projects/ngx-flow/src/lib/ngx-flow.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ import { FlowData } from '../models/flow.model';
[callid]="callid"
[isSimplify]="isSimplify"
></app-tab-flow>
<div style="position: relative; overflow: hidden; height: 1px; width: 1px;">
<div style="position: absolute;">
<app-tab-flow
[callid]="callid"
[dataItem]="{data: _formattedData}"
[exportAsPNG]="exportAsPNG"
[callIDColorList]='callIDColorList'
(pngReady)="exportAsPNG=false"
>
</app-tab-flow>
</div>
</div>
</div>`,
styles: [`
.wrapper-container {
Expand All @@ -30,8 +42,12 @@ export class NgxFlowComponent implements OnInit {
@Input() callid: any;
@Input() isSimplify: boolean = false;
@Input() isFilter: boolean = false;

constructor() { }
exportAsPNG: boolean = false;
constructor() {
document.addEventListener('export-flow-as-png', (e: any) => {
this.exportAsPNG = true
});
}

ngOnInit(): void {
console.log(this.data)
Expand Down Expand Up @@ -69,14 +85,14 @@ export class NgxFlowComponent implements OnInit {
const dist = hosts.find((i: any) => i.name === DIST);

return {
callid: hash((i.messageID || i.title)+''),
callid: hash((i.messageID || i.title) + ''),
codecData: ' ',
description: i.aboveArrow || '',
destination_ip: dist.ip,
destination_port: dist.port,
diff: ' ',
diff_absolute: i.subTitle || '',
diff_num: ' ',
diff_num: ' ',
dstAlias: DIST,
id: 0,
info_date: i.belowArrow || '... ',
Expand Down
137 changes: 61 additions & 76 deletions ngx-flow/projects/ngx-flow/src/tab-flow/tab-flow.component.html
Original file line number Diff line number Diff line change
@@ -1,91 +1,75 @@
<div
class="flowscreen"
[style.min-width.px]="pageWidth + 85"
data-comment="85 = 16 * 2 + 106 / 2"
[style.padding-top.px]="isExport ? 40 : 0"
[style.width]="isExport ? 'calc(100% + 20px)' : 'calc(100% - 1rem)'"
#flowscreen
>
<ng-container *ngIf="arrayItemsVisible?.length === 0">
<h1 style="text-align: center; padding: 8rem; color: #aaa">No Data</h1>
</ng-container>
<div class="flowscreen" [style.min-width.px]="pageWidth + 85" data-comment="85 = 16 * 2 + 106 / 2"
[style.padding-top.px]="isExport ? 40 : 0" [style.width]="isExport ? 'calc(100% + 20px)' : 'calc(100% - 1rem)'"
#flowscreen>
<ng-container *ngIf="arrayItemsVisible?.length === 0">
<h1 style="text-align: center; padding: 8rem; color: #aaa">No Data</h1>
</ng-container>

<div class="flow-grid-lines" [style.min-width.px]="pageWidth - 16 * 2">
<div *ngFor="let title of flowGridLines" class="line"></div>
</div>
<div class="flow-grid-lines" [style.min-width.px]="pageWidth - 16 * 2">
<div *ngFor="let title of flowGridLines" class="line"></div>
</div>

<!-- hosts -->
<!-- hosts -->

<div class="hosts" [style.top.px]="isExport ? 40 : 0">
<div class="hosts-wrapper">
<!-- host titles -->
<ng-template ngFor let-itemhost [ngForOf]="_isCombineByAlias ? hostsCA : hostsIPs">
<div *ngIf="!itemhost.hidden" [ngClass]="'item-wrapper' + (isSimplify ? ' big' : '')">
<!-- wrapper -->
<div class="hosts" [style.top.px]="isExport ? 40 : 0">
<div class="hosts-wrapper">
<!-- host titles -->
<ng-template ngFor let-itemhost [ngForOf]="_isCombineByAlias ? hostsCA : hostsIPs">
<div *ngIf="!itemhost.hidden" [ngClass]="'item-wrapper' + (isSimplify ? ' big' : '')">
<!-- wrapper -->

<div
class="item"
[id]="itemhost.alias && itemhost.alias !== itemhost.ip ? itemhost.alias : ''"
[style.border-color]="(itemhost.color && itemhost.color.border) || 'lightgray'"
>
<!-- container -->
<div class="item" [id]="itemhost.alias && itemhost.alias !== itemhost.ip ? itemhost.alias : ''"
[style.border-color]="(itemhost.color && itemhost.color.border) || 'lightgray'">
<!-- container -->

<div class="aliasfield" (mouseover)="showTooltip(itemhost)" (mouseout)="hideTooltip()">
<ng-template #noAlias> </ng-template>
<div class="alias-img"></div>
<div class="alias-name" *ngIf="!_isCombineByAliasGroup; else itemhostGroup">
{{ itemhost.alias && itemhost.alias !== itemhost.ip ? itemhost.alias : '' }}
</div>
<ng-template #itemhostGroup>
<div>Group:</div>
<div class="alias-name">
{{ itemhost.group || '...other...' }}
<div class="aliasfield" (mouseover)="showTooltip(itemhost)" (mouseout)="hideTooltip()">
<ng-template #noAlias> </ng-template>
<div class="alias-img"></div>
<div class="alias-name" *ngIf="!_isCombineByAliasGroup; else itemhostGroup">
{{ itemhost.alias && itemhost.alias !== itemhost.ip ? itemhost.alias : '' }}
</div>
<ng-template #itemhostGroup>
<div>Group:</div>
<div class="alias-name">
{{ itemhost.group || '...other...' }}
</div>
</ng-template>
</div>
</div>
</div>
</ng-template>
</div>
</div>
</ng-template>
</div>
</ng-template>
</div>
</div>

<!-- flow packets -->
<!-- REAL TIME FLOW -->
<!-- flow packets -->
<!-- REAL TIME FLOW -->

<!-- EXPORT FLOW as PNG -->
<div
*ngIf="isExport"
class="flow-packets-wrapper"
[style.margin-right.rem]="0"
[style.min-width.px]="pageWidth + 100"
>
<div style="height: 92px"></div>
<app-flow-item
*ngFor="let item of arrayItemsVisible; let idx = index"
[isGroupByAlias]="_isCombineByAlias"
[item]="item"
[idx]="idx"
[isSimplify]="false"
>
</app-flow-item>
<div style="height: 40px"></div>
</div>
<!-- </div> -->
<div *ngIf="isExport" class="label-callid-container">
<div class="label-callid-wrapper" *ngFor="let itemLabel of labels" [style.color]="itemLabel.color">
* {{ itemLabel.callid }}
<!-- EXPORT FLOW as PNG -->
<div *ngIf="isExport" class="flow-packets-wrapper" [style.margin-right.rem]="0"
[style.min-width.px]="pageWidth + 100">
<div style="height: 92px"></div>
<app-flow-item *ngFor="let item of arrayItemsVisible; let idx = index" [isGroupByAlias]="_isCombineByAlias"
[item]="item" [idx]="idx" [isSimplify]="false">
</app-flow-item>
<div style="height: 40px"></div>
</div>
<!-- </div> -->
<div *ngIf="isExport" class="label-callid-container">
<div class="label-callid-wrapper" *ngFor="let itemLabel of labels" [style.color]="itemLabel.color">
* {{ itemLabel.callid }}
</div>
</div>
</div>
</div>
<div class="VS-Container-horizontal">
<div
*ngIf="isExport || isSafari"
class="VS-Container"
style="overflow: auto !important"
(scroll)="onScrollVScrollWrapper($event)"
>
<div
class="VS-Container"
style="height: initial; overflow: scroll !important"
style="height: initial; overflow: scroll !important; bottom:unset"
[style.min-width.px]="pageWidth + 100"
>
<div style="height: 92px"></div>
Expand All @@ -101,16 +85,17 @@ <h1 style="text-align: center; padding: 8rem; color: #aaa">No Data</h1>
<div style="height: 60px"></div>
</div>
</div>
<!-- <div
<div
class="VS-Container"
style="overflow-y: hidden !important"
(scroll)="onScrollVScrollWrapper($event)"
*ngIf="!isExport"
*ngIf="!isExport && !isSafari"
#VScrollWrapper
>
<cdk-virtual-scroll-viewport
class="VS-Container hidescroll"
(wheel)="cdkWheelScroll($event)"

(touchstart)="onEvent($event, 'touchstart')"
(touchmove)="onEvent($event, 'touchmove')"
[maxBufferPx]="500"
Expand Down Expand Up @@ -138,19 +123,19 @@ <h1 style="text-align: center; padding: 8rem; color: #aaa">No Data</h1>
</ng-template>
</ng-container>
</cdk-virtual-scroll-viewport>
</div> -->
</div>
</div>

<div id="download" style="display: none">
<img #canvas />
<a #downloadLink></a>
<img #canvas />
<a #downloadLink target="_blank"></a>
</div>
<!-- <div
<div
class="virtual-scrollbar"
*ngIf="!isExport"
*ngIf="!isExport && !isSafari"
(mousedown)="setScrollTarget('virtualScrollbar')"
(scroll)="setVirtualScrollHeight($event)"
#virtualScrollbar
>
<div [style.transform]="getVirtualScrollHeight" [style.padding.px]="1"></div>
</div> -->
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
box-shadow: inset 7px 10px 12px transparent;
}
}
::-webkit-scrollbar-corner { background: rgba(0,0,0,0.5); }


.flow-grid-lines {
display: flex;
Expand Down
67 changes: 46 additions & 21 deletions ngx-flow/projects/ngx-flow/src/tab-flow/tab-flow.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from '../services/message-details.service';
import { Subscription } from 'rxjs';
import { isExternalUrl } from '../helpers/functions';
import * as html2canvas from 'html2canvas';

export class CustomVirtualScrollStrategy extends FixedSizeVirtualScrollStrategy {
constructor() {
Expand Down Expand Up @@ -93,6 +94,7 @@ export class TabFlowComponent
timeout: any;
_interval: any | null = null;
pathPrefix = './assets/';
isSafari = navigator.vendor === 'Apple Computer, Inc.'
outEventDelayOff = 0;
get outEventOff() {
//
Expand Down Expand Up @@ -123,7 +125,7 @@ export class TabFlowComponent
dataItemValue = {
data: JSON.parse(dataItemValueInput)
}
} catch (e) {
} catch (e) {
console.error("JSON PARSING ERROR", e, dataItemValueInput)
dataItemValue = {
data: null
Expand All @@ -137,7 +139,7 @@ export class TabFlowComponent
try {
console.log(JSON_parse(dataItemValueInput.data),JSON.parse(dataItemValueInput.data))
dataItemValue.data = JSON.parse(dataItemValueInput.data)
} catch (e) {
} catch (e) {
console.error("JSON PARSING ERROR", e, dataItemValueInput.data)
dataItemValue = {
data: null
Expand Down Expand Up @@ -216,7 +218,7 @@ export class TabFlowComponent
if (val) {
this.isExport = true;
this.cdr.detectChanges();
// setTimeout(this.onSavePng.bind(this), 500);
setTimeout(this.onSavePng.bind(this), 500);
}
}

Expand All @@ -235,7 +237,10 @@ export class TabFlowComponent
private messageDetailsService: MessageDetailsService,
private transactionFilterService: TransactionFilterService,
private cdr: ChangeDetectorRef,
) { }
) {
console.log('test constructor')

}
public isDataReady() {

}
Expand Down Expand Up @@ -589,8 +594,28 @@ export class TabFlowComponent
const arr = itemhost.arrip || [itemhost.IP];
return arr.join(', ');
}
// onSavePng() {

onSavePng() {
if (!this._flagAfterViewInit) {
setTimeout(this.onSavePng.bind(this), 1000);
return;
}
if (html2canvas && typeof html2canvas === 'function') {
this.cdr.detectChanges();
const f: Function = html2canvas as Function;
f(this.flowscreen.nativeElement).then((canvas: any) => {
this.canvas.nativeElement.src = canvas.toDataURL();
this.downloadLink.nativeElement.href = canvas.toDataURL('image/png');
const date = new Date();
this.downloadLink.nativeElement.download = `${date.toUTCString()}.png`;
console.log()
this.downloadLink.nativeElement.click();
console.log('%cpng ready', 'color:#ff4400; font-size: 50px;', this.downloadLink.nativeElement.href);
setTimeout(() => {
this.pngReady.emit({});
});
});
}
}
labelColor(callid: any, selected: any) {
if (selected) {
const color = this.callIDColorList?.find(
Expand Down Expand Up @@ -623,20 +648,20 @@ export class TabFlowComponent
this.copyTimer = Date.now();
}
copy(value: any) {
// const localTimer = Date.now();
// if (localTimer - this.copyTimer > 700) {
// this.copyService.copy(value.callid, {
// message: 'notifications.success.callidCopy',
// isTranslation: true,
// translationParams: {
// callid: value.callid,
// },
// });
// value.copySelected = true;
// this.timeout = setTimeout(() => {
// value.copySelected = false;
// }, 1800);
// }
// const localTimer = Date.now();
// if (localTimer - this.copyTimer > 700) {
// this.copyService.copy(value.callid, {
// message: 'notifications.success.callidCopy',
// isTranslation: true,
// translationParams: {
// callid: value.callid,
// },
// });
// value.copySelected = true;
// this.timeout = setTimeout(() => {
// value.copySelected = false;
// }, 1800);
// }
}
setScrollTarget(targetString: string) {
this.ScrollTarget = targetString;
Expand Down Expand Up @@ -677,7 +702,7 @@ export class TabFlowComponent
const scrollbar = this.virtualScrollbar?.nativeElement;
let movingAverageArray: any[] = [];
const ma = (p: any) => {
const valMA = 6;
const valMA = 3; // Adjust this to change virtual scroll speed. Lower = faster
if (movingAverageArray.length < valMA) {
movingAverageArray = Array.from({ length: valMA }, (x) => p);
}
Expand Down
Loading

0 comments on commit 00d77b4

Please sign in to comment.