You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by dg...@apache.org on 2020/09/08 14:15:14 UTC

[incubator-dlab] branch develop updated: [DLAB-2026]: Made behavior of filter actions the same on all pages. Fixed minor bugs on library and bucket browser (#896)

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 2833202  [DLAB-2026]: Made behavior of filter actions the same on all pages. Fixed minor bugs on library and bucket browser (#896)
2833202 is described below

commit 28332025f15a6bc90fd0420a580cdee2f0055ede
Author: Dmytro Gnatyshyn <42...@users.noreply.github.com>
AuthorDate: Tue Sep 8 17:15:08 2020 +0300

    [DLAB-2026]: Made behavior of filter actions the same on all pages. Fixed minor bugs on library and bucket browser (#896)
    
    [DLAB-2026]: Made behavior of filter actions the same on all pages.Fixed minor bugs on library and bucket browser
---
 .../management-grid/management-grid.component.html |  4 +-
 .../management-grid/management-grid.component.ts   |  9 ++++
 .../resources/webapp/src/app/app.routing.module.ts |  1 -
 .../convert-action-pipe/convert-action.pipe.ts     |  5 ++-
 .../audit/audit-grid/audit-grid.component.html     |  4 +-
 .../audit/audit-grid/audit-grid.component.ts       |  9 +++-
 .../reporting-grid/reporting-grid.component.html   | 17 ++++----
 .../reporting-grid/reporting-grid.component.scss   | 17 ++++++++
 .../reporting-grid/reporting-grid.component.ts     | 36 +++++++++-------
 .../folder-tree/folder-tree.component.ts           |  6 ++-
 .../install-libraries/filter-libs.model.ts         |  4 +-
 .../install-libraries.component.html               | 12 +++---
 .../install-libraries.component.scss               | 34 ++-------------
 .../install-libraries.component.ts                 | 49 ++++++++++++++++------
 .../resources-grid/resources-grid.component.html   |  4 +-
 .../resources-grid/resources-grid.component.scss   |  2 +-
 .../resources-grid/resources-grid.component.ts     | 18 +++++++-
 .../src/app/resources/resources.component.html     |  2 +-
 .../multi-select-dropdown.component.html           |  4 +-
 .../resources/webapp/src/assets/styles/_theme.scss |  4 +-
 20 files changed, 150 insertions(+), 91 deletions(-)

diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html
index 8d2df70..1235be3 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html
@@ -262,12 +262,12 @@
     <ng-container matColumnDef="actions-filter" sticky>
       <th mat-header-cell *matHeaderCellDef  class="actions-col filter-row-item">
         <div class="actions">
-          <button mat-icon-button class="btn reset" (click)="resetFilterConfigurations()">
+          <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)="applyFilter(filterForm)"
-            [disabled]="allFilteredEnvironmentData?.length == 0 && !filtering">
+            [disabled]="!isFilterChanged">
             <i class="material-icons"
               [ngClass]="{'not-allowed': allFilteredEnvironmentData?.length == 0 && !filtering}">done</i>
           </button>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts
index fa2a37f..ab4bda7 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts
@@ -67,6 +67,8 @@ export class ManagementGridComponent implements OnInit {
   private selected;
   private allActiveNotebooks: any;
   private cashedFilterForm: ManagementConfigModel = new ManagementConfigModel([], '', [], [], [], []);
+  private isFilterSelected: boolean;
+  private isFilterChanged: boolean;
 
   constructor(
     private healthStatusService: HealthStatusService,
@@ -101,6 +103,12 @@ export class ManagementGridComponent implements OnInit {
 
   public onUpdate($event): void {
     this.filterForm[$event.type] = $event.model;
+    this.checkFilters();
+  }
+
+  private checkFilters() {
+    this.isFilterChanged = JSON.stringify(this.cashedFilterForm) !== JSON.stringify(this.filterForm);
+    this.isFilterSelected = Object.keys(this.filterForm).filter(v => this.filterForm[v].length > 0).length > 0;
   }
 
   public toggleFilterRow(): void {
@@ -157,6 +165,7 @@ export class ManagementGridComponent implements OnInit {
       .filter(v => v.name &&
       (v.status === 'running' || v.status === 'stopped') &&
       !this.clustersInProgress(v.resources));
+    this.checkFilters();
   }
 
   getEnvironmentDataCopy() {
diff --git a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
index 81663d4..31f955c 100644
--- a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
@@ -32,7 +32,6 @@ import { ManagementComponent } from './administration/management/management.comp
 import { ProjectComponent } from './administration/project/project.component';
 import { RolesComponent } from './administration/roles/roles.component';
 import { SwaggerComponent } from './swagger/swagger.component';
-
 import { AuthorizationGuard, CheckParamsGuard, CloudProviderGuard, AdminGuard, AuditGuard } from './core/services';
 import {AuditComponent} from './reports/audit/audit.component';
 
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-pipe/convert-action.pipe.ts b/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-pipe/convert-action.pipe.ts
index a415603..0a1a1a0 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-pipe/convert-action.pipe.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-pipe/convert-action.pipe.ts
@@ -22,7 +22,10 @@ import { Pipe, PipeTransform } from '@angular/core';
 @Pipe({ name: 'convertaction' })
 
 export class ConvertActionPipe implements PipeTransform {
-  transform(value: string): any {
+  transform(value: string, lowercase?): any {
+    if (!!lowercase) {
+      return value.toLowerCase().replace(/_/g, ' ');
+    }
     return value.charAt(0) + value.slice(1).toLowerCase().replace(/_/g, ' ');
   }
 }
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 2a57cdf..538fec1 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
@@ -211,11 +211,11 @@
     <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()">
+          <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]="!didFilterChanged()">
+          <button mat-icon-button class="btn apply" (click)="buildAuditGrid(true)" [disabled]="!isNavigationDisabled">
             <i class="material-icons">done</i>
           </button>
         </div>
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 e3010ec..faf887d 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
@@ -55,6 +55,7 @@ export class AuditGridComponent implements OnInit {
   public allItems: number;
   private copiedFilterAuditData: FilterAuditModel;
   public isNavigationDisabled: boolean;
+  public isFilterSelected: boolean;
 
   @Output() resetDateFilter: EventEmitter<any> = new EventEmitter();
 
@@ -96,6 +97,7 @@ export class AuditGridComponent implements OnInit {
         '',
         ''
       );
+      this.checkFilters();
     });
   }
 
@@ -116,6 +118,12 @@ export class AuditGridComponent implements OnInit {
 
   public onUpdate($event): void {
     this.filterAuditData[$event.type] = $event.model;
+    this.checkFilters();
+  }
+
+  private checkFilters() {
+    this.isNavigationDisabled = JSON.stringify(this.copiedFilterAuditData) !== JSON.stringify(this.filterAuditData);
+    this.isFilterSelected = Object.keys(this.filterAuditData).filter(v => this.filterAuditData[v].length > 0).length > 0;
   }
 
   public openActionInfo(element: AuditItem): void {
@@ -166,7 +174,6 @@ export class AuditGridComponent implements OnInit {
   }
 
   public didFilterChanged(): boolean {
-    this.isNavigationDisabled = JSON.stringify(this.copiedFilterAuditData) !== JSON.stringify(this.filterAuditData);
     return this.isNavigationDisabled;
   }
 }
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 5fc1301..1d6ffaf 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
@@ -177,7 +177,7 @@
 
 
         <ng-container matColumnDef="charge" stickyEnd>
-          <th mat-header-cell *matHeaderCellDef class="th_charges label-header" [ngClass]="{'right-sticky': reportData?.length < 5}">
+          <th mat-header-cell *matHeaderCellDef class="th_charges label-header index-102" [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>
@@ -250,13 +250,13 @@
           </th>
         </ng-container>
         <ng-container matColumnDef="actions" stickyEnd>
-          <th mat-header-cell *matHeaderCellDef class="filter-row-item" [ngClass]="{'right-sticky': reportData?.length < 5}">
+          <th mat-header-cell *matHeaderCellDef class="filter-row-item index-102" [ngClass]="{'right-sticky': reportData?.length < 5}" [ngStyle]="{'zIndex': '101 !important'}">
             <div class="actions">
-              <button mat-icon-button class="btn reset" (click)="resetFiltering(); isFiltered = !isFiltered">
+              <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>
@@ -264,7 +264,10 @@
         </ng-container>
         <ng-container matColumnDef="placeholder">
           <td mat-footer-cell *matFooterCellDef colspan="9" class="info">
-            <span>No data available</span>
+            <span *ngIf="!isFilterSelected; else notFound">No data available</span>
+            <ng-template #notFound>
+              <span>No matches found</span>
+            </ng-template>
           </td>
         </ng-container>
 
@@ -280,12 +283,12 @@
       </table>
     </section>
     <div class="buttons" *ngIf="tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0 && reportData?.length">
-      <div class="button-container">
+      <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">
+      <div class="button-container" [ngClass]="{'not-allowed': this.checkMaxRight()}">
         <button mat-mini-fab aria-label="Scroll right"
                 (click)="sctollTo('right')"
                 [ngClass]="{'not-allowed': !(isMaxRight | async)}"
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 c6a5961..7a64ccd 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
@@ -205,6 +205,11 @@
   .table-footer.mat-column-charge{
     text-align: right;
     background-color: #f8f8f8;
+  }
+
+  .mat-column-charge:not(.index-102),
+  .filter-row-item:last-child:not(.index-102),
+  .table-footer.mat-column-charge{
     z-index: 100 !important;
   }
 
@@ -329,6 +334,18 @@
     right: 0;
   }
 
+.wrapper{
+  .table-wrapper{
+    .reporting{
+      tr{
+        th.th_charges.index-102{
+          z-index: 102 !important;
+        }
+      }
+    }
+  }
+}
+
 
 
 @media screen and (max-width: 1280px) {
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 6ea1014..51e8581 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
@@ -51,36 +51,36 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
   fullReport: Array<any>;
   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'];
+  filtered: any;
+  isMaxRight: Subject<boolean> = new BehaviorSubject(false);
+  isFilterSelected: boolean;
+  isFilterChanged: boolean;
   public isScrollButtonsVisible: boolean;
 
   @ViewChild('nameFilter', { static: false }) filter;
   @ViewChild('tableWrapper', { static: false }) tableWrapper;
   @ViewChild('wrapper', { static: false }) wrapper;
-  @ViewChild('pageWrapper', { static: false }) pageWrapper;
 
+  @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;
 
+  @Input() previousFilterData: ReportingConfigModel;
   @HostListener('window:resize', ['$event'])
   onResize(event) {
     this.isScrollButtonsVisible = this.tableWrapper.nativeElement.offsetWidth - this.table._elementRef.nativeElement.offsetWidth < 0;
     this.checkMaxRight();
   }
+
   @HostListener('scroll', ['$event'])
   scrollTable($event: Event) {
     this.checkMaxRight();
   }
 
-
-
-  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);
-
   constructor(private changeDetector: ChangeDetectorRef) {
   }
 
@@ -90,6 +90,7 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
       this.checkMaxRight();
       this.tableEl = this.table._elementRef.nativeElement;
     }, 1000);
+    this.checkFilters();
   }
 
   ngAfterViewInit() {
@@ -98,11 +99,19 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
 
   onUpdate($event): void {
     this.filteredReportData[$event.type] = $event.model;
+    this.checkFilters();
+  }
+
+  private checkFilters() {
+    this.isFilterChanged = JSON.stringify(this.filteredReportData) === JSON.stringify(this.previousFilterData);
+    this.isFilterSelected = Object.keys(this.filteredReportData).filter(v => this.filteredReportData[v].length > 0).length > 0;
   }
 
   refreshData(fullReport, report) {
     this.reportData = [...report];
     this.fullReport = fullReport;
+    console.log(fullReport);
+    this.checkFilters();
   }
 
   setFullReport(data): void {
@@ -145,11 +154,13 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
 
   setConfiguration(reportConfig: ReportingConfigModel): void {
     this.filterConfiguration = reportConfig;
+    this.checkFilters();
   }
 
   filter_btnClick(): void {
     this.filterReport.emit(this.filteredReportData);
     this.isFiltered = true;
+    this.checkFilters();
     this.removeSorting();
   }
 
@@ -159,6 +170,7 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
     this.filter.nativeElement.value = '';
     this.filterReport.emit(this.filteredReportData);
     this.resetRangePicker.emit(true);
+    this.checkFilters();
   }
 
   shapeSplit(shape) {
@@ -176,6 +188,7 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
   }
 
   private checkMaxRight() {
+    console.log('check');
     if (this.reportData && this.reportData.length < 5) {
       const arg = this.pageWrapper.nativeElement.offsetWidth - 15 +
       this.pageWrapper.nativeElement.scrollLeft + 2 <= this.table._elementRef.nativeElement.offsetWidth;
@@ -187,9 +200,4 @@ export class ReportingGridComponent implements OnInit, AfterViewInit {
     }
 
   }
-
-  public isFilterChanged() {
-    return JSON.stringify(this.filteredReportData) === JSON.stringify(this.previousFilterData);
-  }
-
 }
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts
index 7003a33..ac2af44 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts
@@ -116,7 +116,11 @@ export class FolderTreeComponent implements OnDestroy {
     flatNode.item = node.item;
     flatNode.level = level;
     flatNode.expandable = !!node.children;
-    flatNode.obj = node.object.object;
+    if (node.object) {
+      flatNode.obj = node.object.object;
+    } else {
+      flatNode.obj = '';
+    }
     this.flatNodeMap.set(flatNode, node);
     this.nestedNodeMap.set(node, flatNode);
     return flatNode;
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/filter-libs.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/filter-libs.model.ts
index 4d211cc..e55a5ed 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/filter-libs.model.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/filter-libs.model.ts
@@ -22,7 +22,7 @@ export class FilterLibsModel {
     public name: string,
     public group: Array<any>,
     public resource: Array<any>,
-    public resourceType: Array<any>,
+    public resource_type: Array<any>,
     public status: Array<any>,
   ) { }
 
@@ -30,7 +30,7 @@ export class FilterLibsModel {
     this.name = '';
     this.group = [];
     this.resource = [];
-    this.resourceType = [];
+    this.resource_type = [];
     this.status = [];
   }
 }
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 a13eebc..8caee40 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
@@ -276,9 +276,9 @@
             <th class="lib-resource-type filter-col">
               <multi-select-dropdown
                 (selectionChange)="onFilterUpdate($event)"
-                [items]="this.filterConfiguration.resourceType"
-                [type]="'resource type'"
-                [model]="this.filterModel.resourceType"
+                [items]="this.filterConfiguration.resource_type"
+                [type]="'resource_type'"
+                [model]="this.filterModel.resource_type"
               >
               </multi-select-dropdown>
           </th>
@@ -293,12 +293,12 @@
           </th>
            <ng-container matColumnDef="action-filter" stickyEnd>
              <th mat-header-cell>
-               <div class="filter-actions">
-                 <button mat-icon-button class="btn reset" (click)="resetFilterConfigurations()">
+               <div class="filter-actions actions">
+                 <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)="filterLibs()">
+                 <button mat-icon-button class="btn apply" (click)="filterLibs(true)" [disabled]="!isFilterChanged">
                    <i class="material-icons"  [ngClass]="{'not-allowed': filterModel['length'] === 0}">done</i>
                  </button>
                </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 53c453b..3403fe1 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
@@ -363,6 +363,9 @@ mat-chip.mat-chip:not(.mat-basic-chip) {
           padding-left: 15px;
         }
       }
+      .status{
+        text-transform: none;
+      }
     }
   }
 
@@ -518,20 +521,6 @@ mat-chip.mat-chip:not(.mat-basic-chip) {
         display: flex;
       }
     }
-
-    .reset{
-      &:hover {
-        border-color: #f1696e;
-        background: #f9fafb;
-        color: #f1696e;
-      }
-    }
-
-    .apply:hover {
-      border-color: #49af38;
-      background: #f9fafb;
-      color: #49af38;
-    }
   }
 }
 
@@ -546,23 +535,6 @@ mat-chip.mat-chip:not(.mat-basic-chip) {
   }
 }
 
-.filter-row .filter-actions {
-  display: flex;
-
-  .reset{
-      &:hover {
-      border-color: #f1696e;
-      background: #f9fafb;
-      color: #f1696e;
-    }
-  }
-  .apply:hover {
-    border-color: #49af38;
-    background: #f9fafb;
-    color: #49af38;
-  }
-}
-
 .error-message{
   position: absolute;
   left: 20%;
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 99abb96..1ab25fa 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
@@ -88,6 +88,9 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
   public selectedLib: any = null;
   public isLibSelected: boolean = false;
   public isVersionInvalid: boolean = false;
+  private isFilterChanged: boolean;
+  private isFilterSelected: boolean;
+  private cashedFilterForm: FilterLibsModel;
 
   constructor(
     @Inject(MAT_DIALOG_DATA) public data: any,
@@ -199,6 +202,12 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
 
   public onFilterUpdate($event) {
     this.filterModel[$event.type] = $event.model;
+    this.checkFilters();
+  }
+
+  private checkFilters() {
+    this.isFilterChanged = JSON.stringify(this.cashedFilterForm) !== JSON.stringify(this.filterModel);
+    this.isFilterSelected = Object.keys(this.filterModel).filter(v => this.filterModel[v].length > 0).length > 0;
   }
 
   public isDuplicated(item) {
@@ -291,7 +300,12 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
   public isInstallingInProgress(): void {
     this.installingInProgress = this.notebookLibs.some(lib => lib.filteredStatus.some(status => status.status === 'installing'));
       if (this.installingInProgress) {
-        timer(this.INSTALLATION_IN_PROGRESS_CHECK).pipe(take(1)).subscribe(v => this.getInstalledLibrariesList());
+        timer(this.INSTALLATION_IN_PROGRESS_CHECK)
+          .pipe(
+            take(1),
+            takeUntil(this.unsubscribe$)
+          )
+          .subscribe(v => this.getInstalledLibrariesList());
       }
   }
 
@@ -329,7 +343,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
         this.filterConfiguration.group = this.createFilterList(this.notebookLibs.map(v => this.groupsListMap[v.group]));
         this.filterConfiguration.group = SortUtils.libFilterGroupsSort(this.filterConfiguration.group);
         this.filterConfiguration.resource = this.createFilterList(this.notebookLibs.map(lib => lib.status.map(status => status.resource)));
-        this.filterConfiguration.resourceType = this.createFilterList(this.notebookLibs.map(lib =>
+        this.filterConfiguration.resource_type = this.createFilterList(this.notebookLibs.map(lib =>
           lib.status.map(status => status.resourceType)));
         this.filterConfiguration.status = this.createFilterList(this.notebookLibs.map(lib => lib.status.map(status => status.status)));
         this.isInstallingInProgress();
@@ -356,7 +370,10 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
     } else {
       this.libs_uploaded = false;
       this.uploading = true;
-      timer(this.CHECK_GROUPS_TIMEOUT).pipe(take(1)).subscribe(() => this.uploadLibGroups());
+      timer(this.CHECK_GROUPS_TIMEOUT).pipe(
+        take(1),
+        takeUntil(this.unsubscribe$)
+      ).subscribe(() => this.uploadLibGroups());
     }
   }
 
@@ -413,7 +430,8 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
       .subscribe((libs: GetLibrary) => {
         if (libs.autoComplete === 'UPDATING') {
            timer(5000).pipe(
-            take(1)
+            take(1),
+            takeUntil(this.unsubscribe$)
           ).subscribe(_ => {
             this.getMatchedLibs();
           });
@@ -455,26 +473,31 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
     this.filtered = !this.filtered;
   }
 
-  public filterLibs(): void {
+  public filterLibs(updCachedForm?): void {
+    if (!this.cashedFilterForm || updCachedForm) {
+      this.cashedFilterForm = JSON.parse(JSON.stringify(this.filterModel));
+      Object.setPrototypeOf(this.cashedFilterForm, Object.getPrototypeOf(this.filterModel));
+    }
     this.filtredNotebookLibs = this.notebookLibs.filter((lib) => {
-      const isName = this.filterModel.name ?
-        lib.name.toLowerCase().indexOf(this.filterModel.name.toLowerCase().trim()) !== -1
-        || lib.version.indexOf(this.filterModel.name.toLowerCase().trim()) !== -1 : true;
-      const isGroup = this.filterModel.group.length ? this.filterModel.group.includes(this.groupsListMap[lib.group]) : true;
+      const isName = this.cashedFilterForm.name ?
+        lib.name.toLowerCase().indexOf(this.cashedFilterForm.name.toLowerCase().trim()) !== -1
+        || lib.version.indexOf(this.cashedFilterForm.name.toLowerCase().trim()) !== -1 : true;
+      const isGroup = this.cashedFilterForm.group.length ? this.cashedFilterForm.group.includes(this.groupsListMap[lib.group]) : true;
       lib.filteredStatus = lib.status.filter(status => {
-        const isResource = this.filterModel.resource.length ? this.filterModel.resource.includes(status.resource) : true;
-        const isResourceType = this.filterModel.resourceType.length ? this.filterModel.resourceType.includes(status.resourceType) : true;
-        const isStatus = this.filterModel.status.length ? this.filterModel.status.includes(status.status) : true;
+        const isResource = this.cashedFilterForm.resource.length ? this.cashedFilterForm.resource.includes(status.resource) : true;
+        const isResourceType = this.cashedFilterForm.resource_type.length ? this.cashedFilterForm.resource_type.includes(status.resourceType) : true;
+        const isStatus = this.cashedFilterForm.status.length ? this.cashedFilterForm.status.includes(status.status) : true;
         return isResource && isResourceType && isStatus;
       });
+      this.checkFilters();
       return isName && isGroup && lib.filteredStatus.length;
     });
   }
 
   public resetFilterConfigurations(): void {
     this.notebookLibs.forEach(v => v.filteredStatus = v.status);
-    this.filtredNotebookLibs = [...this.notebookLibs];
     this.filterModel.resetFilterLibs();
+    this.filterLibs(true);
   }
 
   public openLibInfo(lib, type) {
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
index afa556c..0e14343 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
@@ -296,12 +296,12 @@
     <ng-container matColumnDef="action-filter" stickyEnd>
       <th mat-header-cell *matHeaderCellDef>
         <div class="actions">
-          <button mat-icon-button class="btn reset" (click)="resetFilterConfigurations()" [disabled]="filteredEnvironments.length == 0 && !filtering">
+          <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)="applyFilter_btnClick(filterForm)"
-            [disabled]="filteredEnvironments.length == 0 && !filtering">
+            [disabled]="!isFilterChanged">
             <i class="material-icons">done</i>
           </button>
         </div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss
index fac9b18..03df6ff 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss
@@ -300,7 +300,7 @@ table.resources {
     font-size: 13px;
   }
 
-  &.data-grid .status {
+  &.data-grid .status-col .status {
     text-transform: capitalize;
   }
 
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts
index 043d328..b6a48af 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts
@@ -40,6 +40,7 @@ import {ProgressBarService} from '../../core/services/progress-bar.service';
 import {ComputationModel} from '../computational/computational-resource.model';
 import {NotebookModel} from '../exploratory/notebook.model';
 import {AuditService} from '../../core/services/audit.service';
+import {JAN} from '@angular/material/core';
 
 export interface SharedEndpoint {
   edge_node_ip: string;
@@ -119,6 +120,9 @@ export class ResourcesGridComponent implements OnInit {
   public displayedFilterColumns: string[] = this.filteringColumns.map(item => item.filter_class);
   public bucketsList: BucketList;
   public activeProjectsList: any;
+  public isFilterChanged: boolean;
+  public isFilterSelected: boolean;
+  private cashedFilterForm: FilterConfigurationModel;
 
   constructor(
     public toastr: ToastrService,
@@ -151,6 +155,7 @@ export class ResourcesGridComponent implements OnInit {
         (this.environments.length) ? this.getUserPreferences() : this.filteredEnvironments = [];
         this.healthStatus && !this.healthStatus.billingEnabled && this.modifyGrid();
         this.progressBarService.stopProgressBar();
+
         }, () => this.progressBarService.stopProgressBar());
   }
 
@@ -160,6 +165,12 @@ export class ResourcesGridComponent implements OnInit {
 
   public onUpdate($event): void {
     this.filterForm[$event.type] = $event.model;
+    this.checkFilters();
+  }
+
+  private checkFilters() {
+    this.isFilterChanged = JSON.stringify(this.cashedFilterForm) !== JSON.stringify(this.filterForm);
+    this.isFilterSelected = Object.keys(this.filterForm).filter(v => this.filterForm[v].length > 0).length > 0;
   }
 
   public selectActiveProject(project = ''): void {
@@ -319,9 +330,11 @@ export class ResourcesGridComponent implements OnInit {
   }
 
   public applyFilter_btnClick(config: FilterConfigurationModel): void {
-
+    const cached = this.loadUserPreferences(config);
+    this.cashedFilterForm = JSON.parse(JSON.stringify(cached));
+    Object.setPrototypeOf(this.cashedFilterForm, Object.getPrototypeOf(cached));
     let filteredData = this.getEnvironmentsListCopy();
-
+    this.checkFilters();
     const containsStatus = (list, selectedItems) => {
       return list.filter((item: any) => { if (selectedItems.indexOf(item.status) !== -1) return item; });
     };
@@ -416,6 +429,7 @@ export class ResourcesGridComponent implements OnInit {
           this.filterForm = this.loadUserPreferences(result.type ? this.filterActiveInstances() : this.aliveStatuses(result));
         }
         this.applyFilter_btnClick(result || this.filterForm);
+        this.checkFilters();
       }, () => this.applyFilter_btnClick(null));
   }
 
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/resources.component.html
index ad6fc53..4accd0d 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources.component.html
@@ -79,7 +79,7 @@
       </span>
       <span>
         <button mat-raised-button class="butt" (click)="refreshGrid()">
-          <i class="material-icons">autorenew</i>Refresh
+          <i class="material-icons highlight">autorenew</i>Refresh
         </button>
       </span>
     </div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/form-controls/multi-select-dropdown/multi-select-dropdown.component.html b/services/self-service/src/main/resources/webapp/src/app/shared/form-controls/multi-select-dropdown/multi-select-dropdown.component.html
index 5ad1f09..781220a 100644
--- a/services/self-service/src/main/resources/webapp/src/app/shared/form-controls/multi-select-dropdown/multi-select-dropdown.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/shared/form-controls/multi-select-dropdown/multi-select-dropdown.component.html
@@ -44,8 +44,8 @@
           <li role="presentation" *ngIf="model">
             <a href="#" class="list-item" role="menuitem" (click)="toggleSelectedOptions($event, model, item)">
               <span class="material-icons" *ngIf="model.indexOf(item) >= 0">done</span>
-              <ng-container *ngIf="type !== 'resource_type' && type !== 'resource_types'">{{item}}</ng-container>
-              <ng-container *ngIf="type === 'resource_type' || type === 'resource_types'">{{item | convertaction}}</ng-container>
+              <ng-container *ngIf="type !== 'resource_type' && type !== 'resource_types' && item !== 'invalid_name' && item !== 'invalid_version' && item !== 'installation_error'">{{item}}</ng-container>
+              <ng-container *ngIf="type === 'resource_type' || type === 'resource_types' || item === 'invalid_name' || item === 'invalid_version' || item === 'installation_error'">{{item | convertaction}}</ng-container>
             </a>
           </li>
         </ng-template>
diff --git a/services/self-service/src/main/resources/webapp/src/assets/styles/_theme.scss b/services/self-service/src/main/resources/webapp/src/assets/styles/_theme.scss
index 2e7a5b8..a56919d 100644
--- a/services/self-service/src/main/resources/webapp/src/assets/styles/_theme.scss
+++ b/services/self-service/src/main/resources/webapp/src/assets/styles/_theme.scss
@@ -939,13 +939,13 @@ mat-progress-bar {
   outline: none;
 }
 
-.filter-row .actions .reset:hover {
+.filter-row .actions .reset:not([disabled]):hover {
   border-color: #f1696e;
   background: #f9fafb;
   color: #f1696e;
 }
 
-.filter-row .actions .apply:hover {
+.filter-row .actions .apply:not([disabled]):hover {
   border-color: #49af38;
   background: #f9fafb;
   color: #49af38;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org