feat: Selling Page
- common Messages page for both buying and selling
diff --git a/erpnext/public/js/hub/PageContainer.vue b/erpnext/public/js/hub/PageContainer.vue
index bb9ba3e..e814be8 100644
--- a/erpnext/public/js/hub/PageContainer.vue
+++ b/erpnext/public/js/hub/PageContainer.vue
@@ -15,7 +15,8 @@
import Seller from './pages/Seller.vue';
import Publish from './pages/Publish.vue';
import Buying from './pages/Buying.vue';
-import BuyingMessages from './pages/BuyingMessages.vue';
+import Selling from './pages/Selling.vue';
+import Messages from './pages/Messages.vue';
import Profile from './pages/Profile.vue';
import NotFound from './pages/NotFound.vue';
@@ -33,7 +34,9 @@
'marketplace/publish': Publish,
'marketplace/my-products': PublishedProducts,
'marketplace/buying': Buying,
- 'marketplace/buying/:item': BuyingMessages,
+ 'marketplace/buying/:item': Messages,
+ 'marketplace/selling': Selling,
+ 'marketplace/selling/:buyer/:item': Messages
}
export default {
diff --git a/erpnext/public/js/hub/Sidebar.vue b/erpnext/public/js/hub/Sidebar.vue
index 208d8fe..b5a4e46 100644
--- a/erpnext/public/js/hub/Sidebar.vue
+++ b/erpnext/public/js/hub/Sidebar.vue
@@ -6,6 +6,9 @@
</li>
</ul>
<ul class="list-unstyled hub-sidebar-group" data-categories>
+ <li class="hub-sidebar-item is-title bold text-muted">
+ {{ __('Categories') }}
+ </li>
<li class="hub-sidebar-item" v-for="category in categories" :key="category.label" v-route="category.route">
{{ category.label }}
</li>
diff --git a/erpnext/public/js/hub/components/EmptyState.vue b/erpnext/public/js/hub/components/EmptyState.vue
index 3d35efc..527194b 100644
--- a/erpnext/public/js/hub/components/EmptyState.vue
+++ b/erpnext/public/js/hub/components/EmptyState.vue
@@ -1,6 +1,6 @@
<template>
- <div class="empty-state flex align-center flex-column justify-center"
- :class="{ bordered: bordered }"
+ <div class="empty-state flex flex-column"
+ :class="{ 'bordered': bordered, 'align-center': centered, 'justify-center': centered }"
:style="{ height: height + 'px' }"
>
<p class="text-muted">{{ message }}</p>
@@ -22,17 +22,20 @@
message: String,
bordered: Boolean,
height: Number,
- action: Object
+ action: Object,
+ centered: {
+ type: Boolean,
+ default: true
+ }
}
}
</script>
-<style lang="less" scoped>
+<style lang="less">
@import "../../../../../../frappe/frappe/public/less/variables.less";
.empty-state {
height: 500px;
- margin: 15px;
}
.empty-state.bordered {
diff --git a/erpnext/public/js/hub/components/ItemListCard.vue b/erpnext/public/js/hub/components/ItemListCard.vue
index 4c68100..70cb566 100644
--- a/erpnext/public/js/hub/components/ItemListCard.vue
+++ b/erpnext/public/js/hub/components/ItemListCard.vue
@@ -5,13 +5,11 @@
<div class="hub-list-body ellipsis">
<div class="hub-list-title">{{item.item_name}}</div>
<div class="hub-list-subtitle ellipsis">
- <span>{{message.sender}}: </span>
- <span>{{message.content}}</span>
-
+ <slot name="subtitle"></slot>
</div>
</div>
</div>
- <div class="hub-list-right">
+ <div class="hub-list-right" v-if="message">
<span class="text-muted" v-html="frappe.datetime.comment_when(message.creation, true)" />
</div>
</div>
diff --git a/erpnext/public/js/hub/pages/Buying.vue b/erpnext/public/js/hub/pages/Buying.vue
index 7a783bc..cec9c9e 100644
--- a/erpnext/public/js/hub/pages/Buying.vue
+++ b/erpnext/public/js/hub/pages/Buying.vue
@@ -3,32 +3,39 @@
<section-header>
<h4>{{ __('Buying') }}</h4>
</section-header>
- <div class="row">
- <div class="col-md-7"
+ <div class="row" v-if="items">
+ <div class="col-md-7 margin-bottom"
v-for="item of items"
:key="item.name"
>
<item-list-card
:item="item"
- :message="item.recent_message"
v-route="'marketplace/buying/' + item.name"
- />
+ >
+ <div slot="subtitle">
+ <span>{{item.recent_message.sender}}: </span>
+ <span>{{item.recent_message.content}}</span>
+ </div>
+ </item-list-card>
</div>
</div>
+ <empty-state v-else message="This page keeps track of items you want to buy from sellers." :centered="false" />
</div>
</template>
<script>
+import EmptyState from '../components/EmptyState.vue';
import SectionHeader from '../components/SectionHeader.vue';
import ItemListCard from '../components/ItemListCard.vue';
export default {
components: {
SectionHeader,
- ItemListCard
+ ItemListCard,
+ EmptyState
},
data() {
return {
- items: []
+ items: null
}
},
created() {
diff --git a/erpnext/public/js/hub/pages/Item.vue b/erpnext/public/js/hub/pages/Item.vue
index ad28f42..74a4647 100644
--- a/erpnext/public/js/hub/pages/Item.vue
+++ b/erpnext/public/js/hub/pages/Item.vue
@@ -20,7 +20,7 @@
></detail-header-item>
<button slot="detail-header-item"
- class="btn btn-primary margin-top"
+ class="btn btn-primary btn-sm margin-top"
@click="primary_action.action"
>
{{ primary_action.label }}
@@ -28,7 +28,7 @@
</detail-view>
- <!-- <review-area :hub_item_code="hub_item_code"></review-area> -->
+ <!-- <review-area :hub_item_name="hub_item_name"></review-area> -->
</div>
</template>
@@ -44,7 +44,7 @@
data() {
return {
page_name: frappe.get_route()[1],
- hub_item_code: frappe.get_route()[2],
+ hub_item_name: frappe.get_route()[2],
init: true,
@@ -131,7 +131,7 @@
},
methods: {
get_profile() {
- hub.call('get_item_details',{ hub_item_code: this.hub_item_code })
+ hub.call('get_item_details', { hub_item_name: this.hub_item_name })
.then(item => {
this.init = false;
this.item = item;
@@ -185,12 +185,12 @@
hub.call('send_message', {
from_seller: hub.settings.company_email,
to_seller: this.item.hub_seller,
- hub_item: this.item.hub_item_code,
+ hub_item: this.item.name,
message
})
.then(() => {
d.hide();
- frappe.set_route('marketplace', 'buy', this.item.hub_item_code);
+ frappe.set_route('marketplace', 'buying', this.item.name);
erpnext.hub.trigger('action:send_message')
});
}
diff --git a/erpnext/public/js/hub/pages/BuyingMessages.vue b/erpnext/public/js/hub/pages/Messages.vue
similarity index 75%
rename from erpnext/public/js/hub/pages/BuyingMessages.vue
rename to erpnext/public/js/hub/pages/Messages.vue
index 49a6656..1930bcb 100644
--- a/erpnext/public/js/hub/pages/BuyingMessages.vue
+++ b/erpnext/public/js/hub/pages/Messages.vue
@@ -1,7 +1,7 @@
<template>
<div v-if="item_details">
<div>
- <a class="text-muted" v-route="'marketplace/buying'">← {{ __('Back to Messages') }}</a>
+ <a class="text-muted" v-route="back_link">← {{ __('Back to Messages') }}</a>
</div>
<section-header>
<div class="flex flex-column margin-bottom">
@@ -40,6 +40,7 @@
},
data() {
return {
+ message_type: frappe.get_route()[1],
item_details: null,
messages: []
}
@@ -49,12 +50,17 @@
this.get_item_details(hub_item_name)
.then(item_details => {
this.item_details = item_details;
- this.get_messages(item_details)
+ this.get_messages()
.then(messages => {
this.messages = messages;
});
});
},
+ computed: {
+ back_link() {
+ return 'marketplace/' + this.message_type;
+ }
+ },
methods: {
send_message(message) {
this.messages.push({
@@ -65,7 +71,7 @@
});
hub.call('send_message', {
from_seller: hub.settings.company_email,
- to_seller: this.item_details.hub_seller,
+ to_seller: this.get_against_seller(),
hub_item: this.item_details.name,
message
});
@@ -76,12 +82,23 @@
get_messages() {
if (!this.item_details) return [];
return hub.call('get_messages', {
- against_seller: this.item_details.hub_seller,
+ against_seller: this.get_against_seller(),
against_item: this.item_details.name
});
},
+ get_against_seller() {
+ if (this.message_type === 'buying') {
+ return this.item_details.hub_seller;
+ } else if (this.message_type === 'selling') {
+ return frappe.get_route()[2];
+ }
+ },
get_hub_item_name() {
- return frappe.get_route()[2];
+ if (this.message_type === 'buying') {
+ return frappe.get_route()[2];
+ } else if (this.message_type === 'selling') {
+ return frappe.get_route()[3];
+ }
}
}
}
diff --git a/erpnext/public/js/hub/pages/Selling.vue b/erpnext/public/js/hub/pages/Selling.vue
new file mode 100644
index 0000000..f8ed560
--- /dev/null
+++ b/erpnext/public/js/hub/pages/Selling.vue
@@ -0,0 +1,64 @@
+<template>
+ <div>
+ <section-header>
+ <h4>{{ __('Selling') }}</h4>
+ </section-header>
+ <div class="row">
+ <div class="col-md-7"
+ style="margin-bottom: 30px;"
+ v-for="item of items"
+ :key="item.name"
+ >
+ <item-list-card
+ :item="item"
+ >
+ <div slot="subtitle">
+ <span class="text-muted">{{ __('{0} conversations', [item.received_messages.length]) }}</span>
+ </div>
+ </item-list-card>
+ <div class="hub-list-item" v-for="(message, index) in item.received_messages" :key="index"
+ v-route="'marketplace/selling/' + message.buyer_email + '/' + item.name"
+ >
+ <div class="hub-list-left">
+ <div class="hub-list-body">
+ <div class="hub-list-title">
+ {{ message.buyer }}
+ </div>
+ <div class="hub-list-subtitle">
+ {{ message.sender }}: {{ message.content }}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+import SectionHeader from '../components/SectionHeader.vue';
+import ItemListCard from '../components/ItemListCard.vue';
+
+export default {
+ components: {
+ SectionHeader,
+ ItemListCard
+ },
+ data() {
+ return {
+ items: []
+ }
+ },
+ created() {
+ this.get_items_for_messages()
+ .then(items => {
+ this.items = items;
+ console.log(items);
+ });
+ },
+ methods: {
+ get_items_for_messages() {
+ return hub.call('get_selling_items_for_messages');
+ }
+ }
+}
+</script>
diff --git a/erpnext/public/less/hub.less b/erpnext/public/less/hub.less
index 618f98f..27321e5 100644
--- a/erpnext/public/less/hub.less
+++ b/erpnext/public/less/hub.less
@@ -198,8 +198,17 @@
justify-content: space-between;
align-items: center;
border: 1px solid @border-color;
- margin-bottom: 15px;
- border-radius: 3px;
+ margin-bottom: -1px;
+ overflow: hidden;
+ }
+
+ .hub-list-item:first-child {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ }
+ .hub-list-item:last-child {
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
}
.hub-list-left {