This is an automated email from the ASF dual-hosted git repository.
jiwq pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git
The following commit(s) were added to refs/heads/master by this push:
new 23bf9c2 SUBMARINE-587. [WEB]The list of notebook instances
23bf9c2 is described below
commit 23bf9c2eca61d306008040f2bcaf7178ef955f49
Author: kobe860219 <[email protected]>
AuthorDate: Fri Aug 21 16:00:21 2020 +0800
SUBMARINE-587. [WEB]The list of notebook instances
### What is this PR for?
Update notebook page of workbench to list all of the notebook instances in
the given namespace.
First screenshot is show the page that list notebook by namespaces.
Second screenshot is the Restful result of `/v1/notebook`
The .gif use mock data to test and show this feature.
And I fix error name of environment file.
### What type of PR is it?
[Feature]
### Todos
* [ ] - Task
### What is the Jira issue?
https://issues.apache.org/jira/browse/SUBMARINE-587
### How should this be tested?
https://travis-ci.org/github/kobe860219/submarine/builds/720220622
### Screenshots (if appropriate)
<img width="1440" alt="截圖 2020-08-21 下午3 58 47"
src="https://user-images.githubusercontent.com/48027290/90960149-34e66180-e4d2-11ea-8cba-635ab76552b9.png">
<img width="1148" alt="截圖 2020-08-22 下午11 21 19"
src="https://user-images.githubusercontent.com/48027290/90960155-3a43ac00-e4d2-11ea-8251-de07a65c32f3.png">

### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No
Author: kobe860219 <[email protected]>
Closes #387 from kobe860219/SUBMARINE-587 and squashes the following
commits:
8967a97 [kobe860219] SUBMARINE-587. [WEB]The list of notebook instances
---
.../src/app/interfaces/environment-info.ts | 2 +-
.../{environment-spce.ts => environment-spec.ts} | 0
.../{environment-spce.ts => notebook-info.ts} | 22 ++++---
.../{environment-spce.ts => notebook-spec.ts} | 26 ++++++--
.../workbench/notebook/notebook.component.html | 48 +++++---------
.../pages/workbench/notebook/notebook.component.ts | 77 +++++++++++++---------
.../src/app/services/notebook.service.ts | 47 +++++++++++++
7 files changed, 143 insertions(+), 79 deletions(-)
diff --git
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-info.ts
b/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-info.ts
index 1e13d70..80ba127 100644
---
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-info.ts
+++
b/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-info.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { EnvironmentSpec } from '@submarine/interfaces/environment-spce';
+import { EnvironmentSpec } from '@submarine/interfaces/environment-spec';
export class Environment {
environmentId: string;
diff --git
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
b/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spec.ts
similarity index 100%
copy from
submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
copy to
submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spec.ts
diff --git
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
b/submarine-workbench/workbench-web-ng/src/app/interfaces/notebook-info.ts
similarity index 76%
copy from
submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
copy to submarine-workbench/workbench-web-ng/src/app/interfaces/notebook-info.ts
index bfe702f..fbd39f7 100644
---
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
+++ b/submarine-workbench/workbench-web-ng/src/app/interfaces/notebook-info.ts
@@ -16,15 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-export interface KernelSpec {
- name: string;
- channels: string[];
- dependencies: string[];
-}
-export interface EnvironmentSpec {
- description: string;
- dockerImage: string;
- image: string;
- kernelSpec: KernelSpec;
+import { Url } from 'url';
+import { NotebookSpec } from '@submarine/interfaces/notebook-spec';
+
+export class Notebook {
+ notebookId: string;
+ name: string;
+ uid: string;
+ url: Url;
+ status: string;
+ createdTime: string;
+ deletedTime: string;
+ spec: NotebookSpec;
}
diff --git
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
b/submarine-workbench/workbench-web-ng/src/app/interfaces/notebook-spec.ts
similarity index 76%
rename from
submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
rename to
submarine-workbench/workbench-web-ng/src/app/interfaces/notebook-spec.ts
index bfe702f..1648d2d 100644
---
a/submarine-workbench/workbench-web-ng/src/app/interfaces/environment-spce.ts
+++ b/submarine-workbench/workbench-web-ng/src/app/interfaces/notebook-spec.ts
@@ -16,15 +16,29 @@
* specific language governing permissions and limitations
* under the License.
*/
-export interface KernelSpec {
+
+export class NotebookSpec {
+ meta: Meta;
+ environment: Environment;
+ spec: Spec;
+}
+
+export class Meta {
name: string;
- channels: string[];
- dependencies: string[];
+ namespace: string;
}
-export interface EnvironmentSpec {
- description: string;
+export class Environment {
+ name: string;
dockerImage: string;
+ kernelSpec: string;
+ description: string;
image: string;
- kernelSpec: KernelSpec;
+}
+
+export class Spec {
+ envVars: {
+ TEST_ENV: string;
+ };
+ resources: string;
}
diff --git
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.html
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.html
index 2c98b7e..cce4926 100644
---
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.html
+++
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.html
@@ -16,6 +16,7 @@
~ specific language governing permissions and limitations
~ under the License.
-->
+
<nz-layout style="margin: -24px -24px 16px;">
<nz-layout class="inner-layout">
<div id="notebookOuter">
@@ -39,12 +40,12 @@
<div nz-row>
<div nz-col nzSpan="12">
<label style="font-size: large; color: black;">Namespaces :</label>
- <nz-select style="margin-left: 5px; width: 240px;"
[(ngModel)]="currentNamespaces">
- <nz-option
- *ngFor="let namespaces of namespacesList"
- [nzValue]="namespaces"
- [nzLabel]="namespaces"
- ></nz-option>
+ <nz-select
+ style="margin-left: 5px; width: 240px;"
+ [(ngModel)]="currentNamespace"
+ (ngModelChange)="switchNamespace($event)"
+ >
+ <nz-option *ngFor="let namespace of namespacesList"
[nzValue]="namespace" [nzLabel]="namespace"></nz-option>
</nz-select>
</div>
<div nz-col nzSpan="12" align="right">
@@ -65,20 +66,18 @@
</div>
</div>
<div>
- <nz-table style="padding-top: 5px;" #basicTable [nzData]="notebookList">
+ <nz-table style="padding-top: 5px;" #basicTable [nzData]="notebookTable">
<thead>
<tr>
<th>
<label nz-checkbox [(ngModel)]="checked"
(ngModelChange)="selectAllNotebook()"></label>
</th>
- <th nzWidth="120px">Status</th>
<th>Name</th>
- <th>Age</th>
<th>Environment</th>
- <th>CPU</th>
- <th>GPU</th>
- <th>Memory</th>
- <th>Action</th>
+ <th>Docker Image</th>
+ <th>Resources</th>
+ <th>Status</th>
+ <th>Environment</th>
</tr>
</thead>
<tbody>
@@ -87,28 +86,15 @@
<label nz-checkbox [(ngModel)]="checkedList[i]"></label>
</td>
<td>
- <nz-tag [nzColor]="statusColor[data.status]">{{ data.status
}}</nz-tag>
- </td>
- <td>
<a>{{ data.name }}</a>
</td>
- <td>{{ data.age }}</td>
- <td>{{ data.environment }}</td>
- <td>{{ data.cpu }}</td>
- <td>{{ data.gpu }}</td>
- <td>{{ data.memory }}</td>
+ <td>{{ data.spec.environment.name }}</td>
+ <td>{{ data.spec.environment.dockerImage }}</td>
<td>
- <a nz-dropdown [nzDropdownMenu]="menu">
- More
- <i nz-icon nzType="down"></i>
- </a>
- <nz-dropdown-menu #menu="nzDropdownMenu">
- <ul nz-menu nzSelectable>
- <li nz-menu-item (click)="runNotebook(data)">Run</li>
- <li nz-menu-item (click)="stopNotebook(data)">Stop</li>
- </ul>
- </nz-dropdown-menu>
+ {{ data.spec.spec.resources }}
</td>
+ <td>{{ data.status }}</td>
+ <td>{{ data.spec.environment.name }}</td>
</tr>
</tbody>
</nz-table>
diff --git
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.ts
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.ts
index 712b914..c427ff1 100644
---
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.ts
+++
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/notebook/notebook.component.ts
@@ -19,6 +19,7 @@
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
+import { NotebookService } from '@submarine/services/notebook.service';
@Component({
selector: 'submarine-notebook',
@@ -38,33 +39,15 @@ export class NotebookComponent implements OnInit {
// New notebook(form)
notebookForm: FormGroup;
- // Mock Data
- namespacesList = ['namespaces1', 'namespaces2'];
- currentNamespaces = this.namespacesList[0];
- notebookList = [
- {
- status: 'Running',
- name: 'Notebook1',
- age: '35 mins',
- environment: 'image1',
- cpu: '2',
- gpu: '1',
- memory: '512 MB',
- volumes: 'volumes1'
- },
- {
- status: 'Stop',
- name: 'Notebook2',
- age: '40 mins',
- environment: 'image2',
- cpu: '4',
- gpu: '4',
- memory: '1024 MB',
- volumes: 'volumes2'
- }
- ];
+ // Namesapces
+ namespacesList = [];
+ currentNamespace;
+
+ // Notebook list
+ notebookList;
+ notebookTable;
- constructor() {}
+ constructor(private notebookService: NotebookService) {}
statusColor: { [key: string]: string } = {
Running: 'green',
@@ -74,16 +57,38 @@ export class NotebookComponent implements OnInit {
ngOnInit() {
this.notebookForm = new FormGroup({
notebookName: new FormControl(null, [Validators.required]),
- namespaces: new FormControl(this.currentNamespaces,
[Validators.required]),
+ namespaces: new FormControl(this.currentNamespace,
[Validators.required]),
environment: new FormControl('env1', [Validators.required]),
cpu: new FormControl(null, [Validators.required]),
gpu: new FormControl(null, [Validators.required]),
memory: new FormControl(null, [Validators.required])
});
- this.checkedList = [];
- for (let i = 0; i < this.notebookList.length; i++) {
- this.checkedList.push(false);
- }
+
+ this.fetchNotebookList();
+ }
+
+ fetchNotebookList() {
+ this.notebookService.fetchNotebookList().subscribe((list) => {
+ this.notebookList = list;
+ this.checkedList = [];
+ for (let i = 0; i < this.notebookList.length; i++) {
+ this.checkedList.push(false);
+ }
+ // Get namespaces
+ this.notebookList.forEach((element) => {
+ if (this.namespacesList.indexOf(element.spec.meta.namespace) < 0) {
+ this.namespacesList.push(element.spec.meta.namespace);
+ }
+ });
+ // Set default namespace and table
+ this.currentNamespace = this.namespacesList[0];
+ this.notebookTable = [];
+ this.notebookList.forEach((item) => {
+ if (item.spec.meta.namespace == this.currentNamespace) {
+ this.notebookTable.push(item);
+ }
+ });
+ });
}
selectAllNotebook() {
@@ -92,6 +97,16 @@ export class NotebookComponent implements OnInit {
}
}
+ switchNamespace(namespace: string) {
+ this.notebookTable = [];
+ this.notebookList.forEach((item) => {
+ if (item.spec.meta.namespace == namespace) {
+ this.notebookTable.push(item);
+ }
+ });
+ console.log(this.notebookTable);
+ }
+
// TODO(kobe860219): Make a notebook run
runNotebook(data) {
data.status = 'Running';
diff --git
a/submarine-workbench/workbench-web-ng/src/app/services/notebook.service.ts
b/submarine-workbench/workbench-web-ng/src/app/services/notebook.service.ts
new file mode 100644
index 0000000..3b54db9
--- /dev/null
+++ b/submarine-workbench/workbench-web-ng/src/app/services/notebook.service.ts
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Rest } from '@submarine/interfaces';
+import { BaseApiService } from '@submarine/services/base-api.service';
+import { of, throwError, Observable } from 'rxjs';
+import { catchError, map, switchMap } from 'rxjs/operators';
+import { Notebook } from '@submarine/interfaces/notebook-info';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class NotebookService {
+ constructor(private baseApi: BaseApiService, private httpClient: HttpClient)
{}
+
+ fetchNotebookList() {
+ const apiUrl = this.baseApi.getRestApi('/v1/notebook');
+ return this.httpClient.get<Rest<Notebook>>(apiUrl).pipe(
+ switchMap((res) => {
+ if (res.success) {
+ console.log(res.result);
+ return of(res.result);
+ } else {
+ throw this.baseApi.createRequestError(res.message, res.code, apiUrl,
'get');
+ }
+ })
+ );
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]