Bläddra i källkod

Merge branch '4.0.0-wip' of github.com:webnotes/wnframework into 4.0.0-wip

version-14
Nabin Hait 11 år sedan
förälder
incheckning
b16bc0cc4f
19 ändrade filer med 116 tillägg och 71 borttagningar
  1. +4
    -1
      webnotes/__init__.py
  2. +0
    -1
      webnotes/boot.py
  3. +0
    -1
      webnotes/cli.py
  4. +2
    -2
      webnotes/core/doctype/bulk_email/bulk_email.txt
  5. +1
    -1
      webnotes/core/page/desktop/desktop.js
  6. +2
    -0
      webnotes/model/doc.py
  7. +12
    -10
      webnotes/templates/base.html
  8. +27
    -1
      webnotes/templates/emails/standard.html
  9. +0
    -2
      webnotes/templates/includes/footer.html
  10. +2
    -2
      webnotes/templates/includes/inline_post.html
  11. +1
    -1
      webnotes/templates/includes/navbar.html
  12. +1
    -1
      webnotes/templates/includes/sidebar.html
  13. +10
    -3
      webnotes/utils/__init__.py
  14. +11
    -11
      webnotes/utils/email_lib/bulk.py
  15. +1
    -1
      webnotes/utils/email_lib/smtp.py
  16. +14
    -11
      webnotes/website/css/website.css
  17. +11
    -10
      webnotes/website/doctype/web_page/web_page.py
  18. +5
    -8
      webnotes/website/js/website.js
  19. +12
    -4
      webnotes/webutils.py

+ 4
- 1
webnotes/__init__.py Visa fil

@@ -22,7 +22,10 @@ local = Local()
class _dict(dict): class _dict(dict):
"""dict like object that exposes keys as attributes""" """dict like object that exposes keys as attributes"""
def __getattr__(self, key): def __getattr__(self, key):
return self.get(key)
ret = self.get(key)
if not ret and key.startswith("__"):
raise AttributeError()
return ret
def __setattr__(self, key, value): def __setattr__(self, key, value):
self[key] = value self[key] = value
def __getstate__(self): def __getstate__(self):


+ 0
- 1
webnotes/boot.py Visa fil

@@ -69,7 +69,6 @@ def get_bootinfo():
from webnotes.model.utils import compress from webnotes.model.utils import compress
bootinfo['docs'] = compress(bootinfo['docs']) bootinfo['docs'] = compress(bootinfo['docs'])


# deal with __slots__ in lang
if bootinfo.lang: if bootinfo.lang:
bootinfo.lang = unicode(bootinfo.lang) bootinfo.lang = unicode(bootinfo.lang)


+ 0
- 1
webnotes/cli.py Visa fil

@@ -240,7 +240,6 @@ def use():
@cmd @cmd
def install(db_name, root_login="root", root_password=None, source_sql=None, def install(db_name, root_login="root", root_password=None, source_sql=None,
admin_password = 'admin', verbose=True, force=False, site_config=None, reinstall=False): admin_password = 'admin', verbose=True, force=False, site_config=None, reinstall=False):
print db_name, source_sql
from webnotes.installer import install_db, install_app, make_site_dirs from webnotes.installer import install_db, install_app, make_site_dirs
install_db(root_login=root_login, root_password=root_password, db_name=db_name, source_sql=source_sql, install_db(root_login=root_login, root_password=root_password, db_name=db_name, source_sql=source_sql,
admin_password = admin_password, verbose=verbose, force=force, site_config=site_config, reinstall=reinstall) admin_password = admin_password, verbose=verbose, force=force, site_config=site_config, reinstall=reinstall)


+ 2
- 2
webnotes/core/doctype/bulk_email/bulk_email.txt Visa fil

@@ -2,7 +2,7 @@
{ {
"creation": "2012-08-02 15:17:28", "creation": "2012-08-02 15:17:28",
"docstatus": 0, "docstatus": 0,
"modified": "2013-12-20 19:23:58",
"modified": "2014-02-12 21:11:05",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
@@ -55,7 +55,7 @@
{ {
"doctype": "DocField", "doctype": "DocField",
"fieldname": "message", "fieldname": "message",
"fieldtype": "Text",
"fieldtype": "Long Text",
"label": "Message" "label": "Message"
}, },
{ {


+ 1
- 1
webnotes/core/page/desktop/desktop.js Visa fil

@@ -132,7 +132,7 @@ wn.desktop.show_all_modules = function() {
var module = wn.modules[m]; var module = wn.modules[m];
if(module.link && desktop_items.indexOf(m)!==-1) { if(module.link && desktop_items.indexOf(m)!==-1) {
module.app_icon = wn.ui.app_icon.get_html(m, true); module.app_icon = wn.ui.app_icon.get_html(m, true);
$(repl('<div class="list-group-item" data-label="%(label)s">\
$(repl('<div class="list-group-item" data-label="%(name)s">\
<div class="row">\ <div class="row">\
<div class="col-xs-2"><a href="#%(link)s">%(app_icon)s</a></div>\ <div class="col-xs-2"><a href="#%(link)s">%(app_icon)s</a></div>\
<div class="col-xs-10" style="padding-top: 14px;">\ <div class="col-xs-10" style="padding-top: 14px;">\


+ 2
- 0
webnotes/model/doc.py Visa fil

@@ -178,6 +178,8 @@ class Document:
elif self.fields.has_key(name): elif self.fields.has_key(name):
return self.fields[name] return self.fields[name]
else: else:
if name.startswith("__"):
raise AttributeError()
return '' return ''
def get(self, name, value=None): def get(self, name, value=None):


+ 12
- 10
webnotes/templates/base.html Visa fil

@@ -7,8 +7,8 @@
<meta name="generator" content="wnframework"> <meta name="generator" content="wnframework">
<script type="text/javascript" src="/assets/webnotes/js/lib/jquery/jquery.min.js"></script> <script type="text/javascript" src="/assets/webnotes/js/lib/jquery/jquery.min.js"></script>
<link rel="shortcut icon" href="{{ favicon }}" type="image/x-icon">
<link rel="icon" href="{{ favicon }}" type="image/x-icon">
<link rel="shortcut icon" href="{{ favicon or "" }}" type="image/x-icon">
<link rel="icon" href="{{ favicon or "" }}" type="image/x-icon">
{% block head -%} {% block head -%}
{%- if meta_description is defined -%} {%- if meta_description is defined -%}
@@ -49,12 +49,17 @@
<header class="page-header"> <header class="page-header">
<div class="container" data-html-block="header"> <div class="container" data-html-block="header">
{%- if header is defined -%}{{ header }}{%- endif -%}
{%- if header is defined -%}{{ header }}{% elif title is defined %}<h2>{{ title }}</h2>{%- endif -%}
</div> </div>
</header>
<header class="page-breadcrumbs">
<div class="container" data-html-block="breadcrumbs">
{%- if breadcrumbs is defined -%}{{ breadcrumbs }}{%- endif -%}
<div class="container">
<div class="row">
<div class="col-xs-10 page-breadcrumbs" data-html-block="breadcrumbs">
{%- if breadcrumbs is defined -%}{{ breadcrumbs }}{%- endif -%}
</div>
<div class="col-xs-2 text-right"><a class="visible-xs toggle-sidebar no-decoration">
<i class="icon-chevron-down"></i>
</a></div>
</div>
</div> </div>
</header> </header>
<div class="container page-container" id="page-{{ name or page_name }}"> <div class="container page-container" id="page-{{ name or page_name }}">
@@ -68,9 +73,6 @@
{%- endblock -%} {%- endblock -%}
</div> </div>
<div class="col-sm-9 col-sm-pull-3 page-content" data-html-block="content"> <div class="col-sm-9 col-sm-pull-3 page-content" data-html-block="content">
<div class="text-right"><a class="visible-xs toggle-sidebar no-decoration">
<i class="icon-chevron-down"></i>
</a></div>
{%- block content -%}{{ content }}{%- endblock -%} {%- block content -%}{{ content }}{%- endblock -%}
</div> </div>
</div> </div>


+ 27
- 1
webnotes/templates/emails/standard.html Visa fil

@@ -78,6 +78,19 @@ body {
padding:10px 0; padding:10px 0;
} }


.left-padding {
padding-left: 10px;
}

.breadcrumb {
list-style: none;
}

.breadcrumb > li {
display: inline-block;
margin-left: 0px;
margin-right: 5px;
}


/* ------------------------------------- /* -------------------------------------
BODY BODY
@@ -183,6 +196,19 @@ table.footer-wrap a{
width: 100%; width: 100%;
} }


a.no-decoration {
text-decoration: none;
color: inherit;
}

small, .small {
font-size: 85%;
}

.text-muted {
color: #999999;
}

</style> </style>
</head> </head>
@@ -240,7 +266,7 @@ table.footer-wrap a{


</div> </div>


<div class="print-html">{{ print_html }}</div>
<div class="print-html">{{ print_html or "" }}</div>


</body> </body>
</html> </html>

+ 0
- 2
webnotes/templates/includes/footer.html Visa fil

@@ -10,8 +10,6 @@
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
<div id="website-login" class="col-xs-3 text-right">
<a href="login">Login</a></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-8"> <div class="col-sm-8">


+ 2
- 2
webnotes/templates/includes/inline_post.html Visa fil

@@ -5,13 +5,13 @@
data-name="{{ post.name }}" data-name="{{ post.name }}"
data-group="{{ post.website_group }}" data-group="{{ post.website_group }}"
itemscope itemtype="http://schema.org/Article"> itemscope itemtype="http://schema.org/Article">
<a class="pull-left media-link" href="{{ post_url }}">
<a class="pull-left media-link" {% if view.name!="post" %} href="{{ post_url }}" {% endif %}>
<img class="media-object post-avatar" src="{{ post.user_image }}"> <img class="media-object post-avatar" src="{{ post.user_image }}">
</a> </a>
<div class="media-body"> <div class="media-body">
{%- if not post.parent_post -%} {%- if not post.parent_post -%}
<h4 class="media-heading" itemprop="headline"> <h4 class="media-heading" itemprop="headline">
{%- if view != "post" -%}
{%- if view.name != "post" -%}
<a class="no-decoration" <a class="no-decoration"
href="{{ post_url }}">{{ post.title }}</a> href="{{ post_url }}">{{ post.title }}</a>
{%- else -%} {%- else -%}


+ 1
- 1
webnotes/templates/includes/navbar.html Visa fil

@@ -66,7 +66,7 @@
</ul> </ul>
</li> </li>
</ul> </ul>
<ul class="btn-login-area nav navbar-nav navbar-right">
<ul class="btn-login-area website-login nav navbar-nav navbar-right">
<li><a href="/login">Sign Up / Login</a></li> <li><a href="/login">Sign Up / Login</a></li>
</ul> </ul>
</div> </div>


+ 1
- 1
webnotes/templates/includes/sidebar.html Visa fil

@@ -1,7 +1,7 @@
{% if children -%} {% if children -%}
{%- for child in children -%} {%- for child in children -%}
<div class="sidebar-item"> <div class="sidebar-item">
<a href="/{{ child.name|lower }}" class="no-decoration">
<a href="{{ child.name }}" class="no-decoration {% if child.name == pathname %}active{% endif %}">
{{ child.page_title }} {{ child.page_title }}
{% if not child.public_read %} {% if not child.public_read %}
(<i class="icon-fixed-width icon-lock"></i>) (<i class="icon-fixed-width icon-lock"></i>)


+ 10
- 3
webnotes/utils/__init__.py Visa fil

@@ -903,9 +903,16 @@ def scrub_urls(html):
def expand_relative_urls(html): def expand_relative_urls(html):
# expand relative urls # expand relative urls
url = get_url() url = get_url()
if not url.endswith("/"): url += "/"
return re.sub('(href|src){1}([\s]*=[\s]*[\'"]?)((?!http)[^\'" >]+)([\'"]?)',
'\g<1>\g<2>{}\g<3>\g<4>'.format(url), html)
if url.endswith("/"): url = url[:-1]
def _expand_relative_urls(match):
to_expand = list(match.groups())
if not to_expand[2].startswith("/"):
to_expand[2] = "/" + to_expand[2]
to_expand.insert(2, url)
return "".join(to_expand)
return re.sub('(href|src){1}([\s]*=[\s]*[\'"]?)((?!http)[^\'" >]+)([\'"]?)', _expand_relative_urls, html)
def quote_urls(html): def quote_urls(html):
def _quote_url(match): def _quote_url(match):


+ 11
- 11
webnotes/utils/email_lib/bulk.py Visa fil

@@ -47,7 +47,7 @@ def send(recipients=None, sender=None, doctype='Profile', email_field='email',
"type": doctype, "type": doctype,
"email_field": email_field "email_field": email_field
})) }))
updated = updated.replace("<!--unsubscribe link here-->", unsubscribe_link) updated = updated.replace("<!--unsubscribe link here-->", unsubscribe_link)
return updated return updated
@@ -57,11 +57,6 @@ def send(recipients=None, sender=None, doctype='Profile', email_field='email',
sender = webnotes.conn.get_value('Email Settings', None, 'auto_email_id') sender = webnotes.conn.get_value('Email Settings', None, 'auto_email_id')
check_bulk_limit(len(recipients)) check_bulk_limit(len(recipients))
try:
text_content = html2text(message)
except HTMLParser.HTMLParseError:
text_content = "[See html attachment]"
formatted = get_formatted_html(subject, message) formatted = get_formatted_html(subject, message)


for r in filter(None, list(set(recipients))): for r in filter(None, list(set(recipients))):
@@ -72,8 +67,13 @@ def send(recipients=None, sender=None, doctype='Profile', email_field='email',
if not is_unsubscribed(doc): if not is_unsubscribed(doc):
# add to queue # add to queue
add(r, sender, subject, update_message(formatted, doc, add_unsubscribe_link),
text_content, ref_doctype, ref_docname)
updated = update_message(formatted, doc, add_unsubscribe_link)
try:
text_content = html2text(updated)
except HTMLParser.HTMLParseError:
text_content = "[See html attachment]"
add(r, sender, subject, updated, text_content, ref_doctype, ref_docname)


def add(email, sender, subject, formatted, text_content=None, def add(email, sender, subject, formatted, text_content=None,
ref_doctype=None, ref_docname=None): ref_doctype=None, ref_docname=None):
@@ -83,7 +83,7 @@ def add(email, sender, subject, formatted, text_content=None,
e.recipient = email e.recipient = email
try: try:
e.message = get_email(email, sender=e.sender, formatted=formatted, subject=subject, e.message = get_email(email, sender=e.sender, formatted=formatted, subject=subject,
text_content = text_content).as_string()
text_content=text_content).as_string()
except webnotes.ValidationError: except webnotes.ValidationError:
# bad email id - don't add to queue # bad email id - don't add to queue
return return
@@ -113,7 +113,7 @@ def unsubscribe():
def flush(from_test=False): def flush(from_test=False):
"""flush email queue, every time: called from scheduler""" """flush email queue, every time: called from scheduler"""
smptserver = SMTPServer()
smtpserver = SMTPServer()
auto_commit = not from_test auto_commit = not from_test
@@ -133,7 +133,7 @@ def flush(from_test=False):
(email["name"],), auto_commit=auto_commit) (email["name"],), auto_commit=auto_commit)
try: try:
if not from_test: if not from_test:
smptserver.sess.sendmail(email["sender"], email["recipient"], email["message"])
smtpserver.sess.sendmail(email["sender"], email["recipient"], email["message"])


webnotes.conn.sql("""update `tabBulk Email` set status='Sent' where name=%s""", webnotes.conn.sql("""update `tabBulk Email` set status='Sent' where name=%s""",
(email["name"],), auto_commit=auto_commit) (email["name"],), auto_commit=auto_commit)


+ 1
- 1
webnotes/utils/email_lib/smtp.py Visa fil

@@ -21,7 +21,7 @@ def send(email, as_bulk=False):
if not email.reply_to: if not email.reply_to:
email.reply_to = email.sender email.reply_to = email.sender
email.sender = smtpserver.login email.sender = smtpserver.login
smtpserver.sess.sendmail(email.sender, email.recipients + (email.cc or []), smtpserver.sess.sendmail(email.sender, email.recipients + (email.cc or []),
email.as_string()) email.as_string())


+ 14
- 11
webnotes/website/css/website.css Visa fil

@@ -215,7 +215,7 @@ fieldset {


.page-header { .page-header {
margin: 0px; margin: 0px;
padding: 5px 0px;
padding: 15px 0px;
} }


.page-container { .page-container {
@@ -233,10 +233,14 @@ fieldset {
margin-bottom: 5px; margin-bottom: 5px;
} }


.page-content {
padding-top: 7px;
}

.sidebar-item { .sidebar-item {
margin: 15px auto; margin: 15px auto;
color: #999; color: #999;
font-size: 90%;
font-size: 85%;
} }


.sidebar-item a:hover { .sidebar-item a:hover {
@@ -346,10 +350,6 @@ textarea {
margin: 30px; margin: 30px;
} }


.img-responsive {
border-radius: 4px;
}

.user-profile { .user-profile {
min-height: 50px; min-height: 50px;
min-width: 70px; min-width: 70px;
@@ -388,20 +388,23 @@ a.no-decoration {
color: inherit; color: inherit;
} }


.page-breadcrumbs {
border-bottom: 1px solid #eee;
a.active {
pointer-events: none;
cursor: default;
color: initial;
} }


.page-breadcrumbs .breadcrumb { .page-breadcrumbs .breadcrumb {
margin-bottom: 0px;
padding: 0px;
margin-bottom: 2px;
background-color: transparent; background-color: transparent;
border-radius: 0px; border-radius: 0px;
padding: 8px 0px;
font-size: 85%;
} }


@media (min-width: 768px) { @media (min-width: 768px) {
.page-sidebar { .page-sidebar {
padding-left: 5em;
padding-left: 3em;
} }
} }




+ 11
- 10
webnotes/website/doctype/web_page/web_page.py Visa fil

@@ -48,7 +48,7 @@ def _sync_statics():
def sync_file(fname, fpath, statics_path, priority=0): def sync_file(fname, fpath, statics_path, priority=0):
url = os.path.relpath(fpath, statics_path).rsplit(".", 1)[0] url = os.path.relpath(fpath, statics_path).rsplit(".", 1)[0]
if fname.rsplit(".", 1)[0]=="index":
if fname.rsplit(".", 1)[0]=="index" and os.path.dirname(fpath) != statics_path:
url = os.path.dirname(url) url = os.path.dirname(url)
parent_website_sitemap = os.path.dirname(url) parent_website_sitemap = os.path.dirname(url)
@@ -100,20 +100,21 @@ def _sync_statics():
with open(os.path.join(basepath, "index.txt"), "r") as indexfile: with open(os.path.join(basepath, "index.txt"), "r") as indexfile:
index = indexfile.read().splitlines() index = indexfile.read().splitlines()
for fname in files:
page_name = fname.rsplit(".", 1)[0]
if page_name=="index" and fname!="index.txt":
sync_file(fname, os.path.join(basepath, fname), statics_path)
has_index = True
break
if basepath!=statics_path:
for fname in files:
page_name = fname.rsplit(".", 1)[0]
if page_name=="index" and fname!="index.txt":
sync_file(fname, os.path.join(basepath, fname), statics_path)
has_index = True
break
if not has_index:
continue
if not has_index:
continue
# other files # other files
for fname in files: for fname in files:
page_name = fname.rsplit(".", 1)[0] page_name = fname.rsplit(".", 1)[0]
if page_name!="index":
if not (page_name=="index" and basepath!=statics_path):
sync_file(fname, os.path.join(basepath, fname), statics_path, sync_file(fname, os.path.join(basepath, fname), statics_path,
index.index(page_name) if page_name in index else 0) index.index(page_name) if page_name in index else 0)


+ 5
- 8
webnotes/website/js/website.js Visa fil

@@ -244,23 +244,19 @@ $.extend(wn, {


}, },
load_via_ajax: function(href) { load_via_ajax: function(href) {
console.log("calling ajax");
// console.log("calling ajax");
window.previous_href = href; window.previous_href = href;
history.pushState(null, null, href); history.pushState(null, null, href);
$.ajax({ url: href, cache: false }).done(function(data) { $.ajax({ url: href, cache: false }).done(function(data) {
history.replaceState(data, data.title, href); history.replaceState(data, data.title, href);
$("html, body").animate({ scrollTop: 0 }, "slow");
wn.render_json(data); wn.render_json(data);
}) })
}, },
render_json: function(data) { render_json: function(data) {
if(data.reload) { if(data.reload) {
window.location = location.href; window.location = location.href;
// } else if(data.html) {
// var newDoc = document.open("text/html", "replace");
// newDoc.write(data.html);
// newDoc.close();
} else { } else {
$('[data-html-block]').each(function(i, section) { $('[data-html-block]').each(function(i, section) {
var $section = $(section); var $section = $(section);
@@ -422,9 +418,10 @@ $(document).ready(function() {
}); });


$(document).on("page_change", function() { $(document).on("page_change", function() {
$(".page-header").toggleClass("hidden", !!!$(".page-header").text().trim());
$(".page-header").toggleClass("hidden", !!!$("[data-html-block='header']").text().trim());
$(".page-footer").toggleClass("hidden", !!!$(".page-footer").text().trim()); $(".page-footer").toggleClass("hidden", !!!$(".page-footer").text().trim());
//$(".page-breadcrumbs").toggleClass("hidden", !!!$(".page-breadcrumbs").text().trim());
$("[data-html-block='breadcrumbs'] .breadcrumb").toggleClass("hidden",
$("[data-html-block='breadcrumbs']").text().trim()==$("[data-html-block='header']").text().trim());


// add prive pages to sidebar // add prive pages to sidebar
if(website.private_pages && $(".page-sidebar").length) { if(website.private_pages && $(".page-sidebar").length) {


+ 12
- 4
webnotes/webutils.py Visa fil

@@ -86,11 +86,13 @@ def build_page(path):
def get_context(path): def get_context(path):
context = None context = None
cache_key = "page_context:{}".format(path) cache_key = "page_context:{}".format(path)
from pickle import dump
from StringIO import StringIO
# try from memcache # try from memcache
if can_cache(): if can_cache():
context = webnotes.cache().get_value(cache_key) context = webnotes.cache().get_value(cache_key)
if not context: if not context:
context = get_sitemap_options(path) context = get_sitemap_options(path)


@@ -99,8 +101,7 @@ def get_context(path):


context = build_context(context) context = build_context(context)


if can_cache(context.no_cache):
del context["access"]
if can_cache(context.no_cache):
webnotes.cache().set_value(cache_key, context) webnotes.cache().set_value(cache_key, context)


else: else:
@@ -147,7 +148,14 @@ def build_sitemap_options(path):


sitemap_options.children = webnotes.conn.sql("""select * from `tabWebsite Sitemap` sitemap_options.children = webnotes.conn.sql("""select * from `tabWebsite Sitemap`
where parent_website_sitemap=%s where parent_website_sitemap=%s
and public_read=1 order by idx asc""", (sitemap_options.name,), as_dict=True)
and public_read=1 order by -idx desc, page_title asc""", (sitemap_options.pathname,), as_dict=True)
# leaf node, show siblings
if not sitemap_options.children:
sitemap_options.children = webnotes.conn.sql("""select * from `tabWebsite Sitemap`
where ifnull(parent_website_sitemap, '')=%s
and public_read=1 order by -idx desc, page_title asc""",
sitemap_options.parent_website_sitemap or "", as_dict=True)
# determine templates to be used # determine templates to be used
if not sitemap_options.base_template_path: if not sitemap_options.base_template_path:


Laddar…
Avbryt
Spara