blog listing + started with products page and listing

This commit is contained in:
Anand Doshi 2012-06-26 18:54:10 +05:30
parent c7b485e724
commit 10bcf5ea25
15 changed files with 364 additions and 107 deletions

View File

@ -33,6 +33,12 @@ def save_pages():
select name from `tabBlog` select name from `tabBlog`
where docstatus = 0 and ifnull(published, 0) = 1""" where docstatus = 0 and ifnull(published, 0) = 1"""
}, },
{
'doctype': 'Item',
'query': """\
select name from `tabItem`
where docstatus = 0 and ifnull(show_in_website, 'No') = 'Yes'"""
}
] ]
for s in save_list: for s in save_list:

View File

@ -46,6 +46,8 @@ class DocType:
return ret return ret
def on_update(self): def on_update(self):
self.update_page_name()
bin = sql("select stock_uom from `tabBin` where item_code = '%s' " % self.doc.item_code) bin = sql("select stock_uom from `tabBin` where item_code = '%s' " % self.doc.item_code)
if bin and cstr(bin[0][0]) != cstr(self.doc.stock_uom): if bin and cstr(bin[0][0]) != cstr(self.doc.stock_uom):
msgprint("Please Update Stock UOM with the help of Stock UOM Replace Utility.") msgprint("Please Update Stock UOM with the help of Stock UOM Replace Utility.")
@ -79,10 +81,15 @@ class DocType:
child.conversion_factor = 1 child.conversion_factor = 1
child.save() child.save()
self.clear_web_cache()
# On delete 1. Delete BIN (if none of the corrosponding transactions present, it gets deleted. if present, rolled back due to exception) # On delete 1. Delete BIN (if none of the corrosponding transactions present, it gets deleted. if present, rolled back due to exception)
def on_trash(self): def on_trash(self):
sql("delete from tabBin where item_code='%s'"%(self.doc.item_code)) sql("delete from tabBin where item_code='%s'"%(self.doc.item_code))
import website.web_cache
website.web_cache.delete_web_cache(self.doc.page_name)
# Check whether Ref Rate is not entered twice for same Price List and Currency # Check whether Ref Rate is not entered twice for same Price List and Currency
def check_ref_rate_detail(self): def check_ref_rate_detail(self):
check_list=[] check_list=[]
@ -163,8 +170,8 @@ class DocType:
if self.doc.has_serial_no == 'Yes' and self.doc.is_stock_item == 'No': if self.doc.has_serial_no == 'Yes' and self.doc.is_stock_item == 'No':
msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1) msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1)
# make product page if self.doc.name:
self.make_page() self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name')
def check_non_asset_warehouse(self): def check_non_asset_warehouse(self):
if self.doc.is_asset_item == "Yes": if self.doc.is_asset_item == "Yes":
@ -218,35 +225,59 @@ Total Available Qty: %s
def on_rename(self,newdn,olddn): def on_rename(self,newdn,olddn):
sql("update tabItem set item_code = %s where name = %s", (newdn, olddn)) sql("update tabItem set item_code = %s where name = %s", (newdn, olddn))
def make_page(self): # def make_page(self):
if self.doc.show_in_website=='Yes': # if self.doc.show_in_website=='Yes':
#
# import website.utils
#
# if self.doc.page_name:
# import webnotes.model
# webnotes.model.delete_doc('Page', self.doc.page_name)
#
# p = website.utils.add_page("Product " + self.doc.item_name)
# self.doc.page_name = p.name
#
# from jinja2 import Template
# import markdown2
# import os
#
#
# self.doc.long_description_html = markdown2.markdown(self.doc.description or '')
#
# with open(os.path.join(os.path.dirname(__file__), 'template.html'), 'r') as f:
# p.content = Template(f.read()).render(doc=self.doc)
#
# with open(os.path.join(os.path.dirname(__file__), 'product_page.js'), 'r') as f:
# p.script = Template(f.read()).render(doc=self.doc)
#
# p.save()
#
# website.utils.add_guest_access_to_page(p.name)
#
# del self.doc.fields['long_description_html']
#
def clear_web_cache(self):
import website.web_cache
import website.utils if hasattr(self, 'old_page_name') and self.old_page_name and \
self.doc.page_name != self.old_page_name:
website.web_cache.delete_web_cache(self.old_page_name)
if self.doc.page_name: if self.doc.show_in_website == 'Yes':
import webnotes.model website.web_cache.clear_web_cache(self.doc.doctype, self.doc.name, self.doc.page_name)
webnotes.model.delete_doc('Page', self.doc.page_name) else:
website.web_cache.delete_web_cache(self.doc.page_name)
p = website.utils.add_page("Product " + self.doc.item_name) def update_page_name(self):
self.doc.page_name = p.name import website.utils
self.doc.page_name = website.utils.page_name(self.doc.name + " " + self.doc.item_name)
webnotes.conn.set_value('Item', self.doc.name, 'page_name', self.doc.page_name)
from jinja2 import Template # no need to check for uniqueness, as name is unique
import markdown2
import os def get_html(self):
import markdown2
self.doc.web_description_html = markdown2.markdown(self.doc.description or '',
self.doc.long_description_html = markdown2.markdown(self.doc.description or '') extras=["wiki-tables"])
with open(os.path.join(os.path.dirname(__file__), 'template.html'), 'r') as f:
p.content = Template(f.read()).render(doc=self.doc)
with open(os.path.join(os.path.dirname(__file__), 'product_page.js'), 'r') as f:
p.script = Template(f.read()).render(doc=self.doc)
p.save()
website.utils.add_guest_access_to_page(p.name)
del self.doc.fields['long_description_html']

View File

@ -54,8 +54,13 @@ class DocType:
from webnotes.cms.make import make_web_core from webnotes.cms.make import make_web_core
make_web_core() make_web_core()
get_obj('Page', 'blog').write_cms_page(force=True) import website.web_cache
get_obj('Page', 'Login Page').write_cms_page(force=True) for page in ['blog', 'products']:
website.web_cache.delete_web_cache(page)
website.web_cache.clear_web_cache(None, None, page)
#get_obj('Page', 'blog').write_cms_page(force=True)
#get_obj('Page', 'Login Page').write_cms_page(force=True)
webnotes.msgprint('Rebuilt all blogs and pages') webnotes.msgprint('Rebuilt all blogs and pages')

View File

@ -1,58 +0,0 @@
{% extends "outer.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="layout-wrapper layout-wrapper-background">
<div class="web-content" id="content-blog">
<div class="layout-main-section">
<h1>Blog</h1>
<br>
<div id="blog-list">
<!-- blog list will be generated dynamically -->
</div>
</div>
<div class="layout-side-section">
<!-- for later
<h4>Get Updates</h4>
<p>
<input name="blog-subscribe">
<button class="btn" id="blog-subscribe">Subscribe</button>
</p>-->
<h4>Subscribe</h4>
<p>
<img src="images/feed.png" style="margin-right: 4px; margin-bottom: -4px">
<a href="rss.xml" target="_blank">RSS Feed</a>
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<script>
// if not a specific blog, show listing
erpnext.blog_list = new wn.ui.Listing({
parent: $(wrapper).find('#blog-list').get(0),
query: 'select tabBlog.name, title, left(content, 1000) as content, tabBlog.creation, \
ifnull(first_name, "") as first_name, ifnull(last_name, "") as last_name \
from tabProfile, tabBlog\
where ifnull(published,0)=1 and tabBlog.owner = tabProfile.name \
order by tabBlog.creation desc',
hide_refresh: true,
no_toolbar: true,
render_row: function(parent, data) {
if(data.content && data.content.length==1000) data.content += '... (read on)';
data.content = wn.markdown(data.content);
if(data.last_name) data.last_name = ' ' + data.last_name;
data.date = prettyDate(data.creation);
parent.innerHTML = repl('<h2>%(title)s</h2>\
<p><div class="help">By %(first_name)s%(last_name)s, %(date)s</div></p>\
<p>%(content)s</p>\
<a href="%(name)s.html">Read Full Text</a><br>', data);
},
page_length: 10
});
erpnext.blog_list.run();
</script>

View File

@ -1,4 +1,4 @@
{% extends "blog.js" %} {% extends "blog/blog.js" %}
{% block content %} {% block content %}
<div class="layout-wrapper layout-wrapper-background"> <div class="layout-wrapper layout-wrapper-background">

View File

@ -0,0 +1,43 @@
{% extends "blog/blog_list.js" %}
{% block title %}Blog{% endblock %}
{% block css %}
<style>
h2 > a, h2 > a:link, h2 > a:visited, h2 > a:active,
h2 > a:hover, h2 > a:focus {
text-decoration: none;
color: inherit;
}
</style>
{% endblock %}
{% block content %}
<div class="layout-wrapper layout-wrapper-background">
<div class="web-content" id="content-blog">
<div class="layout-main-section">
<h1>Blog</h1>
<br>
<div id="blog-list">
<!-- blog list will be generated dynamically -->
</div>
</div>
<div class="layout-side-section">
<!-- for later
<h4>Get Updates</h4>
<p>
<input name="blog-subscribe">
<button class="btn" id="blog-subscribe">Subscribe</button>
</p>-->
<h4>Subscribe</h4>
<p>
<img src="images/feed.png" style="margin-right: 4px; margin-bottom: -4px">
<a href="rss.xml" target="_blank">RSS Feed</a>
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends "page.html" %}
{% block javascript %}
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// js inside blog page
wn.pages['{{ name }}'].onload = function(wrapper) {
erpnext.blog_list = new wn.ui.Listing({
parent: $(wrapper).find('#blog-list').get(0),
query: 'select tabBlog.name, title, left(content, 1000) as content, tabBlog.creation, \
ifnull(first_name, "") as first_name, ifnull(last_name, "") as last_name \
from tabProfile, tabBlog\
where ifnull(published,0)=1 and tabBlog.owner = tabProfile.name \
order by tabBlog.creation desc',
hide_refresh: true,
no_toolbar: true,
render_row: function(parent, data) {
if(data.content && data.content.length==1000) {
data.content += repl('... <a href="%(name)s.html">(read on)</a>', data);
}
data.content = wn.markdown(data.content);
if(data.last_name) data.last_name = ' ' + data.last_name;
data.date = prettyDate(data.creation);
parent.innerHTML = repl('<h2><a href="%(name)s.html">%(title)s</a></h2>\
<p><div class="help">By %(first_name)s%(last_name)s, %(date)s</div></p>\
<p>%(content)s</p><br>', data)
//<a href="%(name)s.html">Read Full Text</a><br>', data);
},
page_length: 10
});
erpnext.blog_list.run();
}
{% endblock %}

View File

@ -24,9 +24,14 @@
}); });
</script> </script>
{% endif %} {% endif %}
{% block css %}
{% if insert_style %} {% if insert_style %}
<style>{{ css }}</style> <style>{{ css }}</style>
{% endif %} {% endif %}
{% endblock %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}

View File

@ -0,0 +1,31 @@
{% extends "product/product.js" %}
{% block title %}{{ item_name }} [{{ name }}]{% endblock %}
{% block content %}
<div class="layout-wrapper layout-wrapper-background">
<div class="web-content" id="content-product-{{ name }}">
<div class="layout-main-section">
<h1>{{ item_name }}</h1>
<div style="float: left;">
<br><br>
<image src="files/{{ website_image }}" style="width: 300px;
margin-left: 15px;" />
<br><br>
{{ web_description_html }}
<button class="btn primary product-inquiry"
data-product="{{ name }}"
data-description="{{ description }}">Send Inquiry</button>
</div>
</div>
<div class="layout-side-section">
<h4>More Categories</h4>
<div class="more-categories"></div>
<br>
<h4>Similar Products</h4>
<div class="similar-products"></div>
</div>
<div style="clear: both"></div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,68 @@
{% extends "page.html" %}
{% block javascript %}
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
wn.require('js/product_category.js');
wn.pages['{{ name }}'].onload = function(wrapper) {
console.log('loaded page');
wrapper.product_group = "{{ item_group }}";
wrapper.product_name = "{{ name }}";
erpnext.make_product_categories(wrapper);
$(wrapper).find('.product-inquiry').click(function() {
loadpage('contact', function() {
$('#content-contact-us [name="contact-message"]').val("Hello,\n\n\
Please send me more information on {{ item_name }} (Item Code:{{ name }})\n\n\
My contact details are:\n\nThank you!\
");
})
});
// similar products
wrapper.similar = new wn.ui.Listing({
parent: $(wrapper).find('.similar-products').get(0),
hide_refresh: true,
page_length: 5,
get_query: function() {
args = {
cat: wrapper.product_group,
name: wrapper.product_name
};
return repl('select name, item_name, website_image, \
page_name, description \
from tabItem \
and ifnull(show_in_website, "No")="Yes" \
and name != "%(name)s" \
and item_group="%(cat)s" order by modified desc', args)
},
render_row: function(parent, data) {
if(data.short_description.length > 100) {
data.short_description = data.short_description.substr(0,100) + '...';
}
parent.innerHTML = repl('<div style="float:left; width: 60px;">\
<img src="files/%(website_image)s" style="width:55px;"></div>\
<div style="float:left; width: 180px">\
<b><a href="%(page_name)s.html">%(item_name)s</a></b>\
<p>%(description)s</p></div>\
<div style="clear: both; margin-bottom: 15px;"></div>', data);
}
});
wrapper.similar.run();
}
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends "product/product_list.js" %}
{% block title %}Products{% endblock %}
{% block content %}
<div class="layout-wrapper layout-wrapper-background">
<div class="web-content" id="content-products">
<div class="layout-main-section">
<h1 class="products-category"></h1>
<div id="product-list">
<!-- product list will be generated dynamically -->
</div>
</div>
<div class="layout-side-section">
<h3>Categories</h3>
<div class="more-categories"></div>
</div>
<div style="clear: both"></div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,40 @@
{% extends "page.html" %}
{% block javascript %}
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// js inside blog page
wn.pages['{{ name }}'].onload = function(wrapper) {
erpnext.product_list = new wn.ui.Listing({
parent: $(wrapper).find('#product-list').get(0),
query: "select name, item_code, item_name, description, page_name \
from `tabItem` \
where docstatus = 0 and ifnull(show_in_website, 'No')='Yes'\
order by item_name asc",
hide_refresh: true,
no_toolbar: true,
render_row: function(parent, data) {
if(data.description && data.description.length==1000) data.description += '... (read on)';
parent.innerHTML = repl('<h4><a href="%(page_name)s.html">%(item_name)s</a></h4>\
<p>%(description)s</p>', data);
},
page_length: 10
});
erpnext.product_list.run();
}
{% endblock %}

View File

@ -32,7 +32,7 @@ def load_from_web_cache(page_name, comments, template):
where name = %s""", page_name) where name = %s""", page_name)
# if page doesn't exist, raise exception # if page doesn't exist, raise exception
if not res and page_name not in ['404', 'index']: if not res and page_name not in ['404', 'index', 'blog', 'products']:
raise Exception, "Page %s not found" % page_name raise Exception, "Page %s not found" % page_name
html, doc_type, doc_name = res and res[0] or (None, None, None) html, doc_type, doc_name = res and res[0] or (None, None, None)
@ -52,23 +52,37 @@ def load_into_web_cache(page_name, template, doc_type, doc_name):
import webnotes import webnotes
outer_env_dict = get_outer_env() outer_env_dict = get_outer_env()
if page_name == '404': if page_name in ['404', 'blog', 'products']:
args = outer_env_dict args = outer_env_dict
args.update({
'name': page_name,
})
else: else:
if page_name == 'index': if page_name == 'index':
page_name, doc_type, doc_name = get_index_page() page_name, doc_type, doc_name = get_index_page()
from webnotes.model.code import get_obj from webnotes.model.code import get_obj
obj = get_obj(doc_type, doc_name) obj = get_obj(doc_type, doc_name)
obj.get_html() if hasattr(obj, 'get_html'):
obj.get_html()
args = obj.doc.fields args = obj.doc.fields
args.update(outer_env_dict) args.update(outer_env_dict)
# decide template and update args
if doc_type == 'Blog': if doc_type == 'Blog':
template = 'blog.html' template = 'blog/blog.html'
args['insert_code'] = 1 args.update({ 'insert_code': 1 })
elif doc_type == 'Item':
template = 'product/product.html'
args.update({ 'insert_code': 1 })
elif doc_type == 'Web Page': elif doc_type == 'Web Page':
template = 'web_page.html' template = 'web_page.html'
elif page_name == 'blog':
template = 'blog/blog_list.html'
args.update({ 'insert_code': 1 })
elif page_name == 'products':
template = 'product/product_list.html'
args.update({ 'insert_code': 1 })
html = build_html(args, template) html = build_html(args, template)

View File

@ -34,13 +34,9 @@ class Page(object):
# page name updates with the title # page name updates with the title
self.update_page_name() self.update_page_name()
# delete web cache entry of old name
if hasattr(self, 'old_page_name') and self.old_page_name != self.doc.page_name:
self.delete_web_cache(self.old_page_name)
self.clear_web_cache() self.clear_web_cache()
self.doc.save(ignore_fields=1) self.doc.save()
def on_trash(self): def on_trash(self):
"""delete Web Cache entry""" """delete Web Cache entry"""
@ -63,6 +59,11 @@ class Page(object):
if web cache entry doesn't exist, it creates one if web cache entry doesn't exist, it creates one
if duplicate entry exists for another doctype, it raises exception if duplicate entry exists for another doctype, it raises exception
""" """
# delete web cache entry of old name
if hasattr(self, 'old_page_name') and self.old_page_name and \
self.old_page_name != self.doc.page_name:
self.delete_web_cache(self.old_page_name)
website.web_cache.clear_web_cache(self.doctype, self.doc.name, self.doc.page_name) website.web_cache.clear_web_cache(self.doctype, self.doc.name, self.doc.page_name)
def delete_web_cache(self, page_name): def delete_web_cache(self, page_name):