@@ -1,5 +1,6 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_guest_to_view": 0, | |||
"allow_import": 0, | |||
"allow_rename": 1, | |||
"autoname": "field:kanban_board_name", | |||
@@ -22,6 +23,8 @@ | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Kanban Board Name", | |||
@@ -49,6 +52,8 @@ | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 0, | |||
"label": "Reference DocType", | |||
@@ -77,6 +82,8 @@ | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Field Name", | |||
@@ -104,6 +111,8 @@ | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"length": 0, | |||
@@ -130,6 +139,8 @@ | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Columns", | |||
@@ -155,9 +166,11 @@ | |||
"columns": 0, | |||
"fieldname": "filters", | |||
"fieldtype": "Text", | |||
"hidden": 0, | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Filters", | |||
@@ -174,20 +187,49 @@ | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "private", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Private", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 1, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
} | |||
], | |||
"has_web_view": 0, | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 0, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2017-02-09 12:23:30.059564", | |||
"modified_by": "Administrator", | |||
"modified": "2017-03-14 23:02:13.267243", | |||
"modified_by": "faris@erpnext.com", | |||
"module": "Desk", | |||
"name": "Kanban Board", | |||
"name_case": "", | |||
@@ -217,6 +259,7 @@ | |||
"quick_entry": 0, | |||
"read_only": 0, | |||
"read_only_onload": 0, | |||
"show_name_in_global_search": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 0, | |||
@@ -11,10 +11,29 @@ from frappe.model.document import Document | |||
class KanbanBoard(Document): | |||
def validate(self): | |||
self.validate_column_name() | |||
def validate_column_name(self): | |||
for column in self.columns: | |||
if not column.column_name: | |||
frappe.msgprint(frappe._("Column Name cannot be empty"), raise_exception=True) | |||
def get_permission_query_conditions(user): | |||
if not user: user = frappe.session.user | |||
if user == "Administrator": | |||
return "" | |||
return """(`tabKanban Board`.private=0 or `tabKanban Board`.owner="{user}")""".format(user=user) | |||
def has_permission(doc, ptype, user): | |||
if doc.private == 0 or user == "Administrator": | |||
return True | |||
if user == doc.owner: | |||
return True | |||
return False | |||
@frappe.whitelist() | |||
def add_column(board_name, column_title): | |||
@@ -118,6 +137,18 @@ def quick_kanban_board(doctype, board_name, field_name): | |||
doc.kanban_board_name = board_name | |||
doc.reference_doctype = doctype | |||
doc.field_name = field_name | |||
if doctype == 'Task': | |||
project = frappe.new_doc('Project') | |||
project.project_name = board_name | |||
project.status = 'Open' | |||
project.save() | |||
doc.filters = '[["Task","project","=","{0}"]]'.format(board_name) | |||
if doctype == 'Note': | |||
doc.private = 1 | |||
doc.save() | |||
return doc | |||
@@ -176,12 +176,12 @@ class FormMeta(Meta): | |||
self.load_kanban_column_fields() | |||
def load_kanban_boards(self): | |||
kanban_boards = frappe.get_all( | |||
'Kanban Board', fields=['name', 'filters', 'reference_doctype'], filters={'reference_doctype': self.name}) | |||
kanban_boards = frappe.get_list( | |||
'Kanban Board', fields=['name', 'filters', 'reference_doctype', 'private'], filters={'reference_doctype': self.name}) | |||
self.set("__kanban_boards", kanban_boards, as_value=True) | |||
def load_kanban_column_fields(self): | |||
values = frappe.get_all( | |||
values = frappe.get_list( | |||
'Kanban Board', fields=['field_name'], | |||
filters={'reference_doctype': self.name}) | |||
@@ -78,6 +78,7 @@ permission_query_conditions = { | |||
"ToDo": "frappe.desk.doctype.todo.todo.get_permission_query_conditions", | |||
"User": "frappe.core.doctype.user.user.get_permission_query_conditions", | |||
"Note": "frappe.desk.doctype.note.note.get_permission_query_conditions", | |||
"Kanban Board": "frappe.desk.doctype.kanban_board.kanban_board.get_permission_query_conditions", | |||
"Contact": "frappe.geo.address_and_contact.get_permission_query_conditions_for_contact", | |||
"Address": "frappe.geo.address_and_contact.get_permission_query_conditions_for_address" | |||
} | |||
@@ -87,6 +88,7 @@ has_permission = { | |||
"ToDo": "frappe.desk.doctype.todo.todo.has_permission", | |||
"User": "frappe.core.doctype.user.user.has_permission", | |||
"Note": "frappe.desk.doctype.note.note.has_permission", | |||
"Kanban Board": "frappe.desk.doctype.kanban_board.kanban_board.has_permission", | |||
"Contact": "frappe.geo.address_and_contact.has_permission", | |||
"Address": "frappe.geo.address_and_contact.has_permission", | |||
"Communication": "frappe.core.doctype.communication.communication.has_permission", | |||
@@ -130,16 +130,18 @@ frappe.views.ListSidebar = Class.extend({ | |||
$('<li role="separator" class="divider"></li>').appendTo($dropdown); | |||
divider = true; | |||
} | |||
$(`<li><a href="#${route}">${__(board.name)}</a></li>`).appendTo($dropdown); | |||
$(`<li><a href="#${route}"> | |||
<span>${__(board.name)}</span> | |||
${board.private ? '<i class="fa fa-lock fa-fw text-warning"></i>' : ''} | |||
</a></li>`).appendTo($dropdown); | |||
}); | |||
$dropdown.find('.new-kanban-board').click(function() { | |||
// frappe.new_doc('Kanban Board', {reference_doctype: me.doctype}); | |||
var select_fields = frappe.get_meta(me.doctype) | |||
.fields.filter(function(df) { | |||
return df.fieldtype === 'Select'; | |||
}).map(function(df) { | |||
return df.fieldname; | |||
return df.fieldtype === 'Select' && | |||
df.fieldname !== 'kanban_column'; | |||
}); | |||
var fields = [ | |||
@@ -149,45 +151,61 @@ frappe.views.ListSidebar = Class.extend({ | |||
label: __('Kanban Board Name'), | |||
reqd: 1 | |||
} | |||
] | |||
]; | |||
if(select_fields.length > 0) { | |||
fields = fields.concat([{ | |||
fieldtype: 'Select', | |||
fieldname: 'field_name', | |||
label: __('Columns based on'), | |||
options: select_fields.join('\n'), | |||
options: select_fields.map(df => df.label).join('\n'), | |||
default: select_fields[0] | |||
}, | |||
{ | |||
fieldtype: 'Check', | |||
fieldname: 'custom_column', | |||
label: __('Add Custom Column Field'), | |||
label: __('Custom Column'), | |||
default: 0, | |||
onchange: function(e) { | |||
var checked = d.get_value('custom_column'); | |||
if(checked) { | |||
d.get_input('field_name').prop('disabled', true); | |||
$(d.body).find('.frappe-control[data-fieldname="field_name"]').hide(); | |||
} else { | |||
d.get_input('field_name').prop('disabled', null); | |||
$(d.body).find('.frappe-control[data-fieldname="field_name"]').show(); | |||
} | |||
} | |||
}]); | |||
} | |||
if(me.doctype === 'Task') { | |||
fields[0].description = __('A new Project with this name will be created'); | |||
} | |||
if(me.doctype === 'Note') { | |||
fields[0].description = __('This Kanban Board will be private'); | |||
} | |||
var d = new frappe.ui.Dialog({ | |||
title: __('New Kanban Board'), | |||
fields: fields, | |||
primary_action: function() { | |||
var values = d.get_values(); | |||
primary_action_label: __('Save'), | |||
primary_action: function(values) { | |||
var custom_column = values.custom_column !== undefined ? | |||
values.custom_column : 1; | |||
if(custom_column) { | |||
var field_name = 'kanban_column'; | |||
} else { | |||
var field_name = | |||
select_fields | |||
.find(df => df.label === values.field_name) | |||
.fieldname; | |||
} | |||
me.add_custom_column_field(custom_column) | |||
.then(function(custom_column) { | |||
var f = custom_column ? | |||
'kanban_column' : values.field_name; | |||
return me.make_kanban_board(values.board_name, f) | |||
return me.make_kanban_board(values.board_name, field_name) | |||
}) | |||
.then(function() { | |||
d.hide(); | |||
@@ -231,11 +249,16 @@ frappe.views.ListSidebar = Class.extend({ | |||
field_name: field_name | |||
}, | |||
callback: function(r) { | |||
var kb = r.message; | |||
if(kb.filters) { | |||
frappe.provide('frappe.kanban_filters'); | |||
frappe.kanban_filters[kb.kanban_board_name] = kb.filters; | |||
} | |||
frappe.set_route( | |||
'List', | |||
me.doctype, | |||
'Kanban', | |||
r.message.kanban_board_name | |||
kb.kanban_board_name | |||
); | |||
} | |||
}); | |||