| <!-- |
| ~ 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()">×</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'"> {{ item.version }}</span> |
| <strong> ({{ groupsListMap[item.group] }}) </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> |
| <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> |