Publish Page

- Code cleanup
- Separate local item card and hub item card
- Use make_search_bar
This commit is contained in:
Faris Ansari
2018-07-28 16:14:22 +05:30
parent abcc8ab8e5
commit 296848cb69
3 changed files with 132 additions and 93 deletions

View File

@@ -67,17 +67,16 @@ def get_valid_items(search_value=''):
@frappe.whitelist() @frappe.whitelist()
def publish_selected_items(items_to_publish): def publish_selected_items(items_to_publish):
for item_code in json.loads(items_to_publish):
frappe.db.set_value('Item', item_code, 'publish_in_hub', 1)
# frappe.db.set_value("Hub Settings", "Hub Settings", "sync_in_progress", 1) items_to_publish = json.loads(items_to_publish)
# time.sleep(10)
# frappe.db.set_value("Hub Settings", "Hub Settings", "sync_in_progress", 0) for item_code in items_to_publish:
frappe.db.set_value('Item', item_code, 'publish_in_hub', 1)
hub_settings = frappe.get_doc('Hub Settings') hub_settings = frappe.get_doc('Hub Settings')
hub_settings.sync() hub_settings.sync()
return return len(items_to_publish)
@frappe.whitelist() @frappe.whitelist()
def get_item_favourites(start=0, limit=20, fields=["*"], order_by=None): def get_item_favourites(start=0, limit=20, fields=["*"], order_by=None):

View File

@@ -28,8 +28,6 @@ erpnext.hub.Marketplace = class Marketplace {
const $target = $(e.currentTarget); const $target = $(e.currentTarget);
const route = $target.data().route; const route = $target.data().route;
frappe.set_route(route); frappe.set_route(route);
e.stopPropagation();
}); });
} }
@@ -218,8 +216,11 @@ erpnext.hub.Home = class Home extends SubPage {
make_wrapper() { make_wrapper() {
super.make_wrapper(); super.make_wrapper();
make_search_bar(this.$wrapper, keyword => { make_search_bar({
frappe.set_route('marketplace', 'search', keyword); wrapper: this.$wrapper,
on_search: keyword => {
frappe.set_route('marketplace', 'search', keyword);
}
}); });
} }
@@ -298,8 +299,11 @@ erpnext.hub.SearchPage = class SearchPage extends SubPage {
make_wrapper() { make_wrapper() {
super.make_wrapper(); super.make_wrapper();
make_search_bar(this.$wrapper, keyword => { make_search_bar({
frappe.set_route('marketplace', 'search', keyword); wrapper: this.$wrapper,
on_search: keyword => {
frappe.set_route('marketplace', 'search', keyword);
}
}); });
} }
@@ -696,6 +700,11 @@ erpnext.hub.Profile = class Profile extends SubPage {
} }
erpnext.hub.Publish = class Publish extends SubPage { erpnext.hub.Publish = class Publish extends SubPage {
make_wrapper() {
super.make_wrapper();
this.load_publish_page();
}
load_publish_page() { load_publish_page() {
const title_html = `<b>${__('Select Products to Publish')}</b>`; const title_html = `<b>${__('Select Products to Publish')}</b>`;
@@ -708,15 +717,11 @@ erpnext.hub.Publish = class Publish extends SubPage {
const publish_button_html = `<button class="btn btn-primary btn-sm publish-items"> const publish_button_html = `<button class="btn btn-primary btn-sm publish-items">
<i class="visible-xs octicon octicon-check"></i> <i class="visible-xs octicon octicon-check"></i>
<span class="hidden-xs">Publish</span> <span class="hidden-xs">${__('Publish')}</span>
</button>`; </button>`;
const select_all_button = `<button class="btn btn-secondary btn-default btn-xs margin-right select-all">Select All</button>`; const select_all_button = `<button class="btn btn-secondary btn-default btn-xs margin-right select-all">${__('Select All')}</button>`;
const deselect_all_button = `<button class="btn btn-secondary btn-default btn-xs deselect-all">Deselect All</button>`; const deselect_all_button = `<button class="btn btn-secondary btn-default btn-xs deselect-all">${__('Deselect All')}</button>`;
const search_html = `<div class="hub-search-container">
<input type="text" class="form-control" placeholder="Search Items">
</div>`;
const subpage_header = $(` const subpage_header = $(`
<div class='subpage-title flex'> <div class='subpage-title flex'>
@@ -726,12 +731,19 @@ erpnext.hub.Publish = class Publish extends SubPage {
</div> </div>
${publish_button_html} ${publish_button_html}
</div> </div>
${search_html}
`); `);
this.$wrapper.append(subpage_header); this.$wrapper.append(subpage_header);
make_search_bar({
wrapper: this.$wrapper,
on_search: keyword => {
this.search_value = keyword;
this.get_items_and_render();
},
placeholder: __('Search Items')
});
this.setup_events(); this.setup_events();
} }
@@ -740,27 +752,32 @@ erpnext.hub.Publish = class Publish extends SubPage {
this.load_publishing_state(); this.load_publishing_state();
this.publish_selected_items() this.publish_selected_items()
.then(r => { .then(r => {
frappe.msgprint('check'); console.log(`${r.message} items will be published`);
}); });
}); });
const $search_input = this.$wrapper.find('.hub-search-container input'); this.$wrapper.on('click', '.hub-card', (e) => {
this.search_value = ''; const $target = $(e.currentTarget);
$target.toggleClass('active');
$search_input.on('keydown', frappe.utils.debounce((e) => { // Get total items
if (e.which === frappe.ui.keyCode.ENTER) { const total_items = this.$wrapper.find('.hub-card.active').length;
this.search_value = $search_input.val();
this.get_items_and_render(); let button_label;
if (total_items > 0) {
const more_than_one = total_items > 1;
button_label = __('Publish {0} item{1}', [total_items, more_than_one ? 's' : '']);
} else {
button_label = __('Publish');
} }
}, 300));
this.$wrapper.find('.publish-items')
.text(button_label)
.prop('disabled', total_items === 0);
});
} }
get_items_and_render() { get_items_and_render() {
if(hub.settings.sync_in_progress) {
this.load_publishing_state();
return;
}
this.$wrapper.find('.hub-card-container').empty(); this.$wrapper.find('.hub-card-container').empty();
this.get_valid_items() this.get_valid_items()
.then(r => { .then(r => {
@@ -769,22 +786,15 @@ erpnext.hub.Publish = class Publish extends SubPage {
} }
refresh() { refresh() {
this.get_items_and_render(); if (hub.settings.sync_in_progress) {
this.load_publishing_state();
} else {
this.get_items_and_render();
}
} }
render(items) { render(items) {
const items_container = $(get_item_card_container_html(items)); const items_container = $(get_item_card_container_html(items, '', get_local_item_card_html));
items_container.addClass('static').on('click', '.hub-card', (e) => {
const $target = $(e.currentTarget);
$target.toggleClass('active');
// Get total items
const total_items = this.$wrapper.find('.hub-card.active').length;
const more_than_one = total_items > 1;
this.$wrapper.find('.publish-items')
.html(__('Publish ' + total_items + ' item' + (more_than_one ? 's' : '')));
});
this.$wrapper.append(items_container); this.$wrapper.append(items_container);
} }
@@ -855,8 +865,8 @@ function get_empty_state(message, action) {
</div>`; </div>`;
} }
function get_item_card_container_html(items, title='') { function get_item_card_container_html(items, title='', get_item_html = get_item_card_html) {
const items_html = (items || []).map(item => get_item_card_html(item)).join(''); const items_html = (items || []).map(item => get_item_html(item)).join('');
const title_html = title const title_html = title
? `<div class="col-sm-12 margin-bottom"> ? `<div class="col-sm-12 margin-bottom">
<b>${title}</b> <b>${title}</b>
@@ -875,11 +885,44 @@ function get_item_card_html(item) {
const item_name = item.item_name || item.name; const item_name = item.item_name || item.name;
const title = strip_html(item_name); const title = strip_html(item_name);
const img_url = item.image; const img_url = item.image;
const company_name = item.company; const company_name = item.company;
const active = item.publish_in_hub; // Subtitle
let subtitle = [comment_when(item.creation)];
const rating = item.average_rating;
if (rating > 0) {
subtitle.push(rating + `<i class='fa fa-fw fa-star-o'></i>`)
}
subtitle.push(company_name);
let dot_spacer = '<span aria-hidden="true"> · </span>';
subtitle = subtitle.join(dot_spacer);
const item_html = `
<div class="col-md-3 col-sm-4 col-xs-6">
<div class="hub-card" data-route="marketplace/item/${item.hub_item_code}">
<div class="hub-card-header">
<div class="hub-card-title ellipsis bold">${title}</div>
<div class="hub-card-subtitle ellipsis text-muted">${subtitle}</div>
</div>
<div class="hub-card-body">
<img class="hub-card-image" src="${img_url}" />
<div class="overlay hub-card-overlay"></div>
</div>
</div>
</div>
`;
return item_html;
}
function get_local_item_card_html(item) {
const item_name = item.item_name || item.name;
const title = strip_html(item_name);
const img_url = item.image;
const company_name = item.company;
const is_active = item.publish_in_hub;
const id = item.hub_item_code || item.item_code; const id = item.hub_item_code || item.item_code;
// Subtitle // Subtitle
@@ -893,36 +936,27 @@ 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);
// Decide item link const edit_item_button = `<div class="hub-card-overlay-button" style="right: 15px; bottom: 15px;" data-route="Form/Item/${item.item_name}">
const is_local = item.source_type === "local"; <button class="btn btn-default zoom-view">
const route = !is_local <i class="octicon octicon-pencil text-muted"></i>
? `marketplace/item/${item.hub_item_code}` </button>
: `Form/Item/${item.item_name}`; </div>`;
const card_route = is_local ? '' : `data-route='${route}'`;
const show_local_item_button = is_local
? `<div class="overlay button-overlay" data-route='${route}' onclick="event.preventDefault();">
<button class="btn btn-default zoom-view">
<i class="octicon octicon-eye"></i>
</button>
</div>`
: '';
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 ${active ? 'active' : ''}" ${card_route} data-id="${id}"> <div class="hub-card is-local ${is_active ? 'active' : ''}" data-id="${id}">
<div class="hub-card-header"> <div class="hub-card-header">
<div class="title"> <div class="hub-card-title ellipsis bold">${title}</div>
<div class="hub-card-title ellipsis bold">${title}</div> <div class="hub-card-subtitle ellipsis text-muted">${subtitle}</div>
<div class="hub-card-subtitle ellipsis text-muted">${subtitle}</div>
</div>
<i class="octicon octicon-check text-success"></i> <i class="octicon octicon-check text-success"></i>
</div> </div>
<div class="hub-card-body"> <div class="hub-card-body">
<img class="hub-card-image" src="${img_url}" /> <img class="hub-card-image" src="${img_url}" />
<div class="overlay hub-card-overlay"></div> <div class="hub-card-overlay">
${show_local_item_button} <div class="hub-card-overlay-body">
${edit_item_button}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -931,6 +965,7 @@ function get_item_card_html(item) {
return item_html; return item_html;
} }
function get_rating_html(rating) { function get_rating_html(rating) {
let rating_html = ``; let rating_html = ``;
for (var i = 0; i < 5; i++) { for (var i = 0; i < 5; i++) {
@@ -941,13 +976,13 @@ function get_rating_html(rating) {
return rating_html; return rating_html;
} }
function make_search_bar($wrapper, on_search) { function make_search_bar({wrapper, on_search, placeholder = __('Search for anything')}) {
const $search = $(` const $search = $(`
<div class="hub-search-container"> <div class="hub-search-container">
<input type="text" class="form-control" placeholder="${__('Search for anything')}"> <input type="text" class="form-control" placeholder="${placeholder}">
</div>` </div>`
); );
$wrapper.append($search); wrapper.append($search);
const $search_input = $search.find('input'); const $search_input = $search.find('input');
$search_input.on('keydown', frappe.utils.debounce((e) => { $search_input.on('keydown', frappe.utils.debounce((e) => {

View File

@@ -43,10 +43,12 @@ body[data-route^="marketplace/"] {
overflow: hidden; overflow: hidden;
cursor: pointer; cursor: pointer;
&:hover .overlay { &:hover .hub-card-overlay {
display: block; display: block;
} }
}
.hub-card.is-local {
&.active { &.active {
.hub-card-header { .hub-card-header {
background-color: #f4ffe5; background-color: #f4ffe5;
@@ -56,42 +58,45 @@ body[data-route^="marketplace/"] {
display: inline; display: inline;
} }
} }
}
.hub-card-header {
padding: 12px 15px;
height: 60px;
border-bottom: 1px solid @border-color;
display: flex;
justify-content: space-between;
.octicon-check { .octicon-check {
display: none; display: none;
position: absolute;
font-size: 20px; font-size: 20px;
right: 15px;
top: 50%;
transform: translateY(-50%);
} }
} }
.hub-card-header {
position: relative;
padding: 12px 15px;
height: 60px;
border-bottom: 1px solid @border-color;
}
.hub-card-body { .hub-card-body {
position: relative; position: relative;
height: 200px; height: 200px;
} }
.overlay { .hub-card-overlay {
display: none; display: none;
position: absolute; position: absolute;
}
.hub-card-overlay {
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.1);
} }
.button-overlay { .hub-card-overlay-body {
top: 155px; position: relative;
left: 15px; height: 100%;
}
.hub-card-overlay-button {
position: absolute;
} }
.hub-card-image { .hub-card-image {