This is an automated email from the ASF dual-hosted git repository. dgnatyshyn pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
The following commit(s) were added to refs/heads/develop by this push: new 1aeff4f [DLAB-1998]: Prevented lib installation during the process of available libs receiving (#880) 1aeff4f is described below commit 1aeff4f9c1071165775fe95f2d1acc9ac1991148 Author: Dmytro Gnatyshyn <42860905+dg1...@users.noreply.github.com> AuthorDate: Mon Aug 31 17:32:40 2020 +0300 [DLAB-1998]: Prevented lib installation during the process of available libs receiving (#880) [DLAB-1998]: Prevented lib installation during the process of available libs receiving --- .../manage-environment-dilog.component.ts | 2 - .../audit/audit-grid/audit-grid.component.html | 2 +- .../audit/audit-grid/audit-grid.component.scss | 8 +- .../reporting-grid/reporting-grid.component.html | 489 +++++++++++---------- .../reporting-grid/reporting-grid.component.scss | 38 +- .../reporting-grid/reporting-grid.component.ts | 59 ++- .../app/reports/reporting/reporting.component.ts | 9 +- .../install-libraries.component.html | 27 +- .../install-libraries.component.scss | 1 + .../install-libraries.component.ts | 23 +- .../src/app/shared/navbar/navbar.component.html | 1 - .../src/app/shared/navbar/navbar.component.ts | 16 +- .../webapp/src/assets/styles/_general.scss | 34 ++ .../src/main/resources/webapp/src/styles.scss | 5 +- 14 files changed, 418 insertions(+), 296 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts index 0c42312..7f28631 100644 --- a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts @@ -60,8 +60,6 @@ export class ManageEnvironmentComponent implements OnInit { public onFormChange() { this.manageUsersForm.valueChanges.subscribe(value => { this.isFormChanged = JSON.stringify(this.initialFormState) === JSON.stringify(this.manageUsersForm.value); - console.log(JSON.stringify(this.initialFormState)); - console.log(JSON.stringify(this.manageUsersForm.value)); if ((this.getCurrentTotalValue() && this.getCurrentTotalValue() >= this.getCurrentUsersTotal())) { this.manageUsersForm.controls['projects']['controls'].forEach(v => { v.controls['budget'].errors && 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 cfdaa59..2a57cdf 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 @@ -17,7 +17,7 @@ ~ under the License. --> -<section class="audit-table-wrapper" id="scrolling"> +<section class="audit-table-wrapper" id="scrolling" [ngClass]="{'scroll': auditData?.length > 6}"> <table mat-table [dataSource]="auditData" class="data-grid audit mat-elevation-z6"> <ng-container matColumnDef="date"> 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 493e094..28b26bb 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 @@ -20,9 +20,13 @@ .audit-table-wrapper { width: 100%; max-height: calc(100vh - 130px); - overflow: auto; + 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); + &.scroll{ + overflow: auto; + } + .audit { width: 100%; min-width: 1100px; @@ -303,7 +307,7 @@ .table-footer { position: sticky; - bottom: 0; + bottom: -1px; background: inherit; border-top: 1px solid #E0E0E0; transform: translateY(-1px); 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 1481d53..5fc1301 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 @@ -16,282 +16,285 @@ ~ specific language governing permissions and limitations ~ under the License. --> +<div class="billing-page-wrapper scrolling" #pageWrapper [ngClass]="{'scroll': reportData?.length < 5}" (scroll)="scrollTable($event)"> + <div class="wrapper" #wrapper> + <section class="table-wrapper" id="scrolling" #tableWrapper (scroll)="scrollTable($event)" [ngClass]="{'scroll': reportData?.length > 4, 'shadow-none': reportData?.length < 5}"> -<div class="wrapper"> -<section class="table-wrapper" id="scrolling" #tableWrapper (scroll)="scrollTable($event)"> + <!-- <div class="navigation-btn">--> + <!-- <div class="left">--> + <!-- <button mat-fab aria-label="Scroll left">--> + <!-- <mat-icon>keyboard_arrow_left</mat-icon>--> + <!-- </button>--> + <!-- </div>--> + <!-- <div class="right">--> + <!-- <button mat-fab aria-label="Scroll right">--> + <!-- <mat-icon>keyboard_arrow_right</mat-icon>--> + <!-- </button>--> + <!-- </div>--> + <!-- </div>--> + <table mat-table [dataSource]="reportData" class="data-grid reporting mat-elevation-z6" #table> -<!-- <div class="navigation-btn">--> -<!-- <div class="left">--> -<!-- <button mat-fab aria-label="Scroll left">--> -<!-- <mat-icon>keyboard_arrow_left</mat-icon>--> -<!-- </button>--> -<!-- </div>--> -<!-- <div class="right">--> -<!-- <button mat-fab aria-label="Scroll right">--> -<!-- <mat-icon>keyboard_arrow_right</mat-icon>--> -<!-- </button>--> -<!-- </div>--> -<!-- </div>--> - <table mat-table [dataSource]="reportData" class="data-grid reporting mat-elevation-z6" #table> - - <ng-container matColumnDef="name"> - <th mat-header-cell *matHeaderCellDef class="env_name label-header"> - <div class="label"><span class="text"> Resource name</span></div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> - <i class="material-icons"> - <span *ngIf="filteredReportData.dlab_id.length > 0; else dlab_id_filtered">filter_list</span> - <ng-template #dlab_id_filtered>more_vert</ng-template> - </i> - </button> - </th> - <td mat-cell *matCellDef="let element"><span class="table-item">{{element.dlabId}}</span></td> - <td mat-footer-cell *matFooterCellDef class="table-footer"></td> - </ng-container> + <ng-container matColumnDef="name"> + <th mat-header-cell *matHeaderCellDef class="env_name label-header"> + <div class="label"><span class="text"> Resource name</span></div> + <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <i class="material-icons"> + <span *ngIf="filteredReportData.dlab_id.length > 0; else dlab_id_filtered">filter_list</span> + <ng-template #dlab_id_filtered>more_vert</ng-template> + </i> + </button> + </th> + <td mat-cell *matCellDef="let element"><span class="table-item">{{element.dlabId}}</span></td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> + </ng-container> - <ng-container matColumnDef="user"> - <th mat-header-cell *matHeaderCellDef class="th_user label-header"> + <ng-container matColumnDef="user"> + <th mat-header-cell *matHeaderCellDef class="th_user label-header"> - <div class="label"> - <div class="sort sort-user"> - <div class="sort-arrow up" (click)="sortBy('user', 'down')" [ngClass]="{'active': !!this.active['userdown']}"></div> - <div class="sort-arrow down" (click)="sortBy('user', 'up')" [ngClass]="{'active': !!this.active['userup']}"></div> - </div> - <span class="text"> User </span> - </div> + <div class="label"> + <div class="sort sort-user"> + <div class="sort-arrow up" (click)="sortBy('user', 'down')" [ngClass]="{'active': !!this.active['userdown']}"></div> + <div class="sort-arrow down" (click)="sortBy('user', 'up')" [ngClass]="{'active': !!this.active['userup']}"></div> + </div> + <span class="text"> User </span> + </div> - <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> - </i> - </button> - </th> - <td mat-cell *matCellDef=" let element"> {{element.user}} </td> - <td mat-footer-cell *matFooterCellDef class="table-footer"></td> - </ng-container> + <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> + </i> + </button> + </th> + <td mat-cell *matCellDef=" let element"> {{element.user}} </td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> + </ng-container> - <ng-container matColumnDef="project"> - <th mat-header-cell *matHeaderCellDef class="th_project label-header"> + <ng-container matColumnDef="project"> + <th mat-header-cell *matHeaderCellDef class="th_project label-header"> - <div class="label"> - <div class="sort sort-project"> - <div class="sort-arrow up" (click)="sortBy('project', 'down')" [ngClass]="{'active': !!this.active['projectdown']}"></div> - <div class="sort-arrow down" (click)="sortBy('project', 'up')" [ngClass]="{'active': !!this.active['projectup']}"></div> - </div> - <span class="text">Project</span> - </div> + <div class="label"> + <div class="sort sort-project"> + <div class="sort-arrow up" (click)="sortBy('project', 'down')" [ngClass]="{'active': !!this.active['projectdown']}"></div> + <div class="sort-arrow down" (click)="sortBy('project', 'up')" [ngClass]="{'active': !!this.active['projectup']}"></div> + </div> + <span class="text">Project</span> + </div> - <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> - <i class="material-icons"> - <span *ngIf="filteredReportData.projects.length > 0; else project_filtered">filter_list</span> - <ng-template #project_filtered>more_vert</ng-template> - </i> - </button> - </th> - <td mat-cell *matCellDef="let element"> {{element.project}} </td> - <td mat-footer-cell *matFooterCellDef class="table-footer"></td> - </ng-container> + <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()"> + <i class="material-icons"> + <span *ngIf="filteredReportData.projects.length > 0; else project_filtered">filter_list</span> + <ng-template #project_filtered>more_vert</ng-template> + </i> + </button> + </th> + <td mat-cell *matCellDef="let element"> {{element.project}} </td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> + </ng-container> - <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()"> - <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> - </i> - </button> - </th> - <td mat-cell *matCellDef="let element"> {{element.resource_type | titlecase}} </td> - <td mat-footer-cell *matFooterCellDef class="table-footer"></td> - </ng-container> + <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()"> + <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> + </i> + </button> + </th> + <td mat-cell *matCellDef="let element"> {{element.resource_type | titlecase}} </td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> + </ng-container> - <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()"> - <i class="material-icons"> - <span *ngIf="filteredReportData.statuses.length > 0; else status_filtered">filter_list</span> - <ng-template #status_filtered>more_vert</ng-template> - </i> - </button> - </th> - <td mat-cell *matCellDef="let element"> + <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()"> + <i class="material-icons"> + <span *ngIf="filteredReportData.statuses.length > 0; else status_filtered">filter_list</span> + <ng-template #status_filtered>more_vert</ng-template> + </i> + </button> + </th> + <td mat-cell *matCellDef="let element"> <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> - </ng-container> + *ngIf="element.status">{{ element.status.toLowerCase() }}</span> + <span *ngIf="!element.status">N/A</span> + </td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> + </ng-container> - <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()"> - <i class="material-icons"> + <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()"> + <i class="material-icons"> <span *ngIf="filteredReportData['shapes'].length > 0; else shape_filtered">filter_list</span> - <ng-template #shape_filtered>more_vert</ng-template> - </i> - </button> - </th> - <td mat-cell *matCellDef="let element"> - <ng-container *ngIf="element.shape"> - <div *ngFor="let shape of shapeSplit(element.shape)">{{shape}}</div> + <ng-template #shape_filtered>more_vert</ng-template> + </i> + </button> + </th> + <td mat-cell *matCellDef="let element"> + <ng-container *ngIf="element.shape"> + <div *ngFor="let shape of shapeSplit(element.shape)">{{shape}}</div> + </ng-container> + </td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> </ng-container> - </td> - <td mat-footer-cell *matFooterCellDef class="table-footer"></td> - </ng-container> - <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()"> - <i class="material-icons"> + <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()"> + <i class="material-icons"> <span - *ngIf="filteredReportData['shapes'].length > 0; else service_filtered">filter_list</span> - <ng-template #service_filtered>more_vert</ng-template> - </i> - </button> - </th> - <td mat-cell *matCellDef="let element"> - {{ element.product }} -<!-- <span *ngIf="element.product">{{ element.product }}</span>--> - </td> - <td mat-footer-cell *matFooterCellDef class="table-footer"></td> - </ng-container> + *ngIf="filteredReportData['products'].length > 0; else service_filtered">filter_list</span> + <ng-template #service_filtered>more_vert</ng-template> + </i> + </button> + </th> + <td mat-cell *matCellDef="let element"> + {{ element.product }} + <!-- <span *ngIf="element.product">{{ element.product }}</span>--> + </td> + <td mat-footer-cell *matFooterCellDef class="table-footer"></td> + </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"> + <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}"> <span class="strong"> Total <span *ngIf="reportData?.length"> {{ fullReport['total_cost'] }} {{ fullReport['currency'] }}</span> </span> - </td> - </ng-container> + </td> + </ng-container> - <ng-container matColumnDef="charge" stickyEnd> - <th mat-header-cell *matHeaderCellDef class="th_charges label-header"> - <div class="label"> - <div class="sort"> - <div class="sort-arrow up" (click)="sortBy('cost', 'down')" [ngClass]="{'active': !!this.active['costdown']}"></div> - <div class="sort-arrow down" (click)="sortBy('cost', 'up')" [ngClass]="{'active': !!this.active['costup']}"></div> - </div> - <span class="text">Service Charges</span> - </div> - </th> + <ng-container matColumnDef="charge" stickyEnd> + <th mat-header-cell *matHeaderCellDef class="th_charges label-header" [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> + <div class="sort-arrow down" (click)="sortBy('cost', 'up')" [ngClass]="{'active': !!this.active['costup']}"></div> + </div> + <span class="text">Service Charges</span> + </div> + </th> - <td mat-cell *matCellDef="let element"> - {{ element.cost }} {{ element['currency'] }} - </td> - <td mat-footer-cell *matFooterCellDef class="table-footer total-cost d-none"> - </td> - </ng-container> + <td mat-cell *matCellDef="let element" [ngClass]="{'right-sticky': reportData?.length < 5}" > + {{ element.cost }} {{ element['currency'] }} + </td > + <td mat-footer-cell *matFooterCellDef class="table-footer total-cost d-none"> + </td> + </ng-container> - <!-- ----------------FILTER --> - <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?.dlab_id" (input)="filteredReportData.dlab_id = $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> - </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> - </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> - </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> - </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> - </th> - </ng-container> + <!-- ----------------FILTER --> + <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?.dlab_id" (input)="filteredReportData.dlab_id = $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> + </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> + </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> + </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> + </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> + </th> + </ng-container> - <ng-container matColumnDef="empty-filter"> - <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - </th> - </ng-container> + <ng-container matColumnDef="empty-filter"> + <th mat-header-cell *matHeaderCellDef class="filter-row-item"> + </th> + </ng-container> - <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> - </th> - </ng-container> - <ng-container matColumnDef="actions" stickyEnd> - <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <div class="actions"> - <button mat-icon-button class="btn reset" (click)="resetFiltering(); isFiltered = !isFiltered"> - <i class="material-icons">close</i> - </button> + <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> + </th> + </ng-container> + <ng-container matColumnDef="actions" stickyEnd> + <th mat-header-cell *matHeaderCellDef class="filter-row-item" [ngClass]="{'right-sticky': reportData?.length < 5}"> + <div class="actions"> + <button mat-icon-button class="btn reset" (click)="resetFiltering(); isFiltered = !isFiltered"> + <i class="material-icons">close</i> + </button> - <button mat-icon-button class="btn apply" (click)="filter_btnClick()"> - <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>No data available</span> - </td> - </ng-container> + <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>No data available</span> + </td> + </ng-container> - <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="header-row"></tr> + <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 mat-row *matRowDef="let row; columns: displayedColumns;" class="content-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="['placeholder']"></tr> - </table> -</section> - <div class="buttons" *ngIf="isScrollButtonsVisible && reportData?.length"> - <div class="button-container"> - <button mat-mini-fab aria-label="Scroll left" (click)="sctollTo('left')" [ngClass]="{'not-allowed': tableWrapper.scrollLeft === 0 }"> - <mat-icon [ngClass]="{'highlight': tableWrapper.scrollLeft !== 0}">keyboard_arrow_left</mat-icon> - </button> - </div> - <div class="button-container"> - <button mat-mini-fab aria-label="Scroll right" - (click)="sctollTo('right')" - [ngClass]="{'not-allowed': !isMaxRight }" - > - <mat-icon [ngClass]="{'highlight': isMaxRight }">keyboard_arrow_right</mat-icon> - </button> + <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 class="buttons" *ngIf="tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0 && reportData?.length"> + <div class="button-container"> + <button mat-mini-fab aria-label="Scroll left" (click)="sctollTo('left')" [ngClass]="{'not-allowed': tableWrapper.scrollLeft === 0 && reportData?.length > 4 || pageWrapper.scrollLeft === 0 && reportData?.length < 5}"> + <mat-icon [ngClass]="{'highlight': tableWrapper.scrollLeft !== 0 || pageWrapper.scrollLeft !== 0 && reportData?.length < 5}">keyboard_arrow_left</mat-icon> + </button> + </div> + <div class="button-container"> + <button mat-mini-fab aria-label="Scroll right" + (click)="sctollTo('right')" + [ngClass]="{'not-allowed': !(isMaxRight | async)}" + > + <mat-icon [ngClass]="{'highlight': isMaxRight | async }">keyboard_arrow_right</mat-icon> + </button> + </div> </div> </div> + + </div> 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 253d354..c6a5961 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,29 +16,34 @@ * specific language governing permissions and limitations * under the License. */ +.billing-page-wrapper{ + height: calc(100vh - 130px); + scroll-behavior: smooth; + margin-left: -15px; + padding-left: 15px; + margin-right: -15px; + padding-right: 15px; + &.scroll{ + overflow: auto; + } +} + .table-wrapper { width: 100%; display: block; max-height: calc(100vh - 130px); - overflow: auto; + 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{ + overflow: auto; + } } .wrapper{ position: relative; - - .buttons{ - position: absolute; - display: flex; - justify-content: space-around; - z-index: 1000; - bottom: 9px; - left: 0; - right: 0; - button{ background-color: #fff; box-shadow: none; @@ -50,7 +55,7 @@ } } } -} + .reporting { @@ -200,6 +205,7 @@ .table-footer.mat-column-charge{ text-align: right; background-color: #f8f8f8; + z-index: 100 !important; } .header-row { @@ -273,7 +279,7 @@ .table-footer{ position: sticky; - bottom: 0; + bottom: -1px; background: inherit; border-top: 1px solid #E0E0E0; transform: translateY(-1px); @@ -298,7 +304,7 @@ .table-footer{ position: sticky; - bottom: 0; + bottom: -1px; background: inherit; border-top: 1px solid #E0E0E0; transform: translateY(-1px); @@ -311,7 +317,7 @@ padding-right: 25px; position: sticky; right: 0; - z-index: 17; + z-index: 101; } } @@ -323,6 +329,8 @@ right: 0; } + + @media screen and (max-width: 1280px) { .dashboard_table.reporting { .env_name, 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 bf25aae..6ea1014 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 @@ -17,18 +17,33 @@ * under the License. */ -import {Component, OnInit, Output, EventEmitter, ViewChild, Input, HostListener, AfterViewInit, ChangeDetectorRef} from '@angular/core'; +import { + Component, + OnInit, + Output, + EventEmitter, + 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'; @Component({ selector: 'dlab-reporting-grid', templateUrl: './reporting-grid.component.html', styleUrls: ['./reporting-grid.component.scss', '../../../resources/resources-grid/resources-grid.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush }) export class ReportingGridComponent implements OnInit, AfterViewInit { - + tableEl = {}; filterConfiguration: ReportingConfigModel; // filteredReportData: ReportingConfigModel = new ReportingConfigModel([], [], [], [], [], '', '', '', []); collapseFilterRow: boolean = false; @@ -40,20 +55,23 @@ export class ReportingGridComponent implements OnInit, AfterViewInit { @ViewChild('nameFilter', { static: false }) filter; @ViewChild('tableWrapper', { static: false }) tableWrapper; + @ViewChild('wrapper', { static: false }) wrapper; + @ViewChild('pageWrapper', { static: false }) pageWrapper; @ViewChild('table', { static: false }) table; @Output() filterReport: EventEmitter<{}> = new EventEmitter(); @Output() resetRangePicker: EventEmitter<boolean> = new EventEmitter(); @Input() filteredReportData: ReportingConfigModel; + @Input() previousFilterData: ReportingConfigModel; @HostListener('window:resize', ['$event']) onResize(event) { this.isScrollButtonsVisible = this.tableWrapper.nativeElement.offsetWidth - this.table._elementRef.nativeElement.offsetWidth < 0; - this.isMaxRight = this.checkMaxRight(); + this.checkMaxRight(); } @HostListener('scroll', ['$event']) scrollTable($event: Event) { - this.isMaxRight = this.checkMaxRight(); + this.checkMaxRight(); } @@ -61,18 +79,21 @@ export class ReportingGridComponent implements OnInit, AfterViewInit { 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: boolean; + isMaxRight: Subject<boolean> = new BehaviorSubject(false); constructor(private changeDetector: ChangeDetectorRef) { } - ngOnInit() {} - - ngAfterViewInit() { + ngOnInit() { window.setTimeout(() => { this.isScrollButtonsVisible = this.tableWrapper.nativeElement.offsetWidth - this.table._elementRef.nativeElement.offsetWidth < 0; - this.isMaxRight = this.checkMaxRight(); - }, 500); + this.checkMaxRight(); + this.tableEl = this.table._elementRef.nativeElement; + }, 1000); + } + + ngAfterViewInit() { + } onUpdate($event): void { @@ -147,14 +168,28 @@ export class ReportingGridComponent implements OnInit, AfterViewInit { public sctollTo(direction: string) { if (direction === 'left') { this.tableWrapper.nativeElement.scrollLeft = 0; + this.pageWrapper.nativeElement.scrollLeft = 0; } else { this.tableWrapper.nativeElement.scrollLeft = this.tableWrapper.nativeElement.offsetWidth; + this.pageWrapper.nativeElement.scrollLeft = this.pageWrapper.nativeElement.offsetWidth; } } private checkMaxRight() { - return this.isMaxRight = this.tableWrapper.nativeElement.offsetWidth + - this.tableWrapper.nativeElement.scrollLeft + 2 <= this.table._elementRef.nativeElement.offsetWidth; + if (this.reportData && this.reportData.length < 5) { + const arg = this.pageWrapper.nativeElement.offsetWidth - 15 + + this.pageWrapper.nativeElement.scrollLeft + 2 <= this.table._elementRef.nativeElement.offsetWidth; + return this.isMaxRight.next(arg); + } else { + const arg = this.tableWrapper.nativeElement.offsetWidth + + this.tableWrapper.nativeElement.scrollLeft + 2 <= this.table._elementRef.nativeElement.offsetWidth; + return this.isMaxRight.next(arg); + } + + } + + public isFilterChanged() { + return JSON.stringify(this.filteredReportData) === JSON.stringify(this.previousFilterData); } } 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 060b284..2285c8c 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 @@ -37,7 +37,12 @@ import {ProgressBarService} from '../../core/services/progress-bar.service'; (setRangeOption)="setRangeOption($event)"> </dlab-toolbar> <mat-divider></mat-divider> - <dlab-reporting-grid (filterReport)="filterReport($event)" (resetRangePicker)="resetRangePicker()" [filteredReportData]="reportData" ></dlab-reporting-grid> + <dlab-reporting-grid + (filterReport)="filterReport($event)" + (resetRangePicker)="resetRangePicker()" + [filteredReportData]="reportData" + [previousFilterData]="this.cashedFilterData" + ></dlab-reporting-grid> </div> `, @@ -67,7 +72,7 @@ export class ReportingComponent implements OnInit, OnDestroy { data: any; billingEnabled: boolean; admin: boolean; - private cashedFilterData: any; + public cashedFilterData: any; constructor( private billingReportService: BillingReportService, diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html index 5e2fa7c..c54f165 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html @@ -31,7 +31,7 @@ <div *ngIf="notebook?.status === 'running'" class="top-wrapper"> <div class="loading-block" *ngIf="!libs_uploaded && uploading && data.status === 'running'"> <div class="uploading"> - <p>Please wait until DLab loads full list of available libraries for you...</p> + <p>Please wait until DLab loads list of available groups for your resource...</p> <img src="assets/img/gif-spinner.gif" alt="loading"> </div> </div> @@ -86,15 +86,18 @@ </div> </mat-option> </ng-template> - <mat-option *ngIf="model.isEmpty(filteredList) && !validity_format && isAutoComplete"> + <mat-option *ngIf="model.isEmpty(filteredList) && !validity_format && autoComplete === 'ENABLED'"> <span class="configuring">No matches found</span> </mat-option> - <mat-option *ngIf="validity_format?.length > 0 && isAutoComplete"> + <mat-option *ngIf="validity_format?.length > 0 && autoComplete === 'ENABLED'"> <span class="configuring" >{{ validity_format }}</span > </mat-option> - <mat-option *ngIf="!isAutoComplete && lib.name?.length > 1"> + <mat-option *ngIf="autoComplete === 'NONE' && lib.name?.length > 1"> <span class="configuring" >Autocomplete is currently unavailable for {{groupsListMap[group]}} group</span > </mat-option> + <mat-option *ngIf="autoComplete === 'UPDATING' && lib.name?.length > 1"> + <span class="configuring" >Autocomplete is currently loading for {{groupsListMap[group]}} group</span > + </mat-option> </mat-autocomplete> </div> <div class="control-group control-select"> @@ -109,12 +112,22 @@ (keyup)="validateVersion(lib.version)" (keydown.enter)="addLibrary(lib)" > - <span class="error-message version-error" *ngIf="isVersionInvalid">Library version can only contain Latin letters, numbers and special characters -, _, :, /, ~, ., +.</span> + <span + class="error-message version-error" + *ngIf="isVersionInvalid"> + Library version can only contain Latin letters, numbers and special characters -, _, :, /, ~, ., +. + </span> <span class="plus-icon" - [ngClass]="{'not-allow': lib.name?.length < 2 || (isAutoComplete && !isLibSelected ) || this.selectedLib?.isInSelectedList || isVersionInvalid}" + [ngClass]="{'not-allow': lib.name?.length < 2 + || (autoComplete === 'ENABLED' && !isLibSelected ) + || this.selectedLib?.isInSelectedList || isVersionInvalid || autoComplete === 'UPDATING'}" + matTooltip="Library is in selected list" matTooltipPosition="above" [matTooltipDisabled]="!this.selectedLib?.isInSelectedList" > - <mat-icon (click)="addLibrary(lib)" [ngClass]="{'not-allowed': lib.name?.length < 2 || (isAutoComplete && !isLibSelected) || this.selectedLib?.isInSelectedList || isVersionInvalid}">add</mat-icon> + <mat-icon + (click)="addLibrary(lib)" + [ngClass]="{'not-allowed': lib.name?.length < 2 || (autoComplete === 'ENABLED' && !isLibSelected) + || this.selectedLib?.isInSelectedList || isVersionInvalid || autoComplete === 'UPDATING'}">add</mat-icon> </span> </div> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.scss index 50ba25f..53c453b 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.scss @@ -48,6 +48,7 @@ justify-content: center; .uploading { + padding-top: 200px; flex-direction: column; align-items: center; align-self: center; diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts index 668bfab..28afa05 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts @@ -28,7 +28,7 @@ import { InstallLibrariesModel } from './install-libraries.model'; import { LibrariesInstallationService } from '../../../core/services'; import {SortUtils, HTTP_STATUS_CODES, PATTERNS} from '../../../core/util'; import {FilterLibsModel} from './filter-libs.model'; -import {Subject} from 'rxjs'; +import {Subject, timer} from 'rxjs'; interface Library { name: string; @@ -36,7 +36,7 @@ interface Library { } interface GetLibrary { - autoComplete: boolean; + autoComplete: string; libraries: Library[]; } @@ -78,7 +78,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy { public filterConfiguration: FilterLibsModel = new FilterLibsModel('', [], [], [], []); public filterModel: FilterLibsModel = new FilterLibsModel('', [], [], [], []); public filtered: boolean; - public isAutoComplete: boolean; + public autoComplete: string; public filtredNotebookLibs: Array<any> = []; @ViewChild('groupSelect', { static: false }) group_select; @ViewChild('resourceSelect', { static: false }) resource_select; @@ -123,7 +123,8 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy { uploadLibGroups(): void { this.libs_uploaded = false; this.uploading = true; - this.librariesInstallationService.getGroupsList(this.notebook.project, this.notebook.name, this.model.computational_name) + + setTimeout(() => this.librariesInstallationService.getGroupsList(this.notebook.project, this.notebook.name, this.model.computational_name) .pipe( takeUntil(this.unsubscribe$), ) @@ -139,7 +140,8 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy { this.group_select && this.group_select.setDefaultOptions( this.groupsList, 'Select group', 'group_lib', null, 'list', this.groupsListMap); }, - error => this.toastr.error(error.message || 'Groups list loading failed!', 'Oops!')); + error => this.toastr.error(error.message || 'Groups list loading failed!', 'Oops!')), 1000); + } private getResourcesList() { @@ -211,7 +213,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy { return lib.name.toLowerCase() === item.name.substring(0, item.name.lastIndexOf(':')).toLowerCase(); }); } - } else if ( !this.isAutoComplete ) { + } else if ( !this.autoComplete ) { this.selectedLib = { name: this.lib.name, version: this.lib.version, @@ -408,7 +410,14 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy { takeUntil(this.unsubscribe$) ) .subscribe((libs: GetLibrary) => { - this.isAutoComplete = libs.autoComplete; + if (libs.autoComplete === 'UPDATING') { + timer(500000).pipe( + take(1) + ).subscribe(_ => { + this.getMatchedLibs(); + }); + } + this.autoComplete = libs.autoComplete; this.filteredList = libs.libraries; this.filteredList.forEach(lib => { lib.isInSelectedList = this.model.selectedLibs.some(el => el.name.toLowerCase() === lib.name.toLowerCase()); diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html index f24a29f..a192d2b 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html @@ -115,7 +115,6 @@ <!-- <span *ngIf="isExpanded; else endpoint">Cloud Endpoint API</span>--> <!-- <ng-template #endpoint>--> <!-- <span>--> -<!-- <svg width="30px" height="27px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">--> <!-- <g>--> <!-- <path d="M127.059657,255.996921 C58.8506544,255.526472 -0.457073619,198.918442 0.00265506057,126.998303 C0.444649399,57.7958628 57.9516598,-0.468967577 129.11002,0.00284555012 C198.267128,0.462386081 256.613109,57.8667711 255.995136,128.194199 C256.568091,197.883453 197.934268,256.489189 127.059657,255.996921 Z M127.059657,255.996921 C58.8506544,255.526472 -0.457073619,198.918442 0.00265506057,126.998303 C0.444649399,57.7958628 57.9516598,-0.468967577 129.11002,0. [...] <!-- <path id="swager-bgr" d="M127.184644,238.997327 C68.0323765,238.589271 16.6036091,189.498744 17.0023028,127.131428 C17.3860285,67.1185953 67.2554,16.5917106 128.963117,17.0024872 C188.934544,17.4010221 239.531905,67.1825241 238.995778,128.169251 C239.492444,188.602381 188.64743,239.424426 127.184644,238.997327 Z M127.184644,238.997327 C68.0323765,238.589271 16.6036091,189.498744 17.0023028,127.131428 C17.3860285,67.1185953 67.2554,16.5917106 128.963117,17.0024872 [...] diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts index 6ac010c..dc1a05d 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Component, ViewEncapsulation, OnInit, OnDestroy, ViewChild } from '@angular/core'; +import {Component, ViewEncapsulation, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ApplicationRef} from '@angular/core'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import {Subscription, timer, interval, Subject} from 'rxjs'; import { ToastrService } from 'ngx-toastr'; @@ -40,6 +40,7 @@ import { } from '@angular/animations'; import {skip, take} from 'rxjs/operators'; import {ProgressBarService} from '../../core/services/progress-bar.service'; +import {tick} from '@angular/core/testing'; interface Quota { @@ -103,10 +104,13 @@ export class NavbarComponent implements OnInit, OnDestroy { private storage: StorageService, private dialog: MatDialog, private progressBarService: ProgressBarService, + private changeDetector: ChangeDetectorRef, + private applicationRef: ApplicationRef, ) { } ngOnInit() { - this.showProgressBarSubscr = this.progressBarService.showProgressBar.subscribe(isProgressBarVissible => this.showProgressBar = isProgressBarVissible); + this.showProgressBarSubscr = this.progressBarService.showProgressBar + .subscribe(isProgressBarVissible => this.showProgressBar = isProgressBarVissible); this.applicationSecurityService.loggedInStatus.subscribe(response => { this.subscriptions.unsubscribe(); this.subscriptions.closed = false; @@ -151,6 +155,11 @@ export class NavbarComponent implements OnInit, OnDestroy { collapse() { this.isExpanded = !this.isExpanded; + const timeout = window.setTimeout(() => { + // this.changeDetector.detectChanges(); + this.applicationRef.tick(); + window.clearTimeout(timeout); + }, 400); } public emitQuotes(alert, total_quota?, exideedProjects?, informProjects?): void { @@ -181,7 +190,8 @@ export class NavbarComponent implements OnInit, OnDestroy { if (exceedProjects.length > 0 && informProjects.length === 0) checkQuotaAlert = 'project_exceed'; if (informProjects.length > 0 && exceedProjects.length > 0) checkQuotaAlert = 'project_inform_and_exceed'; if (params.totalQuotaUsed >= this.quotesLimit && params.totalQuotaUsed < 100 && exceedProjects.length > 0) checkQuotaAlert = 'total_quota_and_project_exceed'; - if (params.totalQuotaUsed >= this.quotesLimit && params.totalQuotaUsed < 100 && informProjects.length > 0 && exceedProjects.length > 0) checkQuotaAlert = 'total_quota_and_project_inform_and_exceed'; + if (params.totalQuotaUsed >= this.quotesLimit && params.totalQuotaUsed < 100 + && informProjects.length > 0 && exceedProjects.length > 0) checkQuotaAlert = 'total_quota_and_project_inform_and_exceed'; if (Number(params.totalQuotaUsed) >= 100) checkQuotaAlert = 'total_exceed'; diff --git a/services/self-service/src/main/resources/webapp/src/assets/styles/_general.scss b/services/self-service/src/main/resources/webapp/src/assets/styles/_general.scss index 9f486fd..875b874 100644 --- a/services/self-service/src/main/resources/webapp/src/assets/styles/_general.scss +++ b/services/self-service/src/main/resources/webapp/src/assets/styles/_general.scss @@ -181,3 +181,37 @@ input[type=file]::-webkit-file-upload-button { .refresh-icon{ color: #35afd5; } + +.buttons { + position: absolute; + display: flex; + justify-content: space-around; + z-index: 10; + bottom: 9px; + left: 0; + right: 0; + + .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; + } + } +} + +.shadow-none{ + box-shadow: none !important; +} + +.right-sticky{ + right: -15px !important; +} + + diff --git a/services/self-service/src/main/resources/webapp/src/styles.scss b/services/self-service/src/main/resources/webapp/src/styles.scss index 31f512e..bd79768 100644 --- a/services/self-service/src/main/resources/webapp/src/styles.scss +++ b/services/self-service/src/main/resources/webapp/src/styles.scss @@ -378,17 +378,19 @@ input[type='number'] { text-align: center; } } -#scrolling{ +#scrolling, .scrolling{ scrollbar-width: thin; } #scrolling::-webkit-scrollbar, +.scrolling::-webkit-scrollbar, .list-selected mat-chip-list .mat-chip-list-wrapper::-webkit-scrollbar { width: 5px; height: 5px; } #scrolling::-webkit-scrollbar-track, +.scrolling::-webkit-scrollbar-track, .list-selected mat-chip-list .mat-chip-list-wrapper::-webkit-scrollbar-track { box-shadow: none; -webkit-box-shadow: none; @@ -396,6 +398,7 @@ input[type='number'] { } #scrolling::-webkit-scrollbar-thumb, +.scrolling::-webkit-scrollbar-thumb, .list-selected mat-chip-list .mat-chip-list-wrapper::-webkit-scrollbar-thumb { background-color: #f6fafe; background-color: rgba(0, 0, 0, 0.4); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@dlab.apache.org For additional commands, e-mail: commits-h...@dlab.apache.org