mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-26 08:24:47 +00:00
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:
@@ -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">
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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')
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user