From bd7f7231f21437d969087be249a664831e81c803 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 15 Jun 2012 14:00:06 +0530 Subject: [PATCH 01/26] cms now powered by jinja2 --- erpnext/website/templates/404.html | 12 ++++++ erpnext/website/templates/__init__.py | 0 erpnext/website/templates/base.html | 20 ++++++++++ erpnext/website/templates/blog.html | 53 +++++++++++++++++++++++++ erpnext/website/templates/outer.html | 57 +++++++++++++++++++++++++++ erpnext/website/templates/page.html | 32 +++++++++++++++ public/js/all-app.js | 2 +- public/js/all-web.js | 2 +- public/{index.cgi => server.py} | 0 public/web.py | 57 +++++++++++++++++++++++++++ 10 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 erpnext/website/templates/404.html create mode 100644 erpnext/website/templates/__init__.py create mode 100644 erpnext/website/templates/base.html create mode 100644 erpnext/website/templates/blog.html create mode 100644 erpnext/website/templates/outer.html create mode 100644 erpnext/website/templates/page.html rename public/{index.cgi => server.py} (100%) create mode 100755 public/web.py diff --git a/erpnext/website/templates/404.html b/erpnext/website/templates/404.html new file mode 100644 index 0000000000..8a30892a66 --- /dev/null +++ b/erpnext/website/templates/404.html @@ -0,0 +1,12 @@ +{% extends "outer.html" %} + +{% block content %} +
+
+

Page missing or moved

+
+

We are very sorry for this, but the page you are looking for is missing + (this could be because of a typo in the address) or moved.

+
+
+{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/__init__.py b/erpnext/website/templates/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/website/templates/base.html b/erpnext/website/templates/base.html new file mode 100644 index 0000000000..cd64139b82 --- /dev/null +++ b/erpnext/website/templates/base.html @@ -0,0 +1,20 @@ + + + + {% block title %}{% endblock %} + + + + + + + + + + {% block header %} + {% endblock %} + + + {% block body %} + {% endblock %} + \ No newline at end of file diff --git a/erpnext/website/templates/blog.html b/erpnext/website/templates/blog.html new file mode 100644 index 0000000000..30dbd3b87e --- /dev/null +++ b/erpnext/website/templates/blog.html @@ -0,0 +1,53 @@ +{% extends "index.html" %} + +{% block content %} +
+
+
+

Blog

+
+
+ +
+
+
+ +

Subscribe

+

+ + RSS Feed +

+
+
+
+
+ + \ No newline at end of file diff --git a/erpnext/website/templates/outer.html b/erpnext/website/templates/outer.html new file mode 100644 index 0000000000..4b8c04dcab --- /dev/null +++ b/erpnext/website/templates/outer.html @@ -0,0 +1,57 @@ +{# + requires, brand, top_bar_items, footer_items, copyright, content +#} + +{% extends "base.html" %} + +{% block body %} + +
+ +
+
+
+ {% block content %} + {% endblock %} +
+
+ + +{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/page.html b/erpnext/website/templates/page.html new file mode 100644 index 0000000000..0eccd87e2e --- /dev/null +++ b/erpnext/website/templates/page.html @@ -0,0 +1,32 @@ +{% extends "outer.html" %} + +{% block title %}{{ title }}{% endblock %} + +{% block header %} + {{ super() }} + {% if script %} + + {% endif %} + {% if style %} + + {% endif %} +{% endblock %} + +{% block content %} + {{ content }} +{% endblock %} \ No newline at end of file diff --git a/public/js/all-app.js b/public/js/all-app.js index 32a2e2965b..859af21f92 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -389,7 +389,7 @@ wn.views.make_404=function(){var page=wn.container.add_page('404');$(page).html( /* * lib/js/wn/request.js */ -wn.provide('wn.request');wn.request.url='index.cgi';wn.request.prepare=function(opts){if(opts.btn)$(opts.btn).set_working();if(opts.show_spinner)set_loading();if(opts.freeze)freeze();if(!opts.args.cmd){console.log(opts) +wn.provide('wn.request');wn.request.url='server.py';wn.request.prepare=function(opts){if(opts.btn)$(opts.btn).set_working();if(opts.show_spinner)set_loading();if(opts.freeze)freeze();if(!opts.args.cmd){console.log(opts) throw"Incomplete Request";}} wn.request.cleanup=function(opts,r){if(opts.btn)$(opts.btn).done_working();if(opts.show_spinner)hide_loading();if(opts.freeze)unfreeze();if(wn.boot&&wn.boot.sid&&wn.get_cookie('sid')!=wn.boot.sid){if(!wn.app.logged_out){msgprint('Session Expired. Logging you out');wn.app.logout();} return;} diff --git a/public/js/all-web.js b/public/js/all-web.js index 381d5f844f..1f703109a4 100644 --- a/public/js/all-web.js +++ b/public/js/all-web.js @@ -276,7 +276,7 @@ wn.views.make_404=function(){var page=wn.container.add_page('404');$(page).html( /* * lib/js/wn/request.js */ -wn.provide('wn.request');wn.request.url='index.cgi';wn.request.prepare=function(opts){if(opts.btn)$(opts.btn).set_working();if(opts.show_spinner)set_loading();if(opts.freeze)freeze();if(!opts.args.cmd){console.log(opts) +wn.provide('wn.request');wn.request.url='server.py';wn.request.prepare=function(opts){if(opts.btn)$(opts.btn).set_working();if(opts.show_spinner)set_loading();if(opts.freeze)freeze();if(!opts.args.cmd){console.log(opts) throw"Incomplete Request";}} wn.request.cleanup=function(opts,r){if(opts.btn)$(opts.btn).done_working();if(opts.show_spinner)hide_loading();if(opts.freeze)unfreeze();if(wn.boot&&wn.boot.sid&&wn.get_cookie('sid')!=wn.boot.sid){if(!wn.app.logged_out){msgprint('Session Expired. Logging you out');wn.app.logout();} return;} diff --git a/public/index.cgi b/public/server.py similarity index 100% rename from public/index.cgi rename to public/server.py diff --git a/public/web.py b/public/web.py new file mode 100755 index 0000000000..d05eb940bd --- /dev/null +++ b/public/web.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +""" +return a dynamic page from website templates +""" + +import cgi, cgitb, os, sys +cgitb.enable() + +# import libs +sys.path.append('..') +import conf +sys.path.append('../lib/py') +sys.path.append(conf.modules_path) + +def get_outer_env(): + """env for outer (cache this)""" + import webnotes + return { + 'top_bar_items': webnotes.conn.sql("""select * from `tabTop Bar Item` + where parent='Website Settings' and parentfield='top_bar_items' + order by idx asc""", as_dict=1), + + 'footer_items': webnotes.conn.sql("""select * from `tabTop Bar Item` + where parent='Website Settings' and parentfield='footer_items' + order by idx asc""", as_dict=1), + + 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html'), + 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), + } + +def get_html(): + import webnotes + from jinja2 import Environment, FileSystemLoader + from webnotes.model.doc import Document + + jenv = Environment(loader = FileSystemLoader('../erpnext/website/templates')) + + webnotes.form = cgi.FieldStorage(keep_blank_values=True) + for key in webnotes.form.keys(): + webnotes.form_dict[key] = webnotes.form.getvalue(key) + webnotes.connect() + + if 'page' in webnotes.form_dict: + try: + page = Document('Page', webnotes.form_dict['page']) + page.fields.update(get_outer_env()) + return jenv.get_template('page.html').render(page.fields) + except Exception, e: + return jenv.get_template('404.html').render(get_outer_env()) + else: + return jenv.get_template('404.html').render(get_outer_env()) + +if __name__=="__main__": + print "Content-Type: text/html" + print + print get_html().encode('utf-8') From 96bf0b7f53201ff9cbbdd8d32d69c916b8b21582 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 15 Jun 2012 17:29:03 +0530 Subject: [PATCH 02/26] web pages don't render into Page and Page does not get written as HTML. Welcome Jinja2 Templates --- .../website/doctype/web_page/template.html | 10 ---- erpnext/website/doctype/web_page/web_page.py | 47 ++++--------------- erpnext/website/doctype/web_page/web_page.txt | 36 +++++++++----- erpnext/website/templates/page.html | 8 ++-- public/web.py | 24 +++++++--- 5 files changed, 55 insertions(+), 70 deletions(-) diff --git a/erpnext/website/doctype/web_page/template.html b/erpnext/website/doctype/web_page/template.html index c6d4b407f0..f46113c0b2 100644 --- a/erpnext/website/doctype/web_page/template.html +++ b/erpnext/website/doctype/web_page/template.html @@ -8,21 +8,11 @@
{% endif %} {{ doc.main_section_html }} - {% if doc.next_page_html %} - {{ doc.next_page_html }} - {% endif %} -
{% if doc.layout and doc.layout.startswith('Two column') %}
{{ doc.side_section_html }} - {% if doc.see_also %} -
-

See Also

- {{ doc.see_also }} -
- {% endif %}
{% endif %}
diff --git a/erpnext/website/doctype/web_page/web_page.py b/erpnext/website/doctype/web_page/web_page.py index b03e42495a..d4405b3a10 100644 --- a/erpnext/website/doctype/web_page/web_page.py +++ b/erpnext/website/doctype/web_page/web_page.py @@ -28,60 +28,29 @@ class DocType: def validate(self): """make page for this product""" from jinja2 import Template - from webnotes.utils import global_date_format - from webnotes.model.code import get_obj import os # we need the name for the templates if self.doc.name.startswith('New Web Page'): self.autoname() - if self.doc.page_name: - webnotes.conn.sql("""delete from tabPage where name=%s""", self.doc.page_name) - - p = website.utils.add_page(self.doc.name) - self.doc.page_name = p.name + # page name updates with the title + self.doc.page_name = website.utils.page_name(self.doc.title) - self.doc.updated = global_date_format(self.doc.modified) + # markdown website.utils.markdown(self.doc, ['head_section','main_section', 'side_section']) - + + # make page layout with open(os.path.join(os.path.dirname(__file__), 'template.html'), 'r') as f: - p.content = Template(f.read()).render(doc=self.doc) - - p.title = self.doc.title - p.web_page = 'Yes' + self.doc.content = Template(f.read()).render(doc=self.doc) - if self.doc.insert_code: - p.script = self.doc.javascript - - if self.doc.insert_style: - p.style = self.doc.css - - p.save() - get_obj(doc=p).write_cms_page() - - website.utils.add_guest_access_to_page(p.name) self.cleanup_temp() self.if_home_clear_cache() - - def add_page_links(self): - """add links for next_page and see_also""" - if self.doc.next_page: - self.doc.next_page_html = """
- Next: - %(title)s
""" % {"name":self.doc.next_page, \ - "title": webnotes.conn.get_value("Page", self.doc.next_page, "title")} - - self.doc.see_also = '' - for d in self.doclist: - if d.doctype=='Related Page': - tmp = {"page":d.page, "title":webnotes.conn.get_value('Page', d.page, 'title')} - self.doc.see_also += """
%(title)s
""" % tmp def cleanup_temp(self): """cleanup temp fields""" - fl = ['main_section_html', 'side_section_html', 'see_also', \ - 'next_page_html', 'head_section_html', 'updated'] + fl = ['main_section_html', 'side_section_html', \ + 'head_section_html'] for f in fl: if f in self.doc.fields: del self.doc.fields[f] diff --git a/erpnext/website/doctype/web_page/web_page.txt b/erpnext/website/doctype/web_page/web_page.txt index c40caff7de..9fba41a2c5 100644 --- a/erpnext/website/doctype/web_page/web_page.txt +++ b/erpnext/website/doctype/web_page/web_page.txt @@ -5,7 +5,7 @@ { 'creation': '2012-04-02 16:02:43', 'docstatus': 0, - 'modified': '2012-05-02 15:24:31', + 'modified': '2012-06-15 17:18:59', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -86,6 +86,17 @@ 'reqd': 1 }, + # DocField + { + 'colour': u'White:FFF', + 'description': u'Page url name (auto-generated) ', + 'doctype': u'DocField', + 'fieldname': u'page_name', + 'fieldtype': u'Data', + 'label': u'Page Name', + 'permlevel': 1 + }, + # DocField { 'doctype': u'DocField', @@ -101,7 +112,7 @@ 'fieldname': u'layout', 'fieldtype': u'Select', 'label': u'Layout', - 'options': u'Two column with header\nTwo column\nSingle column', + 'options': u'Single column\nTwo column\nTwo column with header', 'permlevel': 0 }, @@ -152,6 +163,17 @@ 'permlevel': 0 }, + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'content', + 'fieldtype': u'Code', + 'hidden': 1, + 'label': u'Content', + 'permlevel': 0 + }, + # DocField { 'colour': u'White:FFF', @@ -176,6 +198,7 @@ # DocField { 'colour': u'White:FFF', + 'description': u'Add code as <script>', 'doctype': u'DocField', 'fieldname': u'insert_code', 'fieldtype': u'Check', @@ -212,15 +235,6 @@ 'permlevel': 0 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'page_name', - 'fieldtype': u'Data', - 'label': u'Page Name', - 'permlevel': 1 - }, - # DocField { 'doctype': u'DocField', diff --git a/erpnext/website/templates/page.html b/erpnext/website/templates/page.html index 0eccd87e2e..c34dead322 100644 --- a/erpnext/website/templates/page.html +++ b/erpnext/website/templates/page.html @@ -4,7 +4,7 @@ {% block header %} {{ super() }} - {% if script %} + {% if insert_code %} {% endif %} - {% if style %} - + {% if insert_style %} + {% endif %} {% endblock %} diff --git a/public/web.py b/public/web.py index d05eb940bd..8909bf2f82 100755 --- a/public/web.py +++ b/public/web.py @@ -2,6 +2,8 @@ """ return a dynamic page from website templates + +all html pages except login-page.html get generated here """ import cgi, cgitb, os, sys @@ -29,6 +31,11 @@ def get_outer_env(): 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), } +def get_page_by_short_name(page_name): + """get page by shortname""" + import webnotes + return webnotes.conn.sql("""select name from `tabWeb Page` where page_name=%s""", page_name)[0][0] + def get_html(): import webnotes from jinja2 import Environment, FileSystemLoader @@ -42,12 +49,17 @@ def get_html(): webnotes.connect() if 'page' in webnotes.form_dict: - try: - page = Document('Page', webnotes.form_dict['page']) - page.fields.update(get_outer_env()) - return jenv.get_template('page.html').render(page.fields) - except Exception, e: - return jenv.get_template('404.html').render(get_outer_env()) + page_name = webnotes.form_dict['page'] + if page_name.endswith('.html'): + page_name = page_name[:-5] + + #try: + page_name = get_page_by_short_name(page_name) + page = Document('Web Page', page_name) + page.fields.update(get_outer_env()) + return jenv.get_template('page.html').render(page.fields) + #except Exception, e: + # return jenv.get_template('404.html').render(get_outer_env()) else: return jenv.get_template('404.html').render(get_outer_env()) From 40182bada34fdec6c8c88567493a7f3fb85b07c7 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 19 Jun 2012 14:15:13 +0530 Subject: [PATCH 03/26] added patch --- erpnext/patches/june_2012/cms2.py | 11 ++++++++ erpnext/website/templates/blog.html | 11 +++++--- public/web.py | 39 +++++++++++++++++++---------- 3 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 erpnext/patches/june_2012/cms2.py diff --git a/erpnext/patches/june_2012/cms2.py b/erpnext/patches/june_2012/cms2.py new file mode 100644 index 0000000000..fb9c72cf55 --- /dev/null +++ b/erpnext/patches/june_2012/cms2.py @@ -0,0 +1,11 @@ +def execute(): + import webnotes + from webnotes.model.doclist import DocList + import webnotes.model.sync + + # sync web page doctype + webnotes.model.sync.sync('website', 'web_page') + + # save all web pages to create content + for p in webnotes.conn.sql("""select name from `tabWeb Page` where docstatus=0"""): + DocList('Web Page', p[0]).save() \ No newline at end of file diff --git a/erpnext/website/templates/blog.html b/erpnext/website/templates/blog.html index 30dbd3b87e..d0b9a1362b 100644 --- a/erpnext/website/templates/blog.html +++ b/erpnext/website/templates/blog.html @@ -1,4 +1,7 @@ -{% extends "index.html" %} +{% extends "outer.html" %} + +{% block title %}{{ title }}{% endblock %} + {% block content %}
@@ -28,7 +31,9 @@
\ No newline at end of file diff --git a/public/web.py b/public/web.py index 8909bf2f82..c7c1df2109 100755 --- a/public/web.py +++ b/public/web.py @@ -17,6 +17,9 @@ sys.path.append(conf.modules_path) def get_outer_env(): """env for outer (cache this)""" + + # TODO: Cache this in cache item + import webnotes return { 'top_bar_items': webnotes.conn.sql("""select * from `tabTop Bar Item` @@ -31,7 +34,7 @@ def get_outer_env(): 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), } -def get_page_by_short_name(page_name): +def get_web_page_name(page_name): """get page by shortname""" import webnotes return webnotes.conn.sql("""select name from `tabWeb Page` where page_name=%s""", page_name)[0][0] @@ -47,21 +50,31 @@ def get_html(): for key in webnotes.form.keys(): webnotes.form_dict[key] = webnotes.form.getvalue(key) webnotes.connect() - - if 'page' in webnotes.form_dict: - page_name = webnotes.form_dict['page'] - if page_name.endswith('.html'): - page_name = page_name[:-5] + + # Get web page + try: + if 'page' in webnotes.form_dict: + page_name = webnotes.form_dict['page'] + if page_name.endswith('.html'): + page_name = page_name[:-5] + + if page_name.startswith('blog'): + pass + # page_name = + else: + page_name = get_web_page_name(page_name) + else: + from webnotes.cms import get_home_page + page_name = get_home_page('Guest') - #try: - page_name = get_page_by_short_name(page_name) page = Document('Web Page', page_name) page.fields.update(get_outer_env()) - return jenv.get_template('page.html').render(page.fields) - #except Exception, e: - # return jenv.get_template('404.html').render(get_outer_env()) - else: - return jenv.get_template('404.html').render(get_outer_env()) + return jenv.get_template('page.html').render(page.fields) + \ + ('\n' % page_name) + + except Exception, e: + return jenv.get_template('404.html').render(get_outer_env()) + \ + ('\n' % webnotes.getTraceback()) if __name__=="__main__": print "Content-Type: text/html" From 5d9fc72753c3bcd05da518c839bbeda1b7acdb57 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 21 Jun 2012 11:48:51 +0530 Subject: [PATCH 04/26] updates in web.py and template - page.html --- erpnext/website/templates/page.html | 4 +- public/web.py | 99 ++++++++++++++++------------- 2 files changed, 57 insertions(+), 46 deletions(-) diff --git a/erpnext/website/templates/page.html b/erpnext/website/templates/page.html index c34dead322..97a309ab73 100644 --- a/erpnext/website/templates/page.html +++ b/erpnext/website/templates/page.html @@ -12,7 +12,7 @@ var _page = new wn.views.Page(window.page_name); // page script - {{ insert_code }} + {{ javascript }} // trigger onload _page.trigger('onload'); @@ -23,7 +23,7 @@ {% endif %} {% if insert_style %} - + {% endif %} {% endblock %} diff --git a/public/web.py b/public/web.py index c7c1df2109..751d76206a 100755 --- a/public/web.py +++ b/public/web.py @@ -15,11 +15,49 @@ import conf sys.path.append('../lib/py') sys.path.append(conf.modules_path) +def init(): + import webnotes + webnotes.form = cgi.FieldStorage(keep_blank_values=True) + for key in webnotes.form.keys(): + webnotes.form_dict[key] = webnotes.form.getvalue(key) + webnotes.connect() + +def respond(): + html = get_html() + print "Content-Type: text/html" + print + print html.encode('utf-8') + +def get_html(): + import webnotes + from webnotes.model.doc import Document + # Get web page + outer_env_dict = get_outer_env() + try: + if 'page' in webnotes.form_dict: + page_name = webnotes.form_dict['page'] + if page_name.endswith('.html'): + page_name = page_name[:-5] + + if page_name.startswith('blog'): + raise Exception + #page_name = + else: + page_name = get_web_page_name(page_name) + else: + from webnotes.cms import get_home_page + page_name = get_home_page('Guest') + + page = Document('Web Page', page_name) + page.fields.update(outer_env_dict) + + return build_html(page.fields, "page: %s" % page_name) + + except Exception, e: + return build_html(outer_env_dict, "error: %s" % webnotes.getTraceback(), '404.html') + def get_outer_env(): - """env for outer (cache this)""" - - # TODO: Cache this in cache item - + """env dict for outer template""" import webnotes return { 'top_bar_items': webnotes.conn.sql("""select * from `tabTop Bar Item` @@ -33,50 +71,23 @@ def get_outer_env(): 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html'), 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), } + +def build_html(args, comments, template='page.html'): + """build html using jinja2 templates""" + from webnotes.utils import cstr + from jinja2 import Environment, FileSystemLoader + jenv = Environment(loader = FileSystemLoader('../erpnext/website/templates')) + html = jenv.get_template(template).render(args) + html += "\n" % cstr(comments) + return html + def get_web_page_name(page_name): """get page by shortname""" import webnotes return webnotes.conn.sql("""select name from `tabWeb Page` where page_name=%s""", page_name)[0][0] - -def get_html(): - import webnotes - from jinja2 import Environment, FileSystemLoader - from webnotes.model.doc import Document - - jenv = Environment(loader = FileSystemLoader('../erpnext/website/templates')) - - webnotes.form = cgi.FieldStorage(keep_blank_values=True) - for key in webnotes.form.keys(): - webnotes.form_dict[key] = webnotes.form.getvalue(key) - webnotes.connect() - - # Get web page - try: - if 'page' in webnotes.form_dict: - page_name = webnotes.form_dict['page'] - if page_name.endswith('.html'): - page_name = page_name[:-5] - - if page_name.startswith('blog'): - pass - # page_name = - else: - page_name = get_web_page_name(page_name) - else: - from webnotes.cms import get_home_page - page_name = get_home_page('Guest') - - page = Document('Web Page', page_name) - page.fields.update(get_outer_env()) - return jenv.get_template('page.html').render(page.fields) + \ - ('\n' % page_name) - - except Exception, e: - return jenv.get_template('404.html').render(get_outer_env()) + \ - ('\n' % webnotes.getTraceback()) + if __name__=="__main__": - print "Content-Type: text/html" - print - print get_html().encode('utf-8') + init() + respond() From 72c945b7c681690089c51d550ea4e66d9d99e663 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 22 Jun 2012 20:01:07 +0530 Subject: [PATCH 05/26] template based web page loading using web.py --- erpnext/patches/june_2012/cms2.py | 39 ++++- erpnext/website/doctype/blog/blog.py | 49 +----- erpnext/website/doctype/blog/blog.txt | 29 ++-- erpnext/website/doctype/blog/template.html | 24 --- erpnext/website/doctype/web_cache/__init__.py | 0 .../website/doctype/web_cache/web_cache.txt | 99 +++++++++++ .../website/doctype/web_page/template.html | 20 --- erpnext/website/doctype/web_page/web_page.py | 47 +----- erpnext/website/doctype/web_page/web_page.txt | 25 ++- erpnext/website/templates/blog-old.html | 58 +++++++ erpnext/website/templates/blog.html | 79 +++------ .../blog/blog_page.js => templates/blog.js} | 22 ++- erpnext/website/templates/page.html | 2 + erpnext/website/templates/web_page.html | 23 +++ erpnext/website/utils.py | 43 +---- erpnext/website/web_cache.py | 154 ++++++++++++++++++ erpnext/website/web_page.py | 78 +++++++++ public/js/all-app.js | 6 +- public/js/all-web.js | 6 +- public/web.py | 82 +++------- 20 files changed, 566 insertions(+), 319 deletions(-) delete mode 100644 erpnext/website/doctype/blog/template.html create mode 100644 erpnext/website/doctype/web_cache/__init__.py create mode 100644 erpnext/website/doctype/web_cache/web_cache.txt delete mode 100644 erpnext/website/doctype/web_page/template.html create mode 100644 erpnext/website/templates/blog-old.html rename erpnext/website/{doctype/blog/blog_page.js => templates/blog.js} (89%) create mode 100644 erpnext/website/templates/web_page.html create mode 100644 erpnext/website/web_cache.py create mode 100644 erpnext/website/web_page.py diff --git a/erpnext/patches/june_2012/cms2.py b/erpnext/patches/june_2012/cms2.py index fb9c72cf55..88e70496ed 100644 --- a/erpnext/patches/june_2012/cms2.py +++ b/erpnext/patches/june_2012/cms2.py @@ -1,11 +1,40 @@ def execute(): import webnotes - from webnotes.model.doclist import DocList import webnotes.model.sync - # sync web page doctype + # sync web page, blog doctype webnotes.model.sync.sync('website', 'web_page') + webnotes.model.sync.sync('website', 'blog') + + cleanup() + + save_pages() - # save all web pages to create content - for p in webnotes.conn.sql("""select name from `tabWeb Page` where docstatus=0"""): - DocList('Web Page', p[0]).save() \ No newline at end of file +def cleanup(): + import webnotes + + # delete pages from `tabPage` of module Website or of type Webpage + webnotes.conn.sql("""\ + delete from `tabPage` + where module='Website' and ifnull(web_page, 'No') = 'Yes'""") + +def save_pages(): + """save all web pages, blogs to create content""" + import webnotes + from webnotes.model.doclist import DocList + save_list = [ + { + 'doctype': 'Web Page', + 'query': """select name from `tabWeb Page` where docstatus=0""" + }, + { + 'doctype': 'Blog', + 'query': """\ + select name from `tabBlog` + where docstatus = 0 and ifnull(published, 0) = 1""" + }, + ] + + for s in save_list: + for p in webnotes.conn.sql(s['query'], as_dict=1): + DocList(s['doctype'], p['name']).save() \ No newline at end of file diff --git a/erpnext/website/doctype/blog/blog.py b/erpnext/website/doctype/blog/blog.py index 919b830399..0dfecc0a81 100644 --- a/erpnext/website/doctype/blog/blog.py +++ b/erpnext/website/doctype/blog/blog.py @@ -22,52 +22,17 @@ naming for same name files: file.gif, file-1.gif, file-2.gif etc import webnotes import website.utils +import website.web_page -class DocType(): +class DocType(website.web_page.Page): def __init__(self, d, dl): + super(DocType, self).__init__('Blog') self.doc, self.doclist = d, dl - - def autoname(self): - """save file by its name""" - self.doc.name = website.utils.page_name(self.doc.title) - - def validate(self): - """write/update 'Page' with the blog""" - # we need the name for the templates - if not self.doc.name: - self.autoname() - - if self.doc.page_name: - webnotes.conn.sql("""delete from tabPage where name=%s""", self.doc.page_name) - - p = website.utils.add_page(self.doc.title) - - from jinja2 import Template - import markdown2 - import os + + def get_html(self): + # temp fields from webnotes.utils import global_date_format, get_fullname - from webnotes.model.code import get_obj - - self.doc.content_html = unicode(markdown2.markdown(self.doc.content or '')) self.doc.full_name = get_fullname(self.doc.owner) self.doc.updated = global_date_format(self.doc.modified) - - 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__), 'blog_page.js'), 'r') as f: - p.script = Template(f.read()).render(doc=self.doc) - - p.web_page = 'Yes' - p.save() - get_obj(doc=p).write_cms_page() - - website.utils.add_guest_access_to_page(p.name) - self.doc.page_name = p.name - - # cleanup - for f in ['full_name', 'updated', 'content_html']: - if f in self.doc.fields: - del self.doc.fields[f] - \ No newline at end of file + self.markdown_to_html(['content']) \ No newline at end of file diff --git a/erpnext/website/doctype/blog/blog.txt b/erpnext/website/doctype/blog/blog.txt index ad44d13d96..24187e3bf3 100644 --- a/erpnext/website/doctype/blog/blog.txt +++ b/erpnext/website/doctype/blog/blog.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-04-02 16:02:43', + 'creation': '2012-05-28 19:22:38', 'docstatus': 0, - 'modified': '2012-04-26 16:58:27', + 'modified': '2012-06-22 18:56:16', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -21,7 +21,7 @@ 'name': '__common__', 'section_style': u'Simple', 'show_in_menu': 0, - 'version': 5 + 'version': 1 }, # These values are common for all DocField @@ -51,6 +51,7 @@ # DocPerm { + 'cancel': 1, 'create': 1, 'doctype': u'DocPerm', 'permlevel': 0, @@ -71,7 +72,14 @@ { 'doctype': u'DocPerm', 'permlevel': 1, - 'role': u'All' + 'role': u'Website Manager' + }, + + # DocPerm + { + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Blogger' }, # DocField @@ -99,26 +107,19 @@ 'fieldname': u'content', 'fieldtype': u'Code', 'label': u'Content', + 'options': u'Markdown', 'permlevel': 0, 'reqd': 0 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'content_html', - 'fieldtype': u'Text', - 'label': u'Content HTML', - 'permlevel': 1 - }, - # DocField { 'doctype': u'DocField', 'fieldname': u'page_name', 'fieldtype': u'Data', + 'hidden': 1, 'label': u'Page Name', - 'permlevel': 0 + 'permlevel': 1 }, # DocField diff --git a/erpnext/website/doctype/blog/template.html b/erpnext/website/doctype/blog/template.html deleted file mode 100644 index 510f1bed5f..0000000000 --- a/erpnext/website/doctype/blog/template.html +++ /dev/null @@ -1,24 +0,0 @@ -
-
-
-

{{ doc.title }}

-
By {{ doc.full_name }} on {{ doc.updated }}
-
- {{ doc.content_html }} -

Comments

-
-
-
-
-

All Blogs

-

Recent Posts

-
-

Subscribe

-

- - RSS Feed -

-
-
-
-
\ No newline at end of file diff --git a/erpnext/website/doctype/web_cache/__init__.py b/erpnext/website/doctype/web_cache/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/website/doctype/web_cache/web_cache.txt b/erpnext/website/doctype/web_cache/web_cache.txt new file mode 100644 index 0000000000..98a48918a7 --- /dev/null +++ b/erpnext/website/doctype/web_cache/web_cache.txt @@ -0,0 +1,99 @@ +# DocType, Web Cache +[ + + # These values are common in all dictionaries + { + 'creation': '2012-06-21 12:01:17', + 'docstatus': 0, + 'modified': '2012-06-21 17:25:52', + 'modified_by': u'Administrator', + 'owner': u'Administrator' + }, + + # These values are common for all DocType + { + 'doctype': 'DocType', + 'document_type': u'System', + 'module': u'Website', + 'name': '__common__', + 'version': 1 + }, + + # These values are common for all DocField + { + 'doctype': u'DocField', + 'name': '__common__', + 'parent': u'Web Cache', + 'parentfield': u'fields', + 'parenttype': u'DocType', + 'permlevel': 0 + }, + + # These values are common for all DocPerm + { + 'doctype': u'DocPerm', + 'name': '__common__', + 'parent': u'Web Cache', + 'parentfield': u'permissions', + 'parenttype': u'DocType', + 'permlevel': 0, + 'read': 1, + 'write': 1 + }, + + # DocType, Web Cache + { + 'doctype': 'DocType', + 'name': u'Web Cache' + }, + + # DocPerm + { + 'create': 0, + 'doctype': u'DocPerm', + 'role': u'All' + }, + + # DocPerm + { + 'create': 1, + 'doctype': u'DocPerm', + 'role': u'Website Manager' + }, + + # DocPerm + { + 'create': 1, + 'doctype': u'DocPerm', + 'role': u'Blogger' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'doc_type', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'DocType', + 'options': u'DocType', + 'reqd': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'doc_name', + 'fieldtype': u'Data', + 'in_filter': 0, + 'label': u'DocName', + 'reqd': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'html', + 'fieldtype': u'Long Text', + 'label': u'HTML' + } +] \ No newline at end of file diff --git a/erpnext/website/doctype/web_page/template.html b/erpnext/website/doctype/web_page/template.html deleted file mode 100644 index f46113c0b2..0000000000 --- a/erpnext/website/doctype/web_page/template.html +++ /dev/null @@ -1,20 +0,0 @@ -
-
- - {% if doc.layout and doc.layout.startswith('Two column') %} -
- {% else %} -
- {% endif %} - {{ doc.main_section_html }} -
- - {% if doc.layout and doc.layout.startswith('Two column') %} -
- {{ doc.side_section_html }} -
- {% endif %} -
-
-
diff --git a/erpnext/website/doctype/web_page/web_page.py b/erpnext/website/doctype/web_page/web_page.py index 3f4a39c0a9..37e0cee18b 100644 --- a/erpnext/website/doctype/web_page/web_page.py +++ b/erpnext/website/doctype/web_page/web_page.py @@ -16,51 +16,22 @@ import webnotes import website.utils +import website.web_page -class DocType: +class DocType(website.web_page.Page): def __init__(self, d, dl): + super(DocType, self).__init__('Web Page') self.doc, self.doclist = d, dl - - def autoname(self): - """name from title""" - self.doc.name = website.utils.page_name(self.doc.title) def on_update(self): - """make page for this product""" - from jinja2 import Template - import os - - # we need the name for the templates - if self.doc.name.startswith('New Web Page'): - self.autoname() - - # page name updates with the title - self.doc.page_name = website.utils.page_name(self.doc.title) - - # markdown - website.utils.markdown(self.doc, ['head_section','main_section', 'side_section']) - - # make page layout - with open(os.path.join(os.path.dirname(__file__), 'template.html'), 'r') as f: - self.doc.content = Template(f.read()).render(doc=self.doc) - - self.cleanup_temp() - - self.doc.save() - + super(DocType, self).on_update() self.if_home_clear_cache() - - def cleanup_temp(self): - """cleanup temp fields""" - fl = ['main_section_html', 'side_section_html', \ - 'head_section_html'] - for f in fl: - if f in self.doc.fields: - del self.doc.fields[f] - + def if_home_clear_cache(self): """if home page, clear cache""" if webnotes.conn.get_value("Website Settings", None, "home_page")==self.doc.name: from webnotes.session_cache import clear_cache - clear_cache('Guest') - \ No newline at end of file + clear_cache('Guest') + + def get_html(self): + self.markdown_to_html(['head_section','main_section', 'side_section']) \ No newline at end of file diff --git a/erpnext/website/doctype/web_page/web_page.txt b/erpnext/website/doctype/web_page/web_page.txt index 9fba41a2c5..a1fd8949f9 100644 --- a/erpnext/website/doctype/web_page/web_page.txt +++ b/erpnext/website/doctype/web_page/web_page.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-04-02 16:02:43', + 'creation': '2012-06-19 15:02:20', 'docstatus': 0, - 'modified': '2012-06-15 17:18:59', + 'modified': '2012-06-22 18:49:02', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -36,13 +36,15 @@ # These values are common for all DocPerm { + 'amend': 0, 'doctype': u'DocPerm', 'name': '__common__', 'parent': u'Web Page', 'parentfield': u'permissions', 'parenttype': u'DocType', 'read': 1, - 'role': u'Website Manager' + 'role': u'Website Manager', + 'submit': 0 }, # DocType, Web Page @@ -53,6 +55,7 @@ # DocPerm { + 'cancel': 1, 'create': 1, 'doctype': u'DocPerm', 'permlevel': 0, @@ -61,8 +64,11 @@ # DocPerm { + 'cancel': 0, + 'create': 0, 'doctype': u'DocPerm', - 'permlevel': 1 + 'permlevel': 1, + 'write': 0 }, # DocField @@ -163,17 +169,6 @@ 'permlevel': 0 }, - # DocField - { - 'colour': u'White:FFF', - 'doctype': u'DocField', - 'fieldname': u'content', - 'fieldtype': u'Code', - 'hidden': 1, - 'label': u'Content', - 'permlevel': 0 - }, - # DocField { 'colour': u'White:FFF', diff --git a/erpnext/website/templates/blog-old.html b/erpnext/website/templates/blog-old.html new file mode 100644 index 0000000000..d0b9a1362b --- /dev/null +++ b/erpnext/website/templates/blog-old.html @@ -0,0 +1,58 @@ +{% extends "outer.html" %} + +{% block title %}{{ title }}{% endblock %} + + +{% block content %} +
+
+
+

Blog

+
+
+ +
+
+
+ +

Subscribe

+

+ + RSS Feed +

+
+
+
+
+ + \ No newline at end of file diff --git a/erpnext/website/templates/blog.html b/erpnext/website/templates/blog.html index d0b9a1362b..e188edf921 100644 --- a/erpnext/website/templates/blog.html +++ b/erpnext/website/templates/blog.html @@ -1,58 +1,31 @@ -{% extends "outer.html" %} - -{% block title %}{{ title }}{% endblock %} - +{% extends "blog.js" %} {% block content %} -
-
-
-

Blog

-
-
- +
+
+ +
+

{{ title }}

+
By {{ full_name }} on {{ updated }}
+
+ {{ content_html }} +

Comments

+
+
+ +
+

All Blogs

+

Recent Posts

+
+

Subscribe

+

+ + RSS Feed +

+
+ +
-
- -

Subscribe

-

- - RSS Feed -

-
-
-
- - \ No newline at end of file +{% endblock %} \ No newline at end of file diff --git a/erpnext/website/doctype/blog/blog_page.js b/erpnext/website/templates/blog.js similarity index 89% rename from erpnext/website/doctype/blog/blog_page.js rename to erpnext/website/templates/blog.js index 4b283920fa..80cb813f95 100644 --- a/erpnext/website/doctype/blog/blog_page.js +++ b/erpnext/website/templates/blog.js @@ -1,3 +1,6 @@ +{% extends "page.html" %} + +{% block javascript %} // ERPNext - web based ERP (http://erpnext.com) // Copyright (C) 2012 Web Notes Technologies Pvt Ltd // @@ -15,14 +18,13 @@ // along with this program. If not, see . // js inside blog page - -pscript['onload_{{ doc.name }}'] = function(wrapper) { +wn.pages['{{ name }}'].onload = function(wrapper) { // sidebar wrapper.recent_list = new wn.ui.Listing({ parent: $(wrapper).find('.recent-posts'), no_toolbar: true, query: 'select name, title, left(content, 100) as content from tabBlog\ - where ifnull(published,0)=1 and name!="{{ doc.name }}" order by creation desc', + where ifnull(published,0)=1 and name!="{{ name }}" order by creation desc', hide_refresh: true, render_row: function(parent, data) { //console.log(data); @@ -33,13 +35,13 @@ pscript['onload_{{ doc.name }}'] = function(wrapper) { page_length: 5, }); wrapper.recent_list.run(); - + wrapper.comment_list = new wn.ui.Listing({ parent: $(wrapper).find('.blog-comments').get(0), no_toolbar: true, query: 'select comment, comment_by_fullname, creation\ from `tabComment` where comment_doctype="Page"\ - and comment_docname="{{ doc.name }}" order by creation desc', + and comment_docname="{{ name }}" order by creation desc', no_result_message: 'Be the first one to comment', render_row: function(parent, data) { data.comment_date = prettyDate(data.creation); @@ -48,10 +50,10 @@ pscript['onload_{{ doc.name }}'] = function(wrapper) {
\

%(comment)s


", data)) }, - hide_refresh: true + hide_refresh: true, }); wrapper.comment_list.run(); - + // add comment $(wrapper).find('.layout-main-section').append('
'); @@ -70,7 +72,7 @@ pscript['onload_{{ doc.name }}'] = function(wrapper) { var args = d.get_values(); if(!args) return; args.comment_doctype = 'Page'; - args.comment_docname = '{{ doc.name }}'; + args.comment_docname = '{{ name }}'; $(btn).set_working(); $c('webnotes.widgets.form.comments.add_comment', args, function(r) { $(btn).done_working(); @@ -80,4 +82,6 @@ pscript['onload_{{ doc.name }}'] = function(wrapper) { } d.show(); }) -} \ No newline at end of file +} + +{% endblock %} diff --git a/erpnext/website/templates/page.html b/erpnext/website/templates/page.html index 97a309ab73..a8e20f67f2 100644 --- a/erpnext/website/templates/page.html +++ b/erpnext/website/templates/page.html @@ -12,7 +12,9 @@ var _page = new wn.views.Page(window.page_name); // page script + {% block javascript %} {{ javascript }} + {% endblock %} // trigger onload _page.trigger('onload'); diff --git a/erpnext/website/templates/web_page.html b/erpnext/website/templates/web_page.html new file mode 100644 index 0000000000..8188e71373 --- /dev/null +++ b/erpnext/website/templates/web_page.html @@ -0,0 +1,23 @@ +{% extends "page.html" %} + +{% block content %} +
+
+ + {% if layout and layout.startswith('Two column') %} +
+ {% else %} +
+ {% endif %} + {{ main_section_html }} +
+ + {% if layout and layout.startswith('Two column') %} +
+ {{ side_section_html }} +
+ {% endif %} +
+
+
+{% endblock %} \ No newline at end of file diff --git a/erpnext/website/utils.py b/erpnext/website/utils.py index 57e940a755..06bb60d94b 100644 --- a/erpnext/website/utils.py +++ b/erpnext/website/utils.py @@ -29,43 +29,12 @@ def make_template(doc, path, convert_fields = ['main_section', 'side_section']): return temp.render(doc = doc.fields) -def markdown(doc, fields): - """convert fields to markdown""" - import markdown2 - # markdown - for f in fields: - doc.fields[f + '_html'] = markdown2.markdown(doc.fields[f] or '', \ - extras=["wiki-tables"]) - - def page_name(title): - """make page name from title, and check that there is no duplicate""" - import webnotes.cms - return webnotes.cms.page_name(title) - -def add_page(title): - """add a custom page with title""" - name = page_name(title) - if webnotes.conn.sql("""select name from tabPage where name=%s""", name): - p = Document('Page', name) - else: - p = Document('Page') - - p.title = title - p.name = p.page_name = name - p.module = 'Website' - p.standard = 'No' - - return p - -def add_guest_access_to_page(page): - """add Guest in Page Role""" - if not webnotes.conn.sql("""select parent from `tabPage Role` - where role='Guest' and parent=%s""", page): - d = Document('Page Role') - d.parent = page - d.role = 'Guest' - d.save() + """make page name from title""" + import re + name = title.lower() + name = re.sub('[~!@#$%^&*()<>,."\']', '', name) + return '-'.join(name.split()[:4]) def get_header(page_name): """get page header""" @@ -144,4 +113,4 @@ def get_footer(page_name): {% endfor %}
""").render(website_settings.fields) +
""").render(website_settings.fields) \ No newline at end of file diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py new file mode 100644 index 0000000000..30e3f0015d --- /dev/null +++ b/erpnext/website/web_cache.py @@ -0,0 +1,154 @@ +# 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 . + +# used by web.py +def load_from_web_cache(page_name, comments, template): + """ + * search for page in cache + * if html exists, return + * if not, build html, store it in cache, return + """ + import webnotes + import conf + + if page_name == 'index': + page_name = get_index_page()[0] + + res = webnotes.conn.sql("""\ + select html, doc_type, doc_name from `tabWeb Cache` + where name = %s""", page_name) + + # if page doesn't exist, raise exception + if not res and page_name not in ['404', 'index']: + raise Exception, "Page %s not found" % page_name + + html, doc_type, doc_name = res and res[0] or (None, None, None) + auto_cache_clear = hasattr(conf, 'auto_cache_clear') and conf.auto_cache_clear or 0 + if not html or auto_cache_clear: + comments += "\n\npage load status: fresh" + html = load_into_web_cache(page_name, template, doc_type, doc_name) + else: + comments += "\n\npage load status: cached" + + from webnotes.utils import cstr + html += """\n""" % cstr(comments) + return html + +def load_into_web_cache(page_name, template, doc_type, doc_name): + """build html and store it in web cache""" + import webnotes + outer_env_dict = get_outer_env() + + if page_name == '404': + args = outer_env_dict + else: + if page_name == 'index': + page_name, doc_type, doc_name = get_index_page() + + from webnotes.model.code import get_obj + obj = get_obj(doc_type, doc_name) + obj.get_html() + args = obj.doc.fields + args.update(outer_env_dict) + + if doc_type == 'Blog': + template = 'blog.html' + args['insert_code'] = 1 + elif doc_type == 'Web Page': + template = 'web_page.html' + + html = build_html(args, template) + + # save html in web cache + webnotes.conn.begin() + webnotes.conn.set_value('Web Cache', page_name, 'html', html) + webnotes.conn.commit() + + return html + +def build_html(args, template): + """build html using jinja2 templates""" + from jinja2 import Environment, FileSystemLoader + jenv = Environment(loader = FileSystemLoader('../erpnext/website/templates')) + html = jenv.get_template(template).render(args) + return html + +def get_outer_env(): + """env dict for outer template""" + import webnotes + return { + 'top_bar_items': webnotes.conn.sql("""select * from `tabTop Bar Item` + where parent='Website Settings' and parentfield='top_bar_items' + order by idx asc""", as_dict=1), + + 'footer_items': webnotes.conn.sql("""select * from `tabTop Bar Item` + where parent='Website Settings' and parentfield='footer_items' + order by idx asc""", as_dict=1), + + 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html'), + 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), + } + +def get_index_page(): + import webnotes + doc_type = 'Web Page' + doc_name = webnotes.conn.get_value('Website Settings', None, 'home_page') + page_name = webnotes.conn.get_value(doc_type, doc_name, 'page_name') + return page_name, doc_type, doc_name + +# cache management +def clear_web_cache(doc_type, doc_name, page_name): + """ + * check if a record corresponding to (type, name) exists + * if exists, just clear html column + * if does not exist, create a record for (type, name) + * if a record like (some other type, name) exists, raise exception that the page name is not unique + """ + import webnotes + res = webnotes.conn.get_value('Web Cache', page_name, 'doc_type') + if not res: + import webnotes.model.doc + d = webnotes.model.doc.Document('Web Cache') + d.name = page_name + d.doc_type = doc_type + d.doc_name = doc_name + d.html = None + d.save() + elif res == doc_type: + webnotes.conn.set_value('Web Cache', page_name, 'html', None) + else: + webnotes.msgprint("""Page with name "%s" already exists as a %s. + Please save it with another name.""" % (page_name, res), raise_exception=1) + +def clear_all_web_cache(): + import webnotes + webnotes.conn.sql("update `tabWeb Cache` set html = NULL") + +def delete_web_cache(page_name): + """ + delete entry of page_name from Web Cache + used when: + * web page is deleted + * blog is un-published + """ + import webnotes + webnotes.conn.sql("""\ + delete from `tabWeb Cache` + where name=%s""", page_name) + +def build_web_cache(): + """build web cache so that pages can load faster""" + pass \ No newline at end of file diff --git a/erpnext/website/web_page.py b/erpnext/website/web_page.py new file mode 100644 index 0000000000..4d6f9f0b6b --- /dev/null +++ b/erpnext/website/web_page.py @@ -0,0 +1,78 @@ +# 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 . + +import webnotes +import website.utils +import website.web_cache + +class Page(object): + def __init__(self, doctype): + self.doctype = doctype + + def autoname(self): + """name from title""" + self.doc.name = website.utils.page_name(self.doc.title) + + def validate(self): + if self.doc.name: + self.old_page_name = webnotes.conn.get_value(self.doctype, self.doc.name, 'page_name') + + def on_update(self): + # page name updates with the title + 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.doc.save(ignore_fields=1) + + def on_trash(self): + """delete Web Cache entry""" + self.delete_web_cache(self.doc.page_name) + + def update_page_name(self): + """set page_name and check if it is unique""" + self.doc.page_name = website.utils.page_name(self.doc.title) + + res = webnotes.conn.sql("""\ + select count(*) from `tab%s` + where page_name=%s and name!=%s""" % (self.doctype, '%s', '%s'), + (self.doc.page_name, self.doc.name)) + if res and res[0][0] > 0: + webnotes.msgprint("""A %s with the same title already exists. + Please change the title and save again.""" % self.doctype, raise_exception=1) + + def clear_web_cache(self): + """ + if web cache entry doesn't exist, it creates one + if duplicate entry exists for another doctype, it raises exception + """ + website.web_cache.clear_web_cache(self.doctype, self.doc.name, self.doc.page_name) + + def delete_web_cache(self, page_name): + """delete entry of page name from Web Cache""" + website.web_cache.delete_web_cache(page_name) + + def markdown_to_html(self, fields_list): + """convert fields from markdown to html""" + import markdown2 + for f in fields_list: + field_name = "%s_html" % f + self.doc.fields[field_name] = markdown2.markdown(self.doc.fields.get(f) or '', \ + extras=["wiki-tables"]) \ No newline at end of file diff --git a/public/js/all-app.js b/public/js/all-app.js index 5e3f8f2db4..026903bf41 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -310,13 +310,13 @@ if(me.show_filters){this.add_button('Show Filters',function(){me.filter_list.sho if(me.no_toolbar||me.hide_toolbar){me.$w.find('.list-toolbar-wrapper').toggle(false);}},make_new_doc:function(new_doctype){new_doc(new_doctype);},make_filters:function(){this.filter_list=new wn.ui.FilterList({listobj:this,$parent:this.$w.find('.list-filters').toggle(true),doctype:this.doctype,filter_fields:this.filter_fields});},clear:function(){this.data=[];this.$w.find('.result-list').empty();this.$w.find('.result').toggle(true);this.$w.find('.no-result').toggle(false);this.start=0;},run:function(){var me=this;var a0=arguments[0];var a1=arguments[1];if(a0&&typeof a0=='function') this.onrun=a0;if(a0&&a0.callback) this.onrun=a0.callback;if(!a1&&!(a0&&a0.append)) -this.start=0;me.set_working(true);wn.call({method:this.opts.method||'webnotes.widgets.query_builder.runquery',args:this.get_call_args(a0),callback:function(r){me.set_working(false);me.render_results(r)},no_spinner:this.opts.no_loading});},set_working:function(flag){this.$w.find('.img-load').toggle(flag);},get_call_args:function(opts){if(!this.method){this.query=this.get_query?this.get_query():this.query;this.add_limits();var args={query_max:this.query_max,as_dict:1} -args.simple_query=this.query;}else{var args={limit_start:this.start,limit_page_length:this.page_length}} +this.start=0;me.set_working(true);wn.call({method:this.opts.method||'webnotes.widgets.query_builder.runquery',args:this.get_call_args(a0),callback:function(r){me.set_working(false);me.render_results(r)},no_spinner:this.opts.no_loading});},set_working:function(flag){this.$w.find('.img-load').toggle(flag);},get_call_args:function(opts){if(!this.method){var query=this.get_query?this.get_query():this.query;query=this.add_limits(query);var args={query_max:this.query_max,as_dict:1} +args.simple_query=query;}else{var args={limit_start:this.start,limit_page_length:this.page_length}} if(this.args) $.extend(args,this.args) if(this.get_args){$.extend(args,this.get_args(opts));} return args;},render_results:function(r){if(this.start==0)this.clear();this.$w.find('.btn-more').toggle(false);if(r.message)r.values=r.message;if(r.values&&r.values.length){this.data=this.data.concat(r.values);this.render_list(r.values);this.update_paging(r.values);}else{if(this.start==0){this.$w.find('.result').toggle(false);this.$w.find('.no-result').toggle(true);}} -if(this.onrun)this.onrun();if(this.callback)this.callback(r);},render_list:function(values){var m=Math.min(values.length,this.page_length);for(var i=0;i=this.page_length){this.$w.find('.btn-more').toggle(true);this.start+=this.page_length;}},add_row:function(){return $('
').appendTo(this.$w.find('.result-list')).get(0);},refresh:function(){this.run();},add_limits:function(){this.query+=' LIMIT '+this.start+','+(this.page_length+1);}}); +if(this.onrun)this.onrun();if(this.callback)this.callback(r);},render_list:function(values){var m=Math.min(values.length,this.page_length);for(var i=0;i=this.page_length){this.$w.find('.btn-more').toggle(true);this.start+=this.page_length;}},add_row:function(){return $('
').appendTo(this.$w.find('.result-list')).get(0);},refresh:function(){this.run();},add_limits:function(query){query+=' LIMIT '+this.start+','+(this.page_length+1);return query}}); /* * lib/js/wn/ui/filters.js */ diff --git a/public/js/all-web.js b/public/js/all-web.js index a549dc9e54..9712ff6d14 100644 --- a/public/js/all-web.js +++ b/public/js/all-web.js @@ -197,13 +197,13 @@ if(me.show_filters){this.add_button('Show Filters',function(){me.filter_list.sho if(me.no_toolbar||me.hide_toolbar){me.$w.find('.list-toolbar-wrapper').toggle(false);}},make_new_doc:function(new_doctype){new_doc(new_doctype);},make_filters:function(){this.filter_list=new wn.ui.FilterList({listobj:this,$parent:this.$w.find('.list-filters').toggle(true),doctype:this.doctype,filter_fields:this.filter_fields});},clear:function(){this.data=[];this.$w.find('.result-list').empty();this.$w.find('.result').toggle(true);this.$w.find('.no-result').toggle(false);this.start=0;},run:function(){var me=this;var a0=arguments[0];var a1=arguments[1];if(a0&&typeof a0=='function') this.onrun=a0;if(a0&&a0.callback) this.onrun=a0.callback;if(!a1&&!(a0&&a0.append)) -this.start=0;me.set_working(true);wn.call({method:this.opts.method||'webnotes.widgets.query_builder.runquery',args:this.get_call_args(a0),callback:function(r){me.set_working(false);me.render_results(r)},no_spinner:this.opts.no_loading});},set_working:function(flag){this.$w.find('.img-load').toggle(flag);},get_call_args:function(opts){if(!this.method){this.query=this.get_query?this.get_query():this.query;this.add_limits();var args={query_max:this.query_max,as_dict:1} -args.simple_query=this.query;}else{var args={limit_start:this.start,limit_page_length:this.page_length}} +this.start=0;me.set_working(true);wn.call({method:this.opts.method||'webnotes.widgets.query_builder.runquery',args:this.get_call_args(a0),callback:function(r){me.set_working(false);me.render_results(r)},no_spinner:this.opts.no_loading});},set_working:function(flag){this.$w.find('.img-load').toggle(flag);},get_call_args:function(opts){if(!this.method){var query=this.get_query?this.get_query():this.query;query=this.add_limits(query);var args={query_max:this.query_max,as_dict:1} +args.simple_query=query;}else{var args={limit_start:this.start,limit_page_length:this.page_length}} if(this.args) $.extend(args,this.args) if(this.get_args){$.extend(args,this.get_args(opts));} return args;},render_results:function(r){if(this.start==0)this.clear();this.$w.find('.btn-more').toggle(false);if(r.message)r.values=r.message;if(r.values&&r.values.length){this.data=this.data.concat(r.values);this.render_list(r.values);this.update_paging(r.values);}else{if(this.start==0){this.$w.find('.result').toggle(false);this.$w.find('.no-result').toggle(true);}} -if(this.onrun)this.onrun();if(this.callback)this.callback(r);},render_list:function(values){var m=Math.min(values.length,this.page_length);for(var i=0;i=this.page_length){this.$w.find('.btn-more').toggle(true);this.start+=this.page_length;}},add_row:function(){return $('
').appendTo(this.$w.find('.result-list')).get(0);},refresh:function(){this.run();},add_limits:function(){this.query+=' LIMIT '+this.start+','+(this.page_length+1);}}); +if(this.onrun)this.onrun();if(this.callback)this.callback(r);},render_list:function(values){var m=Math.min(values.length,this.page_length);for(var i=0;i=this.page_length){this.$w.find('.btn-more').toggle(true);this.start+=this.page_length;}},add_row:function(){return $('
').appendTo(this.$w.find('.result-list')).get(0);},refresh:function(){this.run();},add_limits:function(query){query+=' LIMIT '+this.start+','+(this.page_length+1);return query}}); /* * lib/js/wn/ui/filters.js */ diff --git a/public/web.py b/public/web.py index 751d76206a..6f3569e327 100755 --- a/public/web.py +++ b/public/web.py @@ -23,71 +23,41 @@ def init(): webnotes.connect() def respond(): - html = get_html() + import webnotes + try: + if 'page' in webnotes.form_dict: + html = get_html(webnotes.form_dict['page']) + else: + # show home page + html = get_html('index') + except Exception, e: + html = get_html('404') + print "Content-Type: text/html" print print html.encode('utf-8') -def get_html(): +def scrub_page_name(page_name): + if page_name.endswith('.html'): + page_name = page_name[:-5] + return page_name + +def get_html(page_name): import webnotes - from webnotes.model.doc import Document - # Get web page - outer_env_dict = get_outer_env() - try: - if 'page' in webnotes.form_dict: - page_name = webnotes.form_dict['page'] - if page_name.endswith('.html'): - page_name = page_name[:-5] - - if page_name.startswith('blog'): - raise Exception - #page_name = - else: - page_name = get_web_page_name(page_name) - else: - from webnotes.cms import get_home_page - page_name = get_home_page('Guest') - - page = Document('Web Page', page_name) - page.fields.update(outer_env_dict) - - return build_html(page.fields, "page: %s" % page_name) - - except Exception, e: - return build_html(outer_env_dict, "error: %s" % webnotes.getTraceback(), '404.html') - -def get_outer_env(): - """env dict for outer template""" - import webnotes - return { - 'top_bar_items': webnotes.conn.sql("""select * from `tabTop Bar Item` - where parent='Website Settings' and parentfield='top_bar_items' - order by idx asc""", as_dict=1), + import website.web_cache + page_name = scrub_page_name(page_name) - 'footer_items': webnotes.conn.sql("""select * from `tabTop Bar Item` - where parent='Website Settings' and parentfield='footer_items' - order by idx asc""", as_dict=1), - - 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html'), - 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), - } - -def build_html(args, comments, template='page.html'): - """build html using jinja2 templates""" - from webnotes.utils import cstr - from jinja2 import Environment, FileSystemLoader - jenv = Environment(loader = FileSystemLoader('../erpnext/website/templates')) + if page_name == '404': + comments = """error: %s""" % webnotes.getTraceback() + template = '404.html' + else: + comments = """page: %s""" % page_name + template = 'page.html' + + html = website.web_cache.load_from_web_cache(page_name, comments, template) - html = jenv.get_template(template).render(args) - html += "\n" % cstr(comments) return html -def get_web_page_name(page_name): - """get page by shortname""" - import webnotes - return webnotes.conn.sql("""select name from `tabWeb Page` where page_name=%s""", page_name)[0][0] - - if __name__=="__main__": init() respond() From c7b485e72435308190aa11f68b3e77e93729c15f Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 22 Jun 2012 20:08:30 +0530 Subject: [PATCH 06/26] blog - on update - delete cache if not published --- erpnext/website/doctype/blog/blog.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/website/doctype/blog/blog.py b/erpnext/website/doctype/blog/blog.py index 0dfecc0a81..0e8acac196 100644 --- a/erpnext/website/doctype/blog/blog.py +++ b/erpnext/website/doctype/blog/blog.py @@ -29,7 +29,16 @@ class DocType(website.web_page.Page): super(DocType, self).__init__('Blog') self.doc, self.doclist = d, dl + def on_update(self): + super(DocType, self).on_update() + if not webnotes.utils.cint(self.doc.published): + self.delete_web_cache(self.doc.page_name) + def get_html(self): + # this is for double precaution. usually it wont reach this code if not published + if not webnotes.utils.cint(self.doc.published): + raise Exception, "This blog has not been published yet!" + # temp fields from webnotes.utils import global_date_format, get_fullname self.doc.full_name = get_fullname(self.doc.owner) From 10bcf5ea255ec5bc39211100e6717d3c46086ffc Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 26 Jun 2012 18:54:10 +0530 Subject: [PATCH 07/26] blog listing + started with products page and listing --- erpnext/patches/june_2012/cms2.py | 6 ++ erpnext/stock/doctype/item/item.py | 101 ++++++++++++------ .../website_settings/website_settings.py | 9 +- erpnext/website/templates/blog-old.html | 58 ---------- .../website/templates/{ => blog}/blog.html | 2 +- erpnext/website/templates/{ => blog}/blog.js | 0 erpnext/website/templates/blog/blog_list.html | 43 ++++++++ erpnext/website/templates/blog/blog_list.js | 48 +++++++++ erpnext/website/templates/page.html | 5 + .../website/templates/product/product.html | 31 ++++++ erpnext/website/templates/product/product.js | 68 ++++++++++++ .../templates/product/product_list.html | 23 ++++ .../website/templates/product/product_list.js | 40 +++++++ erpnext/website/web_cache.py | 24 ++++- erpnext/website/web_page.py | 13 +-- 15 files changed, 364 insertions(+), 107 deletions(-) delete mode 100644 erpnext/website/templates/blog-old.html rename erpnext/website/templates/{ => blog}/blog.html (96%) rename erpnext/website/templates/{ => blog}/blog.js (100%) create mode 100644 erpnext/website/templates/blog/blog_list.html create mode 100644 erpnext/website/templates/blog/blog_list.js create mode 100644 erpnext/website/templates/product/product.html create mode 100644 erpnext/website/templates/product/product.js create mode 100644 erpnext/website/templates/product/product_list.html create mode 100644 erpnext/website/templates/product/product_list.js diff --git a/erpnext/patches/june_2012/cms2.py b/erpnext/patches/june_2012/cms2.py index 88e70496ed..48f0152985 100644 --- a/erpnext/patches/june_2012/cms2.py +++ b/erpnext/patches/june_2012/cms2.py @@ -33,6 +33,12 @@ def save_pages(): select name from `tabBlog` 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: diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index f0fb5e7ecc..85af0bb73e 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -46,6 +46,8 @@ class DocType: return ret def on_update(self): + self.update_page_name() + 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): msgprint("Please Update Stock UOM with the help of Stock UOM Replace Utility.") @@ -79,9 +81,14 @@ class DocType: child.conversion_factor = 1 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) def on_trash(self): 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 def check_ref_rate_detail(self): @@ -163,9 +170,9 @@ class DocType: 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) - # make product page - self.make_page() - + if self.doc.name: + self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name') + def check_non_asset_warehouse(self): if self.doc.is_asset_item == "Yes": existing_qty = sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name) @@ -218,35 +225,59 @@ Total Available Qty: %s def on_rename(self,newdn,olddn): sql("update tabItem set item_code = %s where name = %s", (newdn, olddn)) - def make_page(self): - 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'] - - \ No newline at end of file + # def make_page(self): + # 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 + + 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.show_in_website == 'Yes': + website.web_cache.clear_web_cache(self.doc.doctype, self.doc.name, self.doc.page_name) + else: + website.web_cache.delete_web_cache(self.doc.page_name) + + def update_page_name(self): + 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) + + # no need to check for uniqueness, as name is unique + + def get_html(self): + import markdown2 + self.doc.web_description_html = markdown2.markdown(self.doc.description or '', + extras=["wiki-tables"]) + + \ No newline at end of file diff --git a/erpnext/website/doctype/website_settings/website_settings.py b/erpnext/website/doctype/website_settings/website_settings.py index 9390e740b8..aec5a39188 100644 --- a/erpnext/website/doctype/website_settings/website_settings.py +++ b/erpnext/website/doctype/website_settings/website_settings.py @@ -54,8 +54,13 @@ class DocType: from webnotes.cms.make import make_web_core make_web_core() - get_obj('Page', 'blog').write_cms_page(force=True) - get_obj('Page', 'Login Page').write_cms_page(force=True) + import website.web_cache + 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') diff --git a/erpnext/website/templates/blog-old.html b/erpnext/website/templates/blog-old.html deleted file mode 100644 index d0b9a1362b..0000000000 --- a/erpnext/website/templates/blog-old.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "outer.html" %} - -{% block title %}{{ title }}{% endblock %} - - -{% block content %} -
-
-
-

Blog

-
-
- -
-
-
- -

Subscribe

-

- - RSS Feed -

-
-
-
-
- - \ No newline at end of file diff --git a/erpnext/website/templates/blog.html b/erpnext/website/templates/blog/blog.html similarity index 96% rename from erpnext/website/templates/blog.html rename to erpnext/website/templates/blog/blog.html index e188edf921..03a2ed7065 100644 --- a/erpnext/website/templates/blog.html +++ b/erpnext/website/templates/blog/blog.html @@ -1,4 +1,4 @@ -{% extends "blog.js" %} +{% extends "blog/blog.js" %} {% block content %}
diff --git a/erpnext/website/templates/blog.js b/erpnext/website/templates/blog/blog.js similarity index 100% rename from erpnext/website/templates/blog.js rename to erpnext/website/templates/blog/blog.js diff --git a/erpnext/website/templates/blog/blog_list.html b/erpnext/website/templates/blog/blog_list.html new file mode 100644 index 0000000000..242f814a9c --- /dev/null +++ b/erpnext/website/templates/blog/blog_list.html @@ -0,0 +1,43 @@ +{% extends "blog/blog_list.js" %} + +{% block title %}Blog{% endblock %} + +{% block css %} + +{% endblock %} + +{% block content %} +
+
+ +
+

Blog

+
+
+ +
+
+ +
+ +

Subscribe

+

+ + RSS Feed +

+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/blog/blog_list.js b/erpnext/website/templates/blog/blog_list.js new file mode 100644 index 0000000000..70628c1540 --- /dev/null +++ b/erpnext/website/templates/blog/blog_list.js @@ -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 . + +// 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('... (read on)', 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('

%(title)s

\ +

By %(first_name)s%(last_name)s, %(date)s

\ +

%(content)s


', data) + //Read Full Text
', data); + }, + page_length: 10 + }); + erpnext.blog_list.run(); +} + +{% endblock %} diff --git a/erpnext/website/templates/page.html b/erpnext/website/templates/page.html index a8e20f67f2..c6e0715232 100644 --- a/erpnext/website/templates/page.html +++ b/erpnext/website/templates/page.html @@ -24,9 +24,14 @@ }); {% endif %} + + {% block css %} {% if insert_style %} + + {% endif %} + {% endblock %} {% endblock %} {% block content %} diff --git a/erpnext/website/templates/product/product.html b/erpnext/website/templates/product/product.html new file mode 100644 index 0000000000..5a04e79d6b --- /dev/null +++ b/erpnext/website/templates/product/product.html @@ -0,0 +1,31 @@ +{% extends "product/product.js" %} + +{% block title %}{{ item_name }} [{{ name }}]{% endblock %} + +{% block content %} +
+
+
+

{{ item_name }}

+
+

+ +

+ {{ web_description_html }} + +
+
+
+

More Categories

+
+
+

Similar Products

+
+
+
+
+
+{% endblock %} diff --git a/erpnext/website/templates/product/product.js b/erpnext/website/templates/product/product.js new file mode 100644 index 0000000000..ee73e7f1ae --- /dev/null +++ b/erpnext/website/templates/product/product.js @@ -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 . + +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('
\ +
\ +
\ + %(item_name)s\ +

%(description)s

\ +
', data); + } + }); + wrapper.similar.run(); +} + +{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/product/product_list.html b/erpnext/website/templates/product/product_list.html new file mode 100644 index 0000000000..416a2fe702 --- /dev/null +++ b/erpnext/website/templates/product/product_list.html @@ -0,0 +1,23 @@ +{% extends "product/product_list.js" %} + +{% block title %}Products{% endblock %} + +{% block content %} +
+
+ +
+

+
+ +
+
+ +
+

Categories

+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/product/product_list.js b/erpnext/website/templates/product/product_list.js new file mode 100644 index 0000000000..82c788687d --- /dev/null +++ b/erpnext/website/templates/product/product_list.js @@ -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 . + +// 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('

%(item_name)s

\ +

%(description)s

', data); + }, + page_length: 10 + }); + erpnext.product_list.run(); +} + +{% endblock %} diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 30e3f0015d..c9f196dc5e 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -32,7 +32,7 @@ def load_from_web_cache(page_name, comments, template): where name = %s""", page_name) # 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 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 outer_env_dict = get_outer_env() - if page_name == '404': + if page_name in ['404', 'blog', 'products']: args = outer_env_dict + args.update({ + 'name': page_name, + }) else: if page_name == 'index': page_name, doc_type, doc_name = get_index_page() from webnotes.model.code import get_obj obj = get_obj(doc_type, doc_name) - obj.get_html() + if hasattr(obj, 'get_html'): + obj.get_html() args = obj.doc.fields args.update(outer_env_dict) + # decide template and update args if doc_type == 'Blog': - template = 'blog.html' - args['insert_code'] = 1 + template = 'blog/blog.html' + args.update({ 'insert_code': 1 }) + elif doc_type == 'Item': + template = 'product/product.html' + args.update({ 'insert_code': 1 }) elif doc_type == 'Web Page': 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) diff --git a/erpnext/website/web_page.py b/erpnext/website/web_page.py index 4d6f9f0b6b..58ff40b868 100644 --- a/erpnext/website/web_page.py +++ b/erpnext/website/web_page.py @@ -29,18 +29,14 @@ class Page(object): def validate(self): if self.doc.name: self.old_page_name = webnotes.conn.get_value(self.doctype, self.doc.name, 'page_name') - + def on_update(self): # page name updates with the title 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.doc.save(ignore_fields=1) + self.doc.save() def on_trash(self): """delete Web Cache entry""" @@ -63,6 +59,11 @@ class Page(object): if web cache entry doesn't exist, it creates one 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) def delete_web_cache(self, page_name): From bba4db1627e52946d86263ca5332bf450cb5c601 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 27 Jun 2012 12:06:45 +0530 Subject: [PATCH 08/26] product listing and pages --- erpnext/website/js/product_category.js | 8 +- .../website/templates/product/product.html | 2 + erpnext/website/templates/product/product.js | 34 ++++-- .../templates/product/product_category.js | 27 +++++ .../templates/product/product_list.html | 19 ++- .../website/templates/product/product_list.js | 114 +++++++++++++++--- erpnext/website/web_cache.py | 5 +- public/js/all-app.js | 3 +- public/js/all-web.js | 3 +- public/js/product_category.js | 7 +- public/web.py | 23 +++- 11 files changed, 201 insertions(+), 44 deletions(-) create mode 100644 erpnext/website/templates/product/product_category.js diff --git a/erpnext/website/js/product_category.js b/erpnext/website/js/product_category.js index 8d3f898883..bed4d2457a 100644 --- a/erpnext/website/js/product_category.js +++ b/erpnext/website/js/product_category.js @@ -18,7 +18,10 @@ erpnext.make_product_categories = function(wrapper) { wrapper.category_list = new wn.ui.Listing({ parent: $(wrapper).find('.more-categories').get(0), query: 'select count(name) as items, item_group \ - from tabItem where is_sales_item="Yes" \ + from tabItem \ + where is_sales_item="Yes" and \ + ifnull(show_in_website, "No")="Yes" and \ + docstatus = 0 \ group by item_group order by items desc', hide_refresh: true, render_row: function(parent, data) { @@ -26,5 +29,6 @@ erpnext.make_product_categories = function(wrapper) { data); } }); - wrapper.category_list.run(); + wrapper.category_list.run(); + console.log('product categories made'); } diff --git a/erpnext/website/templates/product/product.html b/erpnext/website/templates/product/product.html index 5a04e79d6b..5d3c3da980 100644 --- a/erpnext/website/templates/product/product.html +++ b/erpnext/website/templates/product/product.html @@ -9,9 +9,11 @@

{{ item_name }}



+ {% if website_image %}

+ {% endif %} {{ web_description_html }} +
+
-

Categories

+

Categories

diff --git a/erpnext/website/templates/product/product_list.js b/erpnext/website/templates/product/product_list.js index 82c788687d..5166fed639 100644 --- a/erpnext/website/templates/product/product_list.js +++ b/erpnext/website/templates/product/product_list.js @@ -1,6 +1,8 @@ -{% extends "page.html" %} +{% extends "product/product_category.js" %} {% block javascript %} +{{ super() }} + // ERPNext - web based ERP (http://erpnext.com) // Copyright (C) 2012 Web Notes Technologies Pvt Ltd // @@ -18,23 +20,103 @@ // along with this program. If not, see . // js inside blog page +wn.provide('erpnext.products'); + 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('

%(item_name)s

\ -

%(description)s

', data); - }, - page_length: 10 + erpnext.products.wrapper = wrapper; + + // make product categories in the sidebar + erpnext.products.make_product_categories(wrapper); + + // make lists + erpnext.products.make_product_list(wrapper); + + // erpnext.products.product_list.run(); + + // bind search button or enter key + $(wrapper).find('.products-search .btn').click(function() { + erpnext.products.product_list.run(); }); - erpnext.product_list.run(); + + $(wrapper).find('.products-search input').keypress(function(ev) { + if(ev.which==13) $(wrapper).find('.products-search .btn').click(); + }); +} + +erpnext.products.make_product_list = function(wrapper) { + if (!wrapper) { wrapper = erpnext.products.wrapper; } + if (!wrapper) { return; } + + erpnext.products.product_list = new wn.ui.Listing({ + parent: $(wrapper).find('#products-list').get(0), + run_btn: $(wrapper).find('.products-search .btn').get(0), + no_toolbar: true, + get_query: function() { + var srch = $('input[name="products-search"]').val() + var search_cond = 'and (description like "%%(srch)s%"\ + or item_name like "%%(srch)s%")'; + var product_group_cond = 'and item_group="%(group)s"'; + var cur_group = erpnext.products.cur_group + args = { + search_cond: srch ? repl(search_cond, {srch:srch}) : '', + cat: cur_group ? repl(product_group_cond, {group: cur_group}) : '', + }; + return repl('select name, item_name, website_image, \ + description, page_name \ + from tabItem \ + where is_sales_item="Yes" \ + %(cat)s \ + and docstatus = 0 and ifnull(show_in_website, "No")="Yes"\ + %(search_cond)s', args) + }, + render_row: function(parent, data) { + parent.innerHTML = repl('\ +
\ +
\ +

%(item_name)s

\ +

%(description)s

\ +
', data); + + if(data.website_image) { + $(parent).find('.img-area').append(repl( + '', data)) + } else { + $(parent).find('.img-area').append(wn.dom.placeholder(100, + data.item_name)); + } + } + }); +} + +wn.pages['{{ name }}'].onshow = function(wrapper) { + // show default product category + erpnext.products.set_group(); +} + +erpnext.products.set_group = function() { + var cat = erpnext.products.get_group(); + + // get erpnext.products.default_category + var wrapper = erpnext.products.wrapper; + + $(wrapper).find('h1').html(cat.label); + erpnext.products.product_list.run(); +} + +erpnext.products.get_group = function() { + route = wn.get_route(); + if(route && route.length>1) { + // from url + var grp = route[1]; + var label = route[1]; + erpnext.products.cur_group = grp; + } else { + // default + var grp = 'Products'; + var label = 'Products'; + erpnext.products.cur_group = null; + } + return {grp:grp, label:label}; } {% endblock %} diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index c9f196dc5e..42bd1d1111 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -15,7 +15,7 @@ # along with this program. If not, see . # used by web.py -def load_from_web_cache(page_name, comments, template): +def load_from_web_cache(page_name, comments, template): #, script=None): """ * search for page in cache * if html exists, return @@ -45,6 +45,9 @@ def load_from_web_cache(page_name, comments, template): from webnotes.utils import cstr html += """\n""" % cstr(comments) + + # show error in error console + # if script: html += """\n\n""" % cstr(script) return html def load_into_web_cache(page_name, template, doc_type, doc_name): diff --git a/public/js/all-app.js b/public/js/all-app.js index 026903bf41..30b3c96be6 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -252,8 +252,7 @@ wn.re_route={} wn.route=function(){if(wn.re_route[window.location.hash]){var re_route_val=wn.get_route_str(wn.re_route[window.location.hash]);var cur_route_val=wn.get_route_str(wn._cur_route);if(decodeURIComponent(re_route_val)===decodeURIComponent(cur_route_val)){window.history.back();return;}else{window.location.hash=wn.re_route[window.location.hash];}} wn._cur_route=window.location.hash;route=wn.get_route();switch(route[0]){case"List":wn.views.doclistview.show(route[1]);break;case"Form":if(route.length>3){route[2]=route.splice(2).join('/');} wn.views.formview.show(route[1],route[2]);break;case"Report":wn.views.reportview.show(route[1],route[2]);break;case"Report2":wn.views.reportview2.show();break;default:wn.views.pageview.show(route[0]);}} -wn.get_route=function(route){if(!wn.boot){return[window.page_name];} -return $.map(wn.get_route_str(route).split('/'),function(r){return decodeURIComponent(r);});} +wn.get_route=function(route){return $.map(wn.get_route_str(route).split('/'),function(r){return decodeURIComponent(r);});} wn.get_route_str=function(route){if(!route) route=window.location.hash;if(route.substr(0,1)=='#')route=route.substr(1);if(route.substr(0,1)=='!')route=route.substr(1);return route;} wn.set_route=function(){route=$.map(arguments,function(a){return encodeURIComponent(a)}).join('/');window.location.hash=route;wn.app.set_favicon();} diff --git a/public/js/all-web.js b/public/js/all-web.js index 9712ff6d14..b3ab4ed94f 100644 --- a/public/js/all-web.js +++ b/public/js/all-web.js @@ -139,8 +139,7 @@ wn.re_route={} wn.route=function(){if(wn.re_route[window.location.hash]){var re_route_val=wn.get_route_str(wn.re_route[window.location.hash]);var cur_route_val=wn.get_route_str(wn._cur_route);if(decodeURIComponent(re_route_val)===decodeURIComponent(cur_route_val)){window.history.back();return;}else{window.location.hash=wn.re_route[window.location.hash];}} wn._cur_route=window.location.hash;route=wn.get_route();switch(route[0]){case"List":wn.views.doclistview.show(route[1]);break;case"Form":if(route.length>3){route[2]=route.splice(2).join('/');} wn.views.formview.show(route[1],route[2]);break;case"Report":wn.views.reportview.show(route[1],route[2]);break;case"Report2":wn.views.reportview2.show();break;default:wn.views.pageview.show(route[0]);}} -wn.get_route=function(route){if(!wn.boot){return[window.page_name];} -return $.map(wn.get_route_str(route).split('/'),function(r){return decodeURIComponent(r);});} +wn.get_route=function(route){return $.map(wn.get_route_str(route).split('/'),function(r){return decodeURIComponent(r);});} wn.get_route_str=function(route){if(!route) route=window.location.hash;if(route.substr(0,1)=='#')route=route.substr(1);if(route.substr(0,1)=='!')route=route.substr(1);return route;} wn.set_route=function(){route=$.map(arguments,function(a){return encodeURIComponent(a)}).join('/');window.location.hash=route;wn.app.set_favicon();} diff --git a/public/js/product_category.js b/public/js/product_category.js index aac872f16d..da50d78ac9 100644 --- a/public/js/product_category.js +++ b/public/js/product_category.js @@ -3,5 +3,8 @@ * erpnext/website/js/product_category.js */ erpnext.make_product_categories=function(wrapper){wrapper.category_list=new wn.ui.Listing({parent:$(wrapper).find('.more-categories').get(0),query:'select count(name) as items, item_group \ - from tabItem where is_sales_item="Yes" \ - group by item_group order by items desc',hide_refresh:true,render_row:function(parent,data){parent.innerHTML=repl('%(item_group)s (%(items)s)',data);}});wrapper.category_list.run();} \ No newline at end of file + from tabItem \ + where is_sales_item="Yes" and \ + ifnull(show_in_website, "No")="Yes" and \ + docstatus = 0 \ + group by item_group order by items desc',hide_refresh:true,render_row:function(parent,data){parent.innerHTML=repl('%(item_group)s (%(items)s)',data);}});wrapper.category_list.run();console.log('product categories made');} \ No newline at end of file diff --git a/public/web.py b/public/web.py index 6f3569e327..e70b61cd55 100755 --- a/public/web.py +++ b/public/web.py @@ -48,13 +48,26 @@ def get_html(page_name): page_name = scrub_page_name(page_name) if page_name == '404': - comments = """error: %s""" % webnotes.getTraceback() - template = '404.html' + traceback = webnotes.getTraceback() + + # script is used to display traceback in error console + args = { + 'comments': """error: %s""" % traceback, + 'template': '404.html', + } + # 'script': """(function() { + # var error = "ERROR: %s"; + # console.log(error); + # })();""" % traceback.replace('"', '\\"').replace('\n', ' \\\n'), + # } + else: - comments = """page: %s""" % page_name - template = 'page.html' + args = { + 'comments': """page: %s""" % page_name, + 'template': 'page.html', + } - html = website.web_cache.load_from_web_cache(page_name, comments, template) + html = website.web_cache.load_from_web_cache(page_name, **args) return html From e47def842db5f4ae49218a2ab34ea3f0a81ac21a Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 9 Jul 2012 15:56:12 +0530 Subject: [PATCH 09/26] Improvements in product page and its listing Login page rendered via a template --- build.json | 3 - erpnext/patches/june_2012/cms2.py | 6 + erpnext/stock/doctype/item/item.js | 15 ++ erpnext/stock/doctype/item/item.py | 45 +--- erpnext/stock/doctype/item/item.txt | 227 ++++++++++-------- erpnext/stock/doctype/item/product_page.js | 63 ----- erpnext/stock/doctype/item/template.html | 25 -- erpnext/website/product.py | 97 ++++++++ erpnext/website/templates/login/login.html | 53 ++++ erpnext/website/templates/login/login.js | 103 ++++++++ .../website/templates/product/product.html | 60 ++++- erpnext/website/templates/product/product.js | 70 +++--- .../templates/product/product_category.js | 7 +- .../templates/product/product_list.html | 27 ++- .../website/templates/product/product_list.js | 34 +-- erpnext/website/web_cache.py | 17 +- public/js/product_category.js | 10 - 17 files changed, 540 insertions(+), 322 deletions(-) delete mode 100644 erpnext/stock/doctype/item/product_page.js delete mode 100644 erpnext/stock/doctype/item/template.html create mode 100644 erpnext/website/product.py create mode 100644 erpnext/website/templates/login/login.html create mode 100644 erpnext/website/templates/login/login.js delete mode 100644 public/js/product_category.js diff --git a/build.json b/build.json index 7b1dfe6f3b..6efbbc3095 100644 --- a/build.json +++ b/build.json @@ -23,7 +23,4 @@ "public/js/complete_setup.js": [ "erpnext/startup/js/complete_setup.js", ], - "public/js/product_category.js": [ - "erpnext/website/js/product_category.js", - ], } \ No newline at end of file diff --git a/erpnext/patches/june_2012/cms2.py b/erpnext/patches/june_2012/cms2.py index 48f0152985..08174cbb8b 100644 --- a/erpnext/patches/june_2012/cms2.py +++ b/erpnext/patches/june_2012/cms2.py @@ -18,6 +18,12 @@ def cleanup(): delete from `tabPage` where module='Website' and ifnull(web_page, 'No') = 'Yes'""") + # change show_in_website value in item table to 0 or 1 + webnotes.conn.sql("""\ + update `tabItem` + set show_in_website = if(show_in_website = 'Yes', 1, 0) + where show_in_website is not null""") + def save_pages(): """save all web pages, blogs to create content""" import webnotes diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 65698c1f87..572a790264 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -29,8 +29,23 @@ cur_frm.cscript.refresh = function(doc) { } $c_obj(make_doclist(doc.doctype, doc.name),'check_if_sle_exists','',callback); } + + cur_frm.cscript.hide_website_fields(doc); } +cur_frm.cscript.hide_website_fields = function(doc) { + var website_fields_list = ['page_name', 'website_image', 'web_short_description', + 'web_long_description'] + if (cint(doc.show_in_website)) { + unhide_field(website_fields_list); + } else { + hide_field(website_fields_list); + } +} + +cur_frm.cscript.show_in_website = function(doc, dt, dn) { + cur_frm.cscript.hide_website_fields(doc); +} cur_frm.fields_dict['default_bom'].get_query = function(doc) { //var d = locals[this.doctype][this.docname]; diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 85af0bb73e..b2c92352d9 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -225,37 +225,6 @@ Total Available Qty: %s def on_rename(self,newdn,olddn): sql("update tabItem set item_code = %s where name = %s", (newdn, olddn)) - # def make_page(self): - # 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 @@ -263,14 +232,22 @@ Total Available Qty: %s self.doc.page_name != self.old_page_name: website.web_cache.delete_web_cache(self.old_page_name) - if self.doc.show_in_website == 'Yes': + if self.doc.show_in_website: website.web_cache.clear_web_cache(self.doc.doctype, self.doc.name, self.doc.page_name) else: website.web_cache.delete_web_cache(self.doc.page_name) def update_page_name(self): import website.utils - self.doc.page_name = website.utils.page_name(self.doc.name + " " + self.doc.item_name) + + # if same name, do not repeat twice + if self.doc.name == self.doc.item_name: + page_name = self.doc.name + else: + page_name = self.doc.name + " " + self.doc.item_name + + self.doc.page_name = website.utils.page_name(page_name) + webnotes.conn.set_value('Item', self.doc.name, 'page_name', self.doc.page_name) # no need to check for uniqueness, as name is unique @@ -279,5 +256,3 @@ Total Available Qty: %s import markdown2 self.doc.web_description_html = markdown2.markdown(self.doc.description or '', extras=["wiki-tables"]) - - \ No newline at end of file diff --git a/erpnext/stock/doctype/item/item.txt b/erpnext/stock/doctype/item/item.txt index 8a079b815d..06806bac04 100644 --- a/erpnext/stock/doctype/item/item.txt +++ b/erpnext/stock/doctype/item/item.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-04-30 18:33:53', + 'creation': '2012-06-08 12:54:51', 'docstatus': 0, - 'modified': '2012-06-07 16:16:24', + 'modified': '2012-07-04 11:10:29', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -57,73 +57,6 @@ 'name': u'Item' }, - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'Material Manager', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Material Manager', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'Material User', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Material User', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'cancel': 1, - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Material Master Manager', - 'write': 1 - }, - - # DocPerm - { - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'Material Master Manager', - 'write': 0 - }, - # DocPerm { 'cancel': 1, @@ -134,6 +67,25 @@ 'write': 1 }, + # DocPerm + { + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Material Master Manager', + 'write': 0 + }, + + # DocPerm + { + 'cancel': 1, + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Material Master Manager', + 'write': 1 + }, + # DocPerm { 'doctype': u'DocPerm', @@ -141,6 +93,54 @@ 'role': u'System Manager' }, + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Material Manager', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Material Manager', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Material User', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Material User', + 'submit': 0, + 'write': 0 + }, + # DocField { 'doctype': u'DocField', @@ -731,26 +731,6 @@ 'reqd': 1 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'show_in_website', - 'fieldtype': u'Select', - 'label': u'Show in Website', - 'options': u'No\nYes', - 'permlevel': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'website_image', - 'fieldtype': u'Select', - 'label': u'website_image', - 'options': u'attach_files:', - 'permlevel': 0 - }, - # DocField { 'doctype': u'DocField', @@ -794,17 +774,6 @@ 'permlevel': 0 }, - # DocField - { - 'colour': u'White:FFF', - 'description': u'website page link', - 'doctype': u'DocField', - 'fieldname': u'page_name', - 'fieldtype': u'Data', - 'label': u'Page Name', - 'permlevel': 1 - }, - # DocField { 'doctype': u'DocField', @@ -994,5 +963,63 @@ 'no_copy': 1, 'permlevel': 0, 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'website_section', + 'fieldtype': u'Section Break', + 'label': u'Website', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'show_in_website', + 'fieldtype': u'Check', + 'label': u'Show in Website', + 'permlevel': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'website page link', + 'doctype': u'DocField', + 'fieldname': u'page_name', + 'fieldtype': u'Data', + 'label': u'Page Name', + 'permlevel': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'website_image', + 'fieldtype': u'Select', + 'label': u'Image', + 'options': u'attach_files:', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'web_short_description', + 'fieldtype': u'Text', + 'label': u'Short Description', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'web_long_description', + 'fieldtype': u'Code', + 'label': u'Long Description', + 'options': u'Markdown', + 'permlevel': 0 } ] \ No newline at end of file diff --git a/erpnext/stock/doctype/item/product_page.js b/erpnext/stock/doctype/item/product_page.js deleted file mode 100644 index 926ef69f87..0000000000 --- a/erpnext/stock/doctype/item/product_page.js +++ /dev/null @@ -1,63 +0,0 @@ -// 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 . - -wn.require('erpnext/website/js/product_category.js'); - -pscript["onload_{{ doc.page_name }}"] = function(wrapper) { - wrapper.product_group = "{{ doc.item_group }}"; - wrapper.product_name = "{{ doc.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 {{ doc.title }} (Item Code:{{ doc.item }})\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 t1.name, t1.title, t1.thumbnail_image, \ - t1.page_name, t1.short_description \ - from tabProduct t1, tabItem t2 \ - where t1.item = t2.name \ - and ifnull(t1.published,0)=1 \ - and t1.name != "%(name)s" \ - and t2.item_group="%(cat)s" order by t1.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('
\ -
\ -
\ - %(title)s\ -

%(short_description)s

\ -
', data); - } - }); - wrapper.similar.run(); -} \ No newline at end of file diff --git a/erpnext/stock/doctype/item/template.html b/erpnext/stock/doctype/item/template.html deleted file mode 100644 index 8a2f4a9731..0000000000 --- a/erpnext/stock/doctype/item/template.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-
-

{{ doc.item_name }}

-
-

- -

- {{ doc.long_description_html }} - -
-
-
-

More Categories

-
-
-

Similar Products

-
-
-
-
-
\ No newline at end of file diff --git a/erpnext/website/product.py b/erpnext/website/product.py new file mode 100644 index 0000000000..7c6603af7b --- /dev/null +++ b/erpnext/website/product.py @@ -0,0 +1,97 @@ +import webnotes + +@webnotes.whitelist(allow_guest=True) +def get_product_list(args=None): + """ + args = { + 'limit_start': 0, + 'limit_page_length': 20, + 'search': '', + 'product_group': '', + } + """ + import webnotes + from webnotes.utils import cstr, cint + + if not args: args = webnotes.form_dict + + # dict to be passed to sql function + query_args = { + 'limit_start': cint(args.get('limit_start')), + 'limit_page_length': cint(args.get('limit_page_length')) + } + + # base query + query = """\ + select name, item_name, page_name, website_image, + description, web_short_description + from `tabItem` + where is_sales_item = 'Yes' + and docstatus = 0 + and show_in_website = 1""" + + # search term condition + if args.get('search'): + query += """ + and ( + web_short_description like %(search)s or + web_long_description like %(search)s or + description like %(search)s or + item_name like %(search)s or + name like %(search)s + )""" + query_args['search'] = "%" + cstr(args.get('search')) + "%" + + # product group condition + if args.get('product_group') and args.get('product_group') != 'All Products': + query += """ + and item_group = %(product_group)s""" + query_args['product_group'] = args.get('product_group') + + # order by + query += """ + order by item_name asc, name asc""" + + if args.get('limit_page_length'): + query += """ + limit %(limit_start)s, %(limit_page_length)s""" + + return webnotes.conn.sql(query, query_args, as_dict=1) + +@webnotes.whitelist(allow_guest=True) +def get_product_category_list(): + import webnotes + + result = webnotes.conn.sql("""\ + select count(name) as items, item_group + from `tabItem` + where is_sales_item = 'Yes' + and docstatus = 0 + and show_in_website = 1 + group by item_group + order by items desc""", as_dict=1) + + # add All Products link + total_count = sum((r.get('items') or 0 for r in result)) + result = [{'items': total_count, 'item_group': 'All Products'}] + (result or []) + + return result + +@webnotes.whitelist(allow_guest=True) +def get_similar_product_list(args=None): + import webnotes + + if not args: args = webnotes.form_dict + + result = webnotes.conn.sql("""\ + select name, item_name, page_name, website_image, + description, web_short_description + from `tabItem` + where is_sales_item = 'Yes' + and docstatus = 0 + and show_in_website = 1 + and name != %(product_name)s + and item_group = %(product_group)s + order by item_name""", args, as_dict=1) + + return result \ No newline at end of file diff --git a/erpnext/website/templates/login/login.html b/erpnext/website/templates/login/login.html new file mode 100644 index 0000000000..834fc27067 --- /dev/null +++ b/erpnext/website/templates/login/login.html @@ -0,0 +1,53 @@ +{% extends "login/login.js" %} + +{% block css %} + +{% endblock %} + +{% block content %} +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Login Id
Password
Remember Me
  
  + +
+
+

Forgot Password

+
+
+ +{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/login/login.js b/erpnext/website/templates/login/login.js new file mode 100644 index 0000000000..d6b6b24147 --- /dev/null +++ b/erpnext/website/templates/login/login.js @@ -0,0 +1,103 @@ +{% extends "page.html" %} + +{% block javascript %} +{{ super() }} +// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com) +// +// MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +wn.provide('erpnext.login'); + +wn.pages["{{ name }}"].onload = function(wrapper) { + wrapper.appframe = new wn.ui.AppFrame($(wrapper).find('.appframe-area')); + wrapper.appframe.title('Login'); + wrapper.appframe.$w.find('.close').toggle(false); + + var lw = $i('login_wrapper'); + $bs(lw, '1px 1px 3px #888'); + + $('#login_btn').click(erpnext.login.doLogin) + + $('#password').keypress(function(ev){ + if(ev.which==13 && $('#password').val()) { + $('form').submit(function() { + erpnext.login.doLogin(); + return false; + }); + } + }); + $(document).trigger('login_rendered'); +} + +// Login Callback +erpnext.login.onLoginReply = function(r, rtext) { + $('#login_btn').done_working(); + if(r.message=="Logged In"){ + window.location.href='app.html' + (get_url_arg('page') ? ('?page='+get_url_arg('page')) : ''); + } else { + $i('login_message').innerHTML = ''+(r.message)+''; + //if(r.exc)alert(r.exc); + } +} + + +// Login +erpnext.login.doLogin = function(){ + + var args = {}; + args['usr']=$i("login_id").value; + args['pwd']=$i("password").value; + if($i('remember_me').checked) + args['remember_me'] = 1; + + $('#login_btn').set_working(); + + $c("login", args, erpnext.login.onLoginReply); + + return false; +} + + +erpnext.login.show_forgot_password = function(){ + // create dialog + var d = new wn.ui.Dialog({ + title:"Forgot Password", + fields: [ + {'label':'Email Id', 'fieldname':'email_id', 'fieldtype':'Data', 'reqd':true}, + {'label':'Email Me A New Password', 'fieldname':'run', 'fieldtype':'Button'} + ] + }); + + $(d.fields_dict.run.input).click(function() { + var values = d.get_values(); + if(!values) return; + wn.call({ + method:'reset_password', + args: { user: values.email_id }, + callback: function() { + d.hide(); + } + }) + }) + d.show(); +} + +{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/product/product.html b/erpnext/website/templates/product/product.html index 5d3c3da980..6f33ec9508 100644 --- a/erpnext/website/templates/product/product.html +++ b/erpnext/website/templates/product/product.html @@ -1,23 +1,30 @@ {% extends "product/product.js" %} -{% block title %}{{ item_name }} [{{ name }}]{% endblock %} +{% block title %} + {% if item_name != name %} + {{ item_name }} [{{ name }}] + {% else %} + {{ item_name }} + {% endif %} +{% endblock %} {% block content %}

{{ item_name }}

-
+


{% if website_image %} - -

+ + {% else %} +
+ This is an auto-generated Image {% endif %} +

+
{{ web_description_html }} - +
@@ -31,3 +38,40 @@
{% endblock %} + +{% block css %} + +{% endblock %} diff --git a/erpnext/website/templates/product/product.js b/erpnext/website/templates/product/product.js index 3475204413..9e51334b8e 100644 --- a/erpnext/website/templates/product/product.js +++ b/erpnext/website/templates/product/product.js @@ -22,52 +22,60 @@ wn.pages['{{ name }}'].onload = function(wrapper) { wrapper.product_group = "{{ item_group }}"; wrapper.product_name = "{{ name }}"; erpnext.products.make_product_categories(wrapper); + erpnext.products.make_similar_products(wrapper); + + // if website image missing, autogenerate one + var $img = $('.product-page-content').find('.img-area'); + if ($img && $img.length > 0) { + $img.append(wn.dom.placeholder(160, "{{ item_name }}")); + } - // TODO make this working - $(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!\ - "); - }) - }); + // adjust page height based on sidebar height + var $main_page = $('.layout-main-section'); + var $sidebar = $('.layout-side-section'); + if ($sidebar.height() > $main_page.height()) { + $main_page.height($sidebar.height()); + } + +} + +erpnext.products.make_similar_products = function(wrapper) { + if (!wrapper) { wrapper = erpnext.products.wrapper; } + if (!wrapper) { return; } // 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 - }; - var query = repl('select name, item_name, website_image, \ - page_name, description \ - from tabItem \ - where is_sales_item="Yes" \ - and ifnull(show_in_website, "No")="Yes" \ - and name != "%(name)s" and docstatus = 0 \ - and item_group="%(cat)s" order by modified desc', args) - return query + method: 'website.product.get_similar_product_list', + get_args: function() { + return { + product_group: wrapper.product_group, + product_name: wrapper.product_name + } }, render_row: function(parent, data) { - if(data.description.length > 100) { - data.description = data.description.substr(0,100) + '...'; + if (!data.web_short_description) { + data.web_short_description = data.description; + } + if(data.web_short_description.length > 100) { + data.web_short_description = + data.web_short_description.substr(0,100) + '...'; } parent.innerHTML = repl('\ -
\ -
\ - %(item_name)s\ -

%(description)s

\ -
', data); +
\ +
\ +
%(item_name)s
\ + %(web_short_description)s\ +
\ +
', data); if(data.website_image) { $(parent).find('.img-area').append(repl( - '', data)) + '', data)) } else { - $(parent).find('.img-area').append(wn.dom.placeholder(50, + $(parent).find('.img-area').append(wn.dom.placeholder(55, data.item_name)); } } diff --git a/erpnext/website/templates/product/product_category.js b/erpnext/website/templates/product/product_category.js index d8b09b3df2..e1905ac95a 100644 --- a/erpnext/website/templates/product/product_category.js +++ b/erpnext/website/templates/product/product_category.js @@ -8,12 +8,7 @@ erpnext.products.make_product_categories = function(wrapper) { wrapper.category_list = new wn.ui.Listing({ parent: $(wrapper).find('.more-categories').get(0), - query: 'select count(name) as items, item_group \ - from tabItem \ - where is_sales_item="Yes" and \ - ifnull(show_in_website, "No")="Yes" and \ - docstatus = 0 \ - group by item_group order by items desc', + method: 'website.product.get_product_category_list', hide_refresh: true, render_row: function(parent, data) { parent.innerHTML = repl( diff --git a/erpnext/website/templates/product/product_list.html b/erpnext/website/templates/product/product_list.html index 100bfca423..24d559075c 100644 --- a/erpnext/website/templates/product/product_list.html +++ b/erpnext/website/templates/product/product_list.html @@ -2,17 +2,6 @@ {% block title %}Products{% endblock %} -{% block css %} - -{% endblock %} - - {% block content %}
@@ -29,10 +18,24 @@
-

Categories

+

Categories

+{% endblock %} + +{% block css %} + {% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/product/product_list.js b/erpnext/website/templates/product/product_list.js index 5166fed639..1c6f934e80 100644 --- a/erpnext/website/templates/product/product_list.js +++ b/erpnext/website/templates/product/product_list.js @@ -31,8 +31,6 @@ wn.pages['{{ name }}'].onload = function(wrapper) { // make lists erpnext.products.make_product_list(wrapper); - // erpnext.products.product_list.run(); - // bind search button or enter key $(wrapper).find('.products-search .btn').click(function() { erpnext.products.product_list.run(); @@ -51,30 +49,22 @@ erpnext.products.make_product_list = function(wrapper) { parent: $(wrapper).find('#products-list').get(0), run_btn: $(wrapper).find('.products-search .btn').get(0), no_toolbar: true, - get_query: function() { - var srch = $('input[name="products-search"]').val() - var search_cond = 'and (description like "%%(srch)s%"\ - or item_name like "%%(srch)s%")'; - var product_group_cond = 'and item_group="%(group)s"'; - var cur_group = erpnext.products.cur_group - args = { - search_cond: srch ? repl(search_cond, {srch:srch}) : '', - cat: cur_group ? repl(product_group_cond, {group: cur_group}) : '', + method: 'website.product.get_product_list', + get_args: function() { + return { + search: $('input[name="products-search"]').val() || '', + product_group: erpnext.products.cur_group || '', }; - return repl('select name, item_name, website_image, \ - description, page_name \ - from tabItem \ - where is_sales_item="Yes" \ - %(cat)s \ - and docstatus = 0 and ifnull(show_in_website, "No")="Yes"\ - %(search_cond)s', args) }, render_row: function(parent, data) { + if (!data.web_short_description) { + data.web_short_description = data.description; + } parent.innerHTML = repl('\ -
\ -
\ -

%(item_name)s

\ -

%(description)s

\ +
\ +
\ +

%(item_name)s

\ +

%(web_short_description)s

\
', data); if(data.website_image) { diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 42bd1d1111..dbed844aa7 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -32,7 +32,8 @@ def load_from_web_cache(page_name, comments, template): #, script=None): where name = %s""", page_name) # if page doesn't exist, raise exception - if not res and page_name not in ['404', 'index', 'blog', 'products']: + page_exception_list = ['404', 'index', 'blog', 'products', 'login-page'] + if not res and page_name not in page_exception_list: raise Exception, "Page %s not found" % page_name html, doc_type, doc_name = res and res[0] or (None, None, None) @@ -55,7 +56,7 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): import webnotes outer_env_dict = get_outer_env() - if page_name in ['404', 'blog', 'products']: + if page_name in ['404', 'blog', 'products', 'login-page']: args = outer_env_dict args.update({ 'name': page_name, @@ -80,12 +81,14 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): args.update({ 'insert_code': 1 }) elif doc_type == 'Web Page': 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' + else: args.update({ 'insert_code': 1 }) + if page_name == 'blog': + template = 'blog/blog_list.html' + elif page_name == 'products': + template = 'product/product_list.html' + elif page_name == 'login-page': + template = 'login/login.html' html = build_html(args, template) diff --git a/public/js/product_category.js b/public/js/product_category.js deleted file mode 100644 index da50d78ac9..0000000000 --- a/public/js/product_category.js +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * erpnext/website/js/product_category.js - */ -erpnext.make_product_categories=function(wrapper){wrapper.category_list=new wn.ui.Listing({parent:$(wrapper).find('.more-categories').get(0),query:'select count(name) as items, item_group \ - from tabItem \ - where is_sales_item="Yes" and \ - ifnull(show_in_website, "No")="Yes" and \ - docstatus = 0 \ - group by item_group order by items desc',hide_refresh:true,render_row:function(parent,data){parent.innerHTML=repl('%(item_group)s (%(items)s)',data);}});wrapper.category_list.run();console.log('product categories made');} \ No newline at end of file From 40fce896319e205536e7bdcd37c0cc534735053d Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 9 Jul 2012 20:02:52 +0530 Subject: [PATCH 10/26] Favicon for website Started work on comments to be embedded in blog page --- erpnext/patches/june_2012/cms2.py | 7 ++ erpnext/website/doctype/blog/blog.py | 13 +- .../website_settings/website_settings.txt | 38 ++++-- erpnext/website/templates/base.html | 11 +- erpnext/website/templates/blog/blog.html | 36 +++++- erpnext/website/templates/blog/blog.js | 112 ++++++++++-------- erpnext/website/templates/login/login.html | 26 ++-- erpnext/website/templates/product/product.js | 18 ++- .../templates/product/product_list.html | 4 +- erpnext/website/web_cache.py | 15 ++- 10 files changed, 190 insertions(+), 90 deletions(-) diff --git a/erpnext/patches/june_2012/cms2.py b/erpnext/patches/june_2012/cms2.py index 08174cbb8b..fe4774e870 100644 --- a/erpnext/patches/june_2012/cms2.py +++ b/erpnext/patches/june_2012/cms2.py @@ -23,6 +23,13 @@ def cleanup(): update `tabItem` set show_in_website = if(show_in_website = 'Yes', 1, 0) where show_in_website is not null""") + + # move comments from comment_doctype Page to Blog + webnotes.conn.sql("""\ + update `tabComment` comm, `tabBlog` blog + set comm.comment_doctype = 'Blog', comm.comment_docname = blog.name + where comm.comment_docname = blog.page_name""") + def save_pages(): """save all web pages, blogs to create content""" diff --git a/erpnext/website/doctype/blog/blog.py b/erpnext/website/doctype/blog/blog.py index 0e8acac196..89a06d4b0b 100644 --- a/erpnext/website/doctype/blog/blog.py +++ b/erpnext/website/doctype/blog/blog.py @@ -35,6 +35,8 @@ class DocType(website.web_page.Page): self.delete_web_cache(self.doc.page_name) def get_html(self): + import webnotes.utils + # this is for double precaution. usually it wont reach this code if not published if not webnotes.utils.cint(self.doc.published): raise Exception, "This blog has not been published yet!" @@ -44,4 +46,13 @@ class DocType(website.web_page.Page): self.doc.full_name = get_fullname(self.doc.owner) self.doc.updated = global_date_format(self.doc.modified) - self.markdown_to_html(['content']) \ No newline at end of file + self.markdown_to_html(['content']) + + comment_list = webnotes.conn.sql("""\ + select comment, comment_by_fullname, creation + from `tabComment` where comment_doctype="Blog" + and comment_docname=%s order by creation""", self.doc.name, as_dict=1) + + self.doc.comment_list = comment_list or [] + for comment in self.doc.comment_list: + comment['comment_date'] = webnotes.utils.pretty_date(comment['creation']) \ No newline at end of file diff --git a/erpnext/website/doctype/website_settings/website_settings.txt b/erpnext/website/doctype/website_settings/website_settings.txt index 368f963c24..3ae0fbe244 100644 --- a/erpnext/website/doctype/website_settings/website_settings.txt +++ b/erpnext/website/doctype/website_settings/website_settings.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-05-03 18:43:46', + 'creation': '2012-05-21 15:54:09', 'docstatus': 0, - 'modified': '2012-05-21 14:59:25', + 'modified': '2012-07-09 16:20:58', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -18,7 +18,7 @@ 'doctype': 'DocType', 'document_type': u'Other', 'issingle': 1, - 'max_attachments': 1, + 'max_attachments': 10, 'module': u'Website', 'name': '__common__', 'section_style': u'Simple', @@ -180,21 +180,21 @@ # DocField { 'doctype': u'DocField', - 'fieldname': u'file_list', - 'fieldtype': u'Text', - 'hidden': 1, - 'label': u'File List', - 'no_copy': 1, - 'permlevel': 0, - 'print_hide': 1 + 'fieldname': u'misc_section', + 'fieldtype': u'Section Break', + 'label': u'Misc', + 'permlevel': 0 }, # DocField { + 'colour': u'White:FFF', + 'description': u'An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org]', 'doctype': u'DocField', - 'fieldname': u'domains', - 'fieldtype': u'Section Break', - 'label': u'Domains', + 'fieldname': u'favicon', + 'fieldtype': u'Select', + 'label': u'FavIcon', + 'options': u'attach_files:', 'permlevel': 0 }, @@ -221,6 +221,18 @@ 'reqd': 0 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'file_list', + 'fieldtype': u'Text', + 'hidden': 1, + 'label': u'File List', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1 + }, + # DocField { 'doctype': u'DocField', diff --git a/erpnext/website/templates/base.html b/erpnext/website/templates/base.html index cd64139b82..8639a8f546 100644 --- a/erpnext/website/templates/base.html +++ b/erpnext/website/templates/base.html @@ -3,14 +3,21 @@ {% block title %}{% endblock %} - - + {% if favicon %} + + + {% else %} + + + {% endif %} + + {% block header %} {% endblock %} diff --git a/erpnext/website/templates/blog/blog.html b/erpnext/website/templates/blog/blog.html index 03a2ed7065..9132e52be7 100644 --- a/erpnext/website/templates/blog/blog.html +++ b/erpnext/website/templates/blog/blog.html @@ -11,21 +11,51 @@ {{ content_html }}

Comments


-
+
+ {% for comment in comment_list %} +
+
+ {{ comment.comment_by_fullname }} - {{ comment.comment_date }}: + {{ comment.comment_date_type }} +
+

{{ comment.comment }}

+
+
+ {% endfor %} +

All Blogs

-

Recent Posts

-
+

Subscribe

RSS Feed

+
+

Recent Posts

+
+{% endblock %} + +{% block css %} + + {% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/blog/blog.js b/erpnext/website/templates/blog/blog.js index 80cb813f95..3ad1575331 100644 --- a/erpnext/website/templates/blog/blog.js +++ b/erpnext/website/templates/blog/blog.js @@ -18,7 +18,10 @@ // along with this program. If not, see . // js inside blog page +wn.provide('erpnext.blog'); wn.pages['{{ name }}'].onload = function(wrapper) { + erpnext.blog.wrapper = wrapper; + // sidebar wrapper.recent_list = new wn.ui.Listing({ parent: $(wrapper).find('.recent-posts'), @@ -31,57 +34,72 @@ wn.pages['{{ name }}'].onload = function(wrapper) { if(data.content && data.content.length==100) data.content += '...'; parent.innerHTML = repl('%(title)s\
%(content)s

', data); + + // adjust page height depending on sidebar height + erpnext.blog.adjust_page_height(wrapper); }, page_length: 5, }); wrapper.recent_list.run(); - - wrapper.comment_list = new wn.ui.Listing({ - parent: $(wrapper).find('.blog-comments').get(0), - no_toolbar: true, - query: 'select comment, comment_by_fullname, creation\ - from `tabComment` where comment_doctype="Page"\ - and comment_docname="{{ name }}" order by creation desc', - no_result_message: 'Be the first one to comment', - render_row: function(parent, data) { - data.comment_date = prettyDate(data.creation); - $(parent).html(repl("
\ - %(comment_by_fullname)s | %(comment_date)s:\ -
\ -

%(comment)s


", data)) - }, - hide_refresh: true, - }); - wrapper.comment_list.run(); - - // add comment - $(wrapper).find('.layout-main-section').append('
'); - $(wrapper).find('button.add-comment').click(function(){ - d = new wn.widgets.Dialog({ - title: 'Add Comment', - fields: [ - {fieldname:'comment_by_fullname', label:'Your Name', reqd:1, fieldtype:'Data'}, - {fieldname:'comment_by', label:'Email Id', reqd:1, fieldtype:'Data'}, - {fieldname:'comment', label:'Comment', reqd:1, fieldtype:'Text'}, - {fieldname:'post', label:'Post', fieldtype:'Button'} - ] - }); - d.fields_dict.post.input.onclick = function() { - var btn = this; - var args = d.get_values(); - if(!args) return; - args.comment_doctype = 'Page'; - args.comment_docname = '{{ name }}'; - $(btn).set_working(); - $c('webnotes.widgets.form.comments.add_comment', args, function(r) { - $(btn).done_working(); - d.hide(); - wrapper.comment_list.refresh(); - }) - } - d.show(); - }) } +erpnext.blog.adjust_page_height = function(wrapper) { + if (!wrapper) { wrapper = erpnext.blog.wrapper; } + if (!wrapper) { return; } + + // adjust page height based on sidebar height + var $main_page = $(wrapper).find('.layout-main-section'); + var $sidebar = $(wrapper).find('.layout-side-section'); + if ($sidebar.height() > $main_page.height()) { + $main_page.height($sidebar.height()); + } +} + // wrapper.comment_list = new wn.ui.Listing({ + // parent: $(wrapper).find('.blog-comments').get(0), + // no_toolbar: true, + // query: 'select comment, comment_by_fullname, creation\ + // from `tabComment` where comment_doctype="Page"\ + // and comment_docname="{{ name }}" order by creation desc', + // no_result_message: 'Be the first one to comment', + // render_row: function(parent, data) { + // data.comment_date = prettyDate(data.creation); + // $(parent).html(repl("
\ + // %(comment_by_fullname)s | %(comment_date)s:\ + //
\ + //

%(comment)s


", data)) + // }, + // hide_refresh: true, + // }); + // wrapper.comment_list.run(); + // + // // add comment + // $(wrapper).find('.layout-main-section').append('
'); + // $(wrapper).find('button.add-comment').click(function(){ + // d = new wn.widgets.Dialog({ + // title: 'Add Comment', + // fields: [ + // {fieldname:'comment_by_fullname', label:'Your Name', reqd:1, fieldtype:'Data'}, + // {fieldname:'comment_by', label:'Email Id', reqd:1, fieldtype:'Data'}, + // {fieldname:'comment', label:'Comment', reqd:1, fieldtype:'Text'}, + // {fieldname:'post', label:'Post', fieldtype:'Button'} + // ] + // }); + // d.fields_dict.post.input.onclick = function() { + // var btn = this; + // var args = d.get_values(); + // if(!args) return; + // args.comment_doctype = 'Page'; + // args.comment_docname = '{{ name }}'; + // $(btn).set_working(); + // $c('webnotes.widgets.form.comments.add_comment', args, function(r) { + // $(btn).done_working(); + // d.hide(); + // wrapper.comment_list.refresh(); + // }) + // } + // d.show(); + // }) + + {% endblock %} diff --git a/erpnext/website/templates/login/login.html b/erpnext/website/templates/login/login.html index 834fc27067..62d252f5d2 100644 --- a/erpnext/website/templates/login/login.html +++ b/erpnext/website/templates/login/login.html @@ -1,16 +1,7 @@ {% extends "login/login.js" %} -{% block css %} - +{% block title %} + Login Page {% endblock %} {% block content %} @@ -50,4 +41,17 @@
+{% endblock %} + +{% block css %} + {% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/product/product.js b/erpnext/website/templates/product/product.js index 9e51334b8e..f7745d7b1f 100644 --- a/erpnext/website/templates/product/product.js +++ b/erpnext/website/templates/product/product.js @@ -25,18 +25,25 @@ wn.pages['{{ name }}'].onload = function(wrapper) { erpnext.products.make_similar_products(wrapper); // if website image missing, autogenerate one - var $img = $('.product-page-content').find('.img-area'); + var $img = $(wrapper).find('.product-page-content .img-area'); if ($img && $img.length > 0) { $img.append(wn.dom.placeholder(160, "{{ item_name }}")); } + erpnext.products.adjust_page_height(wrapper); + +} + +erpnext.products.adjust_page_height = function(wrapper) { + if (!wrapper) { wrapper = erpnext.products.wrapper; } + if (!wrapper) { return; } + // adjust page height based on sidebar height - var $main_page = $('.layout-main-section'); - var $sidebar = $('.layout-side-section'); + var $main_page = $(wrapper).find('.layout-main-section'); + var $sidebar = $(wrapper).find('.layout-side-section'); if ($sidebar.height() > $main_page.height()) { $main_page.height($sidebar.height()); } - } erpnext.products.make_similar_products = function(wrapper) { @@ -78,6 +85,9 @@ erpnext.products.make_similar_products = function(wrapper) { $(parent).find('.img-area').append(wn.dom.placeholder(55, data.item_name)); } + + // adjust page height, if sidebar height keeps increasing + erpnext.products.adjust_page_height(wrapper); } }); wrapper.similar.run(); diff --git a/erpnext/website/templates/product/product_list.html b/erpnext/website/templates/product/product_list.html index 24d559075c..c8dfd24ed0 100644 --- a/erpnext/website/templates/product/product_list.html +++ b/erpnext/website/templates/product/product_list.html @@ -1,6 +1,8 @@ {% extends "product/product_list.js" %} -{% block title %}Products{% endblock %} +{% block title %} + Products +{% endblock %} {% block content %}
diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index dbed844aa7..5fcae82bc3 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -73,17 +73,15 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): args.update(outer_env_dict) # decide template and update args - if doc_type == 'Blog': - template = 'blog/blog.html' - args.update({ 'insert_code': 1 }) - elif doc_type == 'Item': - template = 'product/product.html' - args.update({ 'insert_code': 1 }) - elif doc_type == 'Web Page': + if doc_type == 'Web Page': template = 'web_page.html' else: args.update({ 'insert_code': 1 }) - if page_name == 'blog': + if doc_type == 'Blog': + template = 'blog/blog.html' + elif doc_type == 'Item': + template = 'product/product.html' + elif page_name == 'blog': template = 'blog/blog_list.html' elif page_name == 'products': template = 'product/product_list.html' @@ -120,6 +118,7 @@ def get_outer_env(): 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html'), 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), + 'favicon': webnotes.conn.get_value('Website Settings', None, 'favicon') } def get_index_page(): From 548a45d550ae051b489d0a89bde183f53c92e063 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 11 Jul 2012 18:40:48 +0530 Subject: [PATCH 11/26] Hong kong timezone added --- erpnext/startup/js/complete_setup.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/erpnext/startup/js/complete_setup.js b/erpnext/startup/js/complete_setup.js index 9180dfa119..ff512827e6 100644 --- a/erpnext/startup/js/complete_setup.js +++ b/erpnext/startup/js/complete_setup.js @@ -138,7 +138,7 @@ $.extend(erpnext.complete_setup, { 'Dominican Republic', 'East Timor', 'Ecuador', 'Egypt', 'El Salvador', 'Equatorial Guinea', 'Eritrea', 'Estonia', 'Ethiopia', 'Federated States of Micronesia', 'Fiji', 'Finland', 'France', 'Gabon', 'Georgia', 'Germany', 'Ghana', 'Greece', - 'Grenada', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Honduras', + 'Grenada', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Honduras', 'Hong Kong' 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran', 'Iraq', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kingdom of the Netherlands', 'Kiribati', 'Kuwait', 'Kyrgyzstan', 'Laos', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', @@ -147,7 +147,7 @@ $.extend(erpnext.complete_setup, { 'Mexico', 'Moldova', 'Monaco', 'Mongolia', 'Montenegro', 'Morocco', 'Mozambique', 'Myanmar', 'Namibia', 'Nauru', 'Nepal', 'New Zealand', 'Nicaragua', 'Niger', 'Nigeria', 'North Korea', 'Norway', 'Oman', 'Pakistan', 'Palau', 'Panama', 'Papua New Guinea', - 'Paraguay', "People's Republic of China", 'Peru', 'Philippines', 'Poland', 'Portugal', + 'Paraguay', "China", 'Peru', 'Philippines', 'Poland', 'Portugal', 'Qatar', 'Republic of Ireland', 'Republic of the Congo', 'Romania', 'Russia', 'Rwanda', 'Saint Kitts and Nevis', 'Saint Lucia', 'Saint Vincent and the Grenadines', 'Samoa', 'San Marino', 'Saudi Arabia', 'Senegal', 'Serbia', 'Seychelles', 'Sierra Leone', @@ -252,6 +252,11 @@ $.extend(erpnext.complete_setup, { 'Cape Verde': ['Atlantic/Cape_Verde'], 'Central African Republic': ['Africa/Bangui'], 'Chad': ['Africa/Ndjamena'], + 'China': ['Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Chongqing', + 'Asia/Urumqi', + 'Asia/Kashgar'], 'Chile': ['America/Santiago', 'Pacific/Easter'], 'Colombia': ['America/Bogota'], 'Comoros': ['Indian/Comoro'], @@ -292,6 +297,7 @@ $.extend(erpnext.complete_setup, { 'Guyana': ['America/Guyana'], 'Haiti': ['America/Guatemala'], 'Honduras': ['America/Tegucigalpa'], + 'Hong Kong': ['Asia/Hong_Kong'], 'Hungary': ['Europe/Budapest'], 'Iceland': ['Atlantic/Reykjavik'], 'India': ['Asia/Calcutta'], @@ -365,11 +371,6 @@ $.extend(erpnext.complete_setup, { 'Panama': ['America/Panama'], 'Papua New Guinea': ['Pacific/Port_Moresby'], 'Paraguay': ['America/Asuncion'], - "People's Republic of China": ['Asia/Shanghai', - 'Asia/Harbin', - 'Asia/Chongqing', - 'Asia/Urumqi', - 'Asia/Kashgar'], 'Peru': ['America/Lima'], 'Philippines': ['Asia/Manila'], 'Poland': ['Europe/Warsaw'], From 8c7e76ba446e8f02e89384c24e5659fa6b6f471c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 11 Jul 2012 18:40:57 +0530 Subject: [PATCH 12/26] RSS for blog Comment addition into blog page's dom --- erpnext/stock/doctype/item/item.py | 2 +- erpnext/website/blog.py | 68 +++++++ erpnext/website/doctype/blog/blog.py | 2 +- erpnext/website/doctype/web_page/web_page.py | 2 +- erpnext/website/product.py | 59 ++++-- erpnext/website/templates/blog/blog.html | 20 +- erpnext/website/templates/blog/blog.js | 199 +++++++++++++------ erpnext/website/templates/blog/comment.html | 14 ++ erpnext/website/web_cache.py | 41 ++-- public/web.py | 6 - 10 files changed, 290 insertions(+), 123 deletions(-) create mode 100644 erpnext/website/blog.py create mode 100644 erpnext/website/templates/blog/comment.html diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index c8d63923a7..798528734c 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -251,7 +251,7 @@ Total Available Qty: %s # no need to check for uniqueness, as name is unique - def get_html(self): + def prepare_template_args(self): import markdown2 self.doc.web_description_html = markdown2.markdown(self.doc.description or '', extras=["wiki-tables"]) diff --git a/erpnext/website/blog.py b/erpnext/website/blog.py new file mode 100644 index 0000000000..56bf8e443c --- /dev/null +++ b/erpnext/website/blog.py @@ -0,0 +1,68 @@ +import webnotes + +@webnotes.whitelist(allow_guest=True) +def get_recent_blog_list(args=None): + """ + args = { + 'limit_start': 0, + 'limit_page_length': 5, + 'name': '', + } + """ + import webnotes + + if not args: args = webnotes.form_dict + + query = """\ + select name, title, left(content, 100) as content + from tabBlog + where ifnull(published,0)=1 and + name!=%(name)s order by creation desc""" + + from webnotes.widgets.query_builder import add_limit_to_query + query, args = add_limit_to_query(query, args) + + result = webnotes.conn.sql(query, args, as_dict=1) + + # strip html tags from content + import webnotes.utils + for res in result: + res['content'] = webnotes.utils.strip_html(res['content']) + + return result + +@webnotes.whitelist(allow_guest=True) +def add_comment(args=None): + """ + args = { + 'comment': '', + 'comment_by': '', + 'comment_by_fullname': '', + 'comment_doctype': '', + 'comment_docname': '', + 'page_name': '', + } + """ + import webnotes + + if not args: args = webnotes.form_dict + + import webnotes.widgets.form.comments + comment = webnotes.widgets.form.comments.add_comment(args) + + # since comments are embedded in the page, clear the web cache + import website.web_cache + website.web_cache.clear_web_cache( + args.get('comment_doctype'), args.get('comment_docname'), + args.get('page_name')) + + import webnotes.utils + + comment['comment_date'] = webnotes.utils.pretty_date(comment['creation']) + template_args = { 'comment_list': [comment] } + + # get html of comment row + comment_html = website.web_cache.build_html(template_args, 'blog/comment.html') + + return comment_html + \ No newline at end of file diff --git a/erpnext/website/doctype/blog/blog.py b/erpnext/website/doctype/blog/blog.py index 89a06d4b0b..bb7b66071f 100644 --- a/erpnext/website/doctype/blog/blog.py +++ b/erpnext/website/doctype/blog/blog.py @@ -34,7 +34,7 @@ class DocType(website.web_page.Page): if not webnotes.utils.cint(self.doc.published): self.delete_web_cache(self.doc.page_name) - def get_html(self): + def prepare_template_args(self): import webnotes.utils # this is for double precaution. usually it wont reach this code if not published diff --git a/erpnext/website/doctype/web_page/web_page.py b/erpnext/website/doctype/web_page/web_page.py index 37e0cee18b..384db4cc84 100644 --- a/erpnext/website/doctype/web_page/web_page.py +++ b/erpnext/website/doctype/web_page/web_page.py @@ -33,5 +33,5 @@ class DocType(website.web_page.Page): from webnotes.session_cache import clear_cache clear_cache('Guest') - def get_html(self): + def prepare_template_args(self): self.markdown_to_html(['head_section','main_section', 'side_section']) \ No newline at end of file diff --git a/erpnext/website/product.py b/erpnext/website/product.py index 7c6603af7b..aff15d95f3 100644 --- a/erpnext/website/product.py +++ b/erpnext/website/product.py @@ -15,12 +15,6 @@ def get_product_list(args=None): if not args: args = webnotes.form_dict - # dict to be passed to sql function - query_args = { - 'limit_start': cint(args.get('limit_start')), - 'limit_page_length': cint(args.get('limit_page_length')) - } - # base query query = """\ select name, item_name, page_name, website_image, @@ -40,36 +34,48 @@ def get_product_list(args=None): item_name like %(search)s or name like %(search)s )""" - query_args['search'] = "%" + cstr(args.get('search')) + "%" + args['search'] = "%" + cstr(args.get('search')) + "%" # product group condition if args.get('product_group') and args.get('product_group') != 'All Products': query += """ and item_group = %(product_group)s""" - query_args['product_group'] = args.get('product_group') # order by query += """ order by item_name asc, name asc""" - - if args.get('limit_page_length'): - query += """ - limit %(limit_start)s, %(limit_page_length)s""" - - return webnotes.conn.sql(query, query_args, as_dict=1) + + from webnotes.widgets.query_builder import add_limit_to_query + query, args = add_limit_to_query(query, args) + + return webnotes.conn.sql(query, args, as_dict=1) @webnotes.whitelist(allow_guest=True) -def get_product_category_list(): +def get_product_category_list(args=None): + """ + args = { + 'limit_start': 0, + 'limit_page_length': 5, + } + """ import webnotes - result = webnotes.conn.sql("""\ + if not args: args = webnotes.form_dict + + query = """\ select count(name) as items, item_group from `tabItem` where is_sales_item = 'Yes' and docstatus = 0 and show_in_website = 1 group by item_group - order by items desc""", as_dict=1) + order by items desc""" + + from webnotes.widgets.query_builder import add_limit_to_query + query, args = add_limit_to_query(query, args) + + + result = webnotes.conn.sql(query, args, as_dict=1) # add All Products link total_count = sum((r.get('items') or 0 for r in result)) @@ -79,11 +85,19 @@ def get_product_category_list(): @webnotes.whitelist(allow_guest=True) def get_similar_product_list(args=None): + """ + args = { + 'limit_start': 0, + 'limit_page_length': 5, + 'product_name': '', + 'product_group': '', + } + """ import webnotes if not args: args = webnotes.form_dict - - result = webnotes.conn.sql("""\ + + query = """\ select name, item_name, page_name, website_image, description, web_short_description from `tabItem` @@ -92,6 +106,11 @@ def get_similar_product_list(args=None): and show_in_website = 1 and name != %(product_name)s and item_group = %(product_group)s - order by item_name""", args, as_dict=1) + order by item_name""" + + from webnotes.widgets.query_builder import add_limit_to_query + query, args = add_limit_to_query(query, args) + + result = webnotes.conn.sql(query, args, as_dict=1) return result \ No newline at end of file diff --git a/erpnext/website/templates/blog/blog.html b/erpnext/website/templates/blog/blog.html index 9132e52be7..d87b128ddc 100644 --- a/erpnext/website/templates/blog/blog.html +++ b/erpnext/website/templates/blog/blog.html @@ -9,19 +9,17 @@
By {{ full_name }} on {{ updated }}

{{ content_html }} -

Comments

-
+
+

Comments


- {% for comment in comment_list %} -
-
- {{ comment.comment_by_fullname }} - {{ comment.comment_date }}: - {{ comment.comment_date_type }} -
-

{{ comment.comment }}

-
+
+

Be the first one to comment

+
- {% endfor %} + + {% include 'blog/comment.html' %} + +
diff --git a/erpnext/website/templates/blog/blog.js b/erpnext/website/templates/blog/blog.js index 3ad1575331..24d5033719 100644 --- a/erpnext/website/templates/blog/blog.js +++ b/erpnext/website/templates/blog/blog.js @@ -23,24 +23,16 @@ wn.pages['{{ name }}'].onload = function(wrapper) { erpnext.blog.wrapper = wrapper; // sidebar - wrapper.recent_list = new wn.ui.Listing({ - parent: $(wrapper).find('.recent-posts'), - no_toolbar: true, - query: 'select name, title, left(content, 100) as content from tabBlog\ - where ifnull(published,0)=1 and name!="{{ name }}" order by creation desc', - hide_refresh: true, - render_row: function(parent, data) { - //console.log(data); - if(data.content && data.content.length==100) data.content += '...'; - parent.innerHTML = repl('%(title)s\ -
%(content)s

', data); - - // adjust page height depending on sidebar height - erpnext.blog.adjust_page_height(wrapper); - }, - page_length: 5, - }); - wrapper.recent_list.run(); + erpnext.blog.render_recent_list(wrapper); + + // unhide no-result if no comments found + erpnext.blog.toggle_no_result(wrapper); + + // bind add comment button to comment dialog + erpnext.blog.make_comment_dialog(wrapper); + + // hide add comment button after 50 comments + erpnext.blog.toggle_add_comment_btn(wrapper); } erpnext.blog.adjust_page_height = function(wrapper) { @@ -54,52 +46,131 @@ erpnext.blog.adjust_page_height = function(wrapper) { $main_page.height($sidebar.height()); } } - // wrapper.comment_list = new wn.ui.Listing({ - // parent: $(wrapper).find('.blog-comments').get(0), - // no_toolbar: true, - // query: 'select comment, comment_by_fullname, creation\ - // from `tabComment` where comment_doctype="Page"\ - // and comment_docname="{{ name }}" order by creation desc', - // no_result_message: 'Be the first one to comment', - // render_row: function(parent, data) { - // data.comment_date = prettyDate(data.creation); - // $(parent).html(repl("
\ - // %(comment_by_fullname)s | %(comment_date)s:\ - //
\ - //

%(comment)s


", data)) - // }, - // hide_refresh: true, - // }); - // wrapper.comment_list.run(); - // - // // add comment - // $(wrapper).find('.layout-main-section').append('
'); - // $(wrapper).find('button.add-comment').click(function(){ - // d = new wn.widgets.Dialog({ - // title: 'Add Comment', - // fields: [ - // {fieldname:'comment_by_fullname', label:'Your Name', reqd:1, fieldtype:'Data'}, - // {fieldname:'comment_by', label:'Email Id', reqd:1, fieldtype:'Data'}, - // {fieldname:'comment', label:'Comment', reqd:1, fieldtype:'Text'}, - // {fieldname:'post', label:'Post', fieldtype:'Button'} - // ] - // }); - // d.fields_dict.post.input.onclick = function() { - // var btn = this; - // var args = d.get_values(); - // if(!args) return; - // args.comment_doctype = 'Page'; - // args.comment_docname = '{{ name }}'; - // $(btn).set_working(); - // $c('webnotes.widgets.form.comments.add_comment', args, function(r) { - // $(btn).done_working(); - // d.hide(); - // wrapper.comment_list.refresh(); - // }) - // } - // d.show(); - // }) +erpnext.blog.render_recent_list = function(wrapper) { + if (!wrapper) { wrapper = erpnext.blog.wrapper; } + if (!wrapper) { return; } + + wrapper.recent_list = new wn.ui.Listing({ + parent: $(wrapper).find('.recent-posts'), + no_toolbar: true, + method: 'website.blog.get_recent_blog_list', + get_args: function() { + return { name: '{{ name }}' } + }, + hide_refresh: true, + render_row: function(parent, data) { + if(data.content && data.content.length>=100) data.content += '...'; + parent.innerHTML = repl('%(title)s\ +
%(content)s

', data); + + // adjust page height depending on sidebar height + erpnext.blog.adjust_page_height(wrapper); + }, + page_length: 5, + }); + wrapper.recent_list.run(); +} + +erpnext.blog.toggle_no_result = function(wrapper) { + if (!wrapper) { wrapper = erpnext.blog.wrapper; } + if (!wrapper) { return; } + + var $blog_comments = $(wrapper).find('.blog-comments'); + var $comment_rows = $blog_comments.find('.comment-row'); + var $no_result = $blog_comments.find('.no-result'); + if ($comment_rows.length == 0) { + $no_result.removeClass('hide'); + } else { + $no_result.addClass('hide'); + } +} + +erpnext.blog.make_comment_dialog = function(wrapper) { + if (!wrapper) { wrapper = erpnext.blog.wrapper; } + if (!wrapper) { return; } + + var $comment_btn = $(wrapper).find('button.add-comment'); + + $comment_btn.click(function() { + if(!erpnext.blog.comment_dialog) { + var d = new wn.widgets.Dialog({ + title: 'Add Comment', + fields: [ + { + fieldname: 'comment_by_fullname', label: 'Your Name', + reqd: 1, fieldtype: 'Data' + }, + { + fieldname: 'comment_by', label: 'Email Id', + reqd: 1, fieldtype: 'Data' + }, + { + fieldname: 'comment', label: 'Comment', + reqd: 1, fieldtype: 'Text' + }, + { + fieldname: 'post_comment', label: 'Post Comment', + fieldtype: 'Button' + }, + ], + }); + + erpnext.blog.comment_dialog = d; + } + + erpnext.blog.comment_dialog.fields_dict.post_comment + .input.onclick = function() { + erpnext.blog.add_comment(wrapper); + } + + erpnext.blog.comment_dialog.show(); + }); + +} + +erpnext.blog.add_comment = function(wrapper) { + var args = erpnext.blog.comment_dialog.get_values(); + + if(!args) return; + + args.comment_doctype = 'Blog'; + args.comment_docname = '{{ name }}'; + args.page_name = '{{ page_name }}'; + + wn.call({ + method: 'website.blog.add_comment', + args: args, + btn: this, + callback: function(r) { + if(!r.exc) { + erpnext.blog.add_comment_to_page(wrapper, r.message); + erpnext.blog.comment_dialog.hide(); + } + } + }); +} + +erpnext.blog.add_comment_to_page = function(wrapper, comment) { + $blog_comments = $(wrapper).find('.blog-comments'); + $comment_rows = $blog_comments.find('.comment-row'); + + if ($comment_rows.length) { + $comment_rows.last().after(comment); + } else { + $blog_comments.find('.no-result').after(comment); + } + + erpnext.blog.toggle_no_result(wrapper); + erpnext.blog.toggle_add_comment_btn(wrapper); +} + +erpnext.blog.toggle_add_comment_btn = function(wrapper) { + var $wrapper = $(wrapper); + if ($wrapper.find('.blog-comments .comment-row').length > 50) { + var $comment_btn = $wrapper.find('button.add-comment'); + $comment_btn.addClass('hide'); + } +} {% endblock %} diff --git a/erpnext/website/templates/blog/comment.html b/erpnext/website/templates/blog/comment.html new file mode 100644 index 0000000000..1323e094d2 --- /dev/null +++ b/erpnext/website/templates/blog/comment.html @@ -0,0 +1,14 @@ +{# + this template generates comment rows for a blog + it is to be included in the blog/blog.html template +#} + +{% for comment in comment_list %} +
+
+ {{ comment.comment_by_fullname }} - {{ comment.comment_date }}: +
+

{{ comment.comment }}

+
+
+{% endfor %} \ No newline at end of file diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 5fcae82bc3..2221df3b22 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -15,7 +15,7 @@ # along with this program. If not, see . # used by web.py -def load_from_web_cache(page_name, comments, template): #, script=None): +def load_from_web_cache(page_name, comments, template): """ * search for page in cache * if html exists, return @@ -47,30 +47,13 @@ def load_from_web_cache(page_name, comments, template): #, script=None): from webnotes.utils import cstr html += """\n""" % cstr(comments) - # show error in error console - # if script: html += """\n\n""" % cstr(script) return html def load_into_web_cache(page_name, template, doc_type, doc_name): """build html and store it in web cache""" import webnotes - outer_env_dict = get_outer_env() - - if page_name in ['404', 'blog', 'products', 'login-page']: - args = outer_env_dict - args.update({ - 'name': page_name, - }) - else: - if page_name == 'index': - page_name, doc_type, doc_name = get_index_page() - from webnotes.model.code import get_obj - obj = get_obj(doc_type, doc_name) - if hasattr(obj, 'get_html'): - obj.get_html() - args = obj.doc.fields - args.update(outer_env_dict) + args = prepare_args(page_name, doc_type, doc_name) # decide template and update args if doc_type == 'Web Page': @@ -96,6 +79,26 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): webnotes.conn.commit() return html + +def prepare_args(page_name, doc_type, doc_name, with_outer_env=1): + if page_name in ['404', 'blog', 'products', 'login-page']: + args = { + 'name': page_name, + } + else: + if page_name == 'index': + page_name, doc_type, doc_name = get_index_page() + + from webnotes.model.code import get_obj + obj = get_obj(doc_type, doc_name) + if hasattr(obj, 'prepare_template_args'): + obj.prepare_template_args() + args = obj.doc.fields + + outer_env_dict = with_outer_env and get_outer_env() or {} + args.update(outer_env_dict) + + return args def build_html(args, template): """build html using jinja2 templates""" diff --git a/public/web.py b/public/web.py index e70b61cd55..32b3cd57d8 100755 --- a/public/web.py +++ b/public/web.py @@ -55,12 +55,6 @@ def get_html(page_name): 'comments': """error: %s""" % traceback, 'template': '404.html', } - # 'script': """(function() { - # var error = "ERROR: %s"; - # console.log(error); - # })();""" % traceback.replace('"', '\\"').replace('\n', ' \\\n'), - # } - else: args = { 'comments': """page: %s""" % page_name, From 51fc20be5b15e437136e078dae43af31d1041eab Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 11 Jul 2012 18:56:13 +0530 Subject: [PATCH 13/26] fixes in index page logic --- erpnext/website/web_cache.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 2221df3b22..3bd6ca7cc6 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -81,14 +81,14 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): return html def prepare_args(page_name, doc_type, doc_name, with_outer_env=1): + if page_name == 'index': + page_name, doc_type, doc_name = get_index_page() + if page_name in ['404', 'blog', 'products', 'login-page']: args = { 'name': page_name, } else: - if page_name == 'index': - page_name, doc_type, doc_name = get_index_page() - from webnotes.model.code import get_obj obj = get_obj(doc_type, doc_name) if hasattr(obj, 'prepare_template_args'): @@ -129,6 +129,8 @@ def get_index_page(): doc_type = 'Web Page' doc_name = webnotes.conn.get_value('Website Settings', None, 'home_page') page_name = webnotes.conn.get_value(doc_type, doc_name, 'page_name') + if not page_name: + page_name = 'login-page' return page_name, doc_type, doc_name # cache management From f7765a899b0a0c57fdb41e9c1b1923304a4e5356 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 11 Jul 2012 19:05:27 +0530 Subject: [PATCH 14/26] Show Brand as ERPNext if brand not specified --- erpnext/website/web_cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 3bd6ca7cc6..163a9487d3 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -119,7 +119,7 @@ def get_outer_env(): where parent='Website Settings' and parentfield='footer_items' order by idx asc""", as_dict=1), - 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html'), + 'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html') or 'ERPNext', 'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'), 'favicon': webnotes.conn.get_value('Website Settings', None, 'favicon') } From be59e7cc1032dc34d8627d46fde124d03cf75013 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 11 Jul 2012 19:12:01 +0530 Subject: [PATCH 15/26] fixes in web cache --- erpnext/website/web_cache.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 163a9487d3..f83e56290b 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -75,6 +75,7 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): # save html in web cache webnotes.conn.begin() + clear_web_cache(doc_type, doc_name, page_name) webnotes.conn.set_value('Web Cache', page_name, 'html', html) webnotes.conn.commit() From 8790188fc86c72ad3b3b57ed7d03652ac900e91e Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 11 Jul 2012 20:04:32 +0530 Subject: [PATCH 16/26] fixes in web cache record insert for exceptional pages like 404, login-page, index etc. --- erpnext/patches/june_2012/cms2.py | 26 ++--------------- erpnext/website/web_cache.py | 48 ++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/erpnext/patches/june_2012/cms2.py b/erpnext/patches/june_2012/cms2.py index fe4774e870..a877c7649b 100644 --- a/erpnext/patches/june_2012/cms2.py +++ b/erpnext/patches/june_2012/cms2.py @@ -33,27 +33,5 @@ def cleanup(): def save_pages(): """save all web pages, blogs to create content""" - import webnotes - from webnotes.model.doclist import DocList - save_list = [ - { - 'doctype': 'Web Page', - 'query': """select name from `tabWeb Page` where docstatus=0""" - }, - { - 'doctype': 'Blog', - 'query': """\ - select name from `tabBlog` - 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 p in webnotes.conn.sql(s['query'], as_dict=1): - DocList(s['doctype'], p['name']).save() \ No newline at end of file + import website.web_cache + website.web_cache.rebuild_web_cache() \ No newline at end of file diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index f83e56290b..0221f47f33 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +page_exception_list = ['404', 'blog', 'products', 'login-page'] + # used by web.py def load_from_web_cache(page_name, comments, template): """ @@ -23,17 +25,13 @@ def load_from_web_cache(page_name, comments, template): """ import webnotes import conf - - if page_name == 'index': - page_name = get_index_page()[0] res = webnotes.conn.sql("""\ select html, doc_type, doc_name from `tabWeb Cache` where name = %s""", page_name) # if page doesn't exist, raise exception - page_exception_list = ['404', 'index', 'blog', 'products', 'login-page'] - if not res and page_name not in page_exception_list: + if not res and page_name not in page_exception_list + ['index']: raise Exception, "Page %s not found" % page_name html, doc_type, doc_name = res and res[0] or (None, None, None) @@ -75,7 +73,8 @@ def load_into_web_cache(page_name, template, doc_type, doc_name): # save html in web cache webnotes.conn.begin() - clear_web_cache(doc_type, doc_name, page_name) + if page_name in page_exception_list + ['index']: + clear_web_cache(doc_type, doc_name, page_name) webnotes.conn.set_value('Web Cache', page_name, 'html', html) webnotes.conn.commit() @@ -85,7 +84,7 @@ def prepare_args(page_name, doc_type, doc_name, with_outer_env=1): if page_name == 'index': page_name, doc_type, doc_name = get_index_page() - if page_name in ['404', 'blog', 'products', 'login-page']: + if page_name in page_exception_list: args = { 'name': page_name, } @@ -143,7 +142,7 @@ def clear_web_cache(doc_type, doc_name, page_name): * if a record like (some other type, name) exists, raise exception that the page name is not unique """ import webnotes - res = webnotes.conn.get_value('Web Cache', page_name, 'doc_type') + res = webnotes.conn.get_value('Web Cache', page_name, ['doc_type', 'name']) if not res: import webnotes.model.doc d = webnotes.model.doc.Document('Web Cache') @@ -152,11 +151,11 @@ def clear_web_cache(doc_type, doc_name, page_name): d.doc_name = doc_name d.html = None d.save() - elif res == doc_type: + elif not doc_type or res[0] == doc_type: webnotes.conn.set_value('Web Cache', page_name, 'html', None) else: webnotes.msgprint("""Page with name "%s" already exists as a %s. - Please save it with another name.""" % (page_name, res), raise_exception=1) + Please save it with another name.""" % (page_name, res[0]), raise_exception=1) def clear_all_web_cache(): import webnotes @@ -174,6 +173,29 @@ def delete_web_cache(page_name): delete from `tabWeb Cache` where name=%s""", page_name) -def build_web_cache(): - """build web cache so that pages can load faster""" - pass \ No newline at end of file +def rebuild_web_cache(): + """build web cache entries""" + import webnotes + from webnotes.model.doclist import DocList + save_list = [ + { + 'doctype': 'Web Page', + 'query': """select name from `tabWeb Page` where docstatus=0""" + }, + { + 'doctype': 'Blog', + 'query': """\ + select name from `tabBlog` + where docstatus = 0 and ifnull(published, 0) = 1""" + }, + { + 'doctype': 'Item', + 'query': """\ + select name from `tabItem` + where docstatus = 0 and ifnull(show_in_website, 0) = 1""" + } + ] + + for s in save_list: + for p in webnotes.conn.sql(s['query'], as_dict=1): + DocList(s['doctype'], p['name']).save() \ No newline at end of file From 179f01af17f45a0e2f4324a4a791b2f1686dad3d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 12 Jul 2012 11:03:39 +0530 Subject: [PATCH 17/26] hong kong added in country list --- erpnext/startup/js/complete_setup.js | 2 +- public/css/all-app.css | 27 +---- public/css/all-web.css | 22 +--- public/js/all-app.js | 165 ++++++++++++++------------- public/js/all-web.js | 19 ++- public/js/complete_setup.js | 2 +- public/js/fields.js | 9 +- public/js/report-legacy.js | 2 +- 8 files changed, 115 insertions(+), 133 deletions(-) diff --git a/erpnext/startup/js/complete_setup.js b/erpnext/startup/js/complete_setup.js index ff512827e6..83d65671c0 100644 --- a/erpnext/startup/js/complete_setup.js +++ b/erpnext/startup/js/complete_setup.js @@ -138,7 +138,7 @@ $.extend(erpnext.complete_setup, { 'Dominican Republic', 'East Timor', 'Ecuador', 'Egypt', 'El Salvador', 'Equatorial Guinea', 'Eritrea', 'Estonia', 'Ethiopia', 'Federated States of Micronesia', 'Fiji', 'Finland', 'France', 'Gabon', 'Georgia', 'Germany', 'Ghana', 'Greece', - 'Grenada', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Honduras', 'Hong Kong' + 'Grenada', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Honduras', 'Hong Kong', 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran', 'Iraq', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kingdom of the Netherlands', 'Kiribati', 'Kuwait', 'Kyrgyzstan', 'Laos', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', diff --git a/public/css/all-app.css b/public/css/all-app.css index ecdbe652f9..84ac2758c3 100644 --- a/public/css/all-app.css +++ b/public/css/all-app.css @@ -2314,11 +2314,6 @@ div.form-title { border-bottom: 1px solid #eee; } -.appframe-titlebar .label { - vertical-align: middle; - margin-right: 7px; -} - div.form-section-head { margin: 11px -15px 3px -15px; border-top: 1px solid #ccc; @@ -3219,8 +3214,6 @@ div.stat-item { height: 18px; border: 1px solid #aaa; border-radius: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; overflow: hidden; } @@ -3229,10 +3222,6 @@ div.stat-bar { left: 0px; height: 100%; z-index: 0; - /* So that this div is also curved like the enclosing one */ - border-radius: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; background: #e0ff84; /* Old browsers */ background: -moz-linear-gradient(top, #e0ff84 0%, #a4e567 100%); /* FF3.6+ */ @@ -3248,8 +3237,12 @@ div.stat-bar { * lib/css/ui/views.css */ -.breadcrumb-area, .breadcrumb-area span { - vertical-align: middle; +.breadcrumbs { + color: #000000; +} + +.breadcrumbs a { + color: #000000; } div.appframe-titlebar { @@ -3267,14 +3260,6 @@ div.appframe-titlebar { border-radius: 5px 5px 0px 0px; -webkit-border-radius: 5px 5px 0px 0px; -moz-border-radius: 5px 5px 0px 0px; - - text-shadow: 0px 1px 1px #fff; - color: #555; -} - -span.appframe-title { - font-size: 160%; - font-weight: bold; } div.appframe-toolbar { diff --git a/public/css/all-web.css b/public/css/all-web.css index 332471b01b..ec2fbcd333 100644 --- a/public/css/all-web.css +++ b/public/css/all-web.css @@ -2470,8 +2470,6 @@ div.stat-item { height: 18px; border: 1px solid #aaa; border-radius: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; overflow: hidden; } @@ -2480,10 +2478,6 @@ div.stat-bar { left: 0px; height: 100%; z-index: 0; - /* So that this div is also curved like the enclosing one */ - border-radius: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; background: #e0ff84; /* Old browsers */ background: -moz-linear-gradient(top, #e0ff84 0%, #a4e567 100%); /* FF3.6+ */ @@ -2499,8 +2493,12 @@ div.stat-bar { * lib/css/ui/views.css */ -.breadcrumb-area, .breadcrumb-area span { - vertical-align: middle; +.breadcrumbs { + color: #000000; +} + +.breadcrumbs a { + color: #000000; } div.appframe-titlebar { @@ -2518,14 +2516,6 @@ div.appframe-titlebar { border-radius: 5px 5px 0px 0px; -webkit-border-radius: 5px 5px 0px 0px; -moz-border-radius: 5px 5px 0px 0px; - - text-shadow: 0px 1px 1px #fff; - color: #555; -} - -span.appframe-title { - font-size: 160%; - font-weight: bold; } div.appframe-toolbar { diff --git a/public/js/all-app.js b/public/js/all-app.js index fd55b1684c..691727aa3a 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -249,7 +249,7 @@ throw new SyntaxError('JSON.parse');};}}()); * lib/js/wn/router.js */ wn.re_route={} -wn.route=function(){if(wn.re_route[window.location.hash]){var re_route_val=wn.get_route_str(wn.re_route[window.location.hash]);var cur_route_val=wn.get_route_str(wn._cur_route);if(decodeURIComponent(re_route_val)===decodeURIComponent(cur_route_val)){window.history.back();return;}else{window.location.hash=wn.re_route[window.location.hash];}} +wn.route=function(){if(wn.re_route[window.location.hash]){window.location.hash=wn.re_route[window.location.hash];} wn._cur_route=window.location.hash;route=wn.get_route();switch(route[0]){case"List":wn.views.doclistview.show(route[1]);break;case"Form":if(route.length>3){route[2]=route.splice(2).join('/');} wn.views.formview.show(route[1],route[2]);break;case"Report":wn.views.reportview.show(route[1],route[2]);break;case"Report2":wn.views.reportview2.show();break;default:wn.views.pageview.show(route[0]);}} wn.get_route=function(route){if(!wn.boot){return[window.page_name];} @@ -350,8 +350,7 @@ df.original_type=df.fieldtype;df.description='';df.reqd=0;if(fieldtype){df.field if(df.fieldtype=='Check'){df.fieldtype='Select';df.options='No\nYes';}else if(['Text','Text Editor','Code','Link'].indexOf(df.fieldtype)!=-1){df.fieldtype='Data';}},set_default_condition:function(df,fieldtype){if(!fieldtype){if(df.fieldtype=='Data'){this.$w.find('.condition').val('like');}else{this.$w.find('.condition').val('=');}}},get_value:function(){var me=this;var val=me.field.get_value();var cond=me.$w.find('.condition').val();if(me.field.df.original_type=='Check'){val=(val=='Yes'?1:0);} if(cond=='like'){val=val+'%';} return[me.fieldselect.$select.find('option:selected').attr('table'),me.field.df.fieldname,me.$w.find('.condition').val(),cstr(val)];}});wn.ui.FieldSelect=Class.extend({init:function(parent,doctype,filter_fields,with_blank){this.doctype=doctype;this.fields_by_name={};this.with_blank=with_blank;this.$select=$('').appendTo(parent);if(filter_fields){for(var i in filter_fields) -this.add_field_option(this.filter_fields[i])}else{this.build_options();}},build_options:function(){var me=this;me.table_fields=[];var std_filters=[{fieldname:'name',fieldtype:'Data',label:'ID',parent:me.doctype},{fieldname:'modified',fieldtype:'Date',label:'Last Modified',parent:me.doctype},{fieldname:'owner',fieldtype:'Data',label:'Created By',parent:me.doctype},{fieldname:'creation',fieldtype:'Date',label:'Created On',parent:me.doctype},{fieldname:'_user_tags',fieldtype:'Data',label:'Tags',parent:me.doctype},{fieldname:'docstatus',fieldtype:'Int',label:'Doc Status',parent:me.doctype},];var doctype_obj=locals['DocType'][me.doctype];if(doctype_obj&&cint(doctype_obj.istable)){std_filters=std_filters.concat([{fieldname:'parent',fieldtype:'Data',label:'Parent',parent:me.doctype}]);} -if(this.with_blank){this.$select.append($('
+ {% if copyright %} diff --git a/erpnext/website/templates/page.html b/erpnext/website/templates/html/page.html similarity index 87% rename from erpnext/website/templates/page.html rename to erpnext/website/templates/html/page.html index c6e0715232..e2eb6f4824 100644 --- a/erpnext/website/templates/page.html +++ b/erpnext/website/templates/html/page.html @@ -1,10 +1,9 @@ -{% extends "outer.html" %} +{% extends "html/outer.html" %} {% block title %}{{ title }}{% endblock %} {% block header %} {{ super() }} - {% if insert_code %} - {% endif %} {% block css %} {% if insert_style %} diff --git a/erpnext/website/templates/product/product.html b/erpnext/website/templates/html/product_page.html similarity index 62% rename from erpnext/website/templates/product/product.html rename to erpnext/website/templates/html/product_page.html index 6f33ec9508..646bba9501 100644 --- a/erpnext/website/templates/product/product.html +++ b/erpnext/website/templates/html/product_page.html @@ -1,4 +1,12 @@ -{% extends "product/product.js" %} +{% extends "html/page.html" %} + +{% block javascript %} + {% include "js/product_page.js" %} +{% endblock %} + +{% block css %} + {% include "css/product_page.css" %} +{% endblock %} {% block title %} {% if item_name != name %} @@ -37,41 +45,4 @@
-{% endblock %} - -{% block css %} - -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/web_page.html b/erpnext/website/templates/html/web_page.html similarity index 81% rename from erpnext/website/templates/web_page.html rename to erpnext/website/templates/html/web_page.html index 8188e71373..6fa7d27b99 100644 --- a/erpnext/website/templates/web_page.html +++ b/erpnext/website/templates/html/web_page.html @@ -1,4 +1,10 @@ -{% extends "page.html" %} +{% extends "html/page.html" %} + +{% block javascript %} + {% if insert_code %} + {{ javascript }} + {% endif %} +{% endblock %} {% block content %}
diff --git a/erpnext/website/templates/blog/blog_list.js b/erpnext/website/templates/js/blog.js similarity index 96% rename from erpnext/website/templates/blog/blog_list.js rename to erpnext/website/templates/js/blog.js index 70628c1540..1212a84c8e 100644 --- a/erpnext/website/templates/blog/blog_list.js +++ b/erpnext/website/templates/js/blog.js @@ -1,6 +1,3 @@ -{% extends "page.html" %} - -{% block javascript %} // ERPNext - web based ERP (http://erpnext.com) // Copyright (C) 2012 Web Notes Technologies Pvt Ltd // @@ -43,6 +40,4 @@ wn.pages['{{ name }}'].onload = function(wrapper) { page_length: 10 }); erpnext.blog_list.run(); -} - -{% endblock %} +} \ No newline at end of file diff --git a/erpnext/website/templates/blog/blog.js b/erpnext/website/templates/js/blog_page.js similarity index 95% rename from erpnext/website/templates/blog/blog.js rename to erpnext/website/templates/js/blog_page.js index 24d5033719..7121677855 100644 --- a/erpnext/website/templates/blog/blog.js +++ b/erpnext/website/templates/js/blog_page.js @@ -1,6 +1,3 @@ -{% extends "page.html" %} - -{% block javascript %} // ERPNext - web based ERP (http://erpnext.com) // Copyright (C) 2012 Web Notes Technologies Pvt Ltd // @@ -18,6 +15,7 @@ // along with this program. If not, see . // js inside blog page + wn.provide('erpnext.blog'); wn.pages['{{ name }}'].onload = function(wrapper) { erpnext.blog.wrapper = wrapper; @@ -79,6 +77,7 @@ erpnext.blog.toggle_no_result = function(wrapper) { var $blog_comments = $(wrapper).find('.blog-comments'); var $comment_rows = $blog_comments.find('.comment-row'); var $no_result = $blog_comments.find('.no-result'); + if ($comment_rows.length == 0) { $no_result.removeClass('hide'); } else { @@ -156,9 +155,9 @@ erpnext.blog.add_comment_to_page = function(wrapper, comment) { $comment_rows = $blog_comments.find('.comment-row'); if ($comment_rows.length) { - $comment_rows.last().after(comment); + $blog_comments.append(comment); } else { - $blog_comments.find('.no-result').after(comment); + $blog_comments.append(comment); } erpnext.blog.toggle_no_result(wrapper); @@ -170,7 +169,12 @@ erpnext.blog.toggle_add_comment_btn = function(wrapper) { if ($wrapper.find('.blog-comments .comment-row').length > 50) { var $comment_btn = $wrapper.find('button.add-comment'); $comment_btn.addClass('hide'); + + // show comments are close + $wrapper.find('.blog-comments').append("\ +
\ +

Comments Closed

\ +
\ +
"); } -} - -{% endblock %} +} \ No newline at end of file diff --git a/erpnext/website/templates/login/login.js b/erpnext/website/templates/js/login.js similarity index 59% rename from erpnext/website/templates/login/login.js rename to erpnext/website/templates/js/login.js index d6b6b24147..29e49226fc 100644 --- a/erpnext/website/templates/login/login.js +++ b/erpnext/website/templates/js/login.js @@ -1,28 +1,18 @@ -{% extends "page.html" %} - -{% block javascript %} -{{ super() }} -// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com) +// ERPNext - web based ERP (http://erpnext.com) +// Copyright (C) 2012 Web Notes Technologies Pvt Ltd // -// MIT License (MIT) +// 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. // -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// 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 . wn.provide('erpnext.login'); @@ -98,6 +88,4 @@ erpnext.login.show_forgot_password = function(){ }) }) d.show(); -} - -{% endblock %} \ No newline at end of file +} \ No newline at end of file diff --git a/erpnext/website/templates/product/product_category.js b/erpnext/website/templates/js/product_category.js similarity index 89% rename from erpnext/website/templates/product/product_category.js rename to erpnext/website/templates/js/product_category.js index e1905ac95a..4229d00c6c 100644 --- a/erpnext/website/templates/product/product_category.js +++ b/erpnext/website/templates/js/product_category.js @@ -1,7 +1,5 @@ -{% extends "page.html" %} - -{% block javascript %} wn.provide('erpnext.products'); + erpnext.products.make_product_categories = function(wrapper) { if (!wrapper) { wrapper = erpnext.products.wrapper; } if (!wrapper) { return; } @@ -17,6 +15,4 @@ erpnext.products.make_product_categories = function(wrapper) { } }); wrapper.category_list.run(); -} - -{% endblock %} \ No newline at end of file +} \ No newline at end of file diff --git a/erpnext/website/templates/product/product.js b/erpnext/website/templates/js/product_page.js similarity index 96% rename from erpnext/website/templates/product/product.js rename to erpnext/website/templates/js/product_page.js index f7745d7b1f..0c4abb4195 100644 --- a/erpnext/website/templates/product/product.js +++ b/erpnext/website/templates/js/product_page.js @@ -1,7 +1,3 @@ -{% extends "product/product_category.js" %} - -{% block javascript %} -{{ super() }} // ERPNext - web based ERP (http://erpnext.com) // Copyright (C) 2012 Web Notes Technologies Pvt Ltd // @@ -17,7 +13,9 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see . -wn.provide('erpnext.products'); + +{% include "js/product_category.js" %} + wn.pages['{{ name }}'].onload = function(wrapper) { wrapper.product_group = "{{ item_group }}"; wrapper.product_name = "{{ name }}"; @@ -91,6 +89,4 @@ erpnext.products.make_similar_products = function(wrapper) { } }); wrapper.similar.run(); -} - -{% endblock %} \ No newline at end of file +} \ No newline at end of file diff --git a/erpnext/website/templates/product/product_list.js b/erpnext/website/templates/js/products.js similarity index 96% rename from erpnext/website/templates/product/product_list.js rename to erpnext/website/templates/js/products.js index 1c6f934e80..f4c68cbf80 100644 --- a/erpnext/website/templates/product/product_list.js +++ b/erpnext/website/templates/js/products.js @@ -1,8 +1,3 @@ -{% extends "product/product_category.js" %} - -{% block javascript %} -{{ super() }} - // ERPNext - web based ERP (http://erpnext.com) // Copyright (C) 2012 Web Notes Technologies Pvt Ltd // @@ -20,7 +15,8 @@ // along with this program. If not, see . // js inside blog page -wn.provide('erpnext.products'); + +{% include "js/product_category.js" %} wn.pages['{{ name }}'].onload = function(wrapper) { erpnext.products.wrapper = wrapper; @@ -107,6 +103,4 @@ erpnext.products.get_group = function() { erpnext.products.cur_group = null; } return {grp:grp, label:label}; -} - -{% endblock %} +} \ No newline at end of file diff --git a/erpnext/website/templates/404.html b/erpnext/website/templates/pages/404.html similarity index 90% rename from erpnext/website/templates/404.html rename to erpnext/website/templates/pages/404.html index 8a30892a66..042360823f 100644 --- a/erpnext/website/templates/404.html +++ b/erpnext/website/templates/pages/404.html @@ -1,4 +1,4 @@ -{% extends "outer.html" %} +{% extends "html/outer.html" %} {% block content %}
diff --git a/erpnext/website/templates/blog/blog_list.html b/erpnext/website/templates/pages/blog.html similarity index 81% rename from erpnext/website/templates/blog/blog_list.html rename to erpnext/website/templates/pages/blog.html index 242f814a9c..40c90c29a3 100644 --- a/erpnext/website/templates/blog/blog_list.html +++ b/erpnext/website/templates/pages/blog.html @@ -1,17 +1,15 @@ -{% extends "blog/blog_list.js" %} +{% extends "html/page.html" %} -{% block title %}Blog{% endblock %} +{% block javascript %} + {% include "js/blog.js" %} +{% endblock %} {% block css %} - + {% include "css/blog.css" %} {% endblock %} +{% block title %}Blog{% endblock %} + {% block content %}
diff --git a/erpnext/website/templates/pages/index.html b/erpnext/website/templates/pages/index.html new file mode 100644 index 0000000000..1307872d4e --- /dev/null +++ b/erpnext/website/templates/pages/index.html @@ -0,0 +1 @@ +{% extends "html/web_page.html" %} \ No newline at end of file diff --git a/erpnext/website/templates/login/login.html b/erpnext/website/templates/pages/login.html similarity index 86% rename from erpnext/website/templates/login/login.html rename to erpnext/website/templates/pages/login.html index 62d252f5d2..9bc3171128 100644 --- a/erpnext/website/templates/login/login.html +++ b/erpnext/website/templates/pages/login.html @@ -1,4 +1,12 @@ -{% extends "login/login.js" %} +{% extends "html/page.html" %} + +{% block javascript %} + {% include "js/login.js" %} +{% endblock %} + +{% block css %} + {% include "css/login.css" %} +{% endblock %} {% block title %} Login Page @@ -41,17 +49,4 @@
-{% endblock %} - -{% block css %} - {% endblock %} \ No newline at end of file diff --git a/erpnext/website/templates/product/product_list.html b/erpnext/website/templates/pages/products.html similarity index 80% rename from erpnext/website/templates/product/product_list.html rename to erpnext/website/templates/pages/products.html index c8dfd24ed0..aa23ea29c4 100644 --- a/erpnext/website/templates/product/product_list.html +++ b/erpnext/website/templates/pages/products.html @@ -1,4 +1,12 @@ -{% extends "product/product_list.js" %} +{% extends "html/page.html" %} + +{% block javascript %} + {% include "js/products.js" %} +{% endblock %} + +{% block css %} + {% include "css/products.css" %} +{% endblock %} {% block title %} Products @@ -26,18 +34,4 @@
-{% endblock %} - -{% block css %} - {% endblock %} \ No newline at end of file diff --git a/erpnext/website/utils.py b/erpnext/website/utils.py index 06bb60d94b..22fcce741f 100644 --- a/erpnext/website/utils.py +++ b/erpnext/website/utils.py @@ -17,6 +17,12 @@ import webnotes from webnotes.model.doc import Document +def scrub_page_name(page_name): + if page_name.endswith('.html'): + page_name = page_name[:-5] + + return page_name + def make_template(doc, path, convert_fields = ['main_section', 'side_section']): """make template""" import os, jinja2 @@ -35,82 +41,3 @@ def page_name(title): name = title.lower() name = re.sub('[~!@#$%^&*()<>,."\']', '', name) return '-'.join(name.split()[:4]) - -def get_header(page_name): - """get page header""" - - from webnotes.model.doc import Document - from jinja2 import Template - import webnotes.utils - - def get_item(l, label): - for i in l: - if i['label']==label: - return i - - top_bar_items = webnotes.conn.sql("""select * from `tabTop Bar Item` - where parent='Website Settings' and parentfield='top_bar_items' - order by idx asc""", as_dict=1) - - # build child items - for t in top_bar_items: - if t.get('parent_label'): - pi = get_item(top_bar_items, t['parent_label']) - if 'child_items' not in pi: - pi['child_items'] = [] - pi['child_items'].append(t) - - website_settings = Document('Website Settings', 'Website Settings') - - return Template("""""").render(top_bar_items = top_bar_items, - brand=website_settings.brand_html or webnotes.utils.get_defaults('company') or 'ERPNext') - -def get_footer(page_name): - """get page footer""" - - from webnotes.model.doc import Document - from jinja2 import Template - - website_settings = Document('Website Settings', 'Website Settings') - - website_settings.footer_items = webnotes.conn.sql("""select * from `tabTop Bar Item` - where parent='Website Settings' and parentfield='footer_items' - order by idx asc""", as_dict=1) - - return Template("""