From 619a4adfd5c3b353cd1fd73bdd857d06a41592df Mon Sep 17 00:00:00 2001 From: "hasnain2808@gmail.com" Date: Thu, 21 Jan 2021 13:10:06 +0530 Subject: [PATCH 001/131] fix: add patch for List View Settings Rename --- frappe/patches.txt | 1 + ...list_view_setting_to_list_view_settings.py | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py diff --git a/frappe/patches.txt b/frappe/patches.txt index 1a086303ba..c49c70ba64 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -318,3 +318,4 @@ frappe.patches.v13_0.remove_custom_link execute:frappe.delete_doc("DocType", "Footer Item") frappe.patches.v13_0.replace_field_target_with_open_in_new_tab frappe.patches.v13_0.delete_package_publish_tool +frappe.patches.v13_0.rename_list_view_setting_to_list_view_settings \ No newline at end of file diff --git a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py new file mode 100644 index 0000000000..ee752ae085 --- /dev/null +++ b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py @@ -0,0 +1,21 @@ +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals +import frappe + + +def execute(): + if frappe.db.table_exists('List View Setting'): + existing_list_view_settings = frappe.get_all('List View Settings', as_list=True) + for list_view_setting in frappe.get_all('List View Setting', fields = ['disable_count', 'disable_sidebar_stats', 'disable_auto_refresh', 'name']): + name = list_view_setting.pop('name') + if name not in [x[0] for x in existing_list_view_settings]: + list_view_setting['doctype'] = 'List View Settings' + list_view_settings = frappe.get_doc(list_view_setting) + # setting name here is necessary because autoname is set as prompt + list_view_settings.name = name + list_view_settings.insert() + frappe.delete_doc("DocType", "List View Setting", force=True) + frappe.db.commit() + frappe.db.sql("DROP TABLE IF EXISTS `tabList View Setting`") From 0c8c76ed1b69f76d5f747de73c27cfea3b024e7f Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Fri, 22 Jan 2021 12:49:23 +0530 Subject: [PATCH 002/131] fix: Do not manually drop the table --- .../v13_0/rename_list_view_setting_to_list_view_settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py index ee752ae085..fcf8afc826 100644 --- a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py +++ b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py @@ -18,4 +18,3 @@ def execute(): list_view_settings.insert() frappe.delete_doc("DocType", "List View Setting", force=True) frappe.db.commit() - frappe.db.sql("DROP TABLE IF EXISTS `tabList View Setting`") From 79cb3f0596f263c989667864ee905a8df1d8bd9e Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 4 Feb 2021 14:06:09 +0530 Subject: [PATCH 003/131] feat: Rename "Custom Script" to "Client Script" * Remove postfix "-Client" from ClientScript.autoname --- frappe/core/doctype/doctype/doctype.json | 2 +- frappe/core/workspace/build/build.json | 7 ++--- .../README.md | 0 .../__init__.py | 0 .../client_script.js} | 2 +- .../client_script.json} | 23 ++++++---------- .../client_script.py} | 4 +-- .../test_client_script.py} | 4 +-- .../customization/customization.json | 17 ++++++++---- frappe/desk/form/meta.py | 2 +- frappe/desk/form/utils.py | 2 +- frappe/model/__init__.py | 2 +- frappe/model/delete_doc.py | 2 +- .../public/js/frappe/form/script_manager.js | 2 +- frappe/public/js/frappe/model/model.js | 2 +- frappe/tests/test_exporter_fixtures.py | 26 +++++++++---------- frappe/utils/fixtures.py | 6 ++--- 17 files changed, 52 insertions(+), 51 deletions(-) rename frappe/custom/doctype/{custom_script => client_script}/README.md (100%) rename frappe/custom/doctype/{custom_script => client_script}/__init__.py (100%) rename frappe/custom/doctype/{custom_script/custom_script.js => client_script/client_script.js} (97%) rename frappe/custom/doctype/{custom_script/custom_script.json => client_script/client_script.json} (86%) rename frappe/custom/doctype/{custom_script/custom_script.py => client_script/client_script.py} (84%) rename frappe/custom/doctype/{custom_script/test_custom_script.py => client_script/test_client_script.py} (65%) diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 569414e98b..3ccd1e7e09 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -555,7 +555,7 @@ }, { "group": "Customization", - "link_doctype": "Custom Script", + "link_doctype": "Client Script", "link_fieldname": "dt" }, { diff --git a/frappe/core/workspace/build/build.json b/frappe/core/workspace/build/build.json index c4bde55d7f..aefda698b1 100644 --- a/frappe/core/workspace/build/build.json +++ b/frappe/core/workspace/build/build.json @@ -11,6 +11,7 @@ "hide_custom": 0, "icon": "tool", "idx": 0, + "is_default": 0, "is_standard": 1, "label": "Build", "links": [ @@ -163,8 +164,8 @@ { "hidden": 0, "is_query_report": 0, - "label": "Custom Script", - "link_to": "Custom Script", + "label": "Client Script", + "link_to": "Client Script", "link_type": "DocType", "onboard": 0, "only_for": "", @@ -181,7 +182,7 @@ "type": "Link" } ], - "modified": "2021-01-02 14:03:15.029699", + "modified": "2021-02-04 13:48:48.493146", "modified_by": "Administrator", "module": "Core", "name": "Build", diff --git a/frappe/custom/doctype/custom_script/README.md b/frappe/custom/doctype/client_script/README.md similarity index 100% rename from frappe/custom/doctype/custom_script/README.md rename to frappe/custom/doctype/client_script/README.md diff --git a/frappe/custom/doctype/custom_script/__init__.py b/frappe/custom/doctype/client_script/__init__.py similarity index 100% rename from frappe/custom/doctype/custom_script/__init__.py rename to frappe/custom/doctype/client_script/__init__.py diff --git a/frappe/custom/doctype/custom_script/custom_script.js b/frappe/custom/doctype/client_script/client_script.js similarity index 97% rename from frappe/custom/doctype/custom_script/custom_script.js rename to frappe/custom/doctype/client_script/client_script.js index 711e7d1796..21e7334b82 100644 --- a/frappe/custom/doctype/custom_script/custom_script.js +++ b/frappe/custom/doctype/client_script/client_script.js @@ -1,7 +1,7 @@ // Copyright (c) 2016, Frappe Technologies and contributors // For license information, please see license.txt -frappe.ui.form.on('Custom Script', { +frappe.ui.form.on('Client Script', { refresh(frm) { if (frm.doc.dt && frm.doc.script) { frm.add_custom_button(__('Go to {0}', [frm.doc.dt]), diff --git a/frappe/custom/doctype/custom_script/custom_script.json b/frappe/custom/doctype/client_script/client_script.json similarity index 86% rename from frappe/custom/doctype/custom_script/custom_script.json rename to frappe/custom/doctype/client_script/client_script.json index 328b247c49..57e6c68094 100644 --- a/frappe/custom/doctype/custom_script/custom_script.json +++ b/frappe/custom/doctype/client_script/client_script.json @@ -2,7 +2,7 @@ "actions": [], "allow_import": 1, "creation": "2013-01-10 16:34:01", - "description": "Adds a client custom script to a DocType", + "description": "Adds a custom client script to a DocType", "doctype": "DocType", "document_type": "Document", "engine": "InnoDB", @@ -22,9 +22,7 @@ "oldfieldname": "dt", "oldfieldtype": "Link", "options": "DocType", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "fieldname": "script", @@ -32,35 +30,29 @@ "label": "Script", "oldfieldname": "script", "oldfieldtype": "Code", - "options": "JS", - "show_days": 1, - "show_seconds": 1 + "options": "JS" }, { "fieldname": "sample", "fieldtype": "HTML", "label": "Sample", - "options": "

Custom Script Help

\n

Custom Scripts are executed only on the client-side (i.e. in Forms). Here are some examples to get you started

\n
\n\n// fetch local_tax_no on selection of customer \n// cur_frm.add_fetch(link_field,  source_fieldname,  target_fieldname); \ncur_frm.add_fetch('customer',  'local_tax_no',  'local_tax_no');\n\n// additional validation on dates \nfrappe.ui.form.on('Task',  'validate',  function(frm) {\n    if (frm.doc.from_date < get_today()) {\n        msgprint('You can not select past date in From Date');\n        validated = false;\n    } \n});\n\n// make a field read-only after saving \nfrappe.ui.form.on('Task',  {\n    refresh: function(frm) {\n        // use the __islocal value of doc,  to check if the doc is saved or not\n        frm.set_df_property('myfield',  'read_only',  frm.doc.__islocal ? 0 : 1);\n    } \n});\n\n// additional permission check\nfrappe.ui.form.on('Task',  {\n    validate: function(frm) {\n        if(user=='user1@example.com' && frm.doc.purpose!='Material Receipt') {\n            msgprint('You are only allowed Material Receipt');\n            validated = false;\n        }\n    } \n});\n\n// calculate sales incentive\nfrappe.ui.form.on('Sales Invoice',  {\n    validate: function(frm) {\n        // calculate incentives for each person on the deal\n        total_incentive = 0\n        $.each(frm.doc.sales_team,  function(i,  d) {\n            // calculate incentive\n            var incentive_percent = 2;\n            if(frm.doc.base_grand_total > 400) incentive_percent = 4;\n            // actual incentive\n            d.incentives = flt(frm.doc.base_grand_total) * incentive_percent / 100;\n            total_incentive += flt(d.incentives)\n        });\n        frm.doc.total_incentive = total_incentive;\n    } \n})\n\n
", - "show_days": 1, - "show_seconds": 1 + "options": "

Client Script Help

\n

Client Scripts are executed only on the client-side (i.e. in Forms). Here are some examples to get you started

\n
\n\n// fetch local_tax_no on selection of customer \n// cur_frm.add_fetch(link_field,  source_fieldname,  target_fieldname); \ncur_frm.add_fetch('customer',  'local_tax_no',  'local_tax_no');\n\n// additional validation on dates \nfrappe.ui.form.on('Task',  'validate',  function(frm) {\n    if (frm.doc.from_date < get_today()) {\n        msgprint('You can not select past date in From Date');\n        validated = false;\n    } \n});\n\n// make a field read-only after saving \nfrappe.ui.form.on('Task',  {\n    refresh: function(frm) {\n        // use the __islocal value of doc,  to check if the doc is saved or not\n        frm.set_df_property('myfield',  'read_only',  frm.doc.__islocal ? 0 : 1);\n    } \n});\n\n// additional permission check\nfrappe.ui.form.on('Task',  {\n    validate: function(frm) {\n        if(user=='user1@example.com' && frm.doc.purpose!='Material Receipt') {\n            msgprint('You are only allowed Material Receipt');\n            validated = false;\n        }\n    } \n});\n\n// calculate sales incentive\nfrappe.ui.form.on('Sales Invoice',  {\n    validate: function(frm) {\n        // calculate incentives for each person on the deal\n        total_incentive = 0\n        $.each(frm.doc.sales_team,  function(i,  d) {\n            // calculate incentive\n            var incentive_percent = 2;\n            if(frm.doc.base_grand_total > 400) incentive_percent = 4;\n            // actual incentive\n            d.incentives = flt(frm.doc.base_grand_total) * incentive_percent / 100;\n            total_incentive += flt(d.incentives)\n        });\n        frm.doc.total_incentive = total_incentive;\n    } \n})\n\n
" }, { "default": "0", "fieldname": "enabled", "fieldtype": "Check", - "label": "Enabled", - "show_days": 1, - "show_seconds": 1 + "label": "Enabled" } ], "icon": "fa fa-glass", "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2020-08-24 21:56:07.719579", + "modified": "2021-02-04 13:57:56.509437", "modified_by": "Administrator", "module": "Custom", - "name": "Custom Script", + "name": "Client Script", "owner": "Administrator", "permissions": [ { @@ -86,6 +78,7 @@ "write": 1 } ], + "sort_field": "modified", "sort_order": "ASC", "track_changes": 1 } \ No newline at end of file diff --git a/frappe/custom/doctype/custom_script/custom_script.py b/frappe/custom/doctype/client_script/client_script.py similarity index 84% rename from frappe/custom/doctype/custom_script/custom_script.py rename to frappe/custom/doctype/client_script/client_script.py index e15819de65..e252e2a750 100644 --- a/frappe/custom/doctype/custom_script/custom_script.py +++ b/frappe/custom/doctype/client_script/client_script.py @@ -5,9 +5,9 @@ import frappe from frappe.model.document import Document -class CustomScript(Document): +class ClientScript(Document): def autoname(self): - self.name = self.dt + "-Client" + self.name = self.dt def on_update(self): frappe.clear_cache(doctype=self.dt) diff --git a/frappe/custom/doctype/custom_script/test_custom_script.py b/frappe/custom/doctype/client_script/test_client_script.py similarity index 65% rename from frappe/custom/doctype/custom_script/test_custom_script.py rename to frappe/custom/doctype/client_script/test_client_script.py index 6947e6060d..de113c1ce7 100644 --- a/frappe/custom/doctype/custom_script/test_custom_script.py +++ b/frappe/custom/doctype/client_script/test_client_script.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe import unittest -# test_records = frappe.get_test_records('Custom Script') +# test_records = frappe.get_test_records('Client Script') -class TestCustomScript(unittest.TestCase): +class TestClientScript(unittest.TestCase): pass diff --git a/frappe/custom/workspace/customization/customization.json b/frappe/custom/workspace/customization/customization.json index 3631914249..cdc3b73366 100644 --- a/frappe/custom/workspace/customization/customization.json +++ b/frappe/custom/workspace/customization/customization.json @@ -10,6 +10,7 @@ "hide_custom": 0, "icon": "customization", "idx": 0, + "is_default": 0, "is_standard": 1, "label": "Customization", "links": [ @@ -81,8 +82,8 @@ "dependencies": "", "hidden": 0, "is_query_report": 0, - "label": "Custom Script", - "link_to": "Custom Script", + "label": "Client Script", + "link_to": "Client Script", "link_type": "DocType", "onboard": 0, "type": "Link" @@ -115,7 +116,7 @@ "type": "Link" } ], - "modified": "2020-12-01 13:38:39.843773", + "modified": "2021-02-04 13:50:35.750463", "modified_by": "Administrator", "module": "Custom", "name": "Customization", @@ -134,8 +135,14 @@ "type": "DocType" }, { - "label": "Custom Script", - "link_to": "Custom Script", + "label": "Client Script", + "link_to": "Client Script", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Server Script", + "link_to": "Server Script", "type": "DocType" } ] diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index d5428b1da2..c63da93a33 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -130,7 +130,7 @@ class FormMeta(Meta): def add_custom_script(self): """embed all require files""" # custom script - custom = frappe.db.get_value("Custom Script", {"dt": self.name, "enabled": 1}, "script") or "" + custom = frappe.db.get_value("Client Script", {"dt": self.name, "enabled": 1}, "script") or "" self.set("__custom_js", custom) diff --git a/frappe/desk/form/utils.py b/frappe/desk/form/utils.py index 4c3bab2e23..395d2b9571 100644 --- a/frappe/desk/form/utils.py +++ b/frappe/desk/form/utils.py @@ -47,7 +47,7 @@ def validate_link(): except Exception as e: error_message = str(e).split("Unknown column '") fieldname = None if len(error_message)<=1 else error_message[1].split("'")[0] - frappe.msgprint(_("Wrong fieldname {0} in add_fetch configuration of custom script").format(fieldname)) + frappe.msgprint(_("Wrong fieldname {0} in add_fetch configuration of custom client script").format(fieldname)) frappe.errprint(frappe.get_traceback()) if fetch_value: diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index c39a73ccd7..af06696621 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -118,7 +118,7 @@ core_doctypes_list = ( 'Customize Form Field', 'Property Setter', 'Custom Field', - 'Custom Script' + 'Client Script' ) log_types = ( diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 7b29692ad1..d0e0a6fb1a 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -68,7 +68,7 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa check_permission_and_not_submitted(doc) frappe.db.sql("delete from `tabCustom Field` where dt = %s", name) - frappe.db.sql("delete from `tabCustom Script` where dt = %s", name) + frappe.db.sql("delete from `tabClient Script` where dt = %s", name) frappe.db.sql("delete from `tabProperty Setter` where doc_type = %s", name) frappe.db.sql("delete from `tabReport` where ref_doctype=%s", name) frappe.db.sql("delete from `tabCustom DocPerm` where parent=%s", name) diff --git a/frappe/public/js/frappe/form/script_manager.js b/frappe/public/js/frappe/form/script_manager.js index 7ac3673b08..770319ba53 100644 --- a/frappe/public/js/frappe/form/script_manager.js +++ b/frappe/public/js/frappe/form/script_manager.js @@ -176,7 +176,7 @@ frappe.ui.form.ScriptManager = Class.extend({ eval(doctype.__custom_js); } catch(e) { frappe.msgprint({ - title: __('Error in Custom Script'), + title: __('Error in Client Script'), indicator: 'orange', message: '
' + e.stack  + '
' }); diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index a2e872085e..9ec7b0e931 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -15,7 +15,7 @@ $.extend(frappe.model, { core_doctypes_list: ['DocType', 'DocField', 'DocPerm', 'User', 'Role', 'Has Role', 'Page', 'Module Def', 'Print Format', 'Report', 'Customize Form', - 'Customize Form Field', 'Property Setter', 'Custom Field', 'Custom Script'], + 'Customize Form Field', 'Property Setter', 'Custom Field', 'Client Script'], std_fields: [ {fieldname:'name', fieldtype:'Link', label:__('ID')}, diff --git a/frappe/tests/test_exporter_fixtures.py b/frappe/tests/test_exporter_fixtures.py index a860cc6a96..b8bd94e3e9 100644 --- a/frappe/tests/test_exporter_fixtures.py +++ b/frappe/tests/test_exporter_fixtures.py @@ -12,9 +12,9 @@ class TestDataImportFixtures(unittest.TestCase): def setUp(self): pass - #start test for Custom Script + #start test for Client Script def test_Custom_Script_fixture_simple(self): - fixture = "Custom Script" + fixture = "Client Script" path = frappe.scrub(fixture) + "_original_style.csv" export_csv(fixture, path) @@ -22,7 +22,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_simple_name_equal_default(self): - fixture = ["Custom Script", {"name":["Item-Client"]}] + fixture = ["Client Script", {"name":["Item"]}] path = frappe.scrub(fixture[0]) + "_simple_name_equal_default.csv" export_csv(fixture, path) @@ -30,7 +30,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_simple_name_equal(self): - fixture = ["Custom Script", {"name":["Item-Client"],"op":"="}] + fixture = ["Client Script", {"name":["Item"],"op":"="}] path = frappe.scrub(fixture[0]) + "_simple_name_equal.csv" export_csv(fixture, path) @@ -38,7 +38,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_simple_name_not_equal(self): - fixture = ["Custom Script", {"name":["Item-Client"],"op":"!="}] + fixture = ["Client Script", {"name":["Item"],"op":"!="}] path = frappe.scrub(fixture[0]) + "_simple_name_not_equal.csv" export_csv(fixture, path) @@ -47,7 +47,7 @@ class TestDataImportFixtures(unittest.TestCase): #without [] around the name... def test_Custom_Script_fixture_simple_name_at_least_equal(self): - fixture = ["Custom Script", {"name":"Item-Cli"}] + fixture = ["Client Script", {"name":"Item-Cli"}] path = frappe.scrub(fixture[0]) + "_simple_name_at_least_equal.csv" export_csv(fixture, path) @@ -55,7 +55,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_multi_name_equal(self): - fixture = ["Custom Script", {"name":["Item-Client", "Customer-Client"],"op":"="}] + fixture = ["Client Script", {"name":["Item", "Customer"],"op":"="}] path = frappe.scrub(fixture[0]) + "_multi_name_equal.csv" export_csv(fixture, path) @@ -63,7 +63,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_multi_name_not_equal(self): - fixture = ["Custom Script", {"name":["Item-Client", "Customer-Client"],"op":"!="}] + fixture = ["Client Script", {"name":["Item", "Customer"],"op":"!="}] path = frappe.scrub(fixture[0]) + "_multi_name_not_equal.csv" export_csv(fixture, path) @@ -71,7 +71,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_empty_object(self): - fixture = ["Custom Script", {}] + fixture = ["Client Script", {}] path = frappe.scrub(fixture[0]) + "_empty_object_should_be_all.csv" export_csv(fixture, path) @@ -79,16 +79,16 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_just_list(self): - fixture = ["Custom Script"] + fixture = ["Client Script"] path = frappe.scrub(fixture[0]) + "_just_list_should_be_all.csv" export_csv(fixture, path) self.assertTrue(True) os.remove(path) - # Custom Script regular expression + # Client Script regular expression def test_Custom_Script_fixture_rex_no_flags(self): - fixture = ["Custom Script", {"name":r"^[i|A]"}] + fixture = ["Client Script", {"name":r"^[i|A]"}] path = frappe.scrub(fixture[0]) + "_rex_no_flags.csv" export_csv(fixture, path) @@ -96,7 +96,7 @@ class TestDataImportFixtures(unittest.TestCase): os.remove(path) def test_Custom_Script_fixture_rex_with_flags(self): - fixture = ["Custom Script", {"name":r"^[i|A]", "flags":"L,M"}] + fixture = ["Client Script", {"name":r"^[i|A]", "flags":"L,M"}] path = frappe.scrub(fixture[0]) + "_rex_with_flags.csv" export_csv(fixture, path) diff --git a/frappe/utils/fixtures.py b/frappe/utils/fixtures.py index a1b4eadbf3..7bad6391cc 100644 --- a/frappe/utils/fixtures.py +++ b/frappe/utils/fixtures.py @@ -38,13 +38,13 @@ def import_custom_scripts(app): "custom_scripts") + os.path.sep + fname) as f: doctype = fname.rsplit(".", 1)[0] script = f.read() - if frappe.db.exists("Custom Script", {"dt": doctype}): - custom_script = frappe.get_doc("Custom Script", {"dt": doctype}) + if frappe.db.exists("Client Script", {"dt": doctype}): + custom_script = frappe.get_doc("Client Script", {"dt": doctype}) custom_script.script = script custom_script.save() else: frappe.get_doc({ - "doctype":"Custom Script", + "doctype":"Client Script", "dt": doctype, "script": script }).insert() From da6e183a1f571d45a006f8a410c6ceb15af88e8a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 4 Feb 2021 17:00:16 +0530 Subject: [PATCH 004/131] chore: Bump modified time of DocType --- frappe/core/doctype/doctype/doctype.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 3ccd1e7e09..1533829b3c 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -609,7 +609,7 @@ "link_fieldname": "reference_doctype" } ], - "modified": "2020-12-10 15:10:09.227205", + "modified": "2021-02-04 15:10:09.227205", "modified_by": "Administrator", "module": "Core", "name": "DocType", From 5bd7ed85e5f4caf956d5e79f766cfcc1ed05a961 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 4 Feb 2021 17:03:03 +0530 Subject: [PATCH 005/131] fix: Added patch to rename custom script to client script --- frappe/patches.txt | 1 + frappe/patches/v13_0/rename_custom_client_script.py | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 frappe/patches/v13_0/rename_custom_client_script.py diff --git a/frappe/patches.txt b/frappe/patches.txt index f076d5bd9c..03f7ea71a1 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -329,3 +329,4 @@ frappe.core.doctype.page.patches.drop_unused_pages execute:frappe.get_doc('Role', 'Guest').save() # remove desk access frappe.patches.v13_0.rename_desk_page_to_workspace # 02.02.2021 frappe.patches.v13_0.delete_package_publish_tool +frappe.patches.v13_0.rename_custom_client_script diff --git a/frappe/patches/v13_0/rename_custom_client_script.py b/frappe/patches/v13_0/rename_custom_client_script.py new file mode 100644 index 0000000000..718f1f6a46 --- /dev/null +++ b/frappe/patches/v13_0/rename_custom_client_script.py @@ -0,0 +1,9 @@ +import frappe + + +def execute(): + if frappe.db.exists("DocType", "Client Script"): + return + + frappe.rename_doc("DocType", "Custom Script", "Client Script") + frappe.reload_doctype("Client Script", force=True) From 3589f724af2e66397db1f602cbf38efbd753309e Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 4 Feb 2021 17:20:44 +0530 Subject: [PATCH 006/131] style: sort imports --- frappe/utils/__init__.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 5ac4de618d..8577d7cd7c 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -1,23 +1,31 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -# util __init__.py +from __future__ import print_function, unicode_literals -from __future__ import unicode_literals, print_function -from werkzeug.test import Client -import os, re, sys, json, hashlib, requests, traceback import functools -from .html_utils import sanitize_html -import frappe -from frappe.utils.identicon import Identicon -from email.utils import parseaddr, formataddr +import hashlib +import io +import json +import os +import re +import sys +import traceback from email.header import decode_header, make_header +from email.utils import formataddr, parseaddr +from gzip import GzipFile +from typing import Generator, Iterable + +import requests +from six import string_types, text_type +from six.moves.urllib.parse import quote +from werkzeug.test import Client + +import frappe # utility functions like cint, int, flt, etc. from frappe.utils.data import * -from six.moves.urllib.parse import quote -from six import text_type, string_types -import io -from gzip import GzipFile +from frappe.utils.identicon import Identicon +from frappe.utils.html_utils import sanitize_html default_fields = ['doctype', 'name', 'owner', 'creation', 'modified', 'modified_by', 'parent', 'parentfield', 'parenttype', 'idx', 'docstatus'] @@ -304,8 +312,8 @@ def unesc(s, esc_chars): def execute_in_shell(cmd, verbose=0): # using Popen instead of os.system - as recommended by python docs - from subprocess import Popen import tempfile + from subprocess import Popen with tempfile.TemporaryFile() as stdout: with tempfile.TemporaryFile() as stderr: @@ -471,8 +479,9 @@ def get_request_session(max_retries=3): def watch(path, handler=None, debug=True): import time - from watchdog.observers import Observer + from watchdog.events import FileSystemEventHandler + from watchdog.observers import Observer class Handler(FileSystemEventHandler): def on_any_event(self, event): @@ -571,9 +580,9 @@ def get_installed_apps_info(): return out def get_site_info(): - from frappe.utils.user import get_system_managers from frappe.core.doctype.user.user import STANDARD_USERS from frappe.email.queue import get_emails_sent_this_month + from frappe.utils.user import get_system_managers # only get system users users = frappe.get_all('User', filters={'user_type': 'System User', 'name': ('not in', STANDARD_USERS)}, From 90f3aeb39bfe7e001312d1ac6815f494950d89db Mon Sep 17 00:00:00 2001 From: "hasnain2808@gmail.com" Date: Fri, 5 Feb 2021 20:28:17 +0530 Subject: [PATCH 007/131] fix: Attach image not displaying in print view --- frappe/templates/print_formats/standard_macros.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frappe/templates/print_formats/standard_macros.html b/frappe/templates/print_formats/standard_macros.html index 7a0dce7f5e..9f5f4cf12c 100644 --- a/frappe/templates/print_formats/standard_macros.html +++ b/frappe/templates/print_formats/standard_macros.html @@ -126,10 +126,14 @@ data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}" {% include doc.print_templates[df.fieldname] %} {% elif df.fieldtype=="Check" %} - {% elif df.fieldtype in ("Image", "Attach Image") %} + {% elif df.fieldtype=="Image" %} + {% elif df.fieldtype=="Attach Image" %} + {% elif df.fieldtype=="Signature" %} From 07b8131d71af023823a5cf9b025233677ce2424f Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 9 Feb 2021 17:15:53 +0530 Subject: [PATCH 008/131] fix: kanban style --- frappe/public/scss/desk/kanban.scss | 46 +++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/frappe/public/scss/desk/kanban.scss b/frappe/public/scss/desk/kanban.scss index 13551c4c17..902164ff10 100644 --- a/frappe/public/scss/desk/kanban.scss +++ b/frappe/public/scss/desk/kanban.scss @@ -15,7 +15,7 @@ .kanban { display: flex; - overflow: auto; + overflow-y: hidden; -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ @@ -32,6 +32,8 @@ border-radius: var(--border-radius); padding: var(--padding-md); min-height: calc(100vh - 250px); + max-height: calc(75vh - 10px); + // overflow: hidden; &.add-new-column { order: 1; @@ -138,7 +140,6 @@ } .kanban-cards { - min-height: 100px; max-height: calc(100vh - 250px); margin: -5px; padding: 5px; @@ -191,10 +192,20 @@ } } - .kanban-card-title { - max-width: 90%; - font-size: $font-size-base; - font-weight: 500; + .kanban-title-area { + margin-bottom: var(--margin-md); + + .kanban-card-title { + max-width: 90%; + font-size: var(--text-md); + font-weight: 500; + } + + .kanban-card-creation { + font-size: var(--text-md); + color: var(--text-muted); + margin-top: var(--margin-xs); + } } .kanban-card-edit { @@ -248,12 +259,35 @@ } .kanban-card-meta { + + .list-comment-count { + width: 30px; + } + + .like-action:not(.liked) { + .icon use { + stroke: var(--text-muted); + } + } + .kanban-assignments { display: flex; float: right; .avatar { cursor: default; + width: 22px; + height: 22px; + } + + .avatar-action { + width: 22px; + height: 22px; + + .icon { + width: 12px; + height: 12px; + } } } } From 0d29d46f7d6c95f67060c70878a874f5a02074ff Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 9 Feb 2021 17:16:58 +0530 Subject: [PATCH 009/131] feat: add likes and creation to kanban --- frappe/public/js/frappe/views/kanban/kanban_board.js | 12 +++++++++--- .../public/js/frappe/views/kanban/kanban_card.html | 5 ++++- frappe/public/js/frappe/views/kanban/kanban_view.js | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/views/kanban/kanban_board.js b/frappe/public/js/frappe/views/kanban/kanban_board.js index 66ae842ae7..e5f28659f4 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_board.js +++ b/frappe/public/js/frappe/views/kanban/kanban_board.js @@ -446,6 +446,7 @@ frappe.provide("frappe.views"); group: "cards", animation: 150, dataIdAttr: 'data-name', + forceFallback: true, onStart: function() { wrapper.find('.kanban-card.add-card').fadeOut(200, function() { wrapper.find('.kanban-cards').height('100vh'); @@ -546,14 +547,14 @@ frappe.provide("frappe.views"); var opts = { name: card.name, title: remove_img_tags(card.title), - disable_click: card._disable_click ? 'disable-click' : '' + disable_click: card._disable_click ? 'disable-click' : '', + creation: card.creation, }; self.$card = $(frappe.render_template('kanban_card', opts)) .appendTo(wrapper); } function render_card_meta() { - var html = ""; if (card.comment_count > 0) html += ` @@ -563,7 +564,10 @@ frappe.provide("frappe.views"); const $assignees_group = get_assignees_group(); - html += ``; + html += ` + + ${cur_list.get_like_html(card)} + `; if (card.color && frappe.ui.color.validate_hex(card.color)) { const $div = $('
'); @@ -630,6 +634,8 @@ frappe.provide("frappe.views"); doctype: state.doctype, name: card.name, title: card[state.card_meta.title_field.fieldname], + creation: moment(card.creation).format('MMM DD, YYYY'), + tags: card._user_tags, column: card[state.board.field_name], assigned_list: card.assigned_list || assigned_list, comment_count: card.comment_count || comment_count, diff --git a/frappe/public/js/frappe/views/kanban/kanban_card.html b/frappe/public/js/frappe/views/kanban/kanban_card.html index 108dadce8c..b67488f46f 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_card.html +++ b/frappe/public/js/frappe/views/kanban/kanban_card.html @@ -2,9 +2,12 @@
-
+
{{ title }}
+
+ {{ creation }} +
diff --git a/frappe/public/js/frappe/views/kanban/kanban_view.js b/frappe/public/js/frappe/views/kanban/kanban_view.js index 46348b0d11..096c882d74 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_view.js +++ b/frappe/public/js/frappe/views/kanban/kanban_view.js @@ -74,6 +74,7 @@ frappe.views.KanbanView = class KanbanView extends frappe.views.ListView { setup_view() { this.setup_realtime_updates(); + this.setup_like(); } set_fields() { From ff27940b8e2848628ba30df093f1a5a2b156fc41 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 4 Feb 2021 17:21:06 +0530 Subject: [PATCH 010/131] refactor(utils): Update create_batch docstring, annotations --- frappe/utils/__init__.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 8577d7cd7c..c8a589c694 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -700,13 +700,19 @@ def get_safe_filters(filters): return filters -def create_batch(iterable, batch_size): - """ - Convert an iterable to multiple batches of constant size of batch_size +def create_batch(iterable: Iterable, size: int) -> Generator[Iterable, None, None]: + """Convert an iterable to multiple batches of constant size of batch_size + + Args: + iterable (Iterable): Iterable object which is subscriptable + size (int): Maximum size of batches to be generated + + Yields: + Generator[List]: Batched iterable of maximum length `size` """ total_count = len(iterable) - for i in range(0, total_count, batch_size): - yield iterable[i:min(i + batch_size, total_count)] + for i in range(0, total_count, size): + yield iterable[i : min(i + size, total_count)] def set_request(**kwargs): from werkzeug.test import EnvironBuilder From 721097e47dc2881b492dcd8b11e8a35e3b9ac167 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 6 Jan 2021 10:41:18 +0530 Subject: [PATCH 011/131] chore: Drop deprecated code --- frappe/utils/__init__.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index c8a589c694..414d3b930f 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -27,24 +27,10 @@ from frappe.utils.data import * from frappe.utils.identicon import Identicon from frappe.utils.html_utils import sanitize_html + default_fields = ['doctype', 'name', 'owner', 'creation', 'modified', 'modified_by', 'parent', 'parentfield', 'parenttype', 'idx', 'docstatus'] -# used in import_docs.py -# TODO: deprecate it -def getCSVelement(v): - """ - Returns the CSV value of `v`, For example: - - * apple becomes "apple" - * hi"there becomes "hi""there" - """ - v = cstr(v) - if not v: return '' - if (',' in v) or ('\n' in v) or ('"' in v): - if '"' in v: v = v.replace('"', '""') - return '"'+v+'"' - else: return v or '' def get_fullname(user=None): """get the full name (first name + last name) of the user from User""" From 051e2027577322f45949af94990c1bf52a63628e Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 10 Feb 2021 13:02:42 +0530 Subject: [PATCH 012/131] fix(minor): context.metatags can be set via script `context.metatags` can be set via scripts in Web Page --- frappe/website/doctype/web_page/web_page.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index e09b978876..86774c79c4 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -144,12 +144,13 @@ class WebPage(WebsiteGenerator): raise frappe.Redirect def set_metatags(self, context): - context.metatags = { - "name": self.meta_title or self.title, - "description": self.meta_description, - "image": self.meta_image or find_first_image(context.main_section or ""), - "og:type": "website" - } + if not context.metatags: + context.metatags = { + "name": self.meta_title or self.title, + "description": self.meta_description, + "image": self.meta_image or find_first_image(context.main_section or ""), + "og:type": "website" + } def validate_dates(self): if self.end_date: From e3b1051b15ec756225e238cd8174f062894342b8 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 10 Feb 2021 15:04:04 +0530 Subject: [PATCH 013/131] fix: Use SVG for rating stars (#12358) --- cypress/integration/control_rating.js | 6 ++-- frappe/public/build.json | 5 +--- frappe/public/icons/timeless/symbol-defs.svg | 3 ++ .../public/js/frappe/form/controls/rating.js | 28 ++++++++++--------- .../public/js/frappe/utils/rating_icons.html | 6 ---- frappe/public/js/frappe/utils/ratings.html | 8 ------ frappe/public/less/controls.less | 14 +--------- frappe/public/scss/desk/controls.scss | 13 ++++++++- frappe/public/scss/desk/dark.scss | 9 ++++++ 9 files changed, 44 insertions(+), 48 deletions(-) delete mode 100644 frappe/public/js/frappe/utils/rating_icons.html delete mode 100644 frappe/public/js/frappe/utils/ratings.html diff --git a/cypress/integration/control_rating.js b/cypress/integration/control_rating.js index 31c036d240..592ed87004 100644 --- a/cypress/integration/control_rating.js +++ b/cypress/integration/control_rating.js @@ -18,7 +18,7 @@ context('Control Rating', () => { get_dialog_with_rating().as('dialog'); cy.get('div.rating') - .children('i.fa') + .children('svg') .first() .click() .should('have.class', 'star-click'); @@ -33,11 +33,11 @@ context('Control Rating', () => { get_dialog_with_rating(); cy.get('div.rating') - .children('i.fa') + .children('svg') .first() .invoke('trigger', 'mouseenter') .should('have.class', 'star-hover') .invoke('trigger', 'mouseleave') .should('not.have.class', 'star-hover'); }); -}); \ No newline at end of file +}); diff --git a/frappe/public/build.json b/frappe/public/build.json index f2a4d65582..6d7ccaa3da 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -36,7 +36,6 @@ "public/js/frappe/model/perm.js", "website/js/website.js", - "public/js/frappe/utils/rating_icons.html", "public/js/frappe/socketio_client.js" ], "js/bootstrap-4-web.min.js": "website/js/bootstrap-4.js", @@ -62,7 +61,6 @@ ], "js/dialog.min.js": [ "public/js/frappe/dom.js", - "public/js/frappe/form/formatters.js", "public/js/frappe/form/layout.js", "public/js/frappe/ui/field_group.js", @@ -108,13 +106,13 @@ "node_modules/moment-timezone/builds/moment-timezone-with-data.min.js", "public/js/lib/socket.io.min.js", "public/js/lib/jSignature.min.js", - "public/js/frappe/translate.js", "public/js/lib/leaflet/leaflet.js", "public/js/lib/leaflet/leaflet.draw.js", "public/js/lib/leaflet/L.Control.Locate.js", "public/js/lib/leaflet/easy-button.js" ], "js/desk.min.js": [ + "public/js/frappe/translate.js", "public/js/frappe/class.js", "public/js/frappe/polyfill.js", "public/js/frappe/provide.js", @@ -213,7 +211,6 @@ "public/js/frappe/query_string.js", "public/js/frappe/ui/comment.js", - "public/js/frappe/utils/rating_icons.html", "public/js/frappe/chat.js", "public/js/frappe/utils/energy_point_utils.js", diff --git a/frappe/public/icons/timeless/symbol-defs.svg b/frappe/public/icons/timeless/symbol-defs.svg index ed02f91a46..cbb038a2a0 100644 --- a/frappe/public/icons/timeless/symbol-defs.svg +++ b/frappe/public/icons/timeless/symbol-defs.svg @@ -684,4 +684,7 @@ + + + diff --git a/frappe/public/js/frappe/form/controls/rating.js b/frappe/public/js/frappe/form/controls/rating.js index 191db35538..351c4f7122 100644 --- a/frappe/public/js/frappe/form/controls/rating.js +++ b/frappe/public/js/frappe/form/controls/rating.js @@ -1,22 +1,24 @@ frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ make_input() { this._super(); + let stars = ''; + [1, 2, 3, 4, 5].forEach(i => { + stars += ` + + `; + }); const star_template = `
- - - - - + ${stars}
`; $(this.input_area).html(star_template); - $(this.input_area).find('i').hover((ev) => { + $(this.input_area).find('svg').hover((ev) => { const el = $(ev.currentTarget); let star_value = el.data('rating'); - el.parent().children('i.fa').each( function(e) { + el.parent().children('svg').each( function(e) { if (e < star_value) { $(this).addClass('star-hover'); } else { @@ -25,16 +27,16 @@ frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ }); }, (ev) => { const el = $(ev.currentTarget); - el.parent().children('i.fa').each( function() { + el.parent().children('svg').each( function() { $(this).removeClass('star-hover'); }); }); - $(this.input_area).find('i').click((ev) => { + $(this.input_area).find('svg').click((ev) => { const el = $(ev.currentTarget); let star_value = el.data('rating'); - el.parent().children('i.fa').each( function(e) { - if (e < star_value){ + el.parent().children('svg').each( function(e) { + if (e < star_value) { $(this).addClass('star-click'); } else { $(this).removeClass('star-click'); @@ -51,7 +53,7 @@ frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ }, set_formatted_input(value) { let el = $(this.input_area).find('i'); - el.children('i.fa').prevObject.each( function(e) { + el.children('svg').prevObject.each( function(e) { if (e < value) { $(this).addClass('star-click'); } else { @@ -59,4 +61,4 @@ frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ } }); } -}); \ No newline at end of file +}); diff --git a/frappe/public/js/frappe/utils/rating_icons.html b/frappe/public/js/frappe/utils/rating_icons.html deleted file mode 100644 index 84b723ad02..0000000000 --- a/frappe/public/js/frappe/utils/rating_icons.html +++ /dev/null @@ -1,6 +0,0 @@ -{% if show_label %} - {{ __("Rating: ") }} -{% endif %} -{% for(var i=1, l=6; i -{% } %} \ No newline at end of file diff --git a/frappe/public/js/frappe/utils/ratings.html b/frappe/public/js/frappe/utils/ratings.html deleted file mode 100644 index 6d1f39348d..0000000000 --- a/frappe/public/js/frappe/utils/ratings.html +++ /dev/null @@ -1,8 +0,0 @@ -
-{% if label && data.show_label %} - {{ __("{0}: ", label) }} -{% endif %} -{% for(var i=1, l=6; i -{% } %} -
\ No newline at end of file diff --git a/frappe/public/less/controls.less b/frappe/public/less/controls.less index d13bd4f8c2..425221c1d3 100644 --- a/frappe/public/less/controls.less +++ b/frappe/public/less/controls.less @@ -43,18 +43,6 @@ margin-bottom: 5px; } -.rating { - i { - color: @text-extra-muted; - } - .star-hover { - color: @text-muted; - } - .star-click { - color: @text-light; - } -} - .barcode-scanner { position: relative; @@ -141,4 +129,4 @@ margin-bottom: 3px; margin-right: 12px; } -} \ No newline at end of file +} diff --git a/frappe/public/scss/desk/controls.scss b/frappe/public/scss/desk/controls.scss index edc658661c..38821dcbb8 100644 --- a/frappe/public/scss/desk/controls.scss +++ b/frappe/public/scss/desk/controls.scss @@ -186,4 +186,15 @@ a.progress-small { .progress-bar-warning { background-color: var(--orange-500); -} \ No newline at end of file +} + +.rating { + // rating + --star-fill: var(--gray-300); + .star-hover { + --star-fill: var(--yellow-100); + } + .star-click { + --star-fill: var(--yellow-300); + } +} diff --git a/frappe/public/scss/desk/dark.scss b/frappe/public/scss/desk/dark.scss index 445c270c03..c60fa810e3 100644 --- a/frappe/public/scss/desk/dark.scss +++ b/frappe/public/scss/desk/dark.scss @@ -131,4 +131,13 @@ fill: var(--gray-700); } } + + .rating { + // rating + --star-fill: var(--gray-500); + .star-hover { + --star-fill: var(--gray-400); + } + } + } From 5811be55823a3e88706c56b9064ab4f8c45832d4 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 10 Feb 2021 18:49:09 +0530 Subject: [PATCH 014/131] fix: Fix modal child tables not showing up Modal child tables don't have frm attached to it, hence added check for undefined state. Closes #12342 ISS-20-21-09425 --- frappe/public/js/frappe/form/grid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index 921ad1cdb5..3bde525fff 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -268,7 +268,7 @@ export default class Grid { } refresh(force) { - if (this.frm.setting_dependency) return; + if (this.frm && this.frm.setting_dependency) return; this.data = this.get_data(); From 7b49882f5f8812ab0c12bbcbfd0fea862644b8a3 Mon Sep 17 00:00:00 2001 From: "hasnain2808@gmail.com" Date: Wed, 10 Feb 2021 23:46:29 +0530 Subject: [PATCH 015/131] fix: minor data import rebrand compatibility --- frappe/public/build.json | 3 ++- frappe/public/js/frappe/data_import/import_preview.js | 5 +++-- frappe/public/js/frappe/ui/colors.js | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/frappe/public/build.json b/frappe/public/build.json index 35e9d62436..fcf2c29673 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -305,5 +305,6 @@ "css/email.css": "public/scss/email.scss", "js/barcode_scanner.min.js": "public/js/frappe/barcode_scanner/quagga.js", "js/user_profile_controller.min.js": "desk/page/user_profile/user_profile_controller.js", - "css/login.css": "public/scss/login.scss" + "css/login.css": "public/scss/login.scss", + "js/data_import_tools.min.js": "public/js/frappe/data_import/index.js" } diff --git a/frappe/public/js/frappe/data_import/import_preview.js b/frappe/public/js/frappe/data_import/import_preview.js index 477cfb0786..32a41587f7 100644 --- a/frappe/public/js/frappe/data_import/import_preview.js +++ b/frappe/public/js/frappe/data_import/import_preview.js @@ -188,12 +188,13 @@ frappe.data_import.ImportPreview = class ImportPreview { .join(','); this.datatable.style.setStyle(row_classes, { pointerEvents: 'none', - backgroundColor: frappe.ui.color.get_color_shade('white', 'light'), - color: frappe.ui.color.get_color_shade('black', 'extra-light') + backgroundColor: frappe.ui.color.get_color_shade('gray', 'extra-light'), + color: frappe.ui.color.get_color_shade('gray', 'dark') }); } add_actions() { + console.log("add_actions") let actions = [ { label: __('Map Columns'), diff --git a/frappe/public/js/frappe/ui/colors.js b/frappe/public/js/frappe/ui/colors.js index 9ce71abae4..ec9607c387 100644 --- a/frappe/public/js/frappe/ui/colors.js +++ b/frappe/public/js/frappe/ui/colors.js @@ -39,7 +39,8 @@ frappe.ui.color = { }; if(Object.keys(shades).includes(shade)) { - return frappe.ui.color_map[color_name][shades[shade]]; + const color = this.get_color(color_name) + return color[shades[shade]]; } else { // eslint-disable-next-line console.warn(`'shade' can be one of ${Object.keys(shades)} and not ${shade}`); From 3fcfc3d0aea61b883f72aade2826ea04aceca62b Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Wed, 10 Feb 2021 23:56:14 +0530 Subject: [PATCH 016/131] fix: sider --- frappe/public/js/frappe/data_import/import_preview.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/public/js/frappe/data_import/import_preview.js b/frappe/public/js/frappe/data_import/import_preview.js index 32a41587f7..786692e552 100644 --- a/frappe/public/js/frappe/data_import/import_preview.js +++ b/frappe/public/js/frappe/data_import/import_preview.js @@ -194,7 +194,6 @@ frappe.data_import.ImportPreview = class ImportPreview { } add_actions() { - console.log("add_actions") let actions = [ { label: __('Map Columns'), From bdc3578c01d3c2562118af5e4c323ccd6255a34d Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Wed, 10 Feb 2021 23:56:53 +0530 Subject: [PATCH 017/131] fix: sider --- frappe/public/js/frappe/ui/colors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/colors.js b/frappe/public/js/frappe/ui/colors.js index ec9607c387..63d7bf4378 100644 --- a/frappe/public/js/frappe/ui/colors.js +++ b/frappe/public/js/frappe/ui/colors.js @@ -39,7 +39,7 @@ frappe.ui.color = { }; if(Object.keys(shades).includes(shade)) { - const color = this.get_color(color_name) + const color = this.get_color(color_name); return color[shades[shade]]; } else { // eslint-disable-next-line From 0f9e77c401c8bdf47b770d3a322f20da5402e6b4 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 11 Feb 2021 10:24:46 +0530 Subject: [PATCH 018/131] refactor: optimize updating of order for kanban board --- .../desk/doctype/kanban_board/kanban_board.py | 73 +++++++++++++++++-- .../js/frappe/views/kanban/kanban_board.js | 72 +++++++++++++++++- 2 files changed, 135 insertions(+), 10 deletions(-) diff --git a/frappe/desk/doctype/kanban_board/kanban_board.py b/frappe/desk/doctype/kanban_board/kanban_board.py index f1ad41db6c..9152e952ab 100644 --- a/frappe/desk/doctype/kanban_board/kanban_board.py +++ b/frappe/desk/doctype/kanban_board/kanban_board.py @@ -17,6 +17,10 @@ class KanbanBoard(Document): def on_update(self): frappe.clear_cache(doctype=self.reference_doctype) + def before_insert(self): + for column in self.columns: + column.order = get_order_for_column(self, column.column_name) + def validate_column_name(self): for column in self.columns: if not column.column_name: @@ -125,6 +129,56 @@ def update_order(board_name, order): board.save() return board, updated_cards +@frappe.whitelist() +def update_order_for_single_card(board_name, docname, from_colname, to_colname, old_index, new_index): + '''Save the order of cards in columns''' + board = frappe.get_doc('Kanban Board', board_name) + doctype = board.reference_doctype + fieldname = board.field_name + old_index = frappe.parse_json(old_index) + new_index = frappe.parse_json(new_index) + + # save current order and index of columns to be updated + for i, col in enumerate(board.columns): + from_col_order, from_col_idx = get_kanban_column_order_and_index(board, from_colname) + to_col_order, to_col_idx = get_kanban_column_order_and_index(board, to_colname) + + if from_colname == to_colname: + from_col_order = to_col_order + + to_col_order.insert(new_index, from_col_order.pop((old_index))) + + # save updated order + board.columns[from_col_idx].order = frappe.as_json(from_col_order) + board.columns[to_col_idx].order = frappe.as_json(to_col_order) + board.save() + + # update changed value in doc + frappe.set_value(doctype, docname, fieldname, to_colname) + + return board + +def get_kanban_column_order_and_index(board, colname): + for i, col in enumerate(board.columns): + if col.column_name == colname: + col_order = frappe.parse_json(col.order) + col_idx = i + + return col_order, col_idx + +@frappe.whitelist() +def add_card(board_name, docname, colname): + board = frappe.get_doc('Kanban Board', board_name) + doctype = board.reference_doctype + fieldname = board.field_name + + col_order, col_idx = get_kanban_column_order_and_index(board, colname) + col_order.insert(0, docname) + + board.columns[col_idx].order = frappe.as_json(col_order) + + board.save() + return board @frappe.whitelist() def quick_kanban_board(doctype, board_name, field_name, project=None): @@ -133,6 +187,13 @@ def quick_kanban_board(doctype, board_name, field_name, project=None): doc = frappe.new_doc('Kanban Board') meta = frappe.get_meta(doctype) + doc.kanban_board_name = board_name + doc.reference_doctype = doctype + doc.field_name = field_name + + if project: + doc.filters = '[["Task","project","=","{0}"]]'.format(project) + options = '' for field in meta.fields: if field.fieldname == field_name: @@ -149,12 +210,6 @@ def quick_kanban_board(doctype, board_name, field_name, project=None): column_name=column )) - doc.kanban_board_name = board_name - doc.reference_doctype = doctype - doc.field_name = field_name - - if project: - doc.filters = '[["Task","project","=","{0}"]]'.format(project) if doctype in ['Note', 'ToDo']: doc.private = 1 @@ -162,6 +217,12 @@ def quick_kanban_board(doctype, board_name, field_name, project=None): doc.save() return doc +def get_order_for_column(board, colname): + filters = [[board.reference_doctype, board.field_name, '=', colname]] + if board.filters: + filters.append(frappe.parse_json(board.filters)[0]) + + return frappe.as_json(frappe.get_list(board.reference_doctype, filters=filters, pluck='name')) @frappe.whitelist() def update_column_order(board_name, order): diff --git a/frappe/public/js/frappe/views/kanban/kanban_board.js b/frappe/public/js/frappe/views/kanban/kanban_board.js index e5f28659f4..495482afd5 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_board.js +++ b/frappe/public/js/frappe/views/kanban/kanban_board.js @@ -124,7 +124,12 @@ frappe.provide("frappe.views"); const new_cards = state.cards.slice(); new_cards[index] = card; updater.set({ cards: new_cards }); - fluxify.doAction('update_order'); + const args = { + new: 1, + name: card.name, + colname: updated_doc[state.board.field_name], + } + fluxify.doAction('update_order_for_single_card', args); }); } else { frappe.new_doc(this.doctype, doc); @@ -155,6 +160,53 @@ frappe.provide("frappe.views"); fluxify.doAction('update_card', updated_card); }); }, + update_order_for_single_card: function(updater, card) { + // cache original order + const _cards = this.cards.slice(); + const _columns = this.columns.slice(); + let args = {}; + let method_name = ""; + + if (card.new) { + method_name = "add_card"; + args = { + board_name: this.board.name, + docname: card.name, + colname: card.colname, + }; + } else { + method_name = "update_order_for_single_card"; + args = { + board_name: this.board.name, + docname: card.name, + from_colname: card.from_colname, + to_colname: card.to_colname, + old_index: card.old_index, + new_index: card.new_index, + }; + } + + frappe.call({ + method: method_prefix + method_name, + args: args, + callback: (r) => { + let board = r.message; + let updated_cards = [{'name': card.name, 'column': card.to_colname || card.colname}]; + let cards = update_cards_column(updated_cards); + let columns = prepare_columns(board.columns); + updater.set({ + cards: cards, + columns: columns + }); + } + }).fail(function() { + // revert original order + updater.set({ + cards: _cards, + columns: _columns + }); + }); + }, update_order: function(updater) { // cache original order const _cards = this.cards.slice(); @@ -447,16 +499,26 @@ frappe.provide("frappe.views"); animation: 150, dataIdAttr: 'data-name', forceFallback: true, - onStart: function() { + onStart: function(e) { wrapper.find('.kanban-card.add-card').fadeOut(200, function() { wrapper.find('.kanban-cards').height('100vh'); }); }, - onEnd: function() { + onEnd: function(e) { wrapper.find('.kanban-card.add-card').fadeIn(100); wrapper.find('.kanban-cards').height('auto'); // update order - fluxify.doAction('update_order'); + let from_col = $(e.from).parents('.kanban-column').attr('data-column-value'); + let to_col = $(e.to).parents('.kanban-column').attr('data-column-value'); + let docname = $(e.item).attr('data-name'); + const args = { + name: docname, + from_colname: from_col, + to_colname: to_col, + old_index: e.oldIndex, + new_index: e.newIndex, + }; + fluxify.doAction('update_order_for_single_card', args); }, onAdd: function() { }, @@ -555,6 +617,8 @@ frappe.provide("frappe.views"); } function render_card_meta() { + let html = ''; + if (card.comment_count > 0) html += ` From 8d847ee52ea94b59ae68777930e1c607260144a7 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 11 Feb 2021 11:09:55 +0530 Subject: [PATCH 019/131] feat: add tags to kanban --- frappe/public/js/frappe/list/list_view.js | 16 +++++++++++----- .../js/frappe/views/kanban/kanban_board.js | 10 +++++++++- frappe/public/scss/desk/kanban.scss | 15 ++++++++++++++- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 2f1f278ecc..66d3198e17 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -164,7 +164,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { const match_rules_list = frappe.perm.get_match_rules(this.doctype); if (match_rules_list.length) { this.restricted_list = $( - `` ).click(() => this.show_restrictions(match_rules_list)).appendTo(this.page.page_form); @@ -676,7 +676,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { if (col.type === "Tag") { const tags_display_class = !this.tags_shown ? 'hide' : ''; - let tags_html = doc._user_tags ? this.get_tags_html(doc._user_tags) : '
-
'; + let tags_html = doc._user_tags ? this.get_tags_html(doc._user_tags, 2) : '
-
'; return `