+
+
+
+
+
\ No newline at end of file
diff --git a/erpnext/website/page/products/products.js b/erpnext/website/page/products/products.js
new file mode 100644
index 00000000000..b9fa167514f
--- /dev/null
+++ b/erpnext/website/page/products/products.js
@@ -0,0 +1,87 @@
+erpnext.products = {}
+
+wn.require('erpnext/website/js/product_category.js');
+
+pscript.onload_products = function(wrapper) {
+ sys_defaults.default_product_category = JSON.parse(sys_defaults.default_product_category);
+ erpnext.products.wrapper = wrapper;
+
+ // make lists
+ erpnext.make_product_categories(wrapper);
+ erpnext.products.make_product_list(wrapper);
+
+ // button
+ $(wrapper).find('.products-search .btn').click(function() {
+ wrapper.mainlist.run();
+ });
+
+ $(wrapper).find('.products-search input').keypress(function(ev) {
+ if(ev.which==13) $(wrapper).find('.products-search .btn').click();
+ });
+}
+
+pscript.onshow_products = function(wrapper) {
+ // show default product category
+ erpnext.products.set_group();
+}
+
+erpnext.products.get_group = function() {
+ var route = window.location.hash.split('/');
+ if(route.length>1) {
+ // from url
+ var grp = erpnext.product_item_group[route[1]];
+ var label = route[1];
+ } else {
+ // default
+ var grp = sys_defaults.default_product_category.item_group;
+ var label = sys_defaults.default_product_category.label;
+ }
+ erpnext.products.cur_group = grp;
+ return {grp:grp, label:label};
+}
+
+erpnext.products.make_product_list = function(wrapper) {
+ wrapper.mainlist = new wn.widgets.Listing({
+ parent: $(wrapper).find('.web-main-section').get(0),
+ run_btn: $(wrapper).find('.products-search .btn').get(0),
+ hide_refresh: true,
+ get_query: function() {
+ var srch = $('input[name="products-search"]').val()
+ var search_cond = 'and (t1.short_description like "%%(srch)s%"\
+ or t1.title like "%%(srch)s%")';
+ args = {
+ search_cond: srch ? repl(search_cond, {srch:srch}) : '',
+ cat: erpnext.products.cur_group
+ };
+ 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 t2.item_group="%(cat)s" \
+ %(search_cond)s', args)
+ },
+ render_row: function(parent, data) {
+ parent.innerHTML = repl('
\
+
s)
\
+
\
+
', data);
+ }
+ });
+}
+
+erpnext.products.set_group = function() {
+ var cat = erpnext.products.get_group();
+ if(!cat.grp) {
+ // still nothing
+ setTimeout('erpnext.products.set_group()', 1000);
+ return;
+ }
+ // get erpnext.products.default_category
+ var wrapper = erpnext.products.wrapper;
+
+ $(wrapper).find('h1').html(cat.label);
+ wrapper.mainlist.run();
+}
diff --git a/erpnext/website/page/products/products.txt b/erpnext/website/page/products/products.txt
new file mode 100644
index 00000000000..f00a05b8e84
--- /dev/null
+++ b/erpnext/website/page/products/products.txt
@@ -0,0 +1,43 @@
+# Page, products
+[
+
+ # These values are common in all dictionaries
+ {
+ 'creation': '2012-01-30 10:49:01',
+ 'docstatus': 0,
+ 'modified': '2012-01-30 10:49:01',
+ 'modified_by': 'Administrator',
+ 'owner': 'Administrator'
+ },
+
+ # These values are common for all Page
+ {
+ 'doctype': 'Page',
+ 'module': 'Website',
+ 'name': '__common__',
+ 'page_name': 'products',
+ 'standard': 'Yes',
+ 'title': 'Products'
+ },
+
+ # These values are common for all Page Role
+ {
+ 'doctype': 'Page Role',
+ 'name': '__common__',
+ 'parent': 'products',
+ 'parentfield': 'roles',
+ 'parenttype': 'Page',
+ 'role': 'Guest'
+ },
+
+ # Page, products
+ {
+ 'doctype': 'Page',
+ 'name': 'products'
+ },
+
+ # Page Role
+ {
+ 'doctype': 'Page Role'
+ }
+]
\ No newline at end of file
diff --git a/erpnext/website/page/unsubscribe/__init__.py b/erpnext/website/page/unsubscribe/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/website/page/unsubscribe/unsubscribe.html b/erpnext/website/page/unsubscribe/unsubscribe.html
new file mode 100644
index 00000000000..7b2b68ee9c6
--- /dev/null
+++ b/erpnext/website/page/unsubscribe/unsubscribe.html
@@ -0,0 +1,13 @@
+
+
+
Unsubscribe
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/erpnext/website/page/unsubscribe/unsubscribe.js b/erpnext/website/page/unsubscribe/unsubscribe.js
new file mode 100644
index 00000000000..7cbed37f4ad
--- /dev/null
+++ b/erpnext/website/page/unsubscribe/unsubscribe.js
@@ -0,0 +1,21 @@
+pscript.onload_unsubscribe = function(wrapper) {
+ var email = window.location.hash.split('/').splice(-1);
+ $(wrapper).find('input[name="unsubscribe"]').val(email)
+
+ $('#btn-unsubscribe').click(function() {
+ var email = $(wrapper).find('input[name="unsubscribe"]').val();
+ if(email) {
+ var btn = this;
+ wn.call({
+ module:'website',
+ page:'unsubscribe',
+ method:'unsubscribe',
+ args:email,
+ btn: this,
+ callback: function() {
+ $(wrapper).find('input[name="unsubscribe"]').val('');
+ }
+ });
+ }
+ });
+}
\ No newline at end of file
diff --git a/erpnext/website/page/unsubscribe/unsubscribe.py b/erpnext/website/page/unsubscribe/unsubscribe.py
new file mode 100644
index 00000000000..c310c61dec5
--- /dev/null
+++ b/erpnext/website/page/unsubscribe/unsubscribe.py
@@ -0,0 +1,10 @@
+import webnotes
+
+@webnotes.whitelist()
+def unsubscribe(arg):
+ """unsubscribe from lists"""
+ lists = [['Blog Subscriber', 'name']]
+ for l in lists:
+ webnotes.conn.sql("""delete from `tab%s` where %s=%s""" % (l[0], l[1], '%s'), arg)
+
+ webnotes.msgprint('Unsubscribed!')
\ No newline at end of file
diff --git a/erpnext/website/page/unsubscribe/unsubscribe.txt b/erpnext/website/page/unsubscribe/unsubscribe.txt
new file mode 100644
index 00000000000..2cc3b58a351
--- /dev/null
+++ b/erpnext/website/page/unsubscribe/unsubscribe.txt
@@ -0,0 +1,43 @@
+# Page, unsubscribe
+[
+
+ # These values are common in all dictionaries
+ {
+ 'creation': '2012-01-27 17:19:02',
+ 'docstatus': 0,
+ 'modified': '2012-01-27 17:19:02',
+ 'modified_by': 'Administrator',
+ 'owner': 'Administrator'
+ },
+
+ # These values are common for all Page
+ {
+ 'doctype': 'Page',
+ 'module': 'Website',
+ 'name': '__common__',
+ 'page_name': 'unsubscribe',
+ 'standard': 'Yes',
+ 'title': 'Unsubscribe'
+ },
+
+ # These values are common for all Page Role
+ {
+ 'doctype': 'Page Role',
+ 'name': '__common__',
+ 'parent': 'unsubscribe',
+ 'parentfield': 'roles',
+ 'parenttype': 'Page',
+ 'role': 'Guest'
+ },
+
+ # Page, unsubscribe
+ {
+ 'doctype': 'Page',
+ 'name': 'unsubscribe'
+ },
+
+ # Page Role
+ {
+ 'doctype': 'Page Role'
+ }
+]
\ No newline at end of file
diff --git a/erpnext/website/utils.py b/erpnext/website/utils.py
new file mode 100644
index 00000000000..66be4d2bb5f
--- /dev/null
+++ b/erpnext/website/utils.py
@@ -0,0 +1,54 @@
+import webnotes
+from webnotes.model.doc import Document
+
+def make_template(doc, path, convert_fields = ['main_section', 'side_section']):
+ """make template"""
+ import os, jinja2
+
+ markdown(doc, convert_fields)
+
+ # write template
+ with open(path, 'r') as f:
+ temp = jinja2.Template(f.read())
+
+ 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 re
+ name = title.lower()
+ name = re.sub('[~!@#$%^&*()<>,."\']', '', name)
+ return '-'.join(name.split()[:4])
+
+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()
diff --git a/images/feed.png b/images/feed.png
new file mode 100755
index 00000000000..315c4f4fa62
Binary files /dev/null and b/images/feed.png differ
diff --git a/index.cgi b/index.cgi
index 3d61c560521..3ec31e7985e 100755
--- a/index.cgi
+++ b/index.cgi
@@ -9,33 +9,35 @@ sys.path.append('lib/py')
sys.path.append('erpnext')
import webnotes
+import webnotes.handler
+import webnotes.auth
-webnotes.form = cgi.FieldStorage()
+def init():
+ # make the form_dict
+ webnotes.form = cgi.FieldStorage(keep_blank_values=True)
+ for key in webnotes.form.keys():
+ webnotes.form_dict[key] = webnotes.form.getvalue(key)
-# make the form_dict
-for key in webnotes.form.keys():
- webnotes.form_dict[key] = webnotes.form.getvalue(key)
+ # init request
+ try:
+ webnotes.http_request = webnotes.auth.HTTPRequest()
+ except Exception, e:
+ if webnotes.response['message']=='Authentication Failed':
+ pass
+ else:
+ raise e
-# url comes with sid, redirect to html, sid set and all
-if 'sid' in webnotes.form_dict:
- import webnotes.auth
- import webnotes.widgets.page_body
-
- webnotes.auth.HTTPRequest()
-
- print "Content-Type: text/html"
-
- # print cookies, if there ar additional cookies defined during the request, add them here
- if webnotes.cookies or webnotes.add_cookies:
- for c in webnotes.add_cookies.keys():
- webnotes.cookies[c] = webnotes.add_cookies[c]
-
- print webnotes.cookies
-
- print
- print webnotes.widgets.page_body.redirect_template % ('Redirecting...', 'index.html')
-
-else:
- # pass on to legacy handler
- import webnotes.handler
+def respond():
+ import webnotes
+ if 'cmd' in webnotes.form_dict:
+ webnotes.handler.handle()
+ else:
+ import webnotes.cms.index
+ print "Content-Type: text/html"
+ webnotes.handler.print_cookies()
+ print
+ print webnotes.cms.index.get()
+if __name__=="__main__":
+ init()
+ respond()
diff --git a/index.html b/index.html
deleted file mode 100644
index 150a2cf730e..00000000000
--- a/index.html
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
ERPNext
-
-
-
-
-
-
-
-
-
-
-
diff --git a/js/app.js b/js/app.js
index 5a8597d48ba..cba6a8493f3 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,8 +1,17 @@
+wn.app = {
+ name: 'ERPNext',
+ license: 'GNU/GPL - Usage Condition: All "erpnext" branding must be kept as it is',
+ source: 'https://github.com/webnotes/erpnext',
+ publisher: 'Web Notes Technologies Pvt Ltd, Mumbai',
+ copyright: '© Web Notes Technologies Pvt Ltd',
+ version: '2.' + window._version_number
+}
+
+wn.modules_path = 'erpnext';
wn.settings.no_history = true;
wn.require('lib/js/lib/jquery.min.js');
wn.require('lib/js/legacy/tiny_mce_33/jquery.tinymce.js');
-wn.require('lib/js/wn/ui/status_bar.js');
// for datepicker
wn.require('lib/js/legacy/jquery/jquery-ui.min.js')
@@ -11,4 +20,8 @@ wn.require('lib/css/legacy/default.css');
$(document).bind('ready', function() {
startup();
-});
\ No newline at end of file
+});
+
+$(document).bind('toolbar_setup', function() {
+ $('.brand').html('
erpnext');
+})
\ No newline at end of file
diff --git a/rss.xml b/rss.xml
new file mode 100755
index 00000000000..f69724b493c
--- /dev/null
+++ b/rss.xml
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+
+import cgi, cgitb, os, sys
+cgitb.enable()
+
+# import libs
+sys.path.append('lib/py')
+
+import webnotes
+import webnotes.auth
+
+if __name__=='__main__':
+ webnotes.http_request = webnotes.auth.HTTPRequest()
+ from webnotes.cms import feed
+ xml = feed.generate()
+ print 'Content-Type: text/xml'
+ print
+ print xml
\ No newline at end of file
diff --git a/sitemap.xml b/sitemap.xml
new file mode 100755
index 00000000000..04e565bc574
--- /dev/null
+++ b/sitemap.xml
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+import cgi, cgitb, os, sys
+cgitb.enable()
+
+# import libs
+sys.path.append('lib/py')
+
+import webnotes
+import webnotes.auth
+
+if __name__=='__main__':
+ webnotes.http_request = webnotes.auth.HTTPRequest()
+ domain = os.environ.get('HTTP_HOST')
+ protocol = os.environ.get('HTTPS') and 'https://' or 'http://'
+ from webnotes.cms import sitemap
+ print 'Content-Type: text/xml'
+ print
+ print sitemap.generate(protocol + domain + '/')
\ No newline at end of file
diff --git a/templates/index.html b/templates/index.html
deleted file mode 100644
index af0b8e5f79e..00000000000
--- a/templates/index.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
ERPNext
-
-
-
-
-
-
-
-
-
-
-
diff --git a/version.num b/version.num
index bc768da71aa..1380537bfd7 100644
--- a/version.num
+++ b/version.num
@@ -1 +1 @@
-146
\ No newline at end of file
+385
\ No newline at end of file
diff --git a/wnf.py b/wnf.py
new file mode 100755
index 00000000000..4f18187fccb
--- /dev/null
+++ b/wnf.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+import os, sys
+
+def replace_code(start, txt1, txt2, extn):
+ """replace all txt1 by txt2 in files with extension (extn)"""
+ import os, re
+ for wt in os.walk(start, followlinks=1):
+ for fn in wt[2]:
+ if fn.split('.')[-1]==extn:
+ fpath = os.path.join(wt[0], fn)
+ with open(fpath, 'r') as f:
+ content = f.read()
+
+ if re.search(txt1, content):
+ a = raw_input('Change in %s [y/n]?' % fpath)
+ if a=='y':
+ with open(fpath, 'w') as f:
+ f.write(re.sub(txt1, txt2, content))
+
+ print 'updated in %s' % fpath
+
+def setup_options():
+ from optparse import OptionParser
+ parser = OptionParser()
+ parser.add_option("-b", "--build", default=False, action="store_true",
+ help="minify + concat js files")
+ parser.add_option("-c", "--clear", default=False, action="store_true",
+ help="increment version")
+ parser.add_option("--replace", nargs=3, default=False,
+ metavar = "search replace_by extension",
+ help="file search-replace")
+ parser.add_option("--status", default=False, action="store_true",
+ help="git status")
+ parser.add_option("--pull", nargs=2, default=False,
+ metavar = "remote branch",
+ help="git pull (both repos)")
+ parser.add_option("--push", nargs=3, default=False,
+ metavar = "remote branch comment",
+ help="git commit + push (both repos) [remote] [branch] [comment]")
+ parser.add_option("-l", "--latest",
+ action="store_true", dest="run_latest", default=False,
+ help="Apply the latest patches")
+ parser.add_option("-p", "--patch", nargs=1, dest="patch_list", metavar='patch_module',
+ action="append",
+ help="Apply patch")
+ parser.add_option("-f", "--force",
+ action="store_true", dest="force", default=False,
+ help="Force Apply all patches specified using option -p or --patch")
+ parser.add_option("-d", "--db",
+ dest="db_name",
+ help="Apply the patches on given db")
+ parser.add_option('--reload_doc', nargs=3, metavar = "module doctype docname",
+ help="reload doc")
+ parser.add_option('--export_doc', nargs=2, metavar = "doctype docname",
+ help="export doc")
+ parser.add_option('--install', nargs=3, metavar = "rootpassword dbname source",
+ help="install fresh db")
+ parser.add_option('--sync_with_gateway', nargs=1, metavar = "1/0", help="Set or Unset Sync with Gateway")
+
+ return parser.parse_args()
+
+def run():
+ sys.path.append('lib')
+ sys.path.append('lib/py')
+ import webnotes
+ import webnotes.defs
+ sys.path.append(webnotes.defs.modules_path)
+
+ (options, args) = setup_options()
+
+
+ from webnotes.db import Database
+ import webnotes.modules.patch_handler
+
+ # connect
+ if options.db_name is not None:
+ webnotes.connect(options.db_name)
+
+ # build
+ if options.build:
+ import build.project
+ build.project.build()
+
+ elif options.clear:
+ from build.project import increment_version
+ print "Version:" + str(increment_version())
+
+ # code replace
+ elif options.replace:
+ replace_code('.', options.replace[0], options.replace[1], options.replace[2])
+
+ # git
+ elif options.status:
+ os.system('git status')
+ os.chdir('lib')
+ os.system('git status')
+
+ elif options.pull:
+ os.system('git pull %s %s' % (options.pull[0], options.pull[1]))
+ os.chdir('lib')
+ os.system('git pull %s %s' % (options.pull[0], options.pull[1]))
+
+ elif options.push:
+ os.system('git commit -a -m "%s"' % options.push[2])
+ os.system('git push %s %s' % (options.push[0], options.push[1]))
+ os.chdir('lib')
+ os.system('git commit -a -m "%s"' % options.push[2])
+ os.system('git push %s %s' % (options.push[0], options.push[1]))
+
+ # patch
+ elif options.patch_list:
+ # clear log
+ webnotes.modules.patch_handler.log_list = []
+
+ # run individual patches
+ for patch in options.patch_list:
+ webnotes.modules.patch_handler.run_single(\
+ patchmodule = patch, force = options.force)
+
+ print '\n'.join(webnotes.modules.patch_handler.log_list)
+
+ # reload
+ elif options.reload_doc:
+ webnotes.modules.patch_handler.reload_doc(\
+ {"module":options.reload_doc[0], "dt":options.reload_doc[1], "dn":options.reload_doc[2]})
+ print '\n'.join(webnotes.modules.patch_handler.log_list)
+
+ elif options.export_doc:
+ from webnotes.modules import export_doc
+ export_doc(options.export_doc[0], options.export_doc[1])
+
+ # run all pending
+ elif options.run_latest:
+ webnotes.modules.patch_handler.run_all()
+ print '\n'.join(webnotes.modules.patch_handler.log_list)
+
+ elif options.install:
+ from webnotes.install_lib.install import Installer
+ inst = Installer('root', options.install[0])
+ inst.import_from_db(options.install[1], source_path=options.install[2], \
+ password='admin', verbose = 1)
+
+ elif options.sync_with_gateway:
+ if int(options.sync_with_gateway[0]) in [0, 1]:
+ webnotes.conn.begin()
+ webnotes.conn.sql("""\
+ UPDATE `tabSingles` SET value=%s
+ WHERE field='sync_with_gateway' AND doctype='Control Panel'""", int(options.sync_with_gateway[0]))
+ webnotes.conn.commit()
+ webnotes.message_log.append("sync_with_gateway set to %s" % options.sync_with_gateway[0])
+ else:
+ webnotes.message_log.append("ERROR: sync_with_gateway can be either 0 or 1")
+
+ # print messages
+ if webnotes.message_log:
+ print '\n'.join(webnotes.message_log)
+
+if __name__=='__main__':
+ run()