messages
diff --git a/erpnext/utilities/page/messages/messages.css b/erpnext/utilities/page/messages/messages.css
index e69de29..81260ab 100644
--- a/erpnext/utilities/page/messages/messages.css
+++ b/erpnext/utilities/page/messages/messages.css
@@ -0,0 +1,35 @@
+#message-post-text {
+	height: 3em;
+}
+
+#message-list {
+	margin: 0px 40px;
+}
+
+.message {
+	border-radius: 5px;
+	max-width: 60%;
+	min-width: 40%;
+	padding: 7px;
+	margin-bottom: 7px;
+}
+
+.message .help {
+	margin-bottom: 0px;
+	padding-bottom: 0px;
+	color: #888;
+	font-size: 11px;
+}
+
+.message-other {
+	background-color: #EBFF9C;
+	border: 1px solid #C3CF78;
+	float: right;
+	text-align: right;
+}
+
+.message-self {
+	background-color: #eee;
+	border: 1px solid #ccc;
+	float: left;	
+}
\ No newline at end of file
diff --git a/erpnext/utilities/page/messages/messages.html b/erpnext/utilities/page/messages/messages.html
index e69de29..b645d3f 100644
--- a/erpnext/utilities/page/messages/messages.html
+++ b/erpnext/utilities/page/messages/messages.html
@@ -0,0 +1,28 @@
+<div class="layout-wrapper layout-wrapper-background">
+	<div class="layout-main-section">
+		<a class="close" onclick="window.history.back();">&times;</a>		
+		<h1>Messages</h1>
+		<div class="well">
+			<textarea id="message-post-text"></textarea>
+			<button disabled="disabled" id="message-post" class="btn btn-small"><i class="icon-play"></i> Post</button>
+		</div>
+		<div id="message-list">
+		</div>
+	</div>
+	<div class="layout-side-section">
+		<div class="psidebar">
+			<div class="section">
+				<div class="section-head">
+					Messages By
+				</div>
+				<div class="section-body">
+					<div class="section-item">
+						<a href="#!messages"><b>All messages</b></a>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div style="clear: both;">
+	</div>	
+</div>
\ No newline at end of file
diff --git a/erpnext/utilities/page/messages/messages.js b/erpnext/utilities/page/messages/messages.js
index e69de29..b59a212 100644
--- a/erpnext/utilities/page/messages/messages.js
+++ b/erpnext/utilities/page/messages/messages.js
@@ -0,0 +1,118 @@
+wn.provide('erpnext.messages');
+
+wn.pages.messages.onload = function(wrapper) {
+	erpnext.messages.show_active_users();
+	erpnext.messages.make_list();
+	
+	// post message
+	$('#message-post').click(function() {
+		var txt = $('#message-post-text').val();
+		if(txt) {
+			wn.call({
+				module:'utilities',
+				page:'messages',
+				method:'post',
+				args: {
+					txt: txt,
+					contact: erpnext.messages.contact
+				},
+				callback:function(r,rt) {
+					$('#message-post-text').val('')
+					erpnext.messages.list.run();
+				},
+				btn: this
+			});
+		}
+	});
+	
+	// enable, disable button
+	$('#message-post-text').keyup(function() {
+		if($(this).val()) {
+			$('#message-post').attr('disabled', false);
+		} else {
+			$('#message-post').attr('disabled', true);
+		}
+	})
+}
+
+wn.pages.messages.onshow = function(wrapper) {
+	erpnext.messages.show();
+	setTimeout(erpnext.messages.refresh, 5000);
+}
+
+erpnext.messages = {
+	show: function() {
+		var contact = erpnext.messages.get_contact();
+
+		// can't send message to self
+		$(wn.pages.messages).find('.well').toggle(contact==user ? false : true);
+
+		$(wn.pages.messages).find('h1:first').html('Messages: ' 
+			+ (user==contact ? 'From everyone' : wn.boot.user_fullnames[contact]))
+
+		erpnext.messages.contact = contact;
+		erpnext.messages.list.opts.args.contact = contact;
+		erpnext.messages.list.run();
+		
+	},
+	// check for updates every 5 seconds if page is active
+	refresh: function() {
+		setTimeout(erpnext.messages.refresh, 10000);
+		if(page_body.cur_page_label != 'messages') return;
+		erpnext.messages.show();
+	},
+	get_contact: function() {
+		var route = location.hash;
+		if(route.indexOf('/')!=-1) {
+			var name = decodeURIComponent(route.split('/')[1]);
+			if(name.indexOf('__at__')!=-1) {
+				name = name.replace('__at__', '@');
+			}
+			return name;
+		}
+		return user;	
+	},
+	make_list: function() {
+		erpnext.messages.list = new wn.widgets.Listing({
+			parent: $('#message-list').get(0),
+			method: 'utilities.page.messages.messages.get_list',
+			args: {
+				contact: null
+			},
+			render_row: function(wrapper, data) {
+				data.creation = dateutil.comment_when(data.creation);
+				data.comment_by_fullname = wn.boot.user_fullnames[data.owner];
+
+				if(data.owner==user) {
+					data.cls = 'message-self';
+					data.comment_by_fullname = 'You';	
+				} else {
+					data.cls = 'message-other'
+				}
+
+				wrapper.innerHTML = repl('<div class="message %(cls)s"><b>%(comment)s</b>\
+					<div class="help">by %(comment_by_fullname)s, %(creation)s</div></div>\
+					<div style="clear: both;"></div>', data);
+			}
+		});
+	},
+	show_active_users: function() {
+		wn.call({
+			module:'utilities',
+			page:'messages',
+			method:'get_active_users',
+			callback: function(r,rt) {
+				var $body = $(wn.pages.messages).find('.section-body');
+				for(var i in r.message) {
+					var p = r.message[i];
+					p.fullname = wn.boot.user_fullnames[p.name];
+					p.name = p.name.replace('@', '__at__');
+					$body.append(repl('<div class="section-item">\
+						<a href="#!messages/%(name)s">%(fullname)s</a></div>', p))
+				}
+			}
+		});
+	}
+}
+
+
diff --git a/erpnext/utilities/page/messages/messages.py b/erpnext/utilities/page/messages/messages.py
index e69de29..0adeb8d 100644
--- a/erpnext/utilities/page/messages/messages.py
+++ b/erpnext/utilities/page/messages/messages.py
@@ -0,0 +1,43 @@
+import webnotes
+
+@webnotes.whitelist()
+def get_list(arg=None):
+	"""get list of messages"""
+	webnotes.form_dict['limit_start'] = int(webnotes.form_dict['limit_start'])
+	webnotes.form_dict['limit_page_length'] = int(webnotes.form_dict['limit_page_length'])
+	webnotes.form_dict['user'] = webnotes.session['user']
+
+	if webnotes.form_dict['contact'] == webnotes.session['user']:
+		return webnotes.conn.sql("""select * from `tabComment Widget Record` 
+		where (owner=%(contact)s or comment_docname=%(user)s)
+		and comment_doctype in ('My Company', 'Message')
+		order by creation desc
+		limit %(limit_start)s, %(limit_page_length)s""", webnotes.form_dict, as_dict=1)		
+	else:
+		return webnotes.conn.sql("""select * from `tabComment Widget Record` 
+		where (owner=%(contact)s and comment_docname=%(user)s)
+		or (owner=%(user)s and comment_docname=%(contact)s)
+		and comment_doctype in ('My Company', 'Message')
+		order by creation desc
+		limit %(limit_start)s, %(limit_page_length)s""", webnotes.form_dict, as_dict=1)
+		
+
+@webnotes.whitelist()
+def get_active_users(arg=None):
+	return webnotes.conn.sql("""select name from tabProfile 
+		where enabled=1 and
+		name not in ('Administrator', 'Guest') 
+		order by first_name""", as_dict=1)
+
+@webnotes.whitelist()
+def post(arg=None):
+	"""post message"""
+	import json
+	arg = json.loads(arg)
+	from webnotes.model.doc import Document
+	d = Document('Comment Widget Record')
+	d.comment = arg['txt']
+	d.comment_docname = arg['contact']
+	d.comment_doctype = 'Message'
+	d.save()
+	
\ No newline at end of file
diff --git a/erpnext/utilities/page/todo/todo.js b/erpnext/utilities/page/todo/todo.js
index 2691912..77e4625 100644
--- a/erpnext/utilities/page/todo/todo.js
+++ b/erpnext/utilities/page/todo/todo.js
@@ -126,7 +126,7 @@
 	});
 }
 
-pscript.onload_todo = function() {
+wn.pages.todo.onload = function() {
 	// load todos
 	erpnext.todo.refresh();
 }
\ No newline at end of file