[refactor][major] Separate out Components
- item_card - item_card_container - detail_view - search_bar - reviews - skeleton_state - empty_state - empty_state
This commit is contained in:
parent
b777f3dbfd
commit
c5a9972785
160
erpnext/public/js/hub/components/detail_view.js
Normal file
160
erpnext/public/js/hub/components/detail_view.js
Normal file
@ -0,0 +1,160 @@
|
||||
function get_detail_view_html(item, allow_edit) {
|
||||
const title = item.item_name || item.name;
|
||||
const seller = item.company;
|
||||
|
||||
const who = __('Posted By {0}', [seller]);
|
||||
const when = comment_when(item.creation);
|
||||
|
||||
const city = item.city ? item.city + ', ' : '';
|
||||
const country = item.country ? item.country : '';
|
||||
const where = `${city}${country}`;
|
||||
|
||||
const dot_spacer = '<span aria-hidden="true"> · </span>';
|
||||
|
||||
const description = item.description || '';
|
||||
|
||||
let stats = __('No views yet');
|
||||
if(item.view_count) {
|
||||
const views_message = __(`${item.view_count} Views`);
|
||||
|
||||
const rating_html = get_rating_html(item.average_rating);
|
||||
const rating_count = item.no_of_ratings > 0 ? `${item.no_of_ratings} reviews` : __('No reviews yet');
|
||||
|
||||
stats = `${views_message}${dot_spacer}${rating_html} (${rating_count})`;
|
||||
}
|
||||
|
||||
|
||||
let menu_items = '';
|
||||
|
||||
if(allow_edit) {
|
||||
menu_items = `
|
||||
<li><a data-action="edit_details">${__('Edit Details')}</a></li>
|
||||
<li><a data-action="unpublish_item">${__('Unpublish')}</a></li>`;
|
||||
} else {
|
||||
menu_items = `
|
||||
<li><a data-action="report_item">${__('Report this item')}</a></li>
|
||||
`;
|
||||
}
|
||||
|
||||
const html = `
|
||||
<div class="hub-item-container">
|
||||
<div class="row visible-xs">
|
||||
<div class="col-xs-12 margin-bottom">
|
||||
<button class="btn btn-xs btn-default" data-route="marketplace/home">${__('Back to home')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row detail-page-section margin-bottom">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-image">
|
||||
<img src="${item.image}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 flex flex-column">
|
||||
<div class="detail-page-header">
|
||||
<h2>${title}</h2>
|
||||
<div class="text-muted">
|
||||
<p>${where}${dot_spacer}${when}</p>
|
||||
<p>${stats}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-actions detail-page-actions">
|
||||
<button class="btn btn-default text-muted favourite-button" data-action="add_to_favourites">
|
||||
${__('Add to Favourites')} <i class="octicon octicon-heart text-extra-muted"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary" data-action="contact_seller">
|
||||
${__('Contact Seller')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<div class="dropdown pull-right hub-item-dropdown">
|
||||
<a class="dropdown-toggle btn btn-xs btn-default" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-right" role="menu">
|
||||
${menu_items}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row hub-item-description">
|
||||
<h6 class="col-md-12 margin-top">
|
||||
<b class="text-muted">Product Description</b>
|
||||
</h6>
|
||||
<p class="col-md-12">
|
||||
${description ? description : __('No details')}
|
||||
</p>
|
||||
</div>
|
||||
<div class="row hub-item-seller">
|
||||
|
||||
<h6 class="col-md-12 margin-top margin-bottom">
|
||||
<b class="text-muted">Seller Information</b>
|
||||
</h6>
|
||||
<div class="col-md-1">
|
||||
<img src="https://picsum.photos/200">
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="margin-bottom"><a href="#marketplace/seller/${seller}" class="bold">${seller}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- review area -->
|
||||
<div class="row hub-item-review-container">
|
||||
<div class="col-md-12 form-footer">
|
||||
<div class="form-comments">
|
||||
<div class="timeline">
|
||||
<div class="timeline-head"></div>
|
||||
<div class="timeline-items"></div>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function get_profile_html(profile) {
|
||||
const p = profile;
|
||||
const profile_html = `<div class="hub-item-container">
|
||||
<div class="row visible-xs">
|
||||
<div class="col-xs-12 margin-bottom">
|
||||
<button class="btn btn-xs btn-default" data-route="marketplace/home">Back to home</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-image">
|
||||
<img src="${p.logo}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h2>${p.company}</h2>
|
||||
<div class="text-muted">
|
||||
<p>${p.country}</p>
|
||||
<p>${p.site_name}</p>
|
||||
<p>${__(`Joined ${comment_when(p.creation)}`)}</p>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="hub-item-description">
|
||||
${'description'
|
||||
? `<p>${p.company_description}</p>`
|
||||
: `<p>__('No description')</p`
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
|
||||
return profile_html;
|
||||
}
|
||||
|
||||
export {
|
||||
get_detail_view_html,
|
||||
get_profile_html
|
||||
}
|
10
erpnext/public/js/hub/components/empty_state.js
Normal file
10
erpnext/public/js/hub/components/empty_state.js
Normal file
@ -0,0 +1,10 @@
|
||||
function get_empty_state(message, action) {
|
||||
return `<div class="empty-state flex align-center flex-column justify-center">
|
||||
<p class="text-muted">${message}</p>
|
||||
${action ? `<p>${action}</p>`: ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
export {
|
||||
get_empty_state
|
||||
}
|
@ -1,27 +1,3 @@
|
||||
function get_empty_state(message, action) {
|
||||
return `<div class="empty-state flex align-center flex-column justify-center">
|
||||
<p class="text-muted">${message}</p>
|
||||
${action ? `<p>${action}</p>`: ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function get_item_card_container_html(items, title='', get_item_html = get_item_card_html, action='') {
|
||||
const items_html = (items || []).map(item => get_item_html(item)).join('');
|
||||
const title_html = title
|
||||
? `<div class="hub-card-container-header col-sm-12 margin-bottom flex">
|
||||
<h4>${title}</h4>
|
||||
${action}
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
const html = `<div class="row hub-card-container">
|
||||
${title_html}
|
||||
${items_html}
|
||||
</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function get_item_card_html(item) {
|
||||
const item_name = item.item_name || item.name;
|
||||
const title = strip_html(item_name);
|
||||
@ -117,28 +93,8 @@ function get_rating_html(rating) {
|
||||
return rating_html;
|
||||
}
|
||||
|
||||
function make_search_bar({wrapper, on_search, placeholder = __('Search for anything')}) {
|
||||
const $search = $(`
|
||||
<div class="hub-search-container">
|
||||
<input type="text" class="form-control" placeholder="${placeholder}">
|
||||
</div>`
|
||||
);
|
||||
wrapper.append($search);
|
||||
const $search_input = $search.find('input');
|
||||
|
||||
$search_input.on('keydown', frappe.utils.debounce((e) => {
|
||||
if (e.which === frappe.ui.keyCode.ENTER) {
|
||||
const search_value = $search_input.val();
|
||||
on_search(search_value);
|
||||
}
|
||||
}, 300));
|
||||
}
|
||||
|
||||
export {
|
||||
get_empty_state,
|
||||
get_item_card_container_html,
|
||||
get_item_card_html,
|
||||
get_local_item_card_html,
|
||||
get_rating_html,
|
||||
make_search_bar,
|
||||
get_local_item_card_html,
|
||||
get_rating_html
|
||||
}
|
22
erpnext/public/js/hub/components/items_container.js
Normal file
22
erpnext/public/js/hub/components/items_container.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { get_item_card_html } from './item_card';
|
||||
|
||||
function get_item_card_container_html(items, title='', get_item_html = get_item_card_html, action='') {
|
||||
const items_html = (items || []).map(item => get_item_html(item)).join('');
|
||||
const title_html = title
|
||||
? `<div class="hub-card-container-header col-sm-12 margin-bottom flex">
|
||||
<h4>${title}</h4>
|
||||
${action}
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
const html = `<div class="row hub-card-container">
|
||||
${title_html}
|
||||
${items_html}
|
||||
</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
export {
|
||||
get_item_card_container_html
|
||||
}
|
71
erpnext/public/js/hub/components/reviews.js
Normal file
71
erpnext/public/js/hub/components/reviews.js
Normal file
@ -0,0 +1,71 @@
|
||||
import { get_rating_html } from './item_card';
|
||||
|
||||
function get_review_html(review) {
|
||||
let username = review.username || review.user || __("Anonymous");
|
||||
|
||||
let image_html = review.user_image
|
||||
? `<div class="avatar-frame" style="background-image: url(${review.user_image})"></div>`
|
||||
: `<div class="standard-image" style="background-color: #fafbfc">${frappe.get_abbr(username)}</div>`
|
||||
|
||||
let edit_html = review.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 rating_html = get_rating_html(review.rating);
|
||||
|
||||
return get_timeline_item(review, image_html, edit_html, rating_html);
|
||||
}
|
||||
|
||||
function get_timeline_item(data, image_html, edit_html, rating_html) {
|
||||
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">
|
||||
${image_html}
|
||||
</span>
|
||||
<div class="pull-left media-body">
|
||||
<div class="media-content-wrapper">
|
||||
<div class="action-btns">${edit_html}</div>
|
||||
|
||||
<div class="comment-header clearfix">
|
||||
<span class="pull-left avatar avatar-small visible-xs">
|
||||
${image_html}
|
||||
</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 class="text-muted">
|
||||
<span class="text-muted hidden-xs">–</span>
|
||||
<span class="hidden-xs">${comment_when(data.modified)}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reply timeline-content-show">
|
||||
<div class="timeline-item-content">
|
||||
<p class="text-muted">
|
||||
${rating_html}
|
||||
</p>
|
||||
<h6 class="bold">${data.subject}</h6>
|
||||
<p class="text-muted">
|
||||
${data.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
export {
|
||||
get_review_html
|
||||
}
|
20
erpnext/public/js/hub/components/search_bar.js
Normal file
20
erpnext/public/js/hub/components/search_bar.js
Normal file
@ -0,0 +1,20 @@
|
||||
function make_search_bar({wrapper, on_search, placeholder = __('Search for anything')}) {
|
||||
const $search = $(`
|
||||
<div class="hub-search-container">
|
||||
<input type="text" class="form-control" placeholder="${placeholder}">
|
||||
</div>`
|
||||
);
|
||||
wrapper.append($search);
|
||||
const $search_input = $search.find('input');
|
||||
|
||||
$search_input.on('keydown', frappe.utils.debounce((e) => {
|
||||
if (e.which === frappe.ui.keyCode.ENTER) {
|
||||
const search_value = $search_input.val();
|
||||
on_search(search_value);
|
||||
}
|
||||
}, 300));
|
||||
}
|
||||
|
||||
export {
|
||||
make_search_bar
|
||||
}
|
27
erpnext/public/js/hub/components/skeleton_state.js
Normal file
27
erpnext/public/js/hub/components/skeleton_state.js
Normal file
@ -0,0 +1,27 @@
|
||||
function get_detail_skeleton_html() {
|
||||
const skeleton = `<div class="hub-item-container">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-skeleton-image"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h2 class="hub-skeleton" style="width: 75%;">Name</h2>
|
||||
<div class="text-muted">
|
||||
<p class="hub-skeleton" style="width: 35%;">Details</p>
|
||||
<p class="hub-skeleton" style="width: 50%;">Ratings</p>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="hub-item-description">
|
||||
<p class="hub-skeleton">Desc</p>
|
||||
<p class="hub-skeleton" style="width: 85%;">Desc</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
return skeleton;
|
||||
}
|
||||
|
||||
export {
|
||||
get_detail_skeleton_html
|
||||
}
|
@ -13,7 +13,6 @@ import './pages/messages';
|
||||
import './pages/not_found';
|
||||
|
||||
// helpers
|
||||
import './helpers';
|
||||
import './hub_call';
|
||||
|
||||
frappe.provide('hub');
|
||||
|
@ -1,5 +1,5 @@
|
||||
import SubPage from './subpage';
|
||||
import { get_item_card_container_html } from '../helpers';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
|
||||
erpnext.hub.Category = class Category extends SubPage {
|
||||
refresh() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import SubPage from './subpage';
|
||||
import { get_item_card_container_html } from '../helpers';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
|
||||
erpnext.hub.Favourites = class Favourites extends SubPage {
|
||||
refresh() {
|
||||
@ -10,7 +10,9 @@ erpnext.hub.Favourites = class Favourites extends SubPage {
|
||||
}
|
||||
|
||||
get_favourites() {
|
||||
return hub.call('get_item_favourites');
|
||||
return hub.call('get_favourite_items_of_seller', {
|
||||
hub_seller: hub.settings.company_email
|
||||
});
|
||||
}
|
||||
|
||||
render(items) {
|
||||
@ -18,4 +20,4 @@ erpnext.hub.Favourites = class Favourites extends SubPage {
|
||||
const html = get_item_card_container_html(items, __('Favourites'));
|
||||
this.$wrapper.append(html)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import SubPage from './subpage';
|
||||
import { make_search_bar, get_item_card_container_html, get_item_card_html } from '../helpers';
|
||||
import { make_search_bar } from '../components/search_bar';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
import { get_item_card_html } from '../components/item_card';
|
||||
|
||||
erpnext.hub.Home = class Home extends SubPage {
|
||||
make_wrapper() {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import SubPage from './subpage';
|
||||
import { get_rating_html } from '../helpers';
|
||||
import { get_detail_view_html } from '../components/detail_view';
|
||||
import { get_detail_skeleton_html } from '../components/skeleton_state';
|
||||
import { get_review_html } from '../components/reviews';
|
||||
|
||||
erpnext.hub.Item = class Item extends SubPage {
|
||||
refresh() {
|
||||
@ -16,30 +18,12 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
});
|
||||
}
|
||||
|
||||
show_skeleton() {
|
||||
const skeleton = `<div class="hub-item-container">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-skeleton-image"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h2 class="hub-skeleton" style="width: 75%;">Name</h2>
|
||||
<div class="text-muted">
|
||||
<p class="hub-skeleton" style="width: 35%;">Details</p>
|
||||
<p class="hub-skeleton" style="width: 50%;">Ratings</p>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="hub-item-description">
|
||||
<p class="hub-skeleton">Desc</p>
|
||||
<p class="hub-skeleton" style="width: 85%;">Desc</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
this.$wrapper.html(skeleton);
|
||||
show_skeleton() {
|
||||
this.$wrapper.html(get_detail_skeleton_html());
|
||||
}
|
||||
|
||||
|
||||
get_item(hub_item_code) {
|
||||
return hub.call('get_item_details', {
|
||||
hub_seller: hub.settings.company_email,
|
||||
@ -47,123 +31,9 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
render(item) {
|
||||
const title = item.item_name || item.name;
|
||||
const seller = item.company;
|
||||
|
||||
const who = __('Posted By {0}', [seller]);
|
||||
const when = comment_when(item.creation);
|
||||
|
||||
const city = item.city ? item.city + ', ' : '';
|
||||
const country = item.country ? item.country : '';
|
||||
const where = `${city}${country}`;
|
||||
|
||||
const dot_spacer = '<span aria-hidden="true"> · </span>';
|
||||
|
||||
const description = item.description || '';
|
||||
|
||||
let stats = __('No views yet');
|
||||
if(item.view_count) {
|
||||
const views_message = __(`${item.view_count} Views`);
|
||||
|
||||
const rating_html = get_rating_html(item.average_rating);
|
||||
const rating_count = item.no_of_ratings > 0 ? `${item.no_of_ratings} reviews` : __('No reviews yet');
|
||||
|
||||
stats = `${views_message}${dot_spacer}${rating_html} (${rating_count})`;
|
||||
}
|
||||
|
||||
|
||||
let menu_items = '';
|
||||
|
||||
if(this.own_item) {
|
||||
menu_items = `
|
||||
<li><a data-action="edit_details">${__('Edit Details')}</a></li>
|
||||
<li><a data-action="unpublish_item">${__('Unpublish')}</a></li>`;
|
||||
} else {
|
||||
menu_items = `
|
||||
<li><a data-action="report_item">${__('Report this item')}</a></li>
|
||||
`;
|
||||
}
|
||||
|
||||
const html = `
|
||||
<div class="hub-item-container">
|
||||
<div class="row visible-xs">
|
||||
<div class="col-xs-12 margin-bottom">
|
||||
<button class="btn btn-xs btn-default" data-route="marketplace/home">${__('Back to home')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row detail-page-section margin-bottom">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-image">
|
||||
<img src="${item.image}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 flex flex-column">
|
||||
<div class="detail-page-header">
|
||||
<h2>${title}</h2>
|
||||
<div class="text-muted">
|
||||
<p>${where}${dot_spacer}${when}</p>
|
||||
<p>${stats}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-actions detail-page-actions">
|
||||
<button class="btn btn-default text-muted" data-action="add_to_favourites">
|
||||
${__('Add to Favourites')} <i class="octicon octicon-heart text-extra-muted"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary" data-action="contact_seller">
|
||||
${__('Contact Seller')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<div class="dropdown pull-right hub-item-dropdown">
|
||||
<a class="dropdown-toggle btn btn-xs btn-default" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-right" role="menu">
|
||||
${menu_items}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row hub-item-description">
|
||||
<h6 class="col-md-12 margin-top">
|
||||
<b class="text-muted">Product Description</b>
|
||||
</h6>
|
||||
<p class="col-md-12">
|
||||
${description ? description : __('No details')}
|
||||
</p>
|
||||
</div>
|
||||
<div class="row hub-item-seller">
|
||||
|
||||
<h6 class="col-md-12 margin-top margin-bottom">
|
||||
<b class="text-muted">Seller Information</b>
|
||||
</h6>
|
||||
<div class="col-md-1">
|
||||
<img src="https://picsum.photos/200">
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="margin-bottom"><a href="#marketplace/seller/${seller}" class="bold">${seller}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- review area -->
|
||||
<div class="row hub-item-review-container">
|
||||
<div class="col-md-12 form-footer">
|
||||
<div class="form-comments">
|
||||
<div class="timeline">
|
||||
<div class="timeline-head"></div>
|
||||
<div class="timeline-items"></div>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const html = get_detail_view_html(item, this.own_item);
|
||||
this.$wrapper.html(html);
|
||||
|
||||
this.make_review_area();
|
||||
@ -171,10 +41,11 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
this.get_reviews()
|
||||
.then(reviews => {
|
||||
this.reviews = reviews;
|
||||
this.render_reviews(reviews);
|
||||
this.render_reviews();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
edit_details() {
|
||||
if (!this.edit_dialog) {
|
||||
this.edit_dialog = new frappe.ui.Dialog({
|
||||
@ -185,6 +56,7 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
this.edit_dialog.show();
|
||||
}
|
||||
|
||||
|
||||
unpublish_item() {
|
||||
if(!this.unpublish_dialog) {
|
||||
this.unpublish_dialog = new frappe.ui.Dialog({
|
||||
@ -196,6 +68,16 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
this.unpublish_dialog.show();
|
||||
}
|
||||
|
||||
|
||||
add_to_favourites(favourite_button) {
|
||||
$(favourite_button).html('Added to Favourites').addClass('disabled');
|
||||
return hub.call('remove_item_from_seller_favourites', {
|
||||
hub_item_code: this.hub_item_code,
|
||||
hub_seller: hub.settings.company_email
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
contact_seller() {
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Send a message'),
|
||||
@ -220,37 +102,48 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
d.show();
|
||||
}
|
||||
|
||||
|
||||
make_review_area() {
|
||||
this.comment_area = new frappe.ui.ReviewArea({
|
||||
parent: this.$wrapper.find('.timeline-head').empty(),
|
||||
mentions: [],
|
||||
on_submit: (values) => {
|
||||
values.user = frappe.session.user;
|
||||
values.username = frappe.session.user_fullname;
|
||||
|
||||
hub.call('add_item_review', {
|
||||
hub_item_code: this.hub_item_code,
|
||||
review: JSON.stringify(values)
|
||||
})
|
||||
.then(review => {
|
||||
this.reviews = this.reviews || [];
|
||||
this.reviews.push(review);
|
||||
this.render_reviews(this.reviews);
|
||||
|
||||
this.comment_area.reset();
|
||||
});
|
||||
}
|
||||
on_submit: this.on_submit_review.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
on_submit_review(values) {
|
||||
values.user = frappe.session.user;
|
||||
values.username = frappe.session.user_fullname;
|
||||
|
||||
hub.call('add_item_review', {
|
||||
hub_item_code: this.hub_item_code,
|
||||
review: JSON.stringify(values)
|
||||
})
|
||||
.then(this.push_review_in_review_area.bind(this));
|
||||
}
|
||||
|
||||
|
||||
push_review_in_review_area(review) {
|
||||
this.reviews = this.reviews || [];
|
||||
this.reviews.push(review);
|
||||
this.render_reviews();
|
||||
|
||||
this.comment_area.reset();
|
||||
}
|
||||
|
||||
|
||||
get_reviews() {
|
||||
return hub.call('get_item_reviews', { hub_item_code: this.hub_item_code }).catch(() => {});
|
||||
}
|
||||
|
||||
render_reviews(reviews=[]) {
|
||||
this.$wrapper.find('.timeline-items').empty();
|
||||
|
||||
reviews.sort((a, b) => {
|
||||
render_reviews() {
|
||||
const $timeline = this.$wrapper.find('.timeline-items');
|
||||
|
||||
$timeline.empty();
|
||||
|
||||
this.reviews.sort((a, b) => {
|
||||
if (a.modified > b.modified) {
|
||||
return -1;
|
||||
}
|
||||
@ -262,75 +155,8 @@ erpnext.hub.Item = class Item extends SubPage {
|
||||
return 0;
|
||||
});
|
||||
|
||||
reviews.forEach(review => this.render_review(review));
|
||||
}
|
||||
|
||||
render_review(review) {
|
||||
let username = review.username || review.user || __("Anonymous");
|
||||
|
||||
let image_html = review.user_image
|
||||
? `<div class="avatar-frame" style="background-image: url(${review.user_image})"></div>`
|
||||
: `<div class="standard-image" style="background-color: #fafbfc">${frappe.get_abbr(username)}</div>`
|
||||
|
||||
let edit_html = review.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 rating_html = get_rating_html(review.rating);
|
||||
|
||||
const $timeline_items = this.$wrapper.find('.timeline-items');
|
||||
|
||||
$(this.get_timeline_item(review, image_html, edit_html, rating_html))
|
||||
.appendTo($timeline_items);
|
||||
}
|
||||
|
||||
get_timeline_item(data, image_html, edit_html, rating_html) {
|
||||
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">
|
||||
${image_html}
|
||||
</span>
|
||||
<div class="pull-left media-body">
|
||||
<div class="media-content-wrapper">
|
||||
<div class="action-btns">${edit_html}</div>
|
||||
|
||||
<div class="comment-header clearfix">
|
||||
<span class="pull-left avatar avatar-small visible-xs">
|
||||
${image_html}
|
||||
</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 class="text-muted">
|
||||
<span class="text-muted hidden-xs">–</span>
|
||||
<span class="hidden-xs">${comment_when(data.modified)}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reply timeline-content-show">
|
||||
<div class="timeline-item-content">
|
||||
<p class="text-muted">
|
||||
${rating_html}
|
||||
</p>
|
||||
<h6 class="bold">${data.subject}</h6>
|
||||
<p class="text-muted">
|
||||
${data.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
this.reviews.forEach(review => {
|
||||
$(get_review_html(review)).appendTo($timeline);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import SubPage from './subpage';
|
||||
import { make_search_bar } from '../helpers';
|
||||
import { make_search_bar } from '../components/search_bar';
|
||||
|
||||
erpnext.hub.Messages = class Messages extends SubPage {
|
||||
make_wrapper() {
|
||||
@ -115,4 +115,4 @@ function get_message_html(message) {
|
||||
<p>${message.content}</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import SubPage from './subpage';
|
||||
import { get_empty_state } from '../components/empty_state';
|
||||
|
||||
erpnext.hub.NotFound = class NotFound extends SubPage {
|
||||
refresh() {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import SubPage from './subpage';
|
||||
import { make_search_bar, get_item_card_container_html, get_local_item_card_html } from '../helpers';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
import { get_local_item_card_html } from '../components/item_card';
|
||||
import { make_search_bar } from '../components/search_bar';
|
||||
|
||||
erpnext.hub.Publish = class Publish extends SubPage {
|
||||
make_wrapper() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import SubPage from './subpage';
|
||||
import { get_item_card_container_html } from '../helpers';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
|
||||
erpnext.hub.PublishedProducts = class PublishedProducts extends SubPage {
|
||||
get_items_and_render() {
|
||||
|
@ -82,29 +82,33 @@ erpnext.hub.Register = class Register extends SubPage {
|
||||
this.$form_container.find('.form-message').removeClass('hidden small').addClass('h4').text(__('Become a Seller'))
|
||||
|
||||
this.$form_container.on('click', '.btn-register', (e) => {
|
||||
const form_values = this.field_group.get_values();
|
||||
this.register_seller();
|
||||
});
|
||||
}
|
||||
|
||||
let values_filled = true;
|
||||
const mandatory_fields = ['company', 'company_email', 'company_description'];
|
||||
mandatory_fields.forEach(field => {
|
||||
const value = form_values[field];
|
||||
if (!value) {
|
||||
this.field_group.set_df_property(field, 'reqd', 1);
|
||||
values_filled = false;
|
||||
}
|
||||
});
|
||||
if (!values_filled) return;
|
||||
register_seller() {
|
||||
const form_values = this.field_group.get_values();
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.doctype.hub_settings.hub_settings.register_seller',
|
||||
args: form_values,
|
||||
btn: $(e.currentTarget)
|
||||
}).then(() => {
|
||||
frappe.set_route('marketplace', 'publish');
|
||||
let values_filled = true;
|
||||
const mandatory_fields = ['company', 'company_email', 'company_description'];
|
||||
mandatory_fields.forEach(field => {
|
||||
const value = form_values[field];
|
||||
if (!value) {
|
||||
this.field_group.set_df_property(field, 'reqd', 1);
|
||||
values_filled = false;
|
||||
}
|
||||
});
|
||||
if (!values_filled) return;
|
||||
|
||||
// custom jquery event
|
||||
this.$wrapper.trigger('seller-registered');
|
||||
});
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.doctype.hub_settings.hub_settings.register_seller',
|
||||
args: form_values,
|
||||
btn: $(e.currentTarget)
|
||||
}).then(() => {
|
||||
frappe.set_route('marketplace', 'publish');
|
||||
|
||||
// custom jquery event
|
||||
this.$wrapper.trigger('seller-registered');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import SubPage from './subpage';
|
||||
import { make_search_bar, get_item_card_container_html } from '../helpers';
|
||||
import { make_search_bar } from '../components/search_bar';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
|
||||
erpnext.hub.SearchPage = class SearchPage extends SubPage {
|
||||
make_wrapper() {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import SubPage from './subpage';
|
||||
import { get_item_card_container_html } from '../helpers';
|
||||
import { get_profile_html } from '../components/detail_view';
|
||||
import { get_item_card_container_html } from '../components/items_container';
|
||||
import { get_detail_skeleton_html } from '../components/skeleton_state';
|
||||
|
||||
erpnext.hub.Seller = class Seller extends SubPage {
|
||||
make_wrapper() {
|
||||
@ -18,64 +20,11 @@ erpnext.hub.Seller = class Seller extends SubPage {
|
||||
}
|
||||
|
||||
show_skeleton() {
|
||||
const skeleton = `<div class="hub-item-container">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-skeleton-image"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h2 class="hub-skeleton" style="width: 75%;">Name</h2>
|
||||
<div class="text-muted">
|
||||
<p class="hub-skeleton" style="width: 35%;">Details</p>
|
||||
<p class="hub-skeleton" style="width: 50%;">Ratings</p>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="hub-item-description">
|
||||
<p class="hub-skeleton">Desc</p>
|
||||
<p class="hub-skeleton" style="width: 85%;">Desc</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
this.$wrapper.html(skeleton);
|
||||
this.$wrapper.html(get_detail_skeleton_html());
|
||||
}
|
||||
|
||||
render(data) {
|
||||
const p = data.profile;
|
||||
|
||||
const profile_html = `<div class="hub-item-container">
|
||||
<div class="row visible-xs">
|
||||
<div class="col-xs-12 margin-bottom">
|
||||
<button class="btn btn-xs btn-default" data-route="marketplace/home">Back to home</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="hub-item-image">
|
||||
<img src="${p.logo}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h2>${p.company}</h2>
|
||||
<div class="text-muted">
|
||||
<p>${p.country}</p>
|
||||
<p>${p.site_name}</p>
|
||||
<p>${__(`Joined ${comment_when(p.creation)}`)}</p>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="hub-item-description">
|
||||
${'description'
|
||||
? `<p>${p.company_description}</p>`
|
||||
: `<p>__('No description')</p`
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
|
||||
this.$wrapper.html(profile_html);
|
||||
this.$wrapper.html(get_profile_html(data.profile));
|
||||
|
||||
let html = get_item_card_container_html(data.items, __('Products by ' + p.company));
|
||||
this.$wrapper.append(html);
|
||||
|
@ -5,11 +5,11 @@ export default class SubPage {
|
||||
|
||||
// generic action handler
|
||||
this.$wrapper.on('click', '[data-action]', e => {
|
||||
const $this = $(e.currentTarget);
|
||||
const action = $this.data().action;
|
||||
const $target = $(e.currentTarget);
|
||||
const action = $target.data().action;
|
||||
|
||||
if (action && this[action]) {
|
||||
this[action].apply(this);
|
||||
this[action].apply(this, $target);
|
||||
}
|
||||
})
|
||||
|
||||
@ -42,4 +42,4 @@ export default class SubPage {
|
||||
hide() {
|
||||
this.$wrapper.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,15 +25,15 @@ body[data-route^="marketplace/"] {
|
||||
font-size: @text-medium;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #89da28;
|
||||
border-color: #61ca23;
|
||||
}
|
||||
// .btn-primary {
|
||||
// background-color: #89da28;
|
||||
// border-color: #61ca23;
|
||||
// }
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #61ca23;
|
||||
border-color: #59b81c;
|
||||
}
|
||||
// .btn-primary:hover {
|
||||
// background-color: #61ca23;
|
||||
// border-color: #59b81c;
|
||||
// }
|
||||
|
||||
.progress-bar {
|
||||
background-color: #89da28;
|
||||
|
Loading…
Reference in New Issue
Block a user