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

liuxun 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 84ff600   SUBMARINE-383. Implement workspace in workbench-ng
84ff600 is described below

commit 84ff6000f1e3352edad3609d121f85942086f8dc
Author: jasoonn <[email protected]>
AuthorDate: Sat Feb 22 22:32:58 2020 +0800

     SUBMARINE-383. Implement workspace in workbench-ng
    
    ### What is this PR for?
    Implement frontend of workspace in workbench server with Angular.
    
    ### What type of PR is it?
    [Feature]
    
    ### Todos
    * [ ] - Task
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-383
    
    ### How should this be tested?
    
    
[Travis](https://travis-ci.org/apache/submarine/builds/653828441?utm_source=github_status&utm_medium=notification)
    
    ### Screenshots
    ![](https://i.imgur.com/n5x7UeO.gif)
    
    ### Questions:
    * Does the licenses files need update? No
    * Is there breaking changes for older versions? No
    * Does this needs documentation? No
    
    Author: jasoonn <[email protected]>
    
    Closes #186 from jasoonn/SUBMARINE-383 and squashes the following commits:
    
    7a67e4b [jasoonn] update minor error
    0f604ed [jasoonn] add newProject
    e5dddae [jasoonn] correcting css using
    8d65664 [jasoonn] revise TODO and coding stye
    6723891 [jasoonn] add e2e
    338caae [jasoonn] add lisence
    acd66fa [jasoonn] Add workspace frontend
---
 .../apache/submarine/integration/workspaceIT.java  |  96 +++++++++++
 .../app/pages/workbench/workbench.component.html   |   2 +-
 .../app/pages/workbench/workbench.component.scss   |   4 +
 .../src/app/pages/workbench/workbench.module.ts    |   9 +-
 .../new-project-page.component.html                | 184 +++++++++++++++++++++
 .../new-project-page.component.scss                |  81 +++++++++
 .../new-project-page/new-project-page.component.ts |  97 +++++++++++
 .../workspace/project/project.component.html       |  77 +++++++++
 .../project.component.scss}                        |  42 +++--
 .../workspace/project/project.component.ts         |  71 ++++++++
 .../workspace/release/release.component.html       |  49 ++++++
 .../release.component.scss}                        |  13 +-
 .../release.component.ts}                          |  13 +-
 .../workspace/shared/shared.component.html         |  49 ++++++
 .../shared.component.scss}                         |  13 +-
 .../shared.component.ts}                           |  15 +-
 .../team.component.html}                           |   5 +-
 .../team.component.scss}                           |   7 +-
 .../team.component.ts}                             |  12 +-
 .../workspace/training/training.component.html     |  56 +++++++
 .../training.component.scss}                       |  41 +++--
 .../training.component.ts}                         |  33 +++-
 .../workbench/workspace/workspace.component.html   |  42 ++++-
 .../workbench/workspace/workspace.component.scss   |   6 +
 .../workbench/workspace/workspace.component.ts     |  18 +-
 .../pages/workbench/workspace/workspace.module.ts  |  57 +++++++
 26 files changed, 1034 insertions(+), 58 deletions(-)

diff --git 
a/submarine-test/e2e/src/test/java/org/apache/submarine/integration/workspaceIT.java
 
b/submarine-test/e2e/src/test/java/org/apache/submarine/integration/workspaceIT.java
new file mode 100644
index 0000000..f292b7c
--- /dev/null
+++ 
b/submarine-test/e2e/src/test/java/org/apache/submarine/integration/workspaceIT.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+package org.apache.submarine.integration;
+
+import org.apache.submarine.AbstractSubmarineIT;
+import org.apache.submarine.WebDriverManager;
+import org.apache.submarine.SubmarineITUtils;
+import org.openqa.selenium.By;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class workspaceIT extends AbstractSubmarineIT {
+
+  public final static Logger LOG = LoggerFactory.getLogger(workspaceIT.class);
+
+  @BeforeClass
+  public static void startUp(){
+    driver =  WebDriverManager.getWebDriver();
+  }
+
+  @AfterClass
+  public static void tearDown(){
+    driver.quit();
+  }
+
+  @Test
+  public void workspaceNavigation() throws Exception {
+    // Login
+    LOG.info("Login");
+    pollingWait(By.cssSelector("input[ng-reflect-name='userName']"), 
MAX_BROWSER_TIMEOUT_SEC).sendKeys("admin");
+    pollingWait(By.cssSelector("input[ng-reflect-name='password']"), 
MAX_BROWSER_TIMEOUT_SEC).sendKeys("admin");
+    clickAndWait(By.cssSelector("button[class='login-form-button ant-btn 
ant-btn-primary']"));
+    pollingWait(By.cssSelector("a[routerlink='/workbench/dashboard']"), 
MAX_BROWSER_TIMEOUT_SEC);
+
+    // Routing to workspace
+    pollingWait(By.xpath("//span[contains(text(), \"Workspace\")]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    Assert.assertEquals(driver.getCurrentUrl(), 
"http://localhost:8080/workbench/workspace";);
+
+    //Test project part
+    pollingWait(By.xpath("//li[contains(text(), \"Project\")]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    Assert.assertEquals(pollingWait(By.xpath("//div[@id='addProjectbtn']"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+    pollingWait(By.xpath("//div[@id='addProjectbtn']/button"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    //step1
+    Assert.assertEquals(pollingWait(By.xpath("//form"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+    pollingWait(By.xpath("//input[@id='username']"), 
MAX_BROWSER_TIMEOUT_SEC).sendKeys("e2e test Project");
+    pollingWait(By.xpath("//textarea[@name='projectDescriptin']"), 
MAX_BROWSER_TIMEOUT_SEC).sendKeys("e2e test Project description");
+    pollingWait(By.xpath("//div[@class='centerDiv']/button"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    //step2
+    Assert.assertEquals(pollingWait(By.xpath("//nz-tabset"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+    pollingWait(By.xpath("//div[@class='centerDiv']/button[last()]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    //step3
+    Assert.assertEquals(pollingWait(By.xpath("//thead"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+    pollingWait(By.xpath("//div[@class='centerDiv']/button[last()-1]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    //return to project page
+    Assert.assertEquals(pollingWait(By.xpath("//div[@id='addProjectbtn']"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+
+
+    //Test release part
+    pollingWait(By.xpath("//li[contains(text(), \"Release\")]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    
Assert.assertEquals(pollingWait(By.xpath("//nz-table[@id='releaseTable']"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+
+    //Test training part
+    pollingWait(By.xpath("//li[contains(text(), \"Training\")]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    Assert.assertEquals(pollingWait(By.xpath("//div[@id='trainingDiv']"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+
+    //Test team part
+    pollingWait(By.xpath("//li[contains(text(), \"Team\")]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    Assert.assertEquals(pollingWait(By.xpath("//div[@id='teamDiv']"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+
+
+    // shared part
+    pollingWait(By.xpath("//li[contains(text(), \"Shared\")]"), 
MAX_BROWSER_TIMEOUT_SEC).click();
+    Assert.assertEquals(pollingWait(By.xpath("//nz-table[@id='sharedTable']"), 
MAX_BROWSER_TIMEOUT_SEC).isDisplayed(), true);
+    
+  }
+}
+
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.html
index 59dd8bd..36e84ba 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.html
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.html
@@ -74,7 +74,7 @@
       </div>
     </div>
   </nz-header>
-  <nz-content>
+  <nz-content id="workbenchContent">
     <router-outlet></router-outlet>
   </nz-content>
 </nz-layout>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.scss
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.scss
index 486c21f..5755429 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.scss
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.component.scss
@@ -105,3 +105,7 @@ nz-layout {
     max-width: calc(100% - 80px);
   }
 }
+
+#workbenchContent{
+  margin: 0;
+}
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.module.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.module.ts
index 801a07c..25609cd 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.module.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workbench.module.ts
@@ -29,6 +29,9 @@ import { JobComponent } from './job/job.component';
 import { ModelComponent } from './model/model.component';
 import { WorkbenchComponent } from './workbench.component';
 import { WorkspaceComponent } from './workspace/workspace.component';
+import { FormsModule } from '@angular/forms';
+import { WorkspaceModule } from './workspace/workspace.module';
+
 
 @NgModule({
   declarations: [
@@ -38,13 +41,15 @@ import { WorkspaceComponent } from 
'./workspace/workspace.component';
     InterpreterComponent,
     JobComponent,
     DataComponent,
-    ModelComponent
+    ModelComponent,
   ],
   imports: [
     CommonModule,
     WorkbenchRoutingModule,
     NgZorroAntdModule,
-    RouterModule
+    RouterModule,
+    FormsModule,
+    WorkspaceModule
   ]
 })
 export class WorkbenchModule {
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.html
new file mode 100644
index 0000000..6a8ffbd
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.html
@@ -0,0 +1,184 @@
+<!--
+  ~ 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.
+  -->
+
+<button nz-button nzType="primary" nzShape="circle" style="float:right;margin: 
15px;" (click)="clearProject()"><i nz-icon
+    nzType="close" nzTheme="outline"></i></button>
+<br>
+<h1 style="margin-left: 30px;"> Create New Project</h1>
+<div style="padding-left:300px;padding-right:300px;">
+  <nz-steps [nzCurrent]="current">
+    <nz-step nzTitle="Basic Information"></nz-step>
+    <nz-step nzTitle="Initial Project"></nz-step>
+    <nz-step nzTitle="Preview project"></nz-step>
+  </nz-steps>
+</div>
+
+<div [ngSwitch]="current">
+  <div *ngSwitchCase="0">
+    <form #f="ngForm">
+      <br>
+      <div>
+        <label class="form-label"><span class="red-star">* </span> Project 
Name:</label>
+        <input type="text" id="username" class="form-control" 
[(ngModel)]="newProjectContent.projectName"
+          name="username" required>
+      </div>
+      <div>
+        <label class="form-label"><span class="red-star">* 
</span>Description:</label>
+        <textarea rows="6" class="form-control" name="projectDescriptin" 
[(ngModel)]="newProjectContent.description"
+          required></textarea>
+      </div>
+      <div>
+        <label class="form-label"><span class="red-star">* 
</span>Visibility:</label>
+        <nz-radio-group name="visibility" 
[(ngModel)]="newProjectContent.visibility">
+          <label class="darkLabel" nz-radio nzValue="Private">Private - Only 
project collaborators can view or edit the
+            project.</label>
+          <label class="darkLabel" nz-radio nzValue="Team">Team - All members 
of the team can view the project.</label>
+          <div *ngIf="newProjectContent.visibility==='Team'"> 
+            <nz-select [(ngModel)]="newProjectContent.team" name="team" 
nzAllowClear nzPlaceHolder="Choose" style="margin-top: 10px;">
+              <nz-option *ngFor="let team of teams" [nzValue]="team" 
[nzLabel]="team"></nz-option>
+            </nz-select>
+          </div>
+          <label class="darkLabel" nz-radio nzValue="Public">Public - All 
authenticated users can view the
+            project.</label>
+        </nz-radio-group>
+      </div>
+      <div 
*ngIf="newProjectContent.visibility==='Team'||newProjectContent.visibility==='Public'">
+        <label class="form-label"><span class="red-star">* 
</span>Permission:</label>
+        <nz-radio-group name="permission" 
[(ngModel)]="newProjectContent.permission">
+          <label class="darkLabel" nz-radio nzValue="View">Can View - All 
members can view the project.</label>
+          <label class="darkLabel" nz-radio nzValue="Edit">Can Edit - All 
members can edit the project.</label>
+          <label class="darkLabel" nz-radio nzValue="Execute">Can Execute - 
All members can execute the project.</label>
+        </nz-radio-group>
+      </div>
+    </form>
+    <div class="centerDiv">
+      <br>
+      <button nz-button nzType="primary" [disabled]="!f.valid" 
(click)="current = current + 1">
+        Next Step
+      </button>
+    </div>
+  </div>
+  <div style="margin:20px;" *ngSwitchCase="1">
+    <nz-tabset [nzTabPosition]="'top'" [nzType]="'card'" 
[(nzSelectedIndex)]="initialState">
+
+      <nz-tab [nzTitle]="blank">
+        <div class="newBlank">
+          <h3 style="padding-top: 130px;">Create a blank project</h3>
+        </div>
+      </nz-tab>
+      <ng-template #blank> <i nz-icon nzType="file" nzTheme="outline"></i> 
Blank </ng-template>
+
+      <nz-tab [nzTitle]="template"> 
+        <nz-table
+          #rowSelectionTable
+          [nzPageSize]="5"
+          [nzData]="Templates"
+        >
+          <thead>
+            <tr>
+              <th
+                [(nzChecked)]="isAllDisplayDataChecked"
+                [nzIndeterminate]="isIndeterminate"
+              ></th>
+              <th>Type</th>
+              <th>Description</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr *ngFor="let data of rowSelectionTable.data">
+              <td
+                nzShowCheckbox
+                [(nzChecked)]="data.checked"
+                (nzCheckedChange)="refreshCheck(data)"
+              ></td>
+              <td>{{ data.type }}</td>
+              <td>{{ data.desciption }}</td>
+            </tr>
+          </tbody>
+        </nz-table>
+      </nz-tab>
+      <ng-template #template> <i nz-icon nzType="database" 
nzTheme="outline"></i> Template </ng-template>
+
+      <nz-tab [nzTitle]="upload">
+        <div id="newUpload"> 
+          <nz-upload
+            nzType="drag"
+            [nzMultiple]="true"
+            [nzLimit]="0"
+            nzAction="https://jsonplaceholder.typicode.com/posts/";
+            (nzChange)="handleChange($event)"
+            >
+            <p class="ant-upload-drag-icon">
+              <i nz-icon nzType="inbox"></i>
+            </p>
+            <p class="ant-upload-text">Click or drag file to this area to 
upload</p>
+            <p class="ant-upload-hint">
+              Support for a single or bulk upload. Strictly prohibit from 
uploading company data or other band files
+            </p>
+          </nz-upload>
+        </div>
+        
+      </nz-tab>
+      <ng-template #upload> <i nz-icon nzType="to-top" nzTheme="outline"></i> 
Upload </ng-template>
+      <nz-tab [nzTitle]="github" [nzDisabled]="true"> upload</nz-tab>
+      <ng-template #github> <i nz-icon nzType="github" 
nzTheme="outline"></i>Git Repo </ng-template>
+    </nz-tabset>
+
+    <div class="centerDiv">
+      <br *ngIf="initialState!==1">
+      <button nz-button nzType="default" (click)="current = current - 1">
+        Previous Step
+      </button>
+      <button nz-button nzType="primary" [disabled]="initialState===1 && 
!templateType" (click)="current = current + 1">
+        Next Step
+      </button>
+    </div>
+  </div>
+  <div *ngSwitchCase="2">
+    <h3 style="margin:30px;color: rgb(82, 82, 82);"><strong>Project 
Files</strong></h3>
+      <nz-table style="margin:30px;" nzBordered #basicTable 
[nzData]="newProjectContent.files" [nzNoResult]="'No data record'">
+        <thead>
+          <tr>
+            <th nzWidth="300px">Name</th>
+            <th nzWidth="40px">Size(KB)</th>
+            <th nzWidth="80px">Last Modified</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr *ngFor="let data of basicTable.data">
+            <td>{{ data.name }}</td>
+            <td>{{ data.size/1024 }}</td>
+            <td>{{ data.lastModifiedDate }}</td>
+          </tr>
+        </tbody>
+      </nz-table>
+      <div class="centerDiv">
+        <br>
+        <button nz-button nzType="default" (click)="current = current - 1" 
style="margin: 3px;">
+          Previous Step
+        </button>
+        <button nz-button nzType="primary" (click)="done()" style="margin: 
3px;">
+          Save
+        </button>
+        <button nz-button nzType="primary" (click)="openNotebook()" 
[disabled]="true" style="margin: 3px;">
+          Open in Notebook
+        </button>
+      </div>
+  </div>
+</div>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.scss
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.scss
new file mode 100644
index 0000000..8f797cc
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.scss
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+ 
+.form-label {
+    float:left;
+    width:150px;
+    text-align: right;
+    padding-right: 12px;
+    margin-top: 20px;
+    margin-left: 20%;
+    clear: left;
+    color: black;
+ }
+
+ label {
+    float: left;
+    margin-top: 20px;
+    clear: left;
+ }
+
+ .visibility {
+    float: left;
+    white-space: nowrap;
+    margin-top: 20px;
+ }
+
+ .darkLabel {
+    float: left;
+    margin-top: 20px;
+    color: black;
+ }
+
+ input, textarea{
+    margin-top: 20px;
+    width: 40%;
+ }
+ .red-star {
+    margin-top: 20px;
+    color: red;
+}
+
+input.ng-invalid.ng-touched {
+    border: 1px solid red;
+}
+
+textarea.ng-invalid.ng-touched {
+   border: 1px solid red;
+}
+
+.newBlank{
+   height: 280px;
+   width: 100%;
+   background-color:whitesmoke;
+   text-align: center;
+   vertical-align: middle;
+   align-items: center;
+}
+
+#newUpload{
+   height: 280px;
+}
+
+.centerDiv{
+   text-align: center;
+}
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.ts
new file mode 100644
index 0000000..cab477a
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/new-project-page/new-project-page.component.ts
@@ -0,0 +1,97 @@
+/*
+ * 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, OnInit, ViewChild, Output, EventEmitter, Input } from 
'@angular/core';
+import { NgForm } from '@angular/forms';
+import { NzMessageService } from 'ng-zorro-antd';
+
+
+@Component({
+  selector: 'app-new-project-page',
+  templateUrl: './new-project-page.component.html',
+  styleUrls: ['./new-project-page.component.scss']
+})
+export class NewProjectPageComponent implements OnInit {
+  @Output() closeProjectPage = new EventEmitter<boolean>();
+  @ViewChild('f', { static: true }) signupForm: NgForm;
+  //TODO(jasoonn): get team from API
+  teams = ['ciil'];
+  
+  current = 0;
+  initialState=0;
+  
+  templateType="Python";
+
+  
+  newProjectContent = { projectName: '', description: '', visibility: 
'Private', team: '' ,permission: 'View', files: []};
+  Templates = [
+    {type:'Python', description: 'Python Template', checked: true},
+    {type:'R', description: 'R Template', checked: false},
+    {type:'Spark', description: 'Spark Template', checked: false},
+    {type:'Tensorflow', description: 'Tensorflow Template', checked: false},
+    {type:'Pytorch', description: 'Pytorch Template', checked: false},
+  ];
+  
+
+  constructor(private msg: NzMessageService) { }
+
+  ngOnInit() {
+  }
+
+  handleChange({ file, fileList }): void {
+    const status = file.status;
+    if (status !== 'uploading') {
+      console.log(file, fileList);
+      console.log(this.newProjectContent.files)
+    }
+    if (status === 'done') {
+      this.msg.success(`${file.name} file uploaded successfully.`);
+      this.newProjectContent.files.push(file);
+    } else if (status === 'error') {
+      this.msg.error(`${file.name} file upload failed.`);
+    }
+  }
+
+
+  clearProject(){
+    this.closeProjectPage.emit(true);
+  }
+
+  refreshCheck(template){
+    if (template.checked === true){
+      this.Templates.forEach(function(item, index, array){
+        if (item.type !== template.type) array[index].checked = false;
+      });
+      this.templateType = template.type;
+    }
+    else this.templateType = "";
+
+  }
+
+  //TODO(jasoonn): Add the new project
+  done(): void{
+    console.log(this.newProjectContent);
+    this.clearProject();
+  }
+
+  //TODO(jasoonn): open in notebook
+  openNotebook() {
+    ;
+  }
+}
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.html
new file mode 100644
index 0000000..1aaa9b7
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.html
@@ -0,0 +1,77 @@
+<!--
+  ~ 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.
+  -->
+
+<br>
+<div *ngIf="!newProject">
+    <div id="addProjectbtn">
+        <button nz-button nzBlock (click)="newProject=true">+ Add New 
Project</button>
+    </div>
+    <div id="projectTagDiv">
+        <div nz-row [nzGutter]="12" nzType="flex" nzJustify="start">
+          <div *ngFor="let project of existProjects" nz-col [nzSpan]="8" 
id="projectDiv">
+            <nz-card [nzTitle]="project.projectName" [nzActions]="[actionEdit, 
actionDownload, actionSetting, actionDelete]">
+                <nz-tag *ngFor="let tag of project.tags" 
[nzMode]="'closeable'" (nzAfterClose)="handleCloseTag(project, tag)">{{ tag 
}}</nz-tag>
+                <nz-tag *ngIf="!project.inputTagVisibility" 
class="editable-tag" nzNoAnimation (click)="showInput(project)">
+                    <i nz-icon nzType="plus"></i> New Tag
+                </nz-tag>
+                <input
+                    #inputElement
+                    nz-input
+                    nzSize="small"
+                    *ngIf="project.inputTagVisibility"
+                    type="text"
+                    [(ngModel)]="project.projectInputTag"
+                    id="projectInputTag"
+                    (blur)="handleInputConfirm(project)"
+                    (keydown.enter)="handleInputConfirm(project)"
+                    />
+                <div>
+                    <br>
+                    {{ project.description}}
+                    <br>
+                    <br>
+                    <label>
+                        <i nz-icon nzType="star" nzTheme="outline"></i> 
&nbsp;{{ project.starNum }} &nbsp; | &nbsp;
+                        <i nz-icon nzType="like" nzTheme="outline"></i> &nbsp; 
{{ project.likeNum }} &nbsp; | &nbsp;
+                        <i nz-icon nzType="message" nzTheme="outline"></i> 
&nbsp; {{ project.msgNum }}
+                    </label>             
+                </div>
+                
+                <ng-template #actionEdit>
+                    <i nz-icon nzType="edit"></i>Edit
+                </ng-template>
+                <ng-template #actionDownload>
+                    <i nz-icon nzType="download"></i>Download
+                </ng-template>
+                <ng-template #actionSetting>
+                    <i nz-icon nzType="setting"></i>Setting
+                </ng-template>
+                <ng-template #actionDelete>
+                    <i nz-icon nzType="delete"></i>Delete
+                </ng-template>
+            </nz-card>
+          </div>
+        </div>
+    </div>
+</div>
+<div *ngIf="newProject" id="projectNewDivOuter">
+    <div  id="projectNewDivInner">
+        <app-new-project-page 
(closeProjectPage)="newProject=false;"></app-new-project-page>
+    </div>
+</div>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.scss
similarity index 63%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.scss
index 6da6c40..530cf06 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.scss
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -17,18 +17,36 @@
  * under the License.
  */
 
-import { Component, OnInit } from '@angular/core';
+.editable-tag {
+    background: rgb(255, 255, 255);
+    border-style: dashed;
+}
 
-@Component({
-  selector: 'submarine-workspace',
-  templateUrl: './workspace.component.html',
-  styleUrls: ['./workspace.component.scss']
-})
-export class WorkspaceComponent implements OnInit {
+#projectNewDivOuter{
+    background-color:whitesmoke;
+    padding-left: 15px;
+    padding-right: 15px
+ }
+ 
+ #projectNewDivInner{
+    background-color:white;
+    padding-left: 10px;
+    padding-right: 10px;
+ }
 
-  constructor() { }
+ #addProjectbtn{
+    padding-left: 30px;
+    padding-right: 30px;
+ }
 
-  ngOnInit() {
-  }
+ #projectTagDiv{
+   padding:30px;
+ }
 
-}
+ #projectInputTag{
+   width: 78px;
+ }
+
+ #projectDiv{
+   padding: 5px;
+ }
\ No newline at end of file
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.ts
new file mode 100644
index 0000000..02a6210
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/project/project.component.ts
@@ -0,0 +1,71 @@
+/*
+ * 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, OnInit, ViewChild, ElementRef } from '@angular/core';
+
+@Component({
+  selector: 'app-project',
+  templateUrl: './project.component.html',
+  styleUrls: ['./project.component.scss']
+})
+export class ProjectComponent implements OnInit {
+  newProject = false;
+  existProjects = [];
+
+  @ViewChild('inputElement', { static: false }) inputElement: ElementRef;
+
+  constructor() { }
+
+  //TODO(jasoonn): get projects data from server
+  ngOnInit() {
+    this.existProjects.push({
+      projectName: 'projectName0', description: 'description', tags: ['12', 
'Tag 2'], inputTagVisibility: false, projectInputTag: '', starNum:0, likeNum:0, 
msgNum:0
+    });
+    this.existProjects.push({
+      projectName: 'projectName1', description: 'description', tags: 
['Unremovable', 'Tag 2'], inputTagVisibility: false, projectInputTag: '', 
starNum:0, likeNum:0, msgNum:0
+    });
+    this.existProjects.push({
+      projectName: 'projectName1', description: 'description', tags: 
['Unremovable', 'Tag 2', 'Tag 3'], inputTagVisibility: false, projectInputTag: 
'', starNum:0, likeNum:0, msgNum:0
+    });
+    this.existProjects.push({
+      projectName: 'projectName1', description: 'description', tags: 
['Unremovable', 'Tag 2', 'Tag 3'], inputTagVisibility: false, projectInputTag: 
'', starNum:0, likeNum:0, msgNum:0
+    })
+  }
+  //TODO(jasoonn): Update tag in server
+  handleCloseTag(project, tag){
+    project.tags = project.tags.filter(itag => itag!==tag);
+    console.log(project);
+    console.log(tag);
+  }
+  //TODO(jasoonn): update tag in server
+  handleInputConfirm(project): void {
+    if (project.projectInputTag && 
project.tags.indexOf(project.projectInputTag) === -1) {
+      project.tags = [...project.tags, project.projectInputTag];
+    }
+    project.inputTagVisibility = false;
+    project.projectInputTag = '';
+  }
+
+  showInput(project): void {
+    project.inputTagVisibility = true;
+    setTimeout(() => {
+      this.inputElement.nativeElement.focus();
+    }, 10);
+  }
+}
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.html
new file mode 100644
index 0000000..e8ffded
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.html
@@ -0,0 +1,49 @@
+<!--
+  ~ 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.
+  -->
+
+<nz-input-group  id="releaseTextInput" [nzSuffix]="suffixIconSearch">
+    <input type="text" nz-input placeholder="input search text" />
+</nz-input-group>
+<ng-template #suffixIconSearch>
+    <i nz-icon nzType="search"></i>
+</ng-template>
+<nz-spin [nzSpinning]="isSpinning">
+    <nz-table id="releaseTable" nzBordered #basicTable [nzData]="dataSet" 
[nzNoResult]="'No data'">
+        <thead>
+          <tr>
+            <th nzWidth="60px">Name</th>
+            <th nzWidth="60px">Owner</th>
+            <th nzWidth="60px">Status</th>
+            <th nzWidth="60px">Commit Info</th>
+            <th nzWidth="60px">LastUpdated</th>
+            <th nzWidth="60px">Action</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr *ngFor="let data of basicTable.data">
+            <td>{{ data.name }}</td>
+            <td>{{ data.owner }}</td>
+            <td>{{ data.status }}</td>
+            <td>{{ data.commitInfo }}</td>
+            <td>{{ data.time }}</td>
+            <td>{{ data.action }}</td>
+          </tr>
+        </tbody>
+    </nz-table>
+</nz-spin>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.scss
similarity index 84%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.scss
index 3d56d22..01802f3 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.scss
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -16,3 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
+ #releaseTable{
+    margin-left:20px;
+    margin-right:20px;
+ }
+ 
+ #releaseTextInput{
+   width: 200px;
+   margin-top: 20px;
+   margin-left: 20px;
+ }
\ No newline at end of file
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.ts
similarity index 81%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.ts
index 6da6c40..93c64be 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/release/release.component.ts
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -20,12 +20,13 @@
 import { Component, OnInit } from '@angular/core';
 
 @Component({
-  selector: 'submarine-workspace',
-  templateUrl: './workspace.component.html',
-  styleUrls: ['./workspace.component.scss']
+  selector: 'app-release',
+  templateUrl: './release.component.html',
+  styleUrls: ['./release.component.scss']
 })
-export class WorkspaceComponent implements OnInit {
-
+export class ReleaseComponent implements OnInit {
+  isSpinning = true;
+  dataSet = [];
   constructor() { }
 
   ngOnInit() {
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.html
new file mode 100644
index 0000000..65c62e2
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.html
@@ -0,0 +1,49 @@
+<!--
+  ~ 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.
+  -->
+
+<nz-input-group  id="sharedSearchInput" [nzSuffix]="suffixIconSearch">
+    <input type="text" nz-input placeholder="input search text" />
+</nz-input-group>
+<ng-template #suffixIconSearch>
+    <i nz-icon nzType="search"></i>
+</ng-template>
+<nz-spin [nzSpinning]="isSpinning">
+    <nz-table id='sharedTable' nzBordered #basicTable [nzData]="dataSet" 
[nzNoResult]="'No data'">
+        <thead>
+          <tr>
+            <th nzWidth="60px">Name</th>
+            <th nzWidth="60px">Owner</th>
+            <th nzWidth="60px">Status</th>
+            <th nzWidth="60px">Commit Info</th>
+            <th nzWidth="60px">LastUpdated</th>
+            <th nzWidth="60px">Action</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr *ngFor="let data of basicTable.data">
+            <td>{{ data.name }}</td>
+            <td>{{ data.owner }}</td>
+            <td>{{ data.status }}</td>
+            <td>{{ data.commitInfo }}</td>
+            <td>{{ data.time }}</td>
+            <td>{{ data.action }}</td>
+          </tr>
+        </tbody>
+    </nz-table>
+</nz-spin>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.scss
similarity index 84%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.scss
index 3d56d22..dda2971 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.scss
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -16,3 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
+ #sharedTable{
+    margin-left:20px;
+    margin-right:20px;
+ }
+ 
+ #sharedSearchInput{
+   width: 200px;
+   margin-top: 20px;
+   margin-left: 20px;
+ }
\ No newline at end of file
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.ts
similarity index 82%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.ts
index 6da6c40..1ac3172 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/shared/shared.component.ts
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -16,16 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 import { Component, OnInit } from '@angular/core';
 
 @Component({
-  selector: 'submarine-workspace',
-  templateUrl: './workspace.component.html',
-  styleUrls: ['./workspace.component.scss']
+  selector: 'app-shared',
+  templateUrl: './shared.component.html',
+  styleUrls: ['./shared.component.scss']
 })
-export class WorkspaceComponent implements OnInit {
-
+export class SharedComponent implements OnInit {
+  isSpinning = true;
+  dataSet = [];
+  
   constructor() { }
 
   ngOnInit() {
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.html
similarity index 91%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.html
index a2d50dc..81aea24 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.html
@@ -17,4 +17,7 @@
   ~ under the License.
   -->
 
-<p>workspace works!</p>
+<div id="teamDiv">
+  <nz-spin [nzSpinning]="isSpinning">
+  </nz-spin>
+</div>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.scss
similarity index 95%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.scss
index 3d56d22..aca80fa 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.scss
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -16,3 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
+ #teamDiv{
+    margin:20px;
+ }
+ 
\ No newline at end of file
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.ts
similarity index 83%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.ts
index 6da6c40..7caf093 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/team/team.component.ts
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -20,12 +20,12 @@
 import { Component, OnInit } from '@angular/core';
 
 @Component({
-  selector: 'submarine-workspace',
-  templateUrl: './workspace.component.html',
-  styleUrls: ['./workspace.component.scss']
+  selector: 'app-team',
+  templateUrl: './team.component.html',
+  styleUrls: ['./team.component.scss']
 })
-export class WorkspaceComponent implements OnInit {
-
+export class TeamComponent implements OnInit {
+  isSpinning = true;
   constructor() { }
 
   ngOnInit() {
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.html
new file mode 100644
index 0000000..cedfac5
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.html
@@ -0,0 +1,56 @@
+<!--
+  ~ 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="trainingDiv">
+    <h3 class="leaveBothMargin">
+        Category:
+        <button *ngFor="let category of categories" nz-button 
[nzType]="category.enable ? 'primary' : 'default'" [nzSize]="'small'" 
(click)="category.enable = ! category.enable" class="leaveMargin">
+            {{ category.name }}
+        </button>
+    </h3>
+    <hr class="horizontal_dotted_line"/>
+    <h3 class="leaveBothMargin"> 
+        Owner:
+        <nz-select [(ngModel)]="tagValue" [nzSize]="size" nzMode="tags" 
nzPlaceHolder="Please select" id="trainingSearchTag">
+            <nz-option *ngFor="let option of listOfOption" 
[nzLabel]="option.label" [nzValue]="option.value"></nz-option>
+        </nz-select>
+        <button nz-button [nzType]="ownProcess ? 'primary' : 'default'" 
[nzSize]="'default'" class="leaveMargin" (click)="ownProcess=!ownProcess">
+            Myself
+        </button>
+    </h3>
+    
+    <hr class="horizontal_dotted_line"/>
+    <h3 class="leaveBothMargin">
+        Others: 
+        <label class="othersLabel">Active user:</label>
+        <nz-select [(ngModel)]="userSelectedValue" nzPlaceHolder="Choose" 
class="leaveMargin">
+            <nz-option nzValue="noLimit" nzLabel="No restriction"></nz-option>
+            <nz-option *ngFor="let activeUser of activeUsers" 
[nzValue]="activeUser" [nzLabel]="activeUser"></nz-option>
+        </nz-select>
+        <label class="othersLabel">Rating:</label>
+        <nz-select [(ngModel)]="ratingSelectedValue" nzPlaceHolder="Choose" 
class="leaveMargin">
+            <nz-option nzValue="noLimit" nzLabel="No restriction"></nz-option>
+            <nz-option *ngFor="let rating of ratings" [nzValue]="rating" 
[nzLabel]="rating"></nz-option>
+        </nz-select>
+    </h3>
+</div>
+<div id="spanningDiv">
+    <nz-spin [nzSpinning]="isSpinning">
+    </nz-spin>
+</div>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.scss
similarity index 65%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.scss
index 6da6c40..85d2b4c 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.scss
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -17,18 +17,37 @@
  * under the License.
  */
 
-import { Component, OnInit } from '@angular/core';
+.horizontal_dotted_line{
+  border-top: 2px dotted whitesmoke;
+  color:transparent;
+} 
 
-@Component({
-  selector: 'submarine-workspace',
-  templateUrl: './workspace.component.html',
-  styleUrls: ['./workspace.component.scss']
-})
-export class WorkspaceComponent implements OnInit {
+#trainingDiv{
+  margin: 30px;
+  padding: 10px;
+  background-color:white;
+}
+
+.leaveMargin{
+  margin-left: 10px;
+}
 
-  constructor() { }
+.leaveBothMargin{
+  margin: 10px;
+}
 
-  ngOnInit() {
-  }
+.othersLabel{
+  color: rgb(122, 114, 114);
+  margin-left: 40px;
+}
+
+#trainingSearchTag{
+  width: 400px;
+  margin-left: 10px;
+}
 
+#spanningDiv{
+  margin: 30px;
+  padding: 30px;
+  background-color:white;
 }
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.ts
similarity index 55%
copy from 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
copy to 
submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.ts
index 6da6c40..1aeec39 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/training/training.component.ts
@@ -1,4 +1,4 @@
-/*!
+/*
  * 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
@@ -20,15 +20,36 @@
 import { Component, OnInit } from '@angular/core';
 
 @Component({
-  selector: 'submarine-workspace',
-  templateUrl: './workspace.component.html',
-  styleUrls: ['./workspace.component.scss']
+  selector: 'app-training',
+  templateUrl: './training.component.html',
+  styleUrls: ['./training.component.scss']
 })
-export class WorkspaceComponent implements OnInit {
-
+export class TrainingComponent implements OnInit {
+  isSpinning = true;
   constructor() { }
 
+  categories = [
+    {name: "Category1", enable:false},
+    {name: "Category2", enable:false},
+    {name: "Category3", enable:false},
+    {name: "Category4", enable:false},
+    {name: "Category5", enable:false},
+    {name: "Category6", enable:false},
+    {name: "Category7", enable:false}
+  ];
+  ownProcess = false;
+  tagValue = ['a10', 'c12', 'tag'];
+  userSelectedValue = 'noLimit';
+  ratingSelectedValue = 'noLimit'
+  activeUsers = ["John", "Jason"];
+  ratings = ["Execellent", "Good", "Moderate"];
+  
   ngOnInit() {
+    
+  }
+
+  performChange(){
+    console.log('cool')
   }
 
 }
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
index a2d50dc..82b910f 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.html
@@ -17,4 +17,44 @@
   ~ under the License.
   -->
 
-<p>workspace works!</p>
+<nz-layout>
+  <nz-layout class="inner-layout">
+    <div id="workspaceOuter">
+      <nz-breadcrumb>
+        <nz-breadcrumb-item>
+          <a [routerLink]="['/', 'workbench', 'home']">Home</a>
+        </nz-breadcrumb-item>
+        <nz-breadcrumb-item>Workspace</nz-breadcrumb-item>
+      </nz-breadcrumb>
+      <br/>
+      <h2>Project</h2>
+      <nz-content>You can click on the project tree directory on the left and 
the project file list will be displayed on the right.</nz-content>
+      <br/>
+      <ul nz-menu nzMode="horizontal">
+        <li nz-menu-item nzSelected (click)="switchState('project')">
+          Project({{basicInfo.project}}) 
+        </li>
+        <li nz-menu-item (click)="switchState('release')">
+          Release({{basicInfo.release}})
+        </li>
+        <li nz-menu-item (click)="switchState('training')">
+          Training({{basicInfo.training}})
+        </li>
+        <li nz-menu-item (click)="switchState('team')">
+          Team({{basicInfo.team}})
+        </li>
+        <li nz-menu-item (click)="switchState('shared')">
+          Shared({{basicInfo.shared}})
+        </li>
+      </ul>
+    </div>
+    
+    <div [ngSwitch]="currentState">
+      <app-project *ngSwitchCase="'project'"></app-project>
+      <app-release *ngSwitchCase="'release'"></app-release>
+      <app-training *ngSwitchCase="'training'"></app-training>
+      <app-team *ngSwitchCase="'team'"></app-team>
+      <app-shared *ngSwitchCase="'shared'"></app-shared>
+    </div>
+  </nz-layout>
+</nz-layout>
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
index 3d56d22..f1a5ffb 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.scss
@@ -16,3 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
+ #workspaceOuter{
+    background-color: white;
+    padding-left: 30px;
+    padding-top: 20px;
+ }
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
index 6da6c40..66c3fe8 100644
--- 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.component.ts
@@ -17,18 +17,32 @@
  * under the License.
  */
 
-import { Component, OnInit } from '@angular/core';
-
+import { Component, OnInit, ViewChild } from '@angular/core';
 @Component({
   selector: 'submarine-workspace',
   templateUrl: './workspace.component.html',
   styleUrls: ['./workspace.component.scss']
 })
 export class WorkspaceComponent implements OnInit {
+  @ViewChild('project', {static: true}) signupForm: any;
+
+  basicInfo = {
+    project: 3,
+    release: 0,
+    training: 0,
+    team: 0,
+    shared: 0
+  };
+
+  currentState = 'project';
 
   constructor() { }
 
   ngOnInit() {
   }
 
+  switchState(state: string){
+    this.currentState = state;
+  }
+
 }
diff --git 
a/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.module.ts
 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.module.ts
new file mode 100644
index 0000000..3ee851b
--- /dev/null
+++ 
b/submarine-workbench/workbench-web-ng/src/app/pages/workbench/workspace/workspace.module.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ComponentsModule } from '@submarine/components/components.module';
+import { NgZorroAntdModule } from 'ng-zorro-antd';
+import { ProjectComponent } from './project/project.component';
+import { ReleaseComponent } from './release/release.component';
+import { TrainingComponent } from './training/training.component';
+import { TeamComponent } from './team/team.component';
+import { SharedComponent } from './shared/shared.component';
+import { FormsModule } from '@angular/forms';
+import { NewProjectPageComponent } from 
'./project/new-project-page/new-project-page.component';
+
+@NgModule({
+    declarations: [
+      ProjectComponent,
+      ReleaseComponent,
+      TrainingComponent,
+      TeamComponent,
+      SharedComponent,
+      NewProjectPageComponent
+    ],
+    imports: [
+      CommonModule,
+      ComponentsModule,
+      NgZorroAntdModule,
+      FormsModule
+    ],
+    exports: [
+      ProjectComponent,
+      ReleaseComponent,
+      TrainingComponent,
+      TeamComponent,
+      SharedComponent,
+      NewProjectPageComponent
+    ]
+  })
+  export class WorkspaceModule {
+  }


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

Reply via email to