diff --git a/frappe/core/doctype/docshare/docshare.json b/frappe/core/doctype/docshare/docshare.json index df0fe2fe15..68ebe45c7b 100644 --- a/frappe/core/doctype/docshare/docshare.json +++ b/frappe/core/doctype/docshare/docshare.json @@ -138,7 +138,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-06 00:44:40.883188", + "modified": "2015-02-12 11:30:52.968078", "modified_by": "Administrator", "module": "Core", "name": "DocShare", diff --git a/frappe/core/page/data_import_tool/importer.py b/frappe/core/page/data_import_tool/importer.py index 622fd6d321..6b01b760c8 100644 --- a/frappe/core/page/data_import_tool/importer.py +++ b/frappe/core/page/data_import_tool/importer.py @@ -138,6 +138,15 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, def main_doc_empty(row): return not (row and ((len(row) > 1 and row[1]) or (len(row) > 2 and row[2]))) + users = frappe.db.sql_list("select name from tabUser") + def prepare_for_insert(doc): + # don't block data import if user is not set + # migrating from another system + if not doc.owner in users: + doc.owner = frappe.session.user + if not doc.modified_by in users: + doc.modified_by = frappe.session.user + # header if not rows: rows = read_csv_content_from_uploaded_file(ignore_encoding_errors) @@ -210,6 +219,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, ret.append('Updated row (#%d) %s' % (row_idx + 1, getlink(original.doctype, original.name))) else: doc = frappe.get_doc(doc) + prepare_for_insert(doc) doc.flags.ignore_links = ignore_links doc.insert() ret.append('Inserted row (#%d) %s' % (row_idx + 1, getlink(doc.doctype, doc.name))) diff --git a/frappe/frappeclient.py b/frappe/frappeclient.py new file mode 100644 index 0000000000..1cc441fb9a --- /dev/null +++ b/frappe/frappeclient.py @@ -0,0 +1,211 @@ +import requests +import json +import frappe + +class AuthError(Exception): + pass + +class FrappeException(Exception): + pass + +class FrappeClient(object): + def __init__(self, url, username, password): + self.session = requests.Session() + self.url = url + self.login(username, password) + + def __enter__(self): + return self + + def __exit__(self, *args, **kwargs): + self.logout() + + def login(self, username, password): + r = self.session.post(self.url, data={ + 'cmd': 'login', + 'usr': username, + 'pwd': password + }) + + if r.json().get('message') == "Logged In": + return r.json() + else: + raise AuthError + + def logout(self): + self.session.get(self.url, params={ + 'cmd': 'logout', + }) + + def get_list(self, doctype, fields='"*"', filters=None, limit_start=0, limit_page_length=0): + """Returns list of records of a particular type""" + params = { + "fields": fields, + } + if filters: + params["filters"] = json.dumps(filters) + if limit_page_length: + params["limit_start"] = limit_start + params["limit_page_length"] = limit_page_length + res = self.session.get(self.url + "/api/resource/" + doctype, params=params) + return self.post_process(res) + + def insert(self, doc): + res = self.session.post(self.url + "/api/resource/" + doc.get("doctype"), + data={"data":json.dumps(doc)}) + return self.post_process(res) + + def update(self, doc): + url = self.url + "/api/resource/" + doc.get("doctype") + "/" + doc.get("name") + res = self.session.put(url, data={"data":json.dumps(doc)}) + return self.post_process(res) + + def bulk_update(self, docs): + return self.post_request({ + "cmd": "frappe.client.bulk_update", + "docs": json.dumps(docs) + }) + + def delete(self, doctype, name): + return self.post_request({ + "cmd": "frappe.model.delete_doc", + "doctype": doctype, + "name": name + }) + + def submit(self, doclist): + return self.post_request({ + "cmd": "frappe.client.submit", + "doclist": json.dumps(doclist) + }) + + def get_value(self, doctype, fieldname=None, filters=None): + return self.get_request({ + "cmd": "frappe.client.get_value", + "doctype": doctype, + "fieldname": fieldname or "name", + "filters": json.dumps(filters) + }) + + def set_value(self, doctype, docname, fieldname, value): + return self.post_request({ + "cmd": "frappe.client.set_value", + "doctype": doctype, + "name": docname, + "fieldname": fieldname, + "value": value + }) + + def cancel(self, doctype, name): + return self.post_request({ + "cmd": "frappe.client.cancel", + "doctype": doctype, + "name": name + }) + + def get_doc(self, doctype, name="", filters=None, fields=None): + params = {} + if filters: + params["filters"] = json.dumps(filters) + if fields: + params["fields"] = json.dumps(fields) + + res = self.session.get(self.url + "/api/resource/" + doctype + "/" + name, + params=params) + + return self.post_process(res) + + def rename_doc(self, doctype, old_name, new_name): + params = { + "cmd": "frappe.client.rename_doc", + "doctype": doctype, + "old_name": old_name, + "new_name": new_name + } + return self.post_request(params) + + def migrate_doctype(self, doctype, filters={}): + """Migrate records from another doctype""" + meta = frappe.get_meta(doctype) + tables = {} + for df in meta.get_table_fields(): + print "getting " + df.options + tables[df.fieldname] = self.get_list(df.options, limit_page_length=999999) + + # get links + print "getting " + doctype + docs = self.get_list(doctype, limit_page_length=999999, filters=filters) + + # build - attach children to parents + if tables: + docs_map = {} + for doc in docs: + docs_map[doc.name] = doc + + for fieldname in tables: + for child in tables[fieldname]: + docs_map[child.parent].append(fieldname, child) + + print "inserting " + doctype + for doc in docs: + if not frappe.db.exists("User", doc.get("owner")): + frappe.get_doc({"doctype": "User", "email": doc.get("owner"), + "first_name": doc.get("owner").split("@")[0] }).insert() + + doc["doctype"] = doctype + frappe.get_doc(doc).insert() + + if doctype != "Comment": + self.migrate_doctype("Comment", {"comment_doctype": doctype}) + + def migrate_single(self, doctype): + doc = self.get_doc(doctype, doctype) + doc = frappe.get_doc(doc) + + # change modified so that there is no error + doc.modified = frappe.db.get_single_value(doctype, "modified") + frappe.get_doc(doc).insert() + + def get_api(self, method, params={}): + res = self.session.get(self.url + "/api/method/" + method + "/", + params=params) + return self.post_process(res) + + def post_api(self, method, params={}): + res = self.session.post(self.url + "/api/method/" + method + "/", + params=params) + return self.post_process(res) + + def get_request(self, params): + res = self.session.get(self.url, params=self.preprocess(params)) + res = self.post_process(res) + return res + + def post_request(self, data): + res = self.session.post(self.url, data=self.preprocess(data)) + res = self.post_process(res) + return res + + def preprocess(self, params): + """convert dicts, lists to json""" + for key, value in params.iteritems(): + if isinstance(value, (dict, list)): + params[key] = json.dumps(value) + + return params + + def post_process(self, response): + try: + rjson = response.json() + except ValueError: + print response.text + raise + + if rjson and ("exc" in rjson) and rjson["exc"]: + raise FrappeException(rjson["exc"]) + if 'message' in rjson: + return rjson['message'] + elif 'data' in rjson: + return rjson['data'] + else: + return None diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 9fad87333d..013666fe9c 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -35,8 +35,8 @@ class DatabaseQuery(object): self.docstatus = docstatus or [] self.group_by = group_by self.order_by = order_by - self.limit_start = limit_start - self.limit_page_length = limit_page_length + self.limit_start = int(limit_start) + self.limit_page_length = int(limit_page_length) self.with_childnames = with_childnames self.debug = debug self.as_list = as_list diff --git a/frappe/public/css/website.css b/frappe/public/css/website.css index 356dd41d24..441ec92466 100644 --- a/frappe/public/css/website.css +++ b/frappe/public/css/website.css @@ -278,60 +278,23 @@ body { margin-bottom: 15px; } /* post and post list */ -.post { +.web-list-item { padding: 15px 0px; - word-wrap: break-word; - border-bottom: 1px solid #eee; + border-bottom: 1px solid #d1d8dd; } -.post:first-child { - margin-top: 15px !important; -} -.post .img-responsive { - border-radius: 4px; -} -.post .media-link { - display: block; - min-width: 50px; - min-height: 50px; -} -.post .media-object { - border-radius: 4px; - max-width: 50px; -} -.post .media-heading { - margin-bottom: 12px; +.web-list-item:last-child { + border-bottom: none; } -.parent-post .post { - border: none; +.web-list-item h3 { + margin: 0 0 5px 0; } -.child-post { - border: 1px solid #eee; - padding-left: 15px; - background-color: #f8f8f8; - margin-top: 0px; +.web-list-item h3 a { + color: inherit !important; + text-decoration: none; } textarea { resize: vertical; } -.post-add-textarea { - height: 200px !important; -} -/* needs review */ -.btn-small, -.post-editor .btn { - padding: 5px; - font-size: 90%; -} -.btn-right, -.post-editor .btn { - margin-left: 5px; -} -.no-posts { - margin-top: 15px; -} -.full-page { - margin: 30px; -} .user-profile { min-height: 50px; min-width: 70px; diff --git a/frappe/public/less/website.less b/frappe/public/less/website.less index 1600db0995..ae33d83acf 100644 --- a/frappe/public/less/website.less +++ b/frappe/public/less/website.less @@ -330,73 +330,26 @@ body { } /* post and post list */ -.post { - padding: 15px 0px; - word-wrap: break-word; - border-bottom: 1px solid #eee; -} -.post:first-child { - margin-top: 15px !important; +.web-list-item { + padding: 15px 0px; + border-bottom: 1px solid @border-color; } - -.post .img-responsive { - border-radius: 4px; +.web-list-item:last-child { + border-bottom: none; } - -.post .media-link { - display: block; - min-width: 50px; - min-height: 50px; +.web-list-item h3 { + margin: 0 0 5px 0; } - -.post .media-object { - border-radius: 4px; - max-width: 50px; -} - -.post .media-heading { - margin-bottom: 12px; -} - -.parent-post .post { - border: none; -} - -.child-post { - border: 1px solid #eee; - padding-left: 15px; - background-color: #f8f8f8; - margin-top: 0px; +.web-list-item h3 a { + color: inherit !important; + text-decoration: none; } textarea { resize: vertical; } -.post-add-textarea { - height: 200px !important; -} - -/* needs review */ - -.btn-small, .post-editor .btn { - padding: 5px; - font-size: 90%; -} - -.btn-right, .post-editor .btn { - margin-left: 5px; -} - -.no-posts { - margin-top: 15px; -} - -.full-page { - margin: 30px; -} - .user-profile { min-height: 50px; min-width: 70px; diff --git a/frappe/templates/includes/blog_list.html b/frappe/templates/includes/blog_list.html index 1c6298cc7a..da9f5e680c 100644 --- a/frappe/templates/includes/blog_list.html +++ b/frappe/templates/includes/blog_list.html @@ -1,10 +1,10 @@ {% for post in posts %} -
{{ post.content }}
diff --git a/frappe/templates/pages/blog.html b/frappe/templates/pages/blog.html index 54d492f897..aa5a496989 100644 --- a/frappe/templates/pages/blog.html +++ b/frappe/templates/pages/blog.html @@ -4,25 +4,6 @@ window.category = null; {% endblock %} -{% block style %} - -{% endblock %} - {% block content %}