[helix-front] Enable/Disable clusters

Project: http://git-wip-us.apache.org/repos/asf/helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/helix/commit/28d1a2f8
Tree: http://git-wip-us.apache.org/repos/asf/helix/tree/28d1a2f8
Diff: http://git-wip-us.apache.org/repos/asf/helix/diff/28d1a2f8

Branch: refs/heads/master
Commit: 28d1a2f8a8303bf418409d312f6cec943780e6e7
Parents: bf181da
Author: Vivo Xu <v...@linkedin.com>
Authored: Fri Sep 8 11:40:57 2017 -0700
Committer: Junkai Xue <j...@linkedin.com>
Committed: Mon Nov 6 17:07:41 2017 -0800

----------------------------------------------------------------------
 helix-front/client/app/app-routing.module.ts    |  4 ---
 .../cluster-detail.component.html               | 33 +++++++++---------
 .../cluster-detail.component.scss               | 13 ++++++++
 .../cluster-detail/cluster-detail.component.ts  | 35 ++++++++++++++++++--
 .../app/cluster/shared/cluster.resolver.ts      |  2 ++
 .../app/cluster/shared/cluster.service.ts       | 10 ++++++
 .../config-detail/config-detail.component.html  |  8 ++---
 .../config-detail/config-detail.component.ts    |  7 ++--
 .../instance-detail.component.html              | 12 +++----
 .../instance-detail.component.scss              |  6 ----
 .../instance-list/instance-list.component.html  |  1 +
 .../instance-list/instance-list.component.ts    |  9 +++--
 .../resource-list.component.spec.ts             | 15 ++++++++-
 .../resource-list/resource-list.component.ts    | 22 +++++++-----
 .../workflow-list/workflow-list.component.html  |  3 ++
 .../workflow-list/workflow-list.component.scss  |  3 ++
 .../workflow-list/workflow-list.component.ts    | 20 +++++------
 17 files changed, 137 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/app-routing.module.ts
----------------------------------------------------------------------
diff --git a/helix-front/client/app/app-routing.module.ts 
b/helix-front/client/app/app-routing.module.ts
index 41c7c47..961bde5 100644
--- a/helix-front/client/app/app-routing.module.ts
+++ b/helix-front/client/app/app-routing.module.ts
@@ -4,7 +4,6 @@ import { RouterModule, Routes } from '@angular/router';
 import { AppComponent } from './app.component';
 import { NodeViewerComponent } from 
'./shared/node-viewer/node-viewer.component';
 import { ClusterComponent } from './cluster/cluster.component';
-import { ClusterResolver } from './cluster/shared/cluster.resolver';
 import { ClusterDetailComponent } from 
'./cluster/cluster-detail/cluster-detail.component';
 import { ConfigDetailComponent } from 
'./configuration/config-detail/config-detail.component';
 import { InstanceListComponent } from 
'./instance/instance-list/instance-list.component';
@@ -36,9 +35,6 @@ const HELIX_ROUTES: Routes = [
       {
         path: ':name',
         component: ClusterDetailComponent,
-        resolve: {
-          cluster: ClusterResolver
-        },
         children: [
           {
             path: '',

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.html
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.html 
b/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.html
index 835481d..4704417 100644
--- 
a/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.html
+++ 
b/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.html
@@ -1,31 +1,32 @@
 <section class="cluster-detail">
-  <section *ngIf="cluster">
+  <section *ngIf="clusterName">
     <md-toolbar class="mat-elevation-z1">
-      <hi-detail-header [cluster]="cluster.name"></hi-detail-header>
-      <md-icon
-        *ngIf="cluster.enabled"
-        color="primary">
-        check_circle
-      </md-icon>
-      <md-icon
-        *ngIf="!cluster.enabled"
-        color="warn"
-        mdTooltip="This cluster is paused.">
-        pause_circle_filled
-      </md-icon>
-      <md-toolbar-row class="information">
+      <hi-detail-header [cluster]="clusterName"></hi-detail-header>
+      <md-toolbar-row *ngIf="isLoading" class="information">
+        <md-spinner></md-spinner>
+      </md-toolbar-row>
+      <md-toolbar-row *ngIf="!isLoading" class="information">
         <h6>Controller:
           <a md-button color="accent" routerLink="controller">{{ 
cluster.controller }}</a>
         </h6>
+        <section *ngIf="!cluster.enabled">
+          <div class="offline">
+            This Cluster is currently DISABLED
+          </div>
+        </section>
         <span fxFlex="1 1 auto"></span>
         <button md-mini-fab *ngIf="can" [mdMenuTriggerFor]="menu">
           <md-icon>menu</md-icon>
         </button>
         <md-menu #menu="mdMenu">
-          <button md-menu-item disabled>
-            <md-icon>pause</md-icon>
+          <button md-menu-item *ngIf="cluster.enabled" 
(click)="disableCluster()">
+            <md-icon>not_interested</md-icon>
             <span>Disable this Cluster</span>
           </button>
+          <button md-menu-item *ngIf="!cluster.enabled" 
(click)="enableCluster()">
+            <md-icon>play_circle_outline</md-icon>
+            <span>Enable this Cluster</span>
+          </button>
           <button md-menu-item (click)="addInstance()">
             <md-icon>add</md-icon>
             <span>Add an Instance</span>

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.scss
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.scss 
b/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.scss
index e69de29..1da0a85 100644
--- 
a/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.scss
+++ 
b/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.scss
@@ -0,0 +1,13 @@
+@import 'client/theme.scss';
+
+.offline {
+  font-size: 14px;
+  padding-left: 24px;
+  color: mat-color($hi-warn);
+}
+
+.mat-spinner {
+  width: 30px;
+  height: 30px;
+  margin: 0 20px;
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.ts
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.ts 
b/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.ts
index 6333117..2f7b37f 100644
--- a/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.ts
+++ b/helix-front/client/app/cluster/cluster-detail/cluster-detail.component.ts
@@ -23,6 +23,8 @@ export class ClusterDetailComponent implements OnInit {
     { label: 'Configuration', link: 'configs' }
   ];
 
+  isLoading = false;
+  clusterName: string; // for better UX needs
   cluster: Cluster;
   can = false;
 
@@ -37,15 +39,26 @@ export class ClusterDetailComponent implements OnInit {
   }
 
   ngOnInit() {
-    this.route.data.subscribe(data => this.cluster = data.cluster);
     this.clusterService.can().subscribe(data => this.can = data);
     this.route.params
       .map(p => p.name)
       .subscribe(name => {
-        console.log(name);
+        this.clusterName = name;
+        this.loadCluster();
       });
   }
 
+  protected loadCluster() {
+    this.isLoading = true;
+    this.clusterService
+      .get(this.clusterName)
+      .subscribe(
+        data => this.cluster = data,
+        error => this.helperService.showError(error),
+        () => this.isLoading = false
+      );
+  }
+
   addInstance() {
     this.dialog
       .open(InputDialogComponent, {
@@ -88,6 +101,24 @@ export class ClusterDetailComponent implements OnInit {
       });
   }
 
+  enableCluster() {
+    this.clusterService
+      .enable(this.clusterName)
+      .subscribe(
+        () => this.loadCluster(),
+        error => this.helperService.showError(error)
+      );
+  }
+
+  disableCluster() {
+    this.clusterService
+      .disable(this.clusterName)
+      .subscribe(
+        () => this.loadCluster(),
+        error => this.helperService.showError(error)
+      );
+  }
+
   deleteCluster() {
     // disable delete function right now since it's too dangerous
     /*

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/cluster/shared/cluster.resolver.ts
----------------------------------------------------------------------
diff --git a/helix-front/client/app/cluster/shared/cluster.resolver.ts 
b/helix-front/client/app/cluster/shared/cluster.resolver.ts
index 51d6df5..c7c737a 100644
--- a/helix-front/client/app/cluster/shared/cluster.resolver.ts
+++ b/helix-front/client/app/cluster/shared/cluster.resolver.ts
@@ -4,6 +4,8 @@ import { Resolve, ActivatedRouteSnapshot } from 
'@angular/router';
 import { ClusterService } from './cluster.service';
 import { Cluster } from './cluster.model';
 
+/* not using this resolver for now since it will break the page when reload 
the page */
+
 @Injectable()
 export class ClusterResolver implements Resolve<Cluster> {
 

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/cluster/shared/cluster.service.ts
----------------------------------------------------------------------
diff --git a/helix-front/client/app/cluster/shared/cluster.service.ts 
b/helix-front/client/app/cluster/shared/cluster.service.ts
index fef409e..2244729 100644
--- a/helix-front/client/app/cluster/shared/cluster.service.ts
+++ b/helix-front/client/app/cluster/shared/cluster.service.ts
@@ -34,4 +34,14 @@ export class ClusterService extends HelixService {
     return this
       .delete(`/clusters/${ name }`);
   }
+
+  public enable(name: string) {
+    return this
+      .post(`/clusters/${ name }?command=enable`, null);
+  }
+
+  public disable(name: string) {
+    return this
+      .post(`/clusters/${ name }?command=disable`, null);
+  }
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/configuration/config-detail/config-detail.component.html
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/configuration/config-detail/config-detail.component.html
 
b/helix-front/client/app/configuration/config-detail/config-detail.component.html
index 1bbf564..7c053c5 100644
--- 
a/helix-front/client/app/configuration/config-detail/config-detail.component.html
+++ 
b/helix-front/client/app/configuration/config-detail/config-detail.component.html
@@ -1,8 +1,8 @@
-<section>
-
-  <!-- TODO vxu: implement loading -->
-
+<section fxLayout="column" fxLayoutAlign="center center">
+  <md-spinner *ngIf="isLoading"></md-spinner>
   <hi-node-viewer
+    *ngIf="!isLoading"
+    fxFlexFill
     [obj]="obj"
     [unlockable]="can && clusterName != null"
     (update)="updateConfig($event)"

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/configuration/config-detail/config-detail.component.ts
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/configuration/config-detail/config-detail.component.ts 
b/helix-front/client/app/configuration/config-detail/config-detail.component.ts
index 31591c2..66b53aa 100644
--- 
a/helix-front/client/app/configuration/config-detail/config-detail.component.ts
+++ 
b/helix-front/client/app/configuration/config-detail/config-detail.component.ts
@@ -53,11 +53,8 @@ export class ConfigDetailComponent implements OnInit {
             () => this.isLoading = false
           );
       } else {
-        this.route.parent.data
-          .subscribe(data => {
-            this.clusterName = data.cluster.name;
-            this.loadClusterConfig();
-          });
+        this.clusterName = this.route.parent.snapshot.params['name'];
+        this.loadClusterConfig();
       }
     }
 

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/instance/instance-detail/instance-detail.component.html
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/instance/instance-detail/instance-detail.component.html
 
b/helix-front/client/app/instance/instance-detail/instance-detail.component.html
index b0af27f..a1d89c4 100644
--- 
a/helix-front/client/app/instance/instance-detail/instance-detail.component.html
+++ 
b/helix-front/client/app/instance/instance-detail/instance-detail.component.html
@@ -9,14 +9,12 @@
         <hi-key-value-pair name="Session ID" 
prop="sessionId"></hi-key-value-pair>
         <hi-key-value-pair name="Helix Version" 
prop="helixVersion"></hi-key-value-pair>
       </hi-key-value-pairs>
-      <section *ngIf="!isLoading && !instance.liveInstance">
+      <section *ngIf="!isLoading && !instance.healthy">
         <div class="offline">
-          This Instance is currently offline.
-        </div>
-      </section>
-      <section *ngIf="!isLoading && !instance.enabled">
-        <div class="disabled">
-          This Instance is currently disabled.
+          This Instance is currently
+          <span *ngIf="!instance.liveInstance">OFFLINE</span>
+          <span *ngIf="!instance.liveInstance && !instance.enabled">and</span>
+          <span *ngIf="!instance.enabled">DISABLED</span>
         </div>
       </section>
       <span fxFlex="1 1 auto"></span>

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/instance/instance-detail/instance-detail.component.scss
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/instance/instance-detail/instance-detail.component.scss
 
b/helix-front/client/app/instance/instance-detail/instance-detail.component.scss
index 21c4df1..2b809df 100644
--- 
a/helix-front/client/app/instance/instance-detail/instance-detail.component.scss
+++ 
b/helix-front/client/app/instance/instance-detail/instance-detail.component.scss
@@ -1,4 +1,3 @@
-@import '~@angular/material/theming';
 @import 'client/theme.scss';
 
 .information {
@@ -15,9 +14,4 @@
     padding-left: 24px;
     color: mat-color($hi-warn);
   }
-
-  .disabled {
-    padding-left: 24px;
-    color: mat-color($hi-accent);
-  }
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/instance/instance-list/instance-list.component.html
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/instance/instance-list/instance-list.component.html 
b/helix-front/client/app/instance/instance-list/instance-list.component.html
index d76137f..192cc1a 100644
--- a/helix-front/client/app/instance/instance-list/instance-list.component.html
+++ b/helix-front/client/app/instance/instance-list/instance-list.component.html
@@ -7,6 +7,7 @@
     columnMode="force"
     [footerHeight]="rowHeight"
     [rows]="instances"
+    [loadingIndicator]="isLoading"
     selectionType="single"
     [sorts]="sorts"
     (select)="onSelect($event)">

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/instance/instance-list/instance-list.component.ts
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/instance/instance-list/instance-list.component.ts 
b/helix-front/client/app/instance/instance-list/instance-list.component.ts
index d03fe3b..748dbc6 100644
--- a/helix-front/client/app/instance/instance-list/instance-list.component.ts
+++ b/helix-front/client/app/instance/instance-list/instance-list.component.ts
@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
 import { Router, ActivatedRoute } from '@angular/router';
 
 import { InstanceService } from '../shared/instance.service';
+import { HelperService } from '../../shared/helper.service';
 
 @Component({
   selector: 'hi-instance-list',
@@ -10,6 +11,7 @@ import { InstanceService } from '../shared/instance.service';
 })
 export class InstanceListComponent implements OnInit {
 
+  isLoading = true;
   clusterName: string;
   instances: any[];
   rowHeight = 40;
@@ -21,7 +23,8 @@ export class InstanceListComponent implements OnInit {
   constructor(
     protected route: ActivatedRoute,
     protected router: Router,
-    protected service: InstanceService
+    protected service: InstanceService,
+    protected helper: HelperService
   ) { }
 
   ngOnInit() {
@@ -30,7 +33,9 @@ export class InstanceListComponent implements OnInit {
       this.service
         .getAll(this.clusterName)
         .subscribe(
-          data => this.instances = data
+          data => this.instances = data,
+          error => this.helper.showError(error),
+          () => this.isLoading = false
         );
     }
   }

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/resource/resource-list/resource-list.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/resource/resource-list/resource-list.component.spec.ts 
b/helix-front/client/app/resource/resource-list/resource-list.component.spec.ts
index 4da2399..24a3e61 100644
--- 
a/helix-front/client/app/resource/resource-list/resource-list.component.spec.ts
+++ 
b/helix-front/client/app/resource/resource-list/resource-list.component.spec.ts
@@ -5,19 +5,32 @@ import { RouterTestingModule } from '@angular/router/testing';
 
 import { ResourceListComponent } from './resource-list.component';
 import { ResourceService } from '../shared/resource.service';
+import { HelperService } from '../../shared/helper.service';
 
 describe('ResourceListComponent', () => {
   let component: ResourceListComponent;
   let fixture: ComponentFixture<ResourceListComponent>;
 
   beforeEach(async(() => {
+    // stub HelperService for test purpose
+    const helperServiceStub = {
+      showError: (message: string) => {},
+      showSnackBar: (message: string) => {}
+    };
+
     TestBed.configureTestingModule({
       imports: [
         HttpModule,
         RouterTestingModule
       ],
       declarations: [ ResourceListComponent ],
-      providers: [ ResourceService ],
+      providers: [
+        ResourceService,
+        {
+          provide: HelperService,
+          useValue: helperServiceStub
+        }
+      ],
       schemas: [
         /* avoid importing modules */
         NO_ERRORS_SCHEMA

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/resource/resource-list/resource-list.component.ts
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/resource/resource-list/resource-list.component.ts 
b/helix-front/client/app/resource/resource-list/resource-list.component.ts
index 3ba184c..4c72cf3 100644
--- a/helix-front/client/app/resource/resource-list/resource-list.component.ts
+++ b/helix-front/client/app/resource/resource-list/resource-list.component.ts
@@ -4,6 +4,7 @@ import { Router, ActivatedRoute } from '@angular/router';
 import { Resource } from '../shared/resource.model';
 import { ResourceService } from '../shared/resource.service';
 import { WorkflowService } from '../../workflow/shared/workflow.service';
+import { HelperService } from '../../shared/helper.service';
 import { Observable } from 'rxjs/Rx';
 import * as _ from 'lodash';
 
@@ -33,7 +34,8 @@ export class ResourceListComponent implements OnInit {
     private router: Router,
     private route: ActivatedRoute,
     private service: ResourceService,
-    private workflowService: WorkflowService
+    private workflowService: WorkflowService,
+    protected helper: HelperService
   ) { }
 
   ngOnInit() {
@@ -53,11 +55,12 @@ export class ResourceListComponent implements OnInit {
             () => this.isLoading = false
           );
       } else {
-        this.route.parent.data.subscribe(data => {
-          this.isLoading = true;
-          this.clusterName = data.cluster.name;
-          this.fetchResources();
-        });
+        this.route.parent.params
+          .map(p => p.name)
+          .subscribe(name => {
+            this.clusterName = name;
+            this.fetchResources();
+          });
       }
     }
   }
@@ -69,6 +72,9 @@ export class ResourceListComponent implements OnInit {
   protected fetchResources() {
     let jobs = [];
 
+    this.isLoading = true;
+    this.resources = null;
+
     this.workflowService
       .getAll(this.clusterName)
       .concatMap(workflows => Observable.from(workflows))
@@ -82,7 +88,7 @@ export class ResourceListComponent implements OnInit {
         list => {
           jobs = jobs.concat(list);
         },
-        error => console.log(error),
+        error => this.helper.showError(error),
         () => {
           this.service
             .getAll(this.clusterName)
@@ -90,7 +96,7 @@ export class ResourceListComponent implements OnInit {
               result => {
                 this.resources = _.differenceWith(result, jobs, (resource: 
Resource, name) => resource.name === name);
               },
-              error => console.log(error),
+              error => this.helper.showError(error),
               () => this.isLoading = false
             );
         }

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/workflow/workflow-list/workflow-list.component.html
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/workflow/workflow-list/workflow-list.component.html 
b/helix-front/client/app/workflow/workflow-list/workflow-list.component.html
index b0089cb..f3b642f 100644
--- a/helix-front/client/app/workflow/workflow-list/workflow-list.component.html
+++ b/helix-front/client/app/workflow/workflow-list/workflow-list.component.html
@@ -1,6 +1,9 @@
 <section fxLayout="column" fxLayoutAlign="center center">
   <md-spinner *ngIf="isLoading"></md-spinner>
   <section fxFlexFill>
+    <section *ngIf="!isLoading && workflows.length == 0" class="empty">
+      There's no workflow here.
+    </section>
     <md-nav-list>
       <a *ngFor="let name of workflows"
         md-list-item

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/workflow/workflow-list/workflow-list.component.scss
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/workflow/workflow-list/workflow-list.component.scss 
b/helix-front/client/app/workflow/workflow-list/workflow-list.component.scss
index e69de29..c9d208f 100644
--- a/helix-front/client/app/workflow/workflow-list/workflow-list.component.scss
+++ b/helix-front/client/app/workflow/workflow-list/workflow-list.component.scss
@@ -0,0 +1,3 @@
+.empty {
+  padding: 20px;
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/28d1a2f8/helix-front/client/app/workflow/workflow-list/workflow-list.component.ts
----------------------------------------------------------------------
diff --git 
a/helix-front/client/app/workflow/workflow-list/workflow-list.component.ts 
b/helix-front/client/app/workflow/workflow-list/workflow-list.component.ts
index 0824b17..08963d9 100644
--- a/helix-front/client/app/workflow/workflow-list/workflow-list.component.ts
+++ b/helix-front/client/app/workflow/workflow-list/workflow-list.component.ts
@@ -22,18 +22,16 @@ export class WorkflowListComponent implements OnInit {
 
   ngOnInit() {
     if (this.route.parent) {
-      this.route.parent.data.subscribe(data => {
-        this.isLoading = true;
-        this.clusterName = data.cluster.name;
+      this.isLoading = true;
+      this.clusterName = this.route.parent.snapshot.params['name'];
 
-        this.service
-          .getAll(this.clusterName)
-          .subscribe(
-            workflows => this.workflows = workflows,
-            error => console.log(error),
-            () => this.isLoading = false
-          );
-      });
+      this.service
+        .getAll(this.clusterName)
+        .subscribe(
+          workflows => this.workflows = workflows,
+          error => console.log(error),
+          () => this.isLoading = false
+        );
     }
   }
 

Reply via email to