diff --git a/README.md b/README.md
index 2a97a3f..07acafc 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,39 @@
-# Project 2
+# Project 2 README.md file
-Web Programming with Python and JavaScript
+ ### Flack Overview:
+Flack is a simple messaging application that allows users to register with a display name, create / join channels (chat rooms) and post messages. To post a message, a user simply selects (or creates) a channel and enters text in the message box located at the bottom of the screen. Pressing the "Post" button, adds the message to the active lists and updates anyone else in the channel
+
+##Personal Touch:
+The personal touch includes the addition of messages badges in the user list that tracks and displays the number of messages posted by each user
+
+## Notes:
+
+1) The application uses pop-ups to prompt the user for their display name and channel - the browser MUST allow pop-ups for proper functionality of the application. Here is what the prompt looks like:
+
+
+
+2) To add channels select the plus (+) icon next to "Channels" - the "General" channel is provided by default just like Slack
+
+3) New users joining the app are displayed in the left side Users column
+
+
+
+4) The application has been tested mostly on Chrome and some on Firefox.
+
+## Key files and resources:
+1) application.py - primary flack application that serves the index.html file, tracks channels / messages and manages user websocket connections.
+
+2) index.js - client side javascript file which is the core of this application. Handles client interactions with the server via websockets
+
+3) index.html - the single page application screen base on boostrap
+
+4) static resources - this includes the index.html file (mentioned above), three graphic files (addGraphic.png,
+favicon.ico, and flackUser.png) and the style.css which is mostly used to to properly configure messages
+
+5) requirements.txt - a list of dependent python modules necessary for running the server
+
+6) README.md - this file
+
+
+
+
diff --git a/application.py b/application.py
index e8edb33..98b8f83 100644
--- a/application.py
+++ b/application.py
@@ -1,13 +1,113 @@
import os
-
-from flask import Flask
+import datetime
+from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
+
+# Configure to use filesystem session type
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
+app.config["SESSION_PERMANENT"] = False
+app.config["SESSION_TYPE"] = "filesystem"
+
socketio = SocketIO(app)
+app.secret_key = os.urandom(32)
+# Global lists and dicts
+channels = {}
+message = {}
+messages = []
+users = {}
+
+MESSAGELIMIT = 100
@app.route("/")
+@app.route("/index")
def index():
- return "Project 2: TODO"
+ return render_template("index.html")
+
+# set up a user who is connecting to the server
+@socketio.on('user connect')
+def connect(data):
+ global channels
+ messages = []
+
+ # check if channels empty - first time through
+ if not channels:
+ # get server date / time
+ current = datetime.datetime.now()
+
+ displayHeader = " | "+str(current.hour)+":"+str(current.minute)+" | "+str(current.month)+" "+str(current.day)+", "+str(current.year)
+
+ # always provide a general channel just like slack
+ messages.insert(0, {'username': "System",
+ 'channel': "General",
+ 'datetime': displayHeader,
+ 'message': "Welcome to Flack!"})
+
+ channels['General'] = messages
+ emit("select channel", channels, broadcast=False)
+ else:
+ # already have some channels so communicate
+ updatedChannels = []
+
+ # extract updated list of channels
+ for key in channels.keys():
+ updatedChannels.append(key)
+
+ # emit current channel list
+ emit("update channels", {'channel': updatedChannels}, broadcast=True)
+
+ # check if user already connected
+ if (data["username"] not in users.values()):
+
+ # if users{} empty - first time through
+ if not users:
+ users.update({0: data["username"]})
+ else:
+ # determine next dict key and increment to add new user
+ dictKeys = list(users.keys())
+ nextKey = max(dictKeys)+1
+ users.update({nextKey: data["username"]})
+
+ # let everyone know a user has joined
+ print(users)
+ emit("add user", users, broadcast=True)
+
+
+@socketio.on('get channel')
+def getChannel(data):
+ global channels
+ updatedChannels = []
+
+ # emit current channel list
+ emit("select channel", channels, broadcast=False)
+
+@socketio.on('new channel')
+def addChannel(data):
+ global channels
+ updatedChannels = []
+
+ # add the new channel to the server channel list
+ channels.update({data['channel']: []})
+
+ # extract updated list of channels
+ for key in channels.keys():
+ updatedChannels.append(key)
+
+ # let everyone know a new channel is available
+ emit("update channels", {'channel': updatedChannels}, broadcast=True)
+
+@socketio.on('post message')
+def addMessage(data):
+ global channels
+
+ # add the message, but keep lists (message queue) to 100
+ if len(channels[data['channel']]) > MESSAGELIMIT:
+ channels.setdefault(data['channel'], []).append(data)
+ channels.setdefault(data['channel'], []).pop(0)
+ else:
+ channels.setdefault(data['channel'], []).append(data)
+
+ # notify everyone of new message
+ emit("add message", data, broadcast=True)
diff --git a/requirements.txt b/requirements.txt
index 55ef84d..260d497 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
Flask
Flask-SocketIO
+datetime
\ No newline at end of file
diff --git a/static/FlackUser.png b/static/FlackUser.png
new file mode 100644
index 0000000..1b41190
Binary files /dev/null and b/static/FlackUser.png differ
diff --git a/static/Index.js b/static/Index.js
new file mode 100644
index 0000000..fd2733a
--- /dev/null
+++ b/static/Index.js
@@ -0,0 +1,269 @@
+// connect to websocket
+var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
+
+// globals
+var username;
+var activeChannel;
+var channelList = [];
+
+var months = ["January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December"];
+
+// prompt user via popup to enter a new channel
+function selectChannel(channelName) {
+ console.log("selectChannel: " + channelName);
+
+ // make sure messages are going to the right channel
+ activeChannel = channelName;
+ localStorage.setItem('channel', activeChannel);
+
+ // source of truth is on the server - request message for the selected channel
+ socket.emit('get channel', {'channel': channelName});
+}
+
+
+// load prior channel state - part of project requirements
+function loadChannel() {
+ console.log("loadChannel");
+ // does user have a prior active channel - must logout cleanly for this to work correctly
+ if (!localStorage.getItem('channel')) {
+ localStorage.setItem('channel', "General");
+ activeChannel = "General";
+ } else {
+ // otherwise we load previous
+ activeChannel = localStorage.getItem('channel');
+ }
+ socket.emit('get channel', {'channel': activeChannel});
+}
+
+
+// builds the channel list
+function buildChannelList(activeChannel) {
+ console.log("buildChannel - length = "+channelList.length);
+ // clear channels
+ var userList = document.getElementById('channels');
+ channels.innerHTML = '';
+
+ // loop through channel list - set active channel
+ for (let i = 0; i < channelList.length; i++) {
+ console.log("constructing channel list...");
+ // building a bootstrap formatted channel list
+ let button = document.createElement('button');
+ if (channelList[i] == activeChannel) {
+ button.setAttribute('class', "list-group-item list-group-item-action active");
+ } else {
+ button.setAttribute('class', "list-group-item list-group-item-action");
+ }
+ button.setAttribute('type', "button");
+ button.setAttribute('onclick', "selectChannel('"+channelList[i]+"');");
+ button.innerHTML = channelList[i];
+ console.log("BUTTON: ", button);
+ document.querySelector('#channels').append(button);
+ }
+ console.log("something went wrong....");
+}
+
+
+// build current message list - user selected another channel
+function buildMessageList(messageList) {
+ console.log("Building message: ", messageList );
+
+ // clear current message list
+ var oldMessages = document.getElementById('messages');
+ messages.innerHTML = '';
+
+ //build new message list from server
+ for (let i = 0; i < messageList.length; i++) {
+
+ // building a bootstrap formatted user message
+ let msgHeader = "