ソースを参照

[cleanup] document flow

version-14
Anand Doshi 9年前
コミット
c8e0384ce1
12個のファイルの変更179行の追加73行の削除
  1. +13
    -10
      frappe/desk/form/linked_with.py
  2. +2
    -1
      frappe/model/document.py
  3. +2
    -0
      frappe/public/build.json
  4. +36
    -16
      frappe/public/css/form.css
  5. +4
    -0
      frappe/public/css/indicator.css
  6. +52
    -0
      frappe/public/js/frappe/form/document_flow.js
  7. +2
    -2
      frappe/public/js/frappe/form/linked_with.js
  8. +12
    -0
      frappe/public/js/frappe/form/templates/form_document_flow.html
  9. +1
    -44
      frappe/public/js/frappe/ui/page.js
  10. +5
    -0
      frappe/public/js/legacy/form.js
  11. +45
    -0
      frappe/public/less/form.less
  12. +5
    -0
      frappe/public/less/indicator.less

+ 13
- 10
frappe/desk/form/linked_with.py ファイルの表示

@@ -11,20 +11,16 @@ import frappe.desk.form.load
@frappe.whitelist() @frappe.whitelist()
def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None): def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None):
key = "linked_with:{doctype}:{name}".format(doctype=doctype, name=name) key = "linked_with:{doctype}:{name}".format(doctype=doctype, name=name)
if isinstance(linkinfo, basestring): if isinstance(linkinfo, basestring):
# additional fields are added in linkinfo # additional fields are added in linkinfo
linkinfo = json.loads(linkinfo) linkinfo = json.loads(linkinfo)
if for_doctype: if for_doctype:
key = "{key}:{for_doctype}".format(key=key, for_doctype=for_doctype) key = "{key}:{for_doctype}".format(key=key, for_doctype=for_doctype)
if linkinfo.get(for_doctype):
linkinfo = {for_doctype: linkinfo.get(for_doctype)}
else:
return {}


results = frappe.cache().get_value(key, user=True) results = frappe.cache().get_value(key, user=True)

if results: if results:
return results return results


@@ -34,8 +30,15 @@ def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None):
if not linkinfo: if not linkinfo:
return results return results


if for_doctype:
if for_doctype in linkinfo:
# only get linked with for this particular doctype
linkinfo = { for_doctype: linkinfo.get(for_doctype) }
else:
return results

me = frappe.db.get_value(doctype, name, ["parenttype", "parent"], as_dict=True) me = frappe.db.get_value(doctype, name, ["parenttype", "parent"], as_dict=True)
for dt, link in linkinfo.items(): for dt, link in linkinfo.items():
link["doctype"] = dt link["doctype"] = dt
link_meta_bundle = frappe.desk.form.load.get_meta_bundle(dt) link_meta_bundle = frappe.desk.form.load.get_meta_bundle(dt)
@@ -44,13 +47,13 @@ def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None):
fields = [d.fieldname for d in linkmeta.get("fields", {"in_list_view":1, fields = [d.fieldname for d in linkmeta.get("fields", {"in_list_view":1,
"fieldtype": ["not in", ["Image", "HTML", "Button", "Table"]]})] \ "fieldtype": ["not in", ["Image", "HTML", "Button", "Table"]]})] \
+ ["name", "modified", "docstatus"] + ["name", "modified", "docstatus"]
if link.get("add_fields"): if link.get("add_fields"):
fields += link["add_fields"] fields += link["add_fields"]


fields = ["`tab{dt}`.`{fn}`".format(dt=dt, fn=sf.strip()) for sf in fields if sf fields = ["`tab{dt}`.`{fn}`".format(dt=dt, fn=sf.strip()) for sf in fields if sf
and "`tab" not in sf] and "`tab" not in sf]
try: try:
if link.get("get_parent"): if link.get("get_parent"):
if me and me.parent and me.parenttype == dt: if me and me.parent and me.parenttype == dt:


+ 2
- 1
frappe/model/document.py ファイルの表示

@@ -693,8 +693,9 @@ class Document(BaseDocument):
# clear linked doctypes list # clear linked doctypes list
cache.hdel("linked_doctypes", doctype) cache.hdel("linked_doctypes", doctype)


# delete linked with cache for all users
# for all users, delete linked with cache and per doctype linked with cache
cache.delete_value("user:*:linked_with:{doctype}:{name}".format(doctype=doctype, name=name)) cache.delete_value("user:*:linked_with:{doctype}:{name}".format(doctype=doctype, name=name))
cache.delete_value("user:*:linked_with:{doctype}:{name}:*".format(doctype=doctype, name=name))


_clear_cache(self) _clear_cache(self)
for d in self.get_all_children(): for d in self.get_all_children():


+ 2
- 0
frappe/public/build.json ファイルの表示

@@ -161,12 +161,14 @@
"public/js/frappe/form/templates/set_sharing.html", "public/js/frappe/form/templates/set_sharing.html",
"public/js/frappe/form/templates/form_sidebar.html", "public/js/frappe/form/templates/form_sidebar.html",
"public/js/frappe/form/templates/form_dashboard.html", "public/js/frappe/form/templates/form_dashboard.html",
"public/js/frappe/form/templates/form_document_flow.html",
"public/js/frappe/form/templates/form_links.html", "public/js/frappe/form/templates/form_links.html",
"public/js/frappe/views/formview.js", "public/js/frappe/views/formview.js",
"public/js/legacy/form.js", "public/js/legacy/form.js",
"public/js/legacy/clientscriptAPI.js", "public/js/legacy/clientscriptAPI.js",
"public/js/frappe/form/toolbar.js", "public/js/frappe/form/toolbar.js",
"public/js/frappe/form/dashboard.js", "public/js/frappe/form/dashboard.js",
"public/js/frappe/form/document_flow.js",
"public/js/frappe/form/save.js", "public/js/frappe/form/save.js",
"public/js/frappe/form/script_manager.js", "public/js/frappe/form/script_manager.js",
"public/js/frappe/form/grid.js", "public/js/frappe/form/grid.js",


+ 36
- 16
frappe/public/css/form.css ファイルの表示

@@ -30,6 +30,42 @@
.form-message { .form-message {
padding: 15px; padding: 15px;
} }
.document-flow-wrapper {
padding: 40px 15px 30px;
font-size: 12px;
border-bottom: 1px solid #EBEFF2;
}
.document-flow-wrapper .document-flow {
display: inline-block;
position: relative;
left: 50%;
transform: translateX(-50%);
}
.document-flow-wrapper .document-flow .document-flow-link-wrapper:not(:last-child) {
border-top: 1px solid #b8c2cc;
padding-right: 60px;
display: inline-block;
margin-right: -4px;
}
.document-flow-wrapper .document-flow .document-flow-link {
margin-top: -10px;
display: inline-block;
}
.document-flow-wrapper .document-flow .document-flow-link:not(.disabled):hover .document-flow-link-label,
.document-flow-wrapper .document-flow .document-flow-link:not(.disabled):focus .document-flow-link-label,
.document-flow-wrapper .document-flow .document-flow-link:not(.disabled):active .document-flow-link-label {
text-decoration: underline;
}
.document-flow-wrapper .document-flow .document-flow-link-label {
display: inline-block;
margin-left: -50%;
margin-top: 5px;
}
@media (max-width: 767px) {
.document-flow-wrapper {
display: none;
}
}
.form-dashboard { .form-dashboard {
border-bottom: 1px solid #EBEFF2; border-bottom: 1px solid #EBEFF2;
} }
@@ -477,19 +513,3 @@ select.form-control {
box-shadow: none; box-shadow: none;
} }
} }

.module-flow {
float:left;
width: 100%;
padding-top:15px;
padding-bottom:15px;
padding-left:10px;
margin-bottom:20px;
background-color: #fafbfc;
border-bottom: 1px solid #EBEFF2;
}
.module-flow a {
margin-left: 5px;
margin-right: 5px;
font-size:12px;
}

+ 4
- 0
frappe/public/css/indicator.css ファイルの表示

@@ -48,6 +48,10 @@
.indicator-right.darkgrey::after { .indicator-right.darkgrey::after {
background: #b8c2cc; background: #b8c2cc;
} }
.indicator.black::before,
.indicator-right.black::after {
background: #36414C;
}
.indicator.yellow::before, .indicator.yellow::before,
.indicator-right.yellow::after { .indicator-right.yellow::after {
background: #FEEF72; background: #FEEF72;


+ 52
- 0
frappe/public/js/frappe/form/document_flow.js ファイルの表示

@@ -0,0 +1,52 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.ui.form.DocumentFlow = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.wrapper = $('<div class="document-flow-wrapper hidden"></div>').prependTo(this.frm.layout.wrapper);
},

refresh: function() {
this.reset();
this.render();
},

reset: function() {
this.wrapper.empty().addClass('hidden');
this.linked_with = {};
},

render: function() {
var me = this;
var module = frappe.get_meta(this.frm.doctype).module
var doctypes = frappe.document_flow[module][this.frm.doctype];
if (!doctypes) {
return;
}

$(frappe.render_template('form_document_flow', {
frm: this.frm,
doctypes: doctypes,
})).appendTo(this.wrapper.removeClass('hidden'));

this.wrapper.on('click', '.document-flow-link', function() {
var doctype = $(this).attr("data-doctype");
if (me.frm.doctype != doctype) {
me.get_linked_docs(doctype);
return false;
}
});
},

get_linked_docs: function(for_doctype) {
if(!this.linked_with[for_doctype]) {
this.linked_with[for_doctype] = new frappe.ui.form.LinkedWith({
frm: this.frm,
for_doctype: for_doctype
});
}

this.linked_with[for_doctype].show();
}
});

+ 2
- 2
frappe/public/js/frappe/form/linked_with.js ファイルの表示

@@ -116,11 +116,11 @@ frappe.ui.form.LinkedWith = Class.extend({
doctype: me.frm.doctype, doctype: me.frm.doctype,
name: me.frm.docname, name: me.frm.docname,
linkinfo: me.frm.__linked_doctypes, linkinfo: me.frm.__linked_doctypes,
for_doctype: me.link_for
for_doctype: me.for_doctype
}, },
callback: function(r) { callback: function(r) {
var parent = me.dialog.fields_dict.list.$wrapper.empty(); var parent = me.dialog.fields_dict.list.$wrapper.empty();
if(keys(r.message || {}).length) { if(keys(r.message || {}).length) {
$.each(keys(r.message).sort(), function(i, doctype) { $.each(keys(r.message).sort(), function(i, doctype) {
var listview = frappe.views.get_listview(doctype, me); var listview = frappe.views.get_listview(doctype, me);


+ 12
- 0
frappe/public/js/frappe/form/templates/form_document_flow.html ファイルの表示

@@ -0,0 +1,12 @@
<div class="document-flow">
{% for dt in doctypes %}
<span class="document-flow-link-wrapper">
<a data-doctype="{{ dt }}"
class="document-flow-link {% if (dt===frm.doctype) { %} strong disabled {% } %} "
style="color: inherit;">
<span class="indicator {% if (dt===frm.doctype) { %} blue {% } else { %} darkgrey {% } %}"></span><br>
<span class="document-flow-link-label">{{ __(dt) }}</span>
</a>
</span>
{% endfor %}
</div>

+ 1
- 44
frappe/public/js/frappe/ui/page.js ファイルの表示

@@ -89,7 +89,6 @@ frappe.ui.Page = Class.extend({


this.page_form = $('<div class="page-form row hide"></div>').prependTo(this.main); this.page_form = $('<div class="page-form row hide"></div>').prependTo(this.main);
this.inner_toolbar = $('<div class="form-inner-toolbar hide"></div>').prependTo(this.main); this.inner_toolbar = $('<div class="form-inner-toolbar hide"></div>').prependTo(this.main);
this.module_flow = $('<div class="module-flow-section"></div>').appendTo(this.body);
this.icon_group = this.page_actions.find(".page-icon-group"); this.icon_group = this.page_actions.find(".page-icon-group");
}, },


@@ -410,48 +409,6 @@ frappe.ui.Page = Class.extend({


this.wrapper.trigger('view-change'); this.wrapper.trigger('view-change');
}, },
add_document_flow: function(frm){
var me = this;
$('.module-flow-section').empty();
if (frm.doctype) {
var module = frappe.get_meta(frm.doctype).module
var module_flow = frappe.module_flow[module][frm.doctype];
if (module_flow){
if (!$('.doc-flow').length) {
$('<div class="module-flow"></div>').prependTo(this.module_flow.removeClass("hide"));
}
$.each(module_flow, function(i, doc) {
var doctype = doc;
if (doc == frm.doctype) {
doctype = "<b>"+__(doc)+"</b>"
}
$('<a data-name="'+__(doc)+'">'+__(doctype)+' </a>').on("click", function(){
me.get_linked_docs(frm, $(this).attr("data-name"))
}).appendTo('.module-flow')
if((module_flow.length-1) != i){
$('<span> > </span>').appendTo('.module-flow')
}
})
}
}
},
get_linked_docs: function(frm, link_for) {
this.linked_with = null;
if(!this.linked_with) {
this.linked_with = new frappe.ui.form.LinkedWith({
frm: frm,
link_for: link_for
});
}
this.linked_with.show();
}
}); });


frappe.ui.scroll = function(element, animate, additional_offset) { frappe.ui.scroll = function(element, animate, additional_offset) {
@@ -462,4 +419,4 @@ frappe.ui.scroll = function(element, animate, additional_offset) {
} else { } else {
$(window).scrollTop(top); $(window).scrollTop(top);
} }
}
}

+ 5
- 0
frappe/public/js/legacy/form.js ファイルの表示

@@ -253,6 +253,10 @@ _f.Frm.prototype.setup_std_layout = function() {
this.fields_dict = this.layout.fields_dict; this.fields_dict = this.layout.fields_dict;
this.fields = this.layout.fields_list; this.fields = this.layout.fields_list;


this.document_flow = new frappe.ui.form.DocumentFlow({
frm: this
});

this.dashboard = new frappe.ui.form.Dashboard({ this.dashboard = new frappe.ui.form.Dashboard({
frm: this, frm: this,
}); });
@@ -341,6 +345,7 @@ _f.Frm.prototype.refresh_header = function(is_a_different_doc) {
this.toolbar.refresh(); this.toolbar.refresh();
} }


this.document_flow.refresh();
this.dashboard.reset(); this.dashboard.reset();


this.clear_custom_buttons(); this.clear_custom_buttons();


+ 45
- 0
frappe/public/less/form.less ファイルの表示

@@ -40,6 +40,51 @@
padding: 15px; padding: 15px;
} }


.document-flow-wrapper {
padding: 40px 15px 30px;
font-size: @text-medium;
border-bottom: 1px solid @light-border-color;

.document-flow {
display: inline-block;
position: relative;
left: 50%;
transform: translateX(-50%);

.document-flow-link-wrapper:not(:last-child) {
border-top: 1px solid @indicator-darkgrey;
padding-right: 60px;
display: inline-block;
margin-right: -4px;
}

.document-flow-link {
margin-top: -10px;
display: inline-block;
}

.document-flow-link:not(.disabled):hover,
.document-flow-link:not(.disabled):focus,
.document-flow-link:not(.disabled):active {
.document-flow-link-label {
text-decoration: underline;
}
}

.document-flow-link-label {
display: inline-block;
margin-left: -50%;
margin-top: 5px;
}
}
}

@media(max-width: @screen-xs) {
.document-flow-wrapper {
display: none;
}
}

.form-dashboard { .form-dashboard {
border-bottom: 1px solid @light-border-color; border-bottom: 1px solid @light-border-color;
} }


+ 5
- 0
frappe/public/less/indicator.less ファイルの表示

@@ -55,6 +55,11 @@
background: @indicator-darkgrey; background: @indicator-darkgrey;
} }


.indicator.black::before,
.indicator-right.black::after {
background: @text-color;
}

.indicator.yellow::before, .indicator.yellow::before,
.indicator-right.yellow::after { .indicator-right.yellow::after {
background: @indicator-yellow; background: @indicator-yellow;


読み込み中…
キャンセル
保存