diff --git a/package-lock.json b/package-lock.json index 51b80e6b..334c7207 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12158,6 +12158,11 @@ "inherits": "^2.0.1" } }, + "roboto-fontface": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz", + "integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g==" + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", diff --git a/package.json b/package.json index eb8c3d66..017cf948 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "ngx-markdown": "^8.2.1", "reflect-metadata": "^0.1.12", "reinstall": "^2.0.0", + "roboto-fontface": "^0.10.0", "rxjs": "^6.5.3", "ts-md5": "^1.2.7", "tslib": "^1.10.0", diff --git a/src/VERSION.ts b/src/VERSION.ts index d9c15e06..f16c6166 100644 --- a/src/VERSION.ts +++ b/src/VERSION.ts @@ -1 +1 @@ -export const VERSION = '7.7.034'; +export const VERSION = '7.8.0'; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8986ec6d..dd57d9c9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -12,9 +12,10 @@ import { AppRoutingModule } from '@app/app-routing.module'; import { FilterPipe } from '@app/filter.pipe'; import { SafePipe } from '@app/safe.pipe'; import { HtmlPipe } from '@app/html.pipe'; +import { MomentPipe } from './moment.pipe'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HepicMaterialModule } from '@app/app.material-module'; - +import {MatIconModule} from '@angular/material/icon'; /* @app/components */ // import * as components from '@app/components'; // import * as widgets from '@app/components/widgets'; @@ -49,6 +50,7 @@ import { ResultWidgetComponent, RsearchWidgetComponent, AlertWidgetComponent, + SmartInputWidgetComponent, SettingClockWidgetComponent, SettingGeneralIframeWidgetComponent, SettingIframeWidgetComponent, @@ -59,7 +61,6 @@ import { SettingResultWidgetComponent, SettingsAceEditorWidgetComponent, SettingAlertWidgetComponent, - } from '@app/components/widgets'; @@ -96,7 +97,7 @@ import { TabLogsComponent, TabLokiComponent, TabMessagesComponent, - TabQosComponent + TabQosComponent, } from '@app/components/search-grid-call'; import { MenuComponent } from '@app/components/menu/menu.component'; @@ -114,6 +115,7 @@ import { MarkdownModule } from 'ngx-markdown'; import { ColorChromeModule } from 'ngx-color/chrome'; import { ColorCircleModule } from 'ngx-color/circle'; + const DEFAULT_ACE_CONFIG: AceConfigInterface = { }; @@ -124,7 +126,7 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { FilterPipe, SafePipe, HtmlPipe, - + MomentPipe, /** components */ AlertComponent, DashboardComponent, @@ -175,6 +177,7 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { AlertWidgetComponent, ResultWidgetComponent, RsearchWidgetComponent, + SmartInputWidgetComponent, SettingClockWidgetComponent, SettingGeneralIframeWidgetComponent, SettingIframeWidgetComponent, @@ -185,7 +188,6 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { SettingResultWidgetComponent, SettingsAceEditorWidgetComponent, SettingAlertWidgetComponent, - /** dialogs */ DialogAdvancedComponent, DialogAgentsubComponent, @@ -219,6 +221,7 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { routing, AppRoutingModule, HepicMaterialModule, + MatIconModule, AgGridModule.withComponents([]), NgxDaterangepickerMd.forRoot(), NgxJsonViewerModule, @@ -226,7 +229,7 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { AceEditorModule, MarkdownModule.forRoot(), ColorChromeModule, - ColorCircleModule + ColorCircleModule, ], entryComponents: [ MenuComponent, @@ -260,6 +263,7 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { ResultWidgetComponent, RsearchWidgetComponent, AlertWidgetComponent, + SmartInputWidgetComponent, SettingClockWidgetComponent, SettingGeneralIframeWidgetComponent, SettingIframeWidgetComponent, @@ -270,7 +274,6 @@ const DEFAULT_ACE_CONFIG: AceConfigInterface = { SettingResultWidgetComponent, SettingsAceEditorWidgetComponent, SettingAlertWidgetComponent, - /** dashboard */ AddDashboardDialogComponent, AddDialogComponent, diff --git a/src/app/components/alert/alert.component.css b/src/app/components/alert/alert.component.scss similarity index 79% rename from src/app/components/alert/alert.component.css rename to src/app/components/alert/alert.component.scss index 10c25bd6..d3719d8a 100644 --- a/src/app/components/alert/alert.component.css +++ b/src/app/components/alert/alert.component.scss @@ -1,4 +1,4 @@ -.alert{ +.alert { width: 400px; padding-right: 15px; padding-left: 70px; @@ -8,13 +8,19 @@ left: 30px; color: white; } -.alert-danger{ +.alert-danger { background-color: #F44336; + .circle { + color: #F44336; + } } -.alert-success{ +.alert-success { background-color: #8BC34A; + .circle { + color: #8BC34A; + } } -.circle{ +.circle { display: flex; justify-content: center; align-items: center; @@ -23,7 +29,7 @@ border-radius: 100%; background-color: white; } -.alert-type{ +.alert-type { display: flex; justify-content: center; align-items: center; @@ -34,13 +40,7 @@ left: 0; top: 0; } -.alert-danger .circle{ - color:#F44336; -} -.alert-success .circle{ - color: #8BC34A; -} -.close-message{ +.close-message { font-size: 20px; height: 20px; width: 20px; @@ -48,4 +48,4 @@ right: 5px; top: 5px; cursor: pointer; -} \ No newline at end of file +} diff --git a/src/app/components/alert/alert.component.ts b/src/app/components/alert/alert.component.ts index f895bfde..48f25947 100644 --- a/src/app/components/alert/alert.component.ts +++ b/src/app/components/alert/alert.component.ts @@ -6,7 +6,7 @@ import { AlertService } from '@app/services'; @Component({ selector: 'alert', templateUrl: 'alert.component.html', - styleUrls: ['./alert.component.css'] + styleUrls: ['./alert.component.scss'] }) export class AlertComponent implements OnInit, OnDestroy { diff --git a/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.css b/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.css deleted file mode 100644 index 0c329b7d..00000000 --- a/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.css +++ /dev/null @@ -1,65 +0,0 @@ -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.hr-or { - width: 100%; - position: relative; -} -.hr-or::before { - content: "or"; - position: absolute; - left: 0; - right: 0; - margin: auto; - width: 35px; - text-align: center; - top: -12px; - color: #999; - background-color: #fff; - padding: 0 10px; - border-radius: 50rem; -} - - - -.file-upload-container { - position: relative; -} - -.file-upload-container > .fileselect { - align-items: center; - background-color: #eee; - border-radius: 1rem; - border-style: dashed; - color: #999; - cursor: pointer; - display: flex; - height: 150px; - justify-content: center; - margin: 0; - min-width: 200px; - padding: 1rem; -} - -.file-upload-container > .fileselect::before { - /* Drop JSON file here */ - content: "Drop JSON file here"; -} -.file-upload-container > input[type="file"] { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - bottom: 0; - right: 0; - cursor: pointer; - opacity: 0; -} - -.file-upload-container > .fileselect.drugOver { - background-color: #ccc; -} \ No newline at end of file diff --git a/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.scss b/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.scss new file mode 100644 index 00000000..9aeb8226 --- /dev/null +++ b/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.scss @@ -0,0 +1,58 @@ +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.hr-or { + width: 100%; + position: relative; + &::before { + content: "or"; + position: absolute; + left: 0; + right: 0; + margin: auto; + width: 35px; + text-align: center; + top: -12px; + color: #999; + background-color: #fff; + padding: 0 10px; + border-radius: 50rem; + } +} +.file-upload-container { + position: relative; + & > .fileselect { + align-items: center; + background-color: #eee; + border-radius: 1rem; + border-style: dashed; + color: #999; + cursor: pointer; + display: flex; + height: 150px; + justify-content: center; + margin: 0; + min-width: 200px; + padding: 1rem; + &::before { + content: "Drop JSON file here"; + } + &.drugOver { + background-color: #ccc; + } + } + & > input[type="file"] { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + bottom: 0; + right: 0; + cursor: pointer; + opacity: 0; + } +} diff --git a/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.ts b/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.ts index 377d936b..d474ec9c 100644 --- a/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.ts +++ b/src/app/components/dashboard/add-dashboard-dialog/add-dashboard-dialog.component.ts @@ -5,7 +5,7 @@ import { DashboardService } from '@app/services'; @Component({ selector: 'app-add-dashboard-dialog', templateUrl: './add-dashboard-dialog.component.html', - styleUrls: ['./add-dashboard-dialog.component.css'] + styleUrls: ['./add-dashboard-dialog.component.scss'] }) export class AddDashboardDialogComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('fileSelect', {static: true}) fileSelect; diff --git a/src/app/components/dashboard/add-dialog/add-dialog.component.css b/src/app/components/dashboard/add-dialog/add-dialog.component.scss similarity index 100% rename from src/app/components/dashboard/add-dialog/add-dialog.component.css rename to src/app/components/dashboard/add-dialog/add-dialog.component.scss diff --git a/src/app/components/dashboard/add-dialog/add-dialog.component.ts b/src/app/components/dashboard/add-dialog/add-dialog.component.ts index 8dbd38ac..4523c1d9 100644 --- a/src/app/components/dashboard/add-dialog/add-dialog.component.ts +++ b/src/app/components/dashboard/add-dialog/add-dialog.component.ts @@ -6,7 +6,7 @@ import { PreferenceAdvancedService } from '@app/services'; @Component({ selector: 'app-add-dialog', templateUrl: './add-dialog.component.html', - styleUrls: ['./add-dialog.component.css'] + styleUrls: ['./add-dialog.component.scss'] }) export class AddDialogComponent { widgets = {}; diff --git a/src/app/components/dashboard/dashboard.component.css b/src/app/components/dashboard/dashboard.component.css deleted file mode 100644 index 774f80eb..00000000 --- a/src/app/components/dashboard/dashboard.component.css +++ /dev/null @@ -1,57 +0,0 @@ -.widget-block { - position: relative; - padding: 0.5rem; - height: calc(100% - 2rem); -} -.top-tool { - display: flex; - align-items: center; - justify-content: space-between; - box-shadow: 0px 3px 4px rgba(0,0,0,0.2); - z-index: 12; - position: relative; -} -.top-tool > h3 { - margin: 0 0.5rem; -} -iframe { - width: 100%; - height: calc(100vh - 85px); - border: 0; -} -.shadow-polygon { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background-color: rgba(255,255,255,0.1); - z-index: 2; -} -.widget-item > -.box-header.drag-handler > -.box-header-btns.pull-right > -.box-icon-header { - opacity: 0; - transition: opacity 0.3s; -} -.widget-item:hover > -.box-header.drag-handler > -.box-header-btns.pull-right > -.box-icon-header { - opacity: 1; -} - - -.no-content { - position: absolute; - display: flex; - justify-content: center; - align-items: center; - color: rgba(0,0,0,0.2); - z-index: 4; - top: 6rem; - left: 0; - right: 0; - bottom: 0; -} \ No newline at end of file diff --git a/src/app/components/dashboard/dashboard.component.html b/src/app/components/dashboard/dashboard.component.html index 2708eaea..dd28cf58 100644 --- a/src/app/components/dashboard/dashboard.component.html +++ b/src/app/components/dashboard/dashboard.component.html @@ -6,42 +6,51 @@

{{ dashboardTitle | uppercase }}

-
- -
- - - -
- -

- {{ item.config ? item.config.title: item.title || item.id }} -

-

LOKI Search

- -
-
- settings - delete + +
+
+ +
+ + +
+ +

+ {{ item.config ? item.config.title: item.title || item.id }} +

+

LOKI Search

+ +
+
+ settings + delete +
-
-
- - -
- - - -
- -

Dashboard is empty

- -
+
+

Widget is too small, we recommend increasing it's size to {{ getSize(item) }}

+ +
+
+ + +
+ + + +
+ +

Dashboard is empty

+ +
+
diff --git a/src/app/components/dashboard/dashboard.component.scss b/src/app/components/dashboard/dashboard.component.scss new file mode 100644 index 00000000..38ac9908 --- /dev/null +++ b/src/app/components/dashboard/dashboard.component.scss @@ -0,0 +1,88 @@ +.widget-block { + position: relative; + padding: 0.5rem; + height: calc(100% - 2rem); +} +.top-tool { + display: flex; + align-items: center; + justify-content: space-between; + box-shadow: 0px 3px 4px rgba(0,0,0,0.2); + z-index: 12; + position: relative; + & > h3 { + margin: 0 0.5rem; + } +} +iframe { + width: 100%; + height: calc(100vh - 85px); + border: 0; +} +.shadow-polygon { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-color: rgba(255,255,255,0.1); + z-index: 2; +} +.widget-item { + & > .box-header { + &.drag-handler { + & > .box-header-btns { + &.pull-right { + & > .box-icon-header { + opacity: 0; + transition: opacity 0.3s; + } + } + } + } + } + &:hover { + & > .box-header { + &.drag-handler { + & > .box-header-btns { + &.pull-right { + & > .box-icon-header { + opacity: 1; + } + } + } + } + } + } +} +.no-content { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + color: rgba(0,0,0,0.2); + z-index: 4; + top: 6rem; + left: 0; + right: 0; + bottom: 0; +} +.widget-warning{ + position: absolute; + top: calc(25%); + left: calc(10%); + background-color: #ff6700; + height: 100px; + width: 80%; + border-radius: .25rem; + padding: 1.25rem 1.25rem; + p{ + font-size: 0.75rem; + width: calc(100% - .75rem) + } + .warning-dismiss{ + position: absolute; + top: -5px; + right: -5px; + } +} diff --git a/src/app/components/dashboard/dashboard.component.ts b/src/app/components/dashboard/dashboard.component.ts index 68ea9cc8..03de23a0 100644 --- a/src/app/components/dashboard/dashboard.component.ts +++ b/src/app/components/dashboard/dashboard.component.ts @@ -1,5 +1,15 @@ // GRIDSTER & ANGULAR -import { Component, OnInit, ViewEncapsulation, ViewChildren, QueryList, OnDestroy, AfterViewInit, ViewChild } from '@angular/core'; +import { + Component, + OnInit, + ViewEncapsulation, + ViewChildren, + QueryList, + OnDestroy, + AfterViewInit, + ViewChild, + HostListener +} from '@angular/core'; import { GridsterConfig, GridType } from 'angular-gridster2'; import { ActivatedRoute, Router } from '@angular/router'; import { DashboardModel, DashboardContentModel } from '@app/models'; @@ -12,12 +22,14 @@ import { IWidget, IWidgetMetaData } from '../widgets/IWidget'; import { Observable } from 'rxjs'; import { WidgetArray, WidgetArrayInstance } from '@app/helpers/widget'; import { Functions } from '@app/helpers/functions'; +import { ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; @Component({ selector: 'app-dashboard', templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.css'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./dashboard.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush }) export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { gridOptions: GridsterConfig; @@ -28,6 +40,8 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { isHome = false; iframeUrl: string; postSaveHash: string; + _interval: any; + @ViewChildren('widgets') widgets: QueryList; @ViewChild('customWidget', {static: false}) customWidget: any; @@ -35,8 +49,47 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { private _route: ActivatedRoute, private _ds: DashboardService, private router: Router, + private cdr: ChangeDetectorRef, public dialog: MatDialog) {} - + @HostListener('document:keydown', ['$event']) onKeydownHandler(event: KeyboardEvent) { + const ls = JSON.parse(localStorage.getItem('searchQueryWidgetsResult')); + let currentWidget: any; + if (ls != null && ls.currentWidget !== undefined) { + currentWidget = ls.currentWidget; + } else { + currentWidget = this._ds.dbs.currentWidget; + } + if (currentWidget !== undefined) { + if (event.key === 'Enter' && event.ctrlKey === true) { + const w: IWidget = WidgetArrayInstance[currentWidget.id]; + if (w && w.doSearchResult) { + w.doSearchResult(); + } + } + } + let widgetList: Array; + if (ls != null && ls.currentWidgetList !== undefined) { + widgetList = ls.currentWidgetList; + } else { + widgetList = this._ds.dbs.currentWidgetList; + } + const firstWidget = widgetList.findIndex(widget => widget.strongIndex === 'ProtosearchWidgetComponent'); + if (event.key === 'Tab' && event.shiftKey === true) { + event.preventDefault(); + let i = 0; + if (currentWidget !== undefined) { + i = this.submitCheck().findIndex(widget => widget.id === currentWidget.id); + if (i < this.submitCheck().length - 1) { + i += 1; + } else { + i = 0; + } + } else { + i = 0; + } + this._ds.setCurrentWidgetId(this.submitCheck()[i]); + } + } ngOnInit() { // Grid options this.gridOptions = { @@ -72,6 +125,8 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { /* */ scrollToNewItems: true, displayGrid: 'none', + cols: 5, + rows: 5, minCols: 5, maxCols: 5, minRows: 5, @@ -79,6 +134,105 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { }; this.getData(); } + + + checkWidgets() { + const widgets = this._ds.dbs.currentWidgetList; + const limitedWidgets = []; + for (let i = 0 ; i < WidgetArray.length; i++) { + if (WidgetArray[i].minHeight !== undefined && limitedWidgets.indexOf(WidgetArray[i]) === -1) { + limitedWidgets.push(WidgetArray[i]); + } + if (WidgetArray[i].minWidth !== undefined && limitedWidgets.indexOf(WidgetArray[i]) === -1) { + limitedWidgets.push(WidgetArray[i]); + } + } + for (let i = 0; i < widgets.length; i++) { + for (let j = 0; j < limitedWidgets.length; j++) { + if (widgets[i].strongIndex === limitedWidgets[j].strongIndex) { + this.checkSize(widgets[i].id, limitedWidgets[j]); + } + } + } + + } + checkSize(id, widgetType) { + const widget = document.getElementById(id); + if (widgetType.minWidth !== undefined && widgetType.minHeight !== undefined) { + this.limitSize(id, widgetType.minHeight, widgetType.minWidth); + } else if (widgetType.minHeight !== undefined) { + this.limitSize(id, widgetType.minHeight, 1); + } else if (widgetType.minWidth !== undefined) { + this.limitSize(id, 1, widgetType.minWidth); + } + } + limitSize(id, height, width) { + let columnRes: number; + let rowRes: number; + const grid = document.getElementById('gridster'); + if (this.dashboardCollection.data.config !== undefined) { + columnRes = grid.getBoundingClientRect().width / this.dashboardCollection.data.config.columns; + rowRes = grid.getBoundingClientRect().height / this.dashboardCollection.data.config.maxrows; + } + if (this.dashboardCollection.data.config !== undefined && this.dashboardCollection.data.config.ignoreMinSize !== 'ignore') { + const i = this.dashboardArray.findIndex(widget => widget.id === id); + const colAmount = Math.ceil(width / columnRes); + if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[i].minItemRows = 1; + this.dashboardArray[i].minItemCols = 1; + } + if (this.dashboardArray[i].rows < colAmount) { + if (this.dashboardCollection.data.config.ignoreMinSize === 'limit') { + this.dashboardArray[i].cols = colAmount; + this.dashboardArray[i].minItemCols = colAmount; + } else if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[i].isWarning = true; + } + } else { + if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[i].isWarning = false; + } + } + const rowAmount = Math.ceil(height / rowRes); + if (this.dashboardArray[i].rows < rowAmount) { + if (this.dashboardCollection.data.config.ignoreMinSize === 'limit') { + this.dashboardArray[i].rows = rowAmount; + this.dashboardArray[i].minItemRows = rowAmount; + } else if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[i].isWarning = true; + } + } else { + if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[i].isWarning = false; + } + } + } else if (this.dashboardCollection.data.config !== undefined && this.dashboardCollection.data.config.ignoreMinSize === 'ignore') { + for (let i = 0; i < this.dashboardArray.length; i++) { + this.dashboardArray[i].minItemRows = 1; + this.dashboardArray[i].minItemCols = 1; + } + } + this.gridOptions.api.optionsChanged(); + } + dismissWarning(item) { + const i = this.dashboardArray.findIndex(widget => widget.id === item.id); + this.dashboardArray[i].isDismissed = true; + } + resizeExcess() { + let rows: number; + let cols: number; + if (this.dashboardCollection.data.config !== undefined) { + rows = this.dashboardCollection.data.config.maxrows; + cols = this.dashboardCollection.data.config.columns; + } + for (let i = 0; i < this.dashboardArray.length; i++) { + if (this.dashboardArray[i].rows > rows || this.dashboardArray[i].cols > cols) { + this.dashboardArray[i].rows = 1; + this.dashboardArray[i].cols = 1; + this.gridOptions.api.getNextPossiblePosition(this.dashboardArray[i]); + } + } + } ngAfterViewInit () { this.updateTrigger(); } @@ -90,6 +244,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { } else { this.scrollTop(); } + Array.from(document.querySelectorAll('.widget-item')).forEach(i => i.scrollTop = 0); }, 100); } updateTrigger() { @@ -100,6 +255,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { i.onmouseup = window.document.body.onmouseleave = evt => shadows.forEach( (j: any) => j.style.display = 'none' ); i.onmousedown = evt => shadows.forEach( (j: any) => j.style.display = 'block' ); }); + this.cdr.detectChanges(); }, 500); } @@ -159,19 +315,121 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { this.updateTrigger(); this.changedOptions(); this.scrollTop(); + this.cdr.detectChanges(); }); } + submitCheck() { + const submitWidgets: Array = []; + const dashboardSubmitWidgets: Array = []; + const ls = JSON.parse(localStorage.getItem('searchQueryWidgetsResult')); + let widgetList: Array; + if (ls != null && ls.currentWidgetList !== undefined) { + widgetList = ls.currentWidgetList; + } else { + widgetList = this._ds.dbs.currentWidgetList; + } + for (let i = 0; i < WidgetArray.length; i++) { + if (WidgetArray[i].submit) { + submitWidgets.push(WidgetArray[i]); + } + } + for (let i = 0; i < widgetList.length; i++) { + for (let j = 0; j < submitWidgets.length; j++) { + if (widgetList[i].strongIndex === submitWidgets[j].strongIndex) { + dashboardSubmitWidgets.push(widgetList[i]); + } + } + } + return dashboardSubmitWidgets; + } + changeCurrent(id: string) { + const ls = JSON.parse(localStorage.getItem('searchQueryWidgetsResult')); + let currentWidget: any; + if (ls != null && ls.currentWidget !== undefined) { + currentWidget = ls.currentWidget; + } else { + currentWidget = this._ds.dbs.currentWidget; + } + if (id !== currentWidget.id) { + for (let i = 0; i < this.submitCheck().length; i++) { + if (id === this.submitCheck()[i].id) { + // currentWidget.id + this._ds.setCurrentWidgetId(this.submitCheck()[i]); + } + } + this.save(); + } + } itemChange(item: any) { + if (item.name === 'iframe') { const w: IWidget = WidgetArrayInstance[item.id]; if (w && w.refresh) { w.refresh(); } } + this.warningCheck(item); this.save(); return true; } + warningCheck(item: any) { + if (this.dashboardCollection.data.config !== undefined && this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + let columnRes: number; + let rowRes: number; + const grid = document.getElementById('gridster'); + if (this.dashboardCollection.data.config !== undefined) { + columnRes = grid.getBoundingClientRect().width / this.dashboardCollection.data.config.columns; + rowRes = grid.getBoundingClientRect().height / this.dashboardCollection.data.config.maxrows; + } + const iW = WidgetArray.findIndex(widget => widget.strongIndex === item.strongIndex); + const iD = this.dashboardArray.findIndex(widget => widget.id === item.id); + const height = WidgetArray[iW].minHeight; + const rowAmount = Math.ceil(height / rowRes); + if (this.dashboardArray[iD].rows < rowAmount) { + if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[iD].isWarning = true; + } + } + const width = WidgetArray[iW].minWidth; + const colAmount = Math.ceil(width / columnRes); + if (this.dashboardArray[iD].rows < colAmount) { + if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[iD].isWarning = true; + } + } + if (this.dashboardArray[iD].rows >= colAmount && this.dashboardArray[iD].rows >= rowAmount) { + if (this.dashboardCollection.data.config.ignoreMinSize === 'warning') { + this.dashboardArray[iD].isWarning = false; + this.dashboardArray[iD].isWarning = false; + } + } + this.cdr.detectChanges(); + } + } + getSize(item) { + const i = WidgetArray.findIndex(widget => widget.strongIndex === item.strongIndex); + let size = ''; + let columnRes: number; + let rowRes: number; + const grid = document.getElementById('gridster'); + if (this.dashboardCollection.data.config !== undefined) { + columnRes = grid.getBoundingClientRect().width / this.dashboardCollection.data.config.columns; + rowRes = grid.getBoundingClientRect().height / this.dashboardCollection.data.config.maxrows; + } + if (WidgetArray[i].minWidth !== undefined) { + const width = WidgetArray[i].minWidth; + const colAmount = Math.ceil(width / columnRes); + size += colAmount + ' columns '; + } + if (WidgetArray[i].minHeight !== undefined) { + const height = WidgetArray[i].minHeight; + const rowAmount = Math.ceil(height / rowRes); + size += rowAmount + ' rows '; + + } + return size; + } private save () { setTimeout(async () => await this.onDashboardSave().toPromise()); } @@ -192,6 +450,11 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { break; } this.gridOptions.api.optionsChanged(); + setTimeout(() => { + this.resizeExcess(); + this.checkWidgets(); + this.cdr.detectChanges(); + }, 100); } openSettings(item: any) { @@ -232,9 +495,21 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { strongIndex, title, output: { changeSettings: this.onChangeWidget.bind(this) } }; + if (!this.gridOptions.api.getNextPossiblePosition(widget)) { + this.gridOptions.gridType = 'scrollVertical'; + this.dashboardCollection.data.config.gridType = 'scrollVertical'; + this.changedOptions(); + widget.x = this.gridOptions.api.getFirstPossiblePosition(widget).x; + widget.y = this.gridOptions.api.getFirstPossiblePosition(widget).y; + } this.dashboardArray.push(widget); this.save(); this._ds.update(); + setTimeout(() => { + this.checkWidgets(); + this.resizeExcess(); + this.cdr.detectChanges(); + }, 100); } onDownloadDashboardSettings() { Functions.saveToFile(JSON.stringify(this.dashboardCollection, null, 2), `${this.dashboardTitle}.json`); @@ -252,6 +527,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { columns: _d.config.columns || 5, maxrows: _d.config.maxrows || 5, pushing: !!_d.config.pushing, + ignoreMinSize: _d.config.ignoreMinSize || 'warning', gridType: _d.config.gridType || GridType.Fit, }}); @@ -272,11 +548,12 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { dd.config.columns = data.columns; dd.config.maxrows = data.maxrows; dd.config.pushing = data.pushing; + dd.config.ignoreMinSize = data.ignoreMinSize; dd.config.gridType = data.gridType; ((g, c) => { - g.maxRows = g.minRows = c.maxrows || 5; - g.maxCols = g.minCols = c.columns || 5; + g.rows = g.maxRows = g.minRows = c.maxrows || 5; + g.column = g.maxCols = g.minCols = c.columns || 5; g.pushItems = !!c.pushing; g.disablePushOnDrag = !c.pushing; g.disablePushOnResize = !c.pushing; @@ -288,11 +565,13 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { this.changedOptions(); })(this.dashboardCollection, _d); - this.onDashboardSave().toPromise().then(() => { this.getData(); this._ds.update(); + this.resizeExcess(); + this.checkWidgets(); }); + this.cdr.detectChanges(); } async onDashboardDelete() { @@ -300,7 +579,9 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { this._ds.deleteDashboardStore(this._ds.getCurrentDashBoardId()).toPromise().then(() => { this.router.navigateByUrl('/'); this._ds.update(); + this.cdr.detectChanges(); }); + this.cdr.detectChanges(); } } @@ -320,6 +601,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { } ngOnDestroy() { + clearInterval(this._interval); } private getWidgetItemClass(item: DashboardContentModel): IWidgetMetaData { diff --git a/src/app/components/dashboard/delete-dialog/delete-dialog.component.css b/src/app/components/dashboard/delete-dialog/delete-dialog.component.scss similarity index 100% rename from src/app/components/dashboard/delete-dialog/delete-dialog.component.css rename to src/app/components/dashboard/delete-dialog/delete-dialog.component.scss diff --git a/src/app/components/dashboard/delete-dialog/delete-dialog.component.ts b/src/app/components/dashboard/delete-dialog/delete-dialog.component.ts index d372f419..3ddcd079 100644 --- a/src/app/components/dashboard/delete-dialog/delete-dialog.component.ts +++ b/src/app/components/dashboard/delete-dialog/delete-dialog.component.ts @@ -4,7 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; @Component({ selector: 'app-delete-dialog', templateUrl: './delete-dialog.component.html', - styleUrls: ['./delete-dialog.component.css'] + styleUrls: ['./delete-dialog.component.scss'] }) export class DeleteDialogComponent { diff --git a/src/app/components/dashboard/edit-dialog/edit-dialog.component.html b/src/app/components/dashboard/edit-dialog/edit-dialog.component.html index 46290f17..f90c86ff 100644 --- a/src/app/components/dashboard/edit-dialog/edit-dialog.component.html +++ b/src/app/components/dashboard/edit-dialog/edit-dialog.component.html @@ -53,6 +53,20 @@

Grid Configuration

Pushing + + +
+
+
+

Widget overflow

+ + Widget minimum size mode + + + {{mode.key}} + + +

diff --git a/src/app/components/dashboard/edit-dialog/edit-dialog.component.css b/src/app/components/dashboard/edit-dialog/edit-dialog.component.scss similarity index 100% rename from src/app/components/dashboard/edit-dialog/edit-dialog.component.css rename to src/app/components/dashboard/edit-dialog/edit-dialog.component.scss diff --git a/src/app/components/dashboard/edit-dialog/edit-dialog.component.ts b/src/app/components/dashboard/edit-dialog/edit-dialog.component.ts index f18e3d4c..ca6ebac5 100644 --- a/src/app/components/dashboard/edit-dialog/edit-dialog.component.ts +++ b/src/app/components/dashboard/edit-dialog/edit-dialog.component.ts @@ -11,12 +11,13 @@ export interface DashboardConfig { columns: number; maxrows: number; pushing: boolean; + ignoreMinSize: string; } @Component({ selector: 'app-edit-dialog', templateUrl: './edit-dialog.component.html', - styleUrls: ['./edit-dialog.component.css'] + styleUrls: ['./edit-dialog.component.scss'] }) export class EditDialogComponent { typeList = []; @@ -29,7 +30,11 @@ export class EditDialogComponent { }; isHomeOrSearch = false; isSEARCH = false; - + ignoreMinSizeList: { [key: string]: string } = { + /*'Limit': 'limit', */ + 'Warning': 'warning', + 'Ignore': 'Ignore' + }; callBackExport: Function = null; constructor( diff --git a/src/app/components/login/login.component.scss b/src/app/components/login/login.component.scss index 10b5ca0f..74babf54 100644 --- a/src/app/components/login/login.component.scss +++ b/src/app/components/login/login.component.scss @@ -17,10 +17,10 @@ mat-card-content { text-align: center; display: flex; flex-direction: column; - h2 { + & h2 { margin-top: 2rem; } - > img { + & > img { width: 190px; } } diff --git a/src/app/components/menu/menu.component.css b/src/app/components/menu/menu.component.css deleted file mode 100644 index 4b0e74da..00000000 --- a/src/app/components/menu/menu.component.css +++ /dev/null @@ -1,100 +0,0 @@ -@keyframes spin { - 100% { - transform: rotate(360deg); transform:rotate(360deg); - } -} - -.logo-base { - display: flex; - align-items: center; - cursor: pointer; -} -.btn-refrash { - z-index: 1; - /* border-right: 1px solid #fff; - border-radius: 0; */ - margin: 0; - padding: 0px; - min-width: initial; - margin-right: 4px; - padding-right: 2px; -} -.btn-refrash-timer { - border-left: 1px solid #fff; - border-radius: 0; - margin-left: 0; - min-width: initial; - padding-left: 0.5rem; -} -button:focus { - outline: none; -} -.menu-item-active { - font-weight: bold; - box-shadow: inset 0 0 8px -4px #000; -} -.logo-text { - border-bottom-color: rgb(255, 255, 255); - border-bottom-style: none; - border-bottom-width: 0px; - border-image-outset: 0px; - border-image-repeat: stretch; - border-image-slice: 100%; - border-image-source: none; - border-image-width: 1; - border-left-color: rgb(255, 255, 255); - border-left-style: none; - border-left-width: 0px; - border-right-color: rgb(255, 255, 255); - border-right-style: none; - border-right-width: 0px; - border-top-color: rgb(255, 255, 255); - border-top-style: none; - border-top-width: 0px; - box-sizing: border-box; - color: rgb(255, 255, 255); - display: inline-block; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 30px; - height: 42px; - line-height: 32px; - margin-bottom: 0px; - margin-left: 0px; - margin-right: 0px; - margin-top: -5px; - outline-color: rgb(255, 255, 255); - outline-style: none; - outline-width: 0px; - padding-bottom: 5px; - padding-left: 5px; - padding-right: 5px; - padding-top: 5px; - text-size-adjust: 100%; - vertical-align: baseline; - width: 120.906px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -.logo-text:first-letter { - color: #E0121A; -} -.logo-base > img { - width: 30px; - margin-left: -14px; -} -.header { - justify-content: space-between; -} -.header .ng-star-inserted .md-drppicker .buttons { - position: absolute; - right: 1rem; - bottom: 1rem; -} -.time-range-icon { - margin: -34px !important; - height: 24px; - top: 7px; - margin-left: 0 !important; -} -.loading-anim { - animation: spin 1.5s linear infinite; -} diff --git a/src/app/components/menu/menu.component.scss b/src/app/components/menu/menu.component.scss new file mode 100644 index 00000000..0c7d6697 --- /dev/null +++ b/src/app/components/menu/menu.component.scss @@ -0,0 +1,103 @@ +@keyframes spin { + 100% { + transform: rotate(360deg); transform:rotate(360deg); + } +} + +.logo-base { + display: flex; + align-items: center; + cursor: pointer; + & > img { + width: 32px; + } +} +.btn-refrash { + z-index: 1; + margin: 0; + padding: 0px; + min-width: initial; + margin-right: 4px; + padding-right: 2px; +} +.btn-refrash-timer { + border-left: 1px solid #fff; + border-radius: 0; + margin-left: 0; + min-width: initial; + padding-left: 0.5rem; +} +button { + &:focus { + outline: none; + } +} +.menu-item-active { + font-weight: bold; + box-shadow: inset 0 0 8px -4px #000; +} +.logo-text { + border-bottom-color: rgb(255, 255, 255); + border-bottom-style: none; + border-bottom-width: 0px; + border-image-outset: 0px; + border-image-repeat: stretch; + border-image-slice: 100%; + border-image-source: none; + border-image-width: 1; + border-left-color: rgb(255, 255, 255); + border-left-style: none; + border-left-width: 0px; + border-right-color: rgb(255, 255, 255); + border-right-style: none; + border-right-width: 0px; + border-top-color: rgb(255, 255, 255); + border-top-style: none; + border-top-width: 0px; + box-sizing: border-box; + color: rgb(255, 255, 255); + display: inline-block; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 30px; + height: 42px; + line-height: 32px; + margin-bottom: 0px; + margin-left: 0px; + margin-right: 0px; + margin-top: -5px; + outline-color: rgb(255, 255, 255); + outline-style: none; + outline-width: 0px; + padding-bottom: 5px; + padding-left: 5px; + padding-right: 5px; + padding-top: 5px; + text-size-adjust: 100%; + vertical-align: baseline; + width: 120.906px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + &:first-letter { + color: #E0121A; + } +} +.header { + justify-content: space-between; + .ng-star-inserted { + .md-drppicker { + .buttons { + position: absolute; + right: 1rem; + bottom: 1rem; + } + } + } +} +.time-range-icon { + margin: -34px !important; + height: 24px; + top: 7px; + margin-left: 0 !important; +} +.loading-anim { + animation: spin 1.5s linear infinite; +} diff --git a/src/app/components/menu/menu.component.ts b/src/app/components/menu/menu.component.ts index 5fecc6a0..bb72e7a9 100644 --- a/src/app/components/menu/menu.component.ts +++ b/src/app/components/menu/menu.component.ts @@ -25,7 +25,7 @@ export interface DashboardData { @Component({ selector: 'app-menu', templateUrl: './menu.component.html', - styleUrls: ['./menu.component.css'] + styleUrls: ['./menu.component.scss'] }) export class MenuComponent implements OnInit, OnDestroy { sessionStorageSubscription: Subscription; @@ -184,7 +184,12 @@ export class MenuComponent implements OnInit, OnDestroy { param: data.param || data.nameNewPanel.toLowerCase(), shared: 0, weight: 10, - widgets: [] + widgets: [], + config: { + ignoreMinSize: 'warning', + maxrows:5, + columns: 5 + } }; if (data.dashboard) { dashboardData = data.dashboard; diff --git a/src/app/components/modal-resizable/modal-resizable.component.css b/src/app/components/modal-resizable/modal-resizable.component.css deleted file mode 100644 index 32dee2f2..00000000 --- a/src/app/components/modal-resizable/modal-resizable.component.css +++ /dev/null @@ -1,144 +0,0 @@ -.on-top { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - display: flex; - align-items: center; - justify-content: center; - /* debug */ - /* background-color: rgba(0,0,0,0.2); */ - width: 1px; - height: 1px; - margin: auto; -} - -.detail-container .title { - cursor: move; -} -.detail-container { - position: relative; - min-width: 200px; - min-height: 200px; - width: 60vw; - border: solid 1px #ccc; - color: rgba(0, 0, 0, 0.87); - /* -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; */ - justify-content: center; - padding: 1.5rem; - overflow: hidden; - background: #fff; - border-radius: 4px; - z-index: 1; - opacity: 1; - /* transition: all 0.3s cubic-bezier(0, 0, 0.2, 1); */ - box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), - 0 2px 2px 0 rgba(0, 0, 0, 0.14), - 0 1px 5px 0 rgba(0, 0, 0, 0.12) -} - -.detail-container:active { - box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), - 0 8px 10px 1px rgba(0, 0, 0, 0.14), - 0 3px 14px 2px rgba(0, 0, 0, 0.12); -} - -.detail-container.full-page { - border: solid 0px #ccc; - border-radius: 0px; - min-width: 100vw !important; - width: 100vw !important; - min-height: 100vh !important; - transform: translate3d(0px, 0px, 0px) !important; -} -.title { - margin: -1.5rem -1.5rem 0 -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} - -.detail-container table { - width: 100%; - overflow: auto; -} -.detail-container table tr { - /* transition: background-color 0.3s; */ -} -.detail-container table tr:hover { - background-color: rgba(0, 0, 0, 0.12); - - cursor: pointer; -} - -.inside-content { - position: absolute; - left: 0.3rem; - right: 0.3rem; - top: 45px; - bottom: 0.3rem; -} - -/* resize controls elements */ -.animation-off { - transition: none; -} -.resize { - position: absolute; -} -.resize.right { - width: 0.5rem; - right: 0; - height: 100%; - top: 0; - cursor: ew-resize; -} -.resize.bottom { - bottom: 0; - height: 0.5rem; - width: 100%; - left: 0; - cursor: ns-resize; -} -.resize.left { - width: 0.5rem; - left: 0; - height: 100%; - top: 0; - cursor: ew-resize; -} -.resize.top { - top: 0; - height: 0.5rem; - width: 100%; - left: 0; - cursor: ns-resize; -} - -.resize.corner { - width: 1rem; - height: 1rem; - cursor: nwse-resize; -} -.resize.corner.tl { - top: 0; - left: 0; -} -.resize.corner.tr { - top: 0; - right: 0; - cursor: nesw-resize; -} -.resize.corner.bl { - bottom: 0; - left: 0; - cursor: nesw-resize; -} -.resize.corner.br { - right: 0; - bottom: 0; -} diff --git a/src/app/components/modal-resizable/modal-resizable.component.html b/src/app/components/modal-resizable/modal-resizable.component.html index d1ee30b2..8780f4db 100644 --- a/src/app/components/modal-resizable/modal-resizable.component.html +++ b/src/app/components/modal-resizable/modal-resizable.component.html @@ -7,7 +7,7 @@ [ngStyle]="{'background-color': headerColor}" (mousedown)="onStartMove($event)">
{{ title }}
-
+
- Advanced Settings
Partition ID diff --git a/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.scss b/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.ts b/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.ts index 59f33a24..4970bc2f 100644 --- a/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.ts +++ b/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.ts @@ -4,7 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; @Component({ selector: 'app-dialog-advanced', templateUrl: './dialog-advanced.component.html', - styleUrls: ['./dialog-advanced.component.css'] + styleUrls: ['./dialog-advanced.component.scss'] }) export class DialogAdvancedComponent { diff --git a/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.css b/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.scss b/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.ts b/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.ts index 5554d2cb..c8298820 100644 --- a/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.ts +++ b/src/app/components/preference/dialogs/dialog-agentsub/dialog-agentsub.component.ts @@ -4,7 +4,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @Component({ selector: 'app-dialog-agentsub', templateUrl: './dialog-agentsub.component.html', - styleUrls: ['./dialog-agentsub.component.css'] + styleUrls: ['./dialog-agentsub.component.scss'] }) export class DialogAgentsubComponent { diff --git a/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.css b/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.css b/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.scss similarity index 100% rename from src/app/components/preference/dialogs/dialog-advanced/dialog-advanced.component.css rename to src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.scss diff --git a/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.ts b/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.ts index 41db1d59..f7ed6098 100644 --- a/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.ts +++ b/src/app/components/preference/dialogs/dialog-alias/dialog-alias.component.ts @@ -4,7 +4,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @Component({ selector: 'app-dialog-alias', templateUrl: './dialog-alias.component.html', - styleUrls: ['./dialog-alias.component.css'] + styleUrls: ['./dialog-alias.component.scss'] }) export class DialogAliasComponent { diff --git a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.css b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.html b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.html index 2bb45279..cc06a194 100644 --- a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.html +++ b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.html @@ -1,16 +1,15 @@ -
Auth Token: {{ data.isnew ? '': data.data.guid }}
+
Auth Token Settings
- Auth Token Settings
+ Auth Token: {{ data.isnew ? '': data.data.guid }}
Auth Token Name
-
Expire Date @@ -20,8 +19,6 @@
Active
- -
diff --git a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.scss b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.ts b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.ts index 4f40374b..7dfb2c23 100644 --- a/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.ts +++ b/src/app/components/preference/dialogs/dialog-authkey/dialog-authkey.component.ts @@ -4,7 +4,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @Component({ selector: 'app-dialog-authkey', templateUrl: './dialog-authkey.component.html', - styleUrls: ['./dialog-authkey.component.css'] + styleUrls: ['./dialog-authkey.component.scss'] }) export class DialogAuthKeyComponent { constructor( diff --git a/src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.css b/src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.scss similarity index 100% rename from src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.css rename to src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.scss diff --git a/src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.ts b/src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.ts index 6b458819..3c1f2ae1 100644 --- a/src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.ts +++ b/src/app/components/preference/dialogs/dialog-authtoken-display/dialog-authtoken-display.component.ts @@ -4,7 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; @Component({ selector: 'app-dialog-authtoken-display', templateUrl: './dialog-authtoken-display.component.html', - styleUrls: ['./dialog-authtoken-display.component.css'] + styleUrls: ['./dialog-authtoken-display.component.scss'] }) export class DialogAuthTokenDisplayComponent { diff --git a/src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.css b/src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.scss similarity index 100% rename from src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.css rename to src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.scss diff --git a/src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.ts b/src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.ts index 93a8ec0b..a86f5f09 100644 --- a/src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.ts +++ b/src/app/components/preference/dialogs/dialog-delete-alert/dialog-delete-alert.component.ts @@ -4,7 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; @Component({ selector: 'app-dialog-delete-alert', templateUrl: './dialog-delete-alert.component.html', - styleUrls: ['./dialog-delete-alert.component.css'] + styleUrls: ['./dialog-delete-alert.component.scss'] }) export class DialogDeleteAlertComponent { diff --git a/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.css b/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.scss b/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.ts b/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.ts index 644a1717..84b41986 100644 --- a/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.ts +++ b/src/app/components/preference/dialogs/dialog-hepsub/dialog-hepsub.component.ts @@ -4,7 +4,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @Component({ selector: 'app-dialog-hepsub', templateUrl: './dialog-hepsub.component.html', - styleUrls: ['./dialog-hepsub.component.css'] + styleUrls: ['./dialog-hepsub.component.scss'] }) export class DialogHepsubComponent { diff --git a/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.css b/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.scss b/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.ts b/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.ts index 1b6e4f66..44b314de 100644 --- a/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.ts +++ b/src/app/components/preference/dialogs/dialog-mapping/dialog-mapping.component.ts @@ -7,7 +7,7 @@ import 'brace/theme/github'; @Component({ selector: 'app-dialog-mapping', templateUrl: './dialog-mapping.component.html', - styleUrls: ['./dialog-mapping.component.css'] + styleUrls: ['./dialog-mapping.component.scss'] }) export class DialogMappingComponent { constructor( diff --git a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.css b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.html b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.html index a66b87bf..00def4f4 100644 --- a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.html +++ b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.html @@ -1,12 +1,11 @@ -
Account of
+
{{data.data.username}} Settings
- - User Settings
+
Username diff --git a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.scss b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.ts b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.ts index 190e7a83..dd4ecde2 100644 --- a/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.ts +++ b/src/app/components/preference/dialogs/dialog-user-settings/dialog-user-settings.component.ts @@ -4,7 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; @Component({ selector: 'app-dialog-user-settings', templateUrl: './dialog-user-settings.component.html', - styleUrls: ['./dialog-user-settings.component.css'] + styleUrls: ['./dialog-user-settings.component.scss'] }) export class DialogUserSettingsComponent { diff --git a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.css b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.css deleted file mode 100644 index 7086c669..00000000 --- a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.css +++ /dev/null @@ -1,20 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} -.hide { - display: none !important; -} \ No newline at end of file diff --git a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.html b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.html index 3972a9a5..212cf412 100644 --- a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.html +++ b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.html @@ -1,12 +1,11 @@ -
Account of
+
User settings
- - User Settings
+
diff --git a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.scss b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.scss new file mode 100644 index 00000000..f6e6cc07 --- /dev/null +++ b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.scss @@ -0,0 +1,19 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} +.hide { + display: none !important; +} diff --git a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.ts b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.ts index 81e7fa71..ae01d707 100644 --- a/src/app/components/preference/dialogs/dialog-users/dialog-users.component.ts +++ b/src/app/components/preference/dialogs/dialog-users/dialog-users.component.ts @@ -8,7 +8,7 @@ import { emailValidator } from '@app/helpers/email-validator.directive'; @Component({ selector: 'app-dialog-users', templateUrl: './dialog-users.component.html', - styleUrls: ['./dialog-users.component.css'] + styleUrls: ['./dialog-users.component.scss'] }) export class DialogUsersComponent { isValidForm = false; diff --git a/src/app/components/preference/preference.component.css b/src/app/components/preference/preference.component.css deleted file mode 100644 index 4918563b..00000000 --- a/src/app/components/preference/preference.component.css +++ /dev/null @@ -1,31 +0,0 @@ -.menu-title { - padding-left: 1rem; - padding-top: 2rem; -} -.nav-list { - background-color: rgb(238, 238, 238); - flex: 0.1; - min-width: 300px; - padding-left: 2rem; - box-sizing: border-box; -} - -table { - width: 100%; -} - -.mat-form-field { - font-size: 14px; - width: 100%; -} -.loading { - text-align: center; - width: calc(100% - 300px - 4rem); - display: flex; - justify-content: center; - height: 10rem; - align-items: center; - background-color: rgba(0,0,0,0.03); - border-radius: 1rem; - position: absolute; -} \ No newline at end of file diff --git a/src/app/components/preference/preference.component.scss b/src/app/components/preference/preference.component.scss new file mode 100644 index 00000000..c8254923 --- /dev/null +++ b/src/app/components/preference/preference.component.scss @@ -0,0 +1,29 @@ +.menu-title { + padding-left: 1rem; + padding-top: 2rem; +} +.nav-list { + background-color: rgb(238, 238, 238); + flex: 0.1; + min-width: 300px; + padding-left: 2rem; + box-sizing: border-box; +} +table { + width: 100%; +} +.mat-form-field { + font-size: 14px; + width: 100%; +} +.loading { + text-align: center; + width: calc(100% - 300px - 4rem); + display: flex; + justify-content: center; + height: 10rem; + align-items: center; + background-color: rgba(0,0,0,0.03); + border-radius: 1rem; + position: absolute; +} diff --git a/src/app/components/preference/preference.component.ts b/src/app/components/preference/preference.component.ts index 866f7f9b..2f1a2db6 100644 --- a/src/app/components/preference/preference.component.ts +++ b/src/app/components/preference/preference.component.ts @@ -46,7 +46,7 @@ import { SessionStorageService } from '../../services/session-storage.service'; @Component({ selector: 'app-preference', templateUrl: './preference.component.html', - styleUrls: ['./preference.component.css'] + styleUrls: ['./preference.component.scss'] }) export class PreferenceComponent implements OnInit, OnDestroy { isLoading = false; @@ -174,8 +174,8 @@ export class PreferenceComponent implements OnInit, OnDestroy { } else { this.pagesStructure = { users: ['Firstname', 'Lastname', 'Username', 'Email', 'tools'], - 'user settings': ['Username', 'Partid', 'Category', 'Param', 'Data', 'tools'], - advanced: ['Partid', 'Category', 'Param', 'Data'], + 'user settings': ['Username', /*'Partid',*/ 'Category', 'Param', 'Data', 'tools'], + advanced: [/*'Partid',*/ 'Category', 'Param', 'Data'], }; this.service = { diff --git a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.css b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.css deleted file mode 100644 index 67e1482b..00000000 --- a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.css +++ /dev/null @@ -1,40 +0,0 @@ -.loading { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - background-color: rgba(255,255,255,0.6); - display: flex; - justify-content: center; - align-content: center; - align-items: center; - z-index: 9999999; -} - -.button-icon-right-top { - position: absolute; - right: 0; - margin: 0.2rem; - z-index: 2; -} - -.filter-container { - /* background-color: rgb(220, 179, 179); */ - background-color: #fff; - top: 3rem; - right: 1rem; - padding: 1rem; - border: 1px solid rgba(0,0,0,0.2); - border-radius: 4px; - box-shadow: 0px 3px 7px rgba(0,0,0,0.4); -} - -.filter-label { - font-size: 0.8em; - color: rgba(0,0,0,0.8); - background-color: rgba(0,0,0,0.2); - margin: -1rem; - margin-bottom: 1rem; - padding: 0.5rem; -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.html b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.html index cddbe843..797260c5 100644 --- a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.html +++ b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.html @@ -21,13 +21,27 @@ class="button-icon-right-top filter-container" #filterContainer> - {{ isSimplify ? 'Extended Format' : 'Simple Format'}} + Extended Format -
- - {{ isSimplifyPort ? 'Show Ports' : 'Hide Ports'}} +
+ + + Combined by Alias +
+ + + Show Ports +
PayloadType:
{{ checkboxItem.title }}
--> - +
CallId:
@@ -72,9 +86,11 @@ diff --git a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.scss b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.scss new file mode 100644 index 00000000..b61e0c98 --- /dev/null +++ b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.scss @@ -0,0 +1,36 @@ +.loading { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-color: rgba(255,255,255,0.6); + display: flex; + justify-content: center; + align-content: center; + align-items: center; + z-index: 9999999; +} +.button-icon-right-top { + position: absolute; + right: 0; + margin: 0.2rem; + z-index: 2; +} +.filter-container { + background-color: #fff; + top: 3rem; + right: 1rem; + padding: 1rem; + border: 1px solid rgba(0,0,0,0.2); + border-radius: 4px; + box-shadow: 0px 3px 7px rgba(0,0,0,0.4); +} +.filter-label { + font-size: 0.8em; + color: rgba(0,0,0,0.8); + background-color: rgba(0,0,0,0.2); + margin: -1rem; + margin-bottom: 1rem; + padding: 0.5rem; +} diff --git a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.ts b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.ts index 2bd3bab0..531ecf4f 100644 --- a/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/detail-dialog.component.ts @@ -1,22 +1,36 @@ -import { Component, Input, Output, EventEmitter, OnInit, HostListener, ElementRef, ViewChild } from '@angular/core'; +import { + Component, + Input, + Output, + EventEmitter, + OnInit, + HostListener, + ElementRef, + ViewChild, + ChangeDetectionStrategy +} from '@angular/core'; import { Functions } from '../../../helpers/functions'; import { PreferenceAdvancedService } from '@app/services'; +import { ChangeDetectorRef } from '@angular/core'; @Component({ selector: 'app-detail-dialog', templateUrl: './detail-dialog.component.html', - styleUrls: ['./detail-dialog.component.css'] + styleUrls: ['./detail-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class DetailDialogComponent implements OnInit { @Input() titleId: string; @Input() sipDataItem: any; - @Input() qosData: any; + @Input() headerColor: any; @Input() mouseEventData: any; @Input() snapShotTimeRange: any; isSimplify = true; - isSimplifyPort = true; + isSimplifyPort = false; + isCombineByAlias = true; IdFromCallID; + RTPFilterForFLOW = true; activeTab = 0; isFilterOpened = false; isFilterOpenedOutside = false; @@ -27,6 +41,7 @@ export class DetailDialogComponent implements OnInit { logs: true, export: false }; + public flowFilters: any; exportAsPNG = false; isBrowserWindow = false; _isLoaded = false; @@ -79,16 +94,28 @@ export class DetailDialogComponent implements OnInit { })); this.checkboxListFilterCallId = filterByParam('sid'); + this.changeDetectorRefs.detectChanges(); } } + _qosData: any; + + @Input() set qosData(value) { + this._qosData = value; + this.changeDetectorRefs.detectChanges(); + } + get qosData() { + return this._qosData; + } + @Output() openMessage: EventEmitter = new EventEmitter(); @Output() close: EventEmitter = new EventEmitter(); @ViewChild('filterContainer', {static: false}) filterContainer: ElementRef; dataLogs: Array; - + constructor( - private _pas: PreferenceAdvancedService + private _pas: PreferenceAdvancedService, + private changeDetectorRefs: ChangeDetectorRef ) { } ngOnInit () { @@ -102,10 +129,22 @@ export class DetailDialogComponent implements OnInit { this.tabs.logs = true; // this.dataLogs.length > 0; this.tabs.messages = this.tabs.flow = this.sipDataItem.data.messages.length > 0; this.tabs.export = this.sipDataItem.data.messages && !!this.IdFromCallID; + this.changeDetectorRefs.detectChanges(); } onTabQos(isVisible: boolean) { setTimeout(() => { this.tabs.qos = isVisible; + if (isVisible) { + const isRTP = this._qosData && this._qosData.rtp && this._qosData.rtp.data && this._qosData.rtp.data.length > 0; + if (isRTP) { + this.checkboxListFilterPayloadType.push({ + payloadType: '5', + selected: true, + title: 'RTP' + }); + this.changeDetectorRefs.detectChanges(); + } + } }); } onClose () { @@ -113,7 +152,7 @@ export class DetailDialogComponent implements OnInit { } addWindow(data: any) { - if (data.method === 'LOG') { + if (data.method === 'LOG' || data.typeItem === 'RTP') { this.openMessage.emit({ data: data, isLog: true, @@ -144,6 +183,7 @@ export class DetailDialogComponent implements OnInit { if (tabpositon && typeof tabpositon === 'string' && tabpositon !== '') { this.tabIndexByDefault = Object.keys(this.tabs).indexOf(tabpositon); this.activeTab = this.tabIndexByDefault; + this.changeDetectorRefs.detectChanges(); } } } catch (err) { } @@ -153,7 +193,10 @@ export class DetailDialogComponent implements OnInit { onExportFlowAsPNG() { this.exportAsPNG = true; - setTimeout(() => { this.exportAsPNG = false; }); + setTimeout(() => { + this.exportAsPNG = false; + this.changeDetectorRefs.detectChanges(); + }); } doFilterMessages() { setTimeout(() => { @@ -171,16 +214,29 @@ export class DetailDialogComponent implements OnInit { return boolPayloadType && boolPort && boolCallId; }); + + const RTPFilter = this.checkboxListFilterPayloadType.find(i => i.title === 'RTP'); + this.RTPFilterForFLOW = RTPFilter ? RTPFilter.selected : true; + const selectedId = this.sipDataItem.data.messages.map(i => i.id); this.sipDataItem.data.calldata = fc(this._messagesBuffer).calldata.filter(i => selectedId.includes(i.id)); this.sipDataItem = Functions.cloneObject(this.sipDataItem); // refresh data + this.flowFilters = { + isSimplify: this.isSimplify, + isSimplifyPort: !this.isSimplifyPort, + isCombineByAlias: this.isCombineByAlias, + PayloadType: this.checkboxListFilterPayloadType, + CallId: this.checkboxListFilterCallId + }; + this.changeDetectorRefs.detectChanges(); }, 100); } doOpenFilter() { setTimeout(() => { this.isFilterOpened = true; + this.changeDetectorRefs.detectChanges(); }, 10); } @@ -190,6 +246,7 @@ export class DetailDialogComponent implements OnInit { const clickedInside = this.filterContainer.nativeElement.contains(targetElement); if (!clickedInside && this.isFilterOpened) { this.isFilterOpened = false; + this.changeDetectorRefs.detectChanges(); } } } diff --git a/src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.css b/src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.scss similarity index 100% rename from src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.css rename to src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.scss diff --git a/src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.ts index 384badd3..c244d6fb 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-export/tab-export.component.ts @@ -7,7 +7,7 @@ import { SearchService } from '@app/services'; @Component({ selector: 'app-tab-export', templateUrl: './tab-export.component.html', - styleUrls: ['./tab-export.component.css'] + styleUrls: ['./tab-export.component.scss'] }) export class TabExportComponent implements OnInit { @Input() callid; diff --git a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.css b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.css deleted file mode 100644 index c9b9bb50..00000000 --- a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.css +++ /dev/null @@ -1,102 +0,0 @@ -.title-container { - display: flex; - justify-content: space-between; - padding: 0.3rem; - position: absolute; - overflow: hidden; - z-index: 2; - right: 20px; - left: 0; -} -.title-container > div { - flex: 1; - min-width: 150px; -} -.title-container > div > .title { - display: inline-block; - border-radius: 4px; - background-color: #eee; - padding: 0.3rem; - font-size: 0.8em; - border: 1px solid #aaa; - /* box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5); */ -} - -.title-container > .grid-vertical-line { - border-right: 1px dotted #ccc; -} - -.grid-container { - z-index: -1; - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - padding: 0; -} - -.arrow { - position: relative; - border-bottom: 2px solid; - padding: 0.5rem 0; - font-size: 0.7em; - cursor: pointer; - background-color: transparent; - transition: background-color 0.3s; - min-width: 150px; -} -.arrow > * { - padding: 0 4px; -} -.rtcp { - border-bottom-style: dotted; -} -.arrow:hover { - background-color: rgba(0, 0, 0, 0.2); -} -.arrow.right > div { - text-align: left; -} -.arrow.left > div { - text-align: right; -} - -.right:before { - content: ""; - border: 7px solid transparent; - border-left: 14px solid; - position: absolute; - right: -8px; - bottom: -8.5px; -} -.left:before { - content: ""; - border: 7px solid transparent; - border-right: 14px solid; - position: absolute; - left: -8px; - bottom: -7.5px; -} - -.label-callid-container { - position: absolute; - left: 0; - right: 0; - margin: auto; - bottom: 20px; - text-align: center; -} - -.label-callid { - text-align: center; - font-weight: 900; - display: inline-block; - padding: 0 1rem; -} -.disable-arrow { - border: 0px !important; -} -.disable-arrow:before { - border: 0px solid transparent !important; -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.html b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.html index b08e959f..cd9ae928 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.html +++ b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.html @@ -1,55 +1,93 @@ -
- -
-
- - {{ title.alias }} -
- {{ title.IP + (!_isSimplifyPort ? title.PORT : '')}} -
- - {{ title.IP + (!_isSimplifyPort ? title.PORT : '') }} - -
+
+ +
+
-
- -
-
+ +
+ + +
+
+
+
{{(!_isSimplifyPort ? 'PORT:' + itemhost.PORT : '')}}
+
{{ itemhost.shortIPtext2 }}
+
+
{{ shortcutIPv6String(ip) }}
+
+
{{ + itemhost.alias === itemhost.ip || itemhost.alias === '' ? + itemhost.shortIPtext2 : + itemhost.alias + }}
+
+
+
- -
-
{{ item.method_text }}
-
{{ item.ruri_user }}
- -
+ +
+
+
-
[{{ idx + 1 }}][{{ item.proto | uppercase }}] {{ item.micro_ts }}
-
+ {{ item.diffTs }} s
+
+
+
{{ + item.method_text + }} {{ + item.QOS ? item.QOS.MOS + ' [' + item.QOS.qosTYPEless + ']' : '' + }}
+
{{item.ruri_user}}
+
{{ item.srcPort }}
+ +
+ +
+ +
{{ item.dstPort }}
+
[{{ idx + 1 }}][{{ item.proto | uppercase }}] {{ item.micro_ts }}
+
+ {{ item.diffTs }} s
+
+
+
-
-
-
* {{ itemLabel.callid }}
-
+
+
* {{ itemLabel.callid }}
+
+ diff --git a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.scss b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.scss new file mode 100644 index 00000000..0f5adc0d --- /dev/null +++ b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.scss @@ -0,0 +1,255 @@ +@keyframes flashing_flashlight { + from { + padding: 0rem; + margin: 0.5rem; + opacity: 0.3; + } + 50% { + opacity: 1; + } + to { + padding: 0.5rem; + margin: 0rem; + opacity: 0.3; + } +} + +.flow-grid-lines { + display: flex; + justify-content: space-between; + margin: 0px 50px; + position: absolute; + top: 0; + z-index: -1; + left: 0px; + bottom: -50px; + right: 0px; + transition: all 0.3s ease; + .line { + margin-right: -1px; + border: 1px dotted #999; + border-right-width: 1px; + border-left-width: 1px; + border-bottom: 0; + min-width: 150px; + transition: all 0.3s ease; + flex: 1; + } +} +::ng-deep .mat-tooltip { + font-size: 14px; +} +.hosts { + position: sticky; + top: 0px; + display: flex; + justify-content: space-between; + z-index: 1; + background: white; + + .item-wrapper { + min-width: 200px; + transition: all 0.3s ease; + &.big { + min-width: 150px; + } + &.hidden { + display: none; + } + &:last-child { + min-width: 0px; + } + .item { + margin: 0; + background-color: #fff; + font-size: 12px; + padding: 0.3rem; + font-weight: 700; + border-bottom: 1px dotted #999; + padding-top: 1rem; + margin-top: 0; + display: flex; + width: 100px; + flex-direction: column; + justify-content: flex-end; + align-items: center; + height: 60px; + } + } +} +.flow-packets-wrapper { + display: flex; + flex-direction: column; + justify-content: flex-start; + margin: 0 50px; + & > div { + display: flex; + justify-content: space-between; + min-width: 150px; + position: relative; + overflow: hidden; + max-height: 95px; + transition: all 0.3s ease; + & > div { + transition: all 0.3s ease; + } + .bg-color-polygon { + position: absolute; + z-index: 0; + opacity: 0.1; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: 0px -50px; + } + .item-flow-packet { + position: relative; + width: 150px; + transition: all 0.3s ease; + &:hover { + background-color: rgba(0, 0, 0, 0.2); + border-radius: 4px; + cursor: pointer; + } + .redial-arrow { + position: relative; + margin-left: 0; + width: 25px; + height: 30px; + border: 2px solid; + border-left: 0px; + border-top-right-radius: 5rem; + border-bottom-right-radius: 5rem; + } + .redial-arrow.rtp { + border-style: dotted; + } + .redial-arrow::before { + content: ""; + border: 7px solid transparent; + border-right: 14px solid; + position: absolute; + left: -9px; + top: 20px; + } + .blinkLamp { + display: inline-block; + padding: 6px; + margin: 0; + border-radius: 1rem; + box-shadow: inset -2px -2px 3px -2px #000; + &.red { + // animation: flashing_flashlight 1s infinite ease-in-out; + background-color:red; + } + &.gray { + // animation: flashing_flashlight 1s infinite ease-in-out; + background-color: gray; + } + &.orange { + // animation: flashing_flashlight 1s infinite ease-in-out; + background-color: orange; + } + &.green { + background-color: #00e600; + } + } + .call_text { + font-size: 16px; + font-weight: 600; + color: #24465f; + padding: 0 4px; + } + .call_text-mini { + font-size: 12px; + color: #24465f; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + transition: height 0.3s ease; + padding: 0 4px; + + } + .port-label-right { + color: #000; + width: 50px; + position: absolute; + right: -47px; + padding: 2px 6px; + border-radius: 32px; + margin-top: -11px; + text-align: center; + font-size: 12px; + color: rgba(0,0,0,0.5); + } + .port-label-left { + color: #000; + width: 50px; + position: absolute; + left: -47px; + padding: 2px 6px; + border-radius: 32px; + margin-top: -11px; + text-align: center; + font-size: 12px; + color: rgba(0,0,0,0.5); + } + .call-text-date { + font-size: 12px; + color: #7e7e7e !important; + overflow: hidden; + transition: max-height 0.3s ease; + padding: 0 4px; + } + .arrow { + // border-bottom: 2px solid; + padding-right: 3px; + padding-left: 3px; + position: relative; + &.arrow-solid { + border-bottom: 2px solid; + } + &.arrow-dotted { + border-bottom: 2px dotted; + } + &:before { + content: ""; + border: 7px solid transparent; + border-left: 14px solid; + position: absolute; + right: -8px; + bottom: -7.5px; + } + &.left { + &:before { + content: ""; + border: 7px solid transparent; + border-right: 14px solid; + position: absolute; + right: initial; + left: -8px; + bottom: -7.5px; + } + } + } + } + } +} +.label-callid-container { + position: absolute; + left: 0; + right: 0; + margin: auto; + line-height: 7px; + bottom: 19px; + text-align: center; + font-size: 12px; + font-weight: 700; + .label-callid-wrapper { + background-color:rgba(255,255,255,0.7); + display: inline-block; + padding: 5px; + border-radius: 4px; + } +} diff --git a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.ts index f67ccea7..73441549 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-flow/tab-flow.component.ts @@ -1,81 +1,113 @@ -import { Component, OnInit, Input, Output, EventEmitter, AfterViewInit, ViewChild, OnDestroy, ElementRef } from '@angular/core'; +import { + Component, + OnInit, + Input, + Output, + EventEmitter, + AfterViewInit, + ViewChild, + OnDestroy, + ElementRef, + ChangeDetectionStrategy, + ChangeDetectorRef +} from '@angular/core'; import * as moment from 'moment'; import { MesagesData } from '../tab-messages/tab-messages.component'; import { Functions } from '../../../../helpers/functions'; import * as html2canvas from 'html2canvas'; +enum FlowItemType { + SIP = 'SIP', + SDP = 'SDP', + RTP = 'RTP', + RTCP = 'RTCP' +} + @Component({ selector: 'app-tab-flow', templateUrl: './tab-flow.component.html', - styleUrls: ['./tab-flow.component.css'] + styleUrls: ['./tab-flow.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class TabFlowComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('flowtitle', {static: false}) flowtitle; - _isSimplify = false; @Input() set isSimplify(val: boolean) { this._isSimplify = val; + this.cdr.detectChanges(); } get isSimplify() { return this._isSimplify; } - - _isSimplifyPort = false; + _qosData: any; _flagAfterViewInit = false; - @Input() - set isSimplifyPort(val: boolean) { - this._isSimplifyPort = val; - } - get isSimplifyPort() { - return this._isSimplifyPort; + _isSimplify = false; + public _isSimplifyPort = true; + public _isCombineByAlias = true; + private _dataItem: any; + flowGridLines = []; + isExport = false; + hosts: Array; + arrayItems: Array = []; + color_sid: string; + labels: Array = []; + + @Input() set flowFilters(filters: any) { + if (!filters) { + return; + } + this._isSimplifyPort = !filters.isSimplifyPort; + this._isCombineByAlias = filters.isCombineByAlias; + setTimeout(this.initData.bind(this)); } @Input() callid: any; - _dataItem: any; - @Input() set dataItem(val) { - this._dataItem = val; + + @Input() set dataItem(dataItemValue) { + this._dataItem = dataItemValue; setTimeout(this.initData.bind(this)); } get dataItem () { return this._dataItem; } + @Input() set qosData(value) { + this._qosData = value; + const { rtp } = this._qosData; + const arrRTP = rtp.data.map((i, key) => this.formattingQosItemAsFlowElement(i, key)); + this.arrayItemsRTP_AGENT = [].concat(arrRTP); + setTimeout(this.initData.bind(this)); + } + _RTPFilterForFLOW = true; + @Input() set RTPFilterForFLOW(val: boolean) { + this._RTPFilterForFLOW = val; + this.initData(); + } + get RTPFilterForFLOW() { + return this._RTPFilterForFLOW; + } @Input() set exportAsPNG(val) { if (val) { this.isExport = true; - setTimeout(() => { - this.onSavePng(); - }, 500); + this.cdr.detectChanges(); + setTimeout(this.onSavePng.bind(this), 500); } } @Output() messageWindow: EventEmitter = new EventEmitter(); @ViewChild('flowpage', {static: true}) flowpage: ElementRef; @ViewChild('flowscreen', {static: true}) flowscreen: ElementRef; - //
@ViewChild('canvas', {static: true}) canvas: ElementRef; @ViewChild('downloadLink', {static: true}) downloadLink: ElementRef; - isExport = false; + aliasTitle: Array; dataSource: Array = []; - arrayItems: Array; - color_sid: string; + arrayItemsRTP_AGENT: Array = []; _interval: any; - labels: Array = []; - constructor() { } + constructor(private cdr: ChangeDetectorRef) { } ngAfterViewInit() { - const self = this; - if (!this._interval) { - this._interval = setInterval(() => { - try { - const wftc = self.flowpage.nativeElement.parentElement.parentElement; - self.flowtitle.nativeElement.style.left = -wftc.scrollLeft + 'px'; - } catch (e) { } - } , 20); // 60 fps - } - this._flagAfterViewInit = true; } ngOnDestroy () { @@ -84,21 +116,110 @@ export class TabFlowComponent implements OnInit, AfterViewInit, OnDestroy { ngOnInit() { this.initData(); } + formattingQosItemAsFlowElement (item: any, pid: number) { + item = Functions.cloneObject(item); + item.micro_ts = item.micro_ts || (item.timeSeconds * 1000 + item.timeUseconds / 1000); + const sIP = item.srcIp; + const sPORT = item.srcPort; + const dIP = item.dstIp; + const dPORT = item.dstPort; + const diffTs = 0; + const protoName = Functions.protoCheck(item.proto).toUpperCase(); + const eventName = item.proto === 'rtcp' ? 'RTCP' : 'RTP'; + const typeItem = item.proto === 'rtcp' ? 'RTCP' : 'RTP'; + return { + id: item.id, + callid: item.sid, + sid: item.sid, + method_text: eventName, + ruri_user: `${sIP}:${sPORT} -> ${dIP}:${dPORT}`, + info_date: `[${pid}][${protoName}] ${moment(item.micro_ts).format('YYYY-MM-DD HH:mm:ss.SSS Z')}`, + diff: `+${diffTs.toFixed(2)}ms`, + source_ip : sIP, + source_port : sPORT, + srcId: item.srcId || `${sIP}:${sPORT}`, + dstId: item.dstId || `${dIP}:${dPORT}`, + srcIp: item.srcIp, + srcPort: item.srcPort, + dstIp: item.dstIp, + dstPort: item.dstPort, + destination_ip: dIP, + destination_port: dPORT, + micro_ts: (item.timeSeconds * 1000 + item.timeUseconds / 1000), + source_data: item, + typeItem, + QOS: item, + MOS: item.raw.MOS, + __is_flow_item__: true, + RTPmessageData: { + id: item.id || '--', + create_date: moment(item.micro_ts).format('YYYY-MM-DD'), + timeSeconds: moment(item.micro_ts).format('HH:mm:ss.SSS Z'), + diff: `${diffTs.toFixed(2)} s`, + method: eventName, + mcolor: Functions.getMethodColor(eventName), + Msg_Size: item.raw ? (JSON.stringify(item.raw) + '').length : '--', + srcIp_srcPort: `${sIP}:${sPORT}`, + dstIp_dstPort: `${dIP}:${dPORT}`, + dstPort: dPORT, + proto: protoName, + type: typeItem, + item: item + } + }; + } initData() { - this.color_sid = Functions.getColorByString(this.callid); + this.color_sid = Functions.getColorByString(this.callid, 100, 40, 1); - const IpList = ([].concat(...this.dataItem.data.calldata.map(i => [i.srcId, i.dstId]))).reduce((a, b) => { - if (!a.includes(b)) { - a.push(b); + let hosts = Functions.cloneObject(this.dataItem.data.hosts); + /** added host from RTP AGENT */ + if (this._RTPFilterForFLOW) { + this.arrayItemsRTP_AGENT.forEach(item => { + [`${item.source_ip}:${item.source_port}`, `${item.destination_ip}:${item.destination_port}`] + .forEach( IP_PORT => { + if (!hosts[IP_PORT]) { + hosts[IP_PORT] = { + host: [IP_PORT], + position: Object.keys(hosts).length + }; + } + }); + }); + } + const data = this.dataItem.data; + const sortedArray = [].concat( + ...(this._RTPFilterForFLOW ? this.arrayItemsRTP_AGENT : []), + ...data.calldata) + .sort((itemA, itemB) => { + const a = itemA.micro_ts; + const b = itemB.micro_ts; + return a < b ? -1 : a > b ? 1 : 0; + }); + + const IpList = [].concat(...sortedArray.map(i => [i.srcId, i.dstId])).reduce((a, b) => { + const _ip = this._isSimplifyPort ? b.match(/\d+$|(\[.*\]|\d+\.\d+\.\d+\.\d+)/g)[0] : b; + if (!a.includes(_ip)) { + a.push(_ip); } return a; }, []); + if (this._isSimplifyPort ) { + const hostNoPortsArray = Object.keys(hosts).sort().map(i => i.match(/\d+$|(\[.*\]|\d+\.\d+\.\d+\.\d+)/g)).filter((i, k, a) => { + if (a[k - 1]) { + return a[k - 1][0] !== i[0]; + } + return true; + }).map(i => i.join(':')); + const filterdHostd = hostNoPortsArray.reduce((a, b) => { + const _ip = this._isSimplifyPort ? b.match(/\d+$|(\[.*\]|\d+\.\d+\.\d+\.\d+)/g)[0] : b; + a[_ip] = hosts[b]; + return a; + }, {}); - let hosts = Functions.cloneObject(this.dataItem.data.hosts); + hosts = filterdHostd; + } - /* sort it */ hosts = this.sortProperties(hosts, 'position', true, false); - let increment = 0; Object.keys(hosts).map(i => { if (!IpList.includes(i)) { @@ -110,32 +231,35 @@ export class TabFlowComponent implements OnInit, AfterViewInit, OnDestroy { }); this.aliasTitle = Object.keys(hosts).map( i => { - const alias = this.dataItem.data.alias[i]; - // This is where the GUI splits port from IP Address. - //Note: not perfect. It works 'backwards' from the end of the string - //If last IPv6 block has letters and digits, and there is no port, then + const __alias = Object.entries(this.dataItem.data.alias).find(j => j[0].includes(i)); + const alias = this.dataItem.data.alias[i] || (__alias && __alias[1]); + // This is where the GUI splits port from IP Address. + // Note: not perfect. It works 'backwards' from the end of the string + // If last IPv6 block has letters and digits, and there is no port, then // the regexp will fail, and result in null. This is a 'best' effort const regex = RegExp('(.*(?!$))(?::)([0-9]+)?$'); - if(regex.exec(i) != null){ - var IP = regex.exec(i)[1] // gives IP - if(IP.indexOf(':') > 0 && IP.indexOf(']') == -1 ) { - //got an IPv6, not already wrapped in brackets '[ipv6]' - //pre+suffix [ IPv6 ] to make addr:port delineation clearer - IP = '[' + IP + ']' - } - var PORT = regex.exec(i)[2] // gives port - PORT = PORT ? ":" + PORT : '' - return { ip: i, alias, IP, PORT }; + let IP, PORT; + if (regex.exec(i) != null) { + IP = regex.exec(i)[1]; // gives IP + PORT = regex.exec(i)[2]; // gives port } else { - //fall back to the old method if things don't work out. - const al = i.split(':'); - const IP = al[0]; - const PORT = al[1] ? ':' + al[1] : ''; - return { ip: i, alias, IP, PORT }; + // fall back to the old method if things don't work out. + const al = i.match(/\d+$|(\[.*\]|\d+\.\d+\.\d+\.\d+)/g); + IP = al[0]; + PORT = al[1] ? ':' + al[1] : ''; } + return { + ip: i, + isIPv6: IP.match(/\:/g) && IP.match(/\:/g).length > 1, + shortIPtext1: this.compIPV6(IP).replace(/\[|\]/g, ''), + shortIPtext2: this.shortcutIPv6String(IP), + alias: alias && alias.includes(i) ? i : alias, + IP, + arrip: [IP.replace(/\[|\]/g, '')], + PORT + }; }); - const colCount = this.aliasTitle.length; - const data = this.dataItem.data; + let diffTs = 0; this.labels = data.calldata.map(i => i.sid).reduce((a, b) => { if (a.indexOf(b) === -1) { @@ -144,45 +268,138 @@ export class TabFlowComponent implements OnInit, AfterViewInit, OnDestroy { return a; }, []).map(i => { return { - color_sid: Functions.getColorByString(i), + color_sid: Functions.getColorByString(i, 100, 40, 1), callid: i - } + }; }); - this.arrayItems = data.calldata.map((item, key, arr) => { - diffTs = key - 1 >= 0 && arr[key - 1] !== null ? (item.micro_ts - arr[key - 1].micro_ts) / 1000 : 0; - const srcPosition = hosts[item.srcId].position, - dstPosition = hosts[item.dstId].position, + /** maping hosts Combinad aliases OR IPs */ + const positionIPs = sortedArray.map(i => this._isSimplifyPort ? [i.srcIp, i.dstIp] : [i.srcId, i.dstId]) + .join(',').split(',').reduce((a, b) => { + if (a[b] === undefined) { + a[b] = Object.keys(a).length; + } + return a; + }, {}); + + /** sort hosts */ + this.aliasTitle = Object.keys(positionIPs).reduce((a, ip) => { + a[positionIPs[ip]] = this.aliasTitle.find(i => i.ip === ip || i.shortIPtext1 === ip); + return a; + }, []); + if (this._isCombineByAlias && this._isSimplifyPort) { + this.aliasTitle = this.aliasTitle.reduce((a, b) => { + if (b.arrip === undefined) { + b.arrip = [b.ip.replace(/\[|\]/g, '')]; + } + const el = a.find(k => k.alias === b.alias || k.ip === b.ip); + if (el) { + el.arrip.push(b.ip.replace(/\[|\]/g, '')); + } else { + a.push(b); + } + return a; + }, []); + } + const getHostPosition = (ip, port, ipId) => { + const [isC, isS] = [this._isCombineByAlias, this._isSimplifyPort]; + let num = 0; + if (isC && isS) { // 1 1 + num = this.aliasTitle.findIndex(i => i.arrip.includes(ip)); + } else + if (!isC && isS) { // 0 1 + num = this.aliasTitle.findIndex(i => i.IP.includes(ip)); + } else + if (!isS) { // 1 0 + num = this.aliasTitle.findIndex(i => (i.IP.includes(ip) && i.PORT === port + '') || i.ip === ipId); + } + return num; + }; + const at = this.aliasTitle; + if (at.length === 2 && at[1].arrip.length) { + at.push({ + empty: true + }) + } + + this.flowGridLines = Array.from({length: at.length - 1}); + + this.arrayItems = sortedArray.map((item, key, arr) => { + diffTs = key - 1 >= 0 && arr[key - 1] !== null ? (item.micro_ts - arr[key - 1].micro_ts) / 1000 : 0; + const {min, max, abs} = Math; + const srcPosition = getHostPosition(item.srcIp , item.srcPort, item.srcId), + dstPosition = getHostPosition(item.dstIp , item.dstPort, item.dstId), course = srcPosition < dstPosition ? 'right' : 'left', - position_from = Math.min(srcPosition, dstPosition), - position_width = Math.abs(srcPosition - dstPosition), - color_method = Functions.getColorByString(item.method_text); + position_from = min(srcPosition, dstPosition), + position_width = abs(srcPosition - dstPosition), + color_method = Functions.getMethodColor(item.method_text); + const a = srcPosition; + const b = dstPosition === a ? a + 1 : dstPosition; + const mosColor = ''; + const isRedialArrow = srcPosition === dstPosition; + const middle = abs(a - b); + const options = { + mosColor, + color: Functions.getColorByString(item.sid, 100, 40, 1), + start: min(a, b), + middle, + direction: a > b, + rightEnd: this.aliasTitle.length - 1 - max(a, b), + shortdata: '', + isRedialArrow, + arrowStyleSolid: item.method_text === 'RTCP' || item.method_text === 'RTP' + }; + const typeItem = item.method_text === 'RTCP' || item.method_text === 'RTP' ? item.method_text : 'SIP'; return { - course : course, + options, + course, + source_data: item, + srcPort: item.srcPort, + dstPort: item.dstPort, method_text: item.method_text, + packetType: item.method_text === 'RTCP' || item.method_text === 'RTP' ? item.method_text : 'SIP', ruri_user: item.ruri_user, id: item.id, color_method: color_method, - color: Functions.getColorByString(item.sid), + color: Functions.getColorByString(item.sid, 100, 40, 1), micro_ts: moment( item.micro_ts).format('YYYY-MM-DD HH:mm:ss.SSS Z'), diffTs: diffTs.toFixed(3), proto: Functions.protoCheck(item.protocol), + typeItem, style: { - left: position_from / colCount * 100, - width: position_width / colCount * 100 + left: position_from / this.aliasTitle.length * 100, + width: position_width / this.aliasTitle.length * 100 } }; }); + + this.dataSource = Functions.messageFormatter(this.dataItem.data.messages); + this.cdr.detectChanges(); } - onClickItem(id: any, event = null) { - const row: any = this.dataSource.filter(i => i.id === id)[0]; - row.mouseEventData = event; - this.messageWindow.emit(row); + onClickItem(item: any, event = null) { + if (item.source_data.QOS) { + const rtpROW: any = Object.assign({ + typeItem: 'RTP', + mouseEventData: event, + }, Functions.cloneObject(item.source_data.RTPmessageData)); + this.messageWindow.emit(rtpROW); + } else { + const row: any = this.dataSource.find(i => i.id === item.id) as any; + row.mouseEventData = event; + this.messageWindow.emit(row); + } + } + compIPV6(input) { + return input.replace(/\b(?:0+:){2,}/, ':'); + } + shortcutIPv6String(str = '') { + const regexp = /^\[?([\da-fA-F]+)\:.*\:([\da-fA-F]+)\]?$/g; + const regfn = (fullstring, start, end) => `${start}:...:${end}`; + return str.replace(regexp, regfn); } - /** * Sort object properties (only own properties will be sorted). * @param {object} obj object to sort properties @@ -191,7 +408,7 @@ export class TabFlowComponent implements OnInit, AfterViewInit, OnDestroy { * @param {bool} reverse false - reverse sorting. * @returns {Array} array of items in [[key,value],[key,value],...] format. */ - sortProperties(obj: any, sortedBy: any = 1, isNumericSort = false, reverse = false) { + private sortProperties(obj: any, sortedBy: any = 1, isNumericSort = false, reverse = false) { const reversed = (reverse) ? -1 : 1; const sortable = []; @@ -217,10 +434,12 @@ export class TabFlowComponent implements OnInit, AfterViewInit, OnDestroy { return target; }, {}); } - + pipeToString(itemhost) { + const arr = itemhost.arrip || [itemhost.IP]; + return arr.join(' | '); + } onSavePng() { if (!this._flagAfterViewInit) { - console.log('waiting FLOW before save a PNG'); setTimeout(this.onSavePng.bind(this), 1000); return; } diff --git a/src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.css b/src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.scss similarity index 100% rename from src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.css rename to src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.scss diff --git a/src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.ts index 85764385..a89ced69 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-hepsub/tab-hepsub.component.ts @@ -1,4 +1,14 @@ -import { Component, OnInit, Input, Output, EventEmitter, ViewChild, OnDestroy } from '@angular/core'; +import { + Component, + OnInit, + Input, + Output, + EventEmitter, + ViewChild, + OnDestroy, + ChangeDetectionStrategy, + ChangeDetectorRef +} from '@angular/core'; import { AgentsubService, SearchService } from '@app/services'; import { Functions } from '@app/helpers/functions'; import { MatTabGroup } from '@angular/material/tabs'; @@ -6,7 +16,8 @@ import { MatTabGroup } from '@angular/material/tabs'; @Component({ selector: 'app-tab-hepsub', templateUrl: './tab-hepsub.component.html', - styleUrls: ['./tab-hepsub.component.css'] + styleUrls: ['./tab-hepsub.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class TabHepsubComponent implements OnInit, OnDestroy { @Input() id: any; @@ -18,14 +29,15 @@ export class TabHepsubComponent implements OnInit, OnDestroy { @ViewChild('matTabGroup', {static: false}) matTabGroup: MatTabGroup; indexTabPosition = 0; - + isLogs = true; subTabList = []; jsonData: any; _interval: any; constructor( private agentsubService: AgentsubService, - private searchService: SearchService + private searchService: SearchService, + private cdr: ChangeDetectorRef ) { } ngOnInit() { @@ -41,28 +53,31 @@ export class TabHepsubComponent implements OnInit, OnDestroy { this.haveData.emit(true); } else { this.haveData.emit(false); - console.error('error', res); } - }) + this.cdr.detectChanges(); + }); setTimeout(() => { this.isLogs = this.dataLogs.length > 0; - }) + this.cdr.detectChanges(); + }); this._interval = setInterval(() => { this.matTabGroup.realignInkBar(); - }, 350) + this.cdr.detectChanges(); + }, 350); } async onTabClick(uuid, type) { const res2 = await this.agentsubService.getHepsubElements({uuid, type, data: this.getQuery()}).toPromise(); if (res2 && res2.data) { this.jsonData = res2.data; this.indexTabPosition = 0; + this.cdr.detectChanges(); } } getProfile() { return this.dataItem && this.dataItem.data && this.dataItem.data.messages && - this.dataItem.data.messages[0] && + this.dataItem.data.messages[0] && this.dataItem.data.messages[0].profile ? this.dataItem.data.messages[0].profile : null; } @@ -77,19 +92,19 @@ export class TabHepsubComponent implements OnInit, OnDestroy { return callidArray; } private getDBNode() { - const data = - this.dataItem && - this.dataItem.data && - this.dataItem.data.messages && - this.dataItem.data.messages[0] && - this.dataItem.data.messages[0].dbnode ? + const data = + this.dataItem && + this.dataItem.data && + this.dataItem.data.messages && + this.dataItem.data.messages[0] && + this.dataItem.data.messages[0].dbnode ? this.dataItem.data.messages[0].dbnode : null; return data; } private getQuery(): any { const query = this.searchService.queryBuilder_EXPORT(this.id, this.getCallIdArray(), this.getProfile()); query.timestamp = Functions.cloneObject(this.snapShotTimeRange); - if( this.getDBNode() && query.param && query.param.location && query.param.location.node ) { + if (this.getDBNode() && query.param && query.param.location && query.param.location.node ) { query.param.location.node = [this.getDBNode()]; } return query; diff --git a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.css b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.css deleted file mode 100644 index 2ca7e2e6..00000000 --- a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.css +++ /dev/null @@ -1,4 +0,0 @@ -.red-container { - padding: 0.5rem; - background-color: rgb(255, 236, 236); -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.html b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.html index 11408d8c..2f10fe5d 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.html +++ b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.html @@ -1,3 +1,31 @@ -
+ +
+
+ +
Timeseconds
+ +
+
+
+Timestamp +
+
+Messages +
+
+
+
+
+{{data.timestamp | moment:'YYYY-MM-DD HH:mm:ss.SSS'}} +

{{data.timestamp}}

+
+
+{{data.message}} +
+
+
+
+ diff --git a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.scss b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.scss new file mode 100644 index 00000000..3ffa5c35 --- /dev/null +++ b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.scss @@ -0,0 +1,53 @@ +.hep-logs { + padding: 10px; +} +.hep-logs > * { + font-family: "Roboto", Helvetica, Arial, sans-serif; + font-size: 14px; +} + +.hep-logs-header { + padding: 5px; + padding-top: 10px; + padding-bottom: 5px; + width: 100%; + display: table; + color: grey !important; + & > div { + display: table-cell; + width: 100%; + font-weight: bold; + } + & .hep-logs-time-header { + width: 180px; + } + & .hep-logs-messages-header { + width: calc(100% - 200px); + width: -moz-calc(100% - 200px); + } +} +.hep-logs-content { + display: table; + padding-top: 0px; + width: 100%; + .body-row { + display: table-row; + & > div { + display: table-cell; + padding: 5px; + } + & .hep-logs-time { + width: 180px; + border-left: 5px solid #dff1ff; + border-bottom: 5px solid transparent; + & p { + padding-bottom: 0px; + margin-bottom: 0px; + } + } + & .hep-logs-messages { + width: calc(100% - 200px); + width: -moz-calc(100% - 200px); + } + } +} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.ts index 7379897b..129a0aae 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-logs/tab-logs.component.ts @@ -1,38 +1,47 @@ import { Component, OnInit, Input } from '@angular/core'; - +export interface HepLog { + timestamp: string; + message: string; +} @Component({ selector: 'app-tab-logs', templateUrl: './tab-logs.component.html', - styleUrls: ['./tab-logs.component.css'] + styleUrls: ['./tab-logs.component.scss'] }) -export class TabLogsComponent implements OnInit { +export class TabLogsComponent { + showTs = false; _data: any; - + _d: any; + dataSource: Array = []; + displayedColumns: string[] = ['timestamp', 'message']; get data() { return this._data; } @Input('data') set data(val) { - this._data = JSON.parse(JSON.stringify(val)); + this._d = JSON.parse(JSON.stringify(val)); + this._data = this.filterPayload([...this._d]); // Compact Objects - this._data.forEach(i => { + + this._data.forEach(i => { try { i.payload.raw = JSON.parse(i.payload.raw); } catch (e) { } try { - i.payload = { - message: i.payload.raw, - timestamp: new Date(i.payload.create_date), - raw: i.payload - }; + if (i.payload.raw) { + i.payload = { + timestamp: i.payload.create_date, + message: i.payload.raw + }; + this.dataSource.push(i.payload); + } delete i.payload.raw.raw; } catch (e) { } }); } - constructor() { } - ngOnInit() { + filterPayload(arr) { + return arr.filter(f => f.payload.payloadType === 100); } - } diff --git a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.css b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.css deleted file mode 100644 index e09ed70a..00000000 --- a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.css +++ /dev/null @@ -1,15 +0,0 @@ -.content-body { - padding: 1rem; - background-color: #ffffff; - margin: 0.3rem; - box-shadow: 1px 1px 5px -2px #000; -} - -.item { - padding-bottom: 1rem; - font-size: 0.8em; -} - -.item-text { - word-break: break-word; -} diff --git a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.html b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.html index a9c5608e..3bdee8a4 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.html +++ b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.html @@ -1,4 +1,4 @@ -
+
-
+ +
+
-
+
Ready to Search Logs! Fine tune your query and hit Refresh
[ No Result Found ]
-
-
- {{i.micro_ts}} - {{i.custom_2}}
- + +
diff --git a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.scss b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.scss new file mode 100644 index 00000000..ab2ba778 --- /dev/null +++ b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.scss @@ -0,0 +1,90 @@ +.loki-search { + padding: 5px; +} +.loki-container { + display: table; + height: 100%; + overflow-y: auto; +} +.loki-body { + padding: 1rem; + margin: 0.3rem; + display: table-row; + & > div { + display: table-cell; + } +} +mat-tab-group { + font-family: "Roboto", Helvetica, Arial, sans-serif; +} +.header-loki { + padding: 1rem; + margin: 0.3rem; + width: 100%; + display: table-row; + font-weight: bold; + color: grey; + & > div { + display: table-cell; + } +} +.item-header { + color: #1d1d1d; +} +.item-tex-loki { + word-break: break-word; + font-size: 14px; + color: #1d1d1d; +} + +.hover { + opacity: 1; + &:hover { + color: #5f5f5f; + } +} +.switches { + display: grid; + grid-template-columns: 1fr 2fr 1fr; + width: 400px; + font-size: 14px; + padding-top: 10px; +} +.swithces { + p { + display: grid; + grid-template-columns: 1fr 1fr; + align-items: center; + } +} +.lokitimeheader { + width: 180px !important; + padding: 5px; + color: grey; +} + +.lokitime { + width: 180px; + padding: 5px; + border-left: 5px solid #dff1ff; + border-bottom: 5px solid transparent; +} + +.lokitags { + width: 160px; + padding: 5px; +} + +.lokimessage { + padding: 5px; + max-width: 60%; +} + +.timeseconds { + margin-top: 10px; + color: #585858; + opacity: 0.75; + &:hover { + opacity: 1; + } +} diff --git a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.ts index e88ec656..57879545 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-loki/tab-loki.component.ts @@ -1,28 +1,34 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit, Input, ViewEncapsulation, ChangeDetectorRef, EventEmitter, ɵConsole } from '@angular/core'; import { DateTimeRangeService } from '@app/services/data-time-range.service'; import { SearchRemoteService } from '@app/services'; -import { Functions } from '@app/helpers/functions'; import { SearchService } from '@app/services'; @Component({ selector: 'app-tab-loki', templateUrl: './tab-loki.component.html', - styleUrls: ['./tab-loki.component.css'] + styleUrls: ['./tab-loki.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class TabLokiComponent implements OnInit { @Input() id; @Input() dataItem: any; - queryText: string; queryObject: any; rxText: string; + showTime: true; + showTags: false; + showTs: true; + checked: boolean; resultData: Array = []; isFirstSearch = true; labels: Array = []; + lokiLabels; + dataSource: Array = [] constructor( private _srs: SearchRemoteService, private _dtrs: DateTimeRangeService, - private searchService: SearchService + private searchService: SearchService, + private cdr : ChangeDetectorRef ) { } ngOnInit() { @@ -35,21 +41,29 @@ export class TabLokiComponent implements OnInit { }, []).join(' | '); this.queryText = `{job="heplify-server"} ${labels}`; + this.cdr.detectChanges(); } async doSerchResult () { - this.rxText = this.queryObject.rxText + this.rxText = this.queryObject.rxText; this.isFirstSearch = false; const data = await this._srs.getData(this.queryBuilder()).toPromise(); this.resultData = data && data.data ? data.data as Array : []; - this.resultData = this.resultData.map(i => { - i.custom_1 = this.highlight(i.custom_1); - return i; + this.lokiLabels = this.resultData.map((l) => { + l.custom_2 = this.labelsFormatter(l.custom_2); + return l; + }) + this.resultData = this.resultData.map((m) => { + m.custom_1 = this.highlight(m.custom_1); + return m; }); + + this.cdr.detectChanges(); } onUpdateData (event) { this.queryObject = event; this.queryObject.limit = 100; + this.cdr.detectChanges(); } queryBuilder() { /** depricated, need use {SearchService} */ return { @@ -62,7 +76,16 @@ export class TabLokiComponent implements OnInit { timestamp: this._dtrs.getDatesForQuery(true) }; } - private highlight(value: string = ''): void { + + private labelsFormatter(rd) { + return JSON.parse(rd); + } + + identify (index, item) { + return item.micro_ts; + } + + private highlight(value: string = '') { let data; if (!!this.rxText) { const rxText = this.rxText.replace(/\s/g, ''); diff --git a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.css b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.css deleted file mode 100644 index ca1a789e..00000000 --- a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.css +++ /dev/null @@ -1,19 +0,0 @@ -table { - width: 100%; - overflow: auto; -} -table tr { - transition: background-color 0.3s; - height: 38px; -} -table tr:hover { - background-color: rgba(0, 0, 0, 0.12); - cursor: pointer; -} - -.mat-row:nth-child(2n+1){ - background-color: #e4f0ec; -} -.mat-row:not(:nth-child(2n+1)){ - background-color:#ffffff; -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.html b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.html index fe79a67c..0a17a4bb 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.html +++ b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.html @@ -1,4 +1,4 @@ - +
@@ -6,7 +6,7 @@ - diff --git a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.scss b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.scss new file mode 100644 index 00000000..fbfac1d9 --- /dev/null +++ b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.scss @@ -0,0 +1,47 @@ +:host{ + overflow-y: auto; + overflow-x: hidden; + table { + width: 100%; + overflow-x: hidden; + border-bottom: 1px solid #d3d3d3; + tr { + transition: background-color 0.3s; + height: 38px; + color:rgb(27, 27, 41); + &:hover { + cursor: pointer; + background-color: rgb(174, 216, 253) !important; + } + } + } + .mat-tab-body-content{ + overflow-x:hidden !important; + } + td.mat-cell{ + border-bottom-style:unset !important; + border-right-style: solid !important; + border-right-width: 1px !important; + border-right-color: lightgray !important; + padding-left:5px !important; + color:rgb(33, 51, 71); + &:last-child.mat-cell { + border-right-style: unset !important; + } + } + + cdk-header-cell{ + padding-left: 5px !important; + } + + .mat-row { + &:nth-child(2n+1){ + background-color: #DFF1FF; + } + &:not(:nth-child(2n+1)){ + background-color:#EFF8FF; + + } + } +} + diff --git a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.ts index 0f5fc23e..918305e9 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-messages/tab-messages.component.ts @@ -1,6 +1,6 @@ -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import * as moment from 'moment'; -import { Functions } from '../../../../helpers/functions'; +import { Functions } from '@app/helpers/functions'; export interface MesagesData { id: string; @@ -21,7 +21,8 @@ export interface MesagesData { @Component({ selector: 'app-tab-messages', templateUrl: './tab-messages.component.html', - styleUrls: ['./tab-messages.component.css'] + styleUrls: ['./tab-messages.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class TabMessagesComponent implements OnInit { @@ -46,17 +47,21 @@ export class TabMessagesComponent implements OnInit { 'dstPort', 'proto', 'type', ]; - constructor() { } + constructor(private cdr: ChangeDetectorRef) { } getAliasByIP (ip) { const alias = this.dataItem.data.alias; return alias[ip] || ip; } + getMethodColor(method){ + return Functions.getMethodColor(method); + } ngOnInit() { this.dataSource = Functions.messageFormatter(this.dataItem.data.messages); } onClickMessageRow(row: any, event = null) { row.mouseEventData = event; this.messageWindow.emit(row); + this.cdr.detectChanges(); } } diff --git a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.css b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.css deleted file mode 100644 index d6671b7d..00000000 --- a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.css +++ /dev/null @@ -1,122 +0,0 @@ -.chart-container { - position: relative; - height: calc(100% - 8.5rem); - width:100%; - min-width: 500px; - min-height: 400px; - flex: 2; -} -h5 { - text-align: center; - background-color: rgba(0,0,0,0.03); -} -.item-container { - display: flex; - flex-wrap: wrap; - justify-content: left; - min-width: 600px; - width: 600px; -} -.item { - background-color: #673ab7; - display: flex; - justify-content: center; - align-items: center; - padding: 0.4rem; - margin: 2px; - flex: 0.5; - min-width: 190px; - border-radius: 4px; - font-size: 0.8em; - box-shadow: 1px 1px 2px rgba(0,0,0,0.4); -} -.hide-button { - width: 149px; - padding: 0; - background: #eee; - border: 0; - border-radius: 4px; - height: 20px; - margin: 67px -62px 67px -60px; - outline: none; - cursor: pointer; - font-size: .9em; -} -.hide-button.rotate90deg { - -moz-transform: rotate(-90.0deg); - -o-transform: rotate(-90.0deg); - -webkit-transform: rotate(-90.0deg); - filter: progid: DXImageTransform.Microsoft.BasicImage(rotation=0.083); - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; - transform: rotate(-90.0deg); -} -.item > .text { - color: #000; -} - -.item > .text-badge { - margin: 0 0.3rem; - padding: 0 5px; - min-width: 30px; - text-align: center; - background-color: white; - border-radius: 4px; - font-weight: bold; - color: #000; - box-shadow: inset 1px 1px 2px rgba(0,0,0,0.3); - -} - -.labels { - flex: 1; - min-width: 650px; -} -.responcive { - width: 100%; - flex-wrap: wrap; - display: flex; - justify-content: baseline; -} - -.color-bable { - min-width: 27px; - min-height: 5px; - padding-bottom: 8px; - margin: 0 5px; - display: inline-block; - border-radius: 1rem; - box-shadow: 0px 1px 3px rgba(0,0,0,0.6); -} -.color1 { - background-color: rgba(255, 127, 127, 0.5); -} -.color2 { - background-color: rgba(124, 249, 177, 0.5); -} -.color3 { - background-color: rgba(0, 255, 255, 0.5); -} -.color4 { - background-color: rgba(222, 184, 135, 0.5); -} -.color5 { - background-color: rgba(100, 149, 237, 0.5); -} -.color6 { - background-color: rgba(7, 136, 24, 0.5); -} - -.cardStreem { - margin: 0.3rem; - min-width: 300px; - flex: 0.3; -} -.error { - margin: 2rem; - padding: 1rem; - background-color: lemonchiffon; - color: red; - display: flex; - align-items: flex-end; - box-shadow: 0 0 5px red; -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.html b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.html index 2e3cb6b7..88bd3acc 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.html +++ b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.html @@ -4,16 +4,24 @@
-
RTP
+
RTP
- +
+
+
+

No Data shown

+

Please select datastreams to display chart

+
+
+
@@ -28,7 +36,7 @@
RTP
- +
{{ item.srcIp }} trending_flat @@ -36,27 +44,27 @@
RTP
- + TOTAL_PK - + EXPECTED_PK - + JITTER - + MOS - + DELTA - + PACKET_LOSS @@ -65,16 +73,24 @@
RTP
-
RTCP
+
RTCP
- +
+
+
+

No Data shown

+

Please select datastreams to display chart

+
+
+
@@ -90,7 +106,7 @@
RTCP
- +
{{ item.srcIp }} trending_flat @@ -98,31 +114,31 @@
RTCP
- + packets - + octets - + highest_seq_no - + mos - + ia_jitter - + lsr - + packets_lost @@ -130,4 +146,4 @@
RTCP
- + \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.scss b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.scss new file mode 100644 index 00000000..4ff7a08b --- /dev/null +++ b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.scss @@ -0,0 +1,153 @@ +.chart-container { + position: relative; + height: calc(100% - 8.5rem); + width: 100%; + min-width: 500px; + min-height: 400px; + flex: 2; +} +.nodata{ + height: 100%; + + .nodata-card{ + height: 100px; + width: 350px; + padding:25px; + border-radius: 3px; + position: absolute; + top: calc(50% - 40px); + left: calc(50% - 175px); + color: white; + font-weight: 400; + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); + .text-container{ + height: 50px; + h1{ + text-align: center; + vertical-align: baseline; + margin-bottom: 5px; + line-height: 26px; + font-size: 26px; + } + p{ + + text-align: center; + vertical-align: baseline; + margin: 0; + line-height: 14px; + font-size: 14px; + } + } + + } + +} +h5 { + text-align: center; + background-color: rgba(0,0,0,0.03); +} +.item-container { + display: flex; + flex-wrap: wrap; + justify-content: left; + min-width: 600px; + width: 600px; +} +.item { + background-color: #673ab7; + display: flex; + justify-content: center; + align-items: center; + padding: 0.4rem; + margin: 2px; + flex: 0.5; + min-width: 190px; + border-radius: 4px; + font-size: 0.8em; + box-shadow: 1px 1px 2px rgba(0,0,0,0.4); + & > .text { + color: #000; + } + & > .text-badge { + margin: 0 0.3rem; + padding: 0 5px; + min-width: 30px; + text-align: center; + background-color: white; + border-radius: 4px; + font-weight: bold; + color: #000; + box-shadow: inset 1px 1px 2px rgba(0,0,0,0.3); + } +} +.hide-button { + width: 149px; + padding: 0; + background: #eee; + border: 0; + border-radius: 4px; + height: 20px; + margin: 67px -62px 67px -60px; + outline: none; + cursor: pointer; + font-size: .9em; + &.rotate90deg { + -moz-transform: rotate(-90.0deg); + -o-transform: rotate(-90.0deg); + -webkit-transform: rotate(-90.0deg); + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; + transform: rotate(-90.0deg); + } +} +.labels { + flex: 1; + min-width: 650px; +} +.responcive { + width: 100%; + flex-wrap: wrap; + display: flex; + justify-content: baseline; +} +.color-bable { + min-width: 27px; + min-height: 5px; + padding-bottom: 8px; + margin: 0 5px; + display: inline-block; + border-radius: 1rem; + box-shadow: 0px 1px 3px rgba(0,0,0,0.6); +} +.color1 { + background-color: rgba(255, 127, 127, 0.5); +} +.color2 { + background-color: rgba(124, 249, 177, 0.5); +} +.color3 { + background-color: rgba(0, 255, 255, 0.5); +} +.color4 { + background-color: rgba(222, 184, 135, 0.5); +} +.color5 { + background-color: rgba(100, 149, 237, 0.5); +} +.color6 { + background-color: rgba(7, 136, 24, 0.5); +} +.cardStreem { + margin: 0.3rem; + min-width: 300px; + flex: 0.3; +} +.error { + margin: 2rem; + padding: 1rem; + background-color: lemonchiffon; + color: red; + display: flex; + align-items: flex-end; + box-shadow: 0 0 5px red; +} \ No newline at end of file diff --git a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.ts b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.ts index 379e73cd..ea2e9bb6 100644 --- a/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.ts +++ b/src/app/components/search-grid-call/detail-dialog/tab-qos/tab-qos.component.ts @@ -1,14 +1,17 @@ -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { ChartType, ChartDataSets, ChartColor } from 'chart.js'; -import { Label, Color } from 'ng2-charts'; +import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Chart, ChartType, ChartDataSets, ChartColor } from 'chart.js'; +import { Label, Color, BaseChartDirective } from 'ng2-charts'; import * as moment from 'moment'; + import { Functions } from '@app/helpers/functions'; @Component({ selector: 'app-tab-qos', templateUrl: './tab-qos.component.html', - styleUrls: ['./tab-qos.component.css'] + styleUrls: ['./tab-qos.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) + export class TabQosComponent implements OnInit { @Input() callid; @Input() dataItem: any; @@ -18,11 +21,14 @@ export class TabQosComponent implements OnInit { @Output() haveData = new EventEmitter(); isError = false; errorMessage: any; - + @ViewChild('rtpChart', { static: false }) rtpChart: BaseChartDirective; + @ViewChild('rtcpChart', { static: false }) rtcpChart: BaseChartDirective; + color: any; labels: Array = []; isRTCP = false; isRTP = false; - + isNoDataRTP = false; + isNoDataRTCP = false; public chartDataRTP: ChartDataSets[] = [ { data: [], @@ -92,7 +98,6 @@ export class TabQosComponent implements OnInit { public chartType: ChartType = 'bar'; public chartLegend = true; public lineChartColors: Color[] = []; - public chartData: ChartDataSets[] = [ { data: [], @@ -100,7 +105,7 @@ export class TabQosComponent implements OnInit { backgroundColor: [], hoverBackgroundColor: [], fill: false, - borderWidth: 0 + borderWidth: 0, }, { data: [], label: 'octets', @@ -207,7 +212,7 @@ export class TabQosComponent implements OnInit { streams: Array = []; streamsRTP: Array = []; - constructor() { } + constructor(private cdr: ChangeDetectorRef) { } ngOnInit() { this.labels = this.dataItem.data.calldata.map(i => i.sid).reduce((a, b) => { @@ -216,7 +221,6 @@ export class TabQosComponent implements OnInit { } return a; }, []); - try { this.parseRTCP(this.qosData.rtcp.data); this.parseRTP(this.qosData.rtp.data); @@ -224,7 +228,7 @@ export class TabQosComponent implements OnInit { } catch (err) { this.onErrorMessage(err); } - + this.color = Functions.getColorByString(this.callid, 75, 60, 1); } onErrorMessage(err: any) { this.isError = true; @@ -253,7 +257,7 @@ export class TabQosComponent implements OnInit { srcIp: item.srcIp, create_date: [], _indeterminate: false, - _chacked: true, + _checked: true, TOTAL_PKData: [], TOTAL_PK: true, EXPECTED_PKData: [], @@ -393,7 +397,7 @@ export class TabQosComponent implements OnInit { srcIp: item.srcIp, create_date: [], _indeterminate: false, - _chacked: true, + _checked: true, packetsData: [], packets: true, octetsData: [], @@ -522,32 +526,32 @@ export class TabQosComponent implements OnInit { }); // avg packets - this.list[1].value = this.avarage(this.streams, 'packetsData'); + this.list[1].value = this.average(this.streams, 'packetsData'); // avg octets - this.list[4].value = this.avarage(this.streams, 'octetsData'); + this.list[4].value = this.average(this.streams, 'octetsData'); // avg highest_seq_no - this.list[7].value = this.avarage(this.streams, 'highest_seq_noData'); + this.list[7].value = this.average(this.streams, 'highest_seq_noData'); // avg ia_jitter - this.list[10].value = this.avarage(this.streams, 'ia_jitterData'); + this.list[10].value = this.average(this.streams, 'ia_jitterData'); // avg lsr - this.list[13].value = this.avarage(this.streams, 'lsrData'); + this.list[13].value = this.average(this.streams, 'lsrData'); // avg mos - this.list[16].value = this.avarage(this.streams, 'mosData'); + this.list[16].value = this.average(this.streams, 'mosData'); // avg packets_lost - this.list[19].value = this.avarage(this.streams, 'packets_lostData'); + this.list[19].value = this.average(this.streams, 'packets_lostData'); this.renderChartData(this.streams, this.chartData); this.isRTCP = true; } - private avarage(streems, labelData) { + private average(streams, labelData) { try { - const t = streems.map(i => i[labelData].reduce((a, b) => (a += b, a), 0) / i[labelData].filter(e => e > 0).length); + const t = streams.map(i => i[labelData].reduce((a, b) => (a += b, a), 0) / i[labelData].filter(e => e > 0).length); const out = t.reduce((a, b) => (a += b, a), 0) / t.filter(e => e > 0).length; return isNaN(out) ? 0 : Math.round(out * 100) / 100; } catch (err) { @@ -557,6 +561,8 @@ export class TabQosComponent implements OnInit { private renderChartData(streams, chartData) { chartData.forEach(i => { i.data = []; + i.backgroundColor = []; + i.hoverBackgroundColor = []; }); streams.forEach(item => { chartData.forEach(val => { @@ -576,7 +582,9 @@ export class TabQosComponent implements OnInit { val.hoverBackgroundColor = arrHoverBackgroundColor .concat(Array.from({ length: _data.length }, i => rColor.borderColor)); }); + }); + this.cdr.detectChanges(); } private setColor( str: string) { @@ -594,37 +602,113 @@ export class TabQosComponent implements OnInit { borderColor: rColor100 }; } - private getData(item: any, index: string) { - const data = item[index + 'Data'] as Array || []; - if (item[index]) { + private getData(item: any, label: string) { + const data = item[label + 'Data'] as Array || []; + if (item[label]) { return Functions.cloneObject( data ); } return Array.from({ length: data.length }, i => 0); } - onChangeChackBox(item: any, base = false) { + onChangeCheckBox(item: any, type: any, base = false) { if (base) { - item.packets = item.octets = item.highest_seq_no = item.ia_jitter = item.lsr = item.mos = item.packets_lost = item._chacked; + item.packets = item.octets = item.highest_seq_no = item.ia_jitter = item.lsr = item.mos = item.packets_lost = item._checked; item._indeterminate = false; } else { - item._chacked = item.packets && item.octets && item.highest_seq_no && + item._checked = item.packets && item.octets && item.highest_seq_no && item.ia_jitter && item.lsr && item.mos && item.packets_lost; - item._indeterminate = !item._chacked && + item._indeterminate = !item._checked && !(!item.packets && !item.octets && !item.highest_seq_no && !item.ia_jitter && !item.lsr && !item.mos && !item.packets_lost); } - this.renderChartData(this.streams, this.chartData); + const checkArray = []; + this.streams.forEach(stream => checkArray.push(stream[type])); + + let index: number; + if (typeof this.rtcpChart !== 'undefined') { + for (let i = 0; i < this.rtcpChart.datasets.length; i++) { + if (this.rtcpChart.datasets[i].label === type) { + index = i; + } + } + } + let streamsCopy = Functions.cloneObject(this.streams); + // Removes disabled datastream + streamsCopy = streamsCopy.filter(lStream => lStream._checked || lStream._indeterminate); + this.streams.forEach((stream) => { + if (!stream._checked && !stream._indeterminate) { + stream.create_date.forEach (create_date => this.chartLabels = + this.chartLabels.filter(label => label !== moment( create_date ).format('YYYY-MM-DD HH:mm:ss'))); + } else if (stream._checked || stream._indeterminate) { + stream.create_date.forEach (create_date => this.chartLabels = + this.chartLabels.filter(label => label !== moment( create_date ).format('YYYY-MM-DD HH:mm:ss'))); + stream.create_date.forEach (create_date => this.chartLabels.push(moment( create_date ).format('YYYY-MM-DD HH:mm:ss'))); + } + }); + if (streamsCopy.length === 0) { + this.isNoDataRTCP = true; + } else { + this.isNoDataRTCP = false; + } + // Hides disabled labels + if (!base && typeof this.rtcpChart !== 'undefined') { + if (checkArray.every(x => x === false)) { + this.rtcpChart.hideDataset(index, true); + } else { + this.rtcpChart.hideDataset(index, false); + } + } + this.renderChartData(streamsCopy, this.chartData); } - onChangeChackBoxRTP(item: any, base = false) { + onChangeCheckBoxRTP(item: any, type: any, base = false) { if (base) { - item.TOTAL_PK = item.EXPECTED_PK = item.JITTER = item.MOS = item.DELTA = item.PACKET_LOSS = item._chacked; + item.TOTAL_PK = item.EXPECTED_PK = item.JITTER = item.MOS = item.DELTA = item.PACKET_LOSS = item._checked; item._indeterminate = false; } else { - item._chacked = item.TOTAL_PK && item.EXPECTED_PK && item.JITTER && item.MOS && item.DELTA && item.PACKET_LOSS; - item._indeterminate = !item._chacked && + item._checked = item.TOTAL_PK && item.EXPECTED_PK && item.JITTER && item.MOS && item.DELTA && item.PACKET_LOSS; + item._indeterminate = !item._checked && !(!item.TOTAL_PK && !item.EXPECTED_PK && !item.JITTER && !item.MOS && !item.DELTA && !item.PACKET_LOSS); } - this.renderChartData(this.streamsRTP, this.chartDataRTP); + const checkArray = []; + this.streamsRTP.forEach(stream => checkArray.push(stream[type])); + let index: number; + if (typeof this.rtpChart !== 'undefined') { + for (let i = 0; i < this.rtpChart.datasets.length; i++) { + if (this.rtpChart.datasets[i].label === type) { + index = i; + } + } + } + let streamsCopy = Functions.cloneObject(this.streamsRTP); + // Removes disabled datastream + streamsCopy = streamsCopy.filter(lStream => lStream._checked || lStream._indeterminate); + this.streamsRTP.forEach((stream) => { + if (!stream._checked && !stream._indeterminate) { + stream.create_date.forEach (create_date => this.chartLabelsRTP = + this.chartLabelsRTP.filter(label => label !== moment( create_date ).format('YYYY-MM-DD HH:mm:ss'))); + } else if (stream._checked || stream._indeterminate) { + stream.create_date.forEach (create_date => this.chartLabelsRTP = + this.chartLabelsRTP.filter(label => label !== moment( create_date ).format('YYYY-MM-DD HH:mm:ss'))); + stream.create_date.forEach (create_date => this.chartLabelsRTP.push(moment( create_date ).format('YYYY-MM-DD HH:mm:ss'))); + } + }); + // Hides disabled labels + if (!base && typeof this.rtpChart !== 'undefined') { + if (checkArray.every(x => x === false)) { + this.rtpChart.hideDataset(index, true); + } else { + this.rtpChart.hideDataset(index, false); + } + } + if (streamsCopy.length === 0) { + console.log('No data') + this.isNoDataRTP = true; + } else { + console.log('Yes data') + this.isNoDataRTP = false; + } + this.renderChartData(streamsCopy, this.chartDataRTP); + } yAxisFormatter (label) { diff --git a/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.css b/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.css deleted file mode 100644 index 7b7afe74..00000000 --- a/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.css +++ /dev/null @@ -1,19 +0,0 @@ -.chack-list { - margin-right: 1.3rem; -} - -.title { - margin: -1.5rem -1.5rem 2rem -1.5rem; - width: initial !important; - display: flex; - justify-content: space-between; -} - -.example-container { - display: flex; - flex-direction: column; -} - -.example-container > * { - width: 100%; -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.scss b/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.scss new file mode 100644 index 00000000..fd045980 --- /dev/null +++ b/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.scss @@ -0,0 +1,16 @@ +.chack-list { + margin-right: 1.3rem; +} +.title { + margin: -1.5rem -1.5rem 2rem -1.5rem; + width: initial !important; + display: flex; + justify-content: space-between; +} +.example-container { + display: flex; + flex-direction: column; + & > * { + width: 100%; + } +} diff --git a/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.ts b/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.ts index 633b20e8..b5776ec2 100644 --- a/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.ts +++ b/src/app/components/search-grid-call/grid-settings-dialog/grid-settings-dialog.ts @@ -6,18 +6,20 @@ export interface DialogData { apicol: any; apipoint: any; columns: any; + lokisort: any; idParent?: string; } @Component({ selector: 'app-grid-setting-dialog', templateUrl: 'grid-settings-dialog.html', - styleUrls: ['./grid-settings-dialog.css'] + styleUrls: ['./grid-settings-dialog.scss'] }) export class DialogSettingsGridDialog { public apiColumn: any; apiPoint: any; + lokiSort: any; id: string; _interval: any; allColumnIds: Array = []; @@ -28,6 +30,7 @@ export class DialogSettingsGridDialog { ) { this.apiColumn = data.apicol; this.apiPoint = data.apipoint; + this.lokiSort = data.lokisort this.id = data.idParent; Object.values(this.apiColumn.getAllColumns() as Object) @@ -38,10 +41,12 @@ export class DialogSettingsGridDialog { selected: column.visible })); this.allColumnIds = this.allColumnIds - .map(i => JSON.stringify(i)) + .map( i => JSON.stringify(i)) .sort() .filter((i, k, arr) => i !== arr[k - 1]) .map(i => JSON.parse(i)); + let ic = this.allColumnIds.findIndex(column => column.field === 'checkbox'); + this.allColumnIds.splice(ic,1); let lsIndex = 'result-state'; if ( this.id ) { lsIndex += `-${this.id}`; @@ -49,6 +54,8 @@ export class DialogSettingsGridDialog { if(localStorage.getItem(lsIndex)){ this.allColumnIds = Functions.cloneObject(JSON.parse(localStorage.getItem(lsIndex))) } + let i = this.allColumnIds.findIndex(column => column.field === 'checkbox'); + this.allColumnIds.splice(i,1); this._bufferData = Functions.cloneObject(this.allColumnIds); } diff --git a/src/app/components/search-grid-call/message-content/message-content.component.css b/src/app/components/search-grid-call/message-content/message-content.component.css deleted file mode 100644 index c9d06dbd..00000000 --- a/src/app/components/search-grid-call/message-content/message-content.component.css +++ /dev/null @@ -1,18 +0,0 @@ - -.message-container { - height: 100%; -} -.message-container .ngx-json-viewer { - height: initial !important; -} -table tr { - height: 38px; -} -.pre-content { - font-family: monospace; - font-size: 10pt; - padding: 0.5rem 2rem; - height: 100%; - box-sizing: border-box; - margin: 0; -} diff --git a/src/app/components/search-grid-call/message-content/message-content.component.html b/src/app/components/search-grid-call/message-content/message-content.component.html index 5bc5e2bc..18f909c0 100644 --- a/src/app/components/search-grid-call/message-content/message-content.component.html +++ b/src/app/components/search-grid-call/message-content/message-content.component.html @@ -9,7 +9,7 @@
-
Id {{element.id}} Date {{element.create_date}} Time {{element.timeSeconds}} Event + {{element.method}}
+
diff --git a/src/app/components/search-grid-call/message-content/message-content.component.scss b/src/app/components/search-grid-call/message-content/message-content.component.scss new file mode 100644 index 00000000..d21f0d8d --- /dev/null +++ b/src/app/components/search-grid-call/message-content/message-content.component.scss @@ -0,0 +1,19 @@ +.message-container { + height: 100%; + .ngx-json-viewer { + height: initial !important; + } +} +table { + tr { + height: 38px; + } +} +.pre-content { + font-family: monospace; + font-size: 10pt; + padding: 0.5rem 2rem; + height: 100%; + box-sizing: border-box; + margin: 0; +} \ No newline at end of file diff --git a/src/app/components/search-grid-call/message-content/message-content.component.ts b/src/app/components/search-grid-call/message-content/message-content.component.ts index 0cb5dc83..5c09654b 100644 --- a/src/app/components/search-grid-call/message-content/message-content.component.ts +++ b/src/app/components/search-grid-call/message-content/message-content.component.ts @@ -4,7 +4,7 @@ import { MatTabGroup } from '@angular/material/tabs'; @Component({ selector: 'app-message-content', templateUrl: './message-content.component.html', - styleUrls: ['./message-content.component.css'] + styleUrls: ['./message-content.component.scss'] }) export class MessageContentComponent implements OnInit, OnDestroy { _data: any; diff --git a/src/app/components/search-grid-call/search-grid-call.component.css b/src/app/components/search-grid-call/search-grid-call.component.css deleted file mode 100644 index 8605751c..00000000 --- a/src/app/components/search-grid-call/search-grid-call.component.css +++ /dev/null @@ -1,53 +0,0 @@ -.resalt-top-tools { - display: flex; - justify-content: space-between; - align-items: center; - align-content: center; - margin: 0 1rem; -} -.loading { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - background-color: rgba(255,255,255,0.6); - display: flex; - justify-content: center; - align-content: center; - align-items: center; - z-index: 9999999; -} -.regex-filter { - position: fixed; - top: 5px; - background: white; - width: 250px; - margin: auto; - right: 311px; - left: 0; - border: 0; - padding: 5px 10px; - border-radius: 6px; - outline: none; - box-shadow: inset 1px 1px 14px -6px rgba(0,0,0,0.4); -} - -.regex-filter.inContainer { - left: initial; - right: 3rem; -} - -.search-slider-footer { - position: absolute; - background: #fff; - bottom: 3rem; - left: 5rem; - right: 5rem; - margin: auto; - box-shadow: 0 -3px 12px -5px #000; - transition: all 0.6s; -} -.search-slider-footer > .content { - padding: 1rem; -} \ No newline at end of file diff --git a/src/app/components/search-grid-call/search-grid-call.component.html b/src/app/components/search-grid-call/search-grid-call.component.html index eba14f8b..b98aa5f0 100644 --- a/src/app/components/search-grid-call/search-grid-call.component.html +++ b/src/app/components/search-grid-call/search-grid-call.component.html @@ -6,6 +6,8 @@ >
LOKI Search + +
+
+ + + + asc + + + desc + + + +
@@ -41,23 +60,25 @@ -
Name {{element.name}}