From 074f0fcc0b8344991f4646dd6feb6622a22787ea Mon Sep 17 00:00:00 2001 From: robert schouten Date: Tue, 31 May 2016 15:53:52 +0800 Subject: [PATCH 001/176] tag catagories --- frappe/config/setup.py | 6 + frappe/core/doctype/tag/__init__.py | 0 frappe/core/doctype/tag/tag.json | 58 ++++++++ frappe/core/doctype/tag/tag.py | 11 ++ frappe/core/doctype/tag_category/__init__.py | 0 .../core/doctype/tag_category/tag_category.js | 9 ++ .../doctype/tag_category/tag_category.json | 131 ++++++++++++++++++ .../core/doctype/tag_category/tag_category.py | 10 ++ .../doctype/tag_category/test_tag_category.py | 12 ++ .../core/doctype/tag_doc_category/__init__.py | 0 .../tag_doc_category/tag_doc_category.json | 58 ++++++++ .../tag_doc_category/tag_doc_category.py | 10 ++ frappe/desk/reportview.py | 11 ++ frappe/desk/tags.py | 14 +- frappe/public/js/frappe/list/doclistview.js | 27 ++-- frappe/public/js/frappe/list/list_sidebar.js | 80 +++++++++-- frappe/public/js/frappe/list/listview.js | 1 + frappe/public/js/frappe/ui/tags.js | 4 +- 18 files changed, 418 insertions(+), 24 deletions(-) create mode 100644 frappe/core/doctype/tag/__init__.py create mode 100644 frappe/core/doctype/tag/tag.json create mode 100644 frappe/core/doctype/tag/tag.py create mode 100644 frappe/core/doctype/tag_category/__init__.py create mode 100644 frappe/core/doctype/tag_category/tag_category.js create mode 100644 frappe/core/doctype/tag_category/tag_category.json create mode 100644 frappe/core/doctype/tag_category/tag_category.py create mode 100644 frappe/core/doctype/tag_category/test_tag_category.py create mode 100644 frappe/core/doctype/tag_doc_category/__init__.py create mode 100644 frappe/core/doctype/tag_doc_category/tag_doc_category.json create mode 100644 frappe/core/doctype/tag_doc_category/tag_doc_category.py diff --git a/frappe/config/setup.py b/frappe/config/setup.py index 07b96ea85f..a1ad6d6214 100644 --- a/frappe/config/setup.py +++ b/frappe/config/setup.py @@ -267,6 +267,12 @@ def get_data(): "type": "doctype", "name": "DocType", "description": _("Add custom forms.") + }, + { + "type": "doctype", + "label": _("Custom Tags"), + "name": "Tag Category", + "description": _("Add your own Tag Categories") } ] diff --git a/frappe/core/doctype/tag/__init__.py b/frappe/core/doctype/tag/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/tag/tag.json b/frappe/core/doctype/tag/tag.json new file mode 100644 index 0000000000..2b38a18cb6 --- /dev/null +++ b/frappe/core/doctype/tag/tag.json @@ -0,0 +1,58 @@ +{ + "allow_copy": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "", + "creation": "2016-05-25 09:43:44.767581", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "fields": [ + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "tag_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Tags", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + } + ], + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2016-05-31 08:29:01.773065", + "modified_by": "Administrator", + "module": "Core", + "name": "Tag", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "read_only": 0, + "read_only_onload": 0, + "sort_field": "modified", + "sort_order": "DESC" +} \ No newline at end of file diff --git a/frappe/core/doctype/tag/tag.py b/frappe/core/doctype/tag/tag.py new file mode 100644 index 0000000000..cc8e17e8d2 --- /dev/null +++ b/frappe/core/doctype/tag/tag.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document + +class Tag(Document): + def validate(self): + self.tag_name = self.tag_name.title() diff --git a/frappe/core/doctype/tag_category/__init__.py b/frappe/core/doctype/tag_category/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/tag_category/tag_category.js b/frappe/core/doctype/tag_category/tag_category.js new file mode 100644 index 0000000000..e01dad063d --- /dev/null +++ b/frappe/core/doctype/tag_category/tag_category.js @@ -0,0 +1,9 @@ +// Copyright (c) 2016, Frappe Technologies and contributors +// For license information, please see license.txt +frappe.ui.form.on('Tag', { + tag_name:function(frm){ + for (var i = 0 ;i Date: Mon, 11 Jul 2016 10:38:00 +0800 Subject: [PATCH 002/176] filter_dashboard --- frappe/core/doctype/docfield/docfield.json | 64 + .../doctype/custom_field/custom_field.json | 66 +- .../doctype/customize_form/customize_form.py | 1 + .../customize_form_field.json | 58 + frappe/desk/reportview.py | 38 +- frappe/public/build.json | 8 +- frappe/public/css/daterangepicker.css | 269 +++ frappe/public/css/filter_dashboard.css | 61 + frappe/public/js/frappe/list/doclistview.js | 40 +- frappe/public/js/frappe/list/list_sidebar.js | 61 +- frappe/public/js/frappe/list/listview.js | 5 - .../js/frappe/ui/filters/filter_dash.html | 9 + .../ui/filters/filter_dash_stat_head.html | 30 + .../frappe/ui/filters/filter_dash_stats.html | 19 + frappe/public/js/frappe/ui/filters/filters.js | 240 ++- frappe/public/js/frappe/ui/listing.html | 7 +- frappe/public/js/frappe/ui/listing.js | 30 +- .../js/frappe/views/reports/reportview.js | 4 +- frappe/public/js/lib/daterangepicker.js | 1567 +++++++++++++++++ 19 files changed, 2483 insertions(+), 94 deletions(-) create mode 100644 frappe/public/css/daterangepicker.css create mode 100644 frappe/public/css/filter_dashboard.css create mode 100644 frappe/public/js/frappe/ui/filters/filter_dash.html create mode 100644 frappe/public/js/frappe/ui/filters/filter_dash_stat_head.html create mode 100644 frappe/public/js/frappe/ui/filters/filter_dash_stats.html create mode 100644 frappe/public/js/lib/daterangepicker.js diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index 21d593b095..60af0742eb 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -22,6 +22,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "", "length": 0, @@ -47,6 +48,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Label", "length": 0, @@ -77,6 +79,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Type", "length": 0, @@ -105,6 +108,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Name", "length": 0, @@ -132,6 +136,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Mandatory", "length": 0, @@ -163,6 +168,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Precision", "length": 0, @@ -190,6 +196,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Length", "length": 0, @@ -216,6 +223,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Index", "length": 0, @@ -245,6 +253,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "In List View", "length": 0, @@ -266,12 +275,39 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fieldname": "in_filter_dash", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_list_view": 0, + "label": "In Standard Filter", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "bold", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Bold", "length": 0, @@ -299,6 +335,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Collapsible", "length": 255, @@ -326,6 +363,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Collapsible Depends On", "length": 0, @@ -352,6 +390,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -377,6 +416,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Options", "length": 0, @@ -404,6 +444,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Default", "length": 0, @@ -431,6 +472,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Permissions", "length": 0, @@ -456,6 +498,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Display Depends On", "length": 255, @@ -483,6 +526,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Hidden", "length": 0, @@ -512,6 +556,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Read Only", "length": 0, @@ -539,6 +584,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Unique", "length": 0, @@ -566,6 +612,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Set Only Once", "length": 0, @@ -591,6 +638,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -616,6 +664,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Perm Level", "length": 0, @@ -646,6 +695,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Ignore User Permissions", "length": 0, @@ -671,6 +721,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Allow on Submit", "length": 0, @@ -700,6 +751,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Report Hide", "length": 0, @@ -730,6 +782,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Ignore XSS Filter", "length": 0, @@ -756,6 +809,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Display", "length": 0, @@ -781,6 +835,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "In Filter", "length": 0, @@ -810,6 +865,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "No Copy", "length": 0, @@ -839,6 +895,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Hide", "length": 0, @@ -869,6 +926,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Hide If No Value", "length": 0, @@ -895,6 +953,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Width", "length": 0, @@ -920,6 +979,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Width", "length": 0, @@ -977,6 +1037,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -1001,6 +1062,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Description", "length": 0, @@ -1030,6 +1092,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -1056,6 +1119,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, diff --git a/frappe/custom/doctype/custom_field/custom_field.json b/frappe/custom/doctype/custom_field/custom_field.json index 65ef909133..a4bbf51f7b 100644 --- a/frappe/custom/doctype/custom_field/custom_field.json +++ b/frappe/custom/doctype/custom_field/custom_field.json @@ -20,6 +20,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 1, + "in_filter_dash": 0, "in_list_view": 1, "label": "Document", "length": 0, @@ -47,6 +48,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 1, + "in_filter_dash": 0, "in_list_view": 0, "label": "Label", "length": 0, @@ -73,6 +75,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Label Help", "length": 0, @@ -98,6 +101,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Fieldname", "length": 0, @@ -126,6 +130,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Insert After", "length": 0, @@ -152,6 +157,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -177,6 +183,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 1, + "in_filter_dash": 0, "in_list_view": 1, "label": "Field Type", "length": 0, @@ -206,6 +213,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Precision", "length": 0, @@ -232,6 +240,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Options", "length": 0, @@ -258,6 +267,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Options Help", "length": 0, @@ -283,6 +293,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -308,6 +319,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Collapsible", "length": 0, @@ -334,6 +346,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Collapsible Depends On", "length": 0, @@ -359,6 +372,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Default Value", "length": 0, @@ -385,6 +399,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Depends On", "length": 255, @@ -409,6 +424,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Field Description", "length": 0, @@ -438,6 +454,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Permission Level", "length": 0, @@ -464,6 +481,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Width", "length": 0, @@ -490,6 +508,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "", "length": 0, @@ -517,6 +536,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Is Mandatory Field", "length": 0, @@ -543,6 +563,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Unique", "length": 0, @@ -568,6 +589,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Read Only", "length": 0, @@ -593,6 +615,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Ignore User Permissions", "length": 0, @@ -617,6 +640,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Hidden", "length": 0, @@ -641,6 +665,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Hide", "length": 0, @@ -668,6 +693,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Hide If No Value", "length": 0, @@ -693,6 +719,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Width", "length": 0, @@ -717,6 +744,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "No Copy", "length": 0, @@ -743,6 +771,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Allow on Submit", "length": 0, @@ -769,6 +798,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "In Report Filter", "length": 0, @@ -795,6 +825,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "In List View", "length": 0, @@ -809,6 +840,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "in_filter_dash", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_list_view": 0, + "label": "In Standard Filter", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -819,6 +876,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Report Hide", "length": 0, @@ -845,6 +903,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Index", "length": 0, @@ -870,6 +929,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Ignore XSS Filter", "length": 0, @@ -896,7 +956,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-05-14 09:22:58.789603", + "modified": "2016-07-06 05:34:23.557083", "modified_by": "Administrator", "module": "Custom", "name": "Custom Field", @@ -916,6 +976,7 @@ "print": 1, "read": 1, "report": 1, + "restrict": 0, "role": "Administrator", "set_user_permissions": 0, "share": 1, @@ -936,9 +997,10 @@ "print": 1, "read": 1, "report": 1, + "restrict": 0, "role": "System Manager", "set_user_permissions": 0, - "share": 1, + "share": 0, "submit": 0, "write": 1 } diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index f6e0b36a13..776aeb7737 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -43,6 +43,7 @@ docfield_properties = { 'ignore_user_permissions': 'Check', 'in_filter': 'Check', 'in_list_view': 'Check', + 'in_filter_dash': 'Check', 'hidden': 'Check', 'collapsible': 'Check', 'collapsible_depends_on': 'Data', diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 2a17514a97..0a43f28e88 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -22,6 +22,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Label and Type", "length": 0, @@ -48,6 +49,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Label", "length": 0, @@ -76,6 +78,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Type", "length": 0, @@ -104,6 +107,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Name", "length": 0, @@ -131,6 +135,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Mandatory", "length": 0, @@ -160,6 +165,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Unique", "length": 0, @@ -186,6 +192,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "In List View", "length": 0, @@ -205,12 +212,39 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fieldname": "in_filter_dash", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_list_view": 0, + "label": "In Standard Filter", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "column_break_7", "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -238,6 +272,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Precision", "length": 0, @@ -266,6 +301,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Length", "length": 0, @@ -293,6 +329,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Options", "length": 0, @@ -320,6 +357,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Permissions", "length": 0, @@ -347,6 +385,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Depends On", "length": 0, @@ -375,6 +414,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Perm Level", "length": 0, @@ -402,6 +442,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Hidden", "length": 0, @@ -431,6 +472,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Read Only", "length": 0, @@ -458,6 +500,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Collapsible", "length": 0, @@ -485,6 +528,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Collapsible Depends On", "length": 0, @@ -511,6 +555,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -536,6 +581,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Ignore User Permissions", "length": 0, @@ -561,6 +607,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Allow on Submit", "length": 0, @@ -588,6 +635,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Report Hide", "length": 0, @@ -615,6 +663,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Display", "length": 0, @@ -641,6 +690,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Default", "length": 0, @@ -668,6 +718,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "In Filter", "length": 0, @@ -697,6 +748,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "length": 0, "no_copy": 0, @@ -722,6 +774,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Description", "length": 0, @@ -751,6 +804,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Hide", "length": 0, @@ -779,6 +833,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Hide If No Value", "length": 0, @@ -806,6 +861,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Print Width", "length": 0, @@ -861,6 +917,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 1, "label": "Width", "length": 0, @@ -890,6 +947,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_filter_dash": 0, "in_list_view": 0, "label": "Is Custom Field", "length": 0, diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 3a5c91e955..0112dfd2fc 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -148,26 +148,58 @@ def get_tag_catagories(doctype): return cat_tags @frappe.whitelist() -def get_stats(stats, doctype): +def get_stats(stats, doctype,filters=[]): """get tag info""" import json tags = json.loads(stats) + if filters: + filters = json.loads(filters) stats = {} columns = frappe.db.get_table_columns(doctype) for tag in tags: if not tag in columns: continue tagcount = execute(doctype, fields=[tag, "count(*)"], - filters=["ifnull(`%s`,'')!=''" % tag], group_by=tag, as_list=True) + #filters=["ifnull(`%s`,'')!=''" % tag], group_by=tag, as_list=True) + filters = filters + ["ifnull(`%s`,'')!=''" % tag], group_by = tag, as_list = True) if tag=='_user_tags': stats[tag] = scrub_user_tags(tagcount) - stats[tag].append(["No Tags",execute(doctype, fields=[tag, "count(*)"], filters=filters+[tag +"= ',' or "+tag+" is null" ] , as_list=True)[0][1]]) + stats[tag].append(["No Tags",execute(doctype, fields=[tag, "count(*)"], filters=filters +["({0} = ',' or {0} is null)".format(tag)], as_list=True)[0][1]]) else: stats[tag] = tagcount return stats +@frappe.whitelist() +def get_dash(stats, doctype,filters=[]): + """get tag info""" + import json + tags = json.loads(stats) + if filters: + filters = json.loads(filters) + stats = {} + + columns = frappe.db.get_table_columns(doctype) + for tag in tags: + if not tag["name"] in columns: continue + tagcount = [] + if tag["type"] not in ['Date', 'Datetime']: + tagcount = execute(doctype, fields=[tag["name"], "count(*)"], + filters = filters + ["ifnull(`%s`,'')!=''" % tag["name"]], group_by = tag["name"], as_list = True) + + if tag["type"] not in ['Check','Select','Date','Datetime']: + stats[tag["name"]] = list(tagcount) + if stats[tag["name"]]: + data =["No Data",execute(doctype, fields=[tag["name"], "count(*)"], filters=filters + ["({0} = '' or {0} is null)".format(tag["name"])], as_list=True)[0][1]] + if data and data[1]!=0: + + stats[tag["name"]].append(data) + else: + stats[tag["name"]] = tagcount + + return stats + def scrub_user_tags(tagcount): """rebuild tag list for tags""" rdict = {} diff --git a/frappe/public/build.json b/frappe/public/build.json index 70f550dcd6..7d271dad6a 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -193,7 +193,9 @@ "css/list.min.css": [ "public/css/list.css", "public/css/tag-it.css", - "public/css/calendar.css" + "public/css/calendar.css", + "public/css/daterangepicker.css", + "public/css/filter_dashboard.css" ], "js/list.min.js": [ "public/js/frappe/ui/listing.html", @@ -201,6 +203,10 @@ "public/js/frappe/model/indicator.js", "public/js/frappe/ui/filters/filters.js", "public/js/frappe/ui/filters/edit_filter.html", + "public/js/frappe/ui/filters/filter_dash.html", + "public/js/frappe/ui/filters/filter_dash_stats.html", + "public/js/frappe/ui/filters/filter_dash_stat_head.html", + "public/js/lib/daterangepicker.js", "public/js/frappe/ui/tags.js", "public/js/frappe/ui/like.js", "public/js/frappe/ui/liked_by.html", diff --git a/frappe/public/css/daterangepicker.css b/frappe/public/css/daterangepicker.css new file mode 100644 index 0000000000..a03ff440aa --- /dev/null +++ b/frappe/public/css/daterangepicker.css @@ -0,0 +1,269 @@ +.daterangepicker { + position: absolute; + color: inherit; + background: #fff; + border-radius: 4px; + width: 278px; + padding: 4px; + margin-top: 1px; + top: 100px; + left: 20px; + /* Calendars */ } + .daterangepicker:before, .daterangepicker:after { + position: absolute; + display: inline-block; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; } + .daterangepicker:before { + top: -7px; + border-right: 7px solid transparent; + border-left: 7px solid transparent; + border-bottom: 7px solid #ccc; } + .daterangepicker:after { + top: -6px; + border-right: 6px solid transparent; + border-bottom: 6px solid #fff; + border-left: 6px solid transparent; } + .daterangepicker.opensleft:before { + right: 9px; } + .daterangepicker.opensleft:after { + right: 10px; } + .daterangepicker.openscenter:before { + left: 0; + right: 0; + width: 0; + margin-left: auto; + margin-right: auto; } + .daterangepicker.openscenter:after { + left: 0; + right: 0; + width: 0; + margin-left: auto; + margin-right: auto; } + .daterangepicker.opensright:before { + left: 9px; } + .daterangepicker.opensright:after { + left: 10px; } + .daterangepicker.dropup { + margin-top: -5px; } + .daterangepicker.dropup:before { + top: initial; + bottom: -7px; + border-bottom: initial; + border-top: 7px solid #ccc; } + .daterangepicker.dropup:after { + top: initial; + bottom: -6px; + border-bottom: initial; + border-top: 6px solid #fff; } + .daterangepicker.dropdown-menu { + max-width: none; + z-index: 3001; } + .daterangepicker.single .ranges, .daterangepicker.single .calendar { + float: none; } + .daterangepicker.show-calendar .calendar { + display: block; } + .daterangepicker .calendar { + display: none; + max-width: 270px; + margin: 4px; } + .daterangepicker .calendar.single .calendar-table { + border: none; } + .daterangepicker .calendar th, .daterangepicker .calendar td { + white-space: nowrap; + text-align: center; + min-width: 32px; } + .daterangepicker .calendar-table { + border: 1px solid #fff; + padding: 4px; + border-radius: 4px; + background: #fff; } + .daterangepicker table { + width: 100%; + margin: 0; } + .daterangepicker td, .daterangepicker th { + text-align: center; + width: 20px; + height: 20px; + border-radius: 4px; + border: 1px solid transparent; + white-space: nowrap; + cursor: pointer; } + .daterangepicker td.available:hover, .daterangepicker th.available:hover { + background-color: #eee; + border-color: transparent; + color: inherit; } + .daterangepicker td.week, .daterangepicker th.week { + font-size: 80%; + color: #ccc; } + .daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date { + background-color: #fff; + border-color: transparent; + color: #999; } + .daterangepicker td.in-range { + background-color: #ebf4f8; + border-color: transparent; + color: #000; + border-radius: 0; } + .daterangepicker td.start-date { + border-radius: 4px 0 0 4px; } + .daterangepicker td.end-date { + border-radius: 0 4px 4px 0; } + .daterangepicker td.start-date.end-date { + border-radius: 4px; } + .daterangepicker td.active, .daterangepicker td.active:hover { + background-color: #357ebd; + border-color: transparent; + color: #fff; } + .daterangepicker th.month { + width: auto; } + .daterangepicker td.disabled, .daterangepicker option.disabled { + color: #999; + cursor: not-allowed; + text-decoration: line-through; } + .daterangepicker select.monthselect, .daterangepicker select.yearselect { + font-size: 12px; + padding: 1px; + height: auto; + margin: 0; + cursor: default; } + .daterangepicker select.monthselect { + margin-right: 2%; + width: 56%; } + .daterangepicker select.yearselect { + width: 40%; } + .daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect { + width: 50px; + margin-bottom: 0; } + .daterangepicker .input-mini { + border: 1px solid #ccc; + border-radius: 4px; + color: #555; + height: 30px; + line-height: 30px; + display: block; + vertical-align: middle; + margin: 0 0 5px 0; + padding: 0 6px 0 28px; + width: 100%; } + .daterangepicker .input-mini.active { + border: 1px solid #08c; + border-radius: 4px; } + .daterangepicker .daterangepicker_input { + position: relative; } + .daterangepicker .daterangepicker_input i { + position: absolute; + left: 8px; + top: 8px; } + .daterangepicker.rtl .input-mini { + padding-right: 28px; + padding-left: 6px; } + .daterangepicker.rtl .daterangepicker_input i { + left: auto; + right: 8px; } + .daterangepicker .calendar-time { + text-align: center; + margin: 5px auto; + line-height: 30px; + position: relative; + padding-left: 28px; } + .daterangepicker .calendar-time select.disabled { + color: #ccc; + cursor: not-allowed; } + +.ranges { + font-size: 11px; + float: none; + margin: 4px; + text-align: left; } + .ranges ul { + list-style: none; + margin: 0 auto; + padding: 0; + width: 100%; } + .ranges li { + font-size: 13px; + background: #f5f5f5; + border: 1px solid #f5f5f5; + border-radius: 4px; + color: #08c; + padding: 3px 12px; + margin-bottom: 8px; + cursor: pointer; } + .ranges li:hover { + background: #08c; + border: 1px solid #08c; + color: #fff; } + .ranges li.active { + background: #08c; + border: 1px solid #08c; + color: #fff; } + +/* Larger Screen Styling */ +@media (min-width: 564px) { + .daterangepicker { + width: auto; } + .daterangepicker .ranges ul { + width: 160px; } + .daterangepicker.single .ranges ul { + width: 100%; } + .daterangepicker.single .calendar.left { + clear: none; } + .daterangepicker.single.ltr .ranges, .daterangepicker.single.ltr .calendar { + float: left; } + .daterangepicker.single.rtl .ranges, .daterangepicker.single.rtl .calendar { + float: right; } + .daterangepicker.ltr { + direction: ltr; + text-align: left; } + .daterangepicker.ltr .calendar.left { + clear: left; + margin-right: 0; } + .daterangepicker.ltr .calendar.left .calendar-table { + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .daterangepicker.ltr .calendar.right { + margin-left: 0; } + .daterangepicker.ltr .calendar.right .calendar-table { + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .daterangepicker.ltr .left .daterangepicker_input { + padding-right: 12px; } + .daterangepicker.ltr .calendar.left .calendar-table { + padding-right: 12px; } + .daterangepicker.ltr .ranges, .daterangepicker.ltr .calendar { + float: left; } + .daterangepicker.rtl { + direction: rtl; + text-align: right; } + .daterangepicker.rtl .calendar.left { + clear: right; + margin-left: 0; } + .daterangepicker.rtl .calendar.left .calendar-table { + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .daterangepicker.rtl .calendar.right { + margin-right: 0; } + .daterangepicker.rtl .calendar.right .calendar-table { + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .daterangepicker.rtl .left .daterangepicker_input { + padding-left: 12px; } + .daterangepicker.rtl .calendar.left .calendar-table { + padding-left: 12px; } + .daterangepicker.rtl .ranges, .daterangepicker.rtl .calendar { + text-align: right; + float: right; } } +@media (min-width: 730px) { + .daterangepicker .ranges { + width: auto; } + .daterangepicker.ltr .ranges { + float: left; } + .daterangepicker.rtl .ranges { + float: right; } + .daterangepicker .calendar.left { + clear: none !important; } } diff --git a/frappe/public/css/filter_dashboard.css b/frappe/public/css/filter_dashboard.css new file mode 100644 index 0000000000..d2f4722d76 --- /dev/null +++ b/frappe/public/css/filter_dashboard.css @@ -0,0 +1,61 @@ +.date-range-picker{ + font-size:85%; +} +.list-filter-dashboard{ + height:204px; + overflow-x:auto; +} +.filter-label{ + margin:0px; + font-weight: bold; +} +.filter-dashboard-items{ + height: 187px; +} +.filter-dash-item{ + width:180px; + padding-left:5px; + padding-right:5px; + float:left; + height:187px; + border-right:1px solid #d1d8dd; +} +.filter-dash-item:after{ + /*top:-10px;*/ +} +.filter-sort{ + font-size:1.5em; +} +.filter-sort-item{ + padding: 5px; +} +.filter-sort-item:hover{ + color: #262626; + text-decoration: none; + background-color: #f0f4f7; +} +.filter-stat{ + overflow-y:scroll; + overflow-x:hidden; + height: 172px; + margin:0px; +} +.selected{ + vertical-align: 10%; + font-size: 1.2em; +} +.filter-sort-item>label{ + float:right; +} +.filter-stat-link>.badge{ + position: absolute; + float:right; +} +.filter-stat-link>.stat{ + width:135px; + white-space: nowrap; + overflow: hidden; +} +.filter-dash-controls>.filter-label{ + padding-bottom: 5px; +} \ No newline at end of file diff --git a/frappe/public/js/frappe/list/doclistview.js b/frappe/public/js/frappe/list/doclistview.js index f7204b1dcc..832baf55c2 100644 --- a/frappe/public/js/frappe/list/doclistview.js +++ b/frappe/public/js/frappe/list/doclistview.js @@ -313,7 +313,6 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ this.init_headers(); this.dirty = true; } - if(this.listview.settings.refresh) { this.listview.settings.refresh(this); } @@ -321,6 +320,9 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ this.set_filters_before_run(); if(this.dirty) { this.run(); + if (this.clean_dash != true) { + this.filter_list.reload_stats(); + } } else { if(new Date() - (this.last_updated_on || 0) > 30000) { // older than 5 mins, refresh @@ -375,7 +377,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ this.last_updated_on = new Date(); this.dirty = false; - + this.clean_dash = false; // set a fresh so that multiple refreshes do not happen // at the same time. This is true when deleting. // AJAX response will try to refresh and list_update notification @@ -855,44 +857,16 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ stats: me.listview.stats, defined_category : me.defined_category, parent: me.$page.find('.layout-side-section'), - set_filter: function(fieldname, label) { - me.set_filter(fieldname, label); + set_filter: function(fieldname, label,norun,noduplicates) { + me.set_filter(fieldname, label,norun,noduplicates); }, + default_filters:me.listview.settings.default_filters, page: me.page, doclistview: me }) } }) }, - set_filter: function(fieldname, label, no_run) { - var filter = this.filter_list.get_filter(fieldname); - if(filter) { - var v = cstr(filter.field.get_parsed_value()); - if(v.indexOf(label)!=-1) { - // already set - return false; - } else { - // second filter set for this field - if(fieldname=='_user_tags' || fieldname=="_liked_by") { - // and for tags - this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label); - } else { - // or for rest using "in" - filter.set_values(this.doctype, fieldname, 'in', v + ', ' + label); - } - } - } else { - // no filter for this item, - // setup one - if(fieldname=='_user_tags' || fieldname=="_liked_by") { - this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label); - } else { - this.filter_list.add_filter(this.doctype, fieldname, '=', label); - } - } - if(!no_run) - this.run(); - }, call_for_selected_items: function(method, args) { var me = this; args.names = $.map(this.get_checked_items(), function(d) { return d.name; }); diff --git a/frappe/public/js/frappe/list/list_sidebar.js b/frappe/public/js/frappe/list/list_sidebar.js index 73dafd203b..774da675bf 100644 --- a/frappe/public/js/frappe/list/list_sidebar.js +++ b/frappe/public/js/frappe/list/list_sidebar.js @@ -115,51 +115,33 @@ frappe.views.ListSidebar = Class.extend({ method: 'frappe.desk.reportview.get_stats', args: { stats: me.stats, - doctype: me.doctype + doctype: me.doctype, + filters:me.default_filters }, callback: function(r) { if (me.defined_category ){ me.cats = {}; + //structure the tag categories for (i in me.defined_category){ - if (me.cats[me.defined_category[i].category]===undefined) - { + if (me.cats[me.defined_category[i].category]===undefined){ me.cats[me.defined_category[i].category]=[me.defined_category[i].tag]; }else{ - me.cats[me.defined_category[i].category].push(me.defined_category[i].tag); } me.cat_tags[i]=me.defined_category[i].tag } - me.tempstats = r.message - var len = me.cats.length + me.tempstats = r.message; + var len = me.cats.length; $.each(me.cats, function (i, v) { me.render_stat(i, (me.tempstats || {})["_user_tags"],v); }); - $.each(me.stats, function (i, v) { - me.render_stat(v, (me.tempstats || {})[v]); - }); + me.render_stat("_user_tags", (me.tempstats || {})["_user_tags"]); } else { //render normal stats - // This gives a predictable stats order - $.each(me.stats, function (i, v) { - me.render_stat(v, (r.message || {})[v]); - }); + me.render_stat("_user_tags", (r.message|| {})["_user_tags"]); } - - - // reload button at the end - // if(me.stats.length) { - // $(''+__('Refresh Stats')+'') - // .css({"margin-top":"15px", "display":"inline-block"}) - // .click(function() { - // me.reload_stats(); - // return false; - // }).appendTo($('
') - // .appendTo(me.sidebar)); - // } - me.doclistview.set_sidebar_height(); } }); @@ -195,7 +177,6 @@ frappe.views.ListSidebar = Class.extend({ { me.tempstats["_user_tags"].splice(nfound,1); } - } field = "_user_tags" } @@ -207,9 +188,8 @@ frappe.views.ListSidebar = Class.extend({ field: field, stat: stats, sum: sum, - label: label==='_user_tags' ? (__("UnCatagorised Tags") + show_tags) : tags ? __(label)+ show_tags: __(label), + label: field==='_user_tags' ? tags ? __(label)+ show_tags:(__("UnCatagorised Tags") + show_tags): __(label), }; - var sidebar_stat = $(frappe.render_template("list_sidebar_stat", context)) .on("click", ".stat-link", function() { var fieldname = $(this).attr('data-field'); @@ -222,7 +202,30 @@ frappe.views.ListSidebar = Class.extend({ } }) .appendTo(this.sidebar); + }, + set_fieldtype: function(df, fieldtype) { + // scrub + if(df.fieldname=="docstatus") { + df.fieldtype="Select", + df.options=[ + {value:0, label:"Draft"}, + {value:1, label:"Submitted"}, + {value:2, label:"Cancelled"}, + ] + } else if(df.fieldtype=='Check') { + df.fieldtype='Select'; + df.options=[{value:0,label:'No'}, + {value:1,label:'Yes'}] + } else if(['Text','Small Text','Text Editor','Code','Tag','Comments', + 'Dynamic Link','Read Only','Assign'].indexOf(df.fieldtype)!=-1) { + df.fieldtype = 'Data'; + } else if(df.fieldtype=='Link' && this.$w.find('.condition').val()!="=") { + df.fieldtype = 'Data'; + } + if(df.fieldtype==="Data" && (df.options || "").toLowerCase()==="email") { + df.options = null; + } }, reload_stats: function() { this.sidebar.find(".sidebar-stat").remove(); diff --git a/frappe/public/js/frappe/list/listview.js b/frappe/public/js/frappe/list/listview.js index 412a71dd79..f513527aa5 100644 --- a/frappe/public/js/frappe/list/listview.js +++ b/frappe/public/js/frappe/list/listview.js @@ -78,11 +78,6 @@ frappe.views.ListView = Class.extend({ } else { add_field(d.fieldname); } - - if(d.fieldtype=="Select") { - if(me.stats.indexOf(d.fieldname)===-1) me.stats.push(d.fieldname); - } - // currency field for symbol (multi-currency) if(d.fieldtype=="Currency" && d.options) { if(d.options.indexOf(":")!=-1) { diff --git a/frappe/public/js/frappe/ui/filters/filter_dash.html b/frappe/public/js/frappe/ui/filters/filter_dash.html new file mode 100644 index 0000000000..f731030c7d --- /dev/null +++ b/frappe/public/js/frappe/ui/filters/filter_dash.html @@ -0,0 +1,9 @@ +
+ +
\ No newline at end of file diff --git a/frappe/public/js/frappe/ui/filters/filter_dash_stat_head.html b/frappe/public/js/frappe/ui/filters/filter_dash_stat_head.html new file mode 100644 index 0000000000..5e9e933f0a --- /dev/null +++ b/frappe/public/js/frappe/ui/filters/filter_dash_stat_head.html @@ -0,0 +1,30 @@ +
+
{%= label %} + {% if(type==="Date" || type==="Datetime"){ %} +
+ + + {% } else { %} + + + + + + + + + + + {% } %} +
\ No newline at end of file diff --git a/frappe/public/js/frappe/ui/filters/filter_dash_stats.html b/frappe/public/js/frappe/ui/filters/filter_dash_stats.html new file mode 100644 index 0000000000..bf7bdec36f --- /dev/null +++ b/frappe/public/js/frappe/ui/filters/filter_dash_stats.html @@ -0,0 +1,19 @@ +
  • + {% if(!stat.length) { %} +
  • {%= __("No records.") %}
  • + {% } else { + for (var i=0, l=stat.length; i < l; i++) { + var stat_label = stat[i][0]; + var stat_count = stat[i][1]; + %} +
  • + + {%= __(labels.length>0? labels[i] : stat_label) %} + {%= stat_count %} + + + +
  • + {% } + } %} + diff --git a/frappe/public/js/frappe/ui/filters/filters.js b/frappe/public/js/frappe/ui/filters/filters.js index 64d4edf758..7f3c3bc8ef 100644 --- a/frappe/public/js/frappe/ui/filters/filters.js +++ b/frappe/public/js/frappe/ui/filters/filters.js @@ -6,14 +6,251 @@ frappe.ui.FilterList = Class.extend({ $.extend(this, opts); this.filters = []; this.wrapper = this.$parent; + this.stats = []; + this.make_dash(); this.set_events(); }, + make_dash: function() { + var me = this; + $(frappe.render_template("filter_dash", {})).appendTo(this.wrapper.find('.show_filters')); + //show filter dashboard + this.$w.find('.show-filter-dashboard').click(function() { + $(this).closest('.show_filters').find('.dashboard-box').toggle(); + $(this).prop('title',($(this).prop('title')===__("Hide Standard Filters"))?__("Show Standard Filters") : __("Hide Standard Filters")) + }); + //add stats + $.each(frappe.meta.docfield_map[this.doctype], function(i,d) { + if (d.in_filter_dash&&frappe.perm.has_perm(me.doctype, d.permlevel, "read")) { + if (d.fieldtype != 'Table') { + me.stats.push({name:d.fieldname,label:d.label,type:d.fieldtype}); + } + } + }); + + me.stats = me.stats.concat([{name:'creation',label:'Created On',type:'Datetime'}, + {name:'modified',label:'Last Modified On',type:'Datetime'}, + {name:'owner',label:'Created By',type:'Data'}, + {name:'modified_by',label:'Last Modified By',type:'Data'}, + {name:'docstatus',label:'Document Status',type:'Data'}]); + $.each(me.stats, function (i, v) { + me.render_dash_headers(v); + }); + me.reload_stats() + }, + render_dash_headers: function(field){ + var me = this; + var context = { + field: field.name, + label: __(field.label), + type:field.type + }; + var sidebar_stat = $(frappe.render_template("filter_dash_stat_head", context)) + .appendTo(this.$w.find(".filter-dashboard-items")); + + //adjust width for horizontal scrolling + var width = (me.stats.length)*180+30 + this.wrapper.find(".filter-dashboard-items").css("width",width); + }, + reload_stats: function(){ + if(this.fresh ) { + return; + } + // set a fresh so that multiple refreshes do not happen + // at the same time. + this.fresh = true; + setTimeout(function() { + me.fresh = false; + }, 1000); + + //get stats + var me = this + return frappe.call({ + type: "GET", + method: 'frappe.desk.reportview.get_dash', + args: { + stats: me.stats, + doctype: me.doctype, + filters:me.default_filters + }, + callback: function(r) { + // This gives a predictable stats order + me.wrapper.find(".filter-stat").empty(); + $.each(me.stats, function (i, v) { + me.render_filters(v, (r.message|| {})[v.name]); + }); + } + }); + }, + render_filters: function(field, stat){ + var me = this; + var sum = 0; + if (['Date', 'Datetime'].indexOf(field.type)!=-1) { + return + } + //sort based on icon + var type = /icon-\S+/g.exec(this.wrapper.find(".filter-label[data-name='"+__(field.label)+"']").find(".filter-sort-active").attr('class')); + if(type[0].indexOf("alphabet")>0){ + stat = (stat || []).sort(function(a, b) {return a[0].toString().toLowerCase().localeCompare(b[0].toString().toLowerCase());}); + + }else{ + stat = (stat || []).sort(function(a, b) { return a[1] - b[1] }); + } + stat = type[0].indexOf("-alt")>0? stat.reverse():stat; + + //check formatting + var options = [] + var df = frappe.meta.has_field(me.doctype,field.name) + var labels =[] + if(df && df.fieldtype=='Check') { + options = [{value: 0, label: 'No'}, + {value: 1, label: 'Yes'}] + }else if(field.name=="docstatus") { + labels.length = stat.length + options = [{value: 0, label: "Draft"}, + {value: 1, label: "Submitted"}, + {value: 2, label: "Cancelled"}] + } + + if(options.length>0) { + for (i in stat) { + for (o in options) { + if (stat[i][0] == options[o].value) { + if (field.name=="docstatus") { + labels[i] = options[o].label + }else{ + stat[i][0] = options[o].label + } + } + } + } + } + var context = { + field: field.name, + stat: stat, + sum: sum, + label: __(field.label), + labels:labels + }; + var dashitem = this.wrapper.find(".filter-stat[data-name='" + __(field.label) + "']") + dashitem.html(frappe.render_template("filter_dash_stats", context)).on("click", ".filter-stat-link", function() { + var fieldname = $(this).attr('data-field'); + var label = $(this).attr('data-label'); + if ((df && df.fieldtype=='Check' )|| field.name=="docstatus") { + var noduplicate = true + } + if (label=="No Data"){ + me.listobj.set_filter(fieldname, '',false,noduplicate); + }else{ + me.listobj.set_filter(fieldname, label,false,noduplicate); + } + return false; + }) + if (stat.length>5) { + //list for autocomplete + var autolist = [] + for (var i = 0; i < stat.length; i++) { + autolist.push({label: stat[i][0], value: field.name}); + } + + dashitem.parent().find(".search-dropdown").removeClass("hide").on("shown.bs.dropdown", function (event) { + $(this).find(".search-dashboard").focus(); + $(this).find(".search-dashboard").val("") + }) + dashitem.parent().find(".search-dashboard").autocomplete({ + source: autolist, + select: function (ev, ui) { + if (ui.item) { + if (df && df.fieldtype == 'Check') { + var noduplicate = true + } + if (ui.item.label == "No Data") { + me.listobj.set_filter(ui.item.value, '', false, noduplicate); + } else { + me.listobj.set_filter(ui.item.value, ui.item.label, false, noduplicate); + } + } + } + }) + } + }, set_events: function() { var me = this; // show filters this.wrapper.find('.new-filter').bind('click', function() { me.add_filter(me.doctype, 'name'); }); + + + this.wrapper.find('.clear-filter').bind('click', function() { + me.clear_filters(); + $('.date-range-picker').val('') + me.listobj.run(); + }); + //set sort filters + this.wrapper.find(".filter-label").on("click", ".filter-sort-item", function() { + var active = $(this).closest(".filter-dash-item").find(".filter-sort-active").attr('class', + function(i, c){ + return c.replace(/(^|\s)icon-\S+/g, ''); + }); + var classes = $(this).find('.filter-sort').attr('class'); + classes = classes.replace('filter-sort',''); + $(active).addClass(classes); + me.reload_stats(); + }); + //setup date-time range pickers + $(".date-range-picker").each(function(i,v) { + var picker = this; + var lab = $(v).data("name"); + $(v).daterangepicker({ + "autoApply": true, + "showDropdowns": true, + "ranges": { + 'Today': [moment(), moment()], + 'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')], + 'Last Week': [moment().subtract(1, 'week').startOf('week'), moment().subtract(1, 'week').endOf('week')], + 'Last 7 Days': [moment().subtract(6, 'days'), moment()], + 'Last 30 Days': [moment().subtract(29, 'days'), moment()], + 'This Month': [moment().startOf('month'), moment().endOf('month')], + 'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 3 Months': [moment().subtract(3, 'month').startOf('month'), moment().endOf('month')], + 'Financial Year': [moment(frappe.defaults.get_default("year_start_date"), "YYYY-MM-DD"), moment(frappe.defaults.get_default("year_end_date"), "YYYY-MM-DD")], + 'Last Financial Year': [moment(frappe.defaults.get_default("year_start_date"), "YYYY-MM-DD").subtract(1, 'year'), moment(frappe.defaults.get_default("year_end_date"), "YYYY-MM-DD").subtract(1, 'year')] + }, + "locale": { + "format": "DD-MM-YYYY", + "firstDay": 1, + "cancelLabel": "Clear" + }, + "linkedCalendars": false, + "alwaysShowCalendars": true, + "cancelClass": "date-range-picker-cancel "+lab, + "autoUpdateInput": false + }).on('apply.daterangepicker',function(ev,picker){ + $(this).val(picker.startDate.format('DD-MM-YYYY') + ' - ' + picker.endDate.format('DD-MM-YYYY')); + var filt = me.get_filter(lab); + if (filt) { + filt.remove(true) + } + var filt = me.get_filter(lab); + if (filt) { + filt.remove(true) + } + me.add_filter(me.doctype, lab, '<=', picker.endDate); + me.add_filter(me.doctype, lab, '>=', picker.startDate); + me.listobj.run(); + }).on('cancel.daterangepicker', function(ev, picker) { + $(this).val(''); + var filt = me.get_filter(lab); + if (filt) { + filt.remove(true) + } + var filt = me.get_filter(lab); + if (filt) { + filt.remove() + } + }); + $(".date-range-picker-cancel." + lab ).removeClass("hide") + }) }, show_filters: function() { @@ -63,7 +300,6 @@ frappe.ui.FilterList = Class.extend({ return filter; }, - push_new_filter: function(doctype, fieldname, condition, value) { if(this.filter_exists(doctype, fieldname, condition, value)) return; @@ -195,6 +431,7 @@ frappe.ui.Filter = Class.extend({ if(!dont_run) { this.flist.listobj.dirty = true; + this.flist.listobj.clean_dash = true; this.flist.listobj.refresh(); } }, @@ -395,6 +632,7 @@ frappe.ui.Filter = Class.extend({ }); this.$btn_group.find(".toggle-filter").on("click", function() { + $(this).closest('.show_filters').find('.filter_area').show() me.wrapper.toggle(); }) this.wrapper.toggle(false); diff --git a/frappe/public/js/frappe/ui/listing.html b/frappe/public/js/frappe/ui/listing.html index 3bef38c4c1..e474cfe29d 100644 --- a/frappe/public/js/frappe/ui/listing.html +++ b/frappe/public/js/frappe/ui/listing.html @@ -2,10 +2,11 @@ diff --git a/frappe/public/js/frappe/ui/listing.js b/frappe/public/js/frappe/ui/listing.js index 36ae779f87..3199922c9a 100644 --- a/frappe/public/js/frappe/ui/listing.js +++ b/frappe/public/js/frappe/ui/listing.js @@ -161,7 +161,8 @@ frappe.ui.Listing = Class.extend({ listobj: this, $parent: this.wrapper.find('.list-filters').toggle(true), doctype: this.doctype, - filter_fields: this.filter_fields + filter_fields: this.filter_fields, + default_filters:this.default_filters? this.default_filters: this.listview?this.listview.settings.default_filters:[] }); if(frappe.model.is_submittable(this.doctype)) { this.filter_list.add_filter(this.doctype, "docstatus", "!=", 2); @@ -407,36 +408,37 @@ frappe.ui.Listing = Class.extend({ query += ' LIMIT ' + this.start + ',' + (this.page_length+1); return query }, - set_filter: function(fieldname, label, doctype) { - if(!doctype) doctype = this.doctype; + set_filter: function(fieldname, label, no_run,no_duplicate) { var filter = this.filter_list.get_filter(fieldname); if(filter) { - var v = filter.field.get_parsed_value(); + var v = cstr(filter.field.get_parsed_value()); if(v.indexOf(label)!=-1) { // already set - return this; + return false + + } else if(no_duplicate) { + filter.set_values(this.doctype, fieldname, "=", label); } else { // second filter set for this field - if(fieldname=='_user_tags') { + if(fieldname=='_user_tags' || fieldname=="_liked_by") { // and for tags - this.filter_list.add_filter(doctype, fieldname, - 'like', '%' + label + '%'); + this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label + '%'); } else { // or for rest using "in" - filter.set_values(doctype, fieldname, 'in', v + ', ' + label); + filter.set_values(this.doctype, fieldname, 'in', v + ', ' + label); } } } else { // no filter for this item, // setup one if(['_user_tags', '_comments', '_assign', '_liked_by'].indexOf(fieldname)!==-1) { - this.filter_list.add_filter(doctype, fieldname, - 'like', '%' + label + '%'); + this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label + '%'); } else { - this.filter_list.add_filter(doctype, fieldname, '=', label); + this.filter_list.add_filter(this.doctype, fieldname, '=', label); } } - return this; + if(!no_run) + this.run(); }, init_list_settings: function() { if(frappe.model.list_settings[this.doctype]) { @@ -445,4 +447,4 @@ frappe.ui.Listing = Class.extend({ this.list_settings = {}; } }, -}); +}); \ No newline at end of file diff --git a/frappe/public/js/frappe/views/reports/reportview.js b/frappe/public/js/frappe/views/reports/reportview.js index 938e2fcedd..f054bc5c5d 100644 --- a/frappe/public/js/frappe/views/reports/reportview.js +++ b/frappe/public/js/frappe/views/reports/reportview.js @@ -316,7 +316,7 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ docfield = columnDef.report_docfield; docfield.link_onclick = - repl('frappe.container.page.reportview.set_filter("%(fieldname)s", "%(value)s").run()', + repl('frappe.container.page.reportview.set_filter("%(fieldname)s", "%(value)s")', {fieldname:docfield.fieldname, value:value}); } return frappe.format(value, docfield, {for_print: for_print, always_show_decimals: true}, dataContext); @@ -507,14 +507,12 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ this.wrapper.find('.result-list').on("click", ".label-info", function() { if($(this).attr("data-label")) { me.set_filter("_user_tags", $(this).attr("data-label")); - me.refresh(); } }); this.wrapper.find('.result-list').on("click", "[data-workflow-state]", function() { if($(this).attr("data-workflow-state")) { me.set_filter(me.state_fieldname, $(this).attr("data-workflow-state")); - me.refresh(); } }); }, diff --git a/frappe/public/js/lib/daterangepicker.js b/frappe/public/js/lib/daterangepicker.js new file mode 100644 index 0000000000..611966e829 --- /dev/null +++ b/frappe/public/js/lib/daterangepicker.js @@ -0,0 +1,1567 @@ +/** +* @version: 2.1.21 +* @author: Dan Grossman http://www.dangrossman.info/ +* @copyright: Copyright (c) 2012-2016 Dan Grossman. All rights reserved. +* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php +* @website: https://www.improvely.com/ +*/ +// Follow the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Make globaly available as well + define(['moment', 'jquery'], function (moment, jquery) { + return (root.daterangepicker = factory(moment, jquery)); + }); + } else if (typeof module === 'object' && module.exports) { + // Node / Browserify + //isomorphic issue + var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined; + if (!jQuery) { + jQuery = require('jquery'); + if (!jQuery.fn) jQuery.fn = {}; + } + module.exports = factory(require('moment'), jQuery); + } else { + // Browser globals + root.daterangepicker = factory(root.moment, root.jQuery); + } +}(this, function(moment, $) { + var DateRangePicker = function(element, options, cb) { + + //default settings for options + this.parentEl = 'body'; + this.element = $(element); + this.startDate = moment().startOf('day'); + this.endDate = moment().endOf('day'); + this.minDate = false; + this.maxDate = false; + this.dateLimit = false; + this.autoApply = false; + this.singleDatePicker = false; + this.showDropdowns = false; + this.showWeekNumbers = false; + this.showISOWeekNumbers = false; + this.timePicker = false; + this.timePicker24Hour = false; + this.timePickerIncrement = 1; + this.timePickerSeconds = false; + this.linkedCalendars = true; + this.autoUpdateInput = true; + this.alwaysShowCalendars = false; + this.ranges = {}; + + this.opens = 'right'; + if (this.element.hasClass('pull-right')) + this.opens = 'left'; + + this.drops = 'down'; + if (this.element.hasClass('dropup')) + this.drops = 'up'; + + this.buttonClasses = 'btn btn-sm'; + this.applyClass = 'btn-success'; + this.cancelClass = 'btn-default'; + + this.locale = { + direction: 'ltr', + format: 'MM/DD/YYYY', + separator: ' - ', + applyLabel: 'Apply', + cancelLabel: 'Cancel', + weekLabel: 'W', + customRangeLabel: 'Custom Range', + daysOfWeek: moment.weekdaysMin(), + monthNames: moment.monthsShort(), + firstDay: moment.localeData().firstDayOfWeek() + }; + + this.callback = function() { }; + + //some state information + this.isShowing = false; + this.leftCalendar = {}; + this.rightCalendar = {}; + + //custom options from user + if (typeof options !== 'object' || options === null) + options = {}; + + //allow setting options with data attributes + //data-api options will be overwritten with custom javascript options + options = $.extend(this.element.data(), options); + + //html template for the picker UI + if (typeof options.template !== 'string' && !(options.template instanceof $)) + options.template = ''; + + this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl); + this.container = $(options.template).appendTo(this.parentEl); + + // + // handle all the possible options overriding defaults + // + + if (typeof options.locale === 'object') { + + if (typeof options.locale.direction === 'string') + this.locale.direction = options.locale.direction; + + if (typeof options.locale.format === 'string') + this.locale.format = options.locale.format; + + if (typeof options.locale.separator === 'string') + this.locale.separator = options.locale.separator; + + if (typeof options.locale.daysOfWeek === 'object') + this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); + + if (typeof options.locale.monthNames === 'object') + this.locale.monthNames = options.locale.monthNames.slice(); + + if (typeof options.locale.firstDay === 'number') + this.locale.firstDay = options.locale.firstDay; + + if (typeof options.locale.applyLabel === 'string') + this.locale.applyLabel = options.locale.applyLabel; + + if (typeof options.locale.cancelLabel === 'string') + this.locale.cancelLabel = options.locale.cancelLabel; + + if (typeof options.locale.weekLabel === 'string') + this.locale.weekLabel = options.locale.weekLabel; + + if (typeof options.locale.customRangeLabel === 'string') + this.locale.customRangeLabel = options.locale.customRangeLabel; + + } + this.container.addClass(this.locale.direction); + + if (typeof options.startDate === 'string') + this.startDate = moment(options.startDate, this.locale.format); + + if (typeof options.endDate === 'string') + this.endDate = moment(options.endDate, this.locale.format); + + if (typeof options.minDate === 'string') + this.minDate = moment(options.minDate, this.locale.format); + + if (typeof options.maxDate === 'string') + this.maxDate = moment(options.maxDate, this.locale.format); + + if (typeof options.startDate === 'object') + this.startDate = moment(options.startDate); + + if (typeof options.endDate === 'object') + this.endDate = moment(options.endDate); + + if (typeof options.minDate === 'object') + this.minDate = moment(options.minDate); + + if (typeof options.maxDate === 'object') + this.maxDate = moment(options.maxDate); + + // sanity check for bad options + if (this.minDate && this.startDate.isBefore(this.minDate)) + this.startDate = this.minDate.clone(); + + // sanity check for bad options + if (this.maxDate && this.endDate.isAfter(this.maxDate)) + this.endDate = this.maxDate.clone(); + + if (typeof options.applyClass === 'string') + this.applyClass = options.applyClass; + + if (typeof options.cancelClass === 'string') + this.cancelClass = options.cancelClass; + + if (typeof options.dateLimit === 'object') + this.dateLimit = options.dateLimit; + + if (typeof options.opens === 'string') + this.opens = options.opens; + + if (typeof options.drops === 'string') + this.drops = options.drops; + + if (typeof options.showWeekNumbers === 'boolean') + this.showWeekNumbers = options.showWeekNumbers; + + if (typeof options.showISOWeekNumbers === 'boolean') + this.showISOWeekNumbers = options.showISOWeekNumbers; + + if (typeof options.buttonClasses === 'string') + this.buttonClasses = options.buttonClasses; + + if (typeof options.buttonClasses === 'object') + this.buttonClasses = options.buttonClasses.join(' '); + + if (typeof options.showDropdowns === 'boolean') + this.showDropdowns = options.showDropdowns; + + if (typeof options.singleDatePicker === 'boolean') { + this.singleDatePicker = options.singleDatePicker; + if (this.singleDatePicker) + this.endDate = this.startDate.clone(); + } + + if (typeof options.timePicker === 'boolean') + this.timePicker = options.timePicker; + + if (typeof options.timePickerSeconds === 'boolean') + this.timePickerSeconds = options.timePickerSeconds; + + if (typeof options.timePickerIncrement === 'number') + this.timePickerIncrement = options.timePickerIncrement; + + if (typeof options.timePicker24Hour === 'boolean') + this.timePicker24Hour = options.timePicker24Hour; + + if (typeof options.autoApply === 'boolean') + this.autoApply = options.autoApply; + + if (typeof options.autoUpdateInput === 'boolean') + this.autoUpdateInput = options.autoUpdateInput; + + if (typeof options.linkedCalendars === 'boolean') + this.linkedCalendars = options.linkedCalendars; + + if (typeof options.isInvalidDate === 'function') + this.isInvalidDate = options.isInvalidDate; + + if (typeof options.isCustomDate === 'function') + this.isCustomDate = options.isCustomDate; + + if (typeof options.alwaysShowCalendars === 'boolean') + this.alwaysShowCalendars = options.alwaysShowCalendars; + + // update day names order to firstDay + if (this.locale.firstDay != 0) { + var iterator = this.locale.firstDay; + while (iterator > 0) { + this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); + iterator--; + } + } + + var start, end, range; + + //if no start/end dates set, check if an input element contains initial values + if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { + if ($(this.element).is('input[type=text]')) { + var val = $(this.element).val(), + split = val.split(this.locale.separator); + + start = end = null; + + if (split.length == 2) { + start = moment(split[0], this.locale.format); + end = moment(split[1], this.locale.format); + } else if (this.singleDatePicker && val !== "") { + start = moment(val, this.locale.format); + end = moment(val, this.locale.format); + } + if (start !== null && end !== null) { + this.setStartDate(start); + this.setEndDate(end); + } + } + } + + if (typeof options.ranges === 'object') { + for (range in options.ranges) { + + if (typeof options.ranges[range][0] === 'string') + start = moment(options.ranges[range][0], this.locale.format); + else + start = moment(options.ranges[range][0]); + + if (typeof options.ranges[range][1] === 'string') + end = moment(options.ranges[range][1], this.locale.format); + else + end = moment(options.ranges[range][1]); + + // If the start or end date exceed those allowed by the minDate or dateLimit + // options, shorten the range to the allowable period. + if (this.minDate && start.isBefore(this.minDate)) + start = this.minDate.clone(); + + var maxDate = this.maxDate; + if (this.dateLimit && maxDate && start.clone().add(this.dateLimit).isAfter(maxDate)) + maxDate = start.clone().add(this.dateLimit); + if (maxDate && end.isAfter(maxDate)) + end = maxDate.clone(); + + // If the end of the range is before the minimum or the start of the range is + // after the maximum, don't display this range option at all. + if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day')) + || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day'))) + continue; + + //Support unicode chars in the range names. + var elem = document.createElement('textarea'); + elem.innerHTML = range; + var rangeHtml = elem.value; + + this.ranges[rangeHtml] = [start, end]; + } + + var list = '
      '; + for (range in this.ranges) { + list += '
    • ' + range + '
    • '; + } + if (!this.alwaysShowCalendars) { + list += '
    • ' + this.locale.customRangeLabel + '
    • '; + } + list += '
    '; + this.container.find('.ranges').prepend(list); + } + + if (typeof cb === 'function') { + this.callback = cb; + } + + if (!this.timePicker) { + this.startDate = this.startDate.startOf('day'); + this.endDate = this.endDate.endOf('day'); + this.container.find('.calendar-time').hide(); + } + + //can't be used together for now + if (this.timePicker && this.autoApply) + this.autoApply = false; + + if (this.autoApply && typeof options.ranges !== 'object') { + this.container.find('.ranges').hide(); + } else if (this.autoApply) { + this.container.find('.applyBtn, .cancelBtn').addClass('hide'); + } + + if (this.singleDatePicker) { + this.container.addClass('single'); + this.container.find('.calendar.left').addClass('single'); + this.container.find('.calendar.left').show(); + this.container.find('.calendar.right').hide(); + this.container.find('.daterangepicker_input input, .daterangepicker_input > i').hide(); + if (!this.timePicker) { + this.container.find('.ranges').hide(); + } + } + + if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) { + this.container.addClass('show-calendar'); + } + + this.container.addClass('opens' + this.opens); + + //swap the position of the predefined ranges if opens right + if (typeof options.ranges !== 'undefined' && this.opens == 'right') { + this.container.find('.ranges').prependTo( this.container.find('.calendar.left').parent() ); + } + + //apply CSS classes and labels to buttons + this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses); + if (this.applyClass.length) + this.container.find('.applyBtn').addClass(this.applyClass); + if (this.cancelClass.length) + this.container.find('.cancelBtn').addClass(this.cancelClass); + this.container.find('.applyBtn').html(this.locale.applyLabel); + this.container.find('.cancelBtn').html(this.locale.cancelLabel); + + // + // event listeners + // + + this.container.find('.calendar') + .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this)) + .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this)) + .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this)) + .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this)) + .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this)) + .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this)) + .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this)) + .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this)) + .on('click.daterangepicker', '.daterangepicker_input input', $.proxy(this.showCalendars, this)) + //.on('keyup.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this)) + .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this)); + + this.container.find('.ranges') + .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) + .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this)) + .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this)) + .on('mouseenter.daterangepicker', 'li', $.proxy(this.hoverRange, this)) + .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this)); + + if (this.element.is('input') || this.element.is('button')) { + this.element.on({ + 'click.daterangepicker': $.proxy(this.show, this), + 'focus.daterangepicker': $.proxy(this.show, this), + 'keyup.daterangepicker': $.proxy(this.elementChanged, this), + 'keydown.daterangepicker': $.proxy(this.keydown, this) + }); + } else { + this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); + } + + // + // if attached to a text input, set the initial value + // + + if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) { + this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); + this.element.trigger('change'); + } else if (this.element.is('input') && this.autoUpdateInput) { + this.element.val(this.startDate.format(this.locale.format)); + this.element.trigger('change'); + } + + }; + + DateRangePicker.prototype = { + + constructor: DateRangePicker, + + setStartDate: function(startDate) { + if (typeof startDate === 'string') + this.startDate = moment(startDate, this.locale.format); + + if (typeof startDate === 'object') + this.startDate = moment(startDate); + + if (!this.timePicker) + this.startDate = this.startDate.startOf('day'); + + if (this.timePicker && this.timePickerIncrement) + this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); + + if (this.minDate && this.startDate.isBefore(this.minDate)) { + this.startDate = this.minDate; + if (this.timePicker && this.timePickerIncrement) + this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); + } + + if (this.maxDate && this.startDate.isAfter(this.maxDate)) { + this.startDate = this.maxDate; + if (this.timePicker && this.timePickerIncrement) + this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); + } + + if (!this.isShowing) + this.updateElement(); + + this.updateMonthsInView(); + }, + + setEndDate: function(endDate) { + if (typeof endDate === 'string') + this.endDate = moment(endDate, this.locale.format); + + if (typeof endDate === 'object') + this.endDate = moment(endDate); + + if (!this.timePicker) + this.endDate = this.endDate.endOf('day'); + + if (this.timePicker && this.timePickerIncrement) + this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); + + if (this.endDate.isBefore(this.startDate)) + this.endDate = this.startDate.clone(); + + if (this.maxDate && this.endDate.isAfter(this.maxDate)) + this.endDate = this.maxDate; + + if (this.dateLimit && this.startDate.clone().add(this.dateLimit).isBefore(this.endDate)) + this.endDate = this.startDate.clone().add(this.dateLimit); + + this.previousRightTime = this.endDate.clone(); + + if (!this.isShowing) + this.updateElement(); + + this.updateMonthsInView(); + }, + + isInvalidDate: function() { + return false; + }, + + isCustomDate: function() { + return false; + }, + + updateView: function() { + if (this.timePicker) { + this.renderTimePicker('left'); + this.renderTimePicker('right'); + if (!this.endDate) { + this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled'); + } else { + this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled'); + } + } + if (this.endDate) { + this.container.find('input[name="daterangepicker_end"]').removeClass('active'); + this.container.find('input[name="daterangepicker_start"]').addClass('active'); + } else { + this.container.find('input[name="daterangepicker_end"]').addClass('active'); + this.container.find('input[name="daterangepicker_start"]').removeClass('active'); + } + this.updateMonthsInView(); + this.updateCalendars(); + this.updateFormInputs(); + }, + + updateMonthsInView: function() { + if (this.endDate) { + + //if both dates are visible already, do nothing + if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month && + (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) + && + (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) + ) { + return; + } + + this.leftCalendar.month = this.startDate.clone().date(2); + if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) { + this.rightCalendar.month = this.endDate.clone().date(2); + } else { + this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month'); + } + + } else { + if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) { + this.leftCalendar.month = this.startDate.clone().date(2); + this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month'); + } + } + if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) { + this.rightCalendar.month = this.maxDate.clone().date(2); + this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month'); + } + }, + + updateCalendars: function() { + + if (this.timePicker) { + var hour, minute, second; + if (this.endDate) { + hour = parseInt(this.container.find('.left .hourselect').val(), 10); + minute = parseInt(this.container.find('.left .minuteselect').val(), 10); + second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0; + if (!this.timePicker24Hour) { + var ampm = this.container.find('.left .ampmselect').val(); + if (ampm === 'PM' && hour < 12) + hour += 12; + if (ampm === 'AM' && hour === 12) + hour = 0; + } + } else { + hour = parseInt(this.container.find('.right .hourselect').val(), 10); + minute = parseInt(this.container.find('.right .minuteselect').val(), 10); + second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0; + if (!this.timePicker24Hour) { + var ampm = this.container.find('.right .ampmselect').val(); + if (ampm === 'PM' && hour < 12) + hour += 12; + if (ampm === 'AM' && hour === 12) + hour = 0; + } + } + this.leftCalendar.month.hour(hour).minute(minute).second(second); + this.rightCalendar.month.hour(hour).minute(minute).second(second); + } + + this.renderCalendar('left'); + this.renderCalendar('right'); + + //highlight any predefined range matching the current start and end dates + this.container.find('.ranges li').removeClass('active'); + if (this.endDate == null) return; + + this.calculateChosenLabel(); + }, + + renderCalendar: function(side) { + + // + // Build the matrix of dates that will populate the calendar + // + + var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar; + var month = calendar.month.month(); + var year = calendar.month.year(); + var hour = calendar.month.hour(); + var minute = calendar.month.minute(); + var second = calendar.month.second(); + var daysInMonth = moment([year, month]).daysInMonth(); + var firstDay = moment([year, month, 1]); + var lastDay = moment([year, month, daysInMonth]); + var lastMonth = moment(firstDay).subtract(1, 'month').month(); + var lastYear = moment(firstDay).subtract(1, 'month').year(); + var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth(); + var dayOfWeek = firstDay.day(); + + //initialize a 6 rows x 7 columns array for the calendar + var calendar = []; + calendar.firstDay = firstDay; + calendar.lastDay = lastDay; + + for (var i = 0; i < 6; i++) { + calendar[i] = []; + } + + //populate the calendar with date objects + var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1; + if (startDay > daysInLastMonth) + startDay -= 7; + + if (dayOfWeek == this.locale.firstDay) + startDay = daysInLastMonth - 6; + + var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]); + + var col, row; + for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) { + if (i > 0 && col % 7 === 0) { + col = 0; + row++; + } + calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second); + curDate.hour(12); + + if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') { + calendar[row][col] = this.minDate.clone(); + } + + if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') { + calendar[row][col] = this.maxDate.clone(); + } + + } + + //make the calendar object available to hoverDate/clickDate + if (side == 'left') { + this.leftCalendar.calendar = calendar; + } else { + this.rightCalendar.calendar = calendar; + } + + // + // Display the calendar + // + + var minDate = side == 'left' ? this.minDate : this.startDate; + var maxDate = this.maxDate; + var selected = side == 'left' ? this.startDate : this.endDate; + var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'}; + + var html = ''; + html += ''; + html += ''; + + // add empty cell for week number + if (this.showWeekNumbers || this.showISOWeekNumbers) + html += ''; + + if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) { + html += ''; + } else { + html += ''; + } + + var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY"); + + if (this.showDropdowns) { + var currentMonth = calendar[1][1].month(); + var currentYear = calendar[1][1].year(); + var maxYear = (maxDate && maxDate.year()) || (currentYear + 5); + var minYear = (minDate && minDate.year()) || (currentYear - 50); + var inMinYear = currentYear == minYear; + var inMaxYear = currentYear == maxYear; + + var monthHtml = '"; + + var yearHtml = ''; + + dateHtml = monthHtml + yearHtml; + } + + html += ''; + if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) { + html += ''; + } else { + html += ''; + } + + html += ''; + html += ''; + + // add week number label + if (this.showWeekNumbers || this.showISOWeekNumbers) + html += ''; + + $.each(this.locale.daysOfWeek, function(index, dayOfWeek) { + html += ''; + }); + + html += ''; + html += ''; + html += ''; + + //adjust maxDate to reflect the dateLimit setting in order to + //grey out end dates beyond the dateLimit + if (this.endDate == null && this.dateLimit) { + var maxLimit = this.startDate.clone().add(this.dateLimit).endOf('day'); + if (!maxDate || maxLimit.isBefore(maxDate)) { + maxDate = maxLimit; + } + } + + for (var row = 0; row < 6; row++) { + html += ''; + + // add week number + if (this.showWeekNumbers) + html += ''; + else if (this.showISOWeekNumbers) + html += ''; + + for (var col = 0; col < 7; col++) { + + var classes = []; + + //highlight today's date + if (calendar[row][col].isSame(new Date(), "day")) + classes.push('today'); + + //highlight weekends + if (calendar[row][col].isoWeekday() > 5) + classes.push('weekend'); + + //grey out the dates in other months displayed at beginning and end of this calendar + if (calendar[row][col].month() != calendar[1][1].month()) + classes.push('off'); + + //don't allow selection of dates before the minimum date + if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day')) + classes.push('off', 'disabled'); + + //don't allow selection of dates after the maximum date + if (maxDate && calendar[row][col].isAfter(maxDate, 'day')) + classes.push('off', 'disabled'); + + //don't allow selection of date if a custom function decides it's invalid + if (this.isInvalidDate(calendar[row][col])) + classes.push('off', 'disabled'); + + //highlight the currently selected start date + if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) + classes.push('active', 'start-date'); + + //highlight the currently selected end date + if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) + classes.push('active', 'end-date'); + + //highlight dates in-between the selected dates + if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate) + classes.push('in-range'); + + //apply custom classes for this date + var isCustom = this.isCustomDate(calendar[row][col]); + if (isCustom !== false) { + if (typeof isCustom === 'string') + classes.push(isCustom); + else + Array.prototype.push.apply(classes, isCustom); + } + + var cname = '', disabled = false; + for (var i = 0; i < classes.length; i++) { + cname += classes[i] + ' '; + if (classes[i] == 'disabled') + disabled = true; + } + if (!disabled) + cname += 'available'; + + html += ''; + + } + html += ''; + } + + html += ''; + html += '
    ' + dateHtml + '
    ' + this.locale.weekLabel + '' + dayOfWeek + '
    ' + calendar[row][0].week() + '' + calendar[row][0].isoWeek() + '' + calendar[row][col].date() + '
    '; + + this.container.find('.calendar.' + side + ' .calendar-table').html(html); + + }, + + renderTimePicker: function(side) { + + var html, selected, minDate, maxDate = this.maxDate; + + if (this.dateLimit && (!this.maxDate || this.startDate.clone().add(this.dateLimit).isAfter(this.maxDate))) + maxDate = this.startDate.clone().add(this.dateLimit); + + if (side == 'left') { + selected = this.startDate.clone(); + minDate = this.minDate; + } else if (side == 'right') { + selected = this.endDate ? this.endDate.clone() : this.previousRightTime.clone(); + minDate = this.startDate; + + if (selected.isBefore(this.startDate)) + selected = this.startDate.clone(); + + if (maxDate && selected.isAfter(maxDate)) + selected = maxDate.clone(); + + //Preserve the time already selected + var timeSelector = this.container.find('.calendar.right .calendar-time div'); + if (!this.endDate && timeSelector.html() != '') { + + selected.hour(timeSelector.find('.hourselect option:selected').val() || selected.hour()); + selected.minute(timeSelector.find('.minuteselect option:selected').val() || selected.minute()); + selected.second(timeSelector.find('.secondselect option:selected').val() || selected.second()); + + if (!this.timePicker24Hour) { + var ampm = timeSelector.find('.ampmselect option:selected').val(); + if (ampm === 'PM' && selected.hour() < 12) + selected.hour(selected.hour() + 12); + if (ampm === 'AM' && selected.hour() === 12) + selected.hour(0); + } + + } + } + + // + // hours + // + + html = ' '; + + // + // minutes + // + + html += ': '; + + // + // seconds + // + + if (this.timePickerSeconds) { + html += ': '; + } + + // + // AM/PM + // + + if (!this.timePicker24Hour) { + html += ''; + } + + this.container.find('.calendar.' + side + ' .calendar-time div').html(html); + + }, + + updateFormInputs: function() { + + //ignore mouse movements while an above-calendar text input has focus + if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) + return; + + this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.locale.format)); + if (this.endDate) + this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.locale.format)); + + if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) { + this.container.find('button.applyBtn').removeAttr('disabled'); + } else { + this.container.find('button.applyBtn').attr('disabled', 'disabled'); + } + + }, + + move: function() { + var parentOffset = { top: 0, left: 0 }, + containerTop; + var parentRightEdge = $(window).width(); + if (!this.parentEl.is('body')) { + parentOffset = { + top: this.parentEl.offset().top - this.parentEl.scrollTop(), + left: this.parentEl.offset().left - this.parentEl.scrollLeft() + }; + parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left; + } + + if (this.drops == 'up') + containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top; + else + containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; + this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('dropup'); + + if (this.opens == 'left') { + this.container.css({ + top: containerTop, + right: parentRightEdge - this.element.offset().left - this.element.outerWidth(), + left: 'auto' + }); + if (this.container.offset().left < 0) { + this.container.css({ + right: 'auto', + left: 9 + }); + } + } else if (this.opens == 'center') { + this.container.css({ + top: containerTop, + left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2 + - this.container.outerWidth() / 2, + right: 'auto' + }); + if (this.container.offset().left < 0) { + this.container.css({ + right: 'auto', + left: 9 + }); + } + } else { + var idealwidth = this.container.outerWidth() + this.container.css({ + top: containerTop, + left: this.element.offset().left - parentOffset.left, + right: 'auto' + }); + if (this.container.offset().left + idealwidth > $(window).width()) { + this.container.css({ + left: 'auto', + right: 0 + }); + } + } + }, + + show: function(e) { + if (this.isShowing) return; + + // Create a click proxy that is private to this instance of datepicker, for unbinding + this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this); + + // Bind global datepicker mousedown for hiding and + $(document) + .on('mousedown.daterangepicker', this._outsideClickProxy) + // also support mobile devices + .on('touchend.daterangepicker', this._outsideClickProxy) + // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them + .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy) + // and also close when focus changes to outside the picker (eg. tabbing between controls) + .on('focusin.daterangepicker', this._outsideClickProxy); + + // Reposition the picker if the window is resized while it's open + $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this)); + + this.oldStartDate = this.startDate.clone(); + this.oldEndDate = this.endDate.clone(); + this.previousRightTime = this.endDate.clone(); + + this.updateView(); + this.container.show(); + this.move(); + this.element.trigger('show.daterangepicker', this); + this.isShowing = true; + }, + + hide: function(e) { + if (!this.isShowing) return; + + //incomplete date selection, revert to last values + if (!this.endDate) { + this.startDate = this.oldStartDate.clone(); + this.endDate = this.oldEndDate.clone(); + } + + //if a new date range was selected, invoke the user callback function + if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) + this.callback(this.startDate, this.endDate, this.chosenLabel); + + //if picker is attached to a text input, update it + this.updateElement(); + + $(document).off('.daterangepicker'); + $(window).off('.daterangepicker'); + this.container.hide(); + this.element.trigger('hide.daterangepicker', this); + this.isShowing = false; + }, + + toggle: function(e) { + if (this.isShowing) { + this.hide(); + } else { + this.show(); + } + }, + + outsideClick: function(e) { + var target = $(e.target); + // if the page is clicked anywhere except within the daterangerpicker/button + // itself then call this.hide() + if ( + // ie modal dialog fix + e.type == "focusin" || + target.closest(this.element).length || + target.closest(this.container).length || + target.closest('.calendar-table').length + ) return; + this.hide(); + }, + + showCalendars: function() { + this.container.addClass('show-calendar'); + this.move(); + this.element.trigger('showCalendar.daterangepicker', this); + }, + + hideCalendars: function() { + this.container.removeClass('show-calendar'); + this.element.trigger('hideCalendar.daterangepicker', this); + }, + + hoverRange: function(e) { + + //ignore mouse movements while an above-calendar text input has focus + if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) + return; + + var label = e.target.innerHTML; + if (label == this.locale.customRangeLabel) { + this.updateView(); + } else { + var dates = this.ranges[label]; + this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.locale.format)); + this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.locale.format)); + } + + }, + + clickRange: function(e) { + var label = e.target.innerHTML; + this.chosenLabel = label; + if (label == this.locale.customRangeLabel) { + this.showCalendars(); + } else { + var dates = this.ranges[label]; + this.startDate = dates[0]; + this.endDate = dates[1]; + + if (!this.timePicker) { + this.startDate.startOf('day'); + this.endDate.endOf('day'); + } + + if (!this.alwaysShowCalendars) + this.hideCalendars(); + this.clickApply(); + } + }, + + clickPrev: function(e) { + var cal = $(e.target).parents('.calendar'); + if (cal.hasClass('left')) { + this.leftCalendar.month.subtract(1, 'month'); + if (this.linkedCalendars) + this.rightCalendar.month.subtract(1, 'month'); + } else { + this.rightCalendar.month.subtract(1, 'month'); + } + this.updateCalendars(); + }, + + clickNext: function(e) { + var cal = $(e.target).parents('.calendar'); + if (cal.hasClass('left')) { + this.leftCalendar.month.add(1, 'month'); + } else { + this.rightCalendar.month.add(1, 'month'); + if (this.linkedCalendars) + this.leftCalendar.month.add(1, 'month'); + } + this.updateCalendars(); + }, + + hoverDate: function(e) { + + //ignore mouse movements while an above-calendar text input has focus + if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) + return; + + //ignore dates that can't be selected + if (!$(e.target).hasClass('available')) return; + + //have the text inputs above calendars reflect the date being hovered over + var title = $(e.target).attr('data-title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(e.target).parents('.calendar'); + var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; + + if (this.endDate) { + this.container.find('input[name=daterangepicker_start]').val(date.format(this.locale.format)); + } else { + this.container.find('input[name=daterangepicker_end]').val(date.format(this.locale.format)); + } + + //highlight the dates between the start date and the date being hovered as a potential end date + var leftCalendar = this.leftCalendar; + var rightCalendar = this.rightCalendar; + var startDate = this.startDate; + if (!this.endDate) { + this.container.find('.calendar td').each(function(index, el) { + + //skip week numbers, only look at dates + if ($(el).hasClass('week')) return; + + var title = $(el).attr('data-title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(el).parents('.calendar'); + var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col]; + + if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) { + $(el).addClass('in-range'); + } else { + $(el).removeClass('in-range'); + } + + }); + } + + }, + + clickDate: function(e) { + + if (!$(e.target).hasClass('available')) return; + + var title = $(e.target).attr('data-title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(e.target).parents('.calendar'); + var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; + + // + // this function needs to do a few things: + // * alternate between selecting a start and end date for the range, + // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date + // * if autoapply is enabled, and an end date was chosen, apply the selection + // * if single date picker mode, and time picker isn't enabled, apply the selection immediately + // + + if (this.endDate || date.isBefore(this.startDate, 'day')) { + if (this.timePicker) { + var hour = parseInt(this.container.find('.left .hourselect').val(), 10); + if (!this.timePicker24Hour) { + var ampm = this.container.find('.left .ampmselect').val(); + if (ampm === 'PM' && hour < 12) + hour += 12; + if (ampm === 'AM' && hour === 12) + hour = 0; + } + var minute = parseInt(this.container.find('.left .minuteselect').val(), 10); + var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0; + date = date.clone().hour(hour).minute(minute).second(second); + } + this.endDate = null; + this.setStartDate(date.clone()); + } else if (!this.endDate && date.isBefore(this.startDate)) { + //special case: clicking the same date for start/end, + //but the time of the end date is before the start date + this.setEndDate(this.startDate.clone()); + } else { + if (this.timePicker) { + var hour = parseInt(this.container.find('.right .hourselect').val(), 10); + if (!this.timePicker24Hour) { + var ampm = this.container.find('.right .ampmselect').val(); + if (ampm === 'PM' && hour < 12) + hour += 12; + if (ampm === 'AM' && hour === 12) + hour = 0; + } + var minute = parseInt(this.container.find('.right .minuteselect').val(), 10); + var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0; + date = date.clone().hour(hour).minute(minute).second(second); + } + this.setEndDate(date.clone()); + if (this.autoApply) { + this.calculateChosenLabel(); + this.clickApply(); + } + } + + if (this.singleDatePicker) { + this.setEndDate(this.startDate); + if (!this.timePicker) + this.clickApply(); + } + + this.updateView(); + + }, + + calculateChosenLabel: function() { + var customRange = true; + var i = 0; + for (var range in this.ranges) { + if (this.timePicker) { + if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) { + customRange = false; + this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html(); + break; + } + } else { + //ignore times when comparing dates if time picker is not enabled + if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) { + customRange = false; + this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html(); + break; + } + } + i++; + } + if (customRange) { + this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html(); + this.showCalendars(); + } + }, + + clickApply: function(e) { + this.hide(); + this.element.trigger('apply.daterangepicker', this); + }, + + clickCancel: function(e) { + this.startDate = this.oldStartDate; + this.endDate = this.oldEndDate; + this.hide(); + this.element.trigger('cancel.daterangepicker', this); + }, + + monthOrYearChanged: function(e) { + var isLeft = $(e.target).closest('.calendar').hasClass('left'), + leftOrRight = isLeft ? 'left' : 'right', + cal = this.container.find('.calendar.'+leftOrRight); + + // Month must be Number for new moment versions + var month = parseInt(cal.find('.monthselect').val(), 10); + var year = cal.find('.yearselect').val(); + + if (!isLeft) { + if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) { + month = this.startDate.month(); + year = this.startDate.year(); + } + } + + if (this.minDate) { + if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) { + month = this.minDate.month(); + year = this.minDate.year(); + } + } + + if (this.maxDate) { + if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) { + month = this.maxDate.month(); + year = this.maxDate.year(); + } + } + + if (isLeft) { + this.leftCalendar.month.month(month).year(year); + if (this.linkedCalendars) + this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month'); + } else { + this.rightCalendar.month.month(month).year(year); + if (this.linkedCalendars) + this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month'); + } + this.updateCalendars(); + }, + + timeChanged: function(e) { + + var cal = $(e.target).closest('.calendar'), + isLeft = cal.hasClass('left'); + + var hour = parseInt(cal.find('.hourselect').val(), 10); + var minute = parseInt(cal.find('.minuteselect').val(), 10); + var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0; + + if (!this.timePicker24Hour) { + var ampm = cal.find('.ampmselect').val(); + if (ampm === 'PM' && hour < 12) + hour += 12; + if (ampm === 'AM' && hour === 12) + hour = 0; + } + + if (isLeft) { + var start = this.startDate.clone(); + start.hour(hour); + start.minute(minute); + start.second(second); + this.setStartDate(start); + if (this.singleDatePicker) { + this.endDate = this.startDate.clone(); + } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) { + this.setEndDate(start.clone()); + } + } else if (this.endDate) { + var end = this.endDate.clone(); + end.hour(hour); + end.minute(minute); + end.second(second); + this.setEndDate(end); + } + + //update the calendars so all clickable dates reflect the new time component + this.updateCalendars(); + + //update the form inputs above the calendars with the new time + this.updateFormInputs(); + + //re-render the time pickers because changing one selection can affect what's enabled in another + this.renderTimePicker('left'); + this.renderTimePicker('right'); + + }, + + formInputsChanged: function(e) { + var isRight = $(e.target).closest('.calendar').hasClass('right'); + var start = moment(this.container.find('input[name="daterangepicker_start"]').val(), this.locale.format); + var end = moment(this.container.find('input[name="daterangepicker_end"]').val(), this.locale.format); + + if (start.isValid() && end.isValid()) { + + if (isRight && end.isBefore(start)) + start = end.clone(); + + this.setStartDate(start); + this.setEndDate(end); + + if (isRight) { + this.container.find('input[name="daterangepicker_start"]').val(this.startDate.format(this.locale.format)); + } else { + this.container.find('input[name="daterangepicker_end"]').val(this.endDate.format(this.locale.format)); + } + + } + + this.updateCalendars(); + if (this.timePicker) { + this.renderTimePicker('left'); + this.renderTimePicker('right'); + } + }, + + elementChanged: function() { + if (!this.element.is('input')) return; + if (!this.element.val().length) return; + if (this.element.val().length < this.locale.format.length) return; + + var dateString = this.element.val().split(this.locale.separator), + start = null, + end = null; + + if (dateString.length === 2) { + start = moment(dateString[0], this.locale.format); + end = moment(dateString[1], this.locale.format); + } + + if (this.singleDatePicker || start === null || end === null) { + start = moment(this.element.val(), this.locale.format); + end = start; + } + + if (!start.isValid() || !end.isValid()) return; + + this.setStartDate(start); + this.setEndDate(end); + this.updateView(); + }, + + keydown: function(e) { + //hide on tab or enter + if ((e.keyCode === 9) || (e.keyCode === 13)) { + this.hide(); + } + }, + + updateElement: function() { + if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) { + this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); + this.element.trigger('change'); + } else if (this.element.is('input') && this.autoUpdateInput) { + this.element.val(this.startDate.format(this.locale.format)); + this.element.trigger('change'); + } + }, + + remove: function() { + this.container.remove(); + this.element.off('.daterangepicker'); + this.element.removeData(); + } + + }; + + $.fn.daterangepicker = function(options, callback) { + this.each(function() { + var el = $(this); + if (el.data('daterangepicker')) + el.data('daterangepicker').remove(); + el.data('daterangepicker', new DateRangePicker(el, options, callback)); + }); + return this; + }; + + return DateRangePicker; + +})); From f0464dbdf132f36e5d5d677226c935cea2cafa9a Mon Sep 17 00:00:00 2001 From: robert schouten Date: Mon, 17 Oct 2016 16:01:13 +0800 Subject: [PATCH 003/176] updating sidebar stats to list_sidebar --- frappe/public/js/frappe/list/listview.js | 2 +- frappe/public/js/frappe/ui/tags.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/list/listview.js b/frappe/public/js/frappe/list/listview.js index f513527aa5..4605c09049 100644 --- a/frappe/public/js/frappe/list/listview.js +++ b/frappe/public/js/frappe/list/listview.js @@ -274,7 +274,7 @@ frappe.views.ListView = Class.extend({ doctype: this.doctype, docname: data.name }, - sidebar_stats: me.doclistview.sidebar_stats, + list_sidebar: me.doclistview.list_sidebar, user_tags: data._user_tags, on_change: function(user_tags) { data._user_tags = user_tags; diff --git a/frappe/public/js/frappe/ui/tags.js b/frappe/public/js/frappe/ui/tags.js index 7836936d45..855f42d6a0 100644 --- a/frappe/public/js/frappe/ui/tags.js +++ b/frappe/public/js/frappe/ui/tags.js @@ -69,7 +69,7 @@ frappe.ui.TagEditor = Class.extend({ args:{ doctype: me.frm.doctype, txt: request.term.toLowerCase(), - cat_tags:JSON.stringify(me.sidebar_stats.get_cat_tags()) + cat_tags:JSON.stringify(me.list_sidebar.get_cat_tags()) }, callback: function(r) { response(r.message); From 01a4845ce721eb9d03b94362cccf9672261f37e3 Mon Sep 17 00:00:00 2001 From: robert schouten Date: Wed, 19 Oct 2016 16:08:46 +0800 Subject: [PATCH 004/176] assorted cleanup and v7.1 fixes --- frappe/core/doctype/docfield/docfield.json | 2 +- .../doctype/custom_field/custom_field.json | 2 +- .../customize_form_field.json | 2 +- frappe/desk/reportview.py | 10 +++---- frappe/desk/tags.py | 2 +- frappe/public/js/frappe/list/doclistview.js | 29 ++++++------------- frappe/public/js/frappe/list/list_sidebar.js | 15 +++++----- frappe/public/js/frappe/ui/filters/filters.js | 10 +++---- frappe/public/js/frappe/ui/listing.js | 2 +- 9 files changed, 32 insertions(+), 42 deletions(-) diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index 60af0742eb..6f8d8a3aad 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -1146,7 +1146,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-08-23 11:59:07.036627", + "modified": "2016-10-18 11:59:07.036627", "modified_by": "Administrator", "module": "Core", "name": "DocField", diff --git a/frappe/custom/doctype/custom_field/custom_field.json b/frappe/custom/doctype/custom_field/custom_field.json index a4bbf51f7b..1d8b112104 100644 --- a/frappe/custom/doctype/custom_field/custom_field.json +++ b/frappe/custom/doctype/custom_field/custom_field.json @@ -956,7 +956,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-07-06 05:34:23.557083", + "modified": "2016-10-18 05:34:23.557083", "modified_by": "Administrator", "module": "Custom", "name": "Custom Field", diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 0a43f28e88..b5e04565f5 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -974,7 +974,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-08-23 12:03:07.126339", + "modified": "2016-10-18 12:03:07.126339", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 0112dfd2fc..e5d7f1d2e2 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -138,17 +138,17 @@ def delete_items(): frappe.delete_doc(doctype, d) @frappe.whitelist() -def get_tag_catagories(doctype): +def get_sidebar_stats(stats, doctype, filters=[]): cat_tags = frappe.db.sql("""select tag.parent as category, tag.tag_name as tag from `tabTag Doc Category` as docCat INNER JOIN tabTag as tag on tag.parent = docCat.parent where docCat.tagdoc=%s ORDER BY tag.parent asc,tag.idx""",doctype,as_dict=1) - return cat_tags + return {"defined_cat":cat_tags, "stats":get_stats(stats, doctype, filters)} @frappe.whitelist() -def get_stats(stats, doctype,filters=[]): +def get_stats(stats, doctype, filters=[]): """get tag info""" import json tags = json.loads(stats) @@ -165,14 +165,14 @@ def get_stats(stats, doctype,filters=[]): if tag=='_user_tags': stats[tag] = scrub_user_tags(tagcount) - stats[tag].append(["No Tags",execute(doctype, fields=[tag, "count(*)"], filters=filters +["({0} = ',' or {0} is null)".format(tag)], as_list=True)[0][1]]) + stats[tag].append(["No Tags",execute(doctype, fields=[tag, "count(*)"], filters=filters +["({0} = ',' or {0} is null)".format(tag)], as_list=True)[0][1]]) else: stats[tag] = tagcount return stats @frappe.whitelist() -def get_dash(stats, doctype,filters=[]): +def get_dash(stats, doctype, filters=[]): """get tag info""" import json tags = json.loads(stats) diff --git a/frappe/desk/tags.py b/frappe/desk/tags.py index 89451946de..b26cef82be 100644 --- a/frappe/desk/tags.py +++ b/frappe/desk/tags.py @@ -49,7 +49,7 @@ def remove_tag(tag, dt, dn): @frappe.whitelist() -def get_tags(doctype, txt,cat_tags): +def get_tags(doctype, txt, cat_tags): tags = json.loads(cat_tags) try: for _user_tags in frappe.db.sql_list("""select DISTINCT `_user_tags` diff --git a/frappe/public/js/frappe/list/doclistview.js b/frappe/public/js/frappe/list/doclistview.js index 832baf55c2..4872d3e61f 100644 --- a/frappe/public/js/frappe/list/doclistview.js +++ b/frappe/public/js/frappe/list/doclistview.js @@ -844,27 +844,16 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ }, refresh_sidebar: function() { var me = this; - frappe.call({ - method: 'frappe.desk.reportview.get_tag_catagories', - args: { - doctype: me.doctype, + me.list_sidebar = new frappe.views.ListSidebar({ + doctype: me.doctype, + stats: me.listview.stats, + parent: me.$page.find('.layout-side-section'), + set_filter: function(fieldname, label, norun, noduplicates) { + me.set_filter(fieldname, label, norun, noduplicates); }, - callback: function(r) { - me.defined_category = r.message; - - me.list_sidebar = new frappe.views.ListSidebar({ - doctype: me.doctype, - stats: me.listview.stats, - defined_category : me.defined_category, - parent: me.$page.find('.layout-side-section'), - set_filter: function(fieldname, label,norun,noduplicates) { - me.set_filter(fieldname, label,norun,noduplicates); - }, - default_filters:me.listview.settings.default_filters, - page: me.page, - doclistview: me - }) - } + default_filters:me.listview.settings.default_filters, + page: me.page, + doclistview: me }) }, call_for_selected_items: function(method, args) { diff --git a/frappe/public/js/frappe/list/list_sidebar.js b/frappe/public/js/frappe/list/list_sidebar.js index 774da675bf..b6352dcebf 100644 --- a/frappe/public/js/frappe/list/list_sidebar.js +++ b/frappe/public/js/frappe/list/list_sidebar.js @@ -110,16 +110,17 @@ frappe.views.ListSidebar = Class.extend({ }, get_stats: function() { var me = this - return frappe.call({ - type: "GET", - method: 'frappe.desk.reportview.get_stats', + frappe.call({ + method: 'frappe.desk.reportview.get_sidebar_stats', args: { stats: me.stats, doctype: me.doctype, filters:me.default_filters }, callback: function(r) { - if (me.defined_category ){ + me.defined_category = r.message; + if (r.message.defined_cat ){ + me.defined_category = r.message.defined_cat me.cats = {}; //structure the tag categories for (i in me.defined_category){ @@ -130,7 +131,7 @@ frappe.views.ListSidebar = Class.extend({ } me.cat_tags[i]=me.defined_category[i].tag } - me.tempstats = r.message; + me.tempstats =r.message.stats var len = me.cats.length; $.each(me.cats, function (i, v) { me.render_stat(i, (me.tempstats || {})["_user_tags"],v); @@ -140,13 +141,13 @@ frappe.views.ListSidebar = Class.extend({ else { //render normal stats - me.render_stat("_user_tags", (r.message|| {})["_user_tags"]); + me.render_stat("_user_tags", (r.message.stats|| {})["_user_tags"]); } me.doclistview.set_sidebar_height(); } }); }, - render_stat: function(field, stat,tags) { + render_stat: function(field, stat, tags) { var me = this; var sum = 0; var stats = [] diff --git a/frappe/public/js/frappe/ui/filters/filters.js b/frappe/public/js/frappe/ui/filters/filters.js index 7f3c3bc8ef..583992def1 100644 --- a/frappe/public/js/frappe/ui/filters/filters.js +++ b/frappe/public/js/frappe/ui/filters/filters.js @@ -14,7 +14,7 @@ frappe.ui.FilterList = Class.extend({ var me = this; $(frappe.render_template("filter_dash", {})).appendTo(this.wrapper.find('.show_filters')); //show filter dashboard - this.$w.find('.show-filter-dashboard').click(function() { + this.wrapper.find('.show-filter-dashboard').click(function() { $(this).closest('.show_filters').find('.dashboard-box').toggle(); $(this).prop('title',($(this).prop('title')===__("Hide Standard Filters"))?__("Show Standard Filters") : __("Hide Standard Filters")) }); @@ -45,7 +45,7 @@ frappe.ui.FilterList = Class.extend({ type:field.type }; var sidebar_stat = $(frappe.render_template("filter_dash_stat_head", context)) - .appendTo(this.$w.find(".filter-dashboard-items")); + .appendTo(this.wrapper.find(".filter-dashboard-items")); //adjust width for horizontal scrolling var width = (me.stats.length)*180+30 @@ -139,9 +139,9 @@ frappe.ui.FilterList = Class.extend({ var noduplicate = true } if (label=="No Data"){ - me.listobj.set_filter(fieldname, '',false,noduplicate); + me.listobj.set_filter(fieldname, '', false, noduplicate); }else{ - me.listobj.set_filter(fieldname, label,false,noduplicate); + me.listobj.set_filter(fieldname, label, false, noduplicate); } return false; }) @@ -623,7 +623,7 @@ frappe.ui.Filter = Class.extend({ title="'+__("Remove Filter")+'">\ \
    ') - .insertAfter(this.flist.wrapper.find(".set-filters .new-filter")); + .insertAfter(this.flist.wrapper.find(".set-filters .clear-filter")); this.set_filter_button_text(); diff --git a/frappe/public/js/frappe/ui/listing.js b/frappe/public/js/frappe/ui/listing.js index 3199922c9a..db7a236422 100644 --- a/frappe/public/js/frappe/ui/listing.js +++ b/frappe/public/js/frappe/ui/listing.js @@ -408,7 +408,7 @@ frappe.ui.Listing = Class.extend({ query += ' LIMIT ' + this.start + ',' + (this.page_length+1); return query }, - set_filter: function(fieldname, label, no_run,no_duplicate) { + set_filter: function(fieldname, label, no_run, no_duplicate) { var filter = this.filter_list.get_filter(fieldname); if(filter) { var v = cstr(filter.field.get_parsed_value()); From 424f99e6f37668601a475065c1126a1d6e6514b8 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 26 Oct 2016 16:47:50 +0530 Subject: [PATCH 005/176] [cleanup] dashboard filters --- frappe/core/doctype/docfield/docfield.json | 88 ++++++------ .../doctype/boilerplate/controller_list.html | 2 +- frappe/core/doctype/doctype/doctype.json | 132 ++++++++++++++---- .../page/desktop/desktop_module_icon.html | 2 +- .../modules_setup/includes/module_icons.html | 2 +- .../page/modules_setup/modules_setup.html | 8 ++ .../core/page/modules_setup/modules_setup.js | 7 +- .../core/page/modules_setup/modules_setup.py | 3 +- .../doctype/custom_field/custom_field.json | 72 +++++----- .../doctype/customize_form/customize_form.py | 2 +- .../customize_form_field.json | 72 +++++----- frappe/data/Framework.sql | 1 + frappe/desk/page/chat/chat_sidebar.html | 2 +- frappe/desk/reportview.py | 23 ++- .../print_format_builder_sidebar.html | 2 +- frappe/public/build.json | 6 +- frappe/public/css/common.css | 17 ++- frappe/public/css/daterangepicker.css | 20 +-- frappe/public/css/desk.css | 18 +-- frappe/public/css/docs.css | 9 ++ frappe/public/css/filter_dashboard.css | 131 ++++++++++------- frappe/public/css/form_grid.css | 9 ++ frappe/public/css/mixins.css | 1 + frappe/public/css/mobile.css | 9 ++ frappe/public/css/navbar.css | 9 ++ frappe/public/css/page.css | 9 ++ frappe/public/css/sidebar.css | 9 ++ frappe/public/css/website.css | 19 +-- frappe/public/js/frappe/form/control.js | 2 +- .../js/frappe/form/footer/attachments.js | 2 +- .../js/frappe/form/footer/timeline_item.html | 2 +- frappe/public/js/frappe/form/grid.js | 2 +- .../js/frappe/list/image_view_item_row.html | 2 +- .../public/js/frappe/list/list_item_main.html | 2 +- .../js/frappe/list/list_item_main_head.html | 2 +- .../public/js/frappe/list/list_item_row.html | 2 +- .../ui/filters/filter_dash_stat_head.html | 30 ---- ...filter_dash.html => filter_dashboard.html} | 2 +- .../ui/filters/filter_dashboard_head.html | 45 ++++++ ...stats.html => filter_dashboard_value.html} | 2 +- frappe/public/js/frappe/ui/filters/filters.js | 131 ++++++++++------- frappe/public/js/frappe/ui/listing.html | 10 +- frappe/public/js/frappe/ui/messages.js | 2 +- frappe/public/js/frappe/ui/page.html | 4 +- .../public/js/frappe/ui/toolbar/navbar.html | 4 +- frappe/public/js/frappe/upload.js | 2 +- frappe/public/less/common.less | 20 +-- frappe/public/less/filter_dashboard.less | 119 ++++++++++++++++ frappe/public/less/mixins.less | 17 +++ 49 files changed, 730 insertions(+), 358 deletions(-) delete mode 100644 frappe/public/js/frappe/ui/filters/filter_dash_stat_head.html rename frappe/public/js/frappe/ui/filters/{filter_dash.html => filter_dashboard.html} (67%) create mode 100644 frappe/public/js/frappe/ui/filters/filter_dashboard_head.html rename frappe/public/js/frappe/ui/filters/{filter_dash_stats.html => filter_dashboard_value.html} (94%) create mode 100644 frappe/public/less/filter_dashboard.less diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index 6f8d8a3aad..a90a62f757 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -22,8 +22,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "", "length": 0, "no_copy": 0, @@ -48,8 +48,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Label", "length": 0, "no_copy": 0, @@ -79,8 +79,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Type", "length": 0, "no_copy": 0, @@ -108,8 +108,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Name", "length": 0, "no_copy": 0, @@ -136,8 +136,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Mandatory", "length": 0, "no_copy": 0, @@ -168,8 +168,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Precision", "length": 0, "no_copy": 0, @@ -196,8 +196,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Length", "length": 0, "no_copy": 0, @@ -223,8 +223,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Index", "length": 0, "no_copy": 0, @@ -253,8 +253,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "In List View", "length": 0, "no_copy": 0, @@ -275,14 +275,14 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "in_filter_dash", + "fieldname": "in_standard_filter", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "In Standard Filter", "length": 0, "no_copy": 0, @@ -301,14 +301,15 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "bold", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Bold", "length": 0, "no_copy": 0, @@ -335,8 +336,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Collapsible", "length": 255, "no_copy": 0, @@ -363,8 +364,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Collapsible Depends On", "length": 0, "no_copy": 0, @@ -390,8 +391,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -416,8 +417,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Options", "length": 0, "no_copy": 0, @@ -444,8 +445,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Default", "length": 0, "no_copy": 0, @@ -472,8 +473,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Permissions", "length": 0, "no_copy": 0, @@ -498,8 +499,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Display Depends On", "length": 255, "no_copy": 0, @@ -526,8 +527,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Hidden", "length": 0, "no_copy": 0, @@ -556,8 +557,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Read Only", "length": 0, "no_copy": 0, @@ -584,8 +585,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Unique", "length": 0, "no_copy": 0, @@ -612,8 +613,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Set Only Once", "length": 0, "no_copy": 0, @@ -638,8 +639,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -664,8 +665,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Perm Level", "length": 0, "no_copy": 0, @@ -695,8 +696,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Ignore User Permissions", "length": 0, "no_copy": 0, @@ -721,8 +722,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Allow on Submit", "length": 0, "no_copy": 0, @@ -751,8 +752,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Report Hide", "length": 0, "no_copy": 0, @@ -782,8 +783,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Ignore XSS Filter", "length": 0, "no_copy": 0, @@ -809,8 +810,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Display", "length": 0, "no_copy": 0, @@ -835,8 +836,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "In Filter", "length": 0, "no_copy": 0, @@ -865,8 +866,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "No Copy", "length": 0, "no_copy": 0, @@ -895,8 +896,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Print Hide", "length": 0, "no_copy": 0, @@ -926,8 +927,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Print Hide If No Value", "length": 0, "no_copy": 0, @@ -953,8 +954,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Print Width", "length": 0, "no_copy": 0, @@ -979,8 +980,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Width", "length": 0, "no_copy": 0, @@ -1012,6 +1013,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Columns", "length": 0, "no_copy": 0, @@ -1037,8 +1039,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -1062,8 +1064,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, @@ -1092,8 +1094,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "oldfieldname": "oldfieldname", @@ -1119,8 +1121,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_filter_dash": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "oldfieldname": "oldfieldtype", @@ -1146,7 +1148,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-10-18 11:59:07.036627", + "modified": "2016-10-26 07:08:29.980636", "modified_by": "Administrator", "module": "Core", "name": "DocField", @@ -1156,5 +1158,5 @@ "read_only": 0, "read_only_onload": 0, "sort_order": "ASC", - "track_seen": 0 -} + "track_seen": 0 +} \ No newline at end of file diff --git a/frappe/core/doctype/doctype/boilerplate/controller_list.html b/frappe/core/doctype/doctype/boilerplate/controller_list.html index 0ad19e561b..5af47827f9 100644 --- a/frappe/core/doctype/doctype/boilerplate/controller_list.html +++ b/frappe/core/doctype/doctype/boilerplate/controller_list.html @@ -1,6 +1,6 @@
    -
    +
    {{%= list.get_avatar_and_id(doc) %}} diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index f7eb5b2180..24a03d18ab 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -25,6 +25,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "", "length": 0, "no_copy": 0, @@ -51,6 +52,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 1, "label": "Module", "length": 0, "no_copy": 0, @@ -80,6 +82,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 1, "label": "Is Child Table", "length": 0, "no_copy": 0, @@ -109,6 +112,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Editable Grid", "length": 0, "no_copy": 0, @@ -136,6 +140,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 1, "label": "Is Single", "length": 0, "no_copy": 0, @@ -163,6 +168,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -187,6 +193,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Document Type", "length": 0, "no_copy": 0, @@ -203,35 +210,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "InnoDB", - "depends_on": "eval:!doc.issingle", - "fieldname": "engine", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Database Engine", - "length": 0, - "no_copy": 0, - "options": "InnoDB\nMyISAM", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -244,6 +222,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Icon", "length": 0, "no_copy": 0, @@ -269,6 +248,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Custom?", "length": 0, "no_copy": 0, @@ -294,6 +274,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Beta", "length": 0, "no_copy": 0, @@ -322,6 +303,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Image View", "length": 0, "no_copy": 0, @@ -348,6 +330,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Plugin", "length": 0, "no_copy": 0, @@ -373,6 +356,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Fields", "length": 0, "no_copy": 0, @@ -399,6 +383,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Fields", "length": 0, "no_copy": 0, @@ -427,6 +412,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Naming", "length": 0, "no_copy": 0, @@ -453,6 +439,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Auto Name", "length": 0, "no_copy": 0, @@ -480,6 +467,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Name Case", "length": 0, "no_copy": 0, @@ -508,6 +496,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, @@ -536,6 +525,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -562,6 +552,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Title Field", "length": 0, "no_copy": 0, @@ -588,6 +579,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Search Fields", "length": 0, "no_copy": 0, @@ -616,6 +608,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Image Field", "length": 0, "no_copy": 0, @@ -645,6 +638,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Sort Field", "length": 0, "no_copy": 0, @@ -672,6 +666,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Sort Order", "length": 0, "no_copy": 0, @@ -700,6 +695,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Timeline Field", "length": 0, "no_copy": 0, @@ -727,6 +723,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Permission Rules", "length": 0, "no_copy": 0, @@ -753,6 +750,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Permissions", "length": 0, "no_copy": 0, @@ -782,6 +780,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -806,6 +805,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Permissions Settings", "length": 0, "no_copy": 0, @@ -831,6 +831,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "User Cannot Create", "length": 0, "no_copy": 0, @@ -858,6 +859,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "User Cannot Search", "length": 0, "no_copy": 0, @@ -885,6 +887,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Is Submittable", "length": 0, "no_copy": 0, @@ -911,6 +914,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Allow Import", "length": 0, "no_copy": 0, @@ -936,6 +940,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Allow Rename", "length": 0, "no_copy": 0, @@ -963,6 +968,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "In Dialog", "length": 0, "no_copy": 0, @@ -990,6 +996,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Show Print First", "length": 0, "no_copy": 0, @@ -1017,6 +1024,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Max Attachments", "length": 0, "no_copy": 0, @@ -1044,6 +1052,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Other Settings", "length": 0, "no_copy": 0, @@ -1069,6 +1078,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Hide Heading", "length": 0, "no_copy": 0, @@ -1096,6 +1106,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Hide Toolbar", "length": 0, "no_copy": 0, @@ -1123,6 +1134,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Hide Copy", "length": 0, "no_copy": 0, @@ -1150,6 +1162,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Track Seen", "length": 0, "no_copy": 0, @@ -1177,6 +1190,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Quick Entry", "length": 0, "no_copy": 0, @@ -1203,6 +1217,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Default Print Format", "length": 0, "no_copy": 0, @@ -1215,6 +1230,63 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "advanced", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Advanced", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "InnoDB", + "depends_on": "eval:!doc.issingle", + "fieldname": "engine", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Database Engine", + "length": 0, + "no_copy": 0, + "options": "InnoDB\nMyISAM", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 } ], "hide_heading": 0, @@ -1228,7 +1300,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-10-13 01:13:58.133080", + "modified": "2016-10-26 07:10:02.183706", "modified_by": "Administrator", "module": "Core", "name": "DocType", diff --git a/frappe/core/page/desktop/desktop_module_icon.html b/frappe/core/page/desktop/desktop_module_icon.html index e384c9285d..f2681944f7 100644 --- a/frappe/core/page/desktop/desktop_module_icon.html +++ b/frappe/core/page/desktop/desktop_module_icon.html @@ -1,7 +1,7 @@
    {{ app_icon }} -
    +
    diff --git a/frappe/core/page/modules_setup/includes/module_icons.html b/frappe/core/page/modules_setup/includes/module_icons.html index fd57ef32b3..12a23feecc 100644 --- a/frappe/core/page/modules_setup/includes/module_icons.html +++ b/frappe/core/page/modules_setup/includes/module_icons.html @@ -3,7 +3,7 @@
    diff --git a/frappe/core/page/modules_setup/modules_setup.html b/frappe/core/page/modules_setup/modules_setup.html index ac59d12a71..48e186d37f 100644 --- a/frappe/core/page/modules_setup/modules_setup.html +++ b/frappe/core/page/modules_setup/modules_setup.html @@ -19,6 +19,14 @@ {% endfor %}
    +
    +
    + +
    +