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/07/24 13:04:22 UTC
[incubator-dlab] 01/02: [DLAB-1960]: Fixed library issues
This is an automated email from the ASF dual-hosted git repository.
dgnatyshyn pushed a commit to branch DLAB-1960
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit d32fc3cd60238748fd539daf2994d177b9f30203
Author: Dmytro_Gnatyshyn <di...@ukr.net>
AuthorDate: Fri Jul 24 15:39:48 2020 +0300
[DLAB-1960]: Fixed library issues
---
.../install-libraries.component.html | 59 +++++----
.../install-libraries.component.scss | 10 +-
.../install-libraries.component.ts | 137 ++++++++++++---------
.../install-libraries/install-libraries.model.ts | 2 +-
.../resources/webapp/src/assets/styles/_theme.scss | 8 ++
.../src/main/resources/webapp/src/styles.scss | 3 +-
6 files changed, 130 insertions(+), 89 deletions(-)
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 c05b6f9..54f1d86 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
@@ -28,13 +28,14 @@
<p class=" message">Cannot install libraries: Exploratory
<strong>{{ notebook?.name }}</strong> is not running</p>
</div>
- <div class="loading-block" *ngIf="!libs_uploaded && uploading && data.status === 'running'">
+ <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>
<img src="assets/img/gif-spinner.gif" alt="loading">
</div>
</div>
- <div *ngIf="notebook?.status === 'running' && !uploading" class="lib-view-wrap">
+ <div *ngIf="notebook?.status === 'running' && !uploading" class="lib-view-wrap">
<div class="search-box">
<div class="search-form">
<div>
@@ -48,7 +49,7 @@
<label class="label">Select group</label>
<div class="control">
<dropdown-list #groupSelect (selectedItem)="onUpdate($event)" (emitClick)="emitClick()"></dropdown-list>
- <span class="error-message" *ngIf="!group && libSearch.value">Group field is required. Please choose appropriate group.</span>
+ <span class="error-message" *ngIf="!group && libSearch?.value">Group field is required. Please choose appropriate group.</span>
</div>
</div>
</div>
@@ -59,7 +60,6 @@
<span class="other-message" *ngIf="group === 'others'">Other group can include libs from Python 2 and Python 3 groups</span>
<input
type="text" [placeholder]="'Enter library name'"
- [(ngModel)]="lib.name"
[disabled]="!group"
[matAutocomplete]="auto"
[formControl]="libSearch"
@@ -68,15 +68,13 @@
>
</div>
<mat-autocomplete #auto="matAutocomplete" class="suggestions" >
- <ng-template ngFor let-item [ngForOf]="filteredList" let-i="index" *ngIf="!selectedLib">
- <mat-option >
+ <ng-template ngFor let-item [ngForOf]="filteredList" let-i="index">
+ <mat-option>
<div class="option" (click)="selectLibrary(item);$event.stopPropagation()" [ngClass]="{'not-allow': item.isInSelectedList}">
<a *ngIf="!item.isInSelectedList">
- <span [innerHTML]="item.name | highlight:query"></span>
+ <span [innerHTML]="item.name | highlight:lib.name.toLowerCase()"></span>
</a>
- <span *ngIf="item.isInSelectedList">{{ item.name }}
-<!-- <span *ngIf="item.version && item.version !== 'N/A' && item.isInstalled && !item.isInSelectedList">{{ item.version }}</span>-->
- </span>
+ <span *ngIf="item.isInSelectedList">{{ item.name }}</span>
<strong *ngIf="item.isInSelectedList">selected
<i class="material-icons">done</i>
</strong>
@@ -113,10 +111,10 @@
<div class="control-group constol-select java-library-search">
<label class="label">Library</label>
<div class="control control-relative">
- <span class="other-message" *ngIf="lib.name.length && !this.selectedLib">groupId:artifactId:versionId</span>
+ <span class="other-message" *ngIf="lib.name?.length && !this.selectedLib">groupId:artifactId:versionId</span>
<input
type="text" [placeholder]="'Enter library name in <groupId>:<artifactId>:<versionId> format'"
- [(ngModel)]="lib.name"
+
[disabled]="!group"
[matAutocomplete]="auto"
[formControl]="libSearch"
@@ -132,11 +130,11 @@
</span>
</div>
<mat-autocomplete #auto="matAutocomplete" class="suggestions">
- <ng-template ngFor let-item [ngForOf]="filteredList" let-i="index" *ngIf="!selectedLib">
+ <ng-template ngFor let-item [ngForOf]="filteredList" let-i="index">
<mat-option >
<div class="option" (click)="selectLibrary(item);$event.stopPropagation()" [ngClass]="{'not-allow': item.isInSelectedList}">
<a *ngIf="!item.isInSelectedList">
- <span [innerHTML]="item.name + ':' + item.version | highlight:query">
+ <span [innerHTML]="item.name + ':' + item.version | highlight:item.name.toLowerCase()">
<span>{{ item.version }}</span>
</span>
</a>
@@ -231,6 +229,10 @@
</div>
</div>
</div>
+ </div>
+
+
+
<div class="libs-info">
<mat-list>
<mat-list-item class="list-header">
@@ -344,8 +346,8 @@
<div class="wrap-col">
<div class="lib-destination-col">{{ item.resource }}</div>
<div class="lib-resource-type-col">{{ item.resourceType }}</div>
- <div class="lib-status-col" ngClass="{{ item.status.toLowerCase() || 'failed' }}">{{ item.status.replace('_', ' ') }}
- <div class="warn-action" *ngIf="(item.status === 'failed' || item.status.toLowerCase() === 'invalid_version') && notebook?.status === 'running'">
+ <div class="lib-status-col" ngClass="{{ item.status.toLowerCase() || 'installation_error' }}">{{ item.status.replace('_', ' ') }}
+ <div class="warn-action" *ngIf="(item.status === 'installation_error' || item.status.toLowerCase() === 'invalid_version') && notebook?.status === 'running'">
<div *ngIf="!item.available_versions">
<span *ngIf="!installingInProgress" (click)="reinstallLibrary(item, lib)" matTooltip="Retry installation" matTooltipPosition="above">
<i class="material-icons">replay</i>
@@ -355,22 +357,23 @@
<i class="material-icons">replay</i>
</span>
</div>
- <div *ngIf="item.status === 'failed' && item.error" class="lib-error" (click)="showErrorMessage(item)">
- <i class="material-icons">error_outline</i>
+ <div *ngIf="item.status === 'installation_error' && item.error" class="lib-error" (click)="showErrorMessage(item)" matTooltip="Show error message" matTooltipPosition="above">
+ <i class="material-icons terminated">error_outline</i>
</div>
<div class="lib-error"
- *ngIf="item.status.toLowerCase() === 'invalid_version' && item.available_versions?.length" class="lib-error"
+ *ngIf="item.status.toLowerCase() === 'invalid_version' && item.available_versions?.length"
(click)="openLibInfo(item, 'available');$event.stopPropagation()"
matTooltip="Show available version" matTooltipPosition="above"
>
- <i class="material-icons terminated">error_outline</i>
+ <i class="material-icons">error_outline</i>
</div>
- </div>
- <div class="warn-action" matTooltip="Show installed dependency" matTooltipPosition="above" *ngIf="item.add_pkgs?.length">
+ <div matTooltip="Show installed dependency" matTooltipPosition="above" *ngIf="item.add_pkgs?.length">
<span class="info-icon" (click)="openLibInfo(item, 'added');$event.stopPropagation() ">
<i class="material-icons">info</i>
</span>
+ </div>
</div>
+
</div>
</div>
@@ -411,8 +414,16 @@
</mat-list>
</div>
<div class="m-top-15 actions" *ngIf="!uploading && notebook?.status === 'running'">
- <button mat-raised-button type="button" class="butt action" (click)="dialogRef.close()">Close</button>
- <button mat-raised-button type="submit" class="butt butt-success action" (click)="model.confirmAction()" [disabled]="!model.selectedLibs.length || installingInProgress || !destination">Install</button>
+ <button mat-raised-button type="button" class="butt action close-btn" (click)="dialogRef.close()">Close</button>
+ <span matTooltip="Please wait until lib installation completes" [matTooltipDisabled]="!installingInProgress" matTooltipPosition="above">
+ <button mat-raised-button type="submit"
+ class="butt butt-success action install-btn"
+ (click)="model.confirmAction()"
+ [disabled]="!model.selectedLibs.length || installingInProgress || !destination"
+ >
+ Install
+ </button>
+ </span>
</div>
</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 86cd434..48ed412 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
@@ -65,6 +65,10 @@
height: 30%;
}
+.top-wrapper{
+ height: 285px;
+}
+
.install-libraries {
height: 100%;
padding-bottom: 130px;
@@ -78,7 +82,6 @@
}
.info {
- height: 40%;
display: flex;
flex-direction: row;
align-items: center;
@@ -99,7 +102,6 @@
.lib-view-wrap {
display: flex;
flex-direction: column;
- height: 40%;
}
.error {
@@ -342,7 +344,6 @@ mat-chip.mat-chip:not(.mat-basic-chip) {
display: flex;
flex: 1 1 auto;
min-height: 0px;
- height: 50%;
.mat-list {
width: 100%;
@@ -555,6 +556,9 @@ mat-chip.mat-chip:not(.mat-basic-chip) {
.btn{
line-height: 26px;
+ &.install-btn{
+ margin-left: 0;
+ }
}
.control-relative{
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 169156d..ae38165 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
@@ -22,12 +22,13 @@ import {Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectorRef, Inje
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { FormControl } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
-import { debounceTime } from 'rxjs/operators';
+import {debounceTime, takeUntil} from 'rxjs/operators';
import { InstallLibrariesModel } from './install-libraries.model';
import { LibrariesInstallationService } from '../../../core/services';
import { SortUtils, HTTP_STATUS_CODES } from '../../../core/util';
import {FilterLibsModel} from './filter-libs.model';
+import {Subject} from 'rxjs';
interface Library {
name: string;
@@ -42,16 +43,13 @@ interface Library {
encapsulation: ViewEncapsulation.None
})
export class InstallLibrariesComponent implements OnInit, OnDestroy {
-
+ private unsubscribe$ = new Subject();
public model: InstallLibrariesModel;
public notebook: any;
public filteredList: any = [];
public groupsList: Array<string>;
public notebookLibs: Array<any> = [];
- public notebookFailedLibs: Array<any> = [];
public loadLibsTimer: any;
-
- public query: string = '';
public group: string;
public destination: any;
public uploading: boolean = false;
@@ -81,10 +79,8 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
@ViewChild('groupSelect', { static: false }) group_select;
@ViewChild('resourceSelect', { static: false }) resource_select;
@ViewChild('trigger', { static: false }) matAutoComplete;
- public isLibInfoOpened = { };
private isLibExist: boolean;
public lib: Library = {name: '', version: ''};
- public javaLib: {group, artifact, version} = {group: '', artifact: '', version: ''};
private selectedLib: any = null;
constructor(
@@ -103,9 +99,11 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
this.libSearch.disable();
this.libSearch.valueChanges
.pipe(
- debounceTime(1000))
- .subscribe(newValue => {
- this.query = newValue;
+ debounceTime(1000),
+ takeUntil(this.unsubscribe$)
+ )
+ .subscribe(value => {
+ this.lib.name = value;
this.isDuplicated(this.lib);
this.filterList();
});
@@ -114,12 +112,17 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
ngOnDestroy() {
window.clearTimeout(this.loadLibsTimer);
window.clearTimeout(this.clear);
+ this.unsubscribe$.next();
+ this.unsubscribe$.complete();
}
uploadLibGroups(): void {
this.libs_uploaded = false;
this.uploading = true;
this.librariesInstallationService.getGroupsList(this.notebook.project, this.notebook.name, this.model.computational_name)
+ .pipe(
+ takeUntil(this.unsubscribe$)
+ )
.subscribe(
response => {
this.libsUploadingStatus(response);
@@ -150,7 +153,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
public filterList(): void {
this.validity_format = '';
- (this.query && this.query.length >= 2 && this.group && !this.selectedLib) ? this.getFilteredList() : this.filteredList = null;
+ (this.lib.name && this.lib.name.length >= 2 && this.group ) ? this.getFilteredList() : this.filteredList = null;
}
public filterGroups(groupsList) {
@@ -166,6 +169,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
if ($event.model.type === 'group_lib') {
this.libSearch.enable();
this.group = $event.model.value;
+ this.lib = {name: '', version: ''};
} else if ($event.model.type === 'destination') {
this.resetDialog();
this.destination = $event.model.value;
@@ -186,25 +190,27 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
public isDuplicated(item) {
if (this.filteredList) {
if (this.group !== 'java') {
- this.selectedLib = this.filteredList.find(lib => lib.name === item.name);
+ this.selectedLib = this.filteredList.find(lib => lib.name.toLowerCase() === item.name.toLowerCase());
} else {
this.selectedLib = this.filteredList.find(lib => {
- return lib.name === item.name.substring(0, item.name.lastIndexOf(':'));
+ return lib.name.toLowerCase() === item.name.substring(0, item.name.lastIndexOf(':')).toLowerCase();
});
}
} else {
this.selectedLib = null;
}
-
- if (this.selectedLib) {
- this.filteredList = null;
- }
}
public addLibrary(item): void {
if (this.selectedLib && !this.selectedLib.isInSelectedList) {
- this.model.selectedLibs.push({ group: this.group, name: item.name, version: item.version || 'N/A' });
- this.query = '';
+ if (this.group !== 'java') {
+ this.model.selectedLibs.push({ group: this.group, name: item.name.toLowerCase(), version: item.version.toLowerCase() || 'N/A' });
+ } else {
+ this.model.selectedLibs.push({
+ group: this.group, name: item.name.substring(0, item.name.lastIndexOf(':')).toLowerCase(),
+ version: item.name.substring(item.name.lastIndexOf(':') + 1).toLowerCase() || 'N/A'
+ });
+ }
this.libSearch.setValue('');
this.lib = {name: '', version: ''};
this.filteredList = null;
@@ -240,7 +246,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
this.resetDialog();
}
},
- error => this.toastr.error(error.message || 'Library installation failed!', 'Oops!'),
+ error => this.toastr.error(error.message || 'Library installation error!', 'Oops!'),
() => {
this.getInstalledLibrariesList(true);
this.changeDetector.detectChanges();
@@ -274,6 +280,9 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
private getInstalledLibrariesList(init?: boolean) {
this.model.getInstalledLibrariesList(this.notebook)
+ .pipe(
+ takeUntil(this.unsubscribe$)
+ )
.subscribe((data: any) => {
if ( !this.filtredNotebookLibs.length || data.length !== this.notebookLibs.length) {
this.filtredNotebookLibs = [...data];
@@ -305,6 +314,9 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
private getInstalledLibsByResource() {
this.librariesInstallationService.getInstalledLibsByResource(this.notebook.project, this.notebook.name, this.model.computational_name)
+ .pipe(
+ takeUntil(this.unsubscribe$)
+ )
.subscribe((data: any) => this.destination.libs = data);
}
@@ -322,52 +334,57 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
private getFilteredList(): void {
this.validity_format = '';
-
- if (this.group === 'java') {
- this.model.getDependencies(this.query)
- .subscribe(
- libs => {
- this.filteredList = [libs];
- this.filteredList.forEach(lib => {
- lib.isInSelectedList = this.model.selectedLibs.some(el => lib.name === el.name.substring(0, el.name.lastIndexOf(':')));
- lib.isInstalled = this.notebookLibs.some(libr => {
- // && lib.version === item.name.substring(item.name.lastIndexOf(':') + 1
- return lib.name === libr.name.substring(0, libr.name.lastIndexOf(':')) &&
- this.group === libr.group &&
- libr.status.some(res => res.resource === this.destination.name);
+ if (this.lib.name.length > 1) {
+ if (this.group === 'java') {
+ this.model.getDependencies(this.lib.name)
+ .pipe(
+ takeUntil(this.unsubscribe$)
+ )
+ .subscribe(
+ libs => {
+ this.filteredList = [libs];
+ this.filteredList.forEach(lib => {
+ lib.isInSelectedList = this.model.selectedLibs.some(el => lib.name.toLowerCase() === el.name.substring(0, el.name.lastIndexOf(':')).toLowerCase());
+ lib.isInstalled = this.notebookLibs.some(libr => {
+ return lib.name.toLowerCase() === libr.name.substring(0, libr.name.lastIndexOf(':')).toLowerCase() &&
+ this.group === libr.group &&
+ libr.status.some(res => res.resource === this.destination.name);
+ }
+ );
+ });
+ this.isDuplicated(this.lib);
+ },
+ error => {
+ if (error.status === HTTP_STATUS_CODES.NOT_FOUND
+ || error.status === HTTP_STATUS_CODES.BAD_REQUEST
+ || error.status === HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR) {
+ this.validity_format = error.message;
+ this.filteredList = null;
}
- );
});
- this.isDuplicated(this.lib);
- },
- error => {
- if (error.status === HTTP_STATUS_CODES.NOT_FOUND
- || error.status === HTTP_STATUS_CODES.BAD_REQUEST
- || error.status === HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR) {
- this.validity_format = error.message;
- this.filteredList = null;
- }
- });
- } else {
- this.getMatchedLibs();
+ } else {
+ this.getMatchedLibs();
+ }
}
}
private getMatchedLibs() {
- if (this.query.length > 1) {
- this.model.getLibrariesList(this.group, this.query)
- .subscribe((libs: Library[]) => {
- this.isLibExist = libs.some(v => v.name === this.query);
- this.filteredList = libs;
- this.filteredList.forEach(lib => {
- lib.isInSelectedList = this.model.selectedLibs.some(el => el.name === lib.name);
- lib.isInstalled = this.notebookLibs.some(libr => lib.name === libr.name &&
- this.group === libr.group &&
- libr.status.some(res => res.resource === this.destination.name));
- });
- this.isDuplicated(this.lib);
+ this.model.getLibrariesList(this.group, this.lib.name.toLowerCase())
+ .pipe(
+ takeUntil(this.unsubscribe$)
+ )
+ .subscribe((libs: Library[]) => {
+ this.isLibExist = libs.some(v => v.name.toLowerCase() === this.lib.name.toLowerCase());
+ this.filteredList = libs;
+ this.filteredList.forEach(lib => {
+ lib.isInSelectedList = this.model.selectedLibs.some(el => el.name.toLowerCase() === lib.name.toLowerCase());
+ lib.isInstalled = this.notebookLibs.some(libr => lib.name === libr.name &&
+ this.group === libr.group &&
+ libr.status.some(res => res.resource === this.destination.name));
});
- }
+ this.isDuplicated(this.lib);
+ });
+
}
private selectorsReset(): void {
@@ -378,7 +395,7 @@ export class InstallLibrariesComponent implements OnInit, OnDestroy {
private resetDialog(): void {
this.group = '';
- this.query = '';
+ this.lib.name = '';
this.libSearch.setValue('');
this.isInstalled = false;
this.isInSelectedList = false;
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.model.ts
index 65896d3..b201904 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.model.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.model.ts
@@ -60,7 +60,7 @@ export class InstallLibrariesModel {
project_name: this.notebook.project,
exploratory_name: this.notebook.name,
group: group,
- start_with: query.slice(0, query.indexOf(':'))
+ start_with: query
};
if (this.computational_name)
lib_query.computational_name = this.computational_name;
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 2500caf..92a7349 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
@@ -49,6 +49,14 @@
&.action {
width: 140px;
+
+ &.install-btn{
+ margin-left: 0;
+ }
+
+ &.close-btn{
+ margin-right: 25px;
+ }
}
&.butt-success {
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 459f495..006bd60 100644
--- a/services/self-service/src/main/resources/webapp/src/styles.scss
+++ b/services/self-service/src/main/resources/webapp/src/styles.scss
@@ -141,7 +141,8 @@ mat-chip.mat-chip strong {
.failed,
.deleting,
.deleted,
-.invalid_version{
+.invalid_version,
+.installation_error{
color: #f1696e;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org