Hub Market (#13325)
* [hub] enable hub with OAuth token from user's client ID * [hub] settings schema for adding users * [hub] image view style listing * [hub] broken image link fallback * [wip] * [hub] bootstrap timeline * [hub] setup quick view * [hub] reformat ratings, add companies autocomplete filter * [hub] common listing frames * [hub] setup sort selector * [hub] timeline * [hub] customize list header * [hub] genuine form fieldtypes * [hub] review products * [hub] suggest missing categories remotely * [hub] Wishlist; header and title templates * [hub] link wishlist, remove company migration * [hub] calculate ratings
This commit is contained in:
parent
c5effbf009
commit
b60a52b194
@ -336,7 +336,7 @@ def get_data():
|
||||
"color": "#009248",
|
||||
"icon": "/assets/erpnext/images/hub_logo.svg",
|
||||
"type": "page",
|
||||
"link": "Hub/Home",
|
||||
"link": "Hub/Item",
|
||||
"label": _("Hub")
|
||||
},
|
||||
{
|
||||
|
@ -22,13 +22,64 @@ def get_list(doctype, start=0, limit=20, fields=["*"], filters="{}", order_by=No
|
||||
response = connection.get_list(doctype,
|
||||
limit_start=start, limit_page_length=limit,
|
||||
filters=filters, fields=fields)
|
||||
return response
|
||||
|
||||
# Bad, need child tables in response
|
||||
listing = []
|
||||
for obj in response:
|
||||
doc = connection.get_doc(doctype, obj['name'])
|
||||
listing.append(doc)
|
||||
|
||||
return listing
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_favourites(start=0, limit=20, fields=["*"], order_by=None):
|
||||
doctype = 'Hub Item'
|
||||
hub_settings = frappe.get_doc('Hub Settings')
|
||||
item_names_str = hub_settings.get('custom_data') or '[]'
|
||||
item_names = json.loads(item_names_str)
|
||||
filters = json.dumps({
|
||||
'hub_item_code': ['in', item_names]
|
||||
})
|
||||
return get_list(doctype, start, limit, fields, filters, order_by)
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_wishlist_item(item_name, remove=0):
|
||||
remove = int(remove)
|
||||
hub_settings = frappe.get_doc('Hub Settings')
|
||||
data = hub_settings.get('custom_data')
|
||||
if not data or not json.loads(data):
|
||||
data = '[]'
|
||||
hub_settings.custom_data = data
|
||||
hub_settings.save()
|
||||
|
||||
item_names_str = data
|
||||
item_names = json.loads(item_names_str)
|
||||
if not remove and item_name not in item_names:
|
||||
item_names.append(item_name)
|
||||
if remove and item_name in item_names:
|
||||
item_names.remove(item_name)
|
||||
|
||||
item_names_str = json.dumps(item_names)
|
||||
|
||||
hub_settings.custom_data = item_names_str
|
||||
hub_settings.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_meta(doctype):
|
||||
connection = get_client_connection()
|
||||
meta = connection.get_doc('DocType', doctype)
|
||||
return meta
|
||||
categories = connection.get_list('Hub Category',
|
||||
limit_start=0, limit_page_length=300,
|
||||
filters={}, fields=['name'])
|
||||
|
||||
categories = [d.get('name') for d in categories]
|
||||
return {
|
||||
'meta': meta,
|
||||
'companies': connection.get_list('Hub Company',
|
||||
limit_start=0, limit_page_length=300,
|
||||
filters={}, fields=['name']),
|
||||
'categories': categories
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_categories(parent='All Categories'):
|
||||
@ -40,12 +91,42 @@ def get_categories(parent='All Categories'):
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_category(item_name, category):
|
||||
def update_category(hub_item_code, category):
|
||||
connection = get_hub_connection()
|
||||
response = connection.update('Hub Item', dict(
|
||||
|
||||
# args = frappe._dict(dict(
|
||||
# doctype='Hub Category',
|
||||
# hub_category_name=category
|
||||
# ))
|
||||
# response = connection.insert('Hub Category', args)
|
||||
|
||||
response = connection.update('Hub Item', frappe._dict(dict(
|
||||
doctype='Hub Item',
|
||||
hub_category = category
|
||||
), item_name)
|
||||
return response.ok
|
||||
)), hub_item_code)
|
||||
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def send_review(hub_item_code, review):
|
||||
review = json.loads(review)
|
||||
hub_connection = get_hub_connection()
|
||||
|
||||
item_doc = hub_connection.connection.get_doc('Hub Item', hub_item_code)
|
||||
existing_reviews = item_doc.get('reviews')
|
||||
|
||||
reviews = [review]
|
||||
review.setdefault('idx', 0)
|
||||
for r in existing_reviews:
|
||||
if r.get('user') != review.get('user'):
|
||||
reviews.append(r)
|
||||
|
||||
response = hub_connection.update('Hub Item', dict(
|
||||
doctype='Hub Item',
|
||||
reviews = reviews
|
||||
), hub_item_code)
|
||||
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_details(hub_sync_id=None, doctype='Hub Item'):
|
||||
@ -53,6 +134,11 @@ def get_details(hub_sync_id=None, doctype='Hub Item'):
|
||||
return
|
||||
connection = get_client_connection()
|
||||
details = connection.get_doc(doctype, hub_sync_id)
|
||||
reviews = details.get('reviews')
|
||||
if len(reviews):
|
||||
for r in reviews:
|
||||
r.setdefault('pretty_date', frappe.utils.pretty_date(r.get('modified')))
|
||||
details.setdefault('reviews', reviews)
|
||||
return details
|
||||
|
||||
def get_client_connection():
|
||||
|
@ -4,10 +4,6 @@
|
||||
"doctype": "Data Migration Plan",
|
||||
"idx": 1,
|
||||
"mappings": [
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Company to Hub Company"
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Item to Hub Item"
|
||||
|
@ -8,18 +8,31 @@ frappe.ui.form.on("Hub Settings", {
|
||||
frm.trigger("enabled");
|
||||
if (frm.doc.enabled) {
|
||||
frm.add_custom_button(__('View Hub'),
|
||||
() => frappe.set_route('hub'));
|
||||
() => frappe.set_route('Hub', 'Item'));
|
||||
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_post_render: function(frm) {
|
||||
if(frm.get_field("unregister_from_hub").$input)
|
||||
@ -48,33 +61,47 @@ frappe.ui.form.on("Hub Settings", {
|
||||
if(frappe.session.user === "Administrator") {
|
||||
frappe.msgprint(__("Please login as another user."))
|
||||
} else {
|
||||
frappe.verify_password(() => {
|
||||
this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "register",
|
||||
args: {},
|
||||
freeze: true,
|
||||
callback: function(r) {},
|
||||
onerror: function() {
|
||||
frappe.msgprint(__("Wrong Password"));
|
||||
frm.set_value("enabled", 0);
|
||||
}
|
||||
});
|
||||
} );
|
||||
// frappe.verify_password(() => {
|
||||
|
||||
// } );
|
||||
|
||||
frm.trigger("call_pre_reg");
|
||||
// frm.trigger("call_register");
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// update_hub: (frm) => {
|
||||
// this.frm.call({
|
||||
// doc: this.frm.doc,
|
||||
// method: "update_hub",
|
||||
// args: {},
|
||||
// freeze: true,
|
||||
// callback: function(r) { },
|
||||
// onerror: function() { }
|
||||
// });
|
||||
// },
|
||||
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,
|
||||
method: "register",
|
||||
args: {},
|
||||
freeze: true,
|
||||
callback: function(r) {},
|
||||
onerror: function() {
|
||||
frappe.msgprint(__("Wrong Password"));
|
||||
frm.set_value("enabled", 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unregister_from_hub: (frm) => {
|
||||
frappe.verify_password(() => {
|
||||
@ -85,3 +112,67 @@ frappe.ui.form.on("Hub Settings", {
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -70,6 +71,39 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "hub_username",
|
||||
"fieldtype": "Data",
|
||||
"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": "Hub Username",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -101,6 +135,102 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_0",
|
||||
"fieldtype": "Column Break",
|
||||
"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": "",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "hub_user_status",
|
||||
"fieldtype": "Data",
|
||||
"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": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Data",
|
||||
"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": "Language",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -133,6 +263,38 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_registered",
|
||||
"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": "Company Registered",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -164,6 +326,38 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_email",
|
||||
"fieldtype": "Data",
|
||||
"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": "Company Email",
|
||||
"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
|
||||
},
|
||||
{
|
||||
@ -195,6 +389,38 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_logo",
|
||||
"fieldtype": "Attach Image",
|
||||
"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": "Company Logo",
|
||||
"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
|
||||
},
|
||||
{
|
||||
@ -225,6 +451,70 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "users_sb",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "Enabled Users",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "users",
|
||||
"fieldtype": "Table",
|
||||
"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": "Users",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Hub Users",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -256,6 +546,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -286,6 +577,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -317,6 +609,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -349,6 +642,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -380,6 +674,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -411,6 +706,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -418,6 +714,39 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "eval:1",
|
||||
"fieldname": "custom_data",
|
||||
"fieldtype": "Code",
|
||||
"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": "Custom Data",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
@ -443,6 +772,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -473,6 +803,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -486,8 +817,8 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-09-21 12:13:50.841646",
|
||||
"modified_by": "manas@erpnext.com",
|
||||
"modified": "2018-03-26 00:55:17.929140",
|
||||
"modified_by": "test1@example.com",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Settings",
|
||||
"name_case": "",
|
||||
|
@ -10,7 +10,24 @@ 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 = "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
|
||||
def get(self, url, params, headers, verify):
|
||||
res = requests.get(url, params=params, headers=self.headers, verify=verify)
|
||||
return res
|
||||
def post(self, url, data, verify):
|
||||
res = requests.post(url, data=data, headers=self.headers, verify=verify)
|
||||
return res
|
||||
def put(self, url, data, verify):
|
||||
res = requests.put(url, data=data, headers=self.headers, verify=verify)
|
||||
return res
|
||||
|
||||
class HubSetupError(frappe.ValidationError): pass
|
||||
|
||||
@ -35,6 +52,33 @@ class HubSettings(Document):
|
||||
|
||||
doc.run()
|
||||
|
||||
def pre_reg(self):
|
||||
site_name = frappe.local.site + ':' + str(frappe.conf.webserver_port)
|
||||
protocol = 'http://'
|
||||
route = '/token'
|
||||
data = {
|
||||
'site_name': site_name,
|
||||
'protocol': protocol,
|
||||
'route': route
|
||||
}
|
||||
|
||||
redirect_url = protocol + site_name + route
|
||||
post_url = hub_url + '/api/method/hub.hub.api.pre_reg'
|
||||
|
||||
response = requests.post(post_url, data=data)
|
||||
response.raise_for_status()
|
||||
message = response.json().get('message')
|
||||
|
||||
if message and message.get('client_id'):
|
||||
print("======CLIENT_ID======")
|
||||
print(message.get('client_id'))
|
||||
|
||||
return {
|
||||
'client_id': message.get('client_id'),
|
||||
'redirect_uri': redirect_url
|
||||
}
|
||||
|
||||
|
||||
def register(self):
|
||||
""" Create a User on hub.erpnext.org and return username/password """
|
||||
data = {
|
||||
|
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Hub Tracked Item', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -0,0 +1,93 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-03-18 09:33:50.267762",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Data",
|
||||
"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": "Item Code",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 1,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-18 09:34:01.757713",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Tracked Item",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class HubTrackedItem(Document):
|
||||
pass
|
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Hub Tracked Item", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Hub Tracked Item
|
||||
() => frappe.tests.make('Hub Tracked Item', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestHubTrackedItem(unittest.TestCase):
|
||||
pass
|
0
erpnext/hub_node/doctype/hub_users/__init__.py
Normal file
0
erpnext/hub_node/doctype/hub_users/__init__.py
Normal file
72
erpnext/hub_node/doctype/hub_users/hub_users.json
Normal file
72
erpnext/hub_node/doctype/hub_users/hub_users.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-03-06 04:38:49.891787",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-06 04:41:17.916243",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Users",
|
||||
"name_case": "",
|
||||
"owner": "test1@example.com",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
10
erpnext/hub_node/doctype/hub_users/hub_users.py
Normal file
10
erpnext/hub_node/doctype/hub_users/hub_users.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class HubUsers(Document):
|
||||
pass
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"css/erpnext.css": [
|
||||
"public/less/erpnext.less"
|
||||
"public/less/erpnext.less",
|
||||
"public/less/hub.less"
|
||||
],
|
||||
"js/erpnext-web.min.js": [
|
||||
"public/js/website_utils.js",
|
||||
@ -21,7 +22,7 @@
|
||||
"public/js/pos/pos.html",
|
||||
"public/js/pos/pos_bill_item.html",
|
||||
"public/js/pos/pos_bill_item_new.html",
|
||||
"public/js/pos/pos_selected_item.html",
|
||||
"public/js/pos/pos_selected_item.html",
|
||||
"public/js/pos/pos_item.html",
|
||||
"public/js/pos/pos_tax_row.html",
|
||||
"public/js/pos/customer_toolbar.html",
|
||||
|
@ -1,130 +0,0 @@
|
||||
body[data-route^="Hub/"] .freeze .image-view-container .list-row-col {
|
||||
background-color: #fafbfc;
|
||||
color: #fafbfc;
|
||||
}
|
||||
body[data-route^="Hub/"] .freeze .image-view-container .placeholder-text {
|
||||
color: #fafbfc;
|
||||
}
|
||||
body[data-route^="Hub/"] .freeze {
|
||||
display: none;
|
||||
}
|
||||
body[data-route^="Hub/"] .image-view-container {
|
||||
justify-content: space-around;
|
||||
}
|
||||
.img-wrapper {
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.img-wrapper .helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* hub */
|
||||
div[data-page-route="hub"] .page-head {
|
||||
height: 80px;
|
||||
}
|
||||
div[data-page-route="hub"] .page-head .title-text {
|
||||
cursor: pointer;
|
||||
}
|
||||
div[data-page-route="hub"] .page-content {
|
||||
margin-top: 80px;
|
||||
}
|
||||
div[data-page-route="hub"] .page-title h1 {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
div[data-page-route="hub"] .account-details {
|
||||
margin-top: 20px;
|
||||
}
|
||||
div[data-page-route="hub"] [data-original-title="Search"] {
|
||||
float: right;
|
||||
width: 220px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-main-section {
|
||||
padding: 30px;
|
||||
}
|
||||
div[data-page-route="hub"] .listing-body {
|
||||
margin: 0;
|
||||
}
|
||||
div[data-page-route="hub"] .main-list-section {
|
||||
padding: 0;
|
||||
}
|
||||
div[data-page-route="hub"] .side-list-section {
|
||||
padding: 0;
|
||||
}
|
||||
div[data-page-route="hub"] .item-list-header h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .item-header {
|
||||
display: flex;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .item-page-image {
|
||||
flex: 1;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content {
|
||||
flex: 3;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content .description {
|
||||
margin: 30px 0px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content .actions {
|
||||
margin-top: 30px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content .actions .rfq-btn.disabled {
|
||||
background-color: #b1bdca;
|
||||
color: #fff;
|
||||
border-color: #b1bdca;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .company-items {
|
||||
margin-top: 40px;
|
||||
}
|
||||
div[data-page-route="hub"] .company-header {
|
||||
display: flex;
|
||||
}
|
||||
div[data-page-route="hub"] .item-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-wrapper {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper {
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper .helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper .standard-image {
|
||||
font-size: 72px;
|
||||
border: none;
|
||||
background-color: #fafbfc;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-title {
|
||||
width: 100%;
|
||||
}
|
||||
div[data-page-route="hub"] .breadcrumb {
|
||||
padding-left: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
@ -9,68 +9,104 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="330"
|
||||
height="345.43808"
|
||||
viewBox="0 0 87.312496 91.397155"
|
||||
version="1.1"
|
||||
id="svg3718"
|
||||
xml:space="preserve"
|
||||
width="162.12097"
|
||||
height="162.3004"
|
||||
viewBox="0 0 162.12098 162.3004"
|
||||
sodipodi:docname="hub_logo.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
|
||||
id="metadata3724"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs3722"><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3734"><path
|
||||
d="M 0,600 H 1000 V 0 H 0 Z"
|
||||
id="path3732"
|
||||
inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview
|
||||
id="svg4635"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="hub-logo.svg"
|
||||
inkscape:export-filename="/home/raghu/Desktop/hub-logo.png"
|
||||
inkscape:export-xdpi="95.878258"
|
||||
inkscape:export-ydpi="95.878258">
|
||||
<defs
|
||||
id="defs4629" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="740"
|
||||
inkscape:window-height="449"
|
||||
id="namedview3720"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="234.27717"
|
||||
inkscape:cy="167.57445"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1278353"
|
||||
inkscape:cx="108.86803"
|
||||
inkscape:cy="50.640564"
|
||||
inkscape:window-x="605"
|
||||
inkscape:window-y="98"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g3726"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="10" /><g
|
||||
id="g3726"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1149"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata4632">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="hub logo"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,-579.98759,522.65266)"><g
|
||||
id="g3728"><g
|
||||
id="g3730"
|
||||
clip-path="url(#clipPath3734)"><g
|
||||
id="g3740"
|
||||
transform="translate(469.3467,296.2959)"><path
|
||||
d="m 0,0 c -16.597,0 -31.587,12.581 -32.298,13.186 l -2.058,1.751 1.131,2.452 c 0.44,0.956 11.012,23.476 30.001,27.662 l 1.527,0.336 C 10.532,48.083 22.675,40.327 25.37,28.098 28.065,15.871 20.307,3.728 8.081,1.033 L 6.551,0.698 C 4.36,0.214 2.167,0 0,0"
|
||||
style="fill:#6be273;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3742"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g3744"
|
||||
transform="translate(519.9316,324.9663)"><path
|
||||
d="m 0,0 c -8.052,0 -16.033,3.513 -21.457,10.266 -4.599,5.724 -6.689,12.896 -5.892,20.196 0.797,7.297 4.39,13.85 10.111,18.446 l 1.524,1.225 c 7.78,6.245 18.871,9.487 32.081,9.388 9.773,-0.076 17.263,-1.928 17.578,-2.006 l 2.621,-0.657 0.074,-2.699 C 36.675,52.862 37.313,22.21 18.708,7.269 L 17.184,6.044 C 12.118,1.977 6.044,0 0,0"
|
||||
style="fill:#49c44c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3746"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g3748"
|
||||
transform="translate(533.21,367.6562)"><path
|
||||
d="m 0,0 c -5.312,-1.335 -13.328,-3.353 -20.459,-7.646 -8.907,-5.364 -13.925,-12.827 -14.923,-22.183 l -0.02,-0.188 v -14.901 c -3.873,3.824 -8.159,6.202 -12.809,7.101 -12.143,2.341 -23.14,-5.967 -29.049,-10.433 l 4.296,-5.686 c 5.024,3.797 14.373,10.864 23.402,9.122 5.207,-1.005 9.965,-4.887 14.16,-11.54 v -33.538 h 7.128 v 59.49 c 1.878,16.413 20.17,21.016 30.01,23.492 z"
|
||||
style="fill:#cef6d1;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3750"
|
||||
inkscape:connector-curvature="0" /></g></g></g></g></svg>
|
||||
id="layer1"
|
||||
transform="translate(121.51931,-138.66452)">
|
||||
<rect
|
||||
rx="13.229166"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-filename="/home/raghu/Desktop/send/hub-02.png"
|
||||
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"
|
||||
id="rect828"
|
||||
width="87.3125"
|
||||
height="87.3125"
|
||||
x="-121.51931"
|
||||
y="142.74918"
|
||||
ry="13.229166" />
|
||||
<path
|
||||
style="opacity:1;vector-effect:none;fill:#63c923;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"
|
||||
clip-path="none"
|
||||
d="m -121.51931,202.96343 v 13.86892 c 0,7.32897 5.90017,13.22917 13.22916,13.22917 h 60.854162 c 6.610072,0 12.056133,-4.80013 13.061216,-11.1187 -43.339761,0.1608 -54.359752,-16.03276 -87.144538,-15.97939 z"
|
||||
id="path830"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
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"
|
||||
clip-path="none"
|
||||
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"
|
||||
id="path832"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path834"
|
||||
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"
|
||||
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79375005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
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"
|
||||
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"
|
||||
id="path838"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 8.2 KiB |
@ -7,25 +7,33 @@ frappe.views.HubFactory = frappe.views.Factory.extend({
|
||||
|
||||
const assets = {
|
||||
'List': [
|
||||
'/assets/erpnext/js/hub/hub_page.js',
|
||||
'/assets/erpnext/css/hub.css',
|
||||
'/assets/erpnext/js/hub/hub_listing.js',
|
||||
],
|
||||
'Form': [
|
||||
'/assets/erpnext/js/hub/hub_form.js',
|
||||
'/assets/erpnext/css/hub.css',
|
||||
'/assets/erpnext/js/hub/hub_form.js'
|
||||
]
|
||||
};
|
||||
frappe.model.with_doc('Hub Settings', 'Hub Settings', () => {
|
||||
this.hub_settings = frappe.get_doc('Hub Settings');
|
||||
|
||||
if (!erpnext.hub.pages[page_name]) {
|
||||
if(!frappe.is_online()) {
|
||||
this.render_offline_card();
|
||||
return;
|
||||
}
|
||||
if (!route[2]) {
|
||||
frappe.require(assets['List'], () => {
|
||||
erpnext.hub.pages[page_name] = new erpnext.hub[page+'Listing']({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
if(page === 'Favourites') {
|
||||
erpnext.hub.pages[page_name] = new erpnext.hub['Favourites']({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
} else {
|
||||
erpnext.hub.pages[page_name] = new erpnext.hub[page+'Listing']({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frappe.require(assets['Form'], () => {
|
||||
@ -35,13 +43,29 @@ frappe.views.HubFactory = frappe.views.Factory.extend({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
});
|
||||
}
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
} else {
|
||||
frappe.container.change_to(page_name);
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render_offline_card() {
|
||||
let html = `<div class='page-card' style='margin: 140px auto;'>
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator red'>${'Failed to connect'}</span>
|
||||
</div>
|
||||
<p>${ __("Please check your network connection.") }</p>
|
||||
<div><a href='#Hub/Item' class='btn btn-primary btn-sm'>
|
||||
${ __("Reload") }</a></div>
|
||||
</div>`;
|
||||
|
||||
let page = $('#body_div');
|
||||
page.append(html);
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
erpnext.hub.HubDetailsPage = class HubDetailsPage extends frappe.views.BaseList {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.method = 'erpnext.hub_node.get_details';
|
||||
@ -8,6 +8,25 @@ erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
this.page_name = route[2];
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
return this.get_meta()
|
||||
.then(r => {
|
||||
this.meta = r.message.meta || this.meta;
|
||||
this.categories = r.message.categories || [];
|
||||
this.bootstrap_data(r.message);
|
||||
|
||||
this.getFormFields();
|
||||
});
|
||||
}
|
||||
|
||||
bootstrap_data() { }
|
||||
|
||||
get_meta() {
|
||||
return new Promise(resolve =>
|
||||
frappe.call('erpnext.hub_node.get_meta', {doctype: 'Hub ' + this.doctype}, resolve));
|
||||
}
|
||||
|
||||
|
||||
set_breadcrumbs() {
|
||||
frappe.breadcrumbs.add({
|
||||
label: __('Hub'),
|
||||
@ -21,12 +40,55 @@ erpnext.hub.HubForm = class HubForm 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() { }
|
||||
|
||||
setup_sort_selector() { }
|
||||
|
||||
// let category = this.quick_view.get_values().hub_category;
|
||||
// return new Promise((resolve, reject) => {
|
||||
// frappe.call({
|
||||
// method: 'erpnext.hub_node.update_category',
|
||||
// args: {
|
||||
// hub_item_code: values.hub_item_code,
|
||||
// category: category,
|
||||
// },
|
||||
// callback: (r) => {
|
||||
// resolve();
|
||||
// },
|
||||
// freeze: true
|
||||
// }).fail(reject);
|
||||
// });
|
||||
|
||||
get_timeline() {
|
||||
return `<div class="timeline">
|
||||
<div class="timeline-head">
|
||||
</div>
|
||||
<div class="timeline-new-email">
|
||||
<button class="btn btn-default btn-reply-email btn-xs">
|
||||
${__("Reply")}
|
||||
</button>
|
||||
</div>
|
||||
<div class="timeline-items"></div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
get_footer() {
|
||||
return `<div class="form-footer">
|
||||
<div class="after-save">
|
||||
<div class="form-comments"></div>
|
||||
</div>
|
||||
<div class="pull-right scroll-to-top">
|
||||
<a onclick="frappe.utils.scroll_to(0)"><i class="fa fa-chevron-up text-muted"></i></a>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
hub_sync_id: this.unique_id,
|
||||
@ -48,108 +110,296 @@ erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
<span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(this.page_title)}</div>`;
|
||||
|
||||
this.sidebar.remove_item('image');
|
||||
this.sidebar.add_item({
|
||||
name: 'image',
|
||||
label: image_html
|
||||
});
|
||||
|
||||
let fields = this.get_field_configs();
|
||||
if(!this.form) {
|
||||
let fields = this.formFields;
|
||||
this.form = new frappe.ui.FieldGroup({
|
||||
parent: this.$result,
|
||||
fields
|
||||
});
|
||||
this.form.make();
|
||||
}
|
||||
|
||||
this.form = new frappe.ui.FieldGroup({
|
||||
parent: this.$result,
|
||||
fields
|
||||
});
|
||||
if(this.data.hub_category) {
|
||||
this.form.fields_dict.set_category.hide();
|
||||
}
|
||||
|
||||
this.form.make();
|
||||
this.form.set_values(this.data);
|
||||
this.$result.show();
|
||||
|
||||
this.$timelineList.empty();
|
||||
if(this.data.reviews.length) {
|
||||
this.data.reviews.map(review => {
|
||||
this.addReviewToTimeline(review);
|
||||
})
|
||||
}
|
||||
|
||||
this.postRender()
|
||||
}
|
||||
|
||||
toggle_result_area() {
|
||||
this.$result.toggle(this.unique_id);
|
||||
this.$paging_area.toggle(this.data.length > 0);
|
||||
this.$no_result.toggle(this.data.length == 0);
|
||||
postRender() {}
|
||||
|
||||
const show_more = (this.start + this.page_length) <= this.data.length;
|
||||
this.$paging_area.find('.btn-more')
|
||||
.toggle(show_more);
|
||||
attachFooter() {
|
||||
let footerHtml = `<div class="form-footer">
|
||||
<div class="form-comments"></div>
|
||||
<div class="pull-right scroll-to-top">
|
||||
<a onclick="frappe.utils.scroll_to(0)"><i class="fa fa-chevron-up text-muted"></i></a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
let parent = $('<div>').appendTo(this.page.main.parent());
|
||||
this.$footer = $(footerHtml).appendTo(parent);
|
||||
}
|
||||
|
||||
attachTimeline() {
|
||||
let timelineHtml = `<div class="timeline">
|
||||
<div class="timeline-head">
|
||||
</div>
|
||||
<div class="timeline-new-email">
|
||||
<button class="btn btn-default btn-reply-email btn-xs">
|
||||
${ __("Reply") }
|
||||
</button>
|
||||
</div>
|
||||
<div class="timeline-items"></div>
|
||||
</div>`;
|
||||
|
||||
let parent = this.$footer.find(".form-comments");
|
||||
this.$timeline = $(timelineHtml).appendTo(parent);
|
||||
|
||||
this.$timelineList = this.$timeline.find(".timeline-items");
|
||||
}
|
||||
|
||||
attachReviewArea() {
|
||||
this.comment_area = new frappe.ui.ReviewArea({
|
||||
parent: this.$footer.find('.timeline-head'),
|
||||
mentions: [],
|
||||
on_submit: (val) => {
|
||||
val.user = frappe.session.user;
|
||||
val.username = frappe.session.user_fullname;
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.send_review',
|
||||
args: {
|
||||
hub_item_code: this.data.hub_item_code,
|
||||
review: val
|
||||
},
|
||||
callback: (r) => {
|
||||
this.refresh();
|
||||
this.comment_area.reset();
|
||||
},
|
||||
freeze: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addReviewToTimeline(data) {
|
||||
let username = data.username || data.user || __("Anonymous")
|
||||
let imageHtml = data.user_image
|
||||
? `<div class="avatar-frame" style="background-image: url(${data.user_image})"></div>`
|
||||
: `<div class="standard-image" style="background-color: #fafbfc">${frappe.get_abbr(username)}</div>`
|
||||
|
||||
let editHtml = data.own
|
||||
? `<div class="pull-right hidden-xs close-btn-container">
|
||||
<span class="small text-muted">
|
||||
${'data.delete'}
|
||||
</span>
|
||||
</div>
|
||||
<div class="pull-right edit-btn-container">
|
||||
<span class="small text-muted">
|
||||
${'data.edit'}
|
||||
</span>
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
let ratingHtml = '';
|
||||
|
||||
for(var i = 0; i < 5; i++) {
|
||||
let starIcon = 'fa-star-o'
|
||||
if(i < data.rating) {
|
||||
starIcon = 'fa-star';
|
||||
}
|
||||
ratingHtml += `<i class="fa fa-fw ${starIcon} star-icon" data-idx='${i}'></i>`;
|
||||
}
|
||||
|
||||
$(this.getTimelineItem(data, imageHtml, editHtml, ratingHtml))
|
||||
.appendTo(this.$timelineList);
|
||||
}
|
||||
|
||||
getTimelineItem(data, imageHtml, editHtml, ratingHtml) {
|
||||
return `<div class="media timeline-item user-content" data-doctype="${''}" data-name="${''}">
|
||||
<span class="pull-left avatar avatar-medium hidden-xs" style="margin-top: 1px">
|
||||
${imageHtml}
|
||||
</span>
|
||||
|
||||
<div class="pull-left media-body">
|
||||
<div class="media-content-wrapper">
|
||||
<div class="action-btns">${editHtml}</div>
|
||||
|
||||
<div class="comment-header clearfix small ${'linksActive'}">
|
||||
<span class="pull-left avatar avatar-small visible-xs">
|
||||
${imageHtml}
|
||||
</span>
|
||||
|
||||
<div class="asset-details">
|
||||
<span class="author-wrap">
|
||||
<i class="octicon octicon-quote hidden-xs fa-fw"></i>
|
||||
<span>${data.username}</span>
|
||||
</span>
|
||||
<a href="#Form/${''}" class="text-muted">
|
||||
<span class="text-muted hidden-xs">–</span>
|
||||
<span class="indicator-right ${'green'}
|
||||
delivery-status-indicator">
|
||||
<span class="hidden-xs">${data.pretty_date}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a class="text-muted reply-link pull-right timeline-content-show"
|
||||
title="${__('Reply')}"> ${''} </a>
|
||||
<span class="comment-likes hidden-xs">
|
||||
<i class="octicon octicon-heart like-action text-extra-muted not-liked fa-fw">
|
||||
</i>
|
||||
<span class="likes-count text-muted">10</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reply timeline-content-show">
|
||||
<div class="timeline-item-content">
|
||||
<p class="text-muted small">
|
||||
<b>${data.subject}</b>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p class="text-muted small">
|
||||
${ratingHtml}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
${data.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
prepareFormFields(fields, fieldnames) {
|
||||
return fields
|
||||
.filter(field => fieldnames.includes(field.fieldname))
|
||||
.map(field => {
|
||||
let {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
} = field;
|
||||
let read_only = 1;
|
||||
return {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
read_only,
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubForm{
|
||||
erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubDetailsPage {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Item';
|
||||
this.image_field_name = 'image';
|
||||
}
|
||||
|
||||
get_field_configs() {
|
||||
let fields = [];
|
||||
this.fields.map(fieldname => {
|
||||
fields.push({
|
||||
label: toTitle(frappe.model.unscrub(fieldname)),
|
||||
fieldname,
|
||||
postRender() {
|
||||
this.categoryDialog = new frappe.ui.Dialog({
|
||||
title: __('Suggest Category'),
|
||||
fields: [
|
||||
{
|
||||
label: __('Category'),
|
||||
fieldname: 'category',
|
||||
fieldtype: 'Autocomplete',
|
||||
options: this.categories,
|
||||
reqd: 1
|
||||
}
|
||||
],
|
||||
primary_action_label: __("Send"),
|
||||
primary_action: () => {
|
||||
let values = this.categoryDialog.get_values();
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.update_category',
|
||||
args: {
|
||||
hub_item_code: this.data.hub_item_code,
|
||||
category: values.category
|
||||
},
|
||||
callback: () => {
|
||||
this.refresh();
|
||||
},
|
||||
freeze: true
|
||||
}).fail(() => {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getFormFields() {
|
||||
let colOneFieldnames = ['item_name', 'item_code', 'description'];
|
||||
let colTwoFieldnames = ['seller', 'company_name', 'country'];
|
||||
let colOneFields = this.prepareFormFields(this.meta.fields, colOneFieldnames);
|
||||
let colTwoFields = this.prepareFormFields(this.meta.fields, colTwoFieldnames);
|
||||
|
||||
let miscFields = [
|
||||
{
|
||||
label: __('Category'),
|
||||
fieldname: 'hub_category',
|
||||
fieldtype: 'Data',
|
||||
read_only: 1
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
let category_field = {
|
||||
label: 'Hub Category',
|
||||
fieldname: 'hub_category',
|
||||
fieldtype: 'Data'
|
||||
}
|
||||
{
|
||||
label: __('Suggest Category?'),
|
||||
fieldname: 'set_category',
|
||||
fieldtype: 'Button',
|
||||
click: () => {
|
||||
this.categoryDialog.show();
|
||||
}
|
||||
},
|
||||
|
||||
if(this.data.company_name === this.hub_settings.company) {
|
||||
this.page.set_primary_action(__('Update'), () => {
|
||||
this.update_on_hub();
|
||||
}, 'octicon octicon-plus');
|
||||
} else {
|
||||
category_field.read_only = 1;
|
||||
}
|
||||
|
||||
fields.unshift(category_field);
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
update_on_hub() {
|
||||
return new Promise((resolve, reject) => {
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.update_category',
|
||||
args: { item: this.unique_id, category: this.form.get_value('hub_category') },
|
||||
callback: resolve,
|
||||
freeze: true
|
||||
}).fail(reject);
|
||||
});
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
this.fields = ['hub_item_code', 'item_name', 'item_code', 'description',
|
||||
'seller', 'company_name', 'country'];
|
||||
{
|
||||
fieldname: 'cb1',
|
||||
fieldtype: 'Column Break'
|
||||
}
|
||||
];
|
||||
this.formFields = colOneFields.concat(miscFields, colTwoFields);
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.CompanyPage = class CompanyPage extends erpnext.hub.HubForm{
|
||||
erpnext.hub.CompanyPage = class CompanyPage extends erpnext.hub.HubDetailsPage {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Company';
|
||||
this.image_field_name = 'company_logo';
|
||||
}
|
||||
|
||||
get_field_configs() {
|
||||
let fields = [];
|
||||
this.fields.map(fieldname => {
|
||||
fields.push({
|
||||
label: toTitle(frappe.model.unscrub(fieldname)),
|
||||
fieldname,
|
||||
fieldtype: 'Data',
|
||||
read_only: 1
|
||||
});
|
||||
});
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
this.fields = ['company_name', 'description', 'route', 'country', 'seller', 'site_name'];
|
||||
getFormFields() {
|
||||
let fieldnames = ['company_name', 'description', 'route', 'country', 'seller', 'site_name'];;
|
||||
this.formFields = this.prepareFormFields(this.meta.fields, fieldnames);
|
||||
}
|
||||
}
|
||||
|
665
erpnext/public/js/hub/hub_listing.js
Normal file
665
erpnext/public/js/hub/hub_listing.js
Normal file
@ -0,0 +1,665 @@
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.page_title = __('');
|
||||
this.method = 'erpnext.hub_node.get_list';
|
||||
|
||||
this.cache = {};
|
||||
|
||||
const route = frappe.get_route();
|
||||
this.page_name = route[1];
|
||||
|
||||
this.menu_items = this.menu_items.concat(this.get_menu_items());
|
||||
|
||||
this.imageFieldName = 'image';
|
||||
|
||||
this.show_filters = 0;
|
||||
}
|
||||
|
||||
set_title() {
|
||||
const title = this.page_title;
|
||||
let iconHtml = `<img class="hub-icon" src="assets/erpnext/images/hub_logo.svg">`;
|
||||
let titleHtml = `<span class="hub-page-title">${title}</span>`;
|
||||
this.page.set_title(iconHtml + titleHtml, '', false, title);
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
return this.get_meta()
|
||||
.then(r => {
|
||||
this.meta = r.message.meta || this.meta;
|
||||
frappe.model.sync(this.meta);
|
||||
this.bootstrap_data(r.message);
|
||||
|
||||
this.prepareFormFields();
|
||||
});
|
||||
}
|
||||
|
||||
get_meta() {
|
||||
return new Promise(resolve =>
|
||||
frappe.call('erpnext.hub_node.get_meta', {doctype: this.doctype}, resolve));
|
||||
}
|
||||
|
||||
set_breadcrumbs() { }
|
||||
|
||||
prepareFormFields() { }
|
||||
|
||||
bootstrap_data() { }
|
||||
|
||||
get_menu_items() {
|
||||
const items = [
|
||||
{
|
||||
label: __('Hub Settings'),
|
||||
action: () => frappe.set_route('Form', 'Hub Settings'),
|
||||
standard: true
|
||||
},
|
||||
{
|
||||
label: __('Favourites'),
|
||||
action: () => frappe.set_route('Hub', 'Favourites'),
|
||||
standard: true
|
||||
},
|
||||
// {
|
||||
// label: __('Toggle Sidebar'),
|
||||
// action: () => this.toggle_side_bar(),
|
||||
// standard: true
|
||||
// }
|
||||
];
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
}
|
||||
|
||||
setup_sort_selector() {
|
||||
this.sort_selector = new frappe.ui.SortSelector({
|
||||
parent: this.filter_area.$filter_list_wrapper,
|
||||
doctype: this.doctype,
|
||||
args: this.order_by,
|
||||
onchange: () => this.refresh(true)
|
||||
});
|
||||
}
|
||||
|
||||
setup_view() { }
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
doctype: this.doctype,
|
||||
start: this.start,
|
||||
limit: this.page_length,
|
||||
order_by: this.order_by,
|
||||
// fields: this.fields,
|
||||
filters: this.get_filters_for_args()
|
||||
};
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
const data = r.message;
|
||||
|
||||
if (this.start === 0) {
|
||||
this.data = data;
|
||||
} else {
|
||||
this.data = this.data.concat(data);
|
||||
}
|
||||
|
||||
this.data_dict = {};
|
||||
}
|
||||
|
||||
freeze(toggle) {
|
||||
// if(!this.$freeze) return;
|
||||
// this.$freeze.toggle(toggle);
|
||||
// if (this.$freeze.find('.image-view-container').length) return;
|
||||
|
||||
// const html = Array.from(new Array(4)).map(d => this.card_html({
|
||||
// name: 'Loading...',
|
||||
// item_name: 'Loading...'
|
||||
// })).join('');
|
||||
|
||||
// this.$freeze.html(`<div class="image-view-container border-top">${html}</div>`);
|
||||
}
|
||||
|
||||
render() {
|
||||
this.data_dict = {};
|
||||
this.render_image_view();
|
||||
|
||||
this.setup_quick_view();
|
||||
this.setup_like();
|
||||
}
|
||||
|
||||
render_offline_card() {
|
||||
let html = `<div class='page-card'>
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator red'>
|
||||
{{ _("Payment Cancelled") }}</span>
|
||||
</div>
|
||||
<p>${ __("Your payment is cancelled.") }</p>
|
||||
<div><a href='' class='btn btn-primary btn-sm'>
|
||||
${ __("Continue") }</a></div>
|
||||
</div>`;
|
||||
|
||||
let page = this.page.wrapper.find('.layout-side-section')
|
||||
page.append(html);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
render_image_view() {
|
||||
var html = this.data.map(this.item_html.bind(this)).join("");
|
||||
|
||||
if (this.start === 0) {
|
||||
// this.renderHeader();
|
||||
this.$result.html(`
|
||||
${this.getHeaderHtml()}
|
||||
<div class="image-view-container small">
|
||||
${html}
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
if(this.data.length) {
|
||||
this.doc = this.data[0];
|
||||
}
|
||||
|
||||
this.data.map(this.loadImage.bind(this));
|
||||
|
||||
this.data_dict = {};
|
||||
this.data.map(d => {
|
||||
this.data_dict[d.hub_item_code] = d;
|
||||
});
|
||||
}
|
||||
|
||||
getHeaderHtml() {
|
||||
// let company_html =
|
||||
return `
|
||||
<header class="list-row-head text-muted small">
|
||||
<div style="display: flex;">
|
||||
<div class="list-header-icon">
|
||||
<img title="Riadco%20Group" alt="Riadco Group" src="https://cdn.pbrd.co/images/HdaPxcg.png">
|
||||
</div>
|
||||
<div class="list-header-info">
|
||||
<h5>Riadco Group</h5>
|
||||
<span class="margin-vertical-10 level-item">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</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
`;
|
||||
}
|
||||
|
||||
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>`;
|
||||
}
|
||||
|
||||
get_image_html(encoded_name, src, alt_text) {
|
||||
return `<img data-name="${encoded_name}" src="${ src }" alt="${ alt_text }">`;
|
||||
}
|
||||
|
||||
get_image_placeholder(title) {
|
||||
return `<span class="placeholder-text">${ frappe.get_abbr(title) }</span>`;
|
||||
}
|
||||
|
||||
loadImage(item) {
|
||||
item._name = encodeURI(item.name);
|
||||
const encoded_name = item._name;
|
||||
const title = strip_html(item[this.meta.title_field || 'name']);
|
||||
|
||||
let placeholder = this.get_image_placeholder(title);
|
||||
let $container = this.$result.find(`.image-field[data-name="${encoded_name}"]`);
|
||||
|
||||
if(!item[this.imageFieldName]) {
|
||||
$container.prepend(placeholder);
|
||||
$container.addClass('no-image');
|
||||
}
|
||||
|
||||
frappe.load_image(item[this.imageFieldName],
|
||||
(imageObj) => {
|
||||
$container.prepend(imageObj)
|
||||
},
|
||||
() => {
|
||||
$container.prepend(placeholder);
|
||||
$container.addClass('no-image');
|
||||
},
|
||||
(imageObj) => {
|
||||
imageObj.title = encoded_name;
|
||||
imageObj.alt = title;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
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 += `<i class='fa fa-fw ${starClass} star-icon' data-index=${i}></i>`;
|
||||
}
|
||||
|
||||
let item_html = `
|
||||
<div class="image-view-item">
|
||||
<div class="image-view-header">
|
||||
<div class="list-row-col list-subject ellipsis level">
|
||||
<span class="level-item bold ellipsis" title="McGuffin">
|
||||
<a href="${route}">${title}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted small" style="margin: 5px 0px;">
|
||||
${ratingHtml}
|
||||
(${reviewLength})
|
||||
</div>
|
||||
<div class="list-row-col">
|
||||
<a href="${'#Hub/Company/'+company_name}"><p>${ company_name }</p></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-view-body">
|
||||
<a data-name="${encoded_name}"
|
||||
title="${encoded_name}"
|
||||
href="${route}"
|
||||
>
|
||||
<div class="image-field ${_class}"
|
||||
data-name="${encoded_name}"
|
||||
>
|
||||
<button class="btn btn-default zoom-view" data-name="${encoded_name}">
|
||||
<i class="octicon octicon-eye" data-name="${encoded_name}"></i>
|
||||
</button>
|
||||
<button class="btn btn-default like-button" data-name="${encoded_name}">
|
||||
<i class="octicon octicon-heart" data-name="${encoded_name}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
return item_html;
|
||||
}
|
||||
|
||||
setup_quick_view() {
|
||||
if(this.quick_view) return;
|
||||
|
||||
this.quick_view = new frappe.ui.Dialog({
|
||||
title: 'Quick View',
|
||||
fields: this.formFields
|
||||
});
|
||||
this.$result.on('click', '.btn.zoom-view', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var name = $(e.target).attr('data-name');
|
||||
name = decodeURIComponent(name);
|
||||
|
||||
this.quick_view.set_title(name);
|
||||
let values = this.data_dict[name];
|
||||
this.quick_view.set_values(values);
|
||||
|
||||
let fields = [];
|
||||
|
||||
this.quick_view.show();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
setup_like() {
|
||||
if(this.setup_like_done) return;
|
||||
this.setup_like_done = 1;
|
||||
this.$result.on('click', '.btn.like-button', (e) => {
|
||||
if($(e.target).hasClass('changing')) return;
|
||||
$(e.target).addClass('changing');
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var name = $(e.target).attr('data-name');
|
||||
name = decodeURIComponent(name);
|
||||
let values = this.data_dict[name];
|
||||
|
||||
let heart = $(e.target);
|
||||
if(heart.hasClass('like-button')) {
|
||||
heart = $(e.target).find('.octicon');
|
||||
}
|
||||
|
||||
let remove = 1;
|
||||
|
||||
if(heart.hasClass('liked')) {
|
||||
// unlike
|
||||
heart.removeClass('liked');
|
||||
} else {
|
||||
// like
|
||||
remove = 0;
|
||||
heart.addClass('liked');
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.update_wishlist_item',
|
||||
args: {
|
||||
item_name: values.hub_item_code,
|
||||
remove: remove
|
||||
},
|
||||
callback: (r) => {
|
||||
let message = __("Added to Favourites");
|
||||
if(remove) {
|
||||
message = __("Removed from Favourites");
|
||||
}
|
||||
frappe.show_alert(message);
|
||||
},
|
||||
freeze: true
|
||||
});
|
||||
|
||||
$(e.target).removeClass('changing');
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Item';
|
||||
this.page_title = __('Products');
|
||||
this.fields = ['name', 'hub_item_code', 'image', 'item_name', 'item_code', 'company_name', 'description', 'country'];
|
||||
this.filters = [];
|
||||
}
|
||||
|
||||
bootstrap_data(response) {
|
||||
let companies = response.companies.map(d => d.name);
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Autocomplete',
|
||||
label: __('Select Company'),
|
||||
condition: 'like',
|
||||
fieldname: 'company_name',
|
||||
options: companies
|
||||
},
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: __('Select Country'),
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
prepareFormFields() {
|
||||
let fieldnames = ['item_name', 'description', 'company_name', 'country'];
|
||||
this.formFields = this.meta.fields
|
||||
.filter(field => fieldnames.includes(field.fieldname))
|
||||
.map(field => {
|
||||
let {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
} = field;
|
||||
let read_only = 1;
|
||||
return {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
read_only,
|
||||
};
|
||||
});
|
||||
|
||||
this.formFields.unshift({
|
||||
label: 'image',
|
||||
fieldname: 'image',
|
||||
fieldtype: 'Attach Image'
|
||||
});
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
super.setup_side_bar();
|
||||
|
||||
let $pitch = $(`<div class="border" style="
|
||||
margin-top: 10px;
|
||||
padding: 0px 10px;
|
||||
border-radius: 3px;
|
||||
">
|
||||
<h5>Sell on HubMarket</h5>
|
||||
<p>Over 2000 products listed. Register your company to start selling.</p>
|
||||
</div>`);
|
||||
|
||||
this.sidebar.$sidebar.append($pitch);
|
||||
|
||||
this.category_tree = new frappe.ui.Tree({
|
||||
parent: this.sidebar.$sidebar,
|
||||
label: 'All Categories',
|
||||
expandable: true,
|
||||
|
||||
args: {parent: this.current_category},
|
||||
method: 'erpnext.hub_node.get_categories',
|
||||
on_click: (node) => {
|
||||
this.update_category(node.label);
|
||||
}
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __('Companies'),
|
||||
on_click: () => frappe.set_route('Hub', 'Company')
|
||||
}, undefined, true);
|
||||
|
||||
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: __("Favourites"),
|
||||
on_click: () => frappe.set_route('Hub', 'Favourites')
|
||||
}, __("Account"));
|
||||
}
|
||||
|
||||
update_category(label) {
|
||||
this.current_category = (label=='All Categories') ? undefined : label;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
if(!this.filter_area) return;
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'item_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
if(this.current_category) {
|
||||
filters['hub_category'] = this.current_category;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
super.update_data(r);
|
||||
|
||||
this.data_dict = {};
|
||||
this.data.map(d => {
|
||||
this.data_dict[d.hub_item_code] = d;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.Favourites = class Favourites extends erpnext.hub.ItemListing {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Item';
|
||||
this.page_title = __('Favourites');
|
||||
this.fields = ['name', 'hub_item_code', 'image', 'item_name', 'item_code', 'company_name', 'description', 'country'];
|
||||
this.filters = [];
|
||||
this.method = 'erpnext.hub_node.get_item_favourites';
|
||||
}
|
||||
|
||||
setup_filter_area() { }
|
||||
|
||||
setup_sort_selector() { }
|
||||
|
||||
// setupHe
|
||||
|
||||
getHeaderHtml() {
|
||||
return '';
|
||||
}
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
start: this.start,
|
||||
limit: this.page_length,
|
||||
order_by: this.order_by,
|
||||
fields: this.fields
|
||||
};
|
||||
}
|
||||
|
||||
bootstrap_data(response) { }
|
||||
|
||||
prepareFormFields() { }
|
||||
|
||||
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')
|
||||
});
|
||||
|
||||
// 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) {
|
||||
this.current_category = (label=='All Categories') ? undefined : label;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
if(!this.filter_area) return;
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'item_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
if(this.current_category) {
|
||||
filters['hub_category'] = this.current_category;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
super.update_data(r);
|
||||
|
||||
this.data_dict = {};
|
||||
this.data.map(d => {
|
||||
this.data_dict[d.hub_item_code] = d;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Company';
|
||||
this.page_title = __('Companies');
|
||||
this.fields = ['company_logo', 'name', 'site_name', 'seller_city', 'seller_description', 'seller', 'country', 'company_name'];
|
||||
this.filters = [];
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: 'Country',
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
this.imageFieldName = 'company_logo';
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'company_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
return filters;
|
||||
}
|
||||
|
||||
card_html(company) {
|
||||
company._name = encodeURI(company.name);
|
||||
const route = `#Hub/Company/${company.company_name}`;
|
||||
|
||||
let image_html = company.company_logo ?
|
||||
`<img src="${company.company_logo}"><span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(company.company_name)}</div>`;
|
||||
|
||||
return `
|
||||
<div class="hub-item-wrapper margin-bottom" style="width: 200px;">
|
||||
<a href="${route}">
|
||||
<div class="hub-item-image">
|
||||
<div class="img-wrapper" style="height: 200px; width: 200px">
|
||||
${ image_html }
|
||||
</div>
|
||||
</div>
|
||||
<div class="hub-item-title">
|
||||
<h5 class="bold">
|
||||
${ company.company_name }
|
||||
</h5>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
};
|
@ -1,244 +0,0 @@
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.page_title = __('Hub');
|
||||
this.method = 'erpnext.hub_node.get_list';
|
||||
|
||||
const route = frappe.get_route();
|
||||
this.page_name = route[1];
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
return this.get_meta()
|
||||
.then(r => {
|
||||
this.meta = r.message || this.meta;
|
||||
frappe.model.sync(this.meta);
|
||||
});
|
||||
}
|
||||
|
||||
get_meta() {
|
||||
return new Promise(resolve =>
|
||||
frappe.call('erpnext.hub_node.get_meta', {doctype: this.doctype}, resolve));
|
||||
}
|
||||
|
||||
set_breadcrumbs() { }
|
||||
|
||||
setup_side_bar() {
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
}
|
||||
|
||||
setup_sort_selector() { }
|
||||
|
||||
setup_view() { }
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
doctype: this.doctype,
|
||||
start: this.start,
|
||||
limit: this.page_length,
|
||||
order_by: this.order_by,
|
||||
fields: this.fields,
|
||||
filters: this.get_filters_for_args()
|
||||
};
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
const data = r.message;
|
||||
|
||||
if (this.start === 0) {
|
||||
this.data = data;
|
||||
} else {
|
||||
this.data = this.data.concat(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
freeze(toggle) {
|
||||
this.$freeze.toggle(toggle);
|
||||
if (this.$freeze.find('.image-view-container').length) return;
|
||||
|
||||
const html = Array.from(new Array(4)).map(d => this.card_html({
|
||||
name: 'Loading...',
|
||||
item_name: 'Loading...'
|
||||
})).join('');
|
||||
|
||||
this.$freeze.html(`<div class="image-view-container border-top">${html}</div>`);
|
||||
}
|
||||
|
||||
render() {
|
||||
this.render_image_view();
|
||||
}
|
||||
|
||||
render_image_view() {
|
||||
let data = this.data;
|
||||
if (this.start === 0) {
|
||||
this.$result.html('<div class="image-view-container small padding-top">');
|
||||
data = this.data.slice(this.start);
|
||||
}
|
||||
|
||||
var html = data.map(this.card_html.bind(this)).join("");
|
||||
this.$result.find('.image-view-container').append(html);
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Item';
|
||||
this.fields = ['name', 'hub_item_code', 'image', 'item_name', 'item_code', 'company_name'];
|
||||
this.filters = [];
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: 'Company',
|
||||
condition: 'like',
|
||||
fieldname: 'company_name',
|
||||
},
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: 'Country',
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
super.setup_side_bar();
|
||||
this.category_tree = new frappe.ui.Tree({
|
||||
parent: this.sidebar.$sidebar,
|
||||
label: 'All Categories',
|
||||
expandable: true,
|
||||
|
||||
args: {parent: this.current_category},
|
||||
method: 'erpnext.hub_node.get_categories',
|
||||
on_click: (node) => {
|
||||
this.update_category(node.label);
|
||||
}
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __('Companies'),
|
||||
on_click: () => frappe.set_route('Hub', 'Company')
|
||||
});
|
||||
|
||||
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) {
|
||||
this.current_category = (label=='All Categories') ? undefined : label;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'item_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
if(this.current_category) {
|
||||
filters['hub_category'] = this.current_category;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
card_html(item) {
|
||||
item._name = encodeURI(item.name);
|
||||
const encoded_name = item._name;
|
||||
const title = strip_html(item['item_name' || 'item_code']);
|
||||
const company_name = item['company_name'];
|
||||
|
||||
const route = `#Hub/Item/${item.hub_item_code}`;
|
||||
|
||||
const image_html = item.image ?
|
||||
`<img src="${item.image}">
|
||||
<span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(title)}</div>`;
|
||||
|
||||
return `
|
||||
<div class="hub-item-wrapper margin-bottom" style="width: 200px;">
|
||||
<a href="${route}">
|
||||
<div class="hub-item-image">
|
||||
<div class="img-wrapper" style="height: 200px; width: 200px">
|
||||
${ image_html }
|
||||
</div>
|
||||
</div>
|
||||
<div class="hub-item-title">
|
||||
<h5 class="bold">
|
||||
${ title }
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
<a href="${'#Hub/Company/'+company_name}"><p>${ company_name }</p></a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Company';
|
||||
this.fields = ['company_logo', 'name', 'site_name', 'seller_city', 'seller_description', 'seller', 'country', 'company_name'];
|
||||
this.filters = [];
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: 'Country',
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'company_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
return filters;
|
||||
}
|
||||
|
||||
card_html(company) {
|
||||
company._name = encodeURI(company.name);
|
||||
const route = `#Hub/Company/${company.company_name}`;
|
||||
|
||||
let image_html = company.company_logo ?
|
||||
`<img src="${company.company_logo}"><span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(company.company_name)}</div>`;
|
||||
|
||||
return `
|
||||
<div class="hub-item-wrapper margin-bottom" style="width: 200px;">
|
||||
<a href="${route}">
|
||||
<div class="hub-item-image">
|
||||
<div class="img-wrapper" style="height: 200px; width: 200px">
|
||||
${ image_html }
|
||||
</div>
|
||||
</div>
|
||||
<div class="hub-item-title">
|
||||
<h5 class="bold">
|
||||
${ company.company_name }
|
||||
</h5>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
};
|
@ -1,176 +1,109 @@
|
||||
@import "../../../../frappe/frappe/public/less/variables.less";
|
||||
|
||||
body[data-route^="Hub/"] {
|
||||
.freeze .image-view-container {
|
||||
.list-row-col {
|
||||
background-color: @light-bg;
|
||||
color: @light-bg;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
color: @light-bg;
|
||||
}
|
||||
.hub-icon {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.freeze {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image-view-container {
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
.helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
/* hub */
|
||||
div[data-page-route="hub"] {
|
||||
.page-head {
|
||||
height: 80px;
|
||||
|
||||
.title-text {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.page-content {
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.page-title h1 {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.account-details {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
[data-original-title="Search"] {
|
||||
float: right;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.hub-main-section {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.listing-body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.main-list-section {
|
||||
padding: 0;
|
||||
// border-right: 1px solid #d1d8dd;
|
||||
}
|
||||
|
||||
.side-list-section {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.item-list-header h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hub-item-page {
|
||||
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.item-header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-page-image {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title-content {
|
||||
flex: 3;
|
||||
|
||||
.description {
|
||||
margin: 30px 0px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 30px;
|
||||
|
||||
.rfq-btn.disabled {
|
||||
background-color: #b1bdca;
|
||||
color: #fff;
|
||||
border-color: #b1bdca;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.company-items {
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.company-header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.hub-item-wrapper {
|
||||
margin-bottom: 20px;
|
||||
.hub-page-title {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
border: 1px solid @border-color;
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.standard-image {
|
||||
font-size: 72px;
|
||||
border: none;
|
||||
background-color: @light-bg;
|
||||
.tree {
|
||||
margin: 10px 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tree.with-skeleton.opened::before {
|
||||
left: 9px;
|
||||
top: 14px;
|
||||
height: calc(~"100% - 32px");
|
||||
}
|
||||
|
||||
.list-header-icon {
|
||||
width: 72px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
margin: 10px;
|
||||
padding: 1px;
|
||||
border: 1px solid @border-color;
|
||||
height: 72px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.hub-item-title {
|
||||
width: 100%;
|
||||
.star-icon.fa-star {
|
||||
color: @indicator-orange;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
padding-left: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 10px;
|
||||
.octicon-heart.liked {
|
||||
color: @indicator-red;
|
||||
}
|
||||
|
||||
}
|
||||
.margin-vertical-10 {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.margin-vertical-15 {
|
||||
margin: 15px 0px;
|
||||
}
|
||||
|
||||
.frappe-list .result {
|
||||
min-height: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.image-view-container {
|
||||
.image-view-body {
|
||||
&:hover .like-button {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.like-button {
|
||||
bottom: 10px !important;
|
||||
left: 10px !important;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
opacity: 0;
|
||||
font-size: 16px;
|
||||
color: @text-color;
|
||||
position: absolute;
|
||||
|
||||
// show zoom button on mobile devices
|
||||
@media (max-width: @screen-xs) {
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
|
||||
.image-view-body:hover .like-button {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.rating-area .star-icon {
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ def get_slide_settings():
|
||||
|
||||
doc = frappe.get_doc("Setup Progress")
|
||||
item = [d for d in doc.get("actions") if d.action_name == "Set Sales Target"]
|
||||
|
||||
|
||||
if len(item):
|
||||
item = item[0]
|
||||
if not item.action_document:
|
||||
|
Loading…
x
Reference in New Issue
Block a user