Merge pull request #10548 from prssanna/workflow-warning-v13
feat: Show warning if documents have workflow states that do not exist in the workflow
This commit is contained in:
commit
9cabe788d2
5 changed files with 191 additions and 3 deletions
|
|
@ -42,6 +42,8 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
this.body = this.$body.get(0);
|
||||
this.$message = $('<div class="hide modal-message"></div>').appendTo(this.modal_body);
|
||||
this.header = this.$wrapper.find(".modal-header");
|
||||
this.buttons = this.header.find('.buttons');
|
||||
this.set_indicator();
|
||||
|
||||
// make fields (if any)
|
||||
super.make();
|
||||
|
|
@ -164,6 +166,11 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
set_title(t) {
|
||||
this.$wrapper.find(".modal-title").html(t);
|
||||
}
|
||||
set_indicator() {
|
||||
if (this.indicator) {
|
||||
this.header.find('.indicator').removeClass().addClass('indicator ' + this.indicator);
|
||||
}
|
||||
}
|
||||
show() {
|
||||
// show it
|
||||
if ( this.animate ) {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,33 @@ frappe.confirm = function(message, ifyes, ifno) {
|
|||
return d;
|
||||
}
|
||||
|
||||
frappe.warn = function(title, message_html, proceed_action, primary_label) {
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: title,
|
||||
indicator: 'red',
|
||||
fields: [
|
||||
{
|
||||
fieldtype: 'HTML',
|
||||
fieldname: 'warning_message',
|
||||
options: `<div class="frappe-warning-message">${message_html}</div>`
|
||||
}
|
||||
],
|
||||
primary_action_label: primary_label,
|
||||
primary_action: () => {
|
||||
if (proceed_action) proceed_action();
|
||||
d.hide();
|
||||
},
|
||||
secondary_action_label: __("Cancel"),
|
||||
});
|
||||
|
||||
d.buttons.find('.btn-primary').removeClass('btn-primary').addClass('btn-danger');
|
||||
const modal_footer = $(`<div class="modal-footer"></div>`).insertAfter($(d.modal_body));
|
||||
modal_footer.html(d.buttons);
|
||||
|
||||
d.show();
|
||||
return d;
|
||||
};
|
||||
|
||||
frappe.prompt = function(fields, callback, title, primary_label) {
|
||||
if (typeof fields === "string") {
|
||||
fields = [{
|
||||
|
|
|
|||
|
|
@ -292,6 +292,25 @@ Object.assign(frappe.utils, {
|
|||
return frappe.utils.guess_style(text, null, true);
|
||||
},
|
||||
|
||||
get_indicator_color: function(state) {
|
||||
return frappe.db.get_list('Workflow State', {filters: {name: state}, fields: ['name', 'style']}).then(res => {
|
||||
const state = res[0];
|
||||
if (!state.style) {
|
||||
return frappe.utils.guess_colour(state.name);
|
||||
}
|
||||
const style = state.style;
|
||||
const colour_map = {
|
||||
"Success": "green",
|
||||
"Warning": "orange",
|
||||
"Danger": "red",
|
||||
"Primary": "blue",
|
||||
};
|
||||
|
||||
return colour_map[style];
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
sort: function(list, key, compare_type, reverse) {
|
||||
if(!list || list.length < 2)
|
||||
return list || [];
|
||||
|
|
|
|||
|
|
@ -5,7 +5,35 @@ frappe.ui.form.on("Workflow", {
|
|||
frm.set_query("document_type", {"issingle": 0, "istable": 0});
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if (frm.doc.document_type) {
|
||||
frm.add_custom_button(__('Go to {0} List', [frm.doc.document_type]), () => {
|
||||
frappe.set_route('List', frm.doc.document_type);
|
||||
});
|
||||
}
|
||||
|
||||
frm.events.update_field_options(frm);
|
||||
frm.ignore_warning = frm.is_new() ? true : false;
|
||||
|
||||
if (frm.is_new()) {
|
||||
return;
|
||||
}
|
||||
|
||||
frm.states = null;
|
||||
frm.trigger('make_state_table');
|
||||
frm.trigger('get_orphaned_states_and_count').then(() => {
|
||||
frm.trigger('render_state_table');
|
||||
});
|
||||
},
|
||||
validate: (frm) => {
|
||||
if (frm.ignore_warning) {
|
||||
return;
|
||||
}
|
||||
return frm.trigger('get_orphaned_states_and_count').then(() => {
|
||||
if (frm.states && frm.states.length) {
|
||||
frappe.validated = false;
|
||||
frm.trigger('create_warning_dialog');
|
||||
}
|
||||
});
|
||||
},
|
||||
document_type: function(frm) {
|
||||
frm.events.update_field_options(frm);
|
||||
|
|
@ -19,6 +47,101 @@ frappe.ui.form.on("Workflow", {
|
|||
frappe.meta.get_docfield("Workflow Document State", "update_field", frm.doc.name).options = [""].concat(resp);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
create_warning_dialog: function(frm) {
|
||||
const warning_html =
|
||||
`<p class="bold">
|
||||
${__('Are you sure you want to save this document?')}
|
||||
</p>
|
||||
<p>${__(`There are documents which have workflow states that do not exist in this Workflow.
|
||||
It is recommended that you add these states to the Workflow and change their states
|
||||
before removing these states.`)}
|
||||
</p>`;
|
||||
const message_html = warning_html + frm.state_table_html;
|
||||
let proceed_action = () => {
|
||||
frm.ignore_warning = true;
|
||||
frm.save();
|
||||
};
|
||||
|
||||
frappe.warn(__(`Worflow States Don't Exist`), message_html, proceed_action, __(`Save Anyway`));
|
||||
},
|
||||
set_table_html: function(frm) {
|
||||
|
||||
const promises = frm.states.map(r => {
|
||||
const state = r[frm.doc.workflow_state_field];
|
||||
return frappe.utils.get_indicator_color(state).then(color => {
|
||||
return `<tr>
|
||||
<td>
|
||||
<div class="indicator ${color}">
|
||||
<a class="text-muted orphaned-state">${r[frm.doc.workflow_state_field]}</a>
|
||||
</div>
|
||||
</td>
|
||||
<td>${r.count}</td></tr>`;
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(promises).then(rows => {
|
||||
const rows_html = rows.join('');
|
||||
frm.state_table_html = (`<table class="table state-table table-bordered" style="margin:0px; width: 65%">
|
||||
<thead style="font-size: 12px">
|
||||
<tr class="text-muted">
|
||||
<th>${__('State')}</th>
|
||||
<th>${__('Count')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${rows_html}
|
||||
</tbody>
|
||||
</table>`);
|
||||
});
|
||||
},
|
||||
get_orphaned_states_and_count: function(frm) {
|
||||
let states_list = [];
|
||||
frm.doc.states.map(state => states_list.push(state.state));
|
||||
return frappe.xcall('frappe.workflow.doctype.workflow.workflow.get_workflow_state_count', {
|
||||
doctype: frm.doc.document_type,
|
||||
workflow_state_field: frm.doc.workflow_state_field,
|
||||
states: states_list
|
||||
}).then(result => {
|
||||
if (result && result.length) {
|
||||
frm.states = result;
|
||||
return frm.trigger('set_table_html');
|
||||
}
|
||||
});
|
||||
},
|
||||
make_state_table: function(frm) {
|
||||
const wrapper = frm.get_field('states').$wrapper;
|
||||
if (frm.state_table) {
|
||||
frm.state_table.empty();
|
||||
}
|
||||
frm.state_table = $(`<div class="state-table"><div>`).insertAfter(wrapper);
|
||||
},
|
||||
render_state_table: function(frm) {
|
||||
if (frm.states && frm.states.length) {
|
||||
const form_state_table_html =
|
||||
`<p class="text-muted small" style="margin-top: 30px">
|
||||
${'Document States that do not exist in your Workflow'}
|
||||
</p>
|
||||
${frm.state_table_html}
|
||||
</div>`;
|
||||
frm.state_table.html(form_state_table_html);
|
||||
|
||||
$(frm.state_table).find('a.orphaned-state').on('click', (e) => {
|
||||
const state = $(e.currentTarget).text();
|
||||
let filters = {};
|
||||
filters[frm.doc.workflow_state_field] = state;
|
||||
frappe.set_route('List', frm.doc.document_type, filters);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Workflow Document State", {
|
||||
states_remove: function(frm) {
|
||||
frm.trigger('get_orphaned_states_and_count').then(() => {
|
||||
frm.trigger('render_state_table');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class Workflow(Document):
|
|||
|
||||
def update_doc_status(self):
|
||||
'''
|
||||
Checks if the docstatus of a state was updated.
|
||||
Checks if the docstatus of a state was updated.
|
||||
If yes then the docstatus of the document with same state will be updated
|
||||
'''
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
|
|
@ -112,3 +112,15 @@ class Workflow(Document):
|
|||
def get_fieldnames_for(doctype):
|
||||
return [f.fieldname for f in frappe.get_meta(doctype).fields \
|
||||
if f.fieldname not in no_value_fields]
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_workflow_state_count(doctype, workflow_state_field, states):
|
||||
states = frappe.parse_json(states)
|
||||
result = frappe.get_all(
|
||||
doctype,
|
||||
fields=[workflow_state_field, 'count(*) as count', 'docstatus'],
|
||||
filters = {'workflow_state': ['not in', states]},
|
||||
group_by = workflow_state_field
|
||||
)
|
||||
return [r for r in result if r[workflow_state_field]]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue