This is an automated email from the ASF dual-hosted git repository. ytykhun pushed a commit to branch DATALAB-2347 in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit d99f8220a5d4c5b95404db5c8ca904de7940e33a Author: Yurii Tykhun <[email protected]> AuthorDate: Fri Aug 6 13:23:17 2021 +0300 [DATALAB-2347] refactored audit and billing components --- .../webapp/src/app/login/login.component.css | 38 ++-- .../audit/audit-grid/audit-grid.component.html | 150 +++++++++--- .../audit/audit-grid/audit-grid.component.scss | 70 +++--- .../audit/audit-grid/audit-grid.component.ts | 70 +++--- .../audit-toolbar/audit-toolbar.component.scss | 11 +- .../audit/audit-toolbar/audit-toolbar.component.ts | 9 +- .../src/app/reports/audit/audit.component.ts | 7 +- .../reporting-grid/reporting-grid.component.html | 253 +++++++++++++++------ .../reporting-grid/reporting-grid.component.scss | 162 +++++++------ .../reporting-grid/reporting-grid.component.ts | 80 ++++--- .../app/reports/reporting/reporting.component.ts | 39 ++-- .../src/app/reports/reporting/reporting.module.ts | 4 +- .../reporting/toolbar/toolbar.component.html | 18 +- .../reporting/toolbar/toolbar.component.scss | 11 +- .../reports/reporting/toolbar/toolbar.component.ts | 16 +- 15 files changed, 580 insertions(+), 358 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/login/login.component.css b/services/self-service/src/main/resources/webapp/src/app/login/login.component.css index 890b9f4..c12189f 100644 --- a/services/self-service/src/main/resources/webapp/src/app/login/login.component.css +++ b/services/self-service/src/main/resources/webapp/src/app/login/login.component.css @@ -22,49 +22,49 @@ } .butt-azure { + padding: 0 15px; + margin-left: 10px; color: #fff; background-color: #5bc0de; - margin-left: 10px; - padding: 0 15px; } .butt-login.mat-raised-button { display: block; - margin: 0 auto; height: 38px; + width: 200px; + margin: 0 auto; background-color: #5bc0de; color: #fff; border-color: #46b8da; - width: 200px; } .butt-login.mat-raised-button:disabled { color: #35afd6; background-color: rgba(0, 0, 0, 0.28); border: 1px solid; - box-shadow: 0 3px 1px -2px rgba(53, 175, 213, 0.74), - 0 2px 2px 0 rgba(53, 175, 213, 0.65), 0 1px 5px 0 rgba(53, 175, 213, 0.47); + box-shadow: 0 3px 1px -2px rgba(53, 175, 213, 0.74), 0 2px 2px 0 rgba(53, 175, 213, 0.65), + 0 1px 5px 0 rgba(53, 175, 213, 0.47); } .login_page .logo { display: flex; justify-content: center; - margin-bottom: 45px; - cursor: default; height: 250px; width: 360px; + margin-bottom: 45px; + cursor: default; } .login_page { - background: url(../../assets/img/login-background.png) top center; - background-size: cover; position: absolute; left: 0; top: 0; + display: table; width: 100%; height: 100%; text-align: center; - display: table; + background: url(../../assets/img/login-background.png) top center; + background-size: cover; } .login_page .content { @@ -95,27 +95,27 @@ .input-icon-group { display: flex; flex-direction: row; - background: #fff; margin-bottom: 20px; + background: #fff; } .input-with-icon { width: 100%; - outline: none; - background-color: #fff; height: 40px !important; - color: #555; padding: 6px 12px; + color: #555; + background-color: #fff; box-sizing: border-box; border: 1px solid #35afd5 !important; border-left: 1px solid #35afd5; - transition: all 0.35s ease-in-out; /* font: 300 14px/24px 'Open Sans', sans-serif !important; */ font-style: normal; font-weight: 300; font-size: 14px; line-height: 24px; - font-family: 'Open Sans', sans-serif !important; + font-family: "Open Sans", sans-serif !important; + transition: all 0.35s ease-in-out; + outline: none; } .input-icon { @@ -143,8 +143,8 @@ } .validation-block { - text-align: left; display: table-caption; + text-align: left; color: red; } @@ -156,9 +156,9 @@ .fountainG { position: absolute; top: 0; - background-color: rgb(79, 163, 189); width: 6px; height: 6px; + background-color: rgb(79, 163, 189); animation-name: bounce_fountainG; -o-animation-name: bounce_fountainG; -ms-animation-name: bounce_fountainG; diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.html index cce35e1..1e3b8df 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.html @@ -23,7 +23,12 @@ <ng-container matColumnDef="date"> <th mat-header-cell *matHeaderCellDef class="th_date label-header"> <div class="label"><span class="text">Date</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span>more_vert</span> </i> @@ -37,7 +42,12 @@ <ng-container matColumnDef="user"> <th mat-header-cell *matHeaderCellDef class="th_user label-header" [ngStyle]="{'z-index': 99}"> <div class="label"><span class="audit-user"> User</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filterAuditData.users.length > 0; else user_filtered">filter_list</span> <ng-template #user_filtered>more_vert</ng-template> @@ -57,7 +67,12 @@ <div class="label"> <span class="text"> Action </span> </div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span>more_vert</span> </i> @@ -71,7 +86,9 @@ [matTooltipClass]="'full-size-tooltip'" matTooltipPosition="above" [matTooltipDisabled]="element.action?.length < 12" - >{{element.action | convertaction }}</span> + > + {{element.action | convertaction }} + </span> <div class="audit-info" (click)="openActionInfo(element)" *ngIf="element.info"> <i class="material-icons">info</i> </div> @@ -83,7 +100,12 @@ <ng-container matColumnDef="project"> <th mat-header-cell *matHeaderCellDef class="th_project label-header"> <div class="label"><span class="text">Project</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filterAuditData.projects.length > 0; else user_filtered">filter_list</span> <ng-template #user_filtered>more_vert</ng-template> @@ -101,7 +123,12 @@ <ng-container matColumnDef="resource-type"> <th mat-header-cell *matHeaderCellDef class="th_resource-type label-header"> <div class="label"><span class="text">Resource type</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filterAuditData.resource_types.length > 0; else user_filtered">filter_list</span> <ng-template #user_filtered>more_vert</ng-template> @@ -125,8 +152,13 @@ <mat-form-field> <mat-label></mat-label> <mat-select [(value)]="showItemsPrPage"> - <mat-option *ngFor="let item of itemsPrPage" [value]="item" (click)="setItemsPrPage(item)"> - {{ item }}</mat-option> + <mat-option + *ngFor="let item of itemsPrPage" + [value]="item" + (click)="setItemsPrPage(item)" + > + {{ item }} + </mat-option> </mat-select> <button class="caret"> <i class="material-icons">keyboard_arrow_down</i> @@ -141,22 +173,38 @@ </span> <span> <span [ngClass]="{'not-active': !isNavigationDisabled || firstItem === 1}"> - <span class="navigation-butts" (click)="loadItemsForPage('first')" [ngClass]="{'not-allowed': firstItem === 1 || !isNavigationDisabled}"> + <span + class="navigation-butts" + (click)="loadItemsForPage('first')" + [ngClass]="{'not-allowed': firstItem === 1 || !isNavigationDisabled}" + > <i class="material-icons">first_page</i> </span> </span> <span [ngClass]="{'not-active': firstItem === 1 || !isNavigationDisabled}"> - <span class="navigation-butts" (click)="loadItemsForPage('previous')" [ngClass]="{'not-allowed': firstItem === 1 || !isNavigationDisabled}"> + <span + class="navigation-butts" + (click)="loadItemsForPage('previous')" + [ngClass]="{'not-allowed': firstItem === 1 || !isNavigationDisabled}" + > <i class="material-icons">keyboard_arrow_left</i> </span> </span> <span [ngClass]="{'not-active': lastItem >= allItems || !isNavigationDisabled}"> - <span class="navigation-butts" (click)="loadItemsForPage('next')" [ngClass]="{'not-allowed': lastItem >= allItems || !isNavigationDisabled}"> + <span + class="navigation-butts" + (click)="loadItemsForPage('next')" + [ngClass]="{'not-allowed': lastItem >= allItems || !isNavigationDisabled}" + > <i class="material-icons">keyboard_arrow_right</i> </span> </span> <span [ngClass]="{'not-active': lastItem >= allItems || !isNavigationDisabled}"> - <span class="navigation-butts" (click)="loadItemsForPage('last')" [ngClass]="{'not-allowed': lastItem >= allItems || !isNavigationDisabled}"> + <span + class="navigation-butts" + (click)="loadItemsForPage('last')" + [ngClass]="{'not-allowed': lastItem >= allItems || !isNavigationDisabled}" + > <i class="material-icons">last_page</i> </span> </span> @@ -168,7 +216,12 @@ <ng-container matColumnDef="resource"> <th mat-header-cell *matHeaderCellDef class="th_resource label-header"> <div class="label"><span class="text">Resource</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filterAuditData.resources.length > 0; else user_filtered">filter_list</span> <ng-template #user_filtered>more_vert</ng-template> @@ -185,9 +238,7 @@ </span> </div> </td> - <td mat-footer-cell *matFooterCellDef class="table-footer" [hidden]="true"> - - </td> + <td mat-footer-cell *matFooterCellDef class="table-footer" [hidden]="true"></td> </ng-container> <ng-container matColumnDef="buttons"> @@ -197,18 +248,28 @@ </td> </ng-container> -<!-- AUDIT FILTER--> + <!-- AUDIT FILTER--> <ng-container matColumnDef="user-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'users'" - [items]="filterConfiguration.users" [model]="filterAuditData.users"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'users'" + [items]="filterConfiguration.users" + [model]="filterAuditData.users" + ></multi-select-dropdown> </th> </ng-container> <ng-container matColumnDef="project-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'projects'" - [items]="filterConfiguration.projects" [model]="filterAuditData.projects"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'projects'" + [items]="filterConfiguration.projects" + [model]="filterAuditData.projects" + ></multi-select-dropdown> </th> </ng-container> @@ -216,37 +277,53 @@ <th mat-header-cell *matHeaderCellDef class="filter-row-item"> <multi-select-dropdown class="audit-resources" - *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'resources'" - [items]="filterConfiguration.resources" [model]="filterAuditData.resources"></multi-select-dropdown> + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'resources'" + [items]="filterConfiguration.resources" + [model]="filterAuditData.resources" + ></multi-select-dropdown> </th> </ng-container> <ng-container matColumnDef="resource-type-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'resource_types'" - [items]="filterConfiguration.resource_types" [model]="filterAuditData.resource_types"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'resource_types'" + [items]="filterConfiguration.resource_types" + [model]="filterAuditData.resource_types" + ></multi-select-dropdown> </th> </ng-container> <ng-container matColumnDef="actions-filter"> - <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - - </th> + <th mat-header-cell *matHeaderCellDef class="filter-row-item"></th> </ng-container> <ng-container matColumnDef="date-filter"> - <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - </th> + <th mat-header-cell *matHeaderCellDef class="filter-row-item"></th> </ng-container> <ng-container matColumnDef="filter-buttons" stickyEnd> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> <div class="actions audit-actions"> - <button mat-icon-button class="btn reset" (click)="resetFilterConfigurations()" [disabled]="!isFilterSelected"> + <button + mat-icon-button + class="btn reset" + (click)="resetFilterConfigurations()" + [disabled]="!isFilterSelected" + > <i class="material-icons">close</i> </button> - <button mat-icon-button class="btn apply" (click)="buildAuditGrid(true)" [disabled]="isNavigationDisabled"> + <button + mat-icon-button + class="btn apply" + (click)="buildAuditGrid(true)" + [disabled]="isNavigationDisabled" + > <i class="material-icons">done</i> </button> </div> @@ -264,11 +341,14 @@ <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="header-row"></tr> - <tr [hidden]="!collapseFilterRow" mat-header-row *matHeaderRowDef="displayedFilterColumns; sticky: true" - class="filter-row"></tr> + <tr + [hidden]="!collapseFilterRow" + mat-header-row + *matHeaderRowDef="displayedFilterColumns; sticky: true" + class="filter-row" + ></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" class="content-row"></tr> <tr [hidden]="!auditData?.length" mat-footer-row *matFooterRowDef="displayedColumns"></tr> - <tr [hidden]="auditData?.length" mat-footer-row *matFooterRowDef="['placeholder']"></tr> </table> </section> diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.scss index 4b289b6..555d7ad 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.scss @@ -24,9 +24,9 @@ max-height: -moz-calc(100vh - 130px); max-height: -webkit-calc(100vh - 130px); overflow: visible; - box-shadow: 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12); + box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12); - &.scroll{ + &.scroll { overflow: auto; } @@ -43,49 +43,49 @@ tr { .th_user { - width: 19%; z-index: 9 !important; + width: 19%; } .th_action { - width: 11%; z-index: 8 !important; + width: 11%; max-width: 250px; } .th_date { - width: 14%; z-index: 10 !important; - padding-left: 0; + width: 14%; max-width: 240px; + padding-left: 0; } .th_project { - width: 11%; z-index: 7 !important; + width: 11%; max-width: 206px; } .th_resource { - width: 14%; z-index: 5 !important; + width: 14%; max-width: 240px; } .th_resource-type { - width: 14%; z-index: 6 !important; + width: 14%; max-width: 240px; } .th_buttons { - width: 6%; z-index: 4 !important; + width: 6%; } th { - padding-right: 5px; z-index: 2 !important; + padding-right: 5px; &.th_charges { z-index: 3 !important; @@ -93,27 +93,26 @@ } td { - font-size: 13px; padding-left: 20px; + font-size: 13px; &.info { z-index: 1 !important; - text-align: center; padding: 40px; + text-align: center; } } &.filter-row { th { padding: 5px; - font-size: 13px; z-index: 103 !important; + font-size: 13px; } .filter-field { font-size: 13px; } - } &.header-row { @@ -127,7 +126,6 @@ } } - .tags { .label { padding-top: 0; @@ -175,14 +173,14 @@ padding: 5px; mat-chip { + display: inline-block; min-height: 20px; + max-width: 110px !important; padding: 5px 10px; + margin: 2px; font-size: 13px; - max-width: 110px !important; white-space: nowrap; - display: inline-block; line-height: 10px; - margin: 2px; } } @@ -219,8 +217,8 @@ width: 6px; height: 6px; border: 3px solid transparent; - border-bottom: 3px solid rgba(0, 0, 0, .54); - border-left: 3px solid rgba(0, 0, 0, .54); + border-bottom: 3px solid rgba(0, 0, 0, 0.54); + border-left: 3px solid rgba(0, 0, 0, 0.54); cursor: pointer; &.active { @@ -240,16 +238,16 @@ } } - .table-item-wrapper{ + .table-item-wrapper { display: flex; align-items: center; justify-content: space-between; padding-right: 10px; - span{ + span { cursor: default; - &::after{ - content: ''; + &::after { + content: ""; display: block; } } @@ -260,7 +258,7 @@ align-items: center; justify-content: space-between; padding-right: 10px; - span{ + span { max-width: 85%; } @@ -278,9 +276,9 @@ .dropdown-multiselect { button { - font-size: 13px; height: 34px; padding: 7px 20px; + font-size: 13px; } } } @@ -308,16 +306,15 @@ } } - .navigation-butts { - cursor: pointer; - color: #35afd5; + .navigation-butts { + cursor: pointer; + color: #35afd5; - .not-active { - color: lightgray; - } + .not-active { + color: lightgray; } } - +} .audit-actions { text-align: right; @@ -332,8 +329,7 @@ position: -webkit-sticky; bottom: -1px; background: inherit; - border-top: 1px solid #E0E0E0; + border-top: 1px solid #e0e0e0; transform: translateY(-1px); border-bottom: none; -} - +} \ No newline at end of file diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.ts index 2dc50a2..090dcb3 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-grid/audit-grid.component.ts @@ -22,10 +22,8 @@ import {FilterAuditModel} from '../filter-audit.model'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; import {AuditService} from '../../../core/services/audit.service'; import {SortUtils} from '../../../core/util'; -import {LocalizationService} from '../../../core/services/localization.service'; import {CompareUtils} from '../../../core/util/compareUtils'; - export interface AuditItem { action: string; info: string; @@ -61,13 +59,11 @@ export class AuditGridComponent implements OnInit { @Output() resetDateFilter: EventEmitter<any> = new EventEmitter(); - constructor( public dialogRef: MatDialogRef<AuditInfoDialogComponent>, public dialog: MatDialog, private auditService: AuditService, - ) { - } + ) { } ngOnInit() {} @@ -130,9 +126,11 @@ export class AuditGridComponent implements OnInit { public openActionInfo(element: AuditItem): void { if (element.type === 'GROUP' && element.info.indexOf('role') !== -1) { - this.dialog.open(AuditInfoDialogComponent, { data: {element, dialogSize: 'big'}, panelClass: 'modal-xl-m' }); + this.dialog.open(AuditInfoDialogComponent, + { data: { element, dialogSize: 'big' }, panelClass: 'modal-xl-m' }); } else { - this.dialog.open(AuditInfoDialogComponent, { data: {element, dialogSize: 'small'}, panelClass: 'modal-md' }); + this.dialog.open(AuditInfoDialogComponent, + { data: {element, dialogSize: 'small' }, panelClass: 'modal-md' }); } } @@ -151,15 +149,18 @@ export class AuditGridComponent implements OnInit { this.lastItem = this.showItemsPrPage; } else if (action === 'previous') { this.firstItem = this.firstItem - this.showItemsPrPage; - this.lastItem = this.lastItem % this.showItemsPrPage === 0 ? - this.lastItem - this.showItemsPrPage : this.lastItem - (this.lastItem % this.showItemsPrPage); + this.lastItem = this.lastItem % this.showItemsPrPage === 0 + ? this.lastItem - this.showItemsPrPage + : this.lastItem - (this.lastItem % this.showItemsPrPage); } else if (action === 'next') { this.firstItem = this.firstItem + this.showItemsPrPage; - this.lastItem = (this.lastItem + this.showItemsPrPage) > this.allItems ? - this.allItems : this.lastItem + this.showItemsPrPage; + this.lastItem = (this.lastItem + this.showItemsPrPage) > this.allItems + ? this.allItems + : this.lastItem + this.showItemsPrPage; } else if (action === 'last') { - this.firstItem = this.allItems % this.showItemsPrPage === 0 ? - this.allItems - this.showItemsPrPage : this.allItems - (this.allItems % this.showItemsPrPage) + 1; + this.firstItem = this.allItems % this.showItemsPrPage === 0 + ? this.allItems - this.showItemsPrPage + : this.allItems - (this.allItems % this.showItemsPrPage) + 1; this.lastItem = this.allItems; } } @@ -176,7 +177,6 @@ export class AuditGridComponent implements OnInit { } } - @Component({ selector: 'audit-info-dialog', template: ` @@ -185,8 +185,15 @@ export class AuditGridComponent implements OnInit { <h4 class="modal-title">{{data.element.action | convertaction}}</h4> <button type="button" class="close" (click)="dialogRef.close()">×</button> </header> - <div mat-dialog-content class="content audit-info-content" [ngClass]="{'pb-40': actionList[0].length > 1}"> - <mat-list *ngIf="actionList[0].length > 1 && data.element.action !== 'FOLLOW_LINK'|| data.element.info.indexOf('Update quota') !== -1;else message"> + <div + mat-dialog-content + class="content audit-info-content" + [ngClass]="{'pb-40': actionList[0].length > 1}" + > + <mat-list + *ngIf="actionList[0].length > 1 && data.element.action !== 'FOLLOW_LINK' + || data.element.info.indexOf('Update quota') !== -1;else message" + > <ng-container *ngIf="data.element.info.indexOf('Update quota') === -1;else quotas"> <mat-list-item class="list-header"> @@ -196,15 +203,27 @@ export class AuditGridComponent implements OnInit { <div class="scrolling-content mat-list-wrapper" id="scrolling"> <mat-list-item class="list-item" *ngFor="let action of actionList"> - <div *ngIf="(data.element.action === 'upload' && action[0] === 'File(s)') || (data.element.action === 'download' && action[0] === 'File(s)');else multiAction" class="info-item-title">File</div> + <div + *ngIf="(data.element.action === 'upload' && action[0] === 'File(s)') + || (data.element.action === 'download' && action[0] === 'File(s)');else multiAction" + class="info-item-title" + > + File + </div> <ng-template #multiAction> <div class="info-item-title" [ngClass]="{'same-column-width': data.dialogSize === 'small'}">{{action[0]}}</div> </ng-template> - <div class="info-item-data" [ngClass]="{'same-column-width': data.dialogSize === 'small'}" *ngIf="action[0] === 'File(s)'"> - <div class="file-description ellipsis" - *ngFor="let description of action[1]?.split(',')" - [matTooltip]="description" - matTooltipPosition="above"> + <div + class="info-item-data" + [ngClass]="{'same-column-width': data.dialogSize === 'small'}" + *ngIf="action[0] === 'File(s)'" + > + <div + class="file-description ellipsis" + *ngFor="let description of action[1]?.split(',')" + [matTooltip]="description" + matTooltipPosition="above" + > {{description}} </div> </div> @@ -215,7 +234,8 @@ export class AuditGridComponent implements OnInit { class="ellipsis" [ngStyle]="description.length < 20 ? {'width' :'fit-content'} : {'width':'100%'}" matTooltipPosition="above" - matTooltipClass="mat-tooltip-description"> + matTooltipClass="mat-tooltip-description" + > {{description}} </div> </div> @@ -333,6 +353,4 @@ export class AuditInfoDialogComponent { } this.actionList = data.element.info.split('\n').map(v => v.split(':')).filter(v => v[0] !== ''); } -} - - +} \ No newline at end of file diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.scss b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.scss index 0bf0071..4d87aeb 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.scss @@ -20,18 +20,18 @@ section.audit-toolbar { display: flex; justify-content: space-between; - font-weight: 300; width: 100%; + font-weight: 300; - >div { + > div { width: 33%; } - >div:nth-child(2) { + > div:nth-child(2) { text-align: center; } - >div:nth-child(3) { + > div:nth-child(3) { text-align: right; } @@ -61,6 +61,3 @@ section.audit-toolbar { } } } - - - diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.ts b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.ts index 680dc0b..9110818 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit-toolbar/audit-toolbar.component.ts @@ -17,13 +17,12 @@ * under the License. */ -import { Component, OnInit, AfterViewInit, Output, EventEmitter, ViewEncapsulation, ViewChild } from '@angular/core'; +import { Component, OnInit, AfterViewInit, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; import { NgDateRangePickerOptions } from 'ng-daterangepicker'; import { DICTIONARY } from '../../../../dictionary/global.dictionary'; -import {skip} from 'rxjs/operators'; -import {Subscription} from 'rxjs'; -import {HealthStatusService} from '../../../core/services'; -import {GeneralEnvironmentStatus} from '../../../administration/management/management.model'; +import { Subscription } from 'rxjs'; +import { HealthStatusService } from '../../../core/services'; +import { GeneralEnvironmentStatus } from '../../../administration/management/management.model'; @Component({ selector: 'audit-toolbar', diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit.component.ts b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit.component.ts index 168f6df..dd75463 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/audit/audit.component.ts @@ -42,16 +42,16 @@ import {AuditGridComponent} from './audit-grid/audit-grid.component'; left: 0; bottom: 0; width: 100%; + padding: 5px 15px; background: #a1b7d1; color: #ffffff; text-align: right; - padding: 5px 15px; font-size: 18px; box-shadow: 0 9px 18px 15px #f5f5f5; } `] }) -export class AuditComponent implements OnInit, OnDestroy { +export class AuditComponent implements OnInit { readonly DICTIONARY = DICTIONARY; @ViewChild(AuditGridComponent, { static: true }) auditGrid: AuditGridComponent; @@ -67,9 +67,6 @@ export class AuditComponent implements OnInit, OnDestroy { this.buildAuditReport(); } - ngOnDestroy() { - } - public buildAuditReport(): void { this.auditGrid.buildAuditGrid(); } diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.html index 11a3411..976b189 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.html @@ -17,30 +17,35 @@ ~ under the License. --> <div - class="billing-page-wrapper scrolling" - #pageWrapper - [ngClass]="{'scroll': reportData?.length < 5}" - (scroll)="scrollTable($event)"> + class="billing-page-wrapper scrolling" + #pageWrapper + [ngClass]="{'scroll': reportData?.length < 5}" + (scroll)="scrollTable($event)" +> <div class="wrapper" #wrapper> <div - class="nav-buttons" - [ngStyle]="tableWrapper.scrollHeight === tableWrapper.clientHeight ? {'width': '100%'} : - {'width': userAgentIndex === -1 ? 'calc(100% - 3px)' : 'calc(100% - 8px)'}" - *ngIf="tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0 && reportData?.length"> + class="nav-buttons" + [ngStyle]="tableWrapper.scrollHeight === tableWrapper.clientHeight ? {'width': '100%'} : + {'width': userAgentIndex === -1 ? 'calc(100% - 3px)' : 'calc(100% - 8px)'}" + *ngIf="tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0 && reportData?.length" + > <div class="button-container" > <button - mat-mini-fab aria-label="Scroll left" - (click)="scrollTo('left')" - [ngClass]="{'not-allowed': tableWrapper.scrollLeft === 0 && reportData?.length}"> + mat-mini-fab aria-label="Scroll left" + (click)="scrollTo('left')" + [ngClass]="{'not-allowed': tableWrapper.scrollLeft === 0 && reportData?.length}" + > <mat-icon [ngClass]="{'highlight': tableWrapper.scrollLeft !== 0 || pageWrapper.scrollLeft !== 0 && reportData?.length < 5}"> keyboard_arrow_left </mat-icon> </button> </div> <div class="button-container" [ngClass]="{'not-allowed': this.checkMaxRight()}"> - <button mat-mini-fab aria-label="Scroll right" - (click)="scrollTo('right')" - [ngClass]="{'not-allowed': !(isMaxRight | async)}"> + <button + mat-mini-fab aria-label="Scroll right" + (click)="scrollTo('right')" + [ngClass]="{'not-allowed': !(isMaxRight | async)}" + > <mat-icon [ngClass]="{'highlight': isMaxRight | async }">keyboard_arrow_right</mat-icon> </button> </div> @@ -49,17 +54,26 @@ </div> </div> - <div class="nav-buttons" - [ngStyle]="tableWrapper.scrollHeight === tableWrapper.clientHeight ? {'width': '100%'} : - {'width': userAgentIndex === -1 ? 'calc(100% - 3px)' : 'calc(100% - 8px)'}" - *ngIf="!(tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0) && reportData?.length"> + <div + class="nav-buttons" + [ngStyle]="tableWrapper.scrollHeight === tableWrapper.clientHeight + ? {'width': '100%'} + : {'width': userAgentIndex === -1 ? 'calc(100% - 3px)' : 'calc(100% - 8px)'}" + *ngIf="!(tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0) && reportData?.length" + > <div class="totaL-item strong" > Total <span>{{fullReport.total_cost | localcurrency}}</span> </div> </div> - <section class="table-wrapper" id="scrolling" #tableWrapper (scroll)="scrollTable($event)" [ngStyle]="!reportData?.length && {'overflow': 'auto'}" [ngClass]="{'scroll': reportData?.length}"> - + <section + class="table-wrapper" + id="scrolling" + #tableWrapper + (scroll)="scrollTable($event)" + [ngStyle]="!reportData?.length && {'overflow': 'auto'}" + [ngClass]="{'scroll': reportData?.length}" + > <table mat-table [dataSource]="reportData" class="data-grid reporting" #table> <ng-container matColumnDef="name"> @@ -72,7 +86,7 @@ </i> </button> </th> - <td mat-cell *matCellDef="let element"><span class="table-item">{{element.datalabId}}</span></td> + <td mat-cell *matCellDef="let element"><span class="table-item">{{element.datalabId}}</span></td> <td mat-footer-cell *matFooterCellDef class="table-footer"></td> </ng-container> @@ -87,7 +101,12 @@ <span class="text"> User </span> </div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filteredReportData.users.length > 0; else user_filtered">filter_list</span> <ng-template #user_filtered>more_vert</ng-template> @@ -100,7 +119,8 @@ [ngStyle]="element.user?.length < 20 ? {'max-width' :'fit-content'} : {'max-width':'200px'}" [matTooltip]="element.user" matTooltipPosition="above" - matTooltipClass="billing-user-name"> + matTooltipClass="billing-user-name" + > {{element.user}} </div> </td> @@ -132,7 +152,12 @@ <ng-container matColumnDef="type"> <th mat-header-cell *matHeaderCellDef class="th_type label-header"> <div class="label"><span class="text"> Resource Type</span> </div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filteredReportData.resource_type.length > 0; else type_filtered">filter_list</span> <ng-template #type_filtered>more_vert</ng-template> @@ -146,7 +171,12 @@ <ng-container matColumnDef="status"> <th mat-header-cell *matHeaderCellDef class="th_status label-header"> <div class="label"><span class="text"> Status</span> </div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> <span *ngIf="filteredReportData.statuses.length > 0; else status_filtered">filter_list</span> <ng-template #status_filtered>more_vert</ng-template> @@ -154,8 +184,13 @@ </button> </th> <td mat-cell *matCellDef="let element"> - <span class="status" ngClass="{{ element.status.toLowerCase() || '' }}" - *ngIf="element.status">{{ element.status.toLowerCase() }}</span> + <span + class="status" + ngClass="{{ element.status.toLowerCase() || '' }}" + *ngIf="element.status" + > + {{ element.status.toLowerCase() }} + </span> <span *ngIf="!element.status">N/A</span> </td> <td mat-footer-cell *matFooterCellDef class="table-footer"></td> @@ -164,10 +199,14 @@ <ng-container matColumnDef="shape"> <th mat-header-cell *matHeaderCellDef class="th_shape label-header"> <div class="label"><span class="text"> Instance size</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> - <span - *ngIf="filteredReportData['shapes'].length > 0; else shape_filtered">filter_list</span> + <span *ngIf="filteredReportData['shapes'].length > 0; else shape_filtered">filter_list</span> <ng-template #shape_filtered>more_vert</ng-template> </i> </button> @@ -183,10 +222,14 @@ <ng-container matColumnDef="service"> <th mat-header-cell *matHeaderCellDef class="service label-header"> <div class="label"><span class="text"> Product</span> </div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <button + mat-icon-button + aria-label="More" + class="ar" + (click)="toggleFilterRow()" + > <i class="material-icons"> - <span - *ngIf="filteredReportData['products'].length > 0; else service_filtered">filter_list</span> + <span *ngIf="filteredReportData['products'].length > 0; else service_filtered">filter_list</span> <ng-template #service_filtered>more_vert</ng-template> </i> </button> @@ -199,21 +242,29 @@ </ng-container> <ng-container matColumnDef="empty"> - <th mat-header-cell *matHeaderCellDef class="th_empty label-header"> - </th> - <td mat-cell *matCellDef="let element"> - </td> - <td mat-footer-cell *matFooterCellDef class="table-footer total-cost" [colSpan]="2" [ngClass]="{'right-sticky': reportData?.length < 5}" [style]="{zIndex: 99999}"> + <th mat-header-cell *matHeaderCellDef class="th_empty label-header"></th> + <td mat-cell *matCellDef="let element"></td> + <td + mat-footer-cell + *matFooterCellDef + class="table-footer total-cost" + [colSpan]="2" + [ngClass]="{'right-sticky': reportData?.length < 5}" + [style]="{zIndex: 99999}" + > <!-- <span class="strong">--> <!-- Total <span *ngIf="reportData?.length">{{fullReport['total_cost'] | localcurrency}}</span>--> <!-- </span>--> </td> </ng-container> - - <ng-container matColumnDef="charge" stickyEnd> - <th mat-header-cell *matHeaderCellDef class="th_charges label-header index-105 charges-th" [ngClass]="{'right-sticky': reportData?.length < 5}"> + <th + mat-header-cell + *matHeaderCellDef + class="th_charges label-header index-105 charges-th" + [ngClass]="{'right-sticky': reportData?.length < 5}" + > <div class="label"> <div class="sort"> <div class="sort-arrow up" (click)="sortBy('cost', 'down')" [ngClass]="{'active': !!this.active['costdown']}"></div> @@ -223,7 +274,11 @@ </div> </th> - <td mat-cell *matCellDef="let element" [ngClass]="{'right-sticky': reportData?.length < 5, 'charges-th': reportData?.length}" > + <td + mat-cell + *matCellDef="let element" + [ngClass]="{'right-sticky': reportData?.length < 5, 'charges-th': reportData?.length}" + > {{element.cost | localcurrency }} </td > <td mat-footer-cell *matFooterCellDef class="table-footer total-cost d-none"> @@ -234,43 +289,74 @@ <ng-container matColumnDef="name-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> <div class="input-wrapper"> - <input #nameFilter type="text" placeholder="Filter by environment name" - class="form-control filter-field" - [value]="filtered?.datalabId" (input)="onFilterNameUpdate($event.target['value'])" + <input + #nameFilter type="text" + placeholder="Filter by environment name" + class="form-control filter-field" + [value]="filtered?.datalabId" + (input)="onFilterNameUpdate($event.target['value'])" /> </div> </th> </ng-container> + <ng-container matColumnDef="user-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'users'" - [items]="filterConfiguration.users" [model]="filteredReportData.users"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'users'" + [items]="filterConfiguration.users" + [model]="filteredReportData.users" + ></multi-select-dropdown> </th> </ng-container> + <ng-container matColumnDef="project-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'projects'" - [items]="filterConfiguration.projects" [model]="filteredReportData.projects"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'projects'" + [items]="filterConfiguration.projects" + [model]="filteredReportData.projects" + ></multi-select-dropdown> </th> </ng-container> + <ng-container matColumnDef="type-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'resource_type'" - [items]="filterConfiguration.resource_type" [model]="filteredReportData.resource_type"> - </multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'resource_type'" + [items]="filterConfiguration.resource_type" + [model]="filteredReportData.resource_type" + ></multi-select-dropdown> </th> </ng-container> + <ng-container matColumnDef="status-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'statuses'" - [items]="filterConfiguration.statuses" [model]="filteredReportData.statuses"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'statuses'" + [items]="filterConfiguration.statuses" + [model]="filteredReportData.statuses" + ></multi-select-dropdown> </th> </ng-container> + <ng-container matColumnDef="shape-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" - [type]="'shapes'" [items]="filterConfiguration['shapes']" - [model]="filteredReportData['shapes']"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="'shapes'" + [items]="filterConfiguration['shapes']" + [model]="filteredReportData['shapes']" + ></multi-select-dropdown> </th> </ng-container> @@ -281,25 +367,46 @@ <ng-container matColumnDef="service-filter"> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" - [type]="['products']" - [items]="filterConfiguration['products']" - [model]="filteredReportData['products']"></multi-select-dropdown> + <multi-select-dropdown + *ngIf="filterConfiguration" + (selectionChange)="onUpdate($event)" + [type]="['products']" + [items]="filterConfiguration['products']" + [model]="filteredReportData['products']" + ></multi-select-dropdown> </th> </ng-container> + <ng-container matColumnDef="actions" stickyEnd> - <th mat-header-cell *matHeaderCellDef class="filter-row-item index-105" [ngClass]="{'right-sticky': reportData?.length < 5}" [ngStyle]="{'zIndex': '101 !important'}"> + <th + mat-header-cell + *matHeaderCellDef + class="filter-row-item index-105" + [ngClass]="{'right-sticky': reportData?.length < 5}" + [ngStyle]="{'zIndex': '101 !important'}" + > <div class="actions"> - <button mat-icon-button class="btn reset" (click)="resetFiltering(); isFiltered = !isFiltered" [disabled]="!isFilterSelected"> + <button + mat-icon-button + class="btn reset" + (click)="resetFiltering(); isFiltered = !isFiltered" + [disabled]="!isFilterSelected" + > <i class="material-icons">close</i> </button> - <button mat-icon-button class="btn apply" (click)="filter_btnClick()" [disabled]="isFilterChanged"> + <button + mat-icon-button + class="btn apply" + (click)="filter_btnClick()" + [disabled]="isFilterChanged" + > <i class="material-icons">done</i> </button> </div> </th> </ng-container> + <ng-container matColumnDef="placeholder"> <td mat-footer-cell *matFooterCellDef colspan="9" class="info"> <span *ngIf="!isFilterSelected; else notFound">No data available</span> @@ -311,14 +418,22 @@ <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="header-row"></tr> - <tr [hidden]="!collapseFilterRow" mat-header-row *matHeaderRowDef="displayedFilterColumns; sticky: true" - class="filter-row"></tr> + <tr + [hidden]="!collapseFilterRow" + mat-header-row + *matHeaderRowDef="displayedFilterColumns; sticky: true" + class="filter-row" + ></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" class="content-row"></tr> - <tr [hidden]="!reportData?.length" mat-footer-row *matFooterRowDef="displayedColumns; sticky: true" - class="header-row"></tr> + <tr + [hidden]="!reportData?.length" + mat-footer-row + *matFooterRowDef="displayedColumns; sticky: true" + class="header-row" + ></tr> <tr [hidden]="reportData?.length" mat-footer-row *matFooterRowDef="['placeholder']"></tr> </table> </section> </div> -</div> +</div> \ No newline at end of file diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.scss index 2d5304f..e209705 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.scss @@ -16,28 +16,29 @@ * specific language governing permissions and limitations * under the License. */ -.billing-page-wrapper{ +.billing-page-wrapper { height: calc(100vh - 130px); - scroll-behavior: smooth; margin-left: -15px; margin-right: -15px; padding-left: 15px; padding-right: 15px; - &.scroll{ + scroll-behavior: smooth; + + &.scroll { overflow: auto; } } - .table-wrapper { - width: 100%; + position: relative; display: block; + width: 100%; max-height: calc(100vh - 130px); overflow: unset; - position: relative; scroll-behavior: smooth; - box-shadow: 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12); - &.scroll{ + box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12); + + &.scroll { overflow: auto; } } @@ -46,42 +47,43 @@ right: 0px !important; } -.wrapper{ +.wrapper { position: relative; .nav-buttons { position: absolute; - z-index: 105; bottom: 0; + z-index: 105; display: flex; justify-content: space-around; align-items: center; height: 48px; background-color: #ffffff; - + .mat-mini-fab { height: 25px; width: 25px; - + .mat-button-wrapper { - padding: 0; - line-height: unset; display: flex; align-items: center; justify-content: center; - padding-top: 2px; + padding: 2px 0 0; + line-height: unset; } } } - - button{ + + button { display: flex; align-items: center; background-color: #fff; box-shadow: none; - mat-icon{ + + mat-icon { color: lightgrey; - &.highlight{ + + &.highlight { color: #35afd5; } } @@ -99,18 +101,20 @@ } tr { + th { padding-right: 5px; - &.th_charges{ + + &.th_charges { z-index: 16 !important; } } td { - font-size: 13px; padding-left: 20px; + font-size: 13px; - &.mat-cell{ + &.mat-cell { border-bottom-color: #e3e5e8; } @@ -123,24 +127,21 @@ &.filter-row { th { + z-index: 103 !important; padding: 5px; font-size: 13px; - z-index: 103 !important; - } .filter-field { font-size: 13px; } - } &.header-row { th { - - .label{ - padding-left: 0; + .label { position: relative; + padding-left: 0; font-size: 13px; } } @@ -148,9 +149,9 @@ } .th_shape { + z-index: 10 !important; width: 12%; min-width: 150px; - z-index: 10 !important; } .th_user, @@ -162,7 +163,7 @@ word-wrap: break-word; } - .service{ + .service { width: 10%; } @@ -173,42 +174,42 @@ } .service { - min-width: 175px; z-index: 9 !important; + min-width: 175px; } .env_name { + z-index: 15 !important; width: 21%; min-width: 200px; - z-index: 15 !important; padding-left: 0; } - .th_user{ + .th_user { z-index: 14 !important; } .th_empty { - width: 3%; z-index: 4 !important; + width: 3%; } - .th_project{ - width: 12%; + .th_project { z-index: 13 !important; + width: 12%; min-width: 150px; } .th_type { + z-index: 12 !important; width: 12%; min-width: 170px; - z-index: 12 !important; } .th_status { + z-index: 11 !important; width: 8%; min-width: 150px; - z-index: 11 !important; } .th_charges { @@ -224,20 +225,20 @@ padding: 5px; mat-chip { + display: inline-block; min-height: 20px; + max-width: 110px !important; + margin: 2px; padding: 5px 10px; font-size: 13px; - max-width: 110px !important; white-space: nowrap; - display: inline-block; line-height: 10px; - margin: 2px; } } .mat-column-charge, .filter-row-item:last-child, - .table-footer.mat-column-charge{ + .table-footer.mat-column-charge { text-align: right; background-color: #f8f8f8; } @@ -252,7 +253,7 @@ padding-top: 10px; } - &.label-header{ + &.label-header { box-shadow: none; border-bottom: 1px solid lightgrey !important; } @@ -263,39 +264,39 @@ padding-top: 13px; vertical-align: super !important; - .text{ - padding-left: 20px; + .text { + padding-left: 20px; } } - .sort{ + .sort { position: absolute; bottom: 2px; &-user, - &-project{ + &-project { right: -15px; } - &-arrow{ + &-arrow { width: 6px; height: 6px; border: 3px solid transparent; - border-bottom: 3px solid rgba(0,0,0,.54); - border-left: 3px solid rgba(0,0,0,.54); + border-bottom: 3px solid rgba(0, 0, 0, 0.54); + border-left: 3px solid rgba(0, 0, 0, 0.54); cursor: pointer; - &.active{ + &.active { border-bottom: 3px solid #35afd5; border-left: 3px solid #35afd5; } } - .down{ + .down { transform: rotate(-45deg); } - .up{ + .up { transform: rotate(135deg); } } @@ -305,20 +306,20 @@ .actions { text-align: right; - button{ + button { background: inherit; } } } - .table-footer{ + .table-footer { position: sticky; bottom: -1px; + padding-left: 0 !important; background: inherit; - border-top: 1px solid #E0E0E0; + border-top: 1px solid #e0e0e0; transform: translateY(-1px); border-bottom: none; - padding-left: 0 !important; } } @@ -329,29 +330,29 @@ .dropdown-multiselect { button { - font-size: 14px; height: 34px; padding: 7px 20px; + font-size: 14px; } } } -.table-footer{ +.table-footer { position: sticky; bottom: -1px; background: inherit; - border-top: 1px solid #E0E0E0; - transform: translateY(-1px); + border-top: 1px solid #e0e0e0; border-bottom: none; + transform: translateY(-1px); - &.total-cost{ - min-width: 140px; - padding-left: 0 !important; - text-align: right; - padding-right: 25px; + &.total-cost { position: sticky; right: 0; z-index: 101; + min-width: 140px; + padding-right: 25px; + padding-left: 0 !important; + text-align: right; } } @@ -364,13 +365,12 @@ right: 0; } -.wrapper{ - .table-wrapper{ - .reporting{ - tr{ +.wrapper { + .table-wrapper { + .reporting { + tr { th.th_charges.index-105, - .filter-row-item.index-105 - { + .filter-row-item.index-105 { z-index: 105 !important; } } @@ -378,8 +378,6 @@ } } - - @media screen and (max-width: 1280px) { .dashboard_table.reporting { .env_name, @@ -399,18 +397,18 @@ } } -.totaL-item{ +.totaL-item { position: absolute; right: 0; - padding-right: 24px; z-index: 115; + padding-right: 24px; font-size: 13px; - &.scrollbar-right{ + &.scrollbar-right { right: 3px; } - &.scrollbar-bottom{ + &.scrollbar-bottom { bottom: 3px; } @@ -419,16 +417,14 @@ } } - - @-moz-document url-prefix() { .totaL-item { - &.scrollbar-right{ + &.scrollbar-right { right: 8px !important; } - &.scrollbar-bottom{ + &.scrollbar-bottom { bottom: 8px !important; } } -} +} \ No newline at end of file diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.ts index ff67351..513ac45 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting-grid/reporting-grid.component.ts @@ -25,14 +25,11 @@ import { ViewChild, Input, HostListener, - AfterViewInit, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core'; import { ReportingConfigModel } from '../../../../dictionary/global.dictionary'; -import {BehaviorSubject, fromEvent, Observable, of, Subject, timer} from 'rxjs'; -import {logger} from 'codelyzer/util/logger'; -import {take} from 'rxjs/operators'; +import {BehaviorSubject, Subject } from 'rxjs'; import {CompareUtils} from '../../../core/util/compareUtils'; export interface IFullReport { @@ -64,8 +61,16 @@ export class ReportingGridComponent implements OnInit { fullReport: IFullReport; isFiltered: boolean = false; active: object = {}; - displayedColumns: string[] = ['name', 'user', 'project', 'type', 'status', 'shape', 'service', 'empty', 'charge']; - displayedFilterColumns: string[] = ['name-filter', 'user-filter', 'project-filter', 'type-filter', 'status-filter', 'shape-filter', 'service-filter', 'empty-filter', 'actions']; + displayedColumns: string[] = [ + 'name', 'user', 'project', + 'type', 'status', 'shape', + 'service', 'empty', 'charge' + ]; + displayedFilterColumns: string[] = [ + 'name-filter', 'user-filter', 'project-filter', + 'type-filter', 'status-filter', 'shape-filter', + 'service-filter', 'empty-filter', 'actions' + ]; filtered: any; isMaxRight: Subject<boolean> = new BehaviorSubject(false); isFilterSelected: boolean; @@ -97,8 +102,7 @@ export class ReportingGridComponent implements OnInit { this.checkMaxRight(); } - constructor(private changeDetector: ChangeDetectorRef) { - } + constructor(private changeDetector: ChangeDetectorRef) { } ngOnInit() { this.userAgentIndex = window.navigator.userAgent.indexOf('Firefox'); @@ -137,35 +141,37 @@ export class ReportingGridComponent implements OnInit { } sortBy(sortItem, direction) { - if (this.previousItem === sortItem && this.previousDirection === direction) { - return; - } - let report: Array<object>; - this.previousItem = sortItem; - this.previousDirection = direction; - if (direction === 'down') { - report = this.reportData.sort((a, b) => { - if (a[sortItem] === null) a[sortItem] = ''; - if (b[sortItem] === null) b[sortItem] = ''; - - if ((a[sortItem] > b[sortItem])) return 1; - if ((a[sortItem] < b[sortItem])) return -1; - return 0; - }); - } - if (direction === 'up') { - report = this.reportData.sort((a, b) => { - if (a[sortItem] === null) a[sortItem] = ''; - if (b[sortItem] === null) b[sortItem] = ''; - - if ((a[sortItem] < b[sortItem])) return 1; - if ((a[sortItem] > b[sortItem])) return -1; - return 0; - }); - } - this.refreshData(this.fullReport, report); - this.removeSorting(); - this.active[sortItem + direction] = true; + if (this.previousItem === sortItem && this.previousDirection === direction) return; + + let report: Array<object>; + this.previousItem = sortItem; + this.previousDirection = direction; + + if (direction === 'down') { + report = this.reportData.sort((a, b) => { + if (a[sortItem] === null) a[sortItem] = ''; + if (b[sortItem] === null) b[sortItem] = ''; + + if ((a[sortItem] > b[sortItem])) return 1; + if ((a[sortItem] < b[sortItem])) return -1; + return 0; + }); + } + + if (direction === 'up') { + report = this.reportData.sort((a, b) => { + if (a[sortItem] === null) a[sortItem] = ''; + if (b[sortItem] === null) b[sortItem] = ''; + + if ((a[sortItem] < b[sortItem])) return 1; + if ((a[sortItem] > b[sortItem])) return -1; + return 0; + }); + } + + this.refreshData(this.fullReport, report); + this.removeSorting(); + this.active[sortItem + direction] = true; } removeSorting() { diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.component.ts b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.component.ts index 20f835e..514ce53 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.component.ts @@ -20,23 +20,24 @@ import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; import { ToastrService } from 'ngx-toastr'; -import {ApplicationSecurityService, BillingReportService, HealthStatusService} from '../../core/services'; +import { BillingReportService, HealthStatusService } from '../../core/services'; import { ReportingGridComponent } from './reporting-grid/reporting-grid.component'; import { ToolbarComponent } from './toolbar/toolbar.component'; import { FileUtils } from '../../core/util'; import { DICTIONARY, ReportingConfigModel } from '../../../dictionary/global.dictionary'; -import {ProgressBarService} from '../../core/services/progress-bar.service'; -import {LocalizationService} from '../../core/services/localization.service'; +import { ProgressBarService } from '../../core/services/progress-bar.service'; +import { LocalizationService } from '../../core/services/localization.service'; @Component({ selector: 'datalab-reporting', template: ` <div class="base-retreat"> - <datalab-toolbar (rebuildReport)="rebuildBillingReport()" - (exportReport)="exportBillingReport()" - (setRangeOption)="setRangeOption($event)"> - </datalab-toolbar> + <datalab-toolbar + (rebuildReport)="rebuildBillingReport()" + (exportReport)="exportBillingReport()" + (setRangeOption)="setRangeOption($event)" + ></datalab-toolbar> <mat-divider></mat-divider> <datalab-reporting-grid (filterReport)="filterReport($event)" @@ -53,10 +54,10 @@ import {LocalizationService} from '../../core/services/localization.service'; left: 0; bottom: 0; width: 100%; + padding: 5px 15px; background: #a1b7d1; color: #ffffff; text-align: right; - padding: 5px 15px; font-size: 18px; box-shadow: 0 9px 18px 15px #f5f5f5; } @@ -136,27 +137,32 @@ export class ReportingComponent implements OnInit, OnDestroy { this.billingReportService.downloadReport(this.reportData) .subscribe( data => FileUtils.downloadFile(data), - () => this.toastr.error('Billing report export failed!', 'Oops!')); + () => this.toastr.error('Billing report export failed!', 'Oops!') + ); } getDefaultFilterConfiguration(data): void { const users = [], types = [], shapes = [], services = [], statuses = [], projects = []; data.report_lines.forEach((item: any) => { - if (item.user && users.indexOf(item.user) === -1) + if (item.user && users.indexOf(item.user) === -1) { users.push(item.user); + } - if (item.status && statuses.indexOf(item.status.toLowerCase()) === -1) + if (item.status && statuses.indexOf(item.status.toLowerCase()) === -1) { statuses.push(item.status.toLowerCase()); + } - if (item.project && projects.indexOf(item.project) === -1) + if (item.project && projects.indexOf(item.project) === -1) { projects.push(item.project); + } - if (item['resource_type'] && types.indexOf(item['resource_type']) === -1) + if (item['resource_type'] && types.indexOf(item['resource_type']) === -1) { types.push(item['resource_type']); + } if (item.shape && types.indexOf(item.shape)) { - if (item.shape.indexOf('Master') > -1) { + if (item.shape.indexOf('Master') > -1) { for (let shape of item.shape.split(/(?=Slave)/g)) { shape = shape.replace('Master: ', ''); shape = shape.replace(/Slave: /, ''); @@ -175,8 +181,9 @@ export class ReportingComponent implements OnInit, OnDestroy { } } - if (item.product && services.indexOf(item.product) === -1) + if (item.product && services.indexOf(item.product) === -1) { services.push(item.product); + } }); if (!this.reportingGrid.filterConfiguration || !localStorage.getItem('report_config')) { @@ -213,4 +220,4 @@ export class ReportingComponent implements OnInit, OnDestroy { this.admin = result.admin; }); } -} +} \ No newline at end of file diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.module.ts b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.module.ts index efcbfd9..c61c1d8 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/reporting.module.ts @@ -27,8 +27,8 @@ import { ReportingComponent } from './reporting.component'; import { KeysPipeModule, LineBreaksPipeModule } from '../../core/pipes'; import { ReportingGridComponent } from './reporting-grid/reporting-grid.component'; import { ToolbarComponent } from './toolbar/toolbar.component'; -import {LocalCurrencyModule} from '../../core/pipes/local-currency-pipe'; -import {LocalDatePipeModule} from '../../core/pipes/local-date-pipe'; +import { LocalCurrencyModule } from '../../core/pipes/local-currency-pipe'; +import { LocalDatePipeModule } from '../../core/pipes/local-date-pipe'; @NgModule({ imports: [ diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.html b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.html index ca883aa..e8aba28 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.html @@ -20,8 +20,9 @@ <div class="info_color" > <div class="general" *ngIf="reportData"> <div><span>Service base name: </span><strong>{{ reportData.sbn }}</strong></div> - <div *ngIf="reportData.tag_resource_id"><span>Resource tag ID: - </span><strong>{{ reportData.tag_resource_id }}</strong></div> + <div *ngIf="reportData.tag_resource_id"> + <span>Resource tag ID:</span><strong>{{ reportData.tag_resource_id }}</strong> + </div> <div class="report-period info_color" *ngIf="availablePeriodFrom && availablePeriodTo"> <span>Available reporting period from:</span> <strong>{{ availablePeriodFrom.join('/') | localDate }} </strong> @@ -31,10 +32,19 @@ </div> <div id="range-picker"> - <ng-daterangepicker [(ngModel)]="value" [options]="options" (ngModelChange)="onChange($event)"></ng-daterangepicker> + <ng-daterangepicker + [(ngModel)]="value" + [options]="options" + (ngModelChange)="onChange($event)" + ></ng-daterangepicker> </div> <div class="action-butt"> - <button mat-raised-button class="butt" (click)="export($event)" [disabled]="!reportData?.report_lines.length"> + <button + mat-raised-button + class="butt" + (click)="export($event)" + [disabled]="!reportData?.report_lines.length" + > <i class="material-icons">file_download</i>Export </button> <button mat-raised-button class="butt" (click)="rebuild($event)"> diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.scss b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.scss index f23b8a9..7b454fa 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.scss @@ -20,18 +20,18 @@ section.toolbar { display: flex; justify-content: space-between; - font-weight: 300; width: 100%; + font-weight: 300; - >div { + > div { width: 33%; } - >div:nth-child(2) { + > div:nth-child(2) { text-align: center; } - >div:nth-child(3) { + > div:nth-child(3) { text-align: right; } @@ -60,5 +60,4 @@ section.toolbar { } } } -} - +} \ No newline at end of file diff --git a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.ts b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.ts index 2b13c8e..af4aee8 100644 --- a/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/reports/reporting/toolbar/toolbar.component.ts @@ -17,13 +17,13 @@ * under the License. */ -import { Component, OnInit, AfterViewInit, Output, EventEmitter, ViewEncapsulation, ViewChild } from '@angular/core'; +import { Component, OnInit, AfterViewInit, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; import { NgDateRangePickerOptions } from 'ng-daterangepicker'; import { DICTIONARY } from '../../../../dictionary/global.dictionary'; -import {skip} from 'rxjs/operators'; -import {Subscription} from 'rxjs'; -import {HealthStatusService} from '../../../core/services'; -import {GeneralEnvironmentStatus} from '../../../administration/management/management.model'; +import { skip } from 'rxjs/operators'; +import { Subscription } from 'rxjs'; +import { HealthStatusService } from '../../../core/services'; +import { GeneralEnvironmentStatus } from '../../../administration/management/management.model'; @Component({ selector: 'datalab-toolbar', @@ -102,11 +102,13 @@ export class ToolbarComponent implements OnInit, AfterViewInit { onChange(dateRange: string): void { const rangeLabels = <NodeListOf<Element>>document.querySelectorAll('.value-txt'); - for (let label = 0; label < rangeLabels.length; ++label) + for (let label = 0; label < rangeLabels.length; ++label) { if (rangeLabels[label].classList.contains('untouched')) { rangeLabels[label].classList.remove('untouched'); rangeLabels[label].classList.remove('d-none'); } + } + const labels = <NodeListOf<Element>>document.querySelectorAll('.label-txt'); labels[0].innerHTML = 'From:'; labels[1].innerHTML = 'To:'; @@ -125,4 +127,4 @@ export class ToolbarComponent implements OnInit, AfterViewInit { export($event): void { this.exportReport.emit($event); } -} +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
