blob: 9954a91739ec40c6aaaaf8e224bfda5ab8bf0cf6 [file] [log] [blame]
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<div class="install-libraries" id="dialog-box" [ngStyle]="notebook?.status !== 'running' && {'padding-bottom': '20px'}">
<header class="dialog-header">
<h4 class="modal-title">Manage <span>{{ notebook?.name }}</span> Libraries</h4>
<button type="button" class="close" (click)="dialogRef.close()">&times;</button>
</header>
<mat-progress-bar *ngIf="autoComplete === 'UPDATING'" mode="indeterminate"></mat-progress-bar>
<div class="dialog-content">
<div class="aligner">
<div class="info" *ngIf="notebook?.status !== 'running'">
<p class=" message">Cannot install libraries: Exploratory
<strong>{{ notebook?.name }}</strong> is not running</p>
</div>
<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 DataLab loads list of available groups for your resource...</p>
<img src="assets/img/gif-spinner.gif" alt="loading">
</div>
</div>
<div *ngIf="notebook?.status === 'running' && !uploading" class="lib-view-wrap">
<div class="search-box">
<div class="search-form">
<div>
<div class="control-group constol-select">
<label class="label">Select resource</label>
<div class="control">
<dropdown-list #resourceSelect (selectedItem)="onUpdate($event)" (emitClick)="emitClick()"></dropdown-list>
</div>
</div>
<div class="control-group control-select">
<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>
</div>
</div>
</div>
<div class="m-top-20" *ngIf="group !== 'java'; else javaGroup">
<div class="control-group constol-select">
<label class="label">Library name</label>
<div class="control control-relative">
<span class="other-message" *ngIf="group === 'others'">
Other group can include libs from Python 2 and Python 3 groups.
Some libs cannot be installed due to Python 2 is no longer supported
</span>
<input
type="text" [placeholder]="'Enter library name'"
[disabled]="!group"
[matAutocomplete]="auto"
[formControl]="libSearch"
#trigger="matAutocompleteTrigger"
(keydown.enter)="addLibrary(lib)"
(keyup)="clearLibSelection($event)"
class="library-input"
>
</div>
<mat-autocomplete #auto="matAutocomplete" class="suggestions scrolling">
<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:lib.name"></span>
</a>
<span *ngIf="item.isInSelectedList">{{ item.name }}</span>
<strong *ngIf="item.isInSelectedList">selected
<i class="material-icons">done</i>
</strong>
<strong *ngIf="item.isInstalled && !item.isInSelectedList">installed
<i class="material-icons">done</i>
</strong>
</div>
</mat-option>
</ng-template>
<mat-option *ngIf="!filteredList?.length && !validity_format && autoComplete === 'ENABLED' && lib.name?.length > 0" disabled>
<span class="configuring">No matches found</span>
</mat-option>
<mat-option *ngIf="validity_format?.length > 0 && autoComplete === 'ENABLED'">
<span class="configuring" >{{ validity_format }}</span >
</mat-option>
<mat-option *ngIf="autoComplete === 'NONE' && lib.name?.length > 1" disabled>
<span class="configuring" >Autocomplete is currently unavailable for {{groupsListMap[group]}} group</span >
</mat-option>
<mat-option *ngIf="autoComplete === 'UPDATING' && lib.name?.length > 1" disabled>
<span class="configuring" >Library list is being loaded at the moment. Please wait...</span>
</mat-option>
</mat-autocomplete>
</div>
<div class="control-group control-select">
<label class="label">Library version</label>
<div class="control control-relative">
<input
type="text"
class="library-input"
[placeholder]="'Enter library version (optional)'"
[(ngModel)]="lib.version"
[disabled]="!lib.name?.trim() || lib.name?.trim().length < 2"
(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="plus-icon"
[ngClass]="{'not-allow': lib.name?.trim().length < 2
|| (autoComplete === 'ENABLED' && !isLibSelected && filteredList?.length)
|| this.selectedLib?.isInSelectedList || isVersionInvalid || autoComplete === 'UPDATING'}"
[matTooltip]="this.selectedLib?.isInSelectedList ? 'Library is in selected list' : 'Please select library from autocomplete'"
matTooltipPosition="above" [matTooltipDisabled]="(!this.selectedLib?.isInSelectedList && isLibSelected) || lib.name?.length < 2 || !this.selectedLib?.isInSelectedList && autoComplete === 'NONE'"
>
<mat-icon
(click)="addLibrary(lib)"
[ngClass]="{'not-allowed': lib.name?.trim().length < 2 || (autoComplete === 'ENABLED' && !isLibSelected && filteredList?.length)
|| this.selectedLib?.isInSelectedList || isVersionInvalid || autoComplete === 'UPDATING'}">add</mat-icon>
</span>
</div>
</div>
</div>
<ng-template #javaGroup>
<div class="m-top-20">
<div class="control-group constol-select java-library-search">
<label class="label">Library</label>
<div class="control control-relative">
<input
type="text" [placeholder]="'Enter library name in <groupId>:<artifactId>:<versionId> format'"
class="library-input"
[disabled]="!group"
[matAutocomplete]="auto"
[formControl]="libSearch"
#trigger="matAutocompleteTrigger"
(keydown.enter)="addLibrary(lib)"
(keyup)="clearLibSelection($event)"
>
<span
class="plus-icon"
[ngClass]="{'not-allow': !this.selectedLib || this.selectedLib?.isInSelectedList || !isLibSelected}"
matTooltip="Library is in selected list" matTooltipPosition="above" [matTooltipDisabled]="!this.selectedLib?.isInSelectedList || !isLibSelected"
>
<mat-icon (click)="addLibrary(lib)" (keyup.enter)="addLibrary(lib)" [ngClass]="{'not-allowed': !this.selectedLib || this.selectedLib?.isInSelectedList || !isLibSelected}">add</mat-icon>
</span>
</div>
<mat-autocomplete #auto="matAutocomplete" class="suggestions">
<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:item.name">
<span>{{ item.version }}</span>
</span>
</a>
<span *ngIf="item.isInSelectedList">{{ item.name }}
<span *ngIf="item.version && item.version !== 'N/A'">{{ item.version }}</span>
</span>
<strong *ngIf="item.isInSelectedList">selected
<i class="material-icons">done</i>
</strong>
<strong *ngIf="item.isInstalled && !item.isInSelectedList">installed
<i class="material-icons">done</i>
</strong>
</div>
</mat-option>
</ng-template>
<mat-option *ngIf="model.isEmpty(filteredList) && !validity_format">
<span class="configuring">No matches found</span>
</mat-option>
<mat-option *ngIf="validity_format?.length > 0">
<span class="configuring" >{{ validity_format }}</span >
</mat-option>
</mat-autocomplete>
</div>
</div>
</ng-template>
<div class="search">
<div class="list-selected list-container scrolling">
<mat-chip-list *ngIf="model.selectedLibs.length && libs_uploaded" [disabled]="true">
<mat-chip *ngFor="let item of model.selectedLibs">
{{ item.name }}
<span *ngIf="item.version && item.version !== 'N/A'">&nbsp;{{ item.version }}</span>
<strong>&nbsp;({{ groupsListMap[item.group] }})&nbsp;</strong>
<a class="material-icons" (click)="removeSelectedLibrary(item)">clear</a>
</mat-chip>
</mat-chip-list>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="libs-info">
<mat-list class="scrolling" [ngStyle]="notebook?.status !== 'running' && {'max-height': '60vh', 'height': 'unset'}">
<mat-list-item class="list-header">
<div class="lib-name">Name
<button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
<i class="material-icons">
<span>more_vert</span>
</i>
</button></div>
<div class="lib-group">Group
<button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
<i class="material-icons">
<span>more_vert</span>
</i>
</button>
</div>
<div class="lib-destination"><span class="">Destination</span>
<button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
<i class="material-icons">
<span>more_vert</span>
</i>
</button>
</div>
<div class="lib-resource-type">Resource type
<button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
<i class="material-icons">
<span>more_vert</span>
</i>
</button>
</div>
<div class="lib-status"><span>Status</span>
<button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
<i class="material-icons">
<span>more_vert</span>
</i>
</button>
</div>
</mat-list-item>
<ng-container *ngIf="filtered" >
<mat-list-item class="filter-row">
<th class="lib-name filter-col">
<input
placeholder="Filter by library name"
[value]="filterModel.name"
(input)="onFilterNameUpdate($event.target['value'])"
type="text"
class="form-control filter-field"
/>
</th>
<th class="lib-group filter-col">
<multi-select-dropdown
(selectionChange)="onFilterUpdate($event)"
[items]="this.filterConfiguration.group"
[type]="'group'"
[model]="this.filterModel.group"
>
</multi-select-dropdown>
</th>
<th class="lib-destination filter-col">
<multi-select-dropdown
(selectionChange)="onFilterUpdate($event)"
[items]="this.filterConfiguration.resource"
[type]="'resource'"
[model]="this.filterModel.resource"
>
</multi-select-dropdown>
</th>
<th class="lib-resource-type filter-col">
<multi-select-dropdown
(selectionChange)="onFilterUpdate($event)"
[items]="this.filterConfiguration.resource_type"
[type]="'resource_type'"
[model]="this.filterModel.resource_type"
>
</multi-select-dropdown>
</th>
<th class="lib-status filter-col">
<multi-select-dropdown
(selectionChange)="onFilterUpdate($event)"
[items]="this.filterConfiguration.status"
[type]="'status'"
[model]="this.filterModel.status"
>
</multi-select-dropdown>
</th>
<ng-container matColumnDef="action-filter" stickyEnd>
<th>
<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(true)" [disabled]="isFilterChanged">
<i class="material-icons" [ngClass]="{'not-allowed': filterModel['length'] === 0}">done</i>
</button>
</div>
</th>
</ng-container>
</mat-list-item>
</ng-container>
<div class="scrollingList" id="scrolling" *ngIf="notebookLibs?.length">
<!-- <div *ngIf="notebook?.status !== 'running' && notebookFailedLibs.length > 0" class="info message">-->
<!-- <p>Cannot retry to reinstall failed libraries: Exploratory {{ notebook?.name }} is not running</p>-->
<!-- </div>-->
<ng-container *ngFor="let lib of filtredNotebookLibs">
<mat-list-item class="table-item">
<div class="lib-name lib-name-col ellipsis" >
<span [matTooltip]="lib.name + ' ' + lib.version" matTooltipPosition="above" class="lib-name-wrapper ellipsis">
<span class="stong" >{{ lib.name }}</span>&nbsp;
<span *ngIf="lib.version && lib.version !== 'N/A'">{{ lib.version }}</span>
</span>
</div>
<div class="lib-group-col">{{ groupsListMap[lib.group] }}</div>
<div class="st-group">
<ng-template let-item ngFor [ngForOf]="lib.filteredStatus">
<div class="wrap-col">
<div class="lib-destination-col">{{ item.resource }}</div>
<div class="lib-resource-type-col uppercase">{{ item.resourceType }}</div>
<div class="lib-status-col uppercase" ngClass="{{ item.status.toLowerCase() || 'installation_error' }}">{{ item.status.replace('_', ' ') }}
<div class="warn-action" *ngIf="(item.status === 'installation_error' || item.status.toLowerCase() === 'invalid_version' || item.add_pkgs?.length) && notebook?.status === 'running'">
<div *ngIf="!item.available_versions">
<span *ngIf="!installingInProgress && item.status === 'installation_error'" (click)="reinstallLibrary(item, lib)" matTooltip="Retry installation" matTooltipPosition="above">
<i class="material-icons">replay</i>
</span>
<span class="not-allow" *ngIf="installingInProgress && item.status === 'installation_error'" matTooltip="Please wait until lib installation completes"
matTooltipPosition="above">
<i class="material-icons not-allowed">replay</i>
</span>
</div>
<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"
(click)="openLibInfo(item, 'available');$event.stopPropagation()"
matTooltip="Show available version" matTooltipPosition="above"
>
<i class="material-icons">error_outline</i>
</div>
<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>
</ng-template>
</div>
</mat-list-item>
</ng-container>
</div>
<div *ngIf="!notebookLibs?.length" class="scrollingList info message">
<p>You have no libraries installed</p>
</div>
<div *ngIf="!filtredNotebookLibs.length && notebookLibs?.length" class="scrollingList info message">
<p>No matches found</p>
</div>
</mat-list>
</div>
<div class="m-top-15 actions" *ngIf="!uploading && notebook?.status === 'running'">
<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>
</div>