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"
},