[hub] Realtime Sync Progress
- Show progress from the migration plan
- Show products being synced
- Disallow publishing in sync state
diff --git a/erpnext/hub_node/doctype/hub_settings/hub_settings.json b/erpnext/hub_node/doctype/hub_settings/hub_settings.json
index a5338e9..10bb959 100644
--- a/erpnext/hub_node/doctype/hub_settings/hub_settings.json
+++ b/erpnext/hub_node/doctype/hub_settings/hub_settings.json
@@ -373,7 +373,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "enabled",
+ "depends_on": "",
"fieldname": "publish_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -675,8 +675,8 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-07-28 00:48:21.210413",
- "modified_by": "cave@aperture.com",
+ "modified": "2018-07-30 08:01:09.024358",
+ "modified_by": "Administrator",
"module": "Hub Node",
"name": "Hub Settings",
"name_case": "",
diff --git a/erpnext/public/js/hub/marketplace.js b/erpnext/public/js/hub/marketplace.js
index 4c3e9ef..28309f3 100644
--- a/erpnext/public/js/hub/marketplace.js
+++ b/erpnext/public/js/hub/marketplace.js
@@ -825,17 +825,44 @@
erpnext.hub.Publish = class Publish extends SubPage {
make_wrapper() {
super.make_wrapper();
+ this.items_to_publish = [];
+ this.unpublished_items = [];
+ this.fetched_items = [];
+ }
+
+ refresh() {
if(!hub.settings.sync_in_progress) {
- this.make_publish_header();
+ this.make_publish_ready_state();
} else {
- this.show_publishing_state();
+ this.make_publish_in_progress_state();
}
}
- make_publish_header() {
- const title_html = `<b>${__('Select Products to Publish')}</b>`;
+ make_publish_ready_state() {
+ this.$wrapper.empty();
+ this.$wrapper.append(this.get_publishing_header());
- const info = `<p class="text-muted">${__("Status decided by the 'Publish in Hub' field in Item.")}</p>`;
+ make_search_bar({
+ wrapper: this.$wrapper,
+ on_search: keyword => {
+ this.search_value = keyword;
+ this.get_items_and_render();
+ },
+ placeholder: __('Search Items')
+ });
+
+ this.setup_publishing_events();
+
+ if(hub.settings.last_sync) {
+ this.show_message(`Last sync was <a href="#marketplace/profile">${hub.settings.last_sync}</a>.
+ <a href="#marketplace/my-products">See your Published Products</a>.`);
+ }
+
+ this.get_items_and_render();
+ }
+
+ get_publishing_header() {
+ const title_html = `<b>${__('Select Products to Publish')}</b>`;
const subtitle_html = `<p class="text-muted">
${__(`Only products with an image, description and category can be published.
@@ -847,10 +874,7 @@
<span class="hidden-xs">${__('Publish')}</span>
</button>`;
- const select_all_button = `<button class="btn btn-secondary btn-default btn-xs margin-right select-all">${__('Select All')}</button>`;
- const deselect_all_button = `<button class="btn btn-secondary btn-default btn-xs deselect-all">${__('Deselect All')}</button>`;
-
- const subpage_header = $(`
+ return $(`
<div class='subpage-title flex'>
<div>
${title_html}
@@ -859,27 +883,12 @@
${publish_button_html}
</div>
`);
-
- this.$wrapper.append(subpage_header);
-
- make_search_bar({
- wrapper: this.$wrapper,
- on_search: keyword => {
- this.search_value = keyword;
- this.get_items_and_render();
- },
- placeholder: __('Search Items')
- });
-
- this.setup_events();
}
- setup_events() {
+ setup_publishing_events() {
this.$wrapper.find('.publish-items').on('click', () => {
this.publish_selected_items()
- .then(r => {
- console.log(`${r.message} items will be published`);
- });
+ .then(this.refresh.bind(this))
});
this.$wrapper.on('click', '.hub-card', (e) => {
@@ -903,33 +912,95 @@
});
}
- get_items_and_render() {
- if(hub.settings.sync_in_progress) {
- this.show_publishing_state();
- return;
- }
+ show_message(message) {
+ const $message = $(`<div class="subpage-message">
+ <p class="text-muted flex">
+ <span>
+ ${message}
+ </span>
+ <i class="octicon octicon-x text-extra-muted"></i>
+ </p>
+ </div>`);
- this.$wrapper.find('.hub-card-container').empty();
- this.get_valid_items()
- .then(r => {
- this.render(r.message);
- });
+ $message.find('.octicon-x').on('click', () => {
+ $message.remove();
+ });
+
+ this.$wrapper.prepend($message);
}
- refresh() {
- if (hub.settings.sync_in_progress) {
- this.load_publishing_state();
+ make_publish_in_progress_state() {
+ this.$wrapper.empty();
+
+ this.$wrapper.append(this.show_publish_progress());
+
+ const subtitle_html = `<p class="text-muted">
+ ${__(`Only products with an image, description and category can be published.
+ Please update them if an item in your inventory does not appear.`)}
+ </p>`;
+
+ this.$wrapper.append(subtitle_html);
+
+ // Show search list with only desctiption, and don't set any events
+ make_search_bar({
+ wrapper: this.$wrapper,
+ on_search: keyword => {
+ this.search_value = keyword;
+ this.get_items_and_render();
+ },
+ placeholder: __('Search Items')
+ });
+
+ this.get_items_and_render();
+ }
+
+ show_publish_progress() {
+ const items_to_publish = this.items_to_publish.length
+ ? this.items_to_publish
+ : JSON.parse(hub.settings.custom_data);
+
+ const $publish_progress = $(`<div class="sync-progress">
+ <p><b>${__(`Syncing ${items_to_publish.length} Products`)}</b></p>
+ <div class="progress">
+ <div class="progress-bar" style="width: 12.875%"></div>
+ </div>
+
+ </div>`);
+
+ const items_to_publish_container = $(get_item_card_container_html(
+ items_to_publish, '', get_local_item_card_html));
+
+ items_to_publish_container.find('.hub-card').addClass('active');
+
+ $publish_progress.append(items_to_publish_container);
+
+ return $publish_progress;
+ }
+
+ get_items_and_render(wrapper = this.$wrapper) {
+ wrapper.find('.results').remove();
+ const items = this.get_valid_items();
+
+ if(!items.then) {
+ this.render(items, wrapper);
} else {
- this.get_items_and_render();
+ items.then(r => {
+ this.fetched_items = r.message;
+ this.render(r.message, wrapper);
+ });
}
}
- render(items) {
+ render(items, wrapper) {
const items_container = $(get_item_card_container_html(items, '', get_local_item_card_html));
- this.$wrapper.append(items_container);
+ items_container.addClass('results');
+ wrapper.append(items_container);
}
get_valid_items() {
+ if(this.unpublished_items.length) {
+ return this.unpublished_items;
+ }
return frappe.call(
'erpnext.hub_node.get_valid_items',
{
@@ -938,26 +1009,33 @@
);
}
- show_publishing_state() {
- this.$wrapper.html(get_empty_state(
- 'Publishing items ... You will be notified once published.'
- ));
- }
-
publish_selected_items() {
- const items_to_publish = [];
+ const item_codes_to_publish = [];
this.$wrapper.find('.hub-card.active').map(function () {
- items_to_publish.push($(this).attr("data-id"));
+ item_codes_to_publish.push($(this).attr("data-id"));
});
- this.show_publishing_state();
+ this.unpublished_items = this.fetched_items.filter(item => {
+ return !item_codes_to_publish.includes(item.item_code);
+ });
- return frappe.call(
- 'erpnext.hub_node.publish_selected_items',
- {
- items_to_publish: items_to_publish
- }
- );
+ const items_to_publish = this.fetched_items.filter(item => {
+ return item_codes_to_publish.includes(item.item_code);
+ });
+ this.items_to_publish = items_to_publish;
+
+ return frappe.db.set_value("Hub Settings", "Hub Settings", {
+ custom_data: JSON.stringify(items_to_publish),
+ // sync_in_progress: 1
+ }).then(() => {
+ hub.settings.sync_in_progress = 1;
+ })
+ // .then(frappe.call(
+ // 'erpnext.hub_node.publish_selected_items',
+ // {
+ // items_to_publish: item_codes_to_publish
+ // }
+ // ));
}
}
diff --git a/erpnext/public/less/hub.less b/erpnext/public/less/hub.less
index a432156..c610aad 100644
--- a/erpnext/public/less/hub.less
+++ b/erpnext/public/less/hub.less
@@ -31,14 +31,33 @@
border-color: #59b81c;
}
+ .progress-bar {
+ background-color: #89da28;
+ }
+
.subpage-title.flex {
align-items: flex-start;
justify-content: space-between;
}
+ .subpage-message {
+ p {
+ padding: 10px 15px;
+ margin-top: 0px;
+ margin-bottom: 15px;
+ background-color: #f9fbf7;
+ justify-content: space-between;
+ }
+
+ .octicon-x {
+ cursor: pointer;
+ }
+ }
+
.hub-card {
- border: 1px solid @border-color;
margin-bottom: 25px;
+ position: relative;
+ border: 1px solid @border-color;
border-radius: 4px;
overflow: hidden;
cursor: pointer;