diff --git a/erpnext/hub_node/__init__.py b/erpnext/hub_node/__init__.py index 371a23f3b47..89ee926d55a 100644 --- a/erpnext/hub_node/__init__.py +++ b/erpnext/hub_node/__init__.py @@ -135,7 +135,7 @@ def get_details(hub_sync_id=None, doctype='Hub Item'): connection = get_client_connection() details = connection.get_doc(doctype, hub_sync_id) reviews = details.get('reviews') - if len(reviews): + if reviews and len(reviews): for r in reviews: r.setdefault('pretty_date', frappe.utils.pretty_date(r.get('modified'))) details.setdefault('reviews', reviews) diff --git a/erpnext/hub_node/doctype/hub_settings/hub_settings.js b/erpnext/hub_node/doctype/hub_settings/hub_settings.js index f13ad44b443..64d20b87fe1 100644 --- a/erpnext/hub_node/doctype/hub_settings/hub_settings.js +++ b/erpnext/hub_node/doctype/hub_settings/hub_settings.js @@ -6,9 +6,9 @@ frappe.ui.form.on("Hub Settings", { })); frm.trigger("enabled"); + frm.add_custom_button(__('View Hub'), + () => frappe.set_route('Hub', 'Item')); if (frm.doc.enabled) { - frm.add_custom_button(__('View Hub'), - () => frappe.set_route('Hub', 'Item')); frm.add_custom_button(__('Sync'), () => frm.call('sync')); } diff --git a/erpnext/hub_node/doctype/hub_settings/hub_settings.py b/erpnext/hub_node/doctype/hub_settings/hub_settings.py index dc69056d93f..15ee4b7da35 100644 --- a/erpnext/hub_node/doctype/hub_settings/hub_settings.py +++ b/erpnext/hub_node/doctype/hub_settings/hub_settings.py @@ -10,12 +10,10 @@ from frappe import _ from erpnext.utilities.product import get_price, get_qty_in_stock from six import string_types -# hub_url = "https://hubmarket.org" -hub_url = "http://159.89.175.122" +hub_url = "https://hubmarket.org" +# hub_url = "http://159.89.175.122" # hub_url = "http://erpnext.hub:8000" -# test_hub_url = "https://hubmarket.org" - class OAuth2Session(): def __init__(self, headers): self.headers = headers diff --git a/erpnext/hub_node/page/__init__.py b/erpnext/hub_node/page/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/patches.txt b/erpnext/patches.txt index f82904178a6..ce208adb1ef 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -515,4 +515,5 @@ erpnext.patches.v10_0.update_hub_connector_domain erpnext.patches.v10_0.set_student_party_type erpnext.patches.v10_0.update_project_in_sle erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract -erpnext.patches.v11_0.add_index_on_nestedset_doctypes \ No newline at end of file +erpnext.patches.v11_0.add_index_on_nestedset_doctypes +erpnext.patches.v11_0.remove_modules_setup_page diff --git a/erpnext/patches/v11_0/remove_modules_setup_page.py b/erpnext/patches/v11_0/remove_modules_setup_page.py new file mode 100644 index 00000000000..bb0bdf59da1 --- /dev/null +++ b/erpnext/patches/v11_0/remove_modules_setup_page.py @@ -0,0 +1,8 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.delete_doc("Page", "modules_setup") diff --git a/erpnext/public/images/hub_logo.svg b/erpnext/public/images/hub_logo.svg index 4af482176ea..1612c6da118 100644 --- a/erpnext/public/images/hub_logo.svg +++ b/erpnext/public/images/hub_logo.svg @@ -1,112 +1,37 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - + class="hub-icon" + height="345.43808" + width="330"> + transform="translate(121.51931,-138.66452)" + id="layer1"> + x="-121.51931" + height="87.3125" + width="87.3125" + id="rect828" + style="opacity:1;vector-effect:none;fill:#89da29;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" + rx="13.229166" /> - + + d="m -34.20681,202.96343 c -32.784694,-0.0533 -43.804846,16.14019 -87.14455,15.97939 1.00509,6.31857 6.45115,11.1187 13.06122,11.1187 h 60.854164 c 7.328992,0 13.229166,-5.9002 13.229166,-13.22917 z" + clip-path="none" + style="opacity:1;vector-effect:none;fill:#59b81c;fill-opacity:1;stroke:none;stroke-width:3.96875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> + d="m -84.351263,175.75725 c -1.30945,0 -2.376091,1.06665 -2.376091,2.37608 v 10.02885 0.001 c 0.06583,4.83083 4.01156,8.73477 8.857351,8.73486 4.8718,5e-5 8.846821,-3.94421 8.871295,-8.81134 v -0.001 -9.95288 c 0,-1.30943 -1.066113,-2.37557 -2.375589,-2.37557 -1.309396,0 -2.376064,1.06614 -2.376064,2.37557 v 9.8888 c 0,2.26045 -1.858169,4.10983 -4.119642,4.10983 -2.263616,0 -4.105699,-1.82766 -4.105699,-4.08968 v -9.90844 c 0,-1.30943 -1.066138,-2.37608 -2.375561,-2.37608 z m -20.887107,0.0925 c -1.30943,0 -2.37609,1.06717 -2.37609,2.3766 v 16.45119 c 0,1.30944 1.06666,2.37609 2.37609,2.37609 1.30945,0 2.37556,-1.06665 2.37556,-2.37609 v -5.97327 h 8.22534 v 5.97327 c 0,1.30944 1.066641,2.37609 2.376091,2.37609 1.309423,0 2.375561,-1.06665 2.375561,-2.37609 v -16.45119 c 0,-1.30943 -1.066138,-2.3766 -2.375561,-2.3766 -1.30945,0 -2.376091,1.06717 -2.376091,2.3766 v 5.72627 h -8.22534 v -5.72627 c 0,-1.30943 -1.06611,-2.3766 -2.37556,-2.3766 z m 41.77419,0 c -0.654712,0 -1.248675,0.26711 -1.678967,0.69764 -0.05368,0.0537 -0.105119,0.10983 -0.153458,0.16846 v 5.3e-4 c -0.04839,0.0586 -0.09427,0.11929 -0.136949,0.18242 v 5.3e-4 c -0.256381,0.37936 -0.406691,0.83617 -0.406691,1.32705 v 16.45119 c 0,0.1635 0.01693,0.3242 0.04858,0.47852 0.09512,0.46331 0.32594,0.87828 0.64852,1.20096 0.161369,0.16136 0.345308,0.29938 0.547264,0.40928 v 0 c 0.134567,0.0732 0.276781,0.13403 0.425318,0.18035 v 0 c 0.148537,0.0463 0.303186,0.0783 0.462518,0.0946 v 0 c 0.07959,0.008 0.160708,0.0124 0.242358,0.0124 h 8.33181 c 0.08747,0 0.167931,-0.0145 0.251142,-0.0238 l 0.09509,0.005 c 0.06019,0.003 0.119407,0.005 0.178779,0.006 h 0.0037 0.0048 c 3.578305,-2e-5 6.487954,-2.90916 6.487981,-6.48747 v -0.001 c -0.0026,-1.51334 -0.578009,-2.9475 -1.540484,-4.10673 0.962448,-1.15892 1.537785,-2.59314 1.540484,-4.10621 v -0.001 c -2.7e-5,-3.57831 -2.909676,-6.48744 -6.487981,-6.48746 h -0.533294 z m 8.865103,4.75062 c 0.96393,0 1.736831,0.77394 1.736831,1.73788 0,0.96394 -0.772901,1.73684 -1.736831,1.73684 v 0 h -0.532792 -5.955718 v -3.47317 h 5.956248 z m 0,8.21552 v 0 c 0.963507,5.3e-4 1.735799,0.77373 1.735799,1.73736 0,0.96394 -0.772901,1.73684 -1.736831,1.73684 h -0.0048 l -0.533294,0.0119 h -5.951591 v -3.4742 h 5.959846 z" + id="path834" /> + d="m -77.859375,138.66406 c -9.653316,0 -18.439915,3.93483 -24.767575,10.28125 a 3.9691471,3.9691471 0 1 0 5.621091,5.60352 c 4.899576,-4.9141 11.6422,-7.94727 19.146484,-7.94727 7.501101,0 14.241542,3.03098 19.140625,7.94141 a 3.9691471,3.9691471 0 1 0 5.619141,-5.60547 c -6.327038,-6.34169 -15.110547,-10.27344 -24.759766,-10.27344 z" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#63c923;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.93750048;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> diff --git a/erpnext/public/js/hub/hub_form.js b/erpnext/public/js/hub/hub_form.js index 5fdcadbbaeb..62c44fcb333 100644 --- a/erpnext/public/js/hub/hub_form.js +++ b/erpnext/public/js/hub/hub_form.js @@ -40,10 +40,6 @@ erpnext.hub.HubDetailsPage = class HubDetailsPage extends frappe.views.BaseList wrapper: this.$page.find('.layout-side-section'), css_class: 'hub-form-sidebar' }); - - this.attachFooter(); - this.attachTimeline(); - this.attachReviewArea(); } setup_filter_area() { } @@ -132,8 +128,8 @@ erpnext.hub.HubDetailsPage = class HubDetailsPage extends frappe.views.BaseList this.form.set_values(this.data); this.$result.show(); - this.$timelineList.empty(); - if(this.data.reviews.length) { + this.$timelineList && this.$timelineList.empty(); + if(this.data.reviews && this.data.reviews.length) { this.data.reviews.map(review => { this.addReviewToTimeline(review); }) @@ -323,6 +319,58 @@ erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubDetailsPage { this.image_field_name = 'image'; } + setup_page_head() { + super.setup_page_head(); + this.set_primary_action(); + } + + setup_side_bar() { + this.setup_side_bar(); + this.attachFooter(); + this.attachTimeline(); + this.attachReviewArea(); + } + + set_primary_action() { + let item = this.data; + this.page.set_primary_action(__('Request a Quote'), () => { + this.show_rfq_modal() + .then(values => { + item.item_code = values.item_code; + delete values.item_code; + + const supplier = values; + return [item, supplier]; + }) + .then(([item, supplier]) => { + return this.make_rfq(item, supplier, this.page.btn_primary); + }) + .then(r => { + console.log(r); + if (r.message && r.message.rfq) { + this.page.btn_primary.addClass('disabled').html(` ${__('Quote Requested')}`); + } else { + throw r; + } + }) + .catch((e) => { + console.log(e); //eslint-disable-line + }); + }, 'octicon octicon-plus'); + } + + make_rfq(item, supplier, btn) { + console.log(supplier); + return new Promise((resolve, reject) => { + frappe.call({ + method: 'erpnext.hub_node.make_rfq_and_send_opportunity', + args: { item, supplier }, + callback: resolve, + btn, + }).fail(reject); + }); + } + postRender() { this.categoryDialog = new frappe.ui.Dialog({ title: __('Suggest Category'), @@ -345,6 +393,7 @@ erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubDetailsPage { category: values.category }, callback: () => { + this.categoryDialog.hide(); this.refresh(); }, freeze: true @@ -383,6 +432,36 @@ erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubDetailsPage { ]; this.formFields = colOneFields.concat(miscFields, colTwoFields); } + + show_rfq_modal() { + let item = this.data; + return new Promise(res => { + let fields = [ + { label: __('Item Code'), fieldtype: 'Data', fieldname: 'item_code', default: item.item_code }, + { fieldtype: 'Column Break' }, + { label: __('Item Group'), fieldtype: 'Link', fieldname: 'item_group', default: item.item_group }, + { label: __('Supplier Details'), fieldtype: 'Section Break' }, + { label: __('Supplier Name'), fieldtype: 'Data', fieldname: 'supplier_name', default: item.company_name }, + { label: __('Supplier Email'), fieldtype: 'Data', fieldname: 'supplier_email', default: item.seller }, + { fieldtype: 'Column Break' }, + { label: __('Supplier Type'), fieldname: 'supplier_type', + fieldtype: 'Link', options: 'Supplier Type' } + ]; + fields = fields.map(f => { f.reqd = 1; return f; }); + + const d = new frappe.ui.Dialog({ + title: __('Request for Quotation'), + fields: fields, + primary_action_label: __('Send'), + primary_action: (values) => { + res(values); + d.hide(); + } + }); + + d.show(); + }); + } } erpnext.hub.CompanyPage = class CompanyPage extends erpnext.hub.HubDetailsPage { diff --git a/erpnext/public/js/hub/hub_listing.js b/erpnext/public/js/hub/hub_listing.js index 9e19f738350..a979d287e6c 100644 --- a/erpnext/public/js/hub/hub_listing.js +++ b/erpnext/public/js/hub/hub_listing.js @@ -152,9 +152,8 @@ erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList { var html = this.data.map(this.item_html.bind(this)).join(""); if (this.start === 0) { - // this.renderHeader(); + // ${this.getHeaderHtml()} this.$result.html(` - ${this.getHeaderHtml()}
${html}
@@ -173,17 +172,21 @@ erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList { }); } - getHeaderHtml() { + getHeaderHtml(title, image, content) { // let company_html = return `
- Riadco Group + ${title}
-
Riadco Group
- Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam +
+ ${title} +
+ + ${content} +
@@ -246,69 +249,6 @@ erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList { ) } - item_html(item) { - item._name = encodeURI(item.name); - const encoded_name = item._name; - const title = strip_html(item[this.meta.title_field || 'name']); - const _class = !item[this.imageFieldName] ? 'no-image' : ''; - const route = `#Hub/Item/${item.hub_item_code}`; - const company_name = item['company_name']; - - const reviewLength = (item.reviews || []).length; - const ratingAverage = reviewLength - ? item.reviews - .map(r => r.rating) - .reduce((a, b) => (a + b, 0))/reviewLength - : -1; - - let ratingHtml = ``; - - for(var i = 0; i < 5; i++) { - let starClass = 'fa-star'; - if(i >= ratingAverage) starClass = 'fa-star-o'; - ratingHtml += ``; - } - - let item_html = ` -
-
-
- - ${title} - -
-
- ${ratingHtml} - (${reviewLength}) -
- -
-
- -
- - -
-
-
- -
- `; - - return item_html; - } - setup_quick_view() { if(this.quick_view) return; @@ -316,6 +256,31 @@ erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList { title: 'Quick View', fields: this.formFields }); + this.quick_view.set_primary_action(__('Request a Quote'), () => { + this.show_rfq_modal() + .then(values => { + item.item_code = values.item_code; + delete values.item_code; + + const supplier = values; + return [item, supplier]; + }) + .then(([item, supplier]) => { + return this.make_rfq(item, supplier, this.page.btn_primary); + }) + .then(r => { + console.log(r); + if (r.message && r.message.rfq) { + this.page.btn_primary.addClass('disabled').html(` ${__('Quote Requested')}`); + } else { + throw r; + } + }) + .catch((e) => { + console.log(e); //eslint-disable-line + }); + }, 'octicon octicon-plus'); + this.$result.on('click', '.btn.zoom-view', (e) => { e.preventDefault(); e.stopPropagation(); @@ -400,6 +365,14 @@ erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing { this.filters = []; } + render() { + this.data_dict = {}; + this.render_image_view(); + + this.setup_quick_view(); + this.setup_like(); + } + bootstrap_data(response) { let companies = response.companies.map(d => d.name); this.custom_filter_configs = [ @@ -486,6 +459,11 @@ erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing { label: __("Favourites"), on_click: () => frappe.set_route('Hub', 'Favourites') }, __("Account")); + + this.sidebar.add_item({ + label: __("Settings"), + on_click: () => frappe.set_route('Form', 'Hub Settings') + }, __("Account")); } update_category(label) { @@ -514,6 +492,70 @@ erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing { this.data_dict[d.hub_item_code] = d; }); } + + item_html(item) { + item._name = encodeURI(item.name); + const encoded_name = item._name; + const title = strip_html(item[this.meta.title_field || 'name']); + const _class = !item[this.imageFieldName] ? 'no-image' : ''; + const route = `#Hub/Item/${item.hub_item_code}`; + const company_name = item['company_name']; + + const reviewLength = (item.reviews || []).length; + const ratingAverage = reviewLength + ? item.reviews + .map(r => r.rating) + .reduce((a, b) => a + b, 0)/reviewLength + : -1; + + let ratingHtml = ``; + + for(var i = 0; i < 5; i++) { + let starClass = 'fa-star'; + if(i >= ratingAverage) starClass = 'fa-star-o'; + ratingHtml += ``; + } + + let item_html = ` +
+
+
+ + ${title} + +
+
+ ${ratingHtml} + (${reviewLength}) +
+ +
+
+ +
+ + +
+
+
+ +
+ `; + + return item_html; + } + }; erpnext.hub.Favourites = class Favourites extends erpnext.hub.ItemListing { @@ -564,16 +606,6 @@ erpnext.hub.Favourites = class Favourites extends erpnext.hub.ItemListing { label: __('Back to Products'), on_click: () => frappe.set_route('Hub', 'Item') }); - - // this.sidebar.add_item({ - // label: this.hub_settings.company, - // on_click: () => frappe.set_route('Form', 'Company', this.hub_settings.company) - // }, __("Account")); - - // this.sidebar.add_item({ - // label: __("My Orders"), - // on_click: () => frappe.set_route('List', 'Request for Quotation') - // }, __("Account")); } update_category(label) { @@ -610,6 +642,11 @@ erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing this.show(); } + render() { + this.data_dict = {}; + this.render_image_view(); + } + setup_defaults() { super.setup_defaults(); this.doctype = 'Hub Company'; @@ -628,6 +665,18 @@ erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing this.imageFieldName = 'company_logo'; } + setup_side_bar() { + this.sidebar = new frappe.ui.Sidebar({ + wrapper: this.page.wrapper.find('.layout-side-section'), + css_class: 'hub-sidebar' + }); + + this.sidebar.add_item({ + label: __('Back to Products'), + on_click: () => frappe.set_route('Hub', 'Item') + }); + } + get_filters_for_args() { let filters = {}; this.filter_area.get().forEach(f => { @@ -637,29 +686,41 @@ erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing return filters; } - card_html(company) { - company._name = encodeURI(company.name); - const route = `#Hub/Company/${company.company_name}`; + item_html(company) { + company._name = encodeURI(company.company_name); + const encoded_name = company._name; + const title = strip_html(company.company_name); + const _class = !company[this.imageFieldName] ? 'no-image' : ''; + const company_name = company['company_name']; + const route = `#Hub/Company/${company_name}`; let image_html = company.company_logo ? `` : `
${frappe.get_abbr(company.company_name)}
`; - return ` -
- -
- `; + + return item_html; } + }; \ No newline at end of file diff --git a/erpnext/public/less/erpnext.less b/erpnext/public/less/erpnext.less index 711a40ac58f..e962e912111 100644 --- a/erpnext/public/less/erpnext.less +++ b/erpnext/public/less/erpnext.less @@ -23,6 +23,20 @@ margin-top: -3px; } +.app-icon-svg { + display: inline-block; + margin: auto; + text-align: center; + border-radius: 16px; + cursor: pointer; + box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.15); +} + +.app-icon-svg .hub-icon { + height: 72px; + width: 72px; +} + .dashboard-list-item { background-color: inherit; padding: 5px 0px; diff --git a/erpnext/public/less/hub.less b/erpnext/public/less/hub.less index f202fa4345c..bdca28f1e74 100644 --- a/erpnext/public/less/hub.less +++ b/erpnext/public/less/hub.less @@ -3,6 +3,7 @@ body[data-route^="Hub/"] { .hub-icon { width: 40px; + height: 40px; } .hub-page-title { @@ -73,6 +74,67 @@ body[data-route^="Hub/"] { .frappe-list .result { min-height: 100px; } + + .frappe-control[data-fieldtype="Attach Image"] { + width: 140px; + height: 180px; + margin-top: 20px; + } + + .frappe-control[data-fieldtype="Attach Image"] .form-group { + display: none; + } + + .frappe-control[data-fieldtype="Attach Image"] .clearfix { + display: none; + } + + .missing-image { + display: block; + position: relative; + border-radius: 4px; + border: 1px solid #d1d8dd; + border-radius: 6px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + } + .missing-image .octicon { + position: relative; + top: 50%; + transform: translate(0px, -50%); + -webkit-transform: translate(0px, -50%); + } + .attach-image-display { + display: block; + position: relative; + border-radius: 4px; + } + .img-container { + height: 100%; + width: 100%; + padding: 2px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + border: 1px solid #d1d8dd; + border-radius: 6px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + } + .img-overlay { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + width: 100%; + height: 100%; + color: #777777; + background-color: rgba(255, 255, 255, 0.7); + opacity: 0; + } + .img-overlay:hover { + opacity: 1; + cursor: pointer; + } } .image-view-container {