feat(messages): split messages into buying and selling

- messages will be organized by their purpose, i.e Buying and Selling
- on clicking the buying item, the message room page will be opened
where sellers can communicate
- invalidate cache using event key
This commit is contained in:
Faris Ansari
2018-08-17 18:39:36 +05:30
parent 335c0f200f
commit 2ce2e1b6b0
6 changed files with 116 additions and 103 deletions

View File

@@ -33,6 +33,12 @@ function get_detail_view_html(item, allow_edit) {
${__('Saved')} ${__('Saved')}
</button>`; </button>`;
const contact_seller_button = item.hub_seller !== hub.settings.company_email
? `<button class="btn btn-primary" data-action="contact_seller">
${__('Contact Seller')}
</button>`
: '';
let menu_items = ''; let menu_items = '';
if(allow_edit) { if(allow_edit) {
@@ -69,9 +75,7 @@ function get_detail_view_html(item, allow_edit) {
<div class="page-actions detail-page-actions"> <div class="page-actions detail-page-actions">
${favourite_button} ${favourite_button}
<button class="btn btn-primary" data-action="contact_seller"> ${contact_seller_button}
${__('Contact Seller')}
</button>
</div> </div>
</div> </div>
<div class="col-md-1"> <div class="col-md-1">

View File

@@ -15,11 +15,16 @@ function get_item_card_html(item) {
let dot_spacer = '<span aria-hidden="true"> · </span>'; let dot_spacer = '<span aria-hidden="true"> · </span>';
subtitle = subtitle.join(dot_spacer); subtitle = subtitle.join(dot_spacer);
// route
if (!item.route) {
item.route = `marketplace/item/${item.hub_item_code}`
}
const item_html = ` const item_html = `
<div class="col-md-3 col-sm-4 col-xs-6"> <div class="col-md-3 col-sm-4 col-xs-6">
<div class="hub-card" <div class="hub-card"
data-hub-item-code="${item.hub_item_code}" data-hub-item-code="${item.hub_item_code}"
data-route="marketplace/item/${item.hub_item_code}"> data-route="${item.route}">
<div class="hub-card-header level"> <div class="hub-card-header level">
<div class="ellipsis"> <div class="ellipsis">

View File

@@ -2,7 +2,7 @@ frappe.provide('hub');
frappe.provide('erpnext.hub'); frappe.provide('erpnext.hub');
erpnext.hub.cache = {}; erpnext.hub.cache = {};
hub.call = function call_hub_method(method, args={}, setup_cache_invalidation = invalidate_after_5_mins) { hub.call = function call_hub_method(method, args={}, clear_cache_on_event) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// cache // cache
@@ -13,7 +13,14 @@ hub.call = function call_hub_method(method, args={}, setup_cache_invalidation =
// cache invalidation // cache invalidation
const clear_cache = () => delete erpnext.hub.cache[key]; const clear_cache = () => delete erpnext.hub.cache[key];
setup_cache_invalidation(clear_cache);
if (!clear_cache_on_event) {
invalidate_after_5_mins(clear_cache);
} else {
erpnext.hub.on(clear_cache_on_event, () => {
clear_cache(key)
});
}
frappe.call({ frappe.call({
method: 'erpnext.hub_node.api.call_hub_method', method: 'erpnext.hub_node.api.call_hub_method',

View File

@@ -26,11 +26,9 @@ erpnext.hub.Favourites = class Favourites extends SubPage {
} }
get_favourites() { get_favourites() {
return hub.call( return hub.call('get_favourite_items_of_seller', {
'get_favourite_items_of_seller', hub_seller: hub.settings.company_email
{ hub_seller: hub.settings.company_email }, }, 'action:item_favourite');
clear_cache => erpnext.hub.on('action:item_favourite', clear_cache)
);
} }
render(items) { render(items) {

View File

@@ -105,6 +105,18 @@ erpnext.hub.Item = class Item extends SubPage {
], ],
primary_action: ({ message }) => { primary_action: ({ message }) => {
if (!message) return; if (!message) return;
hub.call('send_message', {
from_seller: hub.settings.company_email,
to_seller: this.item.hub_seller,
hub_item: this.item.hub_item_code,
message
})
.then(() => {
d.hide();
frappe.set_route('marketplace', 'messages');
erpnext.hub.trigger('action:send_message')
});
} }
}); });

View File

@@ -1,118 +1,105 @@
import SubPage from './subpage'; import SubPage from './subpage';
import { make_search_bar } from '../components/search_bar'; import { get_item_card_container_html } from '../components/items_container';
import { get_empty_state } from '../components/empty_state';
erpnext.hub.Messages = class Messages extends SubPage { erpnext.hub.Messages = class Messages extends SubPage {
make_wrapper() { make_wrapper() {
super.make_wrapper(); super.make_wrapper();
}
const html = ` refresh() {
<div class="row"> const res = Promise.all([
<div class="col-md-5"> this.get_buying_items(),
<div class="seller-list"></div> this.get_selling_items()
</div> ]);
<div class="col-md-7">
${get_message_area_html()}
</div>
</div>
`;
make_search_bar({ res.then(([buying_items, selling_items]) => {
wrapper: this.$wrapper, this.empty();
on_search: keyword => {
}, if (buying_items.length) {
placeholder: __('Search for messages') buying_items.map(item => {
}) item.route = `marketplace/buy/${item.hub_item_code}`
})
this.render(buying_items, __('Buying'));
}
this.$wrapper.append(html); if (selling_items.length) {
// selling_items.map(item => {
// item.route = `marketplace/sell/${item.hub_item_code}/${}`
// });
this.render(selling_items, __('Selling'));
}
this.message_input = new frappe.ui.CommentArea({ if (!buying_items.length && !selling_items.length) {
parent: this.$wrapper.find('.message-input'), this.render_empty_state();
on_submit: (message) => { }
this.message_input.reset(); });
}
// append message html render(items = [], title) {
const $message_list = this.$wrapper.find('.message-list'); const html = get_item_card_container_html(items, title);
const message_html = get_message_html({ this.$wrapper.append(html);
sender: hub.settings.company_email, }
content: message
});
$message_list.append(message_html);
frappe.dom.scroll_to_bottom($message_list);
const to_seller = frappe.get_route()[2]; render_empty_state() {
hub.call('send_message', { const empty_state = get_empty_state(__('You haven\'t interacted with any seller yet.'));
from_seller: hub.settings.company_email, this.$wrapper.html(empty_state);
to_seller, }
message
});
},
no_wrapper: true
});
}
refresh() { get_buying_items() {
this.get_interactions() return hub.call('get_buying_items_for_messages', {}, 'action:send_message');
.then(sellers => { }
const html = sellers.map(get_list_item_html).join('');
this.$wrapper.find('.seller-list').html(html);
});
this.get_messages() get_selling_items() {
.then(messages => { return hub.call('get_selling_items_for_messages');
const $message_list = this.$wrapper.find('.message-list'); }
const html = messages.map(get_message_html).join('');
$message_list.html(html);
frappe.dom.scroll_to_bottom($message_list);
});
}
get_interactions() { get_interactions() {
return hub.call('get_sellers_with_interactions', { for_seller: hub.settings.company_email }); return hub.call('get_sellers_with_interactions', { for_seller: hub.settings.company_email });
} }
get_messages() { get_messages() {
const against_seller = frappe.get_route()[2]; const against_seller = frappe.get_route()[2];
if (!against_seller) return Promise.resolve([]); if (!against_seller) return Promise.resolve([]);
return hub.call('get_messages', { return hub.call('get_messages', {
for_seller: hub.settings.company_email, for_seller: hub.settings.company_email,
against_seller: against_seller against_seller: against_seller
}); });
} }
} }
function get_message_area_html() { function get_message_area_html() {
return ` return `
<div class="message-area border padding flex flex-column"> <div class="message-area border padding flex flex-column">
<div class="message-list"> <div class="message-list">
</div> </div>
<div class="message-input"> <div class="message-input">
</div> </div>
</div> </div>
`; `;
} }
function get_list_item_html(seller) { function get_list_item_html(seller) {
const active_class = frappe.get_route()[2] === seller.email ? 'active' : ''; const active_class = frappe.get_route()[2] === seller.email ? 'active' : '';
return ` return `
<div class="message-list-item ${active_class}" data-route="marketplace/messages/${seller.email}"> <div class="message-list-item ${active_class}" data-route="marketplace/messages/${seller.email}">
<div class="list-item-left"> <div class="list-item-left">
<img src="${seller.image || 'https://picsum.photos/200?random'}"> <img src="${seller.image || 'https://picsum.photos/200?random'}">
</div> </div>
<div class="list-item-body"> <div class="list-item-body">
${seller.company} ${seller.company}
</div> </div>
</div> </div>
`; `;
} }
function get_message_html(message) { function get_message_html(message) {
return ` return `
<div> <div>
<h5>${message.sender}</h5> <h5>${message.sender}</h5>
<p>${message.content}</p> <p>${message.content}</p>
</div> </div>
`; `;
} }