Merge branch 'responsive' of git://github.com/webnotes/wnframework into responsive

This commit is contained in:
Nabin Hait 2013-07-04 15:56:53 +05:30
commit 8308e8594b
18 changed files with 297 additions and 126 deletions

View file

@ -306,3 +306,4 @@ class DocType:
if hasattr(conf, 'developer_mode') and conf.developer_mode:
from webnotes.modules.export_file import export_to_files
export_to_files(record_list=[[self.doc.doctype, self.doc.name]])

View file

@ -17,9 +17,6 @@
"lib/public/css/bootstrap-responsive.css",
"lib/public/css/font-awesome.css",
"lib/public/css/legacy/forms.css",
"lib/public/css/legacy/fields.css",
"lib/public/css/legacy/dialog.css",
"lib/public/css/legacy/tabs.css",
"lib/public/css/ui/common.css",
"lib/public/css/views/tree_grid.css",
]
@ -38,9 +35,6 @@
"lib/public/js/lib/jquery/jquery.hotkeys.js",
"lib/public/js/lib/center_image.js",
"lib/public/js/lib/bootstrap.min.js",
"lib/public/js/lib/tiny_mce_3.5.7/jquery.tinymce.js:concat",
"lib/public/js/lib/mousetrap.min.js",
"lib/public/js/wn/provide.js",
"lib/public/js/wn/class.js",

View file

@ -1,75 +0,0 @@
/***** Dialogs *******/
div.dialog_wrapper {
position: absolute;
width: 440px;
display: none;
z-index: 2;
background-color: #FFF;
box-shadow:1px 1px 8px #444;
-moz-box-shadow: 1px 1px 8px #444;
-webkit-box-shadow: 1px 1px 8px #444;
border-radius: 5px;
overflow: hidden;
}
div.dialog_head {
height: 22px;
padding: 4px;
background-color: #222;
color: #FFF;
}
div.dialog_body {
padding: 8px 8px 16px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
div#freeze {
position: fixed;
display: none;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
background-color: #aaa;
opacity: 0.6;
z-index: 1;
text-align: center;
}
div.dialog_message {
display: none;
position: absolute;
width: 250px;
font-size: 12px;
z-index: 91;
background-color:#FFF;
padding: 12px;
border: 1px solid #444;
}
div.dialog_row {
padding: 8px 8px 0px 8px;
}
div.dialog_row table {
width: 100%;
}
div.dialog_row table td {
}
div.dialog_row input[type="text"], div.dialog_row input[type="password"], div.dialog_row textarea, div.dialog_row select {
width: 80%;
font-size: 14px;
}
div.dialog_row table td textarea {
width: 80%;
height: 200px;
font-size: 12px;
}

View file

@ -5,13 +5,6 @@
/* Documents */
.help ol {
padding-left: 19px;
}
.field_description_top {
margin-bottom: 3px;
}
.link-field .btn {

View file

@ -22,6 +22,21 @@ a {
padding-bottom: 10px;
}
/* freeze */
div#freeze {
position: fixed;
display: none;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
background-color: #aaa;
opacity: 0.6;
z-index: 1;
text-align: center;
}
/* listing */
.list-row {
@ -71,6 +86,18 @@ a {
border-bottom: 1px solid #ddd;
}
.help ol {
padding-left: 19px;
}
.field_description_top {
margin-bottom: 3px;
}
.link-field .btn {
padding-left: 6px;
padding-right: 6px;
}
/* module */
.module-item-progress {
@ -171,6 +198,12 @@ a {
font-size: 24px;
}
.appframe .sub-title-area {
margin-top: -25px;
margin-left: 75px;
font-size: 120%;
}
.appframe .title-icon:active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.3);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.3);

View file

@ -165,7 +165,7 @@ _f.Frm.prototype.get_doclist = function() {
}
_f.Frm.prototype.field_map = function(fnames, fn) {
if(typeof fnames=='string') {
if(typeof fnames==='string') {
if(fnames == '*') {
fnames = keys(this.fields_dict);
} else {

View file

@ -151,8 +151,8 @@ _f.Frm.prototype.watch_model_updates = function() {
if(doc.name===me.docname) {
me.fields_dict[fieldname]
&& me.fields_dict[fieldname].refresh(fieldname);
me.script_manager.trigger(fieldname, doc.doctype, doc.name);
me.refresh_dependency();
me.script_manager.trigger(fieldname, doc.doctype, doc.name);
}
})

View file

@ -1,19 +1,22 @@
wn.ui.form.Dashboard = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.wrapper = $('<div class="row form-dashboard">')
this.wrapper = $('<div class="form-dashboard row"></div>')
.prependTo(this.frm.layout.wrapper);
this.body = $('<div></div>').appendTo(this.wrapper);
},
reset: function(doc) {
this.wrapper.empty().toggle(doc.__islocal ? false : true);
reset: function() {
this.wrapper.toggle(false);
this.body.empty();
this.headline = null;
},
set_headline: function(html) {
if(!this.headline)
this.headline =
$('<div class="form-headline col col-lg-12">').prependTo(this.wrapper);
$('<div class="form-headline col col-lg-12">').prependTo(this.body);
this.headline.html(html);
this.wrapper.toggle(true);
},
set_headline_alert: function(text, alert_class, icon) {
this.set_headline(repl('<div class="alert %(alert_class)s">%(icon)s%(text)s</div>', {
@ -37,9 +40,10 @@ wn.ui.form.Dashboard = Class.extend({
<a class="badge-link">%(label)s</a>\
<span class="badge pull-right">-</span>\
</div></div>', {label:label}))
.appendTo(this.wrapper)
.appendTo(this.body)
badge.find(".badge-link").click(onclick);
this.wrapper.toggle(true);
return badge.find(".alert-badge");
},
@ -51,5 +55,36 @@ wn.ui.form.Dashboard = Class.extend({
.html(cint(count));
});
},
add_progress: function(title, percent) {
var width = cint(percent) < 1 ? 1 : percent;
var progress_class = "";
if(width < 10)
progress_class = "progress-bar-danger";
if(width > 99.9)
progress_class = "progress-bar-success";
var progress_area = this.body.find(".progress-area");
if(!progress_area.length) {
progress_area = $('<div class="progress-area">').appendTo(this.body);
}
$(repl('<div class="progress-chart">\
<h5>%(title)s</h5>\
<div class="progress">\
<div class="progress-bar %(progress_class)s" style="width: %(width)s%"></div>\
</div>\
</div>', {
title:title,
width: width,
progress_class: progress_class
})).appendTo(progress_area);
var n_charts = progress_area.find(".progress-chart").length,
cols = Math.floor(12 / n_charts);
progress_area.find(".progress-chart")
.removeClass().addClass("progress-chart col col-lg-" + cols);
this.wrapper.toggle(true);
}
})

View file

@ -163,7 +163,7 @@ wn.ui.form.GridRow = Class.extend({
<button class="btn btn-success pull-right" \
title="'+wn._("Close")+'"\
style="margin-left: 7px;">\
<i class="icon-ok"></i></button>\
<i class="icon-chevron-up"></i></button>\
<button class="btn btn-default pull-right grid-insert-row" \
title="'+wn._("Insert Row")+'"\
style="margin-left: 7px;">\

View file

@ -46,7 +46,7 @@ wn.ui.form.Layout = Class.extend({
<form>\
<fieldset></fieldset>\
</form>\
</div>').appendTo(this.section)
</div>').appendTo(this.section.body)
.find("form")
.on("submit", function() { return false; })
.find("fieldset");
@ -83,11 +83,7 @@ wn.ui.form.Layout = Class.extend({
+ df.label
+ "</h3>")
.css({
"margin-bottom": "15px",
"font-weight": "bold",
// "color": "white",
// "background-color": "#16a085",
// "padding": "7px"
})
.appendTo(this.section);
if(this.frm.sections.length > 1)
@ -99,10 +95,16 @@ wn.ui.form.Layout = Class.extend({
if(df.description) {
$('<div class="col col-lg-12 small text-muted">' + df.description + '</div>').appendTo(this.section);
}
if(df.label || df.description) {
$('<div class="col col-lg-12"></div>')
.appendTo(this.section)
.css({"height": "20px"});
}
this.frm.fields_dict[df.fieldname] = section;
this.frm.fields.push(section);
}
// for bc
this.section.body = $('<div style="padding: 0px 3%">').appendTo(this.section);
section.row = {
wrapper: section
};

View file

@ -34,6 +34,7 @@ wn.ui.form.Toolbar = Class.extend({
title = title.substr(0,30) + "...";
}
this.appframe.set_title(title, wn._(this.frm.docname));
this.appframe.set_sub_title(wn._(this.frm.doctype));
},
show_infobar: function() {
/* docs:
@ -148,7 +149,7 @@ wn.ui.form.Toolbar = Class.extend({
var status_bar_parent = this.frm.appframe.$w.find(".status-bar").empty();
if(this.frm.meta.is_submittable && !this.frm.doc.__islocal) {
var status_bar = $("<h4>")
.css({"margin": "0px"})
.css({"margin": "0px", "margin-top": "-15px"})
.appendTo(status_bar_parent);
switch(this.frm.doc.docstatus) {

View file

@ -4,7 +4,7 @@ $.extend(wn.model, {
new_names: {},
new_name_count: {},
get_new_doc: function(doctype) {
get_new_doc: function(doctype, parent_doc) {
wn.provide("locals." + doctype);
var doc = {
docstatus: 0,
@ -14,10 +14,10 @@ $.extend(wn.model, {
__unsaved: 1,
owner: user
};
wn.model.set_default_values(doc);
wn.model.set_default_values(doc, parent_doc);
locals[doctype][doc.name] = doc;
wn.provide("wn.model.docinfo." + doctype + "." + doc.name);
return doc;
return doc;
},
make_new_doc_and_get_name: function(doctype) {
@ -32,7 +32,7 @@ $.extend(wn.model, {
return 'New '+ doctype + ' ' + cnt[doctype];
},
set_default_values: function(doc) {
set_default_values: function(doc, parent_doc) {
var doctype = doc.doctype;
var docfields = wn.meta.docfield_list[doctype] || [];
var updated = [];
@ -40,7 +40,7 @@ $.extend(wn.model, {
for(var fid=0;fid<docfields.length;fid++) {
var f = docfields[fid];
if(!in_list(wn.model.no_value_type, f.fieldtype) && doc[f.fieldname]==null) {
var v = wn.model.get_default_value(f, doc);
var v = wn.model.get_default_value(f, doc, parent_doc);
if(v) {
if(in_list(["Int", "Check"], f.fieldtype))
v = cint(v);
@ -55,32 +55,31 @@ $.extend(wn.model, {
return updated;
},
get_default_value: function(df, doc) {
get_default_value: function(df, doc, parent_doc) {
var def_vals = {
"_Login": user,
"__user": user,
"Today": dateutil.get_today(),
"__today": dateutil.get_today(),
"Now": dateutil.get_cur_time()
}
if(def_vals[df["default"]])
if(wn.defaults.get_user_default(df.fieldname))
return wn.defaults.get_user_default(df.fieldname);
else if(df["default"] && df["default"][0]===":")
return wn.model.get_default_from_boot_docs(df, doc, parent_doc);
else if(def_vals[df["default"]])
return def_vals[df["default"]];
else if(df.fieldtype=="Time" && (!df["default"]))
return dateutil.get_cur_time()
else if(df["default"] && df["default"][0]!==":")
return df["default"];
else if(wn.defaults.get_user_default(df.fieldname))
return wn.defaults.get_user_default(df.fieldname);
else if(df["default"] && df["default"][0]===":")
return wn.model.get_default_from_boot_docs(df, doc);
},
get_default_from_boot_docs: function(df, doc) {
get_default_from_boot_docs: function(df, doc, parent_doc) {
// set default from partial docs passed during boot like ":Profile"
if(wn.model.get(df["default"]).length > 0) {
var ref_fieldname = df["default"].slice(1).toLowerCase().replace(" ", "_");
var ref_value = (doc && doc[ref_fieldname]) || (cur_frm && cur_frm.doc[ref_fieldname]);
var ref_value = parent_doc ?
parent_doc[ref_fieldname] :
wn.defaults.get_user_default(ref_fieldname);
var ref_doc = ref_value ? wn.model.get_doc(df["default"], ref_value) : null;
if(ref_doc && ref_doc[df.fieldname]) {
@ -96,7 +95,7 @@ $.extend(wn.model, {
wn.model.get_children(doctype, parent_doc.name, parentfield,
parent_doc.doctype).length + 1;
var d = wn.model.get_new_doc(doctype);
var d = wn.model.get_new_doc(doctype, parent_doc);
$.extend(d, {
parent: parent_doc.name,
parentfield: parentfield,
@ -129,4 +128,20 @@ $.extend(wn.model, {
return newdoc;
},
open_mapped_doc: function(opts) {
wn.call({
type: "GET",
method: opts.method,
args: {
"source_name": opts.source_name
},
callback: function(r) {
if(!r.exc) {
var doclist = wn.model.sync(r.message);
wn.set_route("Form", doclist[0].doctype, doclist[0].name);
}
}
})
}
})

View file

@ -35,10 +35,20 @@ $.extend(wn.model, {
if(doclist && doclist.length)
wn.model.clear_doclist(doclist[0].doctype, doclist[0].name)
var last_parent_name = null;
$.each(doclist, function(i, d) {
if(!d.name) // get name (local if required)
if(!d.name && d.__islocal) { // get name (local if required)
d.name = wn.model.get_new_name(d.doctype);
wn.provide("wn.model.docinfo." + d.doctype + "." + d.name);
if(!d.parenttype)
last_parent_name = d.name;
}
// set parent for subsequent orphans
if(d.parenttype && !d.parent && d.__islocal) {
d.parent = last_parent_name;
}
if(!locals[d.doctype])
locals[d.doctype] = {};

View file

@ -19,8 +19,7 @@ wn.ui.AppFrame = Class.extend({
<div class="title-area"><h2 style="display: inline-block">\
<span class="title-icon" style="display: none"></span>\
<span class="title-text"></span></h2></div>\
<div class="sub-title-area text-muted small" \
style="margin-top: -10px;"></div>\
<div class="sub-title-area text-muted small">&nbsp;</div>\
<div class="status-bar"></div>\
</div>\
</div>\
@ -71,6 +70,13 @@ wn.ui.AppFrame = Class.extend({
add_module_icon: function(module) {
var module_info = wn.modules[module];
if(!module_info) {
module_info = {
icon: "icon-question-sign",
color: "#eeeeee"
}
}
if(module_info && module_info.icon) {
this.$w.find(".title-icon").html('<i class="'
+module_info.icon+'"></i> ')
@ -80,7 +86,8 @@ wn.ui.AppFrame = Class.extend({
})
.attr("module-name", module)
.click(function() {
wn.set_route(wn.modules[$(this).attr("module-name")].link);
var module_info = wn.modules[$(this).attr("module-name")];
wn.set_route(module_info ? module_info.link : "desktop");
});
}
},

View file

@ -160,7 +160,7 @@ def connect(db_name=None, password=None):
import webnotes.profile
global user
user = webnotes.profile.Profile('Administrator')
def get_env_vars(env_var):
import os
return os.environ.get(env_var,'None')
@ -300,6 +300,10 @@ def doc(doctype=None, name=None, fielddata=None):
from webnotes.model.doc import Document
return Document(doctype, name, fielddata)
def new_doc(doctype, parent_doc=None, parentfield=None):
from webnotes.model.create_new import get_new_doc
return get_new_doc(doctype, parent_doc, parentfield)
def doclist(lst=None):
from webnotes.model.doclist import DocList
return DocList(lst)

View file

@ -91,7 +91,9 @@ def dt_map():
from_to_list = form_dict.get('from_to_list')
dm = get_obj('DocType Mapper', from_doctype +'-' + to_doctype)
dl = dm.dt_map(from_doctype, to_doctype, from_docname, Document(fielddata = dt_list[0]), (len(dt_list) > 1) and Bean(dt_list).doclist or [], from_to_list)
dl = dm.dt_map(from_doctype, to_doctype, from_docname,
Document(fielddata = dt_list[0]),
(len(dt_list) > 1) and Bean(dt_list).doclist or [], from_to_list)
webnotes.response['docs'] = dl

View file

@ -0,0 +1,53 @@
from __future__ import unicode_literals
"""
Create a new document with defaults set
"""
import webnotes
from webnotes.utils import nowdate, nowtime, cint, flt
def get_new_doc(doctype, parent_doc = None, parentfield = None):
doc = webnotes.doc({
"doctype": doctype,
"__islocal": 1
})
meta = webnotes.get_doctype(doctype)
if parent_doc:
doc.parent = parent_doc.name
doc.parenttype = parent_doc.doctype
doc.parentfield = parentfield
for d in meta.get({"doctype":"DocField", "parent": doctype}):
default = webnotes.conn.get_default(d.fieldname)
if default:
doc.fields[d.fieldname] = default
elif d.fields.get("default"):
if d.default == "__user":
doc.fields[d.fieldname] = webnotes.session.user
elif d.default == "Today":
doc.fields[d.fieldname] = nowdate()
elif d.default.startswith(":"):
ref_fieldname = d.default[1:].lower().replace(" ", "_")
if parent_doc:
ref_docname = parent_doc.fields[ref_fieldname]
else:
ref_docname = webnotes.conn.get_default(ref_fieldname)
doc.fields[d.fieldname] = webnotes.conn.get_value(d.default[1:],
ref_docname, d.fieldname)
else:
doc.fields[d.fieldname] = d.default
# convert type of default
if d.fieldtype in ("Int", "Check"):
doc.fields[d.fieldname] = cint(doc.fields[d.fieldname])
elif d.fieldtype in ("Float", "Currency"):
doc.fields[d.fieldname] = flt(doc.fields[d.fieldname])
elif d.fieldtype == "Time":
doc.fields[d.fieldname] = nowtime()
return doc

96
webnotes/model/mapper.py Normal file
View file

@ -0,0 +1,96 @@
# Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
#
# MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
from __future__ import unicode_literals
import webnotes, json
from webnotes import _
from webnotes.utils import cstr
from webnotes.model import default_fields
def get_mapped_doclist(from_doctype, from_docname, table_maps, target_doclist=[]):
if not webnotes.has_permission(from_doctype, from_docname):
webnotes.msgprint("No Permission", raise_exception=webnotes.PermissionError)
source = webnotes.bean(from_doctype, from_docname)
source_meta = webnotes.get_doctype(from_doctype)
target_meta = webnotes.get_doctype(table_maps[from_doctype]["doctype"])
# main
if target_doclist:
target_doc = webnotes.doc(target_doclist[0])
else:
target_doc = webnotes.new_doc(table_maps[from_doctype]["doctype"])
map_doc(source.doc, target_doc, table_maps[source.doc.doctype], source_meta, target_meta)
doclist = [target_doc]
# children
for source_d in source.doclist[1:]:
target_doctype = table_maps[source_d.doctype]["doctype"]
parentfield = target_meta.get({
"parent": target_doc.doctype,
"doctype": "DocField",
"fieldtype": "Table",
"options": target_doctype
})[0].fieldname
target_d = webnotes.new_doc(target_doctype, target_doc, parentfield)
map_doc(source_d, target_d, table_maps[source_d.doctype], source_meta, target_meta)
doclist.append(target_d)
return doclist
def map_doc(source_doc, target_doc, table_map, source_meta, target_meta):
no_copy_fields = set(\
[d.fieldname for d in source_meta.get({"no_copy": 1,
"parent": source_doc.doctype})] \
+ [d.fieldname for d in target_meta.get({"no_copy": 1,
"parent": target_doc.doctype})] \
+ default_fields)
if table_map.get("validation"):
for key, condition in table_map["validation"].items():
if condition[0]=="=":
if source_doc.fields.get(key) != condition[1]:
webnotes.msgprint(_("Cannot map because following condition fails: ")
+ key + "=" + cstr(condition[1]), raise_exception=webnotes.ValidationError)
# map same fields
target_fields = target_meta.get({"doctype": "DocField", "parent": target_doc.doctype})
for key in [d.fieldname for d in target_fields]:
if key not in no_copy_fields:
val = source_doc.fields.get(key)
if val not in (None, ""):
target_doc.fields[key] = val
# map other fields
for source_key, target_key in table_map.get("field_map", {}).items():
val = source_doc.fields.get(source_key)
if val not in (None, ""):
target_doc.fields[target_key] = val
# map idx
if source_doc.idx:
target_doc.idx = source_doc.idx