<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>angular 5 test env</title>
  <link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
       <link href="https://unpkg.com/@angular/material/prebuilt-themes/deeppurple-amber.css" rel="stylesheet">
    <link type="text/css" rel="stylesheet" href="./app/style.css" />     
    <script src="https://unpkg.com/zone.js@0.8.12/dist/zone.js"></script>
    <script src="https://unpkg.com/zone.js@0.8.12/dist/long-stack-trace-zone.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
    <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
    <script src="//cdn.jsdelivr.net/underscorejs/1.5.2/underscore-min.js"></script>
    <script data-require="moment.js@2.10.2" data-semver="2.10.2" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.2/moment.min.js"></script>
    
      <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function (err) { console.error(err); });
    </script>
  </head>

  <body>    
    <my-app></my-app>

  </body>

</html>
//our root app component
import { Component, NgModule, OnInit, ViewContainerRef, OnDestroy, ViewChild, ElementRef } from '@angular/core';
import { BrowserModule} from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material';

import { LoginComponent } from './components/login/login.component';
import { StorageService } from './services/storage.service';
import { UtilsService } from './services/utils.service';

// export interface User{
//   name : string;
//   isOnline : boolean;
//   chats : Array<Chat>;
// }
// export interface Chat {
//   owners : Array<string>;
//   messages : Array<Message>;
  
// }
// export interface Message {
//   owner : string;
//   message : string;
//   createdAt : string;
// }
@Component({
  selector: 'my-app',
  templateUrl: './app/app.component.html',
  styleUrl: ['./app/app.component.css']
})
export class AppComponent implements OnInit  {
    users : Array<any> = [];
    onlineUsers : Array<any> = []
    chats : Array<any> = [];
    systemMessages : Array<string> = [];
    
    constructor(
      public loginDialog: MatDialog, 
      public loginDialogRef: MatDialogRef<LoginComponent>,
      private _storageService: StorageService,
      private _utilsService: UtilsService,
      
      ) {
    }
    ngOnInit(): void {
      this.initUsers();    
    }

    onMessageSent(data) {
      let indexes = [];

      _.each(this.onlineUsers, (u, index)=>{
        if(_.indexOf(data.owners, u.userName) > -1) {
          indexes.push(index);
        }
      });
      _.each(indexes, (index)=>{
        this.onlineUsers[index] = this._utilsService.deepCopy(this.onlineUsers[index]);
      });
    }
    addSystemMessage(msg) {
      this.systemMessages.unshift(msg);
      
    }
    onLogout(userName) {
      this.onlineUsers = _.reject(this.onlineUsers, (u) => { return u.userName == userName});
      this.users = this._storageService.getUsers();
      this.addSystemMessage("User " + userName +" logged out!");
    }

    onDeleteUser(userName) {
      this.onlineUsers = _.reject(this.onlineUsers, (u) => { return u.userName == userName});   
      this.users = this._storageService.getUsers();
      this.addSystemMessage("User " + userName +" deleted!");
    }
    onChatAction(data):void {
        if(data.action == "message_sent"){
          this.onMessageSent(data);
          
        } else if (data.action == "logout") {
          this.onLogout(data.user.userName);
        }
        else if (data.action == "delete_user") {
          this.onDeleteUser(data.user.userName);
        }
    }
    initUsers(){
      this._storageService.setAllUsersOnlineStatus(false);
    }


    openChat(){
      let config = new MatDialogConfig();
      this.loginDialogRef = this.loginDialog.open(LoginComponent, config);
      this.loginDialogRef.afterClosed().subscribe(user => {
        if(!user) return;
        this.onlineUsers.push(user);
        this.users = this._storageService.getUsers();
        this.addSystemMessage("User " + user.userName +" joined to chat.");
      });
    }

    withoutCurentUser(user) {
      return _.reject(this.users, (u) => { return u.userName == user.userName});
    }

    resetChat() {
      this.addSystemMessage("All chats and users deleted!");
      this._storageService.reset();
      this.users = [];
      this.onlineUsers = [];
    }

     scrollToBottom(): void {
        try {
            this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;
        } catch(err) { }                 
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { LoginComponent } from './components/login/login.component';
import { ChatComponent } from './components/chat/chat.component';
import { MatDialogModule, MatListModule, MatDialogRef, MAT_DIALOG_DATA, MatButtonModule} from '@angular/material';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/map';
import { StorageService } from './services/storage.service';
import { UtilsService } from './services/utils.service';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        MatDialogModule,
        MatButtonModule,
        ReactiveFormsModule,
        MatListModule,
        //ChatComponent,
    ],
    declarations: [
        AppComponent,
        LoginComponent,
        ChatComponent,
    ],
    entryComponents: [
        LoginComponent, 
        //ChatComponent,
    ],
    exports : [
        LoginComponent,
        //ChatComponent,
    ],
    providers: [
        StorageService,
        UtilsService,
        {
            provide: MatDialogRef,
            useValue: MAT_DIALOG_DATA
        },
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
<div>
  <h1>Welcome to Chat <button class="btn" (click)="openChat()">Join</button> <button class="btn" title="This will delete all chats and users" (click)="resetChat()" style="margin-left:20px;">Reset </button></h1>
  <div class="system-message" #systemMessagesContainer>
    <mat-list class="msgs-list">
      <mat-list-item *ngFor="let m of systemMessages" >
        {{m}}
      </mat-list-item>
      </mat-list>  
  </div>  
</div>
<div class="" >
  <mat-list class="chats-list">
      <mat-list-item  class="chat-item" *ngFor="let u of onlineUsers">
        <app-chat  name="chat" [user]="u" [users]="withoutCurentUser(u)" (notifyOnAction)="onChatAction($event)" ></app-chat>
        
      </mat-list-item>
  </mat-list>
</div>
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule)
import { Injectable } from '@angular/core';
import { Validators, FormControl, FormGroup } from '@angular/forms';

import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { UtilsService } from './utils.service';

@Injectable()
export class StorageService {
    constructor(
        private _utilsService: UtilsService,
    ) { 

    }
    public reset() {
      localStorage.removeItem("chats");
      localStorage.removeItem("chat_users");
      localStorage.setItem("chats", JSON.stringify([]));
    }
    public deleteUser(userName) {
      let users = this.getUsers();
      users = _.reject(users, (u)=> { return u.userName == userName});
      let chats = this.getChats();
      chats = _.reject(chats, (chat)=>{ return _.indexOf(chat.owners, userName) > -1});
      localStorage.setItem("chats", JSON.stringify(chats));
      localStorage.setItem("chat_users", JSON.stringify(users));
    }
    public setAllUsersOnlineStatus(status) {
       let users = this.getUsers();
       _.each(users, (u)=>{ u.isOnline = status;});
       this.setUsers(users)
     }

    public setUserOnlineStatus(userName, status) {
       let users = this.getUsers();
       _.each(users, (u)=>{ 
          if(userName == u.userName) u.isOnline = status;
        });
       this.setUsers(users);
     }

    public getUserOnlineStatus(userName) {
       let user = this.getUser(userName);
       return user.isOnline;
    }

    public getUserChats(userName) {
      let chats = this.getChats();
      let userChats = _.reject(chats, (chat) => { return _.indexOf(chat.owners, userName) < 0 });
       return this._utilsService.deepCopy(userChats, "Array");
    }

    public getChatByOwners(owners, chats) {
      let returnACopy = false;
      if(!chats) {
        chats = this.getChats();
        returnACopy = true;
      }
      let result;
      _.each(chats, (chat)=>{
        if(chat.owners.sort().join(',') === owners.sort().join(',')){
           result = chat;
        }
      });
      return returnACopy ? this._utilsService.deepCopy(result) : result;
    }

    public deleteUserChats(userName) {
      let chats = this.getChats();
      chats = _.reject(chats, (chat) => { return _.indexOf(chat.owners, userName) > 0 });
      return this._utilsService.deepCopy(chats, "Array");
    }

    public getChats () : Array<any>{
      let chats = localStorage.getItem("chats");
      if(!chats) return [];
      let chatsObj = JSON.parse(chats);   
      return this._utilsService.deepCopy(chatsObj, "Array");
    }

    public saveMessage(message, owners) {
      let chats = this.getChats();
      let userChats = this.getChatByOwners(owners, chats);
      userChats.messages.push(message);
      userChats.messages = userChats.messages.sort((a, b) => a.timestamp - b.timestamp);
      this.setChats(chats);
    }
    public getUserData(userName) {
      let interlocutors = _.reject(this.getUsers(), (user) => { return user.userName == userName});
      // let interlocutors = _.reject(chatUsers, (chat) => { return _.indexOf(chat.owners, userName) < 0 });
      let userChatsArray = this.getUserChats(userName);
      let userChatsObj = {};
      _.each(userChatsArray, (chat) => {
        let interlocutor = _.find(chat.owners, (owner)=> {return owner != userName});
        userChatsObj[interlocutor] = chat.messages;
      });
      return {interlocutors : interlocutors || [], userChats : userChatsObj || {}};
    }
    
    public getUsers() : Array<any>{
      let chatUsers = localStorage.getItem("chat_users");
      if (!chatUsers) return [];
      else return JSON.parse(chatUsers);
    }

    public getOnlineUsers() {
      let onlineUsers = this.getUsers();
      onlineUsers = _.reject(onlineUsers, (u) => { return !u.isOnline; });
      return onlineUsers;
    }
    public setUsers(users) {
      localStorage.setItem("chat_users", JSON.stringify(users));
    }
    public setChats(chats) {
      localStorage.setItem("chats", JSON.stringify(chats));
    }
    public addChat(chat) {
      let chats = this.getChats();
      chats.push(chat);
      localStorage.setItem("chats", JSON.stringify(chats));
    }
    public addUser(userName) {
      let user = {
              userName : userName,
              isOnline : true,
            }
      let chatUsers : Array<any> = this.getUsers();
      chatUsers.push(user);
      this.setUsers(chatUsers);
      return this._utilsService.deepCopy(user);
        
    }
    public getUser(userName) : object  {
      let chatUsers = this.getUsers();

      let user = _.find(chatUsers, function(u) { return u.userName == userName;});

      return this._utilsService.deepCopy(user) || null;      
    }
}
import { Injectable } from '@angular/core';

@Injectable()
export class UtilsService {
  public deepCopy (obj, convertToType?) {
    if(!obj) return null;
    var newObj = JSON.parse(JSON.stringify(obj));
    if(convertToType == "Array") {
      newObj = Array.from(newObj)
    }
    return newObj;
  }
  public scrollToBottom(scrollContainer): void {
      try {
          scrollContainer.nativeElement.scrollTop = scrollContainer.nativeElement.scrollHeight;
      } catch(err) { }                 
  }
  public formatDate(date, format) {
    return moment(date).format(format);
  }
}

import { Component, OnInit} from '@angular/core'
import { MatDialog, MatDialogRef, MatDialogConfig } from '@angular/material';
import { FormBuilder, Validators, FormControl, FormGroup } from '@angular/forms';
import { StorageService } from '../../services/storage.service';

@Component({
  selector: 'app-login',
  templateUrl: './app/components/login/login.component.html',
  styleUrl: ['../../app.component.css']
})
export class LoginComponent implements OnInit {

    userName : string = "";
    loginForm ;
    constructor(
              
        public dialog: MatDialog,
        public dialogRef: MatDialogRef<any>,
        public formBuilder: FormBuilder,
        private _storageService: StorageService,
    ){
        dialogRef.disableClose = true;
    }
    ngOnInit(): void {
        this.loginForm = this.formBuilder.group({
                userName: new FormControl('', [Validators.required]),
        });
        
    }
    login(pleaseLogMeIn) {
        if(!pleaseLogMeIn) {
            this.closeDialog(null);
            return;
        }
        if(!this.loginForm || !this.loginForm.get("userName") || this.loginForm.invalid){
            return;
        } 
        let userName = this.loginForm.get("userName").value;
        var user = this._storageService.getUser(userName);
        if(user && !user.isOnline) { 
            this._storageService.setUserOnlineStatus(userName, true);
            this.closeDialog(user);

        } else if (user && user.isOnline) {
            alert("This user already logged in, please choose another address");
            this.loginForm.get("userName").setValue("");
            return;
        }
        else {
            user = this._storageService.addUser(userName);
            this.closeDialog(user);
        }
    }
    closeDialog(responce){
        if(this.dialogRef) this.dialogRef.close(responce);
        this.dialogRef = null;
    }
}
<h2 mat-dialog-title>Log In</h2>
<mat-dialog-content [formGroup]="loginForm" >      
    <input type="text" name="userName" required class="form-control" [formControlName]="'userName'" [placeholder] = "'Please enter Username'">
    <div class="form-field-error" *ngIf="(!loginForm.controls.userName.valid && loginForm.controls.userName.touched && loginForm.controls.userName.errors.required)">Enter Username</div>   
</mat-dialog-content>

<mat-dialog-actions>
    <button mat-button class="mat-button" (click)="login(false)">Close</button>
    <button mat-button class="mat-button mat-primary" (click)="login(true)">Save</button>
</mat-dialog-actions>
import { Component, OnInit, OnDestroy, Input, EventEmitter, Output, ElementRef, ViewChild} from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import { MatDialog, MatDialogRef, MatDialogConfig } from '@angular/material';
import { FormBuilder, Validators, FormControl, FormGroup } from '@angular/forms';
import { StorageService } from '../../services/storage.service';
import { UtilsService } from '../../services/utils.service';
@Component({
  selector: 'app-chat',
  templateUrl: './app/components/chat/chat.component.html',

})
export class ChatComponent implements OnInit, OnDestroy {
    messageForm;
    subscribeToUserUpdates; 
    isPolling = false;
    @ViewChild('msgContainer') private scrollContainer: ElementRef;
    
    private _user;    
    @Input() set user (user) {
        this._user = this.updateUser(user);
    }
    get user() {
        if(this._user.prevUpdated == this._user.lastUpdated)
            this._utilsService.scrollToBottom(this.scrollContainer);
        return this._user;
    }
    private _users;    
    @Input() set users (users) {
        let onlineUsers = _.sortBy(_.reject(users, (u) { return !u.isOnline; }), "userName");
        let offlineUsers = _.sortBy(_.reject(users, (u) { return u.isOnline; }), "userName");
        users = onlineUsers.concat(offlineUsers);
        this._users = users;
        if(this.user && !this.user.activeInterlocutor) this.setActiveInterlocutor(users[0], this.user); 
    }
    get users() {
        return this._users;
    }
    
    @Output() notifyOnAction: EventEmitter<string> = new EventEmitter<string>(); 
    constructor(
        public formBuilder: FormBuilder,
        private _storageService: StorageService,
        private _utilsService: UtilsService,
    ){

    }
    ngOnInit(): void {
        this.messageForm = this.formBuilder.group({
            message: new FormControl(),
        });

    }

    updateUser(user) { 
        let userData = this._storageService.getUserData(user.userName);
            user.chats = userData.userChats;
            
        if(!user.activeInterlocutor && this.users) this.setActiveInterlocutor(this.users[0], user);             
        return user;
    }

    setActiveInterlocutor (interlocutor, user) {
        if(!user || !interlocutor) return;
        if(user && interlocutor &&  user.activeInterlocutor && user.activeInterlocutor.userName == interlocutor.userName) return;
        user.activeInterlocutor = interlocutor;
        if(user.activeInterlocutor && !user.chats[user.activeInterlocutor.userName]) {
            let firstChat = this.createNewChat(user.userName, user.activeInterlocutor.userName);
            user.chats[user.activeInterlocutor.userName] = firstChat.messages;
            this._storageService.addChat(firstChat);
            
        } 
        if(this.messageForm && this.messageForm.get("message")) this.messageForm.get("message").setValue("");
        this._utilsService.scrollToBottom(this.scrollContainer);       
    }
    createNewChat (user, interlocutor) {
      return {
        owners : [user, interlocutor],
        messages : []
      }
    }
    sendMessage() {
        let message = this.messageForm && this.messageForm.get("message") ? this.messageForm.get("message").value : "";
        if(!message) return;
        let owners = [this.user.userName, this.user.activeInterlocutor.userName];
        let messageObj = {
            owner : this.user.userName,
            text : message,
            timestamp : new Date().toISOString(),
        }        

        this._storageService.saveMessage(messageObj, owners);
        this.messageForm.get("message").setValue("");
 
        let data = {
            action: "message_sent",
            message : messageObj,
            owners : owners,
        }
        this.notifyOnAction.emit( data);
    }

    logOut(){
        let data = {
            action: "logout",
            user: this.user,
        }
       
        this._storageService.setUserOnlineStatus(this.user.userName, false);
        this.notifyOnAction.emit( data);
    }

    deleteUser(){
         let data = {
            action: "delete_user",
            user: this.user,
        }        
        this._storageService.deleteUser(this.user.userName);
        this.notifyOnAction.emit( data);      
    }
    ngOnDestroy() {

    }

}
<div class="chat-title" style="display: inline-block; width: 100%;">
  Wellcome {{user.userName}} ! {{!users || !users.length ? "You are first user, please wait until sombody will join the chat." : "" }}{{user.activeInterlocutor ? "Chatting with " + user.activeInterlocutor.userName + " (" + (user.activeInterlocutor.isOnline ? "online" : "offline") + ")" : ""}}
</div>
<div class="users-container" *ngIf="users && users.length">
  <div class="interlocutors" >
    <div class="interlocutor" *ngFor="let interlocutor of users" (click)="setActiveInterlocutor(interlocutor, user)" [ngClass]="{'selected' : user.activeInterlocutor && interlocutor &&user.activeInterlocutor.userName == interlocutor.userName}">
      <span [ngClass]="{'online': interlocutor.isOnline, 'offline': !interlocutor.isOnline }"></span> {{interlocutor.userName}}</div>
  </div>
</div>
<div class="chat-container"  *ngIf="users && users.length && user.activeInterlocutor">
  <div class="messages-container" *ngIf="user && user.chats &&  user.chats[user.activeInterlocutor.userName]" #msgContainer >
    <div class="message" *ngFor="let msg of user.chats[user.activeInterlocutor.userName]" [ngClass]="{'by-owner' : user.userName == msg.owner }">
        {{msg.text}} 
        <span class="msg-details">({{_utilsService.formatDate(msg.timestamp, "dd/MM/YYYY, h:MM:ss")}})</span>
    </div>
  </div>
  <div class="new-message-container">
    <div [formGroup]="messageForm" class="message-form">  
      <input type="text" name="message" required class="form-control message-input" [formControlName]="'message'" [placeholder] = "'Start chatting ...'"/>
      <button class="btn" (click)="sendMessage()">Send</button>
      <br style="clear:both;"/>
    </div>
    <div class="actions">
      <button class="btn" (click)="logOut()">LogOut</button>
      <button class="btn" (click)="deleteUser()">Delete User</button>
    </div>
  </div>
</div>
.form-field-error {
  display:block;
  color: red;
}
button {
  margin-right: 10px;
}
.system-message { 
  width: 100%;
  height: 60px;
  overflow-y: auto;
  overflow-x: hidden;
}
.system-message .mat-list-base .mat-list-item {
   color: orange;
}
.mat-list-base .mat-list-item {
  height:auto !important;
}
.mat-list-base.msgs-list .mat-list-item .mat-list-item-content, .mat-list-base.msgs-list .mat-list-option .mat-list-item-content{
    display: inline-block !important;
    width: 100% !important;
    height: 20px !important;
}

.users-container, .chat-container {
  float:left; 
  width: 30%;
  border:1px solid gray;
  height: 200px;
}
.chat-container {
  width: calc(70% - 10px);
  margin-left: 10px;
  border: none;
}
.chat-container .messages-container{
  border:1px solid gray; 
  border-radius: 5px;
  width:100%; 
  height:100px;
  overflow-x: hidden; 
  overflow-y: auto
}
.chat-container .messages-container .message {
  font-size: 12px;  
}
.chat-container .messages-container .message.by-owner {
  text-align: right;
  font-style: italic;
}
.chat-container .messages-container .message .msg-details  {
  font-size: 10px;  
  color:#eee;
  font-style: italic;
}

.chat-container  .new-message-container {
  margin-top: 10px;
}

.chat-container  .new-message-container .message-form .message-input{
  float: left;
  width: calc(100% - 75px);
}
.chat-container  .new-message-container .message-form button::after {
  clear: both;
}
.chat-container  .new-message-container .message-form button{
  float: right;
  margin:0px 0px 0px 10px;
}
.chat-container  .new-message-container .actions {
  margin-top:10px;
}
.mat-list-base.chats-list .mat-list-item .mat-list-item-content, .mat-list-base.chats-list .mat-list-option .mat-list-item-content{
    display: inline-block !important;
    width: 100% !important;
    height: 250px !important;
    margin-bottom:10px;
    border: 1px solid black !important;
    border-radius: 5px;
}
.mat-list-base.chats-list .chat-item .chat-title {
  display: inline-block;
  width:100%;
  font-size: 14px;
  text-decoration: uppercase;
  color: #333;
}
.interlocutors {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
}
.interlocutors .interlocutor {
  padding: 10px;
  margin-bottom: 5px;
  border-bottom: 1px solid #9ec3ff;
}
.interlocutors .interlocutor.selected {
  background-color : #9ec3ff;
}
.interlocutors .interlocutor .online, .interlocutors .interlocutor .offline { 
  display: inline-block;
  height: 5px;
  width:5px;
  border-radius: 50%;
  background-color: blue;
}
.interlocutors .interlocutor .offline { 
  background-color: red;
}

System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  //map tells the System loader where to look for things
  map: {
    
    'app': 'app',
    
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
    '@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
    '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
    
    '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
    '@angular/material': 'npm:@angular/material/bundles/material.umd.js',
    '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
    '@angular/cdk': 'https://unpkg.com/@angular/cdk/bundles/cdk.umd.js',
    '@angular/cdk/accordion': 'https://unpkg.com/@angular/cdk/bundles/cdk-accordion.umd.js',
    '@angular/cdk/a11y': 'https://unpkg.com/@angular/cdk/bundles/cdk-a11y.umd.js',
    '@angular/cdk/bidi': 'https://unpkg.com/@angular/cdk/bundles/cdk-bidi.umd.js',
    '@angular/cdk/coercion': 'https://unpkg.com/@angular/cdk/bundles/cdk-coercion.umd.js',
    '@angular/cdk/collections': 'https://unpkg.com/@angular/cdk/bundles/cdk-collections.umd.js',
    '@angular/cdk/layout': 'https://unpkg.com/@angular/cdk/bundles/cdk-layout.umd.js',
    '@angular/cdk/keycodes': 'https://unpkg.com/@angular/cdk/bundles/cdk-keycodes.umd.js',
    '@angular/cdk/observers': 'https://unpkg.com/@angular/cdk/bundles/cdk-observers.umd.js',
    '@angular/cdk/overlay': 'https://unpkg.com/@angular/cdk/bundles/cdk-overlay.umd.js',
    '@angular/cdk/platform': 'https://unpkg.com/@angular/cdk/bundles/cdk-platform.umd.js',
    '@angular/cdk/portal': 'https://unpkg.com/@angular/cdk/bundles/cdk-portal.umd.js',
     '@angular/cdk/tree': 'https://unpkg.com/@angular/cdk/bundles/cdk-tree.umd.js',
        '@angular/cdk/text-field': 'https://unpkg.com/@angular/cdk/bundles/cdk-text-field.umd.js',
    '@angular/cdk/rxjs': 'https://unpkg.com/@angular/cdk/bundles/cdk-rxjs.umd.js',
    '@angular/cdk/scrolling': 'https://unpkg.com/@angular/cdk/bundles/cdk-scrolling.umd.js',
    '@angular/cdk/table': 'https://unpkg.com/@angular/cdk/bundles/cdk-table.umd.js',
    '@angular/cdk/stepper': 'https://unpkg.com/@angular/cdk/bundles/cdk-stepper.umd.js',
    '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
    '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
    '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
    
    'tslib': 'npm:tslib/tslib.js',
 'rxjs': 'npm:rxjs',
    'rxjs-compat': 'npm:rxjs-compat',
    'rxjs/operators': 'npm:rxjs/operators',
    'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
 'rxjs': { main: 'index.js', defaultExtension: 'js' },
    'rxjs/operators': {main: 'index.js', defaultExtension: 'js' }
  }
});

{
    "name": "@plnkr/starter-angular",
    "version": "1.0.3",
    "description": "Angular starter template",
    "dependencies": {
        "@types/underscore": "^1.8.3",
        "underscore": "^1.8.3",
        // "rxjs": "^5.4.2",

    },
    "main": "./app/main.ts",
    "plnkr": {
        "runtime": "system",
        "useHotReload": true
    }
}