[hub][init] add publish items page
diff --git a/erpnext/hub_node/__init__.py b/erpnext/hub_node/__init__.py
index a94f6b1..138ff1e 100644
--- a/erpnext/hub_node/__init__.py
+++ b/erpnext/hub_node/__init__.py
@@ -31,12 +31,18 @@
 
 	return listing
 
-
-
+#### LOCAL ITEMS
 @frappe.whitelist()
 def get_valid_items():
-	items = frappe.get_list('Item')
-	return items
+	items = frappe.get_list('Item', fields=["*"])
+	valid_items = filter(lambda x: x.image and x.description, items)
+
+	def attach_source_type(item):
+		item.source_type = "local"
+		return item
+
+	valid_items = map(lambda x: attach_source_type(x), valid_items)
+	return valid_items
 
 @frappe.whitelist()
 def get_item_favourites(start=0, limit=20, fields=["*"], order_by=None):
diff --git a/erpnext/public/js/hub/hub_listing.js b/erpnext/public/js/hub/hub_listing.js
index 218960b..856d538 100644
--- a/erpnext/public/js/hub/hub_listing.js
+++ b/erpnext/public/js/hub/hub_listing.js
@@ -26,6 +26,8 @@
 			const $target = $(e.currentTarget);
 			const route = $target.data().route;
 			frappe.set_route(route);
+		
+			e.stopPropagation();
 		});
 	}
 
@@ -43,6 +45,12 @@
 				<li class="hub-sidebar-item text-muted" data-route="marketplace/register">
 					${__('Become a seller')}
 				</li>
+				<li class="hub-sidebar-item text-muted" data-route="marketplace/profile">
+					${__('Your Profile')}
+				</li>
+				<li class="hub-sidebar-item text-muted" data-route="marketplace/publish">
+					${__('Publish Products')}
+				</li>
 			</ul>
 		`);
 
@@ -60,6 +68,9 @@
 					`<li class="hub-sidebar-item active" data-route="marketplace/home">
 						${__('All')}
 					</li>`,
+					`<li class="hub-sidebar-item" data-route="marketplace/published">
+						${__('Your Products')}
+					</li>`,
 					...categories.map(category => `
 						<li class="hub-sidebar-item text-muted" data-route="marketplace/category/${category}">
 							${__(category)}
@@ -119,6 +130,10 @@
 			this.subpages.register = new erpnext.hub.Register(this.$body);
 		}
 
+		if (route[1] === 'publish' && !this.subpages.publish) {
+			this.subpages.publish = new erpnext.hub.Publish(this.$body);
+		}
+
 
 		if (!Object.keys(this.subpages).includes(route[1])) {
 			frappe.show_not_found();
@@ -217,7 +232,7 @@
 
 	render(items) {
 		const html = get_item_card_container_html(items, __('Favourites'));
-		this.$wrapper.html(html)
+		this.$wrapper.append(html)
 	}
 }
 
@@ -241,7 +256,7 @@
 
 	render(items) {
 		const html = get_item_card_container_html(items, __(this.category));
-		this.$wrapper.html(html)
+		this.$wrapper.append(html)
 	}
 }
 
@@ -551,77 +566,42 @@
 				});
 		});
 	}
-
-	make_form() {
-		const form_html = `<form class="register-form">
-		<div class="register-title margin-bottom margin-top">
-			<b>Become a Seller</b>
-		</div>
-
-		<div class="flex">
-			<div style="flex: 0 0 140px" class="margin-right">
-				<div>			
-					<div class="missing-image attach-missing-image">
-						<i class="octicon octicon-device-camera"></i>
-						</div><div class="img-container" style="display: none;">
-						<img class="img-responsive attach-image-display">
-						<div class="img-overlay">
-							<span class="overlay-text">Change</span>
-						</div>
-					</div>
-				</div>
-			</div>
-
-			<div style="flex: 1; font-size: 12px;">
-				<div class="form-group">
-					<input class="form-control" placeholder="Company" name="company" required="required">
-				</div>
-
-				<div class="form-group">
-					<input class="form-control" placeholder="Country" name="country" required="required">
-				</div>
-
-				<div class="form-group">
-					<input class="form-control" placeholder="Company Email" name="company_email" required="required">
-				</div>
-
-				<div class="form-group">
-					<textarea class="form-control" placeholder="About Your Company" name="company_description" required="required">
-					</textarea>
-				</div>
-
-				<div class="text-right">
-					<button type="submit" class="btn btn-primary btn-sm">${__('Submit')}</button>
-				</div>
-			</div>
-		</div>
-		</form>`;
-
-
-
-		this.$form_container.append(form_html);
-
-		this.$form_container.on('submit', (e) => {
-			e.preventDefault();
-
-			const formValues = this.$form_container.find('form').serializeArray();
-
-			console.log(formValues);
-		})
-	}
 }
 
-erpnext.hub.PublishItems = class PublishItems extends SubPage {
+erpnext.hub.Publish = class Publish extends SubPage {
+	constructor(parent) {
+		super(parent);
+		// this.selected_items = [];
+	}
+
 	refresh() {
-		this.get_favourites()
+		this.get_valid_items()
 			.then(r => {
 				this.render(r.message);
 			});
 	}
 
 	render(items) {
-		const html = get_item_card_container_html(items, __(this.category));
-		this.$wrapper.html(html);
+		const html = get_item_card_container_html(
+			items, 
+
+			__('Select Products to Publish'),
+
+			__(`Only products with an image and description can be published. 
+			Please update them if an item in your inventory does not appear.`),
+
+			`<div class="hub-search-container">
+				<input type="text" class="form-control" placeholder="Search Items">
+			</div>`
+		);
+
+		const container = $(html);
+		container.addClass('static').on('click', '.hub-card', (e) => {
+			const $target = $(e.currentTarget);
+			$target.toggleClass('active');
+		});
+
+		this.$wrapper.append(container);
 	}
 
 	get_valid_items() {
@@ -629,17 +609,23 @@
 	}
 }
 
-function get_item_card_container_html(items, title) {
-	const html = (items || []).map(item => get_item_card_html(item)).join('');
+function get_item_card_container_html(items, title, subtitle='', search_html='') {
+	const items_html = (items || []).map(item => get_item_card_html(item)).join('');
 
-	return `
-		<div class="row hub-card-container">
-			<div class="col-md-12 margin-bottom">
-				<b>${title}</b>
-			</div>
-			${html}
+	const html = `<div class="row hub-card-container">
+		<div class="col-md-12 margin-bottom">
+			<b>${title}</b>
+
+			<p class="text-muted">${subtitle}</p>
+
+			${search_html}
 		</div>
-	`;
+
+		${items_html}
+
+	</div>`;
+
+	return html;
 }
 
 function get_item_card_html(item) {
@@ -648,8 +634,8 @@
 
 	const img_url = item.image;
 	const company_name = item.company_name;
-	const route = `marketplace/item/${item.hub_item_code}`;
 
+	// Subtitle
 	let subtitle = [comment_when(item.creation)];
 	const rating = get_rating(item);
 	if (rating > 0) {
@@ -660,16 +646,36 @@
 	let dot_spacer = '<span aria-hidden="true"> · </span>';
 	subtitle = subtitle.join(dot_spacer);
 
+	// Decide item link
+	const isLocal = item.source_type === "local";
+	const route = !isLocal 
+		? `marketplace/item/${item.hub_item_code}`
+		: `Form/Item/${item.item_name}`;
+
+	const card_route = isLocal ? '' : `data-route='${route}'`;
+
+	const show_local_item_button = isLocal 
+		? `<div class="overlay button-overlay" data-route='${route}' onclick="event.preventDefault();">
+				<button class="btn btn-default zoom-view">
+					<i class="octicon octicon-eye"></i>
+				</button>
+			</div>`
+		: '';
+
 	const item_html = `
 		<div class="col-md-3 col-sm-4 col-xs-6">
-			<div class="hub-card" data-route="${route}">
+			<div class="hub-card" ${card_route}>
 				<div class="hub-card-header">
-					<div class="hub-card-title ellipsis bold">${title}</div>
-					<div class="hub-card-subtitle ellipsis text-muted">${subtitle}</div>
+					<div class="title">
+						<div class="hub-card-title ellipsis bold">${title}</div>
+						<div class="hub-card-subtitle ellipsis text-muted">${subtitle}</div>
+					</div>
+					<i class="octicon octicon-check text-success"></i>
 				</div>
 				<div class="hub-card-body">
 					<img class="hub-card-image ${item.image ? '' : 'no-image'}" src="${img_url}" />
-					<div class="hub-card-overlay"></div>
+					<div class="overlay hub-card-overlay"></div>
+					${show_local_item_button}
 				</div>
 			</div>
 		</div>
@@ -904,23 +910,7 @@
 	}
 
 	renderHeader() {
-		return `<header class="level list-row-head text-muted small">
-			<div class="level-left list-header-subject">
-				<div class="list-row-col list-subject level ">
-					<img title="Riadco%20Group" alt="Riadco Group" src="https://cdn.pbrd.co/images/HdaPxcg.png">
-					<span class="level-item">Products by Blah blah</span>
-				</div>
-			</div>
-			<div class="level-left checkbox-actions">
-				<div class="level list-subject">
-					<input class="level-item list-check-all hidden-xs" type="checkbox" title="${__("Select All")}">
-					<span class="level-item list-header-meta"></span>
-				</div>
-			</div>
-			<div class="level-right">
-				${''}
-			</div>
-		</header>`;
+		return ``;
 	}
 
 	get_image_html(encoded_name, src, alt_text) {
diff --git a/erpnext/public/less/hub.less b/erpnext/public/less/hub.less
index 35e1f8d..1243743 100644
--- a/erpnext/public/less/hub.less
+++ b/erpnext/public/less/hub.less
@@ -21,6 +21,16 @@
 		font-size: @text-medium;
 	}
 
+	.btn-primary {
+		background-color: #89da28;
+		border-color: #61ca23;
+	}
+
+	.btn-primary:hover {
+		background-color: #61ca23;
+		border-color: #59b81c;
+	}
+
 	.hub-card {
 		border: 1px solid @border-color;
 		margin-bottom: 25px;
@@ -28,15 +38,33 @@
 		overflow: hidden;
 		cursor: pointer;
 
-		&:hover .hub-card-overlay {
+		&:hover .overlay {
 			display: block;
 		}
+
+		&.active {
+			.hub-card-header {
+				background-color: #f4ffe5;
+			}
+
+			.octicon-check {
+				display: inline;
+			}
+		}
 	}
 
 	.hub-card-header {
 		padding: 12px 15px;
 		height: 60px;
 		border-bottom: 1px solid @border-color;
+
+		display: flex;
+		justify-content: space-between;
+
+		.octicon-check {
+			display: none;
+			font-size: 20px;
+		}
 	}
 
 	.hub-card-body {
@@ -44,15 +72,23 @@
 		height: 200px;
 	}
 
-	.hub-card-overlay {
+	.overlay {
 		display: none;
 		position: absolute;
+	}
+
+	.hub-card-overlay {
 		top: 0;
 		width: 100%;
 		height: 100%;
 		background-color: rgba(0, 0, 0, 0.1);
 	}
 
+	.button-overlay {
+		top: 155px;
+		left: 15px;
+	}
+
 	.hub-card-image {
 		min-width: 100%;
 		width: 100%;