From a8d8e1c3b3a7c4552ff3bef30e577b40a91a761e Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 26 Feb 2014 12:27:44 +0530 Subject: [PATCH] added fixture sync --- frappe/cli.py | 3 + .../page/data_import_tool/data_import_tool.py | 23 ++-- frappe/model/doctype.py | 2 +- frappe/public/js/frappe/ui/messages.js | 17 +++ frappe/public/js/lib/jscolor/jscolor.js | 118 +++++++++++++----- frappe/templates/includes/footer_powered.html | 2 +- frappe/utils/fixtures.py | 15 +++ frappe/utils/install.py | 2 + .../website_settings/website_settings.js | 20 +++ .../website_settings/website_settings.txt | 2 +- 10 files changed, 165 insertions(+), 39 deletions(-) create mode 100644 frappe/utils/fixtures.py diff --git a/frappe/cli.py b/frappe/cli.py index 42a822474e..6e8846f186 100755 --- a/frappe/cli.py +++ b/frappe/cli.py @@ -297,6 +297,7 @@ def latest(verbose=True, rebuild_website_config=True): import frappe.modules.patch_handler import frappe.model.sync from frappe.website import rebuild_config + from frappe.utils.fixtures import sync_fixtures frappe.connect() @@ -314,6 +315,8 @@ def latest(verbose=True, rebuild_website_config=True): if rebuild_website_config: rebuild_config() + sync_fixtures() + except frappe.modules.patch_handler.PatchError, e: print "\n".join(frappe.local.patch_log_list) raise diff --git a/frappe/core/page/data_import_tool/data_import_tool.py b/frappe/core/page/data_import_tool/data_import_tool.py index e1bcb4d9b2..6483f44db5 100644 --- a/frappe/core/page/data_import_tool/data_import_tool.py +++ b/frappe/core/page/data_import_tool/data_import_tool.py @@ -3,16 +3,14 @@ from __future__ import unicode_literals -import frappe, json -import frappe.model.doc +import frappe, json, os +import frappe.permissions import frappe.model.doctype from frappe.model.meta import get_table_fields -from frappe.model.doc import Document from frappe.utils import cstr from frappe.utils.datautils import UnicodeWriter, check_record, import_doc, getlink, cint, flt from frappe import _ import frappe.permissions -from frappe.widgets import reportview data_keys = frappe._dict({ "data_separator": 'Start entering data below this line', @@ -176,7 +174,7 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data frappe.permissions.can_export(parent_doctype, raise_exception=True) # get permitted data only - data = reportview.execute(doctype, fields=["*"], limit_page_length=None) + data = frappe.get_list(doctype, fields=["*"], limit_page_length=None) for doc in data: # add main table row_group = [] @@ -224,7 +222,6 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data @frappe.whitelist() def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, overwrite=False, ignore_links=False): """upload data""" - import frappe.permissions frappe.flags.mute_emails = True # extra input params params = json.loads(frappe.form_dict.get("params") or '{}') @@ -420,7 +417,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, if parenttype: # child doc - doc = Document(doctype) + doc = frappe.doc(doctype) doc.fields.update(doclist[0]) if parenttype: doc.parenttype = parenttype @@ -514,8 +511,18 @@ def export_json(doctype, name, path): d["__islocal"] = 1 outfile.write(json.dumps([doclist], default=json_handler, indent=1, sort_keys=True)) +@frappe.whitelist() +def export_fixture(doctype, name, app): + if frappe.session.user != "Administrator": + raise frappe.PermissionError + + if not os.path.exists(frappe.get_app_path(app, "fixtures")): + os.mkdir(frappe.get_app_path(app, "fixtures")) + + export_json(doctype, name, frappe.get_app_path(app, "fixtures", frappe.scrub(name) + ".json")) + + def import_doclist(path, overwrite=False, ignore_links=False, ignore_insert=False, insert=False): - import os if os.path.isdir(path): files = [os.path.join(path, f) for f in os.listdir(path)] else: diff --git a/frappe/model/doctype.py b/frappe/model/doctype.py index b777ddbb81..6c41569c2e 100644 --- a/frappe/model/doctype.py +++ b/frappe/model/doctype.py @@ -47,7 +47,7 @@ def get(doctype, processed=False, cached=True): for table_doctype in table_types: doclist += get_doctype_doclist(table_doctype) - + if processed: add_code(doctype, doclist) expand_selects(doclist) diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index 1f5c185f34..0ac8051f67 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -38,6 +38,23 @@ frappe.confirm = function(message, ifyes, ifno) { return d; } +frappe.get_value = function(field, callback) { + var d = new frappe.ui.Dialog({ + fields: [field, {fieldtype:"Button", "label":"Submit"}], + title: __("Enter Value"), + }) + d.get_input("submit").on("click", function() { + var values = d.get_values(); + if(field.reqd && !values[field.fieldname]) { + // ask to re-enter + } else { + d.hide(); + callback(values[field.fieldname]); + } + }) + d.show(); +} + var msg_dialog=null; function msgprint(msg, title) { if(!msg) return; diff --git a/frappe/public/js/lib/jscolor/jscolor.js b/frappe/public/js/lib/jscolor/jscolor.js index 8415310d8d..986f89bfc2 100644 --- a/frappe/public/js/lib/jscolor/jscolor.js +++ b/frappe/public/js/lib/jscolor/jscolor.js @@ -1,11 +1,11 @@ /** * jscolor, JavaScript Color Picker * - * @version 1.3.13 + * @version 1.4.2 * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html * @author Jan Odvarko, http://odvarko.cz * @created 2008-06-15 - * @updated 2012-01-19 + * @updated 2013-11-25 * @link http://jscolor.com */ @@ -13,7 +13,7 @@ var jscolor = { - dir : 'lib/js/lib/jscolor/', // location of jscolor directory (leave empty to autodetect) + dir : 'assets/frappe/js/lib/jscolor/', // location of jscolor directory (leave empty to autodetect) bindClass : 'color', // class name binding : true, // automatic binding via preloading : true, // use image preloading? @@ -36,8 +36,8 @@ var jscolor = { getDir : function() { if(!jscolor.dir) { - //var detected = jscolor.detectDir(); - jscolor.dir = "lib/js/lib/jscolor"; + var detected = jscolor.detectDir(); + jscolor.dir = detected!==false ? detected : 'assets/frappe/js/lib/'; } return jscolor.dir; }, @@ -75,7 +75,7 @@ var jscolor = { var prop = {}; if(m[3]) { try { - eval('prop='+m[3]); + prop = (new Function ('return (' + m[3] + ')'))(); } catch(eInvalidProp) {} } e[i].color = new jscolor.color(e[i], prop); @@ -261,7 +261,7 @@ var jscolor = { t.path = removeDotSegments(r.path); t.query = r.query; } else { - if(r.path === '') { // TODO: == or === ? + if(r.path === '') { t.path = base.path; if(r.query !== null) { t.query = r.query; @@ -272,7 +272,7 @@ var jscolor = { if(r.path.substr(0,1) === '/') { t.path = removeDotSegments(r.path); } else { - if(base.authority !== null && base.path === '') { // TODO: == or === ? + if(base.authority !== null && base.path === '') { t.path = '/'+r.path; } else { t.path = base.path.replace(/[^\/]+$/,'')+r.path; @@ -318,10 +318,10 @@ var jscolor = { }, - /* - * Usage example: - * var myColor = new jscolor.color(myInputElement) - */ + // + // Usage example: + // var myColor = new jscolor.color(myInputElement) + // color : function(target, prop) { @@ -336,6 +336,12 @@ var jscolor = { this.onImmediateChange = null; // onchange callback (can be either string or function) this.hsv = [0, 0, 1]; // read-only 0-6, 0-1, 0-1 this.rgb = [1, 1, 1]; // read-only 0-1, 0-1, 0-1 + this.minH = 0; // read-only 0-6 + this.maxH = 6; // read-only 0-6 + this.minS = 0; // read-only 0-1 + this.maxS = 1; // read-only 0-1 + this.minV = 0; // read-only 0-1 + this.maxV = 1; // read-only 0-1 this.pickerOnfocus = true; // display picker on focus? this.pickerMode = 'HSV'; // HSV | HVS @@ -459,34 +465,44 @@ var jscolor = { this.fromHSV = function(h, s, v, flags) { // null = don't change - h<0 && (h=0) || h>6 && (h=6); - s<0 && (s=0) || s>1 && (s=1); - v<0 && (v=0) || v>1 && (v=1); + if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); } + if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); } + if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); } + this.rgb = HSV_RGB( h===null ? this.hsv[0] : (this.hsv[0]=h), s===null ? this.hsv[1] : (this.hsv[1]=s), v===null ? this.hsv[2] : (this.hsv[2]=v) ); + this.exportColor(flags); }; this.fromRGB = function(r, g, b, flags) { // null = don't change - r<0 && (r=0) || r>1 && (r=1); - g<0 && (g=0) || g>1 && (g=1); - b<0 && (b=0) || b>1 && (b=1); + if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); } + if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); } + if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); } + var hsv = RGB_HSV( - r===null ? this.rgb[0] : (this.rgb[0]=r), - g===null ? this.rgb[1] : (this.rgb[1]=g), - b===null ? this.rgb[2] : (this.rgb[2]=b) + r===null ? this.rgb[0] : r, + g===null ? this.rgb[1] : g, + b===null ? this.rgb[2] : b ); if(hsv[0] !== null) { - this.hsv[0] = hsv[0]; + this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0])); } if(hsv[2] !== 0) { - this.hsv[1] = hsv[1]; + this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1])); } - this.hsv[2] = hsv[2]; + this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2])); + + // update RGB according to final HSV, as some values might be trimmed + var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]); + this.rgb[0] = rgb[0]; + this.rgb[1] = rgb[1]; + this.rgb[2] = rgb[2]; + this.exportColor(flags); }; @@ -611,6 +627,23 @@ var jscolor = { dispatchImmediateChange(); } }; + if('ontouchstart' in window) { // if touch device + var handle_touchmove = function(e) { + var event={ + 'offsetX': e.touches[0].pageX-touchOffset.X, + 'offsetY': e.touches[0].pageY-touchOffset.Y + }; + if (holdPad || holdSld) { + holdPad && setPad(event); + holdSld && setSld(event); + dispatchImmediateChange(); + } + e.stopPropagation(); // prevent move "view" on broswer + e.preventDefault(); // prevent Default - Android Fix (else android generated only 1-2 touchmove events) + }; + p.box.removeEventListener('touchmove', handle_touchmove, false) + p.box.addEventListener('touchmove', handle_touchmove, false) + } p.padM.onmouseup = p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } }; p.padM.onmousedown = function(e) { @@ -619,17 +652,43 @@ var jscolor = { case 0: if (THIS.hsv[2] === 0) { THIS.fromHSV(null, null, 1.0); }; break; case 1: if (THIS.hsv[1] === 0) { THIS.fromHSV(null, 1.0, null); }; break; } + holdSld=false; holdPad=true; setPad(e); dispatchImmediateChange(); }; + if('ontouchstart' in window) { + p.padM.addEventListener('touchstart', function(e) { + touchOffset={ + 'X': e.target.offsetParent.offsetLeft, + 'Y': e.target.offsetParent.offsetTop + }; + this.onmousedown({ + 'offsetX':e.touches[0].pageX-touchOffset.X, + 'offsetY':e.touches[0].pageY-touchOffset.Y + }); + }); + } p.sldM.onmouseup = p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } }; p.sldM.onmousedown = function(e) { + holdPad=false; holdSld=true; setSld(e); dispatchImmediateChange(); }; + if('ontouchstart' in window) { + p.sldM.addEventListener('touchstart', function(e) { + touchOffset={ + 'X': e.target.offsetParent.offsetLeft, + 'Y': e.target.offsetParent.offsetTop + }; + this.onmousedown({ + 'offsetX':e.touches[0].pageX-touchOffset.X, + 'offsetY':e.touches[0].pageY-touchOffset.Y + }); + }); + } // picker var dims = getPickerDims(THIS); @@ -861,11 +920,13 @@ var jscolor = { function dispatchImmediateChange() { if (THIS.onImmediateChange) { + var callback; if (typeof THIS.onImmediateChange === 'string') { - eval(THIS.onImmediateChange); + callback = new Function (THIS.onImmediateChange); } else { - THIS.onImmediateChange(THIS); + callback = THIS.onImmediateChange; } + callback.call(THIS); } } @@ -878,7 +939,8 @@ var jscolor = { styleElement = jscolor.fetchElement(this.styleElement); var holdPad = false, - holdSld = false; + holdSld = false, + touchOffset = {}; var leaveValue = 1<<0, leaveStyle = 1<<1, @@ -932,4 +994,4 @@ var jscolor = { }; -jscolor.install(); +jscolor.install(); \ No newline at end of file diff --git a/frappe/templates/includes/footer_powered.html b/frappe/templates/includes/footer_powered.html index 0b7e00308b..767c8ab161 100644 --- a/frappe/templates/includes/footer_powered.html +++ b/frappe/templates/includes/footer_powered.html @@ -1 +1 @@ -Built on Frappe \ No newline at end of file +Built on Frappe \ No newline at end of file diff --git a/frappe/utils/fixtures.py b/frappe/utils/fixtures.py new file mode 100644 index 0000000000..f5e08c852e --- /dev/null +++ b/frappe/utils/fixtures.py @@ -0,0 +1,15 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals + +import frappe, os +from frappe.core.page.data_import_tool.data_import_tool import import_doclist + +def sync_fixtures(): + for app in frappe.get_installed_apps(): + if os.path.exists(frappe.get_app_path(app, "fixtures")): + for fname in os.listdir(frappe.get_app_path(app, "fixtures")): + if fname.endswith(".json"): + import_doclist(frappe.get_app_path(app, "fixtures", fname)) + \ No newline at end of file diff --git a/frappe/utils/install.py b/frappe/utils/install.py index 51364c6420..563165236e 100644 --- a/frappe/utils/install.py +++ b/frappe/utils/install.py @@ -1,6 +1,8 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt +from __future__ import unicode_literals + import frappe def before_install(): diff --git a/frappe/website/doctype/website_settings/website_settings.js b/frappe/website/doctype/website_settings/website_settings.js index 97b27f44b2..4db6bd9e05 100644 --- a/frappe/website/doctype/website_settings/website_settings.js +++ b/frappe/website/doctype/website_settings/website_settings.js @@ -3,6 +3,26 @@ // update parent select +frappe.ui.form.on("Website Settings", "refresh", function(frm) { + if(user==="Administrator") { + frm.add_custom_button("Export to Fixtures", function() { + frappe.get_value({fieldname:"app", fieldtype:"Data", label:__("App Name"), reqd:1}, function(app) { + frappe.call({ + method: "frappe.core.page.data_import_tool.data_import_tool.export_fixture", + args: { + app: app, + doctype:"Website Settings", + name:"Website Settings", + }, + callback: function(r) { + if(!r.exc) { msgprint(__("Exported")); } + } + }) + }) + }) + } +}) + $.extend(cur_frm.cscript, { refresh: function(doc) { }, diff --git a/frappe/website/doctype/website_settings/website_settings.txt b/frappe/website/doctype/website_settings/website_settings.txt index 53000ae6bc..50975bc243 100644 --- a/frappe/website/doctype/website_settings/website_settings.txt +++ b/frappe/website/doctype/website_settings/website_settings.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-30 12:58:46", "docstatus": 0, - "modified": "2014-02-13 15:31:31", + "modified": "2014-02-26 11:39:10", "modified_by": "Administrator", "owner": "Administrator" },