This is an automated email from the ASF dual-hosted git repository.

pingsutw 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 e8104e5  SUBMARINE-1171. Experiment artifacts ui
e8104e5 is described below

commit e8104e5935a0b15d7ccbb000650f2bfe90525ba0
Author: jeff-901 <[email protected]>
AuthorDate: Sun Jan 2 21:08:57 2022 +0800

    SUBMARINE-1171. Experiment artifacts ui
    
    ### What is this PR for?
    Add experiment artifacts in experiment info page
    
    ### What type of PR is it?
    Feature
    
    ### Todos
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-1171
    
    ### How should this be tested?
    
    ### Screenshots (if appropriate)
    ![experiemnt 
artifact](https://user-images.githubusercontent.com/54139205/147908260-6df0c64e-7c93-476c-9dfe-fc5510bc9e1e.png)
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? No
    
    Author: jeff-901 <[email protected]>
    
    Signed-off-by: Kevin <[email protected]>
    
    Closes #859 from jeff-901/SUBMARINE-1171 and squashes the following commits:
    
    9728a3a1 [jeff-901] add ui
---
 .../submarine/server/rest/ExperimentRestApi.java   | 21 ++++++++++++
 .../experiment-home/experiment-home.component.html | 11 -------
 .../experiment-home/experiment-home.component.ts   | 20 ------------
 .../artifacts/artifacts.component.html             | 22 +++++++++++++
 .../artifacts/artifacts.component.scss             | 26 +++++++++++++++
 .../artifacts/artifacts.component.ts               | 37 ++++++++++++++++++++++
 .../experiment-info/experiment-info.component.html |  9 ++++++
 .../experiment-info/experiment-info.component.ts   | 16 ++++++++++
 .../workbench/experiment/experiment.module.ts      |  2 ++
 .../src/app/services/experiment.service.ts         | 26 +++++++--------
 10 files changed, 146 insertions(+), 44 deletions(-)

diff --git 
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
 
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
index 76331a2..c0a3fba 100644
--- 
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
+++ 
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
@@ -49,6 +49,7 @@ import 
org.apache.submarine.server.api.experiment.ExperimentLog;
 import 
org.apache.submarine.server.api.experimenttemplate.ExperimentTemplateSubmit;
 import org.apache.submarine.server.api.spec.ExperimentSpec;
 import org.apache.submarine.server.response.JsonResponse;
+import org.apache.submarine.server.s3.Client;
 
 /**
  * Experiment Service REST API v1
@@ -57,6 +58,7 @@ import org.apache.submarine.server.response.JsonResponse;
 @Produces({MediaType.APPLICATION_JSON + "; " + RestConstants.CHARSET_UTF8})
 public class ExperimentRestApi {
   private ExperimentManager experimentManager = 
ExperimentManager.getInstance();
+  private Client minioClient = new Client();
 
   @VisibleForTesting
   public void setExperimentManager(ExperimentManager experimentManager) {
@@ -263,6 +265,25 @@ public class ExperimentRestApi {
   }
 
   @GET
+  @Path("/artifacts/{id}")
+  @Operation(summary = "List artifact paths by id",
+      tags = {"experiment"},
+      responses = {
+          @ApiResponse(description = "successful operation", content = 
@Content(
+              schema = @Schema(implementation = JsonResponse.class))),
+          @ApiResponse(responseCode = "404", description = "Experiment not 
found")})
+  public Response getArtifactPaths(@PathParam(RestConstants.ID) String id) {
+    try {
+      List<String> artifactPaths = minioClient.listArtifactByExperimentId(id);
+      return new 
JsonResponse.Builder<List<String>>(Response.Status.OK).success(true)
+          .result(artifactPaths).build();
+
+    } catch (SubmarineRuntimeException e) {
+      return parseExperimentServiceException(e);
+    }
+  }
+
+  @GET
   @Path("/tensorboard")
   @Operation(summary = "Get tensorboard's information",
       tags = {"experiment"},
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
index 9edbce6..3fa8ffb 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
@@ -34,17 +34,6 @@
       target="_blank"
       nzType="primary"
       style="margin: 0px 4px 0px 4px"
-      [nzLoading]="isMlflowLoading"
-      [href]="mlflowUrl"
-    >
-      <i nz-icon nzType="radar-chart"></i>
-      MLflow UI
-    </a>
-    <a
-      nz-button
-      target="_blank"
-      nzType="primary"
-      style="margin: 0px 4px 0px 4px"
       [nzLoading]="isTensorboardLoading"
       [href]="tensorboardUrl"
     >
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
index ce4ec24..e0a0de2 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
@@ -72,7 +72,6 @@ export class ExperimentHomeComponent implements OnInit {
 
     this.experimentService.emitInfo(null);
     this.getTensorboardInfo(1000, 50000);
-    this.getMlflowInfo(1000, 100000);
     this.onSwitchAutoReload();
   }
 
@@ -173,23 +172,4 @@ export class ExperimentHomeComponent implements OnInit {
         (err) => console.log(err)
       );
   }
-
-  getMlflowInfo(period: number, due: number) {
-    interval(period)
-      .pipe(
-        mergeMap(() => this.experimentService.getMlflowInfo()),
-        retryWhen((error) => error),
-        tap((x) => console.log(x)),
-        filter((res) => res.available),
-        take(1),
-        timeout(due)
-      )
-      .subscribe(
-        (res) => {
-          this.isMlflowLoading = !res.available;
-          this.mlflowUrl = res.url;
-        },
-        (err) => console.log(err)
-      );
-  }
 }
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.html
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.html
new file mode 100644
index 0000000..a083fe3
--- /dev/null
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.html
@@ -0,0 +1,22 @@
+<!--
+  ~ 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 id="showArtifactDiv">
+  <p style="white-space: nowrap;" *ngFor="let artifactPath of 
artifactPaths;">{{ artifactPath }}</p>
+</div>
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.scss
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.scss
new file mode 100644
index 0000000..7cee94d
--- /dev/null
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.scss
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#showArtifactDiv {
+  background-color: whitesmoke;
+  color: black;
+  padding: 10px;
+  height: 90vh;
+  overflow: auto;
+}
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.ts
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.ts
new file mode 100644
index 0000000..12e579b
--- /dev/null
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 { Component, Input, OnInit, SimpleChanges } from '@angular/core';
+
+@Component({
+  selector: 'submarine-artifacts',
+  templateUrl: './artifacts.component.html',
+  styleUrls: ['./artifacts.component.scss']
+})
+export class ArtifactsComponent implements OnInit {
+  @Input() artifactPaths;
+  @Input() experimentID;
+
+  constructor() {}
+
+  ngOnInit() {}
+
+  ngOnChanges(chg: SimpleChanges) {  
+  }
+}
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
index 147c833..e91679a 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
@@ -102,6 +102,10 @@
           <i nz-icon nzType="desktop" nzTheme="outline"></i>
           Outputs
         </li>
+        <li nz-menu-item (click)="currentState = 4">
+          <i nz-icon nzType="experiment" nzTheme="outline"></i>
+          Artifacts
+        </li>
       </ul>
     </nz-sider>
     <nz-layout>
@@ -119,6 +123,11 @@
           [experimentID]="experimentID"
           [podLogArr]="podLogArr"
         ></submarine-outputs>
+        <submarine-artifacts
+          *ngSwitchCase="4"
+          [artifactPaths]="artifactPaths"
+          [experimentID]="experimentID"
+        ></submarine-artifacts>
       </div>
     </nz-layout>
   </nz-layout>
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
index 8e1bf8f..d4b2d73 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
@@ -38,6 +38,7 @@ export class ExperimentInfoComponent implements OnInit {
   podLogArr;
   paramData;
   metricData;
+  artifactPaths;
 
   constructor(
     private router: Router,
@@ -78,6 +79,7 @@ export class ExperimentInfoComponent implements OnInit {
     );
 
     this.getExperimentPod();
+    this.getExperimentArtifactPaths();
     this.experimentService.emitInfo(this.experimentID);
   }
 
@@ -123,6 +125,20 @@ export class ExperimentInfoComponent implements OnInit {
       );
   }
 
+  getExperimentArtifactPaths() {
+    this.experimentService
+      .getExperimentArtifactPaths(this.experimentID)
+      .subscribe(
+        (result) => {
+          this.artifactPaths = result;
+        },
+        (err) => {
+          this.nzMessageService.error('Cannot load artifact paths of ' + 
this.experimentID);
+          console.log(err);
+        }
+      );
+  }
+
   onDeleteExperiment() {
     this.experimentService.deleteExperiment(this.experimentID).subscribe(
       () => {
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
index d6bd0da..2f3ff4e 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
@@ -32,6 +32,7 @@ import { HyperParamsComponent } from 
'./experiment-info/hyper-params/hyper-param
 import { MetricsComponent } from './experiment-info/metrics/metrics.component';
 import { ChartsComponent } from './experiment-info/charts/charts.component';
 import { OutputsComponent } from './experiment-info/outputs/outputs.component';
+import { ArtifactsComponent } from 
'./experiment-info/artifacts/artifacts.component';
 import { ExperimentHomeComponent } from 
'./experiment-home/experiment-home.component';
 import { ExperimentService } from '@submarine/services/experiment.service';
 import { ExperimentFormComponent } from 
'./experiment-home/experiment-form/experiment-form.component';
@@ -59,6 +60,7 @@ import { ExperimentCustomizedFormComponent } from 
'./experiment-home/experiment-
     MetricsComponent,
     ChartsComponent,
     OutputsComponent,
+    ArtifactsComponent,
     ExperimentHomeComponent,
     ExperimentFormComponent,
     ExperimentPredefinedFormComponent,
diff --git 
a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts 
b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
index 5916052..56969b9 100644
--- a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
+++ b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
@@ -173,6 +173,19 @@ export class ExperimentService {
     );
   }
 
+  getExperimentArtifactPaths(id: string): Observable<any> {
+    const apiUrl = this.baseApi.getRestApi('/v1/experiment/artifacts/' + id);
+    return this.httpClient.get<Rest<any>>(apiUrl).pipe(
+      switchMap((res) => {
+        if (res.success) {
+          return of(res.result);
+        } else {
+          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 
'get', id);
+        }
+      })
+    );
+  }
+
   fetchExperimentTemplateList(): Observable<ExperimentTemplate[]> {
     const apiUrl = this.baseApi.getRestApi('/v1/template');
     return this.httpClient.get<Rest<ExperimentTemplate[]>>(apiUrl).pipe(
@@ -265,19 +278,6 @@ export class ExperimentService {
     );
   }
 
-  getMlflowInfo(): Observable<MlflowInfo> {
-    const apiUrl = this.baseApi.getRestApi('/v1/experiment/mlflow');
-    return this.httpClient.get<Rest<MlflowInfo>>(apiUrl).pipe(
-      switchMap((res) => {
-        if (res.success) {
-          return of(res.result);
-        } else {
-          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 
'get');
-        }
-      })
-    );
-  }
-
   durationHandle(secs: number) {
     const hr = Math.floor(secs / 3600);
     const min = Math.floor((secs - hr * 3600) / 60);

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to