diff --git a/.gitignore b/.gitignore
index 01489d7dbc..6730398a01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -99,7 +99,7 @@ src/frontend/assets/logo.png
src/frontend/assets/login-bg.jpg
src/frontend/app/custom.module.ts
src/frontend/app/custom-import.module.ts
-src/frontend/app/custom
+# src/frontend/app/custom
src/frontend/assets/custom
src/frontend/sass/custom
src/frontend/index.html
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.html b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.html
new file mode 100644
index 0000000000..8e6e973e4e
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.html
@@ -0,0 +1,13 @@
+
+
+
+ Summary of {{title}} Usage for Last {{period}} in {{unit}}
+
+
+
+
+
+
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.scss b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.spec.ts b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.spec.ts
new file mode 100644
index 0000000000..4f0dd97dd0
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { KubernetesNodeMetricStatsCardComponent } from './kubernetes-node-metric-stats-card.component';
+
+describe('KubernetesNodeMetricStatsCardComponent', () => {
+ let component: KubernetesNodeMetricStatsCardComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ KubernetesNodeMetricStatsCardComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(KubernetesNodeMetricStatsCardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.ts b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.ts
new file mode 100644
index 0000000000..173eda9355
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metric-stats-card/kubernetes-node-metric-stats-card.component.ts
@@ -0,0 +1,50 @@
+import { Component, Input, OnInit, OnDestroy } from '@angular/core';
+import { Observable, of as observableOf, Subscription } from 'rxjs';
+import { KubernetesNodeService, KubeNodeMetric } from '../../../services/kubernetes-node.service';
+import { MetricStatistic } from '../../../store/kube.types';
+import { IMetrics } from '../../../../../store/types/base-metric.types';
+
+@Component({
+ selector: 'app-kubernetes-node-metric-stats-card',
+ templateUrl: './kubernetes-node-metric-stats-card.component.html',
+ styleUrls: ['./kubernetes-node-metric-stats-card.component.scss']
+})
+export class KubernetesNodeMetricStatsCardComponent implements OnInit, OnDestroy {
+
+ @Input()
+ title = 'Memory';
+
+ @Input()
+ metric: KubeNodeMetric;
+
+ @Input()
+ period = 'Hour';
+
+ @Input()
+ unit: string;
+
+ max$: Observable;
+ mean$: Observable;
+ subscriptions: Subscription[] = [];
+ constructor(
+ public kubeNodeService: KubernetesNodeService
+ ) {
+
+ }
+
+ ngOnInit() {
+
+ const maxMetric = this.kubeNodeService.setupMetricObservable(this.metric, MetricStatistic.MAXIMUM);
+ this.subscriptions.push(maxMetric.pollerSub);
+ this.max$ = maxMetric.entity$;
+
+ const meanMetric = this.kubeNodeService.setupMetricObservable(this.metric, MetricStatistic.AVERAGE);
+ this.subscriptions.push(meanMetric.pollerSub);
+ this.mean$ = meanMetric.entity$;
+ }
+
+
+ ngOnDestroy() {
+ this.subscriptions.forEach(s => s.unsubscribe());
+ }
+}
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.html b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.html
new file mode 100644
index 0000000000..fc9dce0d55
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.html
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.scss b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.scss
new file mode 100644
index 0000000000..6f307dd37a
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.scss
@@ -0,0 +1,8 @@
+.kubernetes-node-metrics-chart{
+ padding-top: 40px;
+ width: 100%;
+ &__content{
+ width: 100%;
+ height: 300px;
+ }
+}
\ No newline at end of file
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.spec.ts b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.spec.ts
new file mode 100644
index 0000000000..8cf90af5ac
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { KubernetesNodeMetricsChartComponent } from './kubernetes-node-metrics-chart.component';
+
+describe('KubernetesNodeMetricsChartComponent', () => {
+ let component: KubernetesNodeMetricsChartComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ KubernetesNodeMetricsChartComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(KubernetesNodeMetricsChartComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.ts b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.ts
new file mode 100644
index 0000000000..051cdf89e5
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-metrics-chart/kubernetes-node-metrics-chart.component.ts
@@ -0,0 +1,66 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import { MetricsConfig } from '../../../../../shared/components/metrics-chart/metrics-chart.component';
+import { MetricsLineChartConfig } from '../../../../../shared/components/metrics-chart/metrics-chart.types';
+import { IMetricMatrixResult } from '../../../../../store/types/base-metric.types';
+import { IMetricApplication } from '../../../../../store/types/metric.types';
+import { MetricsChartHelpers } from '../../../../../shared/components/metrics-chart/metrics.component.helpers';
+import { FetchKubernetesMetricsAction } from '../../../store/kubernetes.actions';
+
+@Component({
+ selector: 'app-kubernetes-node-metrics-chart',
+ templateUrl: './kubernetes-node-metrics-chart.component.html',
+ styleUrls: ['./kubernetes-node-metrics-chart.component.scss']
+})
+export class KubernetesNodeMetricsChartComponent implements OnInit {
+
+ @Input()
+ private nodeName: string;
+ @Input()
+ private endpointGuid: string;
+ @Input()
+ private yAxisLabel: string;
+ @Input()
+ private metricName: string;
+ @Input()
+ private seriesTranslation: string;
+ @Input()
+ public title: string;
+
+ public instanceChartConfig: MetricsLineChartConfig;
+ public instanceMetricConfig: MetricsConfig>;
+ constructor() { }
+
+ private buildChartConfig() {
+ const lineChartConfig = new MetricsLineChartConfig();
+ lineChartConfig.xAxisLabel = 'Time';
+ lineChartConfig.yAxisLabel = this.yAxisLabel;
+ lineChartConfig.showLegend = false;
+ return lineChartConfig;
+ }
+
+ ngOnInit() {
+ this.instanceChartConfig = this.buildChartConfig();
+ const query = `${this.metricName}{instance="${this.nodeName}"}[1h]&time=${(new Date()).getTime() / 1000}`;
+ this.instanceMetricConfig = {
+ getSeriesName: result => result.metric.name ? result.metric.name : result.metric.id,
+ mapSeriesItemName: MetricsChartHelpers.getDateSeriesName,
+ sort: MetricsChartHelpers.sortBySeriesName,
+ mapSeriesItemValue: this.getmapSeriesItemValue(),
+ metricsAction: new FetchKubernetesMetricsAction(
+ this.nodeName,
+ this.endpointGuid,
+ query,
+ ),
+ };
+ }
+
+ private getmapSeriesItemValue() {
+ switch (this.seriesTranslation) {
+ case 'mb':
+ return (bytes) => bytes / 1000000;
+ default:
+ return undefined;
+ }
+ }
+}
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.html b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.html
new file mode 100644
index 0000000000..f9cd0fdebd
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.html
@@ -0,0 +1,9 @@
+
+
+ {{ key }}
+
+
+ {{ value }}
+
+
+
\ No newline at end of file
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.scss b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.spec.ts b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.spec.ts
new file mode 100644
index 0000000000..86c56f3d38
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { KubernetesNodeSimpleMetricComponent } from './kubernetes-node-simple-metric.component';
+
+describe('KubernetesNodeSimpleMetricComponent', () => {
+ let component: KubernetesNodeSimpleMetricComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ KubernetesNodeSimpleMetricComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(KubernetesNodeSimpleMetricComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.ts b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.ts
new file mode 100644
index 0000000000..f6bbd0ba85
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/kubernetes-node/kubernetes-node-metrics/kubernetes-node-simple-metric/kubernetes-node-simple-metric.component.ts
@@ -0,0 +1,21 @@
+import { Component, OnInit, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-kubernetes-node-simple-metric',
+ templateUrl: './kubernetes-node-simple-metric.component.html',
+ styleUrls: ['./kubernetes-node-simple-metric.component.scss']
+})
+export class KubernetesNodeSimpleMetricComponent implements OnInit {
+
+ @Input()
+ key: string;
+
+ @Input()
+ value: number;
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.html b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.html
new file mode 100644
index 0000000000..23d4887bdc
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.html
@@ -0,0 +1,7 @@
+
+
+ {{ icons[condition][0] }}
+ {{ titles[condition] }}
+
+
+
diff --git a/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.scss b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.scss
new file mode 100644
index 0000000000..76e109dfbb
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.scss
@@ -0,0 +1,14 @@
+.kube-node-condition {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin-right: 20px;
+ padding-top: 20px;
+ &__title{
+ display: flex;
+ justify-content: center;
+ &__span{
+ margin-left: 10px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.spec.ts b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.spec.ts
new file mode 100644
index 0000000000..b227d5678a
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { KubernetesNodeConditionComponent } from './kubernetes-node-condition.component';
+
+describe('KubernetesNodeConditionComponent', () => {
+ let component: KubernetesNodeConditionComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ KubernetesNodeConditionComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(KubernetesNodeConditionComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.ts b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.ts
new file mode 100644
index 0000000000..af366214e5
--- /dev/null
+++ b/src/frontend/app/custom/kubernetes/list-types/kubernetes-nodes/kubernetes-node-summary/kubernetes-node-condition-card/kubernetes-node-condition/kubernetes-node-condition.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { ConditionType, Condition } from '../../../../../store/kube.types';
+import { KubernetesNodeService } from '../../../../../services/kubernetes-node.service';
+import { map, filter } from 'rxjs/operators';
+import { Observable } from 'rxjs';
+
+@Component({
+ selector: 'app-kubernetes-node-condition',
+ templateUrl: './kubernetes-node-condition.component.html',
+ styleUrls: ['./kubernetes-node-condition.component.scss']
+})
+export class KubernetesNodeConditionComponent implements OnInit {
+
+
+ @Input()
+ condition: ConditionType;
+ condition$: Observable;
+
+ public titles = {
+ 'Ready': 'Ready',
+ 'OutOfDisk': 'Out of Disk',
+ 'MemoryPressure': 'Memory Pressure',
+ 'DiskPressure': 'Disk Pressure'
+ };
+
+ public icons = {
+ 'Ready': ['done_outline', 'material-icons'],
+ 'OutOfDisk': ['storage', 'stratos-icons'],
+ 'MemoryPressure': ['memory', 'material-icons'],
+ 'DiskPressure': ['storage', 'stratos-icons'],
+ };
+
+ constructor(
+ public kubeNodeService: KubernetesNodeService
+ ) { }
+
+ ngOnInit() {
+
+ this.condition$ = this.kubeNodeService.node$.pipe(
+ filter(p => !!p && !!p.entity),
+ map(p => p.entity.status.conditions),
+ map(conditions => conditions.filter(o => o.type === this.condition)[0])
+ );
+ }
+}