To apply the shared module into the kafka page

Issue-ID: DCAEGEN2-2010
Signed-off-by: Ekko Chang <ekko.chang@qct.io>
Change-Id: I830dcc1094d8e70045e0c0744f13f6a7b83d7cc1
diff --git a/components/datalake-handler/admin/src/src/app/app.module.ts b/components/datalake-handler/admin/src/src/app/app.module.ts
index ddc0c10..e15876a 100644
--- a/components/datalake-handler/admin/src/src/app/app.module.ts
+++ b/components/datalake-handler/admin/src/src/app/app.module.ts
@@ -105,6 +105,7 @@
 import { MatTabsModule } from "@angular/material";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 import { TopicModalComponent } from "./views/topics/topic-list/topic-modal/topic-modal.component";
+import { KafkaModalComponent } from './views/kafka/kafka-list/kafka-modal/kafka-modal.component';
 
 @NgModule({
   declarations: [
@@ -151,7 +152,8 @@
     ModalToolsComponent,
     ToolAddModalComponent,
     IconComponent,
-    TopicModalComponent
+    TopicModalComponent,
+    KafkaModalComponent
   ],
   imports: [
     BrowserModule,
@@ -195,7 +197,8 @@
     EditKafkaModalComponent,
     ToolAddModalComponent,
     ModalToolsComponent,
-    TopicModalComponent
+    TopicModalComponent,
+    KafkaModalComponent
   ]
 })
 export class AppModule {}
diff --git a/components/datalake-handler/admin/src/src/app/core/models/kafka.model.ts b/components/datalake-handler/admin/src/src/app/core/models/kafka.model.ts
index 34f283f..2b1803f 100644
--- a/components/datalake-handler/admin/src/src/app/core/models/kafka.model.ts
+++ b/components/datalake-handler/admin/src/src/app/core/models/kafka.model.ts
@@ -15,20 +15,21 @@
 */
 
 export class Kafka {
-  id: number;
-  name: string;
-  enabled: boolean;
-  brokerList: string;
-  zooKeeper: string;
-  group: string;
-  secure: boolean;
-  login: string;
-  pass: string;
-  securityProtocol: string;
-  includedTopic: string;
-  excludedTopic: string;
-  consumerCount: number;
-  timeout: number;
+  public id: number;
+  public name: string;
+  public enabled: boolean;
+  public brokerList: string;
+  public zooKeeper: string;
+  public group: string;
+  public secure: boolean;
+  public login: string;
+  public pass: string;
+  public securityProtocol: string;
+  public includedTopic: string;
+  public excludedTopic: string;
+  public consumerCount: number;
+  public timeout: number;
   // for UI display
-  checkedToSave: boolean;
+  public checkedToSave: boolean;
+  public iconPath: string;
 }
diff --git a/components/datalake-handler/admin/src/src/app/core/services/admin.service.ts b/components/datalake-handler/admin/src/src/app/core/services/admin.service.ts
index 8e126a0..307f51e 100644
--- a/components/datalake-handler/admin/src/src/app/core/services/admin.service.ts
+++ b/components/datalake-handler/admin/src/src/app/core/services/admin.service.ts
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP : DataLake
  * ================================================================================
- * Copyright 2019 QCT
+ * Copyright 2019 - 2020 QCT
  *=================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,4 +47,11 @@
   onKeyPressNumber(data: any) {
     return (data.target.value = data.target.value.replace(/[^0-9.]/g, ""));
   }
+
+  onKeyPressSymbol(data: any) {
+    return (data.target.value = data.target.value.replace(
+      /[~`!#$%\^&*+=\-\[\]\\';,/{}()|\\":<>\?@.]/g,
+      ""
+    ));
+  }
 }
diff --git a/components/datalake-handler/admin/src/src/app/core/services/rest-api.service.ts b/components/datalake-handler/admin/src/src/app/core/services/rest-api.service.ts
index 98eef9a..83d814e 100644
--- a/components/datalake-handler/admin/src/src/app/core/services/rest-api.service.ts
+++ b/components/datalake-handler/admin/src/src/app/core/services/rest-api.service.ts
@@ -339,35 +339,27 @@
       .pipe(retry(1), catchError(this.handleError));
   }
 
-  getAllKafkaList(): Observable<any> {
-    return this.http
-      .get<any>(prefix + "kafkas")
-      .pipe(retry(1), catchError(this.handleError));
-  }
-
-  deleteKafka(id): Observable<any> {
-    return this.http.delete(prefix + "kafkas/" + id).pipe(
-      //online
-      retry(1),
-      map(this.extractData2),
-      catchError(this.handleError)
-    );
-  }
-
-  createNewKafka(k: Kafka): Observable<any> {
-    return this.http.post(prefix + "kafkas", k).pipe(
+  public updateKafka(k: Kafka): Observable<Kafka> {
+    return this.http.put<Kafka>(prefix + "kafkas/" + k.id, k).pipe(
       retry(1),
       tap(_ => this.extractData),
       catchError(this.handleError)
     );
   }
 
-  updateKafka(k: Kafka): Observable<any> {
-    let id = k.id;
-    return this.http.put(prefix + "kafkas/" + id, k).pipe(
+  public addKafka(k: Kafka): Observable<Kafka> {
+    return this.http.post<Kafka>(prefix + "kafkas", k).pipe(
       retry(1),
       tap(_ => this.extractData),
       catchError(this.handleError)
     );
   }
+
+  public deleteKafka(id: string | number): Observable<Kafka> {
+    return this.http.delete<Kafka>(prefix + "kafkas/" + id).pipe(
+      retry(1),
+      tap(_ => console.log(`deleted kafka id=${id}`)),
+      catchError(this.handleError)
+    );
+  }
 }
diff --git a/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.css b/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.css
index 4b76e13..7340ac8 100644
--- a/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.css
+++ b/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.css
@@ -2,7 +2,7 @@
 * ============LICENSE_START=======================================================
 * ONAP : DataLake
 * ================================================================================
-* Copyright 2019 QCT
+* Copyright 2019 - 2020 QCT
 *=================================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -36,3 +36,7 @@
   font-weight: 600;
   font-size: 16px;
 }
+
+.card-panel .add-style {
+  cursor: pointer;
+}
diff --git a/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.html b/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.html
index 7b8d865..101b7fc 100644
--- a/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.html
+++ b/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.html
@@ -2,7 +2,7 @@
 ============LICENSE_START=======================================================
 ONAP : DataLake
 ================================================================================
-Copyright 2019 QCT
+Copyright 2019 - 2020 QCT
 =================================================================================
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -17,47 +17,51 @@
 limitations under the License.
 ============LICENSE_END=========================================================
 -->
-<div class="card-panel d-flex flex-column" (click)="cardClick()">
-  <div class="d-flex flex-row p-2">
+<div class="card-panel d-flex flex-column">
+  <div class="d-flex flex-row">
     <div class="dl-h4 title mr-auto ml-3 mt-2">{{ this.title }}</div>
 
-    <div *ngIf="this.modifiable" class="ml-auto dropdown action-icon-dropdown" data-boundary="window">
+    <div *ngIf="this.modifiable" class="ml-auto dropdown action-icon-dropdown mr-1 mt-1" data-boundary="window">
+
       <a class="badge badge-light action-icon-dropdown" data-toggle="dropdown" style="cursor: pointer">
-        <i class="fas fa-ellipsis-h fa-2x dl-icon-enable"></i>
+        <i class="m-2 fas fa-ellipsis-h fa-2x dl-icon-enable"></i>
       </a>
+
+
       <div class="dropdown-menu action-icon-btn">
-        <button class="dropdown-item" type="button" (click)="cardMoreAction('edit')">
-          {{ 'EDIT' | translate }}
+        <button class="dropdown-item" type="button" (click)="cardMoreClickAction('edit')">
+          {{ "EDIT" | translate }}
         </button>
-        <button class="dropdown-item" type="button" (click)="cardMoreAction('delete')">
-          {{ 'DELETE' | translate }}
+        <button class="dropdown-item" type="button" (click)="cardMoreClickAction('delete')">
+          {{ "DELETE" | translate }}
         </button>
       </div>
     </div>
   </div>
 
-  <div class="mt-auto align-self-center p-2">
+  <div class="mt-auto align-self-center">
     <!-- show icon -->
-    <div *ngIf="this.iconPath">
-      <span [ngSwitch]="this.iconSize">
-        <span *ngSwitchCase="'sm'">
-          <svg-icon [src]="this.iconPath" [svgStyle]="{ 'width.px':80 }"></svg-icon>
-        </span>
-        <span *ngSwitchCase="'lg'">
-          <svg-icon [src]="this.iconPath" [svgStyle]="{ 'width.px':180 }"></svg-icon>
-        </span>
-        <span *ngSwitchDefault>
-          <svg-icon [src]="this.iconPath" [svgStyle]="{ 'width.px':150 }"></svg-icon>
-        </span>
-      </span>
+    <div *ngIf="this.iconPath" class="add-style" (click)="cardClickAction()">
+      <div [ngSwitch]=" this.iconSize">
+        <div *ngSwitchCase="'sm'">
+          <img src="{{ this.iconPath }}" style="width: 60px; height:60px;">
+        </div>
+        <div *ngSwitchCase="'md'">
+          <img src="{{ this.iconPath }}" style="width: 100px; height:100px;">
+        </div>
+        <div *ngSwitchCase="'lg'">
+          <img src="{{ this.iconPath }}" style="width: 140px; height:140px;">
+        </div>
+      </div>
     </div>
+
     <!-- show string -->
     <div *ngIf="this.content" class="dl-h1">
       {{ this.content }}
     </div>
   </div>
 
-  <div class="infoname align-self-center mt-auto p-2">
+  <div class="infoname align-self-center mt-auto pb-2">
     {{ this.subcontent }}
   </div>
 </div>
diff --git a/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.ts b/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.ts
index 9be0b84..792aa8c 100644
--- a/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.ts
+++ b/components/datalake-handler/admin/src/src/app/shared/modules/card/card.component.ts
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP : DataLake
  * ================================================================================
- * Copyright 2019 QCT
+ * Copyright 2019 - 2020 QCT
  *=================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
  * @author Ekko Chang
  *
  */
-import { Component, OnInit, Input, Output, EventEmitter  } from "@angular/core";
+import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
 
 @Component({
   selector: "app-card",
@@ -38,19 +38,18 @@
   @Input() modifiable: boolean;
   @Input() iconSize: string[] = ["sm", "md", "lg"];
 
-  @Output() cardAction = new EventEmitter<object>();
-  @Output() edit = new EventEmitter<object>();
+  @Output() cardClick = new EventEmitter<object>();
+  @Output() cardMoreActionClick = new EventEmitter<object>();
 
-  constructor() {}
+  constructor() { }
 
-  ngOnInit() {}
+  ngOnInit() { }
 
-  cardClick() {
-    this.cardAction.emit();
+  cardClickAction() {
+    this.cardClick.emit();
   }
 
-  cardMoreAction(type) {
-    this.edit.emit(type);
+  cardMoreClickAction(action: any) {
+    this.cardMoreActionClick.emit(action);
   }
-
 }
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.css b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.css
index 1c7a386..8b13789 100644
--- a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.css
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.css
@@ -1,42 +1 @@
-/*
-    Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
-
-    Licensed 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.
-*/
-.dashboard-kafka{
-  padding: 0;
-}
-.kafka-li{
-  float: left;
-  list-style: none;
-  padding: 0;
-  width: 23.5%;
-  hight: 23.5%;
-  margin-right: 2%;
-  margin-bottom: 2%;
-}
-li:nth-child(4n){
-  margin-right: 0;
-}
-.add-kafka{
-  cursor: pointer;
-}
-.kafka-list{
-  padding: 0;
-  width: 100%;
-  hight: 100%;
-}
-.add-style{
-
-}
 
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.html b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.html
index ec611cc..b0390d7 100644
--- a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.html
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.html
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+    Copyright (C) 2019 - 2020 CMCC, Inc. and others. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -13,18 +13,17 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-  <div class="col-md-12 dashboard-kafka">
-      <ul class="kafka-list clearfix">
-        <li class="add-style" *ngFor="let kafka of this.kafkas; let thisIndex=index;" class="col-md-3 kafka-li">
-          <app-card [iconPath]="cardIconPathList[thisIndex]" [iconSize]="'sm'" [subcontent]="kafka.name"
-                    [modifiable]="this.cardModifiable" (edit)="cardMoreAction($event, kafka.id)">
-          </app-card>
-        </li>
 
-
-        <li class="col-md-3 kafka-li add-kafka">
-          <app-card [iconPath]="this.cardAddicon" [iconSize]="'sm'" (click)="newKafkaModal()">
-          </app-card>
-        </li>
-      </ul>
+<div class="d-flex flex-row flex-nowrap">
+  <div class="col-md-3" *ngFor="let kafka of this.kafkas; let thisIndex = index">
+    <app-card [iconPath]="kafka.iconPath" [iconSize]="'md'" [subcontent]="kafka.name" [modifiable]="this.cardModifiable"
+      (cardClick)="openModal('edit', kafka)" (cardMoreActionClick)="cardMoreClickAction($event, kafka)">
+    </app-card>
   </div>
+
+  <div class="col-md-3">
+    <app-card [iconPath]="this.cardAddiconPath" [iconSize]="'sm'" (click)="openModal('new')">
+    </app-card>
+  </div>
+
+</div>
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.ts b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.ts
index b8dbb0e..46a46a0 100644
--- a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.ts
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-list.component.ts
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+    Copyright (C) 2019 - 2020 CMCC, Inc. and others. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -16,238 +16,161 @@
 
 /**
  * @author Chunmeng Guo
+ * @contributor Ekko Chang
  */
 
-import { Component, OnInit, ElementRef } from '@angular/core';
+import { Component, OnInit } from "@angular/core";
 import { RestApiService } from "src/app/core/services/rest-api.service";
 import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
-import { Kafka } from "../../../core/models/kafka.model";
+import { Kafka } from "src/app/core/models/kafka.model";
 
 // Loading spinner
 import { NgxSpinnerService } from "ngx-spinner";
 
-// notify
+import { map, mergeMap } from "rxjs/operators";
+import { from, forkJoin } from "rxjs";
+
+// Notify
 import { ToastrNotificationService } from "src/app/shared/components/toastr-notification/toastr-notification.service";
-import {AlertComponent} from "../../../shared/components/alert/alert.component";
-import {NewKafkaModalComponent} from "./new-kafka-modal/new-kafka-modal.component";
-import {EditKafkaModalComponent} from "./edit-kafka-modal/edit-kafka-modal.component";
+import { AlertComponent } from "src/app/shared/components/alert/alert.component";
+import { ModalContentData } from "src/app/shared/modules/modal/modal.data";
+import { ModalComponent } from "src/app/shared/modules/modal/modal.component";
+import { KafkaModalComponent } from "src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component";
 
 @Component({
-  selector: 'app-kafka-list',
-  templateUrl: './kafka-list.component.html',
-  styleUrls: ['./kafka-list.component.css']
+  selector: "app-kafka-list",
+  templateUrl: "./kafka-list.component.html",
+  styleUrls: ["./kafka-list.component.css"]
 })
 export class KafkaListComponent implements OnInit {
+  kafkas: Array<Kafka> = [];
 
-  kafkaList: any = [];
-  kafkas: Kafka[] = [];
-  cardIconPath: string;
-  cardModifiable: boolean;
-  cardAddicon: string;
-  Kafka_New: Kafka;
-  Kafka_Newbody: Kafka;
-  cardIconPathList: any = [];
-  kafkaData: any = [];
+  // app-card parameters
+  cardModifiable: boolean = true;
+  cardAddiconPath: string = "assets/icons/add.svg";
 
   constructor(
-    private kafkaApiService: RestApiService,
+    private restApiService: RestApiService,
     private notificationService: ToastrNotificationService,
     private modalService: NgbModal,
     private spinner: NgxSpinnerService
-  ) {
-    this.initList();
-  }
+  ) {}
 
   ngOnInit() {
     this.spinner.show();
-    this.cardModifiable = true;
-    this.cardAddicon = "assets/icons/add.svg";
-  }
+    let t_kafkas: Array<Kafka> = [];
 
-  initList() {
-    this.initData().then(data => {
-      this.initKafkasList(this.kafkaList).then(data => {
-        this.kafkas = data;
-        if (this.kafkas.length > 0) {
-          let a = "assets/icons/kafka_able.svg";
-          let b = "assets/icons/kafka_disable.svg";
-          this.cardIconPathList.splice(0,this.cardIconPathList.length);
-          for (let i = 0; i < this.kafkas.length; i++) {
-            this.cardIconPath = (this.kafkas[i].enabled == true) ? a : b;
-            this.cardIconPathList.push(this.cardIconPath);
-          }
+    const get_kafkas = this.restApiService.getAllKafka().pipe(
+      mergeMap(ks => from(ks)),
+      map(k => {
+        if (k.enabled == true) {
+          k.iconPath = "assets/icons/kafka_able.svg";
+        } else {
+          k.iconPath = "assets/icons/kafka_disable.svg";
         }
-        console.log(this.cardIconPathList, "kafkas[]");
-      });
+        t_kafkas.push(k);
+      })
+    );
+
+    forkJoin(get_kafkas).subscribe(data => {
+      this.kafkas = t_kafkas;
+      setTimeout(() => {
+        this.spinner.hide();
+      }, 500);
     });
   }
 
-  async initData() {
-    this.kafkaList = [];
-    this.kafkaList = await this.getKafkaList();
-    setTimeout(() => {
-      this.spinner.hide();
-    }, 500);
-  }
-
-  getKafkaList() {
-    let data: any;
-    data = this.kafkaApiService.getAllKafkaList().toPromise();
-    return data;
-  }
-
-  async getKafkaDetailModal(id: number) {
-    this.kafkaData = [];
-    this.kafkaData = await this.getKafkaModal(id);
-    return this.kafkaData;
-  }
-
-  getKafkaModal(id: number) {
-    return this.kafkaApiService.getKafka(id).toPromise();
-  }
-
-  async initKafkasList(kafkaList: []) {
-    let k: Kafka[] = [];
-    if (kafkaList.length > 0) {
-      for (let i = 0; i < kafkaList.length; i++) {
-        let data = kafkaList[i];
-        let feed = {
-          id: data["id"],
-          name: data["name"],
-          enabled: data["enabled"],
-          brokerList: data["brokerList"],
-          zooKeeper: data["zooKeeper"],
-          group: data["group"],
-          secure: data["secure"],
-          login: data["login"],
-          pass: data["pass"],
-          securityProtocol: data["securityProtocol"],
-          includedTopic: data["includedTopic"],
-          excludedTopic: data["excludedTopic"],
-          consumerCount: data["consumerCount"],
-          timeout: data["timeout"]
-        };
-        k.push(feed);
-      }
-    }
-    return k;
-  }
-
-  deleteKafkaModel(id: number) {
-    const index = this.kafkaList.findIndex(t => t.id === id);
-    const modalRef = this.modalService.open(AlertComponent, {
-      size: "sm",
-      centered: true
-    });
-    modalRef.componentInstance.message = "ARE_YOU_SURE_DELETE";
-    modalRef.componentInstance.passEntry.subscribe(receivedEntry => {
-      // Delete kafka
-      this.kafkaApiService.deleteKafka(id).subscribe(
-        res => {
-          console.log(res);
-          if (JSON.stringify(res).length <= 2) {
-            this.kafkaList.splice(index, 1);
-            this.kafkaList = [...this.kafkaList];
-            this.initList();
-            this.notificationService.success("SUCCESSFULLY_DELETED");
-
-          } else {
-            this.initList();
-            this.notificationService.error("FAILED_DELETED");
-          }
-
-          modalRef.close();
-        },
-        err => {
-          this.notificationService.error(err);
-          modalRef.close();
-        }
-      );
-    });
-
-  }
-
-  newKafkaModal() {
-    const modalRef = this.modalService.open(NewKafkaModalComponent, {
-      windowClass: "dl-md-modal kafkas",
-      centered: true
-    });
-
-    this.Kafka_New = new Kafka();
-    this.Kafka_Newbody = new Kafka();
-    modalRef.componentInstance.kafka = this.Kafka_Newbody;
-    modalRef.componentInstance.kafkaList_length = this.kafkaList.length;
-    modalRef.componentInstance.passEntry.subscribe(receivedEntry => {
-      this.Kafka_Newbody = receivedEntry;
-      this.kafkaApiService
-        .createNewKafka(this.Kafka_Newbody)
-        .subscribe(
-          res => {
-            this.spinner.hide();
-            if (res.statusCode == 200) {
-              this.Kafka_New = res.returnBody;
-              this.kafkaList.push(this.Kafka_New);
-              this.kafkaList = [...this.kafkaList];
-              this.initList();
-              this.notificationService.success("SUCCESSFULLY_CREARED");
-            } else {
-              this.initList();
-              this.notificationService.error("FAILED_CREARED");
-            }
-            modalRef.close();
-          },
-          err => {
-            this.spinner.hide();
-            this.notificationService.error(err);
-            modalRef.close();
-          }
-        );
-    });
-  }
-
-  cardMoreAction($event, id) {
-
-    if($event == "edit"){
-      this.editKafkaModal(id);
-    }else {
-      console.log($event,id);
-      this.deleteKafkaModel(id);
-    }
-  }
-
-  editKafkaModal(id: number) {
-    this.getKafkaDetailModal(id).then(data => {
-      console.log("id", id);
-      const index = this.kafkaList.findIndex(t => t.id === id);
-      const modalRef = this.modalService.open(EditKafkaModalComponent, {
-        windowClass: "dl-md-modal kafkas",
-        centered: true
-      });
-      modalRef.componentInstance.editKafka = data;
-      modalRef.componentInstance.passEntry.subscribe(receivedEntry => {
-        this.Kafka_New = receivedEntry;
-        this.kafkaApiService
-          .updateKafka(this.Kafka_New)
-          .subscribe(
+  cardMoreClickAction(mode: string, k: Kafka) {
+    switch (mode) {
+      case "edit":
+        this.openModal("edit", k);
+        break;
+      case "delete":
+        const modalRef = this.modalService.open(AlertComponent, {
+          size: "sm",
+          centered: true,
+          backdrop: "static"
+        });
+        modalRef.componentInstance.message = "ARE_YOU_SURE_DELETE";
+        modalRef.componentInstance.passEntry.subscribe(recevicedEntry => {
+          this.restApiService.deleteKafka(k.id).subscribe(
             res => {
-              this.spinner.hide();
-              if (res.statusCode == 200) {
-                this.kafkaList[index] = this.Kafka_New;
-                this.kafkaList = [...this.kafkaList];
-                this.notificationService.success("SUCCESSFULLY_UPDATED");
-                this.initList();
-              } else {
-                this.notificationService.error("FAILED_UPDATED");
-              }
-              modalRef.close();
+              this.ngOnInit();
+              setTimeout(() => {
+                this.notificationService.success("SUCCESSFULLY_DELETED");
+              }, 500);
             },
             err => {
               this.notificationService.error(err);
-              modalRef.close();
             }
           );
-      });
+          modalRef.close();
+        });
+        break;
+    }
+  }
+
+  openModal(mode: string, k: Kafka) {
+    const modalRef = this.modalService.open(ModalComponent, {
+      size: "lg",
+      centered: true,
+      backdrop: "static"
     });
 
+    switch (mode) {
+      case "new":
+        let newKafka: Kafka;
+        let componentNew = new ModalContentData(KafkaModalComponent, newKafka);
+
+        modalRef.componentInstance.title = "NEW_KAFKA";
+        modalRef.componentInstance.notice = "";
+        modalRef.componentInstance.mode = "new";
+        modalRef.componentInstance.component = componentNew;
+
+        modalRef.componentInstance.passEntry.subscribe((data: Kafka) => {
+          newKafka = Object.assign({}, data);
+          this.restApiService.addKafka(newKafka).subscribe(
+            res => {
+              this.ngOnInit();
+              setTimeout(() => {
+                this.notificationService.success("SUCCESSFULLY_CREARED");
+              }, 500);
+            },
+            err => {
+              this.notificationService.error(err);
+            }
+          );
+          modalRef.close();
+        });
+        break;
+      case "edit":
+        let editKafka: Kafka = k;
+        let componentEdit = new ModalContentData(
+          KafkaModalComponent,
+          editKafka
+        );
+
+        modalRef.componentInstance.title = editKafka.name;
+        modalRef.componentInstance.notice = "";
+        modalRef.componentInstance.mode = "edit";
+        modalRef.componentInstance.component = componentEdit;
+
+        modalRef.componentInstance.passEntry.subscribe((data: Kafka) => {
+          editKafka = Object.assign({}, data);
+          this.restApiService.updateKafka(editKafka).subscribe(
+            res => {
+              this.ngOnInit();
+              setTimeout(() => {
+                this.notificationService.success("SUCCESSFULLY_UPDATED");
+              }, 500);
+            },
+            err => {
+              this.notificationService.error(err);
+            }
+          );
+          modalRef.close();
+        });
+        break;
+    }
   }
 }
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.css b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.css
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.html b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.html
new file mode 100644
index 0000000..a093095
--- /dev/null
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.html
@@ -0,0 +1,157 @@
+<!--
+============LICENSE_START=======================================================
+ONAP : DataLake
+================================================================================
+Copyright 2019 - 2020 QCT
+=================================================================================
+Licensed 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.
+============LICENSE_END=========================================================
+-->
+
+
+<div class="container p-4">
+
+  <div class="form-group">
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ "NAME" | translate }}</label>
+      </div>
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'STATUS' | translate }}</label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.name" class="form-control dl-input-text" type="text" />
+      </div>
+      <div class="col-md-6">
+        <label class="dl-switch">
+          <input id="switch" type="checkbox" [(ngModel)]="this.data.enabled" />
+          <span class="dl-slider round"></span>
+        </label>
+      </div>
+    </div>
+  </div>
+
+  <div class="form-group">
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'BROKER_LIST' | translate }}</label>
+      </div>
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'ZOOKEEPER' | translate }}</label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.brokerList" class="form-control dl-input-text" type="text" />
+      </div>
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.zooKeeper" class="form-control dl-input-text" type="text" />
+      </div>
+    </div>
+  </div>
+
+  <div class="form-group">
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'Username' | translate }}</label>
+      </div>
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'Password' | translate }}</label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.login" class="form-control dl-input-text" type="text" />
+      </div>
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.pass" class="form-control dl-input-text" type="text" />
+      </div>
+    </div>
+  </div>
+
+  <div class="form-group">
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'AUTHENTICATION' | translate }}</label>
+      </div>
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'SECURITY_PROTOCOL' | translate }}</label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-switch">
+          <input id="switch" type="checkbox" [(ngModel)]="this.data.secure" />
+          <span class="dl-slider round"></span>
+        </label>
+      </div>
+      <div class="col-md-6">
+        <select [(ngModel)]="this.data.securityProtocol" class="custom-select dl-input-text">
+          <option *ngFor="let item of securityProtocol" [selected]="item == this.data.securityProtocol">
+            {{ item }}
+          </option>
+        </select>
+      </div>
+    </div>
+  </div>
+
+  <div class="form-group">
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'GROUP' | translate }}</label>
+      </div>
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'TIME_OUT' | translate }}</label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.group" class="form-control dl-input-text" type="text" />
+      </div>
+      <div class="col-md-6">
+        <input [(ngModel)]="this.data.timeout" class="form-control dl-input-text" type="text"
+          (input)="this.adminService.onKeyPressNumber($event)" />
+      </div>
+    </div>
+  </div>
+
+  <div class="form-group">
+    <div class="row">
+      <div class="col-md-6">
+        <label class="dl-emphasis1">{{ 'EXCLUDED_TOPICS' | translate }}</label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-9">
+        <div class="d-flex row align-items-center" *ngFor="let field of extenFields; let i = index">
+          <div class="col-md-8 order-1">
+            <input [(ngModel)]="field.item" class="form-control dl-input-text" placeholder="AAI-EVENT" type="text"
+              (change)="onChangeSaveIdField()" (input)="this.adminService.onKeyPressSymbol($event)" />
+          </div>
+          <div class="order-2">
+            <button type="button" class="btn dl-icon-enable p-2" (click)="onClickAddIdField(i)">
+              <i class="fa fa-plus fa-xs" aria-hidden="true"></i>
+            </button>
+          </div>
+          <div class="order-3">
+            <button type="button" class="btn dl-icon-enable p-2" (click)="onClickDelIdField(i)">
+              <i class="fa fa-trash fa-xs" aria-hidden="true"></i>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.spec.ts b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.spec.ts
new file mode 100644
index 0000000..c6da221
--- /dev/null
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.spec.ts
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : DataLake
+ * ================================================================================
+ * Copyright 2019 - 2020 QCT
+ *=================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { KafkaModalComponent } from './kafka-modal.component';
+
+describe('KafkaModalComponent', () => {
+  let component: KafkaModalComponent;
+  let fixture: ComponentFixture<KafkaModalComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ KafkaModalComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(KafkaModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.ts b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.ts
new file mode 100644
index 0000000..0c747d9
--- /dev/null
+++ b/components/datalake-handler/admin/src/src/app/views/kafka/kafka-list/kafka-modal/kafka-modal.component.ts
@@ -0,0 +1,91 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : DataLake
+ * ================================================================================
+ * Copyright 2019 - 2020 QCT
+ *=================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ * @author Ekko Chang
+ *
+ */
+
+import { Component, OnInit, Input } from "@angular/core";
+
+import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap";
+import { AdminService } from "src/app/core/services/admin.service";
+import { Kafka } from "src/app/core/models/kafka.model";
+
+@Component({
+  selector: "app-kafka-modal",
+  templateUrl: "./kafka-modal.component.html",
+  styleUrls: ["./kafka-modal.component.css"]
+})
+export class KafkaModalComponent implements OnInit {
+  @Input() data: Kafka;
+  @Input() mode: string;
+
+  securityProtocol: Array<string> = ["None", "SASL_PLAINTEXT"];
+  extenFields: Array<any> = [];
+  newField: any = {};
+
+  constructor(
+    public activeModal: NgbActiveModal,
+    public adminService: AdminService
+  ) {}
+
+  ngOnInit() {
+    // Get excludedTopic field
+    this.extenFields = [];
+    if (this.data.excludedTopic != null) {
+      let feed = this.data.excludedTopic.split(",");
+      for (let i = 0; i < feed.length; i++) {
+        let data = { item: feed[i] };
+        this.extenFields.push(data);
+      }
+    } else {
+      this.extenFields.push([]);
+    }
+  }
+
+  onClickAddIdField() {
+    this.extenFields.push(this.newField);
+    this.newField = {};
+    this.onChangeSaveIdField();
+  }
+
+  onClickDelIdField(index: number) {
+    if (this.extenFields.length > 1) {
+      this.extenFields.splice(index, 1);
+      this.onChangeSaveIdField();
+    }
+  }
+
+  onChangeSaveIdField() {
+    this.data.excludedTopic = "";
+
+    for (let i = 0; i < this.extenFields.length; i++) {
+      if (this.extenFields[i].item) {
+        if (this.data.excludedTopic == "") {
+          this.data.excludedTopic = this.extenFields[i].item;
+        } else {
+          this.data.excludedTopic += "," + this.extenFields[i].item;
+        }
+      }
+    }
+  }
+}
diff --git a/components/datalake-handler/admin/src/src/app/views/test/test.component.html b/components/datalake-handler/admin/src/src/app/views/test/test.component.html
index 549fa54..75d0e1f 100644
--- a/components/datalake-handler/admin/src/src/app/views/test/test.component.html
+++ b/components/datalake-handler/admin/src/src/app/views/test/test.component.html
@@ -9,7 +9,7 @@
     <app-card [title]="this.cardTitle" [content]="this.cardContent">
     </app-card>
     <br>
-    <app-card [iconPath]="this.cardAddicon" [iconSize]="'sm'" (cardAction)="cardClick()">
+    <app-card [iconPath]="assets/icons/add.svg" [iconSize]="'sm'" (cardAction)="cardClick()">
     </app-card>
     <br>
   </div>
diff --git a/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.html b/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.html
index f5f3a7e..849c145 100644
--- a/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.html
+++ b/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.html
@@ -134,7 +134,7 @@
             <div class="d-flex row align-items-center" *ngFor="let field of idExFields; let i = index">
               <div class="col-md-8 order-1">
                 <input [(ngModel)]="field.item" class="form-control dl-input-text" placeholder="/event-header/id"
-                  type="text" [value]="field.item" (change)="onChangeSaveIdField()" />
+                  type="text" (change)="onChangeSaveIdField()" (input)="this.adminService.onKeyPressSymbol($event)" />
               </div>
               <div class="order-2">
                 <button type="button" class="btn dl-icon-enable p-2" (click)="onClickAddIdField(i)">
diff --git a/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.ts b/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.ts
index 3f0223e..9289861 100644
--- a/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.ts
+++ b/components/datalake-handler/admin/src/src/app/views/topics/topic-list/topic-modal/topic-modal.component.ts
@@ -229,21 +229,26 @@
   onClickAddIdField() {
     this.idExFields.push(this.idExNewField);
     this.idExNewField = {};
+    this.onChangeSaveIdField();
   }
 
   onClickDelIdField(index: number) {
     if (this.idExFields.length > 1) {
       this.idExFields.splice(index, 1);
+      this.onChangeSaveIdField();
     }
   }
 
   onChangeSaveIdField() {
     this.data.messageIdPath = "";
+
     for (let i = 0; i < this.idExFields.length; i++) {
-      if (i == 0) {
-        this.data.messageIdPath = this.idExFields[i].item;
-      } else {
-        this.data.messageIdPath += "," + this.idExFields[i].item;
+      if (this.idExFields[i].item) {
+        if (this.data.messageIdPath == "") {
+          this.data.messageIdPath = this.idExFields[i].item;
+        } else {
+          this.data.messageIdPath += "," + this.idExFields[i].item;
+        }
       }
     }
   }
diff --git a/components/datalake-handler/admin/src/src/assets/i18n/en-us.json b/components/datalake-handler/admin/src/src/assets/i18n/en-us.json
index 1165461..2e0892f 100644
--- a/components/datalake-handler/admin/src/src/assets/i18n/en-us.json
+++ b/components/datalake-handler/admin/src/src/assets/i18n/en-us.json
@@ -1,6 +1,6 @@
 {
   "SIDEBAR": {
-    "FEEDFER": "DataLake Feeder",
+    "FEEDER": "DataLake Feeder",
     "KAFKA": "Kafka",
     "TOPICS": "Topics",
     "DATABASE": "Database",