Merge branch 'hub-redesign' of https://github.com/netchampfaris/erpnext into hub-redesign
diff --git a/erpnext/hub_node/__init__.py b/erpnext/hub_node/__init__.py
index d15785f..6dc654b 100644
--- a/erpnext/hub_node/__init__.py
+++ b/erpnext/hub_node/__init__.py
@@ -2,7 +2,7 @@
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
-import frappe, requests, json
+import frappe, requests, json, time
 from frappe.utils import now, nowdate, cint
 from frappe.utils.nestedset import get_root_of
 from frappe.contacts.doctype.contact.contact import get_default_contact
@@ -47,9 +47,15 @@
 #### LOCAL ITEMS
 @frappe.whitelist()
 def get_valid_items(search_value=''):
-	items = frappe.get_list('Item', fields=["*"], filters={
-		'item_name': ['like', '%' + search_value + '%']
-	})
+	items = frappe.get_list(
+		'Item',
+		fields=["*"],
+		filters={
+			'item_name': ['like', '%' + search_value + '%'],
+			'publish_in_hub': 0
+		},
+		order_by="modified desc"
+	)
 
 	valid_items = filter(lambda x: x.image and x.description, items)
 
@@ -61,12 +67,13 @@
 	return valid_items
 
 @frappe.whitelist()
-def publish_selected_items(items_to_publish, items_to_unpublish):
+def publish_selected_items(items_to_publish):
 	for item_code in json.loads(items_to_publish):
 		frappe.db.set_value('Item', item_code, 'publish_in_hub', 1)
 
-	for item_code in json.loads(items_to_unpublish):
-		frappe.db.set_value('Item', item_code, 'publish_in_hub', 0)
+	# frappe.db.set_value("Hub Settings", "Hub Settings", "sync_in_progress", 1)
+	# time.sleep(10)
+	# frappe.db.set_value("Hub Settings", "Hub Settings", "sync_in_progress", 0)
 
 	hub_settings = frappe.get_doc('Hub Settings')
 	hub_settings.sync()
diff --git a/erpnext/hub_node/doctype/hub_settings/hub_settings.js b/erpnext/hub_node/doctype/hub_settings/hub_settings.js
index 29d870b..4bd3333 100644
--- a/erpnext/hub_node/doctype/hub_settings/hub_settings.js
+++ b/erpnext/hub_node/doctype/hub_settings/hub_settings.js
@@ -1,53 +1,23 @@
 frappe.ui.form.on("Hub Settings", {
 	refresh: function(frm) {
+		frm.disable_save();
 		frm.add_custom_button(__('Logs'),
 			() => frappe.set_route('List', 'Data Migration Run', {
 				data_migration_plan: 'Hub Sync'
 			}));
 
-		frm.trigger("enabled");
-
 		if (frm.doc.enabled) {
 			frm.add_custom_button(__('Sync'),
 				() => frm.call('sync'));
 		}
 	},
-	onload: function(frm) {
-		let token = frappe.urllib.get_arg("access_token");
-		if(token) {
-			let email = frm.get_field("user");
-			console.log('token', frappe.urllib.get_arg("access_token"));
-
-			get_user_details(frm, token, email);
-			let row = frappe.model.add_child(frm.doc, "Hub Users", "users");
-			row.user = frappe.session.user;
-		}
-
-		if(!frm.doc.country) {
-			frm.set_value("country", frappe.defaults.get_default("Country"));
-		}
-		if(!frm.doc.company) {
-			frm.set_value("company", frappe.defaults.get_default("Company"));
-		}
-		if(!frm.doc.user) {
-			frm.set_value("user", frappe.session.user);
-		}
-	},
+	onload: function(frm) { },
 	onload_post_render: function(frm) {
 		if(frm.get_field("unregister_from_hub").$input)
 			frm.get_field("unregister_from_hub").$input.addClass("btn-danger");
 	},
 	on_update: function(frm) {
 	},
-	enabled: function(frm) {
-		if(!frm.doc.enabled) {
-			frm.trigger("set_enable_hub_primary_button");
-		} else {
-			frm.page.set_primary_action(__("Save Settings"), () => {
-				frm.save();
-			});
-		}
-	},
 
 	hub_user_email: function(frm) {
 		if(frm.doc.hub_user_email){
@@ -55,39 +25,6 @@
 		}
 	},
 
-	set_enable_hub_primary_button: (frm) => {
-		frm.page.set_primary_action(__("Enable Hub"), () => {
-			if(frappe.session.user === "Administrator") {
-				frappe.msgprint(__("Please login as another user."))
-			} else {
-				// frappe.verify_password(() => {
-
-				// } );
-
-				frm.trigger("call_pre_reg");
-				// frm.trigger("call_register");
-
-			}
-		});
-	},
-
-	call_pre_reg: (frm) => {
-		this.frm.call({
-			doc: this.frm.doc,
-			method: "pre_reg",
-			args: {},
-			freeze: true,
-			callback: function(r) {
-				console.log(r.message);
-				authorize(frm, r.message.client_id, r.message.redirect_uri);
-			},
-			onerror: function() {
-				frappe.msgprint(__("Wrong Password"));
-				frm.set_value("enabled", 0);
-			}
-		});
-	},
-
 	call_register: (frm) => {
 		this.frm.call({
 			doc: this.frm.doc,
@@ -111,67 +48,3 @@
 		});
 	},
 });
-
-// let hub_url = 'https://hubmarket.org'
-let hub_url = 'http://159.89.175.122'
-// let hub_url = 'http://erpnext.hub:8000'
-
-function authorize(frm, client_id, redirect_uri) {
-
-    // queryStringData is details of OAuth Client (Implicit Grant) on Custom App
-	var queryStringData = {
-		response_type : "token",
-		client_id : client_id,
-        redirect_uri : redirect_uri
-	}
-
-    // Get current raw route and build url
-    const route = "/desk#" + frappe.get_raw_route_str();
-    localStorage.removeItem("route");  // Clear previously set route if any
-	localStorage.setItem("route", route);
-
-	// Go authorize!
-	let api_route = "/api/method/frappe.integrations.oauth2.authorize?";
-	let url = hub_url + api_route + $.param(queryStringData);
-	window.location.replace(url, 'test');
-}
-
-function get_user_details(frm, token, email) {
-	console.log('user_details');
-    var route = localStorage.getItem("route");
-    if (token && route) {
-        // Clean up access token from route
-		frappe.set_route(frappe.get_route().join("/"))
-
-        // query protected resource e.g. Hub Items with token
-        var call = {
-            "async": true,
-            "crossDomain": true,
-            "url": hub_url + "/api/resource/User",
-			"method": "GET",
-			"data": {
-				// "email": email,
-				"fields": '["name", "first_name", "language"]',
-				"limit_page_length": 1
-			},
-            "headers": {
-                "authorization": "Bearer " + token,
-                "content-type": "application/x-www-form-urlencoded"
-            }
-		}
-        $.ajax(call).done(function (response) {
-			// display openid profile
-			console.log('response', response);
-
-			let data = response.data[0];
-			frm.set_value("enabled", 1);
-			frm.set_value("hub_username", data.first_name);
-			frm.set_value("hub_user_status", "Starter");
-			frm.set_value("language", data.language);
-			frm.save();
-
-            // clear route from localStorage
-            localStorage.removeItem("route");
-        });
-    }
-}
diff --git a/erpnext/hub_node/doctype/hub_settings/hub_settings.json b/erpnext/hub_node/doctype/hub_settings/hub_settings.json
index c742c57..61ef48c 100644
--- a/erpnext/hub_node/doctype/hub_settings/hub_settings.json
+++ b/erpnext/hub_node/doctype/hub_settings/hub_settings.json
@@ -51,6 +51,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "sync_in_progress", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Sync in Progress", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "company_registered", 
    "fieldtype": "Check", 
    "hidden": 0, 
@@ -611,7 +643,7 @@
  "issingle": 1, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-07-24 18:53:09.442523", 
+ "modified": "2018-07-26 15:56:36.104768", 
  "modified_by": "cave@aperture.com", 
  "module": "Hub Node", 
  "name": "Hub Settings", 
diff --git a/erpnext/hub_node/doctype/hub_settings/hub_settings.py b/erpnext/hub_node/doctype/hub_settings/hub_settings.py
index 561f1f0..621229c 100644
--- a/erpnext/hub_node/doctype/hub_settings/hub_settings.py
+++ b/erpnext/hub_node/doctype/hub_settings/hub_settings.py
@@ -46,10 +46,12 @@
 		doc = frappe.get_doc({
 			'doctype': 'Data Migration Run',
 			'data_migration_plan': 'Hub Sync',
-			'data_migration_connector': 'Hub Connector'
+			'data_migration_connector': 'Hub Connector',
 		}).insert()
 
+		# self.sync_in_progress = 1
 		doc.run()
+		# self.sync_in_progress = 0
 
 	def pre_reg(self):
 		site_name = frappe.local.site + ':' + str(frappe.conf.webserver_port)
diff --git a/erpnext/public/js/hub/hub_listing.js b/erpnext/public/js/hub/hub_listing.js
index 7a82a91..07064f4 100644
--- a/erpnext/public/js/hub/hub_listing.js
+++ b/erpnext/public/js/hub/hub_listing.js
@@ -154,10 +154,16 @@
 			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 (route[1] === 'profile' && !this.subpages.profile) {
+			this.subpages.profile = new erpnext.hub.Profile(this.$body, {data: this.hub_settings});
 		}
 
+		if (route[1] === 'publish' && !this.subpages.publish) {
+			this.subpages.publish = new erpnext.hub.Publish(
+				this.$body,
+				{sync_in_progress: this.hub_settings.sync_in_progress}
+			);
+		}
 
 		if (!Object.keys(this.subpages).includes(route[1])) {
 			frappe.show_not_found();
@@ -171,9 +177,9 @@
 }
 
 class SubPage {
-	constructor(parent) {
+	constructor(parent, options) {
 		this.$parent = $(parent);
-		this.make_wrapper();
+		this.make_wrapper(options);
 	}
 
 	make_wrapper() {
@@ -603,9 +609,60 @@
 	}
 }
 
-erpnext.hub.Publish = class Publish extends SubPage {
+erpnext.hub.Profile = class Profile extends SubPage {
+	constructor(parent, profile_data) {
+		super(parent);
+		this.profile_data = profile_data;
+	}
+
 	make_wrapper() {
 		super.make_wrapper();
+		const profile_html = `<div class="hub-item-container">
+			<div class="row visible-xs">
+				<div class="col-xs-12 margin-bottom">
+					<button class="btn btn-xs btn-default" data-route="marketplace/home">Back to home</button>
+				</div>
+			</div>
+			<div class="row">
+				<div class="col-md-3">
+					<div class="hub-item-image">
+						<img src="${'gd'}">
+					</div>
+				</div>
+				<div class="col-md-6">
+					<h2>${'title'}</h2>
+					<div class="text-muted">
+						<p>${'where'}${'dot_spacer'}${'when'}</p>
+						<p>${'rating_html'}${'rating_count'}</p>
+					</div>
+					<hr>
+					<div class="hub-item-description">
+					${'description' ?
+						`<b>${__('Description')}</b>
+						<p>${'description'}</p>
+						` : __('No description')
+					}
+					</div>
+				</div>
+			</div>
+		</div>`;
+
+		this.$wrapper.html(profile_html);
+	}
+
+	refresh() {}
+
+	render() {}
+}
+erpnext.hub.Publish = class Publish extends SubPage {
+	make_wrapper(options) {
+		super.make_wrapper();
+		this.sync_in_progress = options.sync_in_progress;
+
+		this.load_publish_page();
+	}
+
+	load_publish_page() {
 		const title_html = `<b>${__('Select Products to Publish')}</b>`;
 		const info = `<p class="text-muted">${__("Status decided by the 'Publish in Hub' field in Item.")}</p>`;
 		const subtitle_html = `
@@ -635,9 +692,6 @@
 			</div>
 
 			${search_html}
-
-			${select_all_button}
-			${deselect_all_button}
 		`);
 
 		this.$wrapper.append(subpage_header);
@@ -646,15 +700,8 @@
 	}
 
 	setup_events() {
-		this.$wrapper.find('.select-all').on('click', () => {
-			this.$wrapper.find('.hub-card').addClass('active');
-		});
-
-		this.$wrapper.find('.deselect-all').on('click', () => {
-			this.$wrapper.find('.hub-card').removeClass('active');
-		});
-
 		this.$wrapper.find('.publish-items').on('click', () => {
+			this.load_publishing_state();
 			this.publish_selected_items()
 				.then(r => {
 					frappe.msgprint('check');
@@ -673,6 +720,11 @@
 	}
 
 	get_items_and_render() {
+		if(this.sync_in_progress) {
+			this.load_publishing_state();
+			return;
+		}
+
 		this.$wrapper.find('.hub-card-container').empty();
 		this.get_valid_items()
 			.then(r => {
@@ -689,6 +741,12 @@
 		items_container.addClass('static').on('click', '.hub-card', (e) => {
 			const $target = $(e.currentTarget);
 			$target.toggleClass('active');
+
+			// Get total items
+			const total_items = this.$wrapper.find('.hub-card.active').length;
+			const more_than_one = total_items > 1;
+			this.$wrapper.find('.publish-items')
+				.html(__('Publish ' + total_items + ' item' + (more_than_one ? 's' : '')));
 		});
 
 		this.$wrapper.append(items_container);
@@ -703,29 +761,33 @@
 		);
 	}
 
+	load_publishing_state() {
+		this.$wrapper.html(get_empty_state(
+			'Publishing items ... You will be notified once published.'
+		));
+	}
+
 	publish_selected_items() {
 		const items_to_publish = [];
-		const items_to_unpublish = [];
-		this.$wrapper.find('.hub-card').map(function () {
-			const active = $(this).hasClass('active');
-
-			if(active) {
-				items_to_publish.push($(this).attr("data-id"));
-			} else {
-				items_to_unpublish.push($(this).attr("data-id"));
-			}
+		this.$wrapper.find('.hub-card.active').map(function () {
+			items_to_publish.push($(this).attr("data-id"));
 		});
 
 		return frappe.call(
 			'erpnext.hub_node.publish_selected_items',
 			{
-				items_to_publish: items_to_publish,
-				items_to_unpublish: items_to_unpublish
+				items_to_publish: items_to_publish
 			}
 		);
 	}
 }
 
+function get_empty_state(message) {
+	return `<div class="empty-state flex">
+		<p class="text-muted">${message}</p>
+	</div>`
+}
+
 function get_item_card_container_html(items, title='') {
 	const items_html = (items || []).map(item => get_item_card_html(item)).join('');
 
diff --git a/erpnext/public/less/hub.less b/erpnext/public/less/hub.less
index 8c7392a..bd503fe 100644
--- a/erpnext/public/less/hub.less
+++ b/erpnext/public/less/hub.less
@@ -156,6 +156,11 @@
 		padding: 15px 25px;
 	}
 
+	.empty-state {
+		justify-content: center;
+		padding-top: 159px;
+	}
+
 	.form-container {
 		.frappe-control {
 			max-width: 100% !important;